from collections import namedtuple import libvirt import logging logger = logging.getLogger(__name__) class LibvirtErrorCode: reverse_errors = { getattr(libvirt, err_name): err_name for err_name in filter(lambda x: x.startswith("VIR_ERR_"), libvirt.__dir__()) } def __init__(self, code): self.code = code self.err = self.reverse_errors.get(code, None) def __repr__(self): return "{}".format(self.code) def __str__(self): return "{} [{}]".format(self.err, self.code) def __eq__(self, val): return self.code == val class LibvirtErrorDomain: reverse_domains = { getattr(libvirt, err_name): err_name for err_name in filter(lambda x: x.startswith("VIR_DOMAIN_"), libvirt.__dir__()) } def __init__(self, code): self.code = code self.domain = self.reverse_domains.get(code, None) def __repr__(self): return "{}".format(self.code) def __str__(self): return "{} [{}]".format(self.domain, self.code) def __eq__(self, val): return self.code == val class LibvirtError: params = ( "code", "domain", "message", "level", "str1", "str2", "str3", "int1", "int2", ) def __init__(self, code, domain, message, level, str1, str2, str3, int1, int2): self.code = LibvirtErrorCode(code) self.domain = LibvirtErrorDomain(domain) self.message = message self.level = level self.str1 = str1 self.str2 = str2 self.str3 = str3 self.int1 = int1 self.int2 = int2 def __repr__(self): out = "{}(".format(self.__class__.__name__) for param in self.__class__.params: out += "{}={}, ".format(param, getattr(self, param)) out += ")" return out def __str__(self): return "Libvirt error {}, domain {}. {}".format( self.code, self.domain, self.message ) @property def loglevel(self): levelmap = { 0: logging.INFO, 1: logging.WARNING, 2: logging.ERROR, } return levelmap.get(self.level, logging.CRITICAL) def libvirt_error_handler(_, raw_error): """ Called upon libvirt error """ error = LibvirtError(*raw_error) loglevel = error.loglevel if error.code == libvirt.VIR_ERR_NO_DOMAIN: loglevel = logging.DEBUG logger.log(loglevel, str(error))