Novell Home

Creating a Menu System using ZENworks 7 SP1

Novell Cool Solutions: Feature
By Hamish Speirs

Digg This - Slashdot This

Posted: 1 Nov 2007
 

Using Art Flores work as a basis (Run Bash Scripts from the PXE Menu), I was looking at how to create a menu system using ZEN 7 SP1. Although very informative, some of Art's methods no longer work with ZEN 7SP1, For Example IMGCMD="runScript.s somescript.s" no longer work. Also, the Menu Editor is no longer directly available from the CD, it's in a jar file, see here for details on how to extract it.

Additionally, I wanted a little more flexibility in accessing the custom scripts. For example, not having to rebuild the initrd or root boot files every time I added or modified a script.

Solution

To accomplish this, I modified the /bin/imaging.s script to support executing either a script within the linux file system, or downloading and executing a script from the TFTP server. The imaging script assumes that the script to be downloaded resides in the directory CMDS under the root of the TFTP structure (so, generally: sys:tftp/cmds). I additionally created a new directory /scripts in the initrd file structure that can be used to store scripts that you always want available without having to download.

The modified imaging.s script is as follows:

#!/bin/bash
# imaging.s

. /bin/config.s auto
mountFloppyifLS120
#check for environment variable with command to run
if [ "a0" = "a"${#IMGCMD} ] ; then
/bin/img a

#Return codes for img:
#0SUCCESSFUL, but no changes on hard drive(s)
#1SUCCESSFUL, new image placed on hard drive(s)
#2SUCCESSFUL, proxy had no work to be done
#4SUCCESSFUL, advanced script brought down to be run
else
if test -x "$IMGCMD" ; then
          # Script is executable - we don't need to modify it
          $IMGCMD
        elif test -f "$IMGCMD" ; then
  # if the file is a regular file, assume it is a script and in unix format
  /usr/bin/dos2unix $IMGCMD
  chmod +x $IMGCMD
          $IMGCMD
        else
          # We've been passed a script name, download and execute it
          cd /scripts
          tftp $TFTPIP -c get cmds/$IMGCMD
          chmod +x $IMGCMD
          ./$IMGCMD
         fi
fi
RESULT=$?

if [ $RESULT"a" = "0a" ] || [ $RESULT"a" = "1a" ] || [ $RESULT"a" = "2a" ] ; then
export IMGSUCCESS=1
elif [ $RESULT"a" = "4a" ] ; then
crlf.s /bin/zenAdvancedScript
chmod +x /bin/zenAdvancedScript
. /bin/zenAdvancedScript
else
echo ZENworks imaging failed with error:$RESULT. 
fi
/bin/lilo.s auto

To install this script into the initrd file structure, do the following:

-
  1. Save the script into the CMDS directory under TFTP root.
  2. -
  3. Boot a PXE workstation into ZEN Maintenance mode. (Hold Ctrl-Alt during the PXE boot, then Option 2 from the menu).
  4. Then from the Bash shell do: mkdir /work cd /work tftp $TFTPIP ?m binary ?c get boot/initrd mf initrd initrd.gz gunzip initrd (Ignore the message about trailing garbage) mkdir work mount ?o loop initrd work cd work mkdir scripts cd bin tftp $TFTPIP ?c get cmds/imaging.s chmod +x imaging.s cd /work umount work gzip ?v9c initrd > initrd.gz tftp $TFTPIP ?m binary ?c put boot/initrd.gz
  5. Then on the TFTP server, rename or delete the existing /boot/initrd and rename the initrd.gz to initrd

With the new imaging script in place, the .cmd files called can now be used to run custom scripts from the /tftp/cmds directory by using, for example:

KERNEL boot/linux
APPEND initrd=boot/initrd vga=0x314 install=tftp://$TFTPIP/boot rootimage=/root PROXYADDR=$PROXYADDR TFTPIP=$TFTPIP splash=silent PXEBOOT=YES mode=2 IMGCMD=gx280-4.s

This will PXE boot the workstation into imaging mode, download the gx280-4.s script and execute it. The actual gx280-4.s script contains:

#!/bin/bash
NC='\e[0m'
RED='\e[0;31m'
WHITe='\e[1;37m'
YELLOW='\e[1;33m'
setterm -clear
echo
echo -e " ${YELLOW} Installing Dell GX-280/620 NetWare Client 4.91 SP4 Image ......."
img restorep $TFTPIP //$TFTPIP/vol1/backups/gx280-4.zmg
IResult=$?
setterm -clear

if [$IResult = 0] ; then
  echo -e " ${WHITE} no changes Made ${NC}\a\n\c"
  sleep 10
elif [$IResult = 1] ; then
  echo -e " ${WHITE} Image successfully installed ${NC}\a\n\c"
  sleep 10
elif [$IResult = 2] ; then
  echo -e " ${WHITE} No work to do ${NC}\a\n\c"
  sleep 10
elif [$IResult = 4] ; then
  echo -e " ${WHITE} Advanced Script executed ${NC}\a\n\c"
  sleep 10
else
  echo -e " ${RED} Multicast Image receive Failed!! ${GREEN} Error Code: $IResult ${NC}\a\n\c"
fi
echo
read -s -n1 -p "Press any key to reboot ......"
reboot -f

In addition, to update the root file system with any scripts I do want in the image, the following script allows the easy installation of scripts, avoiding the need to manually create directories, TFTP the files up and down, etc.

It assumes that the scripts you're installing are coming from /TFTP/CMDS and will be installed into /scripts on the root image ? these directories can be modified if desired. Use the same procedure as for updating imaging.s to copy this into /bin of the root image.

Usage is: supdate.s file1 [file2 file3 file4 . . . . . . . . . . . . .]

#!/bin/bash

# User defined directory names

TEMPDIR="/haitch"
WORKDIR="work"
SCRIPTDIR="scripts"
SOURCEDIR="cmds"

# Error Return Codes

BAD_TEMPDIR=1
NO_ROOT=2
BAD_MOVE=3
BROKEN_ROOT=4
BAD_WORKDIR=5
BAD_MOUNT=6
BAD_SCRIPTDIR=7
BAD_UMOUNT=8
BAD_REZIP=9
BAD_UPLOAD=10
BAD_SYNTAx=11

# some Colorization

NC='\e[0m'
RED='\e[0;31m'
WHITe='\e[1;37m'
YELLOW='\e[1;33m'
GREEN='\e[0;32m'


# Assorted procedures to make life easier

Message () {
echo -e "${WHITE}$1${NC}"
}

Caution () {
echo -e "${YELLOW}$1${NC}"
}

Error () {
echo -e "${RED}Error: $1${NC}"
exit $2
}

#check the result passed in $1, and if non zero, error with the message in $2

Check () {
if [ $1 != 0 ] ; then
  Error "$2" $3
  fi
}  

# function MakeDir
# Creates our working directories - first check to see if the dir exists,
# If it exists, verify it is a directory - error if not a directory, otherwise re-use existing 
# directory. 
# If it doesn't exist, create it

MakeDir () {
if [ -a $1 ] ; then
  if [ -d $1 ] ; then
    Caution "Note: $1 already exists"
  else
    Error "$1 exists, but is not a directory!" $2
  fi
else
  mkdir $1 > /dev/null
  Check $? "Could not create $1!" $2
fi
}

# Function tftpcheck
# The tftp module does NOT return an error code when it has a problem, only an error
# message to stdout. soooo ... we jump through a couple of hoops to check for an error.
# the tftp command output is piped to the file tftptemp, we then check to see if there is any
# text in tftptemp - if there is, an error occured.

tftpcheck () {
TEMPVAL=1
if [ -z "$(cat tftptemp)" ] ; then
  TEMPVAL=0
  fi
rm tftptemp
return $TEMPVAL
}


## Main Script starts here.

# check they provided at least one file to add

if [ -z "$1" ] ; then
  Caution "Usage: `basename $0` file1 [file2 file3 ..... fileN]"
  exit BAD_SYNTAX
fi


# Create the top level working directory

MakeDir $TEMPDIR $BAD_TEMP
cd $TEMPDIR

# Download the current root file system

Message "Getting the current root image ......"

tftp $TFTPIP -m binary -c get boot/root > tftptemp
tftpcheck
Check $? "Failed downloading root file system archive" $NO_ROOT

mv root root.gz
Check $? "Failed moving root to root.gz" $BAD_MOVe

Message "Extracting root file system ......"

gunzip root.gz
Check $? "Failed extracting root file system" $BROKEN_ROOT

# Mount the compressed image onto the working directory

Message "Mounting root file system ......"

MakeDir $WORKDIR $BAD_WORKDIR

mount -o loop root work
Check $? "Failed mounting root file system to $TEMPDIR/$WORKDIR" $BAD_MOUNT

cd $WORKDIR

# Create the script directory if required
  
MakeDir $SCRIPTDIR $BAD_SCRIPTDIR
cd $SCRIPTDIR

# Now process each file name

until [ -z "$1" ] ; do
  echo -e "${WHITE}Getting script file: ${GREEN}$1${NC}"
  tftp $TFTPIP -c get $SOURCEDIR/$1 > tftptemp
  tftpcheck
  if [ $? != 0 ] ; then
    Caution "Could not download: $1"
  else 
    chmod +x $1
    cp $1 /$SCRIPTDIR
    fi
  shift
  done

# Close down the fs image

Message "umounting root file system ......"
cd ../..
umount work
Check $? "Could not umount root file system" $BAD_UMOUNT

#Cleanup the working Dir

rmdir $WORKDIR

Message "Compressing root file system ......"
gzip -v9c root > root.gz
Check $? "Failed re-compressing root file sytem" $BAD_REZIP

# and try to upload our new root fs

Message "Uploading new root file system as root.new"
mv root.gz root.new
tftp $TFTPIP -m binary -c put boot/root.new > tftptemp
tftpcheck
Check $? "Failed uploading new root image" $BAD_UPLOAD

rm root.new

echo -e "${GREEN}New root filesystem created and uploaded${NC}"
exit 0

If you have any questions you may contact Hamish at hamish@haitch.net


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell