]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Allow resources to be updated in parallel
authorZane Bitter <zbitter@redhat.com>
Fri, 30 Aug 2013 18:45:54 +0000 (20:45 +0200)
committerZane Bitter <zbitter@redhat.com>
Fri, 30 Aug 2013 18:51:03 +0000 (20:51 +0200)
Turn Resource.update() into a coroutine.

Change-Id: I625a2d81095cc28161f8e2342121bfe1939611e3

12 files changed:
heat/engine/resource.py
heat/engine/resources/autoscaling.py
heat/tests/test_autoscaling.py
heat/tests/test_ceilometer_alarm.py
heat/tests/test_cw_alarm.py
heat/tests/test_instance.py
heat/tests/test_instance_group.py
heat/tests/test_neutron_firewall.py
heat/tests/test_neutron_loadbalancer.py
heat/tests/test_rackspace_cloud_server.py
heat/tests/test_resource.py
heat/tests/test_server.py

index cd82d88a5fa07aa50730505fa9f9b25b3af0a743..c5b3cb70424d5b8ecc17168a28a0740123c94a73 100644 (file)
@@ -420,7 +420,11 @@ class Resource(object):
             tmpl_diff = self.update_template_diff(after, before)
             prop_diff = self.update_template_diff_properties(after, before)
             if callable(getattr(self, 'handle_update', None)):
-                result = self.handle_update(after, tmpl_diff, prop_diff)
+                handle_data = self.handle_update(after, tmpl_diff, prop_diff)
+                yield
+                if callable(getattr(self, 'check_update_complete', None)):
+                    while not self.check_update_complete(handle_data):
+                        yield
         except UpdateReplace:
             logger.debug("Resource %s update requires replacement" % self.name)
             raise
index cfd124d030913b49ceb6e13b039574ed2e0e56e4..7bdfbd045dc1ad367cfb971ba915a1907a3acbb2 100644 (file)
@@ -23,6 +23,7 @@ from heat.openstack.common import log as logging
 from heat.openstack.common import timeutils
 from heat.engine.properties import Properties
 from heat.engine import properties
+from heat.engine import scheduler
 from heat.engine import stack_resource
 
 logger = logging.getLogger(__name__)
@@ -243,7 +244,7 @@ class InstanceGroup(stack_resource.StackResource):
                         (lb,))
                 resolved_snippet = self.stack.resolve_static_data(
                     lb_resource.json_snippet)
-                lb_resource.update(resolved_snippet)
+                scheduler.TaskRunner(lb_resource.update, resolved_snippet)()
 
     def FnGetRefId(self):
         return unicode(self.name)
index 84cb6e6b5a75737aec2b76a988f8dde81b08954c..951b2b33a749a5c77e09ebd62b25e53d50ddc1d7 100644 (file)
@@ -213,7 +213,7 @@ class AutoScalingTest(HeatTestCase):
         # Reduce the min size to 0, should complete without adjusting
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['MinSize'] = '0'
-        self.assertEqual(None, rsrc.update(update_snippet))
+        scheduler.TaskRunner(rsrc.update, update_snippet)()
         self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
 
         # trigger adjustment to reduce to 0, there should be no more instances
@@ -241,8 +241,8 @@ class AutoScalingTest(HeatTestCase):
         self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['AvailabilityZones'] = ['foo']
-        self.assertRaises(resource.UpdateReplace,
-                          rsrc.update, update_snippet)
+        updater = scheduler.TaskRunner(rsrc.update, update_snippet)
+        self.assertRaises(resource.UpdateReplace, updater)
 
         rsrc.delete()
         self.m.VerifyAll()
@@ -503,7 +503,7 @@ class AutoScalingTest(HeatTestCase):
         # Reduce the max size to 2, should complete without adjusting
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['MaxSize'] = '2'
-        self.assertEqual(None, rsrc.update(update_snippet))
+        scheduler.TaskRunner(rsrc.update, update_snippet)()
         self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
 
         self.assertEqual('2', rsrc.properties['MaxSize'])
@@ -534,7 +534,7 @@ class AutoScalingTest(HeatTestCase):
 
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['MinSize'] = '2'
-        self.assertEqual(None, rsrc.update(update_snippet))
+        scheduler.TaskRunner(rsrc.update, update_snippet)()
         self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
                          rsrc.get_instance_names())
         self.assertEqual('2', rsrc.properties['MinSize'])
@@ -565,7 +565,7 @@ class AutoScalingTest(HeatTestCase):
 
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['DesiredCapacity'] = '2'
-        self.assertEqual(None, rsrc.update(update_snippet))
+        scheduler.TaskRunner(rsrc.update, update_snippet)()
         self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
                          rsrc.get_instance_names())
 
@@ -593,7 +593,7 @@ class AutoScalingTest(HeatTestCase):
         # have no effect, it's an optional parameter
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         del(update_snippet['Properties']['DesiredCapacity'])
-        self.assertEqual(None, rsrc.update(update_snippet))
+        scheduler.TaskRunner(rsrc.update, update_snippet)()
         self.assertEqual(['WebServerGroup-0', 'WebServerGroup-1'],
                          rsrc.get_instance_names())
 
@@ -619,7 +619,7 @@ class AutoScalingTest(HeatTestCase):
         self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['Cooldown'] = '61'
-        self.assertEqual(None, rsrc.update(update_snippet))
+        scheduler.TaskRunner(rsrc.update, update_snippet)()
         self.assertEqual('61', rsrc.properties['Cooldown'])
 
         rsrc.delete()
@@ -660,7 +660,7 @@ class AutoScalingTest(HeatTestCase):
         self.assertEqual(['WebServerGroup-0'], rsrc.get_instance_names())
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['Cooldown'] = '61'
-        self.assertEqual(None, rsrc.update(update_snippet))
+        scheduler.TaskRunner(rsrc.update, update_snippet)()
 
         rsrc.delete()
         self.m.VerifyAll()
@@ -1380,7 +1380,7 @@ class AutoScalingTest(HeatTestCase):
         # Update scaling policy
         update_snippet = copy.deepcopy(up_policy.parsed_template())
         update_snippet['Properties']['ScalingAdjustment'] = '2'
-        self.assertEqual(None, up_policy.update(update_snippet))
+        scheduler.TaskRunner(up_policy.update, update_snippet)()
         self.assertEqual('2',
                          up_policy.properties['ScalingAdjustment'])
 
index 84522a1a235dd0ad427a6c5454fec2c05bf3362a..a07f0ecdc945c397a56d21c45cdbd81979c0d6b0 100644 (file)
@@ -164,7 +164,7 @@ class CeilometerAlarmTest(HeatTestCase):
         snippet['Properties']['alarm_actions'] = []
         snippet['Properties']['ok_actions'] = ['signal_handler']
 
-        self.assertEqual(None, rsrc.update(snippet))
+        scheduler.TaskRunner(rsrc.update, snippet)()
 
         self.m.VerifyAll()
 
@@ -189,8 +189,8 @@ class CeilometerAlarmTest(HeatTestCase):
         snippet = copy.deepcopy(rsrc.parsed_template())
         snippet['Properties']['counter_name'] = 'temp'
 
-        self.assertRaises(resource.UpdateReplace,
-                          rsrc.update, snippet)
+        updater = scheduler.TaskRunner(rsrc.update, snippet)
+        self.assertRaises(resource.UpdateReplace, updater)
 
         self.m.VerifyAll()
 
index 188bff075fdcb4b336e0dc117eced260d1215000..c89ebdb0831627ebce36fe8b28444e27344f8ca5 100644 (file)
@@ -90,7 +90,7 @@ class CloudWatchAlarmTest(HeatTestCase):
         snippet['Properties']['Statistic'] = 'Maximum'
         snippet['Properties']['Threshold'] = '39'
 
-        self.assertEqual(None, rsrc.update(snippet))
+        scheduler.TaskRunner(rsrc.update, snippet)()
 
         rsrc.delete()
         self.m.VerifyAll()
@@ -116,8 +116,8 @@ class CloudWatchAlarmTest(HeatTestCase):
         snippet = copy.deepcopy(rsrc.parsed_template())
         snippet['Properties']['MetricName'] = 'temp'
 
-        self.assertRaises(resource.UpdateReplace,
-                          rsrc.update, snippet)
+        updater = scheduler.TaskRunner(rsrc.update, snippet)
+        self.assertRaises(resource.UpdateReplace, updater)
 
         rsrc.delete()
         self.m.VerifyAll()
index cb96e88cead51049dc70c0d3650e8248048c20ab..5377ac449d4d93f10c21ce782c794b5c24321634 100644 (file)
@@ -307,7 +307,7 @@ class InstancesTest(HeatTestCase):
 
         update_template = copy.deepcopy(instance.t)
         update_template['Metadata'] = {'test': 123}
-        self.assertEqual(None, instance.update(update_template))
+        scheduler.TaskRunner(instance.update, update_template)()
         self.assertEqual(instance.metadata, {'test': 123})
 
     def test_instance_update_instance_type(self):
@@ -337,7 +337,7 @@ class InstancesTest(HeatTestCase):
             body={'confirmResize': None}).AndReturn((202, None))
         self.m.ReplayAll()
 
-        self.assertEqual(None, instance.update(update_template))
+        scheduler.TaskRunner(instance.update, update_template)()
         self.assertEqual(instance.state, (instance.UPDATE, instance.COMPLETE))
         self.m.VerifyAll()
 
@@ -366,8 +366,8 @@ class InstancesTest(HeatTestCase):
             body={'resize': {'flavorRef': 2}}).AndReturn((202, None))
         self.m.ReplayAll()
 
-        error = self.assertRaises(exception.ResourceFailure,
-                                  instance.update, update_template)
+        updater = scheduler.TaskRunner(instance.update, update_template)
+        error = self.assertRaises(exception.ResourceFailure, updater)
         self.assertEqual(
             "Error: Resizing to 'm1.small' failed, status 'ACTIVE'",
             str(error))
@@ -381,8 +381,8 @@ class InstancesTest(HeatTestCase):
 
         update_template = copy.deepcopy(instance.t)
         update_template['Notallowed'] = {'test': 123}
-        self.assertRaises(resource.UpdateReplace,
-                          instance.update, update_template)
+        updater = scheduler.TaskRunner(instance.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_instance_update_properties(self):
         return_server = self.fc.servers.list()[1]
@@ -391,8 +391,8 @@ class InstancesTest(HeatTestCase):
 
         update_template = copy.deepcopy(instance.t)
         update_template['Properties']['KeyName'] = 'mustreplace'
-        self.assertRaises(resource.UpdateReplace,
-                          instance.update, update_template)
+        updater = scheduler.TaskRunner(instance.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_instance_status_build(self):
         return_server = self.fc.servers.list()[0]
index 8e06468c1ce6ec58c35387f2b0b3f7c155b2bdfd..e1b4c9b73e3c8299ec6dfc8fa5aad5d2ce3e7387 100644 (file)
@@ -254,8 +254,8 @@ class InstanceGroupTest(HeatTestCase):
         update_snippet['Properties']['Size'] = '2'
         tmpl_diff = {'Properties': {'Size': '2'}}
         prop_diff = {'Size': '2'}
-        self.assertRaises(exception.ResourceFailure,
-                          rsrc.update, update_snippet)
+        updater = scheduler.TaskRunner(rsrc.update, update_snippet)
+        self.assertRaises(exception.ResourceFailure, updater)
 
         self.assertEqual((rsrc.UPDATE, rsrc.FAILED), rsrc.state)
 
@@ -281,8 +281,8 @@ class InstanceGroupTest(HeatTestCase):
 
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Metadata'] = 'notallowedforupdate'
-        self.assertRaises(resource.UpdateReplace,
-                          rsrc.update, update_snippet)
+        updater = scheduler.TaskRunner(rsrc.update, update_snippet)
+        self.assertRaises(resource.UpdateReplace, updater)
 
         rsrc.delete()
         self.m.VerifyAll()
@@ -302,8 +302,8 @@ class InstanceGroupTest(HeatTestCase):
 
         update_snippet = copy.deepcopy(rsrc.parsed_template())
         update_snippet['Properties']['AvailabilityZones'] = ['wibble']
-        self.assertRaises(resource.UpdateReplace,
-                          rsrc.update, update_snippet)
+        updater = scheduler.TaskRunner(rsrc.update, update_snippet)
+        self.assertRaises(resource.UpdateReplace, updater)
 
         rsrc.delete()
         self.m.VerifyAll()
index fc532adbe6ecc0d015de80ddb14b1f950ae89b16..487e048df167530309aaf2bee0ecd7c427612425 100644 (file)
@@ -213,7 +213,7 @@ class FirewallTest(HeatTestCase):
 
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['admin_state_up'] = False
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
 
         self.m.VerifyAll()
 
@@ -343,7 +343,7 @@ class FirewallPolicyTest(HeatTestCase):
 
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['firewall_rules'] = ['3', '4']
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
 
         self.m.VerifyAll()
 
@@ -475,6 +475,6 @@ class FirewallRuleTest(HeatTestCase):
 
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['protocol'] = 'icmp'
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
 
         self.m.VerifyAll()
index 3fd64fba4178997232f4b8eb8d3f6d76b7682a94..7b944dbfeabfcde10a50d2eeabe82132c881c60d 100644 (file)
@@ -212,7 +212,7 @@ class HealthMonitorTest(HeatTestCase):
 
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['delay'] = 10
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
 
         self.m.VerifyAll()
 
@@ -490,7 +490,7 @@ class PoolTest(HeatTestCase):
 
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['admin_state_up'] = False
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
 
         self.m.VerifyAll()
 
@@ -533,7 +533,7 @@ class PoolTest(HeatTestCase):
 
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['monitors'] = ['mon123', 'mon789']
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
 
         self.m.VerifyAll()
 
@@ -588,7 +588,7 @@ class LoadBalancerTest(HeatTestCase):
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['members'] = ['5678']
 
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
         self.m.VerifyAll()
 
     def test_update_missing_member(self):
@@ -602,7 +602,7 @@ class LoadBalancerTest(HeatTestCase):
         update_template = copy.deepcopy(rsrc.t)
         update_template['Properties']['members'] = []
 
-        self.assertEqual(None, rsrc.update(update_template))
+        scheduler.TaskRunner(rsrc.update, update_template)()
         self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
         self.m.VerifyAll()
 
index fa109bd1fbae81220d39fa73633a6d00950a71ab..0b46b8a00d3b193c4eb8daef2d70ab00791b5293 100644 (file)
@@ -313,7 +313,7 @@ class RackspaceCloudServerTest(HeatTestCase):
         self.m.ReplayAll()
         update_template = copy.deepcopy(cs.t)
         update_template['Metadata'] = {'test': 123}
-        self.assertEqual(None, cs.update(update_template))
+        scheduler.TaskRunner(cs.update, update_template)()
         self.assertEqual(cs.metadata, {'test': 123})
 
     def test_cs_update_replace(self):
@@ -322,7 +322,8 @@ class RackspaceCloudServerTest(HeatTestCase):
 
         update_template = copy.deepcopy(cs.t)
         update_template['Notallowed'] = {'test': 123}
-        self.assertRaises(resource.UpdateReplace, cs.update, update_template)
+        updater = scheduler.TaskRunner(cs.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_cs_update_properties(self):
         return_server = self.fc.servers.list()[1]
@@ -330,8 +331,8 @@ class RackspaceCloudServerTest(HeatTestCase):
 
         update_template = copy.deepcopy(cs.t)
         update_template['Properties']['user_data'] = 'mustreplace'
-        self.assertRaises(resource.UpdateReplace,
-                          cs.update, update_template)
+        updater = scheduler.TaskRunner(cs.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_cs_status_build(self):
         return_server = self.fc.servers.list()[0]
index 3b9058177b4c7477051a322e9dac7630250a8501..7cb1919895d38e1e6b38fd24aff0210df88e28f6 100644 (file)
@@ -338,7 +338,7 @@ class ResourceTest(HeatTestCase):
             utmpl, tmpl_diff, prop_diff).AndReturn(None)
         self.m.ReplayAll()
 
-        self.assertEqual(None, res.update(utmpl))
+        scheduler.TaskRunner(res.update, utmpl)()
         self.assertEqual((res.UPDATE, res.COMPLETE), res.state)
         self.m.VerifyAll()
 
@@ -358,7 +358,8 @@ class ResourceTest(HeatTestCase):
             utmpl, tmpl_diff, prop_diff).AndRaise(resource.UpdateReplace())
         self.m.ReplayAll()
         # should be re-raised so parser.Stack can handle replacement
-        self.assertRaises(resource.UpdateReplace, res.update, utmpl)
+        updater = scheduler.TaskRunner(res.update, utmpl)
+        self.assertRaises(resource.UpdateReplace, updater)
         self.m.VerifyAll()
 
     def test_update_fail_missing_req_prop(self):
@@ -372,7 +373,8 @@ class ResourceTest(HeatTestCase):
 
         utmpl = {'Type': 'GenericResourceType', 'Properties': {}}
 
-        self.assertRaises(exception.ResourceFailure, res.update, utmpl)
+        updater = scheduler.TaskRunner(res.update, utmpl)
+        self.assertRaises(exception.ResourceFailure, updater)
         self.assertEqual((res.UPDATE, res.FAILED), res.state)
 
     def test_update_fail_prop_typo(self):
@@ -385,7 +387,8 @@ class ResourceTest(HeatTestCase):
 
         utmpl = {'Type': 'GenericResourceType', 'Properties': {'Food': 'xyz'}}
 
-        self.assertRaises(exception.ResourceFailure, res.update, utmpl)
+        updater = scheduler.TaskRunner(res.update, utmpl)
+        self.assertRaises(exception.ResourceFailure, updater)
         self.assertEqual((res.UPDATE, res.FAILED), res.state)
 
     def test_update_not_implemented(self):
@@ -403,7 +406,8 @@ class ResourceTest(HeatTestCase):
         generic_rsrc.ResourceWithProps.handle_update(
             utmpl, tmpl_diff, prop_diff).AndRaise(NotImplemented)
         self.m.ReplayAll()
-        self.assertRaises(exception.ResourceFailure, res.update, utmpl)
+        updater = scheduler.TaskRunner(res.update, utmpl)
+        self.assertRaises(exception.ResourceFailure, updater)
         self.assertEqual((res.UPDATE, res.FAILED), res.state)
         self.m.VerifyAll()
 
index 6e9ca7509cb002030af4445dd47c6752b65344ef..342eb1a1d2d0030a039eda73a80452cf562c55e6 100644 (file)
@@ -351,7 +351,7 @@ class ServersTest(HeatTestCase):
 
         update_template = copy.deepcopy(server.t)
         update_template['Metadata'] = {'test': 123}
-        self.assertEqual(None, server.update(update_template))
+        scheduler.TaskRunner(server.update, update_template)()
         self.assertEqual(server.metadata, {'test': 123})
 
         server.t['Metadata'] = {'test': 456}
@@ -385,7 +385,7 @@ class ServersTest(HeatTestCase):
             body={'confirmResize': None}).AndReturn((202, None))
         self.m.ReplayAll()
 
-        self.assertEqual(None, server.update(update_template))
+        scheduler.TaskRunner(server.update, update_template)()
         self.assertEqual(server.state, (server.UPDATE, server.COMPLETE))
         self.m.VerifyAll()
 
@@ -414,8 +414,8 @@ class ServersTest(HeatTestCase):
             body={'resize': {'flavorRef': 2}}).AndReturn((202, None))
         self.m.ReplayAll()
 
-        error = self.assertRaises(exception.ResourceFailure,
-                                  server.update, update_template)
+        updater = scheduler.TaskRunner(server.update, update_template)
+        error = self.assertRaises(exception.ResourceFailure, updater)
         self.assertEqual(
             "Error: Resizing to 'm1.small' failed, status 'ACTIVE'",
             str(error))
@@ -433,8 +433,8 @@ class ServersTest(HeatTestCase):
 
         update_template = copy.deepcopy(server.t)
         update_template['Properties']['flavor'] = 'm1.smigish'
-        self.assertRaises(resource.UpdateReplace,
-                          server.update, update_template)
+        updater = scheduler.TaskRunner(server.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_server_update_server_flavor_policy_update(self):
         stack_name = 'test_server_update_flavor_replace'
@@ -449,8 +449,8 @@ class ServersTest(HeatTestCase):
         # update
         update_template['Properties']['flavor_update_policy'] = 'REPLACE'
         update_template['Properties']['flavor'] = 'm1.smigish'
-        self.assertRaises(resource.UpdateReplace,
-                          server.update, update_template)
+        updater = scheduler.TaskRunner(server.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_server_update_replace(self):
         return_server = self.fc.servers.list()[1]
@@ -459,8 +459,8 @@ class ServersTest(HeatTestCase):
 
         update_template = copy.deepcopy(server.t)
         update_template['Notallowed'] = {'test': 123}
-        self.assertRaises(resource.UpdateReplace,
-                          server.update, update_template)
+        updater = scheduler.TaskRunner(server.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_server_update_properties(self):
         return_server = self.fc.servers.list()[1]
@@ -469,8 +469,8 @@ class ServersTest(HeatTestCase):
 
         update_template = copy.deepcopy(server.t)
         update_template['Properties']['key_name'] = 'mustreplace'
-        self.assertRaises(resource.UpdateReplace,
-                          server.update, update_template)
+        updater = scheduler.TaskRunner(server.update, update_template)
+        self.assertRaises(resource.UpdateReplace, updater)
 
     def test_server_status_build(self):
         return_server = self.fc.servers.list()[0]