Use Neutron tag-ext extension

Use Neutron tag-ext extension(supports subnet, port, subnetpool...)
mapping Kuryr resources.

Depends-On: I3ab8c2f47f283bee7219f39f20b07361b8e0c5f1
Change-Id: I8c5726ea702f0a2eb739d72a649bdfb78037db5c
Closes-Bug: #1661148
This commit is contained in:
Dongcan Ye 2017-02-02 12:45:43 +08:00
parent 026b86df32
commit b5bbbb3f69
5 changed files with 78 additions and 52 deletions

View File

@ -42,6 +42,7 @@ LOG = log.getLogger(__name__)
MANDATORY_NEUTRON_EXTENSION = "subnet_allocation"
TAG_NEUTRON_EXTENSION = "tag"
TAG_EXT_NEUTRON_EXTENSION = "tag-ext"
SUBNET_POOLS_V4 = []
SUBNET_POOLS_V6 = []
@ -71,16 +72,20 @@ def check_for_neutron_ext_support():
.format(MANDATORY_NEUTRON_EXTENSION))
def check_for_neutron_ext_tag():
"""Validates for tags extension support availability in neutron."""
app.tag = True
def check_for_neutron_tag_support(ext_name):
"""Validates tag and tag-ext extension support availability in Neutron."""
if ext_name == TAG_EXT_NEUTRON_EXTENSION:
ext_rename = "tag_ext"
else:
ext_rename = ext_name
setattr(app, ext_rename, True)
try:
app.neutron.show_extension(TAG_NEUTRON_EXTENSION)
app.neutron.show_extension(ext_name)
except n_exceptions.NeutronClientException as e:
app.tag = False
setattr(app, ext_rename, False)
if e.status_code == n_exceptions.NotFound.status_code:
app.logger.warning(_LW("Neutron tags not supported. "
"Continue without using them."))
app.logger.warning(_LW("Neutron extension %s not supported. "
"Continue without using them."), ext_name)
def load_default_subnet_pools():
@ -1458,34 +1463,27 @@ def ipam_release_pool():
pool_id = json_data['PoolID']
# Remove subnetpool_id tag from Neutron existing subnet.
if app.tag:
try:
tag_extension = app.neutron.show_extension(TAG_NEUTRON_EXTENSION)
except n_exceptions.NeutronClientException as ex:
app.logger.error(_LE("Failed to show Neutron tags "
"extension: %s"), ex)
raise
if 'subnet' in tag_extension['extension']['description']:
pools = _get_subnetpools_by_attrs(id=pool_id)
if pools:
pool = pools[0]
prefixes = pool['prefixes']
if len(prefixes) > 1:
app.logger.warning(_LW("More than one prefixes present. "
"Picking first one."))
for prefix in prefixes:
subnet_cidr = ipaddress.ip_network(six.text_type(prefix))
break
else:
raise exceptions.NoResourceException(
"No subnetpools with id {0} is found."
.format(pool_id))
subnets_by_cidr = _get_subnets_by_attrs(
cidr=six.text_type(subnet_cidr))
for tmp_subnet in subnets_by_cidr:
if pool_id in tmp_subnet.get('tags', []):
_neutron_subnet_remove_tag(tmp_subnet['id'], pool_id)
break
if app.tag_ext:
pools = _get_subnetpools_by_attrs(id=pool_id)
if pools:
pool = pools[0]
prefixes = pool['prefixes']
if len(prefixes) > 1:
app.logger.warning(_LW("More than one prefixes present. "
"Picking first one."))
for prefix in prefixes:
subnet_cidr = ipaddress.ip_network(six.text_type(prefix))
break
else:
raise exceptions.NoResourceException(
"No subnetpools with id {0} is found."
.format(pool_id))
subnets_by_cidr = _get_subnets_by_attrs(
cidr=six.text_type(subnet_cidr))
for tmp_subnet in subnets_by_cidr:
if pool_id in tmp_subnet.get('tags', []):
_neutron_subnet_remove_tag(tmp_subnet['id'], pool_id)
break
try:
app.neutron.delete_subnetpool(pool_id)
except n_exceptions.Conflict as ex:

View File

@ -26,7 +26,10 @@ def configure_app():
log.setup(config.CONF, 'kuryr')
controllers.neutron_client()
controllers.check_for_neutron_ext_support()
controllers.check_for_neutron_ext_tag()
controllers.check_for_neutron_tag_support(
controllers.TAG_NEUTRON_EXTENSION)
controllers.check_for_neutron_tag_support(
controllers.TAG_EXT_NEUTRON_EXTENSION)
controllers.load_default_subnet_pools()
controllers.load_port_driver()

View File

@ -39,6 +39,7 @@ class TestCase(base.BaseTestCase):
self.app.neutron = client.Client(token=TOKEN, endpoint_url=ENDURL)
app.driver = mock.Mock(spec=driver.Driver)
app.tag = True
app.tag_ext = True
class TestKuryrBase(TestCase):

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import ddt
import mock
import os
from six.moves.urllib import parse
@ -24,6 +25,7 @@ from kuryr_libnetwork.server import start
from kuryr_libnetwork.tests.unit import base
@ddt.ddt
class ConfigurationTest(base.TestKuryrBase):
def test_defaults(self):
@ -46,18 +48,22 @@ class ConfigurationTest(base.TestKuryrBase):
config.CONF.port_driver)
@mock.patch.object(sys, 'argv', return_value='[]')
@mock.patch('kuryr_libnetwork.controllers.check_for_neutron_ext_tag')
@mock.patch('kuryr_libnetwork.controllers.check_for_neutron_tag_support')
@mock.patch('kuryr_libnetwork.controllers.check_for_neutron_ext_support')
@mock.patch('kuryr_libnetwork.controllers.neutron_client')
@mock.patch('kuryr_libnetwork.app.run')
def test_start(self, mock_run, mock_neutron_client,
mock_check_neutron_ext_support, mock_check_neutron_ext_tag,
mock_check_neutron_ext_support,
mock_check_for_neutron_tag_support,
mock_sys_argv):
start()
kuryr_uri = parse.urlparse(config.CONF.kuryr_uri)
mock_neutron_client.assert_called_once()
mock_check_neutron_ext_support.assert_called_once()
mock_check_neutron_ext_tag.assert_called_once()
mock_check_for_neutron_tag_support.assert_any_call(
controllers.TAG_NEUTRON_EXTENSION)
mock_check_for_neutron_tag_support.assert_any_call(
controllers.TAG_EXT_NEUTRON_EXTENSION)
mock_run.assert_called_once_with(kuryr_uri.hostname, 23750,
ssl_context=None)
@ -73,3 +79,30 @@ class ConfigurationTest(base.TestKuryrBase):
ex = exceptions.MandatoryApiMissing
self.assertRaises(ex, controllers.check_for_neutron_ext_support)
mock_extension.assert_called_once_with(ext_alias)
@mock.patch('kuryr_libnetwork.controllers.app.neutron.show_extension')
@ddt.data('tag', 'tag-ext')
def test_check_for_neutron_tag_support_with_ex(self,
ext_name,
mock_extension):
err = n_exceptions.NotFound.status_code
ext_not_found_ex = n_exceptions.NeutronClientException(
status_code=err,
message="")
mock_extension.side_effect = ext_not_found_ex
controllers.check_for_neutron_tag_support(ext_name)
mock_extension.assert_called_once_with(ext_name)
@mock.patch('kuryr_libnetwork.controllers.app.neutron.show_extension')
@ddt.data('fake_ext')
def test_check_for_neutron_tag_support_wrong_ext_name_with_ex(
self,
ext_name,
mock_extension):
err = n_exceptions.NotFound.status_code
ext_not_found_ex = n_exceptions.NeutronClientException(
status_code=err,
message="")
mock_extension.side_effect = ext_not_found_ex
controllers.check_for_neutron_tag_support(ext_name)
mock_extension.assert_called_once_with(ext_name)

View File

@ -172,24 +172,16 @@ class TestKuryrIpam(base.TestKuryrBase):
@mock.patch('kuryr_libnetwork.controllers.app.neutron.remove_tag')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnets')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools')
@mock.patch('kuryr_libnetwork.controllers.app.neutron.show_extension')
@mock.patch('kuryr_libnetwork.controllers.app')
@ddt.data((True), (False))
def test_ipam_driver_release_pool(self,
use_tags,
mock_tag,
mock_show_extension,
use_tag_ext,
mock_app,
mock_list_subnetpools,
mock_list_subnets,
mock_remove_tag,
mock_delete_subnetpool):
mock_tag.tag = use_tags
fake_tag_extension = {
"extension":
{"alias": "tag", "updated": "mock_time",
"name": "Tag support", "links": [],
"description": "mock tag on resources ['subnet', 'network']."}}
mock_show_extension.return_value = fake_tag_extension
mock_app.tag_ext = use_tag_ext
fake_kuryr_subnetpool_id = uuidutils.generate_uuid()
fake_subnetpool_name = lib_utils.get_neutron_subnetpool_name(
@ -223,8 +215,7 @@ class TestKuryrIpam(base.TestKuryrBase):
data=jsonutils.dumps(fake_request))
self.assertEqual(200, response.status_code)
if mock_tag.tag:
mock_show_extension.assert_called_with("tag")
if mock_app.tag_ext:
mock_list_subnetpools.assert_called_with(
id=fake_kuryr_subnetpool_id)
mock_list_subnets.assert_called_with(