mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
bitkeeper revision 1.1327.2.13 (4270d6c35WpxFmhdkREjmSvk82s-Bg)
Merge Jeremy's pygrub bootloader patch. Signed-off-by: Jeremy Katz <katzj@redhat.com> Signed-off-by: Mike Wray <mike.wray@hp.com>
This commit is contained in:
1 parent
b4ac7763be
commit
51a9f171a5
16 files changed
+1190
-17
No files matched your search
@@ -0,0 +1,94 @@
|
||||
#
|
||||
# XendBootloader.py - Framework to run a boot loader for picking the kernel
|
||||
#
|
||||
# Copyright 2005 Red Hat, Inc.
|
||||
# Jeremy Katz <katzj@xxxxxxxxxx>
|
||||
#
|
||||
# This software may be freely redistributed under the terms of the GNU
|
||||
# general public license.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
import os, sys, select
|
||||
import sxp
|
||||
|
||||
from XendLogging import log
|
||||
from XendError import VmError
|
||||
|
||||
BL_FIFO = "/var/lib/xen/xenbl"
|
||||
|
||||
def bootloader(blexec, disk, quiet = 0, vcpus = None, entry = 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."""
|
||||
|
||||
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"
|
||||
log.error(msg)
|
||||
raise VmError(msg)
|
||||
|
||||
os.mkfifo(BL_FIFO, 0600)
|
||||
|
||||
child = os.fork()
|
||||
if (not child):
|
||||
args = [ blexec ]
|
||||
if quiet:
|
||||
args.append("-q")
|
||||
args.append("--output=%s" %(BL_FIFO,))
|
||||
if entry is not None:
|
||||
args.append("--entry=%s" %(entry,))
|
||||
args.append(disk)
|
||||
|
||||
try:
|
||||
os.execvp(args[0], args)
|
||||
except OSError, e:
|
||||
print e
|
||||
pass
|
||||
os._exit(1)
|
||||
|
||||
while 1:
|
||||
try:
|
||||
r = os.open(BL_FIFO, os.O_RDONLY)
|
||||
except OSError, e:
|
||||
if e.errno == 4:
|
||||
continue
|
||||
break
|
||||
ret = ""
|
||||
while 1:
|
||||
select.select([r], [], [])
|
||||
s = os.read(r, 1024)
|
||||
ret = ret + s
|
||||
if len(s) == 0:
|
||||
break
|
||||
|
||||
(pid, status) = os.waitpid(child, 0)
|
||||
os.close(r)
|
||||
os.unlink(BL_FIFO)
|
||||
|
||||
if len(ret) == 0:
|
||||
msg = "Boot loader didn't return any data!"
|
||||
log.error(msg)
|
||||
raise VmError, msg
|
||||
|
||||
pin = sxp.Parser()
|
||||
pin.input(ret)
|
||||
pin.input_eof()
|
||||
|
||||
config_image = pin.val
|
||||
if vcpus and sxp.child_value(config_image, "vcpus") is None:
|
||||
config_image.append(['vcpus', vcpus])
|
||||
|
||||
config = ['image', config_image]
|
||||
return config
|
||||
|
||||
@@ -16,11 +16,13 @@ import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
|
||||
import xen.util.ip
|
||||
from xen.util.ip import _readline, _readlines
|
||||
from xen.xend.server import channel, controller
|
||||
from xen.xend.server.blkif import blkdev_uname_to_file
|
||||
|
||||
from server.channel import channelFactory
|
||||
import server.SrvDaemon; xend = server.SrvDaemon.instance()
|
||||
from server import messages
|
||||
|
||||
from xen.xend.XendBootloader import bootloader
|
||||
import sxp
|
||||
from XendLogging import log
|
||||
from XendError import VmError
|
||||
@@ -294,6 +296,7 @@ class XendDomainInfo:
|
||||
self.image_handler = None
|
||||
self.is_vmx = False
|
||||
self.vcpus = 1
|
||||
self.bootloader = None
|
||||
|
||||
def setdom(self, dom):
|
||||
"""Set the domain id.
|
||||
@@ -496,6 +499,7 @@ class XendDomainInfo:
|
||||
self.find_image_handler()
|
||||
self.init_domain()
|
||||
self.register_domain()
|
||||
self.configure_bootloader()
|
||||
|
||||
# Create domain devices.
|
||||
self.configure_backends()
|
||||
@@ -674,6 +678,13 @@ class XendDomainInfo:
|
||||
memory = memory * 1024 + self.pgtable_size(memory)
|
||||
dom = xc.domain_create(dom= dom, mem_kb= memory,
|
||||
cpu= cpu, cpu_weight= cpu_weight)
|
||||
if self.bootloader:
|
||||
try:
|
||||
if kernel: os.unlink(kernel)
|
||||
if ramdisk: os.unlink(ramdisk)
|
||||
except OSError, e:
|
||||
log.warning('unable to unlink kernel/ramdisk: %s' %(e,))
|
||||
|
||||
if dom <= 0:
|
||||
raise VmError('Creating domain failed: name=%s memory=%d'
|
||||
% (self.name, memory))
|
||||
@@ -854,6 +865,13 @@ class XendDomainInfo:
|
||||
self.config.remove(['device', dev_config])
|
||||
self.deleteDevice(type, dev.getId())
|
||||
|
||||
def configure_bootloader(self):
|
||||
"""Configure boot loader.
|
||||
"""
|
||||
bl = sxp.child_value(self.config, "bootloader")
|
||||
if bl is not None:
|
||||
self.bootloader = bl
|
||||
|
||||
def configure_console(self):
|
||||
"""Configure the vm console port.
|
||||
"""
|
||||
@@ -931,10 +949,30 @@ class XendDomainInfo:
|
||||
self.state = STATE_VM_OK
|
||||
self.restart_check()
|
||||
self.restart_state = STATE_RESTART_BOOTING
|
||||
if self.bootloader:
|
||||
self.config = self.bootloader_config()
|
||||
self.construct(self.config)
|
||||
finally:
|
||||
self.restart_state = None
|
||||
|
||||
def bootloader_config(self):
|
||||
# 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
|
||||
# FIXME: this assumes that we want to use the first disk
|
||||
dev = sxp.child_value(self.config, "device")
|
||||
if dev:
|
||||
disk = sxp.child_value(dev, "uname")
|
||||
fn = blkdev_uname_to_file(disk)
|
||||
blcfg = bootloader(self.bootloader, fn, 1, self.vcpus)
|
||||
if blcfg is None:
|
||||
msg = "Had a bootloader specified, but can't find disk"
|
||||
log.error(msg)
|
||||
raise VmError(msg)
|
||||
config = sxp.merge(['vm', blconfig ], self.config)
|
||||
return config
|
||||
|
||||
def configure_backends(self):
|
||||
"""Set configuration flags if the vm is a backend for netif or blkif.
|
||||
Configure the backends to use for vbd and vif if specified.
|
||||
@@ -1071,6 +1109,7 @@ def vm_image_linux(vm, image):
|
||||
if args:
|
||||
cmdline += " " + args
|
||||
ramdisk = sxp.child_value(image, "ramdisk", '')
|
||||
log.debug("creating linux domain with cmdline: %s" %(cmdline,))
|
||||
vm.create_domain("linux", kernel, ramdisk, cmdline)
|
||||
return vm
|
||||
|
||||
@@ -1169,6 +1208,7 @@ add_config_handler('image', vm_field_ignore)
|
||||
add_config_handler('device', vm_field_ignore)
|
||||
add_config_handler('backend', vm_field_ignore)
|
||||
add_config_handler('vcpus', vm_field_ignore)
|
||||
add_config_handler('bootloader', vm_field_ignore)
|
||||
|
||||
# Register other config handlers.
|
||||
add_config_handler('maxmem', vm_field_maxmem)
|
||||
|
||||
@@ -71,6 +71,15 @@ def blkdev_segment(name):
|
||||
'type' : 'Disk' }
|
||||
return val
|
||||
|
||||
def blkdev_uname_to_file(uname):
|
||||
"""Take a blkdev uname and return the corresponding filename."""
|
||||
fn = None
|
||||
if uname.find(":") != -1:
|
||||
(typ, fn) = uname.split(":")
|
||||
if typ == "phy" and not fn.startswith("/dev/"):
|
||||
fn = "/dev/%s" %(fn,)
|
||||
return fn
|
||||
|
||||
def mount_mode(name):
|
||||
mode = None
|
||||
name = expand_dev_name(name)
|
||||
|
||||
@@ -10,6 +10,8 @@ import socket
|
||||
from xen.xend import sxp
|
||||
from xen.xend import PrettyPrint
|
||||
from xen.xend.XendClient import server, XendError
|
||||
from xen.xend.XendBootloader import bootloader
|
||||
from xen.xend.server import blkif
|
||||
|
||||
from xen.util import console_client
|
||||
|
||||
@@ -94,6 +96,14 @@ gopts.var('name', val='NAME',
|
||||
fn=set_value, default=None,
|
||||
use="Domain name. Must be unique.")
|
||||
|
||||
gopts.var('bootloader', val='FILE',
|
||||
fn=set_value, default=None,
|
||||
use="Path to bootloader.")
|
||||
|
||||
gopts.var('bootentry', val='NAME',
|
||||
fn=set_value, default=None,
|
||||
use="Entry to boot via boot loader")
|
||||
|
||||
gopts.var('kernel', val='FILE',
|
||||
fn=set_value, default=None,
|
||||
use="Path to kernel image.")
|
||||
@@ -252,7 +262,7 @@ def strip(pre, s):
|
||||
else:
|
||||
return s
|
||||
|
||||
def configure_image(config, vals):
|
||||
def configure_image(opts, config, vals):
|
||||
"""Create the image config.
|
||||
"""
|
||||
config_image = [ vals.builder ]
|
||||
@@ -272,7 +282,7 @@ def configure_image(config, vals):
|
||||
config.append(['image', config_image ])
|
||||
|
||||
|
||||
def configure_disks(config_devs, vals):
|
||||
def configure_disks(opts, config_devs, vals):
|
||||
"""Create the config for disks (virtual block devices).
|
||||
"""
|
||||
for (uname, dev, mode, backend) in vals.disk:
|
||||
@@ -284,14 +294,14 @@ def configure_disks(config_devs, vals):
|
||||
config_vbd.append(['backend', backend])
|
||||
config_devs.append(['device', config_vbd])
|
||||
|
||||
def configure_pci(config_devs, vals):
|
||||
def configure_pci(opts, config_devs, vals):
|
||||
"""Create the config for pci devices.
|
||||
"""
|
||||
for (bus, dev, func) in vals.pci:
|
||||
config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
|
||||
config_devs.append(['device', config_pci])
|
||||
|
||||
def configure_usb(config_devs, vals):
|
||||
def configure_usb(opts, config_devs, vals):
|
||||
for path in vals.usb:
|
||||
config_usb = ['usb', ['path', path]]
|
||||
config_devs.append(['device', config_usb])
|
||||
@@ -315,7 +325,7 @@ def randomMAC():
|
||||
random.randint(0x00, 0xff) ]
|
||||
return ':'.join(map(lambda x: "%02x" % x, mac))
|
||||
|
||||
def configure_vifs(config_devs, vals):
|
||||
def configure_vifs(opts, config_devs, vals):
|
||||
"""Create the config for virtual network interfaces.
|
||||
"""
|
||||
vifs = vals.vif
|
||||
@@ -357,7 +367,7 @@ def configure_vifs(config_devs, vals):
|
||||
config_vif.append(['ip', ip])
|
||||
config_devs.append(['device', config_vif])
|
||||
|
||||
def configure_vfr(config, vals):
|
||||
def configure_vfr(opts, config, vals):
|
||||
if not vals.ipaddr: return
|
||||
config_vfr = ['vfr']
|
||||
idx = 0 # No way of saying which IP is for which vif?
|
||||
@@ -365,7 +375,7 @@ def configure_vfr(config, vals):
|
||||
config_vfr.append(['vif', ['id', idx], ['ip', ip]])
|
||||
config.append(config_vfr)
|
||||
|
||||
def configure_vmx(config_devs, vals):
|
||||
def configure_vmx(opts, config_devs, vals):
|
||||
"""Create the config for VMX devices.
|
||||
"""
|
||||
memmap = vals.memmap
|
||||
@@ -375,7 +385,21 @@ def configure_vmx(config_devs, vals):
|
||||
config_devs.append(['device_model', device_model])
|
||||
config_devs.append(['device_config', device_config])
|
||||
|
||||
def make_config(vals):
|
||||
def run_bootloader(opts, config, vals):
|
||||
if not os.access(vals.bootloader, os.X_OK):
|
||||
opts.err("Bootloader isn't executable")
|
||||
if len(vals.disk) < 1:
|
||||
opts.err("No disks configured and boot loader requested")
|
||||
(uname, dev, mode, backend) = vals.disk[0]
|
||||
file = blkif.blkdev_uname_to_file(uname)
|
||||
|
||||
blcfg = bootloader(vals.bootloader, file, not vals.console_autoconnect,
|
||||
vals.vcpus, vals.blentry)
|
||||
|
||||
config.append(['bootloader', vals.bootloader])
|
||||
config.append(blcfg)
|
||||
|
||||
def make_config(opts, vals):
|
||||
"""Create the domain configuration.
|
||||
"""
|
||||
|
||||
@@ -396,15 +420,19 @@ def make_config(vals):
|
||||
config.append(['restart', vals.restart])
|
||||
if vals.console:
|
||||
config.append(['console', vals.console])
|
||||
|
||||
configure_image(config, vals)
|
||||
|
||||
if vals.bootloader:
|
||||
run_bootloader(opts, config, vals)
|
||||
else:
|
||||
configure_image(opts, config, vals)
|
||||
config_devs = []
|
||||
configure_disks(config_devs, vals)
|
||||
configure_pci(config_devs, vals)
|
||||
configure_vifs(config_devs, vals)
|
||||
configure_usb(config_devs, vals)
|
||||
configure_vmx(config_devs, vals)
|
||||
configure_disks(opts, config_devs, vals)
|
||||
configure_pci(opts, config_devs, vals)
|
||||
configure_vifs(opts, config_devs, vals)
|
||||
configure_usb(opts, config_devs, vals)
|
||||
configure_vmx(opts, config_devs, vals)
|
||||
config += config_devs
|
||||
|
||||
return config
|
||||
|
||||
def preprocess_disk(opts, vals):
|
||||
@@ -587,7 +615,8 @@ def main(argv):
|
||||
preprocess(opts, opts.vals)
|
||||
if not opts.getopt('name') and opts.getopt('defconfig'):
|
||||
opts.setopt('name', os.path.basename(opts.getopt('defconfig')))
|
||||
config = make_config(opts.vals)
|
||||
config = make_config(opts, opts.vals)
|
||||
|
||||
if opts.vals.dryrun:
|
||||
PrettyPrint.prettyprint(config)
|
||||
else:
|
||||
|
||||