[et-mgmt-tools] [PATCH] Add support for Solaris PV
john.levon at sun.com
john.levon at sun.com
Tue Dec 9 20:44:38 UTC 2008
# HG changeset patch
# User john.levon at sun.com
# 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 at sun.com>
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",
More information about the et-mgmt-tools
mailing list