mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4443 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			1481 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			1481 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head1
 | 
						|
 | 
						|
	xCAT plugin package to handle z/VM
 | 
						|
	Supported command:
 | 
						|
		zvm->zvm
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
package xCAT_plugin::zvm;
 | 
						|
use xCAT::zvmUtils;
 | 
						|
use xCAT::zvmCPUtils;
 | 
						|
use xCAT::MsgUtils;
 | 
						|
use Sys::Hostname;
 | 
						|
use xCAT::Table;
 | 
						|
use xCAT::Utils;
 | 
						|
use Getopt::Long;
 | 
						|
use strict;
 | 
						|
use warnings;
 | 
						|
 | 
						|
# If this line is not included, you get:
 | 
						|
# /opt/xcat/lib/perl/xCAT_plugin/zvm.pm did not return a true value
 | 
						|
1;
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3  handled_commands
 | 
						|
 | 
						|
	Return list of commands handled by this plugin
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
sub handled_commands {
 | 
						|
	return {
 | 
						|
		rpower => "zvm",
 | 
						|
		rinv   => "zvm",
 | 
						|
		mkvm   => "zvm",
 | 
						|
		rmvm   => "zvm",
 | 
						|
		lsvm   => "zvm",
 | 
						|
		chvm   => "zvm",
 | 
						|
		rscan  => "zvm",
 | 
						|
	};
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3  preprocess_request
 | 
						|
 | 
						|
	Check and setup for hierarchy 
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub preprocess_request {
 | 
						|
	my $req      = shift;
 | 
						|
	my $callback = shift;
 | 
						|
 | 
						|
	# Hash array
 | 
						|
	my %sn;
 | 
						|
 | 
						|
	# Scalar variable
 | 
						|
	my $sn;
 | 
						|
 | 
						|
	# Array
 | 
						|
	my @requests;
 | 
						|
 | 
						|
	# If already preprocessed, go straight to request
 | 
						|
	if ( $req->{_xcatpreprocessed}->[0] == 1 ) { return [$req]; }
 | 
						|
	my $nodes   = $req->{node};
 | 
						|
	my $service = "xcat";
 | 
						|
 | 
						|
	# Find service nodes for requested nodes
 | 
						|
	# Build an individual request for each service node
 | 
						|
	if ($nodes) {
 | 
						|
		$sn = xCAT::Utils->get_ServiceNode( $nodes, $service, "MN" );
 | 
						|
 | 
						|
		# Build each request for each service node
 | 
						|
		foreach my $snkey ( keys %$sn ) {
 | 
						|
			my $n = $sn->{$snkey};
 | 
						|
			print "snkey=$snkey, nodes=@$n\n";
 | 
						|
			my $reqcopy = {%$req};
 | 
						|
			$reqcopy->{node}                   = $sn->{$snkey};
 | 
						|
			$reqcopy->{'_xcatdest'}            = $snkey;
 | 
						|
			$reqcopy->{_xcatpreprocessed}->[0] = 1;
 | 
						|
			push @requests, $reqcopy;
 | 
						|
		}
 | 
						|
 | 
						|
		return \@requests;
 | 
						|
	}
 | 
						|
	else {
 | 
						|
 | 
						|
		# Input error
 | 
						|
		my %rsp;
 | 
						|
		my $rsp;
 | 
						|
		$rsp->{data}->[0] = "Input noderange missing. Useage: zvm <noderange> \n";
 | 
						|
		xCAT::MsgUtils->message( "I", $rsp, $callback, 0 );
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3  process_request
 | 
						|
 | 
						|
	Process the command.  This is the main call.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub process_request {
 | 
						|
	my $request  = shift;
 | 
						|
	my $callback = shift;
 | 
						|
	my $nodes    = $request->{node};
 | 
						|
	my $command  = $request->{command}->[0];
 | 
						|
	my $args     = $request->{arg};
 | 
						|
	my $envs     = $request->{env};
 | 
						|
	my %rsp;
 | 
						|
	my $rsp;
 | 
						|
	my @nodes = @$nodes;
 | 
						|
	my $host  = hostname();
 | 
						|
 | 
						|
	# In order for any SSH command to be sent, you will need to run
 | 
						|
	# xdsh [group | node] -K
 | 
						|
 | 
						|
	# Directory where executables are
 | 
						|
	$::DIR = "/opt/zhcp/bin";
 | 
						|
 | 
						|
	# Process ID for fork()
 | 
						|
	my $pid;
 | 
						|
 | 
						|
	# Child process IDs
 | 
						|
	my @children;
 | 
						|
 | 
						|
	# Controls the power for a single or range of nodes
 | 
						|
	if ( $command eq "rpower" ) {
 | 
						|
		foreach (@nodes) {
 | 
						|
			$pid = fork();
 | 
						|
 | 
						|
			# Parent process
 | 
						|
			if ($pid) {
 | 
						|
				push( @children, $pid );
 | 
						|
			}
 | 
						|
 | 
						|
			# Child process
 | 
						|
			elsif ( $pid == 0 ) {
 | 
						|
				powerVM( $callback, $_, $args );
 | 
						|
 | 
						|
				# Exit process
 | 
						|
				exit(0);
 | 
						|
			}
 | 
						|
			else {
 | 
						|
 | 
						|
				# Ran out of resources
 | 
						|
				die "Error: Could not fork\n";
 | 
						|
			}
 | 
						|
 | 
						|
		}    # End of foreach
 | 
						|
	}    # End of case
 | 
						|
 | 
						|
	# Remote hardware inventory
 | 
						|
	elsif ( $command eq "rinv" ) {
 | 
						|
		foreach (@nodes) {
 | 
						|
			$pid = fork();
 | 
						|
 | 
						|
			# Parent process
 | 
						|
			if ($pid) {
 | 
						|
				push( @children, $pid );
 | 
						|
			}
 | 
						|
 | 
						|
			# Child process
 | 
						|
			elsif ( $pid == 0 ) {
 | 
						|
				inventoryVM( $callback, $_, $args );
 | 
						|
 | 
						|
				# Exit process
 | 
						|
				exit(0);
 | 
						|
			}
 | 
						|
			else {
 | 
						|
 | 
						|
				# Ran out of resources
 | 
						|
				die "Error: Could not fork\n";
 | 
						|
			}
 | 
						|
 | 
						|
		}    # End of foreach
 | 
						|
	}    # End of case
 | 
						|
 | 
						|
	# Creates zVM virtual server
 | 
						|
	elsif ( $command eq "mkvm" ) {
 | 
						|
		foreach (@nodes) {
 | 
						|
 | 
						|
			$pid = fork();
 | 
						|
 | 
						|
			# Parent process
 | 
						|
			if ($pid) {
 | 
						|
				push( @children, $pid );
 | 
						|
			}
 | 
						|
 | 
						|
			# Child process
 | 
						|
			elsif ( $pid == 0 ) {
 | 
						|
 | 
						|
				# Determine if the argument is a node
 | 
						|
				my $ans = 'FALSE';
 | 
						|
				if ( $args->[0] ) {
 | 
						|
					$ans = xCAT::zvmUtils->isZvmNode( $args->[0] );
 | 
						|
				}
 | 
						|
 | 
						|
				# If it is a node -- then clone specified node
 | 
						|
				if ( $ans eq 'TRUE' ) {
 | 
						|
					cloneVM( $callback, $_, $args );
 | 
						|
				}
 | 
						|
 | 
						|
				# If it is not a node -- then create node based on directory entry
 | 
						|
				# Or create a NOLOG if no entry is provided
 | 
						|
				else {
 | 
						|
					makeVM( $callback, $_, $args );
 | 
						|
				}
 | 
						|
 | 
						|
				# Exit process
 | 
						|
				exit(0);
 | 
						|
			}    # End of elsif
 | 
						|
			else {
 | 
						|
 | 
						|
				# Ran out of resources
 | 
						|
				die "Error: Could not fork\n";
 | 
						|
			}
 | 
						|
 | 
						|
		}    # End of foreach
 | 
						|
	}    # End of case
 | 
						|
 | 
						|
	# Removes zVM virtual server
 | 
						|
	elsif ( $command eq "rmvm" ) {
 | 
						|
		foreach (@nodes) {
 | 
						|
			$pid = fork();
 | 
						|
 | 
						|
			# Parent process
 | 
						|
			if ($pid) {
 | 
						|
				push( @children, $pid );
 | 
						|
			}
 | 
						|
 | 
						|
			# Child process
 | 
						|
			elsif ( $pid == 0 ) {
 | 
						|
				removeVM( $callback, $_ );
 | 
						|
 | 
						|
				# Exit process
 | 
						|
				exit(0);
 | 
						|
			}
 | 
						|
			else {
 | 
						|
 | 
						|
				# Ran out of resources
 | 
						|
				die "Error: Could not fork\n";
 | 
						|
			}
 | 
						|
 | 
						|
		}    # End of foreach
 | 
						|
	}    # End of case
 | 
						|
 | 
						|
	# Lists zVM user directory entry
 | 
						|
	elsif ( $command eq "lsvm" ) {
 | 
						|
		foreach (@nodes) {
 | 
						|
			$pid = fork();
 | 
						|
 | 
						|
			# Parent process
 | 
						|
			if ($pid) {
 | 
						|
				push( @children, $pid );
 | 
						|
			}
 | 
						|
 | 
						|
			# Child process
 | 
						|
			elsif ( $pid == 0 ) {
 | 
						|
				listVM( $callback, $_ );
 | 
						|
 | 
						|
				# Exit process
 | 
						|
				exit(0);
 | 
						|
			}
 | 
						|
			else {
 | 
						|
 | 
						|
				# Ran out of resources
 | 
						|
				die "Error: Could not fork\n";
 | 
						|
			}
 | 
						|
 | 
						|
		}    # End of foreach
 | 
						|
	}    # End of case
 | 
						|
 | 
						|
	# Changes zVM user directory entry
 | 
						|
	elsif ( $command eq "chvm" ) {
 | 
						|
		foreach (@nodes) {
 | 
						|
			$pid = fork();
 | 
						|
 | 
						|
			# Parent process
 | 
						|
			if ($pid) {
 | 
						|
				push( @children, $pid );
 | 
						|
			}
 | 
						|
 | 
						|
			# Child process
 | 
						|
			elsif ( $pid == 0 ) {
 | 
						|
				changeVM( $callback, $_, $args );
 | 
						|
 | 
						|
				# Exit process
 | 
						|
				exit(0);
 | 
						|
			}
 | 
						|
			else {
 | 
						|
 | 
						|
				# Ran out of resources
 | 
						|
				die "Error: Could not fork\n";
 | 
						|
			}
 | 
						|
 | 
						|
		}    # End of foreach
 | 
						|
	}    # End of case
 | 
						|
 | 
						|
	# Collects node information from one or more hardware control points.
 | 
						|
	elsif ( $command eq "rscan" ) {
 | 
						|
		foreach (@nodes) {
 | 
						|
			$pid = fork();
 | 
						|
 | 
						|
			# Parent process
 | 
						|
			if ($pid) {
 | 
						|
				push( @children, $pid );
 | 
						|
			}
 | 
						|
 | 
						|
			# Child process
 | 
						|
			elsif ( $pid == 0 ) {
 | 
						|
				scanVM( $callback, $_ );
 | 
						|
 | 
						|
				# Exit process
 | 
						|
				exit(0);
 | 
						|
			}
 | 
						|
			else {
 | 
						|
 | 
						|
				# Ran out of resources
 | 
						|
				die "Error: Could not fork\n";
 | 
						|
			}
 | 
						|
 | 
						|
		}    # End of foreach
 | 
						|
	}    # End of case
 | 
						|
 | 
						|
	# Wait for all processes to end
 | 
						|
	foreach (@children) {
 | 
						|
		waitpid( $_, 0 );
 | 
						|
	}
 | 
						|
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   removeVM
 | 
						|
 | 
						|
	Description	: Removes server
 | 
						|
    Arguments	: Node
 | 
						|
    Returns		: Nothing
 | 
						|
    Example		: removeVM($node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub removeVM {
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $node ) = @_;
 | 
						|
 | 
						|
	# Get HCP
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'hcp' );
 | 
						|
	if ( !$hcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node HCP" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get node userID
 | 
						|
	my $userId = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'userid' );
 | 
						|
	if ( !$userId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Power off userID
 | 
						|
	my $out = `ssh $hcp $::DIR/stopvs $userId`;
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
 | 
						|
	# Get device address for each MDISK
 | 
						|
	my @mdisks = xCAT::zvmUtils->getMdisks( $callback, $node );
 | 
						|
	my @parms;
 | 
						|
	my $addr;
 | 
						|
	foreach (@mdisks) {
 | 
						|
		@parms = split( ' ', $_ );
 | 
						|
		$addr  = $parms[1];
 | 
						|
 | 
						|
		# Remove MDISK
 | 
						|
		# This cleans up the disks before it is put back in the pool
 | 
						|
		$out = `ssh $hcp $::DIR/removemdisk $userId $addr`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
	}
 | 
						|
 | 
						|
	# Sleep 5 seconds
 | 
						|
	# To let the z/VM user directory settle
 | 
						|
	sleep(5);
 | 
						|
 | 
						|
	# Delete user directory entry
 | 
						|
	$out = `ssh $hcp $::DIR/deletevs $userId`;
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
 | 
						|
	# Check for errors
 | 
						|
	my $rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
	if ( $rtn == -1 ) {
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Remove node from 'zvm', 'nodelist', 'nodehm', and 'hosts' table
 | 
						|
	xCAT::zvmUtils->delTabNode( 'zvm',      $node );
 | 
						|
	xCAT::zvmUtils->delTabNode( 'nodelist', $node );
 | 
						|
	xCAT::zvmUtils->delTabNode( 'nodetype', $node );
 | 
						|
	xCAT::zvmUtils->delTabNode( 'nodehm',   $node );
 | 
						|
	xCAT::zvmUtils->delTabNode( 'hosts',    $node );
 | 
						|
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   changeVM
 | 
						|
 | 
						|
 	Description	: Changes server configuration
 | 
						|
 	Arguments	: 	Node
 | 
						|
 					Option
 | 
						|
 		
 | 
						|
 	Options supported:
 | 
						|
		add3390 [disk pool] [device address] [mode] [cylinders]
 | 
						|
		add9336 [disk pool] [virtual device] [mode] [block size] [blocks]
 | 
						|
	 	addnic [address] [type] [device count]
 | 
						|
	 	addprocessor [address]
 | 
						|
	 	addvdisk [userID] [device address] [size]
 | 
						|
	 	connectnic2guestlan [address] [lan] [owner]
 | 
						|
	 	connectnic2vswitch [address] [vswitch]
 | 
						|
	 	dedicatedevice [virtual device] [real device] [mode]
 | 
						|
	 	deleteipl 
 | 
						|
	 	disconnectnic [address]
 | 
						|
	 	removemdisk [virtual device]
 | 
						|
	 	removenic [address]
 | 
						|
	 	removeprocessor [address]
 | 
						|
	 	replacevs [file]
 | 
						|
	 	setipl [ipl target] [load parms] [parms]
 | 
						|
	 	setpassword [password]
 | 
						|
	 	
 | 
						|
	Returns		: Nothing
 | 
						|
 	Example		: changeVM($node, $args);
 | 
						|
 		
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub changeVM {
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $node, $args ) = @_;
 | 
						|
 | 
						|
	# Get HCP
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'hcp' );
 | 
						|
	if ( !$hcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node HCP" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get node userID
 | 
						|
	my $userId = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'userid' );
 | 
						|
	if ( !$userId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	my $out;
 | 
						|
 | 
						|
	# add3390 [disk pool] [device address] [mode] [cylinders]
 | 
						|
	if ( $args->[0] eq "--add3390" ) {
 | 
						|
		my $pool    = $args->[1];
 | 
						|
		my $addr    = $args->[2];
 | 
						|
		my $mode    = $args->[3];
 | 
						|
		my $cyl     = $args->[4];
 | 
						|
		my $readPw  = $args->[5];
 | 
						|
		my $writePw = $args->[6];
 | 
						|
		my $multiPw = $args->[7];
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/add3390 $userId $pool $addr $mode $cyl $readPw $writePw $multiPw`;
 | 
						|
	}
 | 
						|
 | 
						|
	# add9336 [disk pool] [virtual device address] [mode] [block size] [blocks]
 | 
						|
	elsif ( $args->[0] eq "--add9336" ) {
 | 
						|
		my $pool    = $args->[1];
 | 
						|
		my $addr    = $args->[2];
 | 
						|
		my $mode    = $args->[3];
 | 
						|
		my $blksize = $args->[4];
 | 
						|
		my $blks    = $args->[5];
 | 
						|
		my $readPw  = $args->[6];
 | 
						|
		my $writePw = $args->[7];
 | 
						|
		my $multiPw = $args->[8];
 | 
						|
		$out = `ssh $hcp $::DIR/add9336 $userId $pool $addr $mode $blksize $blks $readPw $writePw $multiPw`;
 | 
						|
	}
 | 
						|
 | 
						|
	# addnic [address] [type] [device count]
 | 
						|
	elsif ( $args->[0] eq "--addnic" ) {
 | 
						|
		my $addr     = $args->[1];
 | 
						|
		my $type     = $args->[2];
 | 
						|
		my $devcount = $args->[3];
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/addnic $userId $addr $type $devcount`;
 | 
						|
	}
 | 
						|
 | 
						|
	# addprocessor [address]
 | 
						|
	elsif ( $args->[0] eq "--addprocessor" ) {
 | 
						|
		my $addr = $args->[1];
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/addprocessor $userId $addr`;
 | 
						|
	}
 | 
						|
 | 
						|
	# addvdisk [device address] [size]
 | 
						|
	elsif ( $args->[0] eq "--addvdisk" ) {
 | 
						|
		my $addr = $args->[1];
 | 
						|
		my $size = $args->[2];
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/addvdisk $userId $addr $size`;
 | 
						|
	}
 | 
						|
 | 
						|
	# connectnic2guestlan [address] [lan] [owner]
 | 
						|
	elsif ( $args->[0] eq "--connectnic2guestlan" ) {
 | 
						|
		my $addr  = $args->[1];
 | 
						|
		my $lan   = $args->[2];
 | 
						|
		my $owner = $args->[3];
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/connectnic2guestlan $userId $addr $lan $owner`;
 | 
						|
	}
 | 
						|
 | 
						|
	# connectnic2vswitch [address] [vswitch]
 | 
						|
	elsif ( $args->[0] eq "--connectnic2vswitch" ) {
 | 
						|
		my $addr    = $args->[1];
 | 
						|
		my $vswitch = $args->[2];
 | 
						|
 | 
						|
		# Connect to VSwitch
 | 
						|
		$out = `ssh $hcp $::DIR/connectnic2vswitch $userId $addr $vswitch`;
 | 
						|
 | 
						|
		# Grant access to VSWITCH for Linux user
 | 
						|
		$out .= "Granting access to VSWITCH for $userId...\n  ";
 | 
						|
		$out .= `ssh $hcp vmcp set vswitch $vswitch grant $userId`;
 | 
						|
	}
 | 
						|
 | 
						|
	# dedicatedevice [virtual device] [real device] [mode]
 | 
						|
	elsif ( $args->[0] eq "--dedicatedevice" ) {
 | 
						|
		my $vaddr = $args->[1];
 | 
						|
		my $raddr = $args->[2];
 | 
						|
		my $mode  = $args->[3];
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/dedicatedevice $userId $vaddr $raddr $mode`;
 | 
						|
	}
 | 
						|
 | 
						|
	# deleteipl
 | 
						|
	elsif ( $args->[0] eq "--deleteipl" ) {
 | 
						|
		$out = `ssh $hcp $::DIR/deleteipl $userId`;
 | 
						|
	}
 | 
						|
 | 
						|
	# formatdisk [address] [multi password]
 | 
						|
	elsif ( $args->[0] eq "--formatdisk" ) {
 | 
						|
 | 
						|
		# Get disk address
 | 
						|
		my $addr    = $args->[1];
 | 
						|
		my $lnkAddr = $addr + 1000;
 | 
						|
		my $multiPw = $args->[2];
 | 
						|
 | 
						|
		# Check if there is an existing address (disk address)
 | 
						|
		$out = xCAT::zvmUtils->isAddressUsed( $hcp, $addr );
 | 
						|
 | 
						|
		# If there is an existing address
 | 
						|
		while ( $out == 0 ) {
 | 
						|
 | 
						|
			# Generate a new address
 | 
						|
			# Sleep 2 seconds to let existing disk appear
 | 
						|
			sleep(2);
 | 
						|
			$lnkAddr = $lnkAddr + 1;
 | 
						|
			$out = xCAT::zvmUtils->isAddressUsed( $hcp, $lnkAddr );
 | 
						|
		}
 | 
						|
 | 
						|
		# Load VMCP module
 | 
						|
		$out = xCAT::zvmCPUtils->loadVmcp($node);
 | 
						|
 | 
						|
		# Link target disk
 | 
						|
		$out = `ssh -o ConnectTimeout=5 $hcp vmcp link $userId $addr $lnkAddr MW $multiPw`;
 | 
						|
 | 
						|
		# Check for errors
 | 
						|
		my $rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
		if ( $rtn == -1 ) {
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "Linking disk... Failed" );
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		# Enable disk
 | 
						|
		$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-e", $lnkAddr );
 | 
						|
 | 
						|
		# Determine device node
 | 
						|
		$out = `ssh $hcp cat /proc/dasd/devices | grep ".$lnkAddr("`;
 | 
						|
		my @parms   = split( ' ', $out );
 | 
						|
		my $devNode = $parms[6];
 | 
						|
 | 
						|
		# Format target disk
 | 
						|
		$out = `ssh $hcp dasdfmt -b 4096 -y -f /dev/$devNode`;
 | 
						|
 | 
						|
		# Check for errors
 | 
						|
		$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
		if ( $rtn == -1 ) {
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "Formating disk... Failed" );
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
 | 
						|
			# Disable disk
 | 
						|
			$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-d", $lnkAddr );
 | 
						|
 | 
						|
			# Detatch disk
 | 
						|
			$out = `ssh -o ConnectTimeout=5 $hcp vmcp det $lnkAddr`;
 | 
						|
 | 
						|
			# Check for errors
 | 
						|
			$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
			if ( $rtn == -1 ) {
 | 
						|
				xCAT::zvmUtils->printLn( $callback, "Detaching disk... Failed" );
 | 
						|
				xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		else {
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "Formating disk... Done" );
 | 
						|
		}
 | 
						|
 | 
						|
		# Disable disk
 | 
						|
		$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-d", $lnkAddr );
 | 
						|
 | 
						|
		# Detatch disk
 | 
						|
		$out = `ssh -o ConnectTimeout=5 $hcp vmcp det $lnkAddr`;
 | 
						|
 | 
						|
		# Check for errors
 | 
						|
		$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
		if ( $rtn == -1 ) {
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "Detaching disk... Failed" );
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		$out = "";
 | 
						|
	}
 | 
						|
 | 
						|
	# grantvswitch [VSwitch]
 | 
						|
	elsif ( $args->[0] eq "--grantvswitch" ) {
 | 
						|
		my $vsw = $args->[1];
 | 
						|
		$out = xCAT::zvmCPUtils->grantVSwitch( $callback, $hcp, $userId, $vsw );
 | 
						|
	}
 | 
						|
 | 
						|
	# disconnectnic [address]
 | 
						|
	elsif ( $args->[0] eq "--disconnectnic" ) {
 | 
						|
		my $addr = $args->[1];
 | 
						|
		$out = `ssh $hcp $::DIR/disconnectnic $userId $addr`;
 | 
						|
	}
 | 
						|
 | 
						|
	# removedisk [virtual device address]
 | 
						|
	elsif ( $args->[0] eq "--removedisk" ) {
 | 
						|
		my $addr = $args->[1];
 | 
						|
		$out = `ssh $hcp $::DIR/removemdisk $userId $addr`;
 | 
						|
	}
 | 
						|
 | 
						|
	# removenic [address]
 | 
						|
	elsif ( $args->[0] eq "--removenic" ) {
 | 
						|
		my $addr = $args->[1];
 | 
						|
		$out = `ssh $hcp $::DIR/removenic $userId $addr`;
 | 
						|
	}
 | 
						|
 | 
						|
	# removeprocessor [address]
 | 
						|
	elsif ( $args->[0] eq "--removeprocessor" ) {
 | 
						|
		my $addr = $args->[1];
 | 
						|
		$out = `ssh $hcp $::DIR/removeprocessor $userId $addr`;
 | 
						|
	}
 | 
						|
 | 
						|
	# replacevs [file]
 | 
						|
	elsif ( $args->[0] eq "--replacevs" ) {
 | 
						|
		my $file = $args->[1];
 | 
						|
 | 
						|
		my $dest = "root@";
 | 
						|
		$dest .= $hcp;
 | 
						|
		if ($file) {
 | 
						|
 | 
						|
			# SCP file over to HCP
 | 
						|
			$out = `scp $file $dest:$file`;
 | 
						|
 | 
						|
			# Replace user directory entry
 | 
						|
			$out = `ssh $hcp $::DIR/replacevs $userId $file`;
 | 
						|
		}
 | 
						|
		else {
 | 
						|
			$out = "Error: No directory entry file specified";
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
			return;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	# setipl [ipl target] [load parms] [parms]
 | 
						|
	elsif ( $args->[0] eq "--setipl" ) {
 | 
						|
		my $trgt      = $args->[1];
 | 
						|
		my $loadparms = $args->[2];
 | 
						|
		my $parms     = $args->[3];
 | 
						|
		$out = `ssh $hcp $::DIR/setipl $userId $trgt $loadparms $parms`;
 | 
						|
	}
 | 
						|
 | 
						|
	# setpassword [password]
 | 
						|
	elsif ( $args->[0] eq "--setpassword" ) {
 | 
						|
		my $pw = $args->[1];
 | 
						|
		$out = `ssh $hcp $::DIR/setpassword $userId $pw`;
 | 
						|
	}
 | 
						|
 | 
						|
	# Print out error
 | 
						|
	else {
 | 
						|
		$out = "Error: Option not supported";
 | 
						|
	}
 | 
						|
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   powerVM
 | 
						|
 | 
						|
	Description	: Powers on/off a server
 | 
						|
    Arguments	: 	Node 
 | 
						|
    				Option [on|off|reset|stat]
 | 
						|
    Returns		: Nothing
 | 
						|
    Example		: powerVM($node, $args);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub powerVM {
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $node, $args ) = @_;
 | 
						|
 | 
						|
	# Get HCP
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'hcp' );
 | 
						|
	if ( !$hcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node HCP" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get node userID
 | 
						|
	my $userId = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'userid' );
 | 
						|
	if ( !$userId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	my $out;
 | 
						|
	if ( $args->[0] eq 'on' ) {
 | 
						|
		$out = `ssh $hcp $::DIR/startvs $userId`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
	}
 | 
						|
	elsif ( $args->[0] eq 'off' ) {
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/stopvs $userId`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
	}
 | 
						|
	elsif ( $args->[0] eq 'stat' ) {
 | 
						|
 | 
						|
		# Output is different on SLES 11
 | 
						|
		$out = `vmcp q user $userId 2>/dev/null | sed 's/HCPCQU045E.*/off/' | sed 's/$userId.*/on/'`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$node: $out" );
 | 
						|
	}
 | 
						|
	elsif ( $args->[0] eq 'reset' ) {
 | 
						|
 | 
						|
		$out = `ssh $hcp $::DIR/stopvs $userId`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
 | 
						|
		# Wait for output
 | 
						|
		while ( `vmcp q user $node 2>/dev/null | sed 's/HCPCQU045E.*/proceed/'` != "proceed" ) {
 | 
						|
		}
 | 
						|
		$out = `ssh $hcp $::DIR/startvs $userId`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
	}
 | 
						|
	else {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Option not supported" );
 | 
						|
	}
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   scanVM
 | 
						|
 | 
						|
	Description	: Collects node information from one or more hardware control points.
 | 
						|
    Arguments	: zHCP node
 | 
						|
    Returns		: Nothing
 | 
						|
    Example		: scanVM($node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub scanVM {
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $node ) = @_;
 | 
						|
 | 
						|
	# Get HCP DNS host name
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'hcp' );
 | 
						|
	if ( !$hcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node HCP" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get node userID
 | 
						|
	my $userId = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'userid' );
 | 
						|
	if ( !$userId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Print output string
 | 
						|
	# [Node name]:
 | 
						|
	#	objtype=node
 | 
						|
	#   id=[userID]
 | 
						|
	#   os=[Operating system]
 | 
						|
	#   arch=[Architecture]
 | 
						|
	#   hcp=[HCP node name]
 | 
						|
	#   groups=[Group]
 | 
						|
	#   mgt=zvm
 | 
						|
	#
 | 
						|
	# gpok123:
 | 
						|
	#	objtype=node
 | 
						|
	#   id=LINUX123
 | 
						|
	#   os=SUSE Linux Enterprise Server 10 (s390x)
 | 
						|
	#   arch=s390x
 | 
						|
	#   hcp=gpok456.endicott.ibm.com
 | 
						|
	#   groups=all
 | 
						|
	#   mgt=zvm
 | 
						|
 | 
						|
	my $str = "";
 | 
						|
 | 
						|
	# Get nodes managed by this HCP
 | 
						|
	# Look in 'zvm' table
 | 
						|
	my $tab = xCAT::Table->new( 'zvm', -create => 1, -autocommit => 0 );
 | 
						|
 | 
						|
	my $out;
 | 
						|
	my $managedNode;
 | 
						|
	my $id;
 | 
						|
	my $os;
 | 
						|
	my $arch;
 | 
						|
	my $groups;
 | 
						|
 | 
						|
	# Get 'node' and 'userid' properties
 | 
						|
	my @results = $tab->getAllAttribsWhere( "hcp like '%" . $hcp . "%'", 'node', 'userid' );
 | 
						|
	foreach (@results) {
 | 
						|
		$managedNode = $_->{'node'};
 | 
						|
		$id          = $_->{'userid'};
 | 
						|
		$groups      = xCAT::zvmUtils->getTabProp( 'nodelist', $managedNode, 'groups' );
 | 
						|
 | 
						|
		# Get userID if one is not in the table
 | 
						|
		if ( !$id ) {
 | 
						|
 | 
						|
			# Load VMCP module
 | 
						|
			$out = xCAT::zvmCPUtils->loadVmcp($managedNode);
 | 
						|
 | 
						|
			# Get userID
 | 
						|
			$id = xCAT::zvmCPUtils->getUserId($managedNode);
 | 
						|
		}
 | 
						|
 | 
						|
		# Get operating system
 | 
						|
		$os = xCAT::zvmCPUtils->getOs($managedNode);
 | 
						|
 | 
						|
		# Get architecture
 | 
						|
		$arch = xCAT::zvmCPUtils->getArch($managedNode);
 | 
						|
 | 
						|
		# Create output string
 | 
						|
		$str .= "$managedNode:\n";
 | 
						|
		$str .= "  objtype=node\n";
 | 
						|
		$str .= "  userid=$id\n";
 | 
						|
		$str .= "  os=$os\n";
 | 
						|
		$str .= "  arch=$arch\n";
 | 
						|
		$str .= "  hcp=$hcp\n";
 | 
						|
		$str .= "  groups=$groups\n";
 | 
						|
		$str .= "  mgt=zvm\n\n";
 | 
						|
	}
 | 
						|
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$str" );
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   inventoryVM
 | 
						|
 | 
						|
	Description	: Get server hardware and software inventory
 | 
						|
    Arguments	: Node and arguments
 | 
						|
    Returns		: Nothing
 | 
						|
    Example		: inventoryVM($node, $args);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub inventoryVM {
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $node, $args ) = @_;
 | 
						|
 | 
						|
	# Output string
 | 
						|
	my $str = "";
 | 
						|
 | 
						|
	# Get HCP
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'hcp' );
 | 
						|
 | 
						|
	# Get node userID
 | 
						|
	my $userId = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'userid' );
 | 
						|
	if ( !$userId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Load VMCP module
 | 
						|
	my $out = xCAT::zvmCPUtils->loadVmcp($node);
 | 
						|
 | 
						|
	# Get configuration
 | 
						|
	if ( $args->[0] eq 'config' ) {
 | 
						|
 | 
						|
		# Get z/VM host for specified node
 | 
						|
		my $host = xCAT::zvmCPUtils->getHost($node);
 | 
						|
 | 
						|
		# Get architecture
 | 
						|
		my $arch = xCAT::zvmCPUtils->getArch($node);
 | 
						|
 | 
						|
		# Get operating system
 | 
						|
		my $os = xCAT::zvmCPUtils->getOs($node);
 | 
						|
 | 
						|
		# Get privileges
 | 
						|
		my $priv = xCAT::zvmCPUtils->getPrivileges($node);
 | 
						|
 | 
						|
		# Get memory configuration
 | 
						|
		my $memory = xCAT::zvmCPUtils->getMemory($node);
 | 
						|
 | 
						|
		# Get processors configuration
 | 
						|
		my $proc = xCAT::zvmCPUtils->getCpu($node);
 | 
						|
 | 
						|
		$str .= "z/VM UserID: $userId\n";
 | 
						|
		$str .= "z/VM Host: $host\n";
 | 
						|
		$str .= "Operating System: $os\n";
 | 
						|
		$str .= "Architecture:	$arch\n";
 | 
						|
		$str .= "HCP: $hcp\n";
 | 
						|
		$str .= "Privileges: \n$priv\n";
 | 
						|
		$str .= "Total Memory:	$memory\n";
 | 
						|
		$str .= "Processors: \n$proc\n";
 | 
						|
	}
 | 
						|
	elsif ( $args->[0] eq 'all' ) {
 | 
						|
 | 
						|
		# Get z/VM host for specified node
 | 
						|
		my $host = xCAT::zvmCPUtils->getHost($node);
 | 
						|
 | 
						|
		# Get architecture
 | 
						|
		my $arch = xCAT::zvmCPUtils->getArch($node);
 | 
						|
 | 
						|
		# Get operating system
 | 
						|
		my $os = xCAT::zvmCPUtils->getOs($node);
 | 
						|
 | 
						|
		# Get privileges
 | 
						|
		my $priv = xCAT::zvmCPUtils->getPrivileges($node);
 | 
						|
 | 
						|
		# Get memory configuration
 | 
						|
		my $memory = xCAT::zvmCPUtils->getMemory($node);
 | 
						|
 | 
						|
		# Get processors configuration
 | 
						|
		my $proc = xCAT::zvmCPUtils->getCpu($node);
 | 
						|
 | 
						|
		# Get disks configuration
 | 
						|
		my $storage = xCAT::zvmCPUtils->getDisks($node);
 | 
						|
 | 
						|
		# Get NICs configuration
 | 
						|
		my $nic = xCAT::zvmCPUtils->getNic($node);
 | 
						|
 | 
						|
		# Create output string
 | 
						|
		$str .= "z/VM UserID: $userId\n";
 | 
						|
		$str .= "z/VM Host: $host\n";
 | 
						|
		$str .= "Operating System: $os\n";
 | 
						|
		$str .= "Architecture:	$arch\n";
 | 
						|
		$str .= "HCP: $hcp\n";
 | 
						|
		$str .= "Privileges: \n$priv\n";
 | 
						|
		$str .= "Total Memory:	$memory\n";
 | 
						|
		$str .= "Processors: \n$proc\n";
 | 
						|
		$str .= "Disks: \n$storage\n";
 | 
						|
		$str .= "NICs:	\n$nic\n";
 | 
						|
	}
 | 
						|
	else {
 | 
						|
		$str = "Error: Invalid argument";
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$str" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Append hostname in front
 | 
						|
	$str = xCAT::zvmUtils->appendHostname( $node, $str );
 | 
						|
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$str" );
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   listVM
 | 
						|
 | 
						|
	Description	: Get user directory entry
 | 
						|
    Arguments	: Node
 | 
						|
    Returns		: Nothing
 | 
						|
    Example		: listVM($node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub listVM {
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $node ) = @_;
 | 
						|
 | 
						|
	# Get HCP
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'hcp' );
 | 
						|
	if ( !$hcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node HCP" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get node userID
 | 
						|
	my $userId = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'userid' );
 | 
						|
	if ( !$userId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get virtual server directory entry
 | 
						|
	my $out = `ssh $hcp $::DIR/getuserentry $userId`;
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   makeVM
 | 
						|
 | 
						|
	Description	: Create a server
 | 
						|
    Arguments	: 	Node 
 | 
						|
    				User directory entry as text file
 | 
						|
    Returns		: Nothing
 | 
						|
    Example		: makeVM($node, $args);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub makeVM {
 | 
						|
 | 
						|
	# Before a virtual server can be created
 | 
						|
	# You need to add the virtual server into the tables:
 | 
						|
	# 	mkdef -t node -o gpok123 userid=linux123 hcp=gpok456.endicott.ibm.com mgt=zvm groups=all
 | 
						|
	# 	This will add the node into the 'nodelist', 'nodehm', and 'zvm' tables
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $node, $args ) = @_;
 | 
						|
 | 
						|
	# Get HCP
 | 
						|
	# It was defined in mkdef command
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'hcp' );
 | 
						|
	if ( !$hcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: No HCP defined for this node" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get new node userID
 | 
						|
	my $userId = xCAT::zvmUtils->getTabProp( 'zvm', $node, 'userid' );
 | 
						|
	if ( !$userId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get file (if any)
 | 
						|
	my $file = $args->[0];
 | 
						|
	my $out;
 | 
						|
 | 
						|
	# Create destination string, e.g.
 | 
						|
	# root@gpok123.endicott.ibm.com
 | 
						|
	my $dest = "root@";
 | 
						|
	$dest .= $hcp;
 | 
						|
	if ($file) {
 | 
						|
 | 
						|
		# SCP file over to HCP
 | 
						|
		$out = `scp $file $dest:$file`;
 | 
						|
 | 
						|
		# Create virtual server
 | 
						|
		$out = `ssh $hcp $::DIR/createvs $userId $file`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
	}
 | 
						|
	else {
 | 
						|
 | 
						|
		# Create NOLOG virtual server
 | 
						|
		$out = `ssh $hcp $::DIR/createvs $userId`;
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
	}
 | 
						|
 | 
						|
	return;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   cloneVM
 | 
						|
 | 
						|
	Description	: Clone a server
 | 
						|
    Arguments	: Node and configuration
 | 
						|
    Returns		: Nothing
 | 
						|
    Example		: cloneVM($node, $args);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub cloneVM {
 | 
						|
 | 
						|
	# Before a virtual server can be created
 | 
						|
	# You need to add the virtual server into the tables:
 | 
						|
	# 	mkdef -t node -o gpok123 userid=LINUX123 ip=9.60.18.123 hcp=gpok456.endicott.ibm.com mgt=zvm groups=all
 | 
						|
	# 	This will add the node into the 'nodelist', 'nodehm', 'zvm', and 'hosts' tables
 | 
						|
 | 
						|
	# Get inputs
 | 
						|
	my ( $callback, $targetNode, $args ) = @_;
 | 
						|
 | 
						|
	# Return code for each command
 | 
						|
	my $rtn;
 | 
						|
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$targetNode: Cloning" );
 | 
						|
 | 
						|
	# Get HCP
 | 
						|
	my $hcp = xCAT::zvmUtils->getTabProp( 'zvm', $targetNode, 'hcp' );
 | 
						|
	if ( !$hcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: No HCP defined for this node" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get target node userID
 | 
						|
	my $targetUserId = xCAT::zvmUtils->getTabProp( 'zvm', $targetNode, 'userid' );
 | 
						|
	if ( !$targetUserId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get source node
 | 
						|
	my $sourceNode = $args->[0];
 | 
						|
	if ( !$sourceNode ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing master node" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get source node userID
 | 
						|
	my $sourceId = xCAT::zvmUtils->getTabProp( 'zvm', $sourceNode, 'userid' );
 | 
						|
	if ( !$sourceId ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing master node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get source node HCP
 | 
						|
	my $sourceHcp = xCAT::zvmUtils->getTabProp( 'zvm', $sourceNode, 'hcp' );
 | 
						|
	if ( !$sourceHcp ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing master node ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Exit if source node HCP is not the same as target node HCP
 | 
						|
	elsif ( !( $sourceHcp eq $hcp ) ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback,
 | 
						|
			"Error: Source node HCP ($sourceHcp) is not the same as target node HCP ($hcp)" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get other inputs (4 in total)
 | 
						|
	# Disk pool, read, write, and multi passwords
 | 
						|
	my $i;
 | 
						|
	my @parms;
 | 
						|
	my %inputs;
 | 
						|
	foreach $i ( 1 .. 4 ) {
 | 
						|
		if ( $args->[$i] ) {
 | 
						|
 | 
						|
			# Split parameters by '='
 | 
						|
			@parms = split( "=", $args->[$i] );
 | 
						|
 | 
						|
			# Create hash array
 | 
						|
			$inputs{ $parms[0] } = $parms[1];
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	# Get disk pool
 | 
						|
	my $pool = $inputs{"pool"};
 | 
						|
	if ( !$pool ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing pool ID" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get read, write, and multi password
 | 
						|
	my $trgtPw = $inputs{"pw"};
 | 
						|
	if ( !$trgtPw ) {
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "Error: Missing read/write/multi password" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Get MDisk statements of source node
 | 
						|
	my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $sourceNode );
 | 
						|
 | 
						|
	# Get directory entry of source node
 | 
						|
	# Save user directory entry as /tmp/dirEntry.txt
 | 
						|
	my $dirFile = "/tmp/dirEntry.txt";
 | 
						|
	my $out     = xCAT::zvmUtils->saveDirEntryNoDisk( $callback, $sourceNode, $dirFile );
 | 
						|
 | 
						|
	# SCP directory entry file over to HCP
 | 
						|
	$out = xCAT::zvmUtils->sendFile( $hcp, $dirFile );
 | 
						|
 | 
						|
	# Create new virtual server
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$targetNode: Creating user directory entry" );
 | 
						|
	$out = `ssh $hcp $::DIR/createvs $targetUserId $dirFile`;
 | 
						|
 | 
						|
	# Check for errors
 | 
						|
	$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
	if ( $rtn == -1 ) {
 | 
						|
 | 
						|
		# Exit on bad output
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	# Load VMCP module
 | 
						|
	$out = xCAT::zvmCPUtils->loadVmcp($hcp);
 | 
						|
	$out = xCAT::zvmCPUtils->loadVmcp($sourceNode);
 | 
						|
 | 
						|
	# Get VSwitch of master node
 | 
						|
	my @vswitchId = xCAT::zvmCPUtils->getVswitchId($sourceNode);
 | 
						|
 | 
						|
	# Grant access to VSwitch for Linux user
 | 
						|
	# GuestLan do not need permissions
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$targetNode: Granting VSwitch access" );
 | 
						|
	foreach (@vswitchId) {
 | 
						|
		$out = xCAT::zvmCPUtils->grantVSwitch( $callback, $hcp, $targetUserId, $_ );
 | 
						|
 | 
						|
		# Check for errors
 | 
						|
		$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
		if ( $rtn == -1 ) {
 | 
						|
 | 
						|
			# Exit on bad output
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
			return;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	# Add MDisk to target user directory entry
 | 
						|
	my @trgtDisks;
 | 
						|
	my $addr;
 | 
						|
	my $type;
 | 
						|
	my $mode;
 | 
						|
	my $cyl;
 | 
						|
	my $srcMultiPw;
 | 
						|
	foreach (@srcDisks) {
 | 
						|
 | 
						|
		# Get disk device address
 | 
						|
		@parms = split( ' ', $_ );
 | 
						|
		$addr = $parms[1];
 | 
						|
		push( @trgtDisks, $addr );
 | 
						|
		$type       = $parms[2];
 | 
						|
		$mode       = $parms[6];
 | 
						|
		$srcMultiPw = $parms[9];
 | 
						|
 | 
						|
		# Add ECKD disk
 | 
						|
		if ( $type eq '3390' ) {
 | 
						|
 | 
						|
			# Get disk size (cylinders)
 | 
						|
			$out   = `ssh -o ConnectTimeout=5 $sourceNode vmcp q v dasd | grep "DASD $addr"`;
 | 
						|
			@parms = split( ' ', $out );
 | 
						|
			$cyl   = xCAT::zvmUtils->trim( $parms[5] );
 | 
						|
 | 
						|
			# Add disk
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$targetNode: Adding minidisk" );
 | 
						|
			$out = `ssh $hcp $::DIR/add3390 $targetUserId $pool $addr $mode $cyl $trgtPw $trgtPw $trgtPw`;
 | 
						|
 | 
						|
			# Check for errors
 | 
						|
			$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
			if ( $rtn == -1 ) {
 | 
						|
				xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
 | 
						|
				# Exit on bad output
 | 
						|
				return;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		# Add FBA disk
 | 
						|
		elsif ( $type eq '9336' ) {
 | 
						|
 | 
						|
			# Get disk size (blocks)
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	# Load VMCP module on HCP
 | 
						|
	$out = xCAT::zvmCPUtils->loadVmcp($hcp);
 | 
						|
 | 
						|
	# Link , format, and copy source disks
 | 
						|
	my $srcAddr;
 | 
						|
	my $targetAddr;
 | 
						|
	my $sourceDevNode;
 | 
						|
	my $targetDevNode;
 | 
						|
	foreach (@trgtDisks) {
 | 
						|
		$srcAddr    = $_ + 1000;
 | 
						|
		$targetAddr = $_ + 2000;
 | 
						|
 | 
						|
		# Check if there is an existing address (source address)
 | 
						|
		$out = xCAT::zvmUtils->isAddressUsed( $hcp, $srcAddr );
 | 
						|
 | 
						|
		# If there is an existing address
 | 
						|
		while ( $out == 0 ) {
 | 
						|
 | 
						|
			# Generate a new address
 | 
						|
			# Sleep 2 seconds to let existing disk appear
 | 
						|
			sleep(2);
 | 
						|
			$srcAddr = $srcAddr + 1;
 | 
						|
			$out = xCAT::zvmUtils->isAddressUsed( $hcp, $srcAddr );
 | 
						|
		}
 | 
						|
 | 
						|
		# Check if there is an existing address (target address)
 | 
						|
		$out = xCAT::zvmUtils->isAddressUsed( $hcp, $targetAddr );
 | 
						|
 | 
						|
		# If there is an existing address
 | 
						|
		while ( $out == 0 ) {
 | 
						|
 | 
						|
			# Generate a new address
 | 
						|
			# Sleep 2 seconds to let existing disk appear
 | 
						|
			sleep(2);
 | 
						|
			$targetAddr = $targetAddr + 1;
 | 
						|
			$out = xCAT::zvmUtils->isAddressUsed( $hcp, $targetAddr );
 | 
						|
		}
 | 
						|
 | 
						|
		# Link source disk
 | 
						|
		$out = `ssh -o ConnectTimeout=5 $hcp vmcp link $sourceId $_ $srcAddr MW $srcMultiPw`;
 | 
						|
 | 
						|
		# Check for errors
 | 
						|
		$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
		if ( $rtn == -1 ) {
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		# Link target disk
 | 
						|
		$out = `ssh -o ConnectTimeout=5 $hcp vmcp link $targetUserId $_ $targetAddr MW $trgtPw`;
 | 
						|
 | 
						|
		# Check for errors
 | 
						|
		$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
		if ( $rtn == -1 ) {
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		# Use FLASHCOPY
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$targetNode: Copying source disk using FLASHCOPY" );
 | 
						|
		$out = xCAT::zvmCPUtils->flashCopy( $hcp, $srcAddr, $targetAddr );
 | 
						|
 | 
						|
		# Check for errors
 | 
						|
		$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
		if ( $rtn == -1 ) {
 | 
						|
 | 
						|
			# FLASHCOPY is not supported
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$targetNode: FLASHCOPY not supported.  Using Linux DD" );
 | 
						|
 | 
						|
			# Enable source disk
 | 
						|
			$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-e", $srcAddr );
 | 
						|
 | 
						|
			# Enable target disk
 | 
						|
			$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-e", $targetAddr );
 | 
						|
 | 
						|
			# Determine source device node
 | 
						|
			$out           = `ssh $hcp cat /proc/dasd/devices | grep ".$srcAddr("`;
 | 
						|
			@parms         = split( ' ', $out );
 | 
						|
			$sourceDevNode = $parms[6];
 | 
						|
 | 
						|
			# Determine target device node
 | 
						|
			$out           = `ssh $hcp cat /proc/dasd/devices | grep ".$targetAddr("`;
 | 
						|
			@parms         = split( ' ', $out );
 | 
						|
			$targetDevNode = $parms[6];
 | 
						|
 | 
						|
			# Format target disk
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$targetNode: Formating disk" );
 | 
						|
			$out = `ssh $hcp dasdfmt -b 4096 -y -f /dev/$targetDevNode`;
 | 
						|
 | 
						|
			# Check for errors
 | 
						|
			$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
			if ( $rtn == -1 ) {
 | 
						|
 | 
						|
				# Exit on bad output
 | 
						|
				xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			# Sleep 2 seconds to let the system settle
 | 
						|
			sleep(2);
 | 
						|
 | 
						|
			# Copy source disk to target disk
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$targetNode: Copying source disk" );
 | 
						|
			$out = `ssh $hcp dd if=/dev/$sourceDevNode of=/dev/$targetDevNode bs=4096`;
 | 
						|
 | 
						|
			# Check for error
 | 
						|
			$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
			if ( $rtn == -1 ) {
 | 
						|
				xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			# Sleep 2 seconds to let the system settle
 | 
						|
			sleep(2);
 | 
						|
		}
 | 
						|
 | 
						|
		# Disable and enable target disk
 | 
						|
		$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-d", $targetAddr );
 | 
						|
		$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-e", $targetAddr );
 | 
						|
 | 
						|
		# Determine target device node (it might have changed)
 | 
						|
		$out           = `ssh $hcp cat /proc/dasd/devices | grep ".$targetAddr("`;
 | 
						|
		@parms         = split( ' ', $out );
 | 
						|
		$targetDevNode = $parms[6];
 | 
						|
 | 
						|
		# Get disk address that is the root partition
 | 
						|
		my $rootPartitionAddr = xCAT::zvmUtils->getRootDiskAddr($sourceNode);
 | 
						|
		if ( $_ eq $rootPartitionAddr ) {
 | 
						|
 | 
						|
			# Set network configuration
 | 
						|
			xCAT::zvmUtils->printLn( $callback, "$targetNode: Setting network configuration" );
 | 
						|
 | 
						|
			# Mount target disk
 | 
						|
			my $cloneMntPt = "/mnt/$targetUserId";
 | 
						|
			$targetDevNode .= "1";
 | 
						|
			$out = `ssh $hcp mkdir $cloneMntPt`;
 | 
						|
			$out = `ssh $hcp mount /dev/$targetDevNode $cloneMntPt`;
 | 
						|
 | 
						|
			# Set hostname
 | 
						|
			$out = `ssh $hcp sed --in-place -e "s/$sourceNode/$targetNode/g" $cloneMntPt/etc/HOSTNAME`;
 | 
						|
 | 
						|
			# Set IP address
 | 
						|
			my $sourceIp  = xCAT::zvmUtils->getIp($sourceNode);
 | 
						|
			my $targetIp  = xCAT::zvmUtils->getTabProp( "hosts", $targetNode, "ip" );
 | 
						|
			my $ifcfg     = xCAT::zvmUtils->getIfcfg($sourceNode);
 | 
						|
			my $ifcfgPath = $cloneMntPt;
 | 
						|
			$ifcfgPath .= $ifcfg;
 | 
						|
			$out =
 | 
						|
`ssh $hcp sed --in-place -e "s/$sourceNode/$targetNode/g" \ -e "s/$sourceIp/$targetIp/g" $cloneMntPt/etc/hosts`;
 | 
						|
			$out = `ssh $hcp sed --in-place -e "s/$sourceIp/$targetIp/g" \ -e "s/$sourceNode/$targetNode/g" $ifcfgPath`;
 | 
						|
 | 
						|
			# Flush disk
 | 
						|
			$out = `ssh $hcp sync`;
 | 
						|
 | 
						|
			# Unmount disk
 | 
						|
			$out = `ssh $hcp umount $cloneMntPt`;
 | 
						|
		}
 | 
						|
 | 
						|
		# Disable disks
 | 
						|
		$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-d", $srcAddr );
 | 
						|
		$out = xCAT::zvmUtils->disableEnableDisk( $callback, $hcp, "-d", $targetAddr );
 | 
						|
 | 
						|
		# Detatch disks
 | 
						|
		$out = `ssh $hcp vmcp det $srcAddr`;
 | 
						|
		$out = `ssh $hcp vmcp det $targetAddr`;
 | 
						|
	}
 | 
						|
 | 
						|
	# Power on target virtual server
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$targetNode: Powering on" );
 | 
						|
	$out = `ssh $hcp $::DIR/startvs $targetUserId`;
 | 
						|
 | 
						|
	# Check for error
 | 
						|
	$rtn = xCAT::zvmUtils->isOutputGood( $callback, $out );
 | 
						|
	if ( $rtn == -1 ) {
 | 
						|
 | 
						|
		# Exit on bad output
 | 
						|
		xCAT::zvmUtils->printLn( $callback, "$out" );
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	xCAT::zvmUtils->printLn( $callback, "$targetNode: Done" );
 | 
						|
 | 
						|
	return;
 | 
						|
}
 |