[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] pypxeboot bootloader
Ian Pratt wrote: tftp-hpa as supplied with FC3 seems to work: "tftp tftp-serv -c get foo /tmp/bar" Yes and tftp version 0.43 from http://www.kernel.org/pub/software/network/tftp/ works too. I was using a much older one before so everything should be OK as long as people use a recent version. I've put it in the README. I've attached a fresh patch that addresses this and the other issues you raised, Tim. Could you explain what the problem would be? Do you mean that the DHCP server might not be set up to serve requests from the dom0's subnet? To be honest I hadn't thought that much about more complex setups -- as it is there are embedded assumptions about the way pxelinux is set up.Incidentally, what do you do if the guest vif is not going to be on the same bridge that dom0 eth0 is on? In practice this likely matters more for the dhcp request than the tftp transfer. Stephen -- Dr. Stephen Childs, Research Fellow, EGEE Project, phone: +353-1-8961797 Computer Architecture Group, email: Stephen.Childs @ cs.tcd.ie Trinity College Dublin, Ireland web: http://www.cs.tcd.ie/Stephen.Childs # HG changeset patch # User childss@xxxxxxxxxxxxx # Date 1170952399 0 # Node ID 4cf16fd716cf1dff0859afda632f6cf922c35dfa # Parent 780f097b54c5f9161f7c6cf3f86b2bb72cc43587 pypxeboot, a PXE-like bootloader for getting configuration and kernel images for Domain Us. Signed-off-by: Stephen Childs <childss@xxxxxxxxx> diff -r 780f097b54c5 -r 4cf16fd716cf tools/pypxeboot/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pypxeboot/README Thu Feb 08 16:33:19 2007 +0000 @@ -0,0 +1,44 @@ +pypxeboot is a bootloader for xen that simulates PXE behaviour. It runs on +Domain 0 as part of the domain creation process and downloads boot information +from a previously-configured PXELinux server using TFTP. + +pypxeboot requires the following external programs: + +1) A patched version of udhcp 0.9.8 (http://udhcp.busybox.net/) that supports +a user-specified MAC address. The patch is udhcp_usermac.patch, available +in this distribution. There is also a script needed to output information +received from the DHCP server. This is called outputpy.udhcp.sh and +should be installed at /usr/share/udhcpc/ + +2) The tftp client program (source and RPMs available at +http://www.kernel.org/pub/software/network/tftp/). N.B. pypxeboot +has been tested with version 0.43 of tftp. + +To use pypxeboot, add the following lines to your Xen domain configuration +file: + +bootloader="/usr/bin/pypxeboot" +bootargs=vif[0] + +If the pxelinux.cfg entry is set to localboot you should see output like this: + +[root@tg23 pypxeboot]# xm create cagnode50-slc308 +Using config file "/etc/xen/cagnode50-slc308". +pypxeboot: requesting info for MAC address AA:00:86:e2:35:72 +pypxeboot: getting cfg for IP 134.226.53.114 (86E23572) from server 192.168.12.1 +pypxeboot: dropping to pygrub for local boot +Going to boot Scientific Linux CERN Xen DomU-xenU (2.4.21-47.0.1.EL.cernxenU) + kernel: /vmlinuz-2.4.21-47.0.1.EL.cernxenU + initrd: /initrd-2.4.21-47.0.1.EL.cernxenU.img + +and something like this if the pxelinux.cfg entry specifies a network boot: + +[root@tg23 pypxeboot]# xm create cagnode50-slc308 +Using config file "/etc/xen/cagnode50-slc308". +pypxeboot: requesting info for MAC address AA:00:86:e2:35:72 +pypxeboot: getting cfg for IP 134.226.53.114 (86E23572) from server 192.168.12.1 +pypxeboot: downloading initrd using cmd: tftp -c get 192.168.12.1:slc308_i386_xen/initrd.img +pypxeboot: downloading kernel using cmd: tftp -c get 192.168.12.1:slc308_i386_xen/vmlinuz +Started domain cagnode50 + +The kernel and initrd on the tftp server need to be XenLinux images. diff -r 780f097b54c5 -r 4cf16fd716cf tools/pypxeboot/outputpy.udhcp.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pypxeboot/outputpy.udhcp.sh Thu Feb 08 16:33:19 2007 +0000 @@ -0,0 +1,44 @@ +#!/bin/sh +# +# outputpy.udhcp.sh: a simple script called by udhcpc when a lease is +# obtained. The script takes information passed by udhcpc as environment +# variables and outputs it formatted as key/value pairs. Only the variables +# needed by pypxeboot are currently printed: others are listed in comments +# for reference. +# Copyright 2007 Trinity College Dublin +# Author: Stephen Childs <childss@xxxxxxxxx> + +# we only need to process "bound" events +if [ "$1" == "bound" ]; then +echo ip=$ip +echo siaddr=$siaddr +echo sname=$sname +echo boot_file=$boot_file +echo subnet=$subnet +echo timezone=$timezone +echo router=$router +echo bootfile=$bootfile # - The bootfile name +fi +exit 0 + +# timesvr - A list of time servers +# namesvr +# dns +# logsvr - A list of MIT-LCS UDP log servers +# cookiesvr - A list of RFC 865 cookie servers +# lprsvr - A list of LPR servers +# hostname - The assigned hostname +# bootsize - The length in 512 octect blocks of the bootfile +# domain - The domain name of the network +# swapsvr - The IP address of the client's swap server +# rootpath - The path name of the client's root disk +# ipttl - The TTL to use for this network +# mtu - The MTU to use for this network +# broadcast - The broadcast address for this network +# ntpsrv - A list of NTP servers +# wins - A list of WINS servers +# lease - The lease time, in seconds +# dhcptype - DHCP message type (safely ignored) +# serverid - The IP of the server +# message - Reason for a DHCPNAK +# tftp - The TFTP server name diff -r 780f097b54c5 -r 4cf16fd716cf tools/pypxeboot/pypxeboot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pypxeboot/pypxeboot Thu Feb 08 16:33:19 2007 +0000 @@ -0,0 +1,209 @@ +#!/usr/bin/python +# +# pypxeboot - simple python-based bootloader to fake PXE booting for Xen DomUs +# Uses a modified version of udhcpc that allows MAC address to be passed on +# the command line. Also uses tftp client to download configuration and images +# +# Copyright 2007 Trinity College Dublin +# Stephen Childs <childss@xxxxxxxxx> +# +# 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 commands,sys,re,os,getopt,tempfile,shutil + +udhcpc_command="/usr/bin/udhcpc" +udhcpc_script="/usr/share/udhcpc/outputpy.udhcp.sh" +havekernelargs=False + +def run_pygrub(): + arglist=[] + for arg in sys.argv[1:]: + if not (macre.match(arg)): + arglist.append(arg) + + program="/usr/bin/pygrub" + + os.execvp(program, (program,) + tuple(arglist)) + +def tftp_success(statusoutput): + errorre=re.compile("Error*") + if errorre.match(statusoutput[1]): + return False + else: + return True + +# get arguments from calling program -- most important is MAC address +macre=re.compile("mac*=*",re.IGNORECASE) +outputre=re.compile("--output*",re.IGNORECASE) + +def usage(): + print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--entry=] mac= <image>" %(sys.argv[0],) + +try: + opts, args = getopt.gnu_getopt(sys.argv[1:], 'qh::', + ["quiet", "help", "output=", "entry=", "mac=", + "isconfig"]) +except getopt.GetoptError: + usage() + sys.exit(1) + +if len(args) < 1: + usage() + sys.exit(1) + +output = None + +for o, a in opts: + if o in ("--output",): + output = a + +if output is None or output == "-": + outputfd = sys.stdout.fileno() +else: + outputfd = os.open(output, os.O_WRONLY) + +mac="" + +# look for a mac= option in the options passed in +# should do this properly using getopt? +for arg in sys.argv[1:]: + if macre.match(arg): + mac=arg.split('=')[1] + print "pypxeboot: requesting info for MAC address "+mac+"" + break + +if mac == "": + print "pypxeboot: Didn't get a MAC address, dying" + sys.exit(1) + +# run modified udhcp with specified MAC address +udhcp_result=commands.getstatusoutput(udhcpc_command+" -n -q -s "+ + udhcpc_script+" -M "+mac) + +if (udhcp_result[0] != 0): + print "pypxeboot: udhcpc failed (%s), output: %s\n" %(udhcp_result[0], + udhcp_result[1]) + sys.exit(1) + +# parse output from udhcp-executed script (looking for key=value +# pairs) +udhcplines=udhcp_result[1].split('\n') + +dhcpinfo={} + +for line in udhcplines: + s = line.strip() + if (s.find('=') != -1): + f=s.split('=') + dhcpinfo[f[0]]=f[1] + +# run tftp client to get configuration info +servaddr=dhcpinfo['siaddr'] + +ipaddr=dhcpinfo['ip'] +ipaddrlist=ipaddr.split('.') +hexip=(4 * "%2.2X") % tuple(map (int, ipaddrlist)) + +print "pypxeboot: getting cfg for IP %s (%s) from server %s" %(ipaddr,hexip,servaddr) + +tmpdir="/var/lib/xen/" + +os.chdir(tmpdir) +commandstr="tftp "+servaddr+" -c get pxelinux.cfg/"+hexip +#print "running command "+commandstr +getpxeres=commands.getstatusoutput(commandstr) + +# check for errors in tftp output -- it doesn't use return codes properly! +if not tftp_success(getpxeres): + print ("pypxeboot: error getting pxelinux cfg") + sys.exit(1) + +# read in the downloaded pxelinux cfg file +cfgfilename=tmpdir+hexip +cfgfile=open(cfgfilename) +cfglines=cfgfile.readlines() + +# check whether we should drop to localboot +# XXX should really check that localboot is the default +localbootre=re.compile("\s*localboot\w*") + +for line in cfglines: + if (localbootre.match(line)): + print "pypxeboot: dropping to pygrub for local boot" + run_pygrub() + sys.exit(0) + +# remove downloaded config file +cfgfile.close() +os.remove(cfgfilename) + +# if "network" boot get kernel to local file and return the location as +# sxp as pygrub does + +kernelre=re.compile("kernel*") +appendre=re.compile("append*") + +# parse the pxelinux entry: add key/value pairs to +# a dict and dump all other args to a string +# XXX assumes there's only one entry at the moment +# XXX need to parse properly and use default entry +syslinux={} +simpleargs="" +for line in cfglines: + if (line[0]!='#'): + line=line.strip() + if (kernelre.match(line)): + (k,v)=line.split() + syslinux[k]=v + elif (appendre.match(line)): + havekernelargs=True + for entry in line[6:].split(): + if (entry.find('=') != -1): + (k,v)=entry.split('=') + syslinux[k]=v + else: + simpleargs+=entry+' ' + + +# if network boot, get kernel and initrd +# temp directory should still be the working dir +dlres={} +tmpimages={} +for i in ["initrd","kernel"]: + (tfd,tfn)=tempfile.mkstemp(prefix=i+".", dir=tmpdir) + cmd="tftp "+servaddr+" -c get "+syslinux[i]+" "+tfn + tmpimages[i]=tfn + print "pypxeboot: downloading "+i+" using cmd: "+cmd + dlres[i]=commands.getstatusoutput(cmd) + if not tftp_success (dlres[i]): + print "pypxeboot: tftp failed for "+i+": "+dlres[i][1] + sys.exit(1) + + +# format kernel and args as sxp +# will need to get the --output option and write to that fd +kernelname=syslinux['kernel'].split('/')[-1] +initrdname=syslinux['initrd'].split('/')[-1] + +sxp="linux (kernel %s)" %(tmpimages['kernel'],) + +if 'initrd' in syslinux: + sxp+="(ramdisk %s)" % (tmpimages['initrd'],) +if havekernelargs: + sxp+="(args '" + for arg in syslinux: + if arg != 'kernel' and arg != 'initrd': + sxp+=arg+"="+syslinux[arg]+' ' + sxp+=simpleargs + sxp=sxp[0:-1] # remove trailing space + sxp+="'" +sxp+=")" + +sys.stdout.flush() +os.write(outputfd,sxp) diff -r 780f097b54c5 -r 4cf16fd716cf tools/pypxeboot/udhcp_usermac.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pypxeboot/udhcp_usermac.patch Thu Feb 08 16:33:19 2007 +0000 @@ -0,0 +1,107 @@ +diff -u udhcp-0.9.8/dhcpc.c udhcp-0.9.8.mod/dhcpc.c +--- udhcp-0.9.8/dhcpc.c 2002-10-19 02:10:43.000000000 +0100 ++++ udhcp-0.9.8.mod/dhcpc.c 2007-02-02 14:41:11.000000000 +0000 +@@ -67,6 +67,7 @@ + foreground: 0, + quit_after_lease: 0, + background_if_no_lease: 0, ++ userarp: 0, + interface: "eth0", + pidfile: NULL, + script: DEFAULT_SCRIPT, +@@ -95,6 +96,7 @@ + " -r, --request=IP IP address to request (default: none)\n" + " -s, --script=file Run file at dhcp events (default:\n" + " " DEFAULT_SCRIPT ")\n" ++" -M, --mac=MAC MAC address to use instead of HW MAC\n" + " -v, --version Display version\n" + ); + exit(0); +@@ -132,6 +134,7 @@ + state = INIT_SELECTING; + break; + case INIT_SELECTING: ++ break; + } + + /* start things over */ +@@ -207,6 +210,7 @@ + #endif + { + unsigned char *temp, *message; ++ unsigned char hwmac[6]; + unsigned long t1 = 0, t2 = 0, xid = 0; + unsigned long start = 0, lease; + fd_set rfds; +@@ -233,14 +237,15 @@ + {"request", required_argument, 0, 'r'}, + {"script", required_argument, 0, 's'}, + {"version", no_argument, 0, 'v'}, ++ {"mac", required_argument, 0, 'M'}, + {"help", no_argument, 0, '?'}, + {0, 0, 0, 0} + }; + + /* get options */ + while (1) { +- int option_index = 0; +- c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:v", arg_options, &option_index); ++ int option_index = 0, nrmacfields=0; ++ c = getopt_long(argc, argv, "c:fbH:h:i:np:qr:s:v:M:", arg_options, &option_index); + if (c == -1) break; + + switch (c) { +@@ -290,6 +295,16 @@ + printf("udhcpcd, version %s\n\n", VERSION); + exit_client(0); + break; ++ case 'M': ++ nrmacfields=sscanf(optarg,"%x:%x:%x:%x:%x:%x", ++ (unsigned int *)&client_config.arp[0], ++ (unsigned int *)&client_config.arp[1], ++ (unsigned int *)&client_config.arp[2], ++ (unsigned int *)&client_config.arp[3], ++ (unsigned int *)&client_config.arp[4], ++ (unsigned int *)&client_config.arp[5]); ++ if (nrmacfields == 6) client_config.userarp=1; ++ break; + default: + show_usage(); + } +@@ -302,9 +317,11 @@ + pidfile_write_release(pid_fd); + + if (read_interface(client_config.interface, &client_config.ifindex, +- NULL, client_config.arp) < 0) ++ NULL, hwmac) < 0) + exit_client(1); +- ++ ++ if (!(client_config.userarp)) memcpy(client_config.arp, hwmac, 6); ++ + if (!client_config.clientid) { + client_config.clientid = xmalloc(6 + 3); + client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID; +diff -u udhcp-0.9.8/dhcpc.h udhcp-0.9.8.mod/dhcpc.h +--- udhcp-0.9.8/dhcpc.h 2002-09-20 21:36:15.000000000 +0100 ++++ udhcp-0.9.8.mod/dhcpc.h 2007-02-02 14:13:52.000000000 +0000 +@@ -19,6 +19,7 @@ + char quit_after_lease; /* Quit after obtaining lease */ + char abort_if_no_lease; /* Abort if no lease */ + char background_if_no_lease; /* Fork to background if no lease */ ++ char userarp; /* Did the user give us an ARP address */ + char *interface; /* The name of the interface to use */ + char *pidfile; /* Optionally store the process ID */ + char *script; /* User script to run at dhcp events */ +diff -u udhcp-0.9.8/README.udhcpc udhcp-0.9.8.mod/README.udhcpc +--- udhcp-0.9.8/README.udhcpc 2002-10-31 18:02:09.000000000 +0000 ++++ udhcp-0.9.8.mod/README.udhcpc 2007-02-02 14:12:47.000000000 +0000 +@@ -24,6 +24,7 @@ + -r, --request=IP IP address to request (default: none) + -s, --script=file Run file at dhcp events (default: + /usr/share/udhcpc/default.script) ++-M, --mac=MAC MAC address to use instead of HW MAC + -v, --version Display version + + +Common subdirectories: udhcp-0.9.8/samples and udhcp-0.9.8.mod/samples _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |