Loading ccnode/hypervisor/__init__.py +71 −0 Original line number Diff line number Diff line import logging import weakref from functools import partial from itertools import chain, imap import libvirt Loading Loading @@ -100,6 +102,12 @@ class Hypervisor(object): # TODO cleanup connection on stop _libvirt.connection = libvirt.open('qemu:///system') # currently only support KVM # findout storage self.storage = StorageIndex(_libvirt.connection) logger.debug('Storages: %s', self.storage.paths) #: domains: vms, containers... self.domains = dict() # find defined domains Loading Loading @@ -162,3 +170,66 @@ class Hypervisor(object): hypervisor = None class StorageIndex(object): """Keep an index of all storage volume paths.""" def __init__(self, lv_con): """ :param lv_con: Libvirt connection """ self.storages = dict( (s.name, s) for s in imap( Storage, imap( lv_con.storagePoolLookupByName, chain( lv_con.listDefinedStoragePools(), lv_con.listStoragePools(), ), ), ), ) self.paths = dict( (v.path, v) for v in chain.from_iterable(map( lambda s: s.volumes, self.storages.itervalues(), )), ) def get_volume(self, path): return self.paths.get(path) def get_storage(self, name): return self.Storage.get(name) class Storage(object): """Storage abstraction.""" def __init__(self, lv_storage): """ :param lv_storage: Libvirt pool storage instance """ self.uuid = lv_storage.UUID() self.name = lv_storage.name() self.volumes = map( partial(Volume, storage=self), (lv_storage.storageVolLookupByName(n) for n in lv_storage.listVolumes()), ) class Volume(object): """Volume abstraction.""" def __init__(self, lv_volume, storage): """ :param lv_volume: Libvirt volume instance :param storage: parent storage instance """ # self.storage = None if storage is None else weakref.proxy(storage) self.storage = lv_volume.storagePoolLookupByVolume().name() self.path = lv_volume.path() self.name = lv_volume.name() self.capacity, self.allocation = lv_volume.info()[1:] ccnode/hypervisor/domains/__init__.py +41 −3 Original line number Diff line number Diff line import logging import weakref from StringIO import StringIO from xml.etree import cElementTree as et from ccnode.tags import tag_inspector from ccnode.tags import Tag, tag_inspector from ccnode.hypervisor import lib as _libvirt from ccnode.hypervisor.lib import DOMAIN_STATES as STATE from ccnode.hypervisor.domains import vm_tags Loading @@ -17,15 +19,28 @@ class VirtualMachine(object): :param dom: libvirt domain instance :param hypervisor: hypervisor where the VM is """ self.hypervisor = weakref.proxy(hypervisor) #: UUID string of domain self.uuid = dom.UUIDString() #: state of VM: started, stoped, paused self.state = STATE[dom.info()[0]] #: tags for this VM self.tags = dict((t.name, t) for t in tag_inspector(vm_tags, self)) logger.debug(self.tags) # define dynamic tags i = 0 for v in self.iter_disks(): for t in ( Tag('disk%s_size' % i, v.capacity), Tag('disk%s_path' % i, v.path), Tag('disk%s_pool' % i, v.storage), # FIXME: change Tag('disk%s_vol' % i, v.name), ): self.tags[t.name] = t self.hypervisor = weakref.proxy(hypervisor) i += 1 logger.debug(self.tags) @property def name(self): Loading @@ -50,3 +65,26 @@ class VirtualMachine(object): def undefined(): pass @property def disks(self): return list(self.iter_disks()) def iter_disks(self): for d in et.ElementTree().parse( StringIO(self.lv_dom.XMLDesc(0)) ).findall('devices/disk'): if d.get('device') != 'disk': continue type_ = d.get('type') if type_ not in ('file', 'block'): continue path = d.find('source').get(dict(file='file', block='dev')[type_]) volume = self.hypervisor.storage.get_volume(path) if volume is None: continue yield volume ccnode/hypervisor/domains/vm_tags.py +1 −17 Original line number Diff line number Diff line from xml.etree import cElementTree as et from StringIO import StringIO from ccnode.tags import DynamicTags def uuid(dom): """Unique identifier of the domain.""" Loading Loading @@ -71,21 +69,7 @@ status.ttl = 1 def disk(dom): """Get backend disks.""" try: return et.ElementTree().parse( StringIO(dom.lv_dom.XMLDesc(0)) ).find('devices/disk').get('port') except Exception: logger.exception('VNCPort') class Disks(DynamicTags): def __init__(self): for d in et.ElementTree().parse( StringIO(dom.lv_dom.XMLDesc(0)) ).findall('devices/disk'): # self.disks[] = plop pass return u' '.join(map(str, xrange(len(dom.disks)))) def nic_(): Loading Loading
ccnode/hypervisor/__init__.py +71 −0 Original line number Diff line number Diff line import logging import weakref from functools import partial from itertools import chain, imap import libvirt Loading Loading @@ -100,6 +102,12 @@ class Hypervisor(object): # TODO cleanup connection on stop _libvirt.connection = libvirt.open('qemu:///system') # currently only support KVM # findout storage self.storage = StorageIndex(_libvirt.connection) logger.debug('Storages: %s', self.storage.paths) #: domains: vms, containers... self.domains = dict() # find defined domains Loading Loading @@ -162,3 +170,66 @@ class Hypervisor(object): hypervisor = None class StorageIndex(object): """Keep an index of all storage volume paths.""" def __init__(self, lv_con): """ :param lv_con: Libvirt connection """ self.storages = dict( (s.name, s) for s in imap( Storage, imap( lv_con.storagePoolLookupByName, chain( lv_con.listDefinedStoragePools(), lv_con.listStoragePools(), ), ), ), ) self.paths = dict( (v.path, v) for v in chain.from_iterable(map( lambda s: s.volumes, self.storages.itervalues(), )), ) def get_volume(self, path): return self.paths.get(path) def get_storage(self, name): return self.Storage.get(name) class Storage(object): """Storage abstraction.""" def __init__(self, lv_storage): """ :param lv_storage: Libvirt pool storage instance """ self.uuid = lv_storage.UUID() self.name = lv_storage.name() self.volumes = map( partial(Volume, storage=self), (lv_storage.storageVolLookupByName(n) for n in lv_storage.listVolumes()), ) class Volume(object): """Volume abstraction.""" def __init__(self, lv_volume, storage): """ :param lv_volume: Libvirt volume instance :param storage: parent storage instance """ # self.storage = None if storage is None else weakref.proxy(storage) self.storage = lv_volume.storagePoolLookupByVolume().name() self.path = lv_volume.path() self.name = lv_volume.name() self.capacity, self.allocation = lv_volume.info()[1:]
ccnode/hypervisor/domains/__init__.py +41 −3 Original line number Diff line number Diff line import logging import weakref from StringIO import StringIO from xml.etree import cElementTree as et from ccnode.tags import tag_inspector from ccnode.tags import Tag, tag_inspector from ccnode.hypervisor import lib as _libvirt from ccnode.hypervisor.lib import DOMAIN_STATES as STATE from ccnode.hypervisor.domains import vm_tags Loading @@ -17,15 +19,28 @@ class VirtualMachine(object): :param dom: libvirt domain instance :param hypervisor: hypervisor where the VM is """ self.hypervisor = weakref.proxy(hypervisor) #: UUID string of domain self.uuid = dom.UUIDString() #: state of VM: started, stoped, paused self.state = STATE[dom.info()[0]] #: tags for this VM self.tags = dict((t.name, t) for t in tag_inspector(vm_tags, self)) logger.debug(self.tags) # define dynamic tags i = 0 for v in self.iter_disks(): for t in ( Tag('disk%s_size' % i, v.capacity), Tag('disk%s_path' % i, v.path), Tag('disk%s_pool' % i, v.storage), # FIXME: change Tag('disk%s_vol' % i, v.name), ): self.tags[t.name] = t self.hypervisor = weakref.proxy(hypervisor) i += 1 logger.debug(self.tags) @property def name(self): Loading @@ -50,3 +65,26 @@ class VirtualMachine(object): def undefined(): pass @property def disks(self): return list(self.iter_disks()) def iter_disks(self): for d in et.ElementTree().parse( StringIO(self.lv_dom.XMLDesc(0)) ).findall('devices/disk'): if d.get('device') != 'disk': continue type_ = d.get('type') if type_ not in ('file', 'block'): continue path = d.find('source').get(dict(file='file', block='dev')[type_]) volume = self.hypervisor.storage.get_volume(path) if volume is None: continue yield volume
ccnode/hypervisor/domains/vm_tags.py +1 −17 Original line number Diff line number Diff line from xml.etree import cElementTree as et from StringIO import StringIO from ccnode.tags import DynamicTags def uuid(dom): """Unique identifier of the domain.""" Loading Loading @@ -71,21 +69,7 @@ status.ttl = 1 def disk(dom): """Get backend disks.""" try: return et.ElementTree().parse( StringIO(dom.lv_dom.XMLDesc(0)) ).find('devices/disk').get('port') except Exception: logger.exception('VNCPort') class Disks(DynamicTags): def __init__(self): for d in et.ElementTree().parse( StringIO(dom.lv_dom.XMLDesc(0)) ).findall('devices/disk'): # self.disks[] = plop pass return u' '.join(map(str, xrange(len(dom.disks)))) def nic_(): Loading