Add lock around channel creation
When a neutron agent starts up, it processes different resources in separate eventlet threads. These can race creating the channel which results in redundant privsep-helper processes. This patch fixes that by adding a lock around channel creation. Change-Id: I5de22b72059133b05d64be47f4c1d3f566b46a6e Closes-Bug: #1864664
This commit is contained in:
parent
7b8c4d4597
commit
bbe24aa6e0
|
@ -19,6 +19,7 @@ import logging
|
|||
import multiprocessing
|
||||
import shlex
|
||||
import sys
|
||||
import threading
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_config import types
|
||||
|
@ -144,6 +145,7 @@ class PrivContext(object):
|
|||
# The client_mode should be set to False on Windows.
|
||||
self.client_mode = sys.platform != 'win32'
|
||||
self.channel = None
|
||||
self.start_lock = threading.Lock()
|
||||
|
||||
cfg.CONF.register_opts(OPTS, group=cfg_section)
|
||||
cfg.CONF.set_default('capabilities', group=cfg_section,
|
||||
|
@ -247,18 +249,19 @@ class PrivContext(object):
|
|||
return func(*args, **kwargs)
|
||||
|
||||
def start(self, method=Method.ROOTWRAP):
|
||||
if self.channel is not None:
|
||||
LOG.warning('privsep daemon already running')
|
||||
return
|
||||
with self.start_lock:
|
||||
if self.channel is not None:
|
||||
LOG.warning('privsep daemon already running')
|
||||
return
|
||||
|
||||
if method is Method.ROOTWRAP:
|
||||
channel = daemon.RootwrapClientChannel(context=self)
|
||||
elif method is Method.FORK:
|
||||
channel = daemon.ForkingClientChannel(context=self)
|
||||
else:
|
||||
raise ValueError('Unknown method: %s' % method)
|
||||
if method is Method.ROOTWRAP:
|
||||
channel = daemon.RootwrapClientChannel(context=self)
|
||||
elif method is Method.FORK:
|
||||
channel = daemon.ForkingClientChannel(context=self)
|
||||
else:
|
||||
raise ValueError('Unknown method: %s' % method)
|
||||
|
||||
self.channel = channel
|
||||
self.channel = channel
|
||||
|
||||
def stop(self):
|
||||
if self.channel is not None:
|
||||
|
|
|
@ -127,6 +127,16 @@ class PrivContextTest(testctx.TestContextTestCase):
|
|||
self.assertEqual(testctx.context.helper_command('/sock')[:3],
|
||||
['sudo', 'rootwrap', 'privsep-helper'])
|
||||
|
||||
def test_start_acquires_lock(self):
|
||||
context = priv_context.PrivContext('test', capabilities=[])
|
||||
context.channel = "something not None"
|
||||
context.start_lock = mock.Mock()
|
||||
context.start_lock.__enter__ = mock.Mock()
|
||||
context.start_lock.__exit__ = mock.Mock()
|
||||
self.assertFalse(context.start_lock.__enter__.called)
|
||||
context.start()
|
||||
self.assertTrue(context.start_lock.__enter__.called)
|
||||
|
||||
|
||||
@testtools.skipIf(platform.system() != 'Linux',
|
||||
'works only on Linux platform.')
|
||||
|
|
Loading…
Reference in New Issue