summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2007-02-07 15:01:05 -0500
committerJim Meyering <jim@meyering.net>2007-02-07 15:01:05 -0500
commit9b6d81f33f24d8877502257d029655d3f34601d2 (patch)
treefa381284c56f2d36b9f9e857eeea97c4b92be0ce
parent889f951469da7c4ee42d5149ad03ca25abf93e52 (diff)
downloadcobbler-9b6d81f33f24d8877502257d029655d3f34601d2.tar.gz
cobbler-9b6d81f33f24d8877502257d029655d3f34601d2.tar.xz
cobbler-9b6d81f33f24d8877502257d029655d3f34601d2.zip
Commit before rename, adding pypxeboot for virt management, which I intend to tweak somewhat.
-rwxr-xr-xpypxeboot_mod218
-rw-r--r--setup.py2
2 files changed, 219 insertions, 1 deletions
diff --git a/pypxeboot_mod b/pypxeboot_mod
new file mode 100755
index 00000000..526ebe93
--- /dev/null
+++ b/pypxeboot_mod
@@ -0,0 +1,218 @@
+#!/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@cs.tcd.ie>
+#
+# 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
+
+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)
+
+argstring=''
+for arg in sys.argv[1:]:
+ if not (macre.match(arg)) and not (outputre.match(arg)):
+ argstring+=arg+' '
+
+
+def usage():
+ print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--entry=] <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 python formatted output from udhcp-executed script
+udhcplines=udhcp_result[1].split('\n')
+
+dhcpinfo={}
+
+for line in udhcplines:
+ s = line.strip()
+ f = s.split()
+
+ if s[0]=='{' and s[-1]=='}':
+ dhcpinfo=eval(s, {"__builtins__" : {}})
+ for k in dhcpinfo:
+ dhcpinfo[k]=dhcpinfo[k].strip()
+
+# run tftp client to get configuration info
+servaddr=dhcpinfo['siaddr']
+
+ipaddr=dhcpinfo['ip']
+ipaddrlist=ipaddr.split('.')
+hexip=commands.getstatusoutput("/usr/bin/gethostip -x "+ipaddr)[1]
+
+print "pypxeboot: getting cfg for IP %s (%s) from server %s" %(ipaddr,hexip,servaddr)
+
+tmpdir="/var/lib/xen/"
+
+os.chdir(tmpdir)
+commandstr="tftp -c get "+servaddr+":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
+cfgfile=open(tmpdir+hexip)
+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)
+
+# 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={}
+for i in ["initrd","kernel"]:
+ cmd="tftp -c get "+servaddr+":"+syslinux[i]
+ 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)" %(tmpdir+kernelname,)
+
+if 'initrd' in syslinux:
+ sxp+="(ramdisk %s)" % (tmpdir+initrdname,)
+if havekernelargs:
+ sxp+="(args '"
+ for arg in syslinux:
+ if arg != 'kernel' and arg != 'initrd':
+ sxp+=arg+"="+syslinux[arg]+' '
+ sxp+=simpleargs
+ sxp=sxp[0:-1]
+ sxp+="'"
+sxp+=")"
+
+sys.stdout.flush()
+os.write(outputfd,sxp)
+
+
+
diff --git a/setup.py b/setup.py
index 905830f0..fa32538e 100644
--- a/setup.py
+++ b/setup.py
@@ -24,7 +24,7 @@ if __name__ == "__main__":
url = "http://cobbler.et.redhat.com/",
license = "GPL",
packages = ["koan","koan/yaml"],
- scripts = ["koan/koan"],
+ scripts = ["koan/koan", "pypxeboot_koan"]
data_files = [
(manpath, ['koan.1.gz']),
],