コード例 #1
0
ファイル: check.py プロジェクト: bronhaim/vdsm
 def _start_process(self):
     """
     Starts a dd process performing direct I/O to path, reading the process
     stderr. When stderr has closed, _read_completed will be called.
     """
     cmd = [constants.EXT_DD, "if=%s" % self._path, "of=/dev/null",
            "bs=4096", "count=1", "iflag=direct"]
     cmd = cmdutils.wrap_command(cmd)
     self._proc = CPopen(cmd, stdin=None, stdout=None,
                         stderr=subprocess.PIPE)
     self._reader = self._loop.create_dispatcher(
         asyncevent.BufferedReader, self._proc.stderr, self._read_completed)
コード例 #2
0
def _simple_exec_cmd(command,
                     env=None,
                     nice=None,
                     ioclass=None,
                     stdin=None,
                     stdout=None,
                     stderr=None):

    command = cmdutils.wrap_command(command,
                                    with_ioclass=ioclass,
                                    ioclassdata=None,
                                    with_nice=nice,
                                    with_setsid=False,
                                    with_sudo=False,
                                    reset_cpu_affinity=True)

    logging.debug(cmdutils.command_log_line(command, cwd=None))

    p = CPopen(command,
               close_fds=True,
               cwd=None,
               env=env,
               stdin=stdin,
               stdout=stdout,
               stderr=stderr)
    return p
コード例 #3
0
ファイル: check.py プロジェクト: yingyun001/vdsm
 def _start_process(self):
     """
     Starts a dd process performing direct I/O to path, reading the process
     stderr. When stderr has closed, _read_completed will be called.
     """
     cmd = [constants.EXT_DD, "if=%s" % self._path, "of=/dev/null",
            "bs=4096", "count=1", "iflag=direct"]
     cmd = cmdutils.wrap_command(cmd)
     self._proc = CPopen(cmd, stdin=None, stdout=None,
                         stderr=subprocess.PIPE)
     self._reader = self._loop.create_dispatcher(
         asyncevent.BufferedReader, self._proc.stderr, self._read_completed)
コード例 #4
0
ファイル: check.py プロジェクト: yingyun001/vdsm
class DirectioChecker(object):
    """
    Check path availability using direct I/O.

    DirectioChecker is created with a complete callback.  Each time a check
    cycle is completed, the complete callback will be invoked with a
    CheckResult instance.

    CheckResult provides a delay() method returning the read delay in
    seconds. If the check failed, the delay() method will raise the
    appropriate exception that can be reported to engine.

    Note that the complete callback must not block as it will block the entire
    event loop thread.

    The checker runs exactly every interval seconds. If a check did not
    complete before the next check is scheduled, the next check will be delayed
    to the next interval.

    Checker is not thread safe. Use EventLoop.call_soon_threadsafe() to start
    or stop a checker. The only thread safe method is wait().

    Usage:

        # Start the event loop thread

        loop = asyncevent.EventLoop()
        concurrent.thread(loop.run_forever).start()

        # The complete callback

        def complete(result):
            try:
                check_delay = result.delay()
            except Exception as e:
                check_error = e
            check_time = time.time()

        # Start a checker on the event loop thread

        checker = DirectioChecker(loop, path, complete)
        loop.call_soon_threadsafe(checker.start)

        ...

        # Stop a checker from another thread

        loop.call_soon_threadsafe(checker.stop)

        # If needed, wait until a checker actually stopped.

        checker.wait(30)

    """

    log = logging.getLogger("storage.directiochecker")

    def __init__(self, loop, path, complete, interval=10.0):
        self._loop = loop
        self._path = path
        self._complete = complete
        self._interval = interval
        self._next_check = None
        self._check_time = None
        self._timer = None
        self._proc = None
        self._reader = None
        self._reaper = None
        self._err = None
        self._state = IDLE
        self._stopped = threading.Event()

    def start(self):
        """
        Start the checker.

        Raises RuntimeError if the checker is running.
        """
        if self._state is not IDLE:
            raise RuntimeError("Checker is %s", self._state)
        self._state = RUNNING
        _log.debug("Checker %r started", self._path)
        self._stopped.clear()
        self._next_check = self._loop.time()
        self._check()

    def stop(self):
        """
        Stop the checker.

        If the checker is waiting for the next check, the next check will be
        cancelled. If the checker is in the middle of a check, it will stop
        when the check completes.

        If the checker is not running, the call is ignored silently.
        """
        if self._state is not RUNNING:
            return
        _log.debug("Checker %r stopping", self._path)
        self._state = STOPPING
        if self._timer:
            self._timer.cancel()
            self._timer = None
        if self._proc is None:
            self._stop_completed()

    def wait(self, timeout=None):
        """
        Wait until a checker has stopped.

        Returns True if checker has stopped, False if timeout expired.
        """
        return self._stopped.wait(timeout)

    def is_running(self):
        return self._state is not IDLE

    def _stop_completed(self):
        self._state = IDLE
        _log.debug("Checker %r stopped", self._path)
        self._stopped.set()

    def _check(self):
        """
        Called when starting the checker, and then every interval seconds until
        the checker is stopped.
        """
        assert self._state is RUNNING
        self._timer = None
        self._check_time = self._loop.time()
        _log.debug("START check %r (delay=%.2f)",
                   self._path, self._check_time - self._next_check)
        try:
            self._start_process()
        except Exception as e:
            self._err = "Error starting process: %s" % e
            self._check_completed(EXEC_ERROR)

    def _start_process(self):
        """
        Starts a dd process performing direct I/O to path, reading the process
        stderr. When stderr has closed, _read_completed will be called.
        """
        cmd = [constants.EXT_DD, "if=%s" % self._path, "of=/dev/null",
               "bs=4096", "count=1", "iflag=direct"]
        cmd = cmdutils.wrap_command(cmd)
        self._proc = CPopen(cmd, stdin=None, stdout=None,
                            stderr=subprocess.PIPE)
        self._reader = self._loop.create_dispatcher(
            asyncevent.BufferedReader, self._proc.stderr, self._read_completed)

    def _read_completed(self, data):
        """
        Called when dd process has closed stderr. At this point the process may
        be still running.
        """
        assert self._state is not IDLE
        self._reader = None
        self._err = data
        rc = self._proc.poll()
        # About 95% of runs, the process has terminated at this point. If not,
        # start the reaper to wait for it.
        if rc is None:
            self._reaper = asyncevent.Reaper(self._loop, self._proc,
                                             self._check_completed)
            return
        self._check_completed(rc)

    def _check_completed(self, rc):
        """
        Called when the dd process has exited with exit code rc.
        """
        assert self._state is not IDLE
        now = self._loop.time()
        elapsed = now - self._check_time
        _log.debug("FINISH check %r (rc=%s, elapsed=%.02f)",
                   self._path, rc, elapsed)
        self._reaper = None
        self._proc = None
        if self._state is STOPPING:
            self._stop_completed()
            return
        self._schedule_next_check(now)
        result = CheckResult(self._path, rc, self._err, self._check_time,
                             elapsed)
        self._complete(result)

    def _schedule_next_check(self, now):
        while self._next_check <= now:
            self._next_check += self._interval
        self._timer = self._loop.call_at(self._next_check, self._check)

    def __repr__(self):
        info = [self.__class__.__name__,
                self._path,
                self._state]
        if self._state is RUNNING:
            info.append("next_check=%.2f" % self._next_check)
        return "<%s at 0x%x>" % (" ".join(info), id(self))
コード例 #5
0
ファイル: check.py プロジェクト: bronhaim/vdsm
class DirectioChecker(object):
    """
    Check path availability using direct I/O.

    DirectioChecker is created with a complete callback.  Each time a check
    cycle is completed, the complete callback will be invoked with a
    CheckResult instance.

    CheckResult provides a delay() method returning the read delay in
    seconds. If the check failed, the delay() method will raise the
    appropriate exception that can be reported to engine.

    Note that the complete callback must not block as it will block the entire
    event loop thread.

    The checker runs exactly every interval seconds. If a check did not
    complete before the next check is scheduled, the next check will be delayed
    to the next interval.

    Checker is not thread safe. Use EventLoop.call_soon_threadsafe() to start
    or stop a checker. The only thread safe method is wait().

    Usage::

        # Start the event loop thread

        loop = asyncevent.EventLoop()
        concurrent.thread(loop.run_forever).start()

        # The complete callback

        def complete(result):
            try:
                check_delay = result.delay()
            except Exception as e:
                check_error = e
            check_time = time.time()

        # Start a checker on the event loop thread

        checker = DirectioChecker(loop, path, complete)
        loop.call_soon_threadsafe(checker.start)

        ...

        # Stop a checker from another thread

        loop.call_soon_threadsafe(checker.stop)

        # If needed, wait until a checker actually stopped.

        checker.wait(30)

    """

    log = logging.getLogger("storage.directiochecker")

    def __init__(self, loop, path, complete, interval=10.0):
        self._loop = loop
        self._path = path
        self._complete = complete
        self._interval = interval
        self._next_check = None
        self._check_time = None
        self._timer = None
        self._proc = None
        self._reader = None
        self._reaper = None
        self._err = None
        self._state = IDLE
        self._stopped = threading.Event()

    def start(self):
        """
        Start the checker.

        Raises RuntimeError if the checker is running.
        """
        if self._state is not IDLE:
            raise RuntimeError("Checker is %s", self._state)
        self._state = RUNNING
        _log.debug("Checker %r started", self._path)
        self._stopped.clear()
        self._next_check = self._loop.time()
        self._check()

    def stop(self):
        """
        Stop the checker.

        If the checker is waiting for the next check, the next check will be
        cancelled. If the checker is in the middle of a check, it will stop
        when the check completes.

        If the checker is not running, the call is ignored silently.
        """
        if self._state is not RUNNING:
            return
        _log.debug("Checker %r stopping", self._path)
        self._state = STOPPING
        if self._timer:
            self._timer.cancel()
            self._timer = None
        if self._proc is None:
            self._stop_completed()

    def wait(self, timeout=None):
        """
        Wait until a checker has stopped.

        Returns True if checker has stopped, False if timeout expired.
        """
        return self._stopped.wait(timeout)

    def is_running(self):
        return self._state is not IDLE

    def _stop_completed(self):
        self._state = IDLE
        _log.debug("Checker %r stopped", self._path)
        self._stopped.set()

    def _check(self):
        """
        Called when starting the checker, and then every interval seconds until
        the checker is stopped.
        """
        assert self._state is RUNNING
        self._timer = None
        self._check_time = self._loop.time()
        _log.debug("START check %r (delay=%.2f)",
                   self._path, self._check_time - self._next_check)
        try:
            self._start_process()
        except Exception as e:
            self._err = "Error starting process: %s" % e
            self._check_completed(EXEC_ERROR)

    def _start_process(self):
        """
        Starts a dd process performing direct I/O to path, reading the process
        stderr. When stderr has closed, _read_completed will be called.
        """
        cmd = [constants.EXT_DD, "if=%s" % self._path, "of=/dev/null",
               "bs=4096", "count=1", "iflag=direct"]
        cmd = cmdutils.wrap_command(cmd)
        self._proc = CPopen(cmd, stdin=None, stdout=None,
                            stderr=subprocess.PIPE)
        self._reader = self._loop.create_dispatcher(
            asyncevent.BufferedReader, self._proc.stderr, self._read_completed)

    def _read_completed(self, data):
        """
        Called when dd process has closed stderr. At this point the process may
        be still running.
        """
        assert self._state is not IDLE
        self._reader = None
        self._err = data
        rc = self._proc.poll()
        # About 95% of runs, the process has terminated at this point. If not,
        # start the reaper to wait for it.
        if rc is None:
            self._reaper = asyncevent.Reaper(self._loop, self._proc,
                                             self._check_completed)
            return
        self._check_completed(rc)

    def _check_completed(self, rc):
        """
        Called when the dd process has exited with exit code rc.
        """
        assert self._state is not IDLE
        now = self._loop.time()
        elapsed = now - self._check_time
        _log.debug("FINISH check %r (rc=%s, elapsed=%.02f)",
                   self._path, rc, elapsed)
        self._reaper = None
        self._proc = None
        if self._state is STOPPING:
            self._stop_completed()
            return
        self._schedule_next_check(now)
        result = CheckResult(self._path, rc, self._err, self._check_time,
                             elapsed)
        self._complete(result)

    def _schedule_next_check(self, now):
        while self._next_check <= now:
            self._next_check += self._interval
        self._timer = self._loop.call_at(self._next_check, self._check)

    def __repr__(self):
        info = [self.__class__.__name__,
                self._path,
                self._state]
        if self._state is RUNNING:
            info.append("next_check=%.2f" % self._next_check)
        return "<%s at 0x%x>" % (" ".join(info), id(self))