diff options
author | Dan Smith <danms@us.ibm.com> | 2013-04-30 09:11:48 -0700 |
---|---|---|
committer | Dan Smith <danms@us.ibm.com> | 2013-04-30 09:17:43 -0700 |
commit | 43d657a11e953660f36683d595976c8bd8edb4cc (patch) | |
tree | 00e49181f521b9e81cae5fbc8c6f69a0e130a8ff | |
parent | 08c7cf5c67a75dea9b453bd915a0cd55e67c4adc (diff) | |
download | nova-43d657a11e953660f36683d595976c8bd8edb4cc.tar.gz nova-43d657a11e953660f36683d595976c8bd8edb4cc.tar.xz nova-43d657a11e953660f36683d595976c8bd8edb4cc.zip |
Make _build_network_info_model testable
This restructures the quantumapi _build_network_info_model()
method to be testable and adds tests for each of the smaller
components. It also provides verification for bug 1171636 by
ensuring that ports returned from the client that are not in the
set of networks passed don't cause the failure detailed in that
bug.
Change-Id: I82f20f68122fc38e72c31e52283529614252c174
-rw-r--r-- | nova/network/quantumv2/api.py | 112 | ||||
-rw-r--r-- | nova/tests/network/test_quantumv2.py | 124 |
2 files changed, 187 insertions, 49 deletions
diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index 39c3d47d0..6b2cac9bd 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -807,6 +807,63 @@ class API(base.Base): """Force add a network to the project.""" raise NotImplementedError() + def _nw_info_get_ips(self, client, port): + network_IPs = [] + for fixed_ip in port['fixed_ips']: + fixed = network_model.FixedIP(address=fixed_ip['ip_address']) + floats = self._get_floating_ips_by_fixed_and_port( + client, fixed_ip['ip_address'], port['id']) + for ip in floats: + fip = network_model.IP(address=ip['floating_ip_address'], + type='floating') + fixed.add_floating_ip(fip) + network_IPs.append(fixed) + return network_IPs + + def _nw_info_get_subnets(self, context, port, network_IPs): + subnets = self._get_subnets_from_port(context, port) + for subnet in subnets: + subnet['ips'] = [fixed_ip for fixed_ip in network_IPs + if fixed_ip.is_in_subnet(subnet)] + return subnets + + def _nw_info_build_network(self, port, networks, subnets): + # NOTE(danms): This loop can't fail to find a network since we + # filtered ports to only the ones matching networks in our parent + for net in networks: + if port['network_id'] == net['id']: + network_name = net['name'] + break + + bridge = None + ovs_interfaceid = None + # Network model metadata + should_create_bridge = None + vif_type = port.get('binding:vif_type') + # TODO(berrange) Quantum should pass the bridge name + # in another binding metadata field + if vif_type == network_model.VIF_TYPE_OVS: + bridge = CONF.quantum_ovs_bridge + ovs_interfaceid = port['id'] + elif vif_type == network_model.VIF_TYPE_BRIDGE: + bridge = "brq" + port['network_id'] + should_create_bridge = True + + if bridge is not None: + bridge = bridge[:network_model.NIC_NAME_LEN] + + network = network_model.Network( + id=port['network_id'], + bridge=bridge, + injected=CONF.flat_injected, + label=network_name, + tenant_id=net['tenant_id'] + ) + network['subnets'] = subnets + if should_create_bridge is not None: + network['should_create_bridge'] = should_create_bridge + return network, ovs_interfaceid + def _build_network_info_model(self, context, instance, networks=None): search_opts = {'tenant_id': instance['project_id'], 'device_id': instance['uuid'], } @@ -826,59 +883,16 @@ class API(base.Base): nw_info = network_model.NetworkInfo() for port in ports: - # NOTE(danms): This loop can't fail to find a network since we - # filtered ports to only the ones matching networks above. - for net in networks: - if port['network_id'] == net['id']: - network_name = net['name'] - break - - network_IPs = [] - for fixed_ip in port['fixed_ips']: - fixed = network_model.FixedIP(address=fixed_ip['ip_address']) - floats = self._get_floating_ips_by_fixed_and_port( - client, fixed_ip['ip_address'], port['id']) - for ip in floats: - fip = network_model.IP(address=ip['floating_ip_address'], - type='floating') - fixed.add_floating_ip(fip) - network_IPs.append(fixed) - - subnets = self._get_subnets_from_port(context, port) - for subnet in subnets: - subnet['ips'] = [fixed_ip for fixed_ip in network_IPs - if fixed_ip.is_in_subnet(subnet)] - - bridge = None - ovs_interfaceid = None - # Network model metadata - should_create_bridge = None - vif_type = port.get('binding:vif_type') - # TODO(berrange) Quantum should pass the bridge name - # in another binding metadata field - if vif_type == network_model.VIF_TYPE_OVS: - bridge = CONF.quantum_ovs_bridge - ovs_interfaceid = port['id'] - elif vif_type == network_model.VIF_TYPE_BRIDGE: - bridge = "brq" + port['network_id'] - should_create_bridge = True - - if bridge is not None: - bridge = bridge[:network_model.NIC_NAME_LEN] + network_IPs = self._nw_info_get_ips(client, port) + subnets = self._nw_info_get_subnets(context, port, network_IPs) devname = "tap" + port['id'] devname = devname[:network_model.NIC_NAME_LEN] - network = network_model.Network( - id=port['network_id'], - bridge=bridge, - injected=CONF.flat_injected, - label=network_name, - tenant_id=net['tenant_id'] - ) - network['subnets'] = subnets - if should_create_bridge is not None: - network['should_create_bridge'] = should_create_bridge + network, ovs_interfaceid = self._nw_info_build_network(port, + networks, + subnets) + nw_info.append(network_model.VIF( id=port['id'], address=port['mac_address'], diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py index 6a00b4723..5922d7e1e 100644 --- a/nova/tests/network/test_quantumv2.py +++ b/nova/tests/network/test_quantumv2.py @@ -1233,6 +1233,130 @@ class TestQuantumv2(test.TestCase): self.moxed_client, '1.1.1.1', 1) self.assertEqual(floatingips, []) + def test_nw_info_get_ips(self): + fake_port = { + 'fixed_ips': [ + {'ip_address': '1.1.1.1'}], + 'id': 'port-id', + } + api = quantumapi.API() + self.mox.StubOutWithMock(api, '_get_floating_ips_by_fixed_and_port') + api._get_floating_ips_by_fixed_and_port( + self.moxed_client, '1.1.1.1', 'port-id').AndReturn( + [{'floating_ip_address': '10.0.0.1'}]) + self.mox.ReplayAll() + quantumv2.get_client('fake') + result = api._nw_info_get_ips(self.moxed_client, fake_port) + self.assertEqual(len(result), 1) + self.assertEqual(result[0]['address'], '1.1.1.1') + self.assertEqual(result[0]['floating_ips'][0]['address'], '10.0.0.1') + + def test_nw_info_get_subnets(self): + fake_port = { + 'fixed_ips': [ + {'ip_address': '1.1.1.1'}, + {'ip_address': '2.2.2.2'}], + 'id': 'port-id', + } + fake_subnet = model.Subnet(cidr='1.0.0.0/8') + fake_ips = [model.IP(x['ip_address']) for x in fake_port['fixed_ips']] + api = quantumapi.API() + self.mox.StubOutWithMock(api, '_get_subnets_from_port') + api._get_subnets_from_port(self.context, fake_port).AndReturn( + [fake_subnet]) + self.mox.ReplayAll() + quantumv2.get_client('fake') + subnets = api._nw_info_get_subnets(self.context, fake_port, fake_ips) + self.assertEqual(len(subnets), 1) + self.assertEqual(len(subnets[0]['ips']), 1) + self.assertEqual(subnets[0]['ips'][0]['address'], '1.1.1.1') + + def _test_nw_info_build_network(self, vif_type): + fake_port = { + 'fixed_ips': [{'ip_address': '1.1.1.1'}], + 'id': 'port-id', + 'network_id': 'net-id', + 'binding:vif_type': vif_type, + } + fake_subnets = [model.Subnet(cidr='1.0.0.0/8')] + fake_nets = [{'id': 'net-id', 'name': 'foo', 'tenant_id': 'tenant'}] + api = quantumapi.API() + self.mox.ReplayAll() + quantumv2.get_client('fake') + net, iid = api._nw_info_build_network(fake_port, fake_nets, + fake_subnets) + self.assertEqual(net['subnets'], fake_subnets) + self.assertEqual(net['id'], 'net-id') + self.assertEqual(net['label'], 'foo') + self.assertEqual(net.get_meta('tenant_id'), 'tenant') + self.assertEqual(net.get_meta('injected'), CONF.flat_injected) + return net, iid + + def test_nw_info_build_network_ovs(self): + net, iid = self._test_nw_info_build_network(model.VIF_TYPE_OVS) + self.assertEqual(net['bridge'], CONF.quantum_ovs_bridge) + self.assertFalse('should_create_bridge' in net) + self.assertEqual(iid, 'port-id') + + def test_nw_info_build_network_bridge(self): + net, iid = self._test_nw_info_build_network(model.VIF_TYPE_BRIDGE) + self.assertEqual(net['bridge'], 'brqnet-id') + self.assertTrue(net['should_create_bridge']) + self.assertEqual(iid, None) + + def test_nw_info_build_network_other(self): + net, iid = self._test_nw_info_build_network(None) + self.assertEqual(net['bridge'], None) + self.assertFalse('should_create_bridge' in net) + self.assertEqual(iid, None) + + def test_build_network_info_model(self): + api = quantumapi.API() + fake_inst = {'project_id': 'fake', 'uuid': 'uuid'} + fake_ports = [ + {'id': 'port0', + 'network_id': 'net-id', + 'fixed_ips': [{'ip_address': '1.1.1.1'}], + 'mac_address': 'de:ad:be:ef:00:01', + 'binding:vif_type': model.VIF_TYPE_BRIDGE, + }, + # This does not match the networks we provide below, + # so it should be ignored (and is here to verify that) + {'id': 'port1', + 'network_id': 'other-net-id', + }, + ] + fake_subnets = [model.Subnet(cidr='1.0.0.0/8')] + fake_nets = [ + {'id': 'net-id', + 'name': 'foo', + 'tenant_id': 'fake', + } + ] + quantumv2.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}) + self.mox.StubOutWithMock(api, '_get_floating_ips_by_fixed_and_port') + api._get_floating_ips_by_fixed_and_port( + self.moxed_client, '1.1.1.1', 'port0').AndReturn( + [{'floating_ip_address': '10.0.0.1'}]) + self.mox.StubOutWithMock(api, '_get_subnets_from_port') + api._get_subnets_from_port(self.context, fake_ports[0]).AndReturn( + fake_subnets) + self.mox.ReplayAll() + quantumv2.get_client('fake') + nw_info = api._build_network_info_model(self.context, fake_inst, + fake_nets) + self.assertEqual(len(nw_info), 1) + self.assertEqual(nw_info[0]['id'], 'port0') + self.assertEqual(nw_info[0]['address'], 'de:ad:be:ef:00:01') + self.assertEqual(nw_info[0]['devname'], 'tapport0') + self.assertEqual(nw_info[0]['ovs_interfaceid'], None) + self.assertEqual(nw_info[0]['type'], model.VIF_TYPE_BRIDGE) + self.assertEqual(nw_info[0]['network']['bridge'], 'brqnet-id') + class TestQuantumv2ModuleMethods(test.TestCase): def test_ensure_requested_network_ordering_no_preference_ids(self): |