2006-06-28 15:50:17 -04:00
|
|
|
#
|
|
|
|
|
# Copyright (C) 2006 Red Hat, Inc.
|
|
|
|
|
# Copyright (C) 2006 Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
|
#
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program 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 General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
|
# along with this program; if not, write to the Free Software
|
2007-11-20 11:12:20 -05:00
|
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
|
# MA 02110-1301 USA.
|
2006-06-28 15:50:17 -04:00
|
|
|
#
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-06-14 13:52:46 -04:00
|
|
|
import gobject
|
2010-01-06 13:09:33 -05:00
|
|
|
import gtk
|
|
|
|
|
|
2006-10-25 12:18:06 -04:00
|
|
|
import logging
|
2010-12-10 11:47:07 -05:00
|
|
|
import os
|
|
|
|
|
import sys
|
2007-04-10 18:27:37 -04:00
|
|
|
import traceback
|
2010-01-06 13:09:33 -05:00
|
|
|
import re
|
|
|
|
|
import threading
|
2006-06-14 17:52:49 -04:00
|
|
|
from time import time
|
2006-11-06 10:34:54 -05:00
|
|
|
from socket import gethostbyaddr, gethostname
|
2010-01-06 13:09:33 -05:00
|
|
|
|
2007-03-30 15:01:41 -04:00
|
|
|
import dbus
|
2010-01-06 13:09:33 -05:00
|
|
|
import libvirt
|
2008-02-22 11:48:29 -05:00
|
|
|
import virtinst
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2009-07-11 21:23:16 -04:00
|
|
|
from virtManager import util
|
2006-06-14 17:52:49 -04:00
|
|
|
from virtManager.domain import vmmDomain
|
2007-03-21 12:28:36 -04:00
|
|
|
from virtManager.network import vmmNetwork
|
2008-08-07 17:37:16 -04:00
|
|
|
from virtManager.storagepool import vmmStoragePool
|
2009-11-19 17:35:27 -05:00
|
|
|
from virtManager.interface import vmmInterface
|
2009-11-25 17:07:12 -05:00
|
|
|
from virtManager.netdev import vmmNetDevice
|
2009-11-30 16:16:43 -05:00
|
|
|
from virtManager.mediadev import vmmMediaDevice
|
2010-12-09 12:37:48 -05:00
|
|
|
from virtManager.baseclass import vmmGObject
|
2011-04-09 19:32:30 -04:00
|
|
|
from virtManager.nodedev import vmmNodeDevice
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2010-12-09 12:37:48 -05:00
|
|
|
class vmmConnection(vmmGObject):
|
2006-06-14 13:52:46 -04:00
|
|
|
__gsignals__ = {
|
|
|
|
|
"vm-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
2006-06-14 17:52:49 -04:00
|
|
|
[str, str]),
|
2006-06-14 13:52:46 -04:00
|
|
|
"vm-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
2006-06-14 17:52:49 -04:00
|
|
|
[str, str]),
|
2009-11-19 17:35:27 -05:00
|
|
|
|
2007-03-29 21:22:31 -04:00
|
|
|
"net-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"net-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
2007-04-03 14:01:45 -04:00
|
|
|
"net-started": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"net-stopped": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
2009-11-19 17:35:27 -05:00
|
|
|
|
2008-08-07 17:37:16 -04:00
|
|
|
"pool-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"pool-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"pool-started": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"pool-stopped": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
2009-11-19 17:35:27 -05:00
|
|
|
|
|
|
|
|
"interface-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"interface-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"interface-started": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"interface-stopped": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
|
2009-11-25 14:50:27 -05:00
|
|
|
"nodedev-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
"nodedev-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str, str]),
|
|
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
"mediadev-added": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
2009-11-30 11:56:41 -05:00
|
|
|
[object]),
|
2009-12-10 20:04:26 -05:00
|
|
|
"mediadev-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
2009-11-30 11:56:41 -05:00
|
|
|
[str]),
|
|
|
|
|
|
2007-03-27 19:52:00 -04:00
|
|
|
"resources-sampled": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[]),
|
2007-09-09 22:57:24 -04:00
|
|
|
"state-changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[]),
|
2007-09-10 20:56:01 -04:00
|
|
|
"connect-error": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
|
|
|
|
[str]),
|
2006-06-14 13:52:46 -04:00
|
|
|
}
|
|
|
|
|
|
2007-09-09 22:57:24 -04:00
|
|
|
STATE_DISCONNECTED = 0
|
|
|
|
|
STATE_CONNECTING = 1
|
|
|
|
|
STATE_ACTIVE = 2
|
|
|
|
|
STATE_INACTIVE = 3
|
|
|
|
|
|
2010-12-09 14:06:00 -05:00
|
|
|
def __init__(self, uri, readOnly=False):
|
2010-12-09 12:37:48 -05:00
|
|
|
vmmGObject.__init__(self)
|
2009-07-01 14:59:13 -04:00
|
|
|
|
2007-09-10 20:56:01 -04:00
|
|
|
self.connectThread = None
|
|
|
|
|
self.connectError = None
|
2007-09-09 22:57:24 -04:00
|
|
|
self.uri = uri
|
|
|
|
|
if self.uri is None or self.uri.lower() == "xen":
|
|
|
|
|
self.uri = "xen:///"
|
2007-04-12 19:43:31 -04:00
|
|
|
|
2008-02-23 15:38:32 -05:00
|
|
|
self.readOnly = readOnly
|
2007-09-09 22:57:24 -04:00
|
|
|
self.state = self.STATE_DISCONNECTED
|
|
|
|
|
self.vmm = None
|
2009-11-19 17:38:43 -05:00
|
|
|
|
2010-02-10 17:05:56 -05:00
|
|
|
self._caps = None
|
|
|
|
|
self._caps_xml = None
|
|
|
|
|
|
2009-11-19 17:38:43 -05:00
|
|
|
self.network_capable = None
|
2011-04-07 17:57:19 -04:00
|
|
|
self._storage_capable = None
|
2009-11-19 17:35:27 -05:00
|
|
|
self.interface_capable = None
|
2009-11-25 14:50:27 -05:00
|
|
|
self._nodedev_capable = None
|
2010-02-25 19:35:01 -05:00
|
|
|
|
|
|
|
|
self._xml_flags = {}
|
2010-05-12 12:57:32 -04:00
|
|
|
self._support_dict = {}
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2009-11-25 14:50:27 -05:00
|
|
|
# Physical network interfaces: name -> virtinst.NodeDevice
|
|
|
|
|
self.nodedevs = {}
|
2009-11-25 16:12:03 -05:00
|
|
|
# Physical network interfaces: name (eth0) -> vmmNetDevice
|
|
|
|
|
self.netdevs = {}
|
2009-11-30 11:56:41 -05:00
|
|
|
# Physical media devices: vmmMediaDevice.key -> vmmMediaDevice
|
2009-12-10 20:04:26 -05:00
|
|
|
self.mediadevs = {}
|
2009-11-19 17:35:27 -05:00
|
|
|
# Connection Storage pools: name -> vmmInterface
|
|
|
|
|
self.interfaces = {}
|
2008-08-07 17:37:16 -04:00
|
|
|
# Connection Storage pools: UUID -> vmmStoragePool
|
|
|
|
|
self.pools = {}
|
2007-09-09 22:57:24 -04:00
|
|
|
# Virtual networks UUUID -> vmmNetwork object
|
2007-03-21 12:28:36 -04:00
|
|
|
self.nets = {}
|
2007-09-09 22:57:24 -04:00
|
|
|
# Virtual machines. UUID -> vmmDomain object
|
2006-06-14 10:59:40 -04:00
|
|
|
self.vms = {}
|
2007-09-09 22:57:24 -04:00
|
|
|
# Resource utilization statistics
|
2007-03-27 19:52:00 -04:00
|
|
|
self.record = []
|
2007-09-09 22:57:24 -04:00
|
|
|
self.hostinfo = None
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2009-11-30 11:56:41 -05:00
|
|
|
self.hal_helper_remove_sig = None
|
2011-04-13 09:27:02 -04:00
|
|
|
self.hal_handles = []
|
2009-11-30 16:25:39 -05:00
|
|
|
|
2009-11-25 17:07:12 -05:00
|
|
|
self.netdev_initialized = False
|
|
|
|
|
self.netdev_error = ""
|
|
|
|
|
self.netdev_use_libvirt = False
|
2009-11-25 16:12:03 -05:00
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
self.mediadev_initialized = False
|
|
|
|
|
self.mediadev_error = ""
|
|
|
|
|
self.mediadev_use_libvirt = False
|
2009-03-09 16:21:32 -04:00
|
|
|
|
2009-11-25 17:07:12 -05:00
|
|
|
#################
|
|
|
|
|
# Init routines #
|
|
|
|
|
#################
|
|
|
|
|
|
2009-11-30 13:05:35 -05:00
|
|
|
def _set_hal_remove_sig(self, hal_helper):
|
2009-11-30 11:56:41 -05:00
|
|
|
if not self.hal_helper_remove_sig:
|
2009-11-30 13:05:35 -05:00
|
|
|
sig = hal_helper.connect("device-removed",
|
|
|
|
|
self._haldev_removed)
|
2009-11-30 11:56:41 -05:00
|
|
|
self.hal_helper_remove_sig = sig
|
2011-04-13 09:27:02 -04:00
|
|
|
self.hal_handles.append(sig)
|
2009-11-30 11:56:41 -05:00
|
|
|
|
2009-11-25 17:07:12 -05:00
|
|
|
def _init_netdev(self):
|
|
|
|
|
"""
|
|
|
|
|
Determine how we will be polling for net devices (HAL or libvirt)
|
|
|
|
|
"""
|
2011-04-09 21:51:50 -04:00
|
|
|
if self.is_nodedev_capable() and self.is_interface_capable():
|
2009-11-25 17:07:12 -05:00
|
|
|
try:
|
|
|
|
|
self._build_libvirt_netdev_list()
|
|
|
|
|
self.netdev_use_libvirt = True
|
|
|
|
|
except Exception, e:
|
2009-12-09 10:58:47 -05:00
|
|
|
self.netdev_error = _("Could not build physical interface "
|
2009-11-25 17:07:12 -05:00
|
|
|
"list via libvirt: %s") % str(e)
|
2009-11-30 13:05:35 -05:00
|
|
|
elif self.get_hal_helper():
|
|
|
|
|
hal_helper = self.get_hal_helper()
|
|
|
|
|
|
2009-11-25 17:07:12 -05:00
|
|
|
if self.is_remote():
|
|
|
|
|
self.netdev_error = _("Libvirt version does not support "
|
|
|
|
|
"physical interface listing")
|
|
|
|
|
|
|
|
|
|
else:
|
2009-11-30 13:05:35 -05:00
|
|
|
error = hal_helper.get_init_error()
|
2009-11-25 17:07:12 -05:00
|
|
|
if not error:
|
2011-04-13 09:27:02 -04:00
|
|
|
self.hal_handles.append(
|
|
|
|
|
hal_helper.connect("netdev-added", self._netdev_added))
|
2009-11-30 13:05:35 -05:00
|
|
|
self._set_hal_remove_sig(hal_helper)
|
2009-11-30 11:56:41 -05:00
|
|
|
|
2009-11-25 17:07:12 -05:00
|
|
|
else:
|
|
|
|
|
self.netdev_error = _("Could not initialize HAL for "
|
|
|
|
|
"interface listing: %s") % error
|
|
|
|
|
else:
|
|
|
|
|
self.netdev_error = _("Libvirt version does not support "
|
2009-11-30 11:56:41 -05:00
|
|
|
"physical interface listing.")
|
2009-11-25 17:07:12 -05:00
|
|
|
|
|
|
|
|
self.netdev_initialized = True
|
|
|
|
|
if self.netdev_error:
|
|
|
|
|
logging.debug(self.netdev_error)
|
|
|
|
|
else:
|
|
|
|
|
if self.netdev_use_libvirt:
|
|
|
|
|
logging.debug("Using libvirt API for netdev enumeration")
|
|
|
|
|
else:
|
|
|
|
|
logging.debug("Using HAL for netdev enumeration")
|
|
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
def _init_mediadev(self):
|
2009-11-30 16:16:43 -05:00
|
|
|
if self.is_nodedev_capable():
|
|
|
|
|
try:
|
2009-12-10 20:04:26 -05:00
|
|
|
self.connect("nodedev-added", self._nodedev_mediadev_added)
|
|
|
|
|
self.connect("nodedev-removed", self._nodedev_mediadev_removed)
|
|
|
|
|
self.mediadev_use_libvirt = True
|
2009-11-30 16:16:43 -05:00
|
|
|
except Exception, e:
|
2009-12-10 20:04:26 -05:00
|
|
|
self.mediadev_error = _("Could not build media "
|
|
|
|
|
"list via libvirt: %s") % str(e)
|
2009-11-30 16:16:43 -05:00
|
|
|
|
|
|
|
|
elif self.get_hal_helper():
|
2009-11-30 13:05:35 -05:00
|
|
|
hal_helper = self.get_hal_helper()
|
|
|
|
|
|
2009-11-30 11:56:41 -05:00
|
|
|
if self.is_remote():
|
2009-12-10 20:04:26 -05:00
|
|
|
self.mediadev_error = _("Libvirt version does not support "
|
|
|
|
|
"media listing.")
|
2009-11-30 11:56:41 -05:00
|
|
|
|
|
|
|
|
else:
|
2009-11-30 13:05:35 -05:00
|
|
|
error = hal_helper.get_init_error()
|
2009-11-30 11:56:41 -05:00
|
|
|
if not error:
|
2011-04-13 09:27:02 -04:00
|
|
|
self.hal_handles.append(
|
|
|
|
|
hal_helper.connect("optical-added", self._optical_added))
|
2009-11-30 13:05:35 -05:00
|
|
|
self._set_hal_remove_sig(hal_helper)
|
2009-11-30 11:56:41 -05:00
|
|
|
|
|
|
|
|
else:
|
2009-12-10 20:04:26 -05:00
|
|
|
self.mediadev_error = _("Could not initialize HAL for "
|
|
|
|
|
"media listing: %s") % error
|
2009-11-30 11:56:41 -05:00
|
|
|
else:
|
2009-12-10 20:04:26 -05:00
|
|
|
self.mediadev_error = _("Libvirt version does not support "
|
|
|
|
|
"media listing.")
|
2009-11-30 11:56:41 -05:00
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
self.mediadev_initialized = True
|
|
|
|
|
if self.mediadev_error:
|
|
|
|
|
logging.debug(self.mediadev_error)
|
2009-11-30 11:56:41 -05:00
|
|
|
else:
|
2009-12-10 20:04:26 -05:00
|
|
|
if self.mediadev_use_libvirt:
|
|
|
|
|
logging.debug("Using libvirt API for mediadev enumeration")
|
2009-11-30 16:16:43 -05:00
|
|
|
else:
|
2009-12-10 20:04:26 -05:00
|
|
|
logging.debug("Using HAL for mediadev enumeration")
|
2009-11-25 17:07:12 -05:00
|
|
|
|
|
|
|
|
########################
|
|
|
|
|
# General data getters #
|
|
|
|
|
########################
|
2009-11-25 16:12:03 -05:00
|
|
|
|
2006-06-28 10:40:35 -04:00
|
|
|
def is_read_only(self):
|
|
|
|
|
return self.readOnly
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def get_uri(self):
|
|
|
|
|
return self.uri
|
2009-03-09 16:16:45 -04:00
|
|
|
|
2010-12-08 12:17:14 -05:00
|
|
|
def invalidate_caps(self):
|
2010-02-10 17:05:56 -05:00
|
|
|
self._caps_xml = None
|
|
|
|
|
self._caps = None
|
|
|
|
|
|
|
|
|
|
def _check_caps(self):
|
2010-12-08 12:17:14 -05:00
|
|
|
if not (self._caps_xml or self._caps):
|
|
|
|
|
self._caps_xml = self.vmm.getCapabilities()
|
|
|
|
|
self._caps = virtinst.CapabilitiesParser.parse(self._caps_xml)
|
2010-02-10 17:05:56 -05:00
|
|
|
|
2010-02-10 20:26:40 -05:00
|
|
|
def get_capabilities_xml(self):
|
2010-12-08 12:17:14 -05:00
|
|
|
if not self._caps_xml:
|
2010-02-10 20:26:40 -05:00
|
|
|
self._check_caps()
|
2010-12-08 12:17:14 -05:00
|
|
|
return self._caps_xml
|
2010-02-10 20:26:40 -05:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def get_capabilities(self):
|
2010-12-08 12:17:14 -05:00
|
|
|
if not self._caps:
|
2010-02-10 17:05:56 -05:00
|
|
|
self._check_caps()
|
2010-12-08 12:17:14 -05:00
|
|
|
return self._caps
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
def get_max_vcpus(self, _type=None):
|
|
|
|
|
return virtinst.util.get_max_vcpus(self.vmm, _type)
|
|
|
|
|
|
|
|
|
|
def get_host_info(self):
|
|
|
|
|
return self.hostinfo
|
|
|
|
|
|
|
|
|
|
def pretty_host_memory_size(self):
|
|
|
|
|
if self.vmm is None:
|
|
|
|
|
return ""
|
2011-04-10 17:08:23 -04:00
|
|
|
return util.pretty_mem(self.host_memory_size())
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
def host_memory_size(self):
|
|
|
|
|
if self.vmm is None:
|
|
|
|
|
return 0
|
2010-12-10 11:47:07 -05:00
|
|
|
return self.hostinfo[1] * 1024
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
def host_architecture(self):
|
|
|
|
|
if self.vmm is None:
|
|
|
|
|
return ""
|
|
|
|
|
return self.hostinfo[0]
|
|
|
|
|
|
|
|
|
|
def host_active_processor_count(self):
|
|
|
|
|
if self.vmm is None:
|
|
|
|
|
return 0
|
|
|
|
|
return self.hostinfo[2]
|
|
|
|
|
|
|
|
|
|
def host_maximum_processor_count(self):
|
|
|
|
|
if self.vmm is None:
|
|
|
|
|
return 0
|
|
|
|
|
return (self.hostinfo[4] * self.hostinfo[5] *
|
|
|
|
|
self.hostinfo[6] * self.hostinfo[7])
|
|
|
|
|
|
2009-11-30 11:56:41 -05:00
|
|
|
def connect(self, name, callback, *args):
|
2011-04-11 13:06:59 -04:00
|
|
|
handle_id = vmmGObject.connect(self, name, callback, *args)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
if name == "vm-added":
|
|
|
|
|
for uuid in self.vms.keys():
|
|
|
|
|
self.emit("vm-added", self.uri, uuid)
|
2009-12-10 20:04:26 -05:00
|
|
|
elif name == "mediadev-added":
|
|
|
|
|
for dev in self.mediadevs.values():
|
|
|
|
|
self.emit("mediadev-added", dev)
|
2009-11-30 16:16:43 -05:00
|
|
|
elif name == "nodedev-added":
|
|
|
|
|
for key in self.nodedevs.keys():
|
|
|
|
|
self.emit("nodedev-added", self.get_uri(), key)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
return handle_id
|
|
|
|
|
|
|
|
|
|
##########################
|
|
|
|
|
# URI + hostname helpers #
|
|
|
|
|
##########################
|
2009-11-15 15:17:03 -05:00
|
|
|
|
|
|
|
|
def get_qualified_hostname(self):
|
2009-11-15 20:54:55 -05:00
|
|
|
if virtinst.support.check_conn_support(self.vmm,
|
|
|
|
|
virtinst.support.SUPPORT_CONN_GETHOSTNAME):
|
2009-11-15 15:17:03 -05:00
|
|
|
return self.vmm.getHostname()
|
|
|
|
|
|
|
|
|
|
uri_hostname = self.get_uri_hostname()
|
|
|
|
|
if self.is_remote() and uri_hostname.lower() != "localhost":
|
|
|
|
|
return uri_hostname
|
|
|
|
|
|
|
|
|
|
# This can throw an exception, so beware when calling!
|
|
|
|
|
return gethostbyaddr(gethostname())[0]
|
|
|
|
|
|
|
|
|
|
def get_uri_hostname(self):
|
|
|
|
|
return virtinst.util.get_uri_hostname(self.uri)
|
|
|
|
|
|
2007-09-09 22:57:24 -04:00
|
|
|
def get_short_hostname(self):
|
|
|
|
|
hostname = self.get_hostname()
|
|
|
|
|
offset = hostname.find(".")
|
|
|
|
|
if offset > 0 and not hostname[0].isdigit():
|
|
|
|
|
return hostname[0:offset]
|
|
|
|
|
return hostname
|
|
|
|
|
|
|
|
|
|
def get_hostname(self, resolveLocal=False):
|
2010-12-09 11:22:35 -05:00
|
|
|
ignore = resolveLocal
|
2009-11-15 15:17:03 -05:00
|
|
|
try:
|
|
|
|
|
return self.get_qualified_hostname()
|
|
|
|
|
except:
|
|
|
|
|
return self.get_uri_hostname()
|
2006-11-06 10:34:54 -05:00
|
|
|
|
2007-08-27 21:35:22 -04:00
|
|
|
def get_transport(self):
|
2008-10-30 15:35:16 -04:00
|
|
|
return virtinst.util.get_uri_transport(self.uri)
|
2007-09-09 22:57:24 -04:00
|
|
|
|
|
|
|
|
def get_driver(self):
|
2008-10-30 15:35:16 -04:00
|
|
|
return virtinst.util.get_uri_driver(self.uri)
|
2007-08-28 17:57:25 -04:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def is_local(self):
|
|
|
|
|
return bool(self.get_uri_hostname() == "localhost")
|
2009-03-13 13:13:24 -04:00
|
|
|
|
2009-11-15 15:17:03 -05:00
|
|
|
def is_xen(self):
|
|
|
|
|
scheme = virtinst.util.uri_split(self.uri)[0]
|
2010-02-10 20:26:40 -05:00
|
|
|
return scheme.startswith("xen")
|
2009-03-09 16:16:45 -04:00
|
|
|
|
2010-02-10 20:26:40 -05:00
|
|
|
def is_qemu(self):
|
|
|
|
|
scheme = virtinst.util.uri_split(self.uri)[0]
|
|
|
|
|
return scheme.startswith("qemu")
|
2009-03-09 16:16:45 -04:00
|
|
|
|
2007-08-28 17:57:25 -04:00
|
|
|
def is_remote(self):
|
2008-10-30 15:35:16 -04:00
|
|
|
return virtinst.util.is_uri_remote(self.uri)
|
2007-08-27 21:35:22 -04:00
|
|
|
|
2009-09-23 16:43:40 -04:00
|
|
|
def is_qemu_system(self):
|
|
|
|
|
(scheme, ignore, ignore,
|
|
|
|
|
path, ignore, ignore) = virtinst.util.uri_split(self.uri)
|
|
|
|
|
if path == "/system" and scheme.startswith("qemu"):
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
2008-09-22 17:50:49 +02:00
|
|
|
def is_qemu_session(self):
|
2009-03-09 16:16:45 -04:00
|
|
|
(scheme, ignore, ignore,
|
2008-11-18 14:48:10 -05:00
|
|
|
path, ignore, ignore) = virtinst.util.uri_split(self.uri)
|
2008-09-22 17:50:49 +02:00
|
|
|
if path == "/session" and scheme.startswith("qemu"):
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
2009-03-09 16:16:45 -04:00
|
|
|
def is_test_conn(self):
|
|
|
|
|
(scheme, ignore, ignore,
|
|
|
|
|
ignore, ignore, ignore) = virtinst.util.uri_split(self.uri)
|
|
|
|
|
if scheme.startswith("test"):
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
2010-12-10 18:03:51 -05:00
|
|
|
def is_session_uri(self):
|
|
|
|
|
path = virtinst.util.uri_split(self.uri)[3]
|
|
|
|
|
return path == "/session"
|
|
|
|
|
|
2010-02-10 20:26:40 -05:00
|
|
|
# Connection capabilities debug helpers
|
|
|
|
|
def is_kvm_supported(self):
|
|
|
|
|
return self.get_capabilities().is_kvm_available()
|
|
|
|
|
|
|
|
|
|
def no_install_options(self):
|
|
|
|
|
return self.get_capabilities().no_install_options()
|
|
|
|
|
|
|
|
|
|
def hw_virt_supported(self):
|
|
|
|
|
return self.get_capabilities().hw_virt_supported()
|
|
|
|
|
|
|
|
|
|
def is_bios_virt_disabled(self):
|
|
|
|
|
return self.get_capabilities().is_bios_virt_disabled()
|
|
|
|
|
|
|
|
|
|
# Connection pretty print routines
|
|
|
|
|
|
2010-12-11 23:51:20 -05:00
|
|
|
def _get_pretty_desc(self, active, shorthost, show_trans):
|
2010-01-06 13:09:33 -05:00
|
|
|
def match_whole_string(orig, reg):
|
|
|
|
|
match = re.match(reg, orig)
|
|
|
|
|
if not match:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return ((match.end() - match.start()) == len(orig))
|
|
|
|
|
|
|
|
|
|
def is_ip_addr(orig):
|
|
|
|
|
return match_whole_string(orig, "[0-9.]+")
|
|
|
|
|
|
2010-12-11 23:51:20 -05:00
|
|
|
(scheme, username, hostname,
|
2009-03-09 16:16:45 -04:00
|
|
|
path, ignore, ignore) = virtinst.util.uri_split(self.uri)
|
|
|
|
|
|
2009-07-20 14:47:50 -04:00
|
|
|
hv = ""
|
|
|
|
|
rest = ""
|
2010-12-11 23:51:20 -05:00
|
|
|
transport = ""
|
|
|
|
|
port = ""
|
|
|
|
|
if scheme.count("+"):
|
|
|
|
|
transport = scheme.split("+")[1]
|
|
|
|
|
scheme = scheme.split("+")[0]
|
2009-03-09 16:16:45 -04:00
|
|
|
|
2010-01-06 13:09:33 -05:00
|
|
|
if hostname.count(":"):
|
2010-12-11 23:51:20 -05:00
|
|
|
port = hostname.split(":")[1]
|
2010-01-06 13:09:33 -05:00
|
|
|
hostname = hostname.split(":")[0]
|
|
|
|
|
|
2009-07-28 19:21:56 -04:00
|
|
|
if hostname:
|
2010-01-06 13:09:33 -05:00
|
|
|
if shorthost and not is_ip_addr(hostname):
|
2009-07-28 19:21:56 -04:00
|
|
|
rest = hostname.split(".")[0]
|
|
|
|
|
else:
|
|
|
|
|
rest = hostname
|
|
|
|
|
else:
|
|
|
|
|
rest = "localhost"
|
|
|
|
|
|
2009-03-09 16:16:45 -04:00
|
|
|
if scheme == "qemu":
|
2009-07-20 14:47:50 -04:00
|
|
|
hv = "QEMU"
|
2009-07-28 19:21:56 -04:00
|
|
|
if active and self.is_kvm_supported():
|
|
|
|
|
hv += "/KVM"
|
2010-04-18 00:13:33 -05:00
|
|
|
elif scheme in ('esx', 'gsx'):
|
|
|
|
|
hv = scheme.upper()
|
2009-03-09 16:16:45 -04:00
|
|
|
else:
|
2009-07-20 14:47:50 -04:00
|
|
|
hv = scheme.capitalize()
|
2009-03-09 16:16:45 -04:00
|
|
|
|
2010-12-11 23:51:20 -05:00
|
|
|
if show_trans:
|
|
|
|
|
if transport:
|
|
|
|
|
hv += "+" + transport
|
|
|
|
|
if username:
|
|
|
|
|
hostname = username + "@" + hostname
|
|
|
|
|
if port:
|
|
|
|
|
hostname += ":" + port
|
|
|
|
|
|
2009-12-03 10:22:54 -05:00
|
|
|
if path and path != "/system" and path != "/":
|
2009-07-20 14:47:50 -04:00
|
|
|
if path == "/session":
|
2009-07-28 19:21:56 -04:00
|
|
|
hv += " Usermode"
|
2009-07-20 14:47:50 -04:00
|
|
|
else:
|
2009-07-28 19:21:56 -04:00
|
|
|
hv += " %s" % os.path.basename(path)
|
2009-07-20 14:47:50 -04:00
|
|
|
|
2009-07-28 19:21:56 -04:00
|
|
|
return "%s (%s)" % (rest, hv)
|
2009-07-20 14:47:50 -04:00
|
|
|
|
2010-12-11 23:51:20 -05:00
|
|
|
def get_pretty_desc_inactive(self, shorthost=True, transport=False):
|
|
|
|
|
return self._get_pretty_desc(False, shorthost, transport)
|
2009-07-20 14:47:50 -04:00
|
|
|
|
2010-12-11 23:51:20 -05:00
|
|
|
def get_pretty_desc_active(self, shorthost=True, transport=False):
|
|
|
|
|
return self._get_pretty_desc(True, shorthost, transport)
|
2009-03-09 16:16:45 -04:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
#######################
|
|
|
|
|
# API support helpers #
|
|
|
|
|
#######################
|
|
|
|
|
|
|
|
|
|
def is_storage_capable(self):
|
2011-04-07 17:57:19 -04:00
|
|
|
if self._storage_capable == None:
|
|
|
|
|
self._storage_capable = virtinst.util.is_storage_capable(self.vmm)
|
|
|
|
|
if self._storage_capable is False:
|
|
|
|
|
logging.debug("Connection doesn't seem to support storage "
|
|
|
|
|
"APIs. Skipping all storage polling.")
|
|
|
|
|
else:
|
|
|
|
|
# Try to create the default storage pool
|
|
|
|
|
try:
|
|
|
|
|
util.build_default_pool(self)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logging.debug("Building default pool failed: %s" % str(e))
|
|
|
|
|
|
|
|
|
|
return self._storage_capable
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
def is_network_capable(self):
|
|
|
|
|
if self.network_capable == None:
|
|
|
|
|
self.network_capable = virtinst.support.check_conn_support(
|
|
|
|
|
self.vmm,
|
|
|
|
|
virtinst.support.SUPPORT_CONN_NETWORK)
|
|
|
|
|
if self.network_capable is False:
|
|
|
|
|
logging.debug("Connection doesn't seem to support network "
|
|
|
|
|
"APIs. Skipping all network polling.")
|
|
|
|
|
|
|
|
|
|
return self.network_capable
|
|
|
|
|
|
|
|
|
|
def is_interface_capable(self):
|
|
|
|
|
if self.interface_capable == None:
|
|
|
|
|
self.interface_capable = virtinst.support.check_conn_support(
|
|
|
|
|
self.vmm,
|
|
|
|
|
virtinst.support.SUPPORT_CONN_INTERFACE)
|
|
|
|
|
if self.interface_capable is False:
|
|
|
|
|
logging.debug("Connection doesn't seem to support interface "
|
|
|
|
|
"APIs. Skipping all interface polling.")
|
|
|
|
|
|
|
|
|
|
return self.interface_capable
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def is_nodedev_capable(self):
|
2009-11-25 14:50:27 -05:00
|
|
|
if self._nodedev_capable == None:
|
|
|
|
|
self._nodedev_capable = virtinst.NodeDeviceParser.is_nodedev_capable(self.vmm)
|
|
|
|
|
return self._nodedev_capable
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2010-02-25 19:35:01 -05:00
|
|
|
def _get_flags_helper(self, obj, key, check_func):
|
2010-12-09 11:22:35 -05:00
|
|
|
ignore = obj
|
2010-02-25 19:35:01 -05:00
|
|
|
flags_dict = self._xml_flags.get(key)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2010-02-25 19:35:01 -05:00
|
|
|
if flags_dict == None:
|
|
|
|
|
# Flags already set
|
|
|
|
|
inact, act = check_func()
|
|
|
|
|
flags_dict = {}
|
|
|
|
|
flags_dict["active"] = act
|
|
|
|
|
flags_dict["inactive"] = inact
|
|
|
|
|
|
|
|
|
|
self._xml_flags[key] = flags_dict
|
|
|
|
|
|
|
|
|
|
active_flags = flags_dict["active"]
|
|
|
|
|
inactive_flags = flags_dict["inactive"]
|
|
|
|
|
|
|
|
|
|
return (inactive_flags, active_flags)
|
|
|
|
|
|
|
|
|
|
def get_dom_flags(self, vm):
|
|
|
|
|
key = "domain"
|
|
|
|
|
|
|
|
|
|
def check_func():
|
|
|
|
|
act = 0
|
|
|
|
|
inact = 0
|
|
|
|
|
|
|
|
|
|
if virtinst.support.check_domain_support(vm,
|
|
|
|
|
virtinst.support.SUPPORT_DOMAIN_XML_INACTIVE):
|
|
|
|
|
inact = libvirt.VIR_DOMAIN_XML_INACTIVE
|
|
|
|
|
else:
|
|
|
|
|
logging.debug("Domain XML inactive flag not supported.")
|
|
|
|
|
|
|
|
|
|
if virtinst.support.check_domain_support(vm,
|
|
|
|
|
virtinst.support.SUPPORT_DOMAIN_XML_SECURE):
|
|
|
|
|
inact |= libvirt.VIR_DOMAIN_XML_SECURE
|
|
|
|
|
act = libvirt.VIR_DOMAIN_XML_SECURE
|
|
|
|
|
else:
|
|
|
|
|
logging.debug("Domain XML secure flag not supported.")
|
|
|
|
|
|
|
|
|
|
return inact, act
|
|
|
|
|
|
|
|
|
|
return self._get_flags_helper(vm, key, check_func)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2010-05-12 12:57:32 -04:00
|
|
|
def get_dom_managedsave_supported(self, vm):
|
|
|
|
|
key = virtinst.support.SUPPORT_DOMAIN_MANAGED_SAVE
|
|
|
|
|
if key not in self._support_dict:
|
|
|
|
|
val = virtinst.support.check_domain_support(vm, key)
|
|
|
|
|
logging.debug("Connection managed save support: %s" % val)
|
|
|
|
|
self._support_dict[key] = val
|
|
|
|
|
|
|
|
|
|
return self._support_dict[key]
|
|
|
|
|
|
2010-02-25 19:35:01 -05:00
|
|
|
def get_interface_flags(self, iface):
|
|
|
|
|
key = "interface"
|
|
|
|
|
|
|
|
|
|
def check_func():
|
|
|
|
|
act = 0
|
|
|
|
|
inact = 0
|
|
|
|
|
|
|
|
|
|
if virtinst.support.check_interface_support(iface,
|
|
|
|
|
virtinst.support.SUPPORT_INTERFACE_XML_INACTIVE):
|
|
|
|
|
inact = libvirt.VIR_INTERFACE_XML_INACTIVE
|
|
|
|
|
else:
|
|
|
|
|
logging.debug("Interface XML inactive flag not supported.")
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2010-02-25 19:35:01 -05:00
|
|
|
return (inact, act)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2010-02-25 19:35:01 -05:00
|
|
|
return self._get_flags_helper(iface, key, check_func)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
###################################
|
|
|
|
|
# Connection state getter/setters #
|
|
|
|
|
###################################
|
|
|
|
|
|
|
|
|
|
def _change_state(self, newstate):
|
|
|
|
|
if self.state != newstate:
|
|
|
|
|
self.state = newstate
|
|
|
|
|
self.emit("state-changed")
|
|
|
|
|
|
|
|
|
|
def get_state(self):
|
|
|
|
|
return self.state
|
|
|
|
|
|
|
|
|
|
def get_state_text(self):
|
|
|
|
|
if self.state == self.STATE_DISCONNECTED:
|
|
|
|
|
return _("Disconnected")
|
|
|
|
|
elif self.state == self.STATE_CONNECTING:
|
|
|
|
|
return _("Connecting")
|
|
|
|
|
elif self.state == self.STATE_ACTIVE:
|
|
|
|
|
if self.is_read_only():
|
|
|
|
|
return _("Active (RO)")
|
|
|
|
|
else:
|
|
|
|
|
return _("Active")
|
|
|
|
|
elif self.state == self.STATE_INACTIVE:
|
|
|
|
|
return _("Inactive")
|
|
|
|
|
else:
|
|
|
|
|
return _("Unknown")
|
|
|
|
|
|
|
|
|
|
def pause(self):
|
|
|
|
|
if self.state != self.STATE_ACTIVE:
|
|
|
|
|
return
|
|
|
|
|
self._change_state(self.STATE_INACTIVE)
|
|
|
|
|
|
|
|
|
|
def resume(self):
|
|
|
|
|
if self.state != self.STATE_INACTIVE:
|
|
|
|
|
return
|
|
|
|
|
self._change_state(self.STATE_ACTIVE)
|
|
|
|
|
|
|
|
|
|
def is_active(self):
|
|
|
|
|
return self.state == self.STATE_ACTIVE
|
|
|
|
|
|
|
|
|
|
def is_paused(self):
|
|
|
|
|
return self.state == self.STATE_INACTIVE
|
|
|
|
|
|
|
|
|
|
def is_disconnected(self):
|
|
|
|
|
return self.state == self.STATE_DISCONNECTED
|
|
|
|
|
|
|
|
|
|
def is_connecting(self):
|
|
|
|
|
return self.state == self.STATE_CONNECTING
|
|
|
|
|
|
|
|
|
|
#################################
|
|
|
|
|
# Libvirt object lookup methods #
|
|
|
|
|
#################################
|
2006-06-14 14:36:26 -04:00
|
|
|
|
2009-11-25 17:07:12 -05:00
|
|
|
def _build_libvirt_netdev_list(self):
|
|
|
|
|
bridges = []
|
|
|
|
|
netdev_list = {}
|
|
|
|
|
|
|
|
|
|
def interface_to_netdev(interface):
|
|
|
|
|
name = interface.get_name()
|
|
|
|
|
mac = interface.get_mac()
|
|
|
|
|
is_bridge = interface.is_bridge()
|
|
|
|
|
slave_names = interface.get_slave_names()
|
|
|
|
|
|
|
|
|
|
if is_bridge and slave_names:
|
|
|
|
|
bridges.append((name, slave_names))
|
|
|
|
|
else:
|
|
|
|
|
netdev_list[name] = vmmNetDevice(name, mac, is_bridge, None)
|
|
|
|
|
|
|
|
|
|
def nodedev_to_netdev(nodedev):
|
|
|
|
|
name = nodedev.interface
|
|
|
|
|
mac = nodedev.address
|
|
|
|
|
|
|
|
|
|
if name not in netdev_list.keys():
|
|
|
|
|
netdev_list[name] = vmmNetDevice(name, mac, False, None)
|
|
|
|
|
else:
|
|
|
|
|
# Believe this info over libvirt interface APIs, since
|
|
|
|
|
# this comes from the hardware
|
|
|
|
|
if mac:
|
|
|
|
|
netdev_list[name].mac = mac
|
|
|
|
|
|
|
|
|
|
for name, iface in self.interfaces.items():
|
|
|
|
|
interface_to_netdev(iface)
|
|
|
|
|
|
2011-04-09 19:31:55 -04:00
|
|
|
for nodedev in self.get_nodedevs("net"):
|
2009-11-25 17:07:12 -05:00
|
|
|
nodedev_to_netdev(nodedev)
|
|
|
|
|
|
|
|
|
|
# Mark NetDevices as bridged where appropriate
|
|
|
|
|
for bridge_name, slave_names in bridges:
|
|
|
|
|
for name, netdev in netdev_list.items():
|
|
|
|
|
if name not in slave_names:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# XXX: Can a physical device be in two bridges?
|
|
|
|
|
netdev.bridge = bridge_name
|
|
|
|
|
netdev.shared = True
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
# XXX: How to handle added/removed signals to clients?
|
|
|
|
|
return netdev_list
|
|
|
|
|
|
2006-06-14 16:20:06 -04:00
|
|
|
def get_vm(self, uuid):
|
|
|
|
|
return self.vms[uuid]
|
2007-03-21 12:28:36 -04:00
|
|
|
def get_net(self, uuid):
|
|
|
|
|
return self.nets[uuid]
|
2007-04-10 18:27:37 -04:00
|
|
|
def get_net_device(self, path):
|
2009-11-25 16:12:03 -05:00
|
|
|
return self.netdevs[path]
|
2008-08-07 17:37:16 -04:00
|
|
|
def get_pool(self, uuid):
|
|
|
|
|
return self.pools[uuid]
|
2009-11-19 17:35:27 -05:00
|
|
|
def get_interface(self, name):
|
|
|
|
|
return self.interfaces[name]
|
2009-11-30 16:16:43 -05:00
|
|
|
def get_nodedev(self, name):
|
|
|
|
|
return self.nodedevs[name]
|
2011-04-07 18:08:29 -04:00
|
|
|
def get_nodedevs(self, devtype=None, devcap=None):
|
2009-03-09 16:20:23 -04:00
|
|
|
retdevs = []
|
2011-04-09 19:32:30 -04:00
|
|
|
for dev in self.nodedevs.values():
|
|
|
|
|
vdev = dev.get_virtinst_obj()
|
2009-11-25 14:50:27 -05:00
|
|
|
if devtype and vdev.device_type != devtype:
|
2009-03-09 16:20:23 -04:00
|
|
|
continue
|
|
|
|
|
|
2009-11-25 14:50:27 -05:00
|
|
|
if devcap:
|
|
|
|
|
if (not hasattr(vdev, "capability_type") or
|
|
|
|
|
vdev.capability_type != devcap):
|
|
|
|
|
continue
|
|
|
|
|
|
2009-03-09 16:20:23 -04:00
|
|
|
retdevs.append(vdev)
|
|
|
|
|
|
|
|
|
|
return retdevs
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def get_net_by_name(self, name):
|
|
|
|
|
for net in self.nets.values():
|
|
|
|
|
if net.get_name() == name:
|
|
|
|
|
return net
|
2009-03-08 15:31:15 -04:00
|
|
|
|
2009-03-09 16:16:45 -04:00
|
|
|
def get_pool_by_path(self, path):
|
|
|
|
|
for pool in self.pools.values():
|
|
|
|
|
if pool.get_target_path() == path:
|
|
|
|
|
return pool
|
|
|
|
|
return None
|
|
|
|
|
|
2009-03-09 16:17:09 -04:00
|
|
|
def get_pool_by_name(self, name):
|
|
|
|
|
for p in self.pools.values():
|
|
|
|
|
if p.get_name() == name:
|
|
|
|
|
return p
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def get_vol_by_path(self, path):
|
|
|
|
|
for pool in self.pools.values():
|
|
|
|
|
for vol in pool.get_volumes().values():
|
|
|
|
|
if vol.get_path() == path:
|
|
|
|
|
return vol
|
|
|
|
|
return None
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def list_vm_uuids(self):
|
|
|
|
|
return self.vms.keys()
|
|
|
|
|
def list_net_uuids(self):
|
|
|
|
|
return self.nets.keys()
|
|
|
|
|
def list_net_device_paths(self):
|
2009-11-25 17:07:12 -05:00
|
|
|
# Update netdev list
|
|
|
|
|
if self.netdev_use_libvirt:
|
|
|
|
|
self.netdevs = self._build_libvirt_netdev_list()
|
2009-11-25 16:13:46 -05:00
|
|
|
return self.netdevs.keys()
|
|
|
|
|
def list_pool_uuids(self):
|
|
|
|
|
return self.pools.keys()
|
|
|
|
|
def list_interface_names(self):
|
|
|
|
|
return self.interfaces.keys()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###################################
|
|
|
|
|
# Libvirt object creation methods #
|
|
|
|
|
###################################
|
|
|
|
|
|
|
|
|
|
def create_network(self, xml, start=True, autostart=True):
|
2009-12-11 13:45:53 -05:00
|
|
|
# Define network
|
2009-11-25 16:13:46 -05:00
|
|
|
net = self.vmm.networkDefineXML(xml)
|
2009-12-11 13:45:53 -05:00
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
if start:
|
|
|
|
|
net.create()
|
|
|
|
|
net.setAutostart(autostart)
|
|
|
|
|
except:
|
|
|
|
|
net.undefine()
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
return net
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2011-03-23 16:56:12 -04:00
|
|
|
def rename_vm(self, domainobj, origxml, newxml):
|
|
|
|
|
# Undefine old domain
|
|
|
|
|
domainobj.delete()
|
2011-03-24 13:00:36 -04:00
|
|
|
domainobj.release_handle()
|
2011-03-23 16:56:12 -04:00
|
|
|
|
|
|
|
|
newobj = None
|
|
|
|
|
try:
|
|
|
|
|
try:
|
|
|
|
|
# Redefine new domain
|
|
|
|
|
newobj = self.define_domain(newxml)
|
|
|
|
|
except Exception, renameerr:
|
|
|
|
|
try:
|
|
|
|
|
logging.exception("Error defining new name XML")
|
|
|
|
|
newobj = self.define_domain(origxml)
|
|
|
|
|
except Exception, fixerr:
|
|
|
|
|
logging.exception("Failed to redefine original domain!")
|
|
|
|
|
raise RuntimeError(
|
|
|
|
|
_("Domain rename failed. Attempting to recover also "
|
|
|
|
|
"failed.\n\n"
|
|
|
|
|
"Original error: %s\n\n"
|
|
|
|
|
"Recover error: %s" %
|
|
|
|
|
(str(renameerr), str(fixerr))))
|
|
|
|
|
raise
|
|
|
|
|
finally:
|
|
|
|
|
if newobj:
|
|
|
|
|
# Reinsert handle into new domain
|
|
|
|
|
domainobj.change_name_backend(newobj)
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def define_domain(self, xml):
|
2011-03-23 16:56:12 -04:00
|
|
|
return self.vmm.defineXML(xml)
|
2010-02-25 19:35:01 -05:00
|
|
|
def define_interface(self, xml):
|
|
|
|
|
self.vmm.interfaceDefineXML(xml, 0)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
def restore(self, frm):
|
|
|
|
|
self.vmm.restore(frm)
|
|
|
|
|
try:
|
|
|
|
|
# FIXME: This isn't correct in the remote case. Why do we even
|
|
|
|
|
# do this? Seems like we should provide an option for this
|
|
|
|
|
# to the user.
|
|
|
|
|
os.remove(frm)
|
|
|
|
|
except:
|
|
|
|
|
logging.debug("Couldn't remove save file '%s' used for restore." %
|
|
|
|
|
frm)
|
|
|
|
|
|
|
|
|
|
####################
|
|
|
|
|
# Update listeners #
|
|
|
|
|
####################
|
|
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
# Generic media device helpers
|
|
|
|
|
def _remove_mediadev(self, key):
|
2011-04-11 16:19:47 -04:00
|
|
|
self.mediadevs[key].cleanup()
|
2009-12-10 20:04:26 -05:00
|
|
|
del(self.mediadevs[key])
|
|
|
|
|
self.emit("mediadev-removed", key)
|
|
|
|
|
def _add_mediadev(self, key, dev):
|
|
|
|
|
self.mediadevs[key] = dev
|
|
|
|
|
self.emit("mediadev-added", dev)
|
2009-11-30 16:16:43 -05:00
|
|
|
|
2009-11-30 11:56:41 -05:00
|
|
|
def _haldev_removed(self, ignore, hal_path):
|
|
|
|
|
# Physical net device
|
|
|
|
|
for name, obj in self.netdevs.items():
|
|
|
|
|
if obj.get_hal_path() == hal_path:
|
2011-04-11 16:19:47 -04:00
|
|
|
self.netdevs[name].cleanup()
|
2009-11-30 11:56:41 -05:00
|
|
|
del self.netdevs[name]
|
|
|
|
|
return
|
|
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
for key, obj in self.mediadevs.items():
|
2009-11-30 16:16:43 -05:00
|
|
|
if key == hal_path:
|
2009-12-10 20:04:26 -05:00
|
|
|
self._remove_mediadev(key)
|
2009-11-30 11:56:41 -05:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def _netdev_added(self, ignore, netdev):
|
|
|
|
|
name = netdev.get_name()
|
2010-12-10 11:47:07 -05:00
|
|
|
if name in self.netdevs:
|
2009-11-30 10:12:45 -05:00
|
|
|
return
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
self.netdevs[name] = netdev
|
|
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
# Optical HAL listener
|
2009-11-30 11:56:41 -05:00
|
|
|
def _optical_added(self, ignore, dev):
|
|
|
|
|
key = dev.get_key()
|
2010-12-10 11:47:07 -05:00
|
|
|
if key in self.mediadevs:
|
2009-11-30 11:56:41 -05:00
|
|
|
return
|
2009-11-25 16:13:46 -05:00
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
self._add_mediadev(key, dev)
|
2009-11-30 16:16:43 -05:00
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
def _nodedev_mediadev_added(self, ignore1, ignore2, name):
|
2010-12-10 11:47:07 -05:00
|
|
|
if name in self.mediadevs:
|
2009-11-30 16:16:43 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
vobj = self.get_nodedev(name)
|
2011-04-09 21:56:05 -04:00
|
|
|
mediadev = vmmMediaDevice.mediadev_from_nodedev(vobj)
|
2009-11-30 16:16:43 -05:00
|
|
|
if not mediadev:
|
|
|
|
|
return
|
|
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
self._add_mediadev(name, mediadev)
|
2009-11-30 16:16:43 -05:00
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
def _nodedev_mediadev_removed(self, ignore1, ignore2, name):
|
2010-12-10 11:47:07 -05:00
|
|
|
if name not in self.mediadevs:
|
2009-11-30 16:16:43 -05:00
|
|
|
return
|
|
|
|
|
|
2009-12-10 20:04:26 -05:00
|
|
|
self._remove_mediadev(name)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
######################################
|
|
|
|
|
# Connection closing/opening methods #
|
|
|
|
|
######################################
|
|
|
|
|
|
|
|
|
|
def get_autoconnect(self):
|
2009-11-25 14:16:31 -05:00
|
|
|
return self.config.get_conn_autoconnect(self.get_uri())
|
|
|
|
|
def set_autoconnect(self, val):
|
|
|
|
|
self.config.set_conn_autoconnect(self.get_uri(), val)
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
|
if self.vmm == None:
|
|
|
|
|
return
|
|
|
|
|
|
2011-04-11 11:00:57 -04:00
|
|
|
def cleanup(devs):
|
|
|
|
|
for dev in devs.values():
|
|
|
|
|
dev.cleanup()
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
self.vmm = None
|
2011-04-11 11:00:57 -04:00
|
|
|
self.record = []
|
|
|
|
|
|
|
|
|
|
cleanup(self.nodedevs)
|
2011-03-23 10:07:23 -04:00
|
|
|
self.nodedevs = {}
|
2011-04-11 11:00:57 -04:00
|
|
|
|
|
|
|
|
cleanup(self.netdevs)
|
2011-03-23 10:07:23 -04:00
|
|
|
self.netdevs = {}
|
2011-04-11 11:00:57 -04:00
|
|
|
|
|
|
|
|
cleanup(self.mediadevs)
|
2011-03-23 10:07:23 -04:00
|
|
|
self.mediadevs = {}
|
2011-04-11 11:00:57 -04:00
|
|
|
|
|
|
|
|
cleanup(self.interfaces)
|
2011-03-23 10:07:23 -04:00
|
|
|
self.interfaces = {}
|
2011-04-11 11:00:57 -04:00
|
|
|
|
|
|
|
|
cleanup(self.pools)
|
2009-11-25 16:13:46 -05:00
|
|
|
self.pools = {}
|
2011-04-11 11:00:57 -04:00
|
|
|
|
|
|
|
|
cleanup(self.nets)
|
2011-03-23 10:07:23 -04:00
|
|
|
self.nets = {}
|
2011-04-11 11:00:57 -04:00
|
|
|
|
|
|
|
|
cleanup(self.vms)
|
2009-11-25 16:13:46 -05:00
|
|
|
self.vms = {}
|
2011-03-23 10:07:23 -04:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
self._change_state(self.STATE_DISCONNECTED)
|
|
|
|
|
|
2011-04-13 09:27:02 -04:00
|
|
|
def cleanup(self):
|
|
|
|
|
# Do this first, so signals are unregistered before we change state
|
|
|
|
|
vmmGObject.cleanup(self)
|
|
|
|
|
self.close()
|
|
|
|
|
|
|
|
|
|
hal_helper = self.get_hal_helper()
|
|
|
|
|
if hal_helper:
|
|
|
|
|
for h in self.hal_handles:
|
|
|
|
|
hal_helper.disconnect(h)
|
|
|
|
|
|
2010-12-07 14:26:51 -05:00
|
|
|
def _open_dev_conn(self, uri):
|
|
|
|
|
"""
|
|
|
|
|
Allow using virtinsts connection hacking to fake capabilities
|
|
|
|
|
and other reproducible/testable behavior
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
import virtinst.cli as cli
|
|
|
|
|
if not cli._is_virtinst_test_uri(uri):
|
|
|
|
|
return
|
|
|
|
|
except:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
return cli._open_test_uri(uri)
|
|
|
|
|
except:
|
|
|
|
|
logging.exception("Trouble opening test URI")
|
|
|
|
|
return
|
|
|
|
|
|
2010-11-29 18:00:35 -05:00
|
|
|
def open(self, sync=False):
|
2007-09-09 22:57:24 -04:00
|
|
|
if self.state != self.STATE_DISCONNECTED:
|
|
|
|
|
return
|
|
|
|
|
|
2010-11-29 18:00:35 -05:00
|
|
|
self.connectError = None
|
2009-07-11 21:23:16 -04:00
|
|
|
self._change_state(self.STATE_CONNECTING)
|
2007-09-10 20:56:01 -04:00
|
|
|
|
2010-11-29 18:00:35 -05:00
|
|
|
if sync:
|
|
|
|
|
logging.debug("Opening connection synchronously: %s" % self.uri)
|
|
|
|
|
self._open_thread()
|
|
|
|
|
else:
|
|
|
|
|
logging.debug("Scheduling background open thread for " + self.uri)
|
2010-12-10 11:47:07 -05:00
|
|
|
self.connectThread = threading.Thread(target=self._open_thread,
|
|
|
|
|
name="Connect %s" % self.uri)
|
2010-11-29 18:00:35 -05:00
|
|
|
self.connectThread.setDaemon(True)
|
|
|
|
|
self.connectThread.start()
|
2007-09-10 20:56:01 -04:00
|
|
|
|
2008-01-31 11:39:10 -05:00
|
|
|
def _do_creds_polkit(self, action):
|
2008-09-24 14:55:03 -04:00
|
|
|
if os.getuid() == 0:
|
|
|
|
|
logging.debug("Skipping policykit check as root")
|
|
|
|
|
return 0
|
2008-01-31 11:39:10 -05:00
|
|
|
logging.debug("Doing policykit for %s" % action)
|
2008-05-05 19:38:10 -04:00
|
|
|
|
|
|
|
|
try:
|
2010-01-25 09:31:33 -05:00
|
|
|
bus = dbus.SessionBus()
|
2008-05-07 15:00:41 -04:00
|
|
|
# First try to use org.freedesktop.PolicyKit.AuthenticationAgent
|
|
|
|
|
# which is introduced with PolicyKit-0.7
|
2008-05-05 19:38:10 -04:00
|
|
|
obj = bus.get_object("org.freedesktop.PolicyKit.AuthenticationAgent", "/")
|
|
|
|
|
pkit = dbus.Interface(obj, "org.freedesktop.PolicyKit.AuthenticationAgent")
|
|
|
|
|
pkit.ObtainAuthorization(action, 0, os.getpid())
|
2008-05-07 15:00:41 -04:00
|
|
|
except dbus.exceptions.DBusException, e:
|
|
|
|
|
if e.get_dbus_name() != "org.freedesktop.DBus.Error.ServiceUnknown":
|
|
|
|
|
raise e
|
|
|
|
|
logging.debug("Falling back to org.gnome.PolicyKit")
|
2008-05-05 19:38:10 -04:00
|
|
|
# If PolicyKit < 0.7, fallback to org.gnome.PolicyKit
|
|
|
|
|
obj = bus.get_object("org.gnome.PolicyKit", "/org/gnome/PolicyKit/Manager")
|
|
|
|
|
pkit = dbus.Interface(obj, "org.gnome.PolicyKit.Manager")
|
|
|
|
|
pkit.ShowDialog(action, 0)
|
2008-01-31 11:39:10 -05:00
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def _do_creds_dialog(self, creds):
|
|
|
|
|
try:
|
|
|
|
|
gtk.gdk.threads_enter()
|
|
|
|
|
return self._do_creds_dialog_main(creds)
|
|
|
|
|
finally:
|
|
|
|
|
gtk.gdk.threads_leave()
|
|
|
|
|
|
|
|
|
|
def _do_creds_dialog_main(self, creds):
|
2010-02-24 14:40:22 -05:00
|
|
|
dialog = gtk.Dialog("Authentication required", None, 0,
|
|
|
|
|
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
|
|
|
|
gtk.STOCK_OK, gtk.RESPONSE_OK))
|
2008-01-31 11:39:10 -05:00
|
|
|
label = []
|
|
|
|
|
entry = []
|
|
|
|
|
|
|
|
|
|
box = gtk.Table(2, len(creds))
|
2010-02-24 14:40:22 -05:00
|
|
|
box.set_border_width(6)
|
|
|
|
|
box.set_row_spacings(6)
|
|
|
|
|
box.set_col_spacings(12)
|
2008-01-31 11:39:10 -05:00
|
|
|
|
2010-08-28 19:44:30 +02:00
|
|
|
def _on_ent_activate(ent):
|
|
|
|
|
idx = entry.index(ent)
|
|
|
|
|
|
|
|
|
|
if idx < len(entry) - 1:
|
|
|
|
|
entry[idx + 1].grab_focus()
|
|
|
|
|
else:
|
|
|
|
|
dialog.response(gtk.RESPONSE_OK)
|
|
|
|
|
|
2008-01-31 11:39:10 -05:00
|
|
|
row = 0
|
|
|
|
|
for cred in creds:
|
2010-02-24 14:40:22 -05:00
|
|
|
if (cred[0] == libvirt.VIR_CRED_AUTHNAME or
|
|
|
|
|
cred[0] == libvirt.VIR_CRED_PASSPHRASE):
|
|
|
|
|
prompt = cred[1]
|
|
|
|
|
if not prompt.endswith(":"):
|
|
|
|
|
prompt += ":"
|
|
|
|
|
|
|
|
|
|
text_label = gtk.Label(prompt)
|
|
|
|
|
text_label.set_alignment(0.0, 0.5)
|
|
|
|
|
|
|
|
|
|
label.append(text_label)
|
2008-01-31 11:39:10 -05:00
|
|
|
else:
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
ent = gtk.Entry()
|
|
|
|
|
if cred[0] == libvirt.VIR_CRED_PASSPHRASE:
|
|
|
|
|
ent.set_visibility(False)
|
2010-08-28 19:44:30 +02:00
|
|
|
ent.connect("activate", _on_ent_activate)
|
2008-01-31 11:39:10 -05:00
|
|
|
entry.append(ent)
|
|
|
|
|
|
2010-12-10 11:47:07 -05:00
|
|
|
box.attach(label[row], 0, 1, row, row + 1, gtk.FILL, 0, 0, 0)
|
|
|
|
|
box.attach(entry[row], 1, 2, row, row + 1, gtk.FILL, 0, 0, 0)
|
2008-01-31 11:39:10 -05:00
|
|
|
row = row + 1
|
|
|
|
|
|
|
|
|
|
vbox = dialog.get_child()
|
|
|
|
|
vbox.add(box)
|
|
|
|
|
|
|
|
|
|
dialog.show_all()
|
|
|
|
|
res = dialog.run()
|
|
|
|
|
dialog.hide()
|
|
|
|
|
|
|
|
|
|
if res == gtk.RESPONSE_OK:
|
|
|
|
|
row = 0
|
|
|
|
|
for cred in creds:
|
|
|
|
|
cred[4] = entry[row].get_text()
|
|
|
|
|
row = row + 1
|
|
|
|
|
dialog.destroy()
|
|
|
|
|
return 0
|
|
|
|
|
else:
|
|
|
|
|
dialog.destroy()
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
def _do_creds(self, creds, cbdata):
|
2010-12-09 11:22:35 -05:00
|
|
|
ignore = cbdata
|
2008-01-31 11:39:10 -05:00
|
|
|
try:
|
2009-04-03 14:58:51 -04:00
|
|
|
if (len(creds) == 1 and
|
|
|
|
|
creds[0][0] == libvirt.VIR_CRED_EXTERNAL and
|
|
|
|
|
creds[0][2] == "PolicyKit"):
|
2008-01-31 11:39:10 -05:00
|
|
|
return self._do_creds_polkit(creds[0][1])
|
|
|
|
|
|
|
|
|
|
for cred in creds:
|
2008-03-03 16:11:29 -05:00
|
|
|
if cred[0] == libvirt.VIR_CRED_EXTERNAL:
|
2008-01-31 11:39:10 -05:00
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
return self._do_creds_dialog(creds)
|
2009-04-03 14:58:51 -04:00
|
|
|
except Exception, e:
|
2008-01-31 11:39:10 -05:00
|
|
|
# Detailed error message, in English so it can be Googled.
|
2009-04-03 14:58:51 -04:00
|
|
|
self.connectError = ("Failed to get credentials for '%s':\n%s\n%s"
|
|
|
|
|
% (str(self.uri), str(e),
|
|
|
|
|
"".join(traceback.format_exc())))
|
2008-01-31 11:39:10 -05:00
|
|
|
return -1
|
2007-09-10 20:56:01 -04:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
def _acquire_tgt(self):
|
|
|
|
|
logging.debug("In acquire tgt.")
|
|
|
|
|
try:
|
|
|
|
|
bus = dbus.SessionBus()
|
|
|
|
|
ka = bus.get_object('org.gnome.KrbAuthDialog',
|
|
|
|
|
'/org/gnome/KrbAuthDialog')
|
|
|
|
|
ret = ka.acquireTgt("", dbus_interface='org.gnome.KrbAuthDialog')
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logging.info("Cannot acquire tgt" + str(e))
|
|
|
|
|
ret = False
|
|
|
|
|
return ret
|
|
|
|
|
|
2009-01-26 11:10:39 -05:00
|
|
|
def _try_open(self):
|
2007-09-09 22:57:24 -04:00
|
|
|
try:
|
2008-01-31 11:39:10 -05:00
|
|
|
flags = 0
|
2010-12-07 14:26:51 -05:00
|
|
|
|
|
|
|
|
tmp = self._open_dev_conn(self.uri)
|
|
|
|
|
if tmp:
|
|
|
|
|
self.vmm = tmp
|
|
|
|
|
return
|
|
|
|
|
|
2008-01-31 11:39:10 -05:00
|
|
|
if self.readOnly:
|
2008-08-21 12:29:33 +01:00
|
|
|
logging.info("Caller requested read only connection")
|
2008-01-31 11:39:10 -05:00
|
|
|
flags = libvirt.VIR_CONNECT_RO
|
|
|
|
|
|
2009-12-03 10:22:54 -05:00
|
|
|
if virtinst.support.support_openauth():
|
|
|
|
|
self.vmm = libvirt.openAuth(self.uri,
|
|
|
|
|
[[libvirt.VIR_CRED_AUTHNAME,
|
|
|
|
|
libvirt.VIR_CRED_PASSPHRASE,
|
|
|
|
|
libvirt.VIR_CRED_EXTERNAL],
|
|
|
|
|
self._do_creds,
|
|
|
|
|
None], flags)
|
|
|
|
|
else:
|
|
|
|
|
if flags:
|
|
|
|
|
self.vmm = libvirt.openReadOnly(self.uri)
|
|
|
|
|
else:
|
|
|
|
|
self.vmm = libvirt.open(self.uri)
|
2009-01-26 11:10:39 -05:00
|
|
|
except:
|
2009-07-01 11:13:30 -04:00
|
|
|
return sys.exc_info()
|
2009-01-26 11:10:39 -05:00
|
|
|
|
|
|
|
|
def _open_thread(self):
|
|
|
|
|
logging.debug("Background thread is running")
|
|
|
|
|
|
2009-03-09 16:21:32 -04:00
|
|
|
done = False
|
|
|
|
|
while not done:
|
|
|
|
|
open_error = self._try_open()
|
|
|
|
|
done = True
|
2009-01-26 11:10:39 -05:00
|
|
|
|
2009-03-09 16:21:32 -04:00
|
|
|
if not open_error:
|
|
|
|
|
self.state = self.STATE_ACTIVE
|
2010-08-24 14:55:00 -04:00
|
|
|
continue
|
2009-03-09 16:21:32 -04:00
|
|
|
|
2010-08-24 14:55:00 -04:00
|
|
|
self.state = self.STATE_DISCONNECTED
|
|
|
|
|
(_type, value, stacktrace) = open_error
|
2009-03-09 16:21:32 -04:00
|
|
|
|
2010-08-24 14:55:00 -04:00
|
|
|
if (_type == libvirt.libvirtError and
|
|
|
|
|
value.get_error_code() == libvirt.VIR_ERR_AUTH_FAILED and
|
|
|
|
|
"GSSAPI Error" in value.get_error_message() and
|
|
|
|
|
"No credentials cache found" in value.get_error_message()):
|
|
|
|
|
if self._acquire_tgt():
|
|
|
|
|
done = False
|
|
|
|
|
continue
|
2009-03-09 16:21:32 -04:00
|
|
|
|
2010-08-24 14:55:00 -04:00
|
|
|
tb = "".join(traceback.format_exception(_type, value, stacktrace))
|
2009-04-03 14:58:51 -04:00
|
|
|
|
2010-08-24 14:55:00 -04:00
|
|
|
self.connectError = "%s\n\n%s" % (str(value), str(tb))
|
2007-09-10 20:56:01 -04:00
|
|
|
|
|
|
|
|
# We want to kill off this thread asap, so schedule a gobject
|
|
|
|
|
# idle even to inform the UI of result
|
|
|
|
|
logging.debug("Background open thread complete, scheduling notify")
|
2011-04-18 11:12:36 -04:00
|
|
|
self.safe_idle_add(self._open_notify)
|
2007-09-10 20:56:01 -04:00
|
|
|
self.connectThread = None
|
|
|
|
|
|
|
|
|
|
def _open_notify(self):
|
|
|
|
|
logging.debug("Notifying open result")
|
2009-07-11 21:23:16 -04:00
|
|
|
|
2011-04-18 11:12:36 -04:00
|
|
|
self.idle_emit("state-changed")
|
2010-11-24 14:01:51 -05:00
|
|
|
|
|
|
|
|
if self.state == self.STATE_ACTIVE:
|
|
|
|
|
caps = self.get_capabilities_xml()
|
|
|
|
|
logging.debug("%s capabilities:\n%s" %
|
|
|
|
|
(self.get_uri(), caps))
|
|
|
|
|
|
|
|
|
|
self.tick()
|
|
|
|
|
# If VMs disappeared since the last time we connected to
|
|
|
|
|
# this uri, remove their gconf entries so we don't pollute
|
|
|
|
|
# the database
|
|
|
|
|
self.config.reconcile_vm_entries(self.get_uri(),
|
|
|
|
|
self.vms.keys())
|
|
|
|
|
|
|
|
|
|
if self.state == self.STATE_DISCONNECTED:
|
2011-04-18 11:12:36 -04:00
|
|
|
self.idle_emit("connect-error", self.connectError)
|
2010-11-24 14:01:51 -05:00
|
|
|
self.connectError = None
|
2007-09-10 20:56:01 -04:00
|
|
|
|
2006-10-10 17:24:59 -04:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
#######################
|
|
|
|
|
# Tick/Update methods #
|
|
|
|
|
#######################
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
def _poll_helper(self,
|
|
|
|
|
origlist, typename, check_support,
|
|
|
|
|
active_list, inactive_list,
|
|
|
|
|
lookup_func, build_class):
|
2009-11-19 17:35:27 -05:00
|
|
|
current = {}
|
|
|
|
|
start = []
|
|
|
|
|
stop = []
|
|
|
|
|
new = []
|
|
|
|
|
newActiveNames = []
|
|
|
|
|
newInactiveNames = []
|
|
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
if not check_support():
|
|
|
|
|
return (stop, start, origlist, new, current)
|
2009-11-19 17:35:27 -05:00
|
|
|
|
|
|
|
|
try:
|
2011-04-09 21:51:50 -04:00
|
|
|
newActiveNames = active_list()
|
2011-04-20 17:00:03 -04:00
|
|
|
except Exception, e:
|
|
|
|
|
logging.debug("Unable to list active %ss: %s" % (typename, e))
|
2009-11-19 17:35:27 -05:00
|
|
|
try:
|
2011-04-09 21:51:50 -04:00
|
|
|
newInactiveNames = inactive_list()
|
2011-04-20 17:00:03 -04:00
|
|
|
except Exception, e:
|
|
|
|
|
logging.debug("Unable to list inactive %ss: %s" % (typename, e))
|
2009-11-19 17:35:27 -05:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
def check_obj(key, is_active):
|
|
|
|
|
if key not in origlist:
|
2011-04-20 17:00:03 -04:00
|
|
|
try:
|
|
|
|
|
obj = lookup_func(key)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logging.debug("Could not fetch %s '%s': %s" %
|
|
|
|
|
(typename, key, e))
|
|
|
|
|
return
|
|
|
|
|
|
2009-11-19 17:35:27 -05:00
|
|
|
# Object is brand new this tick period
|
2011-04-09 21:51:50 -04:00
|
|
|
current[key] = build_class(self, obj, key, is_active)
|
2009-11-19 17:35:27 -05:00
|
|
|
new.append(key)
|
|
|
|
|
|
|
|
|
|
if is_active:
|
|
|
|
|
start.append(key)
|
|
|
|
|
else:
|
|
|
|
|
# Previously known object, see if it changed state
|
2011-04-09 21:51:50 -04:00
|
|
|
current[key] = origlist[key]
|
2009-11-19 17:35:27 -05:00
|
|
|
|
|
|
|
|
if current[key].is_active() != is_active:
|
|
|
|
|
current[key].set_active(is_active)
|
|
|
|
|
|
|
|
|
|
if is_active:
|
|
|
|
|
start.append(key)
|
|
|
|
|
else:
|
|
|
|
|
stop.append(key)
|
|
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
del origlist[key]
|
2009-11-19 17:35:27 -05:00
|
|
|
|
|
|
|
|
for name in newActiveNames:
|
|
|
|
|
try:
|
|
|
|
|
check_obj(name, True)
|
2009-12-13 16:31:04 -05:00
|
|
|
except:
|
2009-11-19 17:35:27 -05:00
|
|
|
logging.exception("Couldn't fetch active "
|
2011-04-09 21:51:50 -04:00
|
|
|
"%s '%s'" % (typename, name))
|
2009-11-19 17:35:27 -05:00
|
|
|
|
|
|
|
|
for name in newInactiveNames:
|
|
|
|
|
try:
|
|
|
|
|
check_obj(name, False)
|
2009-12-13 16:31:04 -05:00
|
|
|
except:
|
2009-11-19 17:35:27 -05:00
|
|
|
logging.exception("Couldn't fetch inactive "
|
2011-04-09 21:51:50 -04:00
|
|
|
"%s '%s'" % (typename, name))
|
2009-11-25 14:50:27 -05:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
return (stop, start, origlist, new, current)
|
2009-11-25 14:50:27 -05:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
def _update_nets(self):
|
|
|
|
|
orig = self.nets
|
|
|
|
|
name = "network"
|
|
|
|
|
active_list = self.vmm.listNetworks
|
|
|
|
|
inactive_list = self.vmm.listDefinedNetworks
|
|
|
|
|
check_support = self.is_network_capable
|
|
|
|
|
lookup_func = self.vmm.networkLookupByName
|
|
|
|
|
build_class = vmmNetwork
|
|
|
|
|
|
|
|
|
|
return self._poll_helper(orig, name, check_support,
|
|
|
|
|
active_list, inactive_list,
|
|
|
|
|
lookup_func, build_class)
|
2009-11-25 14:50:27 -05:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
def _update_pools(self):
|
|
|
|
|
orig = self.pools
|
|
|
|
|
name = "pool"
|
|
|
|
|
active_list = self.vmm.listStoragePools
|
|
|
|
|
inactive_list = self.vmm.listDefinedStoragePools
|
|
|
|
|
check_support = self.is_storage_capable
|
|
|
|
|
lookup_func = self.vmm.storagePoolLookupByName
|
|
|
|
|
build_class = vmmStoragePool
|
|
|
|
|
|
|
|
|
|
return self._poll_helper(orig, name, check_support,
|
|
|
|
|
active_list, inactive_list,
|
|
|
|
|
lookup_func, build_class)
|
2009-11-25 14:50:27 -05:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
def _update_interfaces(self):
|
|
|
|
|
orig = self.interfaces
|
|
|
|
|
name = "interface"
|
|
|
|
|
active_list = self.vmm.listInterfaces
|
|
|
|
|
inactive_list = self.vmm.listDefinedInterfaces
|
|
|
|
|
check_support = self.is_interface_capable
|
|
|
|
|
lookup_func = self.vmm.interfaceLookupByName
|
|
|
|
|
build_class = vmmInterface
|
2009-11-25 14:50:27 -05:00
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
return self._poll_helper(orig, name, check_support,
|
|
|
|
|
active_list, inactive_list,
|
|
|
|
|
lookup_func, build_class)
|
2009-11-25 14:50:27 -05:00
|
|
|
|
|
|
|
|
|
2011-04-09 21:51:50 -04:00
|
|
|
def _update_nodedevs(self):
|
|
|
|
|
orig = self.nodedevs
|
|
|
|
|
name = "nodedev"
|
|
|
|
|
active_list = lambda: self.vmm.listDevices(None, 0)
|
|
|
|
|
inactive_list = lambda: []
|
|
|
|
|
check_support = self.is_nodedev_capable
|
|
|
|
|
lookup_func = self.vmm.nodeDeviceLookupByName
|
|
|
|
|
build_class = (lambda conn, obj, key, ignore:
|
|
|
|
|
vmmNodeDevice(conn, obj, key))
|
|
|
|
|
|
|
|
|
|
return self._poll_helper(orig, name, check_support,
|
|
|
|
|
active_list, inactive_list,
|
|
|
|
|
lookup_func, build_class)
|
2009-11-19 17:35:27 -05:00
|
|
|
|
2008-07-09 17:00:49 -04:00
|
|
|
def _update_vms(self):
|
2009-11-19 17:35:27 -05:00
|
|
|
"""
|
|
|
|
|
returns lists of changed VM states
|
|
|
|
|
"""
|
2011-04-09 23:51:43 -04:00
|
|
|
newActiveIDs = []
|
|
|
|
|
newInactiveNames = []
|
2006-10-09 13:28:13 -04:00
|
|
|
oldActiveIDs = {}
|
|
|
|
|
oldInactiveNames = {}
|
2011-04-09 23:51:43 -04:00
|
|
|
|
2011-04-10 18:26:40 -04:00
|
|
|
origlist = self.vms
|
2011-04-09 23:51:43 -04:00
|
|
|
current = {}
|
|
|
|
|
new = []
|
|
|
|
|
|
2011-04-10 17:41:56 -04:00
|
|
|
# Build list of previous vms with proper id/name mappings
|
2011-04-10 18:26:40 -04:00
|
|
|
for uuid in origlist:
|
|
|
|
|
vm = origlist[uuid]
|
2011-04-09 22:40:22 -04:00
|
|
|
if vm.is_active():
|
2006-10-09 13:28:13 -04:00
|
|
|
oldActiveIDs[vm.get_id()] = vm
|
2011-04-10 17:41:56 -04:00
|
|
|
else:
|
|
|
|
|
oldInactiveNames[vm.get_name()] = vm
|
2006-10-09 13:28:13 -04:00
|
|
|
|
2008-03-14 10:15:27 -04:00
|
|
|
try:
|
|
|
|
|
newActiveIDs = self.vmm.listDomainsID()
|
2011-04-20 17:00:03 -04:00
|
|
|
except Exception, e:
|
|
|
|
|
logging.debug("Unable to list active domains: %s" % e)
|
2008-03-14 10:15:27 -04:00
|
|
|
|
2006-10-11 12:05:50 -04:00
|
|
|
try:
|
|
|
|
|
newInactiveNames = self.vmm.listDefinedDomains()
|
2011-04-20 17:00:03 -04:00
|
|
|
except Exception, e:
|
|
|
|
|
logging.exception("Unable to list inactive domains: %s" % e)
|
2006-10-09 13:28:13 -04:00
|
|
|
|
|
|
|
|
# NB in these first 2 loops, we go to great pains to
|
|
|
|
|
# avoid actually instantiating a new VM object so that
|
|
|
|
|
# the common case of 'no new/old VMs' avoids hitting
|
|
|
|
|
# XenD too much & thus slowing stuff down.
|
|
|
|
|
|
2011-04-10 18:26:40 -04:00
|
|
|
def add_vm(vm):
|
|
|
|
|
uuid = vm.get_uuid()
|
|
|
|
|
|
|
|
|
|
current[uuid] = vm
|
|
|
|
|
del(origlist[uuid])
|
|
|
|
|
|
|
|
|
|
def check_new(rawvm, uuid):
|
|
|
|
|
if uuid in origlist:
|
|
|
|
|
vm = origlist[uuid]
|
|
|
|
|
del(origlist[uuid])
|
|
|
|
|
else:
|
|
|
|
|
vm = vmmDomain(self, rawvm, uuid)
|
|
|
|
|
new.append(uuid)
|
|
|
|
|
|
|
|
|
|
current[uuid] = vm
|
|
|
|
|
|
2011-04-09 23:51:43 -04:00
|
|
|
for _id in newActiveIDs:
|
|
|
|
|
if _id in oldActiveIDs:
|
|
|
|
|
# No change, copy across existing VM object
|
|
|
|
|
vm = oldActiveIDs[_id]
|
2011-04-10 18:26:40 -04:00
|
|
|
add_vm(vm)
|
2011-04-09 23:51:43 -04:00
|
|
|
else:
|
2011-04-10 18:26:40 -04:00
|
|
|
# Check if domain is brand new, or old one that changed state
|
2011-04-09 23:51:43 -04:00
|
|
|
try:
|
|
|
|
|
vm = self.vmm.lookupByID(_id)
|
|
|
|
|
uuid = util.uuidstr(vm.UUID())
|
2011-04-10 18:26:40 -04:00
|
|
|
|
|
|
|
|
check_new(vm, uuid)
|
2011-04-09 23:51:43 -04:00
|
|
|
except:
|
|
|
|
|
logging.exception("Couldn't fetch domain id '%s'" % _id)
|
2006-10-09 13:28:13 -04:00
|
|
|
|
2011-04-10 18:26:40 -04:00
|
|
|
|
2011-04-09 23:51:43 -04:00
|
|
|
for name in newInactiveNames:
|
|
|
|
|
if name in oldInactiveNames:
|
|
|
|
|
# No change, copy across existing VM object
|
|
|
|
|
vm = oldInactiveNames[name]
|
2011-04-10 18:26:40 -04:00
|
|
|
add_vm(vm)
|
2011-04-09 23:51:43 -04:00
|
|
|
else:
|
2011-04-10 18:26:40 -04:00
|
|
|
# Check if domain is brand new, or old one that changed state
|
2011-04-09 23:51:43 -04:00
|
|
|
try:
|
|
|
|
|
vm = self.vmm.lookupByName(name)
|
|
|
|
|
uuid = util.uuidstr(vm.UUID())
|
2011-04-10 18:26:40 -04:00
|
|
|
|
|
|
|
|
check_new(vm, uuid)
|
2011-04-09 23:51:43 -04:00
|
|
|
except:
|
|
|
|
|
logging.exception("Couldn't fetch domain '%s'" % name)
|
2006-10-09 13:28:13 -04:00
|
|
|
|
2011-04-15 14:13:05 -04:00
|
|
|
return (new, origlist, current)
|
2006-10-09 13:28:13 -04:00
|
|
|
|
2008-07-09 17:00:49 -04:00
|
|
|
def tick(self, noStatsUpdate=False):
|
|
|
|
|
""" main update function: polls for new objects, updates stats, ..."""
|
|
|
|
|
if self.state != self.STATE_ACTIVE:
|
|
|
|
|
return
|
2006-10-09 13:28:13 -04:00
|
|
|
|
2008-10-06 13:21:06 -04:00
|
|
|
self.hostinfo = self.vmm.getInfo()
|
|
|
|
|
|
2008-07-09 17:00:49 -04:00
|
|
|
# Poll for new virtual network objects
|
2011-04-11 16:19:47 -04:00
|
|
|
(startNets, stopNets, oldNets,
|
|
|
|
|
newNets, self.nets) = self._update_nets()
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2008-08-07 17:37:16 -04:00
|
|
|
# Update pools
|
|
|
|
|
(stopPools, startPools, oldPools,
|
|
|
|
|
newPools, self.pools) = self._update_pools()
|
|
|
|
|
|
2009-11-19 17:35:27 -05:00
|
|
|
# Update interfaces
|
|
|
|
|
(stopInterfaces, startInterfaces, oldInterfaces,
|
|
|
|
|
newInterfaces, self.interfaces) = self._update_interfaces()
|
|
|
|
|
|
2009-11-25 14:50:27 -05:00
|
|
|
# Update nodedevice list
|
2011-04-09 21:51:50 -04:00
|
|
|
(ignore, ignore, oldNodedevs,
|
|
|
|
|
newNodedevs, self.nodedevs) = self._update_nodedevs()
|
2009-11-25 14:50:27 -05:00
|
|
|
|
2008-07-09 17:00:49 -04:00
|
|
|
# Poll for changed/new/removed VMs
|
2011-04-15 14:13:05 -04:00
|
|
|
(newVMs, oldVMs, self.vms) = self._update_vms()
|
2008-07-09 17:00:49 -04:00
|
|
|
|
2009-07-11 21:23:16 -04:00
|
|
|
def tick_send_signals():
|
|
|
|
|
"""
|
|
|
|
|
Responsible for signaling the UI for any updates. All possible UI
|
|
|
|
|
updates need to go here to enable threading that doesn't block the
|
|
|
|
|
app with long tick operations.
|
|
|
|
|
"""
|
2010-02-11 15:25:41 -05:00
|
|
|
# Connection closed out from under us
|
|
|
|
|
if not self.vmm:
|
|
|
|
|
return
|
|
|
|
|
|
2010-02-08 11:44:04 -05:00
|
|
|
# Make sure device polling is setup
|
|
|
|
|
if not self.netdev_initialized:
|
|
|
|
|
self._init_netdev()
|
|
|
|
|
|
|
|
|
|
if not self.mediadev_initialized:
|
|
|
|
|
self._init_mediadev()
|
2009-07-11 21:23:16 -04:00
|
|
|
|
|
|
|
|
# Update VM states
|
|
|
|
|
for uuid in oldVMs:
|
|
|
|
|
self.emit("vm-removed", self.uri, uuid)
|
2011-04-11 16:19:47 -04:00
|
|
|
oldVMs[uuid].cleanup()
|
2009-07-11 21:23:16 -04:00
|
|
|
for uuid in newVMs:
|
|
|
|
|
self.emit("vm-added", self.uri, uuid)
|
|
|
|
|
|
|
|
|
|
# Update virtual network states
|
|
|
|
|
for uuid in oldNets:
|
|
|
|
|
self.emit("net-removed", self.uri, uuid)
|
2011-04-11 16:19:47 -04:00
|
|
|
oldNets[uuid].cleanup()
|
2009-07-11 21:23:16 -04:00
|
|
|
for uuid in newNets:
|
|
|
|
|
self.emit("net-added", self.uri, uuid)
|
|
|
|
|
for uuid in startNets:
|
|
|
|
|
self.emit("net-started", self.uri, uuid)
|
|
|
|
|
for uuid in stopNets:
|
|
|
|
|
self.emit("net-stopped", self.uri, uuid)
|
|
|
|
|
|
2009-11-19 17:35:27 -05:00
|
|
|
# Update storage pool states
|
2009-07-11 21:23:16 -04:00
|
|
|
for uuid in oldPools:
|
|
|
|
|
self.emit("pool-removed", self.uri, uuid)
|
2011-04-11 16:19:47 -04:00
|
|
|
oldPools[uuid].cleanup()
|
2009-07-11 21:23:16 -04:00
|
|
|
for uuid in newPools:
|
|
|
|
|
self.emit("pool-added", self.uri, uuid)
|
|
|
|
|
for uuid in startPools:
|
|
|
|
|
self.emit("pool-started", self.uri, uuid)
|
|
|
|
|
for uuid in stopPools:
|
|
|
|
|
self.emit("pool-stopped", self.uri, uuid)
|
|
|
|
|
|
2009-11-19 17:35:27 -05:00
|
|
|
# Update interface states
|
|
|
|
|
for name in oldInterfaces:
|
|
|
|
|
self.emit("interface-removed", self.uri, name)
|
2011-04-12 12:05:36 -04:00
|
|
|
oldInterfaces[name].cleanup()
|
2009-11-19 17:35:27 -05:00
|
|
|
for name in newInterfaces:
|
|
|
|
|
self.emit("interface-added", self.uri, name)
|
|
|
|
|
for name in startInterfaces:
|
|
|
|
|
self.emit("interface-started", self.uri, name)
|
|
|
|
|
for name in stopInterfaces:
|
|
|
|
|
self.emit("interface-stopped", self.uri, name)
|
|
|
|
|
|
2009-11-25 14:50:27 -05:00
|
|
|
# Update nodedev list
|
|
|
|
|
for name in oldNodedevs:
|
|
|
|
|
self.emit("nodedev-removed", self.uri, name)
|
2011-04-12 12:05:36 -04:00
|
|
|
oldNodedevs[name].cleanup()
|
2009-11-25 14:50:27 -05:00
|
|
|
for name in newNodedevs:
|
|
|
|
|
self.emit("nodedev-added", self.uri, name)
|
2009-11-19 17:35:27 -05:00
|
|
|
|
2011-04-18 11:12:36 -04:00
|
|
|
self.safe_idle_add(tick_send_signals)
|
2008-08-07 17:37:16 -04:00
|
|
|
|
2006-10-09 13:28:13 -04:00
|
|
|
# Finally, we sample each domain
|
2006-06-14 17:52:49 -04:00
|
|
|
now = time()
|
2006-06-14 10:59:40 -04:00
|
|
|
|
2006-10-03 11:53:07 -04:00
|
|
|
updateVMs = self.vms
|
|
|
|
|
if noStatsUpdate:
|
2008-07-09 17:00:49 -04:00
|
|
|
updateVMs = newVMs
|
2006-10-03 11:53:07 -04:00
|
|
|
|
2008-07-09 17:00:49 -04:00
|
|
|
for uuid in updateVMs:
|
2009-09-16 16:02:19 -04:00
|
|
|
vm = self.vms[uuid]
|
|
|
|
|
try:
|
|
|
|
|
vm.tick(now)
|
|
|
|
|
except libvirt.libvirtError, e:
|
|
|
|
|
if e.get_error_code() == libvirt.VIR_ERR_SYSTEM_ERROR:
|
|
|
|
|
raise
|
|
|
|
|
logging.exception("Tick for VM '%s' failed" % vm.get_name())
|
|
|
|
|
except Exception, e:
|
|
|
|
|
logging.exception("Tick for VM '%s' failed" % vm.get_name())
|
2007-03-27 19:52:00 -04:00
|
|
|
|
|
|
|
|
if not noStatsUpdate:
|
2011-04-10 18:26:40 -04:00
|
|
|
self._recalculate_stats(now, updateVMs)
|
2007-03-27 19:52:00 -04:00
|
|
|
|
2011-04-18 11:12:36 -04:00
|
|
|
self.idle_emit("resources-sampled")
|
2009-07-11 21:23:16 -04:00
|
|
|
|
2006-06-14 10:59:40 -04:00
|
|
|
return 1
|
|
|
|
|
|
2011-04-10 18:26:40 -04:00
|
|
|
def _recalculate_stats(self, now, vms):
|
2010-02-11 15:25:41 -05:00
|
|
|
if self.vmm is None:
|
|
|
|
|
return
|
|
|
|
|
|
2007-03-27 19:52:00 -04:00
|
|
|
expected = self.config.get_stats_history_length()
|
|
|
|
|
current = len(self.record)
|
|
|
|
|
if current > expected:
|
|
|
|
|
del self.record[expected:current]
|
|
|
|
|
|
|
|
|
|
mem = 0
|
|
|
|
|
cpuTime = 0
|
2008-10-18 21:21:33 +02:00
|
|
|
rdRate = 0
|
|
|
|
|
wrRate = 0
|
|
|
|
|
rxRate = 0
|
|
|
|
|
txRate = 0
|
2007-03-27 19:52:00 -04:00
|
|
|
|
2011-04-10 18:26:40 -04:00
|
|
|
for uuid in vms:
|
|
|
|
|
vm = vms[uuid]
|
2011-04-09 22:40:22 -04:00
|
|
|
if not vm.is_active():
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
cpuTime += vm.cpu_time()
|
2011-04-10 00:02:39 -04:00
|
|
|
mem += vm.stats_memory()
|
2011-04-09 22:40:22 -04:00
|
|
|
rdRate += vm.disk_read_rate()
|
|
|
|
|
wrRate += vm.disk_write_rate()
|
|
|
|
|
rxRate += vm.network_rx_rate()
|
|
|
|
|
txRate += vm.network_tx_rate()
|
2007-03-27 19:52:00 -04:00
|
|
|
|
|
|
|
|
pcentCpuTime = 0
|
|
|
|
|
if len(self.record) > 0:
|
|
|
|
|
prevTimestamp = self.record[0]["timestamp"]
|
2010-12-10 11:47:07 -05:00
|
|
|
host_cpus = self.host_active_processor_count()
|
|
|
|
|
|
|
|
|
|
pcentCpuTime = ((cpuTime) * 100.0 /
|
|
|
|
|
((now - prevTimestamp) *
|
|
|
|
|
1000.0 * 1000.0 * 1000.0 * host_cpus))
|
2007-03-27 19:52:00 -04:00
|
|
|
|
|
|
|
|
# Due to timing diffs between getting wall time & getting
|
|
|
|
|
# the domain's time, its possible to go a tiny bit over
|
|
|
|
|
# 100% utilization. This freaks out users of the data, so
|
|
|
|
|
# we hard limit it.
|
|
|
|
|
if pcentCpuTime > 100.0:
|
|
|
|
|
pcentCpuTime = 100.0
|
|
|
|
|
# Enforce >= 0 just in case
|
|
|
|
|
if pcentCpuTime < 0.0:
|
|
|
|
|
pcentCpuTime = 0.0
|
|
|
|
|
|
|
|
|
|
pcentMem = mem * 100.0 / self.host_memory_size()
|
2010-04-07 16:36:59 -04:00
|
|
|
if pcentMem > 100.0:
|
|
|
|
|
pcentMem = 100.0
|
2007-03-27 19:52:00 -04:00
|
|
|
|
|
|
|
|
newStats = {
|
|
|
|
|
"timestamp": now,
|
|
|
|
|
"memory": mem,
|
|
|
|
|
"memoryPercent": pcentMem,
|
|
|
|
|
"cpuTime": cpuTime,
|
2008-10-18 21:21:33 +02:00
|
|
|
"cpuTimePercent": pcentCpuTime,
|
|
|
|
|
"diskRdRate" : rdRate,
|
|
|
|
|
"diskWrRate" : wrRate,
|
|
|
|
|
"netRxRate" : rxRate,
|
|
|
|
|
"netTxRate" : txRate,
|
2007-03-27 19:52:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.record.insert(0, newStats)
|
|
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
|
|
|
|
|
########################
|
|
|
|
|
# Stats getter methods #
|
|
|
|
|
########################
|
2007-03-27 19:52:00 -04:00
|
|
|
def cpu_time_vector(self):
|
|
|
|
|
vector = []
|
|
|
|
|
stats = self.record
|
2010-12-10 11:47:07 -05:00
|
|
|
for i in range(self.config.get_stats_history_length() + 1):
|
2007-03-27 19:52:00 -04:00
|
|
|
if i < len(stats):
|
2010-12-10 11:47:07 -05:00
|
|
|
vector.append(stats[i]["cpuTimePercent"] / 100.0)
|
2007-03-27 19:52:00 -04:00
|
|
|
else:
|
|
|
|
|
vector.append(0)
|
|
|
|
|
return vector
|
|
|
|
|
|
|
|
|
|
def cpu_time_vector_limit(self, limit):
|
|
|
|
|
cpudata = self.cpu_time_vector()
|
|
|
|
|
if len(cpudata) > limit:
|
|
|
|
|
cpudata = cpudata[0:limit]
|
|
|
|
|
return cpudata
|
|
|
|
|
|
2011-04-09 23:03:01 -04:00
|
|
|
def stats_memory_vector(self):
|
2007-03-27 19:52:00 -04:00
|
|
|
vector = []
|
|
|
|
|
stats = self.record
|
2010-12-10 11:47:07 -05:00
|
|
|
for i in range(self.config.get_stats_history_length() + 1):
|
2007-03-27 19:52:00 -04:00
|
|
|
if i < len(stats):
|
2010-12-10 11:47:07 -05:00
|
|
|
vector.append(stats[i]["memoryPercent"] / 100.0)
|
2007-03-27 19:52:00 -04:00
|
|
|
else:
|
|
|
|
|
vector.append(0)
|
|
|
|
|
return vector
|
|
|
|
|
|
2011-04-14 12:20:02 -04:00
|
|
|
def disk_io_vector_limit(self, dummy):
|
|
|
|
|
#No point to accumulate unnormalized I/O for a conenction
|
|
|
|
|
return [0.0]
|
|
|
|
|
def network_traffic_vector_limit(self, dummy):
|
|
|
|
|
#No point to accumulate unnormalized Rx/Tx for a connection
|
|
|
|
|
return [0.0]
|
|
|
|
|
|
|
|
|
|
def _get_record_helper(self, record_name):
|
|
|
|
|
if len(self.record) == 0:
|
|
|
|
|
return 0
|
|
|
|
|
return self.record[0][record_name]
|
|
|
|
|
|
|
|
|
|
def stats_memory(self):
|
|
|
|
|
return self._get_record_helper("memory")
|
|
|
|
|
def stats_memory_percentage(self):
|
|
|
|
|
return self._get_record_helper("memoryPercent")
|
|
|
|
|
def cpu_time_percentage(self):
|
|
|
|
|
return self._get_record_helper("cpuTimePercent")
|
|
|
|
|
|
2008-10-18 21:21:33 +02:00
|
|
|
def network_rx_rate(self):
|
2011-04-09 23:03:01 -04:00
|
|
|
return self._get_record_helper("netRxRate")
|
2008-10-18 21:21:33 +02:00
|
|
|
def network_tx_rate(self):
|
2011-04-09 23:03:01 -04:00
|
|
|
return self._get_record_helper("netTxRate")
|
2008-10-18 21:21:33 +02:00
|
|
|
def network_traffic_rate(self):
|
|
|
|
|
return self.network_tx_rate() + self.network_rx_rate()
|
|
|
|
|
|
2011-04-14 12:20:02 -04:00
|
|
|
def pretty_stats_memory(self):
|
|
|
|
|
return util.pretty_mem(self.stats_memory())
|
|
|
|
|
|
2008-10-18 21:21:33 +02:00
|
|
|
def disk_read_rate(self):
|
2011-04-09 23:03:01 -04:00
|
|
|
return self._get_record_helper("diskRdRate")
|
2008-10-18 21:21:33 +02:00
|
|
|
def disk_write_rate(self):
|
2011-04-09 23:03:01 -04:00
|
|
|
return self._get_record_helper("diskWrRate")
|
2008-10-18 21:21:33 +02:00
|
|
|
def disk_io_rate(self):
|
|
|
|
|
return self.disk_read_rate() + self.disk_write_rate()
|
2009-11-25 16:12:03 -05:00
|
|
|
|
2007-09-09 22:57:24 -04:00
|
|
|
|
2009-11-25 16:13:46 -05:00
|
|
|
####################################
|
|
|
|
|
# Per-Connection gconf preferences #
|
|
|
|
|
####################################
|
2007-08-09 16:19:41 -04:00
|
|
|
|
2009-05-11 11:00:03 -04:00
|
|
|
def config_add_iso_path(self, path):
|
|
|
|
|
self.config.set_perhost(self.get_uri(), self.config.add_iso_path, path)
|
|
|
|
|
def config_get_iso_paths(self):
|
|
|
|
|
return self.config.get_perhost(self.get_uri(),
|
|
|
|
|
self.config.get_iso_paths)
|
|
|
|
|
|
2011-04-11 13:06:59 -04:00
|
|
|
vmmGObject.type_register(vmmConnection)
|