mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-12-24 21:34:47 +03:00
164 lines
5.5 KiB
Python
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
|