Application Delivery Management
Application Modernization & Connectivity
IT Operations Management
CyberRes
Even when using automated imaging, there comes a time that you need to restore a specific image file to a computer. Often times, this is for a hard drive replacement or something like that.
The problem comes that you get ready to image, but you don't remember the name of the file you're looking for. This leaves you to having to go back to another computer, find the folder on the server, and then look for the file.
To combat this problem, I have developed this script that, along with a correct FTP configuration, will prompt you with a list of images available that you can select by number.
The script accomplishes this by running a quick FTP command to do a listing of the folder, then enumerating the list of image files so that you can pick by number.
The first step to setting this up is to enable FTP on your ZEN imaging server. With SLES 10 or newer, we have the PureFTPd daemon. I'm not going to go into configuring PureFTPd at this time, but if anyone needs help, post a comment and I will post more information.
Once the FTP daemon is configured and enabled, we will create a local user account. This account will only be used for the restore script to log in to get a directory listing.
For the purpose of this tutorial, we're going to use the following information:
Now that you've created the user, you should have a /home/baseline folder on the server. We now need to create a path to the image files within that folder. To do so, create a folder called /home/baseline/backup
PureFTPd is shipped with SLES in a configuration that will not allow chrooted users to follow symbolic links outside their home directory. This means that we can't simply create a symbolic link to the local path.
One way around this is to use a bind mount. The command to do that is:
mount --bind /images/backup /home/baseline/backup
This creates a mount point that is actually another folder in the directory tree. The advantage of this over a symbolic link is that the system treats this exactly as a local folder.
You can make sure that this mount point always loads when the system boots by adding the following line to /etc/fstab
/var/opt/novell/zenworks/content-repo/images/backup /home/baseline/backup bind defaults,bind 0 0
Now that we've mounted the folder, check that you can log in using an FTP client. Log in as baseline with a password of password and make sure that you can navigate to /backup and get a file listing (ls).
Once that's verified, we're ready to use the script.
A couple points to note about this script:
This script will be stored somewhere in the TFTP server path (/srv/tftp/) of your PXE server. For information about how to automatically download the script each time the imaging environment loads, see my previous article Automating Non-Automatic ZENworks Imaging - Part 1
The script is:
#!/bin/bash
################################################################################
#-- ZENworks Imaging Restoring Script
#
#-- This script is used to restore a previously backed up image to a PC
################################################################################
##--- [BEGIN Configuration section]
# FTP server information
ftpserver="myftp.domain.com" ## Enter your FTP server name here
ftpuser="baseline"
ftppass="password"
# pagelen = Maximum number of files to list per page
pagelen=20
# ftpdir = Directory on FTP server holding the files
# If you are using an OES server with PureFTPd, you cannot use symbolic
# links, so you must do a directory bind mount. Ex:
# mount --bind /[existing location] /[new location]
# If your existing files are in /images/backup and the new location is
# /home/backupuser/images then the command would be:
# mount --bind /images/backup /home/backupuser/images
# NOTE: As with any mount command, the mount point directory must exist
ftpdir="/backup"
# basepath = The ZEN imaging base path for the files. This is the same base path
# (without the filename) that you would type into the img application
# if you were restoring an image manually.
basepath=//$STORAGEADDR/images/backup
##--- [END Configuration section]
##--- [BEGIN additional functions]
## -- Function to display help screen
function getfilename {
## -- Create .netrc file for ftp server authentication
echo "machine $ftpserver" > /.netrc
echo " login $ftpuser" >> /.netrc
echo " password $ftppass" >> /.netrc
chmod 700 /.netrc
## -- Create FTP command file
echo "ls $ftpdir" > /tmp/ftp.cmd
echo "close" >> /tmp/ftp.cmd
echo "quit" >> /tmp/ftp.cmd
ftp $ftpserver < /tmp/ftp.cmd > /tmp/ftp.out
cat /tmp/ftp.out | awk '{print $9}' > /tmp/filelist.txt
while true; do
counter=-1
pagecount=0
filenum=""
echo "Available files to restore:"
echo
for i in $(cat /tmp/filelist.txt); do
if [ $counter -gt 0 ]; then
echo "$counter: $i"
pagecount=$(($pagecount 1))
fi
counter=$(($counter 1))
if [ $pagecount -eq $pagelen ]; then
echo
echo -n "Enter the number of the file you wish to retrieve or enter to continue: "
read filenum
if [ "$filenum" == "\n" ]; then
filenum=""
fi
if [ "$filenum" != "" ]; then
break
fi
echo
echo
echo "Available files to restore:"
echo
pagecount=0
fi
done
if [ "$filenum" == "" ]; then
echo
echo -n "Enter the number of the file you wish to retrieve: "
read filenum
fi
myfile=""
counter=-1
for i in $(cat /tmp/filelist.txt); do
if [ "$counter" -eq "$filenum" 2> /dev/null ]; then
imagename=$i
break
fi
counter=$(($counter 1))
done
if [ "$imagename" != "" ]; then
echo
read -p "Do you want to restore $imagename (y/N)? " reply
if [ `echo $reply | tr [:upper:] [:lower:]` = "y" ]; then
break
fi
fi
echo
if [ "$imagename" == "" ]; then
echo Valid file number not specified.
echo
fi
echo
done
}
## -- Function to display help screen
function syntax {
echo "Correct command syntax is:"
echo " restoreImage [partsize:SIZE] [imagename:IMAGENAME]"
echo
echo " partsize - Specify the size of the boot partition to be created in megabytes."
echo " If not specified, the entire drive will be used. ** 1 GB = 1000 MB"
echo
echo " imagename - optional parameter to specify the name of the image file to"
echo " restore. The extension .zmg is automatically added. If a file name is"
echo " not specified, you will be given a list of available image files to"
echo " choose from."
}
##--- [END additional functions]
##--- [BEGIN script]
partsize="0"
imagename=""
## Parse command line variables
for var in "$@"
do
validcmd=0
cmd=${var%%:*}
if [[ $var == *:* ]]; then
val=${var#*:}
else
val=""
fi
if $cmd == imagename; then
if "$val" != ""; then
imagename=$val
validcmd=1
fi
fi
if $cmd == help; then
syntax
exit
fi
if $validcmd == 0; then
echo "Invalid command."
echo
syntax
exit
fi
done
if [ "$imagename" == "" ]; then
getfilename
fi
## Strip the .zmg from the file name if it is there for consistency
if [ "$imagename" != "" ]; then
namelen=`expr index "$imagename" .zmg`
if [ $namelen -ne -1 ]; then
imagename=${imagename:0:$(($namelen - 1))}
fi
fi
## Delete all existing partitions
img pd-all
## Create primary partition (max size unless specified)
if [ $partsize -eq 0 ]; then
img pc1 ntfs
else
img pc1 ntfs $partsize
fi
## Download the base image
img rp $PROXYADDR "$basepath/$imagename.zmg" a1:p1
## Set first partition to be active
img pa1
## Reboot and complete the process
reboot -f
##--- [END script]