#!/usr/bin/python import os import sys import optparse import shutil from shvar import shvarFile from functions import * version = '0.1' builddir = '' confdir = '' bindir = '' isoimage = '' force = False method = '' anaconda_args = '' buildstamp = '' product_path = '' kernel_version = '' # OK, we`re starting flc_log ('Starting kadischi...') # setup dirs bindir = sys.path [0] confdir = normalize_path(['/etc/kadischi']) # process command line options usage = 'usage: %prog [options] \n\npath-to-the-repository can be a path on the local file system (without any prefixes) but can also be a path to a http, ftp or some other type of repository. For details, consult the documentation at http://fedoraproject.org/wiki/Kadischi/Documentation' version = '%prog ' + version parser = optparse.OptionParser (usage=usage, version=version) parser.add_option ("-f", "--force", dest="force", action="store_true", default=False, help="overwrite destination iso image file, if such exists.") parser.add_option ("-C", "--cmdline", dest="cmdline", action="store_true", default=False, help="run anaconda in command line mode (runs without interface, but requires complete kickstart file)") parser.add_option ("-T", "--text", dest="text", action="store_true", default=False, help="run anaconda in TUI mode") parser.add_option ("", "--graphical", dest="graphical", action="store_true", default=False, help="run anaconda in GUI mode") parser.add_option ("", "--kickstart", dest="ksfile", help="supply anaconda with kickstart file") parser.add_option ("", "--buildstamp", dest="buildstamp", help="buildstamp file (if not set, using the default buildstamp from the config directory)") flc_log ('Parsing command line arguments') (options, args) = parser.parse_args () force = options.force if options.ksfile != None: anaconda_args = anaconda_args + ' --kickstart=' + options.ksfile if options.buildstamp != None: buildstamp = options.buildstamp else: buildstamp = normalize_path ([confdir, 'buildstamp']) # set display mode display_mode = '' if options.graphical: display_mode = ' --graphical' if options.text: display_mode = ' -T' if options.cmdline: display_mode = ' -C' anaconda_args = display_mode + anaconda_args ### check if everything looks OK # checking arguments if len (args) < 2: flc_log ('Not enough arguments.\n') parser.parse_args (['-h']) if len (args) > 2: flc_log ('Too many arguments.\n') parser.parse_args (['-h']) method = args [0] isoimage = normalize_path ([args [1]]) # checking UID - must be root flc_log ('Checking UID') if os.getuid () != 0: flc_log ('You have to be root to run this application. Please restart with root permissions.\n') sys.exit (1) # check if we can open buildstamp file if not os.access(buildstamp, os.R_OK): flc_log ('Can`t open buildstamp file %s. ' % buildstamp) sys.exit (1) # loading productPath from buildstamp flc_log ('Using buildstamp file %s. ' % buildstamp) f = open(buildstamp, "r") lines = f.readlines() if len(lines) >= 4: product_path = lines[3][:-1] flc_log ('Product path set to %s. ' % product_path) else: flc_log ('Product path can`t be found in buildstamp file %s (Product path should be on the 4th line of the file)' % buildstamp) sys.exit (1) # validating the repository flc_log ('Now we are going to try to validate your repository (for now, only http, ftp and local repositories can be checked)') valid = True if method.find (':') == -1: method = normalize_path ([method]) valid = path_exists (method) and path_exists (method + '/' + product_path) and path_exists (method + '/' + product_path + '/' + 'base') and path_exists (method + '/' + product_path + '/' + 'RPMS') elif method.find ('http') == 0 or method.find ('ftp') == 0: method = method.rstrip('/') valid = url_exists (method) and url_exists (method + '/' + product_path) and url_exists (method + '/' + product_path + '/' + 'base') and url_exists (method + '/' + product_path + '/' + 'RPMS') if valid: flc_log ('Repository seems to be OK.') else: flc_log ('Repository validation failed. Aborting execution.') sys.exit (1) # format method string the way anaconda likes it if method.find (':') == -1: method = 'nfs:/' + method # checking if everything is OK with destination (iso image) file if os.path.isfile (isoimage): flc_log ('File %s already exists. ' % isoimage) if force: flc_log ('It will be overwritten.') else: flc_log ('Please choose some other file name, or use -f option to overwrite the existing file.') sys.exit (1) elif not os.path.isdir (os.path.dirname (isoimage)): os.makedirs (os.path.dirname (isoimage)) # check for installed rpms flc_log ('Checking required packages') required_rpms = ['anaconda', 'busybox-anaconda', 'mkisofs', 'syslinux', 'e2fsprogs'] missing_rpms = check_installed_rpms ('/', required_rpms, False) if len (missing_rpms) != 0: flc_log ('Required packages:') for rpm in missing_rpms: flc_log (' %s' % rpm) flc_log ('are missing. Aborting execution.') sys.exit (1) # check for the config file flc_log ('Looking for config file') if not os.path.isfile (normalize_path([confdir, 'build.conf'])): flc_log ('Can`t find config file %s.' % normalize_path([confdir, 'build.conf'])) sys.exit (1) # load config file options flc_log ('Loading config file options') buildconf = shvarFile (normalize_path([confdir, 'build.conf']), True) builddir = buildconf ["BUILDDIR"] buildnum = str (int (buildconf ["BUILDNUM"]) + 1) buildconf ["BUILDNUM"] = buildnum buildconf.write () if builddir == '' or builddir == None: flc_log ('No build dir defined. Please, edit config file option BUILDDIR.') sys.exit(1) # prepare dirs buildsubdir = 'livecd-build_no' + buildnum builddir = normalize_path ([builddir, buildsubdir]) sysdir = normalize_path([builddir, 'system']) csysdir = normalize_path([builddir, 'compressed']) squasharchive = normalize_path([builddir, 'compress.sqsh']) os.makedirs (sysdir) os.makedirs (csysdir) # we shouldn't create squasharchive because mksquashfs wants to create it by itself # Moving the buildstamp file to /tmp/product/.buildstamp so anaconda can find it if not os.path.exists ('/tmp/product'): os.makedirs ('/tmp/product') elif not os.path.isdir ('/tmp/product'): flc_log ('Path /tmp/product is not a directory, temporarly moving to %s' % normalize_path([builddir, 'product'])) shutil.move ('/tmp/product', normalize_path([builddir, 'product'])) os.makedirs ('/tmp/product') elif os.path.exists ('/tmp/product/.buildstamp'): flc_log ('Path /tmp/product/.buildstamp already exists, temporarly moving to %s' % normalize_path([builddir, '.buildstamp'])) shutil.move ('/tmp/product/.buildstamp', normalize_path([builddir, '.buildstamp'])) shutil.copy2 (buildstamp, '/tmp/product/.buildstamp') # run anaconda flc_log ('\n *** running anaconda *** \n') run ("anaconda %s --rootpath=%s --method=%s" % (anaconda_args, sysdir, method), builddir) flc_log ('\n *** anaconda has finished the job *** \n') # now`s the time to pickup kernel version cause when we move files arround, it will be late kernel_version = get_kernel_version (sysdir) # run post_install_scripts flc_log ('running post installation scripts') scripts = [] for root, dirs, files in os.walk (normalize_path([bindir, 'post_install_scripts'])): for file in files: file = normalize_path([bindir, 'post_install_scripts', file]) if os.access(file, 1): scripts.append (file) scripts.sort() for script in scripts: flc_log ('%s' % script) run ("%s %s" % (script, sysdir), builddir) # make initrd image flc_log ('making initrd image') run ("%s %s %s" % (normalize_path([bindir, 'livecd-mkinitrd.sh']), sysdir, kernel_version), builddir) # move files flc_log ('moving files that should be on tmpfs') run ("%s %s" % (normalize_path([bindir, 'movefiles.py']), sysdir), builddir) # compress the tree flc_log ('compressing the tree (order a pizza `cause this will take a while)') # A squashed READ-ONLY filesystem for Linux run ("mksquashfs %s %s" % (sysdir, squasharchive), builddir) # mount the squashfs flc_log('[kadischi]: mounting the squashfs') run ("mount %s %s -t squashfs -o loop" % (squasharchive, csysdir), builddir) # install boot & conf files in compressed tree (they shoudn`t be compressed) flc_log ('installing boot & config files in compressed tree') run ("%s %s %s %s" % (normalize_path([bindir, 'install-boot.sh']), sysdir, csysdir, kernel_version), builddir) run ("cp -f %s %s" % (normalize_path([sysdir, '/livecd/kadischi.tar.gz']), normalize_path([csysdir, '/livecd/kadischi.tar.gz'])), builddir) # delete sysdir - we don`t need it anymore flc_log ('removing uncompressed tree') clean_directory (sysdir) # create iso image flc_log ('creating iso image %s' % isoimage) run ("%s %s %s" % (normalize_path([bindir, 'create-iso.sh']), csysdir, isoimage), builddir) # umount the squashfs flc_log('[kadischi]: umounting the squashfs') run ("umount %s" % (csysdir), builddir) # delete builddir flc_log ('removing builddir') cleanup (builddir) flc_log ('Finished.') sys.exit (0)