From 0f7f95b917b5a48779a327c45bd4a8558efcc7a3 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 4 Feb 2020 18:16:39 +0000 Subject: [PATCH] neutron: Rework how we check for extensions There are couple of changes we can make here: - Always attempt to refresh the cache before checking if an extension is enabled. - Using extension slugs as our reference point rather than extension names. They seem like a better thing to use as a constant and are similarly fixed. - Be consistent in how we name and call the extension check functions - Add documentation for what each extension doing/used for There's a TODO here to remove some code that relies on an out-of-tree extension that I can't see. That's done separately since this is already big enough. Change-Id: I8058902df167239fa455396d3595a56bcf472b2b Signed-off-by: Stephen Finucane --- nova/compute/manager.py | 2 +- nova/conductor/tasks/cross_cell_migrate.py | 2 +- nova/conductor/tasks/live_migrate.py | 5 +- nova/network/constants.py | 47 +++-- nova/network/neutron.py | 180 ++++++++++++------ .../regressions/test_bug_1888395.py | 2 +- .../test_servers_resource_request.py | 5 +- nova/tests/unit/compute/test_compute.py | 7 +- nova/tests/unit/compute/test_compute_mgr.py | 12 +- .../tasks/test_cross_cell_migrate.py | 4 +- .../unit/conductor/tasks/test_live_migrate.py | 6 +- nova/tests/unit/network/test_neutron.py | 168 ++++++++++------ nova/tests/unit/virt/libvirt/test_driver.py | 22 +-- nova/virt/libvirt/driver.py | 2 +- 14 files changed, 294 insertions(+), 170 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index be17fb2db2a6..d446b05b37d0 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -8039,7 +8039,7 @@ class ComputeManager(manager.Manager): LOG.info('Destination was ready for NUMA live migration, ' 'but source is either too old, or is set to an ' 'older upgrade level.', instance=instance) - if self.network_api.supports_port_binding_extension(ctxt): + if self.network_api.has_port_binding_extension(ctxt): # Create migrate_data vifs if not provided by driver. if 'vifs' not in migrate_data: migrate_data.vifs = ( diff --git a/nova/conductor/tasks/cross_cell_migrate.py b/nova/conductor/tasks/cross_cell_migrate.py index 07fa67415913..36db9d5600b3 100644 --- a/nova/conductor/tasks/cross_cell_migrate.py +++ b/nova/conductor/tasks/cross_cell_migrate.py @@ -697,7 +697,7 @@ class CrossCellMigrationTask(base.TaskBase): LOG.debug('Making sure neutron is new enough for cross-cell resize.') # Check that the port binding-extended API extension is available in # neutron because if it's not we can just fail fast. - if not self.network_api.supports_port_binding_extension(self.context): + if not self.network_api.has_port_binding_extension(self.context): raise exception.MigrationPreCheckError( reason=_("Required networking service API extension '%s' " "not found.") % diff --git a/nova/conductor/tasks/live_migrate.py b/nova/conductor/tasks/live_migrate.py index 294abfe4e342..1acae88b2645 100644 --- a/nova/conductor/tasks/live_migrate.py +++ b/nova/conductor/tasks/live_migrate.py @@ -245,8 +245,7 @@ class LiveMigrationTask(base.TaskBase): "are not allowed for live migration.") # All PCI requests are VIF related, now check neutron, # source and destination compute nodes. - if not self.network_api.supports_port_binding_extension( - self.context): + if not self.network_api.has_port_binding_extension(self.context): raise exception.MigrationPreCheckError( reason="Cannot live migrate VIF with related PCI, Neutron " "does not support required port binding extension.") @@ -366,7 +365,7 @@ class LiveMigrationTask(base.TaskBase): raise exception.MigrationPreCheckError(msg) # Check to see that neutron supports the binding-extended API. - if self.network_api.supports_port_binding_extension(self.context): + if self.network_api.has_port_binding_extension(self.context): bindings = self._bind_ports_on_destination( destination, provider_mapping) self._update_migrate_vifs_from_bindings(self.migrate_data.vifs, diff --git a/nova/network/constants.py b/nova/network/constants.py index 4a08c870f6c6..eff49022c16a 100644 --- a/nova/network/constants.py +++ b/nova/network/constants.py @@ -13,23 +13,40 @@ # License for the specific language governing permissions and limitations # under the License. -QOS_QUEUE = 'QoS Queue' -NET_EXTERNAL = 'router:external' -VNIC_INDEX_EXT = 'VNIC Index' -DNS_INTEGRATION = 'DNS Integration' -MULTI_NET_EXT = 'Multi Provider Network' -FIP_PORT_DETAILS = 'Floating IP Port Details Extension' -SUBSTR_PORT_FILTERING = 'IP address substring filtering' -PORT_BINDING = 'Port Binding' -PORT_BINDING_EXTENDED = 'Port Bindings Extended' -DEFAULT_SECGROUP = 'default' +# Port fields + BINDING_PROFILE = 'binding:profile' BINDING_HOST_ID = 'binding:host_id' -MIGRATING_ATTR = 'migrating_to' -L3_NETWORK_TYPES = ['vxlan', 'gre', 'geneve'] -ALLOCATION = 'allocation' RESOURCE_REQUEST = 'resource_request' REQUEST_GROUPS = 'request_groups' -SEGMENT = 'Segment' NUMA_POLICY = 'numa_affinity_policy' -RESOURCE_REQUEST_GROUPS_EXTENSION = "Port Resource Request Groups" + +# Binding profile fields + +MIGRATING_ATTR = 'migrating_to' +ALLOCATION = 'allocation' + +# Core extensions + +DNS_INTEGRATION = 'dns-integration' +MULTI_PROVIDER = 'multi-provider' +FIP_PORT_DETAILS = 'fip-port-details' +PORT_BINDING = 'binding' +PORT_BINDING_EXTENDED = 'binding-extended' +SUBSTR_PORT_FILTERING = 'ip-substring-filtering' +SEGMENT = 'segment' +RESOURCE_REQUEST_GROUPS = 'port-resource-request-groups' + +# Third-party extensions + +VNIC_INDEX = 'vnic-index' # this is provided by the vmware_nsx project +QOS_QUEUE = 'qos-queue' # TODO(stephenfin): what defines this? Xen? + +# Search fields + +NET_EXTERNAL = 'router:external' + +# Misc + +DEFAULT_SECGROUP = 'default' +L3_NETWORK_TYPES = ['vxlan', 'gre', 'geneve'] diff --git a/nova/network/neutron.py b/nova/network/neutron.py index 60ca3453530c..73b2376950c8 100644 --- a/nova/network/neutron.py +++ b/nova/network/neutron.py @@ -381,7 +381,8 @@ class API: # If a host was provided, delete any bindings between that # host and the ports as long as the host isn't the same as # the current instance.host. - has_binding_ext = self.supports_port_binding_extension(context) + has_binding_ext = self.has_port_binding_extension( + client=admin_client) if port_migrating and has_binding_ext: self._delete_port_bindings(context, ports, host) elif port_migrating: @@ -674,8 +675,12 @@ class API: # NOTE: For internal DNS integration (network does not have a # dns_domain), or if we cannot retrieve network info, we use the # admin client to reset dns_name. - if self._has_dns_extension() and not network.get('dns_domain'): + if ( + self.has_dns_extension(client=port_client) and + not network.get('dns_domain') + ): port_req_body['port']['dns_name'] = '' + try: port_client.update_port(port_id, port_req_body) except neutron_client_exc.PortNotFoundClient: @@ -1329,62 +1334,112 @@ class API: return (nets_in_requested_order, ports_in_requested_order, preexisting_port_ids, created_port_ids) - def _refresh_neutron_extensions_cache(self, context, neutron=None): + def _refresh_neutron_extensions_cache(self, client): """Refresh the neutron extensions cache when necessary.""" if (not self.last_neutron_extension_sync or ((time.time() - self.last_neutron_extension_sync) >= CONF.neutron.extension_sync_interval)): - if neutron is None: - neutron = get_client(context) - extensions_list = neutron.list_extensions()['extensions'] + extensions_list = client.list_extensions()['extensions'] self.last_neutron_extension_sync = time.time() self.extensions.clear() - self.extensions = {ext['name']: ext for ext in extensions_list} + self.extensions = {ext['alias']: ext for ext in extensions_list} - def _has_multi_provider_extension(self, context, neutron=None): - self._refresh_neutron_extensions_cache(context, neutron=neutron) - return constants.MULTI_NET_EXT in self.extensions + def _has_extension(self, extension, context=None, client=None): + """Check if the provided neutron extension is enabled. - def _has_dns_extension(self): - return constants.DNS_INTEGRATION in self.extensions + :param extension: The alias of the extension to check + :param client: keystoneauth1.adapter.Adapter + :param context: nova.context.RequestContext + :returns: True if the neutron extension is available, else False + """ + if client is None: + client = get_client(context) - def _has_qos_queue_extension(self, context, neutron=None): - self._refresh_neutron_extensions_cache(context, neutron=neutron) - return constants.QOS_QUEUE in self.extensions + self._refresh_neutron_extensions_cache(client) + return extension in self.extensions - def _has_fip_port_details_extension(self, context, neutron=None): - self._refresh_neutron_extensions_cache(context, neutron=neutron) - return constants.FIP_PORT_DETAILS in self.extensions + def has_multi_provider_extension(self, context=None, client=None): + """Check if the 'multi-provider' extension is enabled. - def has_substr_port_filtering_extension(self, context): - self._refresh_neutron_extensions_cache(context) - return constants.SUBSTR_PORT_FILTERING in self.extensions + This extension allows administrative users to define multiple physical + bindings for a logical network. + """ + return self._has_extension(constants.MULTI_PROVIDER, context, client) - def _has_segment_extension(self, context, neutron=None): - self._refresh_neutron_extensions_cache(context, neutron=neutron) - return constants.SEGMENT in self.extensions + def has_dns_extension(self, context=None, client=None): + """Check if the 'dns-integration' extension is enabled. + + This extension adds the 'dns_name' and 'dns_assignment' attributes to + port resources. + """ + return self._has_extension(constants.DNS_INTEGRATION, context, client) # TODO(gibi): Remove all branches where this is False after Neutron made # the this extension mandatory. In Xena this extension will be optional to # support the scenario where Neutron upgraded first. So Neutron can mark # this mandatory earliest in Yoga. - def has_extended_resource_request_extension(self, context, neutron=None): - self._refresh_neutron_extensions_cache(context, neutron=neutron) - return constants.RESOURCE_REQUEST_GROUPS_EXTENSION in self.extensions + def has_extended_resource_request_extension( + self, context=None, client=None, + ): + return self._has_extension( + constants.RESOURCE_REQUEST_GROUPS, context, client, + ) - def supports_port_binding_extension(self, context): - """This is a simple check to see if the neutron "binding-extended" - extension exists and is enabled. + # TODO(stephenfin): This is optionally used by the XenAPI virt driver, but + # I can't find what defines it and suspect it's dead code. Consider + # removing the functionality + def has_qos_queue_extension(self, context=None, client=None): + """Check if the 'qos-queue' extension is enabled. - The "binding-extended" extension allows nova to bind a port to multiple - hosts at the same time, like during live migration. - - :param context: the user request context - :returns: True if the binding-extended API extension is available, - False otherwise + This extension is provided by a XenServer neutron plugin...we think. """ - self._refresh_neutron_extensions_cache(context) - return constants.PORT_BINDING_EXTENDED in self.extensions + return self._has_extension(constants.QOS_QUEUE, context, client) + + def has_vnic_index_extension(self, context=None, client=None): + """Check if the 'vnic-index' extension is enabled. + + This extension is provided by the VMWare NSX neutron plugin. + """ + return self._has_extension(constants.VNIC_INDEX, context, client) + + def has_fip_port_details_extension(self, context=None, client=None): + """Check if the 'fip-port-details' extension is enabled. + + This extension adds the 'port_details' attribute to floating IPs. + """ + return self._has_extension(constants.FIP_PORT_DETAILS, context, client) + + def has_substr_port_filtering_extension(self, context=None, client=None): + """Check if the 'ip-substring-filtering' extension is enabled. + + This extension adds support for filtering ports by using part of an IP + address. + """ + return self._has_extension( + constants.SUBSTR_PORT_FILTERING, context, client + ) + + def has_segment_extension(self, context=None, client=None): + """Check if the neutron 'segment' extension is enabled. + + This extension exposes information about L2 segments of a network. + """ + return self._has_extension( + constants.SEGMENT, context, client, + ) + + def has_port_binding_extension(self, context=None, client=None): + """Check if the neutron 'binding-extended' extension is enabled. + + This extensions exposes port bindings of a virtual port to external + application. + + This extension allows nova to bind a port to multiple hosts at the same + time, like during live migration. + """ + return self._has_extension( + constants.PORT_BINDING_EXTENDED, context, client + ) def bind_ports_to_host(self, context, instance, host, vnic_types=None, port_profiles=None): @@ -1398,7 +1453,7 @@ class API: In the event of an error, any ports which were successfully bound to the host should have those host bindings removed from the ports. - This method should not be used if "supports_port_binding_extension" + This method should not be used if "has_port_binding_extension" returns False. :param context: the user request context @@ -1477,7 +1532,7 @@ class API: def delete_port_binding(self, context, port_id, host): """Delete the port binding for the given port ID and host - This method should not be used if "supports_port_binding_extension" + This method should not be used if "has_port_binding_extension" returns False. :param context: The request context for the operation. @@ -1586,7 +1641,10 @@ class API: If the extensions loaded contain QOS_QUEUE then pass the rxtx_factor. """ - if self._has_qos_queue_extension(context, neutron=neutron): + if neutron is None: + neutron = get_client(context) + + if self.has_qos_queue_extension(client=neutron): flavor = instance.get_flavor() rxtx_factor = flavor.get('rxtx_factor') port_req_body['port']['rxtx_factor'] = rxtx_factor @@ -1596,7 +1654,7 @@ class API: port_req_body, port_arq) - if self._has_dns_extension(): + if self.has_dns_extension(client=neutron): # If the DNS integration extension is enabled in Neutron, most # ports will get their dns_name attribute set in the port create or # update requests in allocate_for_instance. So we just add the @@ -1622,7 +1680,8 @@ class API: an additional update request. Only a very small fraction of ports will require this additional update request. """ - if self._has_dns_extension() and network.get('dns_domain'): + if self.has_dns_extension(client=neutron) and network.get( + 'dns_domain'): try: port_req_body = {'port': {'dns_name': instance.hostname}} neutron.update_port(port_id, port_req_body) @@ -1634,7 +1693,7 @@ class API: 'name') % {'hostname': instance.hostname}) raise exception.InvalidInput(reason=msg) - def _reset_port_dns_name(self, network, port_id, neutron_client): + def _reset_port_dns_name(self, network, port_id, client): """Reset an instance port dns_name attribute to empty when using external DNS service. @@ -1644,10 +1703,11 @@ class API: request with a Neutron client using user's context, so that the DNS record can be found under user's zone and domain. """ - if self._has_dns_extension() and network.get('dns_domain'): + if self.has_dns_extension(client=client) and network.get( + 'dns_domain'): try: port_req_body = {'port': {'dns_name': ''}} - neutron_client.update_port(port_id, port_req_body) + client.update_port(port_id, port_req_body) except neutron_client_exc.NeutronClientException: LOG.exception("Failed to reset dns_name for port %s", port_id) @@ -2006,7 +2066,7 @@ class API: segments, the first segment that defines a physnet value will be used for the physnet name. """ - if self._has_multi_provider_extension(context, neutron=neutron): + if self.has_multi_provider_extension(client=neutron): network = neutron.show_network(net_id, fields='segments').get('network') segments = network.get('segments', {}) @@ -2681,7 +2741,7 @@ class API: # ...and retrieve the port details for the same reason, but only if # they're not already there because the fip-port-details extension is # present - if not self._has_fip_port_details_extension(context, client): + if not self.has_fip_port_details_extension(client=client): port_id = fip['port_id'] try: fip['port_details'] = client.show_port( @@ -2709,7 +2769,7 @@ class API: # ...and retrieve the port details for the same reason, but only if # they're not already there because the fip-port-details extension is # present - if not self._has_fip_port_details_extension(context, client): + if not self.has_fip_port_details_extension(client=client): port_id = fip['port_id'] try: fip['port_details'] = client.show_port( @@ -2748,7 +2808,7 @@ class API: # ...and retrieve the port details for the same reason, but only if # they're not already there because the fip-port-details extension is # present - if not self._has_fip_port_details_extension(context, client): + if not self.has_fip_port_details_extension(client=client): ports = {port['id']: port for port in client.list_ports( **{'tenant_id': project_id})['ports']} for fip in fips: @@ -2944,7 +3004,7 @@ class API: :raises: nova.exception.PortBindingActivationFailed if any port binding activation fails """ - if not self.supports_port_binding_extension(context): + if not self.has_port_binding_extension(context): # If neutron isn't new enough yet for the port "binding-extended" # API extension, we just no-op. The port binding host will be # be updated in migrate_instance_finish, which is functionally OK, @@ -3470,7 +3530,8 @@ class API: :raises: PortBindingDeletionFailed if port binding deletion fails. """ # First check to see if the port binding extension is supported. - if not self.supports_port_binding_extension(context): + client = get_client(context) + if not self.has_port_binding_extension(client=client): LOG.info("Neutron extension '%s' is not supported; not cleaning " "up port bindings for host %s.", constants.PORT_BINDING_EXTENDED, host, instance=instance) @@ -3661,9 +3722,8 @@ class API: :param vif: The VIF in question. :param index: The index on the instance for the VIF. """ - self._refresh_neutron_extensions_cache(context) - if constants.VNIC_INDEX_EXT in self.extensions: - neutron = get_client(context) + neutron = get_client(context) + if self.has_vnic_index_extension(client=neutron): port_req_body = {'port': {'vnic_index': index}} try: neutron.update_port(vif['id'], port_req_body) @@ -3686,10 +3746,11 @@ class API: either Segment extension isn't enabled in Neutron or if the network isn't configured for routing. """ - if not self._has_segment_extension(context): + client = get_client(context) + + if not self.has_segment_extension(client=client): return [] - client = get_client(context) try: # NOTE(sbauza): We can't use list_segments() directly because the # API is borked and returns both segments but also segmentation IDs @@ -3716,10 +3777,11 @@ class API: extension isn't enabled in Neutron or the provided subnet doesn't have segments (if the related network isn't configured for routing) """ - if not self._has_segment_extension(context): + client = get_client(context) + + if not self.has_segment_extension(client=client): return None - client = get_client(context) try: subnet = client.show_subnet(subnet_id)['subnet'] except neutron_client_exc.NeutronClientException as e: diff --git a/nova/tests/functional/regressions/test_bug_1888395.py b/nova/tests/functional/regressions/test_bug_1888395.py index 36eb0e0f52b3..e582ad3e8519 100644 --- a/nova/tests/functional/regressions/test_bug_1888395.py +++ b/nova/tests/functional/regressions/test_bug_1888395.py @@ -108,7 +108,7 @@ class TestLiveMigrationWithoutMultiplePortBindings( networks=[{'port': self.neutron.port_1['id']}]) self.assertFalse( - self.neutron_api.supports_port_binding_extension(self.ctxt)) + self.neutron_api.has_port_binding_extension(self.ctxt)) # TODO(sean-k-mooney): extend _live_migrate to support passing a host self.api.post_server_action( server['id'], diff --git a/nova/tests/functional/test_servers_resource_request.py b/nova/tests/functional/test_servers_resource_request.py index d3089802099e..57c87634e6d9 100644 --- a/nova/tests/functional/test_servers_resource_request.py +++ b/nova/tests/functional/test_servers_resource_request.py @@ -147,12 +147,13 @@ class ExtendedResourceRequestNeutronFixture(ResourceRequestNeutronFixture): # port_resource_request_groups.py { "updated": "2021-08-02T10:00:00-00:00", - "name": constants.RESOURCE_REQUEST_GROUPS_EXTENSION, + "name": "Port Resource Request Groups", "links": [], "alias": "port-resource-request-groups", - "description": + "description": ( "Support requesting multiple groups of resources and " "traits from the same RP subtree in resource_request" + ), } ) return extensions diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index dfbe245027f2..3d3ced3516b8 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -6070,10 +6070,9 @@ class ComputeTestCase(BaseTestCase, return fake_network.fake_get_instance_nw_info(self) self.stub_out('nova.network.neutron.API.get_instance_nw_info', stupid) - self.useFixture( - std_fixtures.MonkeyPatch( - 'nova.network.neutron.API.supports_port_binding_extension', - lambda *args: True)) + self.useFixture(std_fixtures.MonkeyPatch( + 'nova.network.neutron.API.has_port_binding_extension', + lambda *args: True)) # creating instance testdata instance = self._create_fake_instance_obj({'host': 'dummy'}) c = context.get_admin_context() diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 091c762f0a0a..7c11033310d4 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -3454,7 +3454,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, side_effect=exception.InstanceGroupNotFound(group_uuid=''))) def test_check_can_live_migrate_destination_success(self): self.useFixture(std_fixtures.MonkeyPatch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', lambda *args: True)) self._test_check_can_live_migrate_destination() @@ -3462,7 +3462,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, side_effect=exception.InstanceGroupNotFound(group_uuid=''))) def test_check_can_live_migrate_destination_fail(self): self.useFixture(std_fixtures.MonkeyPatch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', lambda *args: True)) self.assertRaises( test.TestingException, @@ -3473,7 +3473,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, side_effect=exception.InstanceGroupNotFound(group_uuid=''))) def test_check_can_live_migrate_destination_contains_vifs(self): self.useFixture(std_fixtures.MonkeyPatch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', lambda *args: True)) migrate_data = self._test_check_can_live_migrate_destination() self.assertIn('vifs', migrate_data) @@ -3483,7 +3483,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, side_effect=exception.InstanceGroupNotFound(group_uuid=''))) def test_check_can_live_migrate_destination_no_binding_extended(self): self.useFixture(std_fixtures.MonkeyPatch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', lambda *args: False)) migrate_data = self._test_check_can_live_migrate_destination() self.assertNotIn('vifs', migrate_data) @@ -3492,7 +3492,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, side_effect=exception.InstanceGroupNotFound(group_uuid=''))) def test_check_can_live_migrate_destination_src_numa_lm_false(self): self.useFixture(std_fixtures.MonkeyPatch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', lambda *args: True)) self._test_check_can_live_migrate_destination(src_numa_lm=False) @@ -3500,7 +3500,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase, side_effect=exception.InstanceGroupNotFound(group_uuid=''))) def test_check_can_live_migrate_destination_src_numa_lm_true(self): self.useFixture(std_fixtures.MonkeyPatch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', lambda *args: True)) self._test_check_can_live_migrate_destination(src_numa_lm=True) diff --git a/nova/tests/unit/conductor/tasks/test_cross_cell_migrate.py b/nova/tests/unit/conductor/tasks/test_cross_cell_migrate.py index 127d76347795..ec07e6f55fae 100644 --- a/nova/tests/unit/conductor/tasks/test_cross_cell_migrate.py +++ b/nova/tests/unit/conductor/tasks/test_cross_cell_migrate.py @@ -439,7 +439,7 @@ class CrossCellMigrationTaskTestCase(test.NoDBTestCase): what we need. """ with mock.patch.object( - self.task.network_api, 'supports_port_binding_extension', + self.task.network_api, 'has_port_binding_extension', return_value=True) as mock_neutron_check: self.task._perform_external_api_checks() mock_neutron_check.assert_called_once_with(self.task.context) @@ -447,7 +447,7 @@ class CrossCellMigrationTaskTestCase(test.NoDBTestCase): def test_perform_external_api_checks_old_neutron(self): """Tests the case that neutron API is old.""" with mock.patch.object( - self.task.network_api, 'supports_port_binding_extension', + self.task.network_api, 'has_port_binding_extension', return_value=False): ex = self.assertRaises(exception.MigrationPreCheckError, self.task._perform_external_api_checks) diff --git a/nova/tests/unit/conductor/tasks/test_live_migrate.py b/nova/tests/unit/conductor/tasks/test_live_migrate.py index 88f00d0d84aa..cb40c076c82d 100644 --- a/nova/tests/unit/conductor/tasks/test_live_migrate.py +++ b/nova/tests/unit/conductor/tasks/test_live_migrate.py @@ -353,7 +353,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): with test.nested( mock.patch.object(self.task.network_api, - 'supports_port_binding_extension', + 'has_port_binding_extension', return_value=False), mock.patch.object(self.task, '_check_can_migrate_pci')): self.assertIsNone(self.task._check_requested_destination()) @@ -387,7 +387,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): with test.nested( mock.patch.object(self.task.network_api, - 'supports_port_binding_extension', + 'has_port_binding_extension', return_value=False), mock.patch.object(self.task, '_check_can_migrate_pci')): ex = self.assertRaises(exception.MigrationPreCheckError, @@ -813,7 +813,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase): """ @mock.patch.object(self.task.network_api, - 'supports_port_binding_extension') + 'has_port_binding_extension') @mock.patch.object(live_migrate, 'supports_vif_related_pci_allocations') def _test(instance_pci_reqs, diff --git a/nova/tests/unit/network/test_neutron.py b/nova/tests/unit/network/test_neutron.py index 1ac357f39f62..b717e509dff8 100644 --- a/nova/tests/unit/network/test_neutron.py +++ b/nova/tests/unit/network/test_neutron.py @@ -514,7 +514,11 @@ class TestAPIBase(test.TestCase): has_dns_extension = False if kwargs.get('dns_extension'): has_dns_extension = True - self.api.extensions[constants.DNS_INTEGRATION] = 1 + self.api.extensions = { + constants.DNS_INTEGRATION: { + 'alias': constants.DNS_INTEGRATION, + }, + } # Net idx is 1-based for compatibility with existing unit tests nets = self.nets[net_idx - 1] @@ -1166,17 +1170,14 @@ class TestAPI(TestAPIBase): mock_get_physnet.assert_called_once_with( mock.ANY, mock.ANY, self.port_data1[0]['network_id']) - @mock.patch.object(neutronapi, 'get_client') - def test_refresh_neutron_extensions_cache(self, mock_get_client): + def test_refresh_neutron_extensions_cache(self): mocked_client = mock.create_autospec(client.Client) - mock_get_client.return_value = mocked_client mocked_client.list_extensions.return_value = { - 'extensions': [{'name': constants.QOS_QUEUE}]} - self.api._refresh_neutron_extensions_cache(self.context) + 'extensions': [{'alias': constants.QOS_QUEUE}]} + self.api._refresh_neutron_extensions_cache(mocked_client) self.assertEqual( - {constants.QOS_QUEUE: {'name': constants.QOS_QUEUE}}, + {constants.QOS_QUEUE: {'alias': constants.QOS_QUEUE}}, self.api.extensions) - mock_get_client.assert_called_once_with(self.context) mocked_client.list_extensions.assert_called_once_with() @mock.patch.object(neutronapi, 'get_client') @@ -1185,7 +1186,7 @@ class TestAPI(TestAPIBase): mocked_client = mock.create_autospec(client.Client) mock_get_client.return_value = mocked_client mocked_client.list_extensions.return_value = { - 'extensions': [{'name': constants.QOS_QUEUE}]} + 'extensions': [{'alias': constants.QOS_QUEUE}]} flavor = objects.Flavor.get_by_name(self.context, 'm1.small') flavor['rxtx_factor'] = 1 instance = objects.Instance(system_metadata={}) @@ -2412,9 +2413,13 @@ class TestAPI(TestAPIBase): mock_nc.show_port.side_effect = exceptions.PortNotFoundClient if fip_ext_enabled: - self.api.extensions = [constants.FIP_PORT_DETAILS] + self.api.extensions = { + constants.FIP_PORT_DETAILS: { + 'alias': constants.FIP_PORT_DETAILS, + }, + } else: - self.api.extensions = [] + self.api.extensions = {} fip = self.api.get_floating_ip(self.context, uuids.fip_id) @@ -2487,9 +2492,13 @@ class TestAPI(TestAPIBase): mock_nc.show_port.side_effect = exceptions.PortNotFoundClient if fip_ext_enabled: - self.api.extensions = [constants.FIP_PORT_DETAILS] + self.api.extensions = { + constants.FIP_PORT_DETAILS: { + 'alias': constants.FIP_PORT_DETAILS, + }, + } else: - self.api.extensions = [] + self.api.extensions = {} fip = self.api.get_floating_ip_by_address(self.context, '172.1.2.3') @@ -3471,7 +3480,7 @@ class TestAPI(TestAPIBase): 'provider:network_type': 'vxlan'}]}} test_ext_list = {'extensions': [{'name': 'Multi Provider Network', - 'alias': 'multi-segments'}]} + 'alias': 'multi-provider'}]} mock_client = mock_get_client.return_value mock_client.list_extensions.return_value = test_ext_list @@ -3492,7 +3501,7 @@ class TestAPI(TestAPIBase): 'provider:network_type': 'vlan'}} test_ext_list = {'extensions': [{'name': 'Multi Provider Network', - 'alias': 'multi-segments'}]} + 'alias': 'multi-provider'}]} mock_client = mock_get_client.return_value mock_client.list_extensions.return_value = test_ext_list @@ -3518,7 +3527,7 @@ class TestAPI(TestAPIBase): 'provider:network_type': 'vlan'}]}} test_ext_list = {'extensions': [{'name': 'Multi Provider Network', - 'alias': 'multi-segments'}]} + 'alias': 'multi-provider'}]} mock_client = mock_get_client.return_value mock_client.list_extensions.return_value = test_ext_list @@ -4354,7 +4363,7 @@ class TestAPI(TestAPIBase): def test_update_instance_vnic_index(self, mock_get_client, mock_refresh_extensions): api = neutronapi.API() - api.extensions = set([constants.VNIC_INDEX_EXT]) + api.extensions = set([constants.VNIC_INDEX]) mock_client = mock_get_client.return_value mock_client.update_port.return_value = 'port' @@ -4379,7 +4388,7 @@ class TestAPI(TestAPIBase): self, get_client_mock ): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) # We pass in a port profile which has a migration attribute and also # a second port profile attribute 'fake_profile' this can be @@ -4423,7 +4432,7 @@ class TestAPI(TestAPIBase): value is None. """ instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) fake_ports = {'ports': [ {'id': uuids.portid, @@ -4595,7 +4604,7 @@ class TestAPI(TestAPIBase): def test_update_port_bindings_for_instance_with_pci_no_migration(self, get_client_mock, get_pci_device_devspec_mock): - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) devspec = mock.Mock() devspec.get_tags.return_value = {'physical_network': 'physnet1'} @@ -4645,7 +4654,7 @@ class TestAPI(TestAPIBase): def test_update_port_bindings_for_instance_with_same_host_failed_vif_type( self, get_client_mock): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) list_ports_mock = mock.Mock() update_port_mock = mock.Mock() @@ -4690,7 +4699,7 @@ class TestAPI(TestAPIBase): def test_update_port_bindings_for_instance_with_diff_host_unbound_vif_type( self, get_client_mock): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) binding_profile = {'fake_profile': 'fake_data', constants.MIGRATING_ATTR: 'my-dest-host'} @@ -4980,7 +4989,7 @@ class TestAPI(TestAPIBase): self, get_client_mock): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) # We test with an instance host and destination_host where the # port will be moving. get_ports = {'ports': [ @@ -5010,7 +5019,7 @@ class TestAPI(TestAPIBase): destination host and the binding:profile is None in the port. """ instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) # We test with an instance host and destination_host where the # port will be moving but with binding:profile set to None. get_ports = { @@ -5041,7 +5050,7 @@ class TestAPI(TestAPIBase): self, get_client_mock): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) port_id = uuids.port_id get_ports = {'ports': [ {'id': port_id, @@ -5061,7 +5070,7 @@ class TestAPI(TestAPIBase): self, get_client_mock): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) get_ports = {'ports': [ {'id': uuids.port_id, constants.BINDING_HOST_ID: instance.host}]} @@ -5097,7 +5106,7 @@ class TestAPI(TestAPIBase): self, get_client_mock): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) migrate_profile = { constants.MIGRATING_ATTR: 'new-host'} # Pass a port with an migration porfile attribute. @@ -5109,8 +5118,9 @@ class TestAPI(TestAPIBase): self.api.list_ports = mock.Mock(return_value=get_ports) mocked_client = get_client_mock.return_value - with mock.patch.object(self.api, 'supports_port_binding_extension', - return_value=True): + with mock.patch.object( + self.api, 'has_port_binding_extension', return_value=True, + ): self.api.setup_networks_on_host(self.context, instance, host='new-host', @@ -5128,7 +5138,7 @@ class TestAPI(TestAPIBase): which is raised through to the caller. """ instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) migrate_profile = { constants.MIGRATING_ATTR: 'new-host'} # Pass a port with an migration porfile attribute. @@ -5146,8 +5156,9 @@ class TestAPI(TestAPIBase): mocked_client = get_client_mock.return_value mocked_client.delete_port_binding.side_effect = NeutronError - with mock.patch.object(self.api, 'supports_port_binding_extension', - return_value=True): + with mock.patch.object( + self.api, 'has_port_binding_extension', return_value=True, + ): ex = self.assertRaises( exception.PortBindingDeletionFailed, self.api.setup_networks_on_host, @@ -5169,7 +5180,7 @@ class TestAPI(TestAPIBase): self, get_client_mock): instance = fake_instance.fake_instance_obj(self.context) - self.api._has_port_binding_extension = mock.Mock(return_value=True) + self.api.has_port_binding_extension = mock.Mock(return_value=True) # Pass a port without any migration porfile attribute. get_ports = {'ports': [ {'id': uuids.port_id, @@ -5177,7 +5188,7 @@ class TestAPI(TestAPIBase): self.api.list_ports = mock.Mock(return_value=get_ports) update_port_mock = mock.Mock() get_client_mock.return_value.update_port = update_port_mock - with mock.patch.object(self.api, 'supports_port_binding_extension', + with mock.patch.object(self.api, 'has_port_binding_extension', return_value=False): self.api.setup_networks_on_host(self.context, instance, @@ -5235,6 +5246,8 @@ class TestAPI(TestAPIBase): def test_unbind_ports_get_client(self, mock_neutron): self._test_unbind_ports_get_client(mock_neutron) + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.network.neutron.API._show_port') def _test_unbind_ports(self, mock_neutron, mock_show): mock_client = mock.Mock() @@ -5277,7 +5290,11 @@ class TestAPI(TestAPIBase): @mock.patch( 'nova.network.neutron.API.has_extended_resource_request_extension', - new=mock.Mock() + new=mock.Mock(return_value=True), + ) + @mock.patch( + 'nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=True), ) @mock.patch('nova.network.neutron.API.get_instance_nw_info') @mock.patch('nova.network.neutron.excutils') @@ -5760,9 +5777,13 @@ class TestAPI(TestAPIBase): mock_nc.list_ports.return_value = {'ports': []} if fip_ext_enabled: - self.api.extensions = [constants.FIP_PORT_DETAILS] + self.api.extensions = { + constants.FIP_PORT_DETAILS: { + 'alias': constants.FIP_PORT_DETAILS, + }, + } else: - self.api.extensions = [] + self.api.extensions = {} fips = self.api.get_floating_ips_by_project(self.context) @@ -5795,6 +5816,8 @@ class TestAPI(TestAPIBase): """Make sure we don't fail for floating IPs without attached ports.""" self._test_get_floating_ips_by_project(False, False) + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=True)) @mock.patch('nova.network.neutron.API._show_port') def test_unbind_ports_reset_dns_name_by_admin(self, mock_show): neutron = mock.Mock() @@ -5805,7 +5828,6 @@ class TestAPI(TestAPIBase): } } port_client = mock.Mock() - self.api.extensions = [constants.DNS_INTEGRATION] ports = [uuids.port_id] mock_show.return_value = {'id': uuids.port} self.api._unbind_ports(self.context, ports, neutron, port_client) @@ -5818,6 +5840,8 @@ class TestAPI(TestAPIBase): uuids.port_id, port_req_body) neutron.update_port.assert_not_called() + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=True)) @mock.patch('nova.network.neutron.API._show_port') def test_unbind_ports_reset_dns_name_by_non_admin(self, mock_show): neutron = mock.Mock() @@ -5828,7 +5852,6 @@ class TestAPI(TestAPIBase): } } port_client = mock.Mock() - self.api.extensions = [constants.DNS_INTEGRATION] ports = [uuids.port_id] mock_show.return_value = {'id': uuids.port} self.api._unbind_ports(self.context, ports, neutron, port_client) @@ -5842,6 +5865,8 @@ class TestAPI(TestAPIBase): neutron.update_port.assert_called_once_with( uuids.port_id, non_admin_port_req_body) + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.network.neutron.API._show_port') def test_unbind_ports_reset_allocation_in_port_binding(self, mock_show): neutron = mock.Mock() @@ -5857,6 +5882,8 @@ class TestAPI(TestAPIBase): port_client.update_port.assert_called_once_with( uuids.port_id, port_req_body) + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.network.neutron.API._show_port') def test_unbind_ports_reset_binding_profile(self, mock_show): neutron = mock.Mock() @@ -5880,6 +5907,8 @@ class TestAPI(TestAPIBase): port_client.update_port.assert_called_once_with( uuids.port_id, port_req_body) + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.network.neutron.API._populate_neutron_extension_values') @mock.patch('nova.network.neutron.API._update_port', # called twice, fails on the 2nd call and triggers the cleanup @@ -5961,6 +5990,8 @@ class TestAPI(TestAPIBase): neutron_client=mock.ANY) mock_log.assert_not_called() + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.network.neutron.API._show_port', side_effect=Exception) @mock.patch.object(neutronapi.LOG, 'exception') @@ -5978,6 +6009,8 @@ class TestAPI(TestAPIBase): 'binding:profile': {}, 'binding:host_id': None}}) self.assertTrue(mock_log.called) + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.network.neutron.API._show_port') @mock.patch.object(neutronapi.LOG, 'exception') def test_unbind_ports_portnotfound(self, mock_log, mock_show): @@ -5994,6 +6027,8 @@ class TestAPI(TestAPIBase): 'binding:profile': {}, 'binding:host_id': None}}) mock_log.assert_not_called() + @mock.patch('nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.network.neutron.API._show_port') @mock.patch.object(neutronapi.LOG, 'exception') def test_unbind_ports_unexpected_error(self, mock_log, mock_show): @@ -6609,7 +6644,7 @@ class TestAPI(TestAPIBase): """Tests that migrate_instance_start exits early if neutron doesn't have the binding-extended API extension. """ - with mock.patch.object(self.api, 'supports_port_binding_extension', + with mock.patch.object(self.api, 'has_port_binding_extension', return_value=False): self.api.migrate_instance_start( self.context, mock.sentinel.instance, {}) @@ -6629,8 +6664,9 @@ class TestAPI(TestAPIBase): migration = objects.Migration( source_compute='source', dest_compute='dest') - with mock.patch.object(self.api, 'supports_port_binding_extension', - return_value=True): + with mock.patch.object( + self.api, 'has_port_binding_extension', return_value=True, + ): self.api.migrate_instance_start( self.context, instance, migration) @@ -6654,8 +6690,9 @@ class TestAPI(TestAPIBase): migration = objects.Migration( source_compute='source', dest_compute='dest') - with mock.patch.object(self.api, 'supports_port_binding_extension', - return_value=True): + with mock.patch.object( + self.api, 'has_port_binding_extension', return_value=True, + ): self.api.migrate_instance_start( self.context, instance, migration) @@ -6681,8 +6718,9 @@ class TestAPI(TestAPIBase): migration = objects.Migration( source_compute='source', dest_compute='dest') - with mock.patch.object(self.api, 'supports_port_binding_extension', - return_value=True): + with mock.patch.object( + self.api, 'has_port_binding_extension', return_value=True, + ): self.api.migrate_instance_start( self.context, instance, migration) @@ -6705,8 +6743,9 @@ class TestAPI(TestAPIBase): migration = objects.Migration( source_compute='source', dest_compute='dest') - with mock.patch.object(self.api, 'supports_port_binding_extension', - return_value=True): + with mock.patch.object( + self.api, 'has_port_binding_extension', return_value=True, + ): self.api.migrate_instance_start( self.context, instance, migration) @@ -6885,7 +6924,7 @@ class TestAPI(TestAPIBase): def test_get_segment_ids_for_network_no_segment_ext(self): with mock.patch.object( - self.api, '_has_segment_extension', return_value=False + self.api, 'has_segment_extension', return_value=False, ): self.assertEqual( [], self.api.get_segment_ids_for_network(self.context, @@ -6898,7 +6937,7 @@ class TestAPI(TestAPIBase): mock_client.return_value = mocked_client mocked_client.list_subnets.return_value = subnets with mock.patch.object( - self.api, '_has_segment_extension', return_value=True + self.api, 'has_segment_extension', return_value=True, ): res = self.api.get_segment_ids_for_network( self.context, uuids.network_id) @@ -6913,7 +6952,7 @@ class TestAPI(TestAPIBase): mock_client.return_value = mocked_client mocked_client.list_subnets.return_value = subnets with mock.patch.object( - self.api, '_has_segment_extension', return_value=True + self.api, 'has_segment_extension', return_value=True, ): res = self.api.get_segment_ids_for_network( self.context, uuids.network_id) @@ -6928,7 +6967,7 @@ class TestAPI(TestAPIBase): mocked_client.list_subnets.side_effect = ( exceptions.NeutronClientException(status_code=404)) with mock.patch.object( - self.api, '_has_segment_extension', return_value=True + self.api, 'has_segment_extension', return_value=True, ): self.assertRaises(exception.InvalidRoutedNetworkConfiguration, self.api.get_segment_ids_for_network, @@ -6936,7 +6975,7 @@ class TestAPI(TestAPIBase): def test_get_segment_id_for_subnet_no_segment_ext(self): with mock.patch.object( - self.api, '_has_segment_extension', return_value=False + self.api, 'has_segment_extension', return_value=False, ): self.assertIsNone( self.api.get_segment_id_for_subnet(self.context, @@ -6949,7 +6988,7 @@ class TestAPI(TestAPIBase): mock_client.return_value = mocked_client mocked_client.show_subnet.return_value = subnet with mock.patch.object( - self.api, '_has_segment_extension', return_value=True + self.api, 'has_segment_extension', return_value=True, ): res = self.api.get_segment_id_for_subnet( self.context, uuids.subnet_id) @@ -6963,7 +7002,7 @@ class TestAPI(TestAPIBase): mock_client.return_value = mocked_client mocked_client.show_subnet.return_value = subnet with mock.patch.object( - self.api, '_has_segment_extension', return_value=True + self.api, 'has_segment_extension', return_value=True, ): self.assertIsNone( self.api.get_segment_id_for_subnet(self.context, @@ -6976,7 +7015,7 @@ class TestAPI(TestAPIBase): mocked_client.show_subnet.side_effect = ( exceptions.NeutronClientException(status_code=404)) with mock.patch.object( - self.api, '_has_segment_extension', return_value=True + self.api, 'has_segment_extension', return_value=True, ): self.assertRaises(exception.InvalidRoutedNetworkConfiguration, self.api.get_segment_id_for_subnet, @@ -7176,9 +7215,9 @@ class TestInstanceHasExtendedResourceRequest(TestAPIBase): self.addCleanup(patcher.stop) self.mock_client = patcher.start().return_value self.extension = { - "extensions": [ + 'extensions': [ { - "name": constants.RESOURCE_REQUEST_GROUPS_EXTENSION, + 'alias': constants.RESOURCE_REQUEST_GROUPS, } ] } @@ -7782,6 +7821,9 @@ class TestAPIPortbinding(TestAPIBase): self.api.delete_port_binding(self.context, port_id, 'fake-host') + @mock.patch( + 'nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=False)) @mock.patch('nova.accelerator.cyborg._CyborgClient.delete_arqs_by_uuid') @mock.patch('nova.network.neutron.get_binding_profile') @mock.patch('nova.network.neutron.API._show_port') @@ -8171,7 +8213,7 @@ class TestAllocateForInstance(test.NoDBTestCase): requested_ports_dict = {uuids.port1: {}, uuids.port2: {}} mock_neutron.list_extensions.return_value = {"extensions": [ - {"name": "asdf"}]} + {"alias": "asdf"}]} port1 = {"port": {"id": uuids.port1, "mac_address": "mac1r"}} port2 = {"port": {"id": uuids.port2, "mac_address": "mac2r"}} mock_admin.update_port.side_effect = [port1, port2] @@ -8253,6 +8295,10 @@ class TestAPINeutronHostnameDNSPortbinding(TestAPIBase): bind_host_id=self.instance.get('host'), requested_networks=requested_networks) + @mock.patch( + 'nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=True), + ) @mock.patch( 'nova.network.neutron.API.has_extended_resource_request_extension', new=mock.Mock(return_value=False) @@ -8266,8 +8312,8 @@ class TestAPINeutronHostnameDNSPortbinding(TestAPIBase): 11, dns_extension=True, bind_host_id=self.instance.get('host')) @mock.patch( - "nova.network.neutron.API._has_dns_extension", - new=mock.Mock(return_value=True) + 'nova.network.neutron.API.has_dns_extension', + new=mock.Mock(return_value=True), ) def test_allocate_for_instance_with_requested_port_with_dns_domain(self): # The port's dns_name attribute should be set by the port update diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 45b61220abf5..b77ff1113c77 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -10606,7 +10606,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertEqual(drvr._uri(), testuri) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file') @@ -10645,7 +10645,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, return_value.obj_to_primitive()['nova_object.data']) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file') @@ -10685,7 +10685,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, return_value.obj_to_primitive()['nova_object.data']) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file') @@ -10722,7 +10722,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, return_value.obj_to_primitive()['nova_object.data']) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file', @@ -10754,7 +10754,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, str(result.serial_listen_addr)) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file', @@ -10775,7 +10775,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertIsNone(result.serial_listen_addr) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file', @@ -10808,7 +10808,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, result.obj_to_primitive()['nova_object.data']) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file', @@ -10827,7 +10827,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertTrue(result.dst_supports_numa_live_migration) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file', @@ -10844,7 +10844,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertNotIn('dst_supports_numa_live_migration', result) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file') @@ -10885,7 +10885,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, return_value.obj_to_primitive()['nova_object.data']) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=False)) @mock.patch.object(libvirt_driver.LibvirtDriver, '_create_shared_storage_test_file') @@ -10930,7 +10930,7 @@ class LibvirtConnTestCase(test.NoDBTestCase, compute_info, compute_info, False) @mock.patch( - 'nova.network.neutron.API.supports_port_binding_extension', + 'nova.network.neutron.API.has_port_binding_extension', new=mock.Mock(return_value=True)) @mock.patch.object( libvirt_driver.LibvirtDriver, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index fe73cd9ab8d0..1352d44637da 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -9092,7 +9092,7 @@ class LibvirtDriver(driver.ComputeDriver): # populate it if we are using multiple port bindings. # TODO(stephenfin): Remove once we can do this unconditionally in X or # later - if self._network_api.supports_port_binding_extension(context): + if self._network_api.has_port_binding_extension(context): data.vifs = ( migrate_data_obj.VIFMigrateData.create_skeleton_migrate_vifs( instance.get_network_info()))