virt-manager/virtinst/ImageInstaller.py

141 lines
4.8 KiB
Python

# 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
from virtinst import Installer
from virtinst import ImageParser
from virtinst import CapabilitiesParser
from virtinst.VirtualDisk import VirtualDisk
class ImageInstaller(Installer.Installer):
"""
Installer for virt-image-based guests
"""
_has_install_phase = False
def __init__(self, conn, image, boot_index=None):
Installer.Installer.__init__(self, conn)
self._image = image
# Set boot _boot_caps/_boot_parameters
if boot_index is None:
self._boot_caps = match_boots(self.conn.caps,
self.image.domain.boots)
if self._boot_caps is None:
raise RuntimeError(_("Could not find suitable boot "
"descriptor for this host"))
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
self._guest = self.conn.caps.guestForOSType(self.boot_caps.type,
self.boot_caps.arch)
if self._guest is None:
raise RuntimeError(_("Unsupported virtualization type: %s %s" %
(self.boot_caps.type, self.boot_caps.arch)))
self._domain = self._guest.bestDomainType()
# Custom ImageInstaller methods
def get_caps_guest(self):
return self._guest, self._domain
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
def _prepare(self, guest, meter, scratchdir):
ignore = scratchdir
ignore = meter
self._make_disks()
for f in ['pae', 'acpi', 'apic']:
if self.boot_caps.features[f] & CapabilitiesParser.FEATURE_ON:
guest.features[f] = True
elif self.boot_caps.features[f] & CapabilitiesParser.FEATURE_OFF:
guest.features[f] = False
guest.os.kernel = self.boot_caps.kernel
guest.os.initrd = self.boot_caps.initrd
guest.os.kernel_args = self.boot_caps.cmdline
# 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)):
raise RuntimeError(_("System disk %s does not exist") % path)
device = VirtualDisk.DEVICE_DISK
if drive.disk.format == ImageParser.Disk.FORMAT_ISO:
device = VirtualDisk.DEVICE_CDROM
disk = VirtualDisk(self.conn)
disk.path = path
disk.device = device
disk.target = drive.target
disk.set_create_storage(size=size, fmt=drive.disk.format)
disk.validate()
self.install_devices.append(disk)
def _abspath(self, p):
return self.image.abspath(p)
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