2013-03-18 01:06:52 +04:00
#
# Common code for all guests
#
2013-10-28 00:59:47 +04:00
# Copyright 2006-2009, 2013 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
# Jeremy Katz <katzj@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
2013-10-28 00:59:47 +04:00
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
2013-03-18 01:06:52 +04:00
#
# 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
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
import logging
import urlgrabber . progress as progress
import libvirt
2013-10-03 02:06:52 +04:00
from virtcli import cliconfig
2013-07-17 15:53:47 +04:00
import virtinst
2013-04-11 03:48:07 +04:00
from virtinst import util
from virtinst import support
2013-08-09 04:47:17 +04:00
from virtinst import OSXML
from virtinst import VirtualDevice
from virtinst import Clock
from virtinst import Seclabel
from virtinst import CPU
from virtinst import DomainNumatune
from virtinst import DomainFeatures
2013-09-11 02:32:10 +04:00
from virtinst . xmlbuilder import XMLBuilder , XMLProperty , XMLChildProperty
2013-04-11 03:48:07 +04:00
from virtinst import osdict
2013-03-18 01:06:52 +04:00
2013-07-14 02:56:09 +04:00
class Guest ( XMLBuilder ) :
2013-08-09 22:16:59 +04:00
@staticmethod
def check_vm_collision ( conn , name , do_remove ) :
"""
Remove the existing VM with the same name if requested , or error
if there is a collision .
"""
vm = None
try :
vm = conn . lookupByName ( name )
except libvirt . libvirtError :
pass
if vm is None :
return
if not do_remove :
raise RuntimeError ( _ ( " Domain named %s already exists! " ) % name )
try :
logging . debug ( " Explicitly replacing guest ' %s ' " , name )
if vm . ID ( ) != - 1 :
logging . info ( " Destroying guest ' %s ' " , name )
vm . destroy ( )
logging . info ( " Undefining guest ' %s ' " , name )
vm . undefine ( )
except libvirt . libvirtError , e :
raise RuntimeError ( _ ( " Could not remove old vm ' %s ' : %s " ) %
( str ( e ) ) )
@staticmethod
2014-01-18 03:44:26 +04:00
def validate_name ( conn , name , check_collision , validate = True ) :
if validate :
util . validate_name ( _ ( " Guest " ) , name )
2013-08-09 22:16:59 +04:00
if not check_collision :
return
try :
conn . lookupByName ( name )
except :
return
raise ValueError ( _ ( " Guest name ' %s ' is already in use. " ) % name )
2013-07-18 01:58:24 +04:00
2013-09-11 19:47:09 +04:00
_XML_ROOT_NAME = " domain "
2013-09-24 14:56:16 +04:00
_XML_PROP_ORDER = [ " type " , " name " , " uuid " , " title " , " description " ,
2013-07-18 01:58:24 +04:00
" maxmemory " , " memory " , " hugepage " , " vcpus " , " curvcpus " ,
" numatune " , " bootloader " , " os " , " features " , " cpu " , " clock " ,
2013-09-20 18:47:36 +04:00
" on_poweroff " , " on_reboot " , " on_crash " , " emulator " , " _devices " ,
2013-07-18 01:58:24 +04:00
" seclabel " ]
2013-09-11 19:47:09 +04:00
def __init__ ( self , * args , * * kwargs ) :
XMLBuilder . __init__ ( self , * args , * * kwargs )
2013-08-09 19:04:01 +04:00
2013-07-18 01:58:24 +04:00
self . autostart = False
self . replace = False
self . os_autodetect = False
2013-03-18 01:06:52 +04:00
2013-10-03 02:06:52 +04:00
# Allow virt-manager to override the default graphics type
self . default_graphics_type = cliconfig . default_graphics
2013-10-06 17:41:37 +04:00
self . skip_default_console = False
self . skip_default_channel = False
2013-03-18 01:06:52 +04:00
self . _os_variant = None
2013-07-25 22:36:13 +04:00
self . _random_uuid = None
2013-09-11 02:32:10 +04:00
self . _install_devices = [ ]
2013-03-18 01:06:52 +04:00
# The libvirt virDomain object we 'Create'
self . domain = None
2013-09-11 19:47:09 +04:00
self . installer = virtinst . DistroInstaller ( self . conn )
2013-03-18 01:06:52 +04:00
######################
# Property accessors #
######################
2013-07-18 01:58:24 +04:00
def _validate_name ( self , val ) :
if val == self . name :
return
2013-08-09 22:16:59 +04:00
self . validate_name ( self . conn , val , check_collision = not self . replace )
2013-09-19 21:27:30 +04:00
name = XMLProperty ( " ./name " , validate_cb = _validate_name )
2013-03-18 01:06:52 +04:00
2013-07-18 01:58:24 +04:00
def _set_memory ( self , val ) :
if val is None :
return None
2013-03-18 01:06:52 +04:00
if self . maxmemory is None or self . maxmemory < val :
self . maxmemory = val
return val
2013-09-19 21:27:30 +04:00
memory = XMLProperty ( " ./currentMemory " , is_int = True ,
2013-07-18 01:58:24 +04:00
default_cb = lambda s : 1 ,
set_converter = _set_memory )
2013-09-19 21:27:30 +04:00
maxmemory = XMLProperty ( " ./memory " , is_int = True )
2013-03-18 01:06:52 +04:00
2013-07-18 01:58:24 +04:00
def _set_vcpus ( self , val ) :
if val is None :
return None
2013-03-18 01:06:52 +04:00
2013-07-18 01:58:24 +04:00
# Don't force set curvcpus unless already specified
if self . curvcpus is not None and self . curvcpus > val :
self . curvcpus = val
return val
2013-09-19 21:27:30 +04:00
vcpus = XMLProperty ( " ./vcpu " , is_int = True ,
2013-07-18 01:58:24 +04:00
set_converter = _set_vcpus ,
default_cb = lambda s : 1 )
2013-09-19 21:27:30 +04:00
curvcpus = XMLProperty ( " ./vcpu/@current " , is_int = True )
2013-07-18 01:58:24 +04:00
def _validate_cpuset ( self , val ) :
2013-03-18 01:06:52 +04:00
DomainNumatune . validate_cpuset ( self . conn , val )
2013-09-19 21:27:30 +04:00
cpuset = XMLProperty ( " ./vcpu/@cpuset " ,
2013-07-18 01:58:24 +04:00
validate_cb = _validate_cpuset )
2013-07-25 22:36:13 +04:00
def _get_default_uuid ( self ) :
if self . _random_uuid is None :
self . _random_uuid = util . generate_uuid ( self . conn )
return self . _random_uuid
2013-09-19 21:27:30 +04:00
uuid = XMLProperty ( " ./uuid " ,
2013-07-25 22:36:13 +04:00
validate_cb = lambda s , v : util . validate_uuid ( v ) ,
default_cb = _get_default_uuid )
2013-09-24 05:27:42 +04:00
id = XMLProperty ( " ./@id " , is_int = True )
2013-09-19 21:27:30 +04:00
type = XMLProperty ( " ./@type " , default_cb = lambda s : " xen " )
hugepage = XMLProperty ( " ./memoryBacking/hugepages " , is_bool = True )
bootloader = XMLProperty ( " ./bootloader " )
description = XMLProperty ( " ./description " )
2013-09-24 14:56:16 +04:00
title = XMLProperty ( " ./title " )
2013-09-19 21:27:30 +04:00
emulator = XMLProperty ( " ./devices/emulator " )
2013-07-18 01:58:24 +04:00
2013-09-19 21:27:30 +04:00
on_poweroff = XMLProperty ( " ./on_poweroff " ,
2013-07-18 01:58:24 +04:00
default_cb = lambda s : " destroy " )
2013-09-19 21:27:30 +04:00
on_reboot = XMLProperty ( " ./on_reboot " )
on_crash = XMLProperty ( " ./on_crash " )
2013-07-18 01:58:24 +04:00
2013-09-11 19:47:09 +04:00
os = XMLChildProperty ( OSXML , is_single = True )
features = XMLChildProperty ( DomainFeatures , is_single = True )
clock = XMLChildProperty ( Clock , is_single = True )
seclabel = XMLChildProperty ( Seclabel , is_single = True )
cpu = XMLChildProperty ( CPU , is_single = True )
numatune = XMLChildProperty ( DomainNumatune , is_single = True )
2013-07-18 01:58:24 +04:00
###############################
# Distro detection properties #
###############################
2013-08-11 02:48:43 +04:00
def _get_os_variant ( self ) :
2013-03-18 01:06:52 +04:00
return self . _os_variant
2013-08-11 02:48:43 +04:00
def _set_os_variant ( self , val ) :
2013-11-10 03:33:49 +04:00
logging . debug ( " Setting Guest.os_variant to ' %s ' " , val )
2013-03-18 01:06:52 +04:00
val = val . lower ( )
2013-08-11 02:48:43 +04:00
if osdict . lookup_os ( val ) is None :
raise ValueError ( _ ( " Distro ' %s ' does not exist in our dictionary " )
% val )
self . _os_variant = val
os_variant = property ( _get_os_variant , _set_os_variant )
2013-03-18 01:06:52 +04:00
########################################
# Device Add/Remove Public API methods #
########################################
2013-07-25 22:11:09 +04:00
def add_device ( self , dev ) :
2013-03-18 01:06:52 +04:00
"""
Add the passed device to the guest ' s device list.
@param dev : VirtualDevice instance to attach to guest
"""
2013-09-10 03:45:19 +04:00
self . _add_child ( dev )
2013-07-24 16:46:55 +04:00
2013-09-11 02:32:10 +04:00
def remove_device ( self , dev ) :
"""
Remove the passed device from the guest ' s device list
@param dev : VirtualDevice instance
"""
self . _remove_child ( dev )
2013-03-18 01:06:52 +04:00
def get_devices ( self , devtype ) :
"""
Return a list of devices of type ' devtype ' that will installed on
the guest .
@param devtype : Device type to search for ( one of
VirtualDevice . virtual_device_types )
"""
2013-09-11 02:32:10 +04:00
newlist = [ ]
for i in self . _devices :
if devtype == " all " or i . virtual_device_type == devtype :
newlist . append ( i )
return newlist
_devices = XMLChildProperty (
[ VirtualDevice . virtual_device_classes [ _n ]
2013-09-11 19:47:09 +04:00
for _n in VirtualDevice . virtual_device_types ] ,
relative_xpath = " ./devices " )
2013-03-18 01:06:52 +04:00
def get_all_devices ( self ) :
"""
Return a list of all devices being installed with the guest
"""
retlist = [ ]
for devtype in VirtualDevice . virtual_device_types :
retlist . extend ( self . get_devices ( devtype ) )
return retlist
############################
# Install Helper functions #
############################
def _prepare_install ( self , meter , dry = False ) :
2013-07-24 22:37:07 +04:00
for dev in self . _install_devices :
self . remove_device ( dev )
2013-03-18 01:06:52 +04:00
self . _install_devices = [ ]
ignore = dry
# Fetch install media, prepare installer devices
2013-07-17 15:53:47 +04:00
self . installer . prepare ( self , meter ,
util . make_scratchdir ( self . conn , self . type ) )
2013-03-18 01:06:52 +04:00
# Initialize install device list
2013-07-17 00:47:08 +04:00
for dev in self . installer . install_devices :
2013-07-24 22:37:07 +04:00
self . add_device ( dev )
2013-03-18 01:06:52 +04:00
self . _install_devices . append ( dev )
2013-07-18 01:58:24 +04:00
2013-03-18 01:06:52 +04:00
##############
# Public API #
##############
2013-07-18 01:58:24 +04:00
def _prepare_get_xml ( self ) :
2013-07-17 21:06:01 +04:00
# We do a shallow copy of the device list here, and set the defaults.
# This way, default changes aren't persistent, and we don't need
# to worry about when to call set_defaults
2013-09-11 19:47:09 +04:00
#
# XXX: this is hacky, we should find a way to use xmlbuilder.copy(),
# but need to make sure it's not a massive performance hit
2013-09-11 02:32:10 +04:00
data = ( self . _devices [ : ] , self . features , self . os )
2013-07-17 21:06:01 +04:00
try :
2013-09-11 02:32:10 +04:00
self . _propstore [ " _devices " ] = [ dev . copy ( ) for dev in self . _devices ]
2013-09-11 19:47:09 +04:00
self . _propstore [ " features " ] = self . features . copy ( )
self . _propstore [ " os " ] = self . os . copy ( )
2013-07-18 01:58:24 +04:00
except :
self . _finish_get_xml ( data )
raise
return data
def _finish_get_xml ( self , data ) :
2013-09-11 19:47:09 +04:00
( self . _propstore [ " _devices " ] ,
self . _propstore [ " features " ] ,
self . _propstore [ " os " ] ) = data
2013-07-17 21:06:01 +04:00
2013-07-24 19:32:30 +04:00
def get_install_xml ( self , * args , * * kwargs ) :
data = self . _prepare_get_xml ( )
try :
return self . _do_get_install_xml ( * args , * * kwargs )
finally :
self . _finish_get_xml ( data )
def _do_get_install_xml ( self , install = True , disk_boot = False ) :
2013-03-18 01:06:52 +04:00
"""
Return the full Guest xml configuration .
@param install : Whether we want the ' OS install ' configuration or
the ' post-install ' configuration . ( Some Installers ,
like the LiveCDInstaller may not have an ' install '
config . )
@type install : C { bool }
@param disk_boot : Whether we should boot off the harddisk , regardless
of our position in the install process ( this is
used for 2 stage installs , where the second stage
boots off the disk . You probably don ' t need to touch
this . )
@type disk_boot : C { bool }
"""
2013-07-17 21:06:01 +04:00
osblob_install = install and not disk_boot
2013-03-18 01:06:52 +04:00
if osblob_install and not self . installer . has_install_phase ( ) :
return None
2013-07-18 01:58:24 +04:00
self . installer . alter_bootconfig ( self , osblob_install , self . os )
self . _set_transient_device_defaults ( install )
action = install and " destroy " or " restart "
self . on_reboot = action
self . on_crash = action
2013-07-24 19:32:30 +04:00
self . _set_defaults ( )
2013-07-18 01:58:24 +04:00
self . bootloader = None
2013-07-17 21:06:01 +04:00
if ( not install and
self . os . is_xenpv ( ) and
not self . os . kernel ) :
2013-07-18 01:58:24 +04:00
self . bootloader = " /usr/bin/pygrub "
self . os . clear ( )
2013-07-24 19:32:30 +04:00
return self . get_xml_config ( )
2013-03-18 01:06:52 +04:00
def get_continue_inst ( self ) :
"""
Return True if this guest requires a call to ' continue_install ' ,
which means the OS requires a 2 stage install ( windows )
"""
# If we are doing an 'import' or 'liveCD' install, there is
# no true install process, so continue install has no meaning
if not self . installer . has_install_phase ( ) :
return False
2013-08-11 23:29:31 +04:00
return self . _lookup_osdict_key ( " three_stage_install " , False )
2013-03-18 01:06:52 +04:00
2013-07-25 22:36:13 +04:00
2013-03-18 01:06:52 +04:00
##########################
# Actual install methods #
##########################
2013-08-09 22:16:59 +04:00
def start_install ( self , meter = None ,
2013-08-09 19:25:05 +04:00
dry = False , return_xml = False , noboot = False ) :
2013-03-18 01:06:52 +04:00
"""
Begin the guest install ( stage1 ) .
@param return_xml : Don ' t create the guest, just return generated XML
"""
2013-07-14 03:43:52 +04:00
if self . domain is not None :
raise RuntimeError ( _ ( " Domain has already been started! " ) )
2013-03-18 01:06:52 +04:00
2013-07-14 03:43:52 +04:00
is_initial = True
2013-03-18 01:06:52 +04:00
self . _prepare_install ( meter , dry )
try :
# Create devices if required (disk images, etc.)
if not dry :
2013-08-15 03:43:02 +04:00
for dev in self . get_all_devices ( ) :
dev . setup ( meter )
2013-03-18 01:06:52 +04:00
start_xml , final_xml = self . _build_xml ( is_initial )
if return_xml :
return ( start_xml , final_xml )
if dry :
return
# Remove existing VM if requested
2013-08-09 22:16:59 +04:00
self . check_vm_collision ( self . conn , self . name ,
do_remove = self . replace )
2013-03-18 01:06:52 +04:00
2013-08-09 19:25:05 +04:00
self . domain = self . _create_guest ( meter ,
2013-03-18 01:06:52 +04:00
start_xml , final_xml , is_initial ,
noboot )
# Set domain autostart flag if requested
self . _flag_autostart ( )
return self . domain
finally :
2013-08-15 03:43:02 +04:00
self . installer . cleanup ( )
2013-03-18 01:06:52 +04:00
2013-08-09 19:25:05 +04:00
def continue_install ( self , meter = None ,
2013-03-18 01:06:52 +04:00
dry = False , return_xml = False ) :
"""
Continue with stage 2 of a guest install . Only required for
guests which have the ' continue ' flag set ( accessed via
get_continue_inst )
"""
is_initial = False
start_xml , final_xml = self . _build_xml ( is_initial )
if return_xml :
return ( start_xml , final_xml )
if dry :
return
2013-08-09 19:25:05 +04:00
return self . _create_guest ( meter ,
2013-03-18 01:06:52 +04:00
start_xml , final_xml , is_initial , False )
def _build_meter ( self , meter , is_initial ) :
if is_initial :
meter_label = _ ( " Creating domain... " )
else :
meter_label = _ ( " Starting domain... " )
2013-04-13 22:34:52 +04:00
if meter is None :
2013-03-18 01:06:52 +04:00
meter = progress . BaseMeter ( )
meter . start ( size = None , text = meter_label )
return meter
def _build_xml ( self , is_initial ) :
log_label = is_initial and " install " or " continue "
disk_boot = not is_initial
2013-07-24 19:32:30 +04:00
start_xml = self . get_install_xml ( install = True , disk_boot = disk_boot )
final_xml = self . get_install_xml ( install = False )
2013-03-18 01:06:52 +04:00
logging . debug ( " Generated %s XML: %s " ,
log_label ,
( start_xml and ( " \n " + start_xml ) or " None required " ) )
logging . debug ( " Generated boot XML: \n %s " , final_xml )
return start_xml , final_xml
2013-08-09 19:25:05 +04:00
def _create_guest ( self , meter ,
2013-03-18 01:06:52 +04:00
start_xml , final_xml , is_initial , noboot ) :
"""
Actually do the XML logging , guest defining / creating , console
launching and waiting
@param is_initial : If running initial guest creation , else we
are continuing the install
@param noboot : Don ' t boot guest if no install phase
"""
meter = self . _build_meter ( meter , is_initial )
doboot = not noboot or self . installer . has_install_phase ( )
if is_initial and doboot :
dom = self . conn . createLinux ( start_xml or final_xml , 0 )
else :
dom = self . conn . defineXML ( start_xml or final_xml )
if doboot :
dom . create ( )
self . domain = dom
meter . end ( 0 )
self . domain = self . conn . defineXML ( final_xml )
if is_initial :
try :
logging . debug ( " XML fetched from libvirt object: \n %s " ,
dom . XMLDesc ( 0 ) )
except Exception , e :
logging . debug ( " Error fetching XML from libvirt object: %s " , e )
2013-08-09 19:25:05 +04:00
return self . domain
2013-03-18 01:06:52 +04:00
def _flag_autostart ( self ) :
"""
Set the autostart flag for self . domain if the user requested it
"""
if not self . autostart :
return
try :
self . domain . setAutostart ( True )
except libvirt . libvirtError , e :
2013-07-06 19:20:28 +04:00
if util . is_error_nosupport ( e ) :
2013-03-18 01:06:52 +04:00
logging . warn ( " Could not set autostart flag: libvirt "
" connection does not support autostart. " )
else :
raise e
2013-08-17 22:21:30 +04:00
###################################
# Guest Dictionary Helper methods #
###################################
def _lookup_osdict_key ( self , key , default ) :
"""
Use self . os_variant to find key in OSTYPES
@returns : dict value , or None if os_type / variant wasn ' t set
"""
2013-08-18 01:53:17 +04:00
return osdict . lookup_osdict_key ( self . os_variant , key , default )
2013-08-17 22:21:30 +04:00
2013-03-18 01:06:52 +04:00
###################
# Device defaults #
###################
2013-07-25 22:36:13 +04:00
def add_default_input_device ( self ) :
if self . os . is_container ( ) :
return
2013-08-18 16:59:19 +04:00
if not self . os . is_x86 ( ) :
return
2013-10-06 16:30:33 +04:00
if self . get_devices ( " input " ) :
return
2013-07-25 22:36:13 +04:00
self . add_device ( virtinst . VirtualInputDevice ( self . conn ) )
2013-08-18 16:59:19 +04:00
def add_default_sound_device ( self ) :
if not self . os . is_hvm ( ) :
return
if not self . os . is_x86 ( ) :
return
self . add_device ( virtinst . VirtualAudio ( self . conn ) )
2013-07-25 22:36:13 +04:00
def add_default_console_device ( self ) :
2013-10-06 17:41:37 +04:00
if self . skip_default_console :
return
2013-07-25 22:36:13 +04:00
if self . os . is_xenpv ( ) :
return
2013-10-06 16:30:33 +04:00
if self . get_devices ( " console " ) or self . get_devices ( " serial " ) :
return
2013-07-25 22:36:13 +04:00
dev = virtinst . VirtualConsoleDevice ( self . conn )
dev . type = dev . TYPE_PTY
2013-10-06 16:53:05 +04:00
if ( self . os . is_x86 ( ) and
self . _lookup_osdict_key ( " virtioconsole " , False ) and
2013-10-06 18:08:04 +04:00
self . conn . check_support (
2013-10-06 16:53:05 +04:00
self . conn . SUPPORT_CONN_VIRTIO_CONSOLE ) ) :
dev . target_type = " virtio "
2013-07-25 22:36:13 +04:00
self . add_device ( dev )
2013-08-18 16:59:19 +04:00
def add_default_video_device ( self ) :
if self . os . is_container ( ) :
return
2013-10-06 16:30:33 +04:00
if self . get_devices ( " video " ) :
return
if not self . get_devices ( " graphics " ) :
return
2013-08-18 16:59:19 +04:00
self . add_device ( virtinst . VirtualVideoDevice ( self . conn ) )
2013-10-02 23:51:01 +04:00
def add_default_usb_controller ( self ) :
if self . os . is_container ( ) :
return
if not self . os . is_x86 ( ) :
return
2013-10-06 16:30:33 +04:00
if any ( [ d . type == " usb " for d in self . get_devices ( " controller " ) ] ) :
return
2013-10-06 18:08:04 +04:00
if not self . conn . check_support (
2013-10-02 23:51:01 +04:00
self . conn . SUPPORT_CONN_DEFAULT_USB2 ) :
return
for dev in virtinst . VirtualController . get_usb2_controllers ( self . conn ) :
self . add_device ( dev )
2013-10-06 17:19:59 +04:00
def add_default_channels ( self ) :
2013-10-06 17:41:37 +04:00
if self . skip_default_channel :
return
2013-10-06 17:19:59 +04:00
if self . get_devices ( " channel " ) :
return
2014-01-12 23:58:43 +04:00
# Skip qemu-ga on ARM where virtio slots are currently limited
2013-10-06 17:19:59 +04:00
if ( self . conn . is_qemu ( ) and
2014-01-12 23:58:43 +04:00
not self . os . is_arm ( ) and
2013-10-06 17:19:59 +04:00
self . _lookup_osdict_key ( " qemu_ga " , False ) and
2013-10-06 18:08:04 +04:00
self . conn . check_support ( self . conn . SUPPORT_CONN_AUTOSOCKET ) ) :
2013-10-06 17:19:59 +04:00
dev = virtinst . VirtualChannelDevice ( self . conn )
dev . type = " unix "
dev . target_type = " virtio "
dev . target_name = dev . CHANNEL_NAME_QEMUGA
self . add_device ( dev )
2013-07-18 01:58:24 +04:00
def _set_transient_device_defaults ( self , install ) :
def do_remove_media ( d ) :
# Keep cdrom around, but with no media attached,
# But only if we are a distro that doesn't have a multi
# stage install (aka not Windows)
2013-08-17 22:21:30 +04:00
return ( d . is_cdrom ( ) and
d . transient and
not install and
2013-07-18 01:58:24 +04:00
not self . get_continue_inst ( ) )
def do_skip_disk ( d ) :
# Skip transient labeled non-media disks
2013-08-17 22:21:30 +04:00
return ( d . is_disk ( ) and d . transient and not install )
2013-07-18 01:58:24 +04:00
2013-08-17 22:21:30 +04:00
for dev in self . get_devices ( " disk " ) :
2013-07-18 01:58:24 +04:00
if do_skip_disk ( dev ) :
self . remove_device ( dev )
2013-08-17 22:21:30 +04:00
elif do_remove_media ( dev ) :
2013-07-18 01:58:24 +04:00
dev . path = None
2013-07-24 19:32:30 +04:00
def _set_defaults ( self ) :
2013-07-18 01:58:24 +04:00
self . _set_osxml_defaults ( )
2013-07-25 22:36:13 +04:00
self . _set_clock_defaults ( )
2013-07-18 01:58:24 +04:00
self . _set_emulator_defaults ( )
self . _set_cpu_defaults ( )
2013-07-25 22:36:13 +04:00
self . _set_feature_defaults ( )
2013-07-18 01:58:24 +04:00
2013-07-25 22:36:13 +04:00
for dev in self . get_all_devices ( ) :
2013-10-06 21:17:35 +04:00
dev . set_defaults ( self )
2013-07-25 22:36:13 +04:00
self . _add_implied_controllers ( )
2013-09-02 18:56:53 +04:00
self . _check_address_multi ( )
2013-07-25 22:36:13 +04:00
self . _set_disk_defaults ( )
self . _set_net_defaults ( )
self . _set_input_defaults ( )
self . _set_sound_defaults ( )
2013-10-03 02:06:52 +04:00
self . _set_graphics_defaults ( )
2013-07-25 22:36:13 +04:00
self . _set_video_defaults ( )
2013-07-18 01:58:24 +04:00
def _set_osxml_defaults ( self ) :
if self . os . is_container ( ) and not self . os . init :
for fs in self . get_devices ( " filesystem " ) :
if fs . target == " / " :
self . os . init = " /sbin/init "
break
self . os . init = self . os . init or " /bin/sh "
if not self . os . loader and self . os . is_hvm ( ) and self . type == " xen " :
self . os . loader = " /usr/lib/xen/boot/hvmloader "
if self . os . os_type == " xen " and self . type == " xen " :
# Use older libvirt 'linux' value for back compat
self . os . os_type = " linux "
if self . os . kernel or self . os . init :
self . os . bootorder = [ ]
2013-08-18 01:53:17 +04:00
if ( self . os . machine is None and self . os . is_ppc64 ( ) ) :
2013-07-25 22:36:13 +04:00
self . os . machine = " pseries "
2013-03-18 01:06:52 +04:00
2013-07-25 22:36:13 +04:00
def _set_clock_defaults ( self ) :
if not self . os . is_hvm ( ) :
return
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
if self . clock . offset is None :
2013-08-11 23:29:31 +04:00
self . clock . offset = self . _lookup_osdict_key ( " clock " , " utc " )
2013-03-18 01:06:52 +04:00
2013-10-06 01:02:26 +04:00
if self . clock . timers :
return
if not self . os . is_x86 ( ) :
return
2013-10-06 18:08:04 +04:00
if not self . conn . check_support (
2013-10-06 01:02:26 +04:00
self . conn . SUPPORT_CONN_ADVANCED_CLOCK ) :
return
# Set clock policy that maps to qemu options:
# -no-hpet -no-kvm-pit-reinjection -rtc driftfix=slew
#
# hpet: Is unneeded and has a performance penalty
# pit: While it has no effect on windows, it doesn't hurt and
# is beneficial for linux
#
# This is what has been recommended by the RH qemu guys :)
rtc = self . clock . add_timer ( )
rtc . name = " rtc "
rtc . tickpolicy = " catchup "
pit = self . clock . add_timer ( )
pit . name = " pit "
pit . tickpolicy = " delay "
hpet = self . clock . add_timer ( )
hpet . name = " hpet "
hpet . present = False
2013-07-25 22:36:13 +04:00
def _set_emulator_defaults ( self ) :
if self . os . is_xenpv ( ) :
self . emulator = None
return
if self . emulator :
return
2013-03-18 01:06:52 +04:00
2013-07-25 22:36:13 +04:00
if self . os . is_hvm ( ) and self . type == " xen " :
if self . conn . caps . host . arch == " x86_64 " :
self . emulator = " /usr/lib64/xen/bin/qemu-dm "
else :
self . emulator = " /usr/lib/xen/bin/qemu-dm "
2013-03-18 01:06:52 +04:00
2013-07-25 22:36:13 +04:00
def _set_cpu_defaults ( self ) :
self . cpu . set_topology_defaults ( self . vcpus )
2013-03-18 01:06:52 +04:00
2013-07-18 01:58:24 +04:00
def _set_feature_defaults ( self ) :
if self . os . is_container ( ) :
self . features . acpi = None
self . features . apic = None
self . features . pae = None
return
if not self . os . is_hvm ( ) :
return
2013-08-18 01:53:17 +04:00
default = True
if ( self . _lookup_osdict_key ( " xen_disable_acpi " , False ) and
2013-10-06 18:08:04 +04:00
self . conn . check_support (
2013-10-03 00:41:23 +04:00
support . SUPPORT_CONN_SKIP_DEFAULT_ACPI ) ) :
2013-08-18 01:53:17 +04:00
default = False
2013-09-27 23:08:44 +04:00
if self . features . acpi == " default " :
self . features . acpi = self . _lookup_osdict_key ( " acpi " , default )
if self . features . apic == " default " :
self . features . apic = self . _lookup_osdict_key ( " apic " , default )
if self . features . pae == " default " :
self . features . pae = self . conn . caps . support_pae ( )
2013-07-18 01:58:24 +04:00
2013-07-25 22:36:13 +04:00
def _add_implied_controllers ( self ) :
for dev in self . get_all_devices ( ) :
2013-07-18 01:58:24 +04:00
# Add spapr-vio controller if needed
if ( dev . address . type == " spapr-vio " and
2013-07-24 16:46:55 +04:00
dev . virtual_device_type == " disk " and
2013-07-18 01:58:24 +04:00
not any ( [ cont . address . type == " spapr-vio " for cont in
self . get_devices ( " controller " ) ] ) ) :
ctrl = virtinst . VirtualController ( self . conn )
ctrl . type = " scsi "
ctrl . address . set_addrstr ( " spapr-vio " )
self . add_device ( ctrl )
2013-09-02 18:56:53 +04:00
def _check_address_multi ( self ) :
addresses = { }
2013-09-20 18:47:36 +04:00
for d in self . get_all_devices ( ) :
2013-09-02 18:56:53 +04:00
if d . address . type != d . address . ADDRESS_TYPE_PCI :
continue
addr = d . address
addrstr = " %d %d %d " % ( d . address . domain ,
d . address . bus ,
d . address . slot )
if addrstr not in addresses :
addresses [ addrstr ] = { }
if addr . function in addresses [ addrstr ] :
raise ValueError ( _ ( " Duplicate address for devices %s and %s " ) %
( str ( d ) , str ( addresses [ addrstr ] [ addr . function ] ) ) )
addresses [ addrstr ] [ addr . function ] = d
for devs in addresses . values ( ) :
if len ( devs ) > 1 and 0 in devs :
devs [ 0 ] . address . multifunction = True
2013-08-18 01:53:17 +04:00
def _can_virtio ( self , key ) :
2013-08-18 01:59:17 +04:00
if not self . conn . is_qemu ( ) :
2013-08-18 01:53:17 +04:00
return False
if not self . _lookup_osdict_key ( key , False ) :
return False
2013-08-18 16:59:19 +04:00
if self . os . is_x86 ( ) :
return True
if ( self . os . is_arm_vexpress ( ) and
self . os . dtb and
self . _lookup_osdict_key ( " virtiommio " , False ) and
2013-10-06 18:08:04 +04:00
self . conn . check_support ( support . SUPPORT_CONN_VIRTIO_MMIO ) ) :
2013-08-18 16:59:19 +04:00
return True
return False
2013-08-18 01:53:17 +04:00
2013-07-25 22:36:13 +04:00
def _set_disk_defaults ( self ) :
2013-08-18 01:53:17 +04:00
os_disk_bus = self . _lookup_osdict_key ( " diskbus " , None )
2013-07-18 01:58:24 +04:00
2013-07-25 22:36:13 +04:00
def set_disk_bus ( d ) :
2013-08-17 22:21:30 +04:00
if d . is_floppy ( ) :
2013-07-25 22:36:13 +04:00
d . bus = " fdc "
return
if self . os . is_xenpv ( ) :
d . bus = " xen "
return
2013-08-17 22:21:30 +04:00
if not self . os . is_hvm ( ) :
d . bus = " ide "
return
2013-03-18 01:06:52 +04:00
2013-08-18 01:53:17 +04:00
if self . _can_virtio ( " virtiodisk " ) and d . is_disk ( ) :
d . bus = " virtio "
elif os_disk_bus and d . is_disk ( ) :
2013-08-17 22:21:30 +04:00
d . bus = os_disk_bus
2013-08-18 01:53:17 +04:00
elif self . os . is_pseries ( ) :
2013-08-17 22:21:30 +04:00
d . bus = " scsi "
2013-08-18 16:59:19 +04:00
elif self . os . is_arm ( ) :
d . bus = " sd "
2013-08-17 22:21:30 +04:00
else :
d . bus = " ide "
2013-03-18 01:06:52 +04:00
used_targets = [ ]
2013-07-24 16:46:55 +04:00
for disk in self . get_devices ( " disk " ) :
2013-03-18 01:06:52 +04:00
if not disk . bus :
2013-07-25 22:36:13 +04:00
set_disk_bus ( disk )
# Generate disk targets
2013-03-18 01:06:52 +04:00
if disk . target :
used_targets . append ( disk . target )
else :
used_targets . append ( disk . generate_target ( used_targets ) )
2013-07-25 22:36:13 +04:00
def _set_net_defaults ( self ) :
if not self . os . is_hvm ( ) :
net_model = None
2013-08-18 01:53:17 +04:00
elif self . _can_virtio ( " virtionet " ) :
net_model = " virtio "
else :
net_model = self . _lookup_osdict_key ( " netmodel " , None )
2013-07-25 22:36:13 +04:00
for net in self . get_devices ( " interface " ) :
if net_model and not net . model :
net . model = net_model
def _set_input_defaults ( self ) :
2013-08-11 23:29:31 +04:00
input_type = self . _lookup_osdict_key ( " inputtype " , " mouse " )
input_bus = self . _lookup_osdict_key ( " inputbus " , " ps2 " )
2013-07-25 22:36:13 +04:00
if self . os . is_xenpv ( ) :
input_type = virtinst . VirtualInputDevice . TYPE_MOUSE
input_bus = virtinst . VirtualInputDevice . BUS_XEN
for inp in self . get_devices ( " input " ) :
if ( inp . type == inp . TYPE_DEFAULT and
inp . bus == inp . BUS_DEFAULT ) :
inp . type = input_type
inp . bus = input_bus
def _set_sound_defaults ( self ) :
2013-10-06 18:08:04 +04:00
if self . conn . check_support (
2013-10-03 00:41:23 +04:00
support . SUPPORT_CONN_SOUND_ICH6 ) :
2013-08-11 23:29:31 +04:00
default = " ich6 "
2013-10-06 18:08:04 +04:00
elif self . conn . check_support (
2013-10-03 00:41:23 +04:00
support . SUPPORT_CONN_SOUND_AC97 ) :
2013-08-11 23:29:31 +04:00
default = " ac97 "
else :
default = " es1370 "
2013-07-24 16:46:55 +04:00
for sound in self . get_devices ( " sound " ) :
2013-03-18 01:06:52 +04:00
if sound . model == sound . MODEL_DEFAULT :
2013-08-11 23:29:31 +04:00
sound . model = default
2013-03-18 01:06:52 +04:00
2013-10-03 02:06:52 +04:00
def _set_graphics_defaults ( self ) :
for gfx in self . get_devices ( " graphics " ) :
if gfx . type != " default " :
continue
gtype = self . default_graphics_type
logging . debug ( " Using default_graphics= %s " , gtype )
if ( gtype == " spice " and not
2013-10-06 18:08:04 +04:00
self . conn . check_support (
2013-10-03 02:06:52 +04:00
self . conn . SUPPORT_CONN_GRAPHICS_SPICE ) ) :
logging . debug ( " spice requested but HV doesn ' t support it. "
" Using vnc. " )
gtype = " vnc "
gfx . type = gtype
def _add_spice_channels ( self ) :
def has_spice_agent ( ) :
for chn in self . get_devices ( " channel " ) :
if chn . type == chn . TYPE_SPICEVMC :
return True
2013-10-06 17:41:37 +04:00
if self . skip_default_channel :
return
2013-10-03 02:06:52 +04:00
if ( not has_spice_agent ( ) and
2013-10-06 18:08:04 +04:00
self . conn . check_support (
2013-10-03 02:06:52 +04:00
self . conn . SUPPORT_CONN_CHAR_SPICEVMC ) ) :
agentdev = virtinst . VirtualChannelDevice ( self . conn )
agentdev . type = agentdev . TYPE_SPICEVMC
self . add_device ( agentdev )
2013-07-25 22:36:13 +04:00
def _set_video_defaults ( self ) :
2013-03-18 01:06:52 +04:00
def has_spice ( ) :
2013-07-24 16:46:55 +04:00
for gfx in self . get_devices ( " graphics " ) :
2013-03-18 01:06:52 +04:00
if gfx . type == gfx . TYPE_SPICE :
return True
2013-10-03 02:06:52 +04:00
2013-03-18 01:06:52 +04:00
if has_spice ( ) :
2013-10-03 02:06:52 +04:00
self . _add_spice_channels ( )
2013-12-19 01:17:01 +04:00
if has_spice ( ) and self . os . is_x86 ( ) :
video_model = " qxl "
elif self . os . is_ppc64 ( ) and self . os . machine == " pseries " :
video_model = " vga "
2013-03-18 01:06:52 +04:00
else :
2013-08-11 23:29:31 +04:00
video_model = self . _lookup_osdict_key ( " videomodel " , " cirrus " )
2013-03-18 01:06:52 +04:00
2013-07-24 16:46:55 +04:00
for video in self . get_devices ( " video " ) :
2013-07-15 19:07:40 +04:00
if video . model == video . MODEL_DEFAULT :
video . model = video_model