def session_rescan(timeout=None): # Note: keeping old behaviour of taking the module lock while starting the # command, and releasing the lock while the scan command is running. This # looks like a bug since the purpose of the lock is preventing concurrent # iscsiadm commands, but taking a lock for the entire operation may cause # bigger issues. args = [constants.EXT_ISCSIADM, "-m", "session", "-R"] with _iscsiadmLock: p = commands.start(args, sudo=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: out, err = p.communicate(timeout=timeout) except subprocess.TimeoutExpired: zombiereaper.autoReapPID(p.pid) raise IscsiSessionRescanTimeout(p.pid, timeout) # This is an expected condition before connecting to iSCSI storage # server during startup, or after disconnecting. if p.returncode == ISCSI_ERR_OBJECT_NOT_FOUND: log.debug("No iSCSI sessions found") return # Any other error is reported to the caller. if p.returncode != 0: raise IscsiSessionError(p.returncode, out, err)
def testProcessDiesAfterBeingTracked(self): p = Popen(["sleep", "1"]) zombiereaper.autoReapPID(p.pid) # wait for the grim reaper to arrive sleep(4) # Throws error because pid is not found or is not child self.assertRaises(OSError, os.waitpid, p.pid, os.WNOHANG)
def testProcessDiedBeforeBeingTracked(self): p = Popen(["sleep", "0"]) # wait for the process to die sleep(1) zombiereaper.autoReapPID(p.pid) # Throws error because pid is not found or is not child self.assertRaises(OSError, os.waitpid, p.pid, os.WNOHANG)
def terminating(proc): try: yield proc finally: try: if proc.poll() is None: logging.debug('Terminating process pid=%d' % proc.pid) proc.kill() if proc.poll() is None: zombiereaper.autoReapPID(proc.pid) except Exception: logging.exception('Failed to kill process %d' % proc.pid)
def _runAs(self, user, groups, func, args=(), kwargs={}): def child(pipe): res = ex = None try: uid = resolveUid(user) if groups: gids = [resolveGid(g) for g in groups] os.setgid(gids[0]) os.setgroups(gids) os.setuid(uid) res = func(*args, **kwargs) except BaseException as e: ex = e pipe.send((res, ex)) pipe.recv() pipe, hisPipe = Pipe() with closing(pipe), closing(hisPipe): proc = Process(target=child, args=(hisPipe,)) proc.start() needReaping = True try: if not safe_poll(pipe, RUN_AS_TIMEOUT): try: os.kill(proc.pid, signal.SIGKILL) except OSError as e: # Don't add to zombiereaper of PID no longer exists if e.errno == errno.ESRCH: needReaping = False else: raise raise Timeout() res, err = pipe.recv() pipe.send("Bye") proc.terminate() if err is not None: raise err return res finally: # Add to zombiereaper if process has not been waited upon if proc.exitcode is None and needReaping: zombiereaper.autoReapPID(proc.pid)
def _runAs(self, user, groups, func, args=(), kwargs={}): def child(pipe): res = ex = None try: uid = resolveUid(user) if groups: gids = [resolveGid(g) for g in groups] os.setgid(gids[0]) os.setgroups(gids) os.setuid(uid) res = func(*args, **kwargs) except BaseException as e: ex = e pipe.send((res, ex)) pipe.recv() pipe, hisPipe = Pipe() with closing(pipe), closing(hisPipe): proc = Process(target=child, args=(hisPipe, )) proc.start() needReaping = True try: if not safe_poll(pipe, RUN_AS_TIMEOUT): try: os.kill(proc.pid, signal.SIGKILL) except OSError as e: # Don't add to zombiereaper of PID no longer exists if e.errno == errno.ESRCH: needReaping = False else: raise raise Timeout() res, err = pipe.recv() pipe.send("Bye") proc.terminate() if err is not None: raise err return res finally: # Add to zombiereaper if process has not been waited upon if proc.exitcode is None and needReaping: zombiereaper.autoReapPID(proc.pid)
def _abort(self): self._aborted = True if self._proc.returncode is None: logging.debug('Job %r killing virt-v2v process', self._id) try: self._proc.kill() except OSError as e: if e.errno != errno.ESRCH: raise logging.debug('Job %r virt-v2v process not running', self._id) else: logging.debug('Job %r virt-v2v process was killed', self._id) finally: zombiereaper.autoReapPID(self._proc.pid)
def _rescan(): """ Called from supervdsm to perform rescan as root. """ timeout = config.getint('irs', 'scsi_rescan_maximal_timeout') proc = commands.execCmd([constants.EXT_FC_SCAN], sync=False, execCmdLogger=log) try: proc.wait(timeout) finally: if proc.returncode is None: zombiereaper.autoReapPID(proc.pid) raise Error("Timeout scanning (pid=%s)" % proc.pid) elif proc.returncode != 0: stderr = proc.stderr.read(512) raise Error("Scan failed: %r" % stderr)
def _rescan(): """ Called from supervdsm to perform rescan as root. """ timeout = config.getint('irs', 'scsi_rescan_maximal_timeout') p = commands.start([constants.EXT_FC_SCAN], stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: out, err = p.communicate(timeout=timeout) except subprocess.TimeoutExpired: zombiereaper.autoReapPID(p.pid) raise Error("Timeout scanning (pid=%s)" % p.pid) if p.returncode != 0: raise Error("Scan failed with rc=%s out=%r err=%r" % (p.returncode, out, err))
def _abort(self): self._aborted = True if self._proc is None: logging.warning( 'Ignoring request to abort job %r; the job failed to start', self._id) return if self._proc.returncode is None: logging.debug('Job %r killing virt-v2v process', self._id) try: self._proc.kill() except OSError as e: if e.errno != errno.ESRCH: raise logging.debug('Job %r virt-v2v process not running', self._id) else: logging.debug('Job %r virt-v2v process was killed', self._id) finally: for pid in self._proc.pids: zombiereaper.autoReapPID(pid)
def __del__(self): if self._proc.returncode is None: zombiereaper.autoReapPID(self._proc.pid)