Newer
Older
# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl. If not, see <http://www.gnu.org/licenses/>.
import logging
from functools import wraps
from xml.etree import cElementTree as et
from StringIO import StringIO
from cloudcontrol.node.utils import execute
from cloudcontrol.common.client.tags import ttl, refresh, background
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:
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
logger.exception('Unexpected libvirt error')
dom.hypervisor.handler.virt_connect_restart()
return decorated
def uuid(dom):
"""Unique identifier of the domain."""
Antoine Millet
committed
@background(max_concurrent=3)
def rescue(dom):
"""Is rescue mode enabled or not"""
rescue_path = dom.hypervisor.handler.main.config.rescue_script
rcode, output = execute(dom.hypervisor.handler.main, [rescue_path, '-s', dom.name])
if rcode == 0:
return output.strip()
else:
return 'error'
def status(dom):
return dom.state
def hv(dom):
return dom.hypervisor.name
def htype(dom):
return dom.hypervisor.type
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
def t(dom):
"""Title of the VM (or name if title is not defined)."""
if dom.title is None:
return dom.name
else:
return dom.title
def cpu(dom):
"""Number of CPU of the VM."""
return dom.lv_dom.info()[3]
@_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)
# 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.) / vcpu))
if dom.state == 'stopped':
return dom.lv_dom.info()[1] * 1024
else:
return dom.lv_dom.info()[2] * 1024
def memmax(dom):
"""Maximum memory allocation."""
return dom.lv_dom.info()[1] * 1024
def vncport(dom):
"""VNC port for the VM console access."""
try:
).find('devices/graphics[@type="vnc"]').get('port')
try:
if 0 < int(port) < 65536:
return port
except (TypeError, ValueError):
pass
@_vir_tag
def spiceport(dom):
"""Spice port for the VM console access."""
try:
port = et.ElementTree().parse(
StringIO(dom.lv_dom.XMLDesc(0))
).find('devices/graphics[@type="spice"]').get('port')
except Exception:
logger.exception('SpicePort')
raise
try:
if 0 < int(port) < 65536:
return port
except (TypeError, ValueError):
pass
return
return u' '.join(map(str, xrange(len(dom.disks)))) or None
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())]