RequestAddress when subnet has not been created
gw_address is received in IpamDriver.RequestAddress when create network. In Docker 1.12+, it will have NETWORK_GATEWAY_OPTIONS, but in lower docker version, such as 1.9.1, it will not carry this option. This change check if subnet exist first, this makes it can work for both docker version. Change-Id: I1c741172e927179f83284e8a23afce5f07b130f9 Closes-bug: #1611261
This commit is contained in:
parent
4a820b0b98
commit
3e4e6a612f
|
@ -1318,8 +1318,8 @@ def ipam_request_address():
|
|||
else:
|
||||
subnet = subnets_by_cidr[0]
|
||||
|
||||
if is_gateway:
|
||||
if any(subnet):
|
||||
if any(subnet):
|
||||
if is_gateway:
|
||||
# check if request gateway ip same with existed gateway ip
|
||||
existed_gateway_ip = subnet.get('gateway_ip', '')
|
||||
if req_address == existed_gateway_ip:
|
||||
|
@ -1331,59 +1331,65 @@ def ipam_request_address():
|
|||
"gateway {1} in existed "
|
||||
"network.".format(req_address, existed_gateway_ip))
|
||||
else:
|
||||
allocated_address = '/'.join([req_address, pool_prefix_len])
|
||||
else:
|
||||
# allocating address for container port
|
||||
neutron_network_id = subnet['network_id']
|
||||
try:
|
||||
port = {
|
||||
'name': 'kuryr-unbound-port',
|
||||
'admin_state_up': True,
|
||||
'network_id': neutron_network_id,
|
||||
'binding:host_id': utils.get_hostname(),
|
||||
}
|
||||
fixed_ips = port['fixed_ips'] = []
|
||||
fixed_ip = {'subnet_id': subnet['id']}
|
||||
num_ports = 0
|
||||
if req_address:
|
||||
fixed_ip['ip_address'] = req_address
|
||||
fixed_ip_existing = [('subnet_id=%s' % subnet['id'])]
|
||||
fixed_ip_existing.append('ip_address=%s' % str(req_address))
|
||||
filtered_ports = app.neutron.list_ports(
|
||||
fixed_ips=fixed_ip_existing)
|
||||
num_ports = len(filtered_ports.get('ports', []))
|
||||
fixed_ips.append(fixed_ip)
|
||||
# allocating address for container port
|
||||
neutron_network_id = subnet['network_id']
|
||||
try:
|
||||
port = {
|
||||
'name': 'kuryr-unbound-port',
|
||||
'admin_state_up': True,
|
||||
'network_id': neutron_network_id,
|
||||
'binding:host_id': utils.get_hostname(),
|
||||
}
|
||||
fixed_ips = port['fixed_ips'] = []
|
||||
fixed_ip = {'subnet_id': subnet['id']}
|
||||
num_ports = 0
|
||||
if req_address:
|
||||
fixed_ip['ip_address'] = req_address
|
||||
fixed_ip_existing = [('subnet_id=%s' % subnet['id'])]
|
||||
fixed_ip_existing.append('ip_address='
|
||||
'%s' % str(req_address))
|
||||
filtered_ports = app.neutron.list_ports(
|
||||
fixed_ips=fixed_ip_existing)
|
||||
num_ports = len(filtered_ports.get('ports', []))
|
||||
fixed_ips.append(fixed_ip)
|
||||
|
||||
if num_ports:
|
||||
existing_port = filtered_ports['ports'][0]
|
||||
created_port_resp = {'port': existing_port}
|
||||
host = existing_port.get('binding:host_id')
|
||||
vif_type = existing_port.get('binding:vif_type')
|
||||
if not host and vif_type == 'unbound':
|
||||
updated_port = {
|
||||
'admin_state_up': True,
|
||||
'binding:host_id': utils.get_hostname(),
|
||||
}
|
||||
created_port_resp = app.neutron.update_port(
|
||||
existing_port['id'],
|
||||
{'port': updated_port})
|
||||
if num_ports:
|
||||
existing_port = filtered_ports['ports'][0]
|
||||
created_port_resp = {'port': existing_port}
|
||||
host = existing_port.get('binding:host_id')
|
||||
vif_type = existing_port.get('binding:vif_type')
|
||||
if not host and vif_type == 'unbound':
|
||||
updated_port = {
|
||||
'admin_state_up': True,
|
||||
'binding:host_id': utils.get_hostname(),
|
||||
}
|
||||
created_port_resp = app.neutron.update_port(
|
||||
existing_port['id'],
|
||||
{'port': updated_port})
|
||||
else:
|
||||
raise exceptions.AddressInUseException(
|
||||
"Requested ip address {0} already belongs to a "
|
||||
"bound Neutron port: {1}".format(fixed_ip,
|
||||
existing_port['id']))
|
||||
else:
|
||||
raise exceptions.AddressInUseException(
|
||||
"Requested ip address {0} already belongs to a bound "
|
||||
"Neutron port: {1}".format(fixed_ip,
|
||||
existing_port['id']))
|
||||
else:
|
||||
created_port_resp = app.neutron.create_port({'port': port})
|
||||
created_port_resp = app.neutron.create_port({'port': port})
|
||||
|
||||
created_port = created_port_resp['port']
|
||||
app.logger.debug("created port %s", created_port)
|
||||
allocated_address = created_port['fixed_ips'][0]['ip_address']
|
||||
allocated_address = '/'.join(
|
||||
[allocated_address, str(cidr.prefixlen)])
|
||||
except n_exceptions.NeutronClientException as ex:
|
||||
app.logger.error(_LE("Error happened during ip allocation on "
|
||||
"Neutron side: %s"), ex)
|
||||
raise
|
||||
created_port = created_port_resp['port']
|
||||
app.logger.debug("created port %s", created_port)
|
||||
allocated_address = created_port['fixed_ips'][0]['ip_address']
|
||||
allocated_address = '/'.join(
|
||||
[allocated_address, str(cidr.prefixlen)])
|
||||
except n_exceptions.NeutronClientException as ex:
|
||||
app.logger.error(_LE("Error happened during ip allocation on "
|
||||
"Neutron side: %s"), ex)
|
||||
raise
|
||||
else:
|
||||
# Auxiliary address or gw_address is received at network creation time.
|
||||
# This address cannot be reserved with neutron at this time as subnet
|
||||
# is not created yet. In /NetworkDriver.CreateNetwork this address will
|
||||
# be reserved with neutron.
|
||||
if req_address:
|
||||
allocated_address = '/'.join([req_address, pool_prefix_len])
|
||||
|
||||
return flask.jsonify({'Address': allocated_address})
|
||||
|
||||
|
|
|
@ -238,6 +238,41 @@ class TestKuryrIpam(base.TestKuryrBase):
|
|||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual('10.0.0.5/16', decoded_json['Address'])
|
||||
|
||||
def test_ipam_driver_request_address_when_subnet_not_exist(self):
|
||||
requested_address = '10.0.0.5'
|
||||
# faking list_subnetpools
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnetpools')
|
||||
fake_kuryr_subnetpool_id = str(uuid.uuid4())
|
||||
fake_name = utils.get_neutron_subnetpool_name(FAKE_IP4_CIDR)
|
||||
kuryr_subnetpools = self._get_fake_v4_subnetpools(
|
||||
fake_kuryr_subnetpool_id, prefixes=[FAKE_IP4_CIDR],
|
||||
name=fake_name)
|
||||
app.neutron.list_subnetpools(id=fake_kuryr_subnetpool_id).AndReturn(
|
||||
kuryr_subnetpools)
|
||||
|
||||
# faking list_subnets
|
||||
fake_subnet_response = {'subnets': []}
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnets')
|
||||
app.neutron.list_subnets(cidr=FAKE_IP4_CIDR).AndReturn(
|
||||
fake_subnet_response)
|
||||
|
||||
# Apply mocks
|
||||
self.mox.ReplayAll()
|
||||
|
||||
# Testing container ip allocation
|
||||
fake_request = {
|
||||
'PoolID': fake_kuryr_subnetpool_id,
|
||||
'Address': requested_address,
|
||||
'Options': {}
|
||||
}
|
||||
response = self.app.post('/IpamDriver.RequestAddress',
|
||||
content_type='application/json',
|
||||
data=jsonutils.dumps(fake_request))
|
||||
|
||||
self.assertEqual(200, response.status_code)
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(requested_address + '/16', decoded_json['Address'])
|
||||
|
||||
@ddt.data((False), (True))
|
||||
def test_ipam_driver_request_specific_address(self, existing_port):
|
||||
requested_address = '10.0.0.5'
|
||||
|
|
Loading…
Reference in New Issue