#!/usr/bin/perl # # This script is used in disaster recovery to rebuild the # non-rootvg volume groups and volumes on a system. The output # of this script is a script that will run the required mklv and # crfs commands needed to duplicate a systems file system structure. # # This script needs to be run prior to a disaster in order to # produce the volume creation script. The volume creation script # requires some manual editing in order to adapt to the specific # hardware being used for recovery. In the event of a real recovery # the disk names and sizes will differ from the original system # configuration, which requires that the mklv commands be manually # edited. # # Andy Welter - ajw8 # MeadWestvaco # February 2005 # Version 1.4 # v1.4 NOTE: use "lsfs" to get nbpi, frag size, bf, and other file system parms. # v1.3 NOTE: added jfslog and jfs2log volume support. Fixed $lps vs $pps bug. # v1.2 NOTE: fixed file system type error with mklv. Changed output comments. # sub getfsparms { # # Use lsfs to determine the parameters used in creating the file system. my ($fsname)=@_; my $commandOptions=""; my $parms=`lsfs -cq $fsname | tail -1`; chomp $parms; $parms=~s/[\(\)]//g; @parmList=split /:/,$parms; foreach $option (@parmList) { @parsed=split /\s+/,$option; if ($parsed [0] eq "frag" ) { $commandOptions=$commandOptions . " -a frag=$parsed[2]"; } elsif ( $parsed [0] eq "nbpi" ) { $commandOptions=$commandOptions . " -a nbpi=$parsed[1]"; } elsif ( $parsed [0] eq "compress" ) { $commandOptions=$commandOptions . " -a compress=$parsed[1]"; } elsif ( $parsed [0] eq "ag" ) { $commandOptions=$commandOptions . " -a ag=$parsed[1]"; } elsif ( $parsed [0] eq "logname" ) { $commandOptions=$commandOptions . " -a logname=$parsed[1]"; }; }; return $commandOptions; }; $scriptOutput=$ARGV[0]; if ( $scriptOutput ne "" ) { if ( -f $scriptOutput ) { rename ($scriptOutput,"$scriptOutput.old"); }; open (SCRIPT, ">$scriptOutput") || die "cannot write output file $scriptOutput\n"; select SCRIPT; }; open (LSVG, "lsvg |") || die "cannot get vglist\n"; while ( $_ = ) { chomp; if ( $_ ne "rootvg" ) { push (@vglist, $_); }; }; close LSVG; print "#!/usr/bin/ksh\n"; print "## ## This script auto generated by /root/createVgCloneScript ## Edit this script as needed, and run it to recreate ## non-rootvg volume groups and file systems. ##\n"; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime (time); printf ("## Created: %02d/%02d/%04d %02d:%02d:%02d \n", $mon+1, $mday, $year+1900, $hour, $min, $sec); print "echo 'script to clone volume groups:'\n"; print "echo \"@vglist\"\n\n"; print "echo 'Create Volume groups:'\n"; print "echo 'edit script to add physical volumes to each mkvg command'\n"; print "echo 'ex: mkvg -f -y myvgname hdisk1 hdisk2'\n"; print "\n"; print "echo 'NOTE: once this script has been edited with the proper hdisks,'\n"; print "echo ' remove the exit statement from the script so it will run'\n"; print "#################################################\n"; print "## REMOVE THIS EXIT AFTER EDITING MKLV COMMANDS:\n"; print "#################################################\n"; print "exit 1\n\n\n"; foreach $vg (@vglist) { print "# volume group: $vg\n"; open (VGINFO, "lsvg $vg |") ||die "cannot get vginfo for $vg\n"; while ($_ = ) { chomp; @info=split (/\s+/); if ( m/^VG STATE/ ) { $ppSize{$vg}=$info[5]; } elsif ( m/^ACTIVE PVs/) { $vgActive{$vg} = $info[5]; } elsif ( m/TOTAL PPs/) { $vgSize{$vg}="$info[5] $info[6] $info[7]"; } elsif ( m/USED PPs/) { $vgUsed{$vg}="$info[4] $info[5] $info[6]"; }; }; if ( $vgActive {$vg} ne "yes" ) { $noStart="-n"; } else { $noStart=""; }; print ("#####################\n"); print ("# CREATE $vg\n"); print ("# ORIGINAL SIZE: $vgSize{$vg}\n"); print ("# ORIGINAL USED: $vgUsed{$vg}\n"); print ("# mkvg -f -s $ppSize{$vg} $noStart -y $vg \n"); close VGINFO; }; foreach $vg (@vglist) { # # Create jfs and jfs2 log volumes. Need to do this before we # create the file systems. # open (LVLIST, "lsvg -l $vg | tail +3 |") || die "cannot get lvlist for $vg\n"; while ( $_ = ) { ($volname, $type, $lps, $pps, $pvs, $state, $mount) = split /\s+/; if ($type eq "jfslog" || $type eq "jfs2log") { $logType=$type; $logType=~s/log//; print "#\n# $logType log file.\n"; print "mklv -t $type -y $volname $vg $lps\n"; print "logform -V $logType /dev/$volname\n"; }; }; close LVLIST; open (LVLIST, "lsvg -l $vg | tail +3 |") || die "cannot get lvlist for $vg\n"; while ( $_ = ) { ($volname, $type, $lps, $pps, $pvs, $state, $mount) = split /\s+/; if ($type eq "jfs" || $type eq "jfs2" || $type eq "paging") { push (@fsList, $mount); $lvInfo {$vg} = "$type $lps $mount"; if ( $type eq paging ) { print "mkps -s $lps -t lv $vg\n"; } else { $fsParms=getfsparms($mount); # convert number of PPs to number of # 512 byte blocks $fsSize=$lps * $ppSize{$vg} * 2048; print "#\n# $mount file system size = $fsSize bytes\n"; print "lsfs $mount 2> /dev/null >&2\n"; print "if [ \$? -eq 0 ]; then\n\trmfs $mount\nfi\n"; print "mklv -t $type -y $volname $vg $lps\n"; print "crfs -v $type -A yes -d $volname $fsParms -m $mount\n" }; }; }; close LVLIST; }; # # Sort the file systems by mount point name. Mount points # need to be created, and hierarchical file systems need to # be mounted in the proper order in order to create the # sub directory mount points. print "\n##\n## Create mount points and mount file systems\n##\n"; @fsList=sort @fsList; foreach $fs (@fsList) { print "if [ ! -d $fs ]; then\n"; print " mkdir -p $fs\n"; print "fi\n"; print "mount $fs\n"; };