Example #1
0
class VirtQemudSession(object):

    """
    Interaction virtqemud daemon session by directly call the virtqemud command.
    With gdb debugging feature can be optionally started.
    """

    def __init__(self, gdb=False,
                 logging_handler=None,
                 logging_params=(),
                 logging_pattern=r'.*'):
        """
        :param gdb: Whether call the session with gdb debugging support
        :param logging_handler: Callback function to handle logging
        :param logging_params: additional logging parameters
        :param logging_pattern: Regex for filtering specific log lines
        """
        self.gdb = None
        self.tail = None
        self.running = False
        self.pid = None
        self.bundle = {"stop-info": None}
        self.virtqemud_service = VirtQemud()
        self.was_running = self.virtqemud_service.is_running()
        if self.was_running:
            logging.debug('Stopping virtqemud service')
            self.virtqemud_service.stop()

        self.logging_handler = logging_handler
        self.logging_params = logging_params
        self.logging_pattern = logging_pattern

        if gdb:
            self.gdb = GDB('virtqemud')
            self.gdb.set_callback('stop', self._stop_callback, self.bundle)
            self.gdb.set_callback('start', self._start_callback, self.bundle)
            self.gdb.set_callback('termination', self._termination_callback)

    def _output_handler(self, line):
        """
        Adapter output callback function.
        """
        if self.logging_handler is not None:
            if re.match(self.logging_pattern, line):
                self.logging_handler(line, *self.logging_params)

    def _termination_handler(self, status):
        """
        Helper aexpect termination handler
        """
        self.running = False
        self.exit_status = status
        self.pid = None

    def _termination_callback(self, gdb, status):
        """
        Termination handler function triggered when virtqemud exited.

        :param gdb: Instance of the gdb session
        :param status: Return code of exited virtqemud session
        """
        self.running = False
        self.exit_status = status
        self.pid = None

    def _stop_callback(self, gdb, info, params):
        """
        Stop handler function triggered when gdb virtqemud stopped.

        :param gdb: Instance of the gdb session
        :param info: information
        :param params: Parameter lists
        """
        self.running = False
        params['stop-info'] = info

    def _start_callback(self, gdb, info, params):
        """
        Stop handler function triggered when gdb virtqemud started.

        :param gdb: Instance of the gdb session
        :param status: Return code of exited virtqemud session
        """
        self.running = True
        params['stop-info'] = None

    def set_callback(self, callback_type, callback_func, callback_params=None):
        """
        Set a customized gdb callback function.
        """
        if self.gdb:
            self.gdb.set_callback(
                callback_type, callback_func, callback_params)
        else:
            logging.error("Only gdb session supports setting callback")

    def start(self, arg_str='', wait_for_working=True):
        """
        Start virtqemud session.

        :param arg_str: Argument passing to the session
        :param wait_for_working: Whether wait for virtqemud finish loading
        """
        if self.gdb:
            self.gdb.run(arg_str=arg_str)
            self.pid = self.gdb.pid
        else:
            self.tail = aexpect.Tail(
                "%s %s" % ('virtqemud', arg_str),
                output_func=self._output_handler,
                termination_func=self._termination_handler,
            )
            self.running = True

        if wait_for_working:
            self.wait_for_working()

    def cont(self):
        """
        Continue a stopped virtqemud session.
        """
        if self.gdb:
            self.gdb.cont()
        else:
            logging.error("Only gdb session supports continue")

    def kill(self):
        """
        Kill the virtqemud session.
        """
        if self.gdb:
            self.gdb.kill()
        else:
            self.tail.kill()

    def restart(self, arg_str='', wait_for_working=True):
        """
        Restart the virtqemud session.

        :param arg_str: Argument passing to the session
        :param wait_for_working: Whether wait for virtqemud finish loading
        """
        logging.debug("Restarting virtqemud session")
        self.kill()
        self.start(arg_str=arg_str, wait_for_working=wait_for_working)

    def wait_for_working(self, timeout=60):
        """
        Wait for virtqemud to work.

        :param timeout: Max wait time
        """
        logging.debug('Waiting for virtqemud to work')
        return utils_misc.wait_for(
            self.is_working,
            timeout=timeout,
        )

    def back_trace(self):
        """
        Get the backtrace from gdb session.
        """
        if self.gdb:
            return self.gdb.back_trace()
        else:
            logging.warning('Can not get back trace without gdb')

    def insert_break(self, break_func):
        """
        Insert a function breakpoint.

        :param break_func: Function at which breakpoint inserted
        """
        if self.gdb:
            return self.gdb.insert_break(break_func)
        else:
            logging.warning('Can not insert breakpoint without gdb')

    def is_working(self):
        """
        Check if virtqemud is start by return status of 'virsh -c qemu:///system list'
        """
        virsh_cmd = "virsh -c qemu:///system list"
        try:
            process.run(virsh_cmd, timeout=2)
            return True
        except process.CmdError:
            return False

    def wait_for_stop(self, timeout=60, step=0.1):
        """
        Wait for virtqemud to stop.

        :param timeout: Max wait time
        :param step: Checking interval
        """
        logging.debug('Waiting for virtqemud to stop')
        if self.gdb:
            return self.gdb.wait_for_stop(timeout=timeout)
        else:
            return wait.wait_for(
                lambda: not self.running,
                timeout=timeout,
                step=step,
            )

    def wait_for_termination(self, timeout=60):
        """
        Wait for virtqemud gdb session to exit.

        :param timeout: Max wait time
        """
        logging.debug('Waiting for virtqemud to terminate')
        if self.gdb:
            return self.gdb.wait_for_termination(timeout=timeout)
        else:
            logging.error("Only gdb session supports wait_for_termination.")

    def exit(self):
        """
        Exit the virtqemud session.
        """
        if self.gdb:
            self.gdb.exit()
        else:
            if self.tail:
                self.tail.close()

        if self.was_running:
            self.virtqemud_service.start()
class LibvirtdSession(object):

    """
    Interaction libvirt daemon session by directly call the libvirtd command.
    With gdb debugging feature can be optionally started.
    """

    def __init__(self, gdb=False,
                 logging_handler=None,
                 logging_pattern=r'.*'):
        """
        :param gdb: Whether call the session with gdb debugging support
        :param logging_handler: Callback function to handle logging
        :param logging_pattern: Regex for filtering specific log lines
        """
        self.gdb = None
        self.tail = None
        self.running = False
        self.pid = None
        self.bundle = {"stop-info": None}
        self.libvirtd_service = Libvirtd()
        self.was_running = self.libvirtd_service.is_running()
        if self.was_running:
            logging.debug('Stopping libvirtd service')
            self.libvirtd_service.stop()

        self.logging_handler = logging_handler
        self.logging_pattern = logging_pattern

        if gdb:
            self.gdb = GDB(LIBVIRTD)
            self.gdb.set_callback('stop', self._stop_callback, self.bundle)
            self.gdb.set_callback('start', self._start_callback, self.bundle)
            self.gdb.set_callback('termination', self._termination_callback)

    def _output_handler(self, line):
        """
        Adapter output callback function.
        """
        if self.logging_handler is not None:
            if re.match(self.logging_pattern, line):
                self.logging_handler(line)

    def _termination_handler(self, status):
        """
        Helper aexpect terminaltion handler
        """
        self.running = False
        self.exit_status = status
        self.pid = None

    def _termination_callback(self, gdb, status):
        """
        Termination handler function triggered when libvirtd exited.

        :param gdb: Instance of the gdb session
        :param status: Return code of exited libvirtd session
        """
        self.running = False
        self.exit_status = status
        self.pid = None

    def _stop_callback(self, gdb, info, params):
        """
        Stop handler function triggered when gdb libvirtd stopped.

        :param gdb: Instance of the gdb session
        :param status: Return code of exited libvirtd session
        """
        self.running = False
        params['stop-info'] = info

    def _start_callback(self, gdb, info, params):
        """
        Stop handler function triggered when gdb libvirtd started.

        :param gdb: Instance of the gdb session
        :param status: Return code of exited libvirtd session
        """
        self.running = True
        params['stop-info'] = None

    def set_callback(self, callback_type, callback_func, callback_params=None):
        """
        Set a customized gdb callback function.
        """
        if self.gdb:
            self.gdb.set_callback(callback_type, callback_func, callback_params)
        else:
            logging.error("Only gdb session supports setting callback")

    def start(self, arg_str='', wait_for_working=True):
        """
        Start libvirtd session.

        :param arg_str: Argument passing to the session
        :param wait_for_working: Whether wait for libvirtd finish loading
        """
        if self.gdb:
            self.gdb.run(arg_str=arg_str)
            self.pid = self.gdb.pid
        else:
            self.tail = aexpect.Tail(
                "%s %s" % (LIBVIRTD, arg_str),
                output_func=self._output_handler,
                termination_func=self._termination_handler,
            )
            self.running = True

        if wait_for_working:
            self.wait_for_working()

    def cont(self):
        """
        Continue a stopped libvirtd session.
        """
        if self.gdb:
            self.gdb.cont()
        else:
            logging.error("Only gdb session supports continue")

    def kill(self):
        """
        Kill the libvirtd session.
        """
        if self.gdb:
            self.gdb.kill()
        else:
            self.tail.kill()

    def restart(self, arg_str='', wait_for_working=True):
        """
        Restart the libvirtd session.

        :param arg_str: Argument passing to the session
        :param wait_for_working: Whether wait for libvirtd finish loading
        """
        logging.debug("Restarting libvirtd session")
        self.kill()
        self.start(arg_str=arg_str, wait_for_working=wait_for_working)

    def wait_for_working(self, timeout=60):
        """
        Wait for libvirtd to work.

        :param timeout: Max wait time
        """
        logging.debug('Waiting for libvirtd to work')
        return utils_misc.wait_for(
            self.is_working,
            timeout=timeout,
        )

    def back_trace(self):
        """
        Get the backtrace from gdb session.
        """
        if self.gdb:
            return self.gdb.back_trace()
        else:
            logging.warning('Can not get back trace without gdb')

    def insert_break(self, break_func):
        """
        Insert a function breakpoint.

        :param break_func: Function at which breakpoint inserted
        """
        if self.gdb:
            return self.gdb.insert_break(break_func)
        else:
            logging.warning('Can not insert breakpoint without gdb')

    def is_working(self):
        """
        Check if libvirtd is start by return status of 'virsh list'
        """
        virsh_cmd = "virsh list"
        try:
            utils.run(virsh_cmd, timeout=2)
            return True
        except error.CmdError:
            return False

    def wait_for_stop(self, timeout=60, step=0.1):
        """
        Wait for libvirtd to stop.

        :param timeout: Max wait time
        :param step: Checking interval
        """
        logging.debug('Waiting for libvirtd to stop')
        if self.gdb:
            return self.gdb.wait_for_stop(timeout=timeout)
        else:
            return utils.wait_for(
                lambda: not self.running,
                timeout=timeout,
                step=step,
            )

    def wait_for_termination(self, timeout=60):
        """
        Wait for libvirtd gdb session to exit.

        :param timeout: Max wait time
        """
        logging.debug('Waiting for libvirtd to terminate')
        if self.gdb:
            return self.gdb.wait_for_termination(timeout=timeout)
        else:
            logging.error("Only gdb session supports wait_for_termination.")

    def exit(self):
        """
        Exit the libvirtd session.
        """
        if self.gdb:
            self.gdb.exit()
        else:
            if self.tail:
                self.tail.close()

        if self.was_running:
            self.libvirtd_service.start()