diff --git a/perl-xCAT-2.0/xCAT/PPC.pm b/perl-xCAT-2.0/xCAT/PPC.pm
new file mode 100644
index 000000000..25f784cfe
--- /dev/null
+++ b/perl-xCAT-2.0/xCAT/PPC.pm
@@ -0,0 +1,630 @@
+# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
+
+package xCAT::PPC;
+use strict;
+use xCAT::Table;
+use POSIX "WNOHANG";
+use Storable qw(freeze thaw);
+use Time::HiRes qw(gettimeofday);
+use IO::Select;
+use xCAT::PPCcli;
+use xCAT::PPCfsp;
+
+
+##########################################
+# Globals
+##########################################
+my %modules = (
+ rinv => "xCAT::PPCinv",
+ rpower => "xCAT::PPCpower",
+ rvitals => "xCAT::PPCvitals",
+ rscan => "xCAT::PPCscan",
+ mkvm => "xCAT::PPCvm",
+ rmvm => "xCAT::PPCvm",
+ lsvm => "xCAT::PPCvm",
+ chvm => "xCAT::PPCvm",
+ rnetboot => "xCAT::PPCboot",
+ getmacs => "xCAT::PPCmac",
+ reventlog => "xCAT::PPClog"
+);
+
+##########################################
+# Database errors
+##########################################
+my %errmsg = (
+ NODE_UNDEF =>"Node not defined in '%s' database",
+ NO_ATTR =>"'%s' not defined in '%s' database",
+ DB_UNDEF =>"'%s' database not defined"
+);
+
+
+##########################################################################
+# Invokes the callback with the specified message
+##########################################################################
+sub send_msg {
+
+ my $request = shift;
+ my %output;
+
+ #################################################
+ # Called from child process - send to parent
+ #################################################
+ if ( exists( $request->{pipe} )) {
+ my $out = $request->{pipe};
+
+ $output{data} = \@_;
+ print $out freeze( [\%output] );
+ }
+ #################################################
+ # Called from parent - invoke callback directly
+ #################################################
+ elsif ( exists( $request->{callback} )) {
+ my $callback = $request->{callback};
+
+ $output{data} = \@_;
+ $callback->( \%output );
+ }
+}
+
+
+##########################################################################
+# Fork child to execute remote commands
+##########################################################################
+sub process_command {
+
+ my $request = shift;
+ my $maxp = 64;
+ my %nodes = ();
+ my $callback = $request->{callback};
+ my $start;
+
+ if ( exists( $request->{verbose} )) {
+ $start = Time::HiRes::gettimeofday();
+ }
+ #######################################
+ # Group nodes based on command
+ #######################################
+ my $nodes = preprocess_nodes( $request );
+ if ( !defined( $nodes )) {
+ return(1);
+ }
+ #######################################
+ # Fork process
+ #######################################
+ my $children = 0;
+ $SIG{CHLD} = sub { while (waitpid(-1, WNOHANG) > 0) { $children--; } };
+ my $fds = new IO::Select;
+
+ foreach ( @$nodes ) {
+ while ( $children > $maxp ) {
+ sleep(0.1);
+ }
+ my $pipe = fork_cmd( @$_[0], @$_[1], $request );
+ if ( $pipe ) {
+ $fds->add( $pipe );
+ $children++;
+ }
+ }
+ #######################################
+ # Process responses from children
+ #######################################
+ while ( $children > 0 ) {
+ child_response( $callback, $fds );
+ }
+ if ( exists( $request->{verbose} )) {
+ my $elapsed = Time::HiRes::gettimeofday() - $start;
+ printf STDERR "Total Elapsed Time: %.3f sec\n", $elapsed;
+ }
+ return(0);
+}
+
+
+##########################################################################
+# Send response from child process back to xCAT client
+##########################################################################
+sub child_response {
+
+ my $callback = shift;
+ my $fds = shift;
+ my @ready_fds = $fds->can_read(1);
+
+ foreach my $rfh (@ready_fds) {
+ my $data;
+
+ #################################
+ # Read from child
+ #################################
+ while (<$rfh>) {
+ $data.= $_;
+ }
+ #################################
+ # Command results
+ #################################
+ my $responses = thaw($data);
+ foreach (@$responses) {
+ $callback->($_);
+ }
+ $fds->remove($rfh);
+ close($rfh);
+ }
+}
+
+
+##########################################################################
+# Group nodes depending on command
+##########################################################################
+sub preprocess_nodes {
+
+ my $request = shift;
+ my $noderange = $request->{node};
+ my $method = $request->{method};
+ my %nodehash = ();
+ my @nodegroup = ();
+ my %tabs = ();
+
+ ########################################
+ # Special cases
+ # rscan - Nodes are hardware control pts
+ # Direct-attached FSP
+ ########################################
+ if (( $request->{command} eq "rscan" ) or
+ ( $request->{hwtype} eq "fsp" )) {
+
+ my $tab = ($request->{hwtype} eq "fsp") ? "ppcDirect" : "ppchcp";
+ my $db = xCAT::Table->new( $tab );
+
+ if ( !defined( $db )) {
+ send_msg( $request, sprintf( $errmsg{DB_UNDEF}, $tab ));
+ return undef;
+ }
+ ####################################
+ # Process each node
+ ####################################
+ foreach ( @$noderange ) {
+ my ($ent) = $db->getAttribs( {hcp=>$_},"hcp" );
+
+ if ( !defined( $ent )) {
+ my $msg = sprintf( "$_: $errmsg{NODE_UNDEF}", $tab );
+ send_msg( $request, $msg );
+ next;
+ }
+ ################################
+ # Save values
+ ################################
+ push @nodegroup,[$_];
+ }
+ return( \@nodegroup );
+ }
+
+ ##########################################
+ # Open databases needed
+ ##########################################
+ foreach ( qw(ppc vpd nodelist) ) {
+ $tabs{$_} = xCAT::Table->new($_);
+
+ if ( !exists( $tabs{$_} )) {
+ send_msg( $request, sprintf( $errmsg{DB_UNDEF}, $_ ));
+ return undef;
+ }
+ }
+ ##########################################
+ # Group nodes
+ ##########################################
+ foreach my $node ( @$noderange ) {
+ my $d = resolve( $request, $node, \%tabs );
+
+ ######################################
+ # Error locating node attributes
+ ######################################
+ if ( ref($d) ne 'ARRAY' ) {
+ send_msg( $request,"$node: $d");
+ next;
+ }
+ ######################################
+ # Get data values
+ ######################################
+ my $hcp = @$d[3];
+ my $mtms = @$d[2];
+
+ $nodehash{$hcp}{$mtms}{$node} = $d;
+ }
+ ##########################################
+ # Group the nodes - we will fork one
+ # process per nodegroup array element.
+ ##########################################
+
+ ##########################################
+ # These commands are grouped on an
+ # LPAR-by-LPAR basis - fork one process
+ # per LPAR.
+ ##########################################
+ if ( $method =~ /^getmacs|rnetboot$/ ) {
+ while (my ($hcp,$hash) = each(%nodehash) ) {
+ while (my ($mtms,$h) = each(%$hash) ) {
+ while (my ($lpar,$d) = each(%$h)) {
+ push @$d, $lpar;
+ push @nodegroup,[$hcp,$d];
+ }
+ }
+ }
+ return( \@nodegroup );
+ }
+ ##########################################
+ # Power control commands are grouped
+ # by CEC which is the smallest entity
+ # that commands can be sent to in parallel.
+ # If commands are sent in parallel to a
+ # single CEC, the CEC itself will serialize
+ # them - fork one process per CEC.
+ ##########################################
+ elsif ( $method =~ /^powercmd/ ) {
+ while (my ($hcp,$hash) = each(%nodehash) ) {
+ while (my ($mtms,$h) = each(%$hash) ) {
+ push @nodegroup,[$hcp,$h];
+ }
+ }
+ return( \@nodegroup );
+ }
+ ##########################################
+ # All other commands are grouped by
+ # hardware control point - fork one
+ # process per hardware control point.
+ ##########################################
+ while (my ($hcp,$hash) = each(%nodehash) ) {
+ push @nodegroup,[$hcp,$hash];
+ }
+ return( \@nodegroup );
+}
+
+
+
+##########################################################################
+# Findis attributes for given node is various databases
+##########################################################################
+sub resolve {
+
+ my $request = shift;
+ my $node = shift;
+ my $tabs = shift;
+ my @attribs = qw(id profile mgt hcp);
+ my @values = ();
+
+ #################################
+ # Get node type
+ #################################
+ my ($ent) = $tabs->{nodelist}->getAttribs({'node'=>$node}, "nodetype" );
+ if ( !defined( $ent )) {
+ return( sprintf( $errmsg{NODE_UNDEF}, "nodelist" ));
+ }
+ #################################
+ # Check for type
+ #################################
+ if ( !exists( $ent->{nodetype} )) {
+ return( sprintf( $errmsg{NO_ATTR}, $ent->{nodetype}, "nodelist" ));
+ }
+ #################################
+ # Check for valid "type"
+ #################################
+ if ( $ent->{nodetype} !~ /^fsp|bpa|osi$/ ) {
+ return( "Invalid node type: $ent->{nodetype}" );
+ }
+ my $type = $ent->{nodetype};
+
+ #################################
+ # Get attributes
+ #################################
+ my ($att) = $tabs->{ppc}->getAttribs({'node'=>$node}, @attribs );
+
+ if ( !defined( $att )) {
+ return( sprintf( $errmsg{NODE_UNDEF}, "ppc" ));
+ }
+ #################################
+ # Special lpar processing
+ #################################
+ if ( $type =~ /^osi$/ ) {
+ $att->{bpa} = 0;
+ $att->{type} = "lpar";
+ $att->{node} = $att->{mgt};
+
+ if ( !exists( $att->{mgt} )) {
+ return( sprintf( $errmsg{NO_ATTR}, "mgt", "ppc" ));
+ }
+ #############################
+ # Get BPA (if any)
+ #############################
+ if (( $request->{command} eq "rvitals" ) &&
+ ( $request->{method} =~ /^all|temp$/ )) {
+ my ($ent) = $tabs->{ppc}->getAttribs({'node'=>$att->{mgt}}, "mgt" );
+
+ #############################
+ # Find MTMS in vpd database
+ #############################
+ if (( defined( $ent )) && exists( $ent->{mgt} )) {
+ my @attrs = qw(mtm serial);
+ my ($vpd) = $tabs->{vpd}->getAttribs({node=>$ent->{mgt}},@attrs );
+
+ if ( !defined( $vpd )) {
+ return( sprintf( $errmsg{NO_UNDEF}, "vpd" ));
+ }
+ ########################
+ # Verify attributes
+ ########################
+ foreach ( @attrs ) {
+ if ( !exists( $vpd->{$_} )) {
+ return( sprintf( $errmsg{NO_ATTR}, $_, "vpd" ));
+ }
+ }
+ $att->{bpa} = "$vpd->{mtm}*$vpd->{serial}";
+ }
+ }
+ }
+ #################################
+ # Optional and N/A fields
+ #################################
+ elsif ( $type =~ /^fsp$/ ) {
+ $att->{profile} = 0;
+ $att->{id} = 0;
+ $att->{fsp} = 0;
+ $att->{node} = $node;
+ $att->{type} = $type;
+ $att->{mgt} = exists($att->{mgt}) ? $att->{mgt} : 0;
+ $att->{bpa} = $att->{mgt};
+ }
+ elsif ( $type =~ /^bpa$/ ) {
+ $att->{profile} = 0;
+ $att->{id} = 0;
+ $att->{bpa} = 0;
+ $att->{mgt} = 0;
+ $att->{fsp} = 0;
+ $att->{node} = $node;
+ $att->{type} = $type;
+ }
+ #################################
+ # Find MTMS in vpd database
+ #################################
+ my @attrs = qw(mtm serial);
+ my ($vpd) = $tabs->{vpd}->getAttribs({node=>$att->{node}}, @attrs );
+
+ if ( !defined( $vpd )) {
+ return( sprintf( $errmsg{NODE_UNDEF}, "vpd" ));
+ }
+ ################################
+ # Verify both vpd attributes
+ ################################
+ foreach ( @attrs ) {
+ if ( !exists( $vpd->{$_} )) {
+ return( sprintf( $errmsg{NO_ATTR}, $_, "vpd" ));
+ }
+ }
+ $att->{fsp} = "$vpd->{mtm}*$vpd->{serial}";
+
+ #################################
+ # Verify required attributes
+ #################################
+ foreach my $at ( @attribs ) {
+ if ( !exists( $att->{$at} )) {
+ return( sprintf( $errmsg{NO_ATTR}, $at, "ppc" ));
+ }
+ }
+ #################################
+ # Build array of data
+ #################################
+ foreach ( qw(id profile fsp hcp type bpa) ) {
+ push @values, $att->{$_};
+ }
+ return( \@values );
+}
+
+
+
+##########################################################################
+# Forks a process to run the ssh command
+##########################################################################
+sub fork_cmd {
+
+ my $host = shift;
+ my $nodes = shift;
+ my $request = shift;
+
+ #######################################
+ # Pipe childs output back to parent
+ #######################################
+ my $parent;
+ my $child;
+ pipe $parent, $child;
+ my $pid = fork;
+
+ if ( !defined($pid) ) {
+ ###################################
+ # Fork error
+ ###################################
+ send_msg( $request, "Fork error: $!" );
+ return undef;
+ }
+ elsif ( $pid == 0 ) {
+ ###################################
+ # Child process
+ ###################################
+ close( $parent );
+ $request->{pipe} = $child;
+
+ invoke_cmd( $host, $nodes, $request );
+ exit(0);
+ }
+ else {
+ ###################################
+ # Parent process
+ ###################################
+ close( $child );
+ return( $parent );
+ }
+ return(0);
+}
+
+
+##########################################################################
+# Run the command, process the response, and send to parent
+##########################################################################
+sub invoke_cmd {
+
+ my $host = shift;
+ my $nodes = shift;
+ my $request = shift;
+ my $hwtype = $request->{hwtype};
+ my $verbose = $request->{verbose};
+ my @exp;
+ my @outhash;
+
+ ########################################
+ # Direct-attached FSP handler
+ ########################################
+ if ( $hwtype eq "fsp" ) {
+ my $result = xCAT::PPCfsp::handler( $host, $request );
+
+ my $out = $request->{pipe};
+ print $out freeze( $result );
+ return;
+ }
+ ########################################
+ # Connect to list of remote servers
+ ########################################
+ foreach ( split /,/, $host ) {
+ @exp = xCAT::PPCcli::connect( $hwtype, $_, $verbose );
+
+ ####################################
+ # Successfully connected
+ ####################################
+ if ( ref($exp[0]) eq "Expect" ) {
+ last;
+ }
+ }
+ ########################################
+ # Error connecting
+ ########################################
+ if ( ref($exp[0]) ne "Expect" ) {
+ send_msg( $request, $exp[0] );
+ return;
+ }
+ ########################################
+ # Process specific command
+ ########################################
+ my $result = runcmd( $request, $nodes, \@exp );
+
+ ########################################
+ # Close connection to remote server
+ ########################################
+ xCAT::PPCcli::disconnect( \@exp );
+
+ ########################################
+ # Return error
+ ########################################
+ if ( ref($result) ne 'ARRAY' ) {
+ send_msg( $request, $result );
+ return;
+ }
+ ########################################
+ # Send result back to parent process
+ ########################################
+ if ( @$result[0] eq "FORMATTED_DATA" ) {
+ shift(@$result);
+ my $out = $request->{pipe};
+ print $out freeze( [@$result] );
+ return;
+ }
+ ########################################
+ # Format and send back to parent
+ ########################################
+ foreach ( @$result ) {
+ my %output;
+ $output{node}->[0]->{name}->[0] = @$_[0];
+ $output{node}->[0]->{data}->[0]->{contents}->[0] = @$_[1];
+ push @outhash, \%output;
+ }
+ my $out = $request->{pipe};
+ print $out freeze( [@outhash] );
+}
+
+
+##########################################################################
+# Run the command method specified
+##########################################################################
+sub runcmd {
+
+ my $request = shift;
+ my $cmd = $request->{command};
+ my $method = $request->{method};
+ my $modname = $modules{$cmd};
+
+ ######################################
+ # Load specific module
+ ######################################
+ unless ( eval "require $modname" ) {
+ return( ["Can't locate $modname"] );
+ }
+ ######################################
+ # Invoke method
+ ######################################
+ no strict 'refs';
+ my $result = ${$modname."::"}{$method}->($request,@_);
+ use strict;
+
+ return( $result );
+
+}
+
+
+##########################################################################
+# Process request from xCat daemon
+##########################################################################
+sub process_request {
+
+ my $package = shift;
+ my $req = shift;
+ my $callback = shift;
+
+ ####################################
+ # Get hwtype
+ ####################################
+ $package =~ s/xCAT_plugin:://;
+
+ ####################################
+ # Build hash to pass around
+ ####################################
+ my %request;
+ $request{command} = $req->{command}->[0];
+ $request{arg} = $req->{arg};
+ $request{node} = $req->{node};
+ $request{stdin} = $req->{stdin}->[0];
+ $request{hwtype} = $package;
+ $request{callback} = $callback;
+ $request{method} = "parse_args";
+
+ ####################################
+ # Process command-specific options
+ ####################################
+ my $opt = runcmd( \%request );
+
+ ####################################
+ # Return error
+ ####################################
+ if ( ref($opt) eq 'ARRAY' ) {
+ send_msg( \%request, @$opt );
+ return(1);
+ }
+ ####################################
+ # Option -V for verbose output
+ ####################################
+ if ( exists( $opt->{V} )) {
+ $request{verbose} = 1;
+ }
+ ####################################
+ # Process remote command
+ ####################################
+ $request{opt} = $opt;
+ process_command( \%request );
+}
+
+
+
+
+1;
diff --git a/perl-xCAT-2.0/xCAT/PPCboot.pm b/perl-xCAT-2.0/xCAT/PPCboot.pm
new file mode 100644
index 000000000..c7bf432d6
--- /dev/null
+++ b/perl-xCAT-2.0/xCAT/PPCboot.pm
@@ -0,0 +1,170 @@
+# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
+
+package xCAT::PPCboot;
+use strict;
+use Getopt::Long;
+use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR);
+
+
+##########################################################################
+# Parse the command line for options and operands
+##########################################################################
+sub parse_args {
+
+ my $request = shift;
+ my %opt = ();
+ my $cmd = $request->{command};
+ my $args = $request->{arg};
+ my @VERSION = qw( 2.0 );
+
+ #############################################
+ # Responds with usage statement
+ #############################################
+ local *usage = sub {
+ return( [ $_[0],
+ "rnetboot -h|--help",
+ "rnetboot -v|--version",
+ "rnetboot [-V|--verbose] noderange -S server -G gateway -C client -m MAC-address",
+ " -h writes usage information to standard output",
+ " -v displays command version",
+ " -C IP of the partition to network boot",
+ " -G Gateway IP of the partition specified",
+ " -S IP of the machine to retrieve network boot image",
+ " -m MAC address of network adapter to use for network boot",
+ " -V verbose output" ]);
+ };
+ #############################################
+ # Process command-line arguments
+ #############################################
+ if ( !defined( $args )) {
+ return( usage() );
+ }
+ #############################################
+ # Checks case in GetOptions, allows opts
+ # to be grouped (e.g. -vx), and terminates
+ # at the first unrecognized option.
+ #############################################
+ @ARGV = @$args;
+ $Getopt::Long::ignorecase = 0;
+ Getopt::Long::Configure( "bundling" );
+
+ if ( !GetOptions( \%opt,
+ qw(h|help V|Verbose v|version C=s G=s S=s m=s ))) {
+ return( usage() );
+ }
+ ####################################
+ # Option -h for Help
+ ####################################
+ if ( exists( $opt{h} )) {
+ return( usage() );
+ }
+ ####################################
+ # Option -v for version
+ ####################################
+ if ( exists( $opt{v} )) {
+ return( \@VERSION );
+ }
+ ####################################
+ # Check for "-" with no option
+ ####################################
+ if ( grep(/^-$/, @ARGV )) {
+ return(usage( "Missing option: -" ));
+ }
+ ####################################
+ # Check for an extra argument
+ ####################################
+ if ( defined( $ARGV[0] )) {
+ return(usage( "Invalid Argument: $ARGV[0]" ));
+ }
+ ####################################
+ # Option -m required
+ ####################################
+ if ( !exists($opt{m}) ) {
+ return(usage( "Missing option: -m" ));
+ }
+ ####################################
+ # Options -C -G -S required
+ ####################################
+ foreach ( qw(C G S) ) {
+ if ( !exists($opt{$_}) ) {
+ return(usage( "Missing option: -$_" ));
+ }
+ }
+ my $result = validate_ip( $opt{C}, $opt{G}, $opt{S} );
+ if ( @$result[0] ) {
+ return(usage( @$result[1] ));
+ }
+ ####################################
+ # Set method to invoke
+ ####################################
+ $request->{method} = $cmd;
+ return( \%opt );
+}
+
+
+
+##########################################################################
+# Validate list of IPs
+##########################################################################
+sub validate_ip {
+
+ foreach (@_) {
+ my $ip = $_;
+
+ ###################################
+ # Length is 4 for IPv4 addresses
+ ###################################
+ my (@octets) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
+ if ( scalar(@octets) != 4 ) {
+ return( [1,"Invalid IP address: $ip"] );
+ }
+ foreach my $octet ( @octets ) {
+ if (( $octet < 0 ) or ( $octet > 255 )) {
+ return( [1,"Invalid IP address: $ip"] );
+ }
+ }
+ }
+ return([0]);
+}
+
+
+
+##########################################################################
+# Get LPAR MAC addresses
+##########################################################################
+sub rnetboot {
+
+ my $request = shift;
+ my $d = shift;
+ my $exp = shift;
+ my $hwtype = @$exp[2];
+ my $opt = $request->{opt};
+ my @output;
+
+ #####################################
+ # Get node data
+ #####################################
+ my $type = @$d[4];
+ my $name = @$d[6];
+
+ #####################################
+ # Invalid target hardware
+ #####################################
+ if ( $type !~ /^lpar$/ ) {
+ return( [[$name,"Not supported"]] );
+ }
+ my $result = xCAT::PPCcli::lpar_netboot(
+ $exp,
+ $name,
+ $d,
+ $opt->{S},
+ $opt->{G},
+ $opt->{C},
+ $opt->{m} );
+
+ my $Rc = shift(@$result);
+ return( [[$name,@$result[0]]] );
+}
+
+
+1;
diff --git a/perl-xCAT-2.0/xCAT/PPCcli.pm b/perl-xCAT-2.0/xCAT/PPCcli.pm
new file mode 100644
index 000000000..3094c0c4c
--- /dev/null
+++ b/perl-xCAT-2.0/xCAT/PPCcli.pm
@@ -0,0 +1,808 @@
+# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
+
+package xCAT::PPCcli;
+require Exporter;
+ @ISA = qw(Exporter);
+ @EXPORT_OK = qw(SUCCESS RC_ERROR EXPECT_ERROR NR_ERROR);
+use strict;
+use xCAT::PPCdb;
+use Expect;
+
+
+#############################################
+# Removes Ctrl characters from term output
+#############################################
+$ENV{'TERM'} = "vt100";
+
+##############################################
+# Constants
+##############################################
+use constant {
+ SUCCESS => 0,
+ RC_ERROR => 1,
+ EXPECT_ERROR => 2,
+ NR_ERROR => 3
+};
+
+##############################################
+# lssyscfg supported formats
+##############################################
+my %lssyscfg = (
+ fsp =>"lssyscfg -r sys -m %s -F %s",
+ fsps =>"lssyscfg -r sys -F %s",
+ node =>"lssyscfg -r lpar -m %s -F %s --filter lpar_ids=%s",
+ lpar =>"lssyscfg -r lpar -m %s -F %s",
+ bpa =>"lssyscfg -r frame -e %s -F %s",
+ bpas =>"lssyscfg -r frame -F %s",
+ prof =>"lssyscfg -r prof -m %s --filter lpar_ids=%s",
+ cprof =>"lssyscfg -r prof -m %s",
+ cage =>"lssyscfg -r cage -e %s -F %s"
+);
+
+##############################################
+# Power control supported formats
+##############################################
+my %powercmd = (
+ hmc => {
+ reset =>"hmcshutdown -t now -r" },
+ ivm => {
+ reset =>"reboot" },
+ lpar => {
+ on =>"chsysstate -r %s -m %s -o on -b norm --id %s -f %s",
+ of =>"chsysstate -r %s -m %s -o on --id %s -f %s -b of",
+ reset =>"chsysstate -r %s -m %s -o shutdown --id %s --immed --restart",
+ off =>"chsysstate -r %s -m %s -o shutdown --id %s --immed",
+ boot =>"undetermined" },
+ sys => {
+ reset =>"chsysstate -r %s -m %s -o off --immed --restart",
+ on =>"chsysstate -r %s -m %s -o on",
+ off =>"chsysstate -r %s -m %s -o off",
+ boot =>"undetermined" }
+);
+
+
+
+##########################################################################
+# Logon to remote server
+##########################################################################
+sub connect {
+
+ my $hwtype = shift;
+ my $server = shift;
+ my $verbose = shift;
+ my $pwd_prompt = 'assword: $';
+ my $continue = 'continue connecting (yes/no)?';
+ my $timeout = 10;
+ my $success = 0;
+ my $pwd_sent = 0;
+
+ ##################################################
+ # Shell prompt regexp based on HW Type
+ ##################################################
+ my %prompt = (
+ hmc => "~> \$",
+ ivm => "\\\$ \$"
+ );
+ ##################################################
+ # Get userid/password based on Hardware Conrol Pt
+ ##################################################
+ my @cred = xCAT::PPCdb::credentials( $server, $hwtype );
+
+ ##################################################
+ # ssh to remote host
+ ##################################################
+ my $parameters = "$cred[0]\@$server";
+ my $ssh = new Expect;
+
+ ##################################################
+ # raw_pty() disables command echoing and CRLF
+ # translation and gives a more pipe-like behaviour.
+ # Note that this must be set before spawning
+ # the process. Unfortunately, this does not work
+ # with AIX (IVM). stty(qw(-echo)) will at least
+ # disable command echoing on all platforms but
+ # will not suppress CRLF translation.
+ ##################################################
+ #$ssh->raw_pty(1);
+ $ssh->slave->stty(qw(sane -echo));
+
+ ##################################################
+ # exp_internal(1) sets exp_internal debugging.
+ # This is similar in nature to its Tcl counterpart
+ ##################################################
+ if ( $verbose ) {
+ $ssh->exp_internal(1);
+ }
+ ##################################################
+ # log_stdout(0) disables logging to STDOUT. This
+ # corresponds to the Tcl log_user variable.
+ ##################################################
+ if ( !$verbose ) {
+ $ssh->log_stdout(0);
+ }
+ unless ( $ssh->spawn( "ssh", $parameters )) {
+ return( "Unable to spawn ssh connection to server" );
+ }
+ ##################################################
+ # -re $continue
+ # "The authenticity of host can't be established
+ # RSA key fingerprint is ....
+ # Are you sure you want to continue connecting (yes/no)?"
+ #
+ # -re pwd_prompt
+ # If the keys have already been transferred, we
+ # may already be at the command prompt without
+ # sending the password.
+ #
+ ##################################################
+ my @result = $ssh->expect( $timeout,
+ [ $continue,
+ sub {
+ $ssh->send( "yes\r" );
+ $ssh->clear_accum();
+ $ssh->exp_continue();
+ } ],
+ [ $pwd_prompt,
+ sub {
+ if ( ++$pwd_sent == 1 ) {
+ $ssh->send( "$cred[1]\r" );
+ $ssh->exp_continue();
+ }
+ } ],
+ [ $prompt{$hwtype},
+ sub {
+ $success = 1;
+ } ]
+ );
+ ##########################################
+ # Expect error
+ ##########################################
+ if ( defined( $result[1] )) {
+ $ssh->hard_close();
+ return( expect_error(@result) );
+ }
+ ##########################################
+ # Successful logon....
+ # Return:
+ # Expect
+ # HW Shell Prompt regexp
+ # HW Type (hmc/ivm)
+ # Server hostname
+ # UserId
+ # Password
+ ##########################################
+ if ( $success ) {
+ return( $ssh,
+ $prompt{$hwtype},
+ $hwtype,
+ $server,
+ $cred[0],
+ $cred[1] );
+ }
+ ##########################################
+ # Failed logon - kill ssh process
+ ##########################################
+ $ssh->hard_close();
+ return( "Invalid userid/password" );
+}
+
+
+##########################################################################
+# Logoff to remote server
+##########################################################################
+sub disconnect {
+
+ my $exp = shift;
+ my $ssh = @$exp[0];
+
+ $ssh->send( "exit\r" );
+ $ssh->hard_close();
+
+}
+
+
+##########################################################################
+# List attributes for resources (lpars, managed system, etc)
+##########################################################################
+sub lssyscfg {
+
+ my $exp = shift;
+ my $res = shift;
+ my $d1 = shift;
+ my $d2 = shift;
+ my $d3 = shift;
+
+ ###################################
+ # Select command
+ ###################################
+ my $cmd = sprintf( $lssyscfg{$res}, $d1, $d2, $d3 );
+
+ ###################################
+ # Send command
+ ###################################
+ my $result = send_cmd( $exp, $cmd );
+ return( $result );
+}
+
+
+##########################################################################
+# Changes a logical partition configuration data
+##########################################################################
+sub chsyscfg {
+
+ my $exp = shift;
+ my $d = shift;
+ my $cfgdata = shift;
+ my $timeout = 60;
+
+ #####################################
+ # Command only support on LPARs
+ #####################################
+ if ( @$d[4] ne "lpar" ) {
+ return( [RC_ERROR,"Command not supported"] );
+ }
+ #####################################
+ # Format command based on CEC name
+ #####################################
+ my $cmd = "chsyscfg -r prof -m @$d[2] -i \"$cfgdata\"";
+
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd, $timeout );
+ return( $result );
+}
+
+
+##########################################################################
+# Creates a logical partition on the managed system
+##########################################################################
+sub mksyscfg {
+
+ my $exp = shift;
+ my $d = shift;
+ my $cfgdata = shift;
+ my $timeout = 60;
+
+ #####################################
+ # Command only support on LPARs
+ #####################################
+ if ( @$d[4] ne "lpar" ) {
+ return( [RC_ERROR,"Command not supported"] );
+ }
+ #####################################
+ # Format command based on CEC name
+ #####################################
+ my $cmd = "mksyscfg -r lpar -m @$d[2] -i \"$cfgdata\"";
+
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd, $timeout );
+ return( $result );
+}
+
+
+##########################################################################
+# Removes a logical partition on the managed system
+##########################################################################
+sub rmsyscfg {
+
+ my $exp = shift;
+ my $d = shift;
+ my $timeout = 60;
+
+ #####################################
+ # Command only supported on LPARs
+ #####################################
+ if ( @$d[4] ne "lpar" ) {
+ return( [RC_ERROR,"Command not supported"] );
+ }
+ #####################################
+ # Format command based on CEC name
+ #####################################
+ my $cmd = "rmsyscfg -r lpar -m @$d[2] --id @$d[0]";
+
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd, $timeout );
+ return( $result );
+}
+
+
+##########################################################################
+# Lists environmental information
+##########################################################################
+sub lshwinfo {
+
+ my $exp = shift;
+ my $res = shift;
+ my $frame = shift;
+ my $filter = shift;
+
+ #####################################
+ # Format command based on CEC name
+ #####################################
+ my $cmd = "lshwinfo -r $res -e $frame -F $filter";
+
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd );
+ return( $result );
+}
+
+
+##########################################################################
+# Changes the state of a partition or managed system
+##########################################################################
+sub chsysstate {
+
+ my $exp = shift;
+ my $op = shift;
+ my $d = shift;
+
+ #####################################
+ # Format command based on CEC name
+ #####################################
+ my $cmd = power_cmd( $op, $d );
+ if ( !defined( $cmd )) {
+ return( [RC_ERROR,"'$op' command not supported"] );
+ }
+ #####################################
+ # Special case - return immediately
+ #####################################
+ if ( $cmd =~ /^hmcshutdown|reboot/ ) {
+ my $ssh = @$exp[0];
+
+ $ssh->send( "$cmd\r" );
+ return( [SUCCESS,"Success"] );
+ }
+ #####################################
+ # Increase timeout for power command
+ #####################################
+ my $timeout = 15;
+
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd, $timeout );
+ return( $result );
+}
+
+
+
+##########################################################################
+# Opens a virtual terminal session
+##########################################################################
+sub mkvterm {
+
+ my $exp = shift;
+ my $type = shift;
+ my $lparid = shift;
+ my $mtms = shift;
+ my $ssh = @$exp[0];
+ my $hwtype = @$exp[2];
+ my $failed = 0;
+ my $timeout = 3;
+
+ ##########################################
+ # Format command based on HW Type
+ ##########################################
+ my %mkvt = (
+ hmc =>"mkvterm --id %s -m %s",
+ ivm =>"mkvt -id %s"
+ );
+ ##########################################
+ # HMC returns:
+ # "A terminal session is already open
+ # for this partition. Only one open
+ # session is allowed for a partition.
+ # Exiting...."
+ #
+ # HMCs may also return:
+ # "The open failed.
+ # "-The session may already be open on
+ # another management console"
+ #
+ # But Expect (for some reason) sees each
+ # character preceeded with \000 (blank??)
+ #
+ ##########################################
+ my $ivm_open = "Virtual terminal is already connected";
+ my $hmc_open = "\000o\000p\000e\000n\000 \000f\000a\000i\000l\000e\000d";
+ my $hmc_open2 =
+ "\000a\000l\000r\000e\000a\000d\000y\000 \000o\000p\000e\000n";
+
+ ##########################################
+ # Set command based on HW type
+ # mkvterm -id lparid -m cecmtms
+ ##########################################
+ my $cmd = sprintf( $mkvt{$hwtype}, $lparid, $mtms );
+ if ( $type ne "lpar" ) {
+ return( [RC_ERROR,"Command not supported"] );
+ }
+ ##########################################
+ # For IVM, console sessions must explicitly
+ # be closed after each open using rmvt
+ # or they will remain open indefinitely.
+ # For example, if the session is opened
+ # using xterm and closed with the [x] in
+ # the windows upper-right corner, we will
+ # not be able to catch (INT,HUP,QUIT,TERM)
+ # before the window closes in order to
+ # send an rmvt - so force any IVM sessions
+ # closed before we start.
+ #
+ # For HMC, apparently, once the console
+ # session connection is broken, the HMC
+ # closes the session. Therefore, it is not
+ # necessary to explicitly close the session.
+ #
+ ##########################################
+ if ( $hwtype eq "ivm" ) {
+ rmvterm( $exp, $lparid, $mtms );
+ sleep 1;
+ }
+ ##########################################
+ # Send command
+ ##########################################
+ $ssh->clear_accum();
+ $ssh->send( "$cmd\r" );
+
+ ##########################################
+ # Expect result
+ ##########################################
+ my @result = $ssh->expect( $timeout,
+ [ "$hmc_open|$hmc_open2|$ivm_open",
+ sub {
+ $failed = 1;
+ } ]
+ );
+
+ if ( $failed ) {
+ $ssh->hard_close();
+ return( [RC_ERROR,"Virtual terminal is already connected"] );
+ }
+
+ ##########################################
+ # Success...
+ # Give control to the user and intercept
+ # the Ctrl-X (\030), and "~." sequences.
+ ##########################################
+ my $escape = "\030|~.";
+ $ssh->send( "\r" );
+ $ssh->interact( \*STDIN, $escape );
+
+ ##########################################
+ # Close session
+ ##########################################
+ rmvterm( $exp, $lparid, $mtms );
+ $ssh->hard_close();
+
+ return( [SUCCESS,"Success"] );
+}
+
+
+##########################################################################
+# Force close a virtual terminal session
+##########################################################################
+sub rmvterm {
+
+ my $exp = shift;
+ my $lparid = shift;
+ my $mtms = shift;
+ my $ssh = @$exp[0];
+ my $hwtype = @$exp[2];
+
+ #####################################
+ # Format command based on HW Type
+ #####################################
+ my %rmvt = (
+ hmc =>"rmvterm --id %s -m %s",
+ ivm =>"rmvt -id %s"
+ );
+ #####################################
+ # Set command based on HW type
+ # rmvt(erm) -id lparid -m cecmtms
+ #####################################
+ my $cmd = sprintf( $rmvt{$hwtype}, $lparid, $mtms );
+
+ #####################################
+ # Send command
+ #####################################
+ $ssh->clear_accum();
+ $ssh->send( "$cmd\r" );
+}
+
+
+##########################################################################
+# Lists the hardware resources of a managed system
+##########################################################################
+sub lshwres {
+
+ my $exp = shift;
+ my $d = shift;
+ my $mtms = shift;
+ my $cmd = "lshwres -r @$d[1] -m $mtms -F @$d[2]";
+ my $level = @$d[0];
+
+ #####################################
+ # level may be "sys" or "lpar"
+ #####################################
+ if ( defined( $level )) {
+ $cmd .=" --level $level";
+ }
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd );
+ return( $result );
+}
+
+
+##########################################################################
+# Retrieve MAC-address from network adapter or network boots an LPAR
+##########################################################################
+sub lpar_netboot {
+
+ my $exp = shift;
+ my $name = shift;
+ my $d = shift;
+ my $server = shift;
+ my $gateway = shift;
+ my $client = shift;
+ my $mac = shift;
+ my $timeout = 300;
+ my $cmd = "lpar_netboot -t ent";
+
+ #####################################
+ # Get MAC-address or network boot
+ #####################################
+ $cmd.= (defined( $mac )) ? " -m $mac" : " -M -n";
+
+ #####################################
+ # Command only supported on LPARs
+ #####################################
+ if ( @$d[4] ne "lpar" ) {
+ return( [RC_ERROR,"Command not supported"] );
+ }
+ #####################################
+ # Network specified (-D ping test)
+ #####################################
+ if ( defined( $server )) {
+ $cmd.= (!defined( $mac )) ? " -D" : "";
+ $cmd.= " -s auto -d auto -S $server -G $gateway -C $client";
+ }
+ #####################################
+ # Add lpar name, profile, CEC name
+ #####################################
+ $cmd.= " \"$name\" \"@$d[1]\" \"@$d[2]\"";
+
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd, $timeout );
+ return( $result );
+}
+
+
+##########################################################################
+# List Hardware Management Console configuration information
+##########################################################################
+sub lshmc {
+
+ my $exp = shift;
+ my $hwtype = @$exp[2];
+ my $timeout = 10;
+
+ #####################################
+ # Format command based on HW Type
+ #####################################
+ my %cmd = (
+ hmc =>"lshmc -v",
+ ivm =>"lsivm"
+ );
+
+ #####################################
+ # Send command
+ #####################################
+ my $result = send_cmd( $exp, $cmd{$hwtype}, $timeout );
+
+ #####################################
+ # Return error
+ #####################################
+ if ( @$result[0] != SUCCESS ) {
+ return( $result );
+ }
+ #####################################
+ # IVM returns:
+ # 9133-55A,10B7D1G,1
+ #
+ # HMC returns:
+ # "vpd=*FC ????????
+ # *VC 20.0
+ # *N2 Mon Sep 24 13:54:00 GMT 2007
+ # *FC ????????
+ # *DS Hardware Management Console
+ # *TM 7310-CR4
+ # *SE 1017E6B
+ # *MN IBM
+ # *PN Unknown
+ # *SZ 1058721792
+ # *OS Embedded Operating Systems
+ # *NA 9.114.222.111
+ # *FC ????????
+ # *DS Platform Firmware
+ # *RM V7R3.1.0.1
+ #####################################
+ if ( $hwtype eq "ivm" ) {
+ my ($model,$serial,$lparid) = split /,/, @$result[1];
+ return( [SUCCESS,"$model,$serial"] );
+ }
+ my @values;
+ my $vpd = join( ",", @$result );
+
+ #####################################
+ # Type-Model may be in the formats:
+ # "eserver xSeries 336 -[7310CR3]-"
+ # "7310-CR4"
+ #####################################
+ if ( $vpd =~ /\*TM ([^,]+)/ ) {
+ my $temp = $1;
+ my $model = ($temp =~ /\[(.*)\]/) ? $1 : $temp;
+ push @values, $model;
+ }
+ #####################################
+ # Serial number
+ #####################################
+ if ( $vpd =~ /\*SE ([^,]+)/ ) {
+ push @values, $1;
+ }
+ return( [SUCCESS,join( ",",@values)] );
+
+}
+
+
+
+##########################################################################
+# Sends command and waits for response
+##########################################################################
+sub send_cmd {
+
+ my $exp = shift;
+ my $cmd = shift;
+ my $timeout = shift;
+ my $ssh = @$exp[0];
+ my $prompt = @$exp[1];
+
+ ##########################################
+ # Set default Expect timeout
+ ##########################################
+ if ( !defined( $timeout )) {
+ $timeout = 10;
+ }
+ ##########################################
+ # Send command
+ ##########################################
+ $ssh->clear_accum();
+ $ssh->send( "$cmd; echo Rc=\$\?\r" );
+
+ ##########################################
+ # The first element is the number of the
+ # pattern or string that matched, the
+ # same as its return value in scalar
+ # context. The second argument is a
+ # string indicating why expect returned.
+ # If there were no error, the second
+ # argument will be undef. Possible errors
+ # are 1:TIMEOUT, 2:EOF, 3:spawn id(...)died,
+ # and "4:..." (see Expect (3) manpage for
+ # the precise meaning of these messages)
+ # The third argument of expects return list
+ # is the string matched. The fourth argument
+ # is text before the match, and the fifth
+ # argument is text after the match.
+ ##########################################
+ my @result = $ssh->expect( $timeout, "-re", "(.*$prompt)" );
+
+ ##########################################
+ # Expect error
+ ##########################################
+ if ( defined( $result[1] )) {
+ return( [EXPECT_ERROR,expect_error( @result )] );
+ }
+ ##########################################
+ # Extract error code
+ ##########################################
+ if ( $result[3] =~ s/Rc=([0-9])+\r\n// ) {
+ if ( $1 != 0 ) {
+ return( [RC_ERROR,$result[3]] );
+ }
+ }
+ ##########################################
+ # No data found - return error
+ ##########################################
+ if ( $result[3] =~ /No results were found/ ) {
+ return( [NR_ERROR,"No results were found"] );
+ }
+ ##########################################
+ # If no command output, return "Success"
+ ##########################################
+ if ( length( $result[3] ) == 0 ) {
+ $result[3] = "Success";
+ }
+ ##########################################
+ # Success
+ ##########################################
+ my @values = ( SUCCESS );
+ push @values, split /\r\n/, $result[3];
+ return( \@values );
+}
+
+
+##########################################################################
+# Return Expect error
+##########################################################################
+sub expect_error {
+
+ my @error = @_;
+
+ ##########################################
+ # The first element is the number of the
+ # pattern or string that matched, the
+ # same as its return value in scalar
+ # context. The second argument is a
+ # string indicating why expect returned.
+ # If there were no error, the second
+ # argument will be undef. Possible errors
+ # are 1:TIMEOUT, 2:EOF, 3:spawn id(...)died,
+ # and "4:..." (see Expect (3) manpage for
+ # the precise meaning of these messages)
+ # The third argument of expects return list
+ # is the string matched. The fourth argument
+ # is text before the match, and the fifth
+ # argument is text after the match.
+ ##########################################
+ if ( $error[1] eq "1:TIMEOUT" ) {
+ return( "Timeout waiting for prompt" );
+ }
+ if ( $error[1] eq "2:EOF" ) {
+ if ( $error[3] ) {
+ return( $error[3] );
+ }
+ return( "ssh connection terminated unexpectedly" );
+ }
+ return( "Logon failed" );
+}
+
+
+
+##########################################################################
+# Returns built command based on CEC/LPAR action
+##########################################################################
+sub power_cmd {
+
+ my $op = shift;
+ my $d = shift;
+ my $type = @$d[4];
+
+ ##############################
+ # Build command
+ ##############################
+ my $cmd = $powercmd{$type}{$op};
+
+ if ( defined( $cmd )) {
+ return( sprintf( $cmd, $type, @$d[2],@$d[0],@$d[1] ));
+ }
+ ##############################
+ # Command not supported
+ ##############################
+ return undef;
+}
+
+
+
+
+1;
diff --git a/perl-xCAT-2.0/xCAT/PPCdb.pm b/perl-xCAT-2.0/xCAT/PPCdb.pm
new file mode 100644
index 000000000..b563a322a
--- /dev/null
+++ b/perl-xCAT-2.0/xCAT/PPCdb.pm
@@ -0,0 +1,178 @@
+# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
+
+package xCAT::PPCdb;
+use strict;
+use Getopt::Long;
+use xCAT::Table;
+
+
+##########################################################################
+# Adds an LPAR to the xCAT databases
+##########################################################################
+sub add_ppc {
+
+ my $hwtype = shift;
+ my $values = shift;
+ my @tabs = qw(ppc vpd nodehm nodelist);
+ my %db = ();
+
+ ###################################
+ # Open database needed
+ ###################################
+ foreach ( @tabs ) {
+ $db{$_} = xCAT::Table->new( $_, -create=>1, -autocommit=>0 );
+ if ( !$db{$_} ) {
+ return;
+ }
+ }
+ ###################################
+ # Update tables
+ ###################################
+ foreach ( @$values ) {
+ my ($type,
+ $name,
+ $id,
+ $model,
+ $serial,
+ $server,
+ $profile,
+ $mgt,
+ $ips ) = split /,/;
+
+
+ ###############################
+ # Update ppc table
+ ###############################
+ if ( $type =~ /^fsp|bpa|lpar$/ ) {
+ my ($k,$u);
+ $k->{node} = $name;
+ $u->{hcp} = $server;
+ $u->{id} = $id;
+ $u->{profile} = $profile;
+ $u->{mgt} = $mgt;
+ $db{ppc}->setAttribs( $k, $u );
+ $db{ppc}{commit} = 1;
+
+ ###########################
+ # Update nodelist table
+ ###########################
+ my ($k1,$u1);
+ my %nodetype = (
+ fsp => "fsp",
+ bpa => "bpa",
+ lpar => "osi"
+ );
+ $k1->{node} = $name;
+ $u1->{groups} = lc($hwtype).",all";
+ $u1->{nodetype} = $nodetype{$type};
+ $db{nodelist}->setAttribs( $k1,$u1 );
+ $db{nodelist}{commit} = 1;
+
+ ###########################
+ # Update nodehm table
+ ###########################
+ my ($k2,$u2);
+ $k2->{node} = $name;
+ $u2->{mgt} = $hwtype;
+ $db{nodehm}->setAttribs( $k2,$u2 );
+ $db{nodehm}{commit} = 1;
+ }
+ ###############################
+ # Update vpd table
+ ###############################
+ if ( $type =~ /^fsp|bpa$/ ) {
+ my ($k,$u);
+ $k->{node} = $name;
+ $u->{serial} = $serial;
+ $u->{mtm} = $model;
+ $db{vpd}->setAttribs( $k,$u );
+ $db{vpd}{commit} = 1;
+ }
+ }
+
+ ###################################
+ # Commit changes
+ ###################################
+ foreach ( @tabs ) {
+ if ( exists( $db{$_}{commit} )) {
+ $db{$_}->commit;
+ }
+ }
+}
+
+
+##########################################################################
+# Adds a hardware control point to the xCAT database
+##########################################################################
+sub add_ppch {
+
+ my $hwtype = shift;
+ my $uid = shift;
+ my $pw = shift;
+ my $name = shift;
+ my $k;
+ my $u;
+
+ ###################################
+ # Update HWCtrl Point table
+ ###################################
+ my $tab = xCAT::Table->new( 'ppch', -create=>1, -autocommit=>0 );
+ if ( !$tab ) {
+ return;
+ }
+ $k->{hcp} = $name;
+ $u->{username} = $uid;
+ $u->{password} = $pw;
+
+ $tab->setAttribs( $k, $u );
+ $tab->commit;
+
+}
+
+
+##########################################################################
+# Get userids and passwords from tables
+##########################################################################
+sub credentials {
+
+ my $server = shift;
+ my $hwtype = shift;
+ my %db = (
+ hmc => "ppchcp",
+ ivm => "ppchcp",
+ fsp => "ppcDirect"
+ );
+
+ ###########################################
+ # Get userid/password based on HwCtrl Pt
+ ###########################################
+ my $tab = xCAT::Table->new( $db{$hwtype} );
+ if ( $tab ) {
+ my ($ent) = $tab->getAttribs({'hcp'=>$server},'username','password');
+ if ( defined( $ent ) ) {
+ return( $ent->{username},$ent->{password} );
+ }
+ }
+ ###########################################
+ # Get userid/password based on type
+ ###########################################
+ $tab = xCAT::Table->new( 'passwd' );
+ if ( $tab ) {
+ my ($ent) = $tab->getAttribs({'key'=>$hwtype},'username','password');
+ if ( defined( $ent ) ) {
+ return( $ent->{username},$ent->{password} );
+ }
+ }
+ ###########################################
+ # Use factory defaults
+ ###########################################
+ my %logon = (
+ hmc => ["hscroot","abc123"],
+ ivm => ["padmin", "padmin"],
+ fsp => ["dev", "FipSdev"]
+ );
+ return( @{$logon{$hwtype}}[0], @{$logon{$hwtype}}[1] );
+}
+
+
+1;
diff --git a/perl-xCAT-2.0/xCAT/PPCfsp.pm b/perl-xCAT-2.0/xCAT/PPCfsp.pm
new file mode 100644
index 000000000..df7db23d1
--- /dev/null
+++ b/perl-xCAT-2.0/xCAT/PPCfsp.pm
@@ -0,0 +1,568 @@
+# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
+
+package xCAT::PPCfsp;
+use strict;
+use LWP;
+use HTTP::Cookies;
+
+
+##########################################
+# Globals
+##########################################
+my %cmds = (
+ rpower => {
+ state => ["Power On/Off System", \&state],
+ on => ["Power On/Off System", \&on],
+ off => ["Power On/Off System", \&off],
+ reset => ["System Reboot", \&reset],
+ boot => ["Power On/Off System", \&boot] },
+ reventlog => {
+ all => ["Error/Event Logs", \&all],
+ all_clear => ["Error/Event Logs", \&all_clear],
+ entries => ["Error/Event Logs", \&entries],
+ clear => ["Error/Event Logs", \&clear] }
+);
+
+
+
+##########################################################################
+# FSP command handler through HTTP interface
+##########################################################################
+sub handler {
+
+ my $server = shift;
+ my $request = shift;
+ my $command = $request->{command};
+ my $verbose = $request->{verbose};
+ my $method = $request->{method};
+ my $start;
+
+ ##################################
+ # Check command
+ ##################################
+ if ( !exists( $cmds{$command}{$method} )) {
+ my %output;
+ $output{node}->[0]->{name}->[0] = $server;
+ $output{node}->[0]->{data}->[0]->{contents}->[0]= "Unsupported command";
+ return( [\%output] );
+ }
+ ##################################
+ # Start timer
+ ##################################
+ if ( $verbose ) {
+ $start = Time::HiRes::gettimeofday();
+ }
+ ##################################
+ # Connect to remote FSP
+ ##################################
+ my @exp = xCAT::PPCfsp::connect( $server, $verbose );
+
+ if ( ref($exp[0]) ne "LWP::UserAgent" ) {
+ my %output;
+ $output{node}->[0]->{name}->[0] = $server;
+ $output{node}->[0]->{data}->[0]->{contents}->[0] = $exp[0];
+ return( [\%output] );
+ }
+ ##################################
+ # Process FSP command
+ ##################################
+ my $result = process_cmd( \@exp, $request );
+
+ my %output;
+ $output{node}->[0]->{name}->[0] = $server;
+ $output{node}->[0]->{data}->[0]->{contents}->[0] = $result;
+
+ ##################################
+ # Disconnect from FSP
+ ##################################
+ xCAT::PPCfsp::disconnect( \@exp );
+
+ ##################################
+ # Record Total time
+ ##################################
+ if ( $verbose ) {
+ my $elapsed = Time::HiRes::gettimeofday() - $start;
+ my $total = sprintf( "Total Elapsed Time: %.3f sec\n", $elapsed );
+ print STDERR $total;
+ }
+ return( [\%output] );
+
+}
+
+
+##########################################################################
+# Logon through remote FSP HTTP-interface
+##########################################################################
+sub connect {
+
+ my $server = shift;
+ my $verbose = shift;
+
+ ##################################
+ # Get userid/password
+ ##################################
+ my @cred = xCAT::PPCdb::credentials( $server, "fsp" );
+
+ ##################################
+ # Turn on tracing
+ ##################################
+ if ( $verbose ) {
+ LWP::Debug::level( '+' );
+ }
+ ##################################
+ # Create cookie
+ ##################################
+ my $cookie = HTTP::Cookies->new();
+ $cookie->set_cookie( 0,'asm_session','0','cgi-bin','','443',0,0,3600,0 );
+
+ ##################################
+ # Create UserAgent
+ ##################################
+ my $ua = LWP::UserAgent->new();
+
+ ##################################
+ # Set options
+ ##################################
+ my $url = "https://$server/cgi-bin/cgi?form=2";
+ $ua->cookie_jar( $cookie );
+ $ua->timeout(30);
+
+ ##################################
+ # Submit logon
+ ##################################
+ my $res = $ua->post( $url,
+ [ user => $cred[0],
+ password => $cred[1],
+ lang => "0",
+ submit => "Log in"
+ ]
+ );
+
+ ##################################
+ # Logon failed
+ ##################################
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+ ##################################
+ # To minimize number of GET/POSTs,
+ # if we successfully logon, we should
+ # get back a valid cookie:
+ # Set-Cookie: asm_session=3038839768778613290
+ #
+ ##################################
+
+ if ( $res->as_string =~ /Set-Cookie: asm_session=(\d+)/ ) {
+ ##############################
+ # Successful logon....
+ # Return:
+ # UserAgent
+ # Server hostname
+ # UserId
+ ##############################
+ return( $ua,
+ $server,
+ $cred[0] );
+ }
+ ##############################
+ # Logon error
+ ##############################
+ $res = $ua->get( $url );
+
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+ ##############################
+ # Check for specific failures
+ ##############################
+ my @error = (
+ "Invalid user ID or password",
+ "Too many users"
+ );
+ foreach ( @error ) {
+ if ( $res->content =~ /$_/i ) {
+ return( $_ );
+ }
+ }
+ return( "Logon failure" );
+
+}
+
+
+##########################################################################
+# Logoff through remote FSP HTTP-interface
+##########################################################################
+sub disconnect {
+
+ my $exp = shift;
+ my $ua = @$exp[0];
+ my $server = @$exp[1];
+ my $uid = @$exp[2];
+
+ ##################################
+ # POST Logoff
+ ##################################
+ my $res = $ua->post(
+ "https://$server/cgi-bin/cgi?form=1",
+ [submit => "Log out"]);
+
+ ##################################
+ # Logoff failed
+ ##################################
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+}
+
+
+##########################################################################
+# Execute FSP command
+##########################################################################
+sub process_cmd {
+
+ my $exp = shift;
+ my $request = shift;
+ my $ua = @$exp[0];
+ my $server = @$exp[1];
+ my $uid = @$exp[2];
+ my $command = $request->{command};
+ my $method = $request->{method};
+ my %menu = ();
+
+ ##################################
+ # We have to expand the main
+ # menu since unfortunately, the
+ # the forms numbers are not the
+ # same across FSP models/firmware
+ # versions.
+ ##################################
+ my $url = "https://$server/cgi-bin/cgi";
+ my $res = $ua->post( $url,
+ [form => "2",
+ e => "1" ]
+ );
+ ##################################
+ # Return error
+ ##################################
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+ ##################################
+ # Build hash of expanded menus
+ ##################################
+ foreach ( split /\n/, $res->content ) {
+ if ( /form=(\d+).*window.status='(.*)'/ ) {
+ $menu{$2} = $1;
+ }
+ }
+ ##################################
+ # Get form id
+ ##################################
+ my $form = $menu{$cmds{$command}{$method}[0]};
+
+ if ( !defined( $form )) {
+ return( "Cannot find '$cmds{$command}{$method}[0]' menu" );
+ }
+ ##################################
+ # Run command
+ ##################################
+ my $result = $cmds{$command}{$method}[1]($exp, $request, $form, \%menu);
+ return( $result );
+}
+
+
+##########################################################################
+# Returns current power state
+##########################################################################
+sub state {
+
+ my $exp = shift;
+ my $request = shift;
+ my $form = shift;
+ my $menu = shift;
+ my $ua = @$exp[0];
+ my $server = @$exp[1];
+
+ ##################################
+ # Get current power status
+ ##################################
+ my $res = $ua->get( "https://$server/cgi-bin/cgi?form=$form" );
+
+ ##################################
+ # Return error
+ ##################################
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+ ##################################
+ # Get power state
+ ##################################
+ if ( $res->content =~ /Current system power state: (.*)
/) {
+ return( $1 );
+ }
+ return( "unknown" );
+}
+
+
+##########################################################################
+# Powers FSP On
+##########################################################################
+sub on {
+ return( power(@_,"on","on") );
+}
+
+
+##########################################################################
+# Powers FSP Off
+##########################################################################
+sub off {
+ return( power(@_,"off","of") );
+}
+
+
+##########################################################################
+# Powers FSP On/Off
+##########################################################################
+sub power {
+
+ my $exp = shift;
+ my $request = shift;
+ my $form = shift;
+ my $menu = shift;
+ my $state = shift;
+ my $button = shift;
+ my $command = $request->{command};
+ my $ua = @$exp[0];
+ my $server = @$exp[1];
+
+ ##################################
+ # Send Power On command
+ ##################################
+ my $res = $ua->post( "https://$server/cgi-bin/cgi",
+ [form => $form,
+ sp => "255", # System boot speed: Fast
+ is => "1", # Firmware boot side for the next boot: Temporary
+ om => "4", # System operating mode: Normal
+ ip => "2", # Boot to system server firmware: Running
+ plt => "3", # System power off policy: Stay on
+ $button => "Save settings and power $state"]
+ );
+ ##################################
+ # Return error
+ ##################################
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+ if ( $res->content =~
+ /(Powering on or off not allowed: invalid system state)/) {
+
+ ##############################
+ # Check current power state
+ ##############################
+ my $state = xCAT::PPCfsp::state(
+ $exp,
+ $request,
+ $menu->{$cmds{$command}{state}[0]},
+ $menu );
+
+ if ( $state eq $state ) {
+ return( "Success" );
+ }
+ return( $1 );
+ }
+ ##################################
+ # Success
+ ##################################
+ if ( $res->content =~ /(Operation completed successfully)/ ) {
+ return( $1 );
+ }
+ return( "Unknown error" );
+}
+
+
+##########################################################################
+# Reset FSP
+##########################################################################
+sub reset {
+
+ my $exp = shift;
+ my $request = shift;
+ my $form = shift;
+ my $menu = shift;
+ my $ua = @$exp[0];
+ my $server = @$exp[1];
+
+ ##################################
+ # Send Reset command
+ ##################################
+ my $res = $ua->post( "https://$server/cgi-bin/cgi",
+ [form => $form,
+ submit => "Continue" ]
+ );
+ ##################################
+ # Return error
+ ##################################
+ if ( !$res->is_success()) {
+ print STDERR $res->status_line();
+ return;
+ }
+ if ( $res->content =~
+ /(This feature is only available when the system is powered on)/ ) {
+ return( $1 );
+ }
+ ##################################
+ # Success
+ ##################################
+ if ( $res->content =~ /(Operation completed successfully)/ ) {
+ return( $1 );
+ }
+ return( "Unknown error" );
+}
+
+
+##########################################################################
+# Boots FSP (Off->On, On->Reset)
+##########################################################################
+sub boot {
+
+ my $exp = shift;
+ my $request = shift;
+ my $form = shift;
+ my $menu = shift;
+ my $command = $request->{command};
+
+ ##################################
+ # Check current power state
+ ##################################
+ my $state = xCAT::PPCfsp::state(
+ $exp,
+ $request,
+ $menu->{$cmds{$command}{state}[0]},
+ $menu );
+
+ if ( $state !~ /^on|off$/ ) {
+ return( "Unable to boot in state: '$state'" );
+ }
+ ##################################
+ # Get command
+ ##################################
+ my $method = ($state eq "on") ? "reset" : "off";
+
+ ##################################
+ # Get command form id
+ ##################################
+ $form = $menu->{$cmds{$command}{$method}[0]};
+
+ ##################################
+ # Run command
+ ##################################
+ my $result = $cmds{$method}[1]( $exp, $state, $form );
+ return( $result );
+}
+
+
+##########################################################################
+# Clears Error/Event Logs
+##########################################################################
+sub clear {
+
+ my $exp = shift;
+ my $request = shift;
+ my $form = shift;
+ my $menu = shift;
+ my $ua = @$exp[0];
+ my $server = @$exp[1];
+
+ ##################################
+ # Send Clear command
+ ##################################
+ my $url = "https://$server/cgi-bin/cgi";
+ my $res = $ua->post( $url,
+ [form => $form,
+ submit => "Clear all error/event log entries" ]
+ );
+ ##################################
+ # Return error
+ ##################################
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+ return( "Success" );
+}
+
+
+##########################################################################
+# Gets the number of Error/Event Logs entries specified
+##########################################################################
+sub entries {
+
+ my $exp = shift;
+ my $request = shift;
+ my $form = shift;
+ my $menu = shift;
+ my $ua = @$exp[0];
+ my $server = @$exp[1];
+ my $opt = $request->{opt};
+ my $count = (exists($opt->{e})) ? $opt->{e} : 9999;
+ my $result;
+ my $i = 1;
+
+ ##################################
+ # Get log entries
+ ##################################
+ my $url = "https://$server/cgi-bin/cgi?form=$form";
+ my $res = $ua->get( $url );
+
+ ##################################
+ # Return error
+ ##################################
+ if ( !$res->is_success() ) {
+ return( $res->status_line );
+ }
+ my @entries = split /\n/, $res->content;
+
+ ##################################
+ # Prepend header
+ ##################################
+ $result = (@entries) ?
+ "#Log ID Time Failing subsystem Severity SRC\n" :
+ "No entries";
+
+ ##################################
+ # Parse log entries
+ ##################################
+ foreach ( @entries ) {
+ if ( /tabindex=[\d]+><\/td>