#!/usr/bin/ksh # # (c)Copyright 1996 Hewlett-Packard Co., All Rights Reserved. # $Header: /ignite/cold_fusion/src/server_admin/remove_release 10.10 1997/01/20 14:04:01 hmgr Exp $ # ## ## This program is run to remove all Ignite-UX files associated with ## a single HP-UX release. This tool handles both SD filesets for a ## particular release as well as any extra files/dirs generated to handle ## a release. ## ## Conventions: ## - globals are in all caps ## - locals are in all lower-case ## ## TODO: The code which decides what releases are valid is a little too ## simple. It does not allow us to specify a release which is ## only partially there. ## ###################################################################### # # Function: init_globals # # Purpose: Initializes global variables # init_globals() { # where to look for commands PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/ignite/bin:/opt/ignite/lbin # what is truth? FALSE=1 TRUE=0 # filenames MANAGE_INDEX_CMD="/opt/ignite/bin/manage_index" CFG_CLAUSE_LIST_FILE="/tmp/rem_rel_$$" # exit codes CLEAN_EXIT=0 INTERRUPT_EXIT=1 BAD_OPTION_EXIT=2 OTHER_ERROR_EXIT=3 HELP_EXIT=4 BAD_RELEASE_EXIT=5 # release designators RELEASE= DOT_RELEASE= DASH_RELEASE= VALID_RELEASES= # global modes PREVIEW=$FALSE FORCE=$FALSE VERBOSE=1 # global "to remove" lists SD_DEPOT_LIST= SD_INSTALLED_LIST= FILE_LIST= DIR_LIST= # number of cmds (rm or swremove) which have failed NUM_ERRORS=0 # temporary logfile LOG="/tmp/rem_rel_log_$$" # how to use this command USAGE=" USAGE: $MY_NAME -r |? [-c] [-d] [-i] [-o] [-f] [-p] [-q|-v] -r |? Remove items for this release. If "?" is specified, just list the releases currently installed. -c Remove the Ignite-UX tar archives and config files for the specified release. -d Remove all depots for the specified release. -f Force. Do the removal without prompting for an ok. -i Remove cfg clauses for the specified release from the INDEX file. -o Remove all OS archives for the specified release. -p Preview. Don't actually do any removals. -q Quiet. No messages are displayed unless there is an error. -v Verbose. Describe each action as it is taken. " } ###################################################################### # # Function: message # # Purpose: If VERBOSE is 0, write nothing. Otherwise, write out the # message to stdout. # # Inputs: $* messages to write # message() { if (( VERBOSE > 0 )); then printf "$*" fi } ###################################################################### # # Function: verbose # # Purpose: If VERBOSE is at its highest level (2), display the message # to stdout. Otherwise, just ignore. # # Inputs: $* messages to write # verbose() { if (( VERBOSE == 2 )); then printf "$*" fi } ###################################################################### # # Function: cleanup_exit # # Purpose: to cleanup the system before exiting # # Inputs: $1 is the internal exit code # $2 is the error string # # Output: error or finish message # cleanup_exit() { ## # Type some locals. ## trap 1 2 3 15 typeset exit_code typeset mesg ## # Set up the exit code. ## exit_code=$1 ## # Set up the correct message(s) to display. ## case $exit_code in $CLEAN_EXIT) ;; $INTERRUPT_EXIT) mesg="WARNING: Exiting due to user interrupt." ;; $BAD_OPTION_EXIT) mesg="ERROR: $2 Run $MY_NAME -? for help. " ;; $OTHER_ERROR_EXIT) mesg="ERROR: $2" ;; $HELP_EXIT) print -u2 "$USAGE" ;; $BAD_RELEASE_EXIT) print -u2 "ERROR: Invalid (or no) release specified." show_valid_releases ;; esac ## # Write the message if there is one. ## if [[ -n "$mesg" ]]; then print -u2 "$mesg" fi ## # If a log file exists, remove it. ## if [[ -f $LOG ]]; then rm -f $LOG fi ## # If a cfg file clause list file exists, remove it. ## if [[ -f $CFG_CLAUSE_LIST_FILE ]]; then rm -f $CFG_CLAUSE_LIST_FILE fi ## # Exit with the appropriate status. ## exit $exit_code } ###################################################################### # # Function: get_valid_releases # # Purpose: Build a list of valid releases. The list is just the dirs # found in /opt/ignite/data which are Rel_*. # # Inputs: None. # # Output: None. Does set the global VALID_RELEASES. get_valid_releases() { ## # Make sure the /opt/ignite/data directory exists. Build a list of # all Rel_* directories that are found there. ## if [[ -d /opt/ignite/data ]]; then for i in `ls /opt/ignite/data/ 2>/dev/null`; do case $i in Rel_*) if [[ -d "/opt/ignite/data/$i" ]]; then VALID_RELEASES="$VALID_RELEASES ${i#Rel_}" fi ;; *) ;; esac done fi } ###################################################################### # # Function: show_valid_releases # # Purpose: Shows the list of valid releases. # # Inputs: None. Does use the global VALID_RELEASES. # # Output: A formatted list. show_valid_releases() { print -u2 "Here are the valid releases currently present on the system:" for rel in $VALID_RELEASES; do print -u2 " $rel" done } ###################################################################### # # Function: get_archives # # Purpose: Build a list of the OS archives for this release. # # Inputs: None. # # Output: Add to the appropriate global lists of things to remove. get_archives() { ## # Check for the SD fileset OS-Archive-{arch}.OS-Arch-{release} ## for i in `swlist -l fileset OS-Archive-\*.OS-Arch-$DASH_RELEASE 2>/dev/null | grep -v "^#" | grep -v "^$" | awk ' { print $1} '`; do SD_INSTALLED_LIST="$SD_INSTALLED_LIST $i" done } ###################################################################### # # Function: get_fusion # # Purpose: Build a list of the Ignite-UX tar archives and config files # for this release. # # Inputs: None. # # Output: Add to the appropriate global lists of things to remove. get_fusion() { ## # Check for the SD fileset Ignite-UX.FILE-SRV-relname ## for i in `swlist -l fileset Ignite-UX.FILE-SRV-$DASH_RELEASE 2>/dev/null | grep -v "^#" | grep -v "^$" | awk ' { print $1} '`; do SD_INSTALLED_LIST="$SD_INSTALLED_LIST $i" done ## # Check for anything else in /opt/ignite/data/Rel_relname. ## if [[ -d "/opt/ignite/data/Rel_$RELEASE" ]]; then DIR_LIST="$DIR_LIST /opt/ignite/data/Rel_$RELEASE" for i in `ls -1 /opt/ignite/data/Rel_$RELEASE/* 2>/dev/null`; do FILE_LIST="$FILE_LIST $i" done fi ## # Check for anything else in /var/opt/ignite/data/Rel_relname. ## if [[ -d "/var/opt/ignite/data/Rel_$RELEASE" ]]; then DIR_LIST="$DIR_LIST /var/opt/ignite/data/Rel_$RELEASE" for i in `ls -1 /var/opt/ignite/data/Rel_$RELEASE/* 2>/dev/null`; do FILE_LIST="$FILE_LIST $i" done fi } ###################################################################### # # Function: get_index # # Purpose: Build a list of the cfg clauses for this release. # # Output: Add to the appropriate global lists of things to remove. get_index() { ## # Build the list of Ignite-UX cfg clauses. ## $MANAGE_INDEX_CMD -l -r $RELEASE > $CFG_CLAUSE_LIST_FILE } ###################################################################### # # Function: get_depots # # Purpose: Build a list of the Ignite-UX depots for this release. # # Inputs: None. # # Output: Add to the appropriate global lists of things to remove. get_depots() { ## # Check for the SD depots in: # /var/opt/ignite/depots/Rel_relname* ## for i in `swlist -l depot 2>/dev/null | grep -v "^#" | grep -v "^$"`; do case $i in /var/opt/ignite/depots/Rel_$RELEASE*) SD_DEPOT_LIST="$SD_DEPOT_LIST $i" ;; *) ;; esac done } ###################################################################### # # Function: show_removal_items # # Purpose: Displays a list of items which may be removed. # # Inputs: None. # # Output: A formatted list of all item to be removed (by type). show_removal_items() { ## # Display the appropriate header message. ## if (( PREVIEW == TRUE )); then message "\nIf you had not specified -p, the following objects would have been removed:\n" else message "\nThe following objects are selected for removal:\n" fi ## # Handle SD depots. ## if [[ -n "$SD_DEPOT_LIST" ]]; then message "\n SD depots:\n" for i in $SD_DEPOT_LIST; do message " $i\n" done fi ## # Handle installed SD software. ## if [[ -n "$SD_INSTALLED_LIST" ]]; then message "\n Installed SD products/filesets:\n" for i in $SD_INSTALLED_LIST; do message " $i\n" done fi ## # Handle other directories. ## if [[ -n "$DIR_LIST" ]]; then message "\n Directories:\n" for i in $DIR_LIST; do message " $i\n" done fi ## # Handle other files. ## if [[ -n "$FILE_LIST" ]]; then message "\n Files:\n" for i in $FILE_LIST; do message " $i\n" done fi ## # Handle cfg clauses. ## if [[ -s "$CFG_CLAUSE_LIST_FILE" ]]; then message "\n INDEX file cfg clauses:\n" pr -o4 -t $CFG_CLAUSE_LIST_FILE fi } ###################################################################### # # Function: do_cmd # # Purpose: Depending on what options have been set, this either # runs the passed-in command, displays what command to run, # or both. # # Inputs: $* - the command string to run # # Output: Displays the command string (unless "quiet"). If verbose or # if there is an error, display the stdout/stderr from the # command itself. do_cmd() { ## # Handle preview mode. ## if (( PREVIEW == TRUE )); then message " $*\n" return fi ## # Otherwise, execute the command. If verbose is high, print out a # description of what is going on and give the results from the cmd. ## message " $*\n" if (( VERBOSE == 2 )); then eval $* 2>&1 else rm -f $LOG eval $* >$LOG 2>&1 fi ## # If there was a failure, report what happened and go on. ## if (( $? != 0 )) ; then ((NUM_ERRORS = NUM_ERRORS + 1)) if (( VERBOSE == 2 )); then print -u2 "ERROR: Command failed as described above." else if (( VERBOSE == 0 )); then print -u2 "\n ERROR: The command: \"$*\" failed." else print -u2 "\n ERROR: This command failed." fi print -u2 " This is the output from the command:" pr -o8 -t $LOG fi fi } ###################################################################### # # Function: remove_items # # Purpose: Removes the (previously built) lists of items. Handle # preview mode here. # # Errors in the removal commands will be displayed by do_cmd # but they will not cause the script to quit. # # Output: Display a marker for the beginning of the removal process # as well as status indicators for each of the commands # executed. remove_items() { ## # Display the start message. ## if (( PREVIEW == TRUE )); then message "\n\nIf you had not specified -p, the following commands would have been executed:\n" else message "\n\nStarting the removal process:\n" fi ## # Handle SD depots. ## if [[ -n "$SD_DEPOT_LIST" ]]; then message "\n Removing SD depots:\n" for i in $SD_DEPOT_LIST; do do_cmd "swremove -d \"*\" @ $i" done fi ## # Handle installed SD software. ## if [[ -n "$SD_INSTALLED_LIST" ]]; then message "\n Removing installed SD products/filesets:\n" do_cmd "swremove $SD_INSTALLED_LIST" fi ## # Handle other files. ## if [[ -n "$FILE_LIST" ]]; then message "\n Removing other files:\n" for i in $FILE_LIST; do do_cmd "rm -f $i" done fi ## # Handle other directories. ## if [[ -n "$DIR_LIST" ]]; then message "\n Removing other directories:\n" do_cmd "rm -rf $DIR_LIST" fi ## # Handle cfg clauses. ## if [[ -s "$CFG_CLAUSE_LIST_FILE" ]]; then message "\n Removing INDEX file cfg clauses:\n" do_cmd "$MANAGE_INDEX_CMD -d -r $RELEASE" fi } ##################################################################### # Main Program ##################################################################### ## # Set up global variables and prepare for signals from user. ## MY_NAME="$(basename $0)" init_globals trap 'cleanup_exit $INTERRUPT_EXIT' 1 2 3 15 ## # Set up the defaults for the basic modes. ## archive_mode=$FALSE depot_mode=$FALSE index_mode=$FALSE fusion_mode=$FALSE ## # Make sure that this is root. If not, blow off now. ## case $(id) in uid=0*) : # user is root ;; *) cleanup_exit $OTHER_ERROR_EXIT "Must be root to run $MY_NAME." ;; esac ## # Parse the command line. ## while getopts :cdfiopqr:v opt do case $opt in c) fusion_mode=$TRUE ;; d) depot_mode=$TRUE ;; i) index_mode=$TRUE ;; o) archive_mode=$TRUE ;; r) RELEASE=$OPTARG ;; f) FORCE=$TRUE if (( PREVIEW == TRUE )); then cleanup_exit $BAD_OPTION_EXIT "Cannot specify both -p and -f." fi ;; p) PREVIEW=$TRUE if (( FORCE == TRUE )); then cleanup_exit $BAD_OPTION_EXIT "Cannot specify both -p and -f." fi if (( VERBOSE == 0 )); then cleanup_exit $BAD_OPTION_EXIT "Cannot specify both -p and -q." fi ;; q) if (( VERBOSE == 2 )); then cleanup_exit $BAD_OPTION_EXIT "Cannot specify both -q and -v." fi if (( PREVIEW == TRUE )); then cleanup_exit $BAD_OPTION_EXIT "Cannot specify both -p and -q." fi VERBOSE=0 ;; v) if (( VERBOSE == 0 )); then cleanup_exit $BAD_OPTION_EXIT "Cannot specify both -q and -v." fi VERBOSE=2 ;; :) cleanup_exit $BAD_OPTION_EXIT "Must specify a parm with -$OPTARG." ;; \?) cleanup_exit $HELP_EXIT ;; esac done ## # If no operations were specified, default to all. ## if ( (( archive_mode == FALSE )) && (( depot_mode == FALSE )) && (( fusion_mode == FALSE )) && (( index_mode == FALSE )) ); then archive_mode=$TRUE depot_mode=$TRUE fusion_mode=$TRUE index_mode=$TRUE fi ## # Make sure a release was specified and either exists or was "?". If it # is "?", go ahead and handle it here and then exit. ## get_valid_releases if [[ "$RELEASE" = "?" ]]; then show_valid_releases cleanup_exit $CLEAN_EXIT else found=$FALSE for i in $VALID_RELEASES; do if [[ "$i" = "$RELEASE" ]]; then found=$TRUE break fi done if (( found == FALSE )); then cleanup_exit $BAD_RELEASE_EXIT fi fi ## # Figure out the various forms of the release we'll need and # stick them in globals. ## DOT_RELEASE=${RELEASE#[A-Z]\.} DASH_RELEASE=`echo $DOT_RELEASE | tr "." "-"` ## # If we are missing essential commands, exit now. ## whence swlist >/dev/null if (( $? != 0 )); then cleanup_exit $OTHER_ERROR_EXIT "Could not find the swlist command!" fi whence swremove >/dev/null if (( $? != 0 )); then cleanup_exit $OTHER_ERROR_EXIT "Could not find the swremove command!" fi if [[ ! -x $MANAGE_INDEX_CMD ]]; then cleanup_exit $OTHER_ERROR_EXIT "Could not find the manage_index command!" fi ## # Load up what to remove depending on the options given. ## if (( archive_mode == TRUE )); then get_archives fi if (( depot_mode == TRUE )); then get_depots fi if (( fusion_mode == TRUE )); then get_fusion fi if (( index_mode == TRUE )); then get_index fi ## # Show what is about to be removed. ## show_removal_items ## # Prompt to go on unless: # - this is PREVIEW -or- # - this is FORCE ## if (( PREVIEW == FALSE && FORCE == FALSE )); then echo "\nDo you wish to proceed with the removal? (y/n) [n] \c" read yn if [[ ! "$yn" = "y" ]]; then echo "No removals will be done." cleanup_exit $CLEAN_EXIT fi fi ## # Go ahead and do the removals (or just display what we would do if # preview was specified). ## remove_items ## # Print a message to tell how things went. Always print a summary if there # were any errors. If quiet (-q) was specified, don't show a success # message. ## if (( NUM_ERRORS > 0 )); then echo cleanup_exit $OTHER_ERROR_EXIT "$NUM_ERRORS of the removal commands failed.\n" elif (( PREVIEW != TRUE )); then message "\nAll of the removal commands completed successfully.\n" fi ## # Exit with normal status. ## cleanup_exit $CLEAN_EXIT