Index: xen-3.0-testing/tools/python/xen/xm/create.py =================================================================== --- xen-3.0-testing.orig/tools/python/xen/xm/create.py +++ xen-3.0-testing/tools/python/xen/xm/create.py @@ -575,13 +575,24 @@ def configure_hvm(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) + config_image = bootloader(vals.bootloader, vals.disk, + not vals.console_autoconnect, + vals.vcpus, vals.bootentry, vals.root) + # If bootloader does not fill in "args", we should use the + # values from the config file. + if sxp.child_value(config_image, "args") is None: + if vals.cmdline_ip: + cmdline_ip = strip('ip=', vals.cmdline_ip) + config_image.append(['ip', cmdline_ip]) + if vals.root: + cmdline_root = strip('root=', vals.root) + config_image.append(['root', cmdline_root]) + if vals.extra: + config_image.append(['args', vals.extra]) + return config_image def make_config(vals): """Create the domain configuration. @@ -595,7 +606,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', 'vcpus']) if vals.uuid is not None: @@ -612,9 +624,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) Index: xen-3.0-testing/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-3.0-testing.orig/tools/python/xen/xend/XendDomainInfo.py +++ xen-3.0-testing/tools/python/xen/xend/XendDomainInfo.py @@ -32,7 +32,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 @@ -127,6 +126,8 @@ ROUNDTRIPPING_CONFIG_ENTRIES = [ ('memory', int), ('maxmem', int), ('bootloader', str), + ('bootentry', str), + ('root', str), ] ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_PARAMS @@ -562,6 +563,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) @@ -1547,18 +1550,46 @@ class XendDomainInfo: # if we're restarting with a bootloader, we need to run it blcfg = None config = self.sxpr() + # save filled in values ip, root, args + image= sxp.child_value(config, "image") + ip = sxp.child_value(image, "ip") + root = sxp.child_value(image, "root") + args = sxp.child_value(image, "args") + log.debug("bootloader: saved (ip %s) (root %s) (args %s)" \ + % (ip, root, args)) + # Look for disks + vbds = [] # FIXME: this assumes that we want to use the first disk for dev in sxp.children(config, "device"): disk = sxp.child(dev, "vbd") if disk is None: continue - fn = blkdev_uname_to_file(sxp.child_value(disk, "uname")) - blcfg = bootloader(self.info['bootloader'], fn, 1, - self.info['vcpus']) + 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) raise VmError(msg) + # If bootloader has not filled in args, used saved values + # see xm/create.py: run_bootloader(). + if sxp.child_value(blcfg, "args") is None: + if ip: + blcfg.append(['ip', ip]) + if root: + blcfg.append(['root', root]) + if args: + blcfg.append(['args', args]) + self.info['image'] = sxp.to_string(blcfg) Index: xen-3.0-testing/tools/python/xen/xend/XendBootloader.py =================================================================== --- xen-3.0-testing.orig/tools/python/xen/xend/XendBootloader.py +++ xen-3.0-testing/tools/python/xen/xend/XendBootloader.py @@ -18,22 +18,28 @@ import sxp from XendLogging import log from XendError import VmError +from xen.util.blkif import blkdev_uname_to_file -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) @@ -51,7 +57,11 @@ def bootloader(blexec, disk, quiet = 0, args.append("--output=%s" %(fifo,)) if entry is not None: args.append("--entry=%s" %(entry,)) - args.append(disk) + 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) @@ -68,6 +78,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)