# HG changeset patch # User john.levon@xxxxxxx # Date 1228854334 28800 # Node ID 5f97d4577a145a71c0b0ac1d50b0721caa5317ab # Parent 7c692c15dc049d8e62c47ec897ab08979760e032 Add support for Solaris PV Solaris PV comes in two flavours: Nevada and OpenSolaris. In order to correctly build network installs for Nevada, we need to pass down guest options into OSDistro. Signed-off-by: John Levon <john.levon@xxxxxxx> diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py --- a/virtinst/DistroManager.py +++ b/virtinst/DistroManager.py @@ -41,6 +41,8 @@ from OSDistro import DebianDistro from OSDistro import DebianDistro from OSDistro import UbuntuDistro from OSDistro import MandrivaDistro +from OSDistro import SolarisDistro +from OSDistro import OpenSolarisDistro from OSDistro import GenericDistro def _fetcherForURI(uri, scratchdir=None): @@ -87,6 +89,11 @@ def _storeForDistro(fetcher, baseuri, ty stores.append(UbuntuDistro(baseuri, typ, scratchdir, arch)) if distro == "mandriva" or distro is None: stores.append(MandrivaDistro(baseuri, typ, scratchdir, arch)) + # XXX: this is really "nevada" + if distro == "solaris" or distro is None: + stores.append(SolarisDistro(baseuri, type, scratchdir)) + if distro == "solaris" or distro is None: + stores.append(OpenSolarisDistro(baseuri, type, scratchdir)) stores.append(GenericDistro(baseuri, typ, scratchdir, arch)) @@ -100,7 +107,7 @@ def _storeForDistro(fetcher, baseuri, ty # Method to fetch a kernel & initrd pair for a particular distro / HV type -def acquireKernel(baseuri, progresscb, scratchdir="/var/tmp", type=None, +def acquireKernel(guest, baseuri, progresscb, scratchdir="/var/tmp", type=None, distro=None, arch=None): fetcher = _fetcherForURI(baseuri, scratchdir) @@ -113,7 +120,8 @@ def acquireKernel(baseuri, progresscb, s store = _storeForDistro(fetcher=fetcher, baseuri=baseuri, typ=type, progresscb=progresscb, distro=distro, scratchdir=scratchdir, arch=arch) - return store.acquireKernel(fetcher, progresscb) + + return store.acquireKernel(guest, fetcher, progresscb), store.os_type finally: fetcher.cleanupLocation() @@ -239,26 +247,30 @@ class DistroInstaller(Guest.Installer): arch = os.uname()[4] if hasattr(guest, "arch"): arch = guest.arch - (kernelfn, initrdfn, args) = acquireKernel(self.location, - meter, - scratchdir = self.scratchdir, - type = self.os_type, - distro = distro, - arch=arch) + + (kernelfn, initrdfn, args), os_type = acquireKernel(guest, + self.location, meter, scratchdir=self.scratchdir, + type=self.os_type, distro=distro, arch=arch) + + guest.os_type = os_type self.install["kernel"] = kernelfn self.install["initrd"] = initrdfn - if not self.extraargs is None: - self.install["extraargs"] = self.extraargs + " " + args - else: - self.install["extraargs"] = args + self.install["extraargs"] = args self._tmpfiles.append(kernelfn) self._tmpfiles.append(initrdfn) # If they're installing off a local file/device, we map it - # through to a virtual harddisk - if self.location is not None and self.location.startswith("/") and not os.path.isdir(self.location): + # through to a virtual CD or disk + + if (self.location is not None and self.location.startswith("/") + and not os.path.isdir(self.location)): + device = Guest.VirtualDisk.DEVICE_DISK + if guest._lookup_osdict_key('pv_cdrom_install'): + device = Guest.VirtualDisk.DEVICE_CDROM + self._install_disk = VirtualDisk(self.location, + device=device, readOnly=True, transient=True) diff --git a/virtinst/OSDistro.py b/virtinst/OSDistro.py --- a/virtinst/OSDistro.py +++ b/virtinst/OSDistro.py @@ -25,8 +25,10 @@ import re import re import tempfile import platform +import socket import ConfigParser +from virtinst import _util from virtinst import _virtinst as _ def distroFromTreeinfo(fetcher, progresscb, uri, vmtype=None, @@ -83,7 +85,7 @@ class Distro: """Determine if uri points to a tree of the store's distro""" raise NotImplementedError - def acquireKernel(self, fetcher, progresscb): + def acquireKernel(self, guest, fetcher, progresscb): kernelpath = None initrdpath = None if self._hasTreeinfo(fetcher, progresscb): @@ -106,7 +108,7 @@ class Distro: "%(distro)s tree.") % \ { "distro": self.name, "type" : self.type }) - return self._kernelFetchHelper(fetcher, progresscb, kernelpath, + return self._kernelFetchHelper(fetcher, guest, progresscb, kernelpath, initrdpath) def acquireBootDisk(self, fetcher, progresscb): @@ -172,18 +174,21 @@ class Distro: return False - def _kernelFetchHelper(self, fetcher, progresscb, kernelpath, initrdpath): + def _kernelFetchHelper(self, fetcher, guest, progresscb, kernelpath, initrdpath): # Simple helper for fetching kernel + initrd and performing # cleanup if neccessary kernel = fetcher.acquireFile(kernelpath, progresscb) + args = '' + + if not fetcher.location.startswith("/"): + args += "method=" + fetcher.location + + if guest.extraargs: + args += guest.extraargs + try: initrd = fetcher.acquireFile(initrdpath, progresscb) - if fetcher.location.startswith("/"): - # Local host path, so can't pass a location to guest - #for install method - return (kernel, initrd, "") - else: - return (kernel, initrd, "method=" + fetcher.location) + return kernel, initrd, args except: os.unlink(kernel) @@ -193,6 +198,7 @@ class GenericDistro(Distro): as a last resort if we can't recognize any actual distro""" name = "Generic" + os_type = "linux" uses_treeinfo = True _xen_paths = [ ("images/xen/vmlinuz", @@ -249,12 +255,12 @@ class GenericDistro(Distro): return True return False - def acquireKernel(self, fetcher, progresscb): + def acquireKernel(self, guest, fetcher, progresscb): if self._valid_kernel_path == None: raise ValueError(_("Could not find a kernel path for virt type " "'%s'" % self.type)) - return self._kernelFetchHelper(fetcher, progresscb, + return self._kernelFetchHelper(fetcher, guest, progresscb, self._valid_kernel_path[0], self._valid_kernel_path[1]) @@ -270,6 +276,7 @@ class RedHatDistro(Distro): class RedHatDistro(Distro): name = "Red Hat" + os_type = "linux" uses_treeinfo = True _boot_iso_paths = [ "images/boot.iso" ] _hvm_kernel_paths = [ ("images/pxeboot/vmlinuz", @@ -285,6 +292,7 @@ class FedoraDistro(RedHatDistro): class FedoraDistro(RedHatDistro): name = "Fedora" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -300,6 +308,7 @@ class RHELDistro(RedHatDistro): class RHELDistro(RedHatDistro): name = "Red Hat Enterprise Linux" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -322,6 +331,7 @@ class CentOSDistro(RedHatDistro): class CentOSDistro(RedHatDistro): name = "CentOS" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -338,6 +348,7 @@ class SLDistro(RedHatDistro): class SLDistro(RedHatDistro): name = "Scientific Linux" + os_type = "linux" _boot_iso_paths = RedHatDistro._boot_iso_paths + [ "images/SL/boot.iso" ] _hvm_kernel_paths = RedHatDistro._hvm_kernel_paths + \ [ ("images/SL/pxeboot/vmlinuz", @@ -361,6 +372,7 @@ class SuseDistro(Distro): class SuseDistro(Distro): name = "SUSE" + os_type = "linux" _boot_iso_paths = [ "boot/boot.iso" ] _hvm_kernel_paths = [] _xen_kernel_paths = [] @@ -385,11 +397,11 @@ class SuseDistro(Distro): return True return False - def acquireKernel(self, fetcher, progresscb): + def acquireKernel(self, guest, fetcher, progresscb): # If installing a fullvirt guest if self.type is None or self.type == "hvm" or \ fetcher.hasFile("boot/%s/vmlinuz-xen" % self.arch): - return Distro.acquireKernel(self, fetcher, progresscb) + return Distro.acquireKernel(self, guest, fetcher, progresscb) # For Opensuse <= 10.2, we need to perform some heinous stuff logging.debug("Trying Opensuse 10 PV rpm hacking") @@ -590,6 +602,7 @@ class DebianDistro(Distro): # daily builds: http://people.debian.org/~joeyh/d-i/ name = "Debian" + os_type = "linux" def __init__(self, uri, vmtype=None, scratchdir=None, arch=None): Distro.__init__(self, uri, vmtype, scratchdir, arch) @@ -642,6 +655,7 @@ class UbuntuDistro(DebianDistro): class UbuntuDistro(DebianDistro): name = "Ubuntu" + os_type = "linux" def _set_media_paths(self): DebianDistro._set_media_paths(self) @@ -672,6 +686,7 @@ class MandrivaDistro(Distro): # Ex. ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2007.1/x86_64/ name = "Mandriva" + os_type = "linux" _boot_iso_paths = [ "install/images/boot.iso" ] # Kernels for HVM: valid for releases 2007.1, 2008.*, 2009.0 _hvm_kernel_paths = [ ("isolinux/alt0/vmlinuz", "isolinux/alt0/all.rdz")] @@ -692,3 +707,192 @@ class MandrivaDistro(Distro): return False +# Solaris and OpenSolaris distros +class SunDistro(Distro): + + name = "Solaris" + os_type = "solaris" + + def isValidStore(self, fetcher, progresscb): + """Determine if uri points to a tree of the store's distro""" + raise NotImplementedError + + def acquireBootDisk(self, fetcher, progresscb): + return fetcher.acquireFile("images/solarisdvd.iso", progresscb) + + def process_extra_args(self, argstr): + """Collect additional arguments.""" + if not argstr: + return (None, None, None, None) + + kopts = '' + kargs = '' + smfargs = '' + Bargs = '' + + args = argstr.split() + i = 0 + while i < len(args): + exarg = args[i] + if exarg == '-B': + i += 1 + if i == len(args): + continue + + if not Bargs: + Bargs = args[i] + else: + Bargs = ','.join([Bargs, args[i]]) + + elif exarg == '-m': + i += 1 + if i == len(args): + continue + smfargs = args[i] + elif exarg.startswith('-'): + if kopts is None: + kopts = exarg[1:] + else: + kopts = kopts + exarg[1:] + else: + if kargs is None: + kargs = exarg + else: + kargs = kargs + ' ' + exarg + i += 1 + + return kopts, kargs, smfargs, Bargs + +class SolarisDistro(SunDistro): + kernelpath = 'boot/platform/i86xpv/kernel/unix' + initrdpath = 'boot/x86.miniroot' + + def isValidStore(self, fetcher, progresscb): + if fetcher.hasFile(self.kernelpath): + logging.debug('Detected Solaris') + return True + return False + + def install_args(self, guest): + """Construct kernel cmdline args for the installer, consisting of: + the pathname of the kernel (32/64) to load, kernel options + and args, and '-B' boot properties.""" + + # XXX: ignoring smfargs for the time being + (kopts, kargs, smfargs, kbargs) = \ + self.process_extra_args(guest.extraargs) + + args = [ '' ] + if kopts: + args += [ '-%s' % kopts ] + if kbargs: + args += [ '-B', kbargs ] + + netmask = '' + # Yuck. Non-default netmasks require this option to be passed. + # It's distinctly not-trivial to work out the netmask to be used + # automatically. + for karg in kargs.split(): + if karg.startswith('subnet-mask'): + netmask = karg.split('=')[1] + else: + args += [ kargs ] + + iargs = '' + if not guest.graphics['enabled']: + iargs += 'nowin ' + + if guest.location.startswith('nfs:'): + try: + guestIP = socket.gethostbyaddr(guest.name)[2][0] + except: + iargs += ' dhcp' + else: + iserver = guest.location.split(':')[1] + ipath = guest.location.split(':')[2] + iserverIP = socket.gethostbyaddr(iserver)[2][0] + iargs += ' -B install_media=' + iserverIP + ':' + ipath + iargs += ',host-ip=' + guestIP + if netmask: + iargs += ',subnet-mask=%s' % netmask + droute = _util.default_route(guest.nics[0].bridge) + if droute: + iargs += ',router-ip=' + droute + if guest.nics[0].macaddr: + en = guest.nics[0].macaddr.split(':') + for i in range(len(en)): + # remove leading '0' from mac address element + if len(en[i]) > 1 and en[i][0] == '0': + en[i] = en[i][1] + boot_mac = ':'.join(en) + iargs += ',boot-mac=' + boot_mac + else: + iargs += '-B install_media=cdrom' + + args += [ '-', iargs ] + return ' '.join(args) + + def acquireKernel(self, guest, fetcher, progresscb): + + try: + kernel = fetcher.acquireFile(self.kernelpath, progresscb) + except: + raise RuntimeError("Solaris PV kernel not found at %s" % + self.kernelpath) + + # strip boot from the kernel path + kpath = self.kernelpath.split('/')[1:] + args = "/" + "/".join(kpath) + self.install_args(guest) + + try: + initrd = fetcher.acquireFile(self.initrdpath, progresscb) + return (kernel, initrd, args) + except: + os.unlink(kernel) + raise RuntimeError(_("Solaris miniroot not found at %s") % + self.initrdpath) + +class OpenSolarisDistro(SunDistro): + kernelpath = "platform/i86xpv/kernel/unix" + initrdpath = "boot/x86.microroot" + + def isValidStore(self, fetcher, progresscb): + if fetcher.hasFile(self.kernelpath): + logging.debug("Detected OpenSolaris") + return True + return False + + def install_args(self, guest): + """Construct kernel cmdline args for the installer, consisting of: + the pathname of the kernel (32/64) to load, kernel options + and args, and '-B' boot properties.""" + + # XXX: ignoring smfargs and kargs for the time being + (kopts, kargs, smfargs, kbargs) = \ + self.process_extra_args(guest.extraargs) + + args = '' + if kopts: + args += '-' + kopts + if kbargs: + args += ' -B ' + kbargs + + return args + + def acquireKernel(self, guest, fetcher, progresscb): + + try: + kernel = fetcher.acquireFile(self.kernelpath, progresscb) + except: + raise RuntimeError(_("OpenSolaris PV kernel not found at %s") % + self.kernelpath) + + args = "/" + self.kernelpath + self.install_args(guest) + + try: + initrd = fetcher.acquireFile(self.initrdpath, progresscb) + return (kernel, initrd, args) + except: + os.unlink(kernel) + raise RuntimeError(_("OpenSolaris microroot not found at %s") % + self.initrdpath) diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -555,6 +555,7 @@ class VirtualDisk(VirtualDevice): if self.target: disknode = self.target + if not disknode: raise ValueError(_("'disknode' or self.target must be set!")) diff --git a/virtinst/osdict.py b/virtinst/osdict.py --- a/virtinst/osdict.py +++ b/virtinst/osdict.py @@ -31,6 +31,7 @@ DEFAULTS = { \ "continue": False, "distro": None, "label": None, + "pv_cdrom_install": False, "devices" : { # "devname" : { "attribute" : [( ["applicable", "hv-type", list"], # "recommended value for hv-types" ),]}, @@ -146,6 +147,7 @@ OS_TYPES = {\ "solaris": { "label": "Solaris", "clock": "localtime", + "pv_cdrom_install": True, "variants": { "solaris9": { "label": "Sun Solaris 9", }, "solaris10": { "label": "Sun Solaris 10", _______________________________________________ et-mgmt-tools mailing list et-mgmt-tools@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/et-mgmt-tools