fixed_configured=True when Add/Remove port IPs

When updating a port with the fixed_ips request the
fixed_configured argument should be set to true when
calling _ipam_get_subnets() so that all subnets are
returned if host is not set.

Otherwise the ip allocation will be deffered and an
empty list of possible subnets for the port is
returned. Which in turn led to raising an error that
the network requires subnets to allocate an IP
address.

Closes-Bug: #1844124
Change-Id: I2e690ea0cf5fa0614e39be2b0e83afad3daa7f48
(cherry picked from commit def8e95aad)
This commit is contained in:
Harald Jensås 2019-09-16 21:52:51 +02:00
parent 9117f8b6c4
commit 1bab70f909
4 changed files with 39 additions and 6 deletions

View File

@ -295,7 +295,7 @@ class IpamPluggableBackend(ipam_backend_mixin.IpamBackendMixin):
try:
subnets = self._ipam_get_subnets(
context, network_id=port['network_id'], host=host,
service_type=port.get('device_owner'))
service_type=port.get('device_owner'), fixed_configured=True)
except ipam_exc.DeferIpam:
subnets = []

View File

@ -660,8 +660,8 @@ class TestDbBasePluginIpam(test_db_base.NeutronDbPluginV2TestCase):
original_ips, new_ips, mac)
mocks['driver'].get_address_request_factory.assert_called_once_with()
mocks['ipam']._ipam_get_subnets.assert_called_once_with(
context, network_id=port_dict['network_id'], host=None,
service_type=port_dict['device_owner'])
context, network_id=port_dict['network_id'], fixed_configured=True,
host=None, service_type=port_dict['device_owner'])
# Validate port_dict is passed into address_factory
address_factory.get_request.assert_called_once_with(context,
port_dict,

View File

@ -1020,8 +1020,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase):
self.assertEqual(segment_exc.HostConnectedToMultipleSegments.__name__,
res['NeutronError']['type'])
def test_port_update_excludes_hosts_on_segments(self):
"""No binding information is provided, subnets on segments"""
def test_port_update_with_fixed_ips_ok_if_no_binding_host(self):
"""No binding host information is provided, subnets on segments"""
with self.network() as network:
segment = self._test_create_segment(
network_id=network['network']['id'],
@ -1041,7 +1041,33 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase):
port_req = self.new_update_request('ports', data, port_id)
response = port_req.get_response(self.api)
# Gets bad request because there are no eligible subnets.
# The IP is allocated since there is no binding host info any
# subnet can be used for allocation.
self.assertEqual(webob.exc.HTTPOk.code, response.status_int)
def test_port_update_with_fixed_ips_fail_if_host_not_on_segment(self):
"""Binding information is provided, subnets on segments. Update to
subnet on different segment fails.
"""
network, segments, subnets = self._create_test_segments_with_subnets(2)
# Setup host mappings
self._setup_host_mappings([(segments[0]['segment']['id'], 'fakehost')])
# Create a port and validate immediate ip allocation
res = self._create_port_and_show(network,
arg_list=(portbindings.HOST_ID,),
**{portbindings.HOST_ID: 'fakehost'})
self._validate_immediate_ip_allocation(res['port']['id'])
# Try requesting an new IP, but the subnet does not match host segment
port_id = res['port']['id']
data = {'port': {
'fixed_ips': [{'subnet_id': subnets[1]['subnet']['id']}]}}
port_req = self.new_update_request('ports', data, port_id)
response = port_req.get_response(self.api)
# Port update fails.
self.assertEqual(webob.exc.HTTPBadRequest.code, response.status_int)
def _create_port_and_show(self, network, **kwargs):

View File

@ -0,0 +1,7 @@
---
fixes:
- |
When updating the fixed-ips of a port residing on a routed provider
network the port update would always fail if *host* was not set.
See bug: `1844124 <https://bugs.launchpad.net/tripleo/+bug/1844124>`_.