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 17:52:49 -04:00
2013-04-11 17:16:33 -04:00
# pylint: disable=E0611
2012-05-14 14:24:56 +01:00
from gi . repository import GObject
2013-04-11 17:16:33 -04:00
# pylint: enable=E0611
2012-05-14 14:24:56 +01:00
2006-09-25 18:41:47 -04:00
import logging
2010-12-10 16:04:42 -05:00
import time
import threading
2011-04-18 12:39:53 -04:00
import libvirt
2010-02-07 12:16:13 -05:00
import virtinst
2011-04-05 01:35:34 +02:00
from virtinst . VirtualCharDevice import VirtualCharSpicevmcDevice
2006-08-08 11:51:58 -04:00
2011-04-18 12:39:53 -04:00
from virtManager import util
2010-02-25 19:35:01 -05:00
from virtManager . libvirtobject import vmmLibvirtObject
2013-04-13 14:34:52 -04:00
2010-09-08 17:53:51 -04:00
def compare_device ( origdev , newdev , idx ) :
devprops = {
" disk " : [ " target " , " bus " ] ,
" interface " : [ " macaddr " , " vmmindex " ] ,
" input " : [ " bus " , " type " , " vmmindex " ] ,
" sound " : [ " model " , " vmmindex " ] ,
2013-07-15 11:07:40 -04:00
" video " : [ " model " , " vmmindex " ] ,
2010-09-08 17:53:51 -04:00
" watchdog " : [ " vmmindex " ] ,
2011-07-19 12:37:18 -04:00
" hostdev " : [ " type " , " managed " , " vmmindex " ,
" product " , " vendor " ,
" function " , " domain " , " slot " ] ,
2010-09-08 17:53:51 -04:00
" serial " : [ " char_type " , " target_port " ] ,
" parallel " : [ " char_type " , " target_port " ] ,
" console " : [ " char_type " , " target_type " , " target_port " ] ,
" graphics " : [ " type " , " vmmindex " ] ,
2010-12-16 12:41:47 -05:00
" controller " : [ " type " , " index " ] ,
2011-04-05 01:35:32 +02:00
" channel " : [ " char_type " , " target_name " ] ,
2011-05-19 15:18:33 -04:00
" filesystem " : [ " target " , " vmmindex " ] ,
2011-06-23 17:42:03 +02:00
" smartcard " : [ " mode " , " vmmindex " ] ,
2011-09-02 03:23:27 +02:00
" redirdev " : [ " bus " , " type " , " vmmindex " ] ,
2013-06-25 21:45:08 -04:00
" tpm " : [ " type " , " vmmindex " ] ,
2010-09-08 17:53:51 -04:00
}
if id ( origdev ) == id ( newdev ) :
return True
if type ( origdev ) is not type ( newdev ) :
return False
for devprop in devprops [ origdev . virtual_device_type ] :
origval = getattr ( origdev , devprop )
if devprop == " vmmindex " :
newval = idx
else :
newval = getattr ( newdev , devprop )
if origval != newval :
return False
return True
2009-12-02 08:39:10 -05:00
2013-04-13 14:34:52 -04:00
2010-09-08 17:53:51 -04:00
def find_device ( guest , origdev ) :
devlist = guest . get_devices ( origdev . virtual_device_type )
for idx in range ( len ( devlist ) ) :
dev = devlist [ idx ]
if compare_device ( origdev , dev , idx ) :
return dev
2009-12-02 08:39:10 -05:00
2010-09-08 17:53:51 -04:00
return None
2009-12-02 08:39:10 -05:00
2013-04-13 14:34:52 -04:00
2010-12-10 16:04:42 -05:00
def start_job_progress_thread ( vm , meter , progtext ) :
current_thread = threading . currentThread ( )
def jobinfo_cb ( ) :
while True :
time . sleep ( .5 )
if not current_thread . isAlive ( ) :
return False
try :
jobinfo = vm . job_info ( )
data_total = float ( jobinfo [ 3 ] )
2013-04-13 14:34:52 -04:00
# data_processed = float(jobinfo[4])
2010-12-10 16:04:42 -05:00
data_remaining = float ( jobinfo [ 5 ] )
# data_total is 0 if the job hasn't started yet
if not data_total :
continue
if not meter . started :
meter . start ( size = data_total ,
text = progtext )
progress = data_total - data_remaining
meter . update ( progress )
except :
logging . exception ( " Error calling jobinfo " )
return False
return True
if vm . getjobinfo_supported :
t = threading . Thread ( target = jobinfo_cb ,
name = " job progress reporting " ,
args = ( ) )
t . daemon = True
t . start ( )
2013-04-13 14:34:52 -04:00
2012-01-25 11:52:45 -05:00
class vmmInspectionData ( object ) :
def __init__ ( self ) :
self . type = None
self . distro = None
self . major_version = None
self . minor_version = None
self . hostname = None
self . product_name = None
self . product_variant = None
self . icon = None
self . applications = None
2013-04-13 14:34:52 -04:00
2011-05-03 16:17:52 -04:00
class vmmDomain ( vmmLibvirtObject ) :
2012-11-08 14:15:02 +01:00
"""
Class wrapping virDomain libvirt objects . Is also extended to be
backed by a virtinst . Guest object for new VM ' customize before install '
"""
2012-05-14 14:24:56 +01:00
__gsignals__ = {
" status-changed " : ( GObject . SignalFlags . RUN_FIRST , None , [ int , int ] ) ,
" resources-sampled " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
" inspection-changed " : ( GObject . SignalFlags . RUN_FIRST , None , [ ] ) ,
2013-05-13 18:14:11 +08:00
" pre-startup " : ( GObject . SignalFlags . RUN_FIRST , None , [ object ] ) ,
2012-05-14 14:24:56 +01:00
}
2013-07-07 08:42:57 -04:00
def __init__ ( self , conn , backend , key ) :
vmmLibvirtObject . __init__ ( self , conn , backend , key )
2010-02-25 19:35:01 -05:00
2013-07-07 08:42:57 -04:00
self . uuid = key
2010-05-13 10:37:31 -04:00
self . cloning = False
2007-04-12 15:36:04 -04:00
2010-11-29 17:28:52 -05:00
self . record = [ ]
self . maxRecord = {
" diskRdRate " : 10.0 ,
" diskWrRate " : 10.0 ,
" netTxRate " : 10.0 ,
" netRxRate " : 10.0 ,
}
2010-05-13 11:21:01 -04:00
self . _install_abort = False
2011-05-03 16:17:52 -04:00
self . reboot_listener = None
2009-11-17 17:18:09 -05:00
self . _startup_vcpus = None
2011-04-09 22:40:22 -04:00
self . _is_management_domain = None
self . _id = None
self . _name = None
2009-11-17 17:18:09 -05:00
2011-05-03 16:17:52 -04:00
self . _inactive_xml_flags = 0
self . _active_xml_flags = 0
self . lastStatus = libvirt . VIR_DOMAIN_SHUTOFF
2011-07-25 13:52:00 -04:00
self . _getvcpus_supported = None
self . _getjobinfo_supported = None
2010-05-12 12:57:32 -04:00
self . managedsave_supported = False
2011-06-21 11:04:48 -04:00
self . remote_console_supported = False
2010-05-12 12:57:32 -04:00
2011-05-03 16:17:52 -04:00
self . _guest = None
2010-09-08 17:53:51 -04:00
self . _guest_to_define = None
2010-02-08 17:13:36 -05:00
2011-04-11 10:21:19 -04:00
self . _enable_net_poll = False
2010-02-08 17:13:36 -05:00
self . _stats_net_supported = True
2010-02-11 09:30:32 -05:00
self . _stats_net_skip = [ ]
2011-04-11 10:21:19 -04:00
self . _enable_disk_poll = False
2010-02-08 17:13:36 -05:00
self . _stats_disk_supported = True
2010-02-11 09:30:32 -05:00
self . _stats_disk_skip = [ ]
2010-02-08 17:13:36 -05:00
2011-07-18 19:53:55 +01:00
self . inspection = vmmInspectionData ( )
2011-05-03 16:17:52 -04:00
if isinstance ( self . _backend , virtinst . Guest ) :
return
self . _libvirt_init ( )
2011-07-25 13:52:00 -04:00
def _get_getvcpus_supported ( self ) :
if self . _getvcpus_supported is None :
self . _getvcpus_supported = True
try :
self . _backend . vcpus ( )
except libvirt . libvirtError , err :
2013-07-06 11:20:28 -04:00
if virtinst . util . is_error_nosupport ( err ) :
2011-07-25 13:52:00 -04:00
self . _getvcpus_supported = False
return self . _getvcpus_supported
getvcpus_supported = property ( _get_getvcpus_supported )
def _get_getjobinfo_supported ( self ) :
if self . _getjobinfo_supported is None :
2013-07-06 11:20:28 -04:00
self . _getjobinfo_supported = self . conn . check_domain_support (
2011-07-25 13:52:00 -04:00
self . _backend ,
2013-07-06 11:20:28 -04:00
self . conn . SUPPORT_DOMAIN_JOB_INFO )
2011-07-25 13:52:00 -04:00
return self . _getjobinfo_supported
getjobinfo_supported = property ( _get_getjobinfo_supported )
2011-05-03 16:17:52 -04:00
def _libvirt_init ( self ) :
"""
Initialization to do if backed by a libvirt virDomain
"""
self . _reparse_xml ( )
2013-07-06 11:20:28 -04:00
self . managedsave_supported = self . conn . get_dom_managedsave_supported (
self . _backend )
2011-05-03 16:17:52 -04:00
2013-07-06 11:20:28 -04:00
self . remote_console_supported = self . conn . check_domain_support (
self . _backend ,
self . conn . SUPPORT_DOMAIN_CONSOLE_STREAM )
2011-06-21 11:04:48 -04:00
2011-05-03 16:17:52 -04:00
# Determine available XML flags (older libvirt versions will error
# out if passed SECURE_XML, INACTIVE_XML, etc)
( self . _inactive_xml_flags ,
2011-07-22 16:43:26 -04:00
self . _active_xml_flags ) = self . conn . get_dom_flags ( self . _backend )
2011-05-03 16:17:52 -04:00
self . toggle_sample_network_traffic ( )
self . toggle_sample_disk_io ( )
self . force_update_status ( )
# Hook up listeners that need to be cleaned up
self . add_gconf_handle (
self . config . on_stats_enable_net_poll_changed (
self . toggle_sample_network_traffic ) )
self . add_gconf_handle (
self . config . on_stats_enable_disk_poll_changed (
self . toggle_sample_disk_io ) )
self . connect ( " status-changed " , self . _update_start_vcpus )
self . connect ( " config-changed " , self . _reparse_xml )
2013-05-13 18:14:11 +08:00
self . connect ( " pre-startup " , self . _prestartup_nodedev_check )
def _prestartup_nodedev_check ( self , src , ret ) :
ignore = src
2013-05-27 20:04:55 -04:00
error = _ ( " There is more than one ' %s ' device attached to "
2013-05-13 18:14:11 +08:00
" your host, and we can ' t determine which one to "
" use for your guest. \n "
" To fix this, remove and reattach the USB device "
" to your guest using the ' Add Hardware ' wizard. " )
for hostdev in self . get_hostdev_devices ( ) :
devtype = hostdev . type
if devtype != " usb " :
continue
vendor = hostdev . vendor
product = hostdev . product
bus = hostdev . bus
device = hostdev . device
if vendor and product :
count = self . conn . get_nodedevs_number ( " usb_device " ,
vendor ,
product )
if count > 1 and not ( bus and device ) :
prettyname = " %s %s " % ( vendor , product )
ret . append ( error % prettyname )
2011-05-03 16:17:52 -04:00
###########################
# Misc API getter methods #
###########################
2011-03-23 16:56:12 -04:00
2010-02-07 12:10:41 -05:00
def get_name ( self ) :
2012-11-08 14:15:02 +01:00
if self . _name is None :
2011-05-03 16:17:52 -04:00
self . _name = self . _backend . name ( )
return self . _name
2010-02-07 12:10:41 -05:00
def get_id ( self ) :
2012-11-08 14:15:02 +01:00
if self . _id is None :
2011-05-03 16:17:52 -04:00
self . _id = self . _backend . ID ( )
return self . _id
2008-12-17 15:27:06 -05:00
2011-05-03 16:17:52 -04:00
def status ( self ) :
return self . lastStatus
2008-12-17 15:27:06 -05:00
2011-05-03 16:17:52 -04:00
def change_name_backend ( self , newbackend ) :
# Used for changing the domain object after a rename
self . _backend = newbackend
2009-07-26 16:09:23 -04:00
2010-05-13 10:37:31 -04:00
def get_cloning ( self ) :
return self . cloning
def set_cloning ( self , val ) :
self . cloning = bool ( val )
2010-05-13 11:21:01 -04:00
# If manual shutdown or destroy specified, make sure we don't continue
# install process
def get_install_abort ( self ) :
return bool ( self . _install_abort )
2011-07-22 13:13:26 -04:00
def rhel6_defaults ( self ) :
2011-07-22 16:43:26 -04:00
return self . conn . rhel6_defaults ( self . get_emulator ( ) )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
def is_read_only ( self ) :
if self . is_management_domain ( ) :
return True
return False
def is_management_domain ( self ) :
2012-11-08 14:15:02 +01:00
if self . _is_management_domain is None :
2011-05-03 16:17:52 -04:00
self . _is_management_domain = ( self . get_id ( ) == 0 )
return self . _is_management_domain
2013-07-01 14:33:59 -04:00
def has_spicevmc_type_redirdev ( self ) :
devs = self . get_redirdev_devices ( )
for dev in devs :
if dev . type == " spicevmc " :
return True
return False
2011-05-03 16:17:52 -04:00
def get_id_pretty ( self ) :
i = self . get_id ( )
if i < 0 :
return " - "
return str ( i )
#############################
# Internal XML handling API #
#############################
2010-11-29 17:28:52 -05:00
2010-09-08 17:53:51 -04:00
def _invalidate_xml ( self ) :
vmmLibvirtObject . _invalidate_xml ( self )
self . _guest_to_define = None
2011-04-11 11:55:20 -04:00
self . _name = None
self . _id = None
2010-09-08 17:53:51 -04:00
def _get_guest_to_define ( self ) :
if not self . _guest_to_define :
self . _guest_to_define = self . _get_guest ( inactive = True )
return self . _guest_to_define
def _redefine_guest ( self , cb ) :
guest = self . _get_guest_to_define ( )
return cb ( guest )
def _redefine_device ( self , cb , origdev ) :
defguest = self . _get_guest_to_define ( )
dev = find_device ( defguest , origdev )
if dev :
return cb ( dev )
# If we are removing multiple dev from an active VM, a double
# attempt may result in a lookup failure. If device is present
# in the active XML, assume all is good.
if find_device ( self . _get_guest ( ) , origdev ) :
2010-12-10 09:57:42 -05:00
logging . debug ( " Device in active config but not inactive config. " )
2010-09-08 17:53:51 -04:00
return
raise RuntimeError ( _ ( " Could not find specified device in the "
" inactive VM configuration: %s " ) % repr ( origdev ) )
def redefine_cached ( self ) :
if not self . _guest_to_define :
logging . debug ( " No cached XML to define, skipping. " )
return
guest = self . _get_guest_to_define ( )
xml = guest . get_xml_config ( install = False )
self . _redefine_xml ( xml )
2013-06-30 14:33:01 -04:00
def _get_domain_xml ( self , inactive = False , refresh_if_nec = True ) :
2011-05-03 16:17:52 -04:00
return vmmLibvirtObject . get_xml ( self ,
inactive = inactive ,
2013-06-30 14:33:01 -04:00
refresh_if_nec = refresh_if_nec )
2011-05-03 16:17:52 -04:00
2013-06-30 14:33:01 -04:00
def get_xml ( self , inactive = False , refresh_if_nec = True ) :
2011-05-03 16:17:52 -04:00
guest = self . _get_guest ( inactive = inactive ,
2013-06-30 14:33:01 -04:00
refresh_if_nec = refresh_if_nec )
2011-05-03 16:17:52 -04:00
return guest . get_xml_config ( install = False )
2013-06-30 14:33:01 -04:00
def _get_guest ( self , inactive = False , refresh_if_nec = True ) :
xml = self . _get_domain_xml ( inactive , refresh_if_nec )
2011-05-03 16:17:52 -04:00
if inactive :
# If inactive XML requested, always return a fresh guest even
# the current Guest is inactive XML (like when the domain is
# stopped). Callers that request inactive are basically expecting
# a new copy.
return self . _build_guest ( xml )
return self . _guest
2013-07-09 19:50:49 -04:00
get_guest_for_virtinst_func = _get_guest
2011-05-03 16:17:52 -04:00
def _build_guest ( self , xml ) :
2013-07-05 08:59:58 -04:00
return virtinst . Guest ( self . conn . get_backend ( ) ,
2013-07-06 14:12:13 -04:00
parsexml = xml )
2011-05-03 16:17:52 -04:00
def _reparse_xml ( self , ignore = None ) :
self . _guest = self . _build_guest ( self . _get_domain_xml ( ) )
##############################
# Persistent XML change APIs #
##############################
# Rename
def define_name ( self , newname ) :
# Do this, so that _guest_to_define has original inactive XML
self . _invalidate_xml ( )
guest = self . _get_guest_to_define ( )
if guest . name == newname :
return
if self . is_active ( ) :
raise RuntimeError ( _ ( " Cannot rename an active guest " ) )
2012-01-16 22:04:40 -05:00
logging . debug ( " Changing guest name to ' %s ' " , newname )
2011-05-03 16:17:52 -04:00
origxml = guest . get_xml_config ( )
guest . name = newname
newxml = guest . get_xml_config ( )
try :
2011-07-22 16:43:26 -04:00
self . conn . rename_vm ( self , origxml , newxml )
2011-05-03 16:17:52 -04:00
finally :
self . _invalidate_xml ( )
self . emit ( " config-changed " )
# Device Add/Remove
2010-09-08 17:53:51 -04:00
def add_device ( self , devobj ) :
"""
Redefine guest with appended device XML ' devxml '
"""
def change ( guest ) :
guest . add_device ( devobj )
ret = self . _redefine_guest ( change )
self . redefine_cached ( )
return ret
def remove_device ( self , devobj ) :
"""
Remove passed device from the inactive guest XML
"""
# HACK: If serial and console are both present, they both need
# to be removed at the same time
con = None
if hasattr ( devobj , " virtmanager_console_dup " ) :
con = getattr ( devobj , " virtmanager_console_dup " )
def change ( guest ) :
def rmdev ( editdev ) :
if con :
rmcon = find_device ( guest , con )
if rmcon :
guest . remove_device ( rmcon )
guest . remove_device ( editdev )
return self . _redefine_device ( rmdev , devobj )
ret = self . _redefine_guest ( change )
self . redefine_cached ( )
return ret
2011-05-03 16:17:52 -04:00
# CPU define methods
2011-01-13 13:32:19 -05:00
def define_vcpus ( self , vcpus , maxvcpus ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
2010-11-29 12:55:22 -05:00
guest . vcpus = int ( vcpus )
2011-01-13 13:32:19 -05:00
guest . maxvcpus = int ( maxvcpus )
2010-09-08 17:53:51 -04:00
return self . _redefine_guest ( change )
2010-02-07 12:10:41 -05:00
def define_cpuset ( self , cpuset ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
2010-11-29 12:55:22 -05:00
guest . cpuset = cpuset
2010-09-08 17:53:51 -04:00
return self . _redefine_guest ( change )
2009-09-25 09:52:03 -04:00
2010-12-16 16:05:55 -05:00
def define_cpu_topology ( self , sockets , cores , threads ) :
def change ( guest ) :
cpu = guest . cpu
cpu . sockets = sockets
cpu . cores = cores
cpu . threads = threads
return self . _redefine_guest ( change )
2011-03-17 17:41:29 -04:00
def define_cpu ( self , model , vendor , from_host , featurelist ) :
2010-12-16 16:05:55 -05:00
def change ( guest ) :
if from_host :
2013-04-26 15:58:18 -04:00
guest . cpu . copy_host_cpu ( )
elif guest . cpu . model != model :
# Since we don't expose this in the UI, have host value trump
# caps value
guest . cpu . vendor = vendor
2011-03-24 14:53:45 -04:00
2011-01-13 13:14:43 -05:00
guest . cpu . model = model or None
2013-03-19 13:53:46 +09:00
if guest . cpu . model is None :
2013-04-26 15:58:18 -04:00
for f in guest . cpu . features :
guest . cpu . remove_feature ( f )
2013-03-19 13:53:46 +09:00
return
2011-03-17 17:41:29 -04:00
origfeatures = guest . cpu . features
2011-07-13 14:35:34 -04:00
def set_feature ( fname , fpol ) :
for f in origfeatures :
if f . name != fname :
continue
if f . policy != fpol :
if fpol == " default " :
guest . cpu . remove_feature ( f )
else :
f . policy = fpol
return
if fpol != " default " :
guest . cpu . add_feature ( fname , fpol )
# Sync feature lists
for fname , fpol in featurelist :
set_feature ( fname , fpol )
2011-03-17 17:41:29 -04:00
2010-12-16 16:05:55 -05:00
return self . _redefine_guest ( change )
2011-05-03 16:17:52 -04:00
# Mem define methods
2010-02-07 12:10:41 -05:00
def define_both_mem ( self , memory , maxmem ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
2013-07-13 23:07:01 -04:00
guest . memory = int ( memory )
guest . maxmemory = int ( maxmem )
2010-09-08 17:53:51 -04:00
return self . _redefine_guest ( change )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
# Security define methods
2013-02-05 12:28:06 +01:00
def define_seclabel ( self , model , t , label , relabel ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
seclabel = guest . seclabel
seclabel . model = model or None
if not model :
return
2009-09-25 09:52:03 -04:00
2013-02-05 12:28:06 +01:00
if relabel is not None :
if relabel :
seclabel . relabel = " yes "
else :
seclabel . relabel = " no "
2010-09-08 17:53:51 -04:00
seclabel . type = t
if label :
seclabel . label = label
return self . _redefine_guest ( change )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
# Machine config define methods
2011-03-23 16:56:12 -04:00
2010-02-07 12:10:41 -05:00
def define_acpi ( self , newvalue ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
2011-03-24 14:33:35 -04:00
guest . features [ " acpi " ] = newvalue
2010-09-08 17:53:51 -04:00
return self . _redefine_guest ( change )
2010-02-07 12:10:41 -05:00
def define_apic ( self , newvalue ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
2011-03-24 14:33:35 -04:00
guest . features [ " apic " ] = newvalue
2010-09-08 17:53:51 -04:00
return self . _redefine_guest ( change )
2010-02-07 12:10:41 -05:00
def define_clock ( self , newvalue ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
guest . clock . offset = newvalue
return self . _redefine_guest ( change )
2012-01-05 17:35:40 +08:00
def define_machtype ( self , newvalue ) :
def change ( guest ) :
guest . installer . machine = newvalue
return self . _redefine_guest ( change )
2010-02-10 12:16:59 -05:00
def define_description ( self , newvalue ) :
2010-09-08 17:53:51 -04:00
def change ( guest ) :
guest . description = newvalue or None
return self . _redefine_guest ( change )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
# Boot define methods
2010-09-08 17:53:51 -04:00
def set_boot_device ( self , boot_list ) :
def change ( guest ) :
guest . installer . bootconfig . bootorder = boot_list
return self . _redefine_guest ( change )
2010-12-11 22:00:52 -05:00
def set_boot_menu ( self , newval ) :
def change ( guest ) :
guest . installer . bootconfig . enable_bootmenu = bool ( newval )
return self . _redefine_guest ( change )
2010-12-11 23:00:19 -05:00
def set_boot_kernel ( self , kernel , initrd , args ) :
def change ( guest ) :
guest . installer . bootconfig . kernel = kernel or None
guest . installer . bootconfig . initrd = initrd or None
guest . installer . bootconfig . kernel_args = args or None
return self . _redefine_guest ( change )
2011-05-26 12:38:48 -04:00
def set_boot_init ( self , init ) :
def change ( guest ) :
guest . installer . init = init
return self . _redefine_guest ( change )
2010-09-08 17:53:51 -04:00
2011-05-03 16:17:52 -04:00
# Disk define methods
2010-09-08 17:53:51 -04:00
def define_storage_media ( self , devobj , newpath ) :
def change ( editdev ) :
editdev . path = newpath
return self . _redefine_device ( change , devobj )
2010-09-07 18:38:01 -04:00
def define_disk_readonly ( self , devobj , do_readonly ) :
2010-09-08 17:53:51 -04:00
def change ( editdev ) :
editdev . read_only = do_readonly
return self . _redefine_device ( change , devobj )
2010-09-07 18:38:01 -04:00
def define_disk_shareable ( self , devobj , do_shareable ) :
2010-09-08 17:53:51 -04:00
def change ( editdev ) :
editdev . shareable = do_shareable
return self . _redefine_device ( change , devobj )
2010-09-07 18:38:01 -04:00
def define_disk_cache ( self , devobj , new_cache ) :
2010-09-08 17:53:51 -04:00
def change ( editdev ) :
editdev . driver_cache = new_cache or None
return self . _redefine_device ( change , devobj )
2011-07-23 20:41:35 -04:00
def define_disk_io ( self , devobj , val ) :
def change ( editdev ) :
editdev . driver_io = val or None
return self . _redefine_device ( change , devobj )
2010-12-10 19:20:14 -05:00
def define_disk_driver_type ( self , devobj , new_driver_type ) :
def change ( editdev ) :
editdev . driver_type = new_driver_type or None
return self . _redefine_device ( change , devobj )
2012-02-29 16:48:18 +08:00
def define_disk_bus ( self , devobj , newval , addr ) :
2010-12-10 20:33:41 -05:00
def change ( editdev ) :
2012-01-29 15:38:33 -05:00
oldprefix = editdev . get_target_prefix ( ) [ 0 ]
oldbus = editdev . bus
2010-12-10 20:33:41 -05:00
editdev . bus = newval
2012-01-29 15:32:25 -05:00
2012-01-29 15:38:33 -05:00
if oldbus == newval :
2012-01-29 15:32:25 -05:00
return
editdev . address . clear ( )
2012-02-29 16:48:18 +08:00
editdev . set_address ( addr )
2012-01-29 15:32:25 -05:00
2012-01-29 15:38:33 -05:00
if oldprefix == editdev . get_target_prefix ( ) [ 0 ] :
return
2012-01-29 15:32:25 -05:00
used = [ ]
disks = ( self . get_disk_devices ( ) +
self . get_disk_devices ( inactive = True ) )
for d in disks :
used . append ( d . target )
if editdev . target :
used . remove ( editdev . target )
editdev . target = None
editdev . generate_target ( used )
2010-12-10 20:33:41 -05:00
return self . _redefine_device ( change , devobj )
2011-07-13 13:16:19 -04:00
def define_disk_serial ( self , devobj , val ) :
def change ( editdev ) :
if val != editdev . serial :
editdev . serial = val or None
return self . _redefine_device ( change , devobj )
2009-09-25 09:52:03 -04:00
2013-04-16 18:18:03 -04:00
def define_disk_iotune_rbs ( self , devobj , val ) :
2013-02-17 08:40:37 -05:00
def change ( editdev ) :
2013-04-16 18:18:03 -04:00
editdev . iotune_rbs = val
2013-02-17 08:40:37 -05:00
return self . _redefine_device ( change , devobj )
2013-04-16 18:18:03 -04:00
def define_disk_iotune_ris ( self , devobj , val ) :
2013-02-17 08:40:37 -05:00
def change ( editdev ) :
2013-04-16 18:18:03 -04:00
editdev . iotune_ris = val
2013-02-17 08:40:37 -05:00
return self . _redefine_device ( change , devobj )
2013-04-16 18:18:03 -04:00
def define_disk_iotune_tbs ( self , devobj , val ) :
2013-02-17 08:40:37 -05:00
def change ( editdev ) :
2013-04-16 18:18:03 -04:00
editdev . iotune_tbs = val
2013-02-17 08:40:37 -05:00
return self . _redefine_device ( change , devobj )
2013-04-16 18:18:03 -04:00
def define_disk_iotune_tis ( self , devobj , val ) :
2013-02-17 08:40:37 -05:00
def change ( editdev ) :
2013-04-16 18:18:03 -04:00
editdev . iotune_tis = val
2013-02-17 08:40:37 -05:00
return self . _redefine_device ( change , devobj )
2013-04-16 18:18:03 -04:00
def define_disk_iotune_wbs ( self , devobj , val ) :
2013-02-17 08:40:37 -05:00
def change ( editdev ) :
2013-04-16 18:18:03 -04:00
editdev . iotune_wbs = val
2013-02-17 08:40:37 -05:00
return self . _redefine_device ( change , devobj )
2013-04-16 18:18:03 -04:00
def define_disk_iotune_wis ( self , devobj , val ) :
2013-02-17 08:40:37 -05:00
def change ( editdev ) :
2013-04-16 18:18:03 -04:00
editdev . iotune_wis = val
2013-02-17 08:40:37 -05:00
return self . _redefine_device ( change , devobj )
2011-05-03 16:17:52 -04:00
2013-07-13 10:09:00 -04:00
# Network define methods
2011-04-19 13:08:15 +02:00
def define_network_source ( self , devobj , newtype , newsource , newmode ) :
2011-03-17 16:33:40 -04:00
def change ( editdev ) :
if not newtype :
return
editdev . source = None
2011-05-19 12:13:20 -04:00
2011-03-17 16:33:40 -04:00
editdev . type = newtype
editdev . source = newsource
2011-05-19 12:13:20 -04:00
editdev . source_mode = newmode or None
2011-03-17 16:33:40 -04:00
return self . _redefine_device ( change , devobj )
2012-03-05 16:10:15 +08:00
def define_network_model ( self , devobj , newmodel , addr ) :
2010-09-08 17:53:51 -04:00
def change ( editdev ) :
2012-01-29 15:40:53 -05:00
if editdev . model != newmodel :
editdev . address . clear ( )
2012-03-05 16:10:15 +08:00
editdev . set_address ( addr )
2010-09-08 17:53:51 -04:00
editdev . model = newmodel
return self . _redefine_device ( change , devobj )
2010-03-24 00:22:17 -04:00
2011-03-17 15:36:36 -04:00
def define_virtualport ( self , devobj , newtype , newmanagerid ,
newtypeid , newtypeidversion , newinstanceid ) :
2011-03-16 12:43:28 -04:00
def change ( editdev ) :
editdev . virtualport . type = newtype or None
editdev . virtualport . managerid = newmanagerid or None
editdev . virtualport . typeid = newtypeid or None
editdev . virtualport . typeidversion = newtypeidversion or None
editdev . virtualport . instanceid = newinstanceid or None
return self . _redefine_device ( change , devobj )
2011-05-03 16:17:52 -04:00
# Graphics define methods
2010-12-11 20:54:48 -05:00
def define_graphics_password ( self , devobj , newval ) :
def change ( editdev ) :
editdev . passwd = newval or None
return self . _redefine_device ( change , devobj )
def define_graphics_keymap ( self , devobj , newval ) :
def change ( editdev ) :
editdev . keymap = newval
return self . _redefine_device ( change , devobj )
2011-05-04 12:42:00 -04:00
def define_graphics_type ( self , devobj , newval , apply_spice_defaults ) :
def handle_spice ( ) :
if not apply_spice_defaults :
return
guest = self . _get_guest_to_define ( )
is_spice = ( newval == virtinst . VirtualGraphics . TYPE_SPICE )
if is_spice :
guest . add_device ( VirtualCharSpicevmcDevice ( guest . conn ) )
else :
channels = guest . get_devices ( " channel " )
2013-04-11 16:32:00 -04:00
channels = [ x for x in channels if
2011-05-04 12:42:00 -04:00
( x . char_type ==
2013-04-11 16:32:00 -04:00
virtinst . VirtualCharDevice . CHAR_SPICEVMC ) ]
2011-05-04 12:42:00 -04:00
for dev in channels :
guest . remove_device ( dev )
2011-03-17 14:24:36 -04:00
def change ( editdev ) :
editdev . type = newval
2011-05-04 12:42:00 -04:00
handle_spice ( )
2011-04-05 01:35:34 +02:00
2011-03-17 14:24:36 -04:00
return self . _redefine_device ( change , devobj )
2010-12-11 20:54:48 -05:00
2011-05-03 16:17:52 -04:00
# Sound define methods
2010-09-07 18:38:01 -04:00
def define_sound_model ( self , devobj , newmodel ) :
2010-09-08 17:53:51 -04:00
def change ( editdev ) :
2012-01-29 15:40:53 -05:00
if editdev . model != newmodel :
editdev . address . clear ( )
2010-09-08 17:53:51 -04:00
editdev . model = newmodel
return self . _redefine_device ( change , devobj )
2010-03-24 00:22:17 -04:00
2011-05-03 16:17:52 -04:00
# Vide define methods
2010-09-07 18:38:01 -04:00
def define_video_model ( self , devobj , newmodel ) :
2010-09-08 17:53:51 -04:00
def change ( editdev ) :
2013-07-15 11:07:40 -04:00
if newmodel == editdev . model :
2011-05-04 12:45:27 -04:00
return
2013-07-15 11:07:40 -04:00
editdev . model = newmodel
2012-01-29 15:40:53 -05:00
editdev . address . clear ( )
2011-05-04 12:45:27 -04:00
# Clear out heads/ram values so they reset to default. If
# we ever allow editing these values in the UI we should
# drop this
editdev . vram = None
editdev . heads = None
2013-05-27 18:50:25 -04:00
editdev . ram = None
2011-05-04 12:45:27 -04:00
2010-09-08 17:53:51 -04:00
return self . _redefine_device ( change , devobj )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
# Watchdog define methods
2010-09-08 17:53:51 -04:00
def define_watchdog_model ( self , devobj , newval ) :
def change ( editdev ) :
2012-01-29 15:40:53 -05:00
if editdev . model != newval :
editdev . address . clear ( )
2010-09-08 17:53:51 -04:00
editdev . model = newval
return self . _redefine_device ( change , devobj )
def define_watchdog_action ( self , devobj , newval ) :
def change ( editdev ) :
editdev . action = newval
return self . _redefine_device ( change , devobj )
2010-03-24 00:22:17 -04:00
2011-06-23 17:42:03 +02:00
# Smartcard define methods
def define_smartcard_mode ( self , devobj , newmodel ) :
def change ( editdev ) :
editdev . mode = newmodel
2013-07-15 12:36:57 -04:00
editdev . type = editdev . TYPE_DEFAULT
2011-06-23 17:42:03 +02:00
return self . _redefine_device ( change , devobj )
2011-09-23 17:14:15 +02:00
# Controller define methods
def define_controller_model ( self , devobj , newmodel ) :
def change ( editdev ) :
2012-01-16 22:04:40 -05:00
ignore = editdev
2011-09-23 17:14:15 +02:00
guest = self . _get_guest_to_define ( )
ctrls = guest . get_devices ( " controller " )
2013-04-11 16:32:00 -04:00
ctrls = [ x for x in ctrls if ( x . type ==
virtinst . VirtualController . CONTROLLER_TYPE_USB ) ]
2011-09-23 17:14:15 +02:00
for dev in ctrls :
guest . remove_device ( dev )
if newmodel == " ich9-ehci1 " :
guest . add_usb_ich9_controllers ( )
return self . _redefine_device ( change , devobj )
2013-06-25 21:45:08 -04:00
# TPM define methods
def define_tpm_type ( self , devobj , newtype ) :
def change ( editdev ) :
editdev . type = newtype
return self . _redefine_device ( change , devobj )
2011-09-23 17:14:15 +02:00
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
####################
# Hotplug routines #
####################
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
def attach_device ( self , devobj ) :
"""
Hotplug device to running guest
"""
if not self . is_active ( ) :
return
2010-12-13 14:31:27 -05:00
2011-05-03 16:17:52 -04:00
devxml = devobj . get_xml_config ( )
self . _backend . attachDevice ( devxml )
2010-12-13 14:31:27 -05:00
2011-05-03 16:17:52 -04:00
def detach_device ( self , devobj ) :
"""
Hotunplug device from running guest
"""
if not self . is_active ( ) :
return
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
xml = devobj . get_xml_config ( )
self . _backend . detachDevice ( xml )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
def update_device ( self , devobj , flags = 1 ) :
if not self . is_active ( ) :
return
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
# Default flag is VIR_DOMAIN_DEVICE_MODIFY_LIVE
xml = devobj . get_xml_config ( )
self . _backend . updateDeviceFlags ( xml , flags )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
def hotplug_vcpus ( self , vcpus ) :
vcpus = int ( vcpus )
if vcpus != self . vcpu_count ( ) :
self . _backend . setVcpus ( vcpus )
2010-05-12 12:57:32 -04:00
2011-05-03 16:17:52 -04:00
def hotplug_memory ( self , memory ) :
if memory != self . get_memory ( ) :
self . _backend . setMemory ( memory )
def hotplug_maxmem ( self , maxmem ) :
if maxmem != self . maximum_memory ( ) :
self . _backend . setMaxMemory ( maxmem )
def hotplug_both_mem ( self , memory , maxmem ) :
2012-01-16 22:04:40 -05:00
logging . info ( " Hotplugging curmem= %s maxmem= %s for VM ' %s ' " ,
memory , maxmem , self . get_name ( ) )
2011-05-03 16:17:52 -04:00
if self . is_active ( ) :
actual_cur = self . get_memory ( )
if memory :
if maxmem < actual_cur :
# Set current first to avoid error
self . hotplug_memory ( memory )
self . hotplug_maxmem ( maxmem )
else :
self . hotplug_maxmem ( maxmem )
self . hotplug_memory ( memory )
else :
self . hotplug_maxmem ( maxmem )
def hotplug_storage_media ( self , devobj , newpath ) :
devobj . path = newpath
self . attach_device ( devobj )
def hotplug_graphics_password ( self , devobj , newval ) :
devobj . passwd = newval or None
self . update_device ( devobj )
2012-10-16 23:26:06 +02:00
def hotplug_description ( self , desc ) :
# We already fake hotplug like behavior, by reading the
# description from the inactive XML from a running VM
#
# libvirt since 0.9.10 provides a SetMetadata API that provides
# actual <description> 'hotplug', and using that means checkig
# for support, version, etc.
2013-07-06 11:20:28 -04:00
if not self . conn . check_domain_support ( self . _backend ,
self . conn . SUPPORT_DOMAIN_SET_METADATA ) :
2012-10-16 23:26:06 +02:00
return
flags = ( libvirt . VIR_DOMAIN_AFFECT_LIVE |
libvirt . VIR_DOMAIN_AFFECT_CONFIG )
self . _backend . setMetadata (
libvirt . VIR_DOMAIN_METADATA_DESCRIPTION ,
desc , None , None , flags )
2011-05-03 16:17:52 -04:00
########################
# Libvirt API wrappers #
########################
def _define ( self , newxml ) :
2011-07-22 16:43:26 -04:00
self . conn . define_domain ( newxml )
2011-05-03 16:17:52 -04:00
def _XMLDesc ( self , flags ) :
return self . _backend . XMLDesc ( flags )
def pin_vcpu ( self , vcpu_num , pinlist ) :
self . _backend . pinVcpu ( vcpu_num , pinlist )
def vcpu_info ( self ) :
2011-07-25 13:52:00 -04:00
if self . is_active ( ) and self . getvcpus_supported :
return self . _backend . vcpus ( )
2011-05-03 16:17:52 -04:00
return [ [ ] , [ ] ]
def get_autostart ( self ) :
return self . _backend . autostart ( )
def set_autostart ( self , val ) :
if self . get_autostart ( ) == val :
return
self . _backend . setAutostart ( val )
def job_info ( self ) :
return self . _backend . jobInfo ( )
def abort_job ( self ) :
self . _backend . abortJob ( )
2009-09-25 09:52:03 -04:00
2011-06-21 11:04:48 -04:00
def open_console ( self , devname , stream , flags = 0 ) :
return self . _backend . openConsole ( devname , stream , flags )
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
########################
# XML Parsing routines #
########################
2011-05-26 12:38:48 -04:00
def is_container ( self ) :
return self . _get_guest ( ) . installer . is_container ( )
def is_xenpv ( self ) :
return self . _get_guest ( ) . installer . is_xenpv ( )
def is_hvm ( self ) :
return self . _get_guest ( ) . installer . is_hvm ( )
2011-05-03 16:17:52 -04:00
def get_uuid ( self ) :
return self . uuid
def get_abi_type ( self ) :
return self . _get_guest ( ) . installer . os_type
def get_hv_type ( self ) :
return self . _get_guest ( ) . installer . type
2010-02-07 12:10:41 -05:00
def get_pretty_hv_type ( self ) :
return util . pretty_hv ( self . get_abi_type ( ) , self . get_hv_type ( ) )
def get_arch ( self ) :
2010-12-13 12:48:06 -05:00
return self . _get_guest ( ) . installer . arch
2011-05-26 12:38:48 -04:00
def get_init ( self ) :
return self . _get_guest ( ) . installer . init
2010-02-07 12:10:41 -05:00
def get_emulator ( self ) :
2010-12-13 12:48:06 -05:00
return self . _get_guest ( ) . emulator
2010-02-07 12:10:41 -05:00
def get_acpi ( self ) :
2011-03-24 14:33:35 -04:00
return self . _get_guest ( ) . features [ " acpi " ]
2010-02-07 12:10:41 -05:00
def get_apic ( self ) :
2011-03-24 14:33:35 -04:00
return self . _get_guest ( ) . features [ " apic " ]
2010-02-07 12:10:41 -05:00
def get_clock ( self ) :
2010-12-13 12:48:06 -05:00
return self . _get_guest ( ) . clock . offset
2012-01-05 17:35:40 +08:00
def get_machtype ( self ) :
return self . _get_guest ( ) . installer . machine
2009-09-25 09:52:03 -04:00
2010-02-10 12:16:59 -05:00
def get_description ( self ) :
2011-03-15 16:23:15 -04:00
# Always show the inactive <description>, let's us fake hotplug
# for a field that's strictly metadata
return self . _get_guest ( inactive = True ) . description
2010-02-10 12:16:59 -05:00
2010-11-29 12:55:22 -05:00
def get_memory ( self ) :
2013-07-13 23:07:01 -04:00
return int ( self . _get_guest ( ) . memory )
2010-11-29 12:55:22 -05:00
def maximum_memory ( self ) :
2013-07-13 23:07:01 -04:00
return int ( self . _get_guest ( ) . maxmemory )
2010-11-29 12:55:22 -05:00
def vcpu_count ( self ) :
2010-12-13 12:48:06 -05:00
return int ( self . _get_guest ( ) . vcpus )
2010-02-07 12:10:41 -05:00
def vcpu_max_count ( self ) :
2011-01-13 13:32:19 -05:00
guest = self . _get_guest ( )
has_xml_max = ( guest . vcpus != guest . maxvcpus )
if has_xml_max or not self . is_active ( ) :
return guest . maxvcpus
2012-11-08 14:15:02 +01:00
if self . _startup_vcpus is None :
2010-12-13 12:48:06 -05:00
self . _startup_vcpus = int ( self . vcpu_count ( ) )
2010-02-07 12:10:41 -05:00
return int ( self . _startup_vcpus )
2009-11-15 15:17:03 -05:00
2010-11-29 12:55:22 -05:00
def vcpu_pinning ( self ) :
2010-12-13 12:48:06 -05:00
return self . _get_guest ( ) . cpuset or " "
2010-12-16 16:05:55 -05:00
def get_cpu_config ( self ) :
return self . _get_guest ( ) . cpu
2010-02-07 12:10:41 -05:00
def get_boot_device ( self ) :
2010-12-13 12:48:06 -05:00
return self . _get_guest ( ) . installer . bootconfig . bootorder
2010-12-11 22:00:52 -05:00
def get_boot_menu ( self ) :
guest = self . _get_guest ( )
return bool ( guest . installer . bootconfig . enable_bootmenu )
2010-12-11 23:00:19 -05:00
def get_boot_kernel_info ( self ) :
guest = self . _get_guest ( )
kernel = guest . installer . bootconfig . kernel
initrd = guest . installer . bootconfig . initrd
args = guest . installer . bootconfig . kernel_args
return ( kernel , initrd , args )
2010-02-07 12:10:41 -05:00
def get_seclabel ( self ) :
2013-02-05 12:28:06 +01:00
seclabel = self . _get_guest ( ) . seclabel
model = seclabel . model
t = seclabel . type or " dynamic "
label = seclabel . label or " "
relabel = getattr ( seclabel , " relabel " , None )
if relabel is not None :
if relabel == " yes " :
relabel = True
else :
relabel = False
2009-09-25 09:52:03 -04:00
2013-02-05 12:28:06 +01:00
return [ model , t , label , relabel ]
2009-09-25 09:52:03 -04:00
2011-05-03 16:17:52 -04:00
# XML Device listing
2009-09-25 09:52:03 -04:00
2010-02-07 12:10:41 -05:00
def get_serial_devs ( self ) :
2010-09-03 17:56:40 -04:00
devs = self . get_char_devices ( )
devlist = [ ]
2009-11-04 11:07:03 -05:00
2013-04-11 16:32:00 -04:00
devlist + = [ x for x in devs if x . virtual_device_type == " serial " ]
devlist + = [ x for x in devs if x . virtual_device_type == " console " ]
2010-09-03 17:56:40 -04:00
return devlist
2010-02-12 16:33:43 -05:00
2010-09-07 18:38:01 -04:00
def _build_device_list ( self , device_type ,
2013-06-30 14:33:01 -04:00
refresh_if_nec = True , inactive = False ) :
guest = self . _get_guest ( refresh_if_nec = refresh_if_nec ,
2010-09-03 15:19:54 -04:00
inactive = inactive )
devs = guest . get_devices ( device_type )
2010-09-03 14:10:04 -04:00
2010-09-07 18:38:01 -04:00
count = 0
for dev in devs :
2010-09-08 17:53:51 -04:00
dev . vmmindex = count
2010-09-07 18:38:01 -04:00
count + = 1
return devs
2013-06-30 14:33:01 -04:00
def get_network_devices ( self , refresh_if_nec = True ) :
return self . _build_device_list ( " interface " , refresh_if_nec )
2010-09-07 18:38:01 -04:00
def get_video_devices ( self ) :
return self . _build_device_list ( " video " )
def get_hostdev_devices ( self ) :
return self . _build_device_list ( " hostdev " )
def get_watchdog_devices ( self ) :
return self . _build_device_list ( " watchdog " )
def get_input_devices ( self ) :
return self . _build_device_list ( " input " )
def get_graphics_devices ( self ) :
return self . _build_device_list ( " graphics " )
def get_sound_devices ( self ) :
return self . _build_device_list ( " sound " )
2010-12-16 12:41:47 -05:00
def get_controller_devices ( self ) :
return self . _build_device_list ( " controller " )
2011-05-19 15:18:33 -04:00
def get_filesystem_devices ( self ) :
return self . _build_device_list ( " filesystem " )
2011-06-23 17:42:03 +02:00
def get_smartcard_devices ( self ) :
return self . _build_device_list ( " smartcard " )
2011-09-02 03:23:27 +02:00
def get_redirdev_devices ( self ) :
return self . _build_device_list ( " redirdev " )
2013-06-25 21:45:08 -04:00
def get_tpm_devices ( self ) :
return self . _build_device_list ( " tpm " )
2010-09-07 18:38:01 -04:00
2013-06-30 14:33:01 -04:00
def get_disk_devices ( self , refresh_if_nec = True , inactive = False ) :
devs = self . _build_device_list ( " disk " , refresh_if_nec , inactive )
2010-09-07 18:38:01 -04:00
2010-09-03 14:10:04 -04:00
# Iterate through all disks and calculate what number they are
# HACK: We are making a variable in VirtualDisk to store the index
idx_mapping = { }
2010-09-03 15:19:54 -04:00
for dev in devs :
devtype = dev . device
bus = dev . bus
2010-09-03 14:10:04 -04:00
key = devtype + ( bus or " " )
2010-12-10 11:47:07 -05:00
if key not in idx_mapping :
2010-09-03 14:10:04 -04:00
idx_mapping [ key ] = 1
2010-09-03 15:19:54 -04:00
dev . disk_bus_index = idx_mapping [ key ]
2010-09-03 14:10:04 -04:00
idx_mapping [ key ] + = 1
2010-09-03 15:19:54 -04:00
return devs
2009-09-25 09:52:03 -04:00
2010-02-07 12:10:41 -05:00
def get_char_devices ( self ) :
2010-09-03 17:56:40 -04:00
devs = [ ]
2010-09-07 18:38:01 -04:00
serials = self . _build_device_list ( " serial " )
parallels = self . _build_device_list ( " parallel " )
consoles = self . _build_device_list ( " console " )
2011-04-05 01:35:32 +02:00
channels = self . _build_device_list ( " channel " )
2010-09-03 17:56:40 -04:00
2011-04-05 01:35:32 +02:00
for devicelist in [ serials , parallels , consoles , channels ] :
2010-09-03 17:56:40 -04:00
devs . extend ( devicelist )
# Don't display <console> if it's just a duplicate of <serial>
if ( len ( consoles ) > 0 and len ( serials ) > 0 ) :
con = consoles [ 0 ]
ser = serials [ 0 ]
if ( con . char_type == ser . char_type and
con . target_type is None or con . target_type == " serial " ) :
2010-09-07 18:38:01 -04:00
ser . virtmanager_console_dup = con
2010-09-03 17:56:40 -04:00
devs . remove ( con )
return devs
2009-10-05 18:00:13 -04:00
2011-05-03 16:17:52 -04:00
############################
# Domain lifecycle methods #
############################
2012-02-10 14:07:51 -05:00
# All these methods are usually run asynchronously from threads, so
# let's be extra careful and have anything which might touch UI
2012-05-14 14:24:56 +01:00
# or GObject.props invoked in an idle callback
2012-02-10 14:07:51 -05:00
2011-05-03 16:17:52 -04:00
def _unregister_reboot_listener ( self ) :
2012-11-08 14:15:02 +01:00
if self . reboot_listener is None :
2011-05-03 16:17:52 -04:00
return
try :
2012-02-10 14:07:51 -05:00
self . idle_add ( self . disconnect , self . reboot_listener )
2011-05-03 16:17:52 -04:00
self . reboot_listener = None
except :
pass
def manual_reboot ( self ) :
"""
Attempt a manual reboot by invoking ' shutdown ' , then listen
for a state change and restart the VM
"""
def reboot_listener ( vm , ignore1 , ignore2 , self ) :
if vm . is_crashed ( ) :
# Abandon reboot plans
self . reboot_listener = None
return True
if not vm . is_shutoff ( ) :
# Not shutoff, continue waiting
return
try :
logging . debug ( " Fake reboot detected shutdown. Restarting VM " )
vm . startup ( )
except :
logging . exception ( " Fake reboot startup failed " )
self . reboot_listener = None
return True
self . _unregister_reboot_listener ( )
# Request a shutdown
self . shutdown ( )
2012-02-10 14:07:51 -05:00
def add_reboot ( ) :
self . reboot_listener = self . connect_opt_out ( " status-changed " ,
2011-05-03 16:17:52 -04:00
reboot_listener , self )
2012-02-10 14:07:51 -05:00
self . idle_add ( add_reboot )
2011-05-03 16:17:52 -04:00
def shutdown ( self ) :
2012-02-10 14:07:51 -05:00
self . _install_abort = True
2011-05-03 16:17:52 -04:00
self . _unregister_reboot_listener ( )
self . _backend . shutdown ( )
2012-02-10 14:07:51 -05:00
self . idle_add ( self . force_update_status )
2011-05-03 16:17:52 -04:00
def reboot ( self ) :
2012-02-10 14:07:51 -05:00
self . _install_abort = True
2011-05-03 16:17:52 -04:00
self . _backend . reboot ( 0 )
2012-02-10 14:07:51 -05:00
self . idle_add ( self . force_update_status )
def destroy ( self ) :
self . _install_abort = True
self . _unregister_reboot_listener ( )
self . _backend . destroy ( )
self . idle_add ( self . force_update_status )
2011-05-03 16:17:52 -04:00
2013-03-16 17:59:32 -04:00
def reset ( self ) :
self . _install_abort = True
self . _backend . reset ( 0 )
self . idle_add ( self . force_update_status )
2011-05-03 16:17:52 -04:00
def startup ( self ) :
if self . get_cloning ( ) :
raise RuntimeError ( _ ( " Cannot start guest while cloning "
" operation in progress " ) )
2013-05-13 18:14:11 +08:00
pre_startup_ret = [ ]
self . emit ( " pre-startup " , pre_startup_ret )
for error in pre_startup_ret :
raise RuntimeError ( error )
2011-05-03 16:17:52 -04:00
self . _backend . create ( )
2012-02-10 14:07:51 -05:00
self . idle_add ( self . force_update_status )
2011-05-03 16:17:52 -04:00
def suspend ( self ) :
self . _backend . suspend ( )
2012-02-10 14:07:51 -05:00
self . idle_add ( self . force_update_status )
2011-05-03 16:17:52 -04:00
def delete ( self ) :
2012-07-08 16:06:16 -04:00
try :
self . removeSavedImage ( )
except :
logging . exception ( " Failed to remove managed save state " )
2011-05-03 16:17:52 -04:00
self . _backend . undefine ( )
def resume ( self ) :
if self . get_cloning ( ) :
raise RuntimeError ( _ ( " Cannot resume guest while cloning "
" operation in progress " ) )
self . _backend . resume ( )
2012-02-10 14:07:51 -05:00
self . idle_add ( self . force_update_status )
2011-05-03 16:17:52 -04:00
def hasSavedImage ( self ) :
if not self . managedsave_supported :
return False
return self . _backend . hasManagedSaveImage ( 0 )
2012-07-08 16:06:16 -04:00
def removeSavedImage ( self ) :
if not self . hasSavedImage ( ) :
return
self . _backend . managedSaveRemove ( 0 )
2011-05-03 16:17:52 -04:00
def save ( self , filename = None , meter = None ) :
2012-02-10 14:07:51 -05:00
self . _install_abort = True
2011-05-03 16:17:52 -04:00
if meter :
start_job_progress_thread ( self , meter , _ ( " Saving domain to disk " ) )
if not self . managedsave_supported :
self . _backend . save ( filename )
else :
self . _backend . managedSave ( 0 )
2012-02-10 14:07:51 -05:00
self . idle_add ( self . force_update_status )
2011-05-03 16:17:52 -04:00
def support_downtime ( self ) :
2013-07-06 11:20:28 -04:00
return self . conn . check_domain_support ( self . _backend ,
self . conn . SUPPORT_DOMAIN_MIGRATE_DOWNTIME )
2011-05-03 16:17:52 -04:00
def migrate_set_max_downtime ( self , max_downtime , flag = 0 ) :
self . _backend . migrateSetMaxDowntime ( max_downtime , flag )
def migrate ( self , destconn , interface = None , rate = 0 ,
live = False , secure = False , meter = None ) :
2012-02-10 14:07:51 -05:00
self . _install_abort = True
2011-05-03 16:17:52 -04:00
newname = None
flags = 0
if self . status ( ) == libvirt . VIR_DOMAIN_RUNNING and live :
flags | = libvirt . VIR_MIGRATE_LIVE
if secure :
flags | = libvirt . VIR_MIGRATE_PEER2PEER
flags | = libvirt . VIR_MIGRATE_TUNNELLED
2013-07-05 08:59:58 -04:00
destconn = destconn . get_backend ( ) . libvirtconn
2012-01-16 22:04:40 -05:00
logging . debug ( " Migrating: conn= %s flags= %s dname= %s uri= %s rate= %s " ,
2013-07-05 08:59:58 -04:00
destconn , flags , newname , interface , rate )
2011-05-03 16:17:52 -04:00
if meter :
start_job_progress_thread ( self , meter , _ ( " Migrating domain " ) )
2013-07-05 08:59:58 -04:00
self . _backend . migrate ( destconn , flags , newname , interface , rate )
2012-02-10 14:07:51 -05:00
def define_cb ( ) :
newxml = self . get_xml ( inactive = True )
destconn . define_domain ( newxml )
self . idle_add ( define_cb )
2013-07-07 11:06:15 -04:00
# Don't schedule any conn update, migrate dialog handles it for us
2011-05-03 16:17:52 -04:00
###################
# Stats helpers ###
###################
2009-11-04 08:46:09 -05:00
2010-02-07 12:10:41 -05:00
def _sample_mem_stats ( self , info ) :
2011-07-14 16:50:54 -04:00
curmem = info [ 2 ]
if not self . is_active ( ) :
curmem = 0
2011-07-11 21:22:50 -04:00
2013-04-28 00:42:32 +02:00
pcentCurrMem = curmem * 100.0 / self . maximum_memory ( )
2011-07-11 21:22:50 -04:00
pcentCurrMem = max ( 0.0 , min ( pcentCurrMem , 100.0 ) )
2010-04-07 16:36:59 -04:00
2011-07-14 16:50:54 -04:00
return pcentCurrMem , curmem
2009-11-04 08:46:09 -05:00
2010-02-07 12:10:41 -05:00
def _sample_cpu_stats ( self , info , now ) :
prevCpuTime = 0
prevTimestamp = 0
2011-07-11 21:22:50 -04:00
cpuTime = 0
cpuTimeAbs = 0
pcentHostCpu = 0
2011-07-12 08:49:47 -04:00
pcentGuestCpu = 0
2011-07-11 21:22:50 -04:00
2010-02-07 12:10:41 -05:00
if len ( self . record ) > 0 :
prevTimestamp = self . record [ 0 ] [ " timestamp " ]
prevCpuTime = self . record [ 0 ] [ " cpuTimeAbs " ]
2009-11-04 08:46:09 -05:00
2010-02-07 12:10:41 -05:00
if not ( info [ 0 ] in [ libvirt . VIR_DOMAIN_SHUTOFF ,
libvirt . VIR_DOMAIN_CRASHED ] ) :
2011-08-23 15:47:31 -04:00
guestcpus = info [ 3 ]
2010-02-07 12:10:41 -05:00
cpuTime = info [ 4 ] - prevCpuTime
cpuTimeAbs = info [ 4 ]
2011-07-22 16:43:26 -04:00
hostcpus = self . conn . host_active_processor_count ( )
2009-11-04 16:30:51 -05:00
2011-07-12 08:49:47 -04:00
pcentbase = ( ( ( cpuTime ) * 100.0 ) /
( ( now - prevTimestamp ) * 1000.0 * 1000.0 * 1000.0 ) )
pcentHostCpu = pcentbase / hostcpus
pcentGuestCpu = pcentbase / guestcpus
2009-11-04 16:30:51 -05:00
2011-07-11 21:22:50 -04:00
pcentHostCpu = max ( 0.0 , min ( 100.0 , pcentHostCpu ) )
2011-07-12 08:49:47 -04:00
pcentGuestCpu = max ( 0.0 , min ( 100.0 , pcentGuestCpu ) )
2011-07-11 21:22:50 -04:00
2011-07-12 08:49:47 -04:00
return cpuTime , cpuTimeAbs , pcentHostCpu , pcentGuestCpu
2009-11-04 16:30:51 -05:00
2010-02-07 12:10:41 -05:00
def _get_cur_rate ( self , what ) :
if len ( self . record ) > 1 :
2010-11-29 14:06:43 -05:00
ret = ( float ( self . record [ 0 ] [ what ] -
self . record [ 1 ] [ what ] ) /
float ( self . record [ 0 ] [ " timestamp " ] -
self . record [ 1 ] [ " timestamp " ] ) )
2010-02-07 12:10:41 -05:00
else :
ret = 0.0
2013-04-13 14:34:52 -04:00
return max ( ret , 0 , 0 ) # avoid negative values at poweroff
2009-11-05 14:59:11 -05:00
2010-02-07 12:10:41 -05:00
def _set_max_rate ( self , record , what ) :
if record [ what ] > self . maxRecord [ what ] :
self . maxRecord [ what ] = record [ what ]
2011-07-25 15:09:42 -04:00
def _get_max_rate ( self , name1 , name2 ) :
return float ( max ( self . maxRecord [ name1 ] , self . maxRecord [ name2 ] ) )
2009-11-04 16:30:51 -05:00
2011-05-03 16:17:52 -04:00
def _get_record_helper ( self , record_name ) :
if len ( self . record ) == 0 :
return 0
return self . record [ 0 ] [ record_name ]
2006-06-27 14:15:28 -04:00
2010-02-07 12:10:41 -05:00
def _vector_helper ( self , record_name ) :
vector = [ ]
stats = self . record
for i in range ( self . config . get_stats_history_length ( ) + 1 ) :
if i < len ( stats ) :
vector . append ( stats [ i ] [ record_name ] / 100.0 )
else :
vector . append ( 0 )
return vector
2007-04-11 14:48:36 -04:00
2011-07-25 15:09:42 -04:00
def _in_out_vector_helper ( self , name1 , name2 , ceil ) :
2010-02-07 12:10:41 -05:00
vector = [ ]
stats = self . record
2011-07-25 15:09:42 -04:00
if ceil is None :
ceil = self . _get_max_rate ( name1 , name2 )
2010-02-12 13:37:04 -05:00
maxlen = self . config . get_stats_history_length ( )
2011-07-25 15:09:42 -04:00
2010-12-10 11:47:07 -05:00
for n in [ name1 , name2 ] :
2010-02-12 13:37:04 -05:00
for i in range ( maxlen + 1 ) :
2010-02-07 12:10:41 -05:00
if i < len ( stats ) :
2010-12-10 11:47:07 -05:00
vector . append ( float ( stats [ i ] [ n ] ) / ceil )
2010-02-07 12:10:41 -05:00
else :
vector . append ( 0.0 )
return vector
2009-09-25 09:52:03 -04:00
2010-02-07 12:10:41 -05:00
def in_out_vector_limit ( self , data , limit ) :
2010-12-10 11:47:07 -05:00
l = len ( data ) / 2
2011-07-11 21:22:50 -04:00
end = min ( l , limit )
2010-02-07 12:10:41 -05:00
if l > limit :
2010-12-10 11:47:07 -05:00
data = data [ 0 : end ] + data [ l : l + end ]
2011-07-11 21:22:50 -04:00
2013-04-11 16:32:00 -04:00
return [ ( x + y ) / 2 for x , y in zip ( data [ 0 : end ] , data [ end : end * 2 ] ) ]
2009-09-25 09:52:03 -04:00
2013-04-17 17:39:25 -04:00
def toggle_sample_network_traffic ( self ) :
2011-05-03 16:17:52 -04:00
self . _enable_net_poll = self . config . get_stats_enable_net_poll ( )
2009-05-12 13:09:08 -04:00
2011-05-03 16:17:52 -04:00
if self . _enable_net_poll and len ( self . record ) > 1 :
rxBytes , txBytes = self . _sample_network_traffic ( )
self . record [ 0 ] [ " netRxKB " ] = rxBytes / 1024
self . record [ 0 ] [ " netTxKB " ] = txBytes / 1024
2010-03-23 22:15:53 -04:00
2013-04-17 17:39:25 -04:00
def toggle_sample_disk_io ( self ) :
2011-05-03 16:17:52 -04:00
self . _enable_disk_poll = self . config . get_stats_enable_disk_poll ( )
2010-12-11 21:34:09 -05:00
2011-05-03 16:17:52 -04:00
if self . _enable_disk_poll and len ( self . record ) > 1 :
rdBytes , wrBytes = self . _sample_disk_io ( )
self . record [ 0 ] [ " diskRdKB " ] = rdBytes / 1024
self . record [ 0 ] [ " diskWrKB " ] = wrBytes / 1024
2009-07-09 14:35:55 -04:00
2010-03-24 00:22:17 -04:00
2011-05-03 16:17:52 -04:00
###################
# Stats accessors #
###################
2010-03-24 00:22:17 -04:00
2011-05-03 16:17:52 -04:00
def stats_memory ( self ) :
return self . _get_record_helper ( " curmem " )
def cpu_time ( self ) :
return self . _get_record_helper ( " cpuTime " )
2011-07-11 21:22:50 -04:00
def host_cpu_time_percentage ( self ) :
return self . _get_record_helper ( " cpuHostPercent " )
2011-07-12 08:49:47 -04:00
def guest_cpu_time_percentage ( self ) :
return self . _get_record_helper ( " cpuGuestPercent " )
2011-05-03 16:17:52 -04:00
def network_rx_rate ( self ) :
return self . _get_record_helper ( " netRxRate " )
def network_tx_rate ( self ) :
return self . _get_record_helper ( " netTxRate " )
def disk_read_rate ( self ) :
return self . _get_record_helper ( " diskRdRate " )
def disk_write_rate ( self ) :
return self . _get_record_helper ( " diskWrRate " )
2010-03-24 00:22:17 -04:00
2011-05-03 16:17:52 -04:00
def get_memory_pretty ( self ) :
return util . pretty_mem ( self . get_memory ( ) )
def maximum_memory_pretty ( self ) :
return util . pretty_mem ( self . maximum_memory ( ) )
2010-03-24 00:22:17 -04:00
2011-05-03 16:17:52 -04:00
def network_traffic_rate ( self ) :
return self . network_tx_rate ( ) + self . network_rx_rate ( )
2011-07-25 15:09:42 -04:00
def network_traffic_max_rate ( self ) :
return self . _get_max_rate ( " netRxRate " , " netTxRate " )
2011-05-03 16:17:52 -04:00
def disk_io_rate ( self ) :
return self . disk_read_rate ( ) + self . disk_write_rate ( )
2011-07-25 15:09:42 -04:00
def disk_io_max_rate ( self ) :
return self . _get_max_rate ( " diskRdRate " , " diskWrRate " )
2010-03-24 00:22:17 -04:00
2011-07-11 21:22:50 -04:00
def host_cpu_time_vector ( self ) :
return self . _vector_helper ( " cpuHostPercent " )
2011-07-12 08:49:47 -04:00
def guest_cpu_time_vector ( self ) :
return self . _vector_helper ( " cpuGuestPercent " )
2011-05-03 16:17:52 -04:00
def stats_memory_vector ( self ) :
return self . _vector_helper ( " currMemPercent " )
2011-07-25 15:09:42 -04:00
def network_traffic_vector ( self , ceil = None ) :
return self . _in_out_vector_helper ( " netRxRate " , " netTxRate " , ceil )
def disk_io_vector ( self , ceil = None ) :
return self . _in_out_vector_helper ( " diskRdRate " , " diskWrRate " , ceil )
2010-03-24 00:22:17 -04:00
2011-07-11 21:22:50 -04:00
def host_cpu_time_vector_limit ( self , limit ) :
cpudata = self . host_cpu_time_vector ( )
2011-05-03 16:17:52 -04:00
if len ( cpudata ) > limit :
cpudata = cpudata [ 0 : limit ]
return cpudata
2011-07-12 08:49:47 -04:00
def guest_cpu_time_vector_limit ( self , limit ) :
cpudata = self . guest_cpu_time_vector ( )
if len ( cpudata ) > limit :
cpudata = cpudata [ 0 : limit ]
return cpudata
2011-07-25 15:09:42 -04:00
def network_traffic_vector_limit ( self , limit , ceil = None ) :
return self . in_out_vector_limit ( self . network_traffic_vector ( ceil ) ,
limit )
def disk_io_vector_limit ( self , limit , ceil = None ) :
return self . in_out_vector_limit ( self . disk_io_vector ( ceil ) , limit )
2010-03-24 00:22:17 -04:00
2011-05-03 16:17:52 -04:00
###################
# Status helpers ##
###################
2009-07-09 14:35:55 -04:00
2010-05-13 12:37:06 -04:00
def _update_start_vcpus ( self , ignore , oldstatus , status ) :
2010-12-09 11:22:35 -05:00
ignore = status
2010-12-10 11:47:07 -05:00
if oldstatus not in [ libvirt . VIR_DOMAIN_SHUTDOWN ,
libvirt . VIR_DOMAIN_SHUTOFF ,
libvirt . VIR_DOMAIN_CRASHED ] :
2010-02-27 10:42:43 -05:00
return
# Want to track the startup vcpu amount, which is the
# cap of how many VCPUs can be added
self . _startup_vcpus = None
self . vcpu_max_count ( )
2011-05-03 16:17:52 -04:00
def run_status ( self ) :
2012-10-14 00:00:38 -04:00
status = self . status ( )
if status == libvirt . VIR_DOMAIN_RUNNING :
2011-05-03 16:17:52 -04:00
return _ ( " Running " )
2012-10-14 00:00:38 -04:00
elif status == libvirt . VIR_DOMAIN_PAUSED :
2011-05-03 16:17:52 -04:00
return _ ( " Paused " )
2012-10-14 00:00:38 -04:00
elif status == libvirt . VIR_DOMAIN_SHUTDOWN :
2011-05-03 16:17:52 -04:00
return _ ( " Shutting Down " )
2012-10-14 00:00:38 -04:00
elif status == libvirt . VIR_DOMAIN_SHUTOFF :
2011-07-30 22:15:44 +02:00
if self . hasSavedImage ( ) :
return _ ( " Saved " )
else :
return _ ( " Shutoff " )
2012-10-14 00:00:38 -04:00
elif status == libvirt . VIR_DOMAIN_CRASHED :
2011-05-03 16:17:52 -04:00
return _ ( " Crashed " )
2012-10-14 00:00:38 -04:00
elif ( hasattr ( libvirt , " VIR_DOMAIN_PMSUSPENDED " ) and
status == libvirt . VIR_DOMAIN_PMSUSPENDED ) :
return _ ( " Suspended " )
2012-10-29 18:55:51 -04:00
logging . debug ( " Unknown status %d , returning ' Unknown ' " )
2012-10-14 00:00:38 -04:00
return _ ( " Unknown " )
2011-05-03 16:17:52 -04:00
def _normalize_status ( self , status ) :
if status == libvirt . VIR_DOMAIN_NOSTATE :
return libvirt . VIR_DOMAIN_RUNNING
elif status == libvirt . VIR_DOMAIN_BLOCKED :
return libvirt . VIR_DOMAIN_RUNNING
return status
def is_active ( self ) :
return not self . is_shutoff ( )
def is_shutoff ( self ) :
return self . status ( ) == libvirt . VIR_DOMAIN_SHUTOFF
def is_crashed ( self ) :
return self . status ( ) == libvirt . VIR_DOMAIN_CRASHED
def is_stoppable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_RUNNING ,
libvirt . VIR_DOMAIN_PAUSED ]
def is_destroyable ( self ) :
return ( self . is_stoppable ( ) or
self . status ( ) in [ libvirt . VIR_DOMAIN_CRASHED ] )
def is_runable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_SHUTOFF ,
libvirt . VIR_DOMAIN_CRASHED ]
def is_pauseable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_RUNNING ]
def is_unpauseable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_PAUSED ]
def is_paused ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_PAUSED ]
2011-07-12 11:50:11 -04:00
def run_status_icon_name ( self ) :
status_icons = {
libvirt . VIR_DOMAIN_BLOCKED : " state_running " ,
libvirt . VIR_DOMAIN_CRASHED : " state_shutoff " ,
libvirt . VIR_DOMAIN_PAUSED : " state_paused " ,
libvirt . VIR_DOMAIN_RUNNING : " state_running " ,
libvirt . VIR_DOMAIN_SHUTDOWN : " state_shutoff " ,
libvirt . VIR_DOMAIN_SHUTOFF : " state_shutoff " ,
libvirt . VIR_DOMAIN_NOSTATE : " state_running " ,
2012-10-29 18:55:51 -04:00
# VIR_DOMAIN_PMSUSPENDED
7 : " state_paused " ,
2011-07-12 11:50:11 -04:00
}
2012-10-29 18:55:51 -04:00
status = self . status ( )
if status not in status_icons :
logging . debug ( " Unknown status %d , using NOSTATE " )
status = libvirt . VIR_DOMAIN_NOSTATE
return status_icons [ status ]
2011-05-03 16:17:52 -04:00
2011-04-14 12:04:44 -04:00
def force_update_status ( self ) :
2011-05-03 16:17:52 -04:00
"""
Fetch current domain state and clear status cache
"""
2011-04-14 12:04:44 -04:00
try :
2011-05-03 16:17:52 -04:00
info = self . _backend . info ( )
2011-04-14 12:04:44 -04:00
except libvirt . libvirtError , e :
if ( hasattr ( libvirt , " VIR_ERR_NO_DOMAIN " ) and
e . get_error_code ( ) == getattr ( libvirt , " VIR_ERR_NO_DOMAIN " ) ) :
# Possibly a transient domain that was removed on shutdown
return
raise
2011-04-09 22:39:34 -04:00
2011-04-14 12:04:44 -04:00
self . _update_status ( info [ 0 ] )
2011-04-09 22:39:34 -04:00
2011-04-14 12:04:44 -04:00
def _update_status ( self , status ) :
2011-05-03 16:17:52 -04:00
"""
Internal helper to change cached status to ' status ' and signal
clients if we actually changed state
"""
2010-02-07 12:10:41 -05:00
status = self . _normalize_status ( status )
2009-10-05 18:57:29 -04:00
2011-04-14 12:04:44 -04:00
if status == self . lastStatus :
return
oldstatus = self . lastStatus
self . lastStatus = status
2010-06-23 13:05:09 -04:00
2011-04-14 12:04:44 -04:00
# Send 'config-changed' before a status-update, so users
# are operating with fresh XML
self . refresh_xml ( )
2010-06-23 13:05:09 -04:00
2011-04-18 11:12:36 -04:00
self . idle_emit ( " status-changed " , oldstatus , status )
2009-10-05 18:57:29 -04:00
2013-04-17 17:39:25 -04:00
def inspection_data_updated ( self ) :
self . idle_emit ( " inspection-changed " )
2010-11-29 17:40:28 -05:00
2013-04-17 17:39:25 -04:00
##################
# config helpers #
##################
def on_console_scaling_changed ( self , * args , * * kwargs ) :
return self . config . listen_pervm ( self . uuid , " /scaling " ,
* args , * * kwargs )
2011-05-03 16:17:52 -04:00
def set_console_scaling ( self , value ) :
2013-04-17 17:39:25 -04:00
self . config . set_pervm ( self . uuid , " /scaling " , value )
2011-05-03 16:17:52 -04:00
def get_console_scaling ( self ) :
2013-04-17 17:39:25 -04:00
ret = self . config . get_pervm ( self . uuid , " /scaling " )
if ret == - 1 :
return self . config . get_console_scaling ( )
return ret
2010-11-29 17:40:28 -05:00
2011-05-03 16:17:52 -04:00
def set_details_window_size ( self , w , h ) :
2013-04-17 17:39:25 -04:00
self . config . set_pervm ( self . uuid , " /vm-window-size " , ( w , h ) )
2011-05-03 16:17:52 -04:00
def get_details_window_size ( self ) :
2013-04-17 17:39:25 -04:00
ret = self . config . get_pervm ( self . uuid , " /vm-window-size " )
return ret
2010-11-29 17:40:28 -05:00
2013-04-17 17:39:25 -04:00
def get_console_password ( self ) :
return self . config . get_pervm ( self . uuid , " /console-password " )
def set_console_password ( self , username , keyid ) :
return self . config . set_pervm ( self . uuid , " /console-password " ,
( username , keyid ) )
2011-07-18 19:53:55 +01:00
2011-05-03 16:17:52 -04:00
###################
# Polling helpers #
###################
2010-11-29 17:40:28 -05:00
def _sample_network_traffic ( self ) :
rx = 0
tx = 0
2011-07-27 12:02:29 -04:00
if ( not self . _stats_net_supported or
2011-04-11 10:21:19 -04:00
not self . _enable_net_poll or
not self . is_active ( ) ) :
2010-11-29 17:40:28 -05:00
return rx , tx
2013-06-30 14:33:01 -04:00
for netdev in self . get_network_devices ( refresh_if_nec = False ) :
2010-11-29 17:40:28 -05:00
dev = netdev . target_dev
if not dev :
continue
if dev in self . _stats_net_skip :
continue
try :
2011-05-03 16:17:52 -04:00
io = self . _backend . interfaceStats ( dev )
2010-11-29 17:40:28 -05:00
if io :
rx + = io [ 0 ]
tx + = io [ 4 ]
except libvirt . libvirtError , err :
2013-07-06 11:20:28 -04:00
if virtinst . util . is_error_nosupport ( err ) :
2012-01-16 22:04:40 -05:00
logging . debug ( " Net stats not supported: %s " , err )
2010-11-29 17:40:28 -05:00
self . _stats_net_supported = False
else :
logging . error ( " Error reading net stats for "
2012-01-16 22:04:40 -05:00
" ' %s ' dev ' %s ' : %s " ,
self . get_name ( ) , dev , err )
2012-03-01 19:07:56 -05:00
if self . is_active ( ) :
logging . debug ( " Adding %s to skip list " , dev )
self . _stats_net_skip . append ( dev )
else :
logging . debug ( " Aren ' t running, don ' t add to skiplist " )
2010-11-29 17:40:28 -05:00
return rx , tx
def _sample_disk_io ( self ) :
rd = 0
wr = 0
2011-04-11 10:21:19 -04:00
if ( not self . _stats_disk_supported or
not self . _enable_disk_poll or
not self . is_active ( ) ) :
2010-11-29 17:40:28 -05:00
return rd , wr
2013-06-30 14:33:01 -04:00
for disk in self . get_disk_devices ( refresh_if_nec = False ) :
2010-11-29 17:40:28 -05:00
dev = disk . target
if not dev :
continue
if dev in self . _stats_disk_skip :
continue
try :
2011-05-03 16:17:52 -04:00
io = self . _backend . blockStats ( dev )
2010-11-29 17:40:28 -05:00
if io :
rd + = io [ 1 ]
wr + = io [ 3 ]
except libvirt . libvirtError , err :
2013-07-06 11:20:28 -04:00
if virtinst . util . is_error_nosupport ( err ) :
2012-01-16 22:04:40 -05:00
logging . debug ( " Disk stats not supported: %s " , err )
2010-11-29 17:40:28 -05:00
self . _stats_disk_supported = False
else :
logging . error ( " Error reading disk stats for "
2012-01-16 22:04:40 -05:00
" ' %s ' dev ' %s ' : %s " ,
self . get_name ( ) , dev , err )
2012-03-01 19:07:56 -05:00
if self . is_active ( ) :
logging . debug ( " Adding %s to skip list " , dev )
self . _stats_disk_skip . append ( dev )
else :
logging . debug ( " Aren ' t running, don ' t add to skiplist " )
2010-11-29 17:40:28 -05:00
return rd , wr
2009-10-05 18:57:29 -04:00
2013-07-07 09:42:21 -04:00
def tick ( self , stats_update = True ) :
2010-02-07 12:10:41 -05:00
self . _invalidate_xml ( )
2011-05-03 16:17:52 -04:00
info = self . _backend . info ( )
2013-07-07 09:42:21 -04:00
if stats_update :
self . _tick_stats ( info )
self . _update_status ( info [ 0 ] )
if stats_update :
self . idle_emit ( " resources-sampled " )
def _tick_stats ( self , info ) :
2010-02-07 12:10:41 -05:00
expected = self . config . get_stats_history_length ( )
current = len ( self . record )
if current > expected :
del self . record [ expected : current ]
2009-01-15 11:15:04 -05:00
2010-02-07 12:10:41 -05:00
# Xen reports complete crap for Dom0 max memory
# (ie MAX_LONG) so lets clamp it to the actual
# physical RAM in machine which is the effective
# real world limit
2011-07-22 16:43:26 -04:00
if ( self . conn . is_xen ( ) and
2011-04-09 22:40:22 -04:00
self . is_management_domain ( ) ) :
2011-07-22 16:43:26 -04:00
info [ 1 ] = self . conn . host_memory_size ( )
2009-01-15 11:15:04 -05:00
2013-07-07 08:12:15 -04:00
now = time . time ( )
2011-07-12 08:49:47 -04:00
( cpuTime , cpuTimeAbs ,
pcentHostCpu , pcentGuestCpu ) = self . _sample_cpu_stats ( info , now )
2011-07-14 16:50:54 -04:00
pcentCurrMem , curmem = self . _sample_mem_stats ( info )
2011-04-11 10:21:19 -04:00
rdBytes , wrBytes = self . _sample_disk_io ( )
rxBytes , txBytes = self . _sample_network_traffic ( )
2009-06-18 10:38:15 -04:00
2010-12-10 11:47:07 -05:00
newStats = {
" timestamp " : now ,
" cpuTime " : cpuTime ,
" cpuTimeAbs " : cpuTimeAbs ,
2011-07-11 21:22:50 -04:00
" cpuHostPercent " : pcentHostCpu ,
2011-07-12 08:49:47 -04:00
" cpuGuestPercent " : pcentGuestCpu ,
2011-04-10 00:02:39 -04:00
" curmem " : curmem ,
2010-12-10 11:47:07 -05:00
" currMemPercent " : pcentCurrMem ,
" diskRdKB " : rdBytes / 1024 ,
" diskWrKB " : wrBytes / 1024 ,
" netRxKB " : rxBytes / 1024 ,
" netTxKB " : txBytes / 1024 ,
}
2009-06-18 10:38:15 -04:00
2010-12-10 11:47:07 -05:00
for r in [ " diskRd " , " diskWr " , " netRx " , " netTx " ] :
2010-02-07 12:10:41 -05:00
newStats [ r + " Rate " ] = self . _get_cur_rate ( r + " KB " )
self . _set_max_rate ( newStats , r + " Rate " )
self . record . insert ( 0 , newStats )
2008-10-18 21:29:45 +02:00
2010-02-07 12:16:13 -05:00
2011-05-03 16:17:52 -04:00
########################
# Libvirt domain class #
########################
class vmmDomainVirtinst ( vmmDomain ) :
2010-02-07 12:16:13 -05:00
"""
Domain object backed by a virtinst Guest object .
Used for launching a details window for customizing a VM before install .
"""
2013-07-07 08:42:57 -04:00
def __init__ ( self , conn , backend , key ) :
vmmDomain . __init__ ( self , conn , backend , key )
2010-02-07 12:16:13 -05:00
2010-09-08 17:53:51 -04:00
self . _orig_xml = None
2010-02-07 12:16:13 -05:00
def get_name ( self ) :
return self . _backend . name
def get_id ( self ) :
return - 1
2011-05-03 16:17:52 -04:00
def hasSavedImage ( self ) :
return False
def _XMLDesc ( self , flags ) :
raise RuntimeError ( " Shouldn ' t be called " )
2010-02-07 12:16:13 -05:00
2013-06-30 14:33:01 -04:00
def get_xml ( self , inactive = False , refresh_if_nec = True ) :
2010-09-03 12:10:26 -04:00
ignore = inactive
2013-06-30 14:33:01 -04:00
ignore = refresh_if_nec
2010-09-03 12:10:26 -04:00
2010-09-08 17:53:51 -04:00
xml = self . _backend . get_xml_config ( install = False )
if not self . _orig_xml :
self . _orig_xml = xml
2010-05-06 13:54:16 -04:00
return xml
2010-02-25 19:35:01 -05:00
2010-09-08 17:53:51 -04:00
# Internal XML implementations
2013-06-30 14:33:01 -04:00
def _get_guest ( self , inactive = False , refresh_if_nec = True ) :
2010-09-08 17:53:51 -04:00
# Make sure XML is up2date
self . get_xml ( )
2010-09-07 18:38:01 -04:00
return self . _backend
2010-09-08 17:53:51 -04:00
def _define ( self , newxml ) :
2010-12-09 11:22:35 -05:00
ignore = newxml
2010-09-08 17:53:51 -04:00
self . _orig_xml = None
2011-09-26 20:14:12 -04:00
self . emit ( " config-changed " )
2010-09-08 17:53:51 -04:00
def _redefine_xml ( self , newxml ) :
# We need to cache origxml in order to have something to diff against
origxml = self . _orig_xml or self . get_xml ( inactive = True )
return self . _redefine_helper ( origxml , newxml )
def refresh_xml ( self , forcesignal = False ) :
2010-02-07 12:16:13 -05:00
# No caching, so no refresh needed
return
def get_autostart ( self ) :
return self . _backend . autostart
def set_autostart ( self , val ) :
self . _backend . autostart = bool ( val )
2011-09-26 20:14:12 -04:00
self . emit ( " config-changed " )
2010-02-07 12:16:13 -05:00
2011-03-24 13:24:01 -04:00
def define_name ( self , newname ) :
def change ( guest ) :
guest . name = str ( newname )
return self . _redefine_guest ( change )