2013-03-18 01:06:52 +04:00
#
# Common code for all guests
#
2015-02-24 15:32:51 +03:00
# Copyright 2006-2009, 2013, 2014, 2015 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
# Jeremy Katz <katzj@redhat.com>
#
2018-04-04 16:35:41 +03:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 22:00:02 +03:00
# See the COPYING file in the top-level directory.
2013-03-18 01:06:52 +04:00
import logging
import libvirt
2015-04-06 22:42:40 +03:00
from virtcli import CLIConfig
2013-10-03 02:06:52 +04:00
2014-09-12 23:59:22 +04:00
from . import util
2018-03-21 00:23:34 +03:00
from . devices import * # pylint: disable=wildcard-import
2018-03-20 22:10:04 +03:00
from . domain import * # pylint: disable=wildcard-import
2015-02-18 23:16:48 +03:00
from . domcapabilities import DomainCapabilities
2018-03-20 22:10:04 +03:00
from . osdict import OSDB
2014-09-12 23:59:22 +04:00
from . xmlbuilder import XMLBuilder , XMLProperty , XMLChildProperty
2013-03-18 01:06:52 +04:00
2018-03-21 01:59:14 +03:00
_ignore = Device
2013-03-18 01:06:52 +04:00
2018-03-21 00:23:34 +03:00
class _DomainDevices ( XMLBuilder ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " devices "
2018-03-21 01:59:14 +03:00
_XML_PROP_ORDER = [ ' disk ' , ' controller ' , ' filesystem ' , ' interface ' ,
2018-03-21 16:08:30 +03:00
' smartcard ' , ' serial ' , ' parallel ' , ' console ' , ' channel ' ,
' input ' , ' tpm ' , ' graphics ' , ' sound ' , ' video ' , ' hostdev ' ,
' redirdev ' , ' watchdog ' , ' memballoon ' , ' rng ' , ' panic ' ,
' memory ' ]
2018-03-21 01:59:14 +03:00
2018-03-21 00:23:34 +03:00
disk = XMLChildProperty ( DeviceDisk )
controller = XMLChildProperty ( DeviceController )
filesystem = XMLChildProperty ( DeviceFilesystem )
interface = XMLChildProperty ( DeviceInterface )
smartcard = XMLChildProperty ( DeviceSmartcard )
serial = XMLChildProperty ( DeviceSerial )
parallel = XMLChildProperty ( DeviceParallel )
console = XMLChildProperty ( DeviceConsole )
channel = XMLChildProperty ( DeviceChannel )
input = XMLChildProperty ( DeviceInput )
tpm = XMLChildProperty ( DeviceTpm )
graphics = XMLChildProperty ( DeviceGraphics )
sound = XMLChildProperty ( DeviceSound )
video = XMLChildProperty ( DeviceVideo )
hostdev = XMLChildProperty ( DeviceHostdev )
redirdev = XMLChildProperty ( DeviceRedirdev )
watchdog = XMLChildProperty ( DeviceWatchdog )
memballoon = XMLChildProperty ( DeviceMemballoon )
rng = XMLChildProperty ( DeviceRng )
panic = XMLChildProperty ( DevicePanic )
memory = XMLChildProperty ( DeviceMemory )
2018-03-21 18:21:16 +03:00
def get_all ( self ) :
retlist = [ ]
# pylint: disable=protected-access
devtypes = _DomainDevices . _XML_PROP_ORDER
for devtype in devtypes :
retlist . extend ( getattr ( self , devtype ) )
return retlist
2018-03-21 00:23:34 +03: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 ( )
2017-05-05 19:47:21 +03:00
except libvirt . libvirtError as e :
2013-08-09 22:16:59 +04:00
raise RuntimeError ( _ ( " Could not remove old vm ' %s ' : %s " ) %
( str ( e ) ) )
@staticmethod
2018-09-03 22:45:26 +03:00
def validate_name ( conn , name , check_collision = True , validate = True ) :
2014-01-18 03:44:26 +04:00
if validate :
util . validate_name ( _ ( " Guest " ) , name )
2013-08-09 22:16:59 +04:00
if not check_collision :
return
try :
conn . lookupByName ( name )
2017-07-24 11:26:48 +03:00
except Exception :
2013-08-09 22:16:59 +04:00
return
raise ValueError ( _ ( " Guest name ' %s ' is already in use. " ) % name )
2018-09-07 03:04:49 +03:00
@staticmethod
def get_recommended_machine ( capsinfo ) :
"""
2018-09-07 15:47:05 +03:00
Return the recommended machine type for the passed capsinfo .
We only return this for arch cases where there ' s a very clear
preference that ' s different from the default machine type
2018-09-07 03:04:49 +03:00
"""
2018-09-07 15:47:05 +03:00
def _qemu_machine ( ) :
if ( capsinfo . arch in [ " ppc64 " , " ppc64le " ] and
" pseries " in capsinfo . machines ) :
return " pseries "
if capsinfo . arch in [ " armv7l " , " aarch64 " ] :
if " virt " in capsinfo . machines :
return " virt "
if " vexpress-a15 " in capsinfo . machines :
return " vexpress-a15 "
if capsinfo . arch in [ " s390x " ] :
if " s390-ccw-virtio " in capsinfo . machines :
return " s390-ccw-virtio "
if capsinfo . conn . is_qemu ( ) or capsinfo . conn . is_test ( ) :
return _qemu_machine ( )
2018-09-07 03:04:49 +03:00
return None
#################
# init handling #
#################
2013-07-18 01:58:24 +04:00
2018-03-21 17:53:34 +03:00
XML_NAME = " domain "
2018-09-13 00:10:54 +03:00
_XML_PROP_ORDER = [
" type " , " name " , " uuid " , " title " , " description " , " _metadata " ,
2018-09-04 00:03:02 +03:00
" hotplugmemorymax " , " hotplugmemoryslots " , " maxmemory " , " _memory " ,
2018-03-21 00:23:34 +03:00
" blkiotune " , " memtune " , " memoryBacking " ,
2018-09-04 00:03:02 +03:00
" _vcpus " , " curvcpus " , " vcpu_placement " ,
2018-03-21 00:23:34 +03:00
" cpuset " , " numatune " , " resource " , " sysinfo " ,
" bootloader " , " os " , " idmap " , " features " , " cpu " , " clock " ,
" on_poweroff " , " on_reboot " , " on_crash " ,
" pm " , " emulator " , " devices " , " seclabels " ]
2013-07-18 01:58:24 +04:00
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-10-03 02:06:52 +04:00
# Allow virt-manager to override the default graphics type
2015-04-06 22:42:40 +03:00
self . default_graphics_type = CLIConfig . default_graphics
2013-10-03 02:06:52 +04:00
2013-10-06 17:41:37 +04:00
self . skip_default_console = False
self . skip_default_channel = False
2014-02-05 21:49:16 +04:00
self . skip_default_sound = False
2014-02-05 21:58:53 +04:00
self . skip_default_usbredir = False
2014-02-08 01:07:32 +04:00
self . skip_default_graphics = False
2017-03-09 00:54:16 +03:00
self . skip_default_rng = False
2014-02-05 22:51:53 +04:00
self . x86_cpu_default = self . cpu . SPECIAL_MODE_HOST_MODEL_ONLY
2013-10-06 17:41:37 +04:00
2018-09-02 03:13:40 +03:00
self . __osinfo = None
2018-09-07 03:38:59 +03:00
self . _capsinfo = None
2013-03-18 01:06:52 +04:00
######################
# Property accessors #
######################
2018-09-03 22:45:26 +03:00
name = XMLProperty ( " ./name " )
2013-03-18 01:06:52 +04:00
2013-07-18 01:58:24 +04:00
def _set_memory ( self , val ) :
2018-09-04 00:03:02 +03:00
if val is not None :
val = int ( val )
if self . maxmemory is None or self . maxmemory < val :
self . maxmemory = val
self . _memory = val
def _get_memory ( self ) :
return self . _memory
_memory = XMLProperty ( " ./currentMemory " , is_int = True )
memory = property ( _get_memory , _set_memory )
2013-09-19 21:27:30 +04:00
maxmemory = XMLProperty ( " ./memory " , is_int = True )
2017-05-04 14:08:14 +03:00
hotplugmemorymax = XMLProperty ( " ./maxMemory " , is_int = True )
hotplugmemoryslots = XMLProperty ( " ./maxMemory/@slots " , is_int = True )
2013-03-18 01:06:52 +04:00
2013-07-18 01:58:24 +04:00
def _set_vcpus ( self , val ) :
2018-09-04 00:03:02 +03:00
if val is not None :
val = int ( val )
# Don't force set curvcpus unless already specified
if self . curvcpus is not None and self . curvcpus > val :
self . curvcpus = val
self . _vcpus = val
def _get_vcpus ( self ) :
return self . _vcpus
_vcpus = XMLProperty ( " ./vcpu " , is_int = True )
vcpus = property ( _get_vcpus , _set_vcpus )
2013-09-19 21:27:30 +04:00
curvcpus = XMLProperty ( " ./vcpu/@current " , is_int = True )
2015-11-18 22:54:36 +03:00
vcpu_placement = XMLProperty ( " ./vcpu/@placement " )
2018-06-04 21:30:26 +03:00
cpuset = XMLProperty ( " ./vcpu/@cpuset " )
2013-07-18 01:58:24 +04:00
2018-09-02 17:26:20 +03:00
uuid = XMLProperty ( " ./uuid " )
2013-09-24 05:27:42 +04:00
id = XMLProperty ( " ./@id " , is_int = True )
2018-09-02 17:26:20 +03:00
type = XMLProperty ( " ./@type " )
2013-09-19 21:27:30 +04:00
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
2017-02-21 17:27:56 +03:00
on_poweroff = XMLProperty ( " ./on_poweroff " )
on_reboot = XMLProperty ( " ./on_reboot " )
on_crash = XMLProperty ( " ./on_crash " )
2015-10-07 13:50:13 +03:00
on_lockfailure = XMLProperty ( " ./on_lockfailure " )
2013-07-18 01:58:24 +04:00
2018-03-20 22:10:04 +03:00
seclabels = XMLChildProperty ( DomainSeclabel )
os = XMLChildProperty ( DomainOs , is_single = True )
2013-09-11 19:47:09 +04:00
features = XMLChildProperty ( DomainFeatures , is_single = True )
2018-03-20 22:10:04 +03:00
clock = XMLChildProperty ( DomainClock , is_single = True )
cpu = XMLChildProperty ( DomainCpu , is_single = True )
cputune = XMLChildProperty ( DomainCputune , is_single = True )
2013-09-11 19:47:09 +04:00
numatune = XMLChildProperty ( DomainNumatune , is_single = True )
2018-03-20 22:10:04 +03:00
pm = XMLChildProperty ( DomainPm , is_single = True )
2014-02-06 18:41:00 +04:00
blkiotune = XMLChildProperty ( DomainBlkiotune , is_single = True )
2018-03-20 22:10:04 +03:00
memtune = XMLChildProperty ( DomainMemtune , is_single = True )
memoryBacking = XMLChildProperty ( DomainMemoryBacking , is_single = True )
idmap = XMLChildProperty ( DomainIdmap , is_single = True )
2014-06-04 06:08:05 +04:00
resource = XMLChildProperty ( DomainResource , is_single = True )
2018-03-20 22:10:04 +03:00
sysinfo = XMLChildProperty ( DomainSysinfo , is_single = True )
2018-09-13 00:10:54 +03:00
_metadata = XMLChildProperty ( DomainMetadata , is_single = True )
2013-09-11 19:47:09 +04:00
2018-03-20 22:10:04 +03:00
xmlns_qemu = XMLChildProperty ( DomainXMLNSQemu , is_single = True )
2017-03-06 01:12:50 +03:00
2013-07-18 01:58:24 +04:00
2018-09-02 03:22:47 +03:00
##############################
# osinfo related definitions #
##############################
2013-07-18 01:58:24 +04:00
2018-09-02 03:13:40 +03:00
def _get_osinfo ( self ) :
2018-09-13 22:03:36 +03:00
if self . __osinfo :
return self . __osinfo
os_id = self . _metadata . libosinfo . os_id
if os_id :
self . __osinfo = OSDB . lookup_os_by_full_id ( os_id )
if not self . __osinfo :
logging . debug ( " XML had libosinfo os id= %s but we didn ' t "
" find any libosinfo object matching that " , os_id )
2018-09-02 03:13:40 +03:00
if not self . __osinfo :
2018-09-13 00:23:01 +03:00
self . set_os_name ( " generic " )
2018-09-02 03:13:40 +03:00
return self . __osinfo
osinfo = property ( _get_osinfo )
2015-04-04 17:16:58 +03:00
2018-09-13 00:23:01 +03:00
def set_os_name ( self , name ) :
obj = OSDB . lookup_os ( name )
if obj is None :
raise ValueError (
_ ( " Distro ' %s ' does not exist in our dictionary " ) % name )
2018-09-13 22:11:22 +03:00
2018-10-01 02:12:19 +03:00
logging . debug ( " Setting Guest osinfo %s " , obj )
self . __osinfo = obj
self . _metadata . libosinfo . os_id = self . __osinfo . full_id
def set_os_full_id ( self , full_id ) :
obj = OSDB . lookup_os_by_full_id ( full_id )
if obj is None :
raise ValueError ( _ ( " Unknown libosinfo ID ' %s ' " ) % full_id )
logging . debug ( " Setting Guest osinfo %s " , obj )
2018-09-13 00:23:01 +03:00
self . __osinfo = obj
2018-09-29 23:04:05 +03:00
self . _metadata . libosinfo . os_id = self . __osinfo . full_id
2013-03-18 01:06:52 +04:00
2018-09-02 03:22:47 +03:00
def _supports_virtio ( self , os_support ) :
if not self . conn . is_qemu ( ) :
return False
# These _only_ support virtio so don't check the OS
if ( self . os . is_arm_machvirt ( ) or
self . os . is_s390x ( ) or
self . os . is_pseries ( ) ) :
return True
if not os_support :
return False
if self . os . is_x86 ( ) :
return True
return False
def supports_virtionet ( self ) :
return self . _supports_virtio ( self . osinfo . supports_virtionet ( ) )
2018-09-02 18:57:41 +03:00
def supports_virtiodisk ( self ) :
return self . _supports_virtio ( self . osinfo . supports_virtiodisk ( ) )
2018-09-02 03:22:47 +03:00
2018-09-07 03:04:49 +03:00
def stable_defaults ( self , * args , * * kwargs ) :
return self . conn . stable_defaults ( self . emulator , * args , * * kwargs )
2013-03-18 01:06:52 +04:00
2018-09-07 03:04:49 +03:00
###############################
# Public XML APIs and helpers #
###############################
2013-03-18 01:06:52 +04:00
2013-07-25 22:11:09 +04:00
def add_device ( self , dev ) :
2018-03-21 00:23:34 +03:00
self . devices . add_child ( dev )
2013-09-11 02:32:10 +04:00
def remove_device ( self , dev ) :
2018-03-21 00:23:34 +03:00
self . devices . remove_child ( dev )
devices = XMLChildProperty ( _DomainDevices , is_single = True )
2018-09-12 20:43:56 +03:00
def prefers_uefi ( self ) :
2015-02-18 23:16:48 +03:00
"""
2018-09-12 20:43:56 +03:00
Return True if this config prefers UEFI . For example ,
arm + machvirt prefers UEFI since it ' s required for traditional
install methods
"""
return self . os . is_arm_machvirt ( )
def get_uefi_path ( self ) :
"""
If UEFI firmware path is found , return it , otherwise raise an error
2015-02-18 23:16:48 +03:00
"""
2018-09-13 22:51:03 +03:00
if not self . os . arch :
self . set_capabilities_defaults ( )
2015-02-18 23:16:48 +03:00
domcaps = DomainCapabilities . build_from_guest ( self )
if not domcaps . supports_uefi_xml ( ) :
raise RuntimeError ( _ ( " Libvirt version does not support UEFI. " ) )
2015-02-22 19:02:55 +03:00
if not domcaps . arch_can_uefi ( ) :
2015-02-18 23:16:48 +03:00
raise RuntimeError (
_ ( " Don ' t know how to setup UEFI for arch ' %s ' " ) %
self . os . arch )
2015-02-22 19:02:55 +03:00
path = domcaps . find_uefi_path_for_arch ( )
2015-02-18 23:16:48 +03:00
if not path :
raise RuntimeError ( _ ( " Did not find any UEFI binary path for "
" arch ' %s ' " ) % self . os . arch )
2018-09-12 20:43:56 +03:00
return path
2015-02-18 23:16:48 +03:00
2018-09-12 20:43:56 +03:00
def set_uefi_path ( self , path ) :
2017-02-06 15:46:06 +03:00
"""
2018-09-12 20:43:56 +03:00
Configure UEFI for the VM , but only if libvirt is advertising
a known UEFI binary path .
2017-02-06 15:46:06 +03:00
"""
2018-09-12 20:43:56 +03:00
self . os . loader_ro = True
self . os . loader_type = " pflash "
self . os . loader = path
2017-02-06 15:46:06 +03:00
2018-09-12 20:43:56 +03:00
# If the firmware name contains "secboot" it is probably build
# with SMM feature required so we need to enable that feature,
# otherwise the firmware may fail to load. True secure boot is
# currently supported only on x86 architecture and with q35 with
# SMM feature enabled so change the machine to q35 as well.
# To actually enforce the secure boot for the guest if Secure Boot
# Mode is configured we need to enable loader secure feature.
if ( self . os . is_x86 ( ) and
" secboot " in self . os . loader ) :
self . features . smm = True
self . os . loader_secure = True
self . os . machine = " q35 "
2015-02-18 23:16:48 +03:00
2018-09-13 22:51:03 +03:00
# UEFI doesn't work with hyperv bits for some OS
if self . osinfo . broken_uefi_with_hyperv ( ) :
self . features . hyperv_relaxed = None
self . features . hyperv_vapic = None
self . features . hyperv_spinlocks = None
self . features . hyperv_spinlocks_retries = None
for i in self . clock . timers :
if i . name == " hypervclock " :
self . clock . timers . remove ( i )
2018-09-07 03:04:49 +03:00
def has_spice ( self ) :
for gfx in self . devices . graphics :
if gfx . type == gfx . TYPE_SPICE :
return True
2018-09-01 04:06:18 +03:00
2018-09-07 03:04:49 +03:00
def has_gl ( self ) :
for gfx in self . devices . graphics :
if gfx . gl :
return True
2013-03-18 01:06:52 +04:00
2018-09-07 03:04:49 +03:00
def has_listen_none ( self ) :
for gfx in self . devices . graphics :
listen = gfx . get_first_listen_type ( )
if listen and listen == " none " :
return True
return False
def is_full_os_container ( self ) :
if not self . os . is_container ( ) :
return False
for fs in self . devices . filesystem :
if fs . target == " / " :
return True
return False
def hyperv_supported ( self ) :
if not self . osinfo . is_windows ( ) :
return False
if ( self . os . loader_type == " pflash " and
self . osinfo . broken_uefi_with_hyperv ( ) ) :
return False
return True
def lookup_capsinfo ( self ) :
2018-09-07 03:38:59 +03:00
def _compare_to_capsinfo ( capsinfo ) :
if not capsinfo :
return False
if self . type and self . type != capsinfo . hypervisor_type :
return False
if self . os . os_type and self . os . os_type != capsinfo . os_type :
return False
if self . os . arch and self . os . arch != capsinfo . arch :
return False
if self . os . machine and self . os . machine not in capsinfo . machines :
return False
return True
if not _compare_to_capsinfo ( self . _capsinfo ) :
self . _capsinfo = self . conn . caps . guest_lookup (
2018-09-07 03:04:49 +03:00
os_type = self . os . os_type ,
arch = self . os . arch ,
typ = self . type ,
machine = self . os . machine )
2018-09-07 03:38:59 +03:00
return self . _capsinfo
2018-09-07 03:04:49 +03:00
2018-09-07 03:54:59 +03:00
def set_capabilities_defaults ( self , capsinfo = None ) :
if capsinfo :
self . _capsinfo = capsinfo
else :
capsinfo = self . lookup_capsinfo ( )
2018-09-07 03:04:49 +03:00
wants_default_type = not self . type and not self . os . os_type
self . type = capsinfo . hypervisor_type
self . os . os_type = capsinfo . os_type
self . os . arch = capsinfo . arch
if not self . os . loader :
self . os . loader = capsinfo . loader
if ( not self . emulator and
not self . os . is_xenpv ( ) and
not self . type == " vz " ) :
self . emulator = capsinfo . emulator
if not self . os . machine :
self . os . machine = Guest . get_recommended_machine ( capsinfo )
if ( wants_default_type and
self . conn . is_qemu ( ) and
self . os . is_x86 ( ) and
not self . type == " kvm " ) :
logging . warning ( " KVM acceleration not available, using ' %s ' " ,
self . type )
def set_defaults ( self , _guest ) :
if not self . uuid :
self . uuid = util . generate_uuid ( self . conn )
if not self . vcpus :
self . vcpus = 1
2018-09-07 15:47:05 +03:00
2018-09-07 03:04:49 +03:00
self . set_capabilities_defaults ( )
2018-09-12 20:43:56 +03:00
2018-09-12 21:49:10 +03:00
self . _set_default_machine ( )
2018-09-12 20:43:56 +03:00
self . _set_default_uefi ( )
2018-09-12 21:49:10 +03:00
2018-09-07 03:04:49 +03:00
self . _add_default_graphics ( )
self . _add_default_video_device ( )
self . _add_default_input_device ( )
self . _add_default_console_device ( )
self . _add_default_usb_controller ( )
self . _add_default_channels ( )
self . _add_default_rng ( )
self . clock . set_defaults ( self )
self . cpu . set_defaults ( self )
self . features . set_defaults ( self )
for seclabel in self . seclabels :
seclabel . set_defaults ( self )
self . pm . set_defaults ( self )
self . os . set_defaults ( self )
for dev in self . devices . get_all ( ) :
dev . set_defaults ( self )
self . _add_implied_controllers ( )
self . _add_spice_devices ( )
########################
# Private xml routines #
########################
2015-03-23 23:43:39 +03:00
2018-09-12 21:49:10 +03:00
def _set_default_machine ( self ) :
if self . os . machine :
return
if ( self . os . is_x86 ( ) and
self . conn . is_qemu ( ) and
self . osinfo . supports_chipset_q35 ( ) ) :
self . os . machine = " q35 "
return
capsinfo = self . lookup_capsinfo ( )
default = capsinfo . machines and capsinfo . machines [ 0 ] or None
self . os . machine = default
2018-09-12 20:43:56 +03:00
def _set_default_uefi ( self ) :
if ( self . prefers_uefi ( ) and
not self . os . kernel and
not self . os . loader and
self . os . loader_ro is None and
self . os . nvram is None ) :
try :
path = self . get_uefi_path ( )
self . set_uefi_path ( path )
except RuntimeError as e :
logging . debug ( " Error setting UEFI default " ,
exc_info = True )
logging . warning ( " Couldn ' t configure UEFI: %s " , e )
logging . warning ( " Your VM may not boot successfully. " )
2017-06-28 23:12:04 +03:00
def _usb_disabled ( self ) :
2018-03-21 00:23:34 +03:00
controllers = [ c for c in self . devices . controller if
2017-06-28 23:12:04 +03:00
c . type == " usb " ]
if not controllers :
return False
return all ( [ c . model == " none " for c in controllers ] )
2018-09-03 21:47:42 +03:00
def _add_default_input_device ( self ) :
2013-07-25 22:36:13 +04:00
if self . os . is_container ( ) :
return
2018-03-21 00:23:34 +03:00
if self . devices . input :
2013-10-06 16:30:33 +04:00
return
2018-03-21 00:23:34 +03:00
if not self . devices . graphics :
2017-06-28 19:05:14 +03:00
return
2017-06-28 23:22:23 +03:00
if self . _usb_disabled ( ) :
return
usb_tablet = False
usb_keyboard = False
2018-08-22 15:38:33 +03:00
if self . os . is_x86 ( ) and not self . os . is_xenpv ( ) :
2018-09-02 03:13:40 +03:00
usb_tablet = self . osinfo . supports_usbtablet ( )
2017-06-28 23:22:23 +03:00
if self . os . is_arm_machvirt ( ) :
usb_tablet = True
usb_keyboard = True
2017-06-28 23:12:04 +03:00
2017-06-28 23:22:23 +03:00
if usb_tablet :
2018-03-20 19:18:35 +03:00
dev = DeviceInput ( self . conn )
2017-06-28 23:12:04 +03:00
dev . type = " tablet "
dev . bus = " usb "
self . add_device ( dev )
2017-06-28 23:22:23 +03:00
if usb_keyboard :
2018-03-20 19:18:35 +03:00
dev = DeviceInput ( self . conn )
2017-06-28 23:22:23 +03:00
dev . type = " keyboard "
dev . bus = " usb "
self . add_device ( dev )
2013-07-25 22:36:13 +04:00
2018-09-03 21:47:42 +03:00
def _add_default_console_device ( self ) :
2013-10-06 17:41:37 +04:00
if self . skip_default_console :
return
2018-03-21 00:23:34 +03:00
if self . devices . console or self . devices . serial :
2013-10-06 16:30:33 +04:00
return
2018-03-20 19:18:35 +03:00
dev = DeviceConsole ( self . conn )
2013-07-25 22:36:13 +04:00
dev . type = dev . TYPE_PTY
2015-11-13 04:48:13 +03:00
if self . os . is_s390x ( ) :
dev . target_type = " sclp "
2013-07-25 22:36:13 +04:00
self . add_device ( dev )
2018-09-03 21:47:42 +03:00
def _add_default_video_device ( self ) :
2013-08-18 16:59:19 +04:00
if self . os . is_container ( ) :
return
2018-03-21 00:23:34 +03:00
if self . devices . video :
2013-10-06 16:30:33 +04:00
return
2018-03-21 00:23:34 +03:00
if not self . devices . graphics :
2013-10-06 16:30:33 +04:00
return
2018-03-20 19:18:35 +03:00
self . add_device ( DeviceVideo ( self . conn ) )
2013-08-18 16:59:19 +04:00
2018-09-03 21:47:42 +03:00
def _add_default_usb_controller ( self ) :
2018-03-21 00:23:34 +03:00
if any ( [ d . type == " usb " for d in self . devices . controller ] ) :
2013-10-06 16:30:33 +04:00
return
2018-10-04 01:53:16 +03:00
if not self . conn . is_qemu ( ) and not self . conn . is_test ( ) :
return
2017-06-28 22:35:07 +03:00
2018-10-04 01:53:16 +03:00
qemu_usb3 = self . conn . check_support ( self . conn . SUPPORT_CONN_QEMU_XHCI )
2017-06-28 22:35:07 +03:00
usb2 = False
usb3 = False
if self . os . is_x86 ( ) :
2018-10-04 01:53:16 +03:00
if self . osinfo . supports_usb3 ( ) and qemu_usb3 :
usb3 = True
else :
usb2 = True
elif self . os . is_arm_machvirt ( ) :
# For machvirt, we always assume OS supports usb3
if ( qemu_usb3 and
self . conn . check_support (
self . conn . SUPPORT_CONN_MACHVIRT_PCI_DEFAULT ) ) :
usb3 = True
elif self . os . is_pseries ( ) :
# For pseries, we always assume OS supports usb3
if qemu_usb3 :
usb3 = True
2017-06-28 22:35:07 +03:00
if usb2 :
2018-03-20 19:18:35 +03:00
for dev in DeviceController . get_usb2_controllers ( self . conn ) :
2017-06-28 22:35:07 +03:00
self . add_device ( dev )
2018-10-04 01:53:16 +03:00
elif usb3 :
2017-07-11 02:40:19 +03:00
self . add_device (
2018-03-20 19:18:35 +03:00
DeviceController . get_usb3_controller ( self . conn , self ) )
2013-10-02 23:51:01 +04:00
2018-09-03 21:47:42 +03:00
def _add_default_channels ( self ) :
2013-10-06 17:41:37 +04:00
if self . skip_default_channel :
return
2018-03-21 00:23:34 +03:00
if self . devices . channel :
2013-10-06 17:19:59 +04:00
return
2015-11-04 09:30:24 +03:00
if self . os . is_s390x ( ) :
2015-11-11 01:55:13 +03:00
# Not wanted for s390 apparently
return
2013-10-06 17:19:59 +04:00
if ( self . conn . is_qemu ( ) and
2018-09-02 03:13:40 +03:00
self . _supports_virtio ( self . osinfo . supports_virtioserial ( ) ) and
2013-10-06 18:08:04 +04:00
self . conn . check_support ( self . conn . SUPPORT_CONN_AUTOSOCKET ) ) :
2018-03-20 19:18:35 +03:00
dev = DeviceChannel ( self . conn )
2013-10-06 17:19:59 +04:00
dev . type = " unix "
dev . target_type = " virtio "
dev . target_name = dev . CHANNEL_NAME_QEMUGA
self . add_device ( dev )
2018-09-03 21:47:42 +03:00
def _add_default_graphics ( self ) :
2014-02-08 01:07:32 +04:00
if self . skip_default_graphics :
return
2018-03-21 00:23:34 +03:00
if self . devices . graphics :
2014-02-08 01:07:32 +04:00
return
2017-03-13 15:01:53 +03:00
if self . os . is_container ( ) and not self . conn . is_vz ( ) :
2014-02-08 01:07:32 +04:00
return
2017-06-28 22:17:20 +03:00
if self . os . arch not in [ " x86_64 " , " i686 " , " ppc64 " , " ppc64le " ] :
2014-02-08 01:07:32 +04:00
return
2018-03-20 19:18:35 +03:00
self . add_device ( DeviceGraphics ( self . conn ) )
2014-02-08 01:07:32 +04:00
2018-09-03 21:47:42 +03:00
def _add_default_rng ( self ) :
2017-03-09 00:54:16 +03:00
if self . skip_default_rng :
return
2018-03-21 00:23:34 +03:00
if self . devices . rng :
2017-03-09 00:54:16 +03:00
return
2017-06-28 22:11:05 +03:00
if not ( self . os . is_x86 ( ) or
self . os . is_arm_machvirt ( ) or
self . os . is_pseries ( ) ) :
2017-03-09 00:54:16 +03:00
return
if ( self . conn . is_qemu ( ) and
2018-09-02 03:13:40 +03:00
self . osinfo . supports_virtiorng ( ) and
2017-03-09 00:54:16 +03:00
self . conn . check_support ( self . conn . SUPPORT_CONN_RNG_URANDOM ) ) :
2018-03-20 19:18:35 +03:00
dev = DeviceRng ( self . conn )
2017-03-09 00:54:16 +03:00
dev . type = " random "
dev . device = " /dev/urandom "
self . add_device ( dev )
2013-07-25 22:36:13 +04:00
def _add_implied_controllers ( self ) :
2014-11-20 19:27:09 +03:00
has_spapr_scsi = False
has_virtio_scsi = False
has_any_scsi = False
2018-03-21 00:23:34 +03:00
for dev in self . devices . controller :
2014-11-20 19:27:09 +03:00
if dev . type == " scsi " :
has_any_scsi = True
if dev . address . type == " spapr-vio " :
has_spapr_scsi = True
if dev . model == " virtio " :
has_virtio_scsi = True
# Add spapr-vio controller if needed
if not has_spapr_scsi :
2018-03-21 00:23:34 +03:00
for dev in self . devices . disk :
2014-11-20 19:27:09 +03:00
if dev . address . type == " spapr-vio " :
2018-03-20 19:18:35 +03:00
ctrl = DeviceController ( self . conn )
2014-11-20 19:27:09 +03:00
ctrl . type = " scsi "
ctrl . address . set_addrstr ( " spapr-vio " )
2018-09-02 00:05:12 +03:00
ctrl . set_defaults ( self )
2014-11-20 19:27:09 +03:00
self . add_device ( ctrl )
break
# Add virtio-scsi controller if needed
2017-11-30 00:41:03 +03:00
if ( ( self . os . is_arm_machvirt ( ) or self . os . is_pseries ( ) ) and
2014-11-20 19:27:09 +03:00
not has_any_scsi and
not has_virtio_scsi ) :
2018-03-21 00:23:34 +03:00
for dev in self . devices . disk :
2014-11-20 19:27:09 +03:00
if dev . bus == " scsi " :
2018-03-20 19:18:35 +03:00
ctrl = DeviceController ( self . conn )
2014-11-20 19:27:09 +03:00
ctrl . type = " scsi "
ctrl . model = " virtio-scsi "
2018-09-02 00:05:12 +03:00
ctrl . set_defaults ( self )
2014-11-20 19:27:09 +03:00
self . add_device ( ctrl )
break
2013-10-03 02:06:52 +04:00
def _add_spice_channels ( self ) :
2013-10-06 17:41:37 +04:00
if self . skip_default_channel :
return
2018-03-21 00:23:34 +03:00
for chn in self . devices . channel :
2014-02-05 21:49:16 +04:00
if chn . type == chn . TYPE_SPICEVMC :
return
2018-09-02 00:05:12 +03:00
dev = DeviceChannel ( self . conn )
dev . type = DeviceChannel . TYPE_SPICEVMC
dev . set_defaults ( self )
self . add_device ( dev )
2013-10-03 02:06:52 +04:00
2014-02-05 21:49:16 +04:00
def _add_spice_sound ( self ) :
if self . skip_default_sound :
return
2018-03-21 00:23:34 +03:00
if self . devices . sound :
2014-02-05 21:49:16 +04:00
return
2017-06-28 23:28:25 +03:00
if not self . os . is_hvm ( ) :
return
if not ( self . os . is_x86 ( ) or
self . os . is_arm_machvirt ) :
return
2018-09-02 00:05:12 +03:00
dev = DeviceSound ( self . conn )
dev . set_defaults ( self )
self . add_device ( dev )
2014-02-05 21:49:16 +04:00
2014-02-05 21:58:53 +04:00
def _add_spice_usbredir ( self ) :
if self . skip_default_usbredir :
return
2018-03-21 00:23:34 +03:00
if self . devices . redirdev :
2014-02-05 21:58:53 +04:00
return
2017-03-05 22:30:11 +03:00
if not self . os . is_x86 ( ) :
return
2014-02-05 21:58:53 +04:00
2014-09-21 04:16:31 +04:00
# If we use 4 devices here, we fill up all the emulated USB2 slots,
# and directly assigned devices are forced to fall back to USB1
# https://bugzilla.redhat.com/show_bug.cgi?id=1135488
for ignore in range ( 2 ) :
2018-03-20 19:18:35 +03:00
dev = DeviceRedirdev ( self . conn )
2014-02-05 21:58:53 +04:00
dev . bus = " usb "
dev . type = " spicevmc "
2018-09-02 00:05:12 +03:00
dev . set_defaults ( self )
2014-02-05 21:58:53 +04:00
self . add_device ( dev )
2018-09-01 23:34:25 +03:00
def _add_spice_devices ( self ) :
if not self . has_spice ( ) :
return
2018-09-02 16:02:32 +03:00
if ( self . features . vmport is None and
2018-09-01 23:34:25 +03:00
self . os . is_x86 ( ) and
self . conn . check_support ( self . conn . SUPPORT_CONN_VMPORT ) ) :
self . features . vmport = False
self . _add_spice_channels ( )
self . _add_spice_sound ( )
self . _add_spice_usbredir ( )