Support tagging existing subnetpool

Change-Id: Iee68cbff7a491a8d0dda9aa05e677adc9ea30481
Closes-Bug: #1671222
This commit is contained in:
Hongbin Lu 2017-06-03 17:18:30 +00:00
parent f4102b4868
commit 3bc383a6a8
5 changed files with 83 additions and 14 deletions

View File

@ -34,6 +34,7 @@ NEUTRON_ID_UH_OPTION = 'kuryr.net.uuid.uh'
DOCKER_EXPOSED_PORTS_OPTION = 'com.docker.network.endpoint.exposedports' DOCKER_EXPOSED_PORTS_OPTION = 'com.docker.network.endpoint.exposedports'
KURYR_EXISTING_NEUTRON_NET = 'kuryr.net.existing' KURYR_EXISTING_NEUTRON_NET = 'kuryr.net.existing'
KURYR_EXISTING_NEUTRON_SUBNETPOOL = 'kuryr.subnetpool.existing'
KURYR_EXISTING_NEUTRON_PORT = 'kuryr.port.existing' KURYR_EXISTING_NEUTRON_PORT = 'kuryr.port.existing'
NETWORK_GATEWAY_OPTIONS = 'com.docker.network.gateway' NETWORK_GATEWAY_OPTIONS = 'com.docker.network.gateway'
NETWORK_GENERIC_OPTIONS = 'com.docker.network.generic' NETWORK_GENERIC_OPTIONS = 'com.docker.network.generic'

View File

@ -305,6 +305,14 @@ def _neutron_net_remove_tags(netid, tag):
_neutron_net_remove_tag(netid, tag) _neutron_net_remove_tag(netid, tag)
def _neutron_subnetpool_add_tag(poolid, tag):
_neutron_add_tag('subnetpools', poolid, tag)
def _neutron_subnetpool_remove_tag(poolid, tag):
_neutron_remove_tag('subnetpools', poolid, tag)
def _neutron_subnet_add_tag(subnetid, tag): def _neutron_subnet_add_tag(subnetid, tag):
_neutron_add_tag('subnets', subnetid, tag) _neutron_add_tag('subnets', subnetid, tag)
@ -1452,6 +1460,9 @@ def ipam_request_pool():
"exist.").format(pool_id or pool_name)) "exist.").format(pool_id or pool_name))
pool_id = existing_pools[0]['id'] pool_id = existing_pools[0]['id']
if app.tag_ext:
_neutron_subnetpool_add_tag(
pool_id, const.KURYR_EXISTING_NEUTRON_SUBNETPOOL)
prefixes = existing_pools[0]['prefixes'] prefixes = existing_pools[0]['prefixes']
pool_cidr = ipaddress.ip_network(six.text_type(prefixes[0])) pool_cidr = ipaddress.ip_network(six.text_type(prefixes[0]))
if pool_cidr == cidr: if pool_cidr == cidr:
@ -1660,7 +1671,15 @@ def ipam_release_pool():
pools = _get_subnetpools_by_attrs(id=pool_id) pools = _get_subnetpools_by_attrs(id=pool_id)
if pools: if pools:
pool_name = pools[0]['name'] pool_name = pools[0]['name']
if not pool_name.startswith(cfg.CONF.subnetpool_name_prefix): if app.tag_ext:
tags = pools[0].get('tags', [])
if const.KURYR_EXISTING_NEUTRON_SUBNETPOOL in tags:
_neutron_subnetpool_remove_tag(
pool_id, const.KURYR_EXISTING_NEUTRON_SUBNETPOOL)
LOG.debug('Skip the cleanup since this is an existing Neutron '
'subnetpool.')
return flask.jsonify(const.SCHEMA['SUCCESS'])
elif not pool_name.startswith(cfg.CONF.subnetpool_name_prefix):
LOG.debug('Skip the cleanup since this is an existing Neutron ' LOG.debug('Skip the cleanup since this is an existing Neutron '
'subnetpool.') 'subnetpool.')
return flask.jsonify(const.SCHEMA['SUCCESS']) return flask.jsonify(const.SCHEMA['SUCCESS'])

View File

@ -76,9 +76,11 @@ class TestKuryrBase(TestCase):
@staticmethod @staticmethod
def _get_fake_v4_subnetpools(subnetpool_id, prefixes=["192.168.1.0/24"], def _get_fake_v4_subnetpools(subnetpool_id, prefixes=["192.168.1.0/24"],
name="kuryr"): name="kuryr", tags=None):
# 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-ext.html#listSubnetPools # noqa # http://developer.openstack.org/api-ref-networking-v2-ext.html#listSubnetPools # noqa
if tags is None:
tags = []
v4_subnetpools = { v4_subnetpools = {
"subnetpools": [{ "subnetpools": [{
"min_prefixlen": "24", "min_prefixlen": "24",
@ -91,7 +93,8 @@ class TestKuryrBase(TestCase):
"tenant_id": "9fadcee8aa7c40cdb2114fff7d569c08", "tenant_id": "9fadcee8aa7c40cdb2114fff7d569c08",
"prefixes": prefixes, "prefixes": prefixes,
"ip_version": 4, "ip_version": 4,
"shared": False "shared": False,
"tags": tags
}] }]
} }

View File

@ -112,11 +112,17 @@ class TestKuryrIpam(base.TestKuryrBase):
decoded_json = jsonutils.loads(response.data) decoded_json = jsonutils.loads(response.data)
self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID']) self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID'])
@mock.patch('kuryr_libnetwork.controllers.app.neutron.add_tag')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools') @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets') @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets')
@ddt.data((FAKE_IP4_CIDR), (FAKE_IP6_CIDR)) @mock.patch('kuryr_libnetwork.controllers.app')
@ddt.data((True, FAKE_IP4_CIDR), (True, FAKE_IP6_CIDR),
(False, FAKE_IP4_CIDR), (False, FAKE_IP6_CIDR))
@ddt.unpack
def test_ipam_driver_request_pool_with_pool_name_option(self, def test_ipam_driver_request_pool_with_pool_name_option(self,
pool_cidr, mock_list_subnets, mock_list_subnetpools): use_tag_ext, pool_cidr, mock_app, mock_list_subnets,
mock_list_subnetpools, mock_add_tag):
mock_app.tag_ext = use_tag_ext
fake_subnet = {"subnets": []} fake_subnet = {"subnets": []}
mock_list_subnets.return_value = fake_subnet mock_list_subnets.return_value = fake_subnet
@ -149,14 +155,26 @@ class TestKuryrIpam(base.TestKuryrBase):
self.assertEqual(200, response.status_code) self.assertEqual(200, response.status_code)
mock_list_subnets.assert_called_with(cidr=pool_cidr) mock_list_subnets.assert_called_with(cidr=pool_cidr)
if mock_app.tag_ext:
mock_add_tag.assert_called_once_with(
'subnetpools', fake_kuryr_subnetpool_id,
const.KURYR_EXISTING_NEUTRON_SUBNETPOOL)
else:
mock_add_tag.assert_not_called()
decoded_json = jsonutils.loads(response.data) decoded_json = jsonutils.loads(response.data)
self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID']) self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID'])
@mock.patch('kuryr_libnetwork.controllers.app.neutron.add_tag')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools') @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets') @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets')
@ddt.data((FAKE_IP4_CIDR), (FAKE_IP6_CIDR)) @mock.patch('kuryr_libnetwork.controllers.app')
@ddt.data((True, FAKE_IP4_CIDR), (True, FAKE_IP6_CIDR),
(False, FAKE_IP4_CIDR), (False, FAKE_IP6_CIDR))
@ddt.unpack
def test_ipam_driver_request_pool_with_pool_id_option(self, def test_ipam_driver_request_pool_with_pool_id_option(self,
pool_cidr, mock_list_subnets, mock_list_subnetpools): use_tag_ext, pool_cidr, mock_app, mock_list_subnets,
mock_list_subnetpools, mock_add_tag):
mock_app.tag_ext = use_tag_ext
fake_subnet = {"subnets": []} fake_subnet = {"subnets": []}
mock_list_subnets.return_value = fake_subnet mock_list_subnets.return_value = fake_subnet
@ -186,16 +204,27 @@ class TestKuryrIpam(base.TestKuryrBase):
self.assertEqual(200, response.status_code) self.assertEqual(200, response.status_code)
mock_list_subnets.assert_called_with(cidr=pool_cidr) mock_list_subnets.assert_called_with(cidr=pool_cidr)
if mock_app.tag_ext:
mock_add_tag.assert_called_once_with(
'subnetpools', fake_kuryr_subnetpool_id,
const.KURYR_EXISTING_NEUTRON_SUBNETPOOL)
else:
mock_add_tag.assert_not_called()
decoded_json = jsonutils.loads(response.data) decoded_json = jsonutils.loads(response.data)
self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID']) self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID'])
@mock.patch('kuryr_libnetwork.controllers.app.neutron.add_tag')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.create_subnetpool') @mock.patch('kuryr_libnetwork.controllers.app.neutron.create_subnetpool')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools') @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets') @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets')
@ddt.data((FAKE_IP4_CIDR), (FAKE_IP6_CIDR)) @mock.patch('kuryr_libnetwork.controllers.app')
@ddt.data((True, FAKE_IP4_CIDR), (True, FAKE_IP6_CIDR),
(False, FAKE_IP4_CIDR), (False, FAKE_IP6_CIDR))
@ddt.unpack
def test_ipam_driver_request_pool_with_unmatched_cidr(self, def test_ipam_driver_request_pool_with_unmatched_cidr(self,
pool_cidr, mock_list_subnets, mock_list_subnetpools, use_tag_ext, pool_cidr, mock_app, mock_list_subnets,
mock_create_subnetpool): mock_list_subnetpools, mock_create_subnetpool, mock_add_tag):
mock_app.tag_ext = use_tag_ext
fake_subnet = {"subnets": []} fake_subnet = {"subnets": []}
mock_list_subnets.return_value = fake_subnet mock_list_subnets.return_value = fake_subnet
subnet_ip4_cidr = '10.0.0.0/24' subnet_ip4_cidr = '10.0.0.0/24'
@ -263,6 +292,12 @@ class TestKuryrIpam(base.TestKuryrBase):
mock_list_subnets.assert_called_with(cidr=subnet_cidr) mock_list_subnets.assert_called_with(cidr=subnet_cidr)
mock_create_subnetpool.assert_called_with( mock_create_subnetpool.assert_called_with(
{'subnetpool': new_subnetpool}) {'subnetpool': new_subnetpool})
if mock_app.tag_ext:
mock_add_tag.assert_called_once_with(
'subnetpools', fake_existing_subnetpool_id,
const.KURYR_EXISTING_NEUTRON_SUBNETPOOL)
else:
mock_add_tag.assert_not_called()
decoded_json = jsonutils.loads(response.data) decoded_json = jsonutils.loads(response.data)
self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID']) self.assertEqual(fake_kuryr_subnetpool_id, decoded_json['PoolID'])
@ -361,9 +396,12 @@ class TestKuryrIpam(base.TestKuryrBase):
fake_kuryr_subnetpool_id = uuidutils.generate_uuid() fake_kuryr_subnetpool_id = uuidutils.generate_uuid()
fake_subnetpool_name = 'fake_pool_name' fake_subnetpool_name = 'fake_pool_name'
fake_tags = []
if mock_app.tag_ext:
fake_tags.append(const.KURYR_EXISTING_NEUTRON_SUBNETPOOL)
kuryr_subnetpools = self._get_fake_v4_subnetpools( kuryr_subnetpools = self._get_fake_v4_subnetpools(
fake_kuryr_subnetpool_id, prefixes=[FAKE_IP4_CIDR], fake_kuryr_subnetpool_id, prefixes=[FAKE_IP4_CIDR],
name=fake_subnetpool_name) name=fake_subnetpool_name, tags=fake_tags)
mock_list_subnetpools.return_value = kuryr_subnetpools mock_list_subnetpools.return_value = kuryr_subnetpools
docker_endpoint_id = lib_utils.get_hash() docker_endpoint_id = lib_utils.get_hash()
@ -393,9 +431,12 @@ class TestKuryrIpam(base.TestKuryrBase):
id=fake_kuryr_subnetpool_id) id=fake_kuryr_subnetpool_id)
mock_list_subnets.assert_called_with( mock_list_subnets.assert_called_with(
cidr=FAKE_IP4_CIDR) cidr=FAKE_IP4_CIDR)
mock_remove_tag.assert_called_with('subnets', mock_remove_tag.assert_any_call('subnets',
subnet_v4_id, subnet_v4_id,
fake_kuryr_subnetpool_id) fake_kuryr_subnetpool_id)
mock_remove_tag.assert_any_call(
'subnetpools', fake_kuryr_subnetpool_id,
const.KURYR_EXISTING_NEUTRON_SUBNETPOOL)
@mock.patch('kuryr_libnetwork.controllers._neutron_port_add_tag') @mock.patch('kuryr_libnetwork.controllers._neutron_port_add_tag')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.create_port') @mock.patch('kuryr_libnetwork.controllers.app.neutron.create_port')

View File

@ -0,0 +1,5 @@
---
other:
- |
Tag existing subnetpool if tag extension is enabled in Neutron.
This will ensure the subnetpool to deleted is the one kuryr created.