Controller replaces Deployment
diff --git a/planetstack/apigen/modelgen b/planetstack/apigen/modelgen
index 77d1e67..04ca0fa 100644
--- a/planetstack/apigen/modelgen
+++ b/planetstack/apigen/modelgen
@@ -62,10 +62,10 @@
             # These are things that either for historic reasons or due to incorrect naming,
             # got called something different than the autogen thinks they should be
             # called.
-            REST_FIXUP = {'networkdeploymentses': 'networkdeployments',
-                            'imagedeploymentses': 'imagedeployments',
-                            'slicedeploymentses': 'slicedeployments',
-                            'userdeploymentses': 'userdeployments',
+            REST_FIXUP = {'controllernetworkses': 'controllernetworks',
+                            'controllerimageses': 'controllerimages',
+                            'controllersliceses': 'controllerslices',
+                            'controlleruserses': 'controllerusers',
                             'sitedeploymentses': 'sitedeployments',
                             'siteroles': 'site_roles',
                             'sliceprivileges': 'slice_privileges',
diff --git a/planetstack/core/admin.py b/planetstack/core/admin.py
index 9ea1c36..ffa21d9 100644
--- a/planetstack/core/admin.py
+++ b/planetstack/core/admin.py
@@ -394,15 +394,15 @@
     fields = ['backend_status_icon', 'name','deployment','site']
     readonly_fields = ('backend_status_icon', )
 
-class DeploymentPrivilegeInline(PlStackTabularInline):
-    model = DeploymentPrivilege
+class ControllerPrivilegeInline(PlStackTabularInline):
+    model = ControllerPrivilege
     extra = 0
-    suit_classes = 'suit-tab suit-tab-deploymentprivileges'
-    fields = ['backend_status_icon', 'user','role','deployment']
+    suit_classes = 'suit-tab suit-tab-admin-only'
+    fields = ['backend_status_icon', 'user','role','controller']
     readonly_fields = ('backend_status_icon', )
 
     def queryset(self, request):
-        return DeploymentPrivilege.select_by_user(request.user)
+        return ControllerPrivilege.select_by_user(request.user)
 
 class SitePrivilegeInline(PlStackTabularInline):
     model = SitePrivilege
@@ -440,6 +440,24 @@
     def queryset(self, request):
         return SiteDeployments.select_by_user(request.user)
 
+class ControllerSitesInline(PlStackTabularInline):
+    model = ControllerSites
+    extra = 0
+    suit_classes = 'suit-tab suit-tab-admin-only'
+    fields = ['backend_status_icon', 'controller','site']
+    readonly_fields = ('backend_status_icon', )
+
+    def formfield_for_foreignkey(self, db_field, request, **kwargs):
+        if db_field.name == 'site':
+            kwargs['queryset'] = Site.select_by_user(request.user)
+
+        if db_field.name == 'controller':
+            kwargs['queryset'] = Controller.select_by_user(request.user)
+        return super(ControllerSitesInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
+    def queryset(self, request):
+        return ControllerSites.select_by_user(request.user)
+
 
 class SlicePrivilegeInline(PlStackTabularInline):
     model = SlicePrivilege
@@ -475,7 +493,16 @@
     verbose_name = "Image Deployments"
     verbose_name_plural = "Image Deployments"
     suit_classes = 'suit-tab suit-tab-imagedeployments'
-    fields = ['backend_status_icon', 'image', 'deployment', 'glance_image_id']
+    fields = ['backend_status_icon', 'image', 'deployment']
+    readonly_fields = ['backend_status_icon']
+
+class ControllerImagesInline(PlStackTabularInline):
+    model = ControllerImages
+    extra = 0
+    verbose_name = "Controller Images"
+    verbose_name_plural = "Controller Images"
+    suit_classes = 'suit-tab suit-tab-admin-only'
+    fields = ['backend_status_icon', 'image', 'controller', 'glance_image_id']
     readonly_fields = ['backend_status_icon', 'glance_image_id']
 
 class SliceRoleAdmin(PlanetStackBaseAdmin):
@@ -575,7 +602,7 @@
         #    a better way...
 
         self.manipulate_m2m_objs(deployment, self.cleaned_data['sites'], deployment.sitedeployments.all(), SiteDeployments, "deployment", "site")
-        self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments.all(), ImageDeployments, "deployment", "image")
+        self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments.all(), ControllerImages, "deployment", "image")
 
       self.save_m2m()
 
@@ -594,7 +621,7 @@
     model = Deployment
     fieldList = ['backend_status_text', 'name', 'availability_zone', 'sites', 'images', 'flavors', 'accessControl']
     fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
-    inlines = [DeploymentPrivilegeInline,NodeInline,TagInline] # ,ImageDeploymentsInline]
+    inlines = [ControllerPrivilegeInline,NodeInline,TagInline] # ,ControllerImagesInline]
     list_display = ['backend_status_icon', 'name']
     list_display_links = ('backend_status_icon', 'name', )
     readonly_fields = ('backend_status_text', )
@@ -762,13 +789,13 @@
             raise forms.ValidationError('slice name must begin with %s' % site.login_base)
         return cleaned_data
 
-class SliceDeploymentsInline(PlStackTabularInline):
-    model = SliceDeployments
+class ControllerSlicesInline(PlStackTabularInline):
+    model = ControllerSlices
     extra = 0
-    verbose_name = "Slice Deployment"
-    verbose_name_plural = "Slice Deployments"
+    verbose_name = "Controller Slices"
+    verbose_name_plural = "Controller Slices"
     suit_classes = 'suit-tab suit-tab-admin-only'
-    fields = ['backend_status_icon', 'deployment', 'tenant_id']
+    fields = ['backend_status_icon', 'controller', 'tenant_id']
     readonly_fields = ('backend_status_icon', )
 
 class SliceAdmin(PlanetStackBaseAdmin):
@@ -779,7 +806,7 @@
     list_display = ('backend_status_icon', 'name', 'site','serviceClass', 'slice_url', 'max_slivers')
     list_display_links = ('backend_status_icon', 'name', )
     inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
-    admin_inlines = [SliceDeploymentsInline]
+    admin_inlines = [ControllerSlicesInline]
 
     user_readonly_fields = fieldList
 
@@ -821,10 +848,10 @@
             for deployment in flavor.deployments.all():
                 deployment_flavors.append( (deployment.id, flavor.id, flavor.name) )
 
-        deployment_images = []
+        controller_images = []
         for image in Image.objects.all():
-            for imageDeployment in image.imagedeployments.all():
-                deployment_images.append( (imageDeployment.deployment.id, image.id, image.name) )
+            for controller_image in image.controllerimages.all():
+                controller_images.append( (controller_image.controller.id, image.id, image.name) )
 
         site_login_bases = []
         for site in Site.objects.all():
@@ -904,9 +931,9 @@
                ]
     readonly_fields = ('backend_status_text', )
 
-    suit_form_tabs =(('general','Image Details'),('slivers','Slivers'),('imagedeployments','Deployments'))
+    suit_form_tabs =(('general','Image Details'),('slivers','Slivers'),('imagedeployments','Deployments'), ('controllerimages', 'Controllers'))
 
-    inlines = [SliverInline, ImageDeploymentsInline]
+    inlines = [SliverInline, ControllerImagesInline]
 
     user_readonly_fields = ['name', 'disk_format', 'container_format']
 
@@ -1085,7 +1112,7 @@
     # that reference specific fields on auth.User.
     list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
     list_filter = ('site',)
-    inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline,UserDashboardViewInline]
+    inlines = [SlicePrivilegeInline,SitePrivilegeInline,ControllerPrivilegeInline,UserDashboardViewInline]
 
     fieldListLoginDetails = ['backend_status_text', 'email','site','password','is_active','is_readonly','is_admin','public_key']
     fieldListContactInfo = ['firstname','lastname','phone','timezone']
@@ -1118,7 +1145,7 @@
                          ('contact','Contact Information'),
                          ('sliceprivileges','Slice Privileges'),
                          ('siteprivileges','Site Privileges'),
-                         ('deploymentprivileges','Deployment Privileges'),
+                         ('controllerprivileges','Controller Privileges'),
                          ('dashboards','Dashboard Views'))
 
     def formfield_for_foreignkey(self, db_field, request, **kwargs):
@@ -1339,13 +1366,13 @@
     fields = ['backend_status_icon', 'network','slice']
     readonly_fields = ('backend_status_icon', )
 
-class NetworkDeploymentsInline(PlStackTabularInline):
-    model = NetworkDeployments
+class ControllerNetworksInline(PlStackTabularInline):
+    model = ControllerNetworks
     extra = 0
-    verbose_name_plural = "Network Deployments"
-    verbose_name = "Network Deployment"
+    verbose_name_plural = "Controller Networks"
+    verbose_name = "Controller Network"
     suit_classes = 'suit-tab suit-tab-admin-only'
-    fields = ['backend_status_icon', 'deployment','net_id','subnet_id']
+    fields = ['backend_status_icon', 'controller','net_id','subnet_id']
     readonly_fields = ('backend_status_icon', )
 
 class NetworkForm(forms.ModelForm):
@@ -1362,7 +1389,7 @@
     readonly_fields = ("subnet", )
 
     inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
-    admin_inlines = [NetworkDeploymentsInline]
+    admin_inlines = [ControllerNetworksInline]
 
     form=NetworkForm
 
@@ -1544,6 +1571,7 @@
 showAll = False
 
 admin.site.register(Deployment, DeploymentAdmin)
+admin.site.register(Controller, ControllerAdmin)
 admin.site.register(Site, SiteAdmin)
 admin.site.register(Slice, SliceAdmin)
 admin.site.register(Service, ServiceAdmin)
@@ -1559,7 +1587,7 @@
     admin.site.register(ServiceClass, ServiceClassAdmin)
     #admin.site.register(PlanetStack)
     admin.site.register(Tag, TagAdmin)
-    admin.site.register(DeploymentRole)
+    admin.site.register(ControllerRole)
     admin.site.register(SiteRole)
     admin.site.register(SliceRole)
     admin.site.register(PlanetStackRole)
diff --git a/planetstack/core/models/__init__.py b/planetstack/core/models/__init__.py
index ae5c89b..423fe0b 100644
--- a/planetstack/core/models/__init__.py
+++ b/planetstack/core/models/__init__.py
@@ -5,14 +5,14 @@
 from .service import ServiceAttribute
 from .tag import Tag
 from .role import Role
-from .site import Site,Deployment, DeploymentRole, DeploymentPrivilege, SiteDeployments, ControllerSites
+from .site import Site, Deployment, Controller, ControllerRole, ControllerPrivilege, SiteDeployments, ControllerSites
 from .dashboard import DashboardView
 from .user import User, UserDashboardView
 from .serviceclass import ServiceClass
 from .site import ControllerLinkManager,ControllerLinkDeletionManager
 from .slice import Slice, ControllerSlices
 from .controllerusers import ControllerUsers
-from .image import Image, ControllerImages
+from .image import Image, ImageDeployments, ControllerImages
 from .node import Node
 from .serviceresource import ServiceResource
 from .slice import SliceRole
diff --git a/planetstack/core/models/controllerusers.py b/planetstack/core/models/controllerusers.py
new file mode 100644
index 0000000..5a3568a
--- /dev/null
+++ b/planetstack/core/models/controllerusers.py
@@ -0,0 +1,26 @@
+import os
+import datetime
+from collections import defaultdict
+from django.db import models
+from django.db.models import F, Q
+from core.models import PlCoreBase,User,Controller
+from core.models import Controller,ControllerLinkManager,ControllerLinkDeletionManager
+
+class ControllerUsers(PlCoreBase):
+    objects = ControllerLinkManager()
+    deleted_objects = ControllerLinkDeletionManager()
+
+    user = models.ForeignKey(User,related_name='controllerusers')
+    controller = models.ForeignKey(Controller,related_name='controllersusers')
+    kuser_id = models.CharField(null=True, blank=True, max_length=200, help_text="Keystone user id")
+
+    def __unicode__(self):  return u'%s %s' % (self.controller, self.user)
+
+    @staticmethod
+    def select_by_user(user):
+        if user.is_admin:
+            qs = ControllerUsers.objects.all()
+        else:
+            users = Users.select_by_user(user)
+            qs = ControllerUsers.objects.filter(user__in=users)
+        return qs
diff --git a/planetstack/core/models/credential.py b/planetstack/core/models/credential.py
index b74e540..0f80bb8 100644
--- a/planetstack/core/models/credential.py
+++ b/planetstack/core/models/credential.py
@@ -1,9 +1,9 @@
 import os
 from django.db import models
 from core.models import PlCoreBase
-from core.models import User,Site,Slice,Deployment
+from core.models import User,Site,Slice,Controller
 from encrypted_fields import EncryptedCharField
-from core.models import Deployment,DeploymentLinkManager,DeploymentLinkDeletionManager
+from core.models import Controller,ControllerLinkManager,ControllerLinkDeletionManager
 
 class UserCredential(PlCoreBase):
     user = models.ForeignKey(User, related_name='usercredentials', help_text="The User this credential is associated with")
@@ -38,10 +38,10 @@
     def __unicode__(self):
         return self.name
 
-class DeploymentCredential(PlCoreBase):
-    objects = DeploymentLinkManager()
-    deleted_objects = DeploymentLinkDeletionManager()
-    deployment = models.ForeignKey(Deployment, related_name='deploymentcredentials', help_text="The User this credential is associated with")
+class ControllerCredential(PlCoreBase):
+    objects = ControllerLinkManager()
+    deleted_objects = ControllerLinkDeletionManager()
+    controller = models.ForeignKey(Controller, related_name='controllercredentials', help_text="The User this credential is associated with")
 
     name = models.SlugField(help_text="The credential type, e.g. ec2", max_length=128)
     key_id = models.CharField(help_text="The backend id of this credential", max_length=1024)
diff --git a/planetstack/core/models/image.py b/planetstack/core/models/image.py
index a7b63b6..4399c60 100644
--- a/planetstack/core/models/image.py
+++ b/planetstack/core/models/image.py
@@ -1,7 +1,7 @@
 import os
 from django.db import models
 from core.models import PlCoreBase
-from core.models import Controller,ControllerLinkManager,ControllerLinkDeletionManager
+from core.models import Deployment,Controller,ControllerLinkManager,ControllerLinkDeletionManager
 
 # Create your models here.
 
@@ -13,6 +13,12 @@
 
     def __unicode__(self):  return u'%s' % (self.name)
 
+class ImageDeployments(PlCoreBase):
+    image = models.ForeignKey(Image,related_name='imagedeployments')
+    deployment = models.ForeignKey(Deployment,related_name='imagedeployments')
+
+    def __unicode__(self):  return u'%s %s' % (self.image, self.deployment)
+
 class ControllerImages(PlCoreBase):
     objects = ControllerLinkManager()
     deleted_objects = ControllerLinkDeletionManager()
diff --git a/planetstack/core/models/node.py b/planetstack/core/models/node.py
index 903c25f..6ef3a47 100644
--- a/planetstack/core/models/node.py
+++ b/planetstack/core/models/node.py
@@ -1,7 +1,7 @@
 import os
 from django.db import models
 from core.models import PlCoreBase
-from core.models import SiteDeployment, Controller
+from core.models import SiteDeployments, Controller
 from core.models import Tag
 from django.contrib.contenttypes import generic
 
@@ -9,7 +9,7 @@
 
 class Node(PlCoreBase):
     name = models.CharField(max_length=200, unique=True, help_text="Name of the Node")
-    site_deployment = models.ForeignKey(SiteDeployment, related_name='nodes')
+    site_deployment = models.ForeignKey(SiteDeployments, related_name='nodes')
     tags = generic.GenericRelation(Tag)
 
     def __unicode__(self):  return u'%s' % (self.name)
diff --git a/planetstack/core/models/site.py b/planetstack/core/models/site.py
index 5381a08..ae07fc0 100644
--- a/planetstack/core/models/site.py
+++ b/planetstack/core/models/site.py
@@ -12,7 +12,7 @@
 
 class ControllerLinkDeletionManager(PlCoreBaseDeletionManager):
     def get_queryset(self):
-        parent=super(DeploymentLinkDeletionManager, self)
+        parent=super(ControllerLinkDeletionManager, self)
         try:
             backend_type = config.observer_backend_type
         except AttributeError:
@@ -72,7 +72,7 @@
 
 class ControllerManager(PlCoreBaseManager):
     def get_queryset(self):
-        parent=super(DeploymentManager, self)
+        parent=super(ControllerManager, self)
 
         try:
             backend_type = config.observer_backend_type
@@ -166,7 +166,7 @@
         return qs
 
 class Deployment(PlCoreBase):
-    #objects = DeploymentManager()
+    #objects = Controllermanager()
     #deleted_objects = DeploymentDeletionManager()
     name = models.CharField(max_length=200, unique=True, help_text="Name of the Deployment")
     #admin_user = models.CharField(max_length=200, null=True, blank=True, help_text="Username of an admin user at this deployment")
@@ -217,8 +217,8 @@
     def __unicode__(self):  return u'%s' % (self.name)
 
 class ControllerRole(PlCoreBase):
-    #objects = DeploymentLinkManager()
-    #deleted_objects = DeploymentLinkDeletionManager()
+    #objects = ControllerLinkManager()
+    #deleted_objects = ControllerLinkDeletionManager()
 
     ROLE_CHOICES = (('admin','Admin'),)
     role = models.CharField(choices=ROLE_CHOICES, unique=True, max_length=30)
@@ -256,8 +256,8 @@
         return qs 
 
 class SiteDeployments(PlCoreBase):
-    #objects = DeploymentLinkManager()
-    #deleted_objects = DeploymentLinkDeletionManager()
+    #objects = ControllerLinkManager()
+    #deleted_objects = ControllerLinkDeletionManager()
     objects = ControllerManager()
     deleted_objects = ControllerDeletionManager()
 
diff --git a/planetstack/core/models/sliver.py b/planetstack/core/models/sliver.py
index c4789d6..c4449fe 100644
--- a/planetstack/core/models/sliver.py
+++ b/planetstack/core/models/sliver.py
@@ -17,13 +17,13 @@
 
 config = Config()
 
-def get_default_flavor(deployment = None):
+def get_default_flavor(controller = None):
     # Find a default flavor that can be used for a sliver. This is particularly
     # useful in evolution. It's also intended this helper function can be used
     # for admin.py when users
 
-    if deployment:
-        flavors = deployment.flavors.all()
+    if controller:
+        flavors = controller.flavors.all()
     else:
         flavors = Flavor.objects.all()
 
@@ -88,7 +88,7 @@
     creator = models.ForeignKey(User, related_name='slivers', blank=True, null=True)
     slice = models.ForeignKey(Slice, related_name='slivers')
     node = models.ForeignKey(Node, related_name='slivers')
-    deploymentNetwork = models.ForeignKey(Deployment, verbose_name='deployment', related_name='sliver_deploymentNetwork')
+    controllerNetwork = models.ForeignKey(Deployment, verbose_name='controller', related_name='sliver_controllerNetwork')
     numberCores = models.IntegerField(verbose_name="Number of Cores", help_text="Number of cores for sliver", default=0)
     flavor = models.ForeignKey(Flavor, help_text="Flavor of this instance", default=get_default_flavor)
     tags = generic.GenericRelation(Tag)
@@ -108,11 +108,11 @@
         self.name = self.slice.slicename
         if not self.creator and hasattr(self, 'caller'):
             self.creator = self.caller
-        self.deploymentNetwork = self.node.deployment
+        self.controllerNetwork = self.node.controller
 
 # XXX smbaker - disabled for now, was causing fault in tenant view create slice
-#        if not self.deploymentNetwork.test_acl(slice=self.slice):
-#            raise exceptions.ValidationError("Deployment %s's ACL does not allow any of this slice %s's users" % (self.deploymentNetwork.name, self.slice.name))
+#        if not self.controllerNetwork.test_acl(slice=self.slice):
+#            raise exceptions.ValidationError("Deployment %s's ACL does not allow any of this slice %s's users" % (self.controllerNetwork.name, self.slice.name))
 
         super(Sliver, self).save(*args, **kwds)
 
diff --git a/planetstack/genapi.py b/planetstack/genapi.py
index 2510db9..13c41d4 100644
--- a/planetstack/genapi.py
+++ b/planetstack/genapi.py
@@ -58,8 +58,8 @@
         url(r'plstackapi/networkslivers/$', NetworkSliverList.as_view(), name='networksliver-list'),
         url(r'plstackapi/networkslivers/(?P<pk>[a-zA-Z0-9\-]+)/$', NetworkSliverDetail.as_view(), name ='networksliver-detail'),
     
-        url(r'plstackapi/networkdeployments/$', NetworkDeploymentsList.as_view(), name='networkdeployments-list'),
-        url(r'plstackapi/networkdeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', NetworkDeploymentsDetail.as_view(), name ='networkdeployments-detail'),
+        url(r'plstackapi/controllernetworks/$', ControllerNetworksList.as_view(), name='controllernetworks-list'),
+        url(r'plstackapi/controllernetworks/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerNetworksDetail.as_view(), name ='controllernetworks-detail'),
     
         url(r'plstackapi/flavors/$', FlavorList.as_view(), name='flavor-list'),
         url(r'plstackapi/flavors/(?P<pk>[a-zA-Z0-9\-]+)/$', FlavorDetail.as_view(), name ='flavor-detail'),
@@ -106,8 +106,8 @@
         url(r'plstackapi/dashboardviews/$', DashboardViewList.as_view(), name='dashboardview-list'),
         url(r'plstackapi/dashboardviews/(?P<pk>[a-zA-Z0-9\-]+)/$', DashboardViewDetail.as_view(), name ='dashboardview-detail'),
     
-        url(r'plstackapi/imagedeployments/$', ImageDeploymentsList.as_view(), name='imagedeployments-list'),
-        url(r'plstackapi/imagedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', ImageDeploymentsDetail.as_view(), name ='imagedeployments-detail'),
+        url(r'plstackapi/controllerimages/$', ControllerImagesList.as_view(), name='controllerimages-list'),
+        url(r'plstackapi/controllerimages/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerImagesDetail.as_view(), name ='controllerimages-detail'),
     
         url(r'plstackapi/reservedresources/$', ReservedResourceList.as_view(), name='reservedresource-list'),
         url(r'plstackapi/reservedresources/(?P<pk>[a-zA-Z0-9\-]+)/$', ReservedResourceDetail.as_view(), name ='reservedresource-detail'),
@@ -126,12 +126,14 @@
     
         url(r'plstackapi/deployments/$', DeploymentList.as_view(), name='deployment-list'),
         url(r'plstackapi/deployments/(?P<pk>[a-zA-Z0-9\-]+)/$', DeploymentDetail.as_view(), name ='deployment-detail'),
+        url(r'plstackapi/Controller/$', ControllerList.as_view(), name='controller-list'),
+        url(r'plstackapi/Controller/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerDetail.as_view(), name ='controller-detail'),
     
         url(r'plstackapi/reservations/$', ReservationList.as_view(), name='reservation-list'),
         url(r'plstackapi/reservations/(?P<pk>[a-zA-Z0-9\-]+)/$', ReservationDetail.as_view(), name ='reservation-detail'),
     
-        url(r'plstackapi/slicedeployments/$', SliceDeploymentsList.as_view(), name='slicedeployments-list'),
-        url(r'plstackapi/slicedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', SliceDeploymentsDetail.as_view(), name ='slicedeployments-detail'),
+        url(r'plstackapi/controllerslices/$', ControllerSlicesList.as_view(), name='controllerslices-list'),
+        url(r'plstackapi/controllerslices/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerSlicesDetail.as_view(), name ='controllerslices-detail'),
     
         url(r'plstackapi/siteprivileges/$', SitePrivilegeList.as_view(), name='siteprivilege-list'),
         url(r'plstackapi/siteprivileges/(?P<pk>[a-zA-Z0-9\-]+)/$', SitePrivilegeDetail.as_view(), name ='siteprivilege-detail'),
@@ -139,8 +141,8 @@
         url(r'plstackapi/planetstacks/$', PlanetStackList.as_view(), name='planetstack-list'),
         url(r'plstackapi/planetstacks/(?P<pk>[a-zA-Z0-9\-]+)/$', PlanetStackDetail.as_view(), name ='planetstack-detail'),
     
-        url(r'plstackapi/userdeployments/$', UserDeploymentsList.as_view(), name='userdeployments-list'),
-        url(r'plstackapi/userdeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', UserDeploymentsDetail.as_view(), name ='userdeployments-detail'),
+        url(r'plstackapi/controllerusers/$', ControllerUsersList.as_view(), name='controllerusers-list'),
+        url(r'plstackapi/controllerusers/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerUsersDetail.as_view(), name ='controllerusers-detail'),
     
         url(r'plstackapi/accounts/$', AccountList.as_view(), name='account-list'),
         url(r'plstackapi/accounts/(?P<pk>[a-zA-Z0-9\-]+)/$', AccountDetail.as_view(), name ='account-detail'),
@@ -151,17 +153,19 @@
         url(r'plstackapi/sitecredentials/$', SiteCredentialList.as_view(), name='sitecredential-list'),
         url(r'plstackapi/sitecredentials/(?P<pk>[a-zA-Z0-9\-]+)/$', SiteCredentialDetail.as_view(), name ='sitecredential-detail'),
     
-        url(r'plstackapi/deploymentprivileges/$', DeploymentPrivilegeList.as_view(), name='deploymentprivilege-list'),
-        url(r'plstackapi/deploymentprivileges/(?P<pk>[a-zA-Z0-9\-]+)/$', DeploymentPrivilegeDetail.as_view(), name ='deploymentprivilege-detail'),
+        url(r'plstackapi/controllerprivileges/$', ControllerPrivilegeList.as_view(), name='controllerprivilege-list'),
+        url(r'plstackapi/controllerprivileges/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerPrivilegeDetail.as_view(), name ='controllerprivilege-detail'),
     
-        url(r'plstackapi/deploymentroles/$', DeploymentRoleList.as_view(), name='deploymentrole-list'),
-        url(r'plstackapi/deploymentroles/(?P<pk>[a-zA-Z0-9\-]+)/$', DeploymentRoleDetail.as_view(), name ='deploymentrole-detail'),
+        url(r'plstackapi/controllerroles/$', ControllerRoleList.as_view(), name='controllerrole-list'),
+        url(r'plstackapi/controllerroles/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerRoleDetail.as_view(), name ='controllerrole-detail'),
     
         url(r'plstackapi/usercredentials/$', UserCredentialList.as_view(), name='usercredential-list'),
         url(r'plstackapi/usercredentials/(?P<pk>[a-zA-Z0-9\-]+)/$', UserCredentialDetail.as_view(), name ='usercredential-detail'),
     
         url(r'plstackapi/sitedeployments/$', SiteDeploymentsList.as_view(), name='sitedeployments-list'),
         url(r'plstackapi/sitedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', SiteDeploymentsDetail.as_view(), name ='sitedeployments-detail'),
+        url(r'plstackapi/controllersites/$', ControllerSitesList.as_view(), name='sitedeployments-list'),
+        url(r'plstackapi/controllersites/(?P<pk>[a-zA-Z0-9\-]+)/$', ControllerSitesDetail.as_view(), name ='sitedeployments-detail'),
     
         url(r'plstackapi/slicetags/$', SliceTagList.as_view(), name='slicetag-list'),
         url(r'plstackapi/slicetags/(?P<pk>[a-zA-Z0-9\-]+)/$', SliceTagDetail.as_view(), name ='slicetag-detail'),
@@ -190,7 +194,7 @@
         'sliceprivileges': reverse('sliceprivilege-list', request=request, format=format),
         'planetstackroles': reverse('planetstackrole-list', request=request, format=format),
         'networkslivers': reverse('networksliver-list', request=request, format=format),
-        'networkdeploymentses': reverse('networkdeployments-list', request=request, format=format),
+        'controllernetworkses': reverse('controllernetworks-list', request=request, format=format),
         'flavors': reverse('flavor-list', request=request, format=format),
         'projects': reverse('project-list', request=request, format=format),
         'slices': reverse('slice-list', request=request, format=format),
@@ -206,25 +210,27 @@
         'slivers': reverse('sliver-list', request=request, format=format),
         'nodes': reverse('node-list', request=request, format=format),
         'dashboardviews': reverse('dashboardview-list', request=request, format=format),
-        'imagedeploymentses': reverse('imagedeployments-list', request=request, format=format),
+        'controllerimageses': reverse('controllerimages-list', request=request, format=format),
         'reservedresources': reverse('reservedresource-list', request=request, format=format),
         'networkslices': reverse('networkslice-list', request=request, format=format),
         'userdashboardviews': reverse('userdashboardview-list', request=request, format=format),
         'planetstackprivileges': reverse('planetstackprivilege-list', request=request, format=format),
         'users': reverse('user-list', request=request, format=format),
         'deployments': reverse('deployment-list', request=request, format=format),
+        'controllers': reverse('controller-list', request=request, format=format),
         'reservations': reverse('reservation-list', request=request, format=format),
-        'slicedeploymentses': reverse('slicedeployments-list', request=request, format=format),
+        'controllersliceses': reverse('controllerslices-list', request=request, format=format),
         'siteprivileges': reverse('siteprivilege-list', request=request, format=format),
         'planetstacks': reverse('planetstack-list', request=request, format=format),
-        'userdeploymentses': reverse('userdeployments-list', request=request, format=format),
+        'controlleruserses': reverse('controllerusers-list', request=request, format=format),
         'accounts': reverse('account-list', request=request, format=format),
         'networkparametertypes': reverse('networkparametertype-list', request=request, format=format),
         'sitecredentials': reverse('sitecredential-list', request=request, format=format),
-        'deploymentprivileges': reverse('deploymentprivilege-list', request=request, format=format),
-        'deploymentroles': reverse('deploymentrole-list', request=request, format=format),
+        'controllerprivileges': reverse('controllerprivilege-list', request=request, format=format),
+        'controllerroles': reverse('controllerrole-list', request=request, format=format),
         'usercredentials': reverse('usercredential-list', request=request, format=format),
         'sitedeploymentses': reverse('sitedeployments-list', request=request, format=format),
+        'controllersiteses': reverse('controllersites-list', request=request, format=format),
         'slicetags': reverse('slicetag-list', request=request, format=format),
         'networktemplates': reverse('networktemplate-list', request=request, format=format),
         'routers': reverse('router-list', request=request, format=format),
@@ -586,7 +592,7 @@
 
 
 
-class NetworkDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
+class ControllerNetworksSerializer(serializers.HyperlinkedModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -599,10 +605,10 @@
         except:
             return None
     class Meta:
-        model = NetworkDeployments
+        model = ControllerNetworks
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','network','deployment','net_id','router_id','subnet_id','subnet',)
 
-class NetworkDeploymentsIdSerializer(serializers.ModelSerializer):
+class ControllerNetworksIdSerializer(serializers.ModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -615,7 +621,7 @@
         except:
             return None

     class Meta:
-        model = NetworkDeployments
+        model = ControllerNetworks
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','network','deployment','net_id','router_id','subnet_id','subnet',)
 
 
@@ -1226,7 +1232,7 @@
 
 
 
-class ImageDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
+class ControllerImagesSerializer(serializers.HyperlinkedModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1239,10 +1245,10 @@
         except:
             return None
     class Meta:
-        model = ImageDeployments
+        model = ControllerImages
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
 
-class ImageDeploymentsIdSerializer(serializers.ModelSerializer):
+class ControllerImagesIdSerializer(serializers.ModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1255,7 +1261,7 @@
         except:
             return None

     class Meta:
-        model = ImageDeployments
+        model = ControllerImages
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
 
 
@@ -1358,7 +1364,7 @@
         try:
             return obj.getValidators()
         except:
-            return None

+            return None
     class Meta:
         model = UserDashboardView
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','user','dashboardView','order',)
@@ -1371,7 +1377,7 @@
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
     validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):

+    def getHumanReadableName(self, obj):
         return str(obj)
     def getValidators(self, obj):
         try:
@@ -1387,13 +1393,13 @@
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
     validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):

-        return str(obj)

-    def getValidators(self, obj):

+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
         try:
             return obj.getValidators()
         except:
-            return None

+            return None
     class Meta:
         model = PlanetStackPrivilege
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','user','planetstack','role',)
@@ -1406,7 +1412,7 @@
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
     validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):

+    def getHumanReadableName(self, obj):
         return str(obj)
     def getValidators(self, obj):
         try:
@@ -1422,13 +1428,13 @@
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
     validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):

-        return str(obj)

-    def getValidators(self, obj):

+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
         try:
             return obj.getValidators()
         except:
-            return None

+            return None
     class Meta:
         model = User
         fields = ('humanReadableName', 'validators', 'id','password','last_login','email','username','firstname','lastname','phone','user_url','site','public_key','is_active','is_admin','is_staff','is_readonly','created','updated','enacted','backend_status','deleted','timezone',)
@@ -1457,7 +1463,7 @@
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
     validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):

+    def getHumanReadableName(self, obj):
         return str(obj)
     def getValidators(self, obj):
         try:
@@ -1466,7 +1472,25 @@
             return None
     class Meta:
         model = Deployment
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','name','admin_user','admin_password','admin_tenant','auth_url','backend_type','availability_zone','accessControl','sites','sites','flavors','flavors',)
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','name','accessControl','sites','sites','flavors','flavors',)
+
+
+class ControllerSerializer(serializers.HyperlinkedModelSerializer):
+    id = serializers.Field()
+    site_deployments = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='sitedeployment-detail')
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    validators = serializers.SerializerMethodField("getValidators")
+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
+        try:
+            return obj.getValidators()
+        except:
+            return None
+    class Meta:
+        model = Controller
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','admin_user','admin_password','admin_tenant','auth_url','backend_type','availability_zone','accessControl',)
+
 
 class DeploymentIdSerializer(serializers.ModelSerializer):
     id = serializers.Field()
@@ -1501,6 +1525,38 @@
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','name','admin_user','admin_password','admin_tenant','auth_url','backend_type','availability_zone','accessControl','sites','sites','flavors','flavors',)
 
 
+class ControllerSerializer(serializers.HyperlinkedModelSerializer):
+    id = serializers.Field()
+    site_deployments = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='sitedeployment-detail')
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    validators = serializers.SerializerMethodField("getValidators")
+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
+        try:
+            return obj.getValidators()
+        except:
+            return None
+    class Meta:
+        model = Controller
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','admin_user','admin_password','admin_tenant','auth_url','backend_type')
+
+
+class ControllerIdSerializer(serializers.ModelSerializer):
+    id = serializers.Field()
+    sites = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='site-detail')
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    validators = serializers.SerializerMethodField("getValidators")
+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
+        try:
+            return obj.getValidators()
+        except:
+            return None
+    class Meta:
+        model = Controller 
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','admin_user','admin_password','admin_tenant','auth_url','backend_type')
 
 
 class ReservationSerializer(serializers.HyperlinkedModelSerializer):
@@ -1538,7 +1594,7 @@
 
 
 
-class SliceDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
+class ControllerSlicesSerializer(serializers.HyperlinkedModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1551,10 +1607,10 @@
         except:
             return None
     class Meta:
-        model = SliceDeployments
+        model = ControllerSlices
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
 
-class SliceDeploymentsIdSerializer(serializers.ModelSerializer):
+class ControllerSlicesIdSerializer(serializers.ModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1567,7 +1623,7 @@
         except:
             return None

     class Meta:
-        model = SliceDeployments
+        model = ControllerSlices
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
 
 
@@ -1643,7 +1699,7 @@
 
 
 
-class UserDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
+class ControllerUsersSerializer(serializers.HyperlinkedModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1656,10 +1712,10 @@
         except:
             return None
     class Meta:
-        model = UserDeployments
+        model = ControllerUsers
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','user','deployment','kuser_id',)
 
-class UserDeploymentsIdSerializer(serializers.ModelSerializer):
+class ControllerUsersIdSerializer(serializers.ModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1672,7 +1728,7 @@
         except:
             return None

     class Meta:
-        model = UserDeployments
+        model = ControllerUsers
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','user','deployment','kuser_id',)
 
 
@@ -1783,7 +1839,7 @@
 
 
 
-class DeploymentPrivilegeSerializer(serializers.HyperlinkedModelSerializer):
+class ControllerPrivilegeSerializer(serializers.HyperlinkedModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1796,10 +1852,10 @@
         except:
             return None
     class Meta:
-        model = DeploymentPrivilege
+        model = ControllerPrivilege
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','user','deployment','role',)
 
-class DeploymentPrivilegeIdSerializer(serializers.ModelSerializer):
+class ControllerPrivilegeIdSerializer(serializers.ModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1812,13 +1868,13 @@
         except:
             return None

     class Meta:
-        model = DeploymentPrivilege
+        model = ControllerPrivilege
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','user','deployment','role',)
 
 
 
 
-class DeploymentRoleSerializer(serializers.HyperlinkedModelSerializer):
+class ControllerRoleSerializer(serializers.HyperlinkedModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1831,10 +1887,10 @@
         except:
             return None
     class Meta:
-        model = DeploymentRole
+        model = ControllerRole
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','role',)
 
-class DeploymentRoleIdSerializer(serializers.ModelSerializer):
+class ControllerRoleIdSerializer(serializers.ModelSerializer):
     id = serializers.Field()
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
@@ -1847,7 +1903,7 @@
         except:
             return None

     class Meta:
-        model = DeploymentRole
+        model = ControllerRole
         fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','role',)
 
 
@@ -1918,9 +1974,40 @@
             return None

     class Meta:
         model = SiteDeployments
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','site','deployment')
 
 
+class ControllerSitesSerializer(serializers.HyperlinkedModelSerializer):
+    id = serializers.Field()
+
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    validators = serializers.SerializerMethodField("getValidators")
+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
+        try:
+            return obj.getValidators()
+        except:
+            return None
+    class Meta:
+        model = ControllerSites
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','site_deployment','controller','tenant_id',)
+
+class ControllerSitesIdSerializer(serializers.ModelSerializer):
+    id = serializers.Field()
+
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    validators = serializers.SerializerMethodField("getValidators")
+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
+        try:
+            return obj.getValidators()
+        except:
+            return None
+    class Meta:
+        model = ControllerSites
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','backend_status','deleted','site_deployment','controller','tenant_id',)
 
 
 class SliceTagSerializer(serializers.HyperlinkedModelSerializer):
@@ -2085,7 +2172,7 @@
 
                  NetworkSliver: NetworkSliverSerializer,
 
-                 NetworkDeployments: NetworkDeploymentsSerializer,
+                 ControllerNetworks: ControllerNetworksSerializer,
 
                  Flavor: FlavorSerializer,
 
@@ -2117,7 +2204,7 @@
 
                  DashboardView: DashboardViewSerializer,
 
-                 ImageDeployments: ImageDeploymentsSerializer,
+                 ControllerImages: ControllerImagesSerializer,
 
                  ReservedResource: ReservedResourceSerializer,
 
@@ -2133,13 +2220,13 @@
 
                  Reservation: ReservationSerializer,
 
-                 SliceDeployments: SliceDeploymentsSerializer,
+                 ControllerSlices: ControllerSlicesSerializer,
 
                  SitePrivilege: SitePrivilegeSerializer,
 
                  PlanetStack: PlanetStackSerializer,
 
-                 UserDeployments: UserDeploymentsSerializer,
+                 ControllerUsers: ControllerUsersSerializer,
 
                  Account: AccountSerializer,
 
@@ -2147,9 +2234,9 @@
 
                  SiteCredential: SiteCredentialSerializer,
 
-                 DeploymentPrivilege: DeploymentPrivilegeSerializer,
+                 ControllerPrivilege: ControllerPrivilegeSerializer,
 
-                 DeploymentRole: DeploymentRoleSerializer,
+                 ControllerRole: ControllerRoleSerializer,
 
                  UserCredential: UserCredentialSerializer,
 
@@ -2808,10 +2895,10 @@
 
 
 
-class NetworkDeploymentsList(generics.ListCreateAPIView):
-    queryset = NetworkDeployments.objects.select_related().all()
-    serializer_class = NetworkDeploymentsSerializer
-    id_serializer_class = NetworkDeploymentsIdSerializer
+class ControllerNetworksList(generics.ListCreateAPIView):
+    queryset = ControllerNetworks.objects.select_related().all()
+    serializer_class = ControllerNetworksSerializer
+    id_serializer_class = ControllerNetworksIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
     filter_fields = ('id','created','updated','enacted','backend_status','deleted','network','deployment','net_id','router_id','subnet_id','subnet',)
 
@@ -2823,7 +2910,7 @@
             return self.serializer_class
 
     def get_queryset(self):
-        return NetworkDeployments.select_by_user(self.request.user)
+        return ControllerNetworks.select_by_user(self.request.user)
 
     def create(self, request, *args, **kwargs):
         serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -2835,21 +2922,21 @@
         obj = serializer.object
         obj.caller = request.user
         if obj.can_update(request.user):
-            return super(NetworkDeploymentsList, self).create(request, *args, **kwargs)
+            return super(ControllerNetworksList, self).create(request, *args, **kwargs)
         else:
             raise Exception("failed obj.can_update")
 
-        ret = super(NetworkDeploymentsList, self).create(request, *args, **kwargs)
+        ret = super(ControllerNetworksList, self).create(request, *args, **kwargs)
         if (ret.status_code%100 != 200):
             raise Exception(ret.data)
 
         return ret
 
 
-class NetworkDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
-    queryset = NetworkDeployments.objects.select_related().all()
-    serializer_class = NetworkDeploymentsSerializer
-    id_serializer_class = NetworkDeploymentsIdSerializer
+class ControllerNetworksDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = ControllerNetworks.objects.select_related().all()
+    serializer_class = ControllerNetworksSerializer
+    id_serializer_class = ControllerNetworksIdSerializer
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -2859,7 +2946,7 @@
             return self.serializer_class
     
     def get_queryset(self):
-        return NetworkDeployments.select_by_user(self.request.user)
+        return ControllerNetworks.select_by_user(self.request.user)
 
     # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
@@ -3752,10 +3839,10 @@
 
 
 
-class ImageDeploymentsList(generics.ListCreateAPIView):
-    queryset = ImageDeployments.objects.select_related().all()
-    serializer_class = ImageDeploymentsSerializer
-    id_serializer_class = ImageDeploymentsIdSerializer
+class ControllerImagesList(generics.ListCreateAPIView):
+    queryset = ControllerImages.objects.select_related().all()
+    serializer_class = ControllerImagesSerializer
+    id_serializer_class = ControllerImagesIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
     filter_fields = ('id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
 
@@ -3767,7 +3854,7 @@
             return self.serializer_class
 
     def get_queryset(self):
-        return ImageDeployments.select_by_user(self.request.user)
+        return ControllerImages.select_by_user(self.request.user)
 
     def create(self, request, *args, **kwargs):
         serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -3779,21 +3866,21 @@
         obj = serializer.object
         obj.caller = request.user
         if obj.can_update(request.user):
-            return super(ImageDeploymentsList, self).create(request, *args, **kwargs)
+            return super(ControllerImagesList, self).create(request, *args, **kwargs)
         else:
             raise Exception("failed obj.can_update")
 
-        ret = super(ImageDeploymentsList, self).create(request, *args, **kwargs)
+        ret = super(ControllerImagesList, self).create(request, *args, **kwargs)
         if (ret.status_code%100 != 200):
             raise Exception(ret.data)
 
         return ret
 
 
-class ImageDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
-    queryset = ImageDeployments.objects.select_related().all()
-    serializer_class = ImageDeploymentsSerializer
-    id_serializer_class = ImageDeploymentsIdSerializer
+class ControllerImagesDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = ControllerImages.objects.select_related().all()
+    serializer_class = ControllerImagesSerializer
+    id_serializer_class = ControllerImagesIdSerializer
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -3803,7 +3890,7 @@
             return self.serializer_class
     
     def get_queryset(self):
-        return ImageDeployments.select_by_user(self.request.user)
+        return ControllerImages.select_by_user(self.request.user)
 
     # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
@@ -4111,7 +4198,7 @@
     serializer_class = DeploymentSerializer
     id_serializer_class = DeploymentIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
-    filter_fields = ('id','created','updated','enacted','backend_status','deleted','name','admin_user','admin_password','admin_tenant','auth_url','backend_type','availability_zone','accessControl','sites','sites','flavors','flavors',)
+    filter_fields = ('id','created','updated','enacted','backend_status','deleted','name','accessControl','sites','sites','flavors','flavors',)
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4163,7 +4250,57 @@
 
     # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
+class ControllerList(generics.ListCreateAPIView):
+    queryset = Controller.objects.select_related().all()
+    serializer_class = ControllerSerializer
+    id_serializer_class = ControllerIdSerializer
+    filter_backends = (filters.DjangoFilterBackend,)
+    filter_fields = ('id','created','updated','enacted','backend_status','deleted','site_deployment','admin_user','admin_password','admin_tenant','auth_url','backend_type')
 
+    def get_serializer_class(self):
+        no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+        if (no_hyperlinks):
+            return self.id_serializer_class
+        else:
+            return self.serializer_class
+
+    def get_queryset(self):
+        return Controller.select_by_user(self.request.user)
+
+    def create(self, request, *args, **kwargs):
+        serializer = self.get_serializer(data=request.DATA, files=request.FILES)
+        if not (serializer.is_valid()):
+            response = {"error": "validation",
+                        "specific_error": "not serializer.is_valid()",
+                        "reasons": serializer.errors}
+            return Response(response, status=status.HTTP_400_BAD_REQUEST)
+        obj = serializer.object
+        obj.caller = request.user
+        if obj.can_update(request.user):
+            return super(ControllerList, self).create(request, *args, **kwargs)
+        else:
+            raise Exception("failed obj.can_update")
+
+        ret = super(ControllerList, self).create(request, *args, **kwargs)
+        if (ret.status_code%100 != 200):
+            raise Exception(ret.data)
+
+        return ret
+
+class ControllerDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = Controller.objects.select_related().all()
+    serializer_class = ControllerSerializer
+    id_serializer_class = ControllerIdSerializer
+
+    def get_serializer_class(self):
+        no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+        if (no_hyperlinks):
+            return self.id_serializer_class
+        else:
+            return self.serializer_class
+
+    def get_queryset(self):
+        return Controller.select_by_user(self.request.user)
 
 class ReservationList(generics.ListCreateAPIView):
     queryset = Reservation.objects.select_related().all()
@@ -4224,10 +4361,10 @@
 
 
 
-class SliceDeploymentsList(generics.ListCreateAPIView):
-    queryset = SliceDeployments.objects.select_related().all()
-    serializer_class = SliceDeploymentsSerializer
-    id_serializer_class = SliceDeploymentsIdSerializer
+class ControllerSlicesList(generics.ListCreateAPIView):
+    queryset = ControllerSlices.objects.select_related().all()
+    serializer_class = ControllerSlicesSerializer
+    id_serializer_class = ControllerSlicesIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
     filter_fields = ('id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
 
@@ -4239,7 +4376,7 @@
             return self.serializer_class
 
     def get_queryset(self):
-        return SliceDeployments.select_by_user(self.request.user)
+        return ControllerSlices.select_by_user(self.request.user)
 
     def create(self, request, *args, **kwargs):
         serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -4251,21 +4388,21 @@
         obj = serializer.object
         obj.caller = request.user
         if obj.can_update(request.user):
-            return super(SliceDeploymentsList, self).create(request, *args, **kwargs)
+            return super(ControllerSlicesList, self).create(request, *args, **kwargs)
         else:
             raise Exception("failed obj.can_update")
 
-        ret = super(SliceDeploymentsList, self).create(request, *args, **kwargs)
+        ret = super(ControllerSlicesList, self).create(request, *args, **kwargs)
         if (ret.status_code%100 != 200):
             raise Exception(ret.data)
 
         return ret
 
 
-class SliceDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
-    queryset = SliceDeployments.objects.select_related().all()
-    serializer_class = SliceDeploymentsSerializer
-    id_serializer_class = SliceDeploymentsIdSerializer
+class ControllerSlicesDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = ControllerSlices.objects.select_related().all()
+    serializer_class = ControllerSlicesSerializer
+    id_serializer_class = ControllerSlicesIdSerializer
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4275,7 +4412,7 @@
             return self.serializer_class
     
     def get_queryset(self):
-        return SliceDeployments.select_by_user(self.request.user)
+        return ControllerSlices.select_by_user(self.request.user)
 
     # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
@@ -4401,10 +4538,10 @@
 
 
 
-class UserDeploymentsList(generics.ListCreateAPIView):
-    queryset = UserDeployments.objects.select_related().all()
-    serializer_class = UserDeploymentsSerializer
-    id_serializer_class = UserDeploymentsIdSerializer
+class ControllerUsersList(generics.ListCreateAPIView):
+    queryset = ControllerUsers.objects.select_related().all()
+    serializer_class = ControllerUsersSerializer
+    id_serializer_class = ControllerUsersIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
     filter_fields = ('id','created','updated','enacted','backend_status','deleted','user','deployment','kuser_id',)
 
@@ -4416,7 +4553,7 @@
             return self.serializer_class
 
     def get_queryset(self):
-        return UserDeployments.select_by_user(self.request.user)
+        return ControllerUsers.select_by_user(self.request.user)
 
     def create(self, request, *args, **kwargs):
         serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -4428,21 +4565,21 @@
         obj = serializer.object
         obj.caller = request.user
         if obj.can_update(request.user):
-            return super(UserDeploymentsList, self).create(request, *args, **kwargs)
+            return super(ControllerUsersList, self).create(request, *args, **kwargs)
         else:
             raise Exception("failed obj.can_update")
 
-        ret = super(UserDeploymentsList, self).create(request, *args, **kwargs)
+        ret = super(ControllerUsersList, self).create(request, *args, **kwargs)
         if (ret.status_code%100 != 200):
             raise Exception(ret.data)
 
         return ret
 
 
-class UserDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
-    queryset = UserDeployments.objects.select_related().all()
-    serializer_class = UserDeploymentsSerializer
-    id_serializer_class = UserDeploymentsIdSerializer
+class ControllerUsersDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = ControllerUsers.objects.select_related().all()
+    serializer_class = ControllerUsersSerializer
+    id_serializer_class = ControllerUsersIdSerializer
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4452,7 +4589,7 @@
             return self.serializer_class
     
     def get_queryset(self):
-        return UserDeployments.select_by_user(self.request.user)
+        return ControllerUsers.select_by_user(self.request.user)
 
     # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
@@ -4637,10 +4774,10 @@
 
 
 
-class DeploymentPrivilegeList(generics.ListCreateAPIView):
-    queryset = DeploymentPrivilege.objects.select_related().all()
-    serializer_class = DeploymentPrivilegeSerializer
-    id_serializer_class = DeploymentPrivilegeIdSerializer
+class ControllerPrivilegeList(generics.ListCreateAPIView):
+    queryset = ControllerPrivilege.objects.select_related().all()
+    serializer_class = ControllerPrivilegeSerializer
+    id_serializer_class = ControllerPrivilegeIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
     filter_fields = ('id','created','updated','enacted','backend_status','deleted','user','deployment','role',)
 
@@ -4652,7 +4789,7 @@
             return self.serializer_class
 
     def get_queryset(self):
-        return DeploymentPrivilege.select_by_user(self.request.user)
+        return ControllerPrivilege.select_by_user(self.request.user)
 
     def create(self, request, *args, **kwargs):
         serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -4664,21 +4801,21 @@
         obj = serializer.object
         obj.caller = request.user
         if obj.can_update(request.user):
-            return super(DeploymentPrivilegeList, self).create(request, *args, **kwargs)
+            return super(ControllerPrivilegeList, self).create(request, *args, **kwargs)
         else:
             raise Exception("failed obj.can_update")
 
-        ret = super(DeploymentPrivilegeList, self).create(request, *args, **kwargs)
+        ret = super(ControllerPrivilegeList, self).create(request, *args, **kwargs)
         if (ret.status_code%100 != 200):
             raise Exception(ret.data)
 
         return ret
 
 
-class DeploymentPrivilegeDetail(PlanetStackRetrieveUpdateDestroyAPIView):
-    queryset = DeploymentPrivilege.objects.select_related().all()
-    serializer_class = DeploymentPrivilegeSerializer
-    id_serializer_class = DeploymentPrivilegeIdSerializer
+class ControllerPrivilegeDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = ControllerPrivilege.objects.select_related().all()
+    serializer_class = ControllerPrivilegeSerializer
+    id_serializer_class = ControllerPrivilegeIdSerializer
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4688,7 +4825,7 @@
             return self.serializer_class
     
     def get_queryset(self):
-        return DeploymentPrivilege.select_by_user(self.request.user)
+        return ControllerPrivilege.select_by_user(self.request.user)
 
     # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
@@ -4696,10 +4833,10 @@
 
 
 
-class DeploymentRoleList(generics.ListCreateAPIView):
-    queryset = DeploymentRole.objects.select_related().all()
-    serializer_class = DeploymentRoleSerializer
-    id_serializer_class = DeploymentRoleIdSerializer
+class ControllerRoleList(generics.ListCreateAPIView):
+    queryset = ControllerRole.objects.select_related().all()
+    serializer_class = ControllerRoleSerializer
+    id_serializer_class = ControllerRoleIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
     filter_fields = ('id','created','updated','enacted','backend_status','deleted','role',)
 
@@ -4711,7 +4848,7 @@
             return self.serializer_class
 
     def get_queryset(self):
-        return DeploymentRole.select_by_user(self.request.user)
+        return ControllerRole.select_by_user(self.request.user)
 
     def create(self, request, *args, **kwargs):
         serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -4723,21 +4860,21 @@
         obj = serializer.object
         obj.caller = request.user
         if obj.can_update(request.user):
-            return super(DeploymentRoleList, self).create(request, *args, **kwargs)
+            return super(ControllerRoleList, self).create(request, *args, **kwargs)
         else:
             raise Exception("failed obj.can_update")
 
-        ret = super(DeploymentRoleList, self).create(request, *args, **kwargs)
+        ret = super(ControllerRoleList, self).create(request, *args, **kwargs)
         if (ret.status_code%100 != 200):
             raise Exception(ret.data)
 
         return ret
 
 
-class DeploymentRoleDetail(PlanetStackRetrieveUpdateDestroyAPIView):
-    queryset = DeploymentRole.objects.select_related().all()
-    serializer_class = DeploymentRoleSerializer
-    id_serializer_class = DeploymentRoleIdSerializer
+class ControllerRoleDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = ControllerRole.objects.select_related().all()
+    serializer_class = ControllerRoleSerializer
+    id_serializer_class = ControllerRoleIdSerializer
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4747,7 +4884,7 @@
             return self.serializer_class
     
     def get_queryset(self):
-        return DeploymentRole.select_by_user(self.request.user)
+        return ControllerRole.select_by_user(self.request.user)
 
     # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
@@ -4819,7 +4956,7 @@
     serializer_class = SiteDeploymentsSerializer
     id_serializer_class = SiteDeploymentsIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
-    filter_fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
+    filter_fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment')
 
     def get_serializer_class(self):
         no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4871,7 +5008,57 @@
 
     # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
 
+class ControllerSitesList(generics.ListCreateAPIView):
+    queryset = ControllerSites.objects.select_related().all()
+    serializer_class = ControllerSitesSerializer
+    id_serializer_class = ControllerSiteIdSerializer
+    filter_backends = (filters.DjangoFilterBackend,)
+    filter_fields = ('id','created','updated','enacted','backend_status','deleted','site_deployment','controller','tenant_id',)
 
+    def get_serializer_class(self):
+        no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+        if (no_hyperlinks):
+            return self.id_serializer_class
+        else:
+            return self.serializer_class
+
+    def get_queryset(self):
+        return ControllerSites.select_by_user(self.request.user)
+
+    def create(self, request, *args, **kwargs):
+        serializer = self.get_serializer(data=request.DATA, files=request.FILES)
+        if not (serializer.is_valid()):
+            response = {"error": "validation",
+                        "specific_error": "not serializer.is_valid()",
+                        "reasons": serializer.errors}
+            return Response(response, status=status.HTTP_400_BAD_REQUEST)
+        obj = serializer.object
+        obj.caller = request.user
+        if obj.can_update(request.user):
+            return super(ControllerSitesList, self).create(request, *args, **kwargs)
+        else:
+            raise Exception("failed obj.can_update")
+
+        ret = super(ControllerSitesList, self).create(request, *args, **kwargs)
+        if (ret.status_code%100 != 200):
+            raise Exception(ret.data)
+
+        return ret
+
+class ControllerSitesDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+    queryset = ControllerSites.objects.select_related().all()
+    serializer_class = ControllerSitesSerializer
+    id_serializer_class = ControllerSitesIdSerializer
+
+    def get_serializer_class(self):
+        no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+        if (no_hyperlinks):
+            return self.id_serializer_class
+        else:
+            return self.serializer_class
+
+    def get_queryset(self):
+        return ControllerSites.select_by_user(self.request.user)
 
 class SliceTagList(generics.ListCreateAPIView):
     queryset = SliceTag.objects.select_related().all()
diff --git a/planetstack/model_policies/model_policy_Network.py b/planetstack/model_policies/model_policy_Network.py
index f48b25a..d9d138d 100644
--- a/planetstack/model_policies/model_policy_Network.py
+++ b/planetstack/model_policies/model_policy_Network.py
@@ -1,23 +1,23 @@
 from core.models import *
 
 def handle(network):
-	from core.models import SliceDeployments,NetworkDeployments
+	from core.models import ControllerSlices,ControllerNetworks
 	from collections import defaultdict
-	# network deployments are not visible to users. We must ensure
+	# network controllers are not visible to users. We must ensure
 	# networks are deployed at all deploymets available to their slices.
-	slice_deployments = SliceDeployments.objects.all()
+	slice_controllers = ControllerSlices.objects.all()
 	slice_deploy_lookup = defaultdict(list)
-	for slice_deployment in slice_deployments:
-		slice_deploy_lookup[slice_deployment.slice].append(slice_deployment.deployment)
+	for slice_controller in slice_controllers:
+		slice_deploy_lookup[slice_controller.slice].append(slice_controller.controller)
 
-	network_deployments = NetworkDeployments.objects.all()
+	network_controllers = ControllerNetworks.objects.all()
 	network_deploy_lookup = defaultdict(list)
-	for network_deployment in network_deployments:
-		network_deploy_lookup[network_deployment.network].append(network_deployment.deployment)
+	for network_controller in network_controllers:
+		network_deploy_lookup[network_controller.network].append(network_controller.controller)
 
-	expected_deployments = slice_deploy_lookup[network.owner]
-	for expected_deployment in expected_deployments:
+	expected_controllers = slice_deploy_lookup[network.owner]
+	for expected_controller in expected_controllers:
 		if network not in network_deploy_lookup or \
-		  expected_deployment not in network_deploy_lookup[network]:
-			nd = NetworkDeployments(network=network, deployment=expected_deployment)
+		  expected_controller not in network_deploy_lookup[network]:
+			nd = ControllerNetworks(network=network, controller=expected_controller)
 			nd.save()
diff --git a/planetstack/model_policies/model_policy_Slice.py b/planetstack/model_policies/model_policy_Slice.py
index ee34b14..af07e51 100644
--- a/planetstack/model_policies/model_policy_Slice.py
+++ b/planetstack/model_policies/model_policy_Slice.py
@@ -1,25 +1,25 @@
 
 def handle(slice):
-	from core.models import SiteDeployments,SliceDeployments,Deployment,Network,NetworkSlice,NetworkTemplate
+	from core.models import ControllerSites,ControllerSlices,Controller,Network,NetworkSlice,NetworkTemplate
 	from collections import defaultdict
-	site_deployments = SiteDeployments.objects.all()
+	site_controllers = ControllerSites.objects.all()
 	site_deploy_lookup = defaultdict(list)
-	for site_deployment in site_deployments:
-		site_deploy_lookup[site_deployment.site].append(site_deployment.deployment)
+	for site_controller in site_controllers:
+		site_deploy_lookup[site_controller.site].append(site_controller.controller)
 	
-	slice_deployments = SliceDeployments.objects.all()
+	slice_controllers = ControllerSlices.objects.all()
 	slice_deploy_lookup = defaultdict(list)
-	for slice_deployment in slice_deployments:
-		slice_deploy_lookup[slice_deployment.slice].append(slice_deployment.deployment)
+	for slice_controller in slice_controllers:
+		slice_deploy_lookup[slice_controller.slice].append(slice_controller.controller)
 	
-	all_deployments = Deployment.objects.all() 
-	# slices are added to all deployments for now
-	expected_deployments = all_deployments
-	#expected_deployments = site_deploy_lookup[slice.site]
-	for expected_deployment in expected_deployments:
+	all_controllers = Controller.objects.all() 
+	# slices are added to all controllers for now
+	expected_controllers = all_controllers
+	#expected_controllers = site_deploy_lookup[slice.site]
+	for expected_controller in expected_controllers:
 		if slice not in slice_deploy_lookup or \
-		   expected_deployment not in slice_deploy_lookup[slice]:
-			sd = SliceDeployments(slice=slice, deployment=expected_deployment)
+		   expected_controller not in slice_deploy_lookup[slice]:
+			sd = ControllerSlices(slice=slice, controller=expected_controller)
 			sd.save()
 
 	# make sure slice has at least 1 public and 1 private networkd
diff --git a/planetstack/model_policies/model_policy_User.py b/planetstack/model_policies/model_policy_User.py
index 6118a7b..593ba9d 100644
--- a/planetstack/model_policies/model_policy_User.py
+++ b/planetstack/model_policies/model_policy_User.py
@@ -1,32 +1,32 @@
 from core.models import *
 
 def handle(user):
-	from core.models import Deployment,SiteDeployments,UserDeployments
+	from core.models import Controller,ControllerSites,ControllerUsers
 	from collections import defaultdict
-	deployments = Deployment.objects.all()
-	site_deployments = SiteDeployments.objects.all()
-	site_deploy_lookup = defaultdict(list)
-	for site_deployment in site_deployments:
-		site_deploy_lookup[site_deployment.site].append(site_deployment.deployment)
+	controllers = Controller.objects.all()
+	controller_sitements = ControllerSites.objects.all()
+	controller_site_lookup = defaultdict(list)
+	for controller_sitement in controller_sitements:
+		controller_site_lookup[controller_sitement.site].append(controller_sitement.controller)
 
-	user_deploy_lookup = defaultdict(list)
-	for user_deployment in UserDeployments.objects.all():
-		user_deploy_lookup[user_deployment.user].append(user_deployment.deployment)
+	controller_user_lookup = defaultdict(list)
+	for controller_userment in ControllerUsers.objects.all():
+		controller_user_lookup[controller_userment.user].append(controller_userment.controller)
    
-	all_deployments = Deployment.objects.filter() 
+	all_controllers = Controller.objects.filter() 
 	if user.is_admin:
-		# admins should have an account at all deployments
-		expected_deployments = deployments
+		# admins should have an account at all controllers
+		expected_controllers = controllers
 	else:
-		# normal users should have an account at their site's deployments
-		#expected_deployments = site_deploy_lookup[user.site]
-		# users are added to all deployments for now
-		expected_deployments = deployments        
+		# normal users should have an account at their site's controllers
+		#expected_controllers = controller_site_lookup[user.site]
+		# users are added to all controllers for now
+		expected_controllers = controllers        
 
-	for expected_deployment in expected_deployments:
-		if not user in user_deploy_lookup or \
-		  expected_deployment not in user_deploy_lookup[user]: 
+	for expected_controller in expected_controllers:
+		if not user in controller_user_lookup or \
+		  expected_controller not in controller_user_lookup[user]: 
 			# add new record
-			ud = UserDeployments(user=user, deployment=expected_deployment)
+			ud = ControllerUsers(user=user, controller=expected_controller)
 			ud.save()    
 
diff --git a/planetstack/openstack/driver.py b/planetstack/openstack/driver.py
index 5506ca6..f448e40 100644
--- a/planetstack/openstack/driver.py
+++ b/planetstack/openstack/driver.py
@@ -1,7 +1,7 @@
 import commands
 import hashlib
 from planetstack.config import Config
-from core.models import Deployment
+from core.models import Controller
 
 try:
     from openstack.client import OpenStackClient
@@ -24,30 +24,30 @@
 
         self.enabled = manager_enabled
         self.has_openstack = has_openstack
-        self.deployment = None
+        self.controller = None
         self.admin_user = None
 
-    def client_driver(self, caller=None, tenant=None, deployment=None):
+    def client_driver(self, caller=None, tenant=None, controller=None):
         if caller:
             auth = {'username': caller.email,
                     'password': hashlib.md5(caller.password).hexdigest()[:6],
                     'tenant': tenant}
-            client = OpenStackClient(deployment=deployment, **auth)
+            client = OpenStackClient(controller=controller, **auth)
         else:
-            admin_driver = self.admin_driver(tenant=tenant, deployment=deployment)
-            client = OpenStackClient(tenant=tenant, deployment=admin_driver.deployment)
+            admin_driver = self.admin_driver(tenant=tenant, controller=controller)
+            client = OpenStackClient(tenant=tenant, controller=admin_driver.controller)
 
         driver = OpenStackDriver(client=client)
         #driver.admin_user = admin_driver.admin_user
-        #driver.deployment = admin_driver.deployment
+        #driver.controller = admin_driver.controller
         return driver
 
-    def admin_driver(self, tenant=None, deployment=None):
-        deployment = Deployment.objects.get(name=deployment)
-        client = OpenStackClient(tenant=tenant, deployment=deployment)
+    def admin_driver(self, tenant=None, controller=None):
+        controller = Controller.objects.get(id=controller.id)
+        client = OpenStackClient(tenant=tenant, controller=controller)
         driver = OpenStackDriver(client=client)
-        driver.admin_user = client.keystone.users.find(name=deployment.admin_user)
-        driver.deployment = deployment
+        driver.admin_user = client.keystone.users.find(name=controller.admin_user)
+        driver.controller = controller
         return driver    
 
     def create_role(self, name):
diff --git a/planetstack/openstack_observer/steps/__init__.py b/planetstack/openstack_observer/steps/__init__.py
index 0151af3..3f074a5 100644
--- a/planetstack/openstack_observer/steps/__init__.py
+++ b/planetstack/openstack_observer/steps/__init__.py
@@ -1,7 +1,7 @@
 ##from .sync_external_routes import SyncExternalRoutes
 #from .sync_network_slivers import SyncNetworkSlivers
 #from .sync_networks import SyncNetworks
-#from .sync_network_deployments import SyncNetworkDeployments
+#from .sync_controller_networks import SyncControllerNetworks
 #from .sync_site_privileges import SyncSitePrivileges
 #from .sync_sites import SyncSites
 #from .sync_slice_memberships import SyncSliceMemberships
@@ -12,5 +12,5 @@
 #from .sync_roles import SyncRoles
 #from .sync_nodes import SyncNodes
 #from .sync_images import SyncImages
-#from .sync_image_deployments import SyncImageDeployments
+#from .sync_controller_images import SyncControllerImages
 #from .garbage_collector import GarbageCollector
diff --git a/planetstack/openstack_observer/steps/sync_controller_images.py b/planetstack/openstack_observer/steps/sync_controller_images.py
index 20c22a2..67cd7b5 100644
--- a/planetstack/openstack_observer/steps/sync_controller_images.py
+++ b/planetstack/openstack_observer/steps/sync_controller_images.py
@@ -4,74 +4,74 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models import Deployment
-from core.models import Image, ImageDeployments
+from core.models import Controller
+from core.models import Image, ControllerImages
 from util.logger import Logger, logging
 

 logger = Logger(level=logging.INFO)
 
-class SyncImageDeployments(OpenStackSyncStep):
-    provides=[ImageDeployments]
+class SyncControllerImages(OpenStackSyncStep):
+    provides=[ControllerImages]
     requested_interval=0
 
     def fetch_pending(self, deleted):
         if (deleted):
             return []
-         # smbaker: commented out automatic creation of ImageDeployments as
+         # smbaker: commented out automatic creation of ControllerImages as
          #    as they will now be configured in GUI. Not sure if this is
          #    sufficient.
 
-#        # ensure images are available across all deployments
-#        image_deployments = ImageDeployments.objects.all()
+#        # ensure images are available across all controllers
+#        controller_images = ControllerImages.objects.all()
 #        image_deploy_lookup = defaultdict(list)
-#        for image_deployment in image_deployments:
-#            image_deploy_lookup[image_deployment.image].append(image_deployment.deployment)
+#        for controller_image in controller_images:
+#            image_deploy_lookup[controller_image.image].append(controller_image.controller)
 #
-#        all_deployments = Deployment.objects.all()
+#        all_controllers = Controller.objects.all()
 #        for image in Image.objects.all():
-#            expected_deployments = all_deployments
-#            for expected_deployment in expected_deployments:
+#            expected_controllers = all_controllers
+#            for expected_controller in expected_controllers:
 #                if image not in image_deploy_lookup or \
-#                  expected_deployment not in image_deploy_lookup[image]:
-#                    id = ImageDeployments(image=image, deployment=expected_deployment)
+#                  expected_controller not in image_deploy_lookup[image]:
+#                    id = ControllerImages(image=image, controller=expected_controller)
 #                    id.save()
 
         # now we return all images that need to be enacted
-        return ImageDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+        return ControllerImages.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
 
-    def sync_record(self, image_deployment):
-        logger.info("Working on image %s on deployment %s" % (image_deployment.image.name, image_deployment.deployment.name))
-        driver = self.driver.admin_driver(deployment=image_deployment.deployment.name)
+    def sync_record(self, controller_image):
+        logger.info("Working on image %s on controller %s" % (controller_image.image.name, controller_image.controller))
+        driver = self.driver.admin_driver(controller=controller_image.controller.name)
         images = driver.shell.glance.get_images()
         glance_image = None
         for image in images:
-            if image['name'] == image_deployment.image.name:
+            if image['name'] == controller_image.image.name:
                 glance_image = image
                 break
         if glance_image:
-            logger.info("Found image %s on deployment %s" % (image_deployment.image.name, image_deployment.deployment.name))
-            image_deployment.glance_image_id = glance_image['id']
-        elif image_deployment.image.path:
+            logger.info("Found image %s on controller %s" % (controller_image.image.name, controller_image.controller.name))
+            controller_image.glance_image_id = glance_image['id']
+        elif controller_image.image.path:
             image = {
-                'name': image_deployment.image.name,
+                'name': controller_image.image.name,
                 'is_public': True,
                 'disk_format': 'raw',
                 'container_format': 'bare',
-                'file': image_deployment.image.path,
+                'file': controller_image.image.path,
             }
 
-            logger.info("Creating image %s on deployment %s" % (image_deployment.image.name, image_deployment.deployment.name))
+            logger.info("Creating image %s on controller %s" % (controller_image.image.name, controller_image.controller.name))
 
-            glance_image = driver.shell.glanceclient.images.create(name=image_deployment.image.name,
+            glance_image = driver.shell.glanceclient.images.create(name=controller_image.image.name,
                                                                    is_public=True,
                                                                    disk_format='raw',
                                                                    container_format='bare')
-            glance_image.update(data=open(image_deployment.image.path, 'rb'))
+            glance_image.update(data=open(controller_image.image.path, 'rb'))
 
             # While the images returned by driver.shell.glance.get_images()
             #   are dicts, the images returned by driver.shell.glanceclient.images.create
             #   are not dicts. We have to use getattr() instead of [] operator.
             if not glance_image or not getattr(glance_image,"id",None):
-                raise Exception, "Add image failed at deployment %s" % image_deployment.deployment.name
-            image_deployment.glance_image_id = getattr(glance_image, "id")
-        image_deployment.save()
+                raise Exception, "Add image failed at controller %s" % controller_image.controller.name
+            controller_image.glance_image_id = getattr(glance_image, "id")
+        controller_image.save()
diff --git a/planetstack/openstack_observer/steps/sync_controller_networks.py b/planetstack/openstack_observer/steps/sync_controller_networks.py
index a6fc389..bb18b39 100644
--- a/planetstack/openstack_observer/steps/sync_controller_networks.py
+++ b/planetstack/openstack_observer/steps/sync_controller_networks.py
@@ -12,21 +12,21 @@
 
 logger = Logger(level=logging.INFO)
 
-class SyncNetworkDeployments(OpenStackSyncStep):
+class SyncControllerNetworks(OpenStackSyncStep):
     requested_interval = 0
-    provides=[Network, NetworkDeployments, Sliver]
+    provides=[Network, ControllerNetworks, Sliver]
 
     def fetch_pending(self, deleted):
         if (deleted):
-            return NetworkDeployments.deleted_objects.all()
+            return ControllerNetworks.deleted_objects.all()
         else:
-            return NetworkDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+            return ControllerNetworks.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
 
-    def get_next_subnet(self, deployment=None):
+    def get_next_subnet(self, controller=None):
         # limit ourself to 10.0.x.x for now
         valid_subnet = lambda net: net.startswith('10.0')
 
-        driver = self.driver.admin_driver(deployment=deployment,tenant='admin')
+        driver = self.driver.admin_driver(controller=controller,tenant='admin')
         subnets = driver.shell.quantum.list_subnets()['subnets']
         ints = [int(IPNetwork(subnet['cidr']).ip) for subnet in subnets \
                 if valid_subnet(subnet['cidr'])]
@@ -39,98 +39,98 @@
         next_network = IPNetwork(str(IPAddress(last_network) + last_network.size) + "/24")
         return next_network
 
-    def save_network_deployment(self, network_deployment):
-        if (not network_deployment.net_id) and network_deployment.network.template.sharedNetworkName:
+    def save_controller_network(self, controller_network):
+        if (not controller_network.net_id) and controller_network.network.template.sharedNetworkName:
             # It's a shared network, try to find the shared network id
 
-            quantum_networks = self.driver.shell.quantum.list_networks(name=network_deployment.network.template.sharedNetworkName)["networks"]
+            quantum_networks = self.driver.shell.quantum.list_networks(name=controller_network.network.template.sharedNetworkName)["networks"]
             if quantum_networks:
                 logger.info("set shared network id %s" % quantum_networks[0]["id"])
-                network_deployment.net_id = quantum_networks[0]["id"]
+                controller_network.net_id = quantum_networks[0]["id"]
             else:
-                logger.info("failed to find shared network id for deployment")
+                logger.info("failed to find shared network id for controller")
                 return
 
         # At this point, it must be a private network, so create it if it does
         # not exist.
 
-        if not network_deployment.net_id:
-            network_name = network_deployment.network.name
+        if not controller_network.net_id:
+            network_name = controller_network.network.name
 
             # create network
             os_network = self.driver.create_network(network_name, shared=True)
-            network_deployment.net_id = os_network['id']
+            controller_network.net_id = os_network['id']
 
             # create router
             #router = self.driver.create_router(network_name)
-            #network_deployment.router_id = router['id']
+            #controller_network.router_id = router['id']
 
             # create subnet
-            next_subnet = self.get_next_subnet(deployment=network_deployment.deployment.name)
+            next_subnet = self.get_next_subnet(controller=controller_network.controller.name)
             cidr = str(next_subnet.cidr)
             ip_version = next_subnet.version
             start = str(next_subnet[2])
             end = str(next_subnet[-2])
             subnet = self.driver.create_subnet(name=network_name,
-                                               network_id = network_deployment.net_id,
+                                               network_id = controller_network.net_id,
                                                cidr_ip = cidr,
                                                ip_version = ip_version,
                                                start = start,
                                                end = end)
-            network_deployment.subnet = cidr
-            network_deployment.subnet_id = subnet['id']
+            controller_network.subnet = cidr
+            controller_network.subnet_id = subnet['id']
             # add subnet as interface to slice's router
             #self.driver.add_router_interface(router['id'], subnet['id'])
             # add external route
             #self.driver.add_external_route(subnet)
-            logger.info("created private subnet (%s) for network: %s" % (cidr, network_deployment.network))
+            logger.info("created private subnet (%s) for network: %s" % (cidr, controller_network.network))
 
         # Now, figure out the subnet and subnet_id for the network. This works
         # for both private and shared networks.
 
-        if (not network_deployment.subnet_id) or (not network_deployment.subnet):
-            (network_deployment.subnet_id, network_deployment.subnet) = self.driver.get_network_subnet(network_deployment.net_id)
-            logger.info("sync'ed subnet (%s) for network: %s" % (network_deployment.subnet, network_deployment.network))
+        if (not controller_network.subnet_id) or (not controller_network.subnet):
+            (controller_network.subnet_id, controller_network.subnet) = self.driver.get_network_subnet(controller_network.net_id)
+            logger.info("sync'ed subnet (%s) for network: %s" % (controller_network.subnet, controller_network.network))
 
-        if (not network_deployment.subnet):
+        if (not controller_network.subnet):
             # this will generate a non-null database constraint error
             #   ... which in turn leads to transaction errors
             # it's probably caused by networks that no longer exist at the
             # quantum level.
 
-            logger.info("null subnet for network %s, skipping save" % network_deployment.network)
+            logger.info("null subnet for network %s, skipping save" % controller_network.network)
             return
 
-        network_deployment.save()
+        controller_network.save()
 
-    def sync_record(self, network_deployment):
-        logger.info("sync'ing network deployment %s for network %s slice %s deployment %s" % (network_deployment, network_deployment.network, str(network_deployment.network.owner), network_deployment.deployment))
+    def sync_record(self, controller_network):
+        logger.info("sync'ing network controller %s for network %s slice %s controller %s" % (controller_network, controller_network.network, str(controller_network.network.owner), controller_network.controller))
 
-        if not network_deployment.deployment.admin_user:
-            logger.info("deployment %r has no admin_user, skipping" % network_deployment.deployment)
+        if not controller_network.controller.admin_user:
+            logger.info("controller %r has no admin_user, skipping" % controller_network.controller)
             return
 
-        self.driver = self.driver.admin_driver(deployment=network_deployment.deployment,tenant='admin')
-        if network_deployment.network.owner and network_deployment.network.owner.creator:
+        self.driver = self.driver.admin_driver(controller=controller_network.controller,tenant='admin')
+        if controller_network.network.owner and controller_network.network.owner.creator:
             try:
                 # update manager context
 		# Bring back
-                self.save_network_deployment(network_deployment)
-                logger.info("saved network deployment: %s" % (network_deployment))
+                self.save_controller_network(controller_network)
+                logger.info("saved network controller: %s" % (controller_network))
             except Exception,e:
-                logger.log_exc("save network deployment failed: %s" % network_deployment)
+                logger.log_exc("save network controller failed: %s" % controller_network)
                 raise e
 
 
-    def delete_record(self, network_deployment):
-        driver = OpenStackDriver().client_driver(caller=network_deployment.network.owner.creator,
-                                                 tenant=network_deployment.network.owner.name,
-                                                 deployment=network_deployment.deployment.name)
-        if (network_deployment.router_id) and (network_deployment.subnet_id):
-            driver.delete_router_interface(network_deployment.router_id, network_deployment.subnet_id)
-        if network_deployment.subnet_id:
-            driver.delete_subnet(network_deployment.subnet_id)
-        if network_deployment.router_id:
-            driver.delete_router(network_deployment.router_id)
-        if network_deployment.net_id:
-            driver.delete_network(network_deployment.net_id)
+    def delete_record(self, controller_network):
+        driver = OpenStackDriver().client_driver(caller=controller_network.network.owner.creator,
+                                                 tenant=controller_network.network.owner.name,
+                                                 controller=controller_network.controller.name)
+        if (controller_network.router_id) and (controller_network.subnet_id):
+            driver.delete_router_interface(controller_network.router_id, controller_network.subnet_id)
+        if controller_network.subnet_id:
+            driver.delete_subnet(controller_network.subnet_id)
+        if controller_network.router_id:
+            driver.delete_router(controller_network.router_id)
+        if controller_network.net_id:
+            driver.delete_network(controller_network.net_id)
diff --git a/planetstack/openstack_observer/steps/sync_controller_site_deployments.py b/planetstack/openstack_observer/steps/sync_controller_site_deployments.py
new file mode 100644
index 0000000..89bea2c
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_site_deployments.py
@@ -0,0 +1,37 @@
+import os
+import base64
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.openstacksyncstep import OpenStackSyncStep
+from core.models.site import *
+from observer.ansible import *
+
+class SyncControllerSites(OpenStackSyncStep):
+    requested_interval=0
+    provides=[ControllerSiteDeployments, SiteDeployments]
+
+    def sync_record(self, controller_site_deployment):
+
+	template = os_template_env.get_template('sync_controller_site_deployments.yaml')
+	tenant_fields = {'endpoint':controller_site_deployment.controller.auth_url,
+		         'admin_user': controller_site_deployment.controller.admin_user,
+		         'admin_password': controller_site_deployment.controller.admin_password,
+		         'admin_tenant': 'admin',
+		         'tenant': controller_site_deployment.site_deployment.site.login_base,
+		         'tenant_description': controller_site_deployment.site_deployment.site.name}
+
+	rendered = template.render(tenant_fields)
+	res = run_template('sync_controller_site_deployments.yaml', tenant_fields)
+
+	if (len(res)==1):
+		controller_site_deployment.tenant_id = res[0]['id']
+        	controller_site_deployment.save()
+	elif (len(res)):
+		raise Exception('Could not assign roles for user %s'%tenant_fields['tenant'])
+	else:
+		raise Exception('Could not create or update user %s'%tenant_fields['tenant'])
+            
+    def delete_record(self, controller_site_deployment):
+        if controller_site_deployment.tenant_id:
+            driver = self.driver.admin_driver(controller=controller_site_deployment.controller)
+            driver.delete_tenant(controller_site_deployment.tenant_id)
diff --git a/planetstack/openstack_observer/steps/sync_controller_site_deployments.yaml b/planetstack/openstack_observer/steps/sync_controller_site_deployments.yaml
new file mode 100644
index 0000000..4129802
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_site_deployments.yaml
@@ -0,0 +1,5 @@
+---
+- hosts: 127.0.0.1
+  connection: local
+  tasks:
+  - keystone_user: endpoint={{ endpoint }} login_user={{ admin_user }} login_password={{ admin_password }} login_tenant_name={{ admin_tenant }} tenant={{ tenant }} tenant_description="{{ tenant_description }}"
diff --git a/planetstack/openstack_observer/steps/sync_controller_sites.py b/planetstack/openstack_observer/steps/sync_controller_sites.py
new file mode 100644
index 0000000..7e76cc4
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_sites.py
@@ -0,0 +1,37 @@
+import os
+import base64
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.openstacksyncstep import OpenStackSyncStep
+from core.models.site import *
+from observer.ansible import *
+
+class SyncControllerSites(OpenStackSyncStep):
+    requested_interval=0
+    provides=[Controller, Site]
+
+    def sync_record(self, controller):
+
+	template = os_template_env.get_template('sync_controller_sites.yaml')
+	tenant_fields = {'endpoint':controller.auth_url,
+		         'admin_user': controller.admin_user,
+		         'admin_password': controller.admin_password,
+		         'admin_tenant': 'admin',
+		         'tenant': controller.site_deployment.site.login_base,
+		         'tenant_description': controller.site_deployment.site.name}
+
+	rendered = template.render(tenant_fields)
+	res = run_template('sync_controller_sites.yaml', tenant_fields)
+
+	if (len(res)==1):
+		controller.tenant_id = res[0]['id']
+        	controller.save()
+	elif (len(res)):
+		raise Exception('Could not assign roles for user %s'%tenant_fields['tenant'])
+	else:
+		raise Exception('Could not create or update user %s'%tenant_fields['tenant'])
+            
+    def delete_record(self, controller):
+        if controller.tenant_id:
+            driver = self.driver.admin_driver(controller=controller)
+            driver.delete_tenant(controller.tenant_id)
diff --git a/planetstack/openstack_observer/steps/sync_controller_sites.yaml b/planetstack/openstack_observer/steps/sync_controller_sites.yaml
new file mode 100644
index 0000000..4129802
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_sites.yaml
@@ -0,0 +1,5 @@
+---
+- hosts: 127.0.0.1
+  connection: local
+  tasks:
+  - keystone_user: endpoint={{ endpoint }} login_user={{ admin_user }} login_password={{ admin_password }} login_tenant_name={{ admin_tenant }} tenant={{ tenant }} tenant_description="{{ tenant_description }}"
diff --git a/planetstack/openstack_observer/steps/sync_controller_slices.py b/planetstack/openstack_observer/steps/sync_controller_slices.py
new file mode 100644
index 0000000..e51ba7e
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_slices.py
@@ -0,0 +1,105 @@
+import os
+import base64
+from collections import defaultdict
+from netaddr import IPAddress, IPNetwork
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.openstacksyncstep import OpenStackSyncStep
+from core.models.site import Controller, ControllerSites
+from core.models.slice import Slice, ControllerSlices
+from core.models.usercontrollers import ControllerUsers
+from util.logger import Logger, logging
+from observer.ansible import *
+
+logger = Logger(level=logging.INFO)
+
+class SyncControllerSlices(OpenStackSyncStep):
+    provides=[ControllerSlices]
+    requested_interval=0
+
+    def fetch_pending(self, deleted):
+        if (deleted):
+            return ControllerSlices.deleted_objects.all()
+        else:
+            return ControllerSlices.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+
+    def get_next_subnet(self, controller=None):
+        # limit ourself to 10.0.x.x for now
+        valid_subnet = lambda net: net.startswith('10.0')
+        driver = self.driver.admin_driver(controller=controller)
+        subnets = driver.shell.quantum.list_subnets()['subnets']
+        ints = [int(IPNetwork(subnet['cidr']).ip) for subnet in subnets \
+                if valid_subnet(subnet['cidr'])]
+        ints.sort()
+        if ints:
+            last_ip = IPAddress(ints[-1])
+        else:
+            last_ip = IPAddress('10.0.0.1')
+        last_ip = IPAddress(ints[-1])
+        last_network = IPNetwork(str(last_ip) + "/24")
+        next_network = IPNetwork(str(IPAddress(last_network) + last_network.size) + "/24")
+        return next_network
+
+
+    def sync_record(self, controller_slice):
+        logger.info("sync'ing slice controller %s" % controller_slice)
+
+        if not controller_slice.controller.admin_user:
+            logger.info("controller %r has no admin_user, skipping" % controller_slice.controller)
+            return
+
+	controller_users = ControllerUsers.objects.filter(user=controller_slice.slice.creator,
+                                                             controller=controller_slice.controller)            
+    	if not controller_users:
+	    logger.info("slice createor %s has not accout at controller %s" % (controller_slice.slice.creator, controller_slice.controller.name))
+	    roles = []
+    	else:
+	    controller_user = controller_users[0]
+	    roles = ['admin']
+	    
+	max_instances=int(controller_slice.slice.max_slivers)
+	tenant_fields = {'endpoint':controller_slice.controller.auth_url,
+		         'admin_user': controller_slice.controller.admin_user,
+		         'admin_password': controller_slice.controller.admin_password,
+		         'admin_tenant': 'admin',
+		         'tenant': controller_slice.slice.name,
+		         'tenant_description': controller_slice.slice.description,
+			 'roles':roles,
+			 'name':controller_user.user.email,
+			 'max_instances':max_instances}
+
+	res = run_template('sync_controller_slices.yaml', tenant_fields)
+	expected_num = len(roles)+1
+	if (len(res)!=expected_num):
+	    raise Exception('Could not sync tenants for slice %s'%controller_slice.slice.name)
+	else:
+	    tenant_id = res[0]['id']
+	    if (not controller_slice.tenant_id):
+	        handle = os.popen('nova quota-update --instances %d %s'%(max_instances,tenant_id))
+		output = handle.read()
+		result = handle.close()
+		if (result):
+		    logging.info('Could not update quota for %s'%controller_slice.slice.name)
+		controller_slice.tenant_id = tenant_id
+		controller_slice.save()
+			
+
+
+    def delete_record(self, controller_slice):
+        user = User.objects.get(id=controller_slice.slice.creator.id)
+        driver = OpenStackDriver().admin_driver(controller=controller_slice.controller.name)
+        client_driver = driver.client_driver(caller=user,
+                                             tenant=controller_slice.slice.name,
+                                             controller=controller_slice.controller.name)
+
+        if controller_slice.router_id and controller_slice.subnet_id:
+            client_driver.delete_router_interface(controller_slice.router_id, controller_slice.subnet_id)
+        if controller_slice.subnet_id:
+            client_driver.delete_subnet(controller_slice.subnet_id)
+        if controller_slice.router_id:    
+            client_driver.delete_router(controller_slice.router_id)
+        if controller_slice.network_id:
+            client_driver.delete_network(controller_slice.network_id)
+        if controller_slice.tenant_id:
+            driver.delete_tenant(controller_slice.tenant_id)
+        
diff --git a/planetstack/openstack_observer/steps/sync_controller_slices.yaml b/planetstack/openstack_observer/steps/sync_controller_slices.yaml
new file mode 100644
index 0000000..de1caf4
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_slices.yaml
@@ -0,0 +1,8 @@
+---
+- hosts: 127.0.0.1
+  connection: local
+  tasks:
+  - keystone_user: endpoint={{ endpoint }} login_user={{ admin_user }} login_password={{ admin_password }} login_tenant_name={{ admin_tenant }} tenant={{ tenant }} tenant_description="{{ tenant_description }}"
+  {% for role in roles %}
+  - keystone_user: endpoint={{ endpoint}} login_user={{ admin_user }} login_password={{ admin_password }} login_tenant_name={{ admin_tenant }} user="{{ name }}" role={{ role }} tenant={{ tenant }}
+  {% endfor %}
diff --git a/planetstack/openstack_observer/steps/sync_controller_users.py b/planetstack/openstack_observer/steps/sync_controller_users.py
new file mode 100644
index 0000000..63f5ca3
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_users.py
@@ -0,0 +1,86 @@
+import os
+import base64
+import hashlib
+from collections import defaultdict
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.openstacksyncstep import OpenStackSyncStep
+from core.models.site import ControllerSites, Controller
+from core.models.user import User
+from core.models.usercontrollers import ControllerUsers
+from util.logger import Logger, logging
+
+from observer.ansible import *
+
+logger = Logger(level=logging.INFO)
+
+class SyncControllerUsers(OpenStackSyncStep):
+    provides=[ControllerUsers, User]
+    requested_interval=0
+
+    def fetch_pending(self, deleted):
+
+        if (deleted):
+            return ControllerUsers.deleted_objects.all()
+        else:
+            return ControllerUsers.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None)) 
+
+    def sync_record(self, controller_user):
+        logger.info("sync'ing user %s at controller %s" % (controller_user.user, controller_user.controller))
+
+        if not controller_user.controller.admin_user:
+            logger.info("controller %r has no admin_user, skipping" % controller_user.controller)
+            return
+
+	template = os_template_env.get_template('sync_controller_users.yaml')
+	
+        name = controller_user.user.email[:controller_user.user.email.find('@')]
+
+	roles = []
+	# setup user controller home site roles  
+        if controller_user.user.site:
+            site_controllers = ControllerSites.objects.filter(site=controller_user.user.site,
+                                                              controller=controller_user.controller)
+            if site_controllers:
+                # need the correct tenant id for site at the controller
+                tenant_id = site_controllers[0].tenant_id  
+		tenant_name = site_controllers[0].site.login_base
+
+		roles.append('user')
+                if controller_user.user.is_admin:
+                    roles.append('admin')
+	    else:
+		raise Exception('Internal error. Missing ControllerSites for user %s'%controller_user.user.email)
+	else:
+	    raise Exception('Siteless user %s'%controller_user.user.email)
+
+
+        user_fields = {'endpoint':controller_user.controller.auth_url,
+		       'name': controller_user.user.email,
+                       'email': controller_user.user.email,
+                       'password': hashlib.md5(controller_user.user.password).hexdigest()[:6],
+                       'admin_user': controller_user.controller.admin_user,
+		       'admin_password': controller_user.controller.admin_password,
+		       'admin_tenant': 'admin',
+		       'roles':roles,
+		       'tenant':tenant_name}    
+	
+	rendered = template.render(user_fields)
+	res = run_template('sync_controller_users.yaml', user_fields)
+
+	# results is an array in which each element corresponds to an 
+	# "ok" string received per operation. If we get as many oks as
+	# the number of operations we issued, that means a grand success.
+	# Otherwise, the number of oks tell us which operation failed.
+	expected_length = len(roles) + 1
+	if (len(res)==expected_length):
+        	controller_user.save()
+	elif (len(res)):
+		raise Exception('Could not assign roles for user %s'%user_fields['name'])
+	else:
+		raise Exception('Could not create or update user %s'%user_fields['name'])
+
+    def delete_record(self, controller_user):
+        if controller_user.kuser_id:
+            driver = self.driver.admin_driver(controller=controller_user.controller)
+            driver.delete_user(controller_user.kuser_id)
diff --git a/planetstack/openstack_observer/steps/sync_controller_users.yaml b/planetstack/openstack_observer/steps/sync_controller_users.yaml
new file mode 100644
index 0000000..95cdba3
--- /dev/null
+++ b/planetstack/openstack_observer/steps/sync_controller_users.yaml
@@ -0,0 +1,16 @@
+---
+- hosts: 127.0.0.1
+  connection: local
+  tasks:
+  - keystone_user: 
+       endpoint={{ endpoint }} 
+       user="{{ name }}" 
+       email={{ email }} 
+       password={{ password }} 
+       login_user={{ admin_user }} 
+       login_password={{ admin_password }} 
+       login_tenant_name={{ admin_tenant }} 
+       tenant={{ tenant }}
+  {% for role in roles %}
+  - keystone_user: endpoint={{ endpoint}} login_user={{ admin_user }} login_password={{ admin_password }} login_tenant_name={{ admin_tenant }} user="{{ name }}" role={{ role }} tenant={{ tenant }}
+  {% endfor %}
diff --git a/planetstack/openstack_observer/steps/sync_external_routes.py b/planetstack/openstack_observer/steps/sync_external_routes.py
deleted file mode 100644
index 28d24cc..0000000
--- a/planetstack/openstack_observer/steps/sync_external_routes.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import os
-import base64
-from planetstack.config import Config
-from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.site import Deployment
-
-class SyncExternalRoutes(OpenStackSyncStep):
-    # XXX what does this provide?
-    provides=[]
-    requested_interval = 86400 # This step is slow like a pig. Let's run it infrequently
-
-    def call(self, **args):
-	deployments = Deployment.objects.all()
-	self.driver = self.driver.admin_driver(deployment=deployments[0],tenant='admin')
-        routes = self.driver.get_external_routes()
-        subnets = self.driver.shell.quantum.list_subnets()['subnets']
-        for subnet in subnets:
-            try:
-                self.driver.add_external_route(subnet, routes)
-            except:
-                logger.log_exc("failed to add external route for subnet %s" % subnet)
diff --git a/planetstack/openstack_observer/steps/sync_network_slivers.py b/planetstack/openstack_observer/steps/sync_network_slivers.py
index 06ee856..22cfa82 100644
--- a/planetstack/openstack_observer/steps/sync_network_slivers.py
+++ b/planetstack/openstack_observer/steps/sync_network_slivers.py
@@ -3,6 +3,7 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
+from core.models import Controller
 from core.models.network import *
 from util.logger import Logger, logging
 
@@ -29,7 +30,7 @@
         networks = Network.objects.all()
         networks_by_id = {}
         for network in networks:
-            for nd in network.networkdeployments.all():
+            for nd in network.controllernetworks.all():
                 networks_by_id[nd.net_id] = network
 
         #logger.info("networks_by_id = ")
@@ -41,18 +42,18 @@
         for sliver in slivers:
             slivers_by_instance_id[sliver.instance_id] = sliver
 
-        # Get all ports in all deployments
+        # Get all ports in all controllers
 
         ports_by_id = {}
-        for deployment in Deployment.objects.all():
-            if not deployment.admin_tenant:
-                logger.info("deployment %s has no admin_tenant" % deployment.name)
+        for controller in Controller.objects.all():
+            if not controller.admin_tenant:
+                logger.info("controller %s has no admin_tenant" % controller)
                 continue
             try:
-                driver = self.driver.admin_driver(deployment=deployment.name,tenant='admin')
+                driver = self.driver.admin_driver(controller = controller,tenant='admin')
                 ports = driver.shell.quantum.list_ports()["ports"]
             except:
-                logger.log_exc("failed to get ports from deployment %s" % deployment.name)
+                logger.log_exc("failed to get ports from controller %s" % controller)
                 continue
 
             for port in ports:
@@ -139,7 +140,7 @@
             if (neutron_nat_list != nat_list):
                 logger.info("Setting nat:forward_ports for port %s network %s sliver %s to %s" % (str(networkSliver.port_id), str(networkSliver.network.id), str(networkSliver.sliver), str(nat_list)))
                 try:
-                    driver = self.driver.admin_driver(deployment=networkSliver.sliver.node.deployment,tenant='admin')
+                    driver = self.driver.admin_driver(controller=networkSliver.sliver.node.site_deployment.controller,tenant='admin')
                     driver.shell.quantum.update_port(networkSliver.port_id, {"port": {"nat:forward_ports": nat_list}})
                 except:
                     logger.log_exc("failed to update port with nat_list %s" % str(nat_list))
diff --git a/planetstack/openstack_observer/steps/sync_networks.py b/planetstack/openstack_observer/steps/sync_networks.py
index 99f2c01..a4e9552 100644
--- a/planetstack/openstack_observer/steps/sync_networks.py
+++ b/planetstack/openstack_observer/steps/sync_networks.py
@@ -5,7 +5,7 @@
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.network import *
 from util.logger import Logger, logging
-from observer.steps.sync_network_deployments import *
+from observer.steps.sync_controller_networks import *
 
 logger = Logger(level=logging.INFO)
 
@@ -17,10 +17,10 @@
         network.save()
 
     def delete_record(self, network):
-        network_deployment_deleter = SyncNetworkDeployments().delete_record
-        for network_deployment in NetworkDeployments.objects.filter(network=network):
+        controller_networks_deleter = SyncControllerNetworks().delete_record
+        for controller_network in ControllerNetworks.objects.filter(network=network):
             try:
-                network_deployment_deleter(network_deployment)    
+                controller_network_deleter(controller_network)    
             except Exception,e:
-                logger.log_exc("Failed to delete network deployment %s" % network_deployment)
+                logger.log_exc("Failed to delete controller network %s" % controller_network)
                 raise e
diff --git a/planetstack/openstack_observer/steps/sync_nodes.py b/planetstack/openstack_observer/steps/sync_nodes.py
index 3936311..abd5b98 100644
--- a/planetstack/openstack_observer/steps/sync_nodes.py
+++ b/planetstack/openstack_observer/steps/sync_nodes.py
@@ -6,7 +6,7 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.node import Node
-from core.models.site import Site, Deployment
+from core.models.site import SiteDeployments, Controller
 from util.logger import Logger, logging
 
 logger = Logger(level=logging.INFO)
@@ -22,28 +22,28 @@
             return []
 
         # collect local nodes
-        sites = Site.objects.all()
+        site_deployments = SiteDeployments.objects.all()
         nodes = Node.objects.all()
         node_hostnames = [node.name for node in nodes]
 
-        # fetch all nodes from each deployment
-        deployments = Deployment.objects.all()
+        # fetch all nodes from each controller
+        controllers = Controller.objects.all()
         new_nodes = []
-        for deployment in deployments:
+        for controller in controllers:
             try:
-                driver = self.driver.admin_driver(deployment=deployment.name)
+                driver = self.driver.admin_driver(controller=controller.name)
                 compute_nodes = driver.shell.nova.hypervisors.list()
             except:
-                logger.log_exc("Failed to get nodes from deployment %s" % str(deployment))
+                logger.log_exc("Failed to get nodes from controller %s" % str(controller))
                 continue
 
             for compute_node in compute_nodes:
                 if compute_node.hypervisor_hostname not in node_hostnames:
                     # XX TODO:figure out how to correctly identify a node's site.
                     # XX pick a random site to add the node to for now
-                    site_index = random.randint(0, len(sites))
+                    site_index = random.randint(0, len(site_deployments))
                     node = Node(name=compute_node.hypervisor_hostname,
-                                site=sites[site_index], deployment=deployment)
+                                site_deployment=site_deployments[site_index], controller=controller)
                     new_nodes.append(node)
 
         return new_nodes    
diff --git a/planetstack/openstack_observer/steps/sync_roles.py b/planetstack/openstack_observer/steps/sync_roles.py
index bb837db..91c0abb 100644
--- a/planetstack/openstack_observer/steps/sync_roles.py
+++ b/planetstack/openstack_observer/steps/sync_roles.py
@@ -4,7 +4,7 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.role import Role
-from core.models.site import SiteRole, Deployment, DeploymentRole
+from core.models.site import SiteRole, Controller, ControllerRole
 from core.models.slice import SliceRole
 
 class SyncRoles(OpenStackSyncStep):
@@ -18,24 +18,24 @@
 
         site_roles = SiteRole.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
         slice_roles = SliceRole.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
-        deployment_roles = DeploymentRole.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+        controller_roles = ControllerRole.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
 
         roles = []
         for site_role in site_roles:
             roles.append(site_role)
         for slice_role in slice_roles:
             roles.append(slice_role)
-        for deployment_role in deployment_roles:
-            roles.append(deployment_role)
+        for controller_role in controller_roles:
+            roles.append(controller_role)
 
         return roles
 
 
     def sync_record(self, role):
         if not role.enacted:
-            deployments = Deployment.objects.all()
-       	    for deployment in deployments:
-                driver = self.driver.admin_driver(deployment=deployment.name)
+            controllers = Controller.objects.all()
+       	    for controller in controllers:
+                driver = self.driver.admin_driver(controller=controller.name)
                 driver.create_role(role.role)
             role.save()
     
diff --git a/planetstack/openstack_observer/steps/sync_site_privileges.py b/planetstack/openstack_observer/steps/sync_site_privileges.py
index d07b279..2378b88 100644
--- a/planetstack/openstack_observer/steps/sync_site_privileges.py
+++ b/planetstack/openstack_observer/steps/sync_site_privileges.py
@@ -3,7 +3,7 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models import User, UserDeployments, SitePrivilege, SiteDeployments   
+from core.models import User, ControllerUsers, SitePrivilege, ControllerSites   
 
 class SyncSitePrivileges(OpenStackSyncStep):
     requested_interval=0
@@ -17,13 +17,13 @@
         return SitePrivilege.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
 
     def sync_record(self, site_priv):
-        # sync site privileges at all site deployments
-        site_deployments = SiteDeployments.objects.filter(site=site_priv.site)
-        for site_deployment in site_deployments:
-            user_deployments = UserDeployments.objects.filter(deployment=site_deployment.deployment)
-            if user_deployments:
-                kuser_id  = user_deployments[0].kuser_id
-                driver = self.driver.admin_driver(deployment=site_deployment.deployment.name)
+        # sync site privileges at all site controllers
+        controller_sites = ControllerSites.objects.filter(site=site_priv.site)
+        for controller_site in controller_sites:
+            controller_users = ControllerUsers.objects.filter(controller=controller_site.controller)
+            if controller_users:
+                kuser_id  = controller_users[0].kuser_id
+                driver = self.driver.admin_driver(controller=controller_site.controller)
                 driver.add_user_role(kuser_id,
-                                     site_deployment.tenant_id,
+                                     controller_site.tenant_id,
                                      site_priv.role.role)
diff --git a/planetstack/openstack_observer/steps/sync_sites.py b/planetstack/openstack_observer/steps/sync_sites.py
index c560a6a..530301a 100644
--- a/planetstack/openstack_observer/steps/sync_sites.py
+++ b/planetstack/openstack_observer/steps/sync_sites.py
@@ -4,7 +4,7 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.site import Site
-from observer.steps.sync_site_deployments import *
+from observer.steps.sync_controller_sites import *
 
 class SyncSites(OpenStackSyncStep):
     provides=[Site]
@@ -14,7 +14,7 @@
         site.save()
 
     def delete_record(self, site):
-        site_deployments = SiteDeployments.objects.filter(site=site)
-        site_deployment_deleter = SyncSiteDeployments().delete_record
-        for site_deployment in site_deployments:
-            site_deployment_deleter(site_deployment)
+        controller_sites = ControllerSites.objects.filter(site=site)
+        controller_site_deleter = SyncControllerSites().delete_record
+        for controller_site in controller_sites:
+            controller_site_deleter(controller_site)
diff --git a/planetstack/openstack_observer/steps/sync_slice_memberships.py b/planetstack/openstack_observer/steps/sync_slice_memberships.py
index b1cd223..600f012 100644
--- a/planetstack/openstack_observer/steps/sync_slice_memberships.py
+++ b/planetstack/openstack_observer/steps/sync_slice_memberships.py
@@ -4,7 +4,7 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.slice import *
-from core.models.userdeployments import UserDeployments
+from core.models.controllerusers import ControllerUsers
 from util.logger import Logger, logging
 
 logger = Logger(level=logging.INFO)
@@ -20,17 +20,17 @@
         return SlicePrivilege.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
 
     def sync_record(self, slice_memb):
-        # sync slice memberships at all slice deployments 
+        # sync slice memberships at all slice controllers 
         logger.info("syncing slice privilege: %s %s" % (slice_memb.slice.name, slice_memb.user.email))
-        slice_deployments = SliceDeployments.objects.filter(slice=slice_memb.slice)
-        for slice_deployment in slice_deployments:
-            if not slice_deployment.tenant_id:
+        slice_controllers = ControllerSlices.objects.filter(slice=slice_memb.slice)
+        for slice_controller in slice_controllers:
+            if not slice_controller.tenant_id:
                 continue
-            user_deployments = UserDeployments.objects.filter(deployment=slice_deployment.deployment,
+            controller_users = ControllerUsers.objects.filter(controller=slice_controller.controller,
                                                               user=slice_memb.user)
-            if user_deployments:
-                kuser_id  = user_deployments[0].kuser_id
-                driver = self.driver.admin_driver(deployment=slice_deployment.deployment.name)
+            if controller_users:
+                kuser_id  = controller_users[0].kuser_id
+                driver = self.driver.admin_driver(controller=slice_controller.controller.name)
                 driver.add_user_role(kuser_id,
-                                     slice_deployment.tenant_id,
+                                     slice_controller.tenant_id,
                                      slice_memb.role.role)
diff --git a/planetstack/openstack_observer/steps/sync_slices.py b/planetstack/openstack_observer/steps/sync_slices.py
index a6073b6..a792b48 100644
--- a/planetstack/openstack_observer/steps/sync_slices.py
+++ b/planetstack/openstack_observer/steps/sync_slices.py
@@ -4,9 +4,9 @@
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.slice import Slice, SliceDeployments
+from core.models.slice import Slice, ControllerSlices
 from util.logger import Logger, logging
-from observer.steps.sync_slice_deployments import *
+from observer.steps.sync_controller_slices import *
 
 logger = Logger(level=logging.INFO)
 
@@ -15,16 +15,16 @@
     requested_interval=0
 
     def sync_record(self, slice):
-        for slice_deployment in SliceDeployments.objects.filter(slice=slice):
+        for controller_slice in ControllerSlices.objects.filter(slice=slice):
             # bump the 'updated' timestamp and trigger observer to update
-            # slice across all deployments 
-            slice_deployment.save()    
+            # slice across all controllers 
+            controller_slice.save()    
 
     def delete_record(self, slice):
-        slice_deployment_deleter = SyncSliceDeployments().delete_record
-        for slice_deployment in SliceDeployments.objects.filter(slice=slice):
+        controller_slice_deleter = SyncControllerSlices().delete_record
+        for controller_slice in ControllerSlices.objects.filter(slice=slice):
             try:
-                slice_deployment_deleter(slice_deployment)
+                controller_slice_deleter(controller_slice)
             except Exception,e:
-                logger.log_exc("Failed to delete slice_deployment %s" % slice_deployment) 
+                logger.log_exc("Failed to delete controller_slice %s" % controller_slice) 
                 raise e
diff --git a/planetstack/openstack_observer/steps/sync_slivers.py b/planetstack/openstack_observer/steps/sync_slivers.py
index cf41446..de2c919 100644
--- a/planetstack/openstack_observer/steps/sync_slivers.py
+++ b/planetstack/openstack_observer/steps/sync_slivers.py
@@ -4,8 +4,8 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.sliver import Sliver
-from core.models.slice import Slice, SlicePrivilege, SliceDeployments
-from core.models.network import Network, NetworkSlice, NetworkDeployments
+from core.models.slice import Slice, SlicePrivilege, ControllerSlices
+from core.models.network import Network, NetworkSlice, ControllerNetworks
 from util.logger import Logger, logging
 from observer.ansible import *
 
@@ -24,7 +24,7 @@
         return userdata
 
     def sync_record(self, sliver):
-        logger.info("sync'ing sliver:%s slice:%s deployment:%s " % (sliver, sliver.slice.name, sliver.node.deployment))
+        logger.info("sync'ing sliver:%s slice:%s controller:%s " % (sliver, sliver.slice.name, sliver.node.site_controller))
 
         metadata_update = {}
         if (sliver.numberCores):
@@ -43,87 +43,74 @@
         if sliver.slice.creator.public_key:
             pubkeys.add(sliver.slice.creator.public_key)
 
-        nics = []
-        networks = [ns.network for ns in NetworkSlice.objects.filter(slice=sliver.slice)]
-        network_deployments = NetworkDeployments.objects.filter(network__in=networks,
-                                                                deployment=sliver.node.deployment)
+	nics = []
+	networks = [ns.network for ns in NetworkSlice.objects.filter(slice=sliver.slice)]   
+	controller_networks = ControllerNetworks.objects.filter(network__in=networks, 
+								controller=sliver.node.site_controller.controller)
 
-        for network_deployment in network_deployments:
-            if network_deployment.network.template.visibility == 'private' and \
-               network_deployment.network.template.translation == 'none' and network_deployment.net_id:
-                nics.append(network_deployment.net_id)
+	for controller_network in controller_networks:
+	    if controller_network.network.template.visibility == 'private' and \
+	       controller_network.network.template.translation == 'none' and controller_network.net_id: 
+		nics.append(controller_network.net_id)
 
         # now include network template
         network_templates = [network.template.sharedNetworkName for network in networks \
                              if network.template.sharedNetworkName]
 
-        #driver = self.driver.client_driver(caller=sliver.creator, tenant=sliver.slice.name, deployment=sliver.deploymentNetwork)
-        driver = self.driver.admin_driver(tenant='admin', deployment=sliver.deploymentNetwork)
-        nets = driver.shell.quantum.list_networks()['networks']
-        for net in nets:
-            if net['name'] in network_templates:
-                nics.append(net['id'])
+        #driver = self.driver.client_driver(caller=sliver.creator, tenant=sliver.slice.name, controller=sliver.controllerNetwork)
+        driver = self.driver.admin_driver(tenant='admin', controller=sliver.controllerNetwork)
+	nets = driver.shell.quantum.list_networks()['networks']
+	for net in nets:
+	    if net['name'] in network_templates: 
+		nics.append(net['id']) 
 
-        if (not nics):
-            for net in nets:
-                if net['name']=='public':
-                    nics.append(net['id'])
+	if (not nics):
+	    for net in nets:
+	        if net['name']=='public':
+	    	    nics.append(net['id'])
 
-        # look up image id
-        deployment_driver = self.driver.admin_driver(deployment=sliver.deploymentNetwork.name)
-        image_id = None
-        images = deployment_driver.shell.glanceclient.images.list()
-        for image in images:
-            if image.name == sliver.image.name or not image_id:
-                image_id = image.id
+	# look up image id
+	controller_driver = self.driver.admin_driver(controller=sliver.controllerNetwork.name)
+	image_id = None
+	images = controller_driver.shell.glanceclient.images.list()
+	for image in images:
+	    if image.name == sliver.image.name or not image_id:
+		image_id = image.id
+		
+	# look up key name at the controller
+	# create/fetch keypair
+	keyname = None
+	keyname = sliver.creator.email.lower().replace('@', 'AT').replace('.', '') +\
+		  sliver.slice.name
+	key_fields =  {'name': keyname,
+		       'public_key': sliver.creator.public_key}
+	    
 
-        # look up key name at the deployment
-        # create/fetch keypair
-        keyname = None
-        keyname = sliver.creator.email.lower().replace('@', 'AT').replace('.', '') +\
-                  sliver.slice.name
-        key_fields =  {'name': keyname,
-                       'public_key': sliver.creator.public_key}
+	userData = self.get_userdata(sliver)
+	if sliver.userData:
+	    userData = sliver.userData
+	    
+	sliver_name = '@'.join([sliver.slice.name,sliver.node.name])
+	tenant_fields = {'endpoint':sliver.node.controller.auth_url,
+		     'admin_user': sliver.node.controller.admin_user,
+		     'admin_password': sliver.node.controller.admin_password,
+		     'admin_tenant': 'admin',
+		     'tenant': sliver.slice.name,
+		     'tenant_description': sliver.slice.description,
+		     'name':sliver_name,
+		     'image_id':image_id,
+		     'key_name':keyname,
+		     'flavor_id':1,
+		     'nics':nics,
+		     'meta':metadata_update,
+		     'key':key_fields,
+		     'user_data':r'%s'%escape(userData)}
 
-
-        userData = self.get_userdata(sliver)
-        if sliver.userData:
-            userData = sliver.userData
-
-        try:
-            legacy = Config().observer_legacy
-        except:
-            legacy = False
-
-        if (legacy):
-            host_filter = sliver.node.name.split('.',1)[0]
-        else:
-            host_filter = sliver.node.name
-
-        availability_zone_filter = 'nova:%s'%host_filter
-        sliver_name = '@'.join([sliver.slice.name,sliver.node.name])
-        tenant_fields = {'endpoint':sliver.node.deployment.auth_url,
-                     'admin_user': sliver.node.deployment.admin_user,
-                     'admin_password': sliver.node.deployment.admin_password,
-                     'admin_tenant': 'admin',
-                     'tenant': sliver.slice.name,
-                     'availability_zone': availability_zone_filter,
-                     'tenant_description': sliver.slice.description,
-                     'name':sliver_name,
-                     'ansible_tag':sliver_name,
-                     'image_id':image_id,
-                     'key_name':keyname,
-                     'flavor_id':3,
-                     'nics':nics,
-                     'meta':metadata_update,
-                     'key':key_fields,
-                     'user_data':r'%s'%escape(userData)}
-
-        res = run_template('sync_slivers.yaml', tenant_fields, path='slivers')
-        if (len(res)!=2):
-            raise Exception('Could not sync sliver %s'%sliver.slice.name)
-        else:
-            sliver_id = res[1]['id'] # 0 is for the key
+	res = run_template('sync_slivers.yaml', tenant_fields)
+	if (len(res)!=2):
+	    raise Exception('Could not sync sliver %s'%sliver.slice.name)
+	else:
+	    sliver_id = res[1]['id'] # 0 is for the key
 
             sliver.instance_id = sliver_id
             sliver.instance_name = sliver_name
@@ -135,4 +122,3 @@
                          'ansible_tag':sliver_name
                         }
         res = run_template('delete_slivers.yaml', tenant_fields, path='slivers')
-
diff --git a/planetstack/openstack_observer/steps/sync_users.py b/planetstack/openstack_observer/steps/sync_users.py
index a22c213..3c69cad 100644
--- a/planetstack/openstack_observer/steps/sync_users.py
+++ b/planetstack/openstack_observer/steps/sync_users.py
@@ -5,20 +5,20 @@
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.user import User
-from core.models.userdeployments import  UserDeployments
-from observer.steps.sync_user_deployments import SyncUserDeployments
+from core.models.controllerusers import  ControllerUsers
+from observer.steps.sync_controller_users import SyncControllerUsers
 
 class SyncUsers(OpenStackSyncStep):
     provides=[User]
     requested_interval=0
 
     def sync_record(self, user):
-        for user_deployment in UserDeployments.objects.filter(user=user):
+        for controller_user in ControllerUsers.objects.filter(user=user):
             # bump the 'updated' field so user account are updated across 
-            # deployments.
-            user_deployment.save()
+            # controllers.
+            controller_user.save()
 
     def delete_record(self, user):
-        user_deployment_deleter = SyncUserDeployments().delete_record
-        for user_deployment in UserDeployments.objects.filter(user=user):
-            user_deployment_deleter(user_deployment)
+        controller_user_deleter = SyncControllerUsers().delete_record
+        for controller_user in ControllerUsers.objects.filter(user=user):
+            controller_user_deleter(controller_user)