From 62124c4530d19766c6b427448b3a59d7c157c2e7 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Fri, 1 Nov 2013 16:25:32 +1300 Subject: [PATCH] Implement update for neutron subnet resources This change allows any updatable properties to be updated on an existing subnet without replacement. Documentation is limited on what properties are updatable, so discovery was manual. Change-Id: Ia585d1b7d24900f2789f2127a76dd272aa7fb850 --- heat/engine/resources/neutron/subnet.py | 25 ++++++++++++++++---- heat/tests/test_neutron.py | 31 ++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/heat/engine/resources/neutron/subnet.py b/heat/engine/resources/neutron/subnet.py index 39799ac47c..f455c11ab9 100644 --- a/heat/engine/resources/neutron/subnet.py +++ b/heat/engine/resources/neutron/subnet.py @@ -36,20 +36,28 @@ class Subnet(neutron.NeutronResource): 'cidr': {'Type': 'String', 'Required': True}, 'value_specs': {'Type': 'Map', - 'Default': {}}, - 'name': {'Type': 'String'}, + 'Default': {}, + 'UpdateAllowed': True}, + 'name': {'Type': 'String', + 'UpdateAllowed': True}, 'ip_version': {'Type': 'Integer', 'AllowedValues': [4, 6], 'Default': 4}, - 'dns_nameservers': {'Type': 'List'}, - 'gateway_ip': {'Type': 'String'}, - 'enable_dhcp': {'Type': 'Boolean'}, + 'dns_nameservers': {'Type': 'List', + 'UpdateAllowed': True, + 'Default': []}, + 'gateway_ip': {'Type': 'String', + 'UpdateAllowed': True}, + 'enable_dhcp': {'Type': 'Boolean', + 'UpdateAllowed': True, + 'Default': True}, 'allocation_pools': {'Type': 'List', 'Schema': { 'Type': 'Map', 'Schema': allocation_schema }}, 'tenant_id': {'Type': 'String'}} + attributes_schema = { "name": _("Friendly name of the subnet."), "network_id": _("Parent network of the subnet."), @@ -65,6 +73,8 @@ class Subnet(neutron.NeutronResource): "show": _("All attributes."), } + update_allowed_keys = ('Properties',) + @staticmethod def _null_gateway_ip(props): if 'gateway_ip' not in props: @@ -100,6 +110,11 @@ class Subnet(neutron.NeutronResource): def _show_resource(self): return self.neutron().show_subnet(self.resource_id)['subnet'] + def handle_update(self, json_snippet, tmpl_diff, prop_diff): + props = self.prepare_update_properties(json_snippet) + self.neutron().update_subnet( + self.resource_id, {'subnet': props}) + def resource_mapping(): if clients.neutronclient is None: diff --git a/heat/tests/test_neutron.py b/heat/tests/test_neutron.py index 5be68c8fd4..6d207df051 100644 --- a/heat/tests/test_neutron.py +++ b/heat/tests/test_neutron.py @@ -388,6 +388,7 @@ class NeutronSubnetTest(HeatTestCase): self.m.StubOutWithMock(neutronclient.Client, 'create_subnet') self.m.StubOutWithMock(neutronclient.Client, 'delete_subnet') self.m.StubOutWithMock(neutronclient.Client, 'show_subnet') + self.m.StubOutWithMock(neutronclient.Client, 'update_subnet') self.m.StubOutWithMock(clients.OpenStackClients, 'keystone') utils.setup_dummy_db() @@ -411,7 +412,8 @@ class NeutronSubnetTest(HeatTestCase): {'start': u'10.0.3.20', 'end': u'10.0.3.150'}], 'ip_version': 4, 'cidr': u'10.0.3.0/24', - 'tenant_id': 'c1210485b2424d48804aad5d39c61b8f' + 'tenant_id': 'c1210485b2424d48804aad5d39c61b8f', + 'enable_dhcp': True } }).AndReturn({ "subnet": { @@ -453,6 +455,17 @@ class NeutronSubnetTest(HeatTestCase): neutronclient.Client.show_subnet( '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn(sn) + # Update script + neutronclient.Client.update_subnet( + '91e47a57-7508-46fe-afc9-fc454e8580e1', + {'subnet': { + 'dns_nameservers': ['8.8.8.8', '192.168.1.254'], + 'name': 'mysubnet', + 'enable_dhcp': True + }} + ) + + # Delete script neutronclient.Client.delete_subnet( '91e47a57-7508-46fe-afc9-fc454e8580e1' ).AndReturn(None) @@ -485,8 +498,20 @@ class NeutronSubnetTest(HeatTestCase): self.assertIn(stack['port'], stack.dependencies[stack['subnet']]) self.assertIn(stack['port2'], stack.dependencies[stack['subnet']]) - self.assertRaises(resource.UpdateReplace, - rsrc.handle_update, {}, {}, {}) + update_snippet = { + "Type": "OS::Neutron::Subnet", + "Properties": { + "name": 'mysubnet', + "network_id": {"Ref": "network"}, + "tenant_id": "c1210485b2424d48804aad5d39c61b8f", + "ip_version": 4, + "cidr": "10.0.3.0/24", + "allocation_pools": [ + {"start": "10.0.3.20", "end": "10.0.3.150"}], + "dns_nameservers": ["8.8.8.8", "192.168.1.254"] + } + } + rsrc.handle_update(update_snippet, {}, {}) self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None) rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')