"failed", "fail_reason", "cmd"]
- def __init__(self, exit_code, signal, stdout, stderr, cmd):
+ def __init__(self, exit_code, signal_, stdout, stderr, cmd):
self.cmd = cmd
self.exit_code = exit_code
- self.signal = signal
+ self.signal = signal_
self.stdout = stdout
self.stderr = stderr
- self.failed = (signal is not None or exit_code != 0)
+ self.failed = (signal_ is not None or exit_code != 0)
if self.signal is not None:
self.fail_reason = "terminated by signal %s" % self.signal
status = child.wait()
if status >= 0:
exitcode = status
- signal = None
+ signal_ = None
else:
exitcode = None
- signal = -status
+ signal_ = -status
- return RunResult(exitcode, signal, out, err, strcmd)
+ return RunResult(exitcode, signal_, out, err, strcmd)
def RemoveFile(filename):
Returns: true or false, depending on if the pid exists or not
- Remarks: zombie processes treated as not alive
+ Remarks: zombie processes treated as not alive, and giving a pid <=
+ 0 makes the function to return False.
"""
+ if pid <= 0:
+ return False
+
try:
f = open("/proc/%d/status" % pid)
except IOError, err:
return alive
-def IsPidFileAlive(pidfile):
- """Check whether the given pidfile points to a live process.
+def ReadPidFile(pidfile):
+ """Read the pid from a file.
- @param pidfile: Path to a file containing the pid to be checked
- @type pidfile: string (filename)
+ @param pidfile: Path to a file containing the pid to be checked
+ @type pidfile: string (filename)
+ @return: The process id, if the file exista and contains a valid PID,
+ otherwise 0
+ @rtype: int
"""
try:
pf = open(pidfile, 'r')
- except EnvironmentError, open_err:
- if open_err.errno == errno.ENOENT:
- return False
- else:
- raise errors.GenericError("Cannot open file %s. Error: %s" %
- (pidfile, str(open_err)))
+ except EnvironmentError, err:
+ if err.errno != errno.ENOENT:
+ logging.exception("Can't read pid file?!")
+ return 0
try:
pid = int(pf.read())
- except ValueError:
- raise errors.GenericError("Invalid pid string in %s" %
- (pidfile,))
+ except ValueError, err:
+ logging.info("Can't parse pid file contents", exc_info=True)
+ return 0
- return IsProcessAlive(pid)
+ return pid
def MatchNameComponent(key, name_list):
return 0
-def _DaemonPidFileName(name):
+def DaemonPidFileName(name):
"""Compute a ganeti pid file absolute path, given the daemon name.
"""
"""
pid = os.getpid()
- pidfilename = _DaemonPidFileName(name)
- if IsPidFileAlive(pidfilename):
- raise GenericError("%s contains a live process" % pidfilename)
+ pidfilename = DaemonPidFileName(name)
+ if IsProcessAlive(ReadPidFile(pidfilename)):
+ raise errors.GenericError("%s contains a live process" % pidfilename)
WriteFile(pidfilename, data="%d\n" % pid)
"""
pid = os.getpid()
- pidfilename = _DaemonPidFileName(name)
+ pidfilename = DaemonPidFileName(name)
# TODO: we could check here that the file contains our pid
try:
RemoveFile(pidfilename)
pass
+def KillProcess(pid, signal_=signal.SIGTERM, timeout=30):
+ """Kill a process given by its pid.
+
+ @type pid: int
+ @param pid: The PID to terminate.
+ @type signal_: int
+ @param signal_: The signal to send, by default SIGTERM
+ @type timeout: int
+ @param timeout: The timeout after which, if the process is still alive,
+ a SIGKILL will be sent. If not positive, no such checking
+ will be done
+
+ """
+ if pid <= 0:
+ # kill with pid=0 == suicide
+ raise errors.ProgrammerError("Invalid pid given '%s'" % pid)
+
+ if not IsProcessAlive(pid):
+ return
+ os.kill(pid, signal_)
+ if timeout <= 0:
+ return
+ end = time.time() + timeout
+ while time.time() < end and IsProcessAlive(pid):
+ time.sleep(0.1)
+ if IsProcessAlive(pid):
+ os.kill(pid, signal.SIGKILL)
+
+
def FindFile(name, search_path, test=os.path.exists):
"""Look for a filesystem object in a given path.