2006-06-28 23: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 19:12:20 +03:00
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
2006-06-28 23:50:17 +04:00
#
2006-06-15 01:52:49 +04:00
import libvirt
2006-09-26 02:41:47 +04:00
import logging
2010-12-11 00:04:42 +03:00
import time
import threading
import gobject
2009-03-09 08:04:29 +03:00
2010-02-07 20:16:13 +03:00
import virtinst
2009-03-09 08:04:29 +03:00
from virtManager import util
2009-11-16 19:36:13 +03:00
import virtinst . support as support
2006-08-08 19:51:58 +04:00
2010-02-26 03:35:01 +03:00
from virtManager . libvirtobject import vmmLibvirtObject
2010-09-09 01:53:51 +04:00
def compare_device ( origdev , newdev , idx ) :
devprops = {
" disk " : [ " target " , " bus " ] ,
" interface " : [ " macaddr " , " vmmindex " ] ,
" input " : [ " bus " , " type " , " vmmindex " ] ,
" sound " : [ " model " , " vmmindex " ] ,
" video " : [ " model_type " , " vmmindex " ] ,
" watchdog " : [ " vmmindex " ] ,
" hostdev " : [ " vendor " , " product " , " bus " , " device " ,
" type " , " function " , " domain " , " slot " , " managed " ] ,
" serial " : [ " char_type " , " target_port " ] ,
" parallel " : [ " char_type " , " target_port " ] ,
" console " : [ " char_type " , " target_type " , " target_port " ] ,
" graphics " : [ " type " , " vmmindex " ] ,
}
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 16:39:10 +03:00
2010-09-09 01: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 16:39:10 +03:00
2010-09-09 01:53:51 +04:00
return None
2009-12-02 16:39:10 +03:00
2010-12-11 00:04:42 +03: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 ] )
#data_processed = float(jobinfo[4])
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 ( )
2010-02-26 03:35:01 +03:00
class vmmDomainBase ( vmmLibvirtObject ) :
2010-02-07 20:10:41 +03:00
"""
Base class for vmmDomain objects . Provides common set up and methods
for domain backends ( libvirt virDomain , virtinst Guest )
"""
2006-06-15 01:52:49 +04:00
__gsignals__ = {
" status-changed " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE ,
2010-02-27 18:42:43 +03:00
[ int , int ] ) ,
2006-06-15 02:42:04 +04:00
" resources-sampled " : ( gobject . SIGNAL_RUN_FIRST ,
gobject . TYPE_NONE ,
[ ] ) ,
2006-06-15 01:52:49 +04:00
}
2010-12-09 20:37:48 +03:00
def __init__ ( self , connection , backend , uuid ) :
vmmLibvirtObject . __init__ ( self , connection )
2010-02-26 03:35:01 +03:00
2009-09-25 17:52:03 +04:00
self . _backend = backend
2006-06-15 01:52:49 +04:00
self . uuid = uuid
2010-05-13 18:37:31 +04:00
self . cloning = False
2007-04-12 23:36:04 +04:00
2010-11-30 01:28:52 +03:00
self . record = [ ]
self . maxRecord = {
" diskRdRate " : 10.0 ,
" diskWrRate " : 10.0 ,
" netTxRate " : 10.0 ,
" netRxRate " : 10.0 ,
}
2010-05-13 19:21:01 +04:00
self . _install_abort = False
2009-11-18 01:18:09 +03:00
self . _startup_vcpus = None
2010-05-12 20:57:32 +04:00
self . managedsave_supported = False
2010-09-09 01:53:51 +04:00
self . _guest_to_define = None
2010-02-09 01:13:36 +03:00
2010-09-09 01:53:51 +04:00
self . _network_traffic = None
2010-02-09 01:13:36 +03:00
self . _stats_net_supported = True
2010-02-11 17:30:32 +03:00
self . _stats_net_skip = [ ]
2010-09-09 01:53:51 +04:00
self . _disk_io = None
2010-02-09 01:13:36 +03:00
self . _stats_disk_supported = True
2010-02-11 17:30:32 +03:00
self . _stats_disk_skip = [ ]
2010-02-09 01:13:36 +03:00
2010-02-07 20:10:41 +03:00
# Info accessors
def get_name ( self ) :
raise NotImplementedError ( )
def get_id ( self ) :
raise NotImplementedError ( )
def status ( self ) :
raise NotImplementedError ( )
2008-12-17 23:27:06 +03:00
2010-02-07 20:10:41 +03:00
def get_memory_percentage ( self ) :
raise NotImplementedError ( )
def maximum_memory_percentage ( self ) :
raise NotImplementedError ( )
def cpu_time ( self ) :
raise NotImplementedError ( )
def cpu_time_percentage ( self ) :
raise NotImplementedError ( )
def network_rx_rate ( self ) :
raise NotImplementedError ( )
def network_tx_rate ( self ) :
raise NotImplementedError ( )
def disk_read_rate ( self ) :
raise NotImplementedError ( )
def disk_write_rate ( self ) :
raise NotImplementedError ( )
2008-12-17 23:27:06 +03:00
2010-02-07 20:10:41 +03:00
def get_autostart ( self ) :
raise NotImplementedError ( )
2009-07-27 00:09:23 +04:00
2010-05-13 18:37:31 +04:00
def get_cloning ( self ) :
return self . cloning
def set_cloning ( self , val ) :
self . cloning = bool ( val )
2010-05-13 19:21:01 +04:00
# If manual shutdown or destroy specified, make sure we don't continue
# install process
def set_install_abort ( self , val ) :
self . _install_abort = bool ( val )
def get_install_abort ( self ) :
return bool ( self . _install_abort )
2010-09-09 01:53:51 +04:00
# Device/XML hotplug API
2010-02-07 20:10:41 +03:00
def set_autostart ( self , val ) :
raise NotImplementedError ( )
2008-10-18 23:29:45 +04:00
2010-09-09 01:53:51 +04:00
def attach_device ( self , devobj ) :
2010-02-07 20:10:41 +03:00
raise NotImplementedError ( )
2010-09-09 01:53:51 +04:00
def detach_device ( self , devobj ) :
2010-02-07 20:10:41 +03:00
raise NotImplementedError ( )
2009-09-25 17:52:03 +04:00
2010-12-12 05:34:09 +03:00
def hotplug_graphics_password ( self , devobj , newval ) :
raise NotImplementedError ( )
2010-09-09 01:53:51 +04:00
def hotplug_storage_media ( self , devobj , newpath ) :
2010-02-07 20:10:41 +03:00
raise NotImplementedError ( )
2010-09-09 01:53:51 +04:00
def hotplug_vcpus ( self , vcpus ) :
2010-02-07 20:10:41 +03:00
raise NotImplementedError ( )
2010-09-09 01:53:51 +04:00
def hotplug_both_mem ( self , memory , maxmem ) :
2010-02-07 20:10:41 +03:00
raise NotImplementedError ( )
2009-09-25 17:52:03 +04:00
2010-11-30 01:28:52 +03:00
def _get_guest ( self , inactive = False , refresh_if_necc = True ) :
raise NotImplementedError ( )
2010-09-09 01:53:51 +04:00
def _invalidate_xml ( self ) :
vmmLibvirtObject . _invalidate_xml ( self )
self . _guest_to_define = None
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 17:57:42 +03:00
logging . debug ( " Device in active config but not inactive config. " )
2010-09-09 01: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 )
# virtinst.Guest XML persistent change Impls
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
2010-02-07 20:10:41 +03:00
def define_vcpus ( self , vcpus ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
2010-11-29 20:55:22 +03:00
guest . vcpus = int ( vcpus )
2010-09-09 01:53:51 +04:00
return self . _redefine_guest ( change )
2010-02-07 20:10:41 +03:00
def define_cpuset ( self , cpuset ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
2010-11-29 20:55:22 +03:00
guest . cpuset = cpuset
2010-09-09 01:53:51 +04:00
return self . _redefine_guest ( change )
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def define_both_mem ( self , memory , maxmem ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
guest . memory = int ( int ( memory ) / 1024 )
guest . maxmemory = int ( int ( maxmem ) / 1024 )
return self . _redefine_guest ( change )
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def define_seclabel ( self , model , t , label ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
seclabel = guest . seclabel
seclabel . model = model or None
if not model :
return
2009-09-25 17:52:03 +04:00
2010-09-09 01:53:51 +04:00
seclabel . type = t
if label :
seclabel . label = label
return self . _redefine_guest ( change )
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def define_acpi ( self , newvalue ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
guest . features [ " acpi " ] = bool ( newvalue )
return self . _redefine_guest ( change )
2010-02-07 20:10:41 +03:00
def define_apic ( self , newvalue ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
guest . features [ " apic " ] = bool ( newvalue )
return self . _redefine_guest ( change )
2010-02-07 20:10:41 +03:00
def define_clock ( self , newvalue ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
guest . clock . offset = newvalue
return self . _redefine_guest ( change )
2010-02-10 20:16:59 +03:00
def define_description ( self , newvalue ) :
2010-09-09 01:53:51 +04:00
def change ( guest ) :
guest . description = newvalue or None
return self . _redefine_guest ( change )
2009-09-25 17:52:03 +04:00
2010-09-09 01: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-12 06:00:52 +03:00
def set_boot_menu ( self , newval ) :
def change ( guest ) :
guest . installer . bootconfig . enable_bootmenu = bool ( newval )
return self . _redefine_guest ( change )
2010-12-12 07:00:19 +03: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 )
2010-09-09 01:53:51 +04:00
# virtinst.VirtualDevice XML persistent change Impls
def define_storage_media ( self , devobj , newpath ) :
def change ( editdev ) :
editdev . path = newpath
return self . _redefine_device ( change , devobj )
2010-09-08 02:38:01 +04:00
def define_disk_readonly ( self , devobj , do_readonly ) :
2010-09-09 01:53:51 +04:00
def change ( editdev ) :
editdev . read_only = do_readonly
return self . _redefine_device ( change , devobj )
2010-09-08 02:38:01 +04:00
def define_disk_shareable ( self , devobj , do_shareable ) :
2010-09-09 01:53:51 +04:00
def change ( editdev ) :
editdev . shareable = do_shareable
return self . _redefine_device ( change , devobj )
2010-09-08 02:38:01 +04:00
def define_disk_cache ( self , devobj , new_cache ) :
2010-09-09 01:53:51 +04:00
def change ( editdev ) :
editdev . driver_cache = new_cache or None
return self . _redefine_device ( change , devobj )
2010-12-11 03:20:14 +03: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 )
2010-12-11 04:33:41 +03:00
def define_disk_bus ( self , devobj , newval ) :
def change ( editdev ) :
editdev . bus = newval
return self . _redefine_device ( change , devobj )
2009-09-25 17:52:03 +04:00
2010-09-08 02:38:01 +04:00
def define_network_model ( self , devobj , newmodel ) :
2010-09-09 01:53:51 +04:00
def change ( editdev ) :
editdev . model = newmodel
return self . _redefine_device ( change , devobj )
2010-03-24 07:22:17 +03:00
2010-12-12 04:54:48 +03: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 )
2010-09-08 02:38:01 +04:00
def define_sound_model ( self , devobj , newmodel ) :
2010-09-09 01:53:51 +04:00
def change ( editdev ) :
editdev . model = newmodel
return self . _redefine_device ( change , devobj )
2010-03-24 07:22:17 +03:00
2010-09-08 02:38:01 +04:00
def define_video_model ( self , devobj , newmodel ) :
2010-09-09 01:53:51 +04:00
def change ( editdev ) :
editdev . model_type = newmodel
return self . _redefine_device ( change , devobj )
2009-09-25 17:52:03 +04:00
2010-09-09 01:53:51 +04:00
def define_watchdog_model ( self , devobj , newval ) :
def change ( editdev ) :
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 07:22:17 +03:00
2010-02-07 20:10:41 +03:00
########################
# XML Parsing routines #
########################
def get_uuid ( self ) :
return self . uuid
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def set_handle ( self , vm ) :
2010-02-11 22:00:46 +03:00
self . _backend = vm
2010-03-04 16:40:10 +03:00
def release_handle ( self ) :
del ( self . _backend )
self . _backend = None
2010-02-07 20:10:41 +03:00
def get_handle ( self ) :
return self . _backend
2009-09-25 17:52:03 +04:00
2010-12-13 22:31:27 +03:00
def enable_unsupported_rhel_opts ( self ) :
if not self . is_libexec_qemu ( ) :
return True
return self . config . enable_unsupported_rhel_opts
def is_libexec_qemu ( self ) :
return bool ( self . connection . is_qemu_system ( ) and
str ( self . get_emulator ( ) ) . startswith ( " /usr/libexec " ) )
2010-02-07 20:10:41 +03:00
def is_read_only ( self ) :
if self . connection . is_read_only ( ) :
return True
if self . is_management_domain ( ) :
return True
return False
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def is_management_domain ( self ) :
if self . get_id ( ) == 0 :
return True
return False
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def is_hvm ( self ) :
if self . get_abi_type ( ) == " hvm " :
return True
return False
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def is_active ( self ) :
if self . get_id ( ) == - 1 :
return False
2009-09-25 17:52:03 +04:00
else :
2010-02-07 20:10:41 +03:00
return True
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_id_pretty ( self ) :
i = self . get_id ( )
if i < 0 :
return " - "
return str ( i )
2009-09-25 17:52:03 +04:00
2010-05-12 20:57:32 +04:00
def hasSavedImage ( self ) :
return False
2010-02-07 20:10:41 +03:00
def get_abi_type ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . installer . os_type
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_hv_type ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . installer . type
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_pretty_hv_type ( self ) :
return util . pretty_hv ( self . get_abi_type ( ) , self . get_hv_type ( ) )
2009-11-16 19:36:13 +03:00
2010-02-07 20:10:41 +03:00
def get_arch ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . installer . arch
2009-11-16 19:36:13 +03:00
2010-02-07 20:10:41 +03:00
def get_emulator ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . emulator
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_acpi ( self ) :
2010-12-13 20:48:06 +03:00
return bool ( self . _get_guest ( ) . features [ " acpi " ] )
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_apic ( self ) :
2010-12-13 20:48:06 +03:00
return bool ( self . _get_guest ( ) . features [ " apic " ] )
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_clock ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . clock . offset
2009-09-25 17:52:03 +04:00
2010-02-10 20:16:59 +03:00
def get_description ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . description
2010-02-10 20:16:59 +03:00
2010-11-29 20:55:22 +03:00
def get_memory ( self ) :
2010-12-13 20:48:06 +03:00
return int ( self . _get_guest ( ) . memory * 1024 )
2010-11-29 20:55:22 +03:00
def maximum_memory ( self ) :
2010-12-13 20:48:06 +03:00
return int ( self . _get_guest ( ) . maxmemory * 1024 )
2010-11-29 20:55:22 +03:00
def vcpu_count ( self ) :
2010-12-13 20:48:06 +03:00
return int ( self . _get_guest ( ) . vcpus )
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def vcpu_max_count ( self ) :
if self . _startup_vcpus == None :
2010-12-13 20:48:06 +03:00
self . _startup_vcpus = int ( self . vcpu_count ( ) )
2010-02-07 20:10:41 +03:00
return int ( self . _startup_vcpus )
2009-11-15 23:17:03 +03:00
2010-11-29 20:55:22 +03:00
def vcpu_pinning ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . cpuset or " "
2010-11-29 20:55:22 +03:00
2010-02-07 20:10:41 +03:00
def get_boot_device ( self ) :
2010-12-13 20:48:06 +03:00
return self . _get_guest ( ) . installer . bootconfig . bootorder
2010-12-12 07:00:19 +03:00
2010-12-12 06:00:52 +03:00
def get_boot_menu ( self ) :
guest = self . _get_guest ( )
return bool ( guest . installer . bootconfig . enable_bootmenu )
2009-09-25 17:52:03 +04:00
2010-12-12 07:00:19 +03: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 20:10:41 +03:00
def get_seclabel ( self ) :
2010-12-13 20:48:06 +03:00
model = self . _get_guest ( ) . seclabel . model
t = self . _get_guest ( ) . seclabel . type or " dynamic "
label = self . _get_guest ( ) . seclabel . label or " "
2009-09-25 17:52:03 +04:00
2010-12-13 20:48:06 +03:00
return [ model , t , label ]
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
# Device listing
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_serial_devs ( self ) :
2010-09-04 01:56:40 +04:00
devs = self . get_char_devices ( )
devlist = [ ]
2009-11-04 19:07:03 +03:00
2010-09-04 01:56:40 +04:00
serials = filter ( lambda x : x . virtual_device_type == " serial " , devs )
consoles = filter ( lambda x : x . virtual_device_type == " console " , devs )
2009-11-04 19:07:03 +03:00
2010-09-04 01:56:40 +04:00
for dev in serials :
2010-12-10 22:04:33 +03:00
devlist . append ( [ " Serial %s " % ( dev . vmmindex + 1 ) , dev . char_type ,
dev . source_path , dev . vmmindex ] )
2010-09-04 01:56:40 +04:00
for dev in consoles :
2010-12-10 22:04:33 +03:00
devlist . append ( [ " Text Console %s " % ( dev . vmmindex + 1 ) ,
dev . char_type , dev . source_path , dev . vmmindex ] )
2010-09-04 01:56:40 +04:00
return devlist
2010-02-13 00:33:43 +03:00
2010-09-04 01:56:40 +04:00
def get_graphics_console ( self ) :
gdevs = self . get_graphics_devices ( )
2010-02-13 00:33:43 +03:00
connhost = self . connection . get_uri_hostname ( )
2010-02-07 20:10:41 +03:00
transport , username = self . connection . get_transport ( )
2010-09-04 01:56:40 +04:00
vncport = None
gport = None
gtype = None
if gdevs :
gport = gdevs [ 0 ] . port
gtype = gdevs [ 0 ] . type
if gtype == ' vnc ' :
vncport = int ( gport )
2010-02-13 00:33:43 +03:00
2010-02-13 00:37:14 +03:00
if connhost == None :
2010-02-07 20:10:41 +03:00
# Force use of 127.0.0.1, because some (broken) systems don't
# reliably resolve 'localhost' into 127.0.0.1, either returning
# the public IP, or an IPv6 addr. Neither work since QEMU only
# listens on 127.0.0.1 for VNC.
2010-02-13 00:33:43 +03:00
connhost = " 127.0.0.1 "
# Parse URI port
connport = None
if connhost . count ( " : " ) :
connhost , connport = connhost . split ( " : " , 1 )
# Build VNC uri for debugging
vncuri = None
2010-09-04 01:56:40 +04:00
if gtype == ' vnc ' :
2010-02-13 00:33:43 +03:00
vncuri = str ( gtype ) + " :// "
if username :
vncuri = vncuri + str ( username ) + ' @ '
vncuri + = str ( connhost ) + " : " + str ( vncport )
return [ gtype , connhost , vncport , transport , username , connport ,
vncuri ]
2009-03-01 01:21:41 +03:00
2009-03-13 20:13:24 +03:00
2010-09-08 02:38:01 +04:00
def _build_device_list ( self , device_type ,
refresh_if_necc = True , inactive = False ) :
2010-09-03 23:19:54 +04:00
guest = self . _get_guest ( refresh_if_necc = refresh_if_necc ,
inactive = inactive )
devs = guest . get_devices ( device_type )
2010-09-03 22:10:04 +04:00
2010-09-08 02:38:01 +04:00
count = 0
for dev in devs :
2010-09-09 01:53:51 +04:00
dev . vmmindex = count
2010-09-08 02:38:01 +04:00
count + = 1
return devs
def get_network_devices ( self , refresh_if_necc = True ) :
return self . _build_device_list ( " interface " , refresh_if_necc )
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 " )
def get_disk_devices ( self , refresh_if_necc = True , inactive = False ) :
devs = self . _build_device_list ( " disk " , refresh_if_necc , inactive )
2010-09-03 22: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 23:19:54 +04:00
for dev in devs :
devtype = dev . device
bus = dev . bus
2010-09-03 22:10:04 +04:00
key = devtype + ( bus or " " )
2010-12-10 19:47:07 +03:00
if key not in idx_mapping :
2010-09-03 22:10:04 +04:00
idx_mapping [ key ] = 1
2010-09-03 23:19:54 +04:00
dev . disk_bus_index = idx_mapping [ key ]
2010-09-03 22:10:04 +04:00
idx_mapping [ key ] + = 1
2010-09-03 23:19:54 +04:00
return devs
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def get_char_devices ( self ) :
2010-09-04 01:56:40 +04:00
devs = [ ]
2010-09-08 02:38:01 +04:00
serials = self . _build_device_list ( " serial " )
parallels = self . _build_device_list ( " parallel " )
consoles = self . _build_device_list ( " console " )
2010-09-04 01:56:40 +04:00
for devicelist in [ serials , parallels , consoles ] :
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-08 02:38:01 +04:00
ser . virtmanager_console_dup = con
2010-09-04 01:56:40 +04:00
devs . remove ( con )
return devs
2009-10-06 02:00:13 +04:00
2010-02-07 20:10:41 +03:00
# Stats accessors
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
2009-11-04 16:46:09 +03:00
2010-02-07 20:10:41 +03:00
def _sample_mem_stats ( self , info ) :
pcentCurrMem = info [ 2 ] * 100.0 / self . connection . host_memory_size ( )
pcentMaxMem = info [ 1 ] * 100.0 / self . connection . host_memory_size ( )
2010-04-08 00:36:59 +04:00
if pcentCurrMem > 100 :
pcentCurrMem = 100.0
if pcentMaxMem > 100 :
pcentMaxMem = 100.0
2010-02-07 20:10:41 +03:00
return pcentCurrMem , pcentMaxMem
2009-11-04 16:46:09 +03:00
2010-02-07 20:10:41 +03:00
def _sample_cpu_stats ( self , info , now ) :
prevCpuTime = 0
prevTimestamp = 0
if len ( self . record ) > 0 :
prevTimestamp = self . record [ 0 ] [ " timestamp " ]
prevCpuTime = self . record [ 0 ] [ " cpuTimeAbs " ]
2009-11-04 16:46:09 +03:00
2010-02-07 20:10:41 +03:00
cpuTime = 0
cpuTimeAbs = 0
pcentCpuTime = 0
if not ( info [ 0 ] in [ libvirt . VIR_DOMAIN_SHUTOFF ,
libvirt . VIR_DOMAIN_CRASHED ] ) :
cpuTime = info [ 4 ] - prevCpuTime
cpuTimeAbs = info [ 4 ]
2009-11-05 00:30:51 +03:00
2010-12-10 19:47:07 +03:00
pcentCpuTime = (
( cpuTime ) * 100.0 /
( ( ( now - prevTimestamp ) * 1000.0 * 1000.0 * 1000.0 ) *
self . connection . host_active_processor_count ( ) ) )
2010-02-07 20:10:41 +03: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
2009-11-05 00:30:51 +03:00
2010-02-07 20:10:41 +03:00
return cpuTime , cpuTimeAbs , pcentCpuTime
2009-11-05 00:30:51 +03:00
2010-02-07 20:10:41 +03:00
def _get_cur_rate ( self , what ) :
if len ( self . record ) > 1 :
2010-11-29 22:06:43 +03:00
ret = ( float ( self . record [ 0 ] [ what ] -
self . record [ 1 ] [ what ] ) /
float ( self . record [ 0 ] [ " timestamp " ] -
self . record [ 1 ] [ " timestamp " ] ) )
2010-02-07 20:10:41 +03:00
else :
ret = 0.0
2010-11-29 22:06:43 +03:00
return max ( ret , 0 , 0 ) # avoid negative values at poweroff
2009-11-05 22:59:11 +03:00
2010-02-07 20:10:41 +03:00
def _set_max_rate ( self , record , what ) :
if record [ what ] > self . maxRecord [ what ] :
self . maxRecord [ what ] = record [ what ]
2009-11-05 00:30:51 +03:00
2010-02-07 20:10:41 +03:00
def current_memory ( self ) :
if self . get_id ( ) == - 1 :
return 0
return self . get_memory ( )
2009-10-06 02:00:13 +04:00
2010-02-07 20:10:41 +03:00
def current_memory_percentage ( self ) :
if self . get_id ( ) == - 1 :
return 0
return self . get_memory_percentage ( )
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def current_memory_pretty ( self ) :
if self . get_id ( ) == - 1 :
return " 0 MB "
return self . get_memory_pretty ( )
2007-07-24 23:13:03 +04:00
2010-02-07 20:10:41 +03:00
def get_memory_pretty ( self ) :
mem = self . get_memory ( )
2010-12-10 19:47:07 +03:00
if mem > ( 10 * 1024 * 1024 ) :
return " %2.2f GB " % ( mem / ( 1024.0 * 1024.0 ) )
2010-02-07 20:10:41 +03:00
else :
2010-12-10 19:47:07 +03:00
return " %2.0f MB " % ( mem / 1024.0 )
2006-10-11 01:24:59 +04:00
2010-02-07 20:10:41 +03:00
def maximum_memory_pretty ( self ) :
mem = self . maximum_memory ( )
2010-12-10 19:47:07 +03:00
if mem > ( 10 * 1024 * 1024 ) :
return " %2.2f GB " % ( mem / ( 1024.0 * 1024.0 ) )
2010-02-07 20:10:41 +03:00
else :
2010-12-10 19:47:07 +03:00
return " %2.0f MB " % ( mem / 1024.0 )
2006-10-09 21:28:13 +04:00
2010-02-07 20:10:41 +03:00
def cpu_time_pretty ( self ) :
return " %2.2f %% " % self . cpu_time_percentage ( )
2006-06-15 01:52:49 +04:00
2010-02-07 20:10:41 +03:00
def network_traffic_rate ( self ) :
return self . network_tx_rate ( ) + self . network_rx_rate ( )
2006-06-28 18:40:35 +04:00
2010-02-07 20:10:41 +03:00
def disk_io_rate ( self ) :
return self . disk_read_rate ( ) + self . disk_write_rate ( )
2006-06-27 22:15:28 +04:00
2010-02-07 20:10:41 +03: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 22:48:36 +04:00
2010-02-07 20:10:41 +03:00
def _in_out_vector_helper ( self , name1 , name2 ) :
vector = [ ]
stats = self . record
ceil = float ( max ( self . maxRecord [ name1 ] , self . maxRecord [ name2 ] ) )
2010-02-12 21:37:04 +03:00
maxlen = self . config . get_stats_history_length ( )
2010-12-10 19:47:07 +03:00
for n in [ name1 , name2 ] :
2010-02-12 21:37:04 +03:00
for i in range ( maxlen + 1 ) :
2010-02-07 20:10:41 +03:00
if i < len ( stats ) :
2010-12-10 19:47:07 +03:00
vector . append ( float ( stats [ i ] [ n ] ) / ceil )
2010-02-07 20:10:41 +03:00
else :
vector . append ( 0.0 )
return vector
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def in_out_vector_limit ( self , data , limit ) :
2010-12-10 19:47:07 +03:00
l = len ( data ) / 2
2010-02-07 20:10:41 +03:00
end = [ l , limit ] [ l > limit ]
if l > limit :
2010-12-10 19:47:07 +03:00
data = data [ 0 : end ] + data [ l : l + end ]
2010-11-29 22:06:43 +03:00
d = map ( lambda x , y : ( x + y ) / 2 , data [ 0 : end ] , data [ end : end * 2 ] )
2010-02-07 20:10:41 +03:00
return d
2009-09-25 17:52:03 +04:00
2010-02-07 20:10:41 +03:00
def cpu_time_vector ( self ) :
return self . _vector_helper ( " cpuTimePercent " )
def cpu_time_moving_avg_vector ( self ) :
return self . _vector_helper ( " cpuTimeMovingAvgPercent " )
def current_memory_vector ( self ) :
return self . _vector_helper ( " currMemPercent " )
def network_traffic_vector ( self ) :
return self . _in_out_vector_helper ( " netRxRate " , " netTxRate " )
def disk_io_vector ( self ) :
return self . _in_out_vector_helper ( " diskRdRate " , " diskWrRate " )
2009-05-12 21:09:08 +04:00
2010-02-07 20:10:41 +03:00
def cpu_time_vector_limit ( self , limit ) :
cpudata = self . cpu_time_vector ( )
if len ( cpudata ) > limit :
cpudata = cpudata [ 0 : limit ]
return cpudata
def network_traffic_vector_limit ( self , limit ) :
return self . in_out_vector_limit ( self . network_traffic_vector ( ) , limit )
def disk_io_vector_limit ( self , limit ) :
return self . in_out_vector_limit ( self . disk_io_vector ( ) , limit )
2009-05-12 21:09:08 +04:00
2010-03-01 03:40:06 +03:00
def is_shutoff ( self ) :
return self . status ( ) == libvirt . VIR_DOMAIN_SHUTOFF
def is_crashed ( self ) :
return self . status ( ) == libvirt . VIR_DOMAIN_CRASHED
2010-02-07 20:10:41 +03:00
def is_stoppable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_RUNNING ,
libvirt . VIR_DOMAIN_PAUSED ]
2009-05-12 21:09:08 +04:00
2010-02-07 20:10:41 +03:00
def is_destroyable ( self ) :
return ( self . is_stoppable ( ) or
self . status ( ) in [ libvirt . VIR_DOMAIN_CRASHED ] )
2009-05-12 21:09:08 +04:00
2010-02-07 20:10:41 +03:00
def is_runable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_SHUTOFF ,
libvirt . VIR_DOMAIN_CRASHED ]
2008-03-17 20:10:15 +03:00
2010-02-07 20:10:41 +03:00
def is_pauseable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_RUNNING ]
2009-11-04 21:16:38 +03:00
2010-02-07 20:10:41 +03:00
def is_unpauseable ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_PAUSED ]
2009-11-04 21:16:38 +03:00
2010-02-07 20:10:41 +03:00
def is_paused ( self ) :
return self . status ( ) in [ libvirt . VIR_DOMAIN_PAUSED ]
2009-11-04 21:16:38 +03:00
2010-02-07 20:10:41 +03:00
def run_status ( self ) :
if self . status ( ) == libvirt . VIR_DOMAIN_RUNNING :
return _ ( " Running " )
elif self . status ( ) == libvirt . VIR_DOMAIN_PAUSED :
return _ ( " Paused " )
elif self . status ( ) == libvirt . VIR_DOMAIN_SHUTDOWN :
2010-04-05 20:21:03 +04:00
return _ ( " Shutting Down " )
2010-02-07 20:10:41 +03:00
elif self . status ( ) == libvirt . VIR_DOMAIN_SHUTOFF :
return _ ( " Shutoff " )
elif self . status ( ) == libvirt . VIR_DOMAIN_CRASHED :
return _ ( " Crashed " )
2006-06-15 01:52:49 +04:00
2010-02-07 20:10:41 +03:00
def run_status_icon ( self ) :
return self . config . get_vm_status_icon ( self . status ( ) )
def run_status_icon_large ( self ) :
return self . config . get_vm_status_icon_large ( self . status ( ) )
2006-06-15 02:51:58 +04:00
2006-06-15 01:52:49 +04:00
2009-05-11 18:45:25 +04:00
# GConf specific wranglings
def set_console_scaling ( self , value ) :
self . config . set_pervm ( self . connection . get_uri ( ) , self . uuid ,
self . config . set_console_scaling , value )
def get_console_scaling ( self ) :
return self . config . get_pervm ( self . connection . get_uri ( ) , self . uuid ,
self . config . get_console_scaling )
def on_console_scaling_changed ( self , cb ) :
self . config . listen_pervm ( self . connection . get_uri ( ) , self . uuid ,
self . config . on_console_scaling_changed , cb )
2009-11-29 04:07:01 +03:00
def set_details_window_size ( self , w , h ) :
self . config . set_pervm ( self . connection . get_uri ( ) , self . uuid ,
self . config . set_details_window_size , ( w , h ) )
def get_details_window_size ( self ) :
return self . config . get_pervm ( self . connection . get_uri ( ) , self . uuid ,
self . config . get_details_window_size )
2009-05-11 18:45:25 +04:00
2008-12-17 23:27:06 +03:00
2010-02-07 20:10:41 +03:00
########################
# Libvirt domain class #
########################
class vmmDomain ( vmmDomainBase ) :
"""
Domain class backed by a libvirt virDomain
"""
2010-12-09 20:37:48 +03:00
def __init__ ( self , connection , backend , uuid ) :
vmmDomainBase . __init__ ( self , connection , backend , uuid )
2010-02-07 20:10:41 +03:00
2010-02-27 18:42:43 +03:00
self . lastStatus = libvirt . VIR_DOMAIN_SHUTOFF
2010-02-07 20:10:41 +03:00
2010-03-01 03:40:06 +03:00
self . config . on_stats_enable_net_poll_changed (
self . toggle_sample_network_traffic )
self . config . on_stats_enable_disk_poll_changed (
self . toggle_sample_disk_io )
2010-02-07 20:10:41 +03:00
self . getvcpus_supported = support . check_domain_support ( self . _backend ,
support . SUPPORT_DOMAIN_GETVCPUS )
2010-05-12 20:57:32 +04:00
self . managedsave_supported = self . connection . get_dom_managedsave_supported ( self . _backend )
2010-12-08 20:52:33 +03:00
self . getjobinfo_supported = support . check_domain_support ( self . _backend ,
support . SUPPORT_DOMAIN_JOB_INFO )
2010-02-07 20:10:41 +03:00
self . toggle_sample_network_traffic ( )
self . toggle_sample_disk_io ( )
2010-03-17 23:41:50 +03:00
self . reboot_listener = None
2010-09-03 03:08:00 +04:00
self . _guest = None
2010-09-03 20:10:26 +04:00
self . _reparse_xml ( )
2010-03-17 23:41:50 +03:00
2010-02-07 20:10:41 +03:00
# Determine available XML flags (older libvirt versions will error
# out if passed SECURE_XML, INACTIVE_XML, etc)
2010-02-26 03:35:01 +03:00
( self . _inactive_xml_flags ,
self . _active_xml_flags ) = self . connection . get_dom_flags (
self . _backend )
2010-02-07 20:10:41 +03:00
2010-02-27 18:42:43 +03:00
# Hook up our own status listeners
2010-06-23 21:05:09 +04:00
self . _update_status ( )
2010-02-27 18:42:43 +03:00
self . connect ( " status-changed " , self . _update_start_vcpus )
2010-09-03 03:08:00 +04:00
self . connect ( " config-changed " , self . _reparse_xml )
2010-02-27 18:42:43 +03:00
2010-02-07 20:10:41 +03:00
##########################
# Internal virDomain API #
##########################
2008-12-17 23:27:06 +03:00
2010-02-07 20:10:41 +03:00
def _define ( self , newxml ) :
self . get_connection ( ) . define_domain ( newxml )
2008-12-17 23:27:06 +03:00
2010-02-07 20:10:41 +03:00
def _XMLDesc ( self , flags ) :
return self . _backend . XMLDesc ( flags )
2008-10-18 23:29:45 +04:00
2010-11-30 03:11:35 +03:00
def support_downtime ( self ) :
return support . check_domain_support ( self . _backend ,
support . SUPPORT_DOMAIN_MIGRATE_DOWNTIME )
2010-02-07 20:10:41 +03:00
def get_info ( self ) :
return self . _backend . info ( )
2009-03-09 07:48:23 +03:00
2010-02-07 20:10:41 +03:00
def status ( self ) :
return self . lastStatus
2009-09-17 00:01:54 +04:00
2010-02-07 20:10:41 +03:00
def _get_record_helper ( self , record_name ) :
if len ( self . record ) == 0 :
return 0
return self . record [ 0 ] [ record_name ]
2008-10-18 23:21:33 +04:00
2010-02-07 20:10:41 +03:00
def get_memory_percentage ( self ) :
return self . _get_record_helper ( " currMemPercent " )
def maximum_memory_percentage ( self ) :
return self . _get_record_helper ( " maxMemPercent " )
def cpu_time ( self ) :
return self . _get_record_helper ( " cpuTime " )
def cpu_time_percentage ( self ) :
return self . _get_record_helper ( " cpuTimePercent " )
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 " )
2008-10-18 23:29:45 +04:00
2010-03-17 23:41:50 +03:00
def _unregister_reboot_listener ( self ) :
if self . reboot_listener == None :
return
try :
self . disconnect ( self . reboot_listener )
self . reboot_listener = None
except :
pass
def manual_reboot ( self ) :
# Attempt a manual reboot via 'shutdown' followed by startup
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 ( )
self . reboot_listener = util . connect_opt_out ( self , " status-changed " ,
reboot_listener , self )
2010-02-07 20:10:41 +03:00
def shutdown ( self ) :
2010-05-13 19:21:01 +04:00
self . set_install_abort ( True )
2010-03-17 23:41:50 +03:00
self . _unregister_reboot_listener ( )
2010-02-07 20:10:41 +03:00
self . _backend . shutdown ( )
self . _update_status ( )
2009-03-09 07:48:23 +03:00
2010-02-07 20:10:41 +03:00
def reboot ( self ) :
2010-05-13 19:21:01 +04:00
self . set_install_abort ( True )
2010-02-07 20:10:41 +03:00
self . _backend . reboot ( 0 )
self . _update_status ( )
2009-09-17 00:01:54 +04:00
2010-02-07 20:10:41 +03:00
def startup ( self ) :
2010-05-13 18:37:31 +04:00
if self . get_cloning ( ) :
raise RuntimeError ( _ ( " Cannot start guest while cloning "
" operation in progress " ) )
2010-02-07 20:10:41 +03:00
self . _backend . create ( )
self . _update_status ( )
2008-10-18 23:21:33 +04:00
2010-02-07 20:10:41 +03:00
def suspend ( self ) :
self . _backend . suspend ( )
self . _update_status ( )
2008-10-18 23:21:33 +04:00
2010-02-07 20:10:41 +03:00
def delete ( self ) :
self . _backend . undefine ( )
2008-10-18 23:21:33 +04:00
2010-02-07 20:10:41 +03:00
def resume ( self ) :
2010-05-13 18:37:31 +04:00
if self . get_cloning ( ) :
raise RuntimeError ( _ ( " Cannot resume guest while cloning "
" operation in progress " ) )
2010-02-07 20:10:41 +03:00
self . _backend . resume ( )
self . _update_status ( )
2008-12-17 23:27:06 +03:00
2010-05-12 20:57:32 +04:00
def hasSavedImage ( self ) :
if not self . managedsave_supported :
return False
return self . _backend . hasManagedSaveImage ( 0 )
2009-03-01 03:27:20 +03:00
2010-12-11 00:04:42 +03:00
def save ( self , filename = None , meter = None ) :
2010-05-13 19:21:01 +04:00
self . set_install_abort ( True )
2010-12-11 00:04:42 +03:00
if meter :
start_job_progress_thread ( self , meter , _ ( " Saving domain to disk " ) )
2010-05-12 20:57:32 +04:00
if not self . managedsave_supported :
self . _backend . save ( filename )
else :
self . _backend . managedSave ( 0 )
2010-12-11 00:04:42 +03:00
2010-02-07 20:10:41 +03:00
self . _update_status ( )
2006-06-15 01:52:49 +04:00
2010-02-07 20:10:41 +03:00
def destroy ( self ) :
2010-05-13 19:21:01 +04:00
self . set_install_abort ( True )
2010-03-17 23:41:50 +03:00
self . _unregister_reboot_listener ( )
2010-02-07 20:10:41 +03:00
self . _backend . destroy ( )
2010-03-17 23:41:50 +03:00
self . _update_status ( )
2006-11-13 23:23:35 +03:00
2010-02-07 20:10:41 +03:00
def interfaceStats ( self , device ) :
return self . _backend . interfaceStats ( device )
2008-10-18 23:21:33 +04:00
2010-02-07 20:10:41 +03:00
def blockStats ( self , device ) :
return self . _backend . blockStats ( device )
2006-06-15 02:51:58 +04:00
2010-02-07 20:10:41 +03:00
def pin_vcpu ( self , vcpu_num , pinlist ) :
self . _backend . pinVcpu ( vcpu_num , pinlist )
2006-06-15 01:52:49 +04:00
2010-02-07 20:10:41 +03:00
def vcpu_info ( self ) :
if self . is_active ( ) and self . getvcpus_supported :
return self . _backend . vcpus ( )
return [ [ ] , [ ] ]
2009-07-22 21:37:53 +04:00
2010-02-07 20:10:41 +03:00
def get_autostart ( self ) :
return self . _backend . autostart ( )
2009-07-22 21:37:53 +04:00
2010-02-07 20:10:41 +03:00
def set_autostart ( self , val ) :
if self . get_autostart ( ) != val :
self . _backend . setAutostart ( val )
2006-06-15 01:52:49 +04:00
2010-12-11 00:04:42 +03:00
def job_info ( self ) :
return self . _backend . jobInfo ( )
2010-12-08 20:52:33 +03:00
def abort_job ( self ) :
self . _backend . abortJob ( )
2010-11-30 03:11:35 +03:00
def migrate_set_max_downtime ( self , max_downtime , flag = 0 ) :
self . _backend . migrateSetMaxDowntime ( max_downtime , flag )
2010-02-07 20:10:41 +03:00
def migrate ( self , destconn , interface = None , rate = 0 ,
2010-12-11 00:04:42 +03:00
live = False , secure = False , meter = None ) :
self . set_install_abort ( True )
2010-02-07 20:10:41 +03:00
newname = None
2008-10-18 23:21:33 +04:00
2010-02-07 20:10:41 +03:00
flags = 0
if self . status ( ) == libvirt . VIR_DOMAIN_RUNNING and live :
flags | = libvirt . VIR_MIGRATE_LIVE
2006-06-15 01:52:49 +04:00
2010-02-07 20:10:41 +03:00
if secure :
flags | = libvirt . VIR_MIGRATE_PEER2PEER
flags | = libvirt . VIR_MIGRATE_TUNNELLED
2006-06-15 01:52:49 +04:00
2010-09-03 20:10:26 +04:00
newxml = self . get_xml ( inactive = True )
2006-11-22 20:50:50 +03:00
2010-02-07 20:10:41 +03:00
logging . debug ( " Migrating: conn= %s flags= %s dname= %s uri= %s rate= %s " %
( destconn . vmm , flags , newname , interface , rate ) )
2010-12-11 00:04:42 +03:00
if meter :
start_job_progress_thread ( self , meter , _ ( " Migrating domain " ) )
2010-02-07 20:10:41 +03:00
self . _backend . migrate ( destconn . vmm , flags , newname , interface , rate )
destconn . define_domain ( newxml )
2006-11-22 20:50:50 +03:00
2010-02-07 20:10:41 +03:00
# Genertc backend APIs
def get_name ( self ) :
return self . _backend . name ( )
def get_id ( self ) :
return self . _backend . ID ( )
2006-11-22 20:50:50 +03:00
2010-09-09 01:53:51 +04:00
# Hotplug routines
def attach_device ( self , devobj ) :
2010-02-07 20:10:41 +03:00
"""
Hotplug device to running guest
"""
2010-02-23 22:18:12 +03:00
if not self . is_active ( ) :
return
2010-09-09 01:53:51 +04:00
devxml = devobj . get_xml_config ( )
2010-02-23 22:18:12 +03:00
self . _backend . attachDevice ( devxml )
2006-10-12 22:02:45 +04:00
2010-09-09 01:53:51 +04:00
def detach_device ( self , devobj ) :
2010-02-07 20:10:41 +03:00
"""
Hotunplug device from running guest
"""
2010-09-09 01:53:51 +04:00
if not self . is_active ( ) :
return
xml = devobj . get_xml_config ( )
self . _backend . detachDevice ( xml )
2006-11-22 20:50:50 +03:00
2010-12-12 05:34:09 +03:00
def update_device ( self , devobj , flags = 1 ) :
if not self . is_active ( ) :
return
# Default flag is VIR_DOMAIN_DEVICE_MODIFY_LIVE
xml = devobj . get_xml_config ( )
self . _backend . updateDeviceFlags ( xml , flags )
2010-02-07 20:10:41 +03:00
def hotplug_vcpus ( self , vcpus ) :
vcpus = int ( vcpus )
if vcpus != self . vcpu_count ( ) :
self . _backend . setVcpus ( vcpus )
2006-10-12 22:02:45 +04:00
2010-02-07 20:10:41 +03:00
def hotplug_memory ( self , memory ) :
if memory != self . get_memory ( ) :
self . _backend . setMemory ( memory )
2009-10-06 01:31:59 +04:00
2010-02-07 20:10:41 +03:00
def hotplug_maxmem ( self , maxmem ) :
if maxmem != self . maximum_memory ( ) :
self . _backend . setMaxMemory ( maxmem )
2008-10-18 23:21:33 +04:00
2010-02-07 20:10:41 +03:00
def hotplug_both_mem ( self , memory , maxmem ) :
logging . info ( " Hotplugging curmem= %s maxmem= %s for VM ' %s ' " %
( memory , maxmem , self . get_name ( ) ) )
2008-07-31 04:38:09 +04:00
2010-02-07 20:10:41 +03: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 )
2009-07-09 22:35:55 +04:00
2010-09-09 01:53:51 +04:00
def hotplug_storage_media ( self , devobj , newpath ) :
devobj . path = newpath
self . attach_device ( devobj )
2010-03-24 05:15:53 +03:00
2010-12-12 05:34:09 +03:00
def hotplug_graphics_password ( self , devobj , newval ) :
devobj . passwd = newval or None
self . update_device ( devobj )
2010-09-09 01:53:51 +04:00
####################
# End internal API #
####################
2009-07-09 22:35:55 +04:00
2010-09-09 01:53:51 +04:00
###########################
# XML/Config Altering API #
###########################
2010-03-24 07:22:17 +03:00
2010-09-09 01:53:51 +04:00
def _get_domain_xml ( self , inactive = False , refresh_if_necc = True ) :
return vmmLibvirtObject . get_xml ( self ,
inactive = inactive ,
refresh_if_necc = refresh_if_necc )
2010-03-24 07:22:17 +03:00
2010-09-09 01:53:51 +04:00
def get_xml ( self , inactive = False , refresh_if_necc = True ) :
guest = self . _get_guest ( inactive = inactive ,
refresh_if_necc = refresh_if_necc )
return guest . get_xml_config ( install = False )
2010-03-24 07:22:17 +03:00
2010-09-09 01:53:51 +04:00
def _get_guest ( self , inactive = False , refresh_if_necc = True ) :
xml = self . _get_domain_xml ( inactive , refresh_if_necc )
2010-03-24 07:22:17 +03:00
2010-12-10 17:48:22 +03: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.
2010-09-09 01:53:51 +04:00
return self . _build_guest ( xml )
2010-03-24 07:22:17 +03:00
2010-09-09 01:53:51 +04:00
return self . _guest
2010-03-24 07:22:17 +03:00
2010-09-09 01:53:51 +04:00
def _build_guest ( self , xml ) :
2010-12-08 20:17:14 +03:00
return virtinst . Guest ( connection = self . connection . vmm ,
parsexml = xml ,
caps = self . connection . get_capabilities ( ) )
2010-03-24 07:22:17 +03:00
2010-09-09 01:53:51 +04:00
def _reparse_xml ( self , ignore = None ) :
self . _guest = self . _build_guest ( self . _get_domain_xml ( ) )
2010-03-24 07:22:17 +03:00
2010-02-07 20:10:41 +03:00
########################
# End XML Altering API #
########################
2009-07-09 22:35:55 +04:00
2010-05-13 20:37:06 +04:00
def _update_start_vcpus ( self , ignore , oldstatus , status ) :
2010-12-09 19:22:35 +03:00
ignore = status
2010-12-10 19:47:07 +03:00
if oldstatus not in [ libvirt . VIR_DOMAIN_SHUTDOWN ,
libvirt . VIR_DOMAIN_SHUTOFF ,
libvirt . VIR_DOMAIN_CRASHED ] :
2010-02-27 18:42:43 +03: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 ( )
2010-02-07 20:10:41 +03:00
def _update_status ( self , status = None ) :
if status == None :
info = self . get_info ( )
status = info [ 0 ]
status = self . _normalize_status ( status )
2009-10-06 02:57:29 +04:00
2010-02-07 20:10:41 +03:00
if status != self . lastStatus :
2010-02-27 18:42:43 +03:00
oldstatus = self . lastStatus
2010-02-07 20:10:41 +03:00
self . lastStatus = status
2010-06-23 21:05:09 +04:00
# Send 'config-changed' before a status-update, so users
# are operating with fresh XML
self . refresh_xml ( )
2010-02-27 18:42:43 +03:00
util . safe_idle_add ( util . idle_emit , self , " status-changed " ,
oldstatus , status )
2009-10-06 02:57:29 +04:00
2010-11-30 01:40:28 +03:00
##################
# Stats handling #
##################
def toggle_sample_network_traffic ( self , ignore1 = None , ignore2 = None ,
ignore3 = None , ignore4 = None ) :
if not self . config . get_stats_enable_net_poll ( ) :
self . _network_traffic = lambda : ( 0 , 0 )
return
if len ( self . record ) > 1 :
# resample the current value before calculating the rate in
# self.tick() otherwise we'd get a huge spike when switching
# from 0 to bytes_transfered_so_far
rxBytes , txBytes = self . _sample_network_traffic ( )
self . record [ 0 ] [ " netRxKB " ] = rxBytes / 1024
self . record [ 0 ] [ " netTxKB " ] = txBytes / 1024
self . _network_traffic = self . _sample_network_traffic
def toggle_sample_disk_io ( self , ignore1 = None , ignore2 = None ,
ignore3 = None , ignore4 = None ) :
if not self . config . get_stats_enable_disk_poll ( ) :
self . _disk_io = lambda : ( 0 , 0 )
return
if len ( self . record ) > 1 :
# resample the current value before calculating the rate in
# self.tick() otherwise we'd get a huge spike when switching
# from 0 to bytes_transfered_so_far
rdBytes , wrBytes = self . _sample_disk_io ( )
self . record [ 0 ] [ " diskRdKB " ] = rdBytes / 1024
self . record [ 0 ] [ " diskWrKB " ] = wrBytes / 1024
self . _disk_io = self . _sample_disk_io
def _sample_network_traffic ( self ) :
rx = 0
tx = 0
if not self . _stats_net_supported or not self . is_active ( ) :
return rx , tx
for netdev in self . get_network_devices ( refresh_if_necc = False ) :
dev = netdev . target_dev
if not dev :
continue
if dev in self . _stats_net_skip :
continue
try :
io = self . interfaceStats ( dev )
if io :
rx + = io [ 0 ]
tx + = io [ 4 ]
except libvirt . libvirtError , err :
if support . is_error_nosupport ( err ) :
logging . debug ( " Net stats not supported: %s " % err )
self . _stats_net_supported = False
else :
logging . error ( " Error reading net stats for "
" ' %s ' dev ' %s ' : %s " %
( self . get_name ( ) , dev , err ) )
logging . debug ( " Adding %s to skip list. " % dev )
self . _stats_net_skip . append ( dev )
return rx , tx
def _sample_disk_io ( self ) :
rd = 0
wr = 0
if not self . _stats_disk_supported or not self . is_active ( ) :
return rd , wr
for disk in self . get_disk_devices ( refresh_if_necc = False ) :
dev = disk . target
if not dev :
continue
if dev in self . _stats_disk_skip :
continue
try :
io = self . blockStats ( dev )
if io :
rd + = io [ 1 ]
wr + = io [ 3 ]
except libvirt . libvirtError , err :
if support . is_error_nosupport ( err ) :
logging . debug ( " Disk stats not supported: %s " % err )
self . _stats_disk_supported = False
else :
logging . error ( " Error reading disk stats for "
" ' %s ' dev ' %s ' : %s " %
( self . get_name ( ) , dev , err ) )
logging . debug ( " Adding %s to skip list. " % dev )
self . _stats_disk_skip . append ( dev )
return rd , wr
2009-10-06 02:57:29 +04:00
2010-02-07 20:10:41 +03:00
def tick ( self , now ) :
if self . connection . get_state ( ) != self . connection . STATE_ACTIVE :
return
2009-10-06 02:57:29 +04:00
2010-02-07 20:10:41 +03:00
# Invalidate cached xml
self . _invalidate_xml ( )
2009-10-06 02:57:29 +04:00
2010-02-07 20:10:41 +03:00
info = self . get_info ( )
expected = self . config . get_stats_history_length ( )
current = len ( self . record )
if current > expected :
del self . record [ expected : current ]
2009-01-15 19:15:04 +03:00
2010-02-07 20:10:41 +03: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
# XXX need to skip this for non-Xen
if self . get_id ( ) == 0 :
info [ 1 ] = self . connection . host_memory_size ( )
2009-01-15 19:15:04 +03:00
2010-02-07 20:10:41 +03:00
cpuTime , cpuTimeAbs , pcentCpuTime = self . _sample_cpu_stats ( info , now )
pcentCurrMem , pcentMaxMem = self . _sample_mem_stats ( info )
rdBytes , wrBytes = self . _disk_io ( )
rxBytes , txBytes = self . _network_traffic ( )
2009-06-18 18:38:15 +04:00
2010-12-10 19:47:07 +03:00
newStats = {
" timestamp " : now ,
" cpuTime " : cpuTime ,
" cpuTimeAbs " : cpuTimeAbs ,
" cpuTimePercent " : pcentCpuTime ,
" currMemPercent " : pcentCurrMem ,
" maxMemPercent " : pcentMaxMem ,
" diskRdKB " : rdBytes / 1024 ,
" diskWrKB " : wrBytes / 1024 ,
" netRxKB " : rxBytes / 1024 ,
" netTxKB " : txBytes / 1024 ,
}
2009-06-18 18:38:15 +04:00
2010-02-07 20:10:41 +03:00
nSamples = 5
if nSamples > len ( self . record ) :
nSamples = len ( self . record )
2008-03-07 00:43:46 +03:00
2010-02-07 20:10:41 +03:00
if nSamples == 0 :
avg = [ " cpuTimeAbs " ]
percent = 0
else :
2010-12-10 19:47:07 +03:00
startCpuTime = self . record [ nSamples - 1 ] [ " cpuTimeAbs " ]
startTimestamp = self . record [ nSamples - 1 ] [ " timestamp " ]
2009-07-07 20:16:03 +04:00
2010-02-07 20:10:41 +03:00
avg = ( ( newStats [ " cpuTimeAbs " ] - startCpuTime ) / nSamples )
percent = ( ( newStats [ " cpuTimeAbs " ] - startCpuTime ) * 100.0 /
( ( ( now - startTimestamp ) * 1000.0 * 1000.0 * 1000.0 ) *
self . connection . host_active_processor_count ( ) ) )
2009-07-07 20:16:03 +04:00
2010-02-07 20:10:41 +03:00
newStats [ " cpuTimeMovingAvg " ] = avg
newStats [ " cpuTimeMovingAvgPercent " ] = percent
2008-10-18 23:29:45 +04:00
2010-12-10 19:47:07 +03:00
for r in [ " diskRd " , " diskWr " , " netRx " , " netTx " ] :
2010-02-07 20:10:41 +03:00
newStats [ r + " Rate " ] = self . _get_cur_rate ( r + " KB " )
self . _set_max_rate ( newStats , r + " Rate " )
self . record . insert ( 0 , newStats )
self . _update_status ( info [ 0 ] )
2010-02-11 20:32:00 +03:00
util . safe_idle_add ( util . idle_emit , self , " resources-sampled " )
2008-10-18 23:29:45 +04:00
2010-02-07 20:16:13 +03:00
class vmmDomainVirtinst ( vmmDomainBase ) :
"""
Domain object backed by a virtinst Guest object .
Used for launching a details window for customizing a VM before install .
"""
2010-12-09 20:37:48 +03:00
def __init__ ( self , connection , backend , uuid ) :
vmmDomainBase . __init__ ( self , connection , backend , uuid )
2010-02-07 20:16:13 +03:00
2010-09-09 01:53:51 +04:00
self . _orig_xml = None
2010-02-07 20:16:13 +03:00
def get_name ( self ) :
return self . _backend . name
def get_id ( self ) :
return - 1
def status ( self ) :
return libvirt . VIR_DOMAIN_SHUTOFF
2010-09-03 20:10:26 +04:00
def get_xml ( self , inactive = False , refresh_if_necc = True ) :
ignore = inactive
ignore = refresh_if_necc
2010-09-09 01:53:51 +04:00
xml = self . _backend . get_xml_config ( install = False )
if not self . _orig_xml :
self . _orig_xml = xml
2010-05-06 21:54:16 +04:00
return xml
2010-02-26 03:35:01 +03:00
2010-09-09 01:53:51 +04:00
# Internal XML implementations
2010-09-08 02:38:01 +04:00
def _get_guest ( self , inactive = False , refresh_if_necc = True ) :
2010-09-09 01:53:51 +04:00
# Make sure XML is up2date
self . get_xml ( )
2010-09-08 02:38:01 +04:00
return self . _backend
2010-09-09 01:53:51 +04:00
def _define ( self , newxml ) :
2010-12-09 19:22:35 +03:00
ignore = newxml
2010-09-09 01:53:51 +04:00
self . _orig_xml = None
util . safe_idle_add ( util . idle_emit , self , " config-changed " )
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 20:16:13 +03:00
# No caching, so no refresh needed
return
def get_autostart ( self ) :
return self . _backend . autostart
2010-11-29 20:55:22 +03:00
# Stats stubs
2010-02-07 20:16:13 +03:00
def get_memory_percentage ( self ) :
return 0
def maximum_memory_percentage ( self ) :
return 0
def cpu_time ( self ) :
return 0
def cpu_time_percentage ( self ) :
return 0
def network_rx_rate ( self ) :
return 0
def network_tx_rate ( self ) :
return 0
def disk_read_rate ( self ) :
return 0
def disk_write_rate ( self ) :
return 0
2010-09-09 01:53:51 +04:00
# Device/XML hotplug implementations
2010-02-07 20:16:13 +03:00
def set_autostart ( self , val ) :
self . _backend . autostart = bool ( val )
2010-09-09 01:53:51 +04:00
util . safe_idle_add ( util . idle_emit , self , " config-changed " )
2010-02-07 20:16:13 +03:00
2010-09-09 01:53:51 +04:00
def attach_device ( self , devobj ) :
2010-02-07 20:16:13 +03:00
return
2010-09-09 01:53:51 +04:00
def detach_device ( self , devobj ) :
2010-02-07 20:16:13 +03:00
return
2010-12-12 05:34:09 +03:00
def update_device ( self , devobj , flags = 1 ) :
ignore = devobj
ignore = flags
return
def hotplug_graphics_password ( self , devobj , newval ) :
return
2010-09-09 01:53:51 +04:00
def hotplug_storage_media ( self , devobj , newpath ) :
2010-02-07 20:16:13 +03:00
return
def hotplug_vcpus ( self , vcpus ) :
2010-09-09 01:53:51 +04:00
raise NotImplementedError ( )
2010-02-07 20:16:13 +03:00
def hotplug_both_mem ( self , memory , maxmem ) :
2010-09-09 01:53:51 +04:00
raise NotImplementedError ( )
2010-02-07 20:16:13 +03:00
2010-12-09 20:37:48 +03:00
vmmLibvirtObject . type_register ( vmmDomainVirtinst )
vmmLibvirtObject . type_register ( vmmDomainBase )
vmmLibvirtObject . type_register ( vmmDomain )