--- xen/xm/create.py.orig 2005-12-07 21:23:58.000000000 +0100 +++ xen/xm/create.py 2006-01-16 21:20:00.000000000 +0100 @@ -552,13 +552,11 @@ def configure_vmx(config_image, vals): def run_bootloader(vals): if not os.access(vals.bootloader, os.X_OK): err("Bootloader isn't executable") - if len(vals.disk) < 1: + if not vals.disk: err("No disks configured and boot loader requested") - (uname, dev, mode, backend) = vals.disk[0] - file = blkif.blkdev_uname_to_file(uname) - return bootloader(vals.bootloader, file, not vals.console_autoconnect, - vals.vcpus, vals.bootentry) + return bootloader(vals.bootloader, vals.disk, not vals.console_autoconnect, + vals.vcpus, vals.bootentry, vals.root) def make_config(vals): """Create the domain configuration. @@ -572,7 +570,8 @@ def make_config(vals): if v: config.append([n, v]) - map(add_conf, ['name', 'memory', 'ssidref', 'maxmem', 'restart', + map(add_conf, ['name', 'memory', 'ssidref', 'maxmem', + 'root', 'bootloader', 'bootentry', 'restart', 'on_poweroff', 'on_reboot', 'on_crash']) if vals.cpu is not None: @@ -587,9 +586,10 @@ def make_config(vals): config.append(['backend', ['netif']]) if vals.tpmif: config.append(['backend', ['tpmif']]) + if vals.root: + config.append(['root', vals.root]) if vals.bootloader: - config.append(['bootloader', vals.bootloader]) config_image = run_bootloader(vals) else: config_image = configure_image(vals) @@ -742,7 +742,7 @@ def spawn_vnc(display): vncpid = os.spawnvp(os.P_NOWAIT, "vncviewer", vncargs) return VNC_BASE_PORT + display - + def preprocess_vnc(vals): """If vnc was specified, spawn a vncviewer in listen mode and pass its address to the domain on the kernel command line. @@ -758,7 +758,7 @@ def preprocess_vnc(vals): vnc_host = get_host_addr() vnc = 'VNC_VIEWER=%s:%d' % (vnc_host, vnc_port) vals.extra = vnc + ' ' + vals.extra - + def preprocess(vals): if not vals.kernel and not vals.bootloader: err("No kernel specified") @@ -770,7 +770,7 @@ def preprocess(vals): preprocess_nfs(vals) preprocess_vnc(vals) preprocess_vtpm(vals) - + def make_domain(opts, config): """Create, build and start a domain. --- xen/xend/XendDomainInfo.py.orig 2005-12-14 21:03:29.000000000 +0100 +++ xen/xend/XendDomainInfo.py 2006-01-16 22:20:15.000000000 +0100 @@ -31,7 +31,6 @@ import threading import xen.lowlevel.xc from xen.util import asserts -from xen.util.blkif import blkdev_uname_to_file import balloon import image @@ -126,6 +125,8 @@ ROUNDTRIPPING_CONFIG_ENTRIES = [ ('memory', int), ('maxmem', int), ('bootloader', str), + ('bootentry', str), + ('root', str), ] ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_PARAMS @@ -552,6 +553,8 @@ class XendDomainInfo: defaultInfo('memory', lambda: 0) defaultInfo('maxmem', lambda: 0) defaultInfo('bootloader', lambda: None) + defaultInfo('bootentry', lambda: None) + defaultInfo('root', lambda: None) defaultInfo('backend', lambda: []) defaultInfo('device', lambda: []) defaultInfo('image', lambda: None) @@ -1489,17 +1492,29 @@ class XendDomainInfo: if not self.info['bootloader']: return # if we're restarting with a bootloader, we need to run it - # FIXME: this assumes the disk is the first device and - # that we're booting from the first disk blcfg = None config = self.sxpr() - # FIXME: this assumes that we want to use the first disk - dev = sxp.child_value(config, "device") - if dev: - disk = sxp.child_value(dev, "uname") - fn = blkdev_uname_to_file(disk) - blcfg = bootloader(self.info['bootloader'], fn, 1, - self.info['vcpus']) + devices = sxp.children(config, "device") + # bootloader expects disks in config file format: + # [(uname, dev, mode, backend), (...), ...] + # FIXME: Ugly, we use knowledge on the internal sxp storage fmt + # We should use better suited sxp. functions instead. + vbds = [] + for dev in devices: + if dev[1][0] != 'vbd': + continue + vbds.append([sxp.child_value(dev[1], "uname"), + sxp.child_value(dev[1], "dev"), + sxp.child_value(dev[1], "mode"), + sxp.child_value(dev[1], "backend")]) + log.debug("bootloader(%s, %s, 1, %s, %s, %s)" % \ + (self.info['bootloader'], str(vbds), + self.info['vcpus'], self.info['bootentry'], + self.info['root'])) + if vbds: + blcfg = bootloader(self.info['bootloader'], vbds, 1, + self.info['vcpus'], self.info['bootentry'], + self.info['root']) if blcfg is None: msg = "Had a bootloader specified, but can't find disk" log.error(msg) --- xen/xend/XendBootloader.py.orig 2005-12-07 21:23:58.000000000 +0100 +++ xen/xend/XendBootloader.py 2006-01-16 22:25:54.000000000 +0100 @@ -12,32 +12,39 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -import os, select, errno +import os, select, errno, random import sxp from XendLogging import log from XendError import VmError +from xen.util.blkif import blkdev_uname_to_file -BL_FIFO = "/var/lib/xen/xenbl" - -def bootloader(blexec, disk, quiet = 0, vcpus = None, entry = None): +def bootloader(blexec, disks, quiet = 0, vcpus = None, entry = None, root = None): """Run the boot loader executable on the given disk and return a config image. @param blexec Binary to use as the boot loader - @param disk Disk to run the boot loader on. - @param quiet Run in non-interactive mode, just booting the default. - @param vcpus Number of vcpus for the domain. - @param entry Default entry to boot.""" + @param disks Disks for the domain, in [uname, dev, mode, backend] tuples. + @param quiet Run in non-interactive mode, just booting the default. + @param vcpus Number of vcpus for the domain. + @param entry Default entry to boot. + @param root Device with root FS (root= param).""" if not os.access(blexec, os.X_OK): msg = "Bootloader isn't executable" log.error(msg) raise VmError(msg) - if not os.access(disk, os.R_OK): - msg = "Disk isn't accessible" + + firstdisk = disks[0][0] + #firstdisk = sxp.child_value(disks, "uname") + firstdisk = blkdev_uname_to_file(firstdisk) + + if not os.access(firstdisk, os.R_OK): + msg = "First disk isn't accessible" log.error(msg) raise VmError(msg) + BL_FIFO = "/var/lib/xen/xenbl.%5i" % + random.randint(0, 99999) + os.mkfifo(BL_FIFO, 0600) child = os.fork() @@ -45,10 +52,14 @@ def bootloader(blexec, disk, quiet = 0, args = [ blexec ] if quiet: args.append("-q") - args.append("--output=%s" %(BL_FIFO,)) + args.append("--output=%s" % BL_FIFO) if entry is not None: - args.append("--entry=%s" %(entry,)) - args.append(disk) + args.append("--entry=%s" % entry) + args.append("--disks=\"%s\"" % str(disks)) + if root is not None: + root = root[:root.find(" ")] + args.append("--root=%s" % root) + args.append(firstdisk) try: os.execvp(args[0], args) @@ -65,6 +76,7 @@ def bootloader(blexec, disk, quiet = 0, continue break ret = "" + # TODO: Add timeout, cleanup and raise VmError if it occurs while 1: select.select([r], [], []) s = os.read(r, 1024)