Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/openstack/driver.py b/planetstack/openstack/driver.py
index c3e1f35..4f1c177 100644
--- a/planetstack/openstack/driver.py
+++ b/planetstack/openstack/driver.py
@@ -417,11 +417,12 @@
 
         return (subnet_id, subnet)
 
-    def spawn_instance(self, name, key_name=None, hostname=None, image_id=None, security_group=None, pubkeys=[], nics=None, metadata=None, userdata=None):
-        flavor_name = self.config.nova_default_flavor
+    def spawn_instance(self, name, key_name=None, hostname=None, image_id=None, security_group=None, pubkeys=[], nics=None, metadata=None, userdata=None, flavor_name=None):
+        if not flavor_name:
+            flavor_name = self.config.nova_default_flavor
+
         flavor = self.shell.nova.flavors.find(name=flavor_name)
-        #if not image:
-        #    image = self.config.nova_default_imave
+
         if not security_group:
             security_group = self.config.nova_default_security_group
 
diff --git a/planetstack/openstack_observer/event_loop.py b/planetstack/openstack_observer/event_loop.py
index 1f15a8e..9e8c7b4 100644
--- a/planetstack/openstack_observer/event_loop.py
+++ b/planetstack/openstack_observer/event_loop.py
@@ -240,6 +240,8 @@
 	def sync(self, S, deletion):
 		step = self.step_lookup[S]
 		start_time=time.time()
+
+                logger.info("Starting to work on step %s" % step.__name__)
 		
 		dependency_graph = self.dependency_graph if not deletion else self.deletion_dependency_graph
 
@@ -252,9 +254,14 @@
 
 		if (has_deps):
 			for d in deps:
+                                if d==step.__name__:
+                                    logger.info("   step %s self-wait skipped" % step.__name__)
+                                    continue
+
 				cond = self.step_conditions[d]
 				cond.acquire()
 				if (self.step_status[d] is STEP_STATUS_WORKING):
+                                        logger.info("  step %s wait on dep %s" % (step.__name__, d))
 					cond.wait()
 				cond.release()
 			go = self.step_status[d] == STEP_STATUS_OK
@@ -262,7 +269,9 @@
 			go = True
 
 		if (not go):
-			self.failed_steps.append(sync_step)
+                        # SMBAKER: sync_step was not defined here, so I changed
+                        #    this from 'sync_step' to 'step'. Verify.
+			self.failed_steps.append(step)
 			my_status = STEP_STATUS_KO
 		else:
 			sync_step = step(driver=self.driver,error_map=self.error_mapper)
@@ -270,7 +279,7 @@
 			sync_step.dependencies = []
 			try:
 				mlist = sync_step.provides
-				
+
 				for m in mlist:
 					sync_step.dependencies.extend(self.model_dependency_graph[m.__name__])
 			except KeyError:
@@ -285,11 +294,11 @@
 				self.check_schedule(sync_step, deletion) # dont run sync_network_routes if time since last run < 1 hour
 				should_run = True
 			except StepNotReady:
-				logging.info('Step not ready: %s'%sync_step.__name__)
+				logger.info('Step not ready: %s'%sync_step.__name__)
 				self.failed_steps.append(sync_step)
 				my_status = STEP_STATUS_KO
 			except Exception,e:
-				logging.error('%r',e)
+				logger.error('%r' % e)
 				logger.log_exc("sync step failed: %r. Deletion: %r"%(sync_step,deletion))
 				self.failed_steps.append(sync_step)
 				my_status = STEP_STATUS_KO
@@ -307,16 +316,18 @@
 					if failed_objects:
 						self.failed_step_objects.update(failed_objects)
 
+                                        logger.info("Step %r succeeded" % step)
 					my_status = STEP_STATUS_OK
 					self.update_run_time(sync_step,deletion)
 				except Exception,e:
-					logging.error('Model step failed. This seems like a misconfiguration or bug: %r. This error will not be relayed to the user!',e)
+					logger.error('Model step %r failed. This seems like a misconfiguration or bug: %r. This error will not be relayed to the user!' % (step, e))
 					logger.log_exc(e)
 					self.failed_steps.append(S)
 					my_status = STEP_STATUS_KO
 			else:
+                                logger.info("Step %r succeeded due to non-run" % step)
 				my_status = STEP_STATUS_OK
-		
+
 		try:
 			my_cond = self.step_conditions[S]
 			my_cond.acquire()
@@ -324,7 +335,7 @@
 			my_cond.notify_all()
 			my_cond.release()
 		except KeyError,e:
-			logging.info('Step %r is a leaf')
+			logger.info('Step %r is a leaf' % step)
 			pass
 
 	def run(self):
@@ -388,6 +399,6 @@
 
 				self.save_run_times()
 			except Exception, e:
-				logging.error('Core error. This seems like a misconfiguration or bug: %r. This error will not be relayed to the user!',e)
+				logger.error('Core error. This seems like a misconfiguration or bug: %r. This error will not be relayed to the user!' % e)
 				logger.log_exc("Exception in observer run loop")
 				traceback.print_exc()
diff --git a/planetstack/openstack_observer/steps/__init__.py b/planetstack/openstack_observer/steps/__init__.py
index 2ef6922..0151af3 100644
--- a/planetstack/openstack_observer/steps/__init__.py
+++ b/planetstack/openstack_observer/steps/__init__.py
@@ -1,16 +1,16 @@
-#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_site_privileges import SyncSitePrivileges
-from .sync_sites import SyncSites
-from .sync_slice_memberships import SyncSliceMemberships
-from .sync_slices import SyncSlices
-#from .sync_sliver_ips import SyncSliverIps
-from .sync_slivers import SyncSlivers
-from .sync_users import SyncUsers
-from .sync_roles import SyncRoles
-from .sync_nodes import SyncNodes
-from .sync_images import SyncImages
-from .sync_image_deployments import SyncImageDeployments
-from .garbage_collector import GarbageCollector
+##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_site_privileges import SyncSitePrivileges
+#from .sync_sites import SyncSites
+#from .sync_slice_memberships import SyncSliceMemberships
+#from .sync_slices import SyncSlices
+##from .sync_sliver_ips import SyncSliverIps
+#from .sync_slivers import SyncSlivers
+#from .sync_users import SyncUsers
+#from .sync_roles import SyncRoles
+#from .sync_nodes import SyncNodes
+#from .sync_images import SyncImages
+#from .sync_image_deployments import SyncImageDeployments
+#from .garbage_collector import GarbageCollector
diff --git a/planetstack/openstack_observer/steps/sync_network_deployments.py b/planetstack/openstack_observer/steps/sync_network_deployments.py
index 8eecb3b..77d3a3a 100644
--- a/planetstack/openstack_observer/steps/sync_network_deployments.py
+++ b/planetstack/openstack_observer/steps/sync_network_deployments.py
@@ -103,6 +103,10 @@
         network_deployment.save()
 
     def sync_record(self, network_deployment):
+        if not network_deployment.deployment.admin_user:
+            logger.info("deployment %r has no admin_user, skipping" % network_deployment.deployment)
+            return
+
         if network_deployment.network.owner and network_deployment.network.owner.creator:
             try:
                 # update manager context
diff --git a/planetstack/openstack_observer/steps/sync_nodes.py b/planetstack/openstack_observer/steps/sync_nodes.py
index 740b5e1..d648b7d 100644
--- a/planetstack/openstack_observer/steps/sync_nodes.py
+++ b/planetstack/openstack_observer/steps/sync_nodes.py
@@ -1,12 +1,15 @@
 import os
 import base64
 import random
-from datetime import datetime 
+from datetime import datetime
 from django.db.models import F, Q
 from planetstack.config import Config
 from observer.openstacksyncstep import OpenStackSyncStep
 from core.models.node import Node
 from core.models.site import Site, Deployment
+from util.logger import Logger, logging
+
+logger = Logger(level=logging.INFO)
 
 class SyncNodes(OpenStackSyncStep):
     provides=[Node]
@@ -23,12 +26,17 @@
         nodes = Node.objects.all()
         node_hostnames  = [node.name for node in nodes]
 
-        # fetch all nodes from each deployment 
+        # fetch all nodes from each deployment
         deployments = Deployment.objects.all()
         new_nodes = []
         for deployment in deployments:
-            driver = self.driver.admin_driver(deployment=deployment.name)
-            compute_nodes = driver.shell.nova.hypervisors.list()
+            try:
+                driver = self.driver.admin_driver(deployment=deployment.name)
+                compute_nodes = driver.shell.nova.hypervisors.list()
+            except:
+                logger.log_exc("Failed to get nodes from deployment %s" % str(deployment))
+                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.
diff --git a/planetstack/openstack_observer/steps/sync_slice_deployments.py b/planetstack/openstack_observer/steps/sync_slice_deployments.py
index fff2e04..03ea2ca 100644
--- a/planetstack/openstack_observer/steps/sync_slice_deployments.py
+++ b/planetstack/openstack_observer/steps/sync_slice_deployments.py
@@ -42,6 +42,11 @@
 
     def sync_record(self, slice_deployment):
         logger.info("sync'ing slice deployment %s" % slice_deployment)
+
+        if not slice_deployment.deployment.admin_user:
+            logger.info("deployment %r has no admin_user, skipping" % slice_deployment.deployment)
+            return
+
         if not slice_deployment.tenant_id:
             nova_fields = {'tenant_name': slice_deployment.slice.name,
                    'description': slice_deployment.slice.description,
diff --git a/planetstack/openstack_observer/steps/sync_slivers.py b/planetstack/openstack_observer/steps/sync_slivers.py
index 299b02f..dcedd1d 100644
--- a/planetstack/openstack_observer/steps/sync_slivers.py
+++ b/planetstack/openstack_observer/steps/sync_slivers.py
@@ -86,7 +86,8 @@
                                 hostname = sliver.node.name,
                                 pubkeys = pubkeys,
                                 nics = nics,
-                                userdata = userData )
+                                userdata = userData,
+                                flavor_name = sliver.flavor.flavor )
             sliver.instance_id = instance.id
             sliver.instance_name = getattr(instance, 'OS-EXT-SRV-ATTR:instance_name')
             sliver.save()    
diff --git a/planetstack/openstack_observer/steps/sync_user_deployments.py b/planetstack/openstack_observer/steps/sync_user_deployments.py
index 42aae56..43ca260 100644
--- a/planetstack/openstack_observer/steps/sync_user_deployments.py
+++ b/planetstack/openstack_observer/steps/sync_user_deployments.py
@@ -25,6 +25,11 @@
 
     def sync_record(self, user_deployment):
         logger.info("sync'ing user %s at deployment %s" % (user_deployment.user, user_deployment.deployment.name))
+
+        if not user_deployment.deployment.admin_user:
+            logger.info("deployment %r has no admin_user, skipping" % user_deployment.deployment)
+            return
+
         name = user_deployment.user.email[:user_deployment.user.email.find('@')]
         user_fields = {'name': user_deployment.user.email,
                        'email': user_deployment.user.email,