Skip to content
vm_tags.py 3.16 KiB
Newer Older
import logging
from functools import wraps
Anael Beutot's avatar
Anael Beutot committed
from xml.etree import cElementTree as et
from StringIO import StringIO

import libvirt
Anael Beutot's avatar
Anael Beutot committed
from cloudcontrol.common.client.tags import ttl, refresh
Anael Beutot's avatar
Anael Beutot committed

Anael Beutot's avatar
Anael Beutot committed

logger = logging.getLogger(__name__)


def _vir_tag(func):
    """Catches libvirt related exception.

    Decorator used for tag declarations that interacts with libvirt.

    """
    @wraps(func)
    def decorated(dom):
        if not dom.hypervisor.handler.virt_connected:
            return
        try:
Anael Beutot's avatar
Anael Beutot committed
            return func(dom)
Anael Beutot's avatar
Anael Beutot committed
        except libvirt.libvirtError as exc:
            if 'Domain not found' in str(exc):
                # sometimes, libvirt tells us too late when a domain is removed
                # we just ignore the error and remove the domain
                dom.hypervisor.vm_unregister(dom.name)
Anael Beutot's avatar
Anael Beutot committed
                return
            logger.exception('Unexpected libvirt error')
            dom.hypervisor.handler.virt_connect_restart()

    return decorated


Anael Beutot's avatar
Anael Beutot committed
def uuid(dom):
    """Unique identifier of the domain."""
    return dom.uuid


def status(dom):
    return dom.state


def hv(dom):
    #FIXME: what shoud be the value of this tag ?
    return dom.hypervisor.name


def htype(dom):
    return dom.hypervisor.type


Anael Beutot's avatar
Anael Beutot committed
def arch(dom):
    """VM CPU architecture."""
    try:
        return dict(i686='x86', x86_64='x64')[et.ElementTree().parse(
            StringIO(dom.lv_dom.XMLDesc(0))).find('os/type').get('arch')]
    except Exception:
        logger.exception('Error while get Architecture tag')


def h(dom):
    """Name of the VM."""
    return dom.name
Anael Beutot's avatar
Anael Beutot committed
def cpu(dom):
    """Number of CPU of the VM."""
    return dom.lv_dom.info()[3]


Anael Beutot's avatar
Anael Beutot committed
@ttl(10)
@refresh(5)
@_vir_tag
def cpuuse(dom):
    """Represent CPU use in percent average on 5 seconds."""
    state, _, _, vcpu, cpu_time = dom.lv_dom.info()
    if state != 1:  # if VM is not running
        return None
    old_cpu_stats = dom.cpu_stats
    dom.cpu_stats = (dom.hypervisor.handler.main.evloop.now(), cpu_time)
Anael Beutot's avatar
Anael Beutot committed
    # calculate CPU percentage, code is from virt-manager in domain.py:1210
    return '%.2f' % max(0., min(100., ((cpu_time - old_cpu_stats[1]) * 100.) / (
        (dom.cpu_stats[0] - old_cpu_stats[0]) * 1000. * 1000. * 1000.)))
Anael Beutot's avatar
Anael Beutot committed
def mem(dom):
    """Memory currently allocated."""
    return dom.lv_dom.info()[2] * 1024


Anael Beutot's avatar
Anael Beutot committed
def memmax(dom):
    """Maximum memory allocation."""
    return dom.lv_dom.info()[1] * 1024


Anael Beutot's avatar
Anael Beutot committed
def vncport(dom):
    """VNC port for the VM console access."""
    try:
        port = et.ElementTree().parse(
Anael Beutot's avatar
Anael Beutot committed
            StringIO(dom.lv_dom.XMLDesc(0))
        ).find('devices/graphics').get('port')
    except Exception:
        logger.exception('VNCPort')
    if 0 < int(port) < 65536:
        return port

    return
Anael Beutot's avatar
Anael Beutot committed
@ttl(10)
@refresh(10)
Anael Beutot's avatar
Anael Beutot committed
def disk(dom):
    """Get backend disks."""
Anael Beutot's avatar
Anael Beutot committed
    return u' '.join(map(str, xrange(len(dom.disks)))) or None
Anael Beutot's avatar
Anael Beutot committed
@ttl(10)
@refresh(10)
Anael Beutot's avatar
Anael Beutot committed
def nic(dom):
    """VM network interfaces."""
    return u' '.join(map(str, xrange(len(dom.nics)))) or None


@refresh(10)
@_vir_tag
def autostart(dom):
    """Autostart status."""
    return {True: 'yes', False: 'no'}[bool(dom.lv_dom.autostart())]