From f2ab613da511601424763936155a5781355585b5 Mon Sep 17 00:00:00 2001 From: Sahid Orentino Ferdjaoui Date: Thu, 28 May 2015 04:31:53 -0400 Subject: [PATCH] network: fix instance cache refresh for empty list The bug introduce a race condition makes network_info as an empty value. When trying to refresh cache we should use data returned per Neutron. Co-Authored-By: Lee Yarwood (cherry picked from commit 3a850ac72d60b3823c5cb4a971eaf02c580a4a20) Conflicts: - test_neutronv2.py * about assertions imported from Kilo to juno but not in relation with this change. * the _get_preexisting_port_ids does not exist * the name of the api attribute is different Closes-Bug: #1407664 Change-Id: I3b9f60a2c4aea904f39d6914c8f35c4d682a6b3a --- nova/network/neutronv2/api.py | 5 +++ nova/tests/network/test_neutronv2.py | 49 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index 8d4d517e0dab..0fb09dbe4088 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -1366,6 +1366,11 @@ class API(base_api.NetworkAPI): current_neutron_port_map[current_neutron_port['id']] = ( current_neutron_port) + # In that case we should repopulate ports from the state of + # Neutron. + if not port_ids: + port_ids = current_neutron_port_map.keys() + for port_id in port_ids: current_neutron_port = current_neutron_port_map.get(port_id) if current_neutron_port: diff --git a/nova/tests/network/test_neutronv2.py b/nova/tests/network/test_neutronv2.py index 59d5e1ba6a4b..5740c16680eb 100644 --- a/nova/tests/network/test_neutronv2.py +++ b/nova/tests/network/test_neutronv2.py @@ -2528,6 +2528,55 @@ class TestNeutronv2(TestNeutronv2Base): self.assertEqual(nw_infos[4]['id'], 'port4') self.assertEqual(nw_infos[5]['id'], 'port5') + @mock.patch('nova.network.neutronv2.api.API._nw_info_get_subnets') + @mock.patch('nova.network.neutronv2.api.API._nw_info_get_ips') + @mock.patch('nova.network.neutronv2.api.API._nw_info_build_network') + @mock.patch('nova.network.neutronv2.api.API._gather_port_ids_and_networks') + def test_build_network_info_model_empty( + self, mock_gather_port_ids_and_networks, + mock_nw_info_build_network, + mock_nw_info_get_ips, + mock_nw_info_get_subnets): + api = neutronapi.API() + + fake_inst = objects.Instance() + fake_inst.project_id = 'fake' + fake_inst.uuid = 'uuid' + fake_inst.info_cache = objects.InstanceInfoCache() + fake_inst.info_cache.network_info = model.NetworkInfo() + fake_ports = [ + # admin_state_up=True and status='ACTIVE' thus vif.active=True + {'id': 'port1', + 'network_id': 'net-id', + 'admin_state_up': True, + 'status': 'ACTIVE', + 'fixed_ips': [{'ip_address': '1.1.1.1'}], + 'mac_address': 'de:ad:be:ef:00:01', + 'binding:vif_type': model.VIF_TYPE_BRIDGE, + 'binding:vnic_type': model.VNIC_TYPE_NORMAL, + 'binding:vif_details': {}, + }, + ] + fake_subnets = [model.Subnet(cidr='1.0.0.0/8')] + + neutronv2.get_client(mox.IgnoreArg(), admin=True).MultipleTimes( + ).AndReturn(self.moxed_client) + self.moxed_client.list_ports( + tenant_id='fake', device_id='uuid').AndReturn( + {'ports': fake_ports}) + + mock_gather_port_ids_and_networks.return_value = (None, None) + mock_nw_info_build_network.return_value = (None, None) + mock_nw_info_get_ips.return_value = [] + mock_nw_info_get_subnets.return_value = fake_subnets + + self.mox.ReplayAll() + neutronv2.get_client('fake') + + nw_infos = api._build_network_info_model( + self.context, fake_inst) + self.assertEqual(len(nw_infos), 1) + def test_get_subnets_from_port(self): api = neutronapi.API()