From cfcaa895a6357a4bc08ce84928541f2d80c5b0e7 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Wed, 6 Mar 2013 15:29:12 +1300 Subject: [PATCH] Allow instance NetworkInterfaces to be list of str or dict It should be possible to specify NetworkInterfaces of an instance either as an array of strings or as an array of dicts. The following should now be possible: This will define nics in the order specified by DeviceIndex "NetworkInterfaces" : [ { "NetworkInterfaceId" : {"Ref" : "controlXface"}, "DeviceIndex" : "0" }, { "NetworkInterfaceId" : {"Ref" : "controlXface2"}, "DeviceIndex" : "1" }, ], This will define nics in the order specified by list position "NetworkInterfaces" : [{"Ref" : "controlXface"}, {"Ref" : "controlXface2"}], Mixing the 2 forms is supported but the resulting order is not defined. Amazon documentation is ambigious about which form is actually supported http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-networkinterfaces http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-ec2.html#cfn-template-snippets-eni Fixes: Bug #1096013 Change-Id: Id387d2e750cbe533a9b8a1fedc49d5bcf690fbcf --- heat/engine/resources/instance.py | 24 ++++++++++++++++++------ heat/tests/test_instance.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/heat/engine/resources/instance.py b/heat/engine/resources/instance.py index eb2bf053..5e068cbd 100644 --- a/heat/engine/resources/instance.py +++ b/heat/engine/resources/instance.py @@ -216,6 +216,23 @@ class Instance(resource.Resource): return self.mime_string + @staticmethod + def _build_nics(network_interfaces): + if not network_interfaces: + return None + + nics = [] + for nic in network_interfaces: + if isinstance(nic, basestring): + nics.append({ + 'NetworkInterfaceId': nic, + 'DeviceIndex': len(nics)}) + else: + nics.append(nic) + sorted_nics = sorted(nics, key=lambda nic: int(nic['DeviceIndex'])) + + return [{'port-id': nic['NetworkInterfaceId']} for nic in sorted_nics] + def handle_create(self): if self.properties.get('SecurityGroups') is None: security_groups = None @@ -267,12 +284,7 @@ class Instance(resource.Resource): else: scheduler_hints = None - nics = [] - if self.properties['NetworkInterfaces']: - for nic in self.properties['NetworkInterfaces']: - nics.append({'port-id': nic}) - else: - nics = None + nics = self._build_nics(self.properties['NetworkInterfaces']) server_userdata = self._build_userdata(userdata) server = None diff --git a/heat/tests/test_instance.py b/heat/tests/test_instance.py index 1884a019..fcc22c86 100644 --- a/heat/tests/test_instance.py +++ b/heat/tests/test_instance.py @@ -181,3 +181,32 @@ class instancesTest(unittest.TestCase): self.assertEqual(instance.update(update_template), instance.UPDATE_COMPLETE) self.assertEqual(instance.metadata, {'test': 123}) + + def test_build_nics(self): + self.assertEqual(None, instances.Instance._build_nics([])) + self.assertEqual(None, instances.Instance._build_nics(None)) + self.assertEqual([ + {'port-id': 'id3'}, {'port-id': 'id1'}, {'port-id': 'id2'}], + instances.Instance._build_nics([ + 'id3', 'id1', 'id2'])) + self.assertEqual([ + {'port-id': 'id1'}, + {'port-id': 'id2'}, + {'port-id': 'id3'}], instances.Instance._build_nics([ + {'NetworkInterfaceId': 'id3', 'DeviceIndex': '3'}, + {'NetworkInterfaceId': 'id1', 'DeviceIndex': '1'}, + {'NetworkInterfaceId': 'id2', 'DeviceIndex': 2}, + ])) + self.assertEqual([ + {'port-id': 'id1'}, + {'port-id': 'id2'}, + {'port-id': 'id3'}, + {'port-id': 'id4'}, + {'port-id': 'id5'} + ], instances.Instance._build_nics([ + {'NetworkInterfaceId': 'id3', 'DeviceIndex': '3'}, + {'NetworkInterfaceId': 'id1', 'DeviceIndex': '1'}, + {'NetworkInterfaceId': 'id2', 'DeviceIndex': 2}, + 'id4', + 'id5' + ])) -- 2.45.2