API refactor WIP
diff --git a/xos/api/cord/debug.py b/xos/api/cord/debug.py
new file mode 100644
index 0000000..da22d96
--- /dev/null
+++ b/xos/api/cord/debug.py
@@ -0,0 +1,61 @@
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+from rest_framework import serializers
+from rest_framework import generics
+from rest_framework import viewsets
+from rest_framework.decorators import detail_route, list_route
+from rest_framework.views import APIView
+from core.models import *
+from django.forms import widgets
+from django.conf.urls import patterns, url
+from services.cord.models import VOLTTenant, VBNGTenant, CordSubscriberRoot
+from core.xoslib.objects.cordsubscriber import CordSubscriber
+from api.xosapi_helpers import PlusSerializerMixin, XOSViewSet
+from django.shortcuts import get_object_or_404
+from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
+from xos.exceptions import *
+import json
+import subprocess
+
+if hasattr(serializers, "ReadOnlyField"):
+    # rest_framework 3.x
+    ReadOnlyField = serializers.ReadOnlyField
+else:
+    # rest_framework 2.x
+    ReadOnlyField = serializers.Field
+
+class CordDebugIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
+    # Swagger is failing because CordDebugViewSet has neither a model nor
+    # a serializer_class. Stuck this in here as a placeholder for now.
+    id = ReadOnlyField()
+    class Meta:
+        model = CordSubscriber
+
+class CordDebugViewSet(XOSViewSet):
+    base_name = "debug"
+    method_name = "debug"
+    method_kind = "viewset"
+    serializer_class = CordDebugIdSerializer
+
+    @classmethod
+    def get_urlpatterns(self, api_path=""):
+        patterns = []
+        patterns.append( url("^" + api_path + "debug/vbng_dump/$", self.as_view({"get": "get_vbng_dump"}), name="vbng_dump"))
+        return patterns
+
+    # contact vBNG service and dump current list of mappings
+    def get_vbng_dump(self, request, pk=None):
+        result=subprocess.check_output(["curl", "http://10.0.3.136:8181/onos/virtualbng/privateip/map"])
+        if request.GET.get("theformat",None)=="text":
+            from django.http import HttpResponse
+            result = json.loads(result)["map"]
+
+            lines = []
+            for row in result:
+                for k in row.keys():
+                     lines.append( "%s %s" % (k, row[k]) )
+
+            return HttpResponse("\n".join(lines), content_type="text/plain")
+        else:
+            return Response( {"vbng_dump": json.loads(result)["map"] } )
diff --git a/xos/api/cord/subscriber.py b/xos/api/cord/subscriber.py
index f0bee26..ac19420 100644
--- a/xos/api/cord/subscriber.py
+++ b/xos/api/cord/subscriber.py
@@ -11,7 +11,7 @@
 from django.conf.urls import patterns, url
 from services.cord.models import VOLTTenant, VBNGTenant, CordSubscriberRoot
 from core.xoslib.objects.cordsubscriber import CordSubscriber
-from plus import PlusSerializerMixin, XOSViewSet
+from api.xosapi_helpers import PlusSerializerMixin, XOSViewSet
 from django.shortcuts import get_object_or_404
 from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
 from xos.exceptions import *
@@ -101,70 +101,6 @@
     method_kind = "detail"
     method_name = "cordsubscriber"
 
-# We fake a user object by pulling the user data struct out of the
-# subscriber object...
-
-def serialize_user(subscriber, user):
-    return {"id": "%d-%d" % (subscriber.id, user["id"]),
-            "name": user["name"],
-            "level": user.get("level",""),
-            "mac": user.get("mac", ""),
-            "subscriber": subscriber.id }
-
-class CordUserList(APIView):
-    method_kind = "list"
-    method_name = "corduser"
-
-    def get(self, request, format=None):
-        instances=[]
-        for subscriber in CordSubscriber.get_tenant_objects().all():
-            for user in subscriber.users:
-                instances.append( serialize_user(subscriber, user) )
-
-        return Response(instances)
-
-    def post(self, request, format=None):
-        data = request.DATA
-        subscriber = CordSubscriber.get_tenant_objects().get(id=int(data["subscriber"]))
-        user = subscriber.create_user(name=data["name"],
-                                    level=data["level"],
-                                    mac=data["mac"])
-        subscriber.save()
-
-        return Response(serialize_user(subscriber,user))
-
-class CordUserDetail(APIView):
-    method_kind = "detail"
-    method_name = "corduser"
-
-    def get(self, request, format=None, pk=0):
-        parts = pk.split("-")
-        subscriber = CordSubscriber.get_tenant_objects().filter(id=parts[0])
-        for user in subscriber.users:
-            return Response( [ serialize_user(subscriber, user) ] )
-        raise XOSNotFound("Failed to find user %s" % pk)
-
-    def delete(self, request, pk):
-        parts = pk.split("-")
-        subscriber = CordSubscriber.get_tenant_objects().get(id=int(parts[0]))
-        subscriber.delete_user(parts[1])
-        subscriber.save()
-        return Response("okay")
-
-    def put(self, request, pk):
-        kwargs={}
-        if "name" in request.DATA:
-             kwargs["name"] = request.DATA["name"]
-        if "level" in request.DATA:
-             kwargs["level"] = request.DATA["level"]
-        if "mac" in request.DATA:
-             kwargs["mac"] = request.DATA["mac"]
-
-        parts = pk.split("-")
-        subscriber = CordSubscriber.get_tenant_objects().get(id=int(parts[0]))
-        user = subscriber.update_user(parts[1], **kwargs)
-        subscriber.save()
-        return Response(serialize_user(subscriber,user))
 
 #------------------------------------------------------------------------------
 # The "new" API with many more REST endpoints.
@@ -173,7 +109,7 @@
 
 class CordSubscriberViewSet(XOSViewSet):
     base_name = "subscriber"
-    method_name = "rs/subscriber"
+    method_name = "subscriber"
     method_kind = "viewset"
     queryset = CordSubscriber.get_tenant_objects().select_related().all()
     serializer_class = CordSubscriberIdSerializer
@@ -185,8 +121,8 @@
         return subscriber.vcpe
 
     @classmethod
-    def get_urlpatterns(self):
-        patterns = super(CordSubscriberViewSet, self).get_urlpatterns()
+    def get_urlpatterns(self, api_path=""):
+        patterns = super(CordSubscriberViewSet, self).get_urlpatterns(api_path=api_path)
         patterns.append( self.detail_url("vcpe_synced/$", {"get": "get_vcpe_synced"}, "vcpe_synced") )
         patterns.append( self.detail_url("url_filter/$", {"get": "get_url_filter"}, "url_filter") )
         patterns.append( self.detail_url("url_filter/(?P<level>[a-zA-Z0-9\-_]+)/$", {"put": "set_url_filter"}, "url_filter") )
@@ -204,12 +140,8 @@
 
         patterns.append( self.detail_url("bbsdump/$", {"get": "get_bbsdump"}, "bbsdump") )
 
-        patterns.append( url("^rs/initdemo/$", self.as_view({"put": "initdemo", "get": "initdemo"}), name="initdemo") )
-
-        patterns.append( url("^rs/subidlookup/(?P<ssid>[0-9\-]+)/$", self.as_view({"get": "ssiddetail"}), name="ssiddetail") )
-        patterns.append( url("^rs/subidlookup/$", self.as_view({"get": "ssidlist"}), name="ssidlist") )
-
-        patterns.append( url("^rs/vbng_mapping/$", self.as_view({"get": "get_vbng_mapping"}), name="vbng_mapping") )
+        patterns.append( url(self.api_path + "subidlookup/(?P<ssid>[0-9\-]+)/$", self.as_view({"get": "ssiddetail"}), name="ssiddetail") )
+        patterns.append( url(self.api_path + "subidlookup/$", self.as_view({"get": "ssidlist"}), name="ssidlist") )
 
         return patterns
 
@@ -368,47 +300,3 @@
 
         return Response( ssidmap[0] )
 
-    def get_vbng_mapping(self, request):
-        object_list = VBNGTenant.get_tenant_objects().all()
-
-        mappings = []
-        for vbng in object_list:
-            if vbng.mapped_ip and vbng.routeable_subnet:
-                mappings.append( {"private_ip": vbng.mapped_ip, "routeable_subnet": vbng.routeable_subnet, "mac": vbng.mapped_mac, "hostname": vbng.mapped_hostname} )
-
-        return Response( {"vbng_mapping": mappings} )
-
-class CordDebugIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
-    # Swagger is failing because CordDebugViewSet has neither a model nor
-    # a serializer_class. Stuck this in here as a placeholder for now.
-    id = ReadOnlyField()
-    class Meta:
-        model = CordSubscriber
-
-class CordDebugViewSet(XOSViewSet):
-    base_name = "cord_debug"
-    method_name = "rs/cord_debug"
-    method_kind = "viewset"
-    serializer_class = CordDebugIdSerializer
-
-    @classmethod
-    def get_urlpatterns(self):
-        patterns = []
-        patterns.append( url("^rs/cord_debug/vbng_dump/$", self.as_view({"get": "get_vbng_dump"}), name="vbng_dump"))
-        return patterns
-
-    # contact vBNG service and dump current list of mappings
-    def get_vbng_dump(self, request, pk=None):
-        result=subprocess.check_output(["curl", "http://10.0.3.136:8181/onos/virtualbng/privateip/map"])
-        if request.GET.get("theformat",None)=="text":
-            from django.http import HttpResponse
-            result = json.loads(result)["map"]
-
-            lines = []
-            for row in result:
-                for k in row.keys():
-                     lines.append( "%s %s" % (k, row[k]) )
-
-            return HttpResponse("\n".join(lines), content_type="text/plain")
-        else:
-            return Response( {"vbng_dump": json.loads(result)["map"] } )
diff --git a/xos/api/import_methods.py b/xos/api/import_methods.py
index abc62f7..a60b62d 100644
--- a/xos/api/import_methods.py
+++ b/xos/api/import_methods.py
@@ -1,17 +1,19 @@
 from django.views.generic import View
-from django.conf.urls import patterns, url
+from django.conf.urls import patterns, url, include
 from rest_framework.routers import DefaultRouter
 import os, sys
 import inspect
 import importlib
 
-def import_module_from_filename(pathname):
+urlpatterns = []
+
+def import_module_from_filename(dirname, fn):
     sys_path_save = sys.path
     try:
         # __import__() and importlib.import_module() both import modules from
         # sys.path. So we make sure that the path where we can find the views is
         # the first thing in sys.path.
-        sys.path = [dir] + sys.path
+        sys.path = [dirname] + sys.path
 
         module = __import__(fn[:-3])
     finally:
@@ -19,17 +21,18 @@
 
     return module
 
-def import_methods(dir=None, api_path="api"):
-    urlpatterns=[]
+def import_api_methods(dirname=None, api_path="api"):
     subdirs=[]
+    urlpatterns=[]
 
-    if not dir:
-        dir = os.path.dirname(os.path.abspath(__file__))
+    if not dirname:
+        dirname = os.path.dirname(os.path.abspath(__file__))
 
-    for fn in os.listdir(dir):
-        pathname = os.path.join(dir,fn)
+    view_urls = []
+    for fn in os.listdir(dirname):
+        pathname = os.path.join(dirname,fn)
         if os.path.isfile(pathname) and fn.endswith(".py") and (fn!="__init__.py"):
-            module = import_module_from_filename(fn[:-3])
+            module = import_module_from_filename(dirname, fn)
             for classname in dir(module):
                 c = getattr(module, classname, None)
 
@@ -37,12 +40,13 @@
                     globals()[classname] = c
 
                     method_kind = getattr(c, "method_kind", None)
-                    method_name = os.path.join(api_path, getattr(c, "method_name", None))
+                    method_name = getattr(c, "method_name", None)
                     if method_kind and method_name:
+                        method_name = os.path.join(api_path, method_name)
                         view_urls.append( (method_kind, method_name, classname, c) )
 
         elif os.path.isdir(pathname):
-            urlpatterns.extend(import_methods(os.path.append(dir, fn), os.path.append(api_path, fn)))
+            urlpatterns.extend(import_api_methods(pathname, os.path.join(api_path, fn)))
 
     for view_url in view_urls:
         if view_url[0] == "list":
@@ -51,7 +55,9 @@
            urlpatterns.append(url(r'^' + view_url[1] + '/(?P<pk>[a-zA-Z0-9\-]+)/$',  view_url[3].as_view(), name=view_url[1]+'detail'))
         elif view_url[0] == "viewset":
            viewset = view_url[3]
-
-           urlpatterns.extend(viewset.get_urlpatterns())
+           urlpatterns.extend(viewset.get_urlpatterns(api_path=api_path+"/"))
 
     return urlpatterns
+
+urlpatterns = import_api_methods()
+
diff --git a/xos/api/plus.py b/xos/api/xosapi_helpers.py
similarity index 70%
rename from xos/api/plus.py
rename to xos/api/xosapi_helpers.py
index 294fba8..69156af 100644
--- a/xos/api/plus.py
+++ b/xos/api/xosapi_helpers.py
@@ -29,23 +29,27 @@
         return obj.getBackendHtml()
 
 class XOSViewSet(viewsets.ModelViewSet):
+    api_path=""
+
     @classmethod
     def detail_url(self, pattern, viewdict, name):
-        return url(r'^' + self.method_name + r'/(?P<pk>[a-zA-Z0-9\-]+)/' + pattern,
+        return url(r'^' + self.api_path + self.method_name + r'/(?P<pk>[a-zA-Z0-9\-]+)/' + pattern,
                    self.as_view(viewdict),
                    name=self.base_name+"_"+name)
 
     @classmethod
     def list_url(self, pattern, viewdict, name):
-        return url(r'^' + self.method_name + r'/' + pattern,
+        return url(r'^' + self.api_path + self.method_name + r'/' + pattern,
                    self.as_view(viewdict),
                    name=self.base_name+"_"+name)
 
     @classmethod
-    def get_urlpatterns(self):
+    def get_urlpatterns(self, api_path=""):
+        self.api_path = api_path
+
         patterns = []
 
-        patterns.append(url(r'^' + self.method_name + '/$', self.as_view({'get': 'list'}), name=self.base_name+'_list'))
-        patterns.append(url(r'^' + self.method_name + '/(?P<pk>[a-zA-Z0-9\-]+)/$', self.as_view({'get': 'retrieve', 'put': 'update', 'post': 'update', 'delete': 'destroy', 'patch': 'partial_update'}), name=self.base_name+'_detail'))
+        patterns.append(url(r'^' + self.api_path + self.method_name + '/$', self.as_view({'get': 'list'}), name=self.base_name+'_list'))
+        patterns.append(url(r'^' + self.api_path + self.method_name + '/(?P<pk>[a-zA-Z0-9\-]+)/$', self.as_view({'get': 'retrieve', 'put': 'update', 'post': 'update', 'delete': 'destroy', 'patch': 'partial_update'}), name=self.base_name+'_detail'))
 
         return patterns
diff --git a/xos/xos/urls.py b/xos/xos/urls.py
index 4c3f07d..1bc3885 100644
--- a/xos/xos/urls.py
+++ b/xos/xos/urls.py
@@ -10,12 +10,11 @@
 from core.views.legacyapi import LegacyXMLRPC
 from core.views.serviceGraph import ServiceGridView, ServiceGraphView
 from services.helloworld.view import *
-#from core.views.analytics import AnalyticsAjaxView
 from core.models import *
 from rest_framework import generics
 from core.dashboard.sites import SitePlus
 from django.http import HttpResponseRedirect
-#from core.xoslib import XOSLibDataView
+#from api import import_api_methods
 
 admin.site = SitePlus()
 admin.autodiscover()
@@ -43,18 +42,17 @@
     url(r'^', include(admin.site.urls)),
     #url(r'^profile/home', 'core.views.home'),
 
-#    url(r'^admin/xoslib/(?P<name>\w+)/$', XOSLibDataView.as_view(), name="xoslib"),
-
     url(r'^xmlrpc/legacyapi/$', 'core.views.legacyapi.LegacyXMLRPC', name='xmlrpc'),
 
-#    url(r'^analytics/(?P<name>\w+)/$', AnalyticsAjaxView.as_view(), name="analytics"),
-
     url(r'^files/', redirect_to_apache),
 
-    #Adding in rest_framework urls
+    # Adding in rest_framework urls
     url(r'^xos/', include('rest_framework.urls', namespace='rest_framework')),
 
-    # XOSLib rest methods
+    # XOSLib rest methods [deprecated]
     url(r'^xoslib/', include('core.xoslib.methods', namespace='xoslib')),
+
+    url(r'^', include('api.import_methods', namespace='api')),
+
   ) + get_REST_patterns() + get_hpc_REST_patterns()