Fix per-project quotas for L3 plugin

The GBP L3 plugin is using the old quotas driver. This prevents
per-project quotas for L3 resources. The L3 plugin should be
changed to support the new qutoas driver.

Change-Id: Idbc651a905ca5c567527ba2094a83b2d0486ca9a
Closes-Bug: 1709456
(cherry picked from commit 194dd33947)
(cherry picked from commit 41152b4fde)
(cherry picked from commit c5a45bd3ce)
This commit is contained in:
Thomas Bachman 2017-08-08 18:49:25 +00:00
parent 496f33f785
commit 1fb474945e
4 changed files with 136 additions and 0 deletions

View File

@ -33,6 +33,7 @@ extensions.get_extensions_path = get_extensions_path
from neutron.db import models_v2
from neutron.db.quota import driver # noqa
from neutron.plugins.ml2 import db as ml2_db
from neutron.plugins.ml2 import models
from oslo_log import log as logging

View File

@ -19,10 +19,12 @@ from neutron.api import extensions
from neutron.db import common_db_mixin
from neutron.db import db_base_plugin_v2
from neutron.db import extraroute_db
from neutron.db import l3_db
from neutron.db import l3_gwmode_db
from neutron.extensions import l3
from neutron.extensions import portbindings
from neutron.plugins.common import constants
from neutron.quota import resource_registry
from neutron_lib import exceptions
from oslo_log import log as logging
from oslo_utils import excutils
@ -54,6 +56,8 @@ class ApicL3Plugin(common_db_mixin.CommonDbMixin,
def get_plugin_description():
return _("L3 Router Service Plugin using the APIC via AIM")
@resource_registry.tracked_resources(router=l3_db.Router,
floatingip=l3_db.FloatingIP)
def __init__(self):
LOG.info(_LI("APIC AIM L3 Plugin __init__"))
extensions.append_api_extensions_path(extensions_pkg.__path__)

View File

@ -35,8 +35,31 @@ class TestCiscoApicAimL3Plugin(test_aim_mapping_driver.AIMBaseTestCase):
class so that it can inherit test infrastructure from those classes.
'''
def _verify_event_handler_calls(self, data, expected_call_count=1):
if not hasattr(data, '__iter__') or isinstance(data, dict):
data = [data]
self.assertEqual(expected_call_count, self.handler_mock.call_count)
call_idx = -1
for item in data:
if item:
model = self.handler_mock.call_args_list[call_idx][0][-1]
self.assertEqual(model['id'], item['id'])
self.assertEqual(model['tenant_id'], item['tenant_id'])
call_idx = call_idx - 1
def setUp(self):
handler_patch = mock.patch(
'neutron.quota.resource.TrackedResource._db_event_handler')
self.handler_mock = handler_patch.start()
def_sec_group_patch = mock.patch(
'neutron.db.securitygroups_db.SecurityGroupDbMixin.'
'_ensure_default_security_group')
def_sec_group_patch.start()
super(TestCiscoApicAimL3Plugin, self).setUp()
get_sec_group_port_patch = mock.patch(
'neutron.db.securitygroups_db.SecurityGroupDbMixin.'
'_get_security_groups_on_port')
get_sec_group_port_patch.start()
# Set up L2 objects for L3 test
attr = {'tenant_id': TENANT}
@ -93,3 +116,28 @@ class TestCiscoApicAimL3Plugin(test_aim_mapping_driver.AIMBaseTestCase):
def test_remove_router_interface_port(self):
self._test_remove_router_interface(self.interface_info['port'])
def test_create_delete_floating_ip_triggers_event(self):
net = self._make_network('json', 'meh', True)
subnet = self._make_subnet('json', net, '14.0.0.1',
'14.0.0.0/24')['subnet']
self._set_net_external(subnet['network_id'])
kwargs = {'floatingip': {'tenant_id': TENANT,
'subnet_id': subnet['id'],
'floating_network_id': subnet['network_id']}}
self.handler_mock.reset_mock()
floatingip = self.plugin.create_floatingip(self.context, kwargs)
internal_ports = self._show('ports',
floatingip['port_id'])['ports']
for port in internal_ports:
if port['device_owner'] == 'network:floatingip' and (
port['device_id'] == floatingip['id']):
internal_port = port
# When a floatingip is created it also creates port, therefore
# there will be four calls in total to the event handler
self._verify_event_handler_calls(floatingip,
expected_call_count=2)
self._delete('floatingips', floatingip['id'])
# Expecting 2 more calls - 1 for the port, 1 for the floatingip
self._verify_event_handler_calls(
[internal_port, floatingip], expected_call_count=4)

View File

@ -0,0 +1,83 @@
# 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 functools
import mock
from neutron.api import extensions
from neutron.tests.unit.plugins.ml2 import (
test_tracked_resources as n_tracked)
from neutron.tests.unit.plugins.ml2 import test_plugin
from gbpservice.neutron.db import implicitsubnetpool_db # noqa
import gbpservice.neutron.extensions
PLUGIN_NAME = 'ml2plus'
class Ml2PlusConfFixture(test_plugin.PluginConfFixture):
def __init__(self, parent_setup=None):
super(Ml2PlusConfFixture, self).__init__(PLUGIN_NAME, parent_setup)
class Ml2PlusTestTrackedResourcesEventHandler(
n_tracked.TestTrackedResourcesEventHandler):
def setUp(self):
extensions.append_api_extensions_path(
gbpservice.neutron.extensions.__path__)
# Prevent noise from default security group operations
super(Ml2PlusTestTrackedResourcesEventHandler, self).setUp()
get_sec_group_port_patch = mock.patch(
'neutron.db.securitygroups_db.SecurityGroupDbMixin.'
'_get_security_groups_on_port')
get_sec_group_port_patch.start()
def setup_parent(self):
"""Perform parent setup with the common plugin configuration class."""
service_plugins = {'l3_plugin_name': self.l3_plugin}
# Ensure that the parent setup can be called without arguments
# by the common configuration setUp.
parent_setup = functools.partial(
super(test_plugin.Ml2PluginV2TestCase, self).setUp,
plugin=PLUGIN_NAME,
service_plugins=service_plugins,
)
self.useFixture(Ml2PlusConfFixture(parent_setup))
self.port_create_status = 'DOWN'
class Ml2PlusTestTrackedResources(n_tracked.TestTrackedResources):
def setUp(self):
extensions.append_api_extensions_path(
gbpservice.neutron.extensions.__path__)
# Prevent noise from default security group operations
super(Ml2PlusTestTrackedResources, self).setUp()
get_sec_group_port_patch = mock.patch(
'neutron.db.securitygroups_db.SecurityGroupDbMixin.'
'_get_security_groups_on_port')
get_sec_group_port_patch.start()
def setup_parent(self):
"""Perform parent setup with the common plugin configuration class."""
service_plugins = {'l3_plugin_name': self.l3_plugin}
# Ensure that the parent setup can be called without arguments
# by the common configuration setUp.
parent_setup = functools.partial(
super(test_plugin.Ml2PluginV2TestCase, self).setUp,
plugin=PLUGIN_NAME,
service_plugins=service_plugins,
)
self.useFixture(Ml2PlusConfFixture(parent_setup))
self.port_create_status = 'DOWN'