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, '
|
LOG.info('Destination was ready for NUMA live migration, '
|
||||||
'but source is either too old, or is set to an '
|
'but source is either too old, or is set to an '
|
||||||
'older upgrade level.', instance=instance)
|
'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.
|
# Create migrate_data vifs if not provided by driver.
|
||||||
if 'vifs' not in migrate_data:
|
if 'vifs' not in migrate_data:
|
||||||
migrate_data.vifs = (
|
migrate_data.vifs = (
|
||||||
|
@ -698,7 +698,7 @@ class CrossCellMigrationTask(base.TaskBase):
|
|||||||
LOG.debug('Making sure neutron is new enough for cross-cell resize.')
|
LOG.debug('Making sure neutron is new enough for cross-cell resize.')
|
||||||
# Check that the port binding-extended API extension is available in
|
# Check that the port binding-extended API extension is available in
|
||||||
# neutron because if it's not we can just fail fast.
|
# 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(
|
raise exception.MigrationPreCheckError(
|
||||||
reason=_("Required networking service API extension '%s' "
|
reason=_("Required networking service API extension '%s' "
|
||||||
"not found.") %
|
"not found.") %
|
||||||
|
@ -245,8 +245,7 @@ class LiveMigrationTask(base.TaskBase):
|
|||||||
"are not allowed for live migration.")
|
"are not allowed for live migration.")
|
||||||
# All PCI requests are VIF related, now check neutron,
|
# All PCI requests are VIF related, now check neutron,
|
||||||
# source and destination compute nodes.
|
# source and destination compute nodes.
|
||||||
if not self.network_api.supports_port_binding_extension(
|
if not self.network_api.has_port_binding_extension(self.context):
|
||||||
self.context):
|
|
||||||
raise exception.MigrationPreCheckError(
|
raise exception.MigrationPreCheckError(
|
||||||
reason="Cannot live migrate VIF with related PCI, Neutron "
|
reason="Cannot live migrate VIF with related PCI, Neutron "
|
||||||
"does not support required port binding extension.")
|
"does not support required port binding extension.")
|
||||||
@ -366,7 +365,7 @@ class LiveMigrationTask(base.TaskBase):
|
|||||||
raise exception.MigrationPreCheckError(msg)
|
raise exception.MigrationPreCheckError(msg)
|
||||||
|
|
||||||
# Check to see that neutron supports the binding-extended API.
|
# 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(
|
bindings = self._bind_ports_on_destination(
|
||||||
destination, provider_mapping)
|
destination, provider_mapping)
|
||||||
self._update_migrate_vifs_from_bindings(self.migrate_data.vifs,
|
self._update_migrate_vifs_from_bindings(self.migrate_data.vifs,
|
||||||
|
@ -13,23 +13,40 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
QOS_QUEUE = 'QoS Queue'
|
# Port fields
|
||||||
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'
|
|
||||||
BINDING_PROFILE = 'binding:profile'
|
BINDING_PROFILE = 'binding:profile'
|
||||||
BINDING_HOST_ID = 'binding:host_id'
|
BINDING_HOST_ID = 'binding:host_id'
|
||||||
MIGRATING_ATTR = 'migrating_to'
|
|
||||||
L3_NETWORK_TYPES = ['vxlan', 'gre', 'geneve']
|
|
||||||
ALLOCATION = 'allocation'
|
|
||||||
RESOURCE_REQUEST = 'resource_request'
|
RESOURCE_REQUEST = 'resource_request'
|
||||||
REQUEST_GROUPS = 'request_groups'
|
REQUEST_GROUPS = 'request_groups'
|
||||||
SEGMENT = 'Segment'
|
|
||||||
NUMA_POLICY = 'numa_affinity_policy'
|
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
|
# If a host was provided, delete any bindings between that
|
||||||
# host and the ports as long as the host isn't the same as
|
# host and the ports as long as the host isn't the same as
|
||||||
# the current instance.host.
|
# 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:
|
if port_migrating and has_binding_ext:
|
||||||
self._delete_port_bindings(context, ports, host)
|
self._delete_port_bindings(context, ports, host)
|
||||||
elif port_migrating:
|
elif port_migrating:
|
||||||
@ -676,8 +677,12 @@ class API:
|
|||||||
# NOTE: For internal DNS integration (network does not have a
|
# NOTE: For internal DNS integration (network does not have a
|
||||||
# dns_domain), or if we cannot retrieve network info, we use the
|
# dns_domain), or if we cannot retrieve network info, we use the
|
||||||
# admin client to reset dns_name.
|
# 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'] = ''
|
port_req_body['port']['dns_name'] = ''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
port_client.update_port(port_id, port_req_body)
|
port_client.update_port(port_id, port_req_body)
|
||||||
except neutron_client_exc.PortNotFoundClient:
|
except neutron_client_exc.PortNotFoundClient:
|
||||||
@ -1334,62 +1339,112 @@ class API:
|
|||||||
return (nets_in_requested_order, ports_in_requested_order,
|
return (nets_in_requested_order, ports_in_requested_order,
|
||||||
preexisting_port_ids, created_port_ids)
|
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."""
|
"""Refresh the neutron extensions cache when necessary."""
|
||||||
if (not self.last_neutron_extension_sync or
|
if (not self.last_neutron_extension_sync or
|
||||||
((time.time() - self.last_neutron_extension_sync) >=
|
((time.time() - self.last_neutron_extension_sync) >=
|
||||||
CONF.neutron.extension_sync_interval)):
|
CONF.neutron.extension_sync_interval)):
|
||||||
if neutron is None:
|
extensions_list = client.list_extensions()['extensions']
|
||||||
neutron = get_client(context)
|
|
||||||
extensions_list = neutron.list_extensions()['extensions']
|
|
||||||
self.last_neutron_extension_sync = time.time()
|
self.last_neutron_extension_sync = time.time()
|
||||||
self.extensions.clear()
|
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):
|
def _has_extension(self, extension, context=None, client=None):
|
||||||
self._refresh_neutron_extensions_cache(context, neutron=neutron)
|
"""Check if the provided neutron extension is enabled.
|
||||||
return constants.MULTI_NET_EXT in self.extensions
|
|
||||||
|
|
||||||
def _has_dns_extension(self):
|
:param extension: The alias of the extension to check
|
||||||
return constants.DNS_INTEGRATION in self.extensions
|
: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(client)
|
||||||
self._refresh_neutron_extensions_cache(context, neutron=neutron)
|
return extension in self.extensions
|
||||||
return constants.QOS_QUEUE in self.extensions
|
|
||||||
|
|
||||||
def _has_fip_port_details_extension(self, context, neutron=None):
|
def has_multi_provider_extension(self, context=None, client=None):
|
||||||
self._refresh_neutron_extensions_cache(context, neutron=neutron)
|
"""Check if the 'multi-provider' extension is enabled.
|
||||||
return constants.FIP_PORT_DETAILS in self.extensions
|
|
||||||
|
|
||||||
def has_substr_port_filtering_extension(self, context):
|
This extension allows administrative users to define multiple physical
|
||||||
self._refresh_neutron_extensions_cache(context)
|
bindings for a logical network.
|
||||||
return constants.SUBSTR_PORT_FILTERING in self.extensions
|
"""
|
||||||
|
return self._has_extension(constants.MULTI_PROVIDER, context, client)
|
||||||
|
|
||||||
def _has_segment_extension(self, context, neutron=None):
|
def has_dns_extension(self, context=None, client=None):
|
||||||
self._refresh_neutron_extensions_cache(context, neutron=neutron)
|
"""Check if the 'dns-integration' extension is enabled.
|
||||||
return constants.SEGMENT in self.extensions
|
|
||||||
|
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
|
# TODO(gibi): Remove all branches where this is False after Neutron made
|
||||||
# the this extension mandatory. In Xena this extension will be optional to
|
# the this extension mandatory. In Xena this extension will be optional to
|
||||||
# support the scenario where Neutron upgraded first. So Neutron can mark
|
# support the scenario where Neutron upgraded first. So Neutron can mark
|
||||||
# this mandatory earliest in Yoga.
|
# this mandatory earliest in Yoga.
|
||||||
def has_extended_resource_request_extension(self, context, neutron=None):
|
def has_extended_resource_request_extension(
|
||||||
self._refresh_neutron_extensions_cache(context, neutron=neutron)
|
self, context=None, client=None,
|
||||||
return constants.RESOURCE_REQUEST_GROUPS_EXTENSION in self.extensions
|
):
|
||||||
|
return self._has_extension(
|
||||||
|
constants.RESOURCE_REQUEST_GROUPS, context, client,
|
||||||
|
)
|
||||||
|
|
||||||
def supports_port_binding_extension(self, context):
|
# TODO(stephenfin): This is optionally used by the XenAPI virt driver, but
|
||||||
"""This is a simple check to see if the neutron "binding-extended"
|
# I can't find what defines it and suspect it's dead code. Consider
|
||||||
extension exists and is enabled.
|
# 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
|
This extension is provided by a XenServer neutron plugin...we think.
|
||||||
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
|
|
||||||
"""
|
"""
|
||||||
self._refresh_neutron_extensions_cache(context)
|
return self._has_extension(constants.QOS_QUEUE, context, client)
|
||||||
return constants.PORT_BINDING_EXTENDED in self.extensions
|
|
||||||
|
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,
|
def bind_ports_to_host(self, context, instance, host,
|
||||||
vnic_types=None, port_profiles=None):
|
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
|
In the event of an error, any ports which were successfully bound to
|
||||||
the host should have those host bindings removed from the ports.
|
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.
|
returns False.
|
||||||
|
|
||||||
:param context: the user request context
|
:param context: the user request context
|
||||||
@ -1482,7 +1537,7 @@ class API:
|
|||||||
def delete_port_binding(self, context, port_id, host):
|
def delete_port_binding(self, context, port_id, host):
|
||||||
"""Delete the port binding for the given port ID and 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.
|
returns False.
|
||||||
|
|
||||||
:param context: The request context for the operation.
|
: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 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()
|
flavor = instance.get_flavor()
|
||||||
rxtx_factor = flavor.get('rxtx_factor')
|
rxtx_factor = flavor.get('rxtx_factor')
|
||||||
port_req_body['port']['rxtx_factor'] = rxtx_factor
|
port_req_body['port']['rxtx_factor'] = rxtx_factor
|
||||||
@ -1612,7 +1670,7 @@ class API:
|
|||||||
port_req_body,
|
port_req_body,
|
||||||
port_arq)
|
port_arq)
|
||||||
|
|
||||||
if self._has_dns_extension():
|
if self.has_dns_extension(client=neutron):
|
||||||
# If the DNS integration extension is enabled in Neutron, most
|
# If the DNS integration extension is enabled in Neutron, most
|
||||||
# ports will get their dns_name attribute set in the port create or
|
# ports will get their dns_name attribute set in the port create or
|
||||||
# update requests in allocate_for_instance. So we just add the
|
# 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
|
an additional update request. Only a very small fraction of ports will
|
||||||
require this additional update request.
|
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:
|
try:
|
||||||
port_req_body = {'port': {'dns_name': instance.hostname}}
|
port_req_body = {'port': {'dns_name': instance.hostname}}
|
||||||
neutron.update_port(port_id, port_req_body)
|
neutron.update_port(port_id, port_req_body)
|
||||||
@ -1650,7 +1709,7 @@ class API:
|
|||||||
'name') % {'hostname': instance.hostname})
|
'name') % {'hostname': instance.hostname})
|
||||||
raise exception.InvalidInput(reason=msg)
|
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
|
"""Reset an instance port dns_name attribute to empty when using
|
||||||
external DNS service.
|
external DNS service.
|
||||||
|
|
||||||
@ -1660,10 +1719,11 @@ class API:
|
|||||||
request with a Neutron client using user's context, so that the DNS
|
request with a Neutron client using user's context, so that the DNS
|
||||||
record can be found under user's zone and domain.
|
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:
|
try:
|
||||||
port_req_body = {'port': {'dns_name': ''}}
|
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:
|
except neutron_client_exc.NeutronClientException:
|
||||||
LOG.exception("Failed to reset dns_name for port %s", port_id)
|
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
|
segments, the first segment that defines a physnet value will be
|
||||||
used for the physnet name.
|
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,
|
network = neutron.show_network(net_id,
|
||||||
fields='segments').get('network')
|
fields='segments').get('network')
|
||||||
segments = network.get('segments', {})
|
segments = network.get('segments', {})
|
||||||
@ -2712,7 +2772,7 @@ class API:
|
|||||||
# ...and retrieve the port details for the same reason, but only if
|
# ...and retrieve the port details for the same reason, but only if
|
||||||
# they're not already there because the fip-port-details extension is
|
# they're not already there because the fip-port-details extension is
|
||||||
# present
|
# 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']
|
port_id = fip['port_id']
|
||||||
try:
|
try:
|
||||||
fip['port_details'] = client.show_port(
|
fip['port_details'] = client.show_port(
|
||||||
@ -2740,7 +2800,7 @@ class API:
|
|||||||
# ...and retrieve the port details for the same reason, but only if
|
# ...and retrieve the port details for the same reason, but only if
|
||||||
# they're not already there because the fip-port-details extension is
|
# they're not already there because the fip-port-details extension is
|
||||||
# present
|
# 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']
|
port_id = fip['port_id']
|
||||||
try:
|
try:
|
||||||
fip['port_details'] = client.show_port(
|
fip['port_details'] = client.show_port(
|
||||||
@ -2779,7 +2839,7 @@ class API:
|
|||||||
# ...and retrieve the port details for the same reason, but only if
|
# ...and retrieve the port details for the same reason, but only if
|
||||||
# they're not already there because the fip-port-details extension is
|
# they're not already there because the fip-port-details extension is
|
||||||
# present
|
# 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(
|
ports = {port['id']: port for port in client.list_ports(
|
||||||
**{'tenant_id': project_id})['ports']}
|
**{'tenant_id': project_id})['ports']}
|
||||||
for fip in fips:
|
for fip in fips:
|
||||||
@ -2975,7 +3035,7 @@ class API:
|
|||||||
:raises: nova.exception.PortBindingActivationFailed if any port binding
|
:raises: nova.exception.PortBindingActivationFailed if any port binding
|
||||||
activation fails
|
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"
|
# If neutron isn't new enough yet for the port "binding-extended"
|
||||||
# API extension, we just no-op. The port binding host will be
|
# API extension, we just no-op. The port binding host will be
|
||||||
# be updated in migrate_instance_finish, which is functionally OK,
|
# be updated in migrate_instance_finish, which is functionally OK,
|
||||||
@ -3501,7 +3561,8 @@ class API:
|
|||||||
:raises: PortBindingDeletionFailed if port binding deletion fails.
|
:raises: PortBindingDeletionFailed if port binding deletion fails.
|
||||||
"""
|
"""
|
||||||
# First check to see if the port binding extension is supported.
|
# 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 "
|
LOG.info("Neutron extension '%s' is not supported; not cleaning "
|
||||||
"up port bindings for host %s.",
|
"up port bindings for host %s.",
|
||||||
constants.PORT_BINDING_EXTENDED, host, instance=instance)
|
constants.PORT_BINDING_EXTENDED, host, instance=instance)
|
||||||
@ -3692,9 +3753,8 @@ class API:
|
|||||||
:param vif: The VIF in question.
|
:param vif: The VIF in question.
|
||||||
:param index: The index on the instance for the VIF.
|
:param index: The index on the instance for the VIF.
|
||||||
"""
|
"""
|
||||||
self._refresh_neutron_extensions_cache(context)
|
neutron = get_client(context)
|
||||||
if constants.VNIC_INDEX_EXT in self.extensions:
|
if self.has_vnic_index_extension(client=neutron):
|
||||||
neutron = get_client(context)
|
|
||||||
port_req_body = {'port': {'vnic_index': index}}
|
port_req_body = {'port': {'vnic_index': index}}
|
||||||
try:
|
try:
|
||||||
neutron.update_port(vif['id'], port_req_body)
|
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
|
either Segment extension isn't enabled in Neutron or if the network
|
||||||
isn't configured for routing.
|
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 []
|
return []
|
||||||
|
|
||||||
client = get_client(context)
|
|
||||||
try:
|
try:
|
||||||
# NOTE(sbauza): We can't use list_segments() directly because the
|
# NOTE(sbauza): We can't use list_segments() directly because the
|
||||||
# API is borked and returns both segments but also segmentation IDs
|
# 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
|
extension isn't enabled in Neutron or the provided subnet doesn't
|
||||||
have segments (if the related network isn't configured for routing)
|
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
|
return None
|
||||||
|
|
||||||
client = get_client(context)
|
|
||||||
try:
|
try:
|
||||||
subnet = client.show_subnet(subnet_id)['subnet']
|
subnet = client.show_subnet(subnet_id)['subnet']
|
||||||
except neutron_client_exc.NeutronClientException as e:
|
except neutron_client_exc.NeutronClientException as e:
|
||||||
|
@ -108,7 +108,7 @@ class TestLiveMigrationWithoutMultiplePortBindings(
|
|||||||
networks=[{'port': self.neutron.port_1['id']}])
|
networks=[{'port': self.neutron.port_1['id']}])
|
||||||
|
|
||||||
self.assertFalse(
|
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
|
# TODO(sean-k-mooney): extend _live_migrate to support passing a host
|
||||||
self.api.post_server_action(
|
self.api.post_server_action(
|
||||||
server['id'],
|
server['id'],
|
||||||
|
@ -146,12 +146,13 @@ class ExtendedResourceRequestNeutronFixture(ResourceRequestNeutronFixture):
|
|||||||
# port_resource_request_groups.py
|
# port_resource_request_groups.py
|
||||||
{
|
{
|
||||||
"updated": "2021-08-02T10:00:00-00:00",
|
"updated": "2021-08-02T10:00:00-00:00",
|
||||||
"name": constants.RESOURCE_REQUEST_GROUPS_EXTENSION,
|
"name": "Port Resource Request Groups",
|
||||||
"links": [],
|
"links": [],
|
||||||
"alias": "port-resource-request-groups",
|
"alias": "port-resource-request-groups",
|
||||||
"description":
|
"description": (
|
||||||
"Support requesting multiple groups of resources and "
|
"Support requesting multiple groups of resources and "
|
||||||
"traits from the same RP subtree in resource_request"
|
"traits from the same RP subtree in resource_request"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return extensions
|
return extensions
|
||||||
|
@ -6066,10 +6066,9 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
return fake_network.fake_get_instance_nw_info(self)
|
return fake_network.fake_get_instance_nw_info(self)
|
||||||
|
|
||||||
self.stub_out('nova.network.neutron.API.get_instance_nw_info', stupid)
|
self.stub_out('nova.network.neutron.API.get_instance_nw_info', stupid)
|
||||||
self.useFixture(
|
self.useFixture(std_fixtures.MonkeyPatch(
|
||||||
std_fixtures.MonkeyPatch(
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
lambda *args: True))
|
||||||
lambda *args: True))
|
|
||||||
# creating instance testdata
|
# creating instance testdata
|
||||||
instance = self._create_fake_instance_obj({'host': 'dummy'})
|
instance = self._create_fake_instance_obj({'host': 'dummy'})
|
||||||
c = context.get_admin_context()
|
c = context.get_admin_context()
|
||||||
|
@ -3460,7 +3460,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
||||||
def test_check_can_live_migrate_destination_success(self):
|
def test_check_can_live_migrate_destination_success(self):
|
||||||
self.useFixture(std_fixtures.MonkeyPatch(
|
self.useFixture(std_fixtures.MonkeyPatch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
lambda *args: True))
|
lambda *args: True))
|
||||||
self._test_check_can_live_migrate_destination()
|
self._test_check_can_live_migrate_destination()
|
||||||
|
|
||||||
@ -3468,7 +3468,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
||||||
def test_check_can_live_migrate_destination_fail(self):
|
def test_check_can_live_migrate_destination_fail(self):
|
||||||
self.useFixture(std_fixtures.MonkeyPatch(
|
self.useFixture(std_fixtures.MonkeyPatch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
lambda *args: True))
|
lambda *args: True))
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
test.TestingException,
|
test.TestingException,
|
||||||
@ -3479,7 +3479,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
||||||
def test_check_can_live_migrate_destination_contains_vifs(self):
|
def test_check_can_live_migrate_destination_contains_vifs(self):
|
||||||
self.useFixture(std_fixtures.MonkeyPatch(
|
self.useFixture(std_fixtures.MonkeyPatch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
lambda *args: True))
|
lambda *args: True))
|
||||||
migrate_data = self._test_check_can_live_migrate_destination()
|
migrate_data = self._test_check_can_live_migrate_destination()
|
||||||
self.assertIn('vifs', migrate_data)
|
self.assertIn('vifs', migrate_data)
|
||||||
@ -3489,7 +3489,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
||||||
def test_check_can_live_migrate_destination_no_binding_extended(self):
|
def test_check_can_live_migrate_destination_no_binding_extended(self):
|
||||||
self.useFixture(std_fixtures.MonkeyPatch(
|
self.useFixture(std_fixtures.MonkeyPatch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
lambda *args: False))
|
lambda *args: False))
|
||||||
migrate_data = self._test_check_can_live_migrate_destination()
|
migrate_data = self._test_check_can_live_migrate_destination()
|
||||||
self.assertNotIn('vifs', migrate_data)
|
self.assertNotIn('vifs', migrate_data)
|
||||||
@ -3498,7 +3498,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
||||||
def test_check_can_live_migrate_destination_src_numa_lm_false(self):
|
def test_check_can_live_migrate_destination_src_numa_lm_false(self):
|
||||||
self.useFixture(std_fixtures.MonkeyPatch(
|
self.useFixture(std_fixtures.MonkeyPatch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
lambda *args: True))
|
lambda *args: True))
|
||||||
self._test_check_can_live_migrate_destination(src_numa_lm=False)
|
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='')))
|
side_effect=exception.InstanceGroupNotFound(group_uuid='')))
|
||||||
def test_check_can_live_migrate_destination_src_numa_lm_true(self):
|
def test_check_can_live_migrate_destination_src_numa_lm_true(self):
|
||||||
self.useFixture(std_fixtures.MonkeyPatch(
|
self.useFixture(std_fixtures.MonkeyPatch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
lambda *args: True))
|
lambda *args: True))
|
||||||
self._test_check_can_live_migrate_destination(src_numa_lm=True)
|
self._test_check_can_live_migrate_destination(src_numa_lm=True)
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ class CrossCellMigrationTaskTestCase(test.NoDBTestCase):
|
|||||||
what we need.
|
what we need.
|
||||||
"""
|
"""
|
||||||
with mock.patch.object(
|
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:
|
return_value=True) as mock_neutron_check:
|
||||||
self.task._perform_external_api_checks()
|
self.task._perform_external_api_checks()
|
||||||
mock_neutron_check.assert_called_once_with(self.task.context)
|
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):
|
def test_perform_external_api_checks_old_neutron(self):
|
||||||
"""Tests the case that neutron API is old."""
|
"""Tests the case that neutron API is old."""
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
self.task.network_api, 'supports_port_binding_extension',
|
self.task.network_api, 'has_port_binding_extension',
|
||||||
return_value=False):
|
return_value=False):
|
||||||
ex = self.assertRaises(exception.MigrationPreCheckError,
|
ex = self.assertRaises(exception.MigrationPreCheckError,
|
||||||
self.task._perform_external_api_checks)
|
self.task._perform_external_api_checks)
|
||||||
|
@ -353,7 +353,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(self.task.network_api,
|
mock.patch.object(self.task.network_api,
|
||||||
'supports_port_binding_extension',
|
'has_port_binding_extension',
|
||||||
return_value=False),
|
return_value=False),
|
||||||
mock.patch.object(self.task, '_check_can_migrate_pci')):
|
mock.patch.object(self.task, '_check_can_migrate_pci')):
|
||||||
self.assertIsNone(self.task._check_requested_destination())
|
self.assertIsNone(self.task._check_requested_destination())
|
||||||
@ -387,7 +387,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(self.task.network_api,
|
mock.patch.object(self.task.network_api,
|
||||||
'supports_port_binding_extension',
|
'has_port_binding_extension',
|
||||||
return_value=False),
|
return_value=False),
|
||||||
mock.patch.object(self.task, '_check_can_migrate_pci')):
|
mock.patch.object(self.task, '_check_can_migrate_pci')):
|
||||||
ex = self.assertRaises(exception.MigrationPreCheckError,
|
ex = self.assertRaises(exception.MigrationPreCheckError,
|
||||||
@ -813,7 +813,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@mock.patch.object(self.task.network_api,
|
@mock.patch.object(self.task.network_api,
|
||||||
'supports_port_binding_extension')
|
'has_port_binding_extension')
|
||||||
@mock.patch.object(live_migrate,
|
@mock.patch.object(live_migrate,
|
||||||
'supports_vif_related_pci_allocations')
|
'supports_vif_related_pci_allocations')
|
||||||
def _test(instance_pci_reqs,
|
def _test(instance_pci_reqs,
|
||||||
|
@ -515,7 +515,11 @@ class TestAPIBase(test.TestCase):
|
|||||||
has_dns_extension = False
|
has_dns_extension = False
|
||||||
if kwargs.get('dns_extension'):
|
if kwargs.get('dns_extension'):
|
||||||
has_dns_extension = True
|
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
|
# Net idx is 1-based for compatibility with existing unit tests
|
||||||
nets = self.nets[net_idx - 1]
|
nets = self.nets[net_idx - 1]
|
||||||
@ -1167,17 +1171,14 @@ class TestAPI(TestAPIBase):
|
|||||||
mock_get_physnet.assert_called_once_with(
|
mock_get_physnet.assert_called_once_with(
|
||||||
mock.ANY, mock.ANY, self.port_data1[0]['network_id'])
|
mock.ANY, mock.ANY, self.port_data1[0]['network_id'])
|
||||||
|
|
||||||
@mock.patch.object(neutronapi, 'get_client')
|
def test_refresh_neutron_extensions_cache(self):
|
||||||
def test_refresh_neutron_extensions_cache(self, mock_get_client):
|
|
||||||
mocked_client = mock.create_autospec(client.Client)
|
mocked_client = mock.create_autospec(client.Client)
|
||||||
mock_get_client.return_value = mocked_client
|
|
||||||
mocked_client.list_extensions.return_value = {
|
mocked_client.list_extensions.return_value = {
|
||||||
'extensions': [{'name': constants.QOS_QUEUE}]}
|
'extensions': [{'alias': constants.QOS_QUEUE}]}
|
||||||
self.api._refresh_neutron_extensions_cache(self.context)
|
self.api._refresh_neutron_extensions_cache(mocked_client)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{constants.QOS_QUEUE: {'name': constants.QOS_QUEUE}},
|
{constants.QOS_QUEUE: {'alias': constants.QOS_QUEUE}},
|
||||||
self.api.extensions)
|
self.api.extensions)
|
||||||
mock_get_client.assert_called_once_with(self.context)
|
|
||||||
mocked_client.list_extensions.assert_called_once_with()
|
mocked_client.list_extensions.assert_called_once_with()
|
||||||
|
|
||||||
@mock.patch.object(neutronapi, 'get_client')
|
@mock.patch.object(neutronapi, 'get_client')
|
||||||
@ -1186,7 +1187,7 @@ class TestAPI(TestAPIBase):
|
|||||||
mocked_client = mock.create_autospec(client.Client)
|
mocked_client = mock.create_autospec(client.Client)
|
||||||
mock_get_client.return_value = mocked_client
|
mock_get_client.return_value = mocked_client
|
||||||
mocked_client.list_extensions.return_value = {
|
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 = objects.Flavor.get_by_name(self.context, 'm1.small')
|
||||||
flavor['rxtx_factor'] = 1
|
flavor['rxtx_factor'] = 1
|
||||||
instance = objects.Instance(system_metadata={})
|
instance = objects.Instance(system_metadata={})
|
||||||
@ -2415,9 +2416,13 @@ class TestAPI(TestAPIBase):
|
|||||||
mock_nc.show_port.side_effect = exceptions.PortNotFoundClient
|
mock_nc.show_port.side_effect = exceptions.PortNotFoundClient
|
||||||
|
|
||||||
if fip_ext_enabled:
|
if fip_ext_enabled:
|
||||||
self.api.extensions = [constants.FIP_PORT_DETAILS]
|
self.api.extensions = {
|
||||||
|
constants.FIP_PORT_DETAILS: {
|
||||||
|
'alias': constants.FIP_PORT_DETAILS,
|
||||||
|
},
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
self.api.extensions = []
|
self.api.extensions = {}
|
||||||
|
|
||||||
fip = self.api.get_floating_ip(self.context, uuids.fip_id)
|
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
|
mock_nc.show_port.side_effect = exceptions.PortNotFoundClient
|
||||||
|
|
||||||
if fip_ext_enabled:
|
if fip_ext_enabled:
|
||||||
self.api.extensions = [constants.FIP_PORT_DETAILS]
|
self.api.extensions = {
|
||||||
|
constants.FIP_PORT_DETAILS: {
|
||||||
|
'alias': constants.FIP_PORT_DETAILS,
|
||||||
|
},
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
self.api.extensions = []
|
self.api.extensions = {}
|
||||||
|
|
||||||
fip = self.api.get_floating_ip_by_address(self.context, '172.1.2.3')
|
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'}]}}
|
'provider:network_type': 'vxlan'}]}}
|
||||||
test_ext_list = {'extensions':
|
test_ext_list = {'extensions':
|
||||||
[{'name': 'Multi Provider Network',
|
[{'name': 'Multi Provider Network',
|
||||||
'alias': 'multi-segments'}]}
|
'alias': 'multi-provider'}]}
|
||||||
|
|
||||||
mock_client = mock_get_client.return_value
|
mock_client = mock_get_client.return_value
|
||||||
mock_client.list_extensions.return_value = test_ext_list
|
mock_client.list_extensions.return_value = test_ext_list
|
||||||
@ -3495,7 +3504,7 @@ class TestAPI(TestAPIBase):
|
|||||||
'provider:network_type': 'vlan'}}
|
'provider:network_type': 'vlan'}}
|
||||||
test_ext_list = {'extensions':
|
test_ext_list = {'extensions':
|
||||||
[{'name': 'Multi Provider Network',
|
[{'name': 'Multi Provider Network',
|
||||||
'alias': 'multi-segments'}]}
|
'alias': 'multi-provider'}]}
|
||||||
|
|
||||||
mock_client = mock_get_client.return_value
|
mock_client = mock_get_client.return_value
|
||||||
mock_client.list_extensions.return_value = test_ext_list
|
mock_client.list_extensions.return_value = test_ext_list
|
||||||
@ -3521,7 +3530,7 @@ class TestAPI(TestAPIBase):
|
|||||||
'provider:network_type': 'vlan'}]}}
|
'provider:network_type': 'vlan'}]}}
|
||||||
test_ext_list = {'extensions':
|
test_ext_list = {'extensions':
|
||||||
[{'name': 'Multi Provider Network',
|
[{'name': 'Multi Provider Network',
|
||||||
'alias': 'multi-segments'}]}
|
'alias': 'multi-provider'}]}
|
||||||
|
|
||||||
mock_client = mock_get_client.return_value
|
mock_client = mock_get_client.return_value
|
||||||
mock_client.list_extensions.return_value = test_ext_list
|
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,
|
def test_update_instance_vnic_index(self, mock_get_client,
|
||||||
mock_refresh_extensions):
|
mock_refresh_extensions):
|
||||||
api = neutronapi.API()
|
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 = mock_get_client.return_value
|
||||||
mock_client.update_port.return_value = 'port'
|
mock_client.update_port.return_value = 'port'
|
||||||
|
|
||||||
@ -4382,7 +4391,7 @@ class TestAPI(TestAPIBase):
|
|||||||
self, get_client_mock
|
self, get_client_mock
|
||||||
):
|
):
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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
|
# We pass in a port profile which has a migration attribute and also
|
||||||
# a second port profile attribute 'fake_profile' this can be
|
# a second port profile attribute 'fake_profile' this can be
|
||||||
@ -4426,7 +4435,7 @@ class TestAPI(TestAPIBase):
|
|||||||
value is None.
|
value is None.
|
||||||
"""
|
"""
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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': [
|
fake_ports = {'ports': [
|
||||||
{'id': uuids.portid,
|
{'id': uuids.portid,
|
||||||
@ -4602,7 +4611,7 @@ class TestAPI(TestAPIBase):
|
|||||||
def test_update_port_bindings_for_instance_with_pci_no_migration(self,
|
def test_update_port_bindings_for_instance_with_pci_no_migration(self,
|
||||||
get_client_mock,
|
get_client_mock,
|
||||||
get_pci_device_devspec_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 = mock.Mock()
|
||||||
devspec.get_tags.return_value = {'physical_network': 'physnet1'}
|
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(
|
def test_update_port_bindings_for_instance_with_same_host_failed_vif_type(
|
||||||
self, get_client_mock):
|
self, get_client_mock):
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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()
|
list_ports_mock = mock.Mock()
|
||||||
update_port_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(
|
def test_update_port_bindings_for_instance_with_diff_host_unbound_vif_type(
|
||||||
self, get_client_mock):
|
self, get_client_mock):
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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',
|
binding_profile = {'fake_profile': 'fake_data',
|
||||||
constants.MIGRATING_ATTR: 'my-dest-host'}
|
constants.MIGRATING_ATTR: 'my-dest-host'}
|
||||||
@ -4987,7 +4996,7 @@ class TestAPI(TestAPIBase):
|
|||||||
self, get_client_mock):
|
self, get_client_mock):
|
||||||
|
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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
|
# We test with an instance host and destination_host where the
|
||||||
# port will be moving.
|
# port will be moving.
|
||||||
get_ports = {'ports': [
|
get_ports = {'ports': [
|
||||||
@ -5017,7 +5026,7 @@ class TestAPI(TestAPIBase):
|
|||||||
destination host and the binding:profile is None in the port.
|
destination host and the binding:profile is None in the port.
|
||||||
"""
|
"""
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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
|
# We test with an instance host and destination_host where the
|
||||||
# port will be moving but with binding:profile set to None.
|
# port will be moving but with binding:profile set to None.
|
||||||
get_ports = {
|
get_ports = {
|
||||||
@ -5048,7 +5057,7 @@ class TestAPI(TestAPIBase):
|
|||||||
self, get_client_mock):
|
self, get_client_mock):
|
||||||
|
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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
|
port_id = uuids.port_id
|
||||||
get_ports = {'ports': [
|
get_ports = {'ports': [
|
||||||
{'id': port_id,
|
{'id': port_id,
|
||||||
@ -5068,7 +5077,7 @@ class TestAPI(TestAPIBase):
|
|||||||
self, get_client_mock):
|
self, get_client_mock):
|
||||||
|
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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': [
|
get_ports = {'ports': [
|
||||||
{'id': uuids.port_id,
|
{'id': uuids.port_id,
|
||||||
constants.BINDING_HOST_ID: instance.host}]}
|
constants.BINDING_HOST_ID: instance.host}]}
|
||||||
@ -5104,7 +5113,7 @@ class TestAPI(TestAPIBase):
|
|||||||
self, get_client_mock):
|
self, get_client_mock):
|
||||||
|
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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 = {
|
migrate_profile = {
|
||||||
constants.MIGRATING_ATTR: 'new-host'}
|
constants.MIGRATING_ATTR: 'new-host'}
|
||||||
# Pass a port with an migration porfile attribute.
|
# 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)
|
self.api.list_ports = mock.Mock(return_value=get_ports)
|
||||||
mocked_client = get_client_mock.return_value
|
mocked_client = get_client_mock.return_value
|
||||||
|
|
||||||
with mock.patch.object(self.api, 'supports_port_binding_extension',
|
with mock.patch.object(
|
||||||
return_value=True):
|
self.api, 'has_port_binding_extension', return_value=True,
|
||||||
|
):
|
||||||
self.api.setup_networks_on_host(self.context,
|
self.api.setup_networks_on_host(self.context,
|
||||||
instance,
|
instance,
|
||||||
host='new-host',
|
host='new-host',
|
||||||
@ -5135,7 +5145,7 @@ class TestAPI(TestAPIBase):
|
|||||||
which is raised through to the caller.
|
which is raised through to the caller.
|
||||||
"""
|
"""
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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 = {
|
migrate_profile = {
|
||||||
constants.MIGRATING_ATTR: 'new-host'}
|
constants.MIGRATING_ATTR: 'new-host'}
|
||||||
# Pass a port with an migration porfile attribute.
|
# Pass a port with an migration porfile attribute.
|
||||||
@ -5153,8 +5163,9 @@ class TestAPI(TestAPIBase):
|
|||||||
mocked_client = get_client_mock.return_value
|
mocked_client = get_client_mock.return_value
|
||||||
mocked_client.delete_port_binding.side_effect = NeutronError
|
mocked_client.delete_port_binding.side_effect = NeutronError
|
||||||
|
|
||||||
with mock.patch.object(self.api, 'supports_port_binding_extension',
|
with mock.patch.object(
|
||||||
return_value=True):
|
self.api, 'has_port_binding_extension', return_value=True,
|
||||||
|
):
|
||||||
ex = self.assertRaises(
|
ex = self.assertRaises(
|
||||||
exception.PortBindingDeletionFailed,
|
exception.PortBindingDeletionFailed,
|
||||||
self.api.setup_networks_on_host,
|
self.api.setup_networks_on_host,
|
||||||
@ -5176,7 +5187,7 @@ class TestAPI(TestAPIBase):
|
|||||||
self, get_client_mock):
|
self, get_client_mock):
|
||||||
|
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
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.
|
# Pass a port without any migration porfile attribute.
|
||||||
get_ports = {'ports': [
|
get_ports = {'ports': [
|
||||||
{'id': uuids.port_id,
|
{'id': uuids.port_id,
|
||||||
@ -5184,7 +5195,7 @@ class TestAPI(TestAPIBase):
|
|||||||
self.api.list_ports = mock.Mock(return_value=get_ports)
|
self.api.list_ports = mock.Mock(return_value=get_ports)
|
||||||
update_port_mock = mock.Mock()
|
update_port_mock = mock.Mock()
|
||||||
get_client_mock.return_value.update_port = update_port_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):
|
return_value=False):
|
||||||
self.api.setup_networks_on_host(self.context,
|
self.api.setup_networks_on_host(self.context,
|
||||||
instance,
|
instance,
|
||||||
@ -5242,6 +5253,8 @@ class TestAPI(TestAPIBase):
|
|||||||
def test_unbind_ports_get_client(self, mock_neutron):
|
def test_unbind_ports_get_client(self, mock_neutron):
|
||||||
self._test_unbind_ports_get_client(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')
|
@mock.patch('nova.network.neutron.API._show_port')
|
||||||
def _test_unbind_ports(self, mock_neutron, mock_show):
|
def _test_unbind_ports(self, mock_neutron, mock_show):
|
||||||
mock_client = mock.Mock()
|
mock_client = mock.Mock()
|
||||||
@ -5284,7 +5297,11 @@ class TestAPI(TestAPIBase):
|
|||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.has_extended_resource_request_extension',
|
'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.API.get_instance_nw_info')
|
||||||
@mock.patch('nova.network.neutron.excutils')
|
@mock.patch('nova.network.neutron.excutils')
|
||||||
@ -5827,9 +5844,13 @@ class TestAPI(TestAPIBase):
|
|||||||
mock_nc.list_ports.return_value = {'ports': []}
|
mock_nc.list_ports.return_value = {'ports': []}
|
||||||
|
|
||||||
if fip_ext_enabled:
|
if fip_ext_enabled:
|
||||||
self.api.extensions = [constants.FIP_PORT_DETAILS]
|
self.api.extensions = {
|
||||||
|
constants.FIP_PORT_DETAILS: {
|
||||||
|
'alias': constants.FIP_PORT_DETAILS,
|
||||||
|
},
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
self.api.extensions = []
|
self.api.extensions = {}
|
||||||
|
|
||||||
fips = self.api.get_floating_ips_by_project(self.context)
|
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."""
|
"""Make sure we don't fail for floating IPs without attached ports."""
|
||||||
self._test_get_floating_ips_by_project(False, False)
|
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')
|
@mock.patch('nova.network.neutron.API._show_port')
|
||||||
def test_unbind_ports_reset_dns_name_by_admin(self, mock_show):
|
def test_unbind_ports_reset_dns_name_by_admin(self, mock_show):
|
||||||
neutron = mock.Mock()
|
neutron = mock.Mock()
|
||||||
@ -5872,7 +5895,6 @@ class TestAPI(TestAPIBase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
port_client = mock.Mock()
|
port_client = mock.Mock()
|
||||||
self.api.extensions = [constants.DNS_INTEGRATION]
|
|
||||||
ports = [uuids.port_id]
|
ports = [uuids.port_id]
|
||||||
mock_show.return_value = {'id': uuids.port}
|
mock_show.return_value = {'id': uuids.port}
|
||||||
self.api._unbind_ports(self.context, ports, neutron, port_client)
|
self.api._unbind_ports(self.context, ports, neutron, port_client)
|
||||||
@ -5885,6 +5907,8 @@ class TestAPI(TestAPIBase):
|
|||||||
uuids.port_id, port_req_body)
|
uuids.port_id, port_req_body)
|
||||||
neutron.update_port.assert_not_called()
|
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')
|
@mock.patch('nova.network.neutron.API._show_port')
|
||||||
def test_unbind_ports_reset_dns_name_by_non_admin(self, mock_show):
|
def test_unbind_ports_reset_dns_name_by_non_admin(self, mock_show):
|
||||||
neutron = mock.Mock()
|
neutron = mock.Mock()
|
||||||
@ -5895,7 +5919,6 @@ class TestAPI(TestAPIBase):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
port_client = mock.Mock()
|
port_client = mock.Mock()
|
||||||
self.api.extensions = [constants.DNS_INTEGRATION]
|
|
||||||
ports = [uuids.port_id]
|
ports = [uuids.port_id]
|
||||||
mock_show.return_value = {'id': uuids.port}
|
mock_show.return_value = {'id': uuids.port}
|
||||||
self.api._unbind_ports(self.context, ports, neutron, port_client)
|
self.api._unbind_ports(self.context, ports, neutron, port_client)
|
||||||
@ -5909,6 +5932,8 @@ class TestAPI(TestAPIBase):
|
|||||||
neutron.update_port.assert_called_once_with(
|
neutron.update_port.assert_called_once_with(
|
||||||
uuids.port_id, non_admin_port_req_body)
|
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')
|
@mock.patch('nova.network.neutron.API._show_port')
|
||||||
def test_unbind_ports_reset_allocation_in_port_binding(self, mock_show):
|
def test_unbind_ports_reset_allocation_in_port_binding(self, mock_show):
|
||||||
neutron = mock.Mock()
|
neutron = mock.Mock()
|
||||||
@ -5924,6 +5949,8 @@ class TestAPI(TestAPIBase):
|
|||||||
port_client.update_port.assert_called_once_with(
|
port_client.update_port.assert_called_once_with(
|
||||||
uuids.port_id, port_req_body)
|
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')
|
@mock.patch('nova.network.neutron.API._show_port')
|
||||||
def test_unbind_ports_reset_binding_profile(self, mock_show):
|
def test_unbind_ports_reset_binding_profile(self, mock_show):
|
||||||
neutron = mock.Mock()
|
neutron = mock.Mock()
|
||||||
@ -5947,6 +5974,8 @@ class TestAPI(TestAPIBase):
|
|||||||
port_client.update_port.assert_called_once_with(
|
port_client.update_port.assert_called_once_with(
|
||||||
uuids.port_id, port_req_body)
|
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._populate_neutron_extension_values')
|
||||||
@mock.patch('nova.network.neutron.API._update_port',
|
@mock.patch('nova.network.neutron.API._update_port',
|
||||||
# called twice, fails on the 2nd call and triggers the cleanup
|
# called twice, fails on the 2nd call and triggers the cleanup
|
||||||
@ -6028,6 +6057,8 @@ class TestAPI(TestAPIBase):
|
|||||||
neutron_client=mock.ANY)
|
neutron_client=mock.ANY)
|
||||||
mock_log.assert_not_called()
|
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('nova.network.neutron.API._show_port',
|
||||||
side_effect=Exception)
|
side_effect=Exception)
|
||||||
@mock.patch.object(neutronapi.LOG, 'exception')
|
@mock.patch.object(neutronapi.LOG, 'exception')
|
||||||
@ -6045,6 +6076,8 @@ class TestAPI(TestAPIBase):
|
|||||||
'binding:profile': {}, 'binding:host_id': None}})
|
'binding:profile': {}, 'binding:host_id': None}})
|
||||||
self.assertTrue(mock_log.called)
|
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('nova.network.neutron.API._show_port')
|
||||||
@mock.patch.object(neutronapi.LOG, 'exception')
|
@mock.patch.object(neutronapi.LOG, 'exception')
|
||||||
def test_unbind_ports_portnotfound(self, mock_log, mock_show):
|
def test_unbind_ports_portnotfound(self, mock_log, mock_show):
|
||||||
@ -6061,6 +6094,8 @@ class TestAPI(TestAPIBase):
|
|||||||
'binding:profile': {}, 'binding:host_id': None}})
|
'binding:profile': {}, 'binding:host_id': None}})
|
||||||
mock_log.assert_not_called()
|
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('nova.network.neutron.API._show_port')
|
||||||
@mock.patch.object(neutronapi.LOG, 'exception')
|
@mock.patch.object(neutronapi.LOG, 'exception')
|
||||||
def test_unbind_ports_unexpected_error(self, mock_log, mock_show):
|
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
|
"""Tests that migrate_instance_start exits early if neutron doesn't
|
||||||
have the binding-extended API extension.
|
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):
|
return_value=False):
|
||||||
self.api.migrate_instance_start(
|
self.api.migrate_instance_start(
|
||||||
self.context, mock.sentinel.instance, {})
|
self.context, mock.sentinel.instance, {})
|
||||||
@ -6696,8 +6731,9 @@ class TestAPI(TestAPIBase):
|
|||||||
migration = objects.Migration(
|
migration = objects.Migration(
|
||||||
source_compute='source', dest_compute='dest')
|
source_compute='source', dest_compute='dest')
|
||||||
|
|
||||||
with mock.patch.object(self.api, 'supports_port_binding_extension',
|
with mock.patch.object(
|
||||||
return_value=True):
|
self.api, 'has_port_binding_extension', return_value=True,
|
||||||
|
):
|
||||||
self.api.migrate_instance_start(
|
self.api.migrate_instance_start(
|
||||||
self.context, instance, migration)
|
self.context, instance, migration)
|
||||||
|
|
||||||
@ -6721,8 +6757,9 @@ class TestAPI(TestAPIBase):
|
|||||||
migration = objects.Migration(
|
migration = objects.Migration(
|
||||||
source_compute='source', dest_compute='dest')
|
source_compute='source', dest_compute='dest')
|
||||||
|
|
||||||
with mock.patch.object(self.api, 'supports_port_binding_extension',
|
with mock.patch.object(
|
||||||
return_value=True):
|
self.api, 'has_port_binding_extension', return_value=True,
|
||||||
|
):
|
||||||
self.api.migrate_instance_start(
|
self.api.migrate_instance_start(
|
||||||
self.context, instance, migration)
|
self.context, instance, migration)
|
||||||
|
|
||||||
@ -6748,8 +6785,9 @@ class TestAPI(TestAPIBase):
|
|||||||
migration = objects.Migration(
|
migration = objects.Migration(
|
||||||
source_compute='source', dest_compute='dest')
|
source_compute='source', dest_compute='dest')
|
||||||
|
|
||||||
with mock.patch.object(self.api, 'supports_port_binding_extension',
|
with mock.patch.object(
|
||||||
return_value=True):
|
self.api, 'has_port_binding_extension', return_value=True,
|
||||||
|
):
|
||||||
self.api.migrate_instance_start(
|
self.api.migrate_instance_start(
|
||||||
self.context, instance, migration)
|
self.context, instance, migration)
|
||||||
|
|
||||||
@ -6772,8 +6810,9 @@ class TestAPI(TestAPIBase):
|
|||||||
migration = objects.Migration(
|
migration = objects.Migration(
|
||||||
source_compute='source', dest_compute='dest')
|
source_compute='source', dest_compute='dest')
|
||||||
|
|
||||||
with mock.patch.object(self.api, 'supports_port_binding_extension',
|
with mock.patch.object(
|
||||||
return_value=True):
|
self.api, 'has_port_binding_extension', return_value=True,
|
||||||
|
):
|
||||||
self.api.migrate_instance_start(
|
self.api.migrate_instance_start(
|
||||||
self.context, instance, migration)
|
self.context, instance, migration)
|
||||||
|
|
||||||
@ -6952,7 +6991,7 @@ class TestAPI(TestAPIBase):
|
|||||||
|
|
||||||
def test_get_segment_ids_for_network_no_segment_ext(self):
|
def test_get_segment_ids_for_network_no_segment_ext(self):
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
self.api, '_has_segment_extension', return_value=False
|
self.api, 'has_segment_extension', return_value=False,
|
||||||
):
|
):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[], self.api.get_segment_ids_for_network(self.context,
|
[], self.api.get_segment_ids_for_network(self.context,
|
||||||
@ -6965,7 +7004,7 @@ class TestAPI(TestAPIBase):
|
|||||||
mock_client.return_value = mocked_client
|
mock_client.return_value = mocked_client
|
||||||
mocked_client.list_subnets.return_value = subnets
|
mocked_client.list_subnets.return_value = subnets
|
||||||
with mock.patch.object(
|
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(
|
res = self.api.get_segment_ids_for_network(
|
||||||
self.context, uuids.network_id)
|
self.context, uuids.network_id)
|
||||||
@ -6980,7 +7019,7 @@ class TestAPI(TestAPIBase):
|
|||||||
mock_client.return_value = mocked_client
|
mock_client.return_value = mocked_client
|
||||||
mocked_client.list_subnets.return_value = subnets
|
mocked_client.list_subnets.return_value = subnets
|
||||||
with mock.patch.object(
|
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(
|
res = self.api.get_segment_ids_for_network(
|
||||||
self.context, uuids.network_id)
|
self.context, uuids.network_id)
|
||||||
@ -6995,7 +7034,7 @@ class TestAPI(TestAPIBase):
|
|||||||
mocked_client.list_subnets.side_effect = (
|
mocked_client.list_subnets.side_effect = (
|
||||||
exceptions.NeutronClientException(status_code=404))
|
exceptions.NeutronClientException(status_code=404))
|
||||||
with mock.patch.object(
|
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.assertRaises(exception.InvalidRoutedNetworkConfiguration,
|
||||||
self.api.get_segment_ids_for_network,
|
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):
|
def test_get_segment_id_for_subnet_no_segment_ext(self):
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
self.api, '_has_segment_extension', return_value=False
|
self.api, 'has_segment_extension', return_value=False,
|
||||||
):
|
):
|
||||||
self.assertIsNone(
|
self.assertIsNone(
|
||||||
self.api.get_segment_id_for_subnet(self.context,
|
self.api.get_segment_id_for_subnet(self.context,
|
||||||
@ -7016,7 +7055,7 @@ class TestAPI(TestAPIBase):
|
|||||||
mock_client.return_value = mocked_client
|
mock_client.return_value = mocked_client
|
||||||
mocked_client.show_subnet.return_value = subnet
|
mocked_client.show_subnet.return_value = subnet
|
||||||
with mock.patch.object(
|
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(
|
res = self.api.get_segment_id_for_subnet(
|
||||||
self.context, uuids.subnet_id)
|
self.context, uuids.subnet_id)
|
||||||
@ -7030,7 +7069,7 @@ class TestAPI(TestAPIBase):
|
|||||||
mock_client.return_value = mocked_client
|
mock_client.return_value = mocked_client
|
||||||
mocked_client.show_subnet.return_value = subnet
|
mocked_client.show_subnet.return_value = subnet
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
self.api, '_has_segment_extension', return_value=True
|
self.api, 'has_segment_extension', return_value=True,
|
||||||
):
|
):
|
||||||
self.assertIsNone(
|
self.assertIsNone(
|
||||||
self.api.get_segment_id_for_subnet(self.context,
|
self.api.get_segment_id_for_subnet(self.context,
|
||||||
@ -7043,7 +7082,7 @@ class TestAPI(TestAPIBase):
|
|||||||
mocked_client.show_subnet.side_effect = (
|
mocked_client.show_subnet.side_effect = (
|
||||||
exceptions.NeutronClientException(status_code=404))
|
exceptions.NeutronClientException(status_code=404))
|
||||||
with mock.patch.object(
|
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.assertRaises(exception.InvalidRoutedNetworkConfiguration,
|
||||||
self.api.get_segment_id_for_subnet,
|
self.api.get_segment_id_for_subnet,
|
||||||
@ -7251,9 +7290,9 @@ class TestInstanceHasExtendedResourceRequest(TestAPIBase):
|
|||||||
self.addCleanup(patcher.stop)
|
self.addCleanup(patcher.stop)
|
||||||
self.mock_client = patcher.start().return_value
|
self.mock_client = patcher.start().return_value
|
||||||
self.extension = {
|
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,
|
self.api.delete_port_binding(self.context, port_id,
|
||||||
'fake-host')
|
'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.accelerator.cyborg._CyborgClient.delete_arqs_by_uuid')
|
||||||
@mock.patch('nova.network.neutron.get_binding_profile')
|
@mock.patch('nova.network.neutron.get_binding_profile')
|
||||||
@mock.patch('nova.network.neutron.API._show_port')
|
@mock.patch('nova.network.neutron.API._show_port')
|
||||||
@ -8290,7 +8332,7 @@ class TestAllocateForInstance(test.NoDBTestCase):
|
|||||||
requested_ports_dict = {uuids.port1: {}, uuids.port2: {}}
|
requested_ports_dict = {uuids.port1: {}, uuids.port2: {}}
|
||||||
|
|
||||||
mock_neutron.list_extensions.return_value = {"extensions": [
|
mock_neutron.list_extensions.return_value = {"extensions": [
|
||||||
{"name": "asdf"}]}
|
{"alias": "asdf"}]}
|
||||||
port1 = {"port": {"id": uuids.port1, "mac_address": "mac1r"}}
|
port1 = {"port": {"id": uuids.port1, "mac_address": "mac1r"}}
|
||||||
port2 = {"port": {"id": uuids.port2, "mac_address": "mac2r"}}
|
port2 = {"port": {"id": uuids.port2, "mac_address": "mac2r"}}
|
||||||
mock_admin.update_port.side_effect = [port1, port2]
|
mock_admin.update_port.side_effect = [port1, port2]
|
||||||
@ -8372,6 +8414,10 @@ class TestAPINeutronHostnameDNSPortbinding(TestAPIBase):
|
|||||||
bind_host_id=self.instance.get('host'),
|
bind_host_id=self.instance.get('host'),
|
||||||
requested_networks=requested_networks)
|
requested_networks=requested_networks)
|
||||||
|
|
||||||
|
@mock.patch(
|
||||||
|
'nova.network.neutron.API.has_dns_extension',
|
||||||
|
new=mock.Mock(return_value=True),
|
||||||
|
)
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.has_extended_resource_request_extension',
|
'nova.network.neutron.API.has_extended_resource_request_extension',
|
||||||
new=mock.Mock(return_value=False)
|
new=mock.Mock(return_value=False)
|
||||||
@ -8385,8 +8431,8 @@ class TestAPINeutronHostnameDNSPortbinding(TestAPIBase):
|
|||||||
11, dns_extension=True, bind_host_id=self.instance.get('host'))
|
11, dns_extension=True, bind_host_id=self.instance.get('host'))
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
"nova.network.neutron.API._has_dns_extension",
|
'nova.network.neutron.API.has_dns_extension',
|
||||||
new=mock.Mock(return_value=True)
|
new=mock.Mock(return_value=True),
|
||||||
)
|
)
|
||||||
def test_allocate_for_instance_with_requested_port_with_dns_domain(self):
|
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
|
# 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)
|
self.assertEqual(drvr._uri(), testuri)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file')
|
'_create_shared_storage_test_file')
|
||||||
@ -10645,7 +10645,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
return_value.obj_to_primitive()['nova_object.data'])
|
return_value.obj_to_primitive()['nova_object.data'])
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file')
|
'_create_shared_storage_test_file')
|
||||||
@ -10685,7 +10685,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
return_value.obj_to_primitive()['nova_object.data'])
|
return_value.obj_to_primitive()['nova_object.data'])
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file')
|
'_create_shared_storage_test_file')
|
||||||
@ -10722,7 +10722,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
return_value.obj_to_primitive()['nova_object.data'])
|
return_value.obj_to_primitive()['nova_object.data'])
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file',
|
'_create_shared_storage_test_file',
|
||||||
@ -10754,7 +10754,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
str(result.serial_listen_addr))
|
str(result.serial_listen_addr))
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file',
|
'_create_shared_storage_test_file',
|
||||||
@ -10775,7 +10775,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
self.assertIsNone(result.serial_listen_addr)
|
self.assertIsNone(result.serial_listen_addr)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file',
|
'_create_shared_storage_test_file',
|
||||||
@ -10808,7 +10808,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
result.obj_to_primitive()['nova_object.data'])
|
result.obj_to_primitive()['nova_object.data'])
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file',
|
'_create_shared_storage_test_file',
|
||||||
@ -10827,7 +10827,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
self.assertTrue(result.dst_supports_numa_live_migration)
|
self.assertTrue(result.dst_supports_numa_live_migration)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file',
|
'_create_shared_storage_test_file',
|
||||||
@ -10844,7 +10844,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
self.assertNotIn('dst_supports_numa_live_migration', result)
|
self.assertNotIn('dst_supports_numa_live_migration', result)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file')
|
'_create_shared_storage_test_file')
|
||||||
@ -10885,7 +10885,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
return_value.obj_to_primitive()['nova_object.data'])
|
return_value.obj_to_primitive()['nova_object.data'])
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=False))
|
new=mock.Mock(return_value=False))
|
||||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||||
'_create_shared_storage_test_file')
|
'_create_shared_storage_test_file')
|
||||||
@ -10930,7 +10930,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
compute_info, compute_info, False)
|
compute_info, compute_info, False)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.network.neutron.API.supports_port_binding_extension',
|
'nova.network.neutron.API.has_port_binding_extension',
|
||||||
new=mock.Mock(return_value=True))
|
new=mock.Mock(return_value=True))
|
||||||
@mock.patch.object(
|
@mock.patch.object(
|
||||||
libvirt_driver.LibvirtDriver,
|
libvirt_driver.LibvirtDriver,
|
||||||
|
@ -9161,7 +9161,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
# populate it if we are using multiple port bindings.
|
# populate it if we are using multiple port bindings.
|
||||||
# TODO(stephenfin): Remove once we can do this unconditionally in X or
|
# TODO(stephenfin): Remove once we can do this unconditionally in X or
|
||||||
# later
|
# later
|
||||||
if self._network_api.supports_port_binding_extension(context):
|
if self._network_api.has_port_binding_extension(context):
|
||||||
data.vifs = (
|
data.vifs = (
|
||||||
migrate_data_obj.VIFMigrateData.create_skeleton_migrate_vifs(
|
migrate_data_obj.VIFMigrateData.create_skeleton_migrate_vifs(
|
||||||
instance.get_network_info()))
|
instance.get_network_info()))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user