Merge "Do not defer allocation if fixed-ips is in the port create request."

This commit is contained in:
Jenkins 2017-06-14 00:46:00 +00:00 committed by Gerrit Code Review
commit ce33de5f51
3 changed files with 28 additions and 6 deletions

View File

@ -657,14 +657,15 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
# implementations. # implementations.
return host and validators.is_attr_set(host) return host and validators.is_attr_set(host)
def _ipam_get_subnets(self, context, network_id, host, service_type=None): def _ipam_get_subnets(self, context, network_id, host, service_type=None,
fixed_configured=False):
"""Return eligible subnets """Return eligible subnets
If no eligible subnets are found, determine why and potentially raise If no eligible subnets are found, determine why and potentially raise
an appropriate error. an appropriate error.
""" """
subnets = self._find_candidate_subnets( subnets = self._find_candidate_subnets(context, network_id, host,
context, network_id, host, service_type) service_type, fixed_configured)
if subnets: if subnets:
subnet_dicts = [self._make_subnet_dict(subnet, context=context) subnet_dicts = [self._make_subnet_dict(subnet, context=context)
for subnet in subnets] for subnet in subnets]
@ -697,13 +698,20 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
raise ipam_exceptions.IpAddressGenerationFailureNoMatchingSubnet() raise ipam_exceptions.IpAddressGenerationFailureNoMatchingSubnet()
def _find_candidate_subnets(self, context, network_id, host, service_type): def _find_candidate_subnets(self, context, network_id, host, service_type,
fixed_configured):
"""Find canditate subnets for the network, host, and service_type""" """Find canditate subnets for the network, host, and service_type"""
query = self._query_subnets_on_network(context, network_id) query = self._query_subnets_on_network(context, network_id)
query = self._query_filter_service_subnets(query, service_type) query = self._query_filter_service_subnets(query, service_type)
# Select candidate subnets and return them # Select candidate subnets and return them
if not self.is_host_set(host): if not self.is_host_set(host):
if fixed_configured:
# If fixed_ips in request and host is not known all subnets on
# the network are candidates. Host/Segment will be validated
# on port update with binding:host_id set. Allocation _cannot_
# be deferred as requested fixed_ips would then be lost.
return query.all()
# If the host isn't known, we can't allocate on a routed network. # If the host isn't known, we can't allocate on a routed network.
# So, exclude any subnets attached to segments. # So, exclude any subnets attached to segments.
return self._query_exclude_subnets_on_segments(query).all() return self._query_exclude_subnets_on_segments(query).all()

View File

@ -200,15 +200,16 @@ class IpamPluggableBackend(ipam_backend_mixin.IpamBackendMixin):
a subnet_id then allocate an IP address accordingly. a subnet_id then allocate an IP address accordingly.
""" """
p = port['port'] p = port['port']
fixed_configured = p['fixed_ips'] is not constants.ATTR_NOT_SPECIFIED
subnets = self._ipam_get_subnets(context, subnets = self._ipam_get_subnets(context,
network_id=p['network_id'], network_id=p['network_id'],
host=p.get(portbindings.HOST_ID), host=p.get(portbindings.HOST_ID),
service_type=p.get('device_owner')) service_type=p.get('device_owner'),
fixed_configured=fixed_configured)
v4, v6_stateful, v6_stateless = self._classify_subnets( v4, v6_stateful, v6_stateless = self._classify_subnets(
context, subnets) context, subnets)
fixed_configured = p['fixed_ips'] is not constants.ATTR_NOT_SPECIFIED
if fixed_configured: if fixed_configured:
ips = self._test_fixed_ips_for_port(context, ips = self._test_fixed_ips_for_port(context,
p["network_id"], p["network_id"],

View File

@ -880,6 +880,19 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase):
# Don't allocate IPs in this case because we didn't give binding info # Don't allocate IPs in this case because we didn't give binding info
self.assertEqual(0, len(res['port']['fixed_ips'])) self.assertEqual(0, len(res['port']['fixed_ips']))
def test_port_create_fixed_ips_with_segment_subnets_no_binding_info(self):
"""Fixed IP provided and no binding info, do not defer IP allocation"""
network, segment, subnet = self._create_test_segment_with_subnet()
response = self._create_port(self.fmt,
net_id=network['network']['id'],
tenant_id=network['network']['tenant_id'],
fixed_ips=[
{'subnet_id': subnet['subnet']['id']}
])
res = self.deserialize(self.fmt, response)
# We gave fixed_ips, allocate IPs in this case despite no binding info
self._validate_immediate_ip_allocation(res['port']['id'])
def _assert_one_ip_in_subnet(self, response, cidr): def _assert_one_ip_in_subnet(self, response, cidr):
res = self.deserialize(self.fmt, response) res = self.deserialize(self.fmt, response)
self.assertEqual(1, len(res['port']['fixed_ips'])) self.assertEqual(1, len(res['port']['fixed_ips']))