Merge "neutron: Rework how we check for extensions"
This commit is contained in:
commit
f7fa3bf5fc
@ -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 = (
|
||||
|
@ -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.") %
|
||||
|
@ -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,
|
||||
|
@ -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']
|
||||
|
@ -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:
|
||||
|
@ -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'],
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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()))
|
||||
|
Loading…
x
Reference in New Issue
Block a user