Commit 10b49dae authored by Anael Beutot's avatar Anael Beutot
Browse files

Implemented disk related tags for VMs.

parent 09557c17
Loading
Loading
Loading
Loading
+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

@@ -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
@@ -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:]
+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
@@ -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):
@@ -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
+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."""
@@ -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_():