Verify metering label exists before applying rule
If the metering-agent receives a label rule before it
has added the label, it will fail to update the iptables
rules as there are no existing chains.
When the action is "create", check if there is an existing
label, and create one and the corresponding iptables chains,
before trying to add the rule.
Closes-Bug: #1617248
Change-Id: Ia0ec1361188cca53023667d249c2b1e10bc22089
(cherry picked from commit 29652e0aff
)
This commit is contained in:
parent
633b452e28
commit
8275f13dd7
|
@ -233,24 +233,22 @@ class IptablesMeteringDriver(abstract_driver.MeteringAbstractDriver):
|
|||
|
||||
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)
|
||||
im.ipv4['filter'].add_chain(rules_chain, wrap=False)
|
||||
im.ipv4['filter'].add_rule(
|
||||
TOP_CHAIN, '-j ' + rules_chain, wrap=False)
|
||||
|
||||
im.ipv4['filter'].add_rule(
|
||||
label_chain, '', wrap=False)
|
||||
exists = rm.metering_labels.get(label_id)
|
||||
if not exists:
|
||||
self._create_metering_label_chain(rm,
|
||||
label_chain,
|
||||
rules_chain)
|
||||
rm.metering_labels[label_id] = label
|
||||
|
||||
rules = label.get('rules')
|
||||
if rules:
|
||||
self._process_metering_label_rules(
|
||||
rules, label_chain, rules_chain, ext_dev, im)
|
||||
|
||||
rm.metering_labels[label_id] = label
|
||||
|
||||
def _process_associate_metering_label(self, router):
|
||||
self._update_router(router)
|
||||
rm = self.routers.get(router['id'])
|
||||
|
@ -319,9 +317,18 @@ class IptablesMeteringDriver(abstract_driver.MeteringAbstractDriver):
|
|||
def _remove_metering_label_rule(self, router):
|
||||
self._process_metering_rule_action(router, 'delete')
|
||||
|
||||
def _create_metering_label_chain(self, rm, label_chain, rules_chain):
|
||||
rm.iptables_manager.ipv4['filter'].add_chain(label_chain, 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)
|
||||
rm.iptables_manager.ipv4['filter'].add_rule(
|
||||
label_chain, '', wrap=False)
|
||||
|
||||
def _process_metering_rule_action_based_on_ns(
|
||||
self, router, action, ext_dev, im):
|
||||
'''Process metering rule actions based specific namespaces.'''
|
||||
rm = self.routers.get(router['id'])
|
||||
with IptablesManagerTransaction(im):
|
||||
labels = router.get(constants.METERING_LABEL_KEY, [])
|
||||
for label in labels:
|
||||
|
@ -331,6 +338,14 @@ class IptablesMeteringDriver(abstract_driver.MeteringAbstractDriver):
|
|||
|
||||
rules_chain = iptables_manager.get_chain_name(
|
||||
WRAP_NAME + RULE + label_id, wrap=False)
|
||||
|
||||
exists = rm.metering_labels.get(label_id)
|
||||
if action == 'create' and not exists:
|
||||
self._create_metering_label_chain(rm,
|
||||
label_chain,
|
||||
rules_chain)
|
||||
rm.metering_labels[label_id] = label
|
||||
|
||||
rule = label.get('rule')
|
||||
if rule:
|
||||
if action == 'create':
|
||||
|
|
|
@ -104,6 +104,22 @@ TEST_ROUTERS_WITH_ONE_RULE = [
|
|||
'tenant_id': '6c5f5d2a1fa2441e88e35422926f48e8'},
|
||||
]
|
||||
|
||||
TEST_ROUTERS_WITH_NEW_LABEL = [
|
||||
{'_metering_labels': [
|
||||
{'id': 'e27fe2df-376e-4ac7-ae13-92f050a21f84',
|
||||
'rule': {
|
||||
'direction': 'ingress',
|
||||
'excluded': False,
|
||||
'id': '7f1a261f-2489-4ed1-870c-a62754501379',
|
||||
'metering_label_id': 'e27fe2df-376e-4ac7-ae13-92f050a21f84',
|
||||
'remote_ip_prefix': '50.0.0.0/24'}}],
|
||||
'admin_state_up': True,
|
||||
'gw_port_id': '6d411f48-ecc7-45e0-9ece-3b5bdb54fcee',
|
||||
'id': '473ec392-1711-44e3-b008-3251ccfc5099',
|
||||
'name': 'router1',
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '6c5f5d2a1fa2441e88e35422926f48e8'}]
|
||||
|
||||
|
||||
class IptablesDriverTestCase(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
|
@ -440,7 +456,35 @@ class IptablesDriverTestCase(base.BaseTestCase):
|
|||
'-d 40.0.0.0/24 -o qg-7d411f48-ec'
|
||||
' -j neutron-meter-l-eeef45da-c60',
|
||||
wrap=False, top=False),
|
||||
]
|
||||
self.v4filter_inst.assert_has_calls(calls)
|
||||
|
||||
def test_add_metering_label_rule_without_label(self):
|
||||
new_routers_rules = TEST_ROUTERS_WITH_NEW_LABEL
|
||||
# clear all the metering labels
|
||||
for r in TEST_ROUTERS:
|
||||
rm = iptables_driver.RouterWithMetering(self.metering.conf, r)
|
||||
rm.metering_labels = {}
|
||||
|
||||
self.metering.update_routers(None, TEST_ROUTERS)
|
||||
self.metering.add_metering_label_rule(None, new_routers_rules)
|
||||
calls = [
|
||||
mock.call.add_chain('neutron-meter-l-e27fe2df-376',
|
||||
wrap=False),
|
||||
mock.call.add_chain('neutron-meter-r-e27fe2df-376',
|
||||
wrap=False),
|
||||
mock.call.add_rule('neutron-meter-FORWARD',
|
||||
'-j neutron-meter-r-e27fe2df-376',
|
||||
wrap=False),
|
||||
mock.call.add_rule('neutron-meter-l-e27fe2df-376',
|
||||
'',
|
||||
wrap=False),
|
||||
mock.call.add_rule('neutron-meter-r-e27fe2df-376',
|
||||
'-s 50.0.0.0/24 '
|
||||
'-i qg-6d411f48-ec '
|
||||
'-j neutron-meter-l-e27fe2df-376',
|
||||
top=False,
|
||||
wrap=False)
|
||||
]
|
||||
self.v4filter_inst.assert_has_calls(calls)
|
||||
|
||||
|
|
Loading…
Reference in New Issue