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()