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

« back to all changes in this revision

Viewing changes to .pc/9004_ubuntu_correct_tree.patch/virtinst/OSDistro.py

  • Committer: Bazaar Package Importer
  • Author(s): Andres Rodriguez
  • Date: 2011-04-05 18:18:09 UTC
  • Revision ID: james.westby@ubuntu.com-20110405181809-h62kqfjdinrhgbuy
Tags: 0.500.5-1ubuntu3
Correctly detect an UbuntuDistro from an HTTP source. (LP: #751979)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Represents OS distribution specific install data
 
3
#
 
4
# Copyright 2006-2007  Red Hat, Inc.
 
5
# Daniel P. Berrange <berrange@redhat.com>
 
6
#
 
7
# This program is free software; you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free  Software Foundation; either version 2 of the License, or
 
10
# (at your option)  any later version.
 
11
#
 
12
# This program is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with this program; if not, write to the Free Software
 
19
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
20
# MA 02110-1301 USA.
 
21
 
 
22
import logging
 
23
import os
 
24
import gzip
 
25
import re
 
26
import tempfile
 
27
import socket
 
28
import ConfigParser
 
29
 
 
30
import virtinst
 
31
import osdict
 
32
from virtinst import _util
 
33
from virtinst import _virtinst as _
 
34
 
 
35
from ImageFetcher import MountedImageFetcher
 
36
from ImageFetcher import FTPImageFetcher
 
37
from ImageFetcher import HTTPImageFetcher
 
38
from ImageFetcher import DirectImageFetcher
 
39
 
 
40
def safeint(c):
 
41
    try:
 
42
        val = int(c)
 
43
    except:
 
44
        val = 0
 
45
    return val
 
46
 
 
47
def _fetcherForURI(uri, scratchdir=None):
 
48
    if uri.startswith("http://"):
 
49
        fclass = HTTPImageFetcher
 
50
    elif uri.startswith("ftp://"):
 
51
        fclass = FTPImageFetcher
 
52
    elif uri.startswith("nfs://"):
 
53
        fclass = MountedImageFetcher
 
54
    else:
 
55
        if os.path.isdir(uri):
 
56
            fclass = DirectImageFetcher
 
57
        else:
 
58
            fclass = MountedImageFetcher
 
59
    return fclass(uri, scratchdir)
 
60
 
 
61
def _storeForDistro(fetcher, baseuri, typ, progresscb, arch, distro=None,
 
62
                    scratchdir=None):
 
63
    stores = []
 
64
    skip_treeinfo = False
 
65
    logging.debug("Attempting to detect distro:")
 
66
 
 
67
    dist = virtinst.OSDistro.distroFromTreeinfo(fetcher, progresscb, baseuri,
 
68
                                                arch, typ, scratchdir)
 
69
    if dist:
 
70
        return dist
 
71
    skip_treeinfo = True
 
72
 
 
73
    # FIXME: This 'distro ==' doesn't cut it. 'distro' is from our os
 
74
    # dictionary, so would look like 'fedora9' or 'rhel5', so this needs
 
75
    # to be a bit more intelligent
 
76
    if distro == "fedora" or distro is None:
 
77
        stores.append(FedoraDistro)
 
78
    if distro == "rhel" or distro is None:
 
79
        stores.append(RHELDistro)
 
80
    if distro == "centos" or distro is None:
 
81
        stores.append(CentOSDistro)
 
82
    if distro == "sl" or distro is None:
 
83
        stores.append(SLDistro)
 
84
    if distro == "suse" or distro is None:
 
85
        stores.append(SuseDistro)
 
86
    if distro == "debian" or distro is None:
 
87
        stores.append(DebianDistro)
 
88
    if distro == "ubuntu" or distro is None:
 
89
        stores.append(UbuntuDistro)
 
90
    if distro == "mandriva" or distro is None:
 
91
        stores.append(MandrivaDistro)
 
92
    # XXX: this is really "nevada"
 
93
    if distro == "solaris" or distro is None:
 
94
        stores.append(SolarisDistro)
 
95
    if distro == "solaris" or distro is None:
 
96
        stores.append(OpenSolarisDistro)
 
97
    if distro == "netware" or distro is None:
 
98
        stores.append(NetWareDistro)
 
99
 
 
100
    stores.append(GenericDistro)
 
101
 
 
102
    for sclass in stores:
 
103
        store = sclass(baseuri, arch, typ, scratchdir)
 
104
        if skip_treeinfo:
 
105
            store.uses_treeinfo = False
 
106
        if store.isValidStore(fetcher, progresscb):
 
107
            return store
 
108
 
 
109
    raise ValueError(
 
110
        _("Could not find an installable distribution at '%s'\n"
 
111
          "The location must be the root directory of an install tree." %
 
112
          baseuri))
 
113
 
 
114
def _locationCheckWrapper(guest, baseuri, progresscb,
 
115
                          scratchdir, _type, arch, callback):
 
116
    fetcher = _fetcherForURI(baseuri, scratchdir)
 
117
    if guest:
 
118
        arch = guest.arch
 
119
 
 
120
    try:
 
121
        fetcher.prepareLocation()
 
122
    except ValueError, e:
 
123
        raise ValueError(_("Invalid install location: ") + str(e))
 
124
 
 
125
    try:
 
126
        store = _storeForDistro(fetcher=fetcher, baseuri=baseuri, typ=_type,
 
127
                                progresscb=progresscb, scratchdir=scratchdir,
 
128
                                arch=arch)
 
129
 
 
130
        return callback(store, fetcher)
 
131
    finally:
 
132
        fetcher.cleanupLocation()
 
133
 
 
134
def _acquireMedia(iskernel, guest, baseuri, progresscb,
 
135
                  scratchdir="/var/tmp", _type=None):
 
136
 
 
137
    def media_cb(store, fetcher):
 
138
        os_type, os_variant = store.get_osdict_info()
 
139
        media = None
 
140
 
 
141
        if iskernel:
 
142
            media = store.acquireKernel(guest, fetcher, progresscb)
 
143
        else:
 
144
            media = store.acquireBootDisk(guest, fetcher, progresscb)
 
145
 
 
146
        return [store, os_type, os_variant, media]
 
147
 
 
148
    return _locationCheckWrapper(guest, baseuri, progresscb, scratchdir, _type,
 
149
                                 None, media_cb)
 
150
 
 
151
# Helper method to lookup install media distro and fetch an install kernel
 
152
def acquireKernel(guest, baseuri, progresscb, scratchdir, type=None):
 
153
    iskernel = True
 
154
    return _acquireMedia(iskernel, guest, baseuri, progresscb,
 
155
                         scratchdir, type)
 
156
 
 
157
# Helper method to lookup install media distro and fetch a boot iso
 
158
def acquireBootDisk(guest, baseuri, progresscb, scratchdir, type=None):
 
159
    iskernel = False
 
160
    return _acquireMedia(iskernel, guest, baseuri, progresscb,
 
161
                         scratchdir, type)
 
162
 
 
163
def _check_ostype_valid(os_type):
 
164
    return bool(os_type in osdict.sort_helper(osdict.OS_TYPES))
 
165
 
 
166
def _check_osvariant_valid(os_type, os_variant):
 
167
    return bool(_check_ostype_valid(os_type) and
 
168
        os_variant in osdict.sort_helper(osdict.OS_TYPES[os_type]["variants"]))
 
169
 
 
170
# Attempt to detect the os type + variant for the passed location
 
171
def detectMediaDistro(location, arch):
 
172
    import urlgrabber
 
173
    progresscb = urlgrabber.progress.BaseMeter()
 
174
    guest = None
 
175
    baseuri = location
 
176
    scratchdir = "/var/tmp"
 
177
    _type = None
 
178
    def media_cb(store, ignore):
 
179
        return store
 
180
 
 
181
    store = _locationCheckWrapper(guest, baseuri, progresscb, scratchdir,
 
182
                                  _type, arch, media_cb)
 
183
 
 
184
    return store.get_osdict_info()
 
185
 
 
186
 
 
187
def distroFromTreeinfo(fetcher, progresscb, uri, arch, vmtype=None,
 
188
                       scratchdir=None):
 
189
    # Parse treeinfo 'family' field, and return the associated Distro class
 
190
    # None if no treeinfo, GenericDistro if unknown family type.
 
191
    if not fetcher.hasFile(".treeinfo"):
 
192
        return None
 
193
 
 
194
    tmptreeinfo = fetcher.acquireFile(".treeinfo", progresscb)
 
195
    try:
 
196
        treeinfo = ConfigParser.SafeConfigParser()
 
197
        treeinfo.read(tmptreeinfo)
 
198
    finally:
 
199
        os.unlink(tmptreeinfo)
 
200
 
 
201
    try:
 
202
        fam = treeinfo.get("general", "family")
 
203
    except ConfigParser.NoSectionError:
 
204
        return None
 
205
 
 
206
    if re.match(".*Fedora.*", fam):
 
207
        dclass = FedoraDistro
 
208
    elif re.match(".*CentOS.*", fam):
 
209
        dclass = CentOSDistro
 
210
    elif re.match(".*Red Hat Enterprise Linux.*", fam):
 
211
        dclass = RHELDistro
 
212
    elif re.match(".*Scientific Linux.*", fam):
 
213
        dclass = SLDistro
 
214
    else:
 
215
        dclass = GenericDistro
 
216
 
 
217
    ob = dclass(uri, arch, vmtype, scratchdir)
 
218
    ob.treeinfo = treeinfo
 
219
 
 
220
    # Explictly call this, so we populate os_type/variant info
 
221
    ob.isValidStore(fetcher, progresscb)
 
222
 
 
223
    return ob
 
224
 
 
225
 
 
226
# An image store is a base class for retrieving either a bootable
 
227
# ISO image, or a kernel+initrd  pair for a particular OS distribution
 
228
class Distro:
 
229
 
 
230
    name = ""
 
231
 
 
232
    # osdict type and variant values
 
233
    os_type = None
 
234
    os_variant = None
 
235
 
 
236
    _boot_iso_paths = []
 
237
    _hvm_kernel_paths = []
 
238
    _xen_kernel_paths = []
 
239
    uses_treeinfo = False
 
240
 
 
241
    def __init__(self, uri, arch, vmtype=None, scratchdir=None):
 
242
        self.uri = uri
 
243
        self.type = vmtype
 
244
        self.scratchdir = scratchdir
 
245
        self.arch = arch
 
246
        self.treeinfo = None
 
247
 
 
248
    def isValidStore(self, fetcher, progresscb):
 
249
        """Determine if uri points to a tree of the store's distro"""
 
250
        raise NotImplementedError
 
251
 
 
252
    def acquireKernel(self, guest, fetcher, progresscb):
 
253
        kernelpath = None
 
254
        initrdpath = None
 
255
        if self._hasTreeinfo(fetcher, progresscb):
 
256
            kernelpath = self._getTreeinfoMedia("kernel")
 
257
            initrdpath = self._getTreeinfoMedia("initrd")
 
258
        else:
 
259
            # fall back to old code
 
260
            if self.type is None or self.type == "hvm":
 
261
                paths = self._hvm_kernel_paths
 
262
            else:
 
263
                paths = self._xen_kernel_paths
 
264
 
 
265
            for kpath, ipath in paths:
 
266
                if fetcher.hasFile(kpath) and fetcher.hasFile(ipath):
 
267
                    kernelpath = kpath
 
268
                    initrdpath = ipath
 
269
 
 
270
        if not kernelpath or not initrdpath:
 
271
            raise RuntimeError(_("Couldn't find %(type)s kernel for "
 
272
                                 "%(distro)s tree.") % \
 
273
                                 { "distro": self.name, "type" : self.type })
 
274
 
 
275
        return self._kernelFetchHelper(fetcher, guest, progresscb, kernelpath,
 
276
                                       initrdpath)
 
277
 
 
278
    def acquireBootDisk(self, guest, fetcher, progresscb):
 
279
        if self._hasTreeinfo(fetcher, progresscb):
 
280
            return fetcher.acquireFile(self._getTreeinfoMedia("boot.iso"),
 
281
                                       progresscb)
 
282
        else:
 
283
            for path in self._boot_iso_paths:
 
284
                if fetcher.hasFile(path):
 
285
                    return fetcher.acquireFile(path, progresscb)
 
286
            raise RuntimeError(_("Could not find boot.iso in %s tree." % \
 
287
                               self.name))
 
288
 
 
289
    def get_osdict_info(self):
 
290
        """
 
291
        Return (distro, variant) tuple, checking to make sure they are valid
 
292
        osdict entries
 
293
        """
 
294
        if not self.os_type:
 
295
            return (None, None)
 
296
 
 
297
        if not _check_ostype_valid(self.os_type):
 
298
            logging.debug("%s set os_type to %s, which is not in osdict." %
 
299
                          (self, self.os_type))
 
300
            return (None, None)
 
301
 
 
302
        if not self.os_variant:
 
303
            return (self.os_type, None)
 
304
 
 
305
        if not _check_osvariant_valid(self.os_type, self.os_variant):
 
306
            logging.debug("%s set os_variant to %s, which is not in osdict"
 
307
                          " for distro %s." %
 
308
                          (self, self.os_variant, self.os_type))
 
309
            return (self.os_type, None)
 
310
 
 
311
        return (self.os_type, self.os_variant)
 
312
 
 
313
    def _hasTreeinfo(self, fetcher, progresscb):
 
314
        # all Red Hat based distros should have .treeinfo, perhaps others
 
315
        # will in time
 
316
        if not (self.treeinfo is None):
 
317
            return True
 
318
 
 
319
        if not self.uses_treeinfo or not fetcher.hasFile(".treeinfo"):
 
320
            return False
 
321
 
 
322
        logging.debug("Detected .treeinfo file")
 
323
 
 
324
        tmptreeinfo = fetcher.acquireFile(".treeinfo", progresscb)
 
325
        try:
 
326
            self.treeinfo = ConfigParser.SafeConfigParser()
 
327
            self.treeinfo.read(tmptreeinfo)
 
328
        finally:
 
329
            os.unlink(tmptreeinfo)
 
330
        return True
 
331
 
 
332
    def _getTreeinfoMedia(self, mediaName):
 
333
        if self.type == "xen":
 
334
            t = "xen"
 
335
        else:
 
336
            t = self.treeinfo.get("general", "arch")
 
337
 
 
338
        return self.treeinfo.get("images-%s" % t, mediaName)
 
339
 
 
340
    def _fetchAndMatchRegex(self, fetcher, progresscb, filename, regex):
 
341
        # Fetch 'filename' and return True/False if it matches the regex
 
342
        local_file = None
 
343
        try:
 
344
            try:
 
345
                local_file = fetcher.acquireFile(filename, progresscb)
 
346
            except:
 
347
                return False
 
348
 
 
349
            f = open(local_file, "r")
 
350
            try:
 
351
                while 1:
 
352
                    buf = f.readline()
 
353
                    if not buf:
 
354
                        break
 
355
                    if re.match(regex, buf):
 
356
                        return True
 
357
            finally:
 
358
                f.close()
 
359
        finally:
 
360
            if local_file is not None:
 
361
                os.unlink(local_file)
 
362
 
 
363
        return False
 
364
 
 
365
    def _kernelFetchHelper(self, fetcher, guest, progresscb, kernelpath,
 
366
                           initrdpath):
 
367
        # Simple helper for fetching kernel + initrd and performing
 
368
        # cleanup if neccessary
 
369
        kernel = fetcher.acquireFile(kernelpath, progresscb)
 
370
        args = ''
 
371
 
 
372
        if not fetcher.location.startswith("/"):
 
373
            args += "method=" + fetcher.location
 
374
 
 
375
        if guest.extraargs:
 
376
            args += " " + guest.extraargs
 
377
 
 
378
        try:
 
379
            initrd = fetcher.acquireFile(initrdpath, progresscb)
 
380
            return kernel, initrd, args
 
381
        except:
 
382
            os.unlink(kernel)
 
383
 
 
384
 
 
385
class GenericDistro(Distro):
 
386
    """Generic distro store. Check well known paths for kernel locations
 
387
       as a last resort if we can't recognize any actual distro"""
 
388
 
 
389
    name = "Generic"
 
390
    os_type = "linux"
 
391
    uses_treeinfo = True
 
392
 
 
393
    _xen_paths = [ ("images/xen/vmlinuz",
 
394
                    "images/xen/initrd.img"),           # Fedora
 
395
                 ]
 
396
    _hvm_paths = [ ("images/pxeboot/vmlinuz",
 
397
                    "images/pxeboot/initrd.img"),       # Fedora
 
398
                 ]
 
399
    _iso_paths = [ "images/boot.iso",                   # RH/Fedora
 
400
                   "boot/boot.iso",                     # Suse
 
401
                   "current/images/netboot/mini.iso",   # Debian
 
402
                   "install/images/boot.iso",           # Mandriva
 
403
                 ]
 
404
 
 
405
    # Holds values to use when actually pulling down media
 
406
    _valid_kernel_path = None
 
407
    _valid_iso_path = None
 
408
 
 
409
    def isValidStore(self, fetcher, progresscb):
 
410
        if self._hasTreeinfo(fetcher, progresscb):
 
411
            # Use treeinfo to pull down media paths
 
412
            if self.type == "xen":
 
413
                typ = "xen"
 
414
            else:
 
415
                typ = self.treeinfo.get("general", "arch")
 
416
            kernelSection = "images-%s" % typ
 
417
            isoSection = "images-%s" % self.treeinfo.get("general", "arch")
 
418
 
 
419
            if self.treeinfo.has_section(kernelSection):
 
420
                self._valid_kernel_path = (self._getTreeinfoMedia("kernel"),
 
421
                                           self._getTreeinfoMedia("initrd"))
 
422
            if self.treeinfo.has_section(isoSection):
 
423
                self._valid_iso_path = self.treeinfo.get(isoSection, "boot.iso")
 
424
 
 
425
        if self.type == "xen":
 
426
            kern_list = self._xen_paths
 
427
        else:
 
428
            kern_list = self._hvm_paths
 
429
 
 
430
        # If validated media paths weren't found (no treeinfo), check against
 
431
        # list of media location paths.
 
432
        for kern, init in kern_list:
 
433
            if self._valid_kernel_path == None \
 
434
               and fetcher.hasFile(kern) and fetcher.hasFile(init):
 
435
                self._valid_kernel_path = (kern, init)
 
436
                break
 
437
        for iso in self._iso_paths:
 
438
            if self._valid_iso_path == None \
 
439
               and fetcher.hasFile(iso):
 
440
                self._valid_iso_path = iso
 
441
                break
 
442
 
 
443
        if self._valid_kernel_path or self._valid_iso_path:
 
444
            return True
 
445
        return False
 
446
 
 
447
    def acquireKernel(self, guest, fetcher, progresscb):
 
448
        if self._valid_kernel_path == None:
 
449
            raise ValueError(_("Could not find a kernel path for virt type "
 
450
                               "'%s'" % self.type))
 
451
 
 
452
        return self._kernelFetchHelper(fetcher, guest, progresscb,
 
453
                                       self._valid_kernel_path[0],
 
454
                                       self._valid_kernel_path[1])
 
455
 
 
456
    def acquireBootDisk(self, guest, fetcher, progresscb):
 
457
        if self._valid_iso_path == None:
 
458
            raise ValueError(_("Could not find a boot iso path for this tree."))
 
459
 
 
460
        return fetcher.acquireFile(self._valid_iso_path, progresscb)
 
461
 
 
462
 
 
463
# Base image store for any Red Hat related distros which have
 
464
# a common layout
 
465
class RedHatDistro(Distro):
 
466
 
 
467
    name = "Red Hat"
 
468
    os_type = "linux"
 
469
 
 
470
    uses_treeinfo = True
 
471
    _boot_iso_paths   = [ "images/boot.iso" ]
 
472
    _hvm_kernel_paths = [ ("images/pxeboot/vmlinuz",
 
473
                           "images/pxeboot/initrd.img") ]
 
474
    _xen_kernel_paths = [ ("images/xen/vmlinuz",
 
475
                           "images/xen/initrd.img") ]
 
476
 
 
477
    def isValidStore(self, fetcher, progresscb):
 
478
        raise NotImplementedError
 
479
 
 
480
 
 
481
# Fedora distro check
 
482
class FedoraDistro(RedHatDistro):
 
483
 
 
484
    name = "Fedora"
 
485
 
 
486
    def isValidStore(self, fetcher, progresscb):
 
487
        if self._hasTreeinfo(fetcher, progresscb):
 
488
            m = re.match(".*Fedora.*", self.treeinfo.get("general", "family"))
 
489
            ret = (m != None)
 
490
 
 
491
            if ret:
 
492
                ver = self.treeinfo.get("general", "version")
 
493
                if ver == "development":
 
494
                    self.os_variant = self._latestFedoraVariant()
 
495
                elif ver:
 
496
                    self.os_variant = "fedora" + (str(ver).split("-"))[0]
 
497
 
 
498
            return ret
 
499
        else:
 
500
            if fetcher.hasFile("Fedora"):
 
501
                logging.debug("Detected a Fedora distro")
 
502
                return True
 
503
            return False
 
504
 
 
505
    def _latestFedoraVariant(self):
 
506
        ret = None
 
507
        for var in osdict.sort_helper(osdict.OS_TYPES["linux"]["variants"]):
 
508
            if var.startswith("fedora"):
 
509
                # Last fedora* occurence should be the newest
 
510
                ret = var
 
511
        return ret
 
512
 
 
513
# Red Hat Enterprise Linux distro check
 
514
class RHELDistro(RedHatDistro):
 
515
 
 
516
    name = "Red Hat Enterprise Linux"
 
517
 
 
518
    def isValidStore(self, fetcher, progresscb):
 
519
        if self._hasTreeinfo(fetcher, progresscb):
 
520
            m = re.match(".*Red Hat Enterprise Linux.*",
 
521
                         self.treeinfo.get("general", "family"))
 
522
            ret = (m != None)
 
523
 
 
524
            if ret:
 
525
                self._variantFromVersion()
 
526
            return ret
 
527
        else:
 
528
            # fall back to old code
 
529
            if fetcher.hasFile("Server"):
 
530
                logging.debug("Detected a RHEL 5 Server distro")
 
531
                self.os_variant = "rhel5"
 
532
                return True
 
533
            if fetcher.hasFile("Client"):
 
534
                logging.debug("Detected a RHEL 5 Client distro")
 
535
                self.os_variant = "rhel5"
 
536
                return True
 
537
            if fetcher.hasFile("RedHat"):
 
538
                if fetcher.hasFile("dosutils"):
 
539
                    self.os_variant = "rhel3"
 
540
                else:
 
541
                    self.os_variant = "rhel4"
 
542
 
 
543
                logging.debug("Detected a %s distro" % self.os_variant)
 
544
                return True
 
545
            return False
 
546
 
 
547
    def _parseTreeinfoVersion(self, verstr):
 
548
        version = safeint(verstr[0])
 
549
        update = 0
 
550
 
 
551
        updinfo = verstr.split(".")
 
552
        if len(updinfo) > 1:
 
553
            update = safeint(updinfo[1])
 
554
 
 
555
        return version, update
 
556
 
 
557
    def _variantFromVersion(self):
 
558
        ver = self.treeinfo.get("general", "version")
 
559
        if not ver:
 
560
            return
 
561
 
 
562
        version, update = self._parseTreeinfoVersion(ver)
 
563
        self._setRHELVariant(version, update)
 
564
 
 
565
    def _setRHELVariant(self, version, update):
 
566
        if not _check_ostype_valid(self.os_type):
 
567
            return
 
568
 
 
569
        base = "rhel" + str(version)
 
570
        if update < 0:
 
571
            update = 0
 
572
 
 
573
        ret = None
 
574
        while update >= 0:
 
575
            tryvar = base + ".%s" % update
 
576
            if not _check_osvariant_valid(self.os_type, tryvar):
 
577
                update -= 1
 
578
                continue
 
579
 
 
580
            ret = tryvar
 
581
            break
 
582
 
 
583
        if not ret:
 
584
            # Try plain rhel5, rhel6, whatev
 
585
            if _check_osvariant_valid(self.os_type, base):
 
586
                ret = base
 
587
 
 
588
        if ret:
 
589
            self.os_variant = ret
 
590
 
 
591
 
 
592
# CentOS distro check
 
593
class CentOSDistro(RHELDistro):
 
594
 
 
595
    name = "CentOS"
 
596
 
 
597
    def isValidStore(self, fetcher, progresscb):
 
598
        if self._hasTreeinfo(fetcher, progresscb):
 
599
            m = re.match(".*CentOS.*", self.treeinfo.get("general", "family"))
 
600
            ret = (m != None)
 
601
 
 
602
            if ret:
 
603
                self._variantFromVersion()
 
604
            return ret
 
605
        else:
 
606
            # fall back to old code
 
607
            if fetcher.hasFile("CentOS"):
 
608
                logging.debug("Detected a CentOS distro")
 
609
                return True
 
610
            return False
 
611
 
 
612
# Scientific Linux distro check
 
613
class SLDistro(RHELDistro):
 
614
 
 
615
    name = "Scientific Linux"
 
616
 
 
617
    _boot_iso_paths = RHELDistro._boot_iso_paths + [ "images/SL/boot.iso" ]
 
618
    _hvm_kernel_paths = RHELDistro._hvm_kernel_paths + \
 
619
                        [ ("images/SL/pxeboot/vmlinuz",
 
620
                           "images/SL/pxeboot/initrd.img") ]
 
621
 
 
622
    def isValidStore(self, fetcher, progresscb):
 
623
        if self._hasTreeinfo(fetcher, progresscb):
 
624
            m = re.match(".*Scientific Linux.*",
 
625
                         self.treeinfo.get("general", "family"))
 
626
            ret = (m != None)
 
627
 
 
628
            if ret:
 
629
                self._variantFromVersion()
 
630
            return ret
 
631
        else:
 
632
            if fetcher.hasFile("SL"):
 
633
                logging.debug("Detected a Scientific Linux distro")
 
634
                return True
 
635
            return False
 
636
 
 
637
    def _parseTreeinfoVersion(self, verstr):
 
638
        """
 
639
        Overrides method in RHELDistro
 
640
        """
 
641
        version = safeint(verstr[0])
 
642
        update = 0
 
643
 
 
644
        if len(verstr) > 1:
 
645
            update = safeint(verstr[1])
 
646
        return version, update
 
647
 
 
648
 
 
649
# Suse  image store is harder - we fetch the kernel RPM and a helper
 
650
# RPM and then munge bits together to generate a initrd
 
651
class SuseDistro(Distro):
 
652
 
 
653
    name = "SUSE"
 
654
    os_type = "linux"
 
655
    _boot_iso_paths   = [ "boot/boot.iso" ]
 
656
 
 
657
    def __init__(self, uri, arch, vmtype=None, scratchdir=None):
 
658
        Distro.__init__(self, uri, arch, vmtype, scratchdir)
 
659
        if re.match(r'i[4-9]86', arch):
 
660
            self.arch = 'i386'
 
661
 
 
662
        oldkern = "linux"
 
663
        oldinit = "initrd"
 
664
        if arch == "x86_64":
 
665
            oldkern += "64"
 
666
            oldinit += "64"
 
667
 
 
668
        # Tested with Opensuse >= 10.2, 11, and sles 10
 
669
        self._hvm_kernel_paths = [ ("boot/%s/loader/linux" % self.arch,
 
670
                                    "boot/%s/loader/initrd" % self.arch) ]
 
671
        # Tested with Opensuse 10.0
 
672
        self._hvm_kernel_paths.append(("boot/loader/%s" % oldkern,
 
673
                                       "boot/loader/%s" % oldinit))
 
674
 
 
675
        # Matches Opensuse > 10.2 and sles 10
 
676
        self._xen_kernel_paths = [ ("boot/%s/vmlinuz-xen" % self.arch,
 
677
                                    "boot/%s/initrd-xen" % self.arch) ]
 
678
 
 
679
    def isValidStore(self, fetcher, progresscb):
 
680
        # Suse distros always have a 'directory.yast' file in the top
 
681
        # level of install tree, which we use as the magic check
 
682
        if fetcher.hasFile("directory.yast"):
 
683
            logging.debug("Detected a Suse distro.")
 
684
            return True
 
685
        return False
 
686
 
 
687
    def acquireKernel(self, guest, fetcher, progresscb):
 
688
        # If installing a fullvirt guest
 
689
        if self.type is None or self.type == "hvm" or \
 
690
           fetcher.hasFile("boot/%s/vmlinuz-xen" % self.arch):
 
691
            return Distro.acquireKernel(self, guest, fetcher, progresscb)
 
692
 
 
693
        # For Opensuse <= 10.2, we need to perform some heinous stuff
 
694
        logging.debug("Trying Opensuse 10 PV rpm hacking")
 
695
        return self._findXenRPMS(fetcher, progresscb)
 
696
 
 
697
 
 
698
    def _findXenRPMS(self, fetcher, progresscb):
 
699
        kernelrpm = None
 
700
        installinitrdrpm = None
 
701
        filelist = None
 
702
        try:
 
703
            # There is no predictable filename for kernel/install-initrd RPMs
 
704
            # so we have to grok the filelist and find them
 
705
            filelist = fetcher.acquireFile("ls-lR.gz", progresscb)
 
706
            (kernelrpmname, initrdrpmname) = self._extractRPMNames(filelist)
 
707
 
 
708
            # Now fetch the two RPMs we want
 
709
            kernelrpm = fetcher.acquireFile(kernelrpmname, progresscb)
 
710
            installinitrdrpm = fetcher.acquireFile(initrdrpmname, progresscb)
 
711
 
 
712
            # Process the RPMs to extract the kernel & generate an initrd
 
713
            return self._buildKernelInitrd(fetcher, kernelrpm, installinitrdrpm, progresscb)
 
714
        finally:
 
715
            if filelist is not None:
 
716
                os.unlink(filelist)
 
717
            if kernelrpm is not None:
 
718
                os.unlink(kernelrpm)
 
719
            if installinitrdrpm is not None:
 
720
                os.unlink(installinitrdrpm)
 
721
 
 
722
    # We need to parse the ls-lR.gz file, looking for the kernel &
 
723
    # install-initrd RPM entries - capturing the directory they are
 
724
    # in and the version'd filename.
 
725
    def _extractRPMNames(self, filelist):
 
726
        filelistData = gzip.GzipFile(filelist, mode="r")
 
727
        try:
 
728
            arches = [self.arch]
 
729
            # On i686 arch, we also look under i585 and i386 dirs
 
730
            # in case the RPM is built for a lesser arch. We also
 
731
            # need the PAE variant (for Fedora dom0 at least)
 
732
            #
 
733
            # XXX shouldn't hard code that dom0 is PAE
 
734
            if self.arch == "i386":
 
735
                arches.append("i586")
 
736
                arches.append("i686")
 
737
                kernelname = "kernel-xenpae"
 
738
            else:
 
739
                kernelname = "kernel-xen"
 
740
 
 
741
            installinitrdrpm = None
 
742
            kernelrpm = None
 
743
            dirname = None
 
744
            while 1:
 
745
                data = filelistData.readline()
 
746
                if not data:
 
747
                    break
 
748
                if dirname is None:
 
749
                    for arch in arches:
 
750
                        wantdir = "/suse/" + arch
 
751
                        if data == "." + wantdir + ":\n":
 
752
                            dirname = wantdir
 
753
                            break
 
754
                else:
 
755
                    if data == "\n":
 
756
                        dirname = None
 
757
                    else:
 
758
                        if data[:5] != "total":
 
759
                            filename = re.split("\s+", data)[8]
 
760
 
 
761
                            if filename[:14] == "install-initrd":
 
762
                                installinitrdrpm = dirname + "/" + filename
 
763
                            elif filename[:len(kernelname)] == kernelname:
 
764
                                kernelrpm = dirname + "/" + filename
 
765
 
 
766
            if kernelrpm is None:
 
767
                raise Exception(_("Unable to determine kernel RPM path"))
 
768
            if installinitrdrpm is None:
 
769
                raise Exception(_("Unable to determine install-initrd RPM path"))
 
770
            return (kernelrpm, installinitrdrpm)
 
771
        finally:
 
772
            filelistData.close()
 
773
 
 
774
    # We have a kernel RPM and a install-initrd RPM with a generic initrd in it
 
775
    # Now we have to merge the two together to build an initrd capable of
 
776
    # booting the installer.
 
777
    #
 
778
    # Yes, this is crazy ass stuff :-)
 
779
    def _buildKernelInitrd(self, fetcher, kernelrpm, installinitrdrpm, progresscb):
 
780
        progresscb.start(text=_("Building initrd"), size=11)
 
781
        progresscb.update(1)
 
782
        cpiodir = tempfile.mkdtemp(prefix="virtinstcpio.", dir=self.scratchdir)
 
783
        try:
 
784
            # Extract the kernel RPM contents
 
785
            os.mkdir(cpiodir + "/kernel")
 
786
            cmd = "cd " + cpiodir + "/kernel && (rpm2cpio " + kernelrpm + " | cpio --quiet -idm)"
 
787
            logging.debug("Running " + cmd)
 
788
            os.system(cmd)
 
789
            progresscb.update(2)
 
790
 
 
791
            # Determine the raw kernel version
 
792
            kernelinfo = None
 
793
            for f in os.listdir(cpiodir + "/kernel/boot"):
 
794
                if f.startswith("System.map-"):
 
795
                    kernelinfo = re.split("-", f)
 
796
            kernel_override = kernelinfo[1] + "-override-" + kernelinfo[3]
 
797
            kernel_version = kernelinfo[1] + "-" + kernelinfo[2] + "-" + kernelinfo[3]
 
798
            logging.debug("Got kernel version " + str(kernelinfo))
 
799
 
 
800
            # Build a list of all .ko files
 
801
            modpaths = {}
 
802
            for root, dummy, files in os.walk(cpiodir + "/kernel/lib/modules", topdown=False):
 
803
                for name in files:
 
804
                    if name.endswith(".ko"):
 
805
                        modpaths[name] = os.path.join(root, name)
 
806
            progresscb.update(3)
 
807
 
 
808
            # Extract the install-initrd RPM contents
 
809
            os.mkdir(cpiodir + "/installinitrd")
 
810
            cmd = "cd " + cpiodir + "/installinitrd && (rpm2cpio " + installinitrdrpm + " | cpio --quiet -idm)"
 
811
            logging.debug("Running " + cmd)
 
812
            os.system(cmd)
 
813
            progresscb.update(4)
 
814
 
 
815
            # Read in list of mods required for initrd
 
816
            modnames = []
 
817
            fn = open(cpiodir + "/installinitrd/usr/lib/install-initrd/" + kernelinfo[3] + "/module.list", "r")
 
818
            try:
 
819
                while 1:
 
820
                    line = fn.readline()
 
821
                    if not line:
 
822
                        break
 
823
                    line = line[:len(line) - 1]
 
824
                    modnames.append(line)
 
825
            finally:
 
826
                fn.close()
 
827
            progresscb.update(5)
 
828
 
 
829
            # Uncompress the basic initrd
 
830
            cmd = "gunzip -c " + cpiodir + "/installinitrd/usr/lib/install-initrd/initrd-base.gz > " + cpiodir + "/initrd.img"
 
831
            logging.debug("Running " + cmd)
 
832
            os.system(cmd)
 
833
            progresscb.update(6)
 
834
 
 
835
            # Create temp tree to hold stuff we're adding to initrd
 
836
            moddir = cpiodir + "/initrd/lib/modules/" + kernel_override + "/initrd/"
 
837
            moddepdir = cpiodir + "/initrd/lib/modules/" + kernel_version
 
838
            os.makedirs(moddir)
 
839
            os.makedirs(moddepdir)
 
840
            os.symlink("../" + kernel_override, moddepdir + "/updates")
 
841
            os.symlink("lib/modules/" + kernel_override + "/initrd", cpiodir + "/initrd/modules")
 
842
            cmd = "cp " + cpiodir + "/installinitrd/usr/lib/install-initrd/" + kernelinfo[3] + "/module.config" + " " + moddir
 
843
            logging.debug("Running " + cmd)
 
844
            os.system(cmd)
 
845
            progresscb.update(7)
 
846
 
 
847
            # Copy modules we need into initrd staging dir
 
848
            for modname in modnames:
 
849
                if modname in modpaths:
 
850
                    src = modpaths[modname]
 
851
                    dst = moddir + "/" + modname
 
852
                    os.system("cp " + src + " " + dst)
 
853
            progresscb.update(8)
 
854
 
 
855
            # Run depmod across the staging area
 
856
            cmd = "depmod -a -b " + cpiodir + "/initrd -F " + cpiodir + "/kernel/boot/System.map-" + kernel_version + " " + kernel_version
 
857
            logging.debug("Running " + cmd)
 
858
            os.system(cmd)
 
859
            progresscb.update(9)
 
860
 
 
861
            # Add the extra modules to the basic initrd
 
862
            cmd = "cd " + cpiodir + "/initrd && ( find . | cpio --quiet -o -H newc -A -F " + cpiodir + "/initrd.img)"
 
863
            logging.debug("Running " + cmd)
 
864
            os.system(cmd)
 
865
            progresscb.update(10)
 
866
 
 
867
            # Compress the final initrd
 
868
            cmd = "gzip -f9N " + cpiodir + "/initrd.img"
 
869
            logging.debug("Running " + cmd)
 
870
            os.system(cmd)
 
871
            progresscb.end(11)
 
872
 
 
873
            # Save initrd & kernel to temp files for booting...
 
874
            initrdname = fetcher.saveTemp(open(cpiodir + "/initrd.img.gz", "r"), "initrd.img")
 
875
            logging.debug("Saved " + initrdname)
 
876
            try:
 
877
                kernelname = fetcher.saveTemp(open(cpiodir + "/kernel/boot/vmlinuz-" + kernel_version, "r"), "vmlinuz")
 
878
                logging.debug("Saved " + kernelname)
 
879
                return (kernelname, initrdname, "install=" + fetcher.location)
 
880
            except:
 
881
                os.unlink(initrdname)
 
882
        finally:
 
883
            #pass
 
884
            os.system("rm -rf " + cpiodir)
 
885
 
 
886
 
 
887
class DebianDistro(Distro):
 
888
    # ex. http://ftp.egr.msu.edu/debian/dists/sarge/main/installer-i386/
 
889
    # daily builds: http://people.debian.org/~joeyh/d-i/
 
890
 
 
891
    name = "Debian"
 
892
    os_type = "linux"
 
893
 
 
894
    def __init__(self, uri, arch, vmtype=None, scratchdir=None):
 
895
        Distro.__init__(self, uri, arch, vmtype, scratchdir)
 
896
        if uri.count("installer-i386"):
 
897
            self._treeArch = "i386"
 
898
        elif uri.count("installer-amd64"):
 
899
            self._treeArch = "amd64"
 
900
        else:
 
901
            self._treeArch = "i386"
 
902
 
 
903
        if re.match(r'i[4-9]86', arch):
 
904
            self.arch = 'i386'
 
905
 
 
906
        self._prefix = 'current/images'
 
907
        self._set_media_paths()
 
908
 
 
909
    def _set_media_paths(self):
 
910
        # Use self._prefix to set media paths
 
911
        self._boot_iso_paths   = [ "%s/netboot/mini.iso" % self._prefix ]
 
912
        hvmroot = "%s/netboot/debian-installer/%s/" % (self._prefix,
 
913
                                                       self._treeArch)
 
914
        xenroot = "%s/netboot/xen/" % self._prefix
 
915
        self._hvm_kernel_paths = [ (hvmroot + "linux", hvmroot + "initrd.gz") ]
 
916
        self._xen_kernel_paths = [ (xenroot + "vmlinuz",
 
917
                                    xenroot + "initrd.gz") ]
 
918
 
 
919
    def isValidStore(self, fetcher, progresscb):
 
920
 
 
921
        # For regular trees
 
922
        if fetcher.hasFile("%s/MANIFEST" % self._prefix):
 
923
            pass
 
924
        # For daily trees
 
925
        elif fetcher.hasFile("images/daily/MANIFEST"):
 
926
            self._prefix = "images/daily"
 
927
            self._set_media_paths()
 
928
        else:
 
929
            logging.debug("Doesn't look like a Debian distro.")
 
930
            return False
 
931
 
 
932
        filename = "%s/MANIFEST" % self._prefix
 
933
 
 
934
        if self._fetchAndMatchRegex(fetcher, progresscb, filename,
 
935
                                    ".*debian-installer.*"):
 
936
            logging.debug("Detected a Debian distro")
 
937
            return True
 
938
 
 
939
        return False
 
940
 
 
941
 
 
942
class UbuntuDistro(DebianDistro):
 
943
 
 
944
    name = "Ubuntu"
 
945
 
 
946
    def _set_media_paths(self):
 
947
        DebianDistro._set_media_paths(self)
 
948
        root = "%s/netboot/ubuntu-installer/%s/" % (self._prefix,
 
949
                                                    self._treeArch)
 
950
        self._hvm_kernel_paths = [ (root + "linux", root + "initrd.gz") ]
 
951
        self._xen_kernel_paths = []
 
952
 
 
953
    def isValidStore(self, fetcher, progresscb):
 
954
        # Don't support any paravirt installs
 
955
        if self.type is not None and self.type != "hvm":
 
956
            return False
 
957
 
 
958
        # For regular trees
 
959
        if not fetcher.hasFile("%s/MANIFEST" % self._prefix):
 
960
            return False
 
961
 
 
962
        if self._fetchAndMatchRegex(fetcher, progresscb,
 
963
                                    "%s/MANIFEST" % self._prefix,
 
964
                                    ".*ubuntu-installer.*"):
 
965
            logging.debug("Detected an Ubuntu distro")
 
966
            return True
 
967
 
 
968
        return False
 
969
 
 
970
 
 
971
class MandrivaDistro(Distro):
 
972
    # Ex. ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2007.1/x86_64/
 
973
 
 
974
    name = "Mandriva"
 
975
    os_type = "linux"
 
976
    _boot_iso_paths = [ "install/images/boot.iso" ]
 
977
    # Kernels for HVM: valid for releases 2007.1, 2008.*, 2009.0
 
978
    _hvm_kernel_paths = [ ("isolinux/alt0/vmlinuz", "isolinux/alt0/all.rdz")]
 
979
    _xen_kernel_paths = []
 
980
 
 
981
    def isValidStore(self, fetcher, progresscb):
 
982
        # Don't support any paravirt installs
 
983
        if self.type is not None and self.type != "hvm":
 
984
            return False
 
985
 
 
986
        # Mandriva websites / media appear to have a VERSION
 
987
        # file in top level which we can use as our 'magic'
 
988
        # check for validity
 
989
        if not fetcher.hasFile("VERSION"):
 
990
            return False
 
991
 
 
992
        if self._fetchAndMatchRegex(fetcher, progresscb, "VERSION",
 
993
                                    ".*Mandriva.*"):
 
994
            logging.debug("Detected a Mandriva distro")
 
995
            return True
 
996
 
 
997
        return False
 
998
 
 
999
# Solaris and OpenSolaris distros
 
1000
class SunDistro(Distro):
 
1001
 
 
1002
    name = "Solaris"
 
1003
    os_type = "solaris"
 
1004
 
 
1005
    def isValidStore(self, fetcher, progresscb):
 
1006
        """Determine if uri points to a tree of the store's distro"""
 
1007
        raise NotImplementedError
 
1008
 
 
1009
    def acquireBootDisk(self, guest, fetcher, progresscb):
 
1010
        return fetcher.acquireFile("images/solarisdvd.iso", progresscb)
 
1011
 
 
1012
    def process_extra_args(self, argstr):
 
1013
        """Collect additional arguments."""
 
1014
        if not argstr:
 
1015
            return (None, None, None, None)
 
1016
 
 
1017
        kopts = ''
 
1018
        kargs = ''
 
1019
        smfargs = ''
 
1020
        Bargs = ''
 
1021
 
 
1022
        args = argstr.split()
 
1023
        i = 0
 
1024
        while i < len(args):
 
1025
            exarg = args[i]
 
1026
            if exarg == '-B':
 
1027
                i += 1
 
1028
                if i == len(args):
 
1029
                    continue
 
1030
 
 
1031
                if not Bargs:
 
1032
                    Bargs = args[i]
 
1033
                else:
 
1034
                    Bargs = ','.join([Bargs, args[i]])
 
1035
 
 
1036
            elif exarg == '-m':
 
1037
                i += 1
 
1038
                if i == len(args):
 
1039
                    continue
 
1040
                smfargs = args[i]
 
1041
            elif exarg.startswith('-'):
 
1042
                if kopts is None:
 
1043
                    kopts = exarg[1:]
 
1044
                else:
 
1045
                    kopts = kopts + exarg[1:]
 
1046
            else:
 
1047
                if kargs is None:
 
1048
                    kargs = exarg
 
1049
                else:
 
1050
                    kargs = kargs + ' ' + exarg
 
1051
            i += 1
 
1052
 
 
1053
        return kopts, kargs, smfargs, Bargs
 
1054
 
 
1055
class SolarisDistro(SunDistro):
 
1056
    kernelpath = 'boot/platform/i86xpv/kernel/unix'
 
1057
    initrdpath = 'boot/x86.miniroot'
 
1058
 
 
1059
    def isValidStore(self, fetcher, progresscb):
 
1060
        if fetcher.hasFile(self.kernelpath):
 
1061
            logging.debug('Detected Solaris')
 
1062
            return True
 
1063
        return False
 
1064
 
 
1065
    def install_args(self, guest):
 
1066
        """Construct kernel cmdline args for the installer, consisting of:
 
1067
           the pathname of the kernel (32/64) to load, kernel options
 
1068
           and args, and '-B' boot properties."""
 
1069
 
 
1070
        # XXX: ignoring smfargs for the time being
 
1071
        (kopts, kargs, ignore_smfargs, kbargs) = \
 
1072
            self.process_extra_args(guest.extraargs)
 
1073
 
 
1074
        args = [ '' ]
 
1075
        if kopts:
 
1076
            args += [ '-%s' % kopts ]
 
1077
        if kbargs:
 
1078
            args += [ '-B', kbargs ]
 
1079
 
 
1080
        netmask = ''
 
1081
        # Yuck. Non-default netmasks require this option to be passed.
 
1082
        # It's distinctly not-trivial to work out the netmask to be used
 
1083
        # automatically.
 
1084
        if kargs:
 
1085
            for karg in kargs.split():
 
1086
                if karg.startswith('subnet-mask'):
 
1087
                    netmask = karg.split('=')[1]
 
1088
                else:
 
1089
                    args += [ kargs ]
 
1090
 
 
1091
        iargs = ''
 
1092
        if not guest.graphics['enabled']:
 
1093
            iargs += 'nowin '
 
1094
 
 
1095
        if guest.location.startswith('nfs:'):
 
1096
            try:
 
1097
                guestIP = socket.gethostbyaddr(guest.name)[2][0]
 
1098
            except:
 
1099
                iargs += ' dhcp'
 
1100
            else:
 
1101
                iserver = guest.location.split(':')[1]
 
1102
                ipath = guest.location.split(':')[2]
 
1103
                iserverIP = socket.gethostbyaddr(iserver)[2][0]
 
1104
                iargs += ' -B install_media=' + iserverIP + ':' + ipath
 
1105
                iargs += ',host-ip=' + guestIP
 
1106
                if netmask:
 
1107
                    iargs += ',subnet-mask=%s' % netmask
 
1108
                droute = _util.default_route(guest.nics[0].bridge)
 
1109
                if droute:
 
1110
                    iargs += ',router-ip=' + droute
 
1111
                if guest.nics[0].macaddr:
 
1112
                    en = guest.nics[0].macaddr.split(':')
 
1113
                    for i in range(len(en)):
 
1114
                        # remove leading '0' from mac address element
 
1115
                        if len(en[i]) > 1 and en[i][0] == '0':
 
1116
                            en[i] = en[i][1]
 
1117
                    boot_mac = ':'.join(en)
 
1118
                    iargs += ',boot-mac=' + boot_mac
 
1119
        else:
 
1120
            iargs += '-B install_media=cdrom'
 
1121
 
 
1122
        args += [ '-', iargs ]
 
1123
        return ' '.join(args)
 
1124
 
 
1125
    def acquireKernel(self, guest, fetcher, progresscb):
 
1126
 
 
1127
        try:
 
1128
            kernel = fetcher.acquireFile(self.kernelpath, progresscb)
 
1129
        except:
 
1130
            raise RuntimeError("Solaris PV kernel not found at %s" %
 
1131
                self.kernelpath)
 
1132
 
 
1133
        # strip boot from the kernel path
 
1134
        kpath = self.kernelpath.split('/')[1:]
 
1135
        args = "/" + "/".join(kpath) + self.install_args(guest)
 
1136
 
 
1137
        try:
 
1138
            initrd = fetcher.acquireFile(self.initrdpath, progresscb)
 
1139
            return (kernel, initrd, args)
 
1140
        except:
 
1141
            os.unlink(kernel)
 
1142
            raise RuntimeError(_("Solaris miniroot not found at %s") %
 
1143
                self.initrdpath)
 
1144
 
 
1145
class OpenSolarisDistro(SunDistro):
 
1146
 
 
1147
    os_variant = "opensolaris"
 
1148
 
 
1149
    kernelpath = "platform/i86xpv/kernel/unix"
 
1150
    initrdpaths = [ "platform/i86pc/boot_archive", "boot/x86.microroot" ]
 
1151
 
 
1152
    def isValidStore(self, fetcher, progresscb):
 
1153
        if fetcher.hasFile(self.kernelpath):
 
1154
            logging.debug("Detected OpenSolaris")
 
1155
            return True
 
1156
        return False
 
1157
 
 
1158
    def install_args(self, guest):
 
1159
        """Construct kernel cmdline args for the installer, consisting of:
 
1160
           the pathname of the kernel (32/64) to load, kernel options
 
1161
           and args, and '-B' boot properties."""
 
1162
 
 
1163
        # XXX: ignoring smfargs and kargs for the time being
 
1164
        (kopts, ignore_kargs, ignore_smfargs, kbargs) = \
 
1165
            self.process_extra_args(guest.extraargs)
 
1166
 
 
1167
        args = ''
 
1168
        if kopts:
 
1169
            args += ' -' + kopts
 
1170
        if kbargs:
 
1171
            args += ' -B ' + kbargs
 
1172
 
 
1173
        return args
 
1174
 
 
1175
    def acquireKernel(self, guest, fetcher, progresscb):
 
1176
 
 
1177
        try:
 
1178
            kernel = fetcher.acquireFile(self.kernelpath, progresscb)
 
1179
        except:
 
1180
            raise RuntimeError(_("OpenSolaris PV kernel not found at %s") %
 
1181
                self.kernelpath)
 
1182
 
 
1183
        args = "/" + self.kernelpath + self.install_args(guest)
 
1184
 
 
1185
        try:
 
1186
            initrd = fetcher.acquireFile(self.initrdpaths[0], progresscb)
 
1187
            return (kernel, initrd, args)
 
1188
        except Exception, e:
 
1189
            try:
 
1190
                initrd = fetcher.acquireFile(self.initrdpaths[1], progresscb)
 
1191
                return (kernel, initrd, args)
 
1192
            except:
 
1193
                os.unlink(kernel)
 
1194
                raise Exception("No OpenSolaris boot archive found: %s\n" % e)
 
1195
 
 
1196
 
 
1197
# NetWare 6 PV
 
1198
class NetWareDistro(Distro):
 
1199
    name = "NetWare"
 
1200
    os_type = "other"
 
1201
    os_variant = "netware6"
 
1202
 
 
1203
    loaderpath = "STARTUP/XNLOADER.SYS"
 
1204
 
 
1205
    def isValidStore(self, fetcher, progresscb):
 
1206
        if fetcher.hasFile(self.loaderpath):
 
1207
            logging.debug("Detected NetWare")
 
1208
            return True
 
1209
        return False
 
1210
 
 
1211
    def acquireKernel(self, guest, fetcher, progresscb):
 
1212
        loader = fetcher.acquireFile(self.loaderpath, progresscb)
 
1213
        return (loader, "", "")