コード例 #1
0
ファイル: cmdutils_test.py プロジェクト: gobindadas/vdsm
 def test_terminate(self):
     p = CPopen(["sleep", "1"],
                stdin=None,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE)
     p.terminate()
     list(cmdutils.receive(p))
     self.assertEqual(p.returncode, -signal.SIGTERM)
コード例 #2
0
class QemuImgOperation(object):
    REGEXPR = re.compile(r'\s*\(([\d.]+)/100%\)\s*')

    def __init__(self, cmd, cwd=None):
        self._lock = threading.Lock()
        self._aborted = False
        self._progress = 0.0

        self._stdout = bytearray()
        self._stderr = bytearray()

        self.cmd = wrap_command(cmd,
                                with_nice=utils.NICENESS.HIGH,
                                with_ioclass=utils.IOCLASS.IDLE)
        _log.debug(cmdutils.command_log_line(self.cmd, cwd=cwd))
        self._command = CPopen(self.cmd, cwd=cwd, deathSignal=signal.SIGKILL)
        self._stream = utils.CommandStream(self._command, self._recvstdout,
                                           self._recvstderr)

    def _recvstderr(self, buffer):
        self._stderr += buffer

    def _recvstdout(self, buffer):
        self._stdout += buffer

        # Checking the presence of '\r' before splitting will prevent
        # generating the array when it's not needed.
        try:
            idx = self._stdout.rindex('\r')
        except ValueError:
            return

        # qemu-img updates progress by printing \r (0.00/100%) to standard out.
        # The output could end with a partial progress so we must discard
        # everything after the last \r and then try to parse a progress record.
        valid_progress = self._stdout[:idx]
        last_progress = valid_progress.rsplit('\r', 1)[-1]

        # No need to keep old progress information around
        del self._stdout[:idx + 1]

        m = self.REGEXPR.match(last_progress)
        if m is None:
            raise ValueError('Unable to parse: "%r"' % last_progress)

        self._progress = float(m.group(1))

    @property
    def progress(self):
        """
        Returns operation progress as float between 0 and 100.

        This method is threadsafe and may be called from any thread.
        """
        return self._progress

    @property
    def error(self):
        return str(self._stderr)

    @property
    def finished(self):
        return self._command.poll() is not None

    def poll(self, timeout=None):
        self._stream.receive(timeout=timeout)

        if not self._stream.closed:
            return

        self._command.wait()

        if self._aborted:
            raise exception.ActionStopped()

        cmdutils.retcode_log_line(self._command.returncode, self.error)
        if self._command.returncode != 0:
            raise QImgError(self.cmd, self._command.returncode, "", self.error)

    def wait_for_completion(self):
        timeout = config.getint("irs", "progress_interval")
        while not self.finished:
            self.poll(timeout)
            _log.debug('qemu-img operation progress: %s%%', self.progress)

    def abort(self):
        """
        Aborts running operation by sending a termination signal to the
        underlying qemu-img process.

        Note: this is asynchronous operation, returning before the process was
        terminated. You must use wait_for_completion to wait for the underlying
        qemu-img process.

        This method is threadsafe and may be called from any thread.
        """
        with self._lock:
            if self._command is None:
                return
            if self._command.poll() is None:
                self._aborted = True
                self._command.terminate()

    def close(self):
        with self._lock:
            self._stream.close()
            self._command = None
コード例 #3
0
ファイル: qemuimg.py プロジェクト: EdDev/vdsm
class QemuImgOperation(object):
    REGEXPR = re.compile(r'\s*\(([\d.]+)/100%\)\s*')

    def __init__(self, cmd, cwd=None):
        self._lock = threading.Lock()
        self._aborted = False
        self._progress = 0.0

        self._stdout = bytearray()
        self._stderr = bytearray()

        self.cmd = wrap_command(
            cmd,
            with_nice=utils.NICENESS.HIGH,
            with_ioclass=utils.IOCLASS.IDLE)
        _log.debug(cmdutils.command_log_line(self.cmd, cwd=cwd))
        self._command = CPopen(self.cmd, cwd=cwd,
                               deathSignal=signal.SIGKILL)
        self._stream = utils.CommandStream(
            self._command, self._recvstdout, self._recvstderr)

    def _recvstderr(self, buffer):
        self._stderr += buffer

    def _recvstdout(self, buffer):
        self._stdout += buffer

        # Checking the presence of '\r' before splitting will prevent
        # generating the array when it's not needed.
        try:
            idx = self._stdout.rindex('\r')
        except ValueError:
            return

        # qemu-img updates progress by printing \r (0.00/100%) to standard out.
        # The output could end with a partial progress so we must discard
        # everything after the last \r and then try to parse a progress record.
        valid_progress = self._stdout[:idx]
        last_progress = valid_progress.rsplit('\r', 1)[-1]

        # No need to keep old progress information around
        del self._stdout[:idx + 1]

        m = self.REGEXPR.match(last_progress)
        if m is None:
            raise ValueError('Unable to parse: "%r"' % last_progress)

        self._progress = float(m.group(1))

    @property
    def progress(self):
        """
        Returns operation progress as float between 0 and 100.

        This method is threadsafe and may be called from any thread.
        """
        return self._progress

    @property
    def error(self):
        return str(self._stderr)

    @property
    def finished(self):
        return self._command.poll() is not None

    def poll(self, timeout=None):
        self._stream.receive(timeout=timeout)

        if not self._stream.closed:
            return

        self._command.wait()

        if self._aborted:
            raise exception.ActionStopped()

        cmdutils.retcode_log_line(self._command.returncode, self.error)
        if self._command.returncode != 0:
            raise QImgError(self.cmd, self._command.returncode, "",
                            self.error)

    def wait_for_completion(self):
        timeout = config.getint("irs", "progress_interval")
        while not self.finished:
            self.poll(timeout)
            _log.debug('qemu-img operation progress: %s%%', self.progress)

    def abort(self):
        """
        Aborts running operation by sending a termination signal to the
        underlying qemu-img process.

        Note: this is asynchronous operation, returning before the process was
        terminated. You must use wait_for_completion to wait for the underlying
        qemu-img process.

        This method is threadsafe and may be called from any thread.
        """
        with self._lock:
            if self._command is None:
                return
            if self._command.poll() is None:
                self._aborted = True
                self._command.terminate()

    def close(self):
        with self._lock:
            self._stream.close()
            self._command = None