Revision d9f311d7
b/lib/utils.py | ||
---|---|---|
268 | 268 |
|
269 | 269 |
Returns: true or false, depending on if the pid exists or not |
270 | 270 |
|
271 |
Remarks: zombie processes treated as not alive |
|
271 |
Remarks: zombie processes treated as not alive, and giving a pid <= |
|
272 |
0 makes the function to return False. |
|
272 | 273 |
|
273 | 274 |
""" |
275 |
if pid <= 0: |
|
276 |
return False |
|
277 |
|
|
274 | 278 |
try: |
275 | 279 |
f = open("/proc/%d/status" % pid) |
276 | 280 |
except IOError, err: |
... | ... | |
290 | 294 |
return alive |
291 | 295 |
|
292 | 296 |
|
293 |
def IsPidFileAlive(pidfile):
|
|
294 |
"""Check whether the given pidfile points to a live process.
|
|
297 |
def ReadPidFile(pidfile):
|
|
298 |
"""Read the pid from a file.
|
|
295 | 299 |
|
296 |
@param pidfile: Path to a file containing the pid to be checked |
|
297 |
@type pidfile: string (filename) |
|
300 |
@param pidfile: Path to a file containing the pid to be checked |
|
301 |
@type pidfile: string (filename) |
|
302 |
@return: The process id, if the file exista and contains a valid PID, |
|
303 |
otherwise 0 |
|
304 |
@rtype: int |
|
298 | 305 |
|
299 | 306 |
""" |
300 | 307 |
try: |
301 | 308 |
pf = open(pidfile, 'r') |
302 |
except EnvironmentError, open_err: |
|
303 |
if open_err.errno == errno.ENOENT: |
|
304 |
return False |
|
305 |
else: |
|
306 |
raise errors.GenericError("Cannot open file %s. Error: %s" % |
|
307 |
(pidfile, str(open_err))) |
|
309 |
except EnvironmentError, err: |
|
310 |
if err.errno != errno.ENOENT: |
|
311 |
logging.exception("Can't read pid file?!") |
|
312 |
return 0 |
|
308 | 313 |
|
309 | 314 |
try: |
310 | 315 |
pid = int(pf.read()) |
311 |
except ValueError: |
|
312 |
raise errors.GenericError("Invalid pid string in %s" %
|
|
313 |
(pidfile,))
|
|
316 |
except ValueError, err:
|
|
317 |
logging.info("Can't parse pid file contents", exc_info=err)
|
|
318 |
return 0
|
|
314 | 319 |
|
315 |
return IsProcessAlive(pid)
|
|
320 |
return pid
|
|
316 | 321 |
|
317 | 322 |
|
318 | 323 |
def MatchNameComponent(key, name_list): |
... | ... | |
1066 | 1071 |
""" |
1067 | 1072 |
pid = os.getpid() |
1068 | 1073 |
pidfilename = _DaemonPidFileName(name) |
1069 |
if IsPidFileAlive(pidfilename):
|
|
1074 |
if IsProcessAlive(ReadPidFile(pidfilename)):
|
|
1070 | 1075 |
raise errors.GenericError("%s contains a live process" % pidfilename) |
1071 | 1076 |
|
1072 | 1077 |
WriteFile(pidfilename, data="%d\n" % pid) |
b/test/ganeti.utils_unittest.py | ||
---|---|---|
43 | 43 |
ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \ |
44 | 44 |
ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \ |
45 | 45 |
SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree |
46 |
from ganeti.errors import LockError, UnitParseError |
|
46 |
from ganeti.errors import LockError, UnitParseError, GenericError
|
|
47 | 47 |
|
48 | 48 |
def _ChildHandler(signal, stack): |
49 | 49 |
global _ChildFlag |
50 | 50 |
_ChildFlag = True |
51 | 51 |
|
52 |
|
|
52 | 53 |
class TestIsProcessAlive(unittest.TestCase): |
53 | 54 |
"""Testing case for IsProcessAlive""" |
54 | 55 |
|
... | ... | |
99 | 100 |
self.assert_(not IsProcessAlive(self.pid_non_existing), |
100 | 101 |
"noexisting process detected") |
101 | 102 |
|
103 |
|
|
102 | 104 |
class TestPidFileFunctions(unittest.TestCase): |
103 |
"""Tests for WritePidFile, RemovePidFile and IsPidFileAlive"""
|
|
105 |
"""Tests for WritePidFile, RemovePidFile and ReadPidFile"""
|
|
104 | 106 |
|
105 | 107 |
def setUp(self): |
106 | 108 |
self.dir = tempfile.mkdtemp() |
... | ... | |
108 | 110 |
utils._DaemonPidFileName = self.f_dpn |
109 | 111 |
|
110 | 112 |
def testPidFileFunctions(self): |
113 |
pid_file = self.f_dpn('test') |
|
111 | 114 |
utils.WritePidFile('test') |
112 |
self.assert_(os.path.exists(self.f_dpn('test'))) |
|
113 |
self.assert_(utils.IsPidFileAlive(self.f_dpn('test'))) |
|
115 |
self.failUnless(os.path.exists(pid_file), |
|
116 |
"PID file should have been created") |
|
117 |
read_pid = utils.ReadPidFile(pid_file) |
|
118 |
self.failUnlessEqual(read_pid, os.getpid()) |
|
119 |
self.failUnless(utils.IsProcessAlive(read_pid)) |
|
120 |
self.failUnlessRaises(GenericError, utils.WritePidFile, 'test') |
|
121 |
utils.RemovePidFile('test') |
|
122 |
self.failIf(os.path.exists(pid_file), |
|
123 |
"PID file should not exist anymore") |
|
124 |
self.failUnlessEqual(utils.ReadPidFile(pid_file), 0, |
|
125 |
"ReadPidFile should return 0 for missing pid file") |
|
126 |
fh = open(pid_file, "w") |
|
127 |
fh.write("blah\n") |
|
128 |
fh.close() |
|
129 |
self.failUnlessEqual(utils.ReadPidFile(pid_file), 0, |
|
130 |
"ReadPidFile should return 0 for invalid pid file") |
|
114 | 131 |
utils.RemovePidFile('test') |
115 |
self.assert_(not os.path.exists(self.f_dpn('test'))) |
|
132 |
self.failIf(os.path.exists(pid_file), |
|
133 |
"PID file should not exist anymore") |
|
116 | 134 |
|
117 | 135 |
def tearDown(self): |
136 |
for name in os.listdir(self.dir): |
|
137 |
os.unlink(os.path.join(self.dir, name)) |
|
118 | 138 |
os.rmdir(self.dir) |
119 | 139 |
|
120 | 140 |
|
Also available in: Unified diff