def wrapper(*args, **kwargs): try: ret = f(*args, **kwargs) if isinstance(ret, libvirt.virDomain): for name in dir(ret): method = getattr(ret, name) if callable(method) and name[0] != '_': setattr(ret, name, wrapMethod(function.weakmethod(method))) return ret except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() EDOMAINS = (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC) ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR, libvirt.VIR_ERR_NO_CONNECT, libvirt.VIR_ERR_INVALID_CONN) if edom in EDOMAINS and ecode in ECODES: try: __connections.get(id(target)).pingLibvirt() except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() if edom in EDOMAINS and ecode in ECODES: log.warning( 'connection to libvirt broken.' ' ecode: %d edom: %d', ecode, edom) if killOnFailure: log.critical('taking calling process down.') os.kill(os.getpid(), signal.SIGTERM) else: raise raise
def test_raise_on_invalid_weakref(self): obj = ObjectWithDel() method = function.weakmethod(obj.public) obj.public = method self.assertEqual(obj.public(), ("public", (), {})) del obj self.assertRaises(function.InvalidatedWeakRef, method)
def test_without_reference_cycle(self): obj = ObjectWithDel() obj.public = function.weakmethod(obj.public) self.assertEqual(obj.public(), ("public", (), {})) del obj gc.collect() self.assertNotIn(ObjectWithDel, [type(obj) for obj in gc.garbage])
def wrapper(*args, **kwargs): try: ret = f(*args, **kwargs) if isinstance(ret, libvirt.virDomain): for name in dir(ret): method = getattr(ret, name) if callable(method) and name[0] != '_': setattr(ret, name, wrapMethod(function.weakmethod(method))) return ret except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() EDOMAINS = (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC) ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR, libvirt.VIR_ERR_NO_CONNECT, libvirt.VIR_ERR_INVALID_CONN) if edom in EDOMAINS and ecode in ECODES: try: __connections.get(id(target)).pingLibvirt() except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() if edom in EDOMAINS and ecode in ECODES: log.warning('connection to libvirt broken.' ' ecode: %d edom: %d', ecode, edom) if killOnFailure: log.critical('taking calling process down.') os.kill(os.getpid(), signal.SIGTERM) else: raise raise
def test_raise_on_invalid_weakref(self): obj = ObjectWithDel() method = function.weakmethod(obj.public) obj.public = method self.assertEqual(obj.public(), ("public", (), {})) del obj self.assertRaises(function.InvalidatedWeakRef, method)
def test_without_reference_cycle(self): obj = ObjectWithDel() obj.public = function.weakmethod(obj.public) self.assertEqual(obj.public(), ("public", (), {})) del obj gc.collect() self.assertNotIn(ObjectWithDel, [type(obj) for obj in gc.garbage])
def get(target=None, killOnFailure=True): """Return current connection to libvirt or open a new one. Use target to get/create the connection object linked to that object. target must have a callable attribute named 'dispatchLibvirtEvents' which will be registered as a callback on libvirt events. Wrap methods of connection object so that they catch disconnection, and take the current process down. """ def wrapMethod(f): @functools.wraps(f) def wrapper(*args, **kwargs): try: ret = f(*args, **kwargs) if isinstance(ret, libvirt.virDomain): for name in dir(ret): method = getattr(ret, name) if callable(method) and name[0] != '_': setattr(ret, name, wrapMethod(function.weakmethod(method))) return ret except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() EDOMAINS = (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC) ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR, libvirt.VIR_ERR_NO_CONNECT, libvirt.VIR_ERR_INVALID_CONN) if edom in EDOMAINS and ecode in ECODES: try: __connections.get(id(target)).pingLibvirt() except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() if edom in EDOMAINS and ecode in ECODES: log.warning( 'connection to libvirt broken.' ' ecode: %d edom: %d', ecode, edom) if killOnFailure: log.critical('taking calling process down.') os.kill(os.getpid(), signal.SIGTERM) else: raise raise return wrapper with __connectionLock: conn = __connections.get(id(target)) if not conn: log.debug('trying to connect libvirt') password = ProtectedPassword(libvirt_password()) conn = open_connection('qemu:///system', SASL_USERNAME, password) __connections[id(target)] = conn setattr(conn, 'pingLibvirt', getattr(conn, 'getLibVersion')) for name in dir(libvirt.virConnect): method = getattr(conn, name) if callable(method) and name[0] != '_': setattr(conn, name, wrapMethod(function.weakmethod(method))) if target is not None: for ev in (libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, libvirt.VIR_DOMAIN_EVENT_ID_REBOOT, libvirt.VIR_DOMAIN_EVENT_ID_RTC_CHANGE, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, libvirt.VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD): conn.domainEventRegisterAny(None, ev, target.dispatchLibvirtEvents, ev) # In case we're running into troubles with keeping the connections # alive we should place here: # conn.setKeepAlive(interval=5, count=3) # However the values need to be considered wisely to not affect # hosts which are hosting a lot of virtual machines return conn
def get(target=None, killOnFailure=True): """Return current connection to libvirt or open a new one. Use target to get/create the connection object linked to that object. target must have a callable attribute named 'dispatchLibvirtEvents' which will be registered as a callback on libvirt events. Wrap methods of connection object so that they catch disconnection, and take the current process down. """ def wrapMethod(f): @functools.wraps(f) def wrapper(*args, **kwargs): try: ret = f(*args, **kwargs) if isinstance(ret, libvirt.virDomain): for name in dir(ret): method = getattr(ret, name) if callable(method) and name[0] != '_': setattr(ret, name, wrapMethod(function.weakmethod(method))) return ret except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() EDOMAINS = (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC) ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR, libvirt.VIR_ERR_NO_CONNECT, libvirt.VIR_ERR_INVALID_CONN) if edom in EDOMAINS and ecode in ECODES: try: __connections.get(id(target)).pingLibvirt() except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() if edom in EDOMAINS and ecode in ECODES: log.warning('connection to libvirt broken.' ' ecode: %d edom: %d', ecode, edom) if killOnFailure: log.critical('taking calling process down.') os.kill(os.getpid(), signal.SIGTERM) else: raise raise return wrapper with __connectionLock: conn = __connections.get(id(target)) if not conn: log.debug('trying to connect libvirt') password = ProtectedPassword(libvirt_password()) conn = open_connection('qemu:///system', SASL_USERNAME, password) __connections[id(target)] = conn setattr(conn, 'pingLibvirt', getattr(conn, 'getLibVersion')) for name in dir(libvirt.virConnect): method = getattr(conn, name) if callable(method) and name[0] != '_': setattr(conn, name, wrapMethod(function.weakmethod(method))) if target is not None: for ev in (libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, libvirt.VIR_DOMAIN_EVENT_ID_REBOOT, libvirt.VIR_DOMAIN_EVENT_ID_RTC_CHANGE, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, libvirt.VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD): conn.domainEventRegisterAny(None, ev, target.dispatchLibvirtEvents, ev) # In case we're running into troubles with keeping the connections # alive we should place here: # conn.setKeepAlive(interval=5, count=3) # However the values need to be considered wisely to not affect # hosts which are hosting a lot of virtual machines return conn