Merge "Fix router update on L3 agent restart"
This commit is contained in:
commit
d387583720
|
@ -165,8 +165,12 @@ class FWaaSL3AgentExtension(l3_extension.L3AgentExtension):
|
|||
return self._get_in_ns_ports(fwg_port_ids)
|
||||
|
||||
def _get_in_ns_ports(self, port_ids):
|
||||
"""Returns port objects in the local namespace, along with their
|
||||
"""Get ports in namespace by their IDs.
|
||||
|
||||
Returns port objects in the local namespace, along with their
|
||||
router_info.
|
||||
|
||||
:param port_ids: IDs of router ports (set, list or tuple)
|
||||
"""
|
||||
in_ns_ports = {} # This will be converted to a list later.
|
||||
if port_ids and self.agent_api:
|
||||
|
@ -180,13 +184,21 @@ class FWaaSL3AgentExtension(l3_extension.L3AgentExtension):
|
|||
in_ns_ports[router_info] = [port_id]
|
||||
return list(in_ns_ports.items())
|
||||
|
||||
def _invoke_driver_for_sync_from_plugin(self, ctx, port, firewall_group):
|
||||
"""Calls the FWaaS driver's delete_firewall_group method if firewall
|
||||
def _invoke_driver_for_sync_from_plugin(self, ctx, ports, firewall_group):
|
||||
"""Call driver to sync firewall group.
|
||||
|
||||
Calls the FWaaS driver's delete_firewall_group method if firewall
|
||||
group has status of PENDING_DELETE; calls driver's
|
||||
update_firewall_group method for all other statuses. Both of these
|
||||
methods are idempotent.
|
||||
|
||||
:param ctx: RPC context
|
||||
:param ports: IDs of ports associated with a firewall group
|
||||
(set, list or tuple)
|
||||
:param firewall_group: Dictionary describing the firewall group object
|
||||
|
||||
"""
|
||||
port_list = self._get_in_ns_ports([port['id']])
|
||||
port_list = self._get_in_ns_ports(ports)
|
||||
if firewall_group['status'] == nl_constants.PENDING_DELETE:
|
||||
try:
|
||||
self.fwaas_driver.delete_firewall_group(
|
||||
|
@ -243,17 +255,31 @@ class FWaaSL3AgentExtension(l3_extension.L3AgentExtension):
|
|||
ctx = context.Context('', updated_router['tenant_id'])
|
||||
fwg_list = self.fwplugin_rpc.get_firewall_groups_for_project(ctx)
|
||||
|
||||
if nl_constants.INTERFACE_KEY not in updated_router:
|
||||
return
|
||||
|
||||
# Apply a firewall group, as requested, to ports on the new router.
|
||||
if nl_constants.INTERFACE_KEY in updated_router:
|
||||
for port in updated_router[nl_constants.INTERFACE_KEY]:
|
||||
all_router_ports = set(
|
||||
p['id'] for p in updated_router[nl_constants.INTERFACE_KEY]
|
||||
)
|
||||
processed_ports = set()
|
||||
for firewall_group in fwg_list:
|
||||
if (self._has_port_insertion_fields(firewall_group) and
|
||||
(port['id'] in firewall_group['add-port-ids'] or
|
||||
port['id'] in firewall_group['del-port-ids'])):
|
||||
self._invoke_driver_for_sync_from_plugin(ctx, port,
|
||||
firewall_group)
|
||||
if not self._has_port_insertion_fields(firewall_group):
|
||||
continue
|
||||
|
||||
ports_to_process = (set(firewall_group['add-port-ids'] +
|
||||
firewall_group['del-port-ids']) &
|
||||
all_router_ports)
|
||||
# A port can have at most one firewall group.
|
||||
break
|
||||
port_ids_to_exclude = ports_to_process & processed_ports
|
||||
if port_ids_to_exclude:
|
||||
LOG.warning("Port(s) %s is associated with "
|
||||
"more than one firewall group(s).",
|
||||
port_ids_to_exclude)
|
||||
ports_to_process -= port_ids_to_exclude
|
||||
self._invoke_driver_for_sync_from_plugin(
|
||||
ctx, ports_to_process, firewall_group)
|
||||
processed_ports |= ports_to_process
|
||||
|
||||
def add_router(self, context, new_router):
|
||||
"""Handles agent restart and router add. Fetches firewall groups from
|
||||
|
|
|
@ -383,4 +383,62 @@ class TestFWaaSL3AgentExtension(base.BaseTestCase):
|
|||
mock_get_ipt_mgrs_with_if_prefix.assert_any_call(
|
||||
agent.conf.agent_mode, mock.ANY)
|
||||
|
||||
@mock.patch('oslo_utils.importutils.import_object')
|
||||
def test_add_router_with_several_ports(self, mock_import_object):
|
||||
fw_agent = _setup_test_agent_class([fwaas_constants.FIREWALL])
|
||||
cfg.CONF.set_override('enabled', True, 'fwaas')
|
||||
updated_router = {
|
||||
'_interfaces': [
|
||||
{'device_owner': 'network: router_interface',
|
||||
'id': '1',
|
||||
'tenant_id': 'demo_tenant_id'},
|
||||
{'device_owner': 'network: router_interface',
|
||||
'id': '2',
|
||||
'tenant_id': 'demo_tenant_id'},
|
||||
{'device_owner': 'network: router_interface',
|
||||
'id': '3',
|
||||
'tenant_id': 'demo_tenant_id'}],
|
||||
'tenant_id': 'demo_tenant_id',
|
||||
'id': '0b109a4e-d228-479d-ad43-08bf3245adbb',
|
||||
'name': 'demo_router'
|
||||
}
|
||||
fwg1 = {
|
||||
'status': 'ACTIVE',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'demo_tenant_id',
|
||||
'del-port-ids': [],
|
||||
'add-port-ids': ['1', '3'],
|
||||
'id': '2932b3d9-3a7b-48a1-a16c-bf9f7b2751a5'
|
||||
}
|
||||
fwg2 = {
|
||||
'status': 'ACTIVE',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'demo_tenant_id',
|
||||
'del-port-ids': [],
|
||||
'add-port-ids': ['2', '3'],
|
||||
'id': '2932b3d9-3a7b-48a1-a16c-bf9f7b2751a5'
|
||||
}
|
||||
agent = fw_agent(cfg.CONF)
|
||||
agent.agent_api = mock.Mock()
|
||||
agent.fwplugin_rpc = mock.Mock()
|
||||
agent.conf.agent_mode = mock.Mock()
|
||||
agent.fwaas_driver = iptables_fwaas_v2.IptablesFwaasDriver()
|
||||
|
||||
patch_project = mock.patch.object(
|
||||
agent.fwplugin_rpc, 'get_firewall_groups_for_project')
|
||||
patch_invoke = mock.patch.object(
|
||||
agent, '_invoke_driver_for_sync_from_plugin')
|
||||
|
||||
with patch_project as mock_get_firewall_groups, \
|
||||
patch_invoke as mock_invoke_driver:
|
||||
mock_get_firewall_groups.return_value = [fwg1, fwg2]
|
||||
agent.add_router(self.context, updated_router)
|
||||
|
||||
# Check that mock_invoke_driver was called exactly twice with
|
||||
# correct arguments.
|
||||
self.assertEqual([
|
||||
mock.call(mock.ANY, {'1', '3'}, fwg1),
|
||||
mock.call(mock.ANY, {'2'}, fwg2),
|
||||
], mock_invoke_driver.call_args_list)
|
||||
|
||||
#TODO(Margaret) Add test for add_router method.
|
||||
|
|
Loading…
Reference in New Issue