Merge "RequestAddress when subnet has not been created"

This commit is contained in:
Jenkins 2016-08-31 14:10:44 +00:00 committed by Gerrit Code Review
commit 20456034fe
2 changed files with 93 additions and 52 deletions

View File

@ -1323,8 +1323,8 @@ def ipam_request_address():
else: else:
subnet = subnets_by_cidr[0] 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 # check if request gateway ip same with existed gateway ip
existed_gateway_ip = subnet.get('gateway_ip', '') existed_gateway_ip = subnet.get('gateway_ip', '')
if req_address == existed_gateway_ip: if req_address == existed_gateway_ip:
@ -1336,59 +1336,65 @@ def ipam_request_address():
"gateway {1} in existed " "gateway {1} in existed "
"network.".format(req_address, existed_gateway_ip)) "network.".format(req_address, existed_gateway_ip))
else: else:
allocated_address = '/'.join([req_address, pool_prefix_len]) # allocating address for container port
else: neutron_network_id = subnet['network_id']
# allocating address for container port try:
neutron_network_id = subnet['network_id'] port = {
try: 'name': 'kuryr-unbound-port',
port = { 'admin_state_up': True,
'name': 'kuryr-unbound-port', 'network_id': neutron_network_id,
'admin_state_up': True, 'binding:host_id': utils.get_hostname(),
'network_id': neutron_network_id, }
'binding:host_id': utils.get_hostname(), fixed_ips = port['fixed_ips'] = []
} fixed_ip = {'subnet_id': subnet['id']}
fixed_ips = port['fixed_ips'] = [] num_ports = 0
fixed_ip = {'subnet_id': subnet['id']} if req_address:
num_ports = 0 fixed_ip['ip_address'] = req_address
if req_address: fixed_ip_existing = [('subnet_id=%s' % subnet['id'])]
fixed_ip['ip_address'] = req_address fixed_ip_existing.append('ip_address='
fixed_ip_existing = [('subnet_id=%s' % subnet['id'])] '%s' % str(req_address))
fixed_ip_existing.append('ip_address=%s' % str(req_address)) filtered_ports = app.neutron.list_ports(
filtered_ports = app.neutron.list_ports( fixed_ips=fixed_ip_existing)
fixed_ips=fixed_ip_existing) num_ports = len(filtered_ports.get('ports', []))
num_ports = len(filtered_ports.get('ports', [])) fixed_ips.append(fixed_ip)
fixed_ips.append(fixed_ip)
if num_ports: if num_ports:
existing_port = filtered_ports['ports'][0] existing_port = filtered_ports['ports'][0]
created_port_resp = {'port': existing_port} created_port_resp = {'port': existing_port}
host = existing_port.get('binding:host_id') host = existing_port.get('binding:host_id')
vif_type = existing_port.get('binding:vif_type') vif_type = existing_port.get('binding:vif_type')
if not host and vif_type == 'unbound': if not host and vif_type == 'unbound':
updated_port = { updated_port = {
'admin_state_up': True, 'admin_state_up': True,
'binding:host_id': utils.get_hostname(), 'binding:host_id': utils.get_hostname(),
} }
created_port_resp = app.neutron.update_port( created_port_resp = app.neutron.update_port(
existing_port['id'], existing_port['id'],
{'port': updated_port}) {'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: else:
raise exceptions.AddressInUseException( created_port_resp = app.neutron.create_port({'port': port})
"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 = created_port_resp['port'] created_port = created_port_resp['port']
app.logger.debug("created port %s", created_port) app.logger.debug("created port %s", created_port)
allocated_address = created_port['fixed_ips'][0]['ip_address'] allocated_address = created_port['fixed_ips'][0]['ip_address']
allocated_address = '/'.join( allocated_address = '/'.join(
[allocated_address, str(cidr.prefixlen)]) [allocated_address, str(cidr.prefixlen)])
except n_exceptions.NeutronClientException as ex: except n_exceptions.NeutronClientException as ex:
app.logger.error(_LE("Error happened during ip allocation on " app.logger.error(_LE("Error happened during ip allocation on "
"Neutron side: %s"), ex) "Neutron side: %s"), ex)
raise 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}) return flask.jsonify({'Address': allocated_address})

View File

@ -238,6 +238,41 @@ class TestKuryrIpam(base.TestKuryrBase):
decoded_json = jsonutils.loads(response.data) decoded_json = jsonutils.loads(response.data)
self.assertEqual('10.0.0.5/16', decoded_json['Address']) 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)) @ddt.data((False), (True))
def test_ipam_driver_request_specific_address(self, existing_port): def test_ipam_driver_request_specific_address(self, existing_port):
requested_address = '10.0.0.5' requested_address = '10.0.0.5'