virt-manager/virtinst/ImageInstaller.py
2013-04-15 12:37:36 -04:00

164 lines
5.5 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 as Cap
from virtinst.VirtualDisk import VirtualDisk
class ImageInstallerException(Exception):
def __init__(self, msg):
Exception.__init__(self, msg)
class ImageInstaller(Installer.Installer):
"""
Installer for virt-image-based guests
"""
_has_install_phase = False
def __init__(self, image, capabilities=None, boot_index=None, conn=None):
Installer.Installer.__init__(self, conn=conn, caps=capabilities)
self._arch = None
self._image = image
if not (self.conn or self._get_caps()):
raise ValueError(_("'conn' or 'capabilities' must be specified."))
# Set boot _boot_caps/_boot_parameters
if boot_index is None:
self._boot_caps = match_boots(self._get_caps(),
self.image.domain.boots)
if self._boot_caps is None:
raise ImageInstallerException(_("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._get_caps().guestForOSType(self.boot_caps.type,
self.boot_caps.arch)
if self._guest is None:
raise PlatformMatchException(_("Unsupported virtualization type: "
"%s %s" % (self.boot_caps.type,
self.boot_caps.arch)))
self.os_type = self.boot_caps.type
self._domain = self._guest.bestDomainType()
self.type = self._domain.hypervisor_type
self.arch = self._guest.arch
# Custom ImageInstaller methods
def is_hvm(self):
if self._boot_caps.type == "hvm":
return True
return False
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):
self.cleanup()
self._make_disks()
for f in ['pae', 'acpi', 'apic']:
if self.boot_caps.features[f] & Cap.FEATURE_ON:
guest.features[f] = True
elif self.boot_caps.features[f] & Cap.FEATURE_OFF:
guest.features[f] = False
self.bootconfig.kernel = self.boot_caps.kernel
self.bootconfig.initrd = self.boot_caps.initrd
self.bootconfig.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 ImageInstallerException(_("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(conn=self.conn,
path=path,
size=size,
device=device,
format=drive.disk.format)
disk.target = drive.target
self.install_devices.append(disk)
def _abspath(self, p):
return self.image.abspath(p)
class PlatformMatchException(Exception):
def __init__(self, msg):
Exception.__init__(self, msg)
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