Merge "DVR: Fix IPtables driver for metering with DVR routers"

This commit is contained in:
Jenkins 2017-01-20 04:08:55 +00:00 committed by Gerrit Code Review
commit 2614bc6498
4 changed files with 321 additions and 101 deletions

View File

@ -23,6 +23,7 @@ from neutron.common import constants
from neutron.db import _utils as db_utils
from neutron.db import api as db_api
from neutron.db import common_db_mixin as base_db
from neutron.db import l3_dvr_db
from neutron.db.models import l3 as l3_models
from neutron.db.models import metering as metering_models
from neutron.extensions import metering
@ -189,12 +190,14 @@ class MeteringDbMixin(metering.MeteringPluginBase,
return rules
def _make_router_dict(self, router):
distributed = l3_dvr_db.is_distributed_router(router)
res = {'id': router['id'],
'name': router['name'],
'tenant_id': router['tenant_id'],
'admin_state_up': router['admin_state_up'],
'status': router['status'],
'gw_port_id': router['gw_port_id'],
'distributed': distributed,
constants.METERING_LABEL_KEY: []}
return res

View File

@ -20,7 +20,10 @@ import six
from neutron._i18n import _, _LE, _LI
from neutron.agent.common import config
from neutron.agent.l3 import dvr_snat_ns
from neutron.agent.l3 import namespaces
from neutron.agent.linux import interface
from neutron.agent.linux import ip_lib
from neutron.agent.linux import iptables_manager
from neutron.common import constants
from neutron.common import ipv6_utils
@ -31,6 +34,7 @@ LOG = logging.getLogger(__name__)
NS_PREFIX = 'qrouter-'
WRAP_NAME = 'neutron-meter'
EXTERNAL_DEV_PREFIX = 'qg-'
ROUTER_2_FIP_DEV_PREFIX = namespaces.ROUTER_2_FIP_DEV_PREFIX
TOP_CHAIN = WRAP_NAME + "-FORWARD"
RULE = '-r-'
LABEL = '-l-'
@ -70,11 +74,32 @@ class RouterWithMetering(object):
self.router = router
# TODO(cbrandily): deduplicate ns_name generation in metering/l3
self.ns_name = NS_PREFIX + self.id
self.iptables_manager = iptables_manager.IptablesManager(
namespace=self.ns_name,
binary_name=WRAP_NAME,
state_less=True,
use_ipv6=ipv6_utils.is_enabled_and_bind_by_default())
self.iptables_manager = None
self.snat_iptables_manager = None
if self.router['distributed']:
# If distributed routers then we need to apply the
# metering agent label rules in the snat namespace as well.
snat_ns_name = dvr_snat_ns.SnatNamespace.get_snat_ns_name(
self.id)
# Check for namespace existence before we assign the
# snat_iptables_manager
if ip_lib.IPWrapper().netns.exists(snat_ns_name):
self.snat_iptables_manager = iptables_manager.IptablesManager(
namespace=snat_ns_name,
binary_name=WRAP_NAME,
state_less=True,
use_ipv6=ipv6_utils.is_enabled_and_bind_by_default())
# Check of namespace existence before we assign the iptables_manager
# NOTE(Swami): If distributed routers, all external traffic on a
# compute node will flow through the rfp interface in the router
# namespace.
ip_wrapper = ip_lib.IPWrapper(namespace=self.ns_name)
if ip_wrapper.netns.exists(self.ns_name):
self.iptables_manager = iptables_manager.IptablesManager(
namespace=self.ns_name,
binary_name=WRAP_NAME,
state_less=True,
use_ipv6=ipv6_utils.is_enabled_and_bind_by_default())
self.metering_labels = {}
@ -117,7 +142,12 @@ class IptablesMeteringDriver(abstract_driver.MeteringAbstractDriver):
if gw_port_id != old_gw_port_id:
if old_rm:
with IptablesManagerTransaction(old_rm.iptables_manager):
if router.get('distributed'):
old_rm_im = old_rm.snat_iptables_manager
else:
old_rm_im = old_rm.iptables_manager
with IptablesManagerTransaction(old_rm_im):
self._process_disassociate_metering_label(router)
if gw_port_id:
self._process_associate_metering_label(router)
@ -129,32 +159,34 @@ class IptablesMeteringDriver(abstract_driver.MeteringAbstractDriver):
if router_id in self.routers:
del self.routers[router_id]
def get_external_device_name(self, port_id):
return (EXTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]
def get_external_device_names(self, rm):
gw_port_id = rm.router.get('gw_port_id')
if not gw_port_id:
return None, None
def _process_metering_label_rules(self, rm, rules, label_chain,
rules_chain):
im = rm.iptables_manager
ex_gw_port = rm.router.get('gw_port_id')
if not ex_gw_port:
return
# NOTE (Swami): External device 'qg' should be used on the
# Router namespace if the router is legacy and should be used on
# SNAT namespace if the router is distributed.
ext_dev = (EXTERNAL_DEV_PREFIX +
gw_port_id)[:self.driver.DEV_NAME_LEN]
ext_snat_dev = (ROUTER_2_FIP_DEV_PREFIX +
rm.id)[:self.driver.DEV_NAME_LEN]
return ext_dev, ext_snat_dev
ext_dev = self.get_external_device_name(ex_gw_port)
def _process_metering_label_rules(self, rules, label_chain,
rules_chain, ext_dev, im):
if not ext_dev:
return
for rule in rules:
self._add_rule_to_chain(ext_dev, rule, im,
label_chain, rules_chain)
def _process_metering_label_rule_add(self, rm, rule, ext_dev,
label_chain, rules_chain):
im = rm.iptables_manager
def _process_metering_label_rule_add(self, rule, ext_dev,
label_chain, rules_chain, im):
self._add_rule_to_chain(ext_dev, rule, im, label_chain, rules_chain)
def _process_metering_label_rule_delete(self, rm, rule, ext_dev,
label_chain, rules_chain):
im = rm.iptables_manager
def _process_metering_label_rule_delete(self, rule, ext_dev,
label_chain, rules_chain, im):
self._remove_rule_from_chain(ext_dev, rule, im,
label_chain, rules_chain)
@ -191,67 +223,75 @@ class IptablesMeteringDriver(abstract_driver.MeteringAbstractDriver):
ipt_rule = '%s -j %s' % (dir_opt, label_chain)
return ipt_rule
def _process_associate_metering_label(self, router):
self._update_router(router)
def _process_ns_specific_metering_label(self, router, ext_dev, im):
'''Process metering label based on the associated namespaces.'''
rm = self.routers.get(router['id'])
with IptablesManagerTransaction(rm.iptables_manager):
with IptablesManagerTransaction(im):
labels = router.get(constants.METERING_LABEL_KEY, [])
for label in labels:
label_id = label['id']
label_chain = iptables_manager.get_chain_name(WRAP_NAME +
LABEL + label_id,
wrap=False)
rm.iptables_manager.ipv4['filter'].add_chain(label_chain,
wrap=False)
label_chain = iptables_manager.get_chain_name(
WRAP_NAME + LABEL + label_id, wrap=False)
im.ipv4['filter'].add_chain(label_chain, wrap=False)
rules_chain = iptables_manager.get_chain_name(WRAP_NAME +
RULE + label_id,
wrap=False)
rm.iptables_manager.ipv4['filter'].add_chain(rules_chain,
wrap=False)
rm.iptables_manager.ipv4['filter'].add_rule(TOP_CHAIN, '-j ' +
rules_chain,
wrap=False)
rules_chain = iptables_manager.get_chain_name(
WRAP_NAME + RULE + label_id, wrap=False)
im.ipv4['filter'].add_chain(rules_chain, wrap=False)
im.ipv4['filter'].add_rule(
TOP_CHAIN, '-j ' + rules_chain, wrap=False)
rm.iptables_manager.ipv4['filter'].add_rule(label_chain,
'',
wrap=False)
im.ipv4['filter'].add_rule(
label_chain, '', wrap=False)
rules = label.get('rules')
if rules:
self._process_metering_label_rules(rm, rules,
label_chain,
rules_chain)
self._process_metering_label_rules(
rules, label_chain, rules_chain, ext_dev, im)
rm.metering_labels[label_id] = label
def _process_disassociate_metering_label(self, router):
def _process_associate_metering_label(self, router):
self._update_router(router)
rm = self.routers.get(router['id'])
if not rm:
return
with IptablesManagerTransaction(rm.iptables_manager):
ext_dev, ext_snat_dev = self.get_external_device_names(rm)
for (im, dev) in [(rm.iptables_manager, ext_dev),
(rm.snat_iptables_manager, ext_snat_dev)]:
if im:
self._process_ns_specific_metering_label(router, dev, im)
def _process_ns_specific_disassociate_metering_label(self, router, im):
'''Disassociate metering label based on specific namespaces.'''
rm = self.routers.get(router['id'])
with IptablesManagerTransaction(im):
labels = router.get(constants.METERING_LABEL_KEY, [])
for label in labels:
label_id = label['id']
if label_id not in rm.metering_labels:
continue
label_chain = iptables_manager.get_chain_name(WRAP_NAME +
LABEL + label_id,
wrap=False)
rules_chain = iptables_manager.get_chain_name(WRAP_NAME +
RULE + label_id,
wrap=False)
label_chain = iptables_manager.get_chain_name(
WRAP_NAME + LABEL + label_id, wrap=False)
rules_chain = iptables_manager.get_chain_name(
WRAP_NAME + RULE + label_id, wrap=False)
im.ipv4['filter'].remove_chain(label_chain, wrap=False)
im.ipv4['filter'].remove_chain(rules_chain, wrap=False)
rm.iptables_manager.ipv4['filter'].remove_chain(label_chain,
wrap=False)
rm.iptables_manager.ipv4['filter'].remove_chain(rules_chain,
wrap=False)
def _process_disassociate_metering_label(self, router):
rm = self.routers.get(router['id'])
if not rm:
return
del rm.metering_labels[label_id]
for im in [rm.iptables_manager, rm.snat_iptables_manager]:
if im:
self._process_ns_specific_disassociate_metering_label(
router, im)
labels = router.get(constants.METERING_LABEL_KEY, [])
for label in labels:
label_id = label['id']
del rm.metering_labels[label_id]
@log_helpers.log_method_call
def add_metering_label(self, context, routers):
@ -279,61 +319,67 @@ class IptablesMeteringDriver(abstract_driver.MeteringAbstractDriver):
def _remove_metering_label_rule(self, router):
self._process_metering_rule_action(router, 'delete')
def _process_metering_rule_action_based_on_ns(
self, router, action, ext_dev, im):
'''Process metering rule actions based specific namespaces.'''
with IptablesManagerTransaction(im):
labels = router.get(constants.METERING_LABEL_KEY, [])
for label in labels:
label_id = label['id']
label_chain = iptables_manager.get_chain_name(
WRAP_NAME + LABEL + label_id, wrap=False)
rules_chain = iptables_manager.get_chain_name(
WRAP_NAME + RULE + label_id, wrap=False)
rule = label.get('rule')
if rule:
if action == 'create':
self._process_metering_label_rule_add(
rule, ext_dev, label_chain, rules_chain, im)
elif action == 'delete':
self._process_metering_label_rule_delete(
rule, ext_dev, label_chain, rules_chain, im)
def _process_metering_rule_action(self, router, action):
rm = self.routers.get(router['id'])
if not rm:
return
ext_dev = self.get_external_device_name(rm.router['gw_port_id'])
if not ext_dev:
return
with IptablesManagerTransaction(rm.iptables_manager):
ext_dev, ext_snat_dev = self.get_external_device_names(rm)
for (im, dev) in [(rm.iptables_manager, ext_dev),
(rm.snat_iptables_manager, ext_snat_dev)]:
if im and dev:
self._process_metering_rule_action_based_on_ns(
router, action, dev, im)
def _update_metering_label_rules_based_on_ns(self, router, ext_dev, im):
'''Update metering lable rules based on namespace.'''
with IptablesManagerTransaction(im):
labels = router.get(constants.METERING_LABEL_KEY, [])
for label in labels:
label_id = label['id']
label_chain = iptables_manager.get_chain_name(WRAP_NAME +
LABEL + label_id,
wrap=False)
rules_chain = iptables_manager.get_chain_name(WRAP_NAME +
RULE + label_id,
wrap=False)
rule = label.get('rule')
if rule:
if action == 'create':
self._process_metering_label_rule_add(rm, rule,
ext_dev,
label_chain,
rules_chain)
elif action == 'delete':
self._process_metering_label_rule_delete(rm, rule,
ext_dev,
label_chain,
rules_chain)
label_chain = iptables_manager.get_chain_name(
WRAP_NAME + LABEL + label_id, wrap=False)
rules_chain = iptables_manager.get_chain_name(
WRAP_NAME + RULE + label_id, wrap=False)
im.ipv4['filter'].empty_chain(rules_chain, wrap=False)
rules = label.get('rules')
if rules:
self._process_metering_label_rules(
rules, label_chain, rules_chain, ext_dev, im)
def _update_metering_label_rules(self, router):
rm = self.routers.get(router['id'])
if not rm:
return
with IptablesManagerTransaction(rm.iptables_manager):
labels = router.get(constants.METERING_LABEL_KEY, [])
for label in labels:
label_id = label['id']
label_chain = iptables_manager.get_chain_name(WRAP_NAME +
LABEL + label_id,
wrap=False)
rules_chain = iptables_manager.get_chain_name(WRAP_NAME +
RULE + label_id,
wrap=False)
rm.iptables_manager.ipv4['filter'].empty_chain(rules_chain,
wrap=False)
rules = label.get('rules')
if rules:
self._process_metering_label_rules(rm, rules,
label_chain,
rules_chain)
ext_dev, ext_snat_dev = self.get_external_device_names(rm)
for (im, dev) in [(rm.iptables_manager, ext_dev),
(rm.snat_iptables_manager, ext_snat_dev)]:
if im and dev:
self._update_metering_label_rules_based_on_ns(router, dev, im)
@log_helpers.log_method_call
def remove_metering_label(self, context, routers):

View File

@ -34,6 +34,7 @@ TEST_ROUTERS = [
'gw_port_id': '6d411f48-ecc7-45e0-9ece-3b5bdb54fcee',
'id': '473ec392-1711-44e3-b008-3251ccfc5099',
'name': 'router1',
'distributed': False,
'status': 'ACTIVE',
'tenant_id': '6c5f5d2a1fa2441e88e35422926f48e8'},
{'_metering_labels': [
@ -49,9 +50,27 @@ TEST_ROUTERS = [
'id': '373ec392-1711-44e3-b008-3251ccfc5099',
'name': 'router2',
'status': 'ACTIVE',
'distributed': False,
'tenant_id': '6c5f5d2a1fa2441e88e35422926f48e8'},
]
TEST_DVR_ROUTER = [
{'_metering_labels': [
{'id': 'c5df2fe5-c610-4a2a-b2f4-c0fb6df73c83',
'rules': [{
'direction': 'ingress',
'excluded': False,
'id': '7f1a261f-2600-4ed1-870c-a62754501379',
'metering_label_id': 'c5df2fe5-c700-4a2a-b2f4-c0fb6df73c83',
'remote_ip_prefix': '10.0.0.0/24'}]}],
'admin_state_up': True,
'gw_port_id': '6d411f48-ecc7-45e0-9ece-3b5bdb54fcee',
'id': '473ec392-2711-44e3-b008-3251ccfc5099',
'name': 'router-test',
'distributed': True,
'status': 'ACTIVE',
'tenant_id': '6c5f5d2a1fa2441e88e35422926f48e8'}]
TEST_ROUTERS_WITH_ONE_RULE = [
{'_metering_labels': [
{'id': 'c5df2fe5-c600-4a2a-b2f4-c0fb6df73c83',
@ -66,6 +85,7 @@ TEST_ROUTERS_WITH_ONE_RULE = [
'id': '473ec392-1711-44e3-b008-3251ccfc5099',
'name': 'router1',
'status': 'ACTIVE',
'distributed': False,
'tenant_id': '6c5f5d2a1fa2441e88e35422926f48e8'},
{'_metering_labels': [
{'id': 'eeef45da-c600-4a2a-b2f4-c0fb6df73c83',
@ -79,6 +99,7 @@ TEST_ROUTERS_WITH_ONE_RULE = [
'gw_port_id': '7d411f48-ecc7-45e0-9ece-3b5bdb54fcee',
'id': '373ec392-1711-44e3-b008-3251ccfc5099',
'name': 'router2',
'distributed': False,
'status': 'ACTIVE',
'tenant_id': '6c5f5d2a1fa2441e88e35422926f48e8'},
]
@ -96,6 +117,12 @@ class IptablesDriverTestCase(base.BaseTestCase):
self.iptables_inst = mock.Mock()
self.v4filter_inst = mock.Mock()
self.v6filter_inst = mock.Mock()
self.namespace_exists_p = mock.patch(
'neutron.agent.linux.ip_lib.IpNetnsCommand.exists')
self.namespace_exists = self.namespace_exists_p.start()
self.snat_ns_name_p = mock.patch(
'neutron.agent.l3.dvr_snat_ns.SnatNamespace.get_snat_ns_name')
self.snat_ns_name = self.snat_ns_name_p.start()
self.v4filter_inst.chains = []
self.v6filter_inst.chains = []
self.iptables_inst.ipv4 = {'filter': self.v4filter_inst}
@ -108,16 +135,42 @@ class IptablesDriverTestCase(base.BaseTestCase):
def test_create_stateless_iptables_manager(self):
routers = TEST_ROUTERS[:1]
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
self.assertEqual(1, self.iptables_cls.call_count)
self.iptables_cls.assert_called_with(
binary_name=mock.ANY,
namespace=mock.ANY,
state_less=True,
use_ipv6=mock.ANY)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
self.assertTrue(rm.iptables_manager)
self.assertIsNone(rm.snat_iptables_manager)
def test_iptables_manager_never_create_with_no_valid_namespace(self):
routers = TEST_ROUTERS[:1]
self.namespace_exists.return_value = False
self.metering.add_metering_label(None, routers)
self.assertFalse(self.iptables_cls.called)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
self.assertIsNone(rm.iptables_manager)
self.assertIsNone(rm.snat_iptables_manager)
def test_create_iptables_manager_for_distributed_routers(self):
routers = TEST_DVR_ROUTER[:1]
self.namespace_exists.return_value = True
snat_ns_name = 'snat-' + routers[0]['id']
self.snat_ns_name.return_value = snat_ns_name
self.metering.add_metering_label(None, routers)
self.assertEqual(2, self.iptables_cls.call_count)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
self.assertTrue(rm.iptables_manager)
self.assertTrue(rm.snat_iptables_manager)
def test_add_metering_label(self):
routers = TEST_ROUTERS[:1]
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
calls = [mock.call.add_chain('neutron-meter-l-c5df2fe5-c60',
wrap=False),
@ -132,7 +185,52 @@ class IptablesDriverTestCase(base.BaseTestCase):
self.v4filter_inst.assert_has_calls(calls)
def test_add_metering_label_dvr_routers(self):
routers = TEST_DVR_ROUTER[:1]
self.namespace_exists.return_value = True
snat_ns_name = 'snat-' + routers[0]['id']
self.snat_ns_name.return_value = snat_ns_name
self.metering._process_ns_specific_metering_label = mock.Mock()
self.metering.add_metering_label(None, routers)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
ext_dev, ext_snat_dev = self.metering.get_external_device_names(rm)
self.assertEqual(
2, self.metering._process_ns_specific_metering_label.call_count)
# check and validate the right device being passed based on the
# namespace.
self.assertEqual(
self.metering._process_ns_specific_metering_label.mock_calls,
[mock.call(
routers[0], ext_dev, rm.iptables_manager),
mock.call(
routers[0], ext_snat_dev, rm.snat_iptables_manager)])
def test_add_metering_label_legacy_routers(self):
routers = TEST_ROUTERS[:1]
self.namespace_exists.return_value = True
self.metering._process_ns_specific_metering_label = mock.Mock()
self.metering.add_metering_label(None, routers)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
ext_dev, _ = self.metering.get_external_device_names(rm)
self.assertEqual(
self.metering._process_ns_specific_metering_label.mock_calls,
[mock.call(routers[0], ext_dev, rm.iptables_manager)])
def test_add_metering_label_when_no_namespace(self):
routers = TEST_ROUTERS[:1]
self.namespace_exists.return_value = False
self.metering._process_metering_label = mock.Mock()
self.metering.add_metering_label(None, routers)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
self.assertIsNone(rm.iptables_manager)
self.assertIsNone(rm.snat_iptables_manager)
self.assertFalse(self.metering._process_metering_label.called)
def test_process_metering_label_rules(self):
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, TEST_ROUTERS)
calls = [mock.call.add_chain('neutron-meter-l-c5df2fe5-c60',
@ -171,6 +269,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
for router in routers:
router['gw_port_id'] = None
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
calls = [mock.call.add_chain('neutron-meter-l-c5df2fe5-c60',
@ -203,6 +302,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
'excluded': True,
})
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
calls = [mock.call.add_chain('neutron-meter-l-c5df2fe5-c60',
wrap=False),
@ -238,6 +338,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
def test_update_metering_label_rules(self):
routers = TEST_ROUTERS[:1]
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
updates = copy.deepcopy(routers)
@ -292,6 +393,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
'remote_ip_prefix': '20.0.0.0/24',
})
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
del routers[0]['_metering_labels'][0]['rules'][1]
@ -327,6 +429,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
def test_add_metering_label_rule(self):
new_routers_rules = TEST_ROUTERS_WITH_ONE_RULE
self.metering.update_routers(None, TEST_ROUTERS)
self.namespace_exists.return_value = True
self.metering.add_metering_label_rule(None, new_routers_rules)
calls = [
mock.call.add_rule('neutron-meter-r-c5df2fe5-c60',
@ -341,9 +444,53 @@ class IptablesDriverTestCase(base.BaseTestCase):
]
self.v4filter_inst.assert_has_calls(calls)
def test_add_metering_label_rule_dvr_router(self):
routers = TEST_DVR_ROUTER
self.metering.update_routers(None, TEST_DVR_ROUTER)
self.namespace_exists.return_value = True
self.metering._process_metering_rule_action_based_on_ns = mock.Mock()
self.metering.add_metering_label_rule(None, routers)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
ext_dev, ext_snat_dev = self.metering.get_external_device_names(rm)
self.assertEqual(
2,
self.metering._process_metering_rule_action_based_on_ns.call_count)
# check and validate the right device being passed based on the
# namespace.
self.assertEqual(
self.metering._process_metering_rule_action_based_on_ns.mock_calls,
[mock.call(
routers[0], 'create', ext_dev, rm.iptables_manager),
mock.call(
routers[0], 'create', ext_snat_dev,
rm.snat_iptables_manager)])
def test_remove_metering_label_rule_dvr_router(self):
routers = TEST_DVR_ROUTER
self.metering.update_routers(None, TEST_DVR_ROUTER)
self.namespace_exists.return_value = True
self.metering.add_metering_label_rule(None, routers)
self.metering._process_metering_rule_action_based_on_ns = mock.Mock()
self.metering.remove_metering_label_rule(None, routers)
rm = iptables_driver.RouterWithMetering(self.metering.conf, routers[0])
ext_dev, ext_snat_dev = self.metering.get_external_device_names(rm)
self.assertEqual(
2,
self.metering._process_metering_rule_action_based_on_ns.call_count)
# check and validate the right device being passed based on the
# namespace.
self.assertEqual(
self.metering._process_metering_rule_action_based_on_ns.mock_calls,
[mock.call(
routers[0], 'delete', ext_dev, rm.iptables_manager),
mock.call(
routers[0], 'delete', ext_snat_dev,
rm.snat_iptables_manager)])
def test_remove_metering_label_rule(self):
new_routers_rules = TEST_ROUTERS_WITH_ONE_RULE
self.metering.update_routers(None, TEST_ROUTERS)
self.namespace_exists.return_value = True
self.metering.add_metering_label_rule(None, new_routers_rules)
self.metering.remove_metering_label_rule(None, new_routers_rules)
calls = [
@ -361,6 +508,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
def test_remove_metering_label(self):
routers = TEST_ROUTERS[:1]
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
self.metering.remove_metering_label(None, routers)
calls = [mock.call.add_chain('neutron-meter-l-c5df2fe5-c60',
@ -384,6 +532,18 @@ class IptablesDriverTestCase(base.BaseTestCase):
self.v4filter_inst.assert_has_calls(calls)
def test_remove_metering_label_with_dvr_routers(self):
routers = TEST_DVR_ROUTER[:1]
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
self.metering._process_ns_specific_disassociate_metering_label = (
mock.Mock())
self.metering.remove_metering_label(None, routers)
self.assertEqual(
2, (self.metering.
_process_ns_specific_disassociate_metering_label.call_count))
def test_update_routers(self):
routers = copy.deepcopy(TEST_ROUTERS)
routers[1]['_metering_labels'][0]['rules'][0].update({
@ -391,6 +551,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
'excluded': True,
})
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
updates = copy.deepcopy(routers)
@ -449,6 +610,7 @@ class IptablesDriverTestCase(base.BaseTestCase):
def test_update_routers_removal(self):
routers = TEST_ROUTERS
self.namespace_exists.return_value = True
self.metering.add_metering_label(None, routers)
# Remove router id '373ec392-1711-44e3-b008-3251ccfc5099'

View File

@ -138,6 +138,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rules': [],
@ -161,6 +162,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rules': [],
@ -184,6 +186,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rules': [],
@ -204,6 +207,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rules': [],
@ -215,6 +219,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rules': [],
@ -238,6 +243,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rule': {
@ -253,6 +259,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rule': {
@ -351,6 +358,7 @@ class TestMeteringPluginL3AgentScheduler(
'name': 'router1',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rules': [],
@ -360,6 +368,7 @@ class TestMeteringPluginL3AgentScheduler(
'name': 'router2',
'gw_port_id': None,
'admin_state_up': True,
'distributed': False,
'tenant_id': self.tenant_id,
'_metering_labels': [
{'rules': [],