Merge "Add existed network failed if the gateway already created"

This commit is contained in:
Jenkins
2016-06-20 16:07:10 +00:00
committed by Gerrit Code Review
4 changed files with 152 additions and 23 deletions

View File

@@ -34,6 +34,8 @@ NEUTRON_ID_LH_OPTION = 'kuryr.net.uuid.lh'
NEUTRON_ID_UH_OPTION = 'kuryr.net.uuid.uh' NEUTRON_ID_UH_OPTION = 'kuryr.net.uuid.uh'
NET_NAME_PREFIX = 'kuryr-net-' NET_NAME_PREFIX = 'kuryr-net-'
REQUEST_ADDRESS_TYPE = 'RequestAddressType'
NETWORK_GATEWAY_OPTIONS = 'com.docker.network.gateway'
NETWORK_GENERIC_OPTIONS = 'com.docker.network.generic' NETWORK_GENERIC_OPTIONS = 'com.docker.network.generic'
NEUTRON_UUID_OPTION = 'neutron.net.uuid' NEUTRON_UUID_OPTION = 'neutron.net.uuid'
NEUTRON_NAME_OPTION = 'neutron.net.name' NEUTRON_NAME_OPTION = 'neutron.net.name'

View File

@@ -39,6 +39,14 @@ class DuplicatedResourceException(KuryrException):
""" """
class GatewayConflictFailure(KuryrException):
"""Exception represents gateway ip is conflict.
This exception is thrown when request gateway ip is conflict with the
gateway ip in existed network.
"""
class MandatoryApiMissing(KuryrException): class MandatoryApiMissing(KuryrException):
"""Exception represents that mandatory api is not found. """Exception represents that mandatory api is not found.

View File

@@ -1085,6 +1085,7 @@ def ipam_request_address():
jsonschema.validate(json_data, schemata.REQUEST_ADDRESS_SCHEMA) jsonschema.validate(json_data, schemata.REQUEST_ADDRESS_SCHEMA)
pool_id = json_data['PoolID'] pool_id = json_data['PoolID']
req_address = json_data['Address'] req_address = json_data['Address']
is_gateway = False
allocated_address = '' allocated_address = ''
subnet_cidr = '' subnet_cidr = ''
pool_prefix_len = '' pool_prefix_len = ''
@@ -1108,31 +1109,48 @@ def ipam_request_address():
.format(pool_id)) .format(pool_id))
# check if any subnet with matching cidr is present # check if any subnet with matching cidr is present
subnets = _get_subnets_by_attrs(cidr=subnet_cidr) subnets = _get_subnets_by_attrs(cidr=subnet_cidr)
# Check if the port is gateway
options = json_data.get('Options')
if options:
request_address_type = options.get(const.REQUEST_ADDRESS_TYPE)
if request_address_type == const.NETWORK_GATEWAY_OPTIONS:
is_gateway = True
if subnets: if subnets:
subnet = subnets[0] subnet = subnets[0]
# allocating address for container port if is_gateway:
neutron_network_id = subnet['network_id'] # check if request gateway ip same with existed gateway ip
try: existed_gateway_ip = subnet.get('gateway_ip', '')
port = { if req_address == existed_gateway_ip:
'name': 'kuryr-unbound-port', allocated_address = '/'.join([req_address, pool_prefix_len])
'admin_state_up': True, else:
'network_id': neutron_network_id, raise exceptions.GatewayConflictFailure(
'binding:host_id': utils.get_hostname(), "Requested gateway {0} does not match with "
} "gateway {1} in existed "
fixed_ips = port['fixed_ips'] = [] "network.".format(req_address, existed_gateway_ip))
fixed_ip = {'subnet_id': subnet['id']} else:
if req_address: # allocating address for container port
fixed_ip['ip_address'] = req_address neutron_network_id = subnet['network_id']
fixed_ips.append(fixed_ip) try:
created_port_resp = app.neutron.create_port({'port': port}) port = {
created_port = created_port_resp['port'] 'name': 'kuryr-unbound-port',
allocated_address = created_port['fixed_ips'][0]['ip_address'] 'admin_state_up': True,
allocated_address = '/'.join( 'network_id': neutron_network_id,
[allocated_address, str(cidr.prefixlen)]) 'binding:host_id': utils.get_hostname(),
except n_exceptions.NeutronClientException as ex: }
app.logger.error(_LE("Error happened during ip allocation on " fixed_ips = port['fixed_ips'] = []
"Neutron side: %s"), ex) fixed_ip = {'subnet_id': subnet['id']}
raise if req_address:
fixed_ip['ip_address'] = req_address
fixed_ips.append(fixed_ip)
created_port_resp = app.neutron.create_port({'port': port})
created_port = created_port_resp['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: else:
# Auxiliary address or gw_address is received at network creation time. # Auxiliary address or gw_address is received at network creation time.
# This address cannot be reserved with neutron at this time as subnet # This address cannot be reserved with neutron at this time as subnet

View File

@@ -15,6 +15,7 @@ from oslo_serialization import jsonutils
import uuid import uuid
from kuryr.common import config from kuryr.common import config
from kuryr.common import constants as const
from kuryr.controllers import app from kuryr.controllers import app
from kuryr.tests.unit import base from kuryr.tests.unit import base
from kuryr import utils from kuryr import utils
@@ -227,6 +228,106 @@ 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_for_same_gateway(self):
# 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
docker_endpoint_id = utils.get_hash()
neutron_network_id = str(uuid.uuid4())
subnet_v4_id = str(uuid.uuid4())
fake_v4_subnet = self._get_fake_v4_subnet(
neutron_network_id, docker_endpoint_id, subnet_v4_id,
subnetpool_id=fake_kuryr_subnetpool_id,
cidr=FAKE_IP4_CIDR)
fake_v4_subnet['subnet'].update(gateway_ip='10.0.0.1')
fake_subnet_response = {
'subnets': [
fake_v4_subnet['subnet']
]
}
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': '10.0.0.1',
'Options': {
const.REQUEST_ADDRESS_TYPE: const.NETWORK_GATEWAY_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('10.0.0.1/16', decoded_json['Address'])
def test_ipam_driver_request_address_for_different_gateway(self):
# 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
docker_endpoint_id = utils.get_hash()
neutron_network_id = str(uuid.uuid4())
subnet_v4_id = str(uuid.uuid4())
fake_v4_subnet = self._get_fake_v4_subnet(
neutron_network_id, docker_endpoint_id, subnet_v4_id,
subnetpool_id=fake_kuryr_subnetpool_id,
cidr=FAKE_IP4_CIDR)
fake_v4_subnet['subnet'].update(gateway_ip='10.0.0.1')
fake_subnet_response = {
'subnets': [
fake_v4_subnet['subnet']
]
}
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': '10.0.0.5', # Different with existed gw ip
'Options': {
const.REQUEST_ADDRESS_TYPE: const.NETWORK_GATEWAY_OPTIONS
}
}
response = self.app.post('/IpamDriver.RequestAddress',
content_type='application/json',
data=jsonutils.dumps(fake_request))
self.assertEqual(500, response.status_code)
decoded_json = jsonutils.loads(response.data)
self.assertIn('Err', decoded_json)
err_message = ("Requested gateway {0} does not match with "
"gateway {1} in existed network.").format(
'10.0.0.5', '10.0.0.1')
self.assertEqual({'Err': err_message}, decoded_json)
def test_ipam_driver_release_address(self): def test_ipam_driver_release_address(self):
# faking list_subnetpools # faking list_subnetpools
self.mox.StubOutWithMock(app.neutron, 'list_subnetpools') self.mox.StubOutWithMock(app.neutron, 'list_subnetpools')