Always pass device_owner to _ipam_get_subnets()
There was one code path where the existing device_owner
value, which is used for subnet selection when service_type's
are in use was not passed to _imap_get_subnets(). This could
trigger one of two exceptions - HostNotCompatibleWithFixedIps()
or IpAddressGenerationFailureNoMatchingSubnet() depending
on the environment. Pass it along if known.
Also update the IpAddressGenerationFailureNoMatchingSubnet
exception to print the network_id and service_type values since
it could aid in debugging the problem quicker.
Change-Id: Ic13901b92cac05e8ddf1092b66aa5bcc5623fa8a
Closes-bug: #1637366
(cherry picked from commit 0d4889df41
)
This commit is contained in:
parent
fb3f718061
commit
5b7a1f85b3
@ -692,7 +692,8 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
|
||||
# subnets. Happens on routed networks when host isn't known.
|
||||
raise ipam_exceptions.DeferIpam()
|
||||
|
||||
raise ipam_exceptions.IpAddressGenerationFailureNoMatchingSubnet()
|
||||
raise ipam_exceptions.IpAddressGenerationFailureNoMatchingSubnet(
|
||||
network_id=network_id, service_type=service_type)
|
||||
|
||||
def _find_candidate_subnets(self, context, network_id, host, service_type,
|
||||
fixed_configured):
|
||||
@ -773,7 +774,8 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
|
||||
new_host_requested = host and host != old_host
|
||||
if old_ips and new_host_requested and not fixed_ips_requested:
|
||||
valid_subnets = self._ipam_get_subnets(
|
||||
context, old_port['network_id'], host)
|
||||
context, old_port['network_id'], host,
|
||||
service_type=old_port.get('device_owner'))
|
||||
valid_subnet_ids = {s['id'] for s in valid_subnets}
|
||||
for fixed_ip in old_ips:
|
||||
if fixed_ip['subnet_id'] not in valid_subnet_ids:
|
||||
|
@ -69,7 +69,8 @@ class IpAddressGenerationFailureAllSubnets(IpAddressGenerationFailure):
|
||||
|
||||
|
||||
class IpAddressGenerationFailureNoMatchingSubnet(IpAddressGenerationFailure):
|
||||
message = _("No valid service subnet for the given device owner.")
|
||||
message = _("No valid service subnet for the given device owner, "
|
||||
"network %(network_id)s, service type %(service_type)s.")
|
||||
|
||||
|
||||
class IPAllocationFailed(exceptions.NeutronException):
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
import webob.exc
|
||||
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import subnet_service_type_db_models
|
||||
from neutron.extensions import subnet_service_types
|
||||
@ -40,7 +42,7 @@ class SubnetServiceTypesExtensionTestPlugin(
|
||||
"""Test plugin to mixin the subnet service_types extension.
|
||||
"""
|
||||
|
||||
supported_extension_aliases = ["subnet-service-types"]
|
||||
supported_extension_aliases = ["subnet-service-types", "binding"]
|
||||
|
||||
|
||||
class SubnetServiceTypesExtensionTestCase(
|
||||
@ -324,6 +326,29 @@ class SubnetServiceTypesExtensionTestCase(
|
||||
# applied
|
||||
port = self._update('ports', port['id'], data)
|
||||
|
||||
def test_update_port_host_binding(self):
|
||||
with self.network() as network:
|
||||
pass
|
||||
service_type = 'compute:foo'
|
||||
# Create a subnet with a service_type
|
||||
self._create_service_subnet([service_type],
|
||||
cidr=self.CIDRS[1],
|
||||
network=network)
|
||||
# Create a port with a matching device owner
|
||||
network = network['network']
|
||||
port = self._create_port(self.fmt,
|
||||
net_id=network['id'],
|
||||
tenant_id=network['tenant_id'],
|
||||
device_owner=service_type,
|
||||
arg_list=(portbindings.HOST_ID,),
|
||||
**{portbindings.HOST_ID: 'fakehost'})
|
||||
port = self.deserialize('json', port)['port']
|
||||
# Update the port's host binding.
|
||||
data = {'port': {portbindings.HOST_ID: 'fakehost2'}}
|
||||
# self._update will fail with a MismatchError if the update cannot be
|
||||
# applied
|
||||
port = self._update('ports', port['id'], data)
|
||||
|
||||
|
||||
class SubnetServiceTypesExtensionTestCasev6(
|
||||
SubnetServiceTypesExtensionTestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user