import logging import libvirt from ccnode.host import Handler as HostHandler from ccnode.tags import tag_inspector, get_tags from ccnode.hypervisor import tags from ccnode.hypervisor import lib as _libvirt from ccnode.hypervisor.lib import EVENTS, EventLoop from ccnode.hypervisor.domains import VirtualMachine logger = logging.getLogger(__name__) class Handler(HostHandler): def __init__(self, *args, **kwargs): """ :param proxy: sjRpc proxy """ HostHandler.__init__(self, *args, **kwargs) for t in tag_inspector(tags): self.tags[t.name] = t # set tag hv # self.tags['hv'] = Tag('hv', ) # initialize hypervisor instance global hypervisor if hypervisor is None: hypervisor = Hypervisor() # register domains proxy = kwargs.pop('proxy') for dom in hypervisor.domains.itervalues(): name = dom.name logger.debug(u'Registered domain %s' % name) proxy.register(name, 'vm') def sub_tags(self, sub_id, tags=None, noresolve_tags=None): """Get subtags.""" global hypervisor domain = hypervisor.get_domain_by_name(sub_id) if domain is None: logger.debug(u'Failed to find domain with name %s.' % sub_id) return return get_tags(domain, tags, noresolve_tags) def vm_define(self, name): pass def vm_undefine(self, name): pass def vm_export(self, name, format='xml'): pass def vm_stop(self, vm_names=None, force=False): pass def vm_start(self, vm_names=None): pass def vm_suspend(self, vm_names=None): pass def vm_resume(self, vm_names=None): pass class Hypervisor(object): """Container for all hypervisor related state.""" def __init__(self): self.event_loop = EventLoop() # This tells libvirt what event loop implementation it # should use libvirt.virEventRegisterImpl( self.event_loop.add_handle, self.event_loop.update_handle, self.event_loop.remove_handle, self.event_loop.add_timer, self.event_loop.update_timer, self.event_loop.remove_timer, ) self.event_loop.start() # TODO cleanup connection on stop _libvirt.connection = libvirt.open('qemu:///system') # currently only support KVM #: domains: vms, containers... self.domains = dict() # find defined domains for dom_name in _libvirt.connection.listDefinedDomains(): dom = _libvirt.connection.lookupByName(dom_name) self.domains[dom.UUID()] = VirtualMachine(dom) # find started domains for dom_id in _libvirt.connection.listDomainsID(): dom = _libvirt.connection.lookupByID(dom_id) self.domains[dom.UUID()] = VirtualMachine(dom) logger.debug('Domains: %s', self.domains) self.event_loop.register_callbacks(self.callback) def callback(self, conn, dom, event, detail, opaque): """Callback for libvirt event loop.""" logger.debug("myDomainEventCallback1 EVENT: Domain %s(%s) %s %d" % (dom.name(), dom.UUIDString(), EVENTS[event], detail)) event = EVENTS[event] if event == 'Added': self.domains[dom.UUID()] = VirtualMachine(dom) def get_domain_by_name(self, name): """Get a domain by name.""" for d in self.domains.itervalues(): if d.name == name: return d return None def _count_domain(self, filter=lambda d: True): count = 0 for dom in self.domains.itervalues(): if filter(dom): count += 1 return count @property def vm_started(self): """Number of VMs started.""" return self._count_domain(lambda d: d.status == 'started') @property def vm_stopped(self): """Number of VMs stopped.""" return self._count_domain(lambda d: d.status == 'stopped') @property def vm_paused(self): """Number of VMs paused.""" return self._count_domain(lambda d: d.status == 'paused') @property def vm_total(self): """Total number of VMs on the hypervisor.""" return self._count_domain() hypervisor = None