~ubuntu-branches/ubuntu/quantal/virtinst/quantal-proposed

« back to all changes in this revision

Viewing changes to virtinst/ImageManager.py

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2007-11-20 13:40:28 UTC
  • Revision ID: james.westby@ubuntu.com-20071120134028-rg0pjby0jc4mycks
Tags: upstream-0.300.1+hg20071120
ImportĀ upstreamĀ versionĀ 0.300.1+hg20071120

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Installer for images
 
2
#
 
3
# Copyright 2007  Red Hat, Inc.
 
4
# David Lutterkort <dlutter@redhat.com>
 
5
#
 
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.
 
10
#
 
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.
 
15
#
 
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,
 
19
# MA 02110-1301 USA.
 
20
 
 
21
import Guest
 
22
import ImageParser
 
23
import CapabilitiesParser as Cap
 
24
import os
 
25
import util
 
26
 
 
27
import pdb
 
28
 
 
29
class ImageInstallerException(RuntimeError):
 
30
    def __init__(self, msg):
 
31
        Exception.__init__(self, msg)
 
32
 
 
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
 
38
        self._image = image
 
39
        if boot_index is None:
 
40
            self._boot = None
 
41
        else:
 
42
            self._boot = image.domain.boots[boot_index]
 
43
 
 
44
    def get_image(self):
 
45
        return self._image
 
46
    image = property(get_image)
 
47
 
 
48
    def get_boot(self):
 
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"))
 
54
        return self._boot
 
55
    boot = property(get_boot)
 
56
 
 
57
    def get_type(self):
 
58
        return domain_type(self._capabilities, self.boot)
 
59
    def set_type(self, t):
 
60
        pass
 
61
    type = property(get_type, set_type)
 
62
 
 
63
    def prepare(self, guest, meter, distro = None):
 
64
        self._make_disks(guest)
 
65
 
 
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
 
73
 
 
74
    def _make_disks(self, guest):
 
75
        for m in self.boot.disks:
 
76
            p = self._abspath(m.disk.file)
 
77
            s = None
 
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")
 
86
                                              % p)
 
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,
 
91
                                  device = device,
 
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
 
95
            d.target = m.target
 
96
 
 
97
            guest.disks.append(d)
 
98
 
 
99
    def _get_osblob(self, install, hvm, arch = None, loader = None):
 
100
        osblob = "<os>\n"
 
101
 
 
102
        if hvm:
 
103
            type = "hvm"
 
104
        else:
 
105
            type = "linux"
 
106
 
 
107
        if arch:
 
108
            osblob += "    <type arch='%s'>%s</type>\n" % (arch, type)
 
109
        else:
 
110
            osblob += "    <type>%s</type>\n" % type
 
111
 
 
112
        if self.boot.kernel:
 
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
 
116
            osblob += "  </os>"
 
117
        elif hvm:
 
118
            if loader:
 
119
                osblob += "    <loader>%s</loader>\n" % loader
 
120
            if self.boot.bootdev:
 
121
                osblob += "    <boot dev='%s'/>\n" % self.boot.bootdev
 
122
            osblob += "  </os>"
 
123
        elif self.boot.loader == "pygrub" or (self.boot.loader is None and self.boot.type == "xen"):
 
124
            osblob += "  </os>\n"
 
125
            osblob += "  <bootloader>/usr/bin/pygrub</bootloader>"
 
126
 
 
127
        return osblob
 
128
 
 
129
    def post_install_check(self, guest):
 
130
        return True
 
131
 
 
132
    def _abspath(self, p):
 
133
        return os.path.abspath(os.path.join(self.image.base, p))
 
134
 
 
135
class PlatformMatchException(Exception):
 
136
    def __init__(self, msg):
 
137
        Exception.__init__(self, msg)
 
138
 
 
139
def match_boots(capabilities, boots):
 
140
    for b in boots:
 
141
        for g in capabilities.guests:
 
142
            if b.type == g.os_type and b.arch == g.arch:
 
143
                found = True
 
144
                for bf in b.features.names():
 
145
                    if not b.features[bf] & g.features[bf]:
 
146
                        found = False
 
147
                        break
 
148
                if found:
 
149
                    return b
 
150
    return None
 
151
 
 
152
def domain_type(capabilities, boot):
 
153
    if boot.type == "xen":
 
154
        return "xen"
 
155
    assert boot.type == "hvm"
 
156
 
 
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" ]
 
162
    for o in order:
 
163
        if types.count(o) > 0:
 
164
            return o
 
165
    # None of the known types above was found, return the alphabetically
 
166
    # smallest one arbitrarily
 
167
    types.sort()
 
168
    if len(types) > 0:
 
169
        return types[0]
 
170
    raise PlatformMatchException(_("Insufficient HVM capabilities"))