FWaaS v2 utilize L3 Agent Extension framework
This updates the FWaaS v2 L3 code to move away from an inheritance-based model and use the new L3 agent extension framework. This change rolls back [1] which is the inheritance-based model. [1] https://review.openstack.org/315826 Partial-Implements: blueprint fwaas-api-2.0 Co-Authored-By: Nate Johnston <nate_johnston@cable.comcast.com> Co-Authored-By: Chandan Dutta Chowdhury <chandanc@juniper.net> Depends-On: I85f89accbeefd820130335674fd56cb54f1449de Change-Id: Ib29b96e73d09530cbf627a98180fb1a591e42e3f
This commit is contained in:
parent
b09e41243d
commit
6718fd8560
|
@ -35,6 +35,7 @@ function install_fwaas() {
|
||||||
|
|
||||||
function configure_fwaas() {
|
function configure_fwaas() {
|
||||||
neutron_fwaas_configure_driver
|
neutron_fwaas_configure_driver
|
||||||
|
iniset_multiline $Q_L3_CONF_FILE AGENT extensions fwaas
|
||||||
}
|
}
|
||||||
|
|
||||||
function init_fwaas() {
|
function init_fwaas() {
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
# 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 sys
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_service import service
|
|
||||||
|
|
||||||
from neutron.agent.common import config
|
|
||||||
from neutron.agent.l3 import ha
|
|
||||||
from neutron.agent.linux import external_process
|
|
||||||
from neutron.agent.linux import interface
|
|
||||||
from neutron.agent.linux import pd
|
|
||||||
from neutron.agent.linux import ra
|
|
||||||
from neutron.agent.metadata import config as metadata_config
|
|
||||||
from neutron.common import config as common_config
|
|
||||||
from neutron.common import topics
|
|
||||||
from neutron.conf.agent.l3 import config as l3_config
|
|
||||||
from neutron import service as neutron_service
|
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api as fwa
|
|
||||||
|
|
||||||
|
|
||||||
FWAAS_AGENTS = {fwa.FWAAS_V1: ('neutron_fwaas.services.firewall.agents.'
|
|
||||||
'l3reference.firewall_l3_agent.L3WithFWaaS'),
|
|
||||||
fwa.FWAAS_V2: ('neutron_fwaas.services.firewall.agents.'
|
|
||||||
'l3reference.firewall_l3_agent_v2.L3WithFWaaS')}
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
|
||||||
conf.register_opts(l3_config.OPTS)
|
|
||||||
conf.register_opts(metadata_config.DRIVER_OPTS)
|
|
||||||
conf.register_opts(metadata_config.SHARED_OPTS)
|
|
||||||
conf.register_opts(ha.OPTS)
|
|
||||||
config.register_interface_driver_opts_helper(conf)
|
|
||||||
config.register_agent_state_opts_helper(conf)
|
|
||||||
conf.register_opts(interface.OPTS)
|
|
||||||
conf.register_opts(external_process.OPTS)
|
|
||||||
conf.register_opts(pd.OPTS)
|
|
||||||
conf.register_opts(ra.OPTS)
|
|
||||||
config.register_availability_zone_opts_helper(conf)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
register_opts(cfg.CONF)
|
|
||||||
common_config.init(sys.argv[1:])
|
|
||||||
config.setup_logging()
|
|
||||||
manager = FWAAS_AGENTS[cfg.CONF.fwaas.agent_version]
|
|
||||||
server = neutron_service.Service.create(
|
|
||||||
binary='neutron-l3-agent',
|
|
||||||
topic=topics.L3_AGENT,
|
|
||||||
report_interval=cfg.CONF.AGENT.report_interval,
|
|
||||||
manager=manager)
|
|
||||||
service.launch(cfg.CONF, server).wait()
|
|
|
@ -16,4 +16,5 @@
|
||||||
# Constants for "topics"
|
# Constants for "topics"
|
||||||
FIREWALL_PLUGIN = 'q-firewall-plugin'
|
FIREWALL_PLUGIN = 'q-firewall-plugin'
|
||||||
L3_AGENT = 'l3_agent'
|
L3_AGENT = 'l3_agent'
|
||||||
|
FW_AGENT = 'firewall_agent'
|
||||||
FIREWALL_RULE_LIST = 'firewall_rule_list'
|
FIREWALL_RULE_LIST = 'firewall_rule_list'
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutron.common import eventlet_utils
|
from neutron_fwaas.db.firewall.v2 import firewall_db_v2
|
||||||
|
|
||||||
eventlet_utils.monkey_patch()
|
FIREWALL_GROUP = firewall_db_v2.FirewallGroup
|
||||||
|
FIREWALL_POLICY = firewall_db_v2.FirewallPolicy
|
||||||
|
FIREWALL_RULE = firewall_db_v2.FirewallRuleV2
|
|
@ -46,6 +46,10 @@ class FirewallGroupInPendingState(nexception.Conflict):
|
||||||
"%(firewall_id)s is in %(pending_state)s.")
|
"%(firewall_id)s is in %(pending_state)s.")
|
||||||
|
|
||||||
|
|
||||||
|
class FirewallGroupPortInvalid(nexception.Conflict):
|
||||||
|
message = _("Firewall Group Port %(port_id)s is invalid")
|
||||||
|
|
||||||
|
|
||||||
class FirewallGroupPortInvalidProject(nexception.Conflict):
|
class FirewallGroupPortInvalidProject(nexception.Conflict):
|
||||||
message = _("Firewall Group %(port_id)s in invalid Project")
|
message = _("Firewall Group %(port_id)s in invalid Project")
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutron.agent.l3 import agent
|
from neutron.agent.l3 import l3_agent_extension
|
||||||
from neutron.agent.linux import ip_lib
|
from neutron.common import rpc as n_rpc
|
||||||
from neutron import context
|
from neutron import context
|
||||||
from neutron.plugins.common import constants as n_const
|
from neutron.plugins.common import constants as n_const
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
@ -23,12 +23,16 @@ from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron_fwaas._i18n import _, _LE
|
from neutron_fwaas._i18n import _, _LE
|
||||||
from neutron_fwaas.common import fwaas_constants as f_const
|
from neutron_fwaas.common import fwaas_constants as f_const
|
||||||
|
from neutron_fwaas.common import resources as f_resources
|
||||||
from neutron_fwaas.extensions import firewall as fw_ext
|
from neutron_fwaas.extensions import firewall as fw_ext
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_service
|
from neutron_fwaas.services.firewall.agents import firewall_service
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
#TODO(njohnston): There needs to be some extrapolation of the common code
|
||||||
|
# between this module and firewall_l3_agent_v2.py.
|
||||||
|
|
||||||
|
|
||||||
class FWaaSL3PluginApi(api.FWaaSPluginApiMixin):
|
class FWaaSL3PluginApi(api.FWaaSPluginApiMixin):
|
||||||
"""Agent side of the FWaaS agent to FWaaS Plugin RPC API."""
|
"""Agent side of the FWaaS agent to FWaaS Plugin RPC API."""
|
||||||
|
@ -49,14 +53,39 @@ class FWaaSL3PluginApi(api.FWaaSPluginApiMixin):
|
||||||
'get_tenants_with_firewalls', host=self.host)
|
'get_tenants_with_firewalls', host=self.host)
|
||||||
|
|
||||||
|
|
||||||
class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
class FWaaSL3AgentExtension(l3_agent_extension.L3AgentCoreResourceExtension):
|
||||||
"""FWaaS Agent support to be used by Neutron L3 agent."""
|
"""FWaaS Agent support to be used by Neutron L3 agent."""
|
||||||
|
|
||||||
|
SUPPORTED_RESOURCE_TYPES = [f_resources.FIREWALL_GROUP,
|
||||||
|
f_resources.FIREWALL_POLICY,
|
||||||
|
f_resources.FIREWALL_RULE]
|
||||||
|
|
||||||
|
def initialize(self, connection, driver_type):
|
||||||
|
self._register_rpc_consumers(connection)
|
||||||
|
|
||||||
|
def consume_api(self, agent_api):
|
||||||
|
LOG.debug("FWaaS consume_api call occurred with %s" % agent_api)
|
||||||
|
self.agent_api = agent_api
|
||||||
|
|
||||||
|
def _register_rpc_consumers(self, connection):
|
||||||
|
#TODO(njohnston): Add RPC consumer connection loading here.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start_rpc_listeners(self, conf):
|
||||||
|
self.endpoints = [self]
|
||||||
|
|
||||||
|
self.conn = n_rpc.create_connection()
|
||||||
|
self.conn.create_consumer(
|
||||||
|
f_const.FW_AGENT, self.endpoints, fanout=False)
|
||||||
|
return self.conn.consume_in_threads()
|
||||||
|
|
||||||
def __init__(self, host, conf):
|
def __init__(self, host, conf):
|
||||||
LOG.debug("Initializing firewall agent")
|
LOG.debug("Initializing firewall agent")
|
||||||
|
self.agent_api = None
|
||||||
self.neutron_service_plugins = None
|
self.neutron_service_plugins = None
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.fwaas_enabled = cfg.CONF.fwaas.enabled
|
self.fwaas_enabled = cfg.CONF.fwaas.enabled
|
||||||
|
self.start_rpc_listeners(conf)
|
||||||
|
|
||||||
# None means l3-agent has no information on the server
|
# None means l3-agent has no information on the server
|
||||||
# configuration due to the lack of RPC support.
|
# configuration due to the lack of RPC support.
|
||||||
|
@ -77,8 +106,7 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
self.services_sync_needed = False
|
self.services_sync_needed = False
|
||||||
# setup RPC to msg fwaas plugin
|
# setup RPC to msg fwaas plugin
|
||||||
self.fwplugin_rpc = FWaaSL3PluginApi(f_const.FIREWALL_PLUGIN,
|
self.fwplugin_rpc = FWaaSL3PluginApi(f_const.FIREWALL_PLUGIN,
|
||||||
conf.host)
|
host)
|
||||||
super(FWaaSL3AgentRpcCallback, self).__init__(host=conf.host)
|
|
||||||
|
|
||||||
def _has_router_insertion_fields(self, fw):
|
def _has_router_insertion_fields(self, fw):
|
||||||
return 'add-router-ids' in fw
|
return 'add-router-ids' in fw
|
||||||
|
@ -90,36 +118,24 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
return (fw['del-router-ids'] if to_delete
|
return (fw['del-router-ids'] if to_delete
|
||||||
else fw['add-router-ids'])
|
else fw['add-router-ids'])
|
||||||
else:
|
else:
|
||||||
# we are in a upgrade and msg from older version of plugin
|
return [router['id'] for router in
|
||||||
try:
|
self.agent_api.get_routers_in_project(fw['tenant_id'])]
|
||||||
routers = self.plugin_rpc.get_routers(context)
|
|
||||||
except Exception:
|
def _get_routers_in_project(self, project_id):
|
||||||
LOG.exception(
|
if self.agent_api is None:
|
||||||
_LE("FWaaS RPC failure in _get_router_ids_for_fw "
|
LOG.exception(_LE("FWaaS RPC call failed; L3 agent_api failure"))
|
||||||
"for firewall: %(fwid)s"),
|
router_info = self.agent_api._router_info
|
||||||
{'fwid': fw['id']})
|
if project_id:
|
||||||
self.services_sync_needed = True
|
return [ri for ri in router_info.values()
|
||||||
return [
|
if ri.router['tenant_id'] == project_id]
|
||||||
router['id']
|
else:
|
||||||
for router in routers
|
return []
|
||||||
if router['tenant_id'] == fw['tenant_id']]
|
|
||||||
|
|
||||||
def _get_router_info_list_for_tenant(self, router_ids, tenant_id):
|
def _get_router_info_list_for_tenant(self, router_ids, tenant_id):
|
||||||
"""Returns the list of router info objects on which to apply the fw."""
|
"""Returns the list of router info objects on which to apply the fw."""
|
||||||
root_ip = ip_lib.IPWrapper()
|
return [ri for ri in self._get_routers_in_project(tenant_id)
|
||||||
local_ns_list = root_ip.get_namespaces()
|
if ri.router_id in router_ids and
|
||||||
|
self.agent_api.is_router_in_namespace(ri.router_id)]
|
||||||
router_info_list = []
|
|
||||||
# Pick up namespaces for Tenant Routers
|
|
||||||
for rid in router_ids:
|
|
||||||
# for routers without an interface - get_routers returns
|
|
||||||
# the router - but this is not yet populated in router_info
|
|
||||||
if rid not in self.router_info:
|
|
||||||
continue
|
|
||||||
router_ns = self.router_info[rid].ns_name
|
|
||||||
if router_ns in local_ns_list:
|
|
||||||
router_info_list.append(self.router_info[rid])
|
|
||||||
return router_info_list
|
|
||||||
|
|
||||||
def _invoke_driver_for_sync_from_plugin(self, ctx, router_info_list, fw):
|
def _invoke_driver_for_sync_from_plugin(self, ctx, router_info_list, fw):
|
||||||
"""Invoke the delete driver method for status of PENDING_DELETE and
|
"""Invoke the delete driver method for status of PENDING_DELETE and
|
||||||
|
@ -165,17 +181,17 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
fw['id'],
|
fw['id'],
|
||||||
status)
|
status)
|
||||||
|
|
||||||
def _process_router_add(self, ri):
|
def _process_router_add(self, router):
|
||||||
"""On router add, get fw with rules from plugin and update driver."""
|
"""On router add, get fw with rules from plugin and update driver."""
|
||||||
LOG.debug("Process router add, router_id: '%s'", ri.router['id'])
|
LOG.debug("Process router add, router_id: '%s'", router['id'])
|
||||||
router_ids = ri.router['id']
|
router_ids = router['id']
|
||||||
router_info_list = self._get_router_info_list_for_tenant(
|
router_info_list = self._get_router_info_list_for_tenant(
|
||||||
[router_ids],
|
[router_ids],
|
||||||
ri.router['tenant_id'])
|
router['tenant_id'])
|
||||||
if router_info_list:
|
if router_info_list:
|
||||||
# Get the firewall with rules
|
# Get the firewall with rules
|
||||||
# for the tenant the router is on.
|
# for the tenant the router is on.
|
||||||
ctx = context.Context('', ri.router['tenant_id'])
|
ctx = context.Context('', router['tenant_id'])
|
||||||
fw_list = self.fwplugin_rpc.get_firewalls_for_tenant(ctx)
|
fw_list = self.fwplugin_rpc.get_firewalls_for_tenant(ctx)
|
||||||
for fw in fw_list:
|
for fw in fw_list:
|
||||||
if self._has_router_insertion_fields(fw):
|
if self._has_router_insertion_fields(fw):
|
||||||
|
@ -190,7 +206,7 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
# router can be present only on one fw
|
# router can be present only on one fw
|
||||||
return
|
return
|
||||||
|
|
||||||
def process_router_add(self, ri):
|
def add_router(self, context, new_router):
|
||||||
"""On router add, get fw with rules from plugin and update driver.
|
"""On router add, get fw with rules from plugin and update driver.
|
||||||
|
|
||||||
Handles agent restart, when a router is added, query the plugin to
|
Handles agent restart, when a router is added, query the plugin to
|
||||||
|
@ -201,15 +217,26 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
if not self.fwaas_enabled:
|
if not self.fwaas_enabled:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
# TODO(sridar): as per discussion with pc_m, we may want to hook
|
self._process_router_add(new_router)
|
||||||
# this up to the l3 agent observer notification
|
|
||||||
self._process_router_add(ri)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception(
|
LOG.exception(
|
||||||
_LE("FWaaS RPC info call failed for '%s'."),
|
_LE("FWaaS RPC info call failed for '%s'."),
|
||||||
ri.router['id'])
|
new_router['id'])
|
||||||
self.services_sync_needed = True
|
self.services_sync_needed = True
|
||||||
|
|
||||||
|
def update_router(self, context, updated_router):
|
||||||
|
"""The update_router method is just a synonym for add_router"""
|
||||||
|
self.add_router(context, updated_router)
|
||||||
|
|
||||||
|
def delete_router(self, context, new_router):
|
||||||
|
"""Handles router deletion. There is basically nothing to do for this
|
||||||
|
in the context of FWaaS with an IPTables driver; the namespace will
|
||||||
|
already have been deleted, taking the IPTables rules with it.
|
||||||
|
"""
|
||||||
|
#TODO(njohnston): When another firewall driver is implemented, look at
|
||||||
|
# expanding this out so that the driver can handle deletion calls.
|
||||||
|
pass
|
||||||
|
|
||||||
def process_services_sync(self, ctx):
|
def process_services_sync(self, ctx):
|
||||||
if not self.services_sync_needed:
|
if not self.services_sync_needed:
|
||||||
return
|
return
|
||||||
|
@ -403,9 +430,9 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
self.services_sync_needed = True
|
self.services_sync_needed = True
|
||||||
|
|
||||||
|
|
||||||
class L3WithFWaaS(FWaaSL3AgentRpcCallback, agent.L3NATAgentWithStateReport):
|
class L3WithFWaaS(FWaaSL3AgentExtension):
|
||||||
|
|
||||||
def __init__(self, host, conf=None):
|
def __init__(self, conf=None):
|
||||||
if conf:
|
if conf:
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutron.agent.l3 import agent
|
from neutron.agent.l3 import l3_agent_extension
|
||||||
from neutron.agent.linux import ip_lib
|
from neutron.agent.linux import ip_lib
|
||||||
|
from neutron.common import rpc as n_rpc
|
||||||
from neutron import context
|
from neutron import context
|
||||||
from neutron.plugins.common import constants as n_const
|
from neutron.plugins.common import constants as n_const
|
||||||
from neutron_fwaas.common import fwaas_constants as f_const
|
from neutron_fwaas.common import fwaas_constants as f_const
|
||||||
|
@ -23,6 +24,7 @@ from oslo_log import helpers as log_helpers
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron_fwaas._i18n import _, _LE
|
from neutron_fwaas._i18n import _, _LE
|
||||||
|
from neutron_fwaas.common import resources as f_resources
|
||||||
from neutron_fwaas.extensions import firewall as fw_ext
|
from neutron_fwaas.extensions import firewall as fw_ext
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
from neutron_fwaas.services.firewall.agents import firewall_agent_api as api
|
||||||
from neutron_fwaas.services.firewall.agents import firewall_service
|
from neutron_fwaas.services.firewall.agents import firewall_service
|
||||||
|
@ -67,15 +69,40 @@ class FWaaSL3PluginApi(api.FWaaSPluginApiMixin):
|
||||||
fwg_id=fwg_id, status=status, host=self.host)
|
fwg_id=fwg_id, status=status, host=self.host)
|
||||||
|
|
||||||
|
|
||||||
class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
class FWaaSL3AgentExtension(l3_agent_extension.L3AgentCoreResourceExtension):
|
||||||
"""FWaaS agent support to be used by neutron's L3 agent."""
|
"""FWaaS agent extension."""
|
||||||
|
|
||||||
|
SUPPORTED_RESOURCE_TYPES = [f_resources.FIREWALL_GROUP,
|
||||||
|
f_resources.FIREWALL_POLICY,
|
||||||
|
f_resources.FIREWALL_RULE]
|
||||||
|
|
||||||
|
def initialize(self, connection, driver_type):
|
||||||
|
self._register_rpc_consumers(connection)
|
||||||
|
|
||||||
|
def consume_api(self, agent_api):
|
||||||
|
LOG.debug("FWaaS consume_api call occurred with %s" % agent_api)
|
||||||
|
self.agent_api = agent_api
|
||||||
|
|
||||||
|
def _register_rpc_consumers(self, connection):
|
||||||
|
#TODO(njohnston): Add RPC consumer connection loading here.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start_rpc_listeners(self, host, conf):
|
||||||
|
self.endpoints = [self]
|
||||||
|
|
||||||
|
self.conn = n_rpc.create_connection()
|
||||||
|
self.conn.create_consumer(
|
||||||
|
f_const.FW_AGENT, self.endpoints, fanout=False)
|
||||||
|
return self.conn.consume_in_threads()
|
||||||
|
|
||||||
def __init__(self, host, conf):
|
def __init__(self, host, conf):
|
||||||
LOG.debug("Initializing firewall group agent")
|
LOG.debug("Initializing firewall group agent")
|
||||||
|
self.agent_api = None
|
||||||
self.neutron_service_plugins = None
|
self.neutron_service_plugins = None
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.fwaas_enabled = cfg.CONF.fwaas.enabled
|
self.fwaas_enabled = cfg.CONF.fwaas.enabled
|
||||||
|
|
||||||
|
self.start_rpc_listeners(host, conf)
|
||||||
# None means l3-agent has no information on the server
|
# None means l3-agent has no information on the server
|
||||||
# configuration due to the lack of RPC support.
|
# configuration due to the lack of RPC support.
|
||||||
if self.neutron_service_plugins is not None:
|
if self.neutron_service_plugins is not None:
|
||||||
|
@ -96,7 +123,7 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
self.services_sync_needed = False
|
self.services_sync_needed = False
|
||||||
self.fwplugin_rpc = FWaaSL3PluginApi(f_const.FIREWALL_PLUGIN,
|
self.fwplugin_rpc = FWaaSL3PluginApi(f_const.FIREWALL_PLUGIN,
|
||||||
host)
|
host)
|
||||||
super(FWaaSL3AgentRpcCallback, self).__init__(host=host)
|
super(FWaaSL3AgentExtension, self).__init__()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _local_namespaces(self):
|
def _local_namespaces(self):
|
||||||
|
@ -127,7 +154,8 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
else:
|
else:
|
||||||
fwg_port_ids = firewall_group['add-port-ids']
|
fwg_port_ids = firewall_group['add-port-ids']
|
||||||
elif not require_new_plugin:
|
elif not require_new_plugin:
|
||||||
routers = [self.router_info[rid] for rid in self.router_info]
|
routers = self.agent_api.get_routers_in_project(
|
||||||
|
firewall_group['tenant_id'])
|
||||||
for router in routers:
|
for router in routers:
|
||||||
if router.router['tenant_id'] == firewall_group['tenant_id']:
|
if router.router['tenant_id'] == firewall_group['tenant_id']:
|
||||||
fwg_port_ids.extend([p['id'] for p in
|
fwg_port_ids.extend([p['id'] for p in
|
||||||
|
@ -140,21 +168,17 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
"""Returns port objects in the local namespace, along with their
|
"""Returns port objects in the local namespace, along with their
|
||||||
router_info.
|
router_info.
|
||||||
"""
|
"""
|
||||||
in_ns_ports = []
|
in_ns_ports = {} # This will be converted to a list later.
|
||||||
if port_ids:
|
if port_ids and self.agent_api:
|
||||||
for router_id in self.router_info:
|
for port_id in port_ids:
|
||||||
# For routers without an interface - get_routers returns
|
# This fetched router_info is guaranteed to be in_namespace.
|
||||||
# the router - but this is not yet populated in router_info
|
router_info = self.agent_api.get_router_hosting_port(port_id)
|
||||||
router_info = self.router_info[router_id]
|
if router_info:
|
||||||
if router_info.ns_name not in self._local_namespaces:
|
if router_info in in_ns_ports:
|
||||||
continue
|
in_ns_ports[router_info].append(port_id)
|
||||||
in_ns_router_port_ids = []
|
else:
|
||||||
for port in router_info.internal_ports:
|
in_ns_ports[router_info] = [port_id]
|
||||||
if port['id'] in port_ids:
|
return list(in_ns_ports.items())
|
||||||
in_ns_router_port_ids.append(port['id'])
|
|
||||||
if in_ns_router_port_ids:
|
|
||||||
in_ns_ports.append((router_info, in_ns_router_port_ids))
|
|
||||||
return in_ns_ports
|
|
||||||
|
|
||||||
def _invoke_driver_for_sync_from_plugin(self, ctx, port, firewall_group):
|
def _invoke_driver_for_sync_from_plugin(self, ctx, port, firewall_group):
|
||||||
"""Calls the FWaaS driver's delete_firewall_group method if firewall
|
"""Calls the FWaaS driver's delete_firewall_group method if firewall
|
||||||
|
@ -200,29 +224,27 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
self.fwplugin_rpc.set_firewall_group_status(
|
self.fwplugin_rpc.set_firewall_group_status(
|
||||||
ctx, firewall_group['id'], status)
|
ctx, firewall_group['id'], status)
|
||||||
|
|
||||||
def _process_router_add(self, new_router):
|
def _process_router_update(self, updated_router):
|
||||||
"""If the new router is in the local namespace, queries the plugin to
|
"""If a new or existing router in the local namespace is updated,
|
||||||
get the firewall groups for the project in question and then sees if
|
queries the plugin to get the firewall groups for the project in
|
||||||
the router has any ports for any firewall group that is configured
|
question and then sees if the router has any ports for any firewall
|
||||||
for that project. If so, installs firewall group rules on the
|
group that is configured for that project. If so, installs firewall
|
||||||
requested ports on this router.
|
group rules on the requested ports on this router.
|
||||||
"""
|
"""
|
||||||
LOG.debug("Process router add, router_id: %s.",
|
LOG.debug("Process router update, router_id: %s tenant: %s.",
|
||||||
new_router.router['id'])
|
updated_router['id'], updated_router['tenant_id'])
|
||||||
router_id = new_router.router['id']
|
router_id = updated_router['id']
|
||||||
if router_id not in self.router_info or \
|
if not self.agent_api.is_router_in_namespace(router_id):
|
||||||
self.router_info[router_id].ns_name not in \
|
|
||||||
self._local_namespaces:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get the firewall groups for the new router's project.
|
# Get the firewall groups for the new router's project.
|
||||||
# NOTE: Vernacular move from "tenant" to "project" doesn't yet appear
|
# NOTE: Vernacular move from "tenant" to "project" doesn't yet appear
|
||||||
# as a key in router or firewall group objects.
|
# as a key in router or firewall group objects.
|
||||||
ctx = context.Context('', new_router.router['tenant_id'])
|
ctx = context.Context('', updated_router['tenant_id'])
|
||||||
fwg_list = self.fwplugin_rpc.get_firewall_groups_for_project(ctx)
|
fwg_list = self.fwplugin_rpc.get_firewall_groups_for_project(ctx)
|
||||||
|
|
||||||
# Apply a firewall group, as requested, to ports on the new router.
|
# Apply a firewall group, as requested, to ports on the new router.
|
||||||
for port in new_router.router.internal_ports:
|
for port in updated_router['_interfaces']:
|
||||||
for firewall_group in fwg_list:
|
for firewall_group in fwg_list:
|
||||||
if (self._has_port_insertion_fields(firewall_group) and
|
if (self._has_port_insertion_fields(firewall_group) and
|
||||||
(port['id'] in firewall_group['add-port-ids'] or
|
(port['id'] in firewall_group['add-port-ids'] or
|
||||||
|
@ -232,7 +254,7 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
# A port can have at most one firewall group.
|
# A port can have at most one firewall group.
|
||||||
break
|
break
|
||||||
|
|
||||||
def process_router_add(self, new_router):
|
def add_router(self, context, new_router):
|
||||||
"""Handles agent restart and router add. Fetches firewall groups from
|
"""Handles agent restart and router add. Fetches firewall groups from
|
||||||
plugin and updates driver.
|
plugin and updates driver.
|
||||||
"""
|
"""
|
||||||
|
@ -240,12 +262,37 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._process_router_add(new_router)
|
self._process_router_update(new_router)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception(_LE("FWaaS RPC info call failed for %s"),
|
LOG.exception(_LE("FWaaS router add RPC info call failed for %s"),
|
||||||
new_router.router['id'])
|
new_router['id'])
|
||||||
self.services_sync_needed = True
|
self.services_sync_needed = True
|
||||||
|
|
||||||
|
def update_router(self, context, updated_router):
|
||||||
|
"""Handles agent restart and router add. Fetches firewall groups from
|
||||||
|
plugin and updates driver.
|
||||||
|
"""
|
||||||
|
if not self.fwaas_enabled:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._process_router_update(updated_router)
|
||||||
|
except Exception:
|
||||||
|
#TODO(njohnston): This repr should be replaced.
|
||||||
|
LOG.exception(
|
||||||
|
_LE("FWaaS router update RPC info call failed for %s"),
|
||||||
|
repr(updated_router))
|
||||||
|
self.services_sync_needed = True
|
||||||
|
|
||||||
|
def delete_router(self, context, new_router):
|
||||||
|
"""Handles router deletion. There is basically nothing to do for this
|
||||||
|
in the context of FWaaS with an IPTables driver; the namespace will
|
||||||
|
already have been deleted, taking the IPTables rules with it.
|
||||||
|
"""
|
||||||
|
#TODO(njohnston): When another firewall driver is implemented, look at
|
||||||
|
# expanding this out so that the driver can handle deletion calls.
|
||||||
|
pass
|
||||||
|
|
||||||
def process_services_sync(self, ctx):
|
def process_services_sync(self, ctx):
|
||||||
"""Syncs with plugin and applies the sync data.
|
"""Syncs with plugin and applies the sync data.
|
||||||
"""
|
"""
|
||||||
|
@ -283,7 +330,6 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
|
|
||||||
# Get the in-namespace ports to which to add the firewall group.
|
# Get the in-namespace ports to which to add the firewall group.
|
||||||
ports_for_fwg = self._get_firewall_group_ports(context, firewall_group)
|
ports_for_fwg = self._get_firewall_group_ports(context, firewall_group)
|
||||||
|
|
||||||
if not ports_for_fwg:
|
if not ports_for_fwg:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -451,9 +497,9 @@ class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
|
||||||
self.services_sync_needed = True
|
self.services_sync_needed = True
|
||||||
|
|
||||||
|
|
||||||
class L3WithFWaaS(FWaaSL3AgentRpcCallback, agent.L3NATAgentWithStateReport):
|
class L3WithFWaaS(FWaaSL3AgentExtension):
|
||||||
|
|
||||||
def __init__(self, host, conf=None):
|
def __init__(self, conf=None):
|
||||||
if conf:
|
if conf:
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -59,8 +59,8 @@ class FwaasDriverBase(object):
|
||||||
application of rules. Argument agent_mode indicates the l3 agent in DVR or
|
application of rules. Argument agent_mode indicates the l3 agent in DVR or
|
||||||
DVR_SNAT or LEGACY mode.
|
DVR_SNAT or LEGACY mode.
|
||||||
"""
|
"""
|
||||||
|
# TODO(Margaret): Remove the first 3 methods and make the second three
|
||||||
@abc.abstractmethod
|
# @abc.abstractmethod
|
||||||
def create_firewall(self, agent_mode, apply_list, firewall):
|
def create_firewall(self, agent_mode, apply_list, firewall):
|
||||||
"""Create the Firewall with default (drop all) policy.
|
"""Create the Firewall with default (drop all) policy.
|
||||||
|
|
||||||
|
@ -69,7 +69,6 @@ class FwaasDriverBase(object):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def delete_firewall(self, agent_mode, apply_list, firewall):
|
def delete_firewall(self, agent_mode, apply_list, firewall):
|
||||||
"""Delete firewall.
|
"""Delete firewall.
|
||||||
|
|
||||||
|
@ -78,7 +77,6 @@ class FwaasDriverBase(object):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def update_firewall(self, agent_mode, apply_list, firewall):
|
def update_firewall(self, agent_mode, apply_list, firewall):
|
||||||
"""Apply the policy on all trusted interfaces.
|
"""Apply the policy on all trusted interfaces.
|
||||||
|
|
||||||
|
@ -87,6 +85,30 @@ class FwaasDriverBase(object):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def create_firewall_group(self, agent_mode, apply_list, firewall):
|
||||||
|
"""Create the Firewall with default (drop all) policy.
|
||||||
|
|
||||||
|
The default policy will be applied on all the interfaces of
|
||||||
|
trusted zone.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_firewall_group(self, agent_mode, apply_list, firewall):
|
||||||
|
"""Delete firewall.
|
||||||
|
|
||||||
|
Removes all policies created by this instance and frees up
|
||||||
|
all the resources.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_firewall_group(self, agent_mode, apply_list, firewall):
|
||||||
|
"""Apply the policy on all trusted interfaces.
|
||||||
|
|
||||||
|
Remove previous policy and apply the new policy on all trusted
|
||||||
|
interfaces.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def apply_default_policy(self, agent_mode, apply_list, firewall):
|
def apply_default_policy(self, agent_mode, apply_list, firewall):
|
||||||
"""Apply the default policy on all trusted interfaces.
|
"""Apply the default policy on all trusted interfaces.
|
||||||
|
|
|
@ -58,6 +58,9 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
LOG.debug("Initializing fwaas iptables driver")
|
LOG.debug("Initializing fwaas iptables driver")
|
||||||
self.pre_firewall = None
|
self.pre_firewall = None
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def _get_intf_name(self, if_prefix, port_id):
|
def _get_intf_name(self, if_prefix, port_id):
|
||||||
_name = "%s%s" % (if_prefix, port_id)
|
_name = "%s%s" % (if_prefix, port_id)
|
||||||
return _name[:MAX_INTF_NAME_LEN]
|
return _name[:MAX_INTF_NAME_LEN]
|
||||||
|
@ -78,7 +81,7 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
LOG.exception(_LE("Failed to create firewall: %s"), firewall['id'])
|
LOG.exception(_LE("Failed to create firewall: %s"), firewall['id'])
|
||||||
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
|
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
|
||||||
|
|
||||||
def _get_ipt_mgrs_with_if_prefix(self, agent_mode, router_info):
|
def _get_ipt_mgrs_with_if_prefix(self, agent_mode, ri):
|
||||||
"""Gets the iptables manager along with the if prefix to apply rules.
|
"""Gets the iptables manager along with the if prefix to apply rules.
|
||||||
|
|
||||||
With DVR we can have differing namespaces depending on which agent
|
With DVR we can have differing namespaces depending on which agent
|
||||||
|
@ -88,18 +91,18 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
namespace and a fip so this is provided back as a list - so in that
|
namespace and a fip so this is provided back as a list - so in that
|
||||||
scenario rules can be applied on both.
|
scenario rules can be applied on both.
|
||||||
"""
|
"""
|
||||||
if not router_info.router.get('distributed'):
|
if not ri.router.get('distributed'):
|
||||||
return [{'ipt': router_info.iptables_manager,
|
return [{'ipt': ri.iptables_manager,
|
||||||
'if_prefix': INTERNAL_DEV_PREFIX}]
|
'if_prefix': INTERNAL_DEV_PREFIX}]
|
||||||
ipt_mgrs = []
|
ipt_mgrs = []
|
||||||
# TODO(sridar): refactor to get strings to a common location.
|
# TODO(sridar): refactor to get strings to a common location.
|
||||||
if agent_mode == 'dvr_snat':
|
if agent_mode == 'dvr_snat':
|
||||||
if router_info.snat_iptables_manager:
|
if ri.snat_iptables_manager:
|
||||||
ipt_mgrs.append({'ipt': router_info.snat_iptables_manager,
|
ipt_mgrs.append({'ipt': ri.snat_iptables_manager,
|
||||||
'if_prefix': SNAT_INT_DEV_PREFIX})
|
'if_prefix': SNAT_INT_DEV_PREFIX})
|
||||||
if router_info.dist_fip_count:
|
if ri.dist_fip_count:
|
||||||
# handle the fip case on n/w or compute node.
|
# handle the fip case on n/w or compute node.
|
||||||
ipt_mgrs.append({'ipt': router_info.iptables_manager,
|
ipt_mgrs.append({'ipt': ri.iptables_manager,
|
||||||
'if_prefix': ROUTER_2_FIP_DEV_PREFIX})
|
'if_prefix': ROUTER_2_FIP_DEV_PREFIX})
|
||||||
return ipt_mgrs
|
return ipt_mgrs
|
||||||
|
|
||||||
|
@ -108,9 +111,9 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
|
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
|
||||||
fwid = firewall['id']
|
fwid = firewall['id']
|
||||||
try:
|
try:
|
||||||
for router_info, router_fw_ports in apply_list:
|
for ri, router_fw_ports in apply_list:
|
||||||
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
||||||
agent_mode, router_info)
|
agent_mode, ri)
|
||||||
for ipt_if_prefix in ipt_if_prefix_list:
|
for ipt_if_prefix in ipt_if_prefix_list:
|
||||||
ipt_mgr = ipt_if_prefix['ipt']
|
ipt_mgr = ipt_if_prefix['ipt']
|
||||||
self._remove_chains(fwid, ipt_mgr)
|
self._remove_chains(fwid, ipt_mgr)
|
||||||
|
@ -148,9 +151,9 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
|
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
|
||||||
fwid = firewall['id']
|
fwid = firewall['id']
|
||||||
try:
|
try:
|
||||||
for router_info, router_fw_ports in apply_list:
|
for ri, router_fw_ports in apply_list:
|
||||||
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
||||||
agent_mode, router_info)
|
agent_mode, ri)
|
||||||
for ipt_if_prefix in ipt_if_prefix_list:
|
for ipt_if_prefix in ipt_if_prefix_list:
|
||||||
# the following only updates local memory; no hole in FW
|
# the following only updates local memory; no hole in FW
|
||||||
ipt_mgr = ipt_if_prefix['ipt']
|
ipt_mgr = ipt_if_prefix['ipt']
|
||||||
|
@ -172,9 +175,9 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
|
|
||||||
def _setup_firewall(self, agent_mode, apply_list, firewall):
|
def _setup_firewall(self, agent_mode, apply_list, firewall):
|
||||||
fwid = firewall['id']
|
fwid = firewall['id']
|
||||||
for router_info, router_fw_ports in apply_list:
|
for ri, router_fw_ports in apply_list:
|
||||||
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
||||||
agent_mode, router_info)
|
agent_mode, ri)
|
||||||
for ipt_if_prefix in ipt_if_prefix_list:
|
for ipt_if_prefix in ipt_if_prefix_list:
|
||||||
ipt_mgr = ipt_if_prefix['ipt']
|
ipt_mgr = ipt_if_prefix['ipt']
|
||||||
# the following only updates local memory; no hole in FW
|
# the following only updates local memory; no hole in FW
|
||||||
|
@ -298,9 +301,9 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
def _remove_conntrack_new_firewall(self, agent_mode, apply_list, firewall):
|
def _remove_conntrack_new_firewall(self, agent_mode, apply_list, firewall):
|
||||||
"""Remove conntrack when create new firewall"""
|
"""Remove conntrack when create new firewall"""
|
||||||
routers_list = list(set([apply_info[0] for apply_info in apply_list]))
|
routers_list = list(set([apply_info[0] for apply_info in apply_list]))
|
||||||
for router_info in routers_list:
|
for ri in routers_list:
|
||||||
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
||||||
agent_mode, router_info)
|
agent_mode, ri)
|
||||||
for ipt_if_prefix in ipt_if_prefix_list:
|
for ipt_if_prefix in ipt_if_prefix_list:
|
||||||
ipt_mgr = ipt_if_prefix['ipt']
|
ipt_mgr = ipt_if_prefix['ipt']
|
||||||
cmd = self._get_conntrack_cmd_from_rule(ipt_mgr)
|
cmd = self._get_conntrack_cmd_from_rule(ipt_mgr)
|
||||||
|
@ -310,9 +313,9 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
apply_list, pre_firewall, firewall):
|
apply_list, pre_firewall, firewall):
|
||||||
"""Remove conntrack when updated firewall"""
|
"""Remove conntrack when updated firewall"""
|
||||||
routers_list = list(set([apply_info[0] for apply_info in apply_list]))
|
routers_list = list(set([apply_info[0] for apply_info in apply_list]))
|
||||||
for router_info in routers_list:
|
for ri in routers_list:
|
||||||
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
|
||||||
agent_mode, router_info)
|
agent_mode, ri)
|
||||||
for ipt_if_prefix in ipt_if_prefix_list:
|
for ipt_if_prefix in ipt_if_prefix_list:
|
||||||
ipt_mgr = ipt_if_prefix['ipt']
|
ipt_mgr = ipt_if_prefix['ipt']
|
||||||
ch_rules = self._find_changed_rules(pre_firewall,
|
ch_rules = self._find_changed_rules(pre_firewall,
|
||||||
|
@ -391,7 +394,7 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
||||||
jump_rule = ['%s %s -j %s-%s' % (
|
jump_rule = ['%s %s -j %s-%s' % (
|
||||||
IPTABLES_DIR[direction], intf_name,
|
IPTABLES_DIR[direction], intf_name,
|
||||||
bname, chain_name)]
|
bname, chain_name)]
|
||||||
self._add_rules_to_chain(ipt_mgr, ver,
|
self._add_rules_to_chain(ipt_mgr, ver,
|
||||||
'FORWARD', jump_rule)
|
'FORWARD', jump_rule)
|
||||||
|
|
||||||
# jump to DROP_ALL policy
|
# jump to DROP_ALL policy
|
||||||
|
|
|
@ -148,7 +148,7 @@ class FirewallPlugin(
|
||||||
self.start_rpc_listeners()
|
self.start_rpc_listeners()
|
||||||
|
|
||||||
self.agent_rpc = FirewallAgentApi(
|
self.agent_rpc = FirewallAgentApi(
|
||||||
f_const.L3_AGENT,
|
f_const.FW_AGENT,
|
||||||
cfg.CONF.host
|
cfg.CONF.host
|
||||||
)
|
)
|
||||||
firewall_db.subscribe()
|
firewall_db.subscribe()
|
||||||
|
|
|
@ -107,11 +107,11 @@ class FirewallCallbacks(object):
|
||||||
if fwg['status'] == n_const.PENDING_DELETE:
|
if fwg['status'] == n_const.PENDING_DELETE:
|
||||||
fwg_with_rules['add-port-ids'] = []
|
fwg_with_rules['add-port-ids'] = []
|
||||||
fwg_with_rules['del-port-ids'] = (
|
fwg_with_rules['del-port-ids'] = (
|
||||||
self.plugin._get_ports_for_firewall_group(context,
|
self.plugin._get_ports_in_firewall_group(context,
|
||||||
fwg['id']))
|
fwg['id']))
|
||||||
else:
|
else:
|
||||||
fwg_with_rules['add-port-ids'] = (
|
fwg_with_rules['add-port-ids'] = (
|
||||||
self.plugin._get_ports_for_firewall_group(context,
|
self.plugin._get_ports_in_firewall_group(context,
|
||||||
fwg['id']))
|
fwg['id']))
|
||||||
fwg_with_rules['del-port-ids'] = []
|
fwg_with_rules['del-port-ids'] = []
|
||||||
fwg_list.append(fwg_with_rules)
|
fwg_list.append(fwg_with_rules)
|
||||||
|
@ -142,7 +142,7 @@ class FirewallPluginV2(
|
||||||
self.start_rpc_listeners()
|
self.start_rpc_listeners()
|
||||||
|
|
||||||
self.agent_rpc = FirewallAgentApi(
|
self.agent_rpc = FirewallAgentApi(
|
||||||
f_const.L3_AGENT,
|
f_const.FW_AGENT,
|
||||||
cfg.CONF.host
|
cfg.CONF.host
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -205,6 +205,8 @@ class FirewallPluginV2(
|
||||||
# TODO(sridar): elevated context and do we want to use public ?
|
# TODO(sridar): elevated context and do we want to use public ?
|
||||||
for port_id in fwg_ports:
|
for port_id in fwg_ports:
|
||||||
port_db = self._core_plugin._get_port(context, port_id)
|
port_db = self._core_plugin._get_port(context, port_id)
|
||||||
|
if port_db['device_owner'] != "network:router_interface":
|
||||||
|
raise fw_ext.FirewallGroupPortInvalid(port_id=port_id)
|
||||||
if port_db['tenant_id'] != tenant_id:
|
if port_db['tenant_id'] != tenant_id:
|
||||||
raise fw_ext.FirewallGroupPortInvalidProject(port_id=port_id)
|
raise fw_ext.FirewallGroupPortInvalidProject(port_id=port_id)
|
||||||
return
|
return
|
||||||
|
|
|
@ -12,13 +12,15 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import testtools
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import mock
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from neutron.agent.l3 import config as l3_config
|
from neutron.agent.l3 import config as l3_config
|
||||||
from neutron.agent.l3 import ha
|
from neutron.agent.l3 import ha
|
||||||
|
from neutron.agent.l3 import l3_agent_extension_api as l3_agent_api
|
||||||
from neutron.agent.l3 import router_info
|
from neutron.agent.l3 import router_info
|
||||||
from neutron.agent.linux import ip_lib
|
from neutron.agent.linux import ip_lib
|
||||||
from neutron.conf import common as base_config
|
from neutron.conf import common as base_config
|
||||||
|
@ -38,12 +40,12 @@ class FWaasHelper(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FWaasAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, FWaasHelper):
|
class FWaasAgent(firewall_l3_agent.FWaaSL3AgentExtension, FWaasHelper):
|
||||||
neutron_service_plugins = []
|
neutron_service_plugins = []
|
||||||
|
|
||||||
|
|
||||||
def _setup_test_agent_class(service_plugins):
|
def _setup_test_agent_class(service_plugins):
|
||||||
class FWaasTestAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
|
class FWaasTestAgent(firewall_l3_agent.FWaaSL3AgentExtension,
|
||||||
FWaasHelper):
|
FWaasHelper):
|
||||||
neutron_service_plugins = service_plugins
|
neutron_service_plugins = service_plugins
|
||||||
|
|
||||||
|
@ -64,13 +66,15 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
self.conf.register_opts(l3_config.OPTS)
|
self.conf.register_opts(l3_config.OPTS)
|
||||||
self.conf.register_opts(ha.OPTS)
|
self.conf.register_opts(ha.OPTS)
|
||||||
self.conf.register_opts(firewall_agent_api.FWaaSOpts, 'fwaas')
|
self.conf.register_opts(firewall_agent_api.FWaaSOpts, 'fwaas')
|
||||||
self.api = FWaasAgent("myhost", self.conf)
|
self.api = FWaasAgent(host=None, conf=self.conf)
|
||||||
self.api.fwaas_driver = test_firewall_agent_api.NoopFwaasDriver()
|
self.api.fwaas_driver = test_firewall_agent_api.NoopFwaasDriver()
|
||||||
self.adminContext = context.get_admin_context()
|
self.adminContext = context.get_admin_context()
|
||||||
self.router_id = str(uuid.uuid4())
|
self.router_id = str(uuid.uuid4())
|
||||||
self.agent_conf = mock.Mock()
|
self.agent_conf = mock.Mock()
|
||||||
|
project_id = str(uuid.uuid4()) # For 'tenant_id' and 'project_id' keys
|
||||||
self.ri_kwargs = {'router': {'id': self.router_id,
|
self.ri_kwargs = {'router': {'id': self.router_id,
|
||||||
'tenant_id': str(uuid.uuid4())},
|
'tenant_id': project_id,
|
||||||
|
'project_id': project_id},
|
||||||
'agent_conf': self.agent_conf,
|
'agent_conf': self.agent_conf,
|
||||||
'interface_driver': mock.ANY,
|
'interface_driver': mock.ANY,
|
||||||
'use_ipv6': mock.ANY,
|
'use_ipv6': mock.ANY,
|
||||||
|
@ -82,8 +86,8 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
with mock.patch('oslo_utils.importutils.import_object'):
|
with mock.patch('oslo_utils.importutils.import_object'):
|
||||||
test_agent_class(cfg.CONF)
|
test_agent_class(cfg.CONF)
|
||||||
|
|
||||||
|
@testtools.skip('needs to be refactored for fwaas v2')
|
||||||
def test_fw_config_mismatch_plugin_enabled_agent_disabled(self):
|
def test_fw_config_mismatch_plugin_enabled_agent_disabled(self):
|
||||||
self.skipTest('this is broken')
|
|
||||||
test_agent_class = _setup_test_agent_class([constants.FIREWALL])
|
test_agent_class = _setup_test_agent_class([constants.FIREWALL])
|
||||||
cfg.CONF.set_override('enabled', False, 'fwaas')
|
cfg.CONF.set_override('enabled', False, 'fwaas')
|
||||||
self.assertRaises(SystemExit, test_agent_class, cfg.CONF)
|
self.assertRaises(SystemExit, test_agent_class, cfg.CONF)
|
||||||
|
@ -300,9 +304,15 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
|
|
||||||
def test_get_router_info_list_for_tenant(self):
|
def test_get_router_info_list_for_tenant(self):
|
||||||
ri = self._prepare_router_data()
|
ri = self._prepare_router_data()
|
||||||
|
router_info = {ri.router_id: ri}
|
||||||
|
self.api.router_info = router_info
|
||||||
|
|
||||||
|
api_object = l3_agent_api.L3AgentExtensionAPI(router_info)
|
||||||
|
self.api.consume_api(api_object)
|
||||||
|
|
||||||
routers = [ri.router]
|
routers = [ri.router]
|
||||||
router_ids = [router['id'] for router in routers]
|
router_ids = [router['id'] for router in routers]
|
||||||
self.api.router_info = {ri.router_id: ri}
|
|
||||||
with mock.patch.object(ip_lib.IPWrapper,
|
with mock.patch.object(ip_lib.IPWrapper,
|
||||||
'get_namespaces') as mock_get_namespaces:
|
'get_namespaces') as mock_get_namespaces:
|
||||||
mock_get_namespaces.return_value = []
|
mock_get_namespaces.return_value = []
|
||||||
|
@ -316,19 +326,27 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
rtr_with_ri):
|
rtr_with_ri):
|
||||||
# ri.router with associated router_info (ri)
|
# ri.router with associated router_info (ri)
|
||||||
# rtr2 has no router_info
|
# rtr2 has no router_info
|
||||||
|
|
||||||
ri = self._prepare_router_data()
|
ri = self._prepare_router_data()
|
||||||
rtr2 = {'id': str(uuid.uuid4()), 'tenant_id': ri.router['tenant_id']}
|
rtr2 = {'id': str(uuid.uuid4()), 'tenant_id': ri.router['tenant_id']}
|
||||||
|
|
||||||
routers = [rtr2]
|
routers = [rtr2]
|
||||||
self.api.router_info = {}
|
router_info = {}
|
||||||
ri_expected = []
|
ri_expected = []
|
||||||
|
|
||||||
if rtr_with_ri:
|
if rtr_with_ri:
|
||||||
self.api.router_info[ri.router_id] = ri
|
router_info[ri.router_id] = ri
|
||||||
routers.append(ri.router)
|
routers.append(ri.router)
|
||||||
ri_expected.append(ri)
|
ri_expected.append(ri)
|
||||||
|
|
||||||
|
self.api.router_info = router_info
|
||||||
router_ids = [router['id'] for router in routers]
|
router_ids = [router['id'] for router in routers]
|
||||||
|
|
||||||
with mock.patch.object(ip_lib.IPWrapper,
|
with mock.patch.object(ip_lib.IPWrapper,
|
||||||
'get_namespaces') as mock_get_namespaces:
|
'get_namespaces') as mock_get_namespaces:
|
||||||
mock_get_namespaces.return_value = ri.ns_name
|
mock_get_namespaces.return_value = [ri.ns_name]
|
||||||
|
api_object = l3_agent_api.L3AgentExtensionAPI(router_info)
|
||||||
|
self.api.consume_api(api_object)
|
||||||
router_info_list = self.api._get_router_info_list_for_tenant(
|
router_info_list = self.api._get_router_info_list_for_tenant(
|
||||||
router_ids,
|
router_ids,
|
||||||
ri.router['tenant_id'])
|
ri.router['tenant_id'])
|
||||||
|
|
|
@ -19,6 +19,7 @@ import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from neutron.agent.l3 import config as l3_config
|
from neutron.agent.l3 import config as l3_config
|
||||||
|
from neutron.agent.l3 import l3_agent_extension_api as l3_agent_api
|
||||||
from neutron.agent.l3 import router_info
|
from neutron.agent.l3 import router_info
|
||||||
from neutron.agent.linux import ip_lib
|
from neutron.agent.linux import ip_lib
|
||||||
from neutron import context
|
from neutron import context
|
||||||
|
@ -33,35 +34,54 @@ from neutron_fwaas.tests.unit.services.firewall.agents \
|
||||||
|
|
||||||
|
|
||||||
class FWaasHelper(object):
|
class FWaasHelper(object):
|
||||||
def __init__(self, host):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FWaasAgent(firewall_l3_agent_v2.FWaaSL3AgentRpcCallback, FWaasHelper):
|
class FWaasAgent(firewall_l3_agent_v2.L3WithFWaaS, FWaasHelper):
|
||||||
neutron_service_plugins = []
|
neutron_service_plugins = []
|
||||||
|
|
||||||
|
def add_router(self, context, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_router(self, context, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_router(self, context, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _setup_test_agent_class(service_plugins):
|
def _setup_test_agent_class(service_plugins):
|
||||||
class FWaasTestAgent(firewall_l3_agent_v2.FWaaSL3AgentRpcCallback,
|
class FWaasTestAgent(firewall_l3_agent_v2.L3WithFWaaS,
|
||||||
FWaasHelper):
|
FWaasHelper):
|
||||||
neutron_service_plugins = service_plugins
|
neutron_service_plugins = service_plugins
|
||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
self.event_observers = mock.Mock()
|
self.event_observers = mock.Mock()
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
super(FWaasTestAgent, self).__init__('myhost', conf)
|
super(FWaasTestAgent, self).__init__(conf)
|
||||||
|
|
||||||
|
def add_router(self, context, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_router(self, context, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_router(self, context, data):
|
||||||
|
pass
|
||||||
|
|
||||||
return FWaasTestAgent
|
return FWaasTestAgent
|
||||||
|
|
||||||
|
|
||||||
class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
class TestFWaaSL3AgentExtension(base.BaseTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestFwaasL3AgentRpcCallback, self).setUp()
|
super(TestFWaaSL3AgentExtension, self).setUp()
|
||||||
|
|
||||||
self.conf = cfg.ConfigOpts()
|
self.conf = cfg.ConfigOpts()
|
||||||
self.conf.register_opts(l3_config.OPTS)
|
self.conf.register_opts(l3_config.OPTS)
|
||||||
self.conf.register_opts(firewall_agent_api.FWaaSOpts, 'fwaas')
|
self.conf.register_opts(firewall_agent_api.FWaaSOpts, 'fwaas')
|
||||||
self.api = FWaasAgent('myhost', self.conf)
|
self.conf.host = 'myhost'
|
||||||
|
self.api = FWaasAgent(self.conf)
|
||||||
self.api.fwaas_driver = test_firewall_agent_api.NoopFwaasDriverV2()
|
self.api.fwaas_driver = test_firewall_agent_api.NoopFwaasDriverV2()
|
||||||
self.adminContext = context.get_admin_context()
|
self.adminContext = context.get_admin_context()
|
||||||
self.context = mock.sentinel.context
|
self.context = mock.sentinel.context
|
||||||
|
@ -279,7 +299,9 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
ports = [{'id': pid} for pid in port_ids]
|
ports = [{'id': pid} for pid in port_ids]
|
||||||
ri = self._prepare_router_data()
|
ri = self._prepare_router_data()
|
||||||
ri.internal_ports = ports
|
ri.internal_ports = ports
|
||||||
self.api.router_info = {ri.router_id: ri}
|
router_info = {ri.router_id: ri}
|
||||||
|
api_object = l3_agent_api.L3AgentExtensionAPI(router_info)
|
||||||
|
self.api.consume_api(api_object)
|
||||||
fw_port_ids = port_ids
|
fw_port_ids = port_ids
|
||||||
|
|
||||||
with mock.patch.object(ip_lib.IPWrapper,
|
with mock.patch.object(ip_lib.IPWrapper,
|
||||||
|
@ -288,7 +310,7 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
mock_get_namespaces.return_value = []
|
mock_get_namespaces.return_value = []
|
||||||
ports_for_fw_list = self.api._get_in_ns_ports(fw_port_ids)
|
ports_for_fw_list = self.api._get_in_ns_ports(fw_port_ids)
|
||||||
|
|
||||||
mock_get_namespaces.assert_called_once_with()
|
mock_get_namespaces.assert_called_with()
|
||||||
self.assertFalse(ports_for_fw_list)
|
self.assertFalse(ports_for_fw_list)
|
||||||
|
|
||||||
def test_get_in_ns_ports_for_fw(self):
|
def test_get_in_ns_ports_for_fw(self):
|
||||||
|
@ -296,8 +318,10 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
ports = [{'id': pid} for pid in port_ids]
|
ports = [{'id': pid} for pid in port_ids]
|
||||||
ri = self._prepare_router_data()
|
ri = self._prepare_router_data()
|
||||||
ri.internal_ports = ports
|
ri.internal_ports = ports
|
||||||
self.api.router_info = {}
|
router_info = {}
|
||||||
self.api.router_info[ri.router_id] = ri
|
router_info[ri.router_id] = ri
|
||||||
|
api_object = l3_agent_api.L3AgentExtensionAPI(router_info)
|
||||||
|
self.api.consume_api(api_object)
|
||||||
fw_port_ids = port_ids
|
fw_port_ids = port_ids
|
||||||
ports_for_fw_expected = [(ri, port_ids)]
|
ports_for_fw_expected = [(ri, port_ids)]
|
||||||
|
|
||||||
|
@ -306,3 +330,5 @@ class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
|
||||||
mock_get_namespaces.return_value = [ri.ns_name]
|
mock_get_namespaces.return_value = [ri.ns_name]
|
||||||
ports_for_fw_actual = self.api._get_in_ns_ports(fw_port_ids)
|
ports_for_fw_actual = self.api._get_in_ns_ports(fw_port_ids)
|
||||||
self.assertEqual(ports_for_fw_expected, ports_for_fw_actual)
|
self.assertEqual(ports_for_fw_expected, ports_for_fw_actual)
|
||||||
|
|
||||||
|
#TODO(Margaret) Add test for add_router method.
|
||||||
|
|
|
@ -28,13 +28,13 @@ class NoopFwaasDriver(fwaas_base.FwaasDriverBase):
|
||||||
This driver is for disabling Fwaas functionality.
|
This driver is for disabling Fwaas functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def create_firewall(self, agent_mode, apply_list, firewall):
|
def create_firewall_group(self, agent_mode, apply_list, firewall):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def delete_firewall(self, agent_mode, apply_list, firewall):
|
def delete_firewall_group(self, agent_mode, apply_list, firewall):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def update_firewall(self, agent_mode, apply_list, firewall):
|
def update_firewall_group(self, agent_mode, apply_list, firewall):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def apply_default_policy(self, agent_mode, apply_list, firewall):
|
def apply_default_policy(self, agent_mode, apply_list, firewall):
|
||||||
|
|
|
@ -181,11 +181,14 @@ class IptablesFwaasTestCase(base.BaseTestCase):
|
||||||
mock.call.add_rule(egress_chain, rule2),
|
mock.call.add_rule(egress_chain, rule2),
|
||||||
mock.call.add_rule(egress_chain, rule3)]
|
mock.call.add_rule(egress_chain, rule3)]
|
||||||
|
|
||||||
intf_name = self._get_intf_name(if_prefix, FAKE_PORT_IDS[-1])
|
for port in FAKE_PORT_IDS:
|
||||||
calls.append(mock.call.add_rule('FORWARD',
|
intf_name = self._get_intf_name(if_prefix, port)
|
||||||
'-o %s -j %s' % (intf_name, ipt_mgr_ichain)))
|
calls.append(mock.call.add_rule('FORWARD',
|
||||||
calls.append(mock.call.add_rule('FORWARD',
|
'-o %s -j %s' % (intf_name, ipt_mgr_ichain)))
|
||||||
'-i %s -j %s' % (intf_name, ipt_mgr_echain)))
|
for port in FAKE_PORT_IDS:
|
||||||
|
intf_name = self._get_intf_name(if_prefix, port)
|
||||||
|
calls.append(mock.call.add_rule('FORWARD',
|
||||||
|
'-i %s -j %s' % (intf_name, ipt_mgr_echain)))
|
||||||
|
|
||||||
for direction in ['o', 'i']:
|
for direction in ['o', 'i']:
|
||||||
for port_id in FAKE_PORT_IDS:
|
for port_id in FAKE_PORT_IDS:
|
||||||
|
|
|
@ -27,13 +27,12 @@ setup-hooks =
|
||||||
pbr.hooks.setup_hook
|
pbr.hooks.setup_hook
|
||||||
|
|
||||||
[entry_points]
|
[entry_points]
|
||||||
console_scripts =
|
|
||||||
neutron-l3-agent = neutron_fwaas.cmd.eventlet.agents.fw:main
|
|
||||||
firewall_drivers =
|
firewall_drivers =
|
||||||
# These are for backwards compat with Juno firewall service provider
|
# These are for backwards compat with Juno firewall service provider
|
||||||
# configuration values
|
# configuration values
|
||||||
neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
||||||
iptables = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
iptables = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
||||||
|
iptables_v2 = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas_v2:IptablesFwaasDriver
|
||||||
neutron.service_plugins =
|
neutron.service_plugins =
|
||||||
firewall = neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin
|
firewall = neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin
|
||||||
firewall_v2 = neutron_fwaas.services.firewall.fwaas_plugin_v2:FirewallPluginV2
|
firewall_v2 = neutron_fwaas.services.firewall.fwaas_plugin_v2:FirewallPluginV2
|
||||||
|
@ -45,6 +44,9 @@ tempest.test_plugins =
|
||||||
neutron-fwaas = neutron_fwaas.tests.tempest_plugin.plugin:NeutronFWaaSPlugin
|
neutron-fwaas = neutron_fwaas.tests.tempest_plugin.plugin:NeutronFWaaSPlugin
|
||||||
oslo.config.opts =
|
oslo.config.opts =
|
||||||
firewall.agent = neutron_fwaas.opts:list_agent_opts
|
firewall.agent = neutron_fwaas.opts:list_agent_opts
|
||||||
|
neutron.agent.l3.extensions =
|
||||||
|
fwaas = neutron_fwaas.services.firewall.agents.l3reference.firewall_l3_agent:L3WithFWaaS
|
||||||
|
fwaas_v2 = neutron_fwaas.services.firewall.agents.l3reference.firewall_l3_agent_v2:L3WithFWaaS
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
all_files = 1
|
all_files = 1
|
||||||
|
|
Loading…
Reference in New Issue