NSX-TV fwaas drivers

Drivers for FWaaS V1/V2 for the NSX-TV plugin
Those drivers are just wrappers calling the right driver according to
the project of the firewall object.

Change-Id: Ia073da9c91cb4d69d772b3e0d0ab6f5c3fd60795
This commit is contained in:
Adit Sarfaty 2017-12-13 14:09:25 +02:00
parent 792a6a0103
commit 189d8d6955
13 changed files with 273 additions and 15 deletions

View File

@ -39,6 +39,8 @@ firewall_drivers =
vmware_nsxv3_edge = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v1:EdgeFwaasV3DriverV1
vmware_nsxv3_edge_v1 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v1:EdgeFwaasV3DriverV1
vmware_nsxv3_edge_v2 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v2:EdgeFwaasV3DriverV2
vmware_nsxtv_edge_v1 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v1:EdgeFwaasTVDriverV1
vmware_nsxtv_edge_v2 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v2:EdgeFwaasTVDriverV2
neutron.service_plugins =
vmware_nsxv_qos = vmware_nsx.services.qos.nsx_v.plugin:NsxVQosPlugin
neutron.qos.notification_drivers =

View File

@ -39,10 +39,22 @@ class NsxFwaasCallbacks(firewall_l3_agent.L3WithFWaaS):
neutron_conf = cfg.CONF
neutron_conf.agent_mode = 'nsx'
super(NsxFwaasCallbacks, self).__init__(conf=neutron_conf)
self._core_plugin = None
@property
def plugin_type(self):
pass
@property
def core_plugin(self):
return directory.get_plugin()
"""Get the NSX-V3 core plugin"""
if not self._core_plugin:
self._core_plugin = directory.get_plugin()
if self._core_plugin.is_tvd_plugin():
# get the plugin that match this driver
self._core_plugin = self._core_plugin.get_plugin_by_type(
self.plugin_type)
return self._core_plugin
# Override functions using the agent_api that is not used by our plugin
def _get_router_ids_for_fw(self, context, fw, to_delete=False):

View File

@ -42,10 +42,22 @@ class NsxFwaasCallbacksV2(firewall_l3_agent_v2.L3WithFWaaS):
neutron_conf.agent_mode = 'nsx'
super(NsxFwaasCallbacksV2, self).__init__(conf=neutron_conf)
self.agent_api = DummyAgentApi()
self._core_plugin = None
@property
def plugin_type(self):
pass
@property
def core_plugin(self):
return directory.get_plugin()
"""Get the NSX-V3 core plugin"""
if not self._core_plugin:
self._core_plugin = directory.get_plugin()
if self._core_plugin.is_tvd_plugin():
# get the plugin that match this driver
self._core_plugin = self._core_plugin.get_plugin_by_type(
self.plugin_type)
return self._core_plugin
# Override functions using the agent_api that is not used by our plugin
def _get_firewall_group_ports(self, context, firewall_group,

View File

@ -0,0 +1,92 @@
# Copyright 2017 VMware, Inc.
# All Rights Reserved
#
# 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.
from oslo_log import helpers as log_helpers
from oslo_log import log as logging
from neutron_fwaas.services.firewall.drivers import fwaas_base
from neutron_lib import context as n_context
from neutron_lib.exceptions import firewall_v1 as exceptions
from vmware_nsx.db import db as nsx_db
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver as v_driver
from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_v1 as t_driver
LOG = logging.getLogger(__name__)
FWAAS_DRIVER_NAME = 'FwaaS V1 NSX-TV driver'
class EdgeFwaasTVDriverV1(fwaas_base.FwaasDriverBase):
"""NSX-TV driver for Firewall As A Service - V1.
This driver is just a wrapper calling the relevant nsx-v/t driver
"""
def __init__(self):
super(EdgeFwaasTVDriverV1, self).__init__()
self.driver_name = FWAAS_DRIVER_NAME
# supported drivers:
self.drivers = {}
self.drivers[projectpluginmap.NsxPlugins.NSX_T] = (
t_driver.EdgeFwaasV3DriverV1())
self.drivers[projectpluginmap.NsxPlugins.NSX_V] = (
v_driver.EdgeFwaasDriver())
def get_T_driver(self):
return self.drivers[projectpluginmap.NsxPlugins.NSX_T]
def get_V_driver(self):
return self.drivers[projectpluginmap.NsxPlugins.NSX_V]
def _get_driver_for_project(self, project):
context = n_context.get_admin_context()
mapping = nsx_db.get_project_plugin_mapping(
context.session, project)
if mapping:
plugin_type = mapping['plugin']
else:
LOG.error("Didn't find the plugin project %s is using", project)
raise exceptions.FirewallInternalDriverError(
driver=self.driver_name)
if plugin_type not in self.drivers:
LOG.error("Project %(project)s with plugin %(plugin)s has no "
"support for FWaaS V1", {'project': project,
'plugin': plugin_type})
raise exceptions.FirewallInternalDriverError(
driver=self.driver_name)
return self.drivers[plugin_type]
@log_helpers.log_method_call
def create_firewall(self, agent_mode, apply_list, firewall):
d = self._get_driver_for_project(firewall['tenant_id'])
return d.create_firewall(agent_mode, apply_list, firewall)
@log_helpers.log_method_call
def update_firewall(self, agent_mode, apply_list, firewall):
d = self._get_driver_for_project(firewall['tenant_id'])
return d.update_firewall(agent_mode, apply_list, firewall)
@log_helpers.log_method_call
def delete_firewall(self, agent_mode, apply_list, firewall):
d = self._get_driver_for_project(firewall['tenant_id'])
return d.delete_firewall(agent_mode, apply_list, firewall)
@log_helpers.log_method_call
def apply_default_policy(self, agent_mode, apply_list, firewall):
d = self._get_driver_for_project(firewall['tenant_id'])
return d.apply_default_policy(agent_mode, apply_list, firewall)

View File

@ -0,0 +1,86 @@
# Copyright 2017 VMware, Inc.
# All Rights Reserved
#
# 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.
from oslo_log import helpers as log_helpers
from oslo_log import log as logging
from neutron_fwaas.services.firewall.drivers import fwaas_base_v2
from neutron_lib import context as n_context
from neutron_lib.exceptions import firewall_v2 as exceptions
from vmware_nsx.db import db as nsx_db
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_v2 as t_driver
LOG = logging.getLogger(__name__)
FWAAS_DRIVER_NAME = 'FwaaS V2 NSX-TV driver'
class EdgeFwaasTVDriverV2(fwaas_base_v2.FwaasDriverBase):
"""NSX-TV driver for Firewall As A Service - V2.
This driver is just a wrapper calling the relevant nsx-v3 driver
"""
def __init__(self):
super(EdgeFwaasTVDriverV2, self).__init__()
self.driver_name = FWAAS_DRIVER_NAME
# supported drivers (Only NSX-T):
self.drivers = {}
self.drivers[projectpluginmap.NsxPlugins.NSX_T] = (
t_driver.EdgeFwaasV3DriverV2())
def get_T_driver(self):
return self.drivers[projectpluginmap.NsxPlugins.NSX_T]
def _get_driver_for_project(self, project):
context = n_context.get_admin_context()
mapping = nsx_db.get_project_plugin_mapping(
context.session, project)
if mapping:
plugin_type = mapping['plugin']
else:
LOG.error("Didn't find the plugin project %s is using", project)
raise exceptions.FirewallInternalDriverError(
driver=self.driver_name)
if plugin_type not in self.drivers:
LOG.error("Project %(project)s with plugin %(plugin)s has no "
"support for FWaaS V2", {'project': project,
'plugin': plugin_type})
raise exceptions.FirewallInternalDriverError(
driver=self.driver_name)
return self.drivers[plugin_type]
@log_helpers.log_method_call
def create_firewall_group(self, agent_mode, apply_list, firewall_group):
d = self._get_driver_for_project(firewall_group['tenant_id'])
return d.create_firewall_group(agent_mode, apply_list, firewall_group)
@log_helpers.log_method_call
def update_firewall_group(self, agent_mode, apply_list, firewall_group):
d = self._get_driver_for_project(firewall_group['tenant_id'])
return d.update_firewall_group(agent_mode, apply_list, firewall_group)
@log_helpers.log_method_call
def delete_firewall_group(self, agent_mode, apply_list, firewall_group):
d = self._get_driver_for_project(firewall_group['tenant_id'])
return d.delete_firewall_group(agent_mode, apply_list, firewall_group)
@log_helpers.log_method_call
def apply_default_policy(self, agent_mode, apply_list, firewall_group):
d = self._get_driver_for_project(firewall_group['tenant_id'])
return d.apply_default_policy(agent_mode, apply_list, firewall_group)

View File

@ -22,10 +22,11 @@ from oslo_log import log as logging
from neutron_fwaas.services.firewall.drivers import fwaas_base
from vmware_nsx.common import locking
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
LOG = logging.getLogger(__name__)
FWAAS_DRIVER_NAME = 'Fwaas NSX-V driver'
FWAAS_DRIVER_NAME = 'Fwaas V1 NSX-V driver'
RULE_NAME_PREFIX = 'Fwaas-'
@ -36,6 +37,10 @@ class EdgeFwaasDriver(fwaas_base.FwaasDriverBase):
def core_plugin(self):
if not self._core_plugin:
self._core_plugin = directory.get_plugin()
if self._core_plugin.is_tvd_plugin():
self._core_plugin = self._core_plugin.get_plugin_by_type(
projectpluginmap.NsxPlugins.NSX_V)
# make sure plugin init was completed
if not self._core_plugin.init_is_complete:
self._core_plugin.init_complete(None, None, {})
return self._core_plugin
@ -45,7 +50,7 @@ class EdgeFwaasDriver(fwaas_base.FwaasDriverBase):
return self.core_plugin.edge_manager
def __init__(self):
LOG.debug("Loading FWaaS NsxVDriver.")
LOG.debug("Loading FWaaS V1 NsxVDriver.")
super(EdgeFwaasDriver, self).__init__()
self.driver_name = FWAAS_DRIVER_NAME
self._core_plugin = None

View File

@ -15,7 +15,9 @@
from oslo_log import log as logging
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.services.fwaas.common import fwaas_callbacks_v1 as com_clbcks
from vmware_nsx.services.fwaas.nsx_tv import edge_fwaas_driver_v1 as tv_driver
LOG = logging.getLogger(__name__)
@ -23,6 +25,19 @@ LOG = logging.getLogger(__name__)
class NsxvFwaasCallbacks(com_clbcks.NsxFwaasCallbacks):
"""NSX-V RPC callbacks for Firewall As A Service - V1."""
def __init__(self):
super(NsxvFwaasCallbacks, self).__init__()
# update the fwaas driver in case of TV plugin
if self.fwaas_enabled:
if self.fwaas_driver.driver_name == tv_driver.FWAAS_DRIVER_NAME:
self.internal_driver = self.fwaas_driver.get_V_driver()
else:
self.internal_driver = self.fwaas_driver
@property
def plugin_type(self):
return projectpluginmap.NsxPlugins.NSX_V
def should_apply_firewall_to_router(self, context, router, router_id):
"""Return True if the FWaaS rules should be added to this router."""
# in case of a distributed-router:
@ -46,7 +61,7 @@ class NsxvFwaasCallbacks(com_clbcks.NsxFwaasCallbacks):
return False
# Check if the FWaaS driver supports this router
if not self.fwaas_driver.should_apply_firewall_to_router(
if not self.internal_driver.should_apply_firewall_to_router(
router_data, raise_exception=False):
return False
@ -63,5 +78,5 @@ class NsxvFwaasCallbacks(com_clbcks.NsxFwaasCallbacks):
def _get_fw_applicable_rules(self, context, fw_id):
fw = self._get_fw_from_plugin(context, fw_id)
if fw is not None and fw['id'] == fw_id:
return self.fwaas_driver.get_firewall_translated_rules(fw)
return self.internal_driver.get_firewall_translated_rules(fw)
return []

View File

@ -23,6 +23,7 @@ from neutron_lib.callbacks import resources
from neutron_lib.plugins import directory
from oslo_log import log as logging
from vmware_nsx.extensions import projectpluginmap
from vmware_nsxlib.v3 import nsx_constants as consts
LOG = logging.getLogger(__name__)
@ -45,8 +46,12 @@ class CommonEdgeFwaasV3Driver(fwaas_base.FwaasDriverBase):
@property
def core_plugin(self):
"""Get the NSX-V3 core plugin"""
if not self._core_plugin:
self._core_plugin = directory.get_plugin()
if self._core_plugin.is_tvd_plugin():
self._core_plugin = self._core_plugin.get_plugin_by_type(
projectpluginmap.NsxPlugins.NSX_T)
# make sure plugin init was completed
if not self._core_plugin.init_is_complete:
self._core_plugin.init_complete(None, None, {})

View File

@ -15,7 +15,9 @@
from oslo_log import log as logging
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.services.fwaas.common import fwaas_callbacks_v1 as com_clbcks
from vmware_nsx.services.fwaas.nsx_tv import edge_fwaas_driver_v1 as tv_driver
LOG = logging.getLogger(__name__)
@ -25,6 +27,16 @@ class Nsxv3FwaasCallbacksV1(com_clbcks.NsxFwaasCallbacks):
def __init__(self):
super(Nsxv3FwaasCallbacksV1, self).__init__()
# update the fwaas driver in case of TV plugin
if self.fwaas_enabled:
if self.fwaas_driver.driver_name == tv_driver.FWAAS_DRIVER_NAME:
self.internal_driver = self.fwaas_driver.get_T_driver()
else:
self.internal_driver = self.fwaas_driver
@property
def plugin_type(self):
return projectpluginmap.NsxPlugins.NSX_T
def should_apply_firewall_to_router(self, context, router_id):
"""Return True if the FWaaS rules should be added to this router."""
@ -41,7 +53,8 @@ class Nsxv3FwaasCallbacksV1(com_clbcks.NsxFwaasCallbacks):
return False
# Check if the FWaaS driver supports this router
if not self.fwaas_driver.should_apply_firewall_to_router(router_data):
if not self.internal_driver.should_apply_firewall_to_router(
router_data):
return False
return True
@ -62,7 +75,7 @@ class Nsxv3FwaasCallbacksV1(com_clbcks.NsxFwaasCallbacks):
fw_id = firewall['id']
# Add the FW rules
fw_rules.extend(self.fwaas_driver.get_router_translated_rules(
fw_rules.extend(self.internal_driver.get_router_translated_rules(
router_id, firewall))
# Add plugin additional allow rules
@ -70,15 +83,15 @@ class Nsxv3FwaasCallbacksV1(com_clbcks.NsxFwaasCallbacks):
context, router_id))
# Add the default drop all rule
fw_rules.append(self.fwaas_driver.get_default_backend_rule(
fw_rules.append(self.internal_driver.get_default_backend_rule(
section_id, allow_all=False))
else:
# default allow all rule
fw_rules.append(self.fwaas_driver.get_default_backend_rule(
fw_rules.append(self.internal_driver.get_default_backend_rule(
section_id, allow_all=True))
# update the backend
nsxlib.firewall_section.update(section_id, rules=fw_rules)
# Also update the router tags
self.fwaas_driver.update_nsx_router_tags(nsx_router_id, fw_id=fw_id)
self.internal_driver.update_nsx_router_tags(nsx_router_id, fw_id=fw_id)

View File

@ -16,8 +16,10 @@
from oslo_log import log as logging
from vmware_nsx.db import db as nsx_db
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.services.fwaas.common import fwaas_callbacks_v2 as \
com_callbacks
from vmware_nsx.services.fwaas.nsx_tv import edge_fwaas_driver_v2 as tv_driver
LOG = logging.getLogger(__name__)
@ -27,6 +29,17 @@ class Nsxv3FwaasCallbacksV2(com_callbacks.NsxFwaasCallbacksV2):
def __init__(self):
super(Nsxv3FwaasCallbacksV2, self).__init__()
# update the fwaas driver in case of TV plugin
self.internal_driver = None
if self.fwaas_enabled:
if self.fwaas_driver.driver_name == tv_driver.FWAAS_DRIVER_NAME:
self.internal_driver = self.fwaas_driver.get_T_driver()
else:
self.internal_driver = self.fwaas_driver
@property
def plugin_type(self):
return projectpluginmap.NsxPlugins.NSX_T
def should_apply_firewall_to_router(self, context, router_id):
"""Return True if the FWaaS rules should be added to this router."""
@ -43,14 +56,15 @@ class Nsxv3FwaasCallbacksV2(com_callbacks.NsxFwaasCallbacksV2):
return False
# Check if the FWaaS driver supports this router
if not self.fwaas_driver.should_apply_firewall_to_router(router_data):
if not self.internal_driver.should_apply_firewall_to_router(
router_data):
return False
return True
def get_port_rules(self, nsx_port_id, fwg, plugin_rules):
return self.fwaas_driver.get_port_translated_rules(nsx_port_id, fwg,
plugin_rules)
return self.internal_driver.get_port_translated_rules(
nsx_port_id, fwg, plugin_rules)
def update_router_firewall(self, context, nsxlib, router_id,
router_interfaces, nsx_router_id, section_id):
@ -79,7 +93,7 @@ class Nsxv3FwaasCallbacksV2(com_callbacks.NsxFwaasCallbacksV2):
plugin_rules))
# add a default allow-all rule to all other traffic & ports
fw_rules.append(self.fwaas_driver.get_default_backend_rule(
fw_rules.append(self.internal_driver.get_default_backend_rule(
section_id, allow_all=True))
# update the backend router firewall

View File

@ -65,6 +65,7 @@ class Nsxv3FwaasTestCase(test_v3_plugin.NsxV3PluginTestCaseMixin):
Nsxv3FwaasCallbacksV1()
self.plugin.fwaas_callbacks.fwaas_enabled = True
self.plugin.fwaas_callbacks.fwaas_driver = self.firewall
self.plugin.fwaas_callbacks.internal_driver = self.firewall
self.plugin.init_is_complete = True
def _default_rule(self, drop=True):

View File

@ -65,6 +65,7 @@ class Nsxv3FwaasTestCase(test_v3_plugin.NsxV3PluginTestCaseMixin):
Nsxv3FwaasCallbacksV2()
self.plugin.fwaas_callbacks.fwaas_enabled = True
self.plugin.fwaas_callbacks.fwaas_driver = self.firewall
self.plugin.fwaas_callbacks.internal_driver = self.firewall
self.plugin.init_is_complete = True
def _default_rule(self):