diff --git a/vmware_nsx/common/utils.py b/vmware_nsx/common/utils.py index 216ac263d8..0dea560aac 100644 --- a/vmware_nsx/common/utils.py +++ b/vmware_nsx/common/utils.py @@ -13,12 +13,15 @@ # License for the specific language governing permissions and limitations # under the License. +import functools import hashlib +import eventlet from neutron.api.v2 import attributes from neutron import version from neutron_lib import exceptions from oslo_config import cfg +from oslo_context import context as common_context from oslo_log import log import retrying import six @@ -257,3 +260,26 @@ def is_ipv4_ip_address(addr): if not _valid_part(ip_part): return False return True + + +def spawn_n(func, *args, **kwargs): + """Passthrough method for eventlet.spawn_n. + + This utility exists so that it can be stubbed for testing without + interfering with the service spawns. + + It will also grab the context from the threadlocal store and add it to + the store on the new thread. This allows for continuity in logging the + context when using this method to spawn a new thread. + """ + _context = common_context.get_current() + + @functools.wraps(func) + def context_wrapper(*args, **kwargs): + # NOTE: If update_store is not called after spawn_n it won't be + # available for the logger to pull from threadlocal storage. + if _context is not None: + _context.update_store() + func(*args, **kwargs) + + eventlet.spawn_n(context_wrapper, *args, **kwargs) diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index 9c25726ada..1f3de2d6f8 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -291,35 +291,39 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin, def _process_security_groups_rules_logging(self): - with locking.LockManager.get_lock('nsx-dfw-section', - lock_file_prefix='dfw-section', - external=True): - context = n_context.get_admin_context() - log_all_rules = cfg.CONF.nsxv.log_security_groups_allowed_traffic + def process_security_groups_rules_logging(*args, **kwargs): + with locking.LockManager.get_lock('nsx-dfw-section', + lock_file_prefix='dfw-section'): + context = n_context.get_admin_context() + log_allowed = cfg.CONF.nsxv.log_security_groups_allowed_traffic - # If the section/sg is already logged, then no action is - # required. - for sg in [sg for sg in self.get_security_groups(context) - if sg[sg_logging.LOGGING] is False]: - section_uri = self._get_section_uri(context.session, sg['id']) - if section_uri is None: - continue + # If the section/sg is already logged, then no action is + # required. + for sg in [sg for sg in self.get_security_groups(context) + if sg[sg_logging.LOGGING] is False]: + section_uri = self._get_section_uri(context.session, + sg['id']) + if section_uri is None: + continue - # Section/sg is not logged, update rules logging according to - # the 'log_security_groups_allowed_traffic' config option. - try: - h, c = self.nsx_v.vcns.get_section(section_uri) - section = self.nsx_sg_utils.parse_section(c) - section_needs_update = ( - self.nsx_sg_utils.set_rules_logged_option( - section, log_all_rules)) - if section_needs_update: - self.nsx_v.vcns.update_section( - section_uri, - self.nsx_sg_utils.to_xml_string(section), h) - except Exception as exc: - LOG.error(_LE('Unable to update section for logging. %s'), - exc) + # Section/sg is not logged, update rules logging according + # to the 'log_security_groups_allowed_traffic' config + # option. + try: + h, c = self.nsx_v.vcns.get_section(section_uri) + section = self.nsx_sg_utils.parse_section(c) + section_needs_update = ( + self.nsx_sg_utils.set_rules_logged_option( + section, log_allowed)) + if section_needs_update: + self.nsx_v.vcns.update_section( + section_uri, + self.nsx_sg_utils.to_xml_string(section), h) + except Exception as exc: + LOG.error(_LE('Unable to update section for logging. ' + '%s'), exc) + + c_utils.spawn_n(process_security_groups_rules_logging) def _create_dhcp_static_binding(self, context, neutron_port_db): diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index 453c64433c..98cb465964 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -272,19 +272,25 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin, return self._get_port_security_profile() def _process_security_group_logging(self): - context = q_context.get_admin_context() - log_all_rules = cfg.CONF.nsx_v3.log_security_groups_allowed_traffic - secgroups = self.get_security_groups(context, - fields=['id', sg_logging.LOGGING]) - for sg in [sg for sg in secgroups if sg[sg_logging.LOGGING] is False]: - _, section_id = security.get_sg_mappings(context.session, sg['id']) - try: - security.set_firewall_rule_logging_for_section( - section_id, logging=log_all_rules) - except nsx_exc.ManagerError: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Failed to update firewall rule logging for " - "rule in section %s"), section_id) + def process_security_group_logging(*args, **kwargs): + context = q_context.get_admin_context() + log_all_rules = cfg.CONF.nsx_v3.log_security_groups_allowed_traffic + secgroups = self.get_security_groups(context, + fields=['id', + sg_logging.LOGGING]) + for sg in [sg for sg in secgroups + if sg[sg_logging.LOGGING] is False]: + _, section_id = security.get_sg_mappings(context.session, + sg['id']) + try: + security.set_firewall_rule_logging_for_section( + section_id, logging=log_all_rules) + except nsx_exc.ManagerError: + with excutils.save_and_reraise_exception(): + LOG.error(_LE("Failed to update firewall rule logging " + "for rule in section %s"), section_id) + + utils.spawn_n(process_security_group_logging) def _init_nsgroup_manager_and_default_section_rules(self): with locking.LockManager.get_lock('nsxv3_nsgroup_manager_init'):