Merge "neutron: Rework how we check for extensions"

This commit is contained in:
Zuul 2022-02-08 22:56:47 +00:00 committed by Gerrit Code Review
commit f7fa3bf5fc
14 changed files with 294 additions and 170 deletions

View File

@ -8046,7 +8046,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 = (

View File

@ -698,7 +698,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.") %

View File

@ -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,

View File

@ -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']

View File

@ -382,7 +382,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:
@ -676,8 +677,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:
@ -1334,62 +1339,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):
@ -1403,7 +1458,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
@ -1482,7 +1537,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.
@ -1602,7 +1657,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
@ -1612,7 +1670,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
@ -1638,7 +1696,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)
@ -1650,7 +1709,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.
@ -1660,10 +1719,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)
@ -2037,7 +2097,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', {})
@ -2712,7 +2772,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(
@ -2740,7 +2800,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(
@ -2779,7 +2839,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:
@ -2975,7 +3035,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,
@ -3501,7 +3561,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)
@ -3692,9 +3753,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)
@ -3717,10 +3777,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
@ -3747,10 +3808,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:

View File

@ -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'],

View File

@ -146,12 +146,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

View File

@ -6066,10 +6066,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()

View File

@ -3460,7 +3460,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()
@ -3468,7 +3468,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,
@ -3479,7 +3479,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)
@ -3489,7 +3489,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)
@ -3498,7 +3498,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)
@ -3506,7 +3506,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)

View File

@ -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)

View File

@ -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,

View File

@ -515,7 +515,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]
@ -1167,17 +1171,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')
@ -1186,7 +1187,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={})
@ -2415,9 +2416,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)
@ -2490,9 +2495,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')
@ -3474,7 +3483,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
@ -3495,7 +3504,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
@ -3521,7 +3530,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
@ -4357,7 +4366,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'
@ -4382,7 +4391,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
@ -4426,7 +4435,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,
@ -4602,7 +4611,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'}
@ -4652,7 +4661,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()
@ -4697,7 +4706,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'}
@ -4987,7 +4996,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': [
@ -5017,7 +5026,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 = {
@ -5048,7 +5057,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,
@ -5068,7 +5077,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}]}
@ -5104,7 +5113,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.
@ -5116,8 +5125,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',
@ -5135,7 +5145,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.
@ -5153,8 +5163,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,
@ -5176,7 +5187,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,
@ -5184,7 +5195,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,
@ -5242,6 +5253,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()
@ -5284,7 +5297,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')
@ -5827,9 +5844,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)
@ -5862,6 +5883,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()
@ -5872,7 +5895,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)
@ -5885,6 +5907,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()
@ -5895,7 +5919,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)
@ -5909,6 +5932,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()
@ -5924,6 +5949,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()
@ -5947,6 +5974,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
@ -6028,6 +6057,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')
@ -6045,6 +6076,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):
@ -6061,6 +6094,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):
@ -6676,7 +6711,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, {})
@ -6696,8 +6731,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)
@ -6721,8 +6757,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)
@ -6748,8 +6785,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)
@ -6772,8 +6810,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)
@ -6952,7 +6991,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,
@ -6965,7 +7004,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)
@ -6980,7 +7019,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)
@ -6995,7 +7034,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,
@ -7003,7 +7042,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,
@ -7016,7 +7055,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)
@ -7030,7 +7069,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,
@ -7043,7 +7082,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,
@ -7251,9 +7290,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,
}
]
}
@ -7901,6 +7940,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')
@ -8290,7 +8332,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]
@ -8372,6 +8414,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)
@ -8385,8 +8431,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

View File

@ -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,

View File

@ -9161,7 +9161,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()))