Change Daemon class to better match process command lines.
Add additional uuid argument Daemon class to help it better match output from /proc/$id/cmdline to the correct daemon. If there is a stale pid in the pidfile, and that process has the same name, then it could match accidentally and not start the daemon up properly. Fixes bug 1177416 Change-Id: I1109ca73c539c5e96cbe3dbb55ce68c92013ee10
This commit is contained in:
parent
17336b9cb6
commit
6db5b0b77d
@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class Pidfile(object):
|
class Pidfile(object):
|
||||||
def __init__(self, pidfile, procname, root_helper='sudo'):
|
def __init__(self, pidfile, procname, uuid=None, root_helper='sudo'):
|
||||||
try:
|
try:
|
||||||
self.fd = os.open(pidfile, os.O_CREAT | os.O_RDWR)
|
self.fd = os.open(pidfile, os.O_CREAT | os.O_RDWR)
|
||||||
except IOError:
|
except IOError:
|
||||||
@ -36,6 +36,7 @@ class Pidfile(object):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.pidfile = pidfile
|
self.pidfile = pidfile
|
||||||
self.procname = procname
|
self.procname = procname
|
||||||
|
self.uuid = uuid
|
||||||
self.root_helper = root_helper
|
self.root_helper = root_helper
|
||||||
if not not fcntl.flock(self.fd, fcntl.LOCK_EX):
|
if not not fcntl.flock(self.fd, fcntl.LOCK_EX):
|
||||||
raise IOError(_('Unable to lock pid file'))
|
raise IOError(_('Unable to lock pid file'))
|
||||||
@ -67,7 +68,9 @@ class Pidfile(object):
|
|||||||
|
|
||||||
cmd = ['cat', '/proc/%s/cmdline' % pid]
|
cmd = ['cat', '/proc/%s/cmdline' % pid]
|
||||||
try:
|
try:
|
||||||
return self.procname in utils.execute(cmd, self.root_helper)
|
exec_out = utils.execute(cmd, self.root_helper)
|
||||||
|
return self.procname in exec_out and (not self.uuid or
|
||||||
|
self.uuid in exec_out)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -78,12 +81,13 @@ class Daemon(object):
|
|||||||
Usage: subclass the Daemon class and override the run() method
|
Usage: subclass the Daemon class and override the run() method
|
||||||
"""
|
"""
|
||||||
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null',
|
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null',
|
||||||
stderr='/dev/null', procname='python', root_helper='sudo'):
|
stderr='/dev/null', procname='python', uuid=None,
|
||||||
|
root_helper='sudo'):
|
||||||
self.stdin = stdin
|
self.stdin = stdin
|
||||||
self.stdout = stdout
|
self.stdout = stdout
|
||||||
self.stderr = stderr
|
self.stderr = stderr
|
||||||
self.procname = procname
|
self.procname = procname
|
||||||
self.pidfile = Pidfile(pidfile, procname, root_helper)
|
self.pidfile = Pidfile(pidfile, procname, uuid, root_helper)
|
||||||
|
|
||||||
def _fork(self):
|
def _fork(self):
|
||||||
try:
|
try:
|
||||||
|
@ -131,7 +131,8 @@ class NetworkMetadataProxyHandler(object):
|
|||||||
|
|
||||||
class ProxyDaemon(daemon.Daemon):
|
class ProxyDaemon(daemon.Daemon):
|
||||||
def __init__(self, pidfile, port, network_id=None, router_id=None):
|
def __init__(self, pidfile, port, network_id=None, router_id=None):
|
||||||
super(ProxyDaemon, self).__init__(pidfile)
|
uuid = network_id or router_id
|
||||||
|
super(ProxyDaemon, self).__init__(pidfile, uuid=uuid)
|
||||||
self.network_id = network_id
|
self.network_id = network_id
|
||||||
self.router_id = router_id
|
self.router_id = router_id
|
||||||
self.port = port
|
self.port = port
|
||||||
|
@ -95,6 +95,30 @@ class TestPidfile(base.BaseTestCase):
|
|||||||
execute.assert_called_once_with(
|
execute.assert_called_once_with(
|
||||||
['cat', '/proc/34/cmdline'], 'sudo')
|
['cat', '/proc/34/cmdline'], 'sudo')
|
||||||
|
|
||||||
|
def test_is_running_uuid_true(self):
|
||||||
|
with mock.patch('quantum.agent.linux.utils.execute') as execute:
|
||||||
|
execute.return_value = 'python 1234'
|
||||||
|
p = daemon.Pidfile('thefile', 'python', uuid='1234')
|
||||||
|
|
||||||
|
with mock.patch.object(p, 'read') as read:
|
||||||
|
read.return_value = 34
|
||||||
|
self.assertTrue(p.is_running())
|
||||||
|
|
||||||
|
execute.assert_called_once_with(
|
||||||
|
['cat', '/proc/34/cmdline'], 'sudo')
|
||||||
|
|
||||||
|
def test_is_running_uuid_false(self):
|
||||||
|
with mock.patch('quantum.agent.linux.utils.execute') as execute:
|
||||||
|
execute.return_value = 'python 1234'
|
||||||
|
p = daemon.Pidfile('thefile', 'python', uuid='6789')
|
||||||
|
|
||||||
|
with mock.patch.object(p, 'read') as read:
|
||||||
|
read.return_value = 34
|
||||||
|
self.assertFalse(p.is_running())
|
||||||
|
|
||||||
|
execute.assert_called_once_with(
|
||||||
|
['cat', '/proc/34/cmdline'], 'sudo')
|
||||||
|
|
||||||
|
|
||||||
class TestDaemon(base.BaseTestCase):
|
class TestDaemon(base.BaseTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user