From c686a2b555a15de6f8c1759dfa6d7ff589792975 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Fri, 5 Nov 2021 14:02:48 +0000 Subject: [PATCH] Improve DHCP RPC handler Remove unnecessary DB retrieval operations from "get_network_info" method. Partial-Bug: #1950662 Change-Id: If4b33c8437dba411fed913e7e1c7f06d899c08f7 --- neutron/agent/linux/dhcp.py | 10 +- neutron/api/rpc/handlers/dhcp_rpc.py | 69 ++++++++------ .../tests/functional/agent/linux/test_dhcp.py | 2 +- .../tests/functional/agent/test_dhcp_agent.py | 2 +- neutron/tests/unit/agent/dhcp/test_agent.py | 65 ++++++------- neutron/tests/unit/agent/linux/test_dhcp.py | 8 +- .../unit/api/rpc/handlers/test_dhcp_rpc.py | 93 +++++++++++-------- 7 files changed, 143 insertions(+), 106 deletions(-) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index dd10d5e1e46..90ae0e9e915 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -170,6 +170,14 @@ class NetModel(DictModel): def namespace(self): return self._ns_name + # TODO(ralonsoh): remove in Z+. + @property + def project_id(self): + try: + return self['project_id'] + except KeyError: + return self['tenant_id'] + class DhcpBase(object, metaclass=abc.ABCMeta): @@ -1584,7 +1592,7 @@ class DeviceManager(object): admin_state_up=True, device_id=device_id, network_id=network.id, - tenant_id=network.tenant_id, + project_id=network.project_id, fixed_ips=unique_ip_subnets) return self.plugin.create_dhcp_port({'port': port_dict}) diff --git a/neutron/api/rpc/handlers/dhcp_rpc.py b/neutron/api/rpc/handlers/dhcp_rpc.py index 20dcdb5a9b3..e8a3d30b46c 100644 --- a/neutron/api/rpc/handlers/dhcp_rpc.py +++ b/neutron/api/rpc/handlers/dhcp_rpc.py @@ -36,6 +36,7 @@ from neutron._i18n import _ from neutron.common import utils from neutron.db import provisioning_blocks from neutron.extensions import segment as segment_ext +from neutron.objects import network as network_obj from neutron.quota import resource_registry @@ -218,43 +219,53 @@ class DhcpRpcCallback(object): LOG.debug('Network %(network_id)s requested from ' '%(host)s', {'network_id': network_id, 'host': host}) - plugin = directory.get_plugin() - try: - network = plugin.get_network(context, network_id) - except exceptions.NetworkNotFound: - LOG.debug("Network %s could not be found, it might have " - "been deleted concurrently.", network_id) + network = network_obj.Network.get_object(context, id=network_id) + if not network: + LOG.debug('Network %s could not be found, it might have ' + 'been deleted concurrently.', network_id) return - subnet_filters = {'network_id': [network_id], 'enable_dhcp': [True]} - subnets = plugin.get_subnets(context, filters=subnet_filters) + seg_plug = directory.get_plugin( segment_ext.SegmentPluginBase.get_plugin_type()) + plugin = directory.get_plugin() + # Only subnets with DHCP enabled. + subnets = [plugin._make_subnet_dict(subnet) for subnet in + network.db_obj.subnets if subnet.enable_dhcp] + seg_subnets = [subnet for subnet in subnets if + subnet.get('segment_id')] nonlocal_subnets = [] - if seg_plug and subnets: - seg_subnets = [subnet for subnet in subnets - if subnet.get('segment_id')] - # If there are no subnets with segments, then this is not a routed - # network and no filtering should take place. - if seg_subnets: - segment_ids = seg_plug.get_segments_by_hosts(context, [host]) - # There might be something to do if no segment_ids exist that - # are mapped to this host. However, it seems that if this - # host is not mapped to any segments and this is a routed - # network, then this host shouldn't have even been scheduled - # to. - nonlocal_subnets = [subnet for subnet in seg_subnets - if subnet['segment_id'] not in segment_ids] - subnets = [subnet for subnet in seg_subnets - if subnet['segment_id'] in segment_ids] + # If there are no subnets with segments, then this is not a routed + # network and no filtering should take place. + if seg_plug and seg_subnets: + # Network subnets can be associated only to network segments. + # From those segments, we retrieve only those ones mapped to + # 'host'. + segment_ids = {ns.id for ns in network.segments if + host in ns.hosts} + # There might be something to do if no segment_ids exist that + # are mapped to this host. However, it seems that if this + # host is not mapped to any segments and this is a routed + # network, then this host shouldn't have even been scheduled + # to. + nonlocal_subnets = [subnet for subnet in seg_subnets + if subnet.get('segment_id') not in segment_ids] + subnets = [subnet for subnet in seg_subnets + if subnet.get('segment_id') in segment_ids] # NOTE(kevinbenton): we sort these because the agent builds tags # based on position in the list and has to restart the process if # the order changes. - network['subnets'] = sorted(subnets, key=operator.itemgetter('id')) - network['non_local_subnets'] = sorted(nonlocal_subnets, - key=operator.itemgetter('id')) port_filters = {'network_id': [network_id]} - network['ports'] = plugin.get_ports(context, filters=port_filters) - return network + # TODO(ralonsoh): in Z+, remove "tenant_id" parameter. DHCP agents + # should read only "project_id". + return {'id': network.id, + 'project_id': network.project_id, + 'tenant_id': network.project_id, + 'admin_state_up': network.admin_state_up, + 'subnets': sorted(subnets, key=operator.itemgetter('id')), + 'non_local_subnets': sorted(nonlocal_subnets, + key=operator.itemgetter('id')), + 'ports': plugin.get_ports(context, filters=port_filters), + 'mtu': network.mtu} @db_api.retry_db_errors def release_dhcp_port(self, context, **kwargs): diff --git a/neutron/tests/functional/agent/linux/test_dhcp.py b/neutron/tests/functional/agent/linux/test_dhcp.py index cdd7c11265e..c6524fa35bf 100644 --- a/neutron/tests/functional/agent/linux/test_dhcp.py +++ b/neutron/tests/functional/agent/linux/test_dhcp.py @@ -49,7 +49,7 @@ class TestDhcp(functional_base.BaseSudoTestCase): dev_mgr = dhcp.DeviceManager(self.conf, plugin) network = { 'id': 'foo_id', - 'tenant_id': 'foo_tenant', + 'project_id': 'foo_project', 'namespace': 'qdhcp-foo_id', 'ports': [], 'subnets': [tests_base.AttributeDict({'id': 'subnet_foo_id', diff --git a/neutron/tests/functional/agent/test_dhcp_agent.py b/neutron/tests/functional/agent/test_dhcp_agent.py index 958918afeb4..5d72e377737 100644 --- a/neutron/tests/functional/agent/test_dhcp_agent.py +++ b/neutron/tests/functional/agent/test_dhcp_agent.py @@ -147,7 +147,7 @@ class DHCPAgentOVSTestFramework(base.BaseSudoTestCase): non_local_subnets=non_local_subnets, ports=ports, admin_state_up=True, - tenant_id=uuidutils.generate_uuid()) + project_id=uuidutils.generate_uuid()) return net_dict def get_interface_name(self, network, port): diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index b7b61267333..5c7c29d1ed0 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -51,7 +51,7 @@ DEVICE_MANAGER = '%s.%s' % (dev_man.__module__, dev_man.__name__) DHCP_PLUGIN = '%s.%s' % (rpc_api.__module__, rpc_api.__name__) FAKE_NETWORK_UUID = '12345678-1234-5678-1234567890ab' FAKE_NETWORK_DHCP_NS = "qdhcp-%s" % FAKE_NETWORK_UUID -FAKE_TENANT_ID = 'aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa' +FAKE_PROJECT_ID = 'aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa' FAKE_PRIORITY = 6 @@ -60,7 +60,7 @@ fake_subnet1_allocation_pools = dhcp.DictModel(id='', start='172.9.9.2', fake_subnet1 = dhcp.DictModel(id='bbbbbbbb-bbbb-bbbb-bbbbbbbbbbbb', network_id=FAKE_NETWORK_UUID, cidr='172.9.9.0/24', enable_dhcp=True, name='', - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, gateway_ip='172.9.9.1', host_routes=[], dns_nameservers=[], ip_version=const.IP_VERSION_4, @@ -72,7 +72,8 @@ fake_subnet2_allocation_pools = dhcp.DictModel(id='', start='172.9.8.2', fake_subnet2 = dhcp.DictModel(id='dddddddd-dddd-dddd-dddddddddddd', network_id=FAKE_NETWORK_UUID, cidr='172.9.8.0/24', enable_dhcp=False, name='', - tenant_id=FAKE_TENANT_ID, gateway_ip='172.9.8.1', + project_id=FAKE_PROJECT_ID, + gateway_ip='172.9.8.1', host_routes=[], dns_nameservers=[], ip_version=const.IP_VERSION_4, allocation_pools=fake_subnet2_allocation_pools) @@ -85,7 +86,7 @@ fake_subnet3 = dhcp.DictModel(id='bbbbbbbb-1111-2222-bbbbbbbbbbbb', fake_ipv6_subnet = dhcp.DictModel(id='bbbbbbbb-1111-2222-bbbbbbbbbbbb', network_id=FAKE_NETWORK_UUID, cidr='2001:0db8::0/64', enable_dhcp=True, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, gateway_ip='2001:0db8::1', ip_version=const.IP_VERSION_6, ipv6_ra_mode='slaac', ipv6_address_mode=None) @@ -160,44 +161,44 @@ fake_dist_port = dhcp.DictModel(id='12345678-1234-aaaa-1234567890ab', fixed_ips=[fake_meta_fixed_ip]) fake_network = dhcp.NetModel(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_subnet1, fake_subnet2], ports=[fake_port1]) fake_network_ipv6 = dhcp.NetModel(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_ipv6_subnet], ports=[fake_ipv6_port]) fake_network_ipv6_ipv4 = dhcp.NetModel( id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_ipv6_subnet, fake_subnet1], ports=[fake_port1]) isolated_network = dhcp.NetModel(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_subnet1], ports=[fake_port1]) nonisolated_dist_network = dhcp.NetModel(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_subnet1], ports=[fake_port1, fake_port2]) empty_network = dhcp.NetModel(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_subnet1], ports=[]) fake_meta_network = dhcp.NetModel(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_meta_subnet], ports=[fake_meta_port]) @@ -206,13 +207,13 @@ fake_meta_dvr_network = dhcp.NetModel(fake_meta_network) fake_meta_dvr_network['ports'] = [fake_meta_dvr_port] fake_dist_network = dhcp.NetModel(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[fake_meta_subnet], ports=[fake_meta_port, fake_dist_port]) fake_down_network = dhcp.NetModel(id='12345678-dddd-dddd-1234567890ab', - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=False, subnets=[], ports=[]) @@ -1113,7 +1114,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): def test_refresh_dhcp_helper_no_dhcp_enabled_networks(self): network = dhcp.NetModel(dict(id='net-id', - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[], ports=[])) @@ -1130,7 +1131,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): def test_refresh_dhcp_helper_exception_during_rpc(self): network = dhcp.NetModel(dict(id='net-id', - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, admin_state_up=True, subnets=[], ports=[])) @@ -1221,7 +1222,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): def test_subnet_update_end_restart(self): new_state = dhcp.NetModel(dict(id=fake_network.id, - tenant_id=fake_network.tenant_id, + project_id=fake_network.project_id, admin_state_up=True, subnets=[fake_subnet1, fake_subnet3], ports=[fake_port1])) @@ -1240,7 +1241,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): def test_subnet_delete_end_no_network_id(self): prev_state = dhcp.NetModel(dict(id=fake_network.id, - tenant_id=fake_network.tenant_id, + project_id=fake_network.project_id, admin_state_up=True, subnets=[fake_subnet1, fake_subnet3], ports=[fake_port1])) @@ -1264,7 +1265,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): def test_subnet_update_end_delete_payload(self): prev_state = dhcp.NetModel(dict(id=fake_network.id, - tenant_id=fake_network.tenant_id, + project_id=fake_network.project_id, admin_state_up=True, subnets=[fake_subnet1, fake_subnet3], ports=[fake_port1])) @@ -1593,7 +1594,7 @@ class TestNetworkCache(base.BaseTestCase): def test_get_port_ids(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, subnets=[fake_subnet1], ports=[fake_port1])) self.nc.put(fake_net) @@ -1604,7 +1605,7 @@ class TestNetworkCache(base.BaseTestCase): def test_get_port_ids_limited_nets(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, subnets=[fake_subnet1], ports=[fake_port1])) fake_port2 = copy.deepcopy(fake_port1) @@ -1612,7 +1613,7 @@ class TestNetworkCache(base.BaseTestCase): fake_port2['network_id'] = '12345678-1234-5678-1234567890ac' fake_net2 = dhcp.NetModel( dict(id='12345678-1234-5678-1234567890ac', - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, subnets=[fake_subnet1], ports=[fake_port2])) self.nc.put(fake_net) @@ -1628,7 +1629,7 @@ class TestNetworkCache(base.BaseTestCase): def test_put_port(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, subnets=[fake_subnet1], ports=[fake_port1])) self.nc.put(fake_net) @@ -1639,7 +1640,7 @@ class TestNetworkCache(base.BaseTestCase): def test_put_port_existing(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, subnets=[fake_subnet1], ports=[fake_port1, fake_port2])) self.nc.put(fake_net) @@ -1651,7 +1652,7 @@ class TestNetworkCache(base.BaseTestCase): def test_remove_port_existing(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID, + project_id=FAKE_PROJECT_ID, subnets=[fake_subnet1], ports=[fake_port1, fake_port2])) self.nc.put(fake_net) @@ -1891,7 +1892,7 @@ class TestDeviceManager(base.BaseTestCase): plugin.assert_has_calls([ mock.call.create_dhcp_port( {'port': {'name': '', 'admin_state_up': True, - 'network_id': net.id, 'tenant_id': net.tenant_id, + 'network_id': net.id, 'project_id': net.project_id, 'fixed_ips': [{'subnet_id': port.fixed_ips[0].subnet_id}], 'device_id': mock.ANY}})]) @@ -1981,7 +1982,7 @@ class TestDeviceManager(base.BaseTestCase): mock.call.create_dhcp_port( {'port': {'name': '', 'admin_state_up': True, 'network_id': net.id, - 'tenant_id': net.tenant_id, + 'project_id': net.project_id, 'fixed_ips': [{'subnet_id': fake_dhcp_port.fixed_ips[0].subnet_id}], 'device_id': mock.ANY}})]) @@ -2027,8 +2028,8 @@ class TestDeviceManager(base.BaseTestCase): plugin.assert_has_calls([ mock.call.create_dhcp_port( {'port': {'name': '', 'admin_state_up': True, - 'network_id': - fake_network.id, 'tenant_id': fake_network.tenant_id, + 'network_id': fake_network.id, + 'project_id': fake_network.project_id, 'fixed_ips': [{'subnet_id': fake_fixed_ip1.subnet_id}], 'device_id': mock.ANY}})]) @@ -2111,7 +2112,7 @@ class TestDeviceManager(base.BaseTestCase): def test_destroy(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID)) + project_uid=FAKE_PROJECT_ID)) with mock.patch('neutron.agent.linux.interface.NullDriver') as dvr_cls: mock_driver = mock.MagicMock() @@ -2134,7 +2135,7 @@ class TestDeviceManager(base.BaseTestCase): def test_destroy_with_none(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID)) + project_id=FAKE_PROJECT_ID)) with mock.patch('neutron.agent.linux.interface.NullDriver') as dvr_cls: mock_driver = mock.MagicMock() @@ -2155,7 +2156,7 @@ class TestDeviceManager(base.BaseTestCase): def test_get_interface_name(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID)) + project_id=FAKE_PROJECT_ID)) fake_port = dhcp.DictModel( dict(id='12345678-1234-aaaa-1234567890ab', @@ -2181,7 +2182,7 @@ class TestDeviceManager(base.BaseTestCase): def test_get_device_id(self): fake_net = dhcp.NetModel( dict(id=FAKE_NETWORK_UUID, - tenant_id=FAKE_TENANT_ID)) + project_id=FAKE_PROJECT_ID)) expected = ('dhcp1ae5f96c-c527-5079-82ea-371a01645457-12345678-1234-' '5678-1234567890ab') # the DHCP port name only contains the hostname and not the domain name diff --git a/neutron/tests/unit/agent/linux/test_dhcp.py b/neutron/tests/unit/agent/linux/test_dhcp.py index f1b42a3c2e7..927fa6ce1e1 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -3148,7 +3148,7 @@ class TestDeviceManager(TestConfBase): # Setup with no existing DHCP port - expect a new DHCP port to # be created. network = FakeDeviceManagerNetwork() - network.tenant_id = 'Tenant A' + network.project_id = 'Project A' def mock_create(dict): port = dhcp.DictModel(dict['port']) @@ -3231,7 +3231,7 @@ class TestDeviceManager(TestConfBase): # Setup with a reserved DHCP port. network = FakeDualNetworkReserved() - network.tenant_id = 'Tenant A' + network.project_id = 'Project A' reserved_port = network.ports[-1] def mock_update(port_id, dict): @@ -3302,7 +3302,7 @@ class TestDeviceManager(TestConfBase): # Setup with a reserved DHCP port. network = FakeDualNetworkReserved2() - network.tenant_id = 'Tenant A' + network.project_id = 'Project A' reserved_port_1 = network.ports[-2] reserved_port_2 = network.ports[-1] @@ -3333,7 +3333,7 @@ class TestDeviceManager(TestConfBase): """ # Setup with a reserved DHCP port. fake_network = FakeDualNetworkReserved2() - fake_network.tenant_id = 'Tenant A' + fake_network.project_id = 'Project A' reserved_port_2 = fake_network.ports[-1] mock_plugin = mock.Mock() diff --git a/neutron/tests/unit/api/rpc/handlers/test_dhcp_rpc.py b/neutron/tests/unit/api/rpc/handlers/test_dhcp_rpc.py index 743328a634d..5a6b1da854f 100644 --- a/neutron/tests/unit/api/rpc/handlers/test_dhcp_rpc.py +++ b/neutron/tests/unit/api/rpc/handlers/test_dhcp_rpc.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import operator from unittest import mock from neutron_lib.api.definitions import portbindings @@ -23,10 +24,12 @@ from neutron_lib.plugins import constants as plugin_constants from neutron_lib.plugins import directory from oslo_db import exception as db_exc from oslo_messaging.rpc import dispatcher as rpc_dispatcher +from oslo_utils import uuidutils from neutron.api.rpc.handlers import dhcp_rpc from neutron.common import utils from neutron.db import provisioning_blocks +from neutron.objects import network as network_obj from neutron.tests import base @@ -207,50 +210,64 @@ class TestDhcpRpcCallback(base.BaseTestCase): context='ctx', host='host', port_id='66', port={'port': {'network_id': 'a'}})) - def test_get_network_info_return_none_on_not_found(self): - self.plugin.get_network.side_effect = exceptions.NetworkNotFound( - net_id='a') + @mock.patch.object(network_obj.Network, 'get_object', return_value=None) + def test_get_network_info_return_none_on_not_found(self, *args): retval = self.callbacks.get_network_info(mock.Mock(), network_id='a') self.assertIsNone(retval) - def _test_get_network_info(self, segmented_network=False, - routed_network=False): - network_retval = dict(id='a') - if not routed_network: - subnet_retval = [dict(id='a'), dict(id='c'), dict(id='b')] - else: - subnet_retval = [dict(id='c', segment_id='1'), - dict(id='b', segment_id='2'), - dict(id='a', segment_id='1')] - port_retval = mock.Mock() + @mock.patch.object(network_obj.Network, 'get_object') + def _test_get_network_info(self, mock_net_get_object, + segmented_network=False, routed_network=False): + def _network_to_dict(network, ports): + segment_ids = ['1'] + subnets = [_make_subnet_dict(sn) for sn in network.db_obj.subnets] + if routed_network: + non_local_subnets = [subnet for subnet in subnets + if subnet.get('segment_id') not in + segment_ids] + subnets = [subnet for subnet in subnets + if subnet.get('segment_id') in segment_ids] + else: + non_local_subnets = [] + return {'id': network.id, + 'project_id': network.project_id, + 'tenant_id': network.project_id, + 'admin_state_up': network.admin_state_up, + 'ports': ports, + 'subnets': sorted(subnets, key=operator.itemgetter('id')), + 'non_local_subnets': sorted(non_local_subnets, + key=operator.itemgetter('id')), + 'mtu': network.mtu} + + def _make_subnet_dict(subnet): + ret = {'id': subnet.id} + if type(subnet.segment_id) == str: + ret['segment_id'] = subnet.segment_id + return ret + + if not routed_network: + subnets = [mock.Mock(id='a'), mock.Mock(id='c'), mock.Mock(id='b')] + else: + subnets = [mock.Mock(id='a', segment_id='1'), + mock.Mock(id='c', segment_id='2'), + mock.Mock(id='b', segment_id='1')] + db_obj = mock.Mock(subnets=subnets) + project_id = uuidutils.generate_uuid() + network = mock.Mock(id='a', admin_state_up=True, db_obj=db_obj, + project_id=project_id, mtu=1234) + ports = mock.Mock() + mock_net_get_object.return_value = network + self.plugin.get_ports.return_value = ports + self.plugin._make_subnet_dict = _make_subnet_dict - self.plugin.get_network.return_value = network_retval - self.plugin.get_subnets.return_value = subnet_retval - self.plugin.get_ports.return_value = port_retval if segmented_network: - self.segment_plugin.get_segments.return_value = [dict(id='1'), - dict(id='2')] - self.segment_plugin.get_segments_by_hosts.return_value = ['1'] + network.segments = [mock.Mock(id='1', hosts=['host1']), + mock.Mock(id='2', hosts=['host2'])] - retval = self.callbacks.get_network_info(mock.Mock(), network_id='a') - self.assertEqual(retval, network_retval) - sorted_nonlocal_subnet_retval = [] - if not routed_network: - sorted_subnet_retval = [dict(id='a'), dict(id='b'), dict(id='c')] - else: - sorted_subnet_retval = [dict(id='a', segment_id='1'), - dict(id='c', segment_id='1')] - sorted_nonlocal_subnet_retval = [dict(id='b', segment_id='2')] - self.assertEqual(retval['subnets'], sorted_subnet_retval) - self.assertEqual(retval['non_local_subnets'], - sorted_nonlocal_subnet_retval) - self.assertEqual(retval['ports'], port_retval) - subnet_filters = {'network_id': [network_retval['id']], - 'enable_dhcp': [True]} - self.plugin.assert_has_calls( - [mock.call.get_network(mock.ANY, 'a'), - mock.call.get_subnets(mock.ANY, filters=subnet_filters), - mock.call.get_ports(mock.ANY, filters={'network_id': ['a']})]) + retval = self.callbacks.get_network_info(mock.Mock(), network_id='a', + host='host1') + reference = _network_to_dict(network, ports) + self.assertEqual(reference, retval) def test_get_network_info(self): self._test_get_network_info()