Source code for virttest.utils_libvirtd

"""
Module to control libvirtd service.
"""
import re
import logging
import aexpect

from virttest import remote, utils_misc
from autotest.client import utils, os_dep
from autotest.client.shared import error
from virttest.staging import service
from virttest.utils_gdb import GDB


try:
    os_dep.command("libvirtd")
    LIBVIRTD = "libvirtd"
except ValueError:
    LIBVIRTD = None


[docs]class Libvirtd(object): """ Class to manage libvirtd service on host or guest. """ def __init__(self, session=None): """ Initialize an service object for libvirtd. :params session: An session to guest or remote host. """ self.session = session if self.session: self.remote_runner = remote.RemoteRunner(session=self.session) runner = self.remote_runner.run else: runner = utils.run if LIBVIRTD is None: logging.warning("Libvirtd service is not available in host, " "utils_libvirtd module will not function normally") self.libvirtd = service.Factory.create_service(LIBVIRTD, run=runner) def _wait_for_start(self, timeout=60): """ Wait n seconds for libvirt to start. Default is 10 seconds. """ def _check_start(): virsh_cmd = "virsh list" try: if self.session: self.session.cmd(virsh_cmd, timeout=2) else: utils.run(virsh_cmd, timeout=2) return True except: return False return utils_misc.wait_for(_check_start, timeout=timeout)
[docs] def start(self, reset_failed=True): if reset_failed: self.libvirtd.reset_failed() if not self.libvirtd.start(): return False return self._wait_for_start()
[docs] def stop(self): return self.libvirtd.stop()
[docs] def restart(self, reset_failed=True): if reset_failed: self.libvirtd.reset_failed() if not self.libvirtd.restart(): return False return self._wait_for_start()
[docs] def is_running(self): return self.libvirtd.status()
[docs]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
[docs] 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")
[docs] 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()
[docs] def cont(self): """ Continue a stopped libvirtd session. """ if self.gdb: self.gdb.cont() else: logging.error("Only gdb session supports continue")
[docs] def kill(self): """ Kill the libvirtd session. """ if self.gdb: self.gdb.kill() else: self.tail.kill()
[docs] 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)
[docs] 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, )
[docs] 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')
[docs] 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')
[docs] 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
[docs] 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, )
[docs] 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.")
[docs] 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()
[docs]def deprecation_warning(): """ As the utils_libvirtd.libvirtd_xxx interfaces are deprecated, this function are printing the warning to user. """ logging.warning("This function was deprecated, Please use " "class utils_libvirtd.Libvirtd to manage " "libvirtd service.")
[docs]def libvirtd_start(): libvirtd_instance = Libvirtd() deprecation_warning() return libvirtd_instance.start()
[docs]def libvirtd_is_running(): libvirtd_instance = Libvirtd() deprecation_warning() return libvirtd_instance.is_running()
[docs]def libvirtd_stop(): libvirtd_instance = Libvirtd() deprecation_warning() return libvirtd_instance.stop()
[docs]def libvirtd_restart(): libvirtd_instance = Libvirtd() deprecation_warning() return libvirtd_instance.restart()
[docs]def service_libvirtd_control(action, session=None): libvirtd_instance = Libvirtd(session) deprecation_warning() getattr(libvirtd_instance, action)()