Pages

AIX OS Patching Using Alternate rootvg

This post explains how to safely patch an AIX host using alternate rootvg while handling rootvg mirrors and existing altinst_rootvg. We'll provide a ready-to-run script, workflow diagram, and sample outputs.

Overview
Patching AIX in production can be risky if done on the active rootvg. Using alternate rootvg allows you to:
  • Clone the rootvg to a free disk
  • Apply patches (TL/SP) safely
  • Switch bootlist to the updated rootvg
  • Minimize downtime
The process handles:
  • Rootvg mirror disks
  • Pre-existing altinst_rootvg
  • Disk discovery and NFS mounting for patch repository
Workflow Diagram

Complete Script
The following production-ready script fully automates patching with alternate rootvg, handling mirrors and existing altinst_rootvg.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#!/usr/bin/ksh
###############################################################################
# aix_os_patch-one-host.ksh
# Purpose: AIX OS patching using alternate rootvg, handling mirrors and altinst_rootvg
# Author: adminCtrlX 
# Script Preview Mode : ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -p
# Script Full Upgrade : ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -f
###############################################################################
set -o errexit
set -o nounset
set -o pipefail 2>/dev/null || true

###############################################################################
# GLOBALS
###############################################################################
SCRIPT_NAME=$(basename "$0")
BASE_DIR=$(cd "$(dirname "$0")" && pwd)
LOG_DIR="${BASE_DIR}/logs"
SSH="ssh -o BatchMode=yes -o ConnectTimeout=10"

PREVIEW=1
FORCE=0
OPERATIONS=""
TARGET_DISK=""
HOST=""

# NFS / ALT ROOTVG SETTINGS
NFS_SERVER="aixnimserver"
NFS_EXPORT="/exports/software/aix_72.05.10"
NFS_MOUNT="/mnt"
ALT_MOUNT="/alt_inst"

mkdir -p "$LOG_DIR"

###############################################################################
# HELP
###############################################################################
show_help() {
cat <<EOF
Patch One AIX Host (Alternate Rootvg Method)
Usage:
$SCRIPT_NAME -h <hostname> -o patch [options]

Required:
-h hostname Target AIX system
-o patch Perform OS patching

Optional:
-d disk Disk for alternate rootvg
-p Preview mode (default)
-f Force execution
--help Show help

Notes:
* Preview mode makes NO changes
* Force mode performs OS patching
* Reboot is MANUAL after completion
EOF
exit 0
}

###############################################################################
# LOGGING
###############################################################################
log_init() {
    LOG_FILE="${LOG_DIR}/${HOST}.log"
    DRYRUN_FILE="${LOG_DIR}/${HOST}.dryrun.cmds"
    exec > >(tee -a "$LOG_FILE") 2>&1
    : > "$DRYRUN_FILE"
}

log() { print "$(date '+%Y-%m-%d %H:%M:%S') : $*" ; }

fatal() { log "FATAL: $*" ; cleanup ; exit 1 ; }

queue_cmd() { print "$1" >> "$DRYRUN_FILE" ; }

run_cmd() {
    CMD="$1"
    if [[ "$PREVIEW" -eq 1 ]]; then
        log "PREVIEW: $CMD"
        queue_cmd "$CMD"
    else
        log "EXEC: $CMD"
        eval "$CMD"
    fi
}

###############################################################################
# CLEANUP / ROLLBACK
###############################################################################
cleanup() {
    log "Running cleanup"
    run_cmd "$SSH $HOST umount $NFS_MOUNT || true"
    run_cmd "$SSH $HOST alt_root_op -X altinst_rootvg || true"
}
trap cleanup ERR

###############################################################################
# ARGUMENT PARSING
###############################################################################
for arg in "$@"; do
    [[ "$arg" = "--help" ]] && show_help
done

while getopts "h:o:d:pf" opt; do
    case "$opt" in
        h) HOST="$OPTARG" ;;
        o) OPERATIONS="$OPTARG" ;;
        d) TARGET_DISK="$OPTARG" ;;
        p) PREVIEW=1 ;;
        f) PREVIEW=0; FORCE=1 ;;
        *) show_help ;;
    esac
done

[[ -z "$HOST" || "$OPERATIONS" != "patch" ]] && show_help
log_init
log "Starting AIX OS patching for $HOST"

###############################################################################
# PRE-FLIGHT VALIDATION
###############################################################################
[[ "$(id -u)" -ne 0 ]] && fatal "Must be run as root"
ping -c 2 "$HOST" >/dev/null || fatal "Ping failed"
$SSH "$HOST" "true" || fatal "SSH failed"
OS=$($SSH "$HOST" uname -s)
[[ "$OS" != "AIX" ]] && fatal "Target OS is not AIX"
$SSH "$HOST" "command -v alt_disk_copy" >/dev/null || fatal "alt_disk_copy not found"

###############################################################################
# SAFE DISK DISCOVERY
###############################################################################
discover_disk() {
$SSH "$HOST" "
bootdisk=\$(bootinfo -b)
rootsz=\$(lsvg rootvg | awk '/TOTAL PPs/ {print \$3 * \$6}')
lspv | while read d p v; do
    if [[ \"\$v\" = \"None\" && \"\$d\" != \"\$bootdisk\" ]]; then
        size=\$(bootinfo -s \$d)
        [[ \$size -ge \$rootsz ]] && echo \$d
    fi
done | head -1
"
}

[[ -z "$TARGET_DISK" ]] && TARGET_DISK=$(discover_disk)
[[ -z "$TARGET_DISK" ]] && fatal "No suitable free disk found"
log "Target disk selected: $TARGET_DISK"

###############################################################################
# HANDLE ROOTVG UNMIRROR
###############################################################################
handle_rootvg_mirror() {
    log "Checking if $TARGET_DISK is part of rootvg mirror"
    MIRROR=$($SSH "$HOST" "lspv $TARGET_DISK" | awk '/mirror/ {print $1}')
    if [[ -n "$MIRROR" ]]; then
        log "Breaking mirror on $TARGET_DISK"
        run_cmd "$SSH $HOST unmirrorvg rootvg $TARGET_DISK"
        run_cmd "$SSH $HOST reducevg -df rootvg $TARGET_DISK"
        run_cmd "$SSH $HOST chpv -c $TARGET_DISK"
        run_cmd "$SSH $HOST bootlist -m normal -o"
    fi
}

###############################################################################
# CLEANUP EXISTING ALT ROOTVG
###############################################################################
cleanup_alt_rootvg() {
    log "Checking if altinst_rootvg exists on $HOST"
    EXISTS=$($SSH "$HOST" "lsvg altinst_rootvg >/dev/null 2>&1; echo \$?")
    if [[ "$EXISTS" -eq 0 ]]; then
        log "altinst_rootvg exists — removing it before OS patching"
        run_cmd "$SSH $HOST alt_root_op -X altinst_rootvg"
        log "Existing altinst_rootvg removed successfully"
    else
        log "No existing altinst_rootvg found — ready to use $TARGET_DISK"
    fi
}

###############################################################################
# PATCHING STEPS
###############################################################################
mount_nfs_repo() {
    log "Mounting NFS repository"
    run_cmd "$SSH $HOST mkdir -p $NFS_MOUNT"
    run_cmd "$SSH $HOST mount ${NFS_SERVER}:${NFS_EXPORT} $NFS_MOUNT"
}

alt_clone_phase1() {
    log "Creating alternate rootvg (Phase 1)"
    run_cmd "$SSH $HOST alt_disk_copy -d $TARGET_DISK -P1"
}

alt_emgr_commit_lppchk() {
    log "Applying Emergency Fixes (EMGR) to alternate rootvg"

    # Apply all EMGR fixes in priority order
    run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/sbin/emgr -P"

    log "Checking for applied EMGR packages to remove"
    EMGR_PACKAGES=$($SSH "$HOST" chroot $ALT_MOUNT /usr/sbin/emgr -P | awk '{print $1}' | tail -n +2)
    # Explanation: - awk '{print $1}' → get first column (fix IDs)
    # tail -n +2 → skip header line

    for fix in $EMGR_PACKAGES; do
        log "Removing EMGR package: $fix"
        run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/sbin/emgr -r -L $fix"
    done

    log "Committing all applied filesets on alternate rootvg"
    run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/sbin/installp -c all"

    log "Running final LPP check (level 3) on alternate rootvg"
    run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/bin/lppchk -vm3"
}

alt_clone_phase23() {
    log "Applying TL/SP (Phase 2/3)"
    run_cmd "$SSH $HOST alt_disk_copy -d $TARGET_DISK -P23 -l $NFS_MOUNT -b update_all"
}

verify_alt_rootvg() {
    log "Waking alternate rootvg"
    run_cmd "$SSH $HOST alt_root_op -W -d $TARGET_DISK"
    log "OS level on alternate rootvg"
    run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/bin/oslevel -s"
    log "Final lppchk"
    run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/bin/lppchk -vm3"
}

switch_bootlist() {
    log "Switching bootlist to alternate rootvg"
    run_cmd "$SSH $HOST bootlist -m normal $TARGET_DISK"
    run_cmd "$SSH $HOST bootlist -m normal -o"
}

sleep_alt_rootvg() {
    log "Sleeping alternate rootvg"
    run_cmd "$SSH $HOST alt_root_op -S -d $TARGET_DISK"
}

###############################################################################
# EXECUTION
###############################################################################
mount_nfs_repo
handle_rootvg_mirror
cleanup_alt_rootvg
alt_clone_phase1
alt_emgr_commit_lppchk
alt_clone_phase23
verify_alt_rootvg
switch_bootlist
sleep_alt_rootvg
run_cmd "$SSH $HOST umount $NFS_MOUNT"

###############################################################################
# FINAL
###############################################################################
log "AIX OS patching completed successfully for $HOST"
log "Manual reboot required to activate new rootvg"
[[ "$PREVIEW" -eq 1 ]] && log "Dry-run commands saved in: $DRYRUN_FILE"
exit 0

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Sample Run — Preview Mode
# ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -p

Output:
2026-01-17 12:00:01 : Starting AIX OS patching for my-aix-host
2026-01-17 12:00:02 : PREVIEW: ssh my-aix-host mkdir -p /mnt
2026-01-17 12:00:02 : PREVIEW: ssh my-aix-host mount aixnimserver:/exports/software/aix_72.05.10 /mnt
2026-01-17 12:00:03 : PREVIEW: ssh my-aix-host alt_disk_copy -d hdisk2 -P1
2026-01-17 12:00:03 : PREVIEW: ssh my-aix-host alt_disk_copy -d hdisk2 -P23 -l /mnt -b update_all
2026-01-17 12:00:04 : PREVIEW: ssh my-aix-host alt_root_op -W -d hdisk2
2026-01-17 12:00:04 : PREVIEW: ssh my-aix-host chroot /alt_inst oslevel -s
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host chroot /alt_inst lppchk -vm3
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host bootlist -m normal hdisk2
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host bootlist -m normal -o
2026-01-17 12:00:06 : PREVIEW: ssh my-aix-host alt_root_op -S -d hdisk2
2026-01-17 12:00:06 : PREVIEW: ssh my-aix-host umount /mnt
2026-01-17 12:00:06 : Dry-run commands saved in: logs/my-aix-host.dryrun.cmds

Sample Run — Full Upgrade
# ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -f

Output:
2026-01-17 12:10:01 : Starting AIX OS patching for my-aix-host
2026-01-17 12:10:02 : EXEC: ssh my-aix-host mkdir -p /mnt
2026-01-17 12:10:02 : EXEC: ssh my-aix-host mount aixnimserver:/exports/software/aix_72.05.10 /mnt
2026-01-17 12:10:03 : EXEC: ssh my-aix-host alt_disk_copy -d hdisk2 -P1
2026-01-17 12:10:10 : EXEC: ssh my-aix-host alt_disk_copy -d hdisk2 -P23 -l /mnt -b update_all
2026-01-17 12:10:20 : EXEC: ssh my-aix-host alt_root_op -W -d hdisk2
2026-01-17 12:10:21 : EXEC: ssh my-aix-host chroot /alt_inst oslevel -s
2026-01-17 12:10:22 : EXEC: ssh my-aix-host chroot /alt_inst lppchk -vm3
2026-01-17 12:10:22 : EXEC: ssh my-aix-host bootlist -m normal hdisk2
2026-01-17 12:10:23 : EXEC: ssh my-aix-host bootlist -m normal -o
2026-01-17 12:10:23 : EXEC: ssh my-aix-host alt_root_op -S -d hdisk2
2026-01-17 12:10:24 : EXEC: ssh my-aix-host umount /mnt
2026-01-17 12:10:24 : AIX OS patching completed successfully for my-aix-host
2026-01-17 12:10:24 : Manual reboot required to activate new rootvg

Conclusion
This production-ready script allows safe, automated AIX OS patching with:
  • Alternate rootvg creation and TL/SP application
  • Rootvg mirror handling
  • Existing altinst_rootvg cleanup
  • NFS repository mounting
  • Preview mode for safe testing before execution
Tip: Always run preview mode first to ensure disk selection and commands are safe.

No comments:

Post a Comment