Cool Solutions

Renaming Managed Device Objects in ZENworks Linux Management 7

coolguys

By:

June 8, 2006 12:00 am

Reads: 3911

Comments:0

Score:0

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

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

Categories: Uncategorized

Disclaimer: This content is not supported by Novell. It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test it thoroughly before using it in a production environment.

Comment

RSS