518 lines (513 with data), 18.1 kB
#!/usr/bin/php5
<?
/*
VMLMAT: VM Linux Management and Archival Tool.
Copyright (c) 2007, Ronnie Michael, BMC Software Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the BMC Software Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#
# lets process the clone (backup/restore) request.
# this routine supports multi-volume backups and restores.
# Due to limitations that can create, it is recommended to use single volume systems
# for the greatest interoperability between client machines and backups.
#
# Edit parmfile for the atab and ntab if your
# client VM with standard images doesn't specify
# zipl.conf file with a dasd=xx1-xxf range of device addresses
# where xx is hexadecimal number. If you use another address range adjust atab
# to map to ntab correctly.
#
# Be mindful of Linux partitioning as
# it should be consistent with your standard images since it will effect the device name
# to mount in /etc/fstab: /dev/dasda or /dev/dasda1 for example.
# Specify rpart in parmfile so that the backup/restore will know the installation's intentions
# regarding the first volume since during a backup, fstab can only be read after the first volume
# is mounted.
#
# functions
function cmslink($pfile,$samail,$cvm,$hostname,$mdf,$mdlink) {
#
# Let control vm to shutdown, logoff, and link the minidisk
#
#
touch($pfile);chmod($pfile,0777);
system('hcp msg ' . $cvm . ' link ' . $hostname . ' ' . $mdf . ' ' . $mdlink);
#lets sleep-spin until we get the post
$i=0; /* lets kill the wait if too long and notify SysAdmin as the CMS Control VM may be hung. */
while (file_exists($pfile)) {$i++;if($i=="120"){unlink($pfile);system('/var/clone/bkmail ' . $hostname . ' ' . $samail . ' 27 x');} system('sleep 1');}
#
return;
}
function cmsdetach($pfile,$samail,$cvm,$hostname,$mdlink) {
#
# Let control vm to detach the minidisk
#
touch($pfile);chmod($pfile,0777);
system('hcp msg ' . $cvm . ' detach ' . $hostname . ' ' . $mdlink);
#lets sleep-spin until we get the post
$i=0; /* lets kill the wait if too long and notify SysAdmin as the CMS Control VM may be hung. */
while (file_exists($pfile)) {$i++;if($i=="120"){unlink($pfile);system('/var/clone/bkmail ' . $hostname . ' ' . $samail . ' 27 x');} system('sleep 1');}
#
return;
}
function cmsup($pfile,$samail,$cvm,$hostname) {
#
# Let control vm to bring up the hostname
#
touch($pfile);chmod($pfile,0777);
system('hcp msg ' . $cvm . ' up ' . $hostname);
#lets sleep-spin until we get the post
$i=0; /* lets kill the wait if too long and notify SysAdmin as the CMS Control VM may be hung. */
while (file_exists($pfile)) {$i++;if($i=="120"){unlink($pfile);system('/var/clone/bkmail ' . $hostname . ' ' . $samail . ' 27 x');} system('sleep 1');}
#
return;
}
function cmsdown($pfile,$samail,$cvm,$hostname) {
#
# Let control vm to shutdown hte hostname
#
touch($pfile);chmod($pfile,0777);
system('hcp msg ' . $cvm . ' down ' . $hostname);
#lets sleep-spin until we get the post
$i=0; /* lets kill the wait if too long and notify SysAdmin as the CMS Control VM may be hung. */
while (file_exists($pfile)) {$i++;if($i=="120"){unlink($pfile);system('/var/clone/bkmail ' . $hostname . ' ' . $samail . ' 27 x');} system('sleep 1');}
#
return;
}
# this function will get all the related _volyx.tar files of the tarfile prefix
function getarcvols($files,$arcpath,$tarfile) {
$path=$arcpath . ".";
$handle=opendir($path);
while ($file = readdir($handle)) {
if ($file == "." || $file == "..") { } else {
$sln=strlen($file);
# remove the _volyx.tar
$name=substr($file,0,$sln-10);
if ($tarfile == $name) {
system('echo file is ' . $file);
$files[]=$file;
}
}
}
closedir($handle);
# we sort the array to make sure we restore starting with the first volume of Linux / mountpoint
array_multisort($files);
return $files;
}
# this function will read /etc/fstab and get all device names with /dev/dasd prefix
function readfstab($devs) {
# get device names /dev/dasda1 etc.
$filen="/mnt/new/etc/fstab";
$fp = fopen($filen, 'r' );
$file_data = fread( $fp, filesize( $filen ) );
fclose( $fp );
$lines = explode ( "\n", $file_data );
$cnt = count($lines);
for ( $i=0; $i < $cnt-1; $i++ ) {
$line=$lines[$i];
#foreach ( $lines as $line ) {
list( $devname, $dir, $options ) = preg_split("/\s+/", $line );
if (strtolower(substr($devname,0,9)) == "/dev/dasd") {$devs[]="1".$devname;}
else {
# system('echo '.$dir);
if ($dir == "/") {$devs[]="0".$devname;}
}
}
array_multisort($devs);
return $devs;
}
function cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink) {
system("chccwdev -d $mdlink");
cmsdetach($pfile,$samail,$cvm,$hostname,$mdlink);
system('/var/clone/bkmail ' . $hostname . ' ' . $samail . ' ' . $message . ' x');
system('/var/clone/bkupgen ' . $message);
return;
}
?>
<?
#main procedure
# lets define the CMS post file
$pfile="/tmp/post.txt";
# get the tarfile that was passed to this routine.
$tarfile = $argv[1];
#
# get parmfile variables needed
include 'bkinc.php';
#
# lets setup the array of mapping tables of atable to ntable.
# The following arrays map device name letters to suffix minidisk address numbers
$atable = explode ( ",", $atab );
$ntable = explode ( ",", $ntab );
#
# lets get the request info
$rfile = "reqfile.txt";
$prfile="/mnt/request/" . $rfile;
$fh = fopen($prfile, 'r');
$rdata = fgets($fh);
fclose($fh);
$strgs = explode(" ", $rdata);
/* array starts at offset zero */
$rusr=$strgs[8];
$email=$strgs[7];
$hostname=$strgs[4];
$req=$strgs[3];
#
#
# Lets shutdown the system
cmsdown($pfile,$samail,$cvm,$hostname);
# update up/down status of vm guests
system('/var/clone/bkstat');
#are we processing an autobackup?
if ($req=="5" ) {
#do we need to notify?
if ($notify=="YES") {
$message="22";
system('/var/clone/bknot ' . $hostname . ' ' . $message . ' x');
}
}
else {
$message="10";
#system('echo /var/clone/bkmail ' . $hostname . ' ' . $email . ' ' . $message . ' x');
#system('/var/clone/bkmail ' . $hostname . ' ' . $email . ' ' . $message . ' x');
}
#
# lets make sure our target mount point is umounted
system('umount /mnt/new');
#
#
# if our request is for a restore then process this block of commands
if ( $req == "0" ) {
#
# find all the vols associated with the tarfile;
$files=array();
$files=getarcvols($files,$arcpath,$tarfile);
# the output of files is sorted so the first volume is the Linux / mountpoint
$t=count($files);
if ($t == 0 && $reip == "YES" && $reipid==strtoupper($rusr)) $t=1;
system('echo t is ' . $t);
$i=0;
#get the y value of volyx.tar of the first volume (first alpha)
#$falpha=substr($files[$i],strlen($files[$i]-6,1);
# the while begins the processing of all volumes that need to be restored.
while ($t > $i) {
#
# Lets calculate the mdf address.
# get the y value of volyx.tar
#
$alpha=substr($files[$i],strlen($files[$i])-6,1);
$j=0;
$mdf=substr($mdlink,0,2).$ntable[0];
while ($j < "15") {
if ($atable[$j]==$alpha) $mdf=substr($mdlink,0,2).$ntable[$j];
$j++;
}
#
$tar=$files[$i];
# lets get the x of _volyx.tar
$fln=strlen($files[$i]);
$la=substr($files[$i],$fln-5,1);
if (intval($la) > 0) $part=$la;
else $part="0";
if ($reip == "YES" && $reipid == strtoupper($rusr) and $rpart == "1") $part="1";
#
# lets link the minidisk xxx to the mdlink value and therefore devname.
cmslink($pfile,$samail,$cvm,$hostname,$mdf,$mdlink);
#
# We need to add the /proc/dasd/devices for $mdlink our vm minidisk we will be processing
system("chccwdev -e $mdlink",$rc);
if ($rc != 0 ) {
$message="2";
system('echo "chccwdev failed"');
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
# must give time for device online
system('sleep 2');
#
if ( $reip == "YES" && $reipid == strtoupper($rusr)) {
# For re-ip we must mount then change the hostname/ip per request
# so we test for i==0 so we confirm we are also on the first volume which is
# the ipl volume.
if ($i==0)
{
# We must now mount this new filesystem on their vm minidisk
system('echo Mount the new disk:');
if ($part != "0") {
system('mount ' . $devname . $part . ' /mnt/new',$rc);}
else {
system('mount ' . $devname . ' /mnt/new',$rc);}
if ( $rc != 0 ) {
system('echo "mount failed"');
$message="6";
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
system('sleep 1');
#
# we must update the etc changes for this specific distro
# to replace hostname and ipadder info
system('echo Execute changes:');
system('/var/clone/change');
}
$message="26";
}
else {
# process as a normal restore request
# does the sys admin want
# linux to format and partition?
if ( $diskfmt == "YES" ) {
# lets start by reformatting the vm minidisk
system('echo Run dasdfmt - this will take a couple of minutes:');
system("dasdfmt -b 4096 -y -f $devname",$rc);
if ( $rc != 0 ) {
system('echo "dasdfmt failed"');
$message="3";
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
#part variable comes from parsing the _volyx of the tar file out on archive or from the rpart
#set by the installation.
if ($part != "0") {
# now lets partition it
system('echo Run fdasd:');
system("fdasd -a $devname",$rc);
if ( $rc != 0 ) {
system('echo "fdasd failed"');
$message="4";
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
}
}
#give time for processes to finish
system('sleep 2');
#
# okay now lets make a file system
system('echo Run mkfs');
#
# we need to prepare for Redhat type filelabels for the / mountpoint
# This version of VMLMAT does not currently support filelabels for any other mount point
# and instead requires the device /dev/dasdyx be used in fstab for these other mount points.
if ($i==0) $fl='-L / ';
else $fl=' ';
#
# if partition indicated then partition.
if ($part != "0") {
system($fsmake . ' -b 4096 ' . $fl . $devname . $part,$rc);}
else {
system($fsmake . ' -b 4096 ' . $fl . $devname,$rc);}
if ( $rc != 0 ) {
system('echo "mkfs failed"');
$message="5";
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
#
# We must now mount this new filesystem on their vm minidisk
system('echo Mount the new disk:');
if ($part != "0") {
system('mount ' . $devname . $part . ' /mnt/new',$rc);}
else {
system('mount ' . $devname . ' /mnt/new',$rc);}
if ( $rc != 0 ) {
system('echo "mount failed"');
$message="6";
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
#
# lets cd to our new requestors vm minidisk new system
# and begin restore of the tarfile
system('echo /var/clone/bkrtar ' . $tar . ' ' . $arcpath . ' ' . $mdlink);
system('/var/clone/bkrtar ' . $tar . ' ' . $arcpath . ' ' . $mdlink,$rc);
if ( $rc != 0 ) {
$message="13";
system('umount /mnt/new');
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
#
# are we at the first volume ?, if so, the convention is this is Linux /
# and we need this as an ipl volume
# This test could be $i==0 (first volume of our sorted array of tarfiles)
# or does the parmlib atab first entry agree with our first volume ($atable[$i]==$falpha)
# if the admin changes the parmlib for atab then falpha test will fail
# so lets work on the assumption that first volume of our sorted array of tarfiles is our
# Linux mount point.
if ($i==0) {
#
#make ready with zipl to allow system to boot
system('echo change root and run zipl:');
system('chroot /mnt/new zipl');
#
# we must update the etc changes for this specific distro
# to replace hostname and ipadder info
system('echo Execute changes:');
system('/var/clone/change');
}
}
#
# okay lets umount their system
system('echo umount /mnt/new');
system('umount /mnt/new');
system('sleep 2');
#
#then lets take the device offline at /proc/dasd/devices
system("echo chccwdev -d $mdlink");
system("chccwdev -d $mdlink");
#
# Lets detach the minidisk
cmsdetach($pfile,$samail,$cvm,$hostname,$mdlink);
# Okay this must be a backup instead so lets process this block of commands
$i++;
}
$message="8";
}
else {
# lets do a backup...
if ( $reip == "YES" && $reipid == strtoupper($rusr)) {
# For re-ip we must do nothing but create html form
$message = "25";
} else {
# Lets set the process error for backup as 0; Good backup assumed.
$perr=0;
$i=0;
# we can assume one volume system so t = 1
$t=1;
# the while begins the processing of all volumes that need to be archived.
while ($t > $i) {
# Are we are processing the first volume i = 0?
if ($i==0) {
#
# Note the code uses this logic for backups when dealing with the very first volume assumed
# to be the Linux / mountpoint:
# We have to hard code the volyx value since we have not read the fstab yet.
# Therefore, we will use the values from parmfile rpart and first entry of atab
# with the device prefix of /dev/dasd
# To setup mdf (minidisk from) address, we will use the parmfile mdlink and the first entry of ntab to
# correspond with the the first atab entry.
#
$tar=$tarfile."_vol".$atable[0].$rpart.".tar";
$mdf=substr($mdlink,0,2).$ntable[0];
# We need to know the parition requirement for this volume
# as rpart is installation specified for the first volume
$part=$rpart;
}
else {
#
# Lets calculate the tarfile name.
# get y of /dev/dasdyx
$alpha=substr($devs[$i],10,1);
# do we have a partition value on the devicename?
if (strlen($devs[$i])>11) $part=substr($devs[$i],11,1);
else $part="0";
$tar=$tarfile."_vol".$alpha.$part.".tar";
system('echo tar ' . $tar);
#
# lets now calculate the mdf
$j=0;
# lets set a default just in case
$mdf=substr($mdlink,0,2).$ntable[0];
while ($j < "15") {
if ($atable[$j]==$alpha) $mdf=substr($mdlink,0,2).$ntable[$j];
$j++;
}
}
#
# lets link the minidisk xxx to the mdlink value and therefore devname.
cmslink($pfile,$samail,$cvm,$hostname,$mdf,$mdlink);
#
# We need to add the /proc/dasd/devices for $mdlink our vm minidisk we will be processing
system("chccwdev -e $mdlink",$rc);
if ($rc != 0 ) {
$message="2";
system('echo "chccwdev failed"');
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
# must give time for device online
system('sleep 2');
#
#
#
# lets mount the requestors minidisk
system('echo Mount the new disk:');
if ($part != "0") {
system('mount ' . $devname . $part . ' /mnt/new',$rc);}
else {
system('mount ' . $devname . ' /mnt/new',$rc);}
if ( $rc != 0 ) {
$message="6";
system('echo "mount failed"');
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
#
# check to see if first volume i = 0 and mvol = yes (we support multi-volumes),
# if so we need to read fstab to see if this is a multivolume system
#
if ($i == 0 && $mvol == "YES") {
$devs=array();
$devs=readfstab($devs);
$t=count($devs);
system('echo t = ' . $t);
if ($t == 0 ) {
# unable to find at least the / mountpoint in fstab
$t=1;
system('echo multi-vol is yes but could not read this system fstab correctly');
$perr=1;
}
}
#
# okay now lets cd to the minidisk and begin the backup
system('echo /var/clone/bkbtar ' . $tar . ' ' . $arcpath . ' ' . $mdlink);
system('/var/clone/bkbtar ' . $tar . ' ' . $arcpath . ' ' . $mdlink,$rc);
if ( $rc != 0 ) {
$message="7";
system('umount /mnt/new');
cmsclean($message,$hostname,$samail,$pfile,$cvm,$hostname,$mdlink);
exit(1);
}
# okay lets umount their system
system('echo umount /mnt/new');
system('umount /mnt/new');
system('sleep 2');
#
#then lets take the device offline at /proc/dasd/devices
system("echo chccwdev -d $mdlink");
system("chccwdev -d $mdlink");
#
# Lets detach the minidisk
cmsdetach($pfile,$samail,$cvm,$hostname,$mdlink);
$i++;
}
$message="9";
}
#create backup form html
system('echo /var/clone/bkuph');
system('/var/clone/bkuph');
if ($perr != 0) $message="24";
}
#
# Both backups and restores will process these last few commands
#
#
# lets finish by bringing the system up and notify
system('echo /var/clone/bkupgen ' . $message);
system('/var/clone/bkupgen ' . $message);
?>