Short-Term fix for overlapping cidrs using docker options
A quick alternative solution, until PRs to upstream Docker get accepted, can be Docker user passing pool name to both Kuryr ipam driver and Kuryr network driver using corresponding network and ipam options respectively: $sudo docker network create --driver=kuryr --ipam-driver=kuryr \ --subnet 10.0.0.0/16 --ip-range 10.0.0.0/24 \ -o neutron.pool.name=neutron_pool1 \ --ipam-opt=neutron.pool.name=neutron_pool1 \ foo eddb51ebca09339cb17aaec05e48ffe60659ced6f3fc41b020b0eb506d364 Now Docker user creates another network with same cidr as the previous, i.e 10.0.0.0/16, but with different pool name, neutron_pool2: $sudo docker network create --driver=kuryr --ipam-driver=kuryr \ --subnet 10.0.0.0/16 --ip-range 10.0.0.0/24 \ -o neutron.pool.name=neutron_pool2 \ --ipam-opt=neutron.pool.name=neutron_pool2 \ bar 397badb51ebca09339cb17aaec05e48ffe60659ced6f3fc41b020b0eb506d786 At ``/IpamDriver.RequestAddress``, correct subnet will be filtered out using corresponding pool name received from the libnetwork as explained above. Please refer https://review.openstack.org/#/c/326894/6 TODO: unit test cases covering docker option scenario DocImpact Change-Id: I7090027e68e8c78219a387da66e1bd30be900ab1 Closes-bug: #1585572
This commit is contained in:
parent
4dc7caf89c
commit
709fede534
@ -43,3 +43,4 @@ NETWORK_GENERIC_OPTIONS = 'com.docker.network.generic'
|
||||
NEUTRON_UUID_OPTION = 'neutron.net.uuid'
|
||||
NEUTRON_NAME_OPTION = 'neutron.net.name'
|
||||
KURYR_EXISTING_NEUTRON_NET = 'kuryr.net.existing'
|
||||
NEUTRON_POOL_NAME_OPTION = 'neutron.pool.name'
|
||||
|
@ -171,11 +171,6 @@ def _get_networks_by_attrs(**attrs):
|
||||
|
||||
def _get_subnets_by_attrs(**attrs):
|
||||
subnets = app.neutron.list_subnets(**attrs)
|
||||
if len(subnets.get('subnets', [])) > 2: # subnets for IPv4 and/or IPv6
|
||||
raise exceptions.DuplicatedResourceException(
|
||||
"Multiple Neutron subnets exist for the params {0} "
|
||||
.format(', '.join(['{0}={1}'.format(k, v)
|
||||
for k, v in attrs.items()])))
|
||||
return subnets['subnets']
|
||||
|
||||
|
||||
@ -214,6 +209,11 @@ def _get_subnets_by_interface_cidr(neutron_network_id,
|
||||
str(cidr.prefixlen)])
|
||||
subnets = _get_subnets_by_attrs(
|
||||
network_id=neutron_network_id, cidr=subnet_cidr)
|
||||
if len(subnets) > 2:
|
||||
raise exceptions.DuplicatedResourceException(
|
||||
"Multiple Neutron subnets exist for the network_id={0}"
|
||||
"and cidr={1}"
|
||||
.format(neutron_network_id, cidr))
|
||||
return subnets
|
||||
|
||||
|
||||
@ -512,12 +512,24 @@ def network_driver_create_network():
|
||||
|
||||
neutron_uuid = None
|
||||
neutron_name = None
|
||||
pool_name = ''
|
||||
pool_id = ''
|
||||
options = json_data.get('Options')
|
||||
if options:
|
||||
generic_options = options.get(const.NETWORK_GENERIC_OPTIONS)
|
||||
if generic_options:
|
||||
neutron_uuid = generic_options.get(const.NEUTRON_UUID_OPTION)
|
||||
neutron_name = generic_options.get(const.NEUTRON_NAME_OPTION)
|
||||
pool_name = generic_options.get(const.NEUTRON_POOL_NAME_OPTION)
|
||||
|
||||
if pool_name:
|
||||
pools = _get_subnetpools_by_attrs(name=pool_name)
|
||||
if pools:
|
||||
pool_id = pools[0]['id']
|
||||
else:
|
||||
raise exceptions.KuryrException(
|
||||
("Specified pool name({0}) does not "
|
||||
"exist.").format(pool_name))
|
||||
|
||||
if not neutron_uuid and not neutron_name:
|
||||
network = app.neutron.create_network(
|
||||
@ -565,6 +577,11 @@ def network_driver_create_network():
|
||||
subnet_cidr = '/'.join([subnet_network, str(cidr.prefixlen)])
|
||||
subnets = _get_subnets_by_attrs(
|
||||
network_id=network_id, cidr=subnet_cidr)
|
||||
if len(subnets) > 1:
|
||||
raise exceptions.DuplicatedResourceException(
|
||||
"Multiple Neutron subnets exist for the network_id={0}"
|
||||
"and cidr={1}".format(network_id, cidr))
|
||||
|
||||
if not subnets:
|
||||
new_subnets = [{
|
||||
'name': pool_cidr,
|
||||
@ -573,6 +590,8 @@ def network_driver_create_network():
|
||||
'cidr': subnet_cidr,
|
||||
'enable_dhcp': app.enable_dhcp,
|
||||
}]
|
||||
if pool_id:
|
||||
new_subnets[0]['subnetpool_id'] = pool_id
|
||||
if gateway_ip:
|
||||
new_subnets[0]['gateway_ip'] = gateway_ip
|
||||
|
||||
@ -642,6 +661,10 @@ def network_driver_delete_network():
|
||||
neutron_network_id = filtered_networks[0]['id']
|
||||
filtered_subnets = _get_subnets_by_attrs(
|
||||
network_id=neutron_network_id)
|
||||
if len(filtered_subnets) > 2: # subnets for IPv4 and/or IPv6
|
||||
raise exceptions.DuplicatedResourceException(
|
||||
"Multiple Neutron subnets exist for the network_id={0} "
|
||||
.format(neutron_network_id))
|
||||
for subnet in filtered_subnets:
|
||||
try:
|
||||
subnetpool_id = subnet.get('subnetpool_id', None)
|
||||
@ -836,6 +859,10 @@ def network_driver_join():
|
||||
.format(neutron_port_name))
|
||||
neutron_port = filtered_ports[0]
|
||||
all_subnets = _get_subnets_by_attrs(network_id=neutron_network_id)
|
||||
if len(all_subnets) > 2: # subnets for IPv4 and/or IPv6
|
||||
raise exceptions.DuplicatedResourceException(
|
||||
"Multiple Neutron subnets exist for the network_id={0} "
|
||||
.format(neutron_network_id))
|
||||
|
||||
try:
|
||||
ifname, peer_name, (stdout, stderr) = binding.port_bind(
|
||||
@ -1046,6 +1073,11 @@ def ipam_request_pool():
|
||||
v6 = json_data['V6']
|
||||
pool_id = ''
|
||||
subnet_cidr = ''
|
||||
pool_name = ''
|
||||
pools = []
|
||||
options = json_data.get('Options')
|
||||
if options:
|
||||
pool_name = options.get(const.NEUTRON_POOL_NAME_OPTION)
|
||||
if requested_pool:
|
||||
app.logger.info(_LI("Creating subnetpool with the given pool CIDR"))
|
||||
if requested_subpool:
|
||||
@ -1053,11 +1085,14 @@ def ipam_request_pool():
|
||||
else:
|
||||
cidr = netaddr.IPNetwork(requested_pool)
|
||||
subnet_cidr = _get_subnet_cidr_using_cidr(cidr)
|
||||
pool_name = utils.get_neutron_subnetpool_name(subnet_cidr)
|
||||
# Check if requested pool already exist
|
||||
pools = _get_subnetpools_by_attrs(name=pool_name)
|
||||
if pools:
|
||||
pool_id = pools[0]['id']
|
||||
if not pool_name:
|
||||
pool_name = utils.get_neutron_subnetpool_name(subnet_cidr)
|
||||
pools = _get_subnetpools_by_attrs(name=pool_name)
|
||||
if len(pools):
|
||||
raise exceptions.KuryrException(
|
||||
"Another pool with same cidr exist. ipam and network"
|
||||
" options not used to pass pool name")
|
||||
|
||||
if not pools:
|
||||
new_subnetpool = {
|
||||
'name': pool_name,
|
||||
@ -1085,6 +1120,7 @@ def ipam_request_pool():
|
||||
subnet_cidr = _get_subnet_cidr_using_cidr(cidr)
|
||||
else:
|
||||
app.logger.error(_LE("Default neutron pools not found."))
|
||||
|
||||
req_pool_res = {'PoolID': pool_id,
|
||||
'Pool': subnet_cidr}
|
||||
return flask.jsonify(req_pool_res)
|
||||
@ -1123,6 +1159,7 @@ def ipam_request_address():
|
||||
is_gateway = False
|
||||
allocated_address = ''
|
||||
subnet_cidr = ''
|
||||
subnet = {}
|
||||
pool_prefix_len = ''
|
||||
pools = _get_subnetpools_by_attrs(id=pool_id)
|
||||
if pools:
|
||||
@ -1143,56 +1180,64 @@ def ipam_request_address():
|
||||
"No subnetpools with id {0} is found."
|
||||
.format(pool_id))
|
||||
# check if any subnet with matching cidr is present
|
||||
subnets = _get_subnets_by_attrs(cidr=subnet_cidr)
|
||||
subnets_by_cidr = _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:
|
||||
subnet = subnets[0]
|
||||
if is_gateway:
|
||||
if subnets_by_cidr:
|
||||
if len(subnets_by_cidr) > 1:
|
||||
for tmp_subnet in subnets_by_cidr:
|
||||
if tmp_subnet.get('subnetpool_id', '') == pool_id:
|
||||
subnet = tmp_subnet
|
||||
if not any(subnet) and not is_gateway:
|
||||
raise exceptions.KuryrException(
|
||||
("Subnet with cidr({0}) and pool {1}, does not "
|
||||
"exist.").format(cidr, pool_id))
|
||||
else:
|
||||
subnet = subnets_by_cidr[0]
|
||||
|
||||
if is_gateway:
|
||||
if any(subnet):
|
||||
# check if request gateway ip same with existed gateway ip
|
||||
existed_gateway_ip = subnet.get('gateway_ip', '')
|
||||
if req_address == existed_gateway_ip:
|
||||
allocated_address = '/'.join([req_address, pool_prefix_len])
|
||||
allocated_address = '/'.join(
|
||||
[req_address, pool_prefix_len])
|
||||
else:
|
||||
raise exceptions.GatewayConflictFailure(
|
||||
"Requested gateway {0} does not match with "
|
||||
"gateway {1} in existed "
|
||||
"network.".format(req_address, existed_gateway_ip))
|
||||
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']}
|
||||
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:
|
||||
# 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])
|
||||
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']}
|
||||
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']
|
||||
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
|
||||
|
||||
return flask.jsonify({'Address': allocated_address})
|
||||
|
||||
@ -1277,7 +1322,18 @@ def ipam_release_address():
|
||||
if not len(subnets):
|
||||
app.logger.info(_LI("Subnet already deleted."))
|
||||
return flask.jsonify(const.SCHEMA['SUCCESS'])
|
||||
subnet = subnets[0]
|
||||
if len(subnets) > 1:
|
||||
subnet = {}
|
||||
for tmp_subnet in subnets:
|
||||
if tmp_subnet['subnetpool_id'] == pool_id:
|
||||
subnet = tmp_subnet
|
||||
if not subnet:
|
||||
raise exceptions.KuryrException(
|
||||
("Subnet with cidr({0}) and pool {1}, does not "
|
||||
"exist.").format(cidr, pool_id))
|
||||
else:
|
||||
subnet = subnets[0]
|
||||
|
||||
cidr_address = netaddr.IPNetwork(rel_address)
|
||||
rcvd_fixed_ips = []
|
||||
fixed_ip = {'subnet_id': subnet['id']}
|
||||
|
@ -140,8 +140,8 @@ class TestKuryrBase(TestCase):
|
||||
# The following fake response is retrieved from the Neutron doc:
|
||||
# http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa
|
||||
fake_subnet_response = {
|
||||
"subnets": [{
|
||||
"name": '-'.join([docker_endpoint_id, '192.168.1.0']),
|
||||
"subnets": [
|
||||
{"name": '-'.join([docker_endpoint_id, '192.168.1.0']),
|
||||
"network_id": neutron_network_id,
|
||||
"tenant_id": "c1210485b2424d48804aad5d39c61b8f",
|
||||
"allocation_pools": [{"start": "192.168.1.2",
|
||||
@ -150,9 +150,9 @@ class TestKuryrBase(TestCase):
|
||||
"ip_version": 4,
|
||||
"cidr": "192.168.1.0/24",
|
||||
"id": fake_neutron_subnet_v4_id,
|
||||
"enable_dhcp": True
|
||||
}, {
|
||||
"name": '-'.join([docker_endpoint_id, 'fe80::']),
|
||||
"enable_dhcp": True,
|
||||
"subnetpool_id": ''},
|
||||
{"name": '-'.join([docker_endpoint_id, 'fe80::']),
|
||||
"network_id": neutron_network_id,
|
||||
"tenant_id": "c1210485b2424d48804aad5d39c61b8f",
|
||||
"allocation_pools": [{"start": "fe80::f816:3eff:fe20:57c4",
|
||||
@ -161,8 +161,9 @@ class TestKuryrBase(TestCase):
|
||||
"ip_version": 6,
|
||||
"cidr": "fe80::/64",
|
||||
"id": fake_neutron_subnet_v6_id,
|
||||
"enable_dhcp": True
|
||||
}]
|
||||
"enable_dhcp": True,
|
||||
"subnetpool_id": ''}
|
||||
]
|
||||
}
|
||||
return fake_subnet_response
|
||||
|
||||
@ -243,7 +244,8 @@ class TestKuryrBase(TestCase):
|
||||
"ip_version": 4,
|
||||
"cidr": '192.168.1.0/24',
|
||||
"id": subnet_v4_id,
|
||||
"enable_dhcp": True
|
||||
"enable_dhcp": True,
|
||||
"subnetpool_id": ''
|
||||
}
|
||||
}
|
||||
if subnetpool_id:
|
||||
|
@ -144,6 +144,286 @@ class TestKuryr(base.TestKuryrBase):
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
|
||||
|
||||
def test_network_driver_create_network_with_net_name_option(self):
|
||||
docker_network_id = utils.get_hash()
|
||||
fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
|
||||
self.mox.StubOutWithMock(app.neutron, "list_networks")
|
||||
fake_neutron_net_name = 'my_network_name'
|
||||
fake_existing_networks_response = {
|
||||
"networks": [{
|
||||
"status": "ACTIVE",
|
||||
"subnets": [],
|
||||
"admin_state_up": True,
|
||||
"tenant_id": "9bacb3c5d39d41a79512987f338cf177",
|
||||
"router:external": False,
|
||||
"segments": [],
|
||||
"shared": False,
|
||||
"id": fake_neutron_net_id,
|
||||
"name": "my_network_name"
|
||||
}]
|
||||
}
|
||||
app.neutron.list_networks(
|
||||
name=fake_neutron_net_name).AndReturn(
|
||||
fake_existing_networks_response)
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, "add_tag")
|
||||
tags = utils.create_net_tags(docker_network_id)
|
||||
for tag in tags:
|
||||
app.neutron.add_tag('networks', fake_neutron_net_id, tag)
|
||||
|
||||
app.neutron.add_tag(
|
||||
'networks', fake_neutron_net_id, 'kuryr.net.existing')
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnets')
|
||||
fake_existing_subnets_response = {
|
||||
"subnets": []
|
||||
}
|
||||
fake_cidr_v4 = '192.168.42.0/24'
|
||||
app.neutron.list_subnets(
|
||||
network_id=fake_neutron_net_id,
|
||||
cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response)
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, 'create_subnet')
|
||||
fake_subnet_request = {
|
||||
"subnets": [{
|
||||
'name': fake_cidr_v4,
|
||||
'network_id': fake_neutron_net_id,
|
||||
'ip_version': 4,
|
||||
'cidr': fake_cidr_v4,
|
||||
'enable_dhcp': app.enable_dhcp,
|
||||
'gateway_ip': '192.168.42.1',
|
||||
}]
|
||||
}
|
||||
subnet_v4_id = str(uuid.uuid4())
|
||||
fake_v4_subnet = self._get_fake_v4_subnet(
|
||||
fake_neutron_net_id, subnet_v4_id,
|
||||
name=fake_cidr_v4, cidr=fake_cidr_v4)
|
||||
fake_subnet_response = {
|
||||
'subnets': [
|
||||
fake_v4_subnet['subnet']
|
||||
]
|
||||
}
|
||||
app.neutron.create_subnet(
|
||||
fake_subnet_request).AndReturn(fake_subnet_response)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
network_request = {
|
||||
'NetworkID': docker_network_id,
|
||||
'IPv4Data': [{
|
||||
'AddressSpace': 'foo',
|
||||
'Pool': '192.168.42.0/24',
|
||||
'Gateway': '192.168.42.1/24',
|
||||
}],
|
||||
'IPv6Data': [{
|
||||
'AddressSpace': 'bar',
|
||||
'Pool': 'fe80::/64',
|
||||
'Gateway': 'fe80::f816:3eff:fe20:57c3/64',
|
||||
}],
|
||||
'Options': {
|
||||
'com.docker.network.enable_ipv6': False,
|
||||
'com.docker.network.generic': {
|
||||
'neutron.net.name': 'my_network_name'
|
||||
}
|
||||
}
|
||||
}
|
||||
response = self.app.post('/NetworkDriver.CreateNetwork',
|
||||
content_type='application/json',
|
||||
data=jsonutils.dumps(network_request))
|
||||
|
||||
self.assertEqual(200, response.status_code)
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
|
||||
|
||||
def test_network_driver_create_network_with_netid_option(self):
|
||||
docker_network_id = utils.get_hash()
|
||||
fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
|
||||
self.mox.StubOutWithMock(app.neutron, "list_networks")
|
||||
fake_existing_networks_response = {
|
||||
"networks": [{
|
||||
"status": "ACTIVE",
|
||||
"subnets": [],
|
||||
"admin_state_up": True,
|
||||
"tenant_id": "9bacb3c5d39d41a79512987f338cf177",
|
||||
"router:external": False,
|
||||
"segments": [],
|
||||
"shared": False,
|
||||
"id": fake_neutron_net_id,
|
||||
}]
|
||||
}
|
||||
app.neutron.list_networks(
|
||||
id=fake_neutron_net_id).AndReturn(
|
||||
fake_existing_networks_response)
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, "add_tag")
|
||||
tags = utils.create_net_tags(docker_network_id)
|
||||
for tag in tags:
|
||||
app.neutron.add_tag('networks', fake_neutron_net_id, tag)
|
||||
|
||||
app.neutron.add_tag(
|
||||
'networks', fake_neutron_net_id, 'kuryr.net.existing')
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnets')
|
||||
fake_existing_subnets_response = {
|
||||
"subnets": []
|
||||
}
|
||||
fake_cidr_v4 = '192.168.42.0/24'
|
||||
app.neutron.list_subnets(
|
||||
network_id=fake_neutron_net_id,
|
||||
cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response)
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, 'create_subnet')
|
||||
fake_subnet_request = {
|
||||
"subnets": [{
|
||||
'name': fake_cidr_v4,
|
||||
'network_id': fake_neutron_net_id,
|
||||
'ip_version': 4,
|
||||
'cidr': fake_cidr_v4,
|
||||
'enable_dhcp': app.enable_dhcp,
|
||||
'gateway_ip': '192.168.42.1',
|
||||
}]
|
||||
}
|
||||
subnet_v4_id = str(uuid.uuid4())
|
||||
fake_v4_subnet = self._get_fake_v4_subnet(
|
||||
fake_neutron_net_id, subnet_v4_id,
|
||||
name=fake_cidr_v4, cidr=fake_cidr_v4)
|
||||
fake_subnet_response = {
|
||||
'subnets': [
|
||||
fake_v4_subnet['subnet']
|
||||
]
|
||||
}
|
||||
app.neutron.create_subnet(
|
||||
fake_subnet_request).AndReturn(fake_subnet_response)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
network_request = {
|
||||
'NetworkID': docker_network_id,
|
||||
'IPv4Data': [{
|
||||
'AddressSpace': 'foo',
|
||||
'Pool': '192.168.42.0/24',
|
||||
'Gateway': '192.168.42.1/24',
|
||||
}],
|
||||
'IPv6Data': [{
|
||||
'AddressSpace': 'bar',
|
||||
'Pool': 'fe80::/64',
|
||||
'Gateway': 'fe80::f816:3eff:fe20:57c3/64',
|
||||
}],
|
||||
'Options': {
|
||||
'com.docker.network.enable_ipv6': False,
|
||||
'com.docker.network.generic': {
|
||||
'neutron.net.uuid': '4e8e5957-649f-477b-9e5b-f1f75b21c03c'
|
||||
}
|
||||
}
|
||||
}
|
||||
response = self.app.post('/NetworkDriver.CreateNetwork',
|
||||
content_type='application/json',
|
||||
data=jsonutils.dumps(network_request))
|
||||
|
||||
self.assertEqual(200, response.status_code)
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
|
||||
|
||||
def test_network_driver_create_network_with_pool_name_option(self):
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnetpools')
|
||||
fake_kuryr_subnetpool_id = str(uuid.uuid4())
|
||||
fake_name = "fake_pool_name"
|
||||
kuryr_subnetpools = self._get_fake_v4_subnetpools(
|
||||
fake_kuryr_subnetpool_id, name=fake_name)
|
||||
app.neutron.list_subnetpools(name=fake_name).AndReturn(
|
||||
{'subnetpools': kuryr_subnetpools['subnetpools']})
|
||||
docker_network_id = utils.get_hash()
|
||||
self.mox.StubOutWithMock(app.neutron, "create_network")
|
||||
fake_request = {
|
||||
"network": {
|
||||
"name": utils.make_net_name(docker_network_id),
|
||||
"admin_state_up": True
|
||||
}
|
||||
}
|
||||
# The following fake response is retrieved from the Neutron doc:
|
||||
# http://developer.openstack.org/api-ref-networking-v2.html#createNetwork # noqa
|
||||
fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
|
||||
fake_response = {
|
||||
"network": {
|
||||
"status": "ACTIVE",
|
||||
"subnets": [],
|
||||
"name": utils.make_net_name(docker_network_id),
|
||||
"admin_state_up": True,
|
||||
"tenant_id": "9bacb3c5d39d41a79512987f338cf177",
|
||||
"router:external": False,
|
||||
"segments": [],
|
||||
"shared": False,
|
||||
"id": fake_neutron_net_id
|
||||
}
|
||||
}
|
||||
app.neutron.create_network(fake_request).AndReturn(fake_response)
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, "add_tag")
|
||||
tags = utils.create_net_tags(docker_network_id)
|
||||
for tag in tags:
|
||||
app.neutron.add_tag('networks', fake_neutron_net_id, tag)
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnets')
|
||||
fake_existing_subnets_response = {
|
||||
"subnets": []
|
||||
}
|
||||
fake_cidr_v4 = '192.168.42.0/24'
|
||||
app.neutron.list_subnets(
|
||||
network_id=fake_neutron_net_id,
|
||||
cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response)
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, 'create_subnet')
|
||||
fake_subnet_request = {
|
||||
"subnets": [{
|
||||
'name': fake_cidr_v4,
|
||||
'network_id': fake_neutron_net_id,
|
||||
'ip_version': 4,
|
||||
'cidr': fake_cidr_v4,
|
||||
'enable_dhcp': app.enable_dhcp,
|
||||
'gateway_ip': '192.168.42.1',
|
||||
'subnetpool_id': fake_kuryr_subnetpool_id,
|
||||
}]
|
||||
}
|
||||
subnet_v4_id = str(uuid.uuid4())
|
||||
fake_v4_subnet = self._get_fake_v4_subnet(
|
||||
fake_neutron_net_id, subnet_v4_id,
|
||||
name=fake_cidr_v4, cidr=fake_cidr_v4)
|
||||
fake_subnet_response = {
|
||||
'subnets': [
|
||||
fake_v4_subnet['subnet']
|
||||
]
|
||||
}
|
||||
app.neutron.create_subnet(
|
||||
fake_subnet_request).AndReturn(fake_subnet_response)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
network_request = {
|
||||
'NetworkID': docker_network_id,
|
||||
'IPv4Data': [{
|
||||
'AddressSpace': 'foo',
|
||||
'Pool': '192.168.42.0/24',
|
||||
'Gateway': '192.168.42.1/24',
|
||||
}],
|
||||
'IPv6Data': [{
|
||||
'AddressSpace': 'bar',
|
||||
'Pool': 'fe80::/64',
|
||||
'Gateway': 'fe80::f816:3eff:fe20:57c3/64',
|
||||
}],
|
||||
'Options': {
|
||||
'com.docker.network.enable_ipv6': False,
|
||||
'com.docker.network.generic': {
|
||||
'neutron.pool.name': 'fake_pool_name'
|
||||
}
|
||||
}
|
||||
}
|
||||
response = self.app.post('/NetworkDriver.CreateNetwork',
|
||||
content_type='application/json',
|
||||
data=jsonutils.dumps(network_request))
|
||||
|
||||
self.assertEqual(200, response.status_code)
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
|
||||
|
||||
def test_network_driver_create_network_wo_gw(self):
|
||||
docker_network_id = utils.get_hash()
|
||||
self.mox.StubOutWithMock(app.neutron, "create_network")
|
||||
|
@ -39,13 +39,15 @@ class TestKuryrEndpointFailures(base.TestKuryrFailures):
|
||||
'network_id': neutron_network_id,
|
||||
'ip_version': 4,
|
||||
"cidr": '192.168.1.0/24',
|
||||
'enable_dhcp': 'False'
|
||||
'enable_dhcp': 'False',
|
||||
'subnetpool_id': ''
|
||||
}, {
|
||||
'name': '-'.join([docker_endpoint_id, 'fe80::']),
|
||||
'network_id': neutron_network_id,
|
||||
'ip_version': 6,
|
||||
"cidr": 'fe80::/64',
|
||||
'enable_dhcp': 'False'
|
||||
'enable_dhcp': 'False',
|
||||
'subnetpool_id': ''
|
||||
}]
|
||||
}
|
||||
fake_subnets = self._get_fake_subnets(
|
||||
|
@ -94,23 +94,33 @@ class TestKuryrIpam(base.TestKuryrBase):
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID'])
|
||||
|
||||
def test_ipam_driver_request_pool_with_default_v4pool(self):
|
||||
def test_ipam_driver_request_pool_with_pool_name_option(self):
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnetpools')
|
||||
fake_kuryr_subnetpool_id = str(uuid.uuid4())
|
||||
fake_name = 'kuryr'
|
||||
fake_name = 'fake_pool_name'
|
||||
new_subnetpool = {
|
||||
'name': fake_name,
|
||||
'default_prefixlen': 16,
|
||||
'prefixes': [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(name=fake_name).AndReturn(
|
||||
{'subnetpools': kuryr_subnetpools['subnetpools']})
|
||||
fake_subnetpool_response = {
|
||||
'subnetpool': kuryr_subnetpools['subnetpools'][0]
|
||||
}
|
||||
|
||||
self.mox.StubOutWithMock(app.neutron, 'create_subnetpool')
|
||||
app.neutron.create_subnetpool(
|
||||
{'subnetpool': new_subnetpool}).AndReturn(fake_subnetpool_response)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
fake_request = {
|
||||
'AddressSpace': '',
|
||||
'Pool': '',
|
||||
'Pool': FAKE_IP4_CIDR,
|
||||
'SubPool': '', # In the case --ip-range is not given
|
||||
'Options': {},
|
||||
'Options': {'neutron.pool.name': 'fake_pool_name'},
|
||||
'V6': False
|
||||
}
|
||||
response = self.app.post('/IpamDriver.RequestPool',
|
||||
@ -228,6 +238,84 @@ 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_overlapping_cidr(self):
|
||||
# faking list_subnetpools
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnetpools')
|
||||
|
||||
fake_kuryr_subnetpool_id = str(uuid.uuid4())
|
||||
fake_kuryr_subnetpool_id2 = 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())
|
||||
neutron_network_id2 = str(uuid.uuid4())
|
||||
|
||||
neutron_subnet_v4_id = str(uuid.uuid4())
|
||||
neutron_subnet_v4_id2 = str(uuid.uuid4())
|
||||
|
||||
fake_v4_subnet = self._get_fake_v4_subnet(
|
||||
neutron_network_id, docker_endpoint_id, neutron_subnet_v4_id,
|
||||
subnetpool_id=fake_kuryr_subnetpool_id,
|
||||
cidr=FAKE_IP4_CIDR)
|
||||
|
||||
fake_v4_subnet2 = self._get_fake_v4_subnet(
|
||||
neutron_network_id2, docker_endpoint_id, neutron_subnet_v4_id2,
|
||||
subnetpool_id=fake_kuryr_subnetpool_id2,
|
||||
cidr=FAKE_IP4_CIDR)
|
||||
|
||||
fake_subnet_response = {
|
||||
'subnets': [
|
||||
fake_v4_subnet2['subnet'],
|
||||
fake_v4_subnet['subnet']
|
||||
]
|
||||
}
|
||||
self.mox.StubOutWithMock(app.neutron, 'list_subnets')
|
||||
app.neutron.list_subnets(cidr=FAKE_IP4_CIDR).AndReturn(
|
||||
fake_subnet_response)
|
||||
# faking create_port
|
||||
fake_neutron_port_id = str(uuid.uuid4())
|
||||
fake_port = base.TestKuryrBase._get_fake_port(
|
||||
docker_endpoint_id, neutron_network_id,
|
||||
fake_neutron_port_id,
|
||||
neutron_subnet_v4_id=neutron_subnet_v4_id,
|
||||
neutron_subnet_v4_address="10.0.0.5")
|
||||
port_request = {
|
||||
'name': 'kuryr-unbound-port',
|
||||
'admin_state_up': True,
|
||||
'network_id': neutron_network_id,
|
||||
'binding:host_id': utils.get_hostname(),
|
||||
}
|
||||
port_request['fixed_ips'] = []
|
||||
fixed_ip = {'subnet_id': neutron_subnet_v4_id}
|
||||
port_request['fixed_ips'].append(fixed_ip)
|
||||
self.mox.StubOutWithMock(app.neutron, 'create_port')
|
||||
app.neutron.create_port({'port': port_request}).AndReturn(fake_port)
|
||||
|
||||
# Apply mocks
|
||||
self.mox.ReplayAll()
|
||||
|
||||
# Testing container ip allocation
|
||||
fake_request = {
|
||||
'PoolID': fake_kuryr_subnetpool_id,
|
||||
'Address': '', # Querying for container 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('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')
|
||||
|
Loading…
Reference in New Issue
Block a user