#!/usr/bin/python
#
# iso-to-pxe: Extract the files needed to PXE boot from an iso
#
# Copyright (C) 2012 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# Author(s): Brian C. Lane
#
import os
import sys
import argparse
import shutil
from pylorax.sysutils import joinpaths
from pylorax.executils import execWithRedirect, execWithCapture
import tempfile
# ==== SETUP ====
# Full path to top level of the PXE server's image directory
IMAGE_DIR = "/extra/redhat/tftpboot/images/"
# Relative path to use in the PXE config
PXE_TOP_DIR = "images/"
# URL pointing to IMAGE_DIR, for retrieving LiveOS/squashfs.img
IMAGE_URL = "http://proxy.brianlane.com/"
# Directory of PXE config files, named DEF_DIST
PXE_CFG_DIR = "/extra/redhat/tftpboot/pxelinux.cfg/"
# This is appended to IMAGE_DIR as a path and to PXE_CFG_DIR as a config file
DEF_DIST = "fedora"
# This is appended to DEF_DIST and can be a path
DEF_RELEASE = "18"
# Default extra args to add to the APPEND line
DEF_ARGS = ""
# from livemedia-creator
class IsoMountpoint(object):
"""
Mount the iso on a temporary directory and check to make sure the
vmlinuz and initrd.img files exist
Check the iso for a LiveOS directory and set a flag.
Extract the iso's label.
"""
def __init__( self, iso_path ):
self.label = None
self.iso_path = iso_path
self.mount_dir = tempfile.mkdtemp()
if not self.mount_dir:
raise Exception("Error creating temporary directory")
cmd = ["mount", "-o", "loop", self.iso_path, self.mount_dir]
print(cmd)
execWithRedirect( cmd[0], cmd[1:] )
self.kernel = self.mount_dir+"/isolinux/vmlinuz"
self.initrd = self.mount_dir+"/isolinux/initrd.img"
if os.path.isdir( self.mount_dir+"/repodata" ):
self.repo = self.mount_dir
else:
self.repo = None
self.liveos = os.path.isdir( self.mount_dir+"/LiveOS" )
try:
for f in [self.kernel, self.initrd]:
if not os.path.isfile(f):
raise Exception("Missing file on iso: {0}".format(f))
except:
self.umount()
raise
# self.get_iso_label()
def umount( self ):
cmd = ["umount", self.mount_dir]
print(cmd)
execWithRedirect( cmd[0], cmd[1:] )
os.rmdir( self.mount_dir )
def get_iso_label( self ):
"""
Get the iso's label using isoinfo
"""
cmd = [ "isoinfo", "-d", "-i", self.iso_path ]
print(cmd)
isoinfo_output = execWithCapture( cmd[0], cmd[1:] )
print(isoinfo_output)
for line in isoinfo_output.splitlines():
if line.startswith("Volume id: "):
self.label = line[11:]
return
def make_parents(path):
""" Make parent directories
"""
if not os.path.isdir(path):
os.makedirs(path)
def run():
""" run iso-to-pxe
"""
parser = argparse.ArgumentParser(description="Setup PXE from .iso")
parser.add_argument("-d", "--imagedir", default=IMAGE_DIR,
help="Full path to top level image directory")
parser.add_argument("-t", "--pxe-top", default=PXE_TOP_DIR,
help="PXE top level directory")
parser.add_argument("-u", "--url", default=IMAGE_URL,
help="URL for stage2")
parser.add_argument("-c", "--config", default=PXE_CFG_DIR,
help="PXE config file directory")
parser.add_argument("-D", "--dist", default=DEF_DIST,
help="Distribution directory/config name")
parser.add_argument("-r", "--releasever", default=DEF_RELEASE,
help="Release version directory")
parser.add_argument("-s", "--skip-pxe", default=False,
help="Skip appending PXE config")
parser.add_argument("-x", "--extra", default=DEF_ARGS,
help="Extra args for PXE APPEND line")
parser.add_argument("iso", type=os.path.abspath,
help="path to iso")
args = parser.parse_args()
if os.geteuid() != 0:
print("You must run this as root")
sys.exit(1)
# mount iso on a temp dir
iso = IsoMountpoint(args.iso)
# copy the files
files = []
initrd_src = joinpaths(iso.mount_dir, "isolinux/initrd.img")
initrd_dest = joinpaths(args.imagedir, args.dist, args.releasever)
files.append((initrd_src, initrd_dest))
vmlinuz_src = joinpaths(iso.mount_dir, "isolinux/vmlinuz")
vmlinuz_dest = joinpaths(args.imagedir, args.dist, args.releasever)
files.append((vmlinuz_src, vmlinuz_dest))
liveos_src = joinpaths(iso.mount_dir, "LiveOS/squashfs.img")
liveos_dest = joinpaths(args.imagedir, args.dist, args.releasever, "LiveOS")
files.append((liveos_src, liveos_dest))
for src, dest in files:
make_parents(dest)
print("Copying %s to %s" % (src, dest))
shutil.copy2(src, dest)
if not args.skip_pxe:
pxe_config = """
LABEL %(dist)s %(releasever)s
MENU %(dist)s %(releasever)s
KERNEL %(pxe_top)s/%(dist)s/%(releasever)s/vmlinuz
APPEND initrd=%(pxe_top)s/%(dist)s/%(releasever)s/initrd.img stage2=%(url)s/%(dist)s/%(releasever)s/ %(extra)s
""" % (vars(args))
print pxe_config
with open(joinpaths(args.config,args.dist), "a") as f:
f.write(pxe_config)
iso.umount()
if __name__ == "__main__":
run()