2013-03-18 01:06:52 +04:00
#
# Common code for all guests
#
2013-10-28 00:59:46 +04:00
# Copyright 2006-2009, 2013 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
#
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 os
import logging
2019-06-08 00:32:51 +03:00
from . import progress
from . import unattended
2018-03-20 19:27:37 +03:00
from . devices import DeviceDisk
2018-03-20 22:10:04 +03:00
from . domain import DomainOs
2019-06-09 18:26:28 +03:00
from . osdict import OSDB
2018-10-13 01:35:09 +03:00
from . installertreemedia import InstallerTreeMedia
2019-06-10 01:48:22 +03:00
from . installerinject import perform_cdrom_injections
2013-03-18 01:06:52 +04:00
2013-07-17 15:53:47 +04:00
class Installer ( object ) :
2013-03-18 01:06:52 +04:00
"""
2019-01-31 01:15:52 +03:00
Class for kicking off VM installs . The VM is set up separately in a Guest
instance . This class tracks the install media / bootdev choice , alters the
Guest XML , boots it for the install , then saves the post install XML
config . The Guest is passed in via start_install , only install media
selection is done at __init__ time
: param cdrom : Path to a cdrom device or iso . Maps to virt - install - - cdrom
: param location : An install tree URI , local directory , or ISO / CDROM path .
Largely handled by installtreemedia helper class . Maps to virt - install
- - location
: param install_bootdev : The VM bootdev to use ( HD , NETWORK , CDROM , FLOPPY )
2019-02-01 02:07:09 +03:00
: param location_kernel : URL pointing to a kernel to fetch , or a relative
path to indicate where the kernel is stored in location
: param location_initrd : location_kernel , but pointing to an initrd
2013-03-18 01:06:52 +04:00
"""
2019-02-01 02:07:09 +03:00
def __init__ ( self , conn , cdrom = None , location = None , install_bootdev = None ,
location_kernel = None , location_initrd = None ) :
2013-07-17 15:53:47 +04:00
self . conn = conn
2014-01-12 00:28:21 +04:00
2014-09-11 05:33:50 +04:00
self . livecd = False
2018-10-13 23:29:32 +03:00
self . extra_args = [ ]
2013-07-17 04:05:24 +04:00
2018-10-13 16:42:15 +03:00
# Entry point for virt-manager 'Customize' wizard to change autostart
self . autostart = False
2018-10-13 01:35:09 +03:00
self . _install_bootdev = install_bootdev
2013-07-17 04:05:24 +04:00
self . _install_kernel = None
self . _install_initrd = None
2019-05-23 22:55:58 +03:00
self . _install_cdrom_device_added = False
2019-06-07 13:00:56 +03:00
self . _unattended_install_cdrom_device = None
2019-06-08 22:20:16 +03:00
self . _tmpfiles = [ ]
2018-09-03 21:34:53 +03:00
self . _defaults_are_set = False
2019-03-29 00:44:47 +03:00
self . _unattended_data = None
2013-03-18 01:06:52 +04:00
2019-02-01 02:07:09 +03:00
if location_kernel or location_initrd :
if not location :
raise ValueError ( _ ( " location kernel/initrd may only "
" be specified with a location URL/path " ) )
if not ( location_kernel and location_initrd ) :
raise ValueError ( _ ( " location kernel/initrd must be "
" be specified as a pair " ) )
2018-10-13 01:35:09 +03:00
self . _cdrom = None
self . _treemedia = None
if cdrom :
cdrom = InstallerTreeMedia . validate_path ( self . conn , cdrom )
self . _cdrom = cdrom
self . _install_bootdev = " cdrom "
if location :
2019-02-01 02:07:09 +03:00
self . _treemedia = InstallerTreeMedia ( self . conn , location ,
location_kernel , location_initrd )
2013-03-18 01:06:52 +04:00
2013-07-17 02:12:13 +04:00
###################
# Private helpers #
###################
2013-03-18 01:06:52 +04:00
2018-10-13 01:35:09 +03:00
def _cdrom_path ( self ) :
if self . _treemedia :
return self . _treemedia . cdrom_path ( )
return self . _cdrom
2018-09-03 20:11:17 +03:00
def _add_install_cdrom_device ( self , guest ) :
2019-05-23 22:55:58 +03:00
if self . _install_cdrom_device_added :
2019-06-12 00:19:01 +03:00
return # pragma: no cover
2018-10-13 01:35:09 +03:00
if not bool ( self . _cdrom_path ( ) ) :
2018-09-03 20:11:17 +03:00
return
dev = DeviceDisk ( self . conn )
dev . device = dev . DEVICE_CDROM
2018-10-13 17:11:26 +03:00
dev . path = self . _cdrom_path ( )
dev . sync_path_props ( )
dev . validate ( )
2019-05-23 22:55:58 +03:00
self . _install_cdrom_device_added = True
2018-10-13 17:23:00 +03:00
# Insert the CDROM before any other CDROM, so boot=cdrom picks
# it as the priority
for idx , disk in enumerate ( guest . devices . disk ) :
if disk . is_cdrom ( ) :
2019-05-23 22:55:58 +03:00
guest . devices . add_child ( dev , idx = idx )
2018-10-13 17:23:00 +03:00
return
2019-05-23 22:55:58 +03:00
guest . add_device ( dev )
2018-09-03 20:11:17 +03:00
def _remove_install_cdrom_media ( self , guest ) :
2019-05-23 22:55:58 +03:00
if not self . _install_cdrom_device_added :
2018-09-03 20:11:17 +03:00
return
if guest . osinfo . is_windows ( ) :
# Keep media attached for windows which has a multi stage install
return
2019-05-23 22:55:58 +03:00
for disk in guest . devices . disk :
if disk . is_cdrom ( ) and disk . path == self . _cdrom_path ( ) :
disk . path = None
disk . sync_path_props ( )
break
2018-09-03 20:11:17 +03:00
2019-06-07 13:00:56 +03:00
def _add_unattended_install_cdrom_device ( self , guest , location ) :
if self . _unattended_install_cdrom_device :
2019-06-12 00:19:01 +03:00
return # pragma: no cover
2019-03-29 00:44:45 +03:00
dev = DeviceDisk ( self . conn )
2019-06-07 13:00:56 +03:00
dev . device = dev . DEVICE_CDROM
2019-03-29 00:44:45 +03:00
dev . path = location
dev . sync_path_props ( )
dev . validate ( )
dev . set_defaults ( guest )
2019-06-07 13:00:56 +03:00
self . _unattended_install_cdrom_device = dev
guest . add_device ( self . _unattended_install_cdrom_device )
2019-03-29 00:44:45 +03:00
2019-06-08 22:33:37 +03:00
if self . conn . in_testsuite ( ) :
# pylint: disable=protected-access
# Hack to set just the XML path differently for the test suite.
# Setting this via regular 'path' will error that it doesn't exist
dev . _source_file = " /TESTSUITE_UNATTENDED_ISO "
2019-06-07 13:00:56 +03:00
def _remove_unattended_install_cdrom_device ( self , guest ) :
2019-03-29 00:44:45 +03:00
dummy = guest
2019-06-07 13:00:56 +03:00
if not self . _unattended_install_cdrom_device :
2019-03-29 00:44:45 +03:00
return
2019-06-07 13:00:56 +03:00
self . _unattended_install_cdrom_device . path = None
self . _unattended_install_cdrom_device . sync_path_props ( )
2019-03-29 00:44:45 +03:00
2018-09-03 18:47:59 +03:00
def _build_boot_order ( self , guest , bootdev ) :
bootorder = [ bootdev ]
2013-03-18 01:06:52 +04:00
# If guest has an attached disk, always have 'hd' in the boot
# list, so disks are marked as bootable/installable (needed for
# windows virtio installs, and booting local disk from PXE)
2018-03-21 00:23:34 +03:00
for disk in guest . devices . disk :
2013-03-18 01:06:52 +04:00
if disk . device == disk . DEVICE_DISK :
2013-07-17 15:53:47 +04:00
bootdev = " hd "
2013-03-18 01:06:52 +04:00
if bootdev not in bootorder :
bootorder . append ( bootdev )
break
return bootorder
2018-09-03 21:34:53 +03:00
def _can_set_guest_bootorder ( self , guest ) :
return ( not guest . os . is_container ( ) and
not guest . os . kernel and
not any ( [ d . boot . order for d in guest . devices . get_all ( ) ] ) )
2018-09-03 20:11:17 +03:00
def _alter_bootconfig ( self , guest ) :
2013-03-18 01:06:52 +04:00
"""
Generate the portion of the guest xml that determines boot devices
and parameters . ( typically the < os > < / os > block )
2018-02-14 15:17:31 +03:00
: param guest : Guest instance we are installing
2013-03-18 01:06:52 +04:00
"""
2018-09-03 18:47:59 +03:00
guest . on_reboot = " destroy "
2013-07-17 04:05:24 +04:00
2013-07-17 15:53:47 +04:00
if self . _install_kernel :
2019-06-08 04:40:47 +03:00
guest . os . kernel = ( self . conn . in_testsuite ( ) and
" /TESTSUITE_KERNEL_PATH " or self . _install_kernel )
2013-07-17 15:53:47 +04:00
if self . _install_initrd :
2019-06-08 04:40:47 +03:00
guest . os . initrd = ( self . conn . in_testsuite ( ) and
" /TESTSUITE_INITRD_PATH " or self . _install_initrd )
2018-10-13 23:29:32 +03:00
if self . extra_args :
guest . os . kernel_args = " " . join ( self . extra_args )
2013-03-18 01:06:52 +04:00
2018-10-13 01:35:09 +03:00
bootdev = self . _install_bootdev
2018-09-03 21:34:53 +03:00
if bootdev and self . _can_set_guest_bootorder ( guest ) :
2018-09-03 18:47:59 +03:00
guest . os . bootorder = self . _build_boot_order ( guest , bootdev )
else :
guest . os . bootorder = [ ]
2019-03-22 18:23:41 +03:00
def _alter_install_resources ( self , guest , meter ) :
"""
Sets the appropriate amount of ram needed when performing a " network "
based installation
: param guest : Guest instance we are installing
"""
if not self . _treemedia :
return
if not self . _treemedia . requires_internet ( guest , meter ) :
return
2019-06-09 17:14:48 +03:00
ram = guest . osinfo . get_network_install_required_ram ( guest )
ram = ( ram or 0 ) / / 1024
if ram > guest . currentMemory :
2019-03-22 18:23:41 +03:00
logging . debug ( " Setting ram from libosinfo network-install "
2019-06-09 17:14:48 +03:00
" resources to %s " , ram )
guest . currentMemory = ram
2019-05-11 20:34:21 +03:00
2013-07-17 02:12:13 +04:00
##########################
# Internal API overrides #
##########################
2019-06-10 02:10:19 +03:00
def _prepare_unattended_data ( self , guest , script ) :
2019-06-08 22:20:16 +03:00
expected_filename = script . get_expected_filename ( )
2019-06-10 02:10:19 +03:00
unattended_cmdline = script . generate_cmdline ( )
logging . debug ( " Generated unattended cmdline: %s " , unattended_cmdline )
scriptpath = script . write ( guest )
self . _tmpfiles . append ( scriptpath )
2019-06-08 21:16:52 +03:00
2019-06-08 22:20:16 +03:00
iso = perform_cdrom_injections ( [ ( scriptpath , expected_filename ) ] ,
2019-06-08 21:16:52 +03:00
guest . conn . get_app_cache_dir ( ) )
2019-06-10 02:10:19 +03:00
self . _tmpfiles . append ( iso )
2019-06-08 21:16:52 +03:00
self . _add_unattended_install_cdrom_device ( guest , iso )
2019-06-10 02:10:19 +03:00
def _prepare_unattended_script ( self , guest , meter ) :
2019-06-10 21:20:45 +03:00
url = None
2019-06-10 02:10:19 +03:00
if self . _treemedia :
2019-06-10 21:20:45 +03:00
if self . _treemedia . is_network_url ( ) :
url = self . location
2019-06-10 02:10:19 +03:00
os_media = self . _treemedia . get_os_media ( guest , meter )
else :
osguess = OSDB . guess_os_by_iso ( self . cdrom )
os_media = osguess [ 1 ] if osguess else None
return unattended . prepare_install_script (
guest , self . _unattended_data , url , os_media )
2019-06-08 21:16:52 +03:00
2018-09-03 18:47:59 +03:00
def _prepare ( self , guest , meter ) :
2019-06-10 02:10:19 +03:00
unattended_script = None
if self . _unattended_data :
unattended_script = self . _prepare_unattended_script ( guest , meter )
2018-10-13 01:35:09 +03:00
if self . _treemedia :
2019-06-10 02:10:19 +03:00
k , i , a = self . _treemedia . prepare ( guest , meter ,
unattended_script )
2018-10-13 01:35:09 +03:00
self . _install_kernel = k
self . _install_initrd = i
2018-10-13 23:30:19 +03:00
if a and " VIRTINST_INITRD_TEST " not in os . environ :
2018-10-13 23:29:32 +03:00
self . extra_args . append ( a )
2019-06-10 02:10:19 +03:00
elif unattended_script :
self . _prepare_unattended_data ( guest , unattended_script )
2018-09-03 18:47:59 +03:00
2018-09-03 20:11:17 +03:00
def _cleanup ( self , guest ) :
2018-10-13 01:35:09 +03:00
if self . _treemedia :
self . _treemedia . cleanup ( guest )
2019-06-08 22:20:16 +03:00
for f in self . _tmpfiles :
logging . debug ( " Removing %s " , str ( f ) )
os . unlink ( f )
2018-09-03 20:11:17 +03:00
2018-09-03 18:47:59 +03:00
def _get_postinstall_bootdev ( self , guest ) :
2018-10-13 01:35:09 +03:00
if self . cdrom and self . livecd :
return DomainOs . BOOT_DEVICE_CDROM
if self . _install_bootdev :
2018-10-12 22:15:20 +03:00
if any ( [ d for d in guest . devices . disk
if d . device == d . DEVICE_DISK ] ) :
return DomainOs . BOOT_DEVICE_HARDDISK
2018-10-13 01:35:09 +03:00
return self . _install_bootdev
2018-10-12 22:15:20 +03:00
2018-09-03 17:58:25 +03:00
device = guest . devices . disk and guest . devices . disk [ 0 ] . device or None
if device == DeviceDisk . DEVICE_DISK :
return DomainOs . BOOT_DEVICE_HARDDISK
elif device == DeviceDisk . DEVICE_CDROM :
return DomainOs . BOOT_DEVICE_CDROM
elif device == DeviceDisk . DEVICE_FLOPPY :
return DomainOs . BOOT_DEVICE_FLOPPY
return DomainOs . BOOT_DEVICE_HARDDISK
2013-07-17 02:12:13 +04:00
##############
# Public API #
##############
2018-10-13 01:35:09 +03:00
@property
def location ( self ) :
if self . _treemedia :
return self . _treemedia . location
@property
def cdrom ( self ) :
return self . _cdrom
def set_initrd_injections ( self , initrd_injections ) :
if self . _treemedia :
2018-10-13 22:51:38 +03:00
self . _treemedia . initrd_injections = initrd_injections
2018-10-13 01:35:09 +03:00
2018-09-03 21:34:53 +03:00
def set_install_defaults ( self , guest ) :
2018-09-03 18:47:59 +03:00
"""
2018-09-03 21:34:53 +03:00
Allow API users to set defaults ahead of time if they want it .
Used by vmmDomainVirtinst so the ' Customize before install ' dialog
shows accurate values .
If the user doesn ' t explicitly call this, it will be called by
start_install ( )
2018-09-03 18:47:59 +03:00
"""
2018-09-03 21:34:53 +03:00
if self . _defaults_are_set :
return
self . _add_install_cdrom_device ( guest )
if not guest . os . bootorder and self . _can_set_guest_bootorder ( guest ) :
bootdev = self . _get_postinstall_bootdev ( guest )
guest . os . bootorder = self . _build_boot_order ( guest , bootdev )
guest . set_defaults ( None )
self . _defaults_are_set = True
2018-09-03 18:47:59 +03:00
2019-02-07 21:58:55 +03:00
def get_search_paths ( self , guest ) :
2013-07-17 02:12:13 +04:00
"""
2019-02-07 21:58:55 +03:00
Return a list of paths that the hypervisor will need search access
for to perform this install .
2013-07-17 02:12:13 +04:00
"""
2019-02-07 21:58:55 +03:00
search_paths = [ ]
if self . _treemedia :
2019-06-07 20:58:19 +03:00
search_paths . append ( InstallerTreeMedia . make_scratchdir ( guest ) )
2019-02-07 21:58:55 +03:00
if self . _cdrom_path ( ) :
search_paths . append ( self . _cdrom_path ( ) )
return search_paths
2013-07-17 02:12:13 +04:00
2013-03-18 01:06:52 +04:00
def has_install_phase ( self ) :
"""
Return True if the requested setup is actually installing an OS
into the guest . Things like LiveCDs , Import , or a manually specified
bootorder do not have an install phase .
"""
2018-10-13 01:35:09 +03:00
if self . cdrom and self . livecd :
return False
return bool ( self . _cdrom or
self . _install_bootdev or
self . _treemedia )
2015-06-06 23:56:03 +03:00
2013-09-26 21:04:28 +04:00
def detect_distro ( self , guest ) :
2013-03-18 01:06:52 +04:00
"""
Attempt to detect the distro for the Installer ' s ' location ' . If
an error is encountered in the detection process ( or if detection
2014-09-07 19:57:04 +04:00
is not relevant for the Installer type ) , None is returned .
2013-03-18 01:06:52 +04:00
2018-02-14 15:17:31 +03:00
: returns : distro variant string , or None
2013-03-18 01:06:52 +04:00
"""
2018-10-13 01:35:09 +03:00
ret = None
2019-01-31 01:07:36 +03:00
if self . _treemedia :
ret = self . _treemedia . detect_distro ( guest )
elif self . cdrom :
if guest . conn . is_remote ( ) :
logging . debug ( " Can ' t detect distro for cdrom "
" remote connection. " )
2018-10-13 01:35:09 +03:00
else :
2019-01-31 01:07:36 +03:00
osguess = OSDB . guess_os_by_iso ( self . cdrom )
if osguess :
ret = osguess [ 0 ]
else :
logging . debug ( " No media for distro detection. " )
2018-10-13 01:35:09 +03:00
logging . debug ( " installer.detect_distro returned= %s " , ret )
return ret
2013-03-18 01:06:52 +04:00
2019-02-22 11:40:18 +03:00
def set_unattended_data ( self , unattended_data ) :
2019-06-10 02:10:19 +03:00
self . _unattended_data = unattended_data
2019-02-22 11:40:18 +03:00
2013-04-12 17:51:26 +04:00
2018-09-03 20:11:17 +03:00
##########################
# guest install handling #
##########################
def _prepare_get_install_xml ( self , guest ) :
# We do a shallow copy of the OS block here, so that we can
# set the install time properties but not permanently overwrite
# any config the user explicitly requested.
data = ( guest . os . bootorder , guest . os . kernel , guest . os . initrd ,
2019-05-11 20:34:21 +03:00
guest . os . kernel_args , guest . on_reboot , guest . currentMemory ,
guest . memory )
2018-09-03 20:11:17 +03:00
return data
def _finish_get_install_xml ( self , guest , data ) :
( guest . os . bootorder , guest . os . kernel , guest . os . initrd ,
2019-05-11 20:34:21 +03:00
guest . os . kernel_args , guest . on_reboot , guest . currentMemory ,
guest . memory ) = data
2018-09-03 20:11:17 +03:00
2019-03-22 18:23:41 +03:00
def _get_install_xml ( self , guest , meter ) :
2018-09-03 20:11:17 +03:00
data = self . _prepare_get_install_xml ( guest )
try :
self . _alter_bootconfig ( guest )
2019-03-22 18:23:41 +03:00
self . _alter_install_resources ( guest , meter )
2018-09-03 20:11:17 +03:00
ret = guest . get_xml ( )
return ret
finally :
self . _remove_install_cdrom_media ( guest )
2019-06-07 13:00:56 +03:00
self . _remove_unattended_install_cdrom_device ( guest )
2018-09-03 20:11:17 +03:00
self . _finish_get_install_xml ( guest , data )
2019-03-22 18:23:41 +03:00
def _build_xml ( self , guest , meter ) :
2018-09-03 20:11:17 +03:00
install_xml = None
if self . has_install_phase ( ) :
2019-03-22 18:23:41 +03:00
install_xml = self . _get_install_xml ( guest , meter )
2018-09-03 20:11:17 +03:00
final_xml = guest . get_xml ( )
logging . debug ( " Generated install XML: %s " ,
( install_xml and ( " \n " + install_xml ) or " None required " ) )
logging . debug ( " Generated boot XML: \n %s " , final_xml )
return install_xml , final_xml
def _manual_transient_create ( self , install_xml , final_xml , needs_boot ) :
"""
For hypervisors ( like vz ) that don ' t implement createXML,
we need to define + start , and undefine on start failure
"""
domain = self . conn . defineXML ( install_xml or final_xml )
if not needs_boot :
return domain
# Handle undefining the VM if the initial startup fails
try :
domain . create ( )
2019-06-10 21:15:50 +03:00
except Exception : # pragma: no cover
2018-09-03 20:11:17 +03:00
try :
domain . undefine ( )
except Exception :
pass
raise
if install_xml and install_xml != final_xml :
domain = self . conn . defineXML ( final_xml )
return domain
def _create_guest ( self , guest ,
meter , install_xml , final_xml , doboot , transient ) :
"""
Actually do the XML logging , guest defining / creating
: param doboot : Boot guest even if it has no install phase
"""
meter_label = _ ( " Creating domain... " )
2019-06-08 00:32:51 +03:00
meter = progress . ensure_meter ( meter )
2018-09-03 20:11:17 +03:00
meter . start ( size = None , text = meter_label )
needs_boot = doboot or self . has_install_phase ( )
if guest . type == " vz " :
if transient :
raise RuntimeError ( _ ( " Domain type ' vz ' doesn ' t support "
" transient installs. " ) )
domain = self . _manual_transient_create (
install_xml , final_xml , needs_boot )
else :
if transient or needs_boot :
domain = self . conn . createXML ( install_xml or final_xml , 0 )
if not transient :
domain = self . conn . defineXML ( final_xml )
try :
logging . debug ( " XML fetched from libvirt object: \n %s " ,
2018-09-03 20:41:39 +03:00
domain . XMLDesc ( 0 ) )
2019-06-10 21:15:50 +03:00
except Exception as e : # pragma: no cover
2018-09-03 20:11:17 +03:00
logging . debug ( " Error fetching XML from libvirt object: %s " , e )
2018-09-03 20:41:39 +03:00
return domain
2018-09-03 20:11:17 +03:00
2018-09-03 20:41:39 +03:00
def _flag_autostart ( self , domain ) :
2018-09-03 20:11:17 +03:00
"""
2018-09-03 20:41:39 +03:00
Set the autostart flag for domain if the user requested it
2018-09-03 20:11:17 +03:00
"""
try :
2018-09-03 20:41:39 +03:00
domain . setAutostart ( True )
2019-06-10 21:15:50 +03:00
except Exception as e : # pragma: no cover
2019-06-07 23:48:21 +03:00
if not self . conn . support . is_error_nosupport ( e ) :
raise
logging . warning ( " Could not set autostart flag: libvirt "
" connection does not support autostart. " )
2018-09-03 20:11:17 +03:00
######################
# Public install API #
######################
def start_install ( self , guest , meter = None ,
dry = False , return_xml = False ,
2018-10-13 16:42:15 +03:00
doboot = True , transient = False ) :
2018-09-03 20:11:17 +03:00
"""
2018-09-03 20:45:09 +03:00
Begin the guest install . Will add install media to the guest config ,
launch it , then redefine the XML with the postinstall config .
2018-09-03 20:11:17 +03:00
: param return_xml : Don ' t create the guest, just return generated XML
"""
2018-09-03 22:45:26 +03:00
guest . validate_name ( guest . conn , guest . name )
2018-09-03 21:34:53 +03:00
self . set_install_defaults ( guest )
2018-09-03 20:11:17 +03:00
try :
self . _prepare ( guest , meter )
if not dry :
2018-09-03 23:44:38 +03:00
for dev in guest . devices . disk :
dev . build_storage ( meter )
2018-09-03 20:11:17 +03:00
2019-03-22 18:23:41 +03:00
install_xml , final_xml = self . _build_xml ( guest , meter )
2019-06-12 00:19:01 +03:00
if dry or return_xml :
2018-09-03 20:11:17 +03:00
return ( install_xml , final_xml )
2018-09-03 20:41:39 +03:00
domain = self . _create_guest (
guest , meter , install_xml , final_xml ,
doboot , transient )
2018-09-03 20:11:17 +03:00
2018-10-13 16:42:15 +03:00
if self . autostart :
2018-09-03 20:45:09 +03:00
self . _flag_autostart ( domain )
2018-09-03 20:41:39 +03:00
return domain
2018-09-03 20:11:17 +03:00
finally :
self . _cleanup ( guest )
def get_created_disks ( self , guest ) :
return [ d for d in guest . devices . disk if d . storage_was_created ]
def cleanup_created_disks ( self , guest , meter ) :
"""
Remove any disks we created as part of the install . Only ever
called by clients .
"""
clean_disks = self . get_created_disks ( guest )
if not clean_disks :
return
for disk in clean_disks :
logging . debug ( " Removing created disk path= %s vol_object= %s " ,
disk . path , disk . get_vol_object ( ) )
name = os . path . basename ( disk . path )
try :
meter . start ( size = None , text = _ ( " Removing disk ' %s ' " ) % name )
if disk . get_vol_object ( ) :
disk . get_vol_object ( ) . delete ( )
2019-06-10 21:15:50 +03:00
else : # pragma: no cover
# This case technically shouldn't happen here, but
# it's here incase future assumptions change
2018-09-03 20:11:17 +03:00
os . unlink ( disk . path )
meter . end ( 0 )
2019-06-10 21:15:50 +03:00
except Exception as e : # pragma: no cover
2018-09-03 20:11:17 +03:00
logging . debug ( " Failed to remove disk ' %s ' " ,
name , exc_info = True )
logging . error ( " Failed to remove disk ' %s ' : %s " , name , e )