diff --git a/vmware_nsx/common/nsx_constants.py b/vmware_nsx/common/nsx_constants.py index 4e733b6c68..11d1d12bf9 100644 --- a/vmware_nsx/common/nsx_constants.py +++ b/vmware_nsx/common/nsx_constants.py @@ -18,3 +18,5 @@ VIF_TYPE_DVS = 'dvs' # NSXv3 CORE PLUGIN PATH VMWARE_NSX_V3_PLUGIN_NAME = 'vmware_nsxv3' + +INTERNAL_V3_TENANT_ID = 'v3_internal_project' diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index 320f7b56f9..c719544252 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -93,6 +93,7 @@ from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import l3_rpc_agent_api from vmware_nsx.common import locking from vmware_nsx.common import managers +from vmware_nsx.common import nsx_constants from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db from vmware_nsx.db import extended_security_group @@ -135,6 +136,8 @@ NSX_V3_EXCLUDED_PORT_NSGROUP_NAME = 'neutron_excluded_port_nsgroup' NSX_V3_NON_VIF_PROFILE = 'nsx-default-switch-security-non-vif-profile' NSX_V3_SERVER_SSL_PROFILE = 'nsx-default-server-ssl-profile' NSX_V3_CLIENT_SSL_PROFILE = 'nsx-default-client-ssl-profile' +# Default UUID for the global OS rule +NSX_V3_OS_DFW_UUID = '00000000-def0-0000-0fed-000000000000' def inject_headers(): @@ -217,11 +220,10 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, def __init__(self): self.fwaas_callbacks = None self._is_sub_plugin = tvd_utils.is_tvd_core_plugin() - self.init_is_complete = False - nsxlib_utils.set_is_attr_callback(validators.is_attr_set) self._extend_fault_map() if self._is_sub_plugin: extension_drivers = cfg.CONF.nsx_tvd.nsx_v3_extension_drivers + self._update_project_mapping() else: extension_drivers = cfg.CONF.nsx_extension_drivers self._extension_manager = managers.ExtensionManager( @@ -262,16 +264,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, self._translate_configured_names_to_uuids() self._init_dhcp_metadata() - # Include default section NSGroup - LOG.debug("Initializing NSX v3 default section NSGroup") - self._default_section_nsgroup = None - self._default_section_nsgroup = self._init_default_section_nsgroup() - if not self._default_section_nsgroup: - msg = _("Unable to initialize NSX v3 default section NSGroup %s" - ) % NSX_V3_FW_DEFAULT_NS_GROUP - raise nsx_exc.NsxPluginException(err_msg=msg) - - self.default_section = self._init_default_section_rules() + self._prepare_default_rules() self._process_security_group_logging() # init profiles on nsx backend @@ -314,6 +307,69 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, resources.PROCESS, events.AFTER_INIT) + def _update_project_mapping(self): + ctx = q_context.get_admin_context() + try: + nsx_db.add_project_plugin_mapping( + ctx.session, + nsx_constants.INTERNAL_V3_TENANT_ID, + projectpluginmap.NsxPlugins.NSX_T) + except db_exc.DBDuplicateEntry: + pass + + def _ensure_default_rules(self): + # Include default section NSGroup + LOG.debug("Initializing NSX v3 default section NSGroup") + self._default_section_nsgroup = None + self._default_section_nsgroup = self._init_default_section_nsgroup() + if not self._default_section_nsgroup: + msg = _("Unable to initialize NSX v3 default section NSGroup %s" + ) % NSX_V3_FW_DEFAULT_NS_GROUP + raise nsx_exc.NsxPluginException(err_msg=msg) + self.default_section = self._init_default_section_rules() + + def _ensure_global_sg_placeholder(self, context): + try: + super(NsxV3Plugin, self).get_security_group( + context, NSX_V3_OS_DFW_UUID, fields=['id']) + except ext_sg.SecurityGroupNotFound: + sec_group = {'security_group': + {'id': NSX_V3_OS_DFW_UUID, + 'tenant_id': nsx_constants.INTERNAL_V3_TENANT_ID, + 'name': 'NSX Internal', + 'description': None}} + try: + # ensure that the global default is created + super(NsxV3Plugin, self).create_security_group( + context, sec_group, True) + except Exception: + # Treat a race of multiple processing creating the seg group + LOG.warning('Unable to create global security group') + + def _prepare_default_rules(self): + ctx = q_context.get_admin_context() + # Need a global placeholder as the DB below has a foreign key to + # this security group + self._ensure_global_sg_placeholder(ctx) + self._ensure_default_rules() + # Validate if there is a race between processes + nsgroup_id, section_id = nsx_db.get_sg_mappings( + ctx.session, NSX_V3_OS_DFW_UUID) + if nsgroup_id is None or section_id is None: + default_ns_group_id = self._default_section_nsgroup.get('id') + try: + nsx_db.save_sg_mappings(ctx, + NSX_V3_OS_DFW_UUID, + default_ns_group_id, + self.default_section) + except Exception: + LOG.warning("Duplicate rules created. Cleaning up!") + # Delete duplicates created + self.nsxlib.firewall_section.delete(self.default_section) + self.nsxlib.ns_group.delete(default_ns_group_id) + # Ensure global variables are updated + self._ensure_default_rules() + @staticmethod def plugin_type(): return projectpluginmap.NsxPlugins.NSX_T diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index 0b1b700439..e534229e7b 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -189,6 +189,12 @@ class NsxV3PluginTestCaseMixin(test_plugin.NeutronDbPluginV2TestCase, mock_process_security_group_logging = mock.patch.object( nsx_plugin.NsxV3Plugin, '_process_security_group_logging') mock_process_security_group_logging.start() + # need to mock the global placeholder. This is due to the fact that + # the generic security group tests assume that there is just one + # security group. + mock_ensure_global_sg_placeholder = mock.patch.object( + nsx_plugin.NsxV3Plugin, '_ensure_global_sg_placeholder') + mock_ensure_global_sg_placeholder.start() def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None,