#!/usr/bin/perl ############################################################################### # IBM(c) 2015 EPL license http://www.eclipse.org/legal/epl-v10.html ############################################################################### # COMPONENT: mkdummyimage # # This script creates a dummy image. ############################################################################### use strict; use warnings; use File::Basename; use File::Path; use File::Spec; use File::Temp; use Getopt::Long; use MIME::Base64; use Sys::Hostname; use Socket; my $version = "1.0"; my $defaultName = 'dummy.img'; # Default image file name my $dest = ''; # Target destination (filespec) my $displayHelp = 0; # Display help information my $eckdImage = 0; # ECKD image is wanted my $fbaImage = 0; # FBA image is wanted my $remoteHost = ''; # Remote host transfer information my $remoteUser = ''; # Remote user transfer information my $verbose = 0; # Verbose flag - 0: quiet, 1: verbose my $versionOpt = 0; # Show version information flag # set the usage message my $usage_string = "Usage:\n $0 [ --eckd | --fba ] [ -V | --verbose ] [ -d | --destination ] [-R | --remotehost ]\n or\n $0 -v | --version\n or\n $0 -h | --help\n The following options are supported:\n -d | --destination File specification of the image file to be created. Either the filename only or a fully qualified name. If the destination is within the xCAT MN then it must be within the directory specified by the installdir property in the xCAT site table. The default file name is $defaultName.\n --eckd Create an empty ECKD disk image. This is the default image type if neither --eckd or --fba is specifed.\n --fba Create an empty FBA disk image\n -h | --help Display help information\n -R | --remotehost Indicates that the destination specified on the command invocation is the file specification on a host other than the management node. The 'host' operand is the IP address or DNS host name of the target server. A user may be specified in a similar way as it is specified with the SCP command using the format 'user\@host' where 'user' is the name of the user on the remote system and 'host' operand is as previously stated. The image is created in the directory specified by the tmpdir property in the site table and then moved to the remote host using SCP. After moving the image off the xCAT MN, the image is removed from the xCAT MN. Prior to specifying the command, the keystore on the remote host must be set up with the public key of the xCAT MN.\n -v | --version Display the version of this script.\n -V | --verbose Display verbose processing messages.\n"; #------------------------------------------------------- =head3 createImage Description : Create the dummy image file. Arguments : None Returns : 0 - No error non-zero - Error detected. Example : $rc = createImage(); =cut #------------------------------------------------------- sub createImage{ my $rc = 0; my $buildDir = ''; my $header; # Create a temporary directory in which to create the image. my $tmpDir = `/opt/xcat/sbin/tabdump site| grep '^"tmpdir",' | sed s/'^"tmpdir","'//g| sed s/'".*'//g`; chomp $tmpDir; if ( $tmpDir eq '' ) { print "Error: The 'tmpdir' value is missing from the site table.\n"; $rc = 11; goto FINISH_createImage; } $buildDir = mkdtemp( "$tmpDir/image.$$.XXXXXX" ); # Create the image my $imageFile = $defaultName; open( my $fh, '>', "$buildDir/$imageFile" ) or die "Could not open file '$buildDir/$imageFile'"; if ( $verbose ) { print "Creating the image in $buildDir as $imageFile.\n"; } if ( $eckdImage ) { $header = "xCAT CKD Disk Image:"; $header = "$header 0 CYL"; } elsif ( $fbaImage ) { $header = "xCAT FBA Disk Image:"; $header = "$header 0 BLK"; } $header = "$header HLen: 0055"; # Header size increased by x from 0055 $header = "$header GZIP: 0"; printf $fh "%-512s", "$header"; close( $fh ); # Move the image to the target location. if ( $remoteHost ne '' ) { # Do a remote transfer my $remoteTarget = $remoteHost . ':' . $dest; if ( $remoteUser ne '' ) { $remoteTarget = "$remoteUser\@$remoteTarget"; } my $scpVerbose = ''; if ( $verbose ) { print "Moving the image $imageFile to the remote system $remoteHost as $dest.\n"; $scpVerbose = '-v' } $rc = system( "/usr/bin/scp $scpVerbose -B $buildDir/$imageFile $remoteTarget" ); if ( $rc ) { $rc = $rc >> 8; print "Error: Unable to copy the image $buildDir/$imageFile to the remote host: $remoteHost, rc: $rc\n"; $rc = 30; goto FINISH_createImage; } } else { # Move the file to a local directory $rc = system( "cp $buildDir/$imageFile $dest" ); if ( $rc ) { $rc = $rc >> 8; print "Error: Unable to copy the image $buildDir/$imageFile to the destination: $dest, rc: $rc\n"; $rc = 40; goto FINISH_createImage; } } if ( $remoteHost ne '' ) { print "Image created on $remoteHost: $dest\n"; } else { print "Image created: $dest\n"; } FINISH_createImage: if ( -d $buildDir ) { rmtree $buildDir; } return $rc; } #------------------------------------------------------- =head3 showHelp Description : Show the help inforamtion. Arguments : None. Returns : None. Example : showHelp(); =cut #------------------------------------------------------- sub showHelp{ print "$0 prepares a special image file that contains no disk\ncontents.\n\n"; print $usage_string; return; } #***************************************************************************** # Main routine #***************************************************************************** my $rc = 0; my $out; # Parse the arguments $Getopt::Long::ignorecase = 0; Getopt::Long::Configure( "bundling" ); if (!GetOptions( 'eckd' => \$eckdImage, 'd|destination=s' => \$dest, 'fba' => \$fbaImage, 'h|help' => \$displayHelp, 'R|remotehost=s' => \$remoteHost, 'v|version' => \$versionOpt, 'V|verbose' => \$verbose )) { print $usage_string; goto FINISH_main; } if ( $versionOpt ) { print "Version: $version\n"; } if ( $displayHelp ) { showHelp(); } if ( $displayHelp or $versionOpt ) { goto FINISH_main; } if ( !$eckdImage and !$fbaImage ) { $eckdImage = 1; } if ( $remoteHost ne '' ) { $remoteHost =~ s/^\s+|\s+$//g; # trim blanks from both ends of the value my $spaceCnt = scalar( () = $remoteHost =~ /\s+/g ); if ( $spaceCnt != 0 ) { print "Error: Remote host value is not a single word.\n"; $rc = 1; goto FINISH_main; } if ( $remoteHost =~ /@/ ) { my @parts = split( /@/, $remoteHost ); if ( substr( $remoteHost, -1) eq '@' or @parts > 2 or !defined $parts[0] or $parts[0] eq '' or !defined $parts[1] or $parts[1] eq '' ) { print "Error: Remote host value is not valid.\n" . " It should be in the form of 'hostname' or 'user\@hostname'.\n"; $rc = 2; goto FINISH_main; } $remoteUser = $parts[0]; $remoteHost = $parts[1]; } else { $remoteUser = 'root'; } } # Determine the destination and make certain it is valid. my $installDir = `/opt/xcat/sbin/tabdump site| grep '^"installdir",' | sed s/'^"installdir","'//g| sed s/'".*'//g`; chomp $installDir; if ( $installDir eq '' ) { print "Error: The 'installDir' value is missing from the site table.\n"; $rc = 10; goto FINISH_main; } if ( $dest eq '' ){ # Set default destination for either a local or remote location. if ( $remoteHost eq '' ) { $dest = "$installDir/$defaultName"; } else { $dest = "$defaultName"; } } else { # Can only verify local destination here. SCP will verify the remote destination. if ( $remoteHost eq '' ) { if ( $dest !~ /\// ) { $dest = "$installDir/$dest"; } else { if ( $dest !~ /^$installDir/ ) { print "Error: The destination is not within the install directory specified in the site table.\n"; $rc = 20; goto FINISH_main; } } } } # Create the image file. createImage(); FINISH_main: exit $rc;