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
(cherry picked from commit 6db5b0b77d)
This commit is contained in:
Brian Haley 2013-05-07 11:06:29 -04:00 committed by Gary Kotton
parent 0f51668c5a
commit 83eae03e9d
3 changed files with 35 additions and 6 deletions

View File

@ -28,7 +28,7 @@ LOG = logging.getLogger(__name__)
class Pidfile(object):
def __init__(self, pidfile, procname, root_helper='sudo'):
def __init__(self, pidfile, procname, uuid=None, root_helper='sudo'):
try:
self.fd = os.open(pidfile, os.O_CREAT | os.O_RDWR)
except IOError, e:
@ -36,6 +36,7 @@ class Pidfile(object):
sys.exit(1)
self.pidfile = pidfile
self.procname = procname
self.uuid = uuid
self.root_helper = root_helper
if not not fcntl.flock(self.fd, fcntl.LOCK_EX):
raise IOError(_('Unable to lock pid file'))
@ -67,8 +68,10 @@ class Pidfile(object):
cmd = ['cat', '/proc/%s/cmdline' % pid]
try:
return self.procname in utils.execute(cmd, self.root_helper)
except RuntimeError, e:
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:
return False
@ -79,12 +82,13 @@ class Daemon(object):
Usage: subclass the Daemon class and override the run() method
"""
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.stdout = stdout
self.stderr = stderr
self.procname = procname
self.pidfile = Pidfile(pidfile, procname, root_helper)
self.pidfile = Pidfile(pidfile, procname, uuid, root_helper)
def _fork(self):
try:

View File

@ -131,7 +131,8 @@ class NetworkMetadataProxyHandler(object):
class ProxyDaemon(daemon.Daemon):
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.router_id = router_id
self.port = port

View File

@ -94,6 +94,30 @@ class TestPidfile(base.BaseTestCase):
execute.assert_called_once_with(
['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):
def setUp(self):