From 0874cb9b69a0e82c527497c5d98b5b19039b5947 Mon Sep 17 00:00:00 2001 From: Akihiro MOTOKI Date: Thu, 30 Aug 2012 23:27:59 +0900 Subject: Make sure to return an empty subnet list for a network without sunbet. Fixes bug 1043827. This commit fixes a bug that when launching an instance with a quantum network without subnet allocate_for_instance() in network/quantumv2/api.py returns non-related subnet info as instance_nw_info. A port created on a network without subnet is associated with no subnet and subnet info in instance_nw_info should be an empty list. Change-Id: I2cfb78886ab10dd94eb795f5288b26b77f379998 --- nova/network/quantumv2/api.py | 7 +++++++ nova/tests/network/test_quantumv2.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index 5d657dc21..65762cb31 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -367,6 +367,13 @@ class API(base.Base): """Return the subnets for a given port.""" fixed_ips = port['fixed_ips'] + # No fixed_ips for the port means there is no subnet associated + # with the network the port is created on. + # Since list_subnets(id=[]) returns all subnets visible for the + # current tenant, returned subnets may contain subnets which is not + # related to the port. To avoid this, the method returns here. + if not fixed_ips: + return [] search_opts = {'id': [ip['subnet_id'] for ip in fixed_ips]} data = quantumv2.get_client(context).list_subnets(**search_opts) ipam_subnets = data.get('subnets', []) diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py index 19ba84edf..f0cfd0ba1 100644 --- a/nova/tests/network/test_quantumv2.py +++ b/nova/tests/network/test_quantumv2.py @@ -159,6 +159,7 @@ class TestQuantumv2(test.TestCase): self.nets4 = [{'id': 'his_netid4', 'name': 'his_netname4', 'tenant_id': 'his_tenantid'}] + self.nets = [self.nets1, self.nets2, self.nets3, self.nets4] self.port_data1 = [{'network_id': 'my_netid1', @@ -179,6 +180,12 @@ class TestQuantumv2(test.TestCase): 'fixed_ips': [{'ip_address': '10.0.2.2', 'subnet_id': 'my_subid2'}], 'mac_address': 'my_mac2', }) + self.port_data3 = [{'network_id': 'my_netid1', + 'device_id': 'device_id3', + 'device_owner': 'compute:nova', + 'id': 'my_portid3', + 'fixed_ips': [], # no fixed ip + 'mac_address': 'my_mac3', }] self.subnet_data1 = [{'id': 'my_subid1', 'cidr': '10.0.1.0/24', 'network_id': 'my_netid1', @@ -274,6 +281,35 @@ class TestQuantumv2(test.TestCase): networks=self.nets1) self._verify_nw_info(nw_inf, 0) + def test_get_instance_nw_info_without_subnet(self): + """Test get instance_nw_info for a port without subnet.""" + api = quantumapi.API() + self.mox.StubOutWithMock(api.db, 'instance_info_cache_update') + api.db.instance_info_cache_update( + mox.IgnoreArg(), + self.instance['uuid'], mox.IgnoreArg()) + self.moxed_client.list_ports( + tenant_id=self.instance['project_id'], + device_id=self.instance['uuid']).AndReturn( + {'ports': self.port_data3}) + self.moxed_client.list_networks( + shared=False, + tenant_id=self.instance['project_id']).AndReturn( + {'networks': self.nets1}) + self.moxed_client.list_networks( + shared=True).AndReturn({'networks': []}) + self.mox.ReplayAll() + + nw_inf = api.get_instance_nw_info(self.context, + self.instance) + + id_suffix = 3 + self.assertEquals(0, len(nw_inf.fixed_ips())) + self.assertEquals('my_netname1', nw_inf[0]['network']['label']) + self.assertEquals('my_portid%s' % id_suffix, nw_inf[0]['id']) + self.assertEquals('my_mac%s' % id_suffix, nw_inf[0]['address']) + self.assertEquals(0, len(nw_inf[0]['network']['subnets'])) + def _allocate_for_instance(self, net_idx=1, **kwargs): api = quantumapi.API() self.mox.StubOutWithMock(api, 'get_instance_nw_info') -- cgit