3
# Copyright 2007 Red Hat, Inc.
4
# David Lutterkort <dlutter@redhat.com>
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23
import CapabilitiesParser as Cap
29
class ImageInstallerException(RuntimeError):
30
def __init__(self, msg):
31
Exception.__init__(self, msg)
33
class ImageInstaller(Guest.Installer):
34
"""Installer for image-based guests"""
35
def __init__(self, image, capabilities, boot_index = None):
36
Guest.Installer.__init__(self)
37
self._capabilities = capabilities
39
if boot_index is None:
42
self._boot = image.domain.boots[boot_index]
46
image = property(get_image)
49
if self._boot is None:
50
self._boot = match_boots(self._capabilities,
51
self.image.domain.boots)
52
if self._boot is None:
53
raise ImageInstallerException(_("Could not find suitable boot descriptor for this host"))
55
boot = property(get_boot)
58
return domain_type(self._capabilities, self.boot)
59
def set_type(self, t):
61
type = property(get_type, set_type)
63
def prepare(self, guest, meter, distro = None):
64
self._make_disks(guest)
66
# Ugly: for PV xen, there's no guest.features, and nothing to toggle
67
if self.type != "xen":
68
for f in ['pae', 'acpi', 'apic']:
69
if self.boot.features[f] & Cap.FEATURE_ON:
70
guest.features[f] = True
71
elif self.boot.features[f] & Cap.FEATURE_OFF:
72
guest.features[f] = False
74
def _make_disks(self, guest):
75
for m in self.boot.disks:
76
p = self._abspath(m.disk.file)
78
if m.disk.size is not None:
79
s = float(m.disk.size)/1024
80
# FIXME: This is awkward; the image should be able to express
81
# whether the disk is expected to be there or not independently
82
# of its classification, especially for user disks
83
# FIXME: We ignore the target for the mapping in m.target
84
if m.disk.use == ImageParser.Disk.USE_SYSTEM and not os.path.exists(p):
85
raise ImageInstallerException(_("System disk %s does not exist")
87
device = Guest.VirtualDisk.DEVICE_DISK
88
if m.disk.format == ImageParser.Disk.FORMAT_ISO:
89
device = Guest.VirtualDisk.DEVICE_CDROM
90
d = Guest.VirtualDisk(p, s,
92
type = Guest.VirtualDisk.TYPE_FILE)
93
if self.boot.type == "xen" and util.is_blktap_capable():
94
d.driver_name = Guest.VirtualDisk.DRIVER_TAP
99
def _get_osblob(self, install, hvm, arch = None, loader = None):
108
osblob += " <type arch='%s'>%s</type>\n" % (arch, type)
110
osblob += " <type>%s</type>\n" % type
113
osblob += " <kernel>%s</kernel>\n" % self._abspath(self.boot.kernel)
114
osblob += " <initrd>%s</initrd>\n" % self._abspath(self.boot.initrd)
115
osblob += " <cmdline>%s</cmdline>\n" % self.boot.cmdline
119
osblob += " <loader>%s</loader>\n" % loader
120
if self.boot.bootdev:
121
osblob += " <boot dev='%s'/>\n" % self.boot.bootdev
123
elif self.boot.loader == "pygrub" or (self.boot.loader is None and self.boot.type == "xen"):
125
osblob += " <bootloader>/usr/bin/pygrub</bootloader>"
129
def post_install_check(self, guest):
132
def _abspath(self, p):
133
return os.path.abspath(os.path.join(self.image.base, p))
135
class PlatformMatchException(Exception):
136
def __init__(self, msg):
137
Exception.__init__(self, msg)
139
def match_boots(capabilities, boots):
141
for g in capabilities.guests:
142
if b.type == g.os_type and b.arch == g.arch:
144
for bf in b.features.names():
145
if not b.features[bf] & g.features[bf]:
152
def domain_type(capabilities, boot):
153
if boot.type == "xen":
155
assert boot.type == "hvm"
157
types = [ guest.hypervisor_type for guest in capabilities.guests
158
if guest.os_type == "hvm" ]
159
# FIXME: The order shouldn't be defined here, it should
160
# somehow come from libvirt
161
order = [ "xen", "kvm", "kqemu", "qemu" ]
163
if types.count(o) > 0:
165
# None of the known types above was found, return the alphabetically
166
# smallest one arbitrarily
170
raise PlatformMatchException(_("Insufficient HVM capabilities"))