User Tools

Site Tools


auto-ks

Automated Kickstart File Generation

Anaconda is the installer for Red Hat Enterprise Linux and Fedora distributions. Kickstart is a method of automating anaconda installs. Kickstart by itself does a very good job of automatically installing single systems or groups of identical systems. However, maintaining a kickstart file per system and per distribution becomes error prone with many heterogeneous systems. By utilizing kickstart's “%pre” section to collect system information and PHP for content generation, customized kickstart files can be generated per system on the fly.

This presentation is going to be given at the 2008 Ottawa Linux Symposium

Presentation

Source Code

git clone http://smoser.brickies.net/git/auto-ks.git

Interactive Example

There is an interactive web example in the git repository at form.php

stage1 ks file

install
lang en_US.UTF-8
nfs --server=nfs.example.com --dir /export/install/F-8/i386/os
%include /tmp/install-stage2
 
%pre
# see "pre script"
%end

pre script

#%pre
#!/bin/sh
STAGE2="http://example.com/ks/?stage=2&label=F8";
TMPFILE=/tmp/.${0##*/};
 
urlencode() {
   # modified from http://wiki.piertopier.net/index.php/Urlencode
   # also: http://www.shelldorado.com/scripts/cmds/urlencode.txt
   case "$1" in
      *[^a-zA-Z0-9.-]*) :;;
      *) _RET="${1}"; return 0;;
   esac
   _RET=$(printf "%s\n" "$1" | awk '
     BEGIN {
         # We assume an awk implementation that is just plain dumb.
         # We will convert an character to its ASCII value with the
         # table ord[], and produce two-digit hexadecimal output
         # without the printf("%02X") feature.
 
         split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ")
         hextab[0] = 0
         for ( i=1; i<=255; ++i ) ord[ sprintf ("%c", i) "" ] = i + 0
     }
     {
         encoded = ""
         for ( i=1; i<=length ($0); ++i ) {
             c = substr ($0, i, 1)
             if ( c ~ /[a-zA-Z0-9.-]/ ) {
                 encoded = encoded c             # safe character
             } else if ( c == " " ) {
                 encoded = encoded "+"   # special handling
             } else {
                 # unsafe character, encode it as a two-digit hex-number
                 lo = ord[c] % 16
                 hi = int (ord[c] / 16);
                 encoded = encoded "%" hextab[hi] hextab[lo]
             }
         }
         print encoded
     }' )
}
 
parseip() {
   local line="" name="" up="" mac="" nics=""
   # get network interfaces
   ip link > "${TMPFILE}"
   while read line; do
      set -- ${line}
      case "$1" in
         [0-9]:*|[0-9][0-9]:*)
            name=${2%:};
            up=0; [ "${3##*,UP}" = "${3}" ] || up=1;;
         *) mac=${2};
            nics="${nics},${name}|${up}|${mac}";;
      esac
   done < "${TMPFILE}"
   _RET=${nics#,}
}
doparseifconfig() {
   local line="" name="" up="" mac="" nics="" addr=""
   while read line; do
      set -- $line;
      if [ "$1" != "-" ]; then
         [ -n "$name" ] && { nics="${nics},$name|$up|${mac}"; }
         name="";
      fi
      case $2 in
         Link) name=$1; mac=$5;;
         UP) up=1;;
         inet) addr=${3#addr:};;
         BROADCAST) up=0;;
         *) : ;;
      esac
   done
   [ -n "$name" ] && { nics="${nics},$name|$up|${mac}"; }
   _RET=${nics#,}
}
parseifconfig() {
   ifconfig -a >/dev/null || return 1;
   ifconfig -a | sed 's,^[ ],-,' > "${TMPFILE}"
   doparseifconfig < "${TMPFILE}";
}
 
 
# get kernel command line
read cmdline < /proc/cmdline
[ -n "$XCMDLINE" ] && cmdline=${XCMDLINE}
urlencode "${cmdline}" && STAGE2="${STAGE2}&cmdline=${_RET}"
 
if which ip >/dev/null 2>&1; then
   parseip;
else
   parseifconfig;
fi
echo "======= _RET=${_RET}"
urlencode "${_RET}" && STAGE2="${STAGE2}&nics=${_RET}"
 
# get disks available
disks=""
while read maj min blocks name ; do
   [ "$maj" = "major" -o -z "$maj" ] && continue;
   [ ${name%[0-9]} = ${name} ] && disks="${disks},${name}|${blocks}"
done < /proc/partitions
disks=${disks#,}
 
urlencode "${disks}" && STAGE2="${STAGE2}&disks=${_RET}"
 
# get meminfo
mem=$(awk '$1 == "MemTotal:" { print $2 }' < /proc/meminfo)
urlencode "${disks}" && STAGE2="${STAGE2}&mem=${_RET}"
 
 
wget "${STAGE2}" -O  "/tmp/stage2" --quiet
auto-ks.txt · Last modified: 2008/07/25 00:47 (external edit)