Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/core/models/plcorebase.py b/planetstack/core/models/plcorebase.py
index e310b5e..4b63062 100644
--- a/planetstack/core/models/plcorebase.py
+++ b/planetstack/core/models/plcorebase.py
@@ -158,8 +158,9 @@
     created = models.DateTimeField(auto_now_add=True, default=timezone.now)
     updated = models.DateTimeField(auto_now=True, default=timezone.now)
     enacted = models.DateTimeField(null=True, blank=True, default=None)
+    policed = models.DateTimeField(null=True, blank=True, default=None)
     backend_status = models.CharField(max_length=140,
-                                      default="Provisioning in progress")
+                                      default="0 - Provisioning in progress")
     deleted = models.BooleanField(default=False)
 
     class Meta:
diff --git a/planetstack/core/models/user.py b/planetstack/core/models/user.py
index 7fdde19..244ef6a 100644
--- a/planetstack/core/models/user.py
+++ b/planetstack/core/models/user.py
@@ -162,6 +162,7 @@
     created = models.DateTimeField(auto_now_add=True)
     updated = models.DateTimeField(auto_now=True)
     enacted = models.DateTimeField(null=True, default=None)
+    policed = models.DateTimeField(null=True, default=None)
     backend_status = models.CharField(max_length=140,
                                       default="Provisioning in progress")
     deleted = models.BooleanField(default=False)
diff --git a/planetstack/model_policies/__init__.py b/planetstack/model_policies/__init__.py
index f1c8071..cfcbe8f 100644
--- a/planetstack/model_policies/__init__.py
+++ b/planetstack/model_policies/__init__.py
@@ -4,3 +4,6 @@
 from .model_policy_Site import *
 from .model_policy_SitePrivilege import *
 from .model_policy_SlicePrivilege import *
+from .model_policy_ControllerSlice import *
+from .model_policy_Controller import *
+from .model_policy_Image import *
diff --git a/planetstack/model_policies/model_policy_Controller.py b/planetstack/model_policies/model_policy_Controller.py
index 98eeaff..6d73e0c 100644
--- a/planetstack/model_policies/model_policy_Controller.py
+++ b/planetstack/model_policies/model_policy_Controller.py
@@ -3,9 +3,6 @@
     from core.models import Controller, Site, ControllerSite, Slice, ControllerSlice, User, ControllerUser
     from collections import defaultdict
 
-    #controller = Controller.get(controller_id)
-
-	
     # relations for all sites
     ctrls_by_site = defaultdict(list)
     ctrl_sites = ControllerSite.objects.all()
diff --git a/planetstack/model_policies/model_policy_ControllerSlice.py b/planetstack/model_policies/model_policy_ControllerSlice.py
new file mode 100644
index 0000000..a7f6c9a
--- /dev/null
+++ b/planetstack/model_policies/model_policy_ControllerSlice.py
@@ -0,0 +1,16 @@
+def handle(controller_slice):
+    from core.models import ControllerSlice, Slice
+   
+    try:
+        my_status_code = int(controller_slice.backend_status[0])
+        try:
+            his_status_code = int(controller_slice.slice.backend_status[0])
+        except:
+            his_status_code = 0
+ 
+        print "My: %d His: %d"%(my_status_code, his_status_code)
+        if (my_status_code not in [0,his_status_code]):
+            controller_slice.slice.backend_status = controller_slice.backend_status
+    except Exception,e:
+        print str(e)	
+        pass
diff --git a/planetstack/model_policies/model_policy_Image.py b/planetstack/model_policies/model_policy_Image.py
new file mode 100644
index 0000000..72f76fa
--- /dev/null
+++ b/planetstack/model_policies/model_policy_Image.py
@@ -0,0 +1,13 @@
+def handle(image):
+    from core.models import Controller, ControllerImages, Image
+    from collections import defaultdict
+
+    controller_images = ControllerImages.objects.filter(image=image)
+    existing_controllers = [cs.controller for cs in controller_images] 
+    
+    all_controllers = Controller.objects.all() 
+    for controller in all_controllers:
+        if controller not in existing_controllers:
+            sd = ControllerImages(image=image, controller=controller)
+            sd.save()
+
diff --git a/planetstack/model_policies/model_policy_SitePrivilege.py b/planetstack/model_policies/model_policy_SitePrivilege.py
index 6e9a65c..d9c6a1e 100644
--- a/planetstack/model_policies/model_policy_SitePrivilege.py
+++ b/planetstack/model_policies/model_policy_SitePrivilege.py
@@ -6,7 +6,7 @@
     controller_site_privileges = ControllerSitePrivilege.objects.filter(
         site_privilege = site_privilege,
         )
-    existing_controllers = [csp.controller for sp in controller_site_privileges]
+    existing_controllers = [sp.controller for sp in controller_site_privileges]
     all_controllers = Controller.objects.all()
     for controller in all_controllers:
         if controller not in existing_controllers:
diff --git a/planetstack/model_policies/model_policy_Slice.py b/planetstack/model_policies/model_policy_Slice.py
index 1f58570..a9936bd 100644
--- a/planetstack/model_policies/model_policy_Slice.py
+++ b/planetstack/model_policies/model_policy_Slice.py
@@ -7,7 +7,7 @@
 
     controller_slices = ControllerSlice.objects.filter(slice=slice)
     existing_controllers = [cs.controller for cs in controller_slices] 
-    
+        
     all_controllers = Controller.objects.all() 
     for controller in all_controllers:
         if controller not in existing_controllers:
diff --git a/planetstack/model_policies/model_policy_SlicePrivilege.py b/planetstack/model_policies/model_policy_SlicePrivilege.py
index e58a973..bca7f22 100644
--- a/planetstack/model_policies/model_policy_SlicePrivilege.py
+++ b/planetstack/model_policies/model_policy_SlicePrivilege.py
@@ -6,7 +6,7 @@
     controller_slice_privileges = ControllerSlicePrivilege.objects.filter(
         slice_privilege = slice_privilege,
         )
-    existing_controllers = [csp.controller for sp in controller_slice_privileges]
+    existing_controllers = [sp.controller for sp in controller_slice_privileges]
     all_controllers = Controller.objects.all()
     for controller in all_controllers:
         if controller not in existing_controllers:
diff --git a/planetstack/model_policy.py b/planetstack/model_policy.py
index 7aef793..8ddb82e 100644
--- a/planetstack/model_policy.py
+++ b/planetstack/model_policy.py
@@ -1,11 +1,14 @@
 from django.db.models.signals import post_save
 from django.dispatch import receiver
 import pdb
-from core.models import *
 from dependency_walker import *
 import model_policies
 from util.logger import logger
-
+from datetime import datetime
+import time
+from core.models import *
+from django.db.transaction import atomic
+from django.db.models import F, Q
 
 modelPolicyEnabled = True
 
@@ -22,40 +25,48 @@
 	
 def delete_if_inactive(d, o):
 	#print "Deleting %s (%s)"%(d,d.__class__.__name__)
-	d.delete()	
+	# d.delete()	
 	return
 
-def execute_model_policy(policy_name, instance, update_fields_empty, deleted):
-	if (update_fields_empty):
-		# Automatic dirtying
-		#walk_inv_deps(update_dep, instance)
+@atomic
+def execute_model_policy(instance, deleted):
+	# Automatic dirtying
+	walk_inv_deps(update_dep, instance)
 
+	sender_name = instance.__class__.__name__
+	policy_name = 'model_policy_%s'%sender_name
+	noargs = False
+
+	if deleted:
+		walk_inv_deps(delete_if_inactive, instance)
+	else:
 		try:
 			policy_handler = getattr(model_policies, policy_name, None)
-                        logger.error("POLICY HANDLER: %s %s" % (policy_name, policy_handler))                       
+			logger.error("POLICY HANDLER: %s %s" % (policy_name, policy_handler))                       
 			if policy_handler is not None:
 				policy_handler.handle(instance)
 		except:
 			logger.log_exc("Model Policy Error:") 
 			print "Policy Exceution Error"
-	elif deleted:
-		walk_inv_deps(delete_if_inactive, instance)
 
+	instance.policed=datetime.now()
+        instance.save(update_fields=['policed'])
 
-@receiver(post_save)
-def post_save_handler(sender, instance, **kwargs):
-        if not modelPolicyEnabled:
-            return
+def run_policy():
+        from core.models import Slice,Controller,Network,User,SlicePrivilege,Site,SitePrivilege,Image,ControllerSlice
+	while (True):
+		start = time.time()
+		models = [Slice, Controller, Network, User, SlicePrivilege, Site, SitePrivilege, Image, ControllerSlice]
+		objects = []
+		
+		for m in models:
+        		res = m.objects.filter(Q(policed__lt=F('updated')) | Q(policed=None))
+			objects.extend(res)	
 
-	sender_name = sender.__name__
-	policy_name = 'model_policy_%s'%sender_name
-        if (not kwargs['update_fields']):
-		noargs = True
-		deleted = False
-	else:
-		noargs = False
-		deleted = True
-
-	execute_model_policy(policy_name, instance, noargs, deleted)
-	
-	
+		for o in objects:
+			print "Working on %r"%o
+			execute_model_policy(o, False)
+		
+		
+		if (time.time()-start<1):
+			time.sleep(1)	
diff --git a/planetstack/openstack_observer/ansible.py b/planetstack/openstack_observer/ansible.py
index 5761327..41dc6f0 100644
--- a/planetstack/openstack_observer/ansible.py
+++ b/planetstack/openstack_observer/ansible.py
@@ -6,6 +6,7 @@
 import pdb
 import string
 import random
+import re
 
 try:
     step_dir = Config().observer_steps_dir
@@ -42,16 +43,18 @@
 def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
     return ''.join(random.choice(chars) for _ in range(size))
 
-def run_template(name, opts,path=''):
+def shellquote(s):
+    return "'" + s.replace("'", "'\\''") + "'"
+
+def run_template(name, opts,path='', expected_num=None):
     template = os_template_env.get_template(name)
     buffer = template.render(opts)
 
-
-    #f = open('/tmp/obsans','w')
     try:
         objname = opts['ansible_tag']
     except:
         objname= id_generator()
+
     os.system('mkdir -p %s'%'/'.join([sys_dir,path]))
     fqp = '/'.join([sys_dir,path,objname])
 
@@ -60,12 +63,15 @@
     f.write(buffer)
     f.flush()
 
-    run = os.popen('/opt/planetstack/observer/run_ansible '+fqp)
+    run = os.popen('/opt/planetstack/observer/run_ansible %s'%shellquote(fqp))
+    #run = os.popen('ansible-playbook -v %s'%shellquote(fqp))
     msg = run.read()
     status = run.close()
 
     try:
         ok_results = parse_output(msg)
+	if (len(ok_results) != expected_num):
+		raise ValueError('Unexpected num')
     except ValueError,e:
         all_fatal = re.findall(r'^msg: (.*)',msg,re.MULTILINE)
         all_fatal2 = re.findall(r'^ERROR: (.*)',msg,re.MULTILINE)
diff --git a/planetstack/openstack_observer/backend.py b/planetstack/openstack_observer/backend.py
index 8e4cab3..fe623ca 100644
--- a/planetstack/openstack_observer/backend.py
+++ b/planetstack/openstack_observer/backend.py
@@ -3,6 +3,7 @@
 from observer.event_loop import PlanetStackObserver
 from observer.event_manager import EventListener
 from util.logger import Logger, logging
+from model_policy import run_policy
 
 logger = Logger(level=logging.INFO)
 
@@ -14,6 +15,10 @@
             observer_thread = threading.Thread(target=observer.run)
             observer_thread.start()
             
+            # start model policies thread
+            model_policy_thread = threading.Thread(target=run_policy)
+            model_policy_thread.start()
+
             # start event listene
             event_manager = EventListener(wake_up=observer.wake_up)
             event_manager_thread = threading.Thread(target=event_manager.run)
diff --git a/planetstack/openstack_observer/run_ansible b/planetstack/openstack_observer/run_ansible
index 224a6d7..8d97f5f 100644
--- a/planetstack/openstack_observer/run_ansible
+++ b/planetstack/openstack_observer/run_ansible
@@ -1,4 +1,4 @@
 #!/bin/bash
 
-source /opt/ansible/hacking/env-setup
+source /opt/ansible/hacking/env-setup >> /dev/null
 ansible-playbook -v $@
diff --git a/planetstack/openstack_observer/steps/sync_controller_images.py b/planetstack/openstack_observer/steps/sync_controller_images.py
index 2014a25..17ffe57 100644
--- a/planetstack/openstack_observer/steps/sync_controller_images.py
+++ b/planetstack/openstack_observer/steps/sync_controller_images.py
@@ -32,11 +32,9 @@
                         'ansible_tag': '%s@%s'%(controller_image.image.name,controller_image.controller.name), # name of ansible playbook
                         }
 
-        res = run_template('sync_controller_images.yaml', image_fields, path='controller_images')
 
-        if (len(res)!=1):
-            raise Exception('Could not sync image %s'%controller_image.image.name)
-        else:
-            image_id = res[0]['id']
-            controller_image.glance_image_id = image_id
-            controller_image.save()
+        res = run_template('sync_controller_images.yaml', image_fields, path='controller_images', expected_num=1)
+
+        image_id = res[0]['id']
+        controller_image.glance_image_id = 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 cb82680..655b07d 100644
--- a/planetstack/openstack_observer/steps/sync_controller_networks.py
+++ b/planetstack/openstack_observer/steps/sync_controller_networks.py
@@ -18,14 +18,16 @@
     provides=[ControllerNetwork, Network]
 
     def alloc_subnet(self, uuid):
+        # 16 bits only
+        uuid_masked = uuid & 0xffff
         a = 10
-        b = uuid >> 32
-        c = uuid & 0xffffffff
-	d = 0
+        b = uuid_masked >> 8
+        c = uuid_masked & 0xff
+        d = 0
 
-	cidr = '%d.%d.%d.%d/24'%(a,b,c,d)
-	return cidr
-	
+        cidr = '%d.%d.%d.%d/24'%(a,b,c,d)
+        return cidr
+
 
     def fetch_pending(self, deleted):
         if (deleted):
@@ -35,34 +37,29 @@
 
 
     def save_controller_network(self, controller_network):
-            network_name = controller_network.network.name
-            subnet_name = '%s-%d'%(network_name,controller_network.pk)
-	    cidr = self.alloc_subnet(controller_network.pk)
-	    slice = controller_network.network.slices.all()[0] # XXX: FIXME!!
+        network_name = controller_network.network.name
+        subnet_name = '%s-%d'%(network_name,controller_network.pk)
+        cidr = self.alloc_subnet(controller_network.pk)
+        slice = controller_network.network.slices.all()[0] # XXX: FIXME!!
 
-	    network_fields = {'endpoint':controller_network.controller.auth_url,
-			'admin_user':slice.creator.email, # XXX: FIXME
-			'tenant_name':slice.name, # XXX: FIXME
-			'admin_password':slice.creator.remote_password,
-			'name':network_name,
-			'subnet_name':subnet_name,
-			'ansible_tag':'%s-%s@%s'%(network_name,slice.slicename,controller_network.controller.name),
-			'cidr':cidr
-			}
+        network_fields = {'endpoint':controller_network.controller.auth_url,
+                    'admin_user':slice.creator.email, # XXX: FIXME
+                    'tenant_name':slice.name, # XXX: FIXME
+                    'admin_password':slice.creator.remote_password,
+                    'name':network_name,
+                    'subnet_name':subnet_name,
+                    'ansible_tag':'%s-%s@%s'%(network_name,slice.slicename,controller_network.controller.name),
+                    'cidr':cidr
+                    }
 
-	    res = run_template('sync_controller_networks.yaml', network_fields, path = 'controller_networks')
+        res = run_template('sync_controller_networks.yaml', network_fields, path = 'controller_networks',expected_num=2)
 
-	    if (len(res)!=2):
-		raise Exception('Could not sync network %s'%controller_network.network.name)
-	    else:
-		network_id = res[0]['id'] 
-		subnet_id = res[1]['id'] 
-		controller_network.net_id = network_id
-		controller_network.subnet = cidr
-		controller_network.subnet_id = subnet_id
-		controller_network.save()
-
-            	logger.info("sync'ed subnet (%s) for network: %s" % (controller_network.subnet, controller_network.network))
+        network_id = res[0]['id']
+        subnet_id = res[1]['id']
+        controller_network.net_id = network_id
+        controller_network.subnet = cidr
+        controller_network.subnet_id = subnet_id
+        controller_network.save()
 
 
     def sync_record(self, controller_network):
@@ -73,15 +70,8 @@
             return
 
         if controller_network.network.owner and controller_network.network.owner.creator:
-            try:
-                # update manager context
-		# Bring back
-                self.save_controller_network(controller_network)
-                logger.info("saved network controller: %s" % (controller_network))
-            except Exception,e:
-                logger.log_exc("save network controller failed: %s" % controller_network)
-                raise e
-
+	    self.save_controller_network(controller_network)
+	    logger.info("saved network controller: %s" % (controller_network))
 
     def delete_record(self, controller_network):
         driver = OpenStackDriver().client_driver(caller=controller_network.network.owner.creator,
diff --git a/planetstack/openstack_observer/steps/sync_controller_networks.yaml b/planetstack/openstack_observer/steps/sync_controller_networks.yaml
index 9b42ea6..8f0d4c1 100644
--- a/planetstack/openstack_observer/steps/sync_controller_networks.yaml
+++ b/planetstack/openstack_observer/steps/sync_controller_networks.yaml
@@ -27,5 +27,6 @@
         state=absent
         {% else %}
         state=present 
+        no_gateway=true 
         cidr={{ cidr }}
         {% endif %}
diff --git a/planetstack/openstack_observer/steps/sync_controller_site_privileges.py b/planetstack/openstack_observer/steps/sync_controller_site_privileges.py
index 99a5987..c87f6d5 100644
--- a/planetstack/openstack_observer/steps/sync_controller_site_privileges.py
+++ b/planetstack/openstack_observer/steps/sync_controller_site_privileges.py
@@ -59,20 +59,15 @@
 		       'tenant':controller_site_privilege.site_privilege.site.login_base}    
 	
 	    rendered = template.render(user_fields)
-	    res = run_template('sync_controller_users.yaml', user_fields,path='controller_site_privileges')
+	    expected_length = len(roles) + 1
+	    res = run_template('sync_controller_users.yaml', user_fields,path='controller_site_privileges', expected_num=expected_length)
 
 	    # 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_site_privilege.role_id = res[0]['id']
-                controller_site_privilege.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'])
+            controller_site_privilege.role_id = res[0]['id']
+            controller_site_privilege.save()
 
     def delete_record(self, controller_site_privilege):
         if controller_site_privilege.role_id:
diff --git a/planetstack/openstack_observer/steps/sync_controller_sites.py b/planetstack/openstack_observer/steps/sync_controller_sites.py
index 71837a3..3aa20d7 100644
--- a/planetstack/openstack_observer/steps/sync_controller_sites.py
+++ b/planetstack/openstack_observer/steps/sync_controller_sites.py
@@ -26,15 +26,10 @@
 		         'tenant_description': controller_site.site.name}
 
 	rendered = template.render(tenant_fields)
-	res = run_template('sync_controller_sites.yaml', tenant_fields, path='controller_sites')
+	res = run_template('sync_controller_sites.yaml', tenant_fields, path='controller_sites', expected_num=1)
 
-	if (len(res)==1):
-		controller_site.tenant_id = res[0]['id']
-        	controller_site.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'])
+	controller_site.tenant_id = res[0]['id']
+        controller_site.save()
             
     def delete_record(self, controller_site):
 	if controller_site.tenant_id:
diff --git a/planetstack/openstack_observer/steps/sync_controller_slice_privileges.py b/planetstack/openstack_observer/steps/sync_controller_slice_privileges.py
index 94d5d21..5ec434c 100644
--- a/planetstack/openstack_observer/steps/sync_controller_slice_privileges.py
+++ b/planetstack/openstack_observer/steps/sync_controller_slice_privileges.py
@@ -59,20 +59,15 @@
 		       'tenant':controller_slice_privilege.slice_privilege.slice.name}    
 	
 	    rendered = template.render(user_fields)
-	    res = run_template('sync_controller_users.yaml', user_fields,path='controller_slice_privileges')
+	    expected_length = len(roles) + 1
+	    res = run_template('sync_controller_users.yaml', user_fields, path='controller_slice_privileges', expected_num=expected_length)
 
 	    # 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_slice_privilege.role_id = res[0]['id']
-                controller_slice_privilege.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'])
+            controller_slice_privilege.role_id = res[0]['id']
+            controller_slice_privilege.save()
 
     def delete_record(self, controller_slice_privilege):
         if controller_slice_privilege.role_id:
diff --git a/planetstack/openstack_observer/steps/sync_controller_slices.py b/planetstack/openstack_observer/steps/sync_controller_slices.py
index 0f8b6fc..0e37524 100644
--- a/planetstack/openstack_observer/steps/sync_controller_slices.py
+++ b/planetstack/openstack_observer/steps/sync_controller_slices.py
@@ -50,22 +50,19 @@
                          'ansible_tag':'%s@%s'%(controller_slice.slice.name,controller_slice.controller.name),
                          'max_instances':max_instances}
 
-        res = run_template('sync_controller_slices.yaml', tenant_fields, path='controller_slices')
         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):
-                try:
-                        driver = OpenStackDriver().admin_driver(controller=controller_slice.controller)
-                        driver.shell.nova.quotas.update(tenant_id=controller_slice.tenant_id, instances=int(controller_slice.slice.max_slivers))
-                except:
-                        logger.log_exc('Could not update quota for %s'%controller_slice.slice.name)
-                        raise Exception('Could not update quota for %s'%controller_slice.slice.name)
+        res = run_template('sync_controller_slices.yaml', tenant_fields, path='controller_slices', expected_num=expected_num)
+        tenant_id = res[0]['id']
+        if (not controller_slice.tenant_id):
+            try:
+                    driver = OpenStackDriver().admin_driver(controller=controller_slice.controller)
+                    driver.shell.nova.quotas.update(tenant_id=controller_slice.tenant_id, instances=int(controller_slice.slice.max_slivers))
+            except:
+                    logger.log_exc('Could not update quota for %s'%controller_slice.slice.name)
+                    raise Exception('Could not update quota for %s'%controller_slice.slice.name)
                 
-                controller_slice.tenant_id = tenant_id
-                controller_slice.save()
+            controller_slice.tenant_id = tenant_id
+            controller_slice.save()
 
 
     def delete_record(self, controller_slice):
diff --git a/planetstack/openstack_observer/steps/sync_controller_users.py b/planetstack/openstack_observer/steps/sync_controller_users.py
index 0c35047..ca2909c 100644
--- a/planetstack/openstack_observer/steps/sync_controller_users.py
+++ b/planetstack/openstack_observer/steps/sync_controller_users.py
@@ -65,20 +65,12 @@
 		       'tenant':controller_user.user.site.login_base}    
 	
 	    rendered = template.render(user_fields)
-	    res = run_template('sync_controller_users.yaml', user_fields,path='controller_users')
-
-	    # 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.kuser_id = res[0]['id']
-                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'])
+
+	    res = run_template('sync_controller_users.yaml', user_fields,path='controller_users', expected_num=expected_length)
+
+            controller_user.kuser_id = res[0]['id']
+            controller_user.save()
 
     def delete_record(self, controller_user):
         if controller_user.kuser_id:
diff --git a/planetstack/openstack_observer/steps/sync_slivers.py b/planetstack/openstack_observer/steps/sync_slivers.py
index 8155c10..3989c16 100644
--- a/planetstack/openstack_observer/steps/sync_slivers.py
+++ b/planetstack/openstack_observer/steps/sync_slivers.py
@@ -1,5 +1,6 @@
 import os
 import base64
+import socket
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
@@ -120,28 +121,35 @@
                      '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]['info']['OS-EXT-SRV-ATTR:instance_name'] # 0 is for the key
-            sliver_uuid = res[1]['id'] # 0 is for the key
+        res = run_template('sync_slivers.yaml', tenant_fields,path='slivers', expected_num=2)
+        sliver_id = res[1]['info']['OS-EXT-SRV-ATTR:instance_name'] # 0 is for the key
+        sliver_uuid = res[1]['id'] # 0 is for the key
 
-            try:
-                hostname = res[1]['info']['OS-EXT-SRV-ATTR:hypervisor_hostname']
-                ip = socket.gethostbyname(hostname)
-                sliver.ip = ip
-            except:
-                pass
+        try:
+            hostname = res[1]['info']['OS-EXT-SRV-ATTR:hypervisor_hostname']
+            ip = socket.gethostbyname(hostname)
+            sliver.ip = ip
+        except:
+            pass
 
-            sliver.instance_id = sliver_id
-            sliver.instance_uuid = sliver_uuid
-            sliver.instance_name = sliver_name
-            sliver.save()
+        sliver.instance_id = sliver_id
+        sliver.instance_uuid = sliver_uuid
+        sliver.instance_name = sliver_name
+        sliver.save()
 
     def delete_record(self, sliver):
-        sliver_name = '@'.join([sliver.slice.name,sliver.node.name])
-        tenant_fields = {'name':sliver_name,
-                         'ansible_tag':sliver_name
-                        }
-        res = run_template('delete_slivers.yaml', tenant_fields, path='slivers')
+        sliver_name = '%s-%d'%(sliver.slice.name,sliver.id)
+        controller = sliver.node.site_deployment.controller
+        tenant_fields = {'endpoint':controller.auth_url,
+                     'admin_user': sliver.creator.email,
+                     'admin_password': sliver.creator.remote_password,
+                     'admin_tenant': sliver.slice.name,
+                     'tenant': sliver.slice.name,
+                     'tenant_description': sliver.slice.description,
+                     'name':sliver_name,
+                     'ansible_tag':sliver_name,
+                     'delete': True}
+
+        res = run_template('sync_slivers.yaml', tenant_fields,path='slivers')
+        if (len(res)!=1):
+            raise Exception('Could not delete sliver %s'%sliver.slice.name)
diff --git a/planetstack/openstack_observer/syncstep.py b/planetstack/openstack_observer/syncstep.py
index 72a740c..fd34f55 100644
--- a/planetstack/openstack_observer/syncstep.py
+++ b/planetstack/openstack_observer/syncstep.py
@@ -83,15 +83,15 @@
                 else:
                     self.sync_record(o)
                     o.enacted = datetime.now() # Is this the same timezone? XXX
-                    o.backend_status = "OK"
+                    o.backend_status = "1 - OK"
                     o.save(update_fields=['enacted'])
             except Exception,e:
                 logger.log_exc("sync step failed!")
                 str_e = '%r'%e
                 try:
-                    o.backend_status = self.error_map.map(str_e)
+                    o.backend_status = '2 - %s'%self.error_map.map(str_e)
                 except:
-                    o.backend_status = str_e
+                    o.backend_status = '2 - %s'%str_e
 
                 # TOFIX:
                 # DatabaseError: value too long for type character varying(140)