Novell Home

Renaming Managed Device Objects in ZENworks Linux Management 7

Novell Cool Solutions: Feature
By Jason Brothers

Digg This - Slashdot This

Posted: 8 Jun 2006
 

PROBLEM: With the current ZLM 7 offering there is no mechanism built in to automatically rename Managed Device objects in the case of a hostname change.

SOLUTION: This script shows the power of what a little scripting can do in your ZLM 7 environment. The provided script is limited to a certain configuration (only deals with Servers folder and managed device naming of hostname - OS), however, with a bit of imagination it could be modified to fit your environment.

This script can be placed in a Remote Execute Policy and automatically run on your ZLM Primary Server.

#!/bin/bash 
###################################################################################
# Name: rename   
# Version: 0.1
# Purpose: To rename objects based on the data contained in the database and
#   the following registration format:   hostname - ostarget
###################################################################################

######## Variables ########
#Number of days the device has last contacted.
LASTCONTACT=2
#Location where the file hibernate.cfg.xml can be found for the system.
DBCONNECT=/etc/opt/novell/zenworks/hibernate.cfg.xml
#Location where temporary work files are stored
WORKDIR=/tmp
LOCKFILE=/etc/opt/novell/zenworks/zlm-rename.lock
LOGFILE=/var/opt/novell/log/zenworks/zlm-rename.log

#Exclusion List
#Any device in this list will be excluded from the rename operations.  
#This variable has the following requirements:
#   1) Each name is terminated with a line feed (\n)
#   2) Any device that is not in the root Server folder needs to have the folder prepended
#      to the path
#   3) Slashes (/) in the path need to be escaped with five back-slashes (\).
#
# Worst case example:
#  EXCLUDED="server 1\n
#  test\\\\\/server 2\n"

EXCLUDED="server1\n
folder\\\\\/server2\n 
"

######## Functions ########

#Used to validate the credentials stored in ~.zlmanrc are present and correct.
function PassCheck {
zlman ping >/dev/null

if [ "$?" != "0" ];
then
        echo The username or password set in ~.zlmanrc
        echo Please verify the credentials in ~.zlmanrc
        exit 1
fi
}

#Setup the Database connection
function InitDB { 
#Parse the information from hibernate.xml.cfg
DBUSER=`fgrep "connection.username" $DBCONNECT |awk -F \> '{print $2}' | awk -F \< '{print $1}'`
DBPASS=`fgrep "connection.password" $DBCONNECT |awk -F \> '{print $2}' | awk -F \< '{print $1}'`
DBURL=`fgrep "connection.url" $DBCONNECT |awk -F \> '{print $2}' | awk -F \< '{print $1}'`

declare -a DBINFO=(`echo $DBURL\
        | sed 's/\/\///g' \
        |sed 's/\// /' \
        |sed 's/:/ /g' \
        | cut -d " " -f 3-`)

#DBHOST=${DBINFO[0]}
#DBPORT=${DBINFO[1]}
#DBNAME=${DBINFO[2]}

export PGPASSWORD=$DBPASS
export PGCONNECT="psql -d ${DBINFO[2]} -h ${DBINFO[0]} -p ${DBINFO[1]} -U $DBUSER"
}

#Create a file that contains a master list of the Managed Servers in the zone.
function BuildList {
#Use zlman to build the list,  remove whitespace from the output, and then printout the full path to the object.
zlman sl -r \
| sed 's/ *| */|/g' \
|sed 's/ *$//g' \
| awk -F \| '{if (match($2, "Server")>0){ print  $3 "/" $1 }}' \
| sed 's/\/Devices\/Servers\///g' > $WORKDIR/Renamelist.txt

#Remove the Excluded Servers from the file.
ScrubList $WORKDIR/Renamelist.txt
}

#Determine if there are any duplicate alias names,  if so, build the list so they can be handled.
function IdentDups {
#This will return all of the duplicate alias names.
$PGCONNECT -o $WORKDIR/RenameDUPS.txt -A -t -c "SELECT alias FROM zen_device WHERE role='Server' group by alias having ( count(alias) > 1 );"
sed -i '/^ *$/d' $WORKDIR/RenameDUPS.txt

#Remove the Excluded Servers from the file
ScrubList $WORKDIR/RenameDUPS.txt
}

#Does the work of removing the Excluded servers from the passed in file.
function ScrubList {
echo -e $EXCLUDED | sed '/^ *$/d' \
| while read line;
do
        sed -i "/$line/d" $1
done
}

#Process the duplicate alias names.  Need to cross reference the GUID stored in the DB with the Device object. 
#Duplicate entries are processed separately for two reasons:
# 1) It is necessary to perform an additional zlman query  (zlman si) to verify the correct object is being dealt with. 
#    The deviceguid value is used as a cross reference.
# 2) Compared to straight database queries, zlman si is relatively slow and the script could take a very long time on a large zone.
function ProcessDups {
cat $WORKDIR/RenameDUPS.txt | while read line;
do
#Build up the desired name for alias based on the naming rule of "hostname - ostarget".
#Return all devices with the exception of Orphans.  Only return Orphan devices that have not contacted the server in $LASTCONTACT days.
if [ -z "`echo "$line"| grep -E '^ORPHAN'`" ];
                then
                        RESULT="`$PGCONNECT -A -t -c "SELECT deviceguid, hostname || ' - ' ||  name FROM zen_device z, os_targets o WHERE z.osid=o.osid AND role='Server' AND alias='$line';"`"
                else
                        RESULT="`$PGCONNECT -A -t -c "SELECT deviceguid, hostname || ' - ' ||  name FROM zen_device z, os_targets o WHERE z.osid=o.osid AND role='Server' AND alias='$line' AND last_contact > now() - '$LASTCONTACT day'::interval;"`"
                fi

                echo "$RESULT"  \
| sed '/^ *$/d' \
| while read info;
do
       GUID=`echo "$info" | cut -d \| -f 1`
NAME=`echo "$info" | cut -d \| -f 2`

#Determine if the current value for alias matches the desired value.
        export alias=`$PGCONNECT -A -t -c "SELECT alias FROM zen_device WHERE alias!='$NAME' AND deviceguid='$GUID';"\
| sed '/^ *$/d'`

#If the desired name does not match the current name,  then rename the object with zlman.
        if [ "$alias" ];
then
grep -E "$alias$" $WORKDIR/Renamelist.txt \
| while read serverloc;
do
result=`zlman si "$serverloc"\
| grep GUID        \
| sed 's/ *| */|/g' \
| sed 's/ *$//g'    \
| cut -d \| -f 2`

if [ "$result" == "$GUID" ];
then
$DRYRUN zlman srn "$serverloc" "$NAME" | sed "s/$alias$/$alias to $NAME/" | sed '/Fatal Error:/d' >> $LOGFILE
#Should implement a case statement to catch all errors.
if [ "$?" == "101" ] && ["$alias" != "$NAME-$GUID"];
then
#Object must exist already,  retry
$DRYRUN zlman srn "$serverloc" "$NAME-$GUID" | sed "s/$alias$/$alias to $NAME-$GUID/" | sed '/Fatal Error:/d'  >> $LOGFILE
fi
fi
done
fi
done
done
}

function RenameObject {
#Rename any Managed Server object that has not contacted the server in $LASTCONTACT days.
$PGCONNECT -A -t -c "SELECT deviceguid, hostname || ' - ' ||  name FROM zen_device z, os_targets o WHERE z.osid=o.osid AND role='Server' AND (alias NOT LIKE 'ORPHAN-%' OR (alias like 'ORPHAN-%' AND last_contact > now() - '$LASTCONTACT day'::interval));"  \
| sed '/^ *$/d' \
| while read info;
do
       GUID=`echo "$info" | cut -d \| -f 1`
NAME=`echo "$info" | cut -d \| -f 2`

alias=`$PGCONNECT -A -t -c "SELECT alias FROM zen_device WHERE alias!='$NAME' AND deviceguid='$GUID';"\
| sed '/^ *$/d'`

serverloc="`grep -E "(^|/)$alias$" $WORKDIR/Renamelist.txt`"

if [ "$serverloc" ]; 
then
$DRYRUN zlman srn "$serverloc" "$NAME" | sed "s/$alias$/$alias to $NAME/" | sed '/Fatal Error:/d' >> $LOGFILE
                if [ "$?" == "101" ] && [ "$alias" != "$NAME-$GUID" ];  
               then
               #Object must exist already,  retry
$DRYRUN zlman srn "$serverloc" "$NAME-$GUID" | sed "s/$alias$/$alias to $NAME-$GUID/" | sed '/Fatal Error:/d' >> $LOGFILE
fi
               fi
done
}


######## Main Script ########
if [ "$1" ];
then
        case "$1" in
                         "--help" | "-h" )
                                        echo
                                        echo "Usage: rename <options>"
                                        echo
                                        echo "The following options are supported:"
                                        echo -e "--help, -h\t\t This help page"
                                        echo -e "--dry, -d\t\t Performs a dry run only"
                                        exit 0
                        ;;

                        "--dry" | "-d" )
                                        export DRYRUN="echo Would have performed ..."
                        ;;
                         * )
                                        echo Unknown option
                                        exit 1
                        ;;
        esac
fi

if ( set -o noclobber; echo "$$" > "$LOCKFILE") 2> /dev/null;
then
   trap 'rm -f "$LOCKFILE"; exit $?' INT TERM EXIT
echo "Process started `date`" >> $LOGFILE

PassCheck
InitDB
BuildList
IdentDups

if [ `cat $WORKDIR/RenameDUPS.txt | wc -l` -gt 0 ]; 
then
ProcessDups
fi

RenameObject
echo "Process ended `date`" >> $LOGFILE

   rm -f "$LOCKFILE"
   trap - INT TERM EXIT
else
   echo "Failed to acquire lockfile: $LOCKFILE." >> $LOGFILE
   echo "Held by $(cat $LOCKFILE)" >> $LOGFILE
fi

If you have any questions you may contact Jason at jbrothers@novell.com


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

© 2014 Novell