2013-03-18 01:06:52 +04:00
# Installer for images
#
# Copyright 2007 Red Hat, Inc.
# David Lutterkort <dlutter@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
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
import os
2013-04-11 03:48:07 +04:00
from virtinst import Installer
from virtinst import ImageParser
2013-07-06 22:12:13 +04:00
from virtinst import CapabilitiesParser
2013-04-11 03:48:07 +04:00
from virtinst . VirtualDisk import VirtualDisk
2013-03-18 02:18:22 +04:00
2013-03-18 01:06:52 +04:00
class ImageInstaller ( Installer . Installer ) :
2013-04-15 00:31:18 +04:00
"""
Installer for virt - image - based guests
"""
_has_install_phase = False
2013-07-06 04:14:57 +04:00
def __init__ ( self , conn , image , boot_index = None ) :
Installer . Installer . __init__ ( self , conn )
2013-03-18 01:06:52 +04:00
self . _image = image
# Set boot _boot_caps/_boot_parameters
if boot_index is None :
2013-07-06 22:12:13 +04:00
self . _boot_caps = match_boots ( self . conn . caps ,
2013-03-18 01:06:52 +04:00
self . image . domain . boots )
if self . _boot_caps is None :
2013-07-06 04:14:57 +04:00
raise RuntimeError ( _ ( " Could not find suitable boot "
" descriptor for this host " ) )
2013-03-18 01:06:52 +04:00
else :
if ( boot_index < 0 or
( boot_index + 1 ) > len ( image . domain . boots ) ) :
raise ValueError ( _ ( " boot_index out of range. " ) )
self . _boot_caps = image . domain . boots [ boot_index ]
# Set up internal caps.guest object
2013-07-06 22:12:13 +04:00
self . _guest = self . conn . caps . guestForOSType ( self . boot_caps . type ,
2013-07-17 15:53:47 +04:00
self . boot_caps . arch )
2013-03-18 01:06:52 +04:00
if self . _guest is None :
2013-07-06 04:14:57 +04:00
raise RuntimeError ( _ ( " Unsupported virtualization type: %s %s " %
( self . boot_caps . type , self . boot_caps . arch ) ) )
2013-03-18 01:06:52 +04:00
self . _domain = self . _guest . bestDomainType ( )
2013-07-17 15:53:47 +04:00
# Custom ImageInstaller methods
def get_caps_guest ( self ) :
return self . _guest , self . _domain
2013-03-18 01:06:52 +04:00
def get_image ( self ) :
return self . _image
image = property ( get_image )
def get_boot_caps ( self ) :
return self . _boot_caps
boot_caps = property ( get_boot_caps )
# General Installer methods
2013-07-17 15:53:47 +04:00
def _prepare ( self , guest , meter , scratchdir ) :
ignore = scratchdir
ignore = meter
2013-03-18 01:06:52 +04:00
self . _make_disks ( )
for f in [ ' pae ' , ' acpi ' , ' apic ' ] :
2013-07-06 22:12:13 +04:00
if self . boot_caps . features [ f ] & CapabilitiesParser . FEATURE_ON :
2013-03-18 01:06:52 +04:00
guest . features [ f ] = True
2013-07-06 22:12:13 +04:00
elif self . boot_caps . features [ f ] & CapabilitiesParser . FEATURE_OFF :
2013-03-18 01:06:52 +04:00
guest . features [ f ] = False
2013-07-17 15:53:47 +04:00
guest . os . kernel = self . boot_caps . kernel
guest . os . initrd = self . boot_caps . initrd
guest . os . kernel_args = self . boot_caps . cmdline
2013-03-18 01:06:52 +04:00
# Private methods
def _get_bootdev ( self , isinstall , guest ) :
return self . boot_caps . bootdev
def _make_disks ( self ) :
for drive in self . boot_caps . drives :
path = self . _abspath ( drive . disk . file )
size = None
if drive . disk . size is not None :
size = float ( drive . disk . size ) / 1024
# FIXME: This is awkward; the image should be able to express
# whether the disk is expected to be there or not independently
# of its classification, especially for user disks
# FIXME: We ignore the target for the mapping in m.target
if ( drive . disk . use == ImageParser . Disk . USE_SYSTEM and
not os . path . exists ( path ) ) :
2013-07-06 04:14:57 +04:00
raise RuntimeError ( _ ( " System disk %s does not exist " ) % path )
2013-03-18 01:06:52 +04:00
device = VirtualDisk . DEVICE_DISK
if drive . disk . format == ImageParser . Disk . FORMAT_ISO :
device = VirtualDisk . DEVICE_CDROM
2013-07-13 18:09:00 +04:00
disk = VirtualDisk ( self . conn )
disk . path = path
disk . device = device
2013-03-18 01:06:52 +04:00
disk . target = drive . target
2013-07-13 18:09:00 +04:00
disk . set_create_storage ( size = size , fmt = drive . disk . format )
disk . validate ( )
2013-03-18 01:06:52 +04:00
self . install_devices . append ( disk )
def _abspath ( self , p ) :
return self . image . abspath ( p )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def match_boots ( capabilities , boots ) :
for b in boots :
for g in capabilities . guests :
if b . type == g . os_type and b . arch == g . arch :
found = True
for bf in b . features . names ( ) :
if not b . features [ bf ] & g . features [ bf ] :
found = False
break
if found :
return b
return None