NSX: do not block init with security group logging configuration

Ensure that service is not blocked when updating the security group
logging configuration

Change-Id: I76eeeb351a9a7dfb8ded5aa47ae4f29d91fa3939
This commit is contained in:
Gary Kotton 2016-04-03 01:25:35 -07:00
parent 026a656893
commit 9089b5bc8d
3 changed files with 76 additions and 40 deletions

View File

@ -13,12 +13,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 functools
import hashlib import hashlib
import eventlet
from neutron.api.v2 import attributes from neutron.api.v2 import attributes
from neutron import version from neutron import version
from neutron_lib import exceptions from neutron_lib import exceptions
from oslo_config import cfg from oslo_config import cfg
from oslo_context import context as common_context
from oslo_log import log from oslo_log import log
import retrying import retrying
import six import six
@ -257,3 +260,26 @@ def is_ipv4_ip_address(addr):
if not _valid_part(ip_part): if not _valid_part(ip_part):
return False return False
return True 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)

View File

@ -291,35 +291,39 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
def _process_security_groups_rules_logging(self): def _process_security_groups_rules_logging(self):
with locking.LockManager.get_lock('nsx-dfw-section', def process_security_groups_rules_logging(*args, **kwargs):
lock_file_prefix='dfw-section', with locking.LockManager.get_lock('nsx-dfw-section',
external=True): lock_file_prefix='dfw-section'):
context = n_context.get_admin_context() context = n_context.get_admin_context()
log_all_rules = cfg.CONF.nsxv.log_security_groups_allowed_traffic log_allowed = cfg.CONF.nsxv.log_security_groups_allowed_traffic
# If the section/sg is already logged, then no action is # If the section/sg is already logged, then no action is
# required. # required.
for sg in [sg for sg in self.get_security_groups(context) for sg in [sg for sg in self.get_security_groups(context)
if sg[sg_logging.LOGGING] is False]: if sg[sg_logging.LOGGING] is False]:
section_uri = self._get_section_uri(context.session, sg['id']) section_uri = self._get_section_uri(context.session,
if section_uri is None: sg['id'])
continue if section_uri is None:
continue
# Section/sg is not logged, update rules logging according to # Section/sg is not logged, update rules logging according
# the 'log_security_groups_allowed_traffic' config option. # to the 'log_security_groups_allowed_traffic' config
try: # option.
h, c = self.nsx_v.vcns.get_section(section_uri) try:
section = self.nsx_sg_utils.parse_section(c) h, c = self.nsx_v.vcns.get_section(section_uri)
section_needs_update = ( section = self.nsx_sg_utils.parse_section(c)
self.nsx_sg_utils.set_rules_logged_option( section_needs_update = (
section, log_all_rules)) self.nsx_sg_utils.set_rules_logged_option(
if section_needs_update: section, log_allowed))
self.nsx_v.vcns.update_section( if section_needs_update:
section_uri, self.nsx_v.vcns.update_section(
self.nsx_sg_utils.to_xml_string(section), h) section_uri,
except Exception as exc: self.nsx_sg_utils.to_xml_string(section), h)
LOG.error(_LE('Unable to update section for logging. %s'), except Exception as exc:
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): def _create_dhcp_static_binding(self, context, neutron_port_db):

View File

@ -272,19 +272,25 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
return self._get_port_security_profile() return self._get_port_security_profile()
def _process_security_group_logging(self): def _process_security_group_logging(self):
context = q_context.get_admin_context() def process_security_group_logging(*args, **kwargs):
log_all_rules = cfg.CONF.nsx_v3.log_security_groups_allowed_traffic context = q_context.get_admin_context()
secgroups = self.get_security_groups(context, log_all_rules = cfg.CONF.nsx_v3.log_security_groups_allowed_traffic
fields=['id', sg_logging.LOGGING]) secgroups = self.get_security_groups(context,
for sg in [sg for sg in secgroups if sg[sg_logging.LOGGING] is False]: fields=['id',
_, section_id = security.get_sg_mappings(context.session, sg['id']) sg_logging.LOGGING])
try: for sg in [sg for sg in secgroups
security.set_firewall_rule_logging_for_section( if sg[sg_logging.LOGGING] is False]:
section_id, logging=log_all_rules) _, section_id = security.get_sg_mappings(context.session,
except nsx_exc.ManagerError: sg['id'])
with excutils.save_and_reraise_exception(): try:
LOG.error(_LE("Failed to update firewall rule logging for " security.set_firewall_rule_logging_for_section(
"rule in section %s"), section_id) 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): def _init_nsgroup_manager_and_default_section_rules(self):
with locking.LockManager.get_lock('nsxv3_nsgroup_manager_init'): with locking.LockManager.get_lock('nsxv3_nsgroup_manager_init'):