Support for existing Neutron nets

An existing Neutron network can be specified as the network
being used for a Docker network being created. The Neutron
network id or name can be specified.

If a Docker network is deleted, the corresponding pre existing
Neutron network will not be deleted.

Usage:
 docker network create -d kuryr --ipam-driver=kuryr
     --subnet=10.10.0.0/24 --gateway=10.10.0.1
     -o neutron.net.uuid=d98d1259-03d1-4b45-9b86-b039cba1d90d mynet

 docker network create -d kuryr --ipam-driver=kuryr
     --subnet=10.10.0.0/24 --gateway=10.10.0.1
     -o neutron.net.name=my_neutron_net mynet

If subnet being specified does not exist, it will be created by
Kuryr. If exists it will be used.

Blueprint existing-neutron-network

Change-Id: I570aa4e77c906d3f04768e882f02050cd0cad558
This commit is contained in:
Mohammad Banikazemi 2016-03-28 15:18:39 -04:00
parent 794a9444e0
commit b25eca0d7d
6 changed files with 288 additions and 61 deletions

View File

@ -23,3 +23,8 @@ DEVICE_OWNER = 'kuryr:container'
NEUTRON_ID_LH_OPTION = 'kuryr.net.uuid.lh' 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-'
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'

View File

@ -327,10 +327,24 @@ def _create_or_update_port(neutron_network_id, endpoint_id,
return response_interface return response_interface
def _neutron_add_tags(netid, tag): def _neutron_net_add_tag(netid, tag):
app.neutron.add_tag('networks', netid, tag)
def _neutron_net_add_tags(netid, tag):
tags = utils.create_net_tags(tag) tags = utils.create_net_tags(tag)
for tag in tags: for tag in tags:
app.neutron.add_tag('networks', netid, tag) _neutron_net_add_tag(netid, tag)
def _neutron_net_remove_tag(netid, tag):
app.neutron.remove_tag('networks', netid, tag)
def _neutron_net_remove_tags(netid, tag):
tags = utils.create_net_tags(tag)
for tag in tags:
_neutron_net_remove_tag(netid, tag)
@app.route('/Plugin.Activate', methods=['POST']) @app.route('/Plugin.Activate', methods=['POST'])
@ -449,23 +463,50 @@ def network_driver_create_network():
app.logger.debug("gateway_cidr {0}, gateway_ip {1}" app.logger.debug("gateway_cidr {0}, gateway_ip {1}"
.format(gateway_cidr, gateway_ip)) .format(gateway_cidr, gateway_ip))
network = app.neutron.create_network( neutron_uuid = None
{'network': {'name': neutron_network_name, "admin_state_up": True}}) neutron_name = None
_neutron_add_tags(network['network']['id'], container_net_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)
app.logger.info(_LI("Created a new network with name {0}" if not neutron_uuid and not neutron_name:
" successfully: {1}") network = app.neutron.create_network(
.format(neutron_network_name, network)) {'network': {'name': neutron_network_name,
"admin_state_up": True}})
network_id = network['network']['id']
_neutron_net_add_tags(network['network']['id'], container_net_id)
app.logger.info(_LI("Created a new network with name {0}"
" successfully: {1}")
.format(neutron_network_name, network))
else:
try:
if neutron_uuid:
networks = _get_networks_by_attrs(id=neutron_uuid)
else:
networks = _get_networks_by_attrs(name=neutron_name)
network_id = networks[0]['id']
except n_exceptions.NeutronClientException as ex:
app.logger.error(_LE("Error happened during listing "
"Neutron networks: {0}").format(ex))
raise
_neutron_net_add_tags(network_id, container_net_id)
_neutron_net_add_tag(network_id, const.KURYR_EXISTING_NEUTRON_NET)
app.logger.info(_LI("Using existing network {0} successfully")
.format(neutron_uuid))
cidr = netaddr.IPNetwork(pool_cidr) cidr = netaddr.IPNetwork(pool_cidr)
subnet_network = str(cidr.network) subnet_network = str(cidr.network)
subnet_cidr = '/'.join([subnet_network, str(cidr.prefixlen)]) subnet_cidr = '/'.join([subnet_network, str(cidr.prefixlen)])
subnets = _get_subnets_by_attrs( subnets = _get_subnets_by_attrs(
network_id=network['network']['id'], cidr=subnet_cidr) network_id=network_id, cidr=subnet_cidr)
if not subnets: if not subnets:
new_subnets = [{ new_subnets = [{
'name': pool_cidr, 'name': pool_cidr,
'network_id': network['network']['id'], 'network_id': network_id,
'ip_version': cidr.version, 'ip_version': cidr.version,
'cidr': subnet_cidr, 'cidr': subnet_cidr,
'enable_dhcp': app.enable_dhcp, 'enable_dhcp': app.enable_dhcp,
@ -498,21 +539,36 @@ def network_driver_delete_network():
" /NetworkDriver.DeleteNetwork".format(json_data)) " /NetworkDriver.DeleteNetwork".format(json_data))
jsonschema.validate(json_data, schemata.NETWORK_DELETE_SCHEMA) jsonschema.validate(json_data, schemata.NETWORK_DELETE_SCHEMA)
neutron_network_tags = utils.make_net_tags(json_data['NetworkID']) container_net_id = json_data['NetworkID']
neutron_network_tags = utils.make_net_tags(container_net_id)
existing_network_tags = neutron_network_tags + ','
existing_network_tags += const.KURYR_EXISTING_NEUTRON_NET
try:
existing_networks = _get_networks_by_attrs(tags=existing_network_tags)
except n_exceptions.NeutronClientException as ex:
app.logger.error(_LE("Error happened during listing "
"Neutron networks: {0}").format(ex))
raise
if existing_networks:
app.logger.warn(_LW("Network is a pre existing Neutron network, "
"not deleting in Neutron. removing tags: {0}")
.format(existing_network_tags))
neutron_net_id = existing_networks[0]['id']
_neutron_net_remove_tags(neutron_net_id, container_net_id)
_neutron_net_remove_tag(neutron_net_id,
const.KURYR_EXISTING_NEUTRON_NET)
return flask.jsonify(const.SCHEMA['SUCCESS'])
try: try:
filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags)
except n_exceptions.NeutronClientException as ex: except n_exceptions.NeutronClientException as ex:
app.logger.error(_LE("Error happened during listing " app.logger.error(_LE("Error happened during listing "
"Neutron networks: {0}").format(ex)) "Neutron networks: {0}").format(ex))
raise raise
# We assume Neutron's Network names are not conflicted in Kuryr because
# they are Docker IDs, 256 bits hashed values, which are rarely conflicted.
# However, if there're multiple networks associated with the single
# NetworkID, it raises DuplicatedResourceException and stops processes.
# See the following doc for more details about Docker's IDs:
# https://github.com/docker/docker/blob/master/docs/terms/container.md#container-ids # noqa
if not filtered_networks: if not filtered_networks:
app.logger.warn("Network with tags {0} cannot be found" app.logger.warn(_LW("Network with tags {0} cannot be found")
.format(neutron_network_tags)) .format(neutron_network_tags))
else: else:
neutron_network_id = filtered_networks[0]['id'] neutron_network_id = filtered_networks[0]['id']

View File

@ -14,6 +14,7 @@ from neutronclient.tests.unit import test_cli20
from kuryr import app from kuryr import app
from kuryr import binding from kuryr import binding
from kuryr.common import constants as const
from kuryr import utils from kuryr import utils
@ -56,12 +57,15 @@ class TestKuryrBase(TestCase):
self.mox.ReplayAll() self.mox.ReplayAll()
return fake_unbinding_response return fake_unbinding_response
def _mock_out_network(self, neutron_network_id, docker_network_id): def _mock_out_network(self, neutron_network_id, docker_network_id,
check_existing=False):
no_networks_response = {
"networks": []
}
fake_list_response = { fake_list_response = {
"networks": [{ "networks": [{
"status": "ACTIVE", "status": "ACTIVE",
"subnets": [], "subnets": [],
"name": utils.make_net_name(docker_network_id),
"admin_state_up": True, "admin_state_up": True,
"tenant_id": "9bacb3c5d39d41a79512987f338cf177", "tenant_id": "9bacb3c5d39d41a79512987f338cf177",
"router:external": False, "router:external": False,
@ -72,9 +76,13 @@ class TestKuryrBase(TestCase):
} }
self.mox.StubOutWithMock(app.neutron, 'list_networks') self.mox.StubOutWithMock(app.neutron, 'list_networks')
t = utils.make_net_tags(docker_network_id) t = utils.make_net_tags(docker_network_id)
if check_existing:
te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET
app.neutron.list_networks(tags=te).AndReturn(
no_networks_response)
app.neutron.list_networks(tags=t).AndReturn(fake_list_response) app.neutron.list_networks(tags=t).AndReturn(fake_list_response)
self.mox.ReplayAll()
self.mox.ReplayAll()
return neutron_network_id return neutron_network_id
@staticmethod @staticmethod

View File

@ -69,7 +69,7 @@ class TestKuryr(base.TestKuryrBase):
} }
# The following fake response is retrieved from the Neutron doc: # The following fake response is retrieved from the Neutron doc:
# http://developer.openstack.org/api-ref-networking-v2.html#createNetwork # noqa # http://developer.openstack.org/api-ref-networking-v2.html#createNetwork # noqa
fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
fake_response = { fake_response = {
"network": { "network": {
"status": "ACTIVE", "status": "ACTIVE",
@ -80,7 +80,7 @@ class TestKuryr(base.TestKuryrBase):
"router:external": False, "router:external": False,
"segments": [], "segments": [],
"shared": False, "shared": False,
"id": fake_neutron_network_id "id": fake_neutron_net_id
} }
} }
app.neutron.create_network(fake_request).AndReturn(fake_response) app.neutron.create_network(fake_request).AndReturn(fake_response)
@ -88,7 +88,7 @@ class TestKuryr(base.TestKuryrBase):
self.mox.StubOutWithMock(app.neutron, "add_tag") self.mox.StubOutWithMock(app.neutron, "add_tag")
tags = utils.create_net_tags(docker_network_id) tags = utils.create_net_tags(docker_network_id)
for tag in tags: for tag in tags:
app.neutron.add_tag('networks', fake_neutron_network_id, tag) app.neutron.add_tag('networks', fake_neutron_net_id, tag)
self.mox.StubOutWithMock(app.neutron, 'list_subnets') self.mox.StubOutWithMock(app.neutron, 'list_subnets')
fake_existing_subnets_response = { fake_existing_subnets_response = {
@ -96,14 +96,14 @@ class TestKuryr(base.TestKuryrBase):
} }
fake_cidr_v4 = '192.168.42.0/24' fake_cidr_v4 = '192.168.42.0/24'
app.neutron.list_subnets( app.neutron.list_subnets(
network_id=fake_neutron_network_id, network_id=fake_neutron_net_id,
cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response) cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response)
self.mox.StubOutWithMock(app.neutron, 'create_subnet') self.mox.StubOutWithMock(app.neutron, 'create_subnet')
fake_subnet_request = { fake_subnet_request = {
"subnets": [{ "subnets": [{
'name': fake_cidr_v4, 'name': fake_cidr_v4,
'network_id': fake_neutron_network_id, 'network_id': fake_neutron_net_id,
'ip_version': 4, 'ip_version': 4,
'cidr': fake_cidr_v4, 'cidr': fake_cidr_v4,
'enable_dhcp': app.enable_dhcp, 'enable_dhcp': app.enable_dhcp,
@ -112,7 +112,7 @@ class TestKuryr(base.TestKuryrBase):
} }
subnet_v4_id = str(uuid.uuid4()) subnet_v4_id = str(uuid.uuid4())
fake_v4_subnet = self._get_fake_v4_subnet( fake_v4_subnet = self._get_fake_v4_subnet(
fake_neutron_network_id, subnet_v4_id, fake_neutron_net_id, subnet_v4_id,
name=fake_cidr_v4, cidr=fake_cidr_v4) name=fake_cidr_v4, cidr=fake_cidr_v4)
fake_subnet_response = { fake_subnet_response = {
'subnets': [ 'subnets': [
@ -158,7 +158,7 @@ class TestKuryr(base.TestKuryrBase):
} }
# The following fake response is retrieved from the Neutron doc: # The following fake response is retrieved from the Neutron doc:
# http://developer.openstack.org/api-ref-networking-v2.html#createNetwork # noqa # http://developer.openstack.org/api-ref-networking-v2.html#createNetwork # noqa
fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
fake_response = { fake_response = {
"network": { "network": {
"status": "ACTIVE", "status": "ACTIVE",
@ -169,7 +169,7 @@ class TestKuryr(base.TestKuryrBase):
"router:external": False, "router:external": False,
"segments": [], "segments": [],
"shared": False, "shared": False,
"id": fake_neutron_network_id "id": fake_neutron_net_id
} }
} }
app.neutron.create_network(fake_request).AndReturn(fake_response) app.neutron.create_network(fake_request).AndReturn(fake_response)
@ -177,7 +177,7 @@ class TestKuryr(base.TestKuryrBase):
self.mox.StubOutWithMock(app.neutron, "add_tag") self.mox.StubOutWithMock(app.neutron, "add_tag")
tags = utils.create_net_tags(docker_network_id) tags = utils.create_net_tags(docker_network_id)
for tag in tags: for tag in tags:
app.neutron.add_tag('networks', fake_neutron_network_id, tag) app.neutron.add_tag('networks', fake_neutron_net_id, tag)
self.mox.StubOutWithMock(app.neutron, 'list_subnets') self.mox.StubOutWithMock(app.neutron, 'list_subnets')
fake_existing_subnets_response = { fake_existing_subnets_response = {
@ -185,14 +185,14 @@ class TestKuryr(base.TestKuryrBase):
} }
fake_cidr_v4 = '192.168.42.0/24' fake_cidr_v4 = '192.168.42.0/24'
app.neutron.list_subnets( app.neutron.list_subnets(
network_id=fake_neutron_network_id, network_id=fake_neutron_net_id,
cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response) cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response)
self.mox.StubOutWithMock(app.neutron, 'create_subnet') self.mox.StubOutWithMock(app.neutron, 'create_subnet')
fake_subnet_request = { fake_subnet_request = {
"subnets": [{ "subnets": [{
'name': fake_cidr_v4, 'name': fake_cidr_v4,
'network_id': fake_neutron_network_id, 'network_id': fake_neutron_net_id,
'ip_version': 4, 'ip_version': 4,
'cidr': fake_cidr_v4, 'cidr': fake_cidr_v4,
'enable_dhcp': app.enable_dhcp, 'enable_dhcp': app.enable_dhcp,
@ -200,7 +200,7 @@ class TestKuryr(base.TestKuryrBase):
} }
subnet_v4_id = str(uuid.uuid4()) subnet_v4_id = str(uuid.uuid4())
fake_v4_subnet = self._get_fake_v4_subnet( fake_v4_subnet = self._get_fake_v4_subnet(
fake_neutron_network_id, subnet_v4_id, fake_neutron_net_id, subnet_v4_id,
name=fake_cidr_v4, cidr=fake_cidr_v4) name=fake_cidr_v4, cidr=fake_cidr_v4)
fake_subnet_response = { fake_subnet_response = {
'subnets': [ 'subnets': [
@ -236,15 +236,16 @@ class TestKuryr(base.TestKuryrBase):
def test_network_driver_delete_network(self): def test_network_driver_delete_network(self):
docker_network_id = hashlib.sha256( docker_network_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_neutron_network_id = str(uuid.uuid4()) fake_neutron_net_id = str(uuid.uuid4())
self._mock_out_network(fake_neutron_network_id, docker_network_id) self._mock_out_network(fake_neutron_net_id, docker_network_id,
check_existing=True)
self.mox.StubOutWithMock(app.neutron, 'list_subnets') self.mox.StubOutWithMock(app.neutron, 'list_subnets')
fake_neutron_subnets_response = {"subnets": []} fake_neutron_subnets_response = {"subnets": []}
app.neutron.list_subnets(network_id=fake_neutron_network_id).AndReturn( app.neutron.list_subnets(network_id=fake_neutron_net_id).AndReturn(
fake_neutron_subnets_response) fake_neutron_subnets_response)
self.mox.StubOutWithMock(app.neutron, 'delete_network') self.mox.StubOutWithMock(app.neutron, 'delete_network')
app.neutron.delete_network(fake_neutron_network_id).AndReturn(None) app.neutron.delete_network(fake_neutron_net_id).AndReturn(None)
self.mox.ReplayAll() self.mox.ReplayAll()
data = {'NetworkID': docker_network_id} data = {'NetworkID': docker_network_id}
@ -262,8 +263,9 @@ class TestKuryr(base.TestKuryrBase):
docker_endpoint_id = hashlib.sha256( docker_endpoint_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_neutron_network_id = str(uuid.uuid4()) fake_neutron_net_id = str(uuid.uuid4())
self._mock_out_network(fake_neutron_network_id, docker_network_id) self._mock_out_network(fake_neutron_net_id, docker_network_id,
check_existing=True)
# The following fake response is retrieved from the Neutron doc: # The following fake response is retrieved from the Neutron doc:
# http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa # http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa
subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031" subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031"
@ -280,7 +282,7 @@ class TestKuryr(base.TestKuryrBase):
} }
self.mox.StubOutWithMock(app.neutron, 'list_subnets') self.mox.StubOutWithMock(app.neutron, 'list_subnets')
app.neutron.list_subnets(network_id=fake_neutron_network_id).AndReturn( app.neutron.list_subnets(network_id=fake_neutron_net_id).AndReturn(
fake_subnets_response) fake_subnets_response)
self.mox.StubOutWithMock(app.neutron, 'list_subnetpools') self.mox.StubOutWithMock(app.neutron, 'list_subnetpools')
@ -295,7 +297,7 @@ class TestKuryr(base.TestKuryrBase):
app.neutron.delete_subnet(subnet_v6_id).AndReturn(None) app.neutron.delete_subnet(subnet_v6_id).AndReturn(None)
self.mox.StubOutWithMock(app.neutron, 'delete_network') self.mox.StubOutWithMock(app.neutron, 'delete_network')
app.neutron.delete_network(fake_neutron_network_id).AndReturn(None) app.neutron.delete_network(fake_neutron_net_id).AndReturn(None)
self.mox.ReplayAll() self.mox.ReplayAll()
data = {'NetworkID': docker_network_id} data = {'NetworkID': docker_network_id}
@ -313,8 +315,8 @@ class TestKuryr(base.TestKuryrBase):
docker_endpoint_id = hashlib.sha256( docker_endpoint_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_neutron_network_id = str(uuid.uuid4()) fake_neutron_net_id = str(uuid.uuid4())
self._mock_out_network(fake_neutron_network_id, docker_network_id) self._mock_out_network(fake_neutron_net_id, docker_network_id)
# The following fake response is retrieved from the Neutron doc: # The following fake response is retrieved from the Neutron doc:
# http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa # http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa
@ -337,17 +339,17 @@ class TestKuryr(base.TestKuryrBase):
} }
self.mox.StubOutWithMock(app.neutron, 'list_subnets') self.mox.StubOutWithMock(app.neutron, 'list_subnets')
app.neutron.list_subnets(network_id=fake_neutron_network_id, app.neutron.list_subnets(network_id=fake_neutron_net_id,
cidr='192.168.1.0/24').AndReturn(fake_subnetv4_response) cidr='192.168.1.0/24').AndReturn(fake_subnetv4_response)
app.neutron.list_subnets( app.neutron.list_subnets(
network_id=fake_neutron_network_id, network_id=fake_neutron_net_id,
cidr='fe80::/64').AndReturn(fake_subnetv6_response) cidr='fe80::/64').AndReturn(fake_subnetv6_response)
fake_ipv4cidr = '192.168.1.2/24' fake_ipv4cidr = '192.168.1.2/24'
fake_ipv6cidr = 'fe80::f816:3eff:fe20:57c4/64' fake_ipv6cidr = 'fe80::f816:3eff:fe20:57c4/64'
fake_port_id = str(uuid.uuid4()) fake_port_id = str(uuid.uuid4())
fake_port = self._get_fake_port( fake_port = self._get_fake_port(
docker_endpoint_id, fake_neutron_network_id, docker_endpoint_id, fake_neutron_net_id,
fake_port_id, fake_port_id,
subnet_v4_id, subnet_v6_id) subnet_v4_id, subnet_v6_id)
fake_fixed_ips = ['subnet_id=%s' % subnet_v4_id, fake_fixed_ips = ['subnet_id=%s' % subnet_v4_id,
@ -408,15 +410,15 @@ class TestKuryr(base.TestKuryrBase):
self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_network_driver_join(self): def test_network_driver_join(self):
fake_docker_network_id = hashlib.sha256( fake_docker_net_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_docker_endpoint_id = hashlib.sha256( fake_docker_endpoint_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_container_id = hashlib.sha256( fake_container_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_neutron_network_id = str(uuid.uuid4()) fake_neutron_net_id = str(uuid.uuid4())
self._mock_out_network(fake_neutron_network_id, fake_docker_network_id) self._mock_out_network(fake_neutron_net_id, fake_docker_net_id)
fake_neutron_port_id = str(uuid.uuid4()) fake_neutron_port_id = str(uuid.uuid4())
self.mox.StubOutWithMock(app.neutron, 'list_ports') self.mox.StubOutWithMock(app.neutron, 'list_ports')
neutron_port_name = utils.get_neutron_port_name( neutron_port_name = utils.get_neutron_port_name(
@ -424,7 +426,7 @@ class TestKuryr(base.TestKuryrBase):
fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v4_subnet_id = str(uuid.uuid4())
fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4())
fake_neutron_ports_response = self._get_fake_ports( fake_neutron_ports_response = self._get_fake_ports(
fake_docker_endpoint_id, fake_neutron_network_id, fake_docker_endpoint_id, fake_neutron_net_id,
fake_neutron_port_id, fake_neutron_port_id,
fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id)
app.neutron.list_ports(name=neutron_port_name).AndReturn( app.neutron.list_ports(name=neutron_port_name).AndReturn(
@ -432,9 +434,9 @@ class TestKuryr(base.TestKuryrBase):
self.mox.StubOutWithMock(app.neutron, 'list_subnets') self.mox.StubOutWithMock(app.neutron, 'list_subnets')
fake_neutron_subnets_response = self._get_fake_subnets( fake_neutron_subnets_response = self._get_fake_subnets(
fake_docker_endpoint_id, fake_neutron_network_id, fake_docker_endpoint_id, fake_neutron_net_id,
fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id)
app.neutron.list_subnets(network_id=fake_neutron_network_id).AndReturn( app.neutron.list_subnets(network_id=fake_neutron_net_id).AndReturn(
fake_neutron_subnets_response) fake_neutron_subnets_response)
fake_neutron_port = fake_neutron_ports_response['ports'][0] fake_neutron_port = fake_neutron_ports_response['ports'][0]
fake_neutron_subnets = fake_neutron_subnets_response['subnets'] fake_neutron_subnets = fake_neutron_subnets_response['subnets']
@ -446,7 +448,7 @@ class TestKuryr(base.TestKuryrBase):
for subnet in fake_neutron_subnets} for subnet in fake_neutron_subnets}
join_request = { join_request = {
'NetworkID': fake_docker_network_id, 'NetworkID': fake_docker_net_id,
'EndpointID': fake_docker_endpoint_id, 'EndpointID': fake_docker_endpoint_id,
'SandboxKey': utils.get_sandbox_key(fake_container_id), 'SandboxKey': utils.get_sandbox_key(fake_container_id),
'Options': {}, 'Options': {},
@ -474,13 +476,13 @@ class TestKuryr(base.TestKuryrBase):
self.assertEqual(expected_response, decoded_json) self.assertEqual(expected_response, decoded_json)
def test_network_driver_leave(self): def test_network_driver_leave(self):
fake_docker_network_id = hashlib.sha256( fake_docker_net_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_docker_endpoint_id = hashlib.sha256( fake_docker_endpoint_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest() utils.getrandbits(256)).hexdigest()
fake_neutron_network_id = str(uuid.uuid4()) fake_neutron_net_id = str(uuid.uuid4())
self._mock_out_network(fake_neutron_network_id, fake_docker_network_id) self._mock_out_network(fake_neutron_net_id, fake_docker_net_id)
fake_neutron_port_id = str(uuid.uuid4()) fake_neutron_port_id = str(uuid.uuid4())
self.mox.StubOutWithMock(app.neutron, 'list_ports') self.mox.StubOutWithMock(app.neutron, 'list_ports')
neutron_port_name = utils.get_neutron_port_name( neutron_port_name = utils.get_neutron_port_name(
@ -488,7 +490,7 @@ class TestKuryr(base.TestKuryrBase):
fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v4_subnet_id = str(uuid.uuid4())
fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4())
fake_neutron_ports_response = self._get_fake_ports( fake_neutron_ports_response = self._get_fake_ports(
fake_docker_endpoint_id, fake_neutron_network_id, fake_docker_endpoint_id, fake_neutron_net_id,
fake_neutron_port_id, fake_neutron_port_id,
fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id)
app.neutron.list_ports(name=neutron_port_name).AndReturn( app.neutron.list_ports(name=neutron_port_name).AndReturn(
@ -498,7 +500,7 @@ class TestKuryr(base.TestKuryrBase):
self._mock_out_unbinding(fake_docker_endpoint_id, fake_neutron_port) self._mock_out_unbinding(fake_docker_endpoint_id, fake_neutron_port)
leave_request = { leave_request = {
'NetworkID': fake_docker_network_id, 'NetworkID': fake_docker_net_id,
'EndpointID': fake_docker_endpoint_id, 'EndpointID': fake_docker_endpoint_id,
} }
response = self.app.post('/NetworkDriver.Leave', response = self.app.post('/NetworkDriver.Leave',

View File

@ -0,0 +1,147 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import hashlib
import uuid
from ddt import ddt
from oslo_serialization import jsonutils
from kuryr import app
from kuryr.common import constants as const
from kuryr.tests.unit import base
from kuryr import utils
@ddt
class TestKuryrNetworkPreExisting(base.TestKuryrBase):
def _ids(self):
docker_network_id = hashlib.sha256(
utils.getrandbits(256)).hexdigest()
fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
fake_response = {
'networks':
[
{
"status": "ACTIVE",
"subnets": [],
"admin_state_up": True,
"tenant_id": "9bacb3c5d39d41a79512987f338cf177",
"router:external": False,
"segments": [],
"shared": False,
"id": fake_neutron_net_id
}
]
}
return docker_network_id, fake_neutron_net_id, fake_response
def test_create_network_pre_existing(self):
docker_network_id, fake_neutron_net_id, fake_response = self._ids()
self.mox.StubOutWithMock(app.neutron, "list_networks")
app.neutron.list_networks(id=fake_neutron_net_id).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)
app.neutron.add_tag('networks', fake_neutron_net_id,
const.KURYR_EXISTING_NEUTRON_NET)
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': {
const.NETWORK_GENERIC_OPTIONS: {
const.NEUTRON_UUID_OPTION: fake_neutron_net_id
}
}
}
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(const.SCHEMA['SUCCESS'], decoded_json)
def test_delete_network_pre_existing(self):
docker_network_id, fake_neutron_net_id, fake_response = self._ids()
self.mox.StubOutWithMock(app.neutron, 'list_networks')
t = utils.make_net_tags(docker_network_id)
te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET
app.neutron.list_networks(tags=te).AndReturn(
fake_response)
self.mox.StubOutWithMock(app.neutron, "remove_tag")
tags = utils.create_net_tags(docker_network_id)
for tag in tags:
app.neutron.remove_tag('networks', fake_neutron_net_id, tag)
app.neutron.remove_tag('networks', fake_neutron_net_id,
const.KURYR_EXISTING_NEUTRON_NET)
self.mox.ReplayAll()
data = {'NetworkID': docker_network_id}
response = self.app.post('/NetworkDriver.DeleteNetwork',
content_type='application/json',
data=jsonutils.dumps(data))
self.assertEqual(200, response.status_code)
decoded_json = jsonutils.loads(response.data)
self.assertEqual(const.SCHEMA['SUCCESS'], decoded_json)

View File

@ -18,6 +18,7 @@ from neutronclient.common import exceptions
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from kuryr import app from kuryr import app
from kuryr.common import constants as const
from kuryr.tests.unit import base from kuryr.tests.unit import base
from kuryr import utils from kuryr import utils
@ -97,10 +98,11 @@ class TestKuryrNetworkDeleteFailures(base.TestKuryrFailures):
""" """
def _delete_network_with_exception(self, network_id, ex): def _delete_network_with_exception(self, network_id, ex):
fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
no_networks_response = {
"networks": []
}
if ex == exceptions.NotFound: if ex == exceptions.NotFound:
fake_networks_response = { fake_networks_response = no_networks_response
"networks": []
}
else: else:
fake_networks_response = { fake_networks_response = {
"networks": [{ "networks": [{
@ -117,6 +119,8 @@ class TestKuryrNetworkDeleteFailures(base.TestKuryrFailures):
} }
self.mox.StubOutWithMock(app.neutron, 'list_networks') self.mox.StubOutWithMock(app.neutron, 'list_networks')
t = utils.make_net_tags(network_id) t = utils.make_net_tags(network_id)
te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET
app.neutron.list_networks(tags=te).AndReturn(no_networks_response)
app.neutron.list_networks(tags=t).AndReturn(fake_networks_response) app.neutron.list_networks(tags=t).AndReturn(fake_networks_response)
subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031" subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031"
subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51" subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51"
@ -158,6 +162,9 @@ class TestKuryrNetworkDeleteFailures(base.TestKuryrFailures):
def _delete_network_with_subnet_exception(self, network_id, ex): def _delete_network_with_subnet_exception(self, network_id, ex):
fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
no_networks_response = {
"networks": []
}
fake_networks_response = { fake_networks_response = {
"networks": [{ "networks": [{
"status": "ACTIVE", "status": "ACTIVE",
@ -173,6 +180,8 @@ class TestKuryrNetworkDeleteFailures(base.TestKuryrFailures):
} }
self.mox.StubOutWithMock(app.neutron, 'list_networks') self.mox.StubOutWithMock(app.neutron, 'list_networks')
t = utils.make_net_tags(network_id) t = utils.make_net_tags(network_id)
te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET
app.neutron.list_networks(tags=te).AndReturn(no_networks_response)
app.neutron.list_networks(tags=t).AndReturn(fake_networks_response) app.neutron.list_networks(tags=t).AndReturn(fake_networks_response)
subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031" subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031"
subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51" subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51"