From f0497e0707d1ffb44631b58957c3cd086d07350e Mon Sep 17 00:00:00 2001 From: Rabi Mishra Date: Sat, 26 Mar 2016 15:27:13 +0530 Subject: [PATCH] Add id and name properties for flavor resource This adds `flavorid` and `name` properties for the OS::Nova::Flavor resource plugin. Change-Id: I6d201683e2177a662093a33e3e6698cca30e3c94 Closes-Bug: #1562283 --- .../engine/resources/openstack/nova/flavor.py | 26 ++++++++--- heat/tests/openstack/nova/test_flavor.py | 43 ++++++++++++++++++- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/heat/engine/resources/openstack/nova/flavor.py b/heat/engine/resources/openstack/nova/flavor.py index 2f5692ed36..94214d9916 100644 --- a/heat/engine/resources/openstack/nova/flavor.py +++ b/heat/engine/resources/openstack/nova/flavor.py @@ -40,11 +40,11 @@ class NovaFlavor(resource.Resource): entity = 'flavors' PROPERTIES = ( - RAM, VCPUS, DISK, SWAP, EPHEMERAL, - RXTX_FACTOR, EXTRA_SPECS, IS_PUBLIC + ID, NAME, RAM, VCPUS, DISK, SWAP, + EPHEMERAL, RXTX_FACTOR, EXTRA_SPECS, IS_PUBLIC ) = ( - 'ram', 'vcpus', 'disk', 'swap', 'ephemeral', - 'rxtx_factor', 'extra_specs', 'is_public', + 'flavorid', 'name', 'ram', 'vcpus', 'disk', 'swap', + 'ephemeral', 'rxtx_factor', 'extra_specs', 'is_public', ) ATTRIBUTES = ( @@ -54,6 +54,17 @@ class NovaFlavor(resource.Resource): ) properties_schema = { + ID: properties.Schema( + properties.Schema.STRING, + _('Unique ID of the flavor. If not specified, ' + 'an UUID will be auto generated and used.'), + support_status=support.SupportStatus(version='7.0.0') + ), + NAME: properties.Schema( + properties.Schema.STRING, + _('Name of the flavor.'), + support_status=support.SupportStatus(version='7.0.0'), + ), RAM: properties.Schema( properties.Schema.INTEGER, _('Memory in MB for the flavor.'), @@ -112,10 +123,11 @@ class NovaFlavor(resource.Resource): def handle_create(self): args = dict(self.properties) - args['flavorid'] = 'auto' - args['name'] = self.physical_resource_name() + if not args['flavorid']: + args['flavorid'] = 'auto' + if not args['name']: + args['name'] = self.physical_resource_name() flavor_keys = args.pop(self.EXTRA_SPECS) - flavor = self.client().flavors.create(**args) self.resource_id_set(flavor.id) if flavor_keys: diff --git a/heat/tests/openstack/nova/test_flavor.py b/heat/tests/openstack/nova/test_flavor.py index fae477dfeb..b1c7d9b9cc 100644 --- a/heat/tests/openstack/nova/test_flavor.py +++ b/heat/tests/openstack/nova/test_flavor.py @@ -45,11 +45,15 @@ class NovaFlavorTest(common.HeatTestCase): return_value=True) self.ctx = utils.dummy_context() + def create_flavor(self, with_name_id=False): + if with_name_id: + props = flavor_template['resources']['my_flavor']['properties'] + props['name'] = 'test_flavor' + props['flavorid'] = '1234' self.stack = stack.Stack( self.ctx, 'nova_flavor_test_stack', template.Template(flavor_template) ) - self.my_flavor = self.stack['my_flavor'] nova = mock.MagicMock() self.novaclient = mock.MagicMock() @@ -57,7 +61,16 @@ class NovaFlavorTest(common.HeatTestCase): nova.return_value = self.novaclient self.flavors = self.novaclient.flavors - def test_flavor_handle_create(self): + def test_flavor_handle_create_no_id_name(self): + self.create_flavor() + kwargs = { + 'vcpus': 2, 'disk': 20, 'swap': 2, + 'flavorid': 'auto', 'is_public': True, + 'rxtx_factor': 1.0, 'ram': 1024, + 'ephemeral': 0, 'name': 'm1.xxx' + } + self.patchobject(self.my_flavor, 'physical_resource_name', + return_value='m1.xxx') value = mock.MagicMock() flavor_id = '927202df-1afb-497f-8368-9c2d2f26e5db' value.id = flavor_id @@ -65,11 +78,35 @@ class NovaFlavorTest(common.HeatTestCase): self.flavors.create.return_value = value self.flavors.get.return_value = value self.my_flavor.handle_create() + self.flavors.create.assert_called_once_with(**kwargs) + value.set_keys.assert_called_once_with({"foo": "bar"}) + self.assertEqual(flavor_id, self.my_flavor.resource_id) + self.assertTrue(self.my_flavor.FnGetAtt('is_public')) + + def test_flavor_handle_create_with_id_name(self): + self.create_flavor(with_name_id=True) + kwargs = { + 'vcpus': 2, 'disk': 20, 'swap': 2, + 'flavorid': '1234', 'is_public': True, + 'rxtx_factor': 1.0, 'ram': 1024, + 'ephemeral': 0, 'name': 'test_flavor' + } + self.patchobject(self.my_flavor, 'physical_resource_name', + return_value='m1.xxx') + value = mock.MagicMock() + flavor_id = '927202df-1afb-497f-8368-9c2d2f26e5db' + value.id = flavor_id + value.is_public = True + self.flavors.create.return_value = value + self.flavors.get.return_value = value + self.my_flavor.handle_create() + self.flavors.create.assert_called_once_with(**kwargs) value.set_keys.assert_called_once_with({"foo": "bar"}) self.assertEqual(flavor_id, self.my_flavor.resource_id) self.assertTrue(self.my_flavor.FnGetAtt('is_public')) def test_private_flavor_handle_create(self): + self.create_flavor() value = mock.MagicMock() flavor_id = '927202df-1afb-497f-8368-9c2d2f26e5db' value.id = flavor_id @@ -82,6 +119,7 @@ class NovaFlavorTest(common.HeatTestCase): self.assertFalse(self.my_flavor.FnGetAtt('is_public')) def test_flavor_handle_update_keys(self): + self.create_flavor() value = mock.MagicMock() self.flavors.get.return_value = value value.get_keys.return_value = {} @@ -94,6 +132,7 @@ class NovaFlavorTest(common.HeatTestCase): value.set_keys.assert_called_once_with(new_keys) def test_flavor_show_resource(self): + self.create_flavor() self.my_flavor.resource_id = 'flavor_test_id' self.my_flavor.client = mock.MagicMock() flavors = mock.MagicMock()