]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Handle instance volume attachments with co-routines
authorZane Bitter <zbitter@redhat.com>
Fri, 24 May 2013 08:31:27 +0000 (10:31 +0200)
committerZane Bitter <zbitter@redhat.com>
Fri, 24 May 2013 08:31:27 +0000 (10:31 +0200)
Don't sit in a loop when attaching volumes to instances, use a task that
yields control and allows them to run in parallel - and, in future, in
parallel with other resources being created.

Change-Id: I4653baa87b09a9fb6c2c16b51218f4ea2f2ae6dd

heat/engine/resources/instance.py

index 2f637a5845a494590fa8dd9fab2ee5f6d168cd1a..2dfc4c9b2589e57982df8f8e3ff8ce985c31fe66 100644 (file)
@@ -345,23 +345,34 @@ class Instance(resource.Resource):
             if server is not None:
                 self.resource_id_set(server.id)
 
-        return server
-
-    def check_create_complete(self, server):
-        if server.status == 'ACTIVE':
-            return True
-
-        server.get()
-        if server.status in self._deferred_server_statuses:
-            return False
-        if server.status == 'ACTIVE':
-            self._set_ipaddress(server.networks)
-            self.attach_volumes()
-            return True
+        attach_tasks = (volume.VolumeAttachTask(self.stack,
+                                                self.resource_id,
+                                                volume_id,
+                                                device)
+                        for volume_id, device in self.volumes())
+        attach_volumes_task = scheduler.PollingTaskGroup(attach_tasks)
+
+        return server, scheduler.TaskRunner(attach_volumes_task)
+
+    def check_create_complete(self, cookie):
+        server, volume_attach = cookie
+
+        if not volume_attach.started():
+            if server.status != 'ACTIVE':
+                server.get()
+
+            if server.status in self._deferred_server_statuses:
+                return False
+            elif server.status == 'ACTIVE':
+                self._set_ipaddress(server.networks)
+                volume_attach.start()
+                return volume_attach.done()
+            else:
+                raise exception.Error('%s instance[%s] status[%s]' %
+                                      ('nova reported unexpected',
+                                       self.name, server.status))
         else:
-            raise exception.Error('%s instance[%s] status[%s]' %
-                                  ('nova reported unexpected',
-                                   self.name, server.status))
+            return volume_attach.step()
 
     def volumes(self):
         """
@@ -374,14 +385,6 @@ class Instance(resource.Resource):
 
         return ((vol['VolumeId'], vol['Device']) for vol in volumes)
 
-    def attach_volumes(self):
-        for volume_id, device in self.volumes():
-            attach_task = volume.VolumeAttachTask(self.stack,
-                                                  self.resource_id,
-                                                  volume_id,
-                                                  device)
-            scheduler.TaskRunner(attach_task)()
-
     def detach_volumes(self):
         for volume_id, device in self.volumes():
             detach_task = volume.VolumeDetachTask(self.stack,