diff --git a/perl-xCAT/xCAT/FSPboot.pm b/perl-xCAT/xCAT/FSPboot.pm new file mode 100644 index 000000000..23aa170c4 --- /dev/null +++ b/perl-xCAT/xCAT/FSPboot.pm @@ -0,0 +1,389 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +package xCAT::FSPboot; +use strict; +use Getopt::Long; +use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); +use xCAT::Usage; +use xCAT::Utils; +use xCAT::MsgUtils; +use xCAT::PPCboot; + +########################################################################## +# Parse the command line for options and operands +########################################################################## +sub parse_args { + xCAT::PPCboot::parse_args(@_); +} + + +########################################################################## +# Netboot the lpar +########################################################################## +sub do_rnetboot { + + my $request = shift; + my $d = shift; + my $exp = shift; + my $name = shift; + my $node = shift; + my $opt = shift; + my $ssh = @$exp[0]; + my $userid = @$exp[4]; + my $pw = @$exp[5]; + my $cmd; + my $result; + + ####################################### + # Disconnect Expect session + ####################################### + #xCAT::PPCcli::disconnect( $exp ); + + ####################################### + # Get node data + ####################################### + my $id = @$d[0]; + my $pprofile = @$d[1]; + my $fsp = @$d[2]; + my $hcp = @$d[3]; + + ####################################### + # Find Expect script + ####################################### + $cmd = ($::XCATROOT) ? "$::XCATROOT/sbin/" : "/opt/xcat/sbin/"; + $cmd .= "lpar_netboot2.expect"; + + ####################################### + # Check command installed + ####################################### + if ( !-x $cmd ) { + return( [RC_ERROR,"Command not installed: $cmd"] ); + } + ####################################### + # Save user name and passwd of hcp to + # environment variables. + # lpar_netboot.expect depends on it + ####################################### + $ENV{HCP_USERID} = $userid; + $ENV{HCP_PASSWD} = $pw; + + ####################################### + # Turn on verbose and debugging + ####################################### + if ( exists($request->{verbose}) ) { + $cmd.= " -v -x"; + } + ####################################### + # Force LPAR shutdown + ####################################### + if ( exists( $opt->{f} ) || !xCAT::Utils->isAIX() ) { + $cmd.= " -i"; + } + + ####################################### + # Write boot order + ####################################### + if ( exists( $opt->{s} )) { + foreach ($opt->{s}) { + if ( /^net$/ ) { + $cmd.= " -w 1"; + } elsif ( /^net,hd$/ ) { + $cmd.= " -w 2"; + } elsif ( /^hd,net$/ ) { + $cmd.= " -w 3"; + } elsif ( /^hd$/ ) { + $cmd.= " -w 4"; + } + } + } + + ####################################### + # Network specified + ####################################### + $cmd.= " -s auto -d auto -m $opt->{m} -S $opt->{S} -G $opt->{G} -C $opt->{C}"; + + ####################################### + # Add command options + ####################################### + $cmd.= " -t ent -f \"$name\" \"$pprofile\" \"$fsp\" $id $hcp \"$node\""; + print "cmd: $cmd\n"; + my $done = 0; + my $Rc = SUCCESS; + while ( $done < 2 ) { + ####################################### + # Execute command + ####################################### + print "cmd:$cmd\n"; + my $pid = open( OUTPUT, "$cmd 2>&1 |"); + $SIG{INT} = $SIG{TERM} = sub { #prepare to process job termination and propogate it down + kill 9, $pid; + return( [RC_ERROR,"Received INT or TERM signal"] ); + }; + if ( !$pid ) { + return( [RC_ERROR,"$cmd fork error: $!"] ); + } + ####################################### + # Get command output + ####################################### + while ( ) { + $result.=$_; + } + close OUTPUT; + + ####################################### + # Get command exit code + ####################################### + + foreach ( split /\n/, $result ) { + if ( /^lpar_netboot: / ) { + $Rc = RC_ERROR; + last; + } + } + + if ( $Rc == SUCCESS ) { + $done = 2; + } else { + $done = $done + 1; + sleep 1; + } + } + return( [$Rc,$result] ); +} + + +########################################################################## +# Get LPAR MAC addresses +########################################################################## +sub rnetboot { + + my $request = shift; + my $d = shift; + my $exp = shift; + my $options = $request->{opt}; + my $hwtype = @$exp[2]; + my $result; + my $name; + my $callback = $request->{callback}; + ##################################### + # Get node data + ##################################### + my $lparid = @$d[0]; + my $mtms = @$d[2]; + my $type = @$d[4]; + my $node = @$d[6]; + my $o = @$d[7]; + + ##################################### + # Gateway (-G) + # Server (-S) + # Client (-C) + # mac (-m) + ##################################### + my %opt = ( + G => $o->{gateway}, + S => $o->{server}, + C => $o->{client}, + m => $o->{mac} + ); + ##################################### + # Strip colons from mac address + ##################################### + $opt{m} =~ s/://g; + + ##################################### + # Force LPAR shutdown + ##################################### + if ( exists( $options->{f} )) { + $opt{f} = 1; + } + ##################################### + # Write boot device order + ##################################### + if ( exists( $options->{s} )) { + $opt{s} = $options->{s}; + } + + ##################################### + # Invalid target hardware + ##################################### + if ( $type !~ /^lpar$/ ) { + return( [[$name,"Not supported",RC_ERROR]] ); + } + ######################################### + # Get name known by HCP + ######################################### + #my $filter = "name,lpar_id"; + #my $values = xCAT::PPCcli::lssyscfg( $exp, $type, $mtms, $filter ); + #my $Rc = shift(@$values); + + ######################################### + # Return error + ######################################### + #if ( $Rc != SUCCESS ) { + # return( [[$node,@$values[0],$Rc]] ); + #} + ######################################### + # Find LPARs by lpar_id + ######################################### + #foreach ( @$values ) { + # if ( /^(.*),$lparid$/ ) { + # $name = $1; + # last; + # } + #} + ######################################### + # Node not found by lpar_id + ######################################### + #if ( !defined( $name )) { + # return( [[$node,"Node not found, lparid=$lparid",RC_ERROR]] ); + #} + my $Rc; + ######################################### + # Check current node state. + # It is not allowed to rinitialize node + # if it is in boot state + ######################################### + if ( !exists( $options->{F} ) && !xCAT::Utils->isAIX() ) { + my $chaintab = xCAT::Table->new('chain'); + my $vcon = $chaintab->getAttribs({ node => "$node"}, 'currstate'); + if ( $vcon and $vcon->{"currstate"} and $vcon->{"currstate"} eq "boot" ) { + return( [[$node,"Node is in boot state. Use nimnodeset command before rnetboot or -F option to forcely reinitialize",RC_ERROR]] ); + } + } + + my $sitetab = xCAT::Table->new('site'); + my $vcon = $sitetab->getAttribs({key => "conserverondemand"}, 'value'); + if ($vcon and $vcon->{"value"} and $vcon->{"value"} eq "yes" ) { + # $result = xCAT::PPCcli::lpar_netboot( + # $exp, + # $request->{verbose}, + # $name, + # $d, + # \%opt ); + return( [[$node,"Not support conserverondemand's value is yes",RC_ERROR]] ); + } else { + ######################################### + # Manually perform boot. + ######################################### + $result = do_rnetboot( $request, $d, $exp, $name, $node, \%opt ); + } + $sitetab->close; + + if (defined($request->{opt}->{m})) { + + my $retries = 0; + my @monnodes = ($name); + my $monsettings = xCAT::Utils->generate_monsettings($request, \@monnodes); + xCAT::Utils->monitor_installation($request, $monsettings);; + while ($retries++ < $monsettings->{'retrycount'} && scalar(keys %{$monsettings->{'nodes'}}) > 0) { + ####lparnetboot can not support multiple nodes in one invocation + ####for now, does not know how the $d and \%opt will be changed if + ####support mulitiple nodes in one invocation, + ####so just use the original node name and node attribute array and hash + + my $rsp={}; + $rsp->{data}->[0] = "$node: Reinitializing the installation: $retries retry"; + xCAT::MsgUtils->message("I", $rsp, $callback); + if ($vcon and $vcon->{"value"} and $vcon->{"value"} eq "yes" ) { + # $result = xCAT::PPCcli::lpar_netboot( + # $exp, + # $request->{verbose}, + # $name, + # $d, + # \%opt ); + return( [[$node,"Not support conserverondemand's value is yes",RC_ERROR]] ); + } else { + $result = do_rnetboot( $request, $d, $exp, $name, $node, \%opt ); + } + xCAT::Utils->monitor_installation($request, $monsettings); + + } + #failed after retries + if (scalar(keys %{$monsettings->{'nodes'}}) > 0) { + foreach my $node (keys %{$monsettings->{'nodes'}}) { + my $rsp={}; + $rsp->{data}->[0] = "The node \"$node\" can not reach the expected status after $monsettings->{'retrycount'} retries, the installation for this done failed"; + xCAT::MsgUtils->message("E", $rsp, $callback); + } + } + } + $Rc = shift(@$result); + + + ################################## + # Form string from array results + ################################## + if ( exists($request->{verbose}) ) { + return( [[$node,join( '', @$result ),$Rc]] ); + } + ################################## + # Return error + # lpar_netboot returns (for example): + # # Connecting to lpar1 + # # Connected + # # Checking for power off. + # # Power off the node + # # Wait for power off. + # # Power off complete. + # # Power on lpar1 to Open Firmware. + # # Power on complete. + # lpar_netboot: can not find mac address 42DAB. + # + ################################## + if ( $Rc != SUCCESS ) { + if ( @$result[0] =~ /lpar_netboot: (.*)/ ) { + return( [[$node,$1,$Rc]] ); + } + return( [[$node,join( '', @$result ),$Rc]] ); + } + ################################## + # Split array into string + ################################## + my $data = @$result[0]; + if ( $hwtype eq "hmc" ) { + $data = join( '', @$result ); + } + ################################## + # lpar_netboot returns: + # + # # Connecting to lpar1 + # # Connected + # ... + # lpar_netboot Status: network boot initiated + # # bootp sent over network. + # lpar_netboot Status: waiting for the boot image to boot up. + # # Network boot proceeding, lpar_netboot is exiting. + # # Finished. + # + ##################################### + if ( $data =~ /Finished/) { + return( [[$node,"Success",$Rc]] ); + } + ##################################### + # Can still be error w/ Rc=0: + # + # # Connecting to lpar1 + # # Connected + # ... + # lpar_netboot Status: network boot initiated + # # bootp sent over network. + # lpar_netboot Status: waiting for the boot image to boot up. + # lpar_netboot: bootp operation failed. + # + ##################################### + if ( $data =~ /lpar_netboot: (.*)/ ) { + return( [[$node,$1,RC_ERROR]] ); + } + return( [[$node,$data,RC_ERROR]] ); +} + + +1; + + + + + + + diff --git a/perl-xCAT/xCAT/FSPmac.pm b/perl-xCAT/xCAT/FSPmac.pm new file mode 100644 index 000000000..928714045 --- /dev/null +++ b/perl-xCAT/xCAT/FSPmac.pm @@ -0,0 +1,609 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +package xCAT::FSPmac; +use Socket; +use strict; +use Getopt::Long; +use xCAT::PPCmac; +use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); + +########################################################################## +# Parse the command line for options and operands +########################################################################## +sub parse_args { + xCAT::PPCmac::parse_args(@_); +} + + +########################################################################## +# Get LPAR MAC addresses +########################################################################## +sub do_getmacs { + + my $request = shift; + my $d = shift; + my $exp = shift; + my $name = shift; + my $node = shift; + my $opt = $request->{opt}; + my $ssh = @$exp[0]; + my $userid = @$exp[4]; + my $pw = @$exp[5]; + my $cmd; + my $result; + + ####################################### + # Disconnect Expect session + ####################################### + #xCAT::PPCcli::disconnect( $exp ); + + ####################################### + # Get node data + ####################################### + my $id = @$d[0]; + my $pprofile = @$d[1]; + my $fsp = @$d[2]; + my $hcp = @$d[3]; + + ####################################### + # Find Expect script + ####################################### + $cmd = ($::XCATROOT) ? "$::XCATROOT/sbin/" : "/opt/xcat/sbin/"; + $cmd .= "lpar_netboot2.expect"; + + ####################################### + # Check command installed + ####################################### + if ( !-x $cmd ) { + return( [RC_ERROR,"Command not installed: $cmd"] ); + } + ####################################### + # Save user name and passwd of hcp to + # environment variables. + # lpar_netboot.expect depends on this + ####################################### + $ENV{HCP_USERID} = $userid; + $ENV{HCP_PASSWD} = $pw; + + ####################################### + # Turn on verbose and debugging + ####################################### + if ( exists($request->{verbose}) ) { + $cmd.= " -v -x"; + } + ####################################### + # Force LPAR shutdown + ####################################### + if ( exists( $opt->{f} )) { + $cmd.= " -i"; + } else { + ################################# + # Force LPAR shutdown if LPAR is + # running Linux + ################################# + my $table = "nodetype"; + my $intable = 0; + my @TableRowArray = xCAT::DBobjUtils->getDBtable($table); + if ( defined(@TableRowArray) ) { + foreach ( @TableRowArray ) { + my @nodelist = split(',', $_->{'node'}); + my @oslist = split(',', $_->{'os'}); + my $osname = "AIX"; + if ( grep(/^$node$/, @nodelist) ) { + if ( !grep(/^$osname$/, @oslist) ) { + $cmd.= " -i"; + } + $intable = 1; + last; + } + } + } + ################################# + # Force LPAR shutdown if LPAR OS + # type is not assigned in table + # but mnt node is running Linux + ################################# + if ( xCAT::Utils->isLinux() && $intable == 0 ) { + $cmd.= " -i"; + } + } + + ####################################### + # Network specified (-D ping test) + ####################################### + if ( exists( $opt->{S} )) { + $cmd.= " -D -s auto -d auto -S $opt->{S} -G $opt->{G} -C $opt->{C}"; + } + ####################################### + # Add command options + ####################################### + $cmd.= " -t ent -f -M -A -n \"$name\" \"$pprofile\" \"$fsp\" $id $hcp \"$node\""; + print "cmd : $cmd\n"; + ####################################### + # Execute command + ####################################### + my $pid = open( OUTPUT, "$cmd 2>&1 |"); + $SIG{INT} = $SIG{TERM} = sub { #prepare to process job termination and propogate it down + kill 9, $pid; + return( [RC_ERROR,"Received INT or TERM signal"] ); + }; + if ( !$pid ) { + return( [RC_ERROR,"$cmd fork error: $!"] ); + } + + ####################################### + # Get command output + ####################################### + while ( ) { + $result.=$_; + } + close OUTPUT; + + ####################################### + # Get command exit code + ####################################### + my $Rc = SUCCESS; + + foreach ( split /\n/, $result ) { + if ( /^lpar_netboot: / ) { + $Rc = RC_ERROR; + last; + } + } + ###################################### + # Split results into array + ###################################### + return( [$Rc, split( /\n/, $result)] ); +} + + +########################################################################## +# Get LPAR MAC addresses +########################################################################## +sub getmacs { + + my $request = shift; + my $par = shift; + my $exp = shift; + my $opt = $request->{opt}; + my $hwtype = @$exp[2]; + my $result; + my $name; + my @emptynode; + + if ( $par =~ /^HASH/ ) { + + return( [["","Please use -D -f options to getmacs through FSP directly",RC_ERROR]] ); + + ######################################### + # Parse the filters specified by user + ######################################### + my $filter; + if ( $opt->{F} ) { + my @filters = split /,/,$opt->{F}; + foreach ( @filters ) { + my @value = split /=/,$_; + $filter->{@value[0]} = @value[1]; + } + } + + ######################################### + # A hash to save lpar attributes + ######################################### + my %nodeatt = (); + + ######################################### + # Cleanup old data + ######################################### + my $result = (); + + ######################################### + # No ping test performed, call lshwres + # to achieve the MAC address + ######################################### + foreach my $hcp ( keys %$par ) { + my $hash = $par->{$hcp}; + my $cmd; + + ######################################### + # Achieve virtual ethernet MAC address + ######################################### + @$cmd[0] = ["lpar","virtualio","","eth"]; + @$cmd[1] = ["port","hea","","logical"]; + @$cmd[2] = ["port","hea","","phys"]; + + ######################################### + # Parse the output of lshwres command + ######################################### + for ( my $stat = 0; $stat < 3; $stat++ ) { + my $output = xCAT::PPCcli::lshwres( $exp, @$cmd[$stat], $hcp); + my $macs; + + foreach my $line ( @$output ) { + if ( $line =~ /^.*lpar\_id=(\d+),.*$/ ) { + ######################################### + # For the first two commands + ######################################### + my $lparid = $1; + $nodeatt{$hcp}{$lparid}{'num'}++; + $macs = $nodeatt{$hcp}{$lparid}{'num'}; + my @attrs = split /,/, $line; + foreach ( @attrs ) { + my @attr = split /=/, $_; + $nodeatt{$hcp}{$lparid}{$macs}{@attr[0]} = @attr[1]; + } + + } elsif ( ($line =~ /^(.*)port\_group=(\d+),(.*),"log\_port\_ids=(.*)"/) || ($line =~ /^(.*)port\_group=(\d+),(.*),log\_port\_ids=(.*)/) ) { + ######################################### + # For the third command + ######################################### + my $port_group = $2; + if ( $4 !~ /^none$/ ) { + my @ids = split /,/, $4; + my @attrs = split /,/, $1; + foreach (@attrs) { + my @attr = split /=/,$_; + foreach (@ids) { + $nodeatt{$hcp}{$port_group}{$_}{@attr[0]} = @attr[1]; + } + } + my @attrs = split /,/, $3; + foreach (@attrs) { + my @attr = split /=/,$_; + foreach (@ids) { + $nodeatt{$hcp}{$port_group}{$_}{@attr[0]} = @attr[1]; + } + } + } + } + } + } + + foreach ( keys %$hash ) { + my $node = $_; + my $d = $hash->{$_}; + my $mtms = @$d[2]; + my $id = @$d[0]; + my $nodetype = @$d[4]; + + my $mac_count = $nodeatt{$mtms}{$id}{'num'}; + my $value = (); + my $data = (); + my $type; + + ######################################### + # Invalid target hardware + ######################################### + if ( $nodetype ne "lpar" ) { + return( [[$node,"Node must be LPAR",RC_ERROR]] ); + } + + ######################################### + # Put all the attributes required + # together + ######################################### + push @$value,"\n#Type Phys_Port_Loc MAC_Address Adapter Port_Group Phys_Port Logical_Port VLan VSwitch Curr_Conn_Speed"; + + for ( my $num = 1; $num <= $mac_count; $num++ ) { + my $mac_addr = $nodeatt{$mtms}{$id}{$num}{'mac_addr'}; + my $adapter_id = $nodeatt{$mtms}{$id}{$num}{'adapter_id'}; + my $port_group = $nodeatt{$mtms}{$id}{$num}{'port_group'}; + my $phys_port_id = $nodeatt{$mtms}{$id}{$num}{'phys_port_id'}; + my $logical_port_id = $nodeatt{$mtms}{$id}{$num}{'logical_port_id'}; + my $vlan_id = $nodeatt{$mtms}{$id}{$num}{'port_vlan_id'}; + my $vswitch = $nodeatt{$mtms}{$id}{$num}{'vswitch'}; + my $phys_port_loc = $nodeatt{$mtms}{$port_group}{$logical_port_id}{'phys_port_loc'}; + my $curr_conn_speed = $nodeatt{$mtms}{$port_group}{$logical_port_id}{'curr_conn_speed'}; + + if ( $phys_port_loc ) { + $type = "hea"; + } else { + $type = "virtualio"; + } + + my %att = (); + $att{'MAC_Address'} = ($mac_addr) ? $mac_addr : "N/A"; + $att{'Adapter'} = ($adapter_id) ? $adapter_id : "N/A"; + $att{'Port_Group'} = ($port_group) ? $port_group : "N/A"; + $att{'Phys_Port'} = ($phys_port_id) ? $phys_port_id : "N/A"; + $att{'Logical_Port'} = ($logical_port_id) ? $logical_port_id : "N/A"; + $att{'VLan'} = ($vlan_id) ? $vlan_id : "N/A"; + $att{'VSwitch'} = ($vswitch) ? $vswitch : "N/A"; + $att{'Phys_Port_Loc'} = ($phys_port_loc) ? $phys_port_loc : "N/A"; + $att{'Curr_Conn_Speed'} = ($curr_conn_speed) ? $curr_conn_speed : "N/A"; + $att{'Type'} = $type; + + ######################################### + # Parse the adapter with the filters + # specified + ######################################### + if ( defined($filter) ) { + my $matched = 1; + foreach ( keys %$filter ) { + if ( $att{$_} ne $filter->{$_} ) { + $matched = 0; + last; + } + } + if ( $matched == 1 ) { + push @$value,"$att{'Type'} $att{'Phys_Port_Loc'} $att{'MAC_Address'} $att{'Adapter'} $att{'Port_Group'} $att{'Phys_Port'} $att{'Logical_Port'} $att{'VLan'} $att{'VSwitch'} $att{'Curr_Conn_Speed'}"; + } + } else { + push @$value,"$att{'Type'} $att{'Phys_Port_Loc'} $att{'MAC_Address'} $att{'Adapter'} $att{'Port_Group'} $att{'Phys_Port'} $att{'Logical_Port'} $att{'VLan'} $att{'VSwitch'} $att{'Curr_Conn_Speed'}"; + } + } + ######################################### + # Write MAC address to database + ######################################### + if ( !exists( $opt->{d} )) { + writemac( $node, $value ); + } + + + if ( scalar(@$value) < 2 ) { + my $filter = "lpar_id,curr_profile"; + my $prof = xCAT::PPCcli::lssyscfg( $exp, "node", $mtms, $filter, $id ); + my $Rc = shift(@$prof); + + ######################################### + # Return error + ######################################### + if ( $Rc != SUCCESS ) { + return( [[$node,@$prof[0],$Rc]] ); + } + + foreach my $val ( @$prof ) { + my ($lpar_id,$curr_profile) = split /,/, $val; + if ( !length($curr_profile) || ($curr_profile =~ /^none$/) ) { + push @emptynode,$node; + } + } + } + foreach ( @$value ) { + if ( /^#\s?Type/ ) { + $data.= "\n$_\n"; + } else { + $data.= format_mac( $_ ); + } + } + + push @$result,[$node,$data,0]; + } + } + if ( scalar(@emptynode) > 0 ) { + return([[join(",", @emptynode),"\nThese nodes have no active profiles. Please active the nodes to enable the default profiles",RC_ERROR]]); + } + return([@$result]); + } else { + ######################################### + # Connect to fsp to achieve MAC address + ######################################### + my $d = $par; + + ######################################### + # Get node data + ######################################### + my $lparid = @$d[0]; + my $mtms = @$d[2]; + my $type = @$d[4]; + my $node = @$d[6]; + + ######################################### + # Invalid target hardware + ######################################### + if ( $type ne "lpar" ) { + return( [[$node,"Node must be LPAR",RC_ERROR]] ); + } + ######################################### + # Get name known by HCP + ######################################### + my $filter = "name,lpar_id"; + # my $values = xCAT::PPCcli::lssyscfg( $exp, $type, $mtms, $filter ); + #my $Rc = shift(@$values); + + ######################################### + # Return error + ######################################### + #if ( $Rc != SUCCESS ) { + # return( [[$node,@$values[0],$Rc]] ); + # } + ######################################### + # Find LPARs by lpar_id + ######################################### + # foreach ( @$values ) { + # if ( /^(.*),$lparid$/ ) { + # $name = $1; + # last; + # } + # } + ######################################### + # Node not found by lpar_id + ######################################### + # if ( !defined( $name )) { + # return( [[$node,"Node not found, lparid=$lparid",RC_ERROR]] ); + # } + my $Rc; + my $sitetab = xCAT::Table->new('site'); + my $vcon = $sitetab->getAttribs({key => "conserverondemand"}, 'value'); + if ($vcon and $vcon->{"value"} and $vcon->{"value"} eq "yes" ) { + # $result = xCAT::PPCcli::lpar_netboot( + # $exp, + # $request->{verbose}, + # $name, + # $d, + # $opt ); + return( [[$node,"Not support conserverondemand's value is yes",RC_ERROR]] ); + } else { + ######################################### + # Manually collect MAC addresses. + ######################################### + $result = do_getmacs( $request, $d, $exp, $name, $node ); + } + $sitetab->close; + $Rc = shift(@$result); + + ################################## + # Form string from array results + ################################## + if ( exists($request->{verbose}) ) { + if ( $Rc == SUCCESS ) { + if ( !exists( $opt->{d} )) { + writemac( $node, $result ); + } + } + return( [[$node,join( '', @$result ),$Rc]] ); + } + ################################## + # Return error + ################################## + if ( $Rc != SUCCESS ) { + if ( @$result[0] =~ /lpar_netboot: (.*)/ ) { + return( [[$node,$1,$Rc]] ); + } + return( [[$node,join( '', @$result ),$Rc]] ); + } + ##################################### + # lpar_netboot returns: + # + # # Connecting to lpar4\n + # # Connected\n + # # Checking for power off.\n + # # Power off complete.\n + # # Power on lpar4 to Open Firmware.\n + # # Power on complete.\n + # # Getting adapter location codes.\n + # # Type\t Location Code\t MAC Address\t Full Path Name\tPing Result\n + # ent U9117.MMA.10F6F3D-V5-C3-T1 1e0e122a930d /vdevice/l-lan@30000003 + # + ##################################### + my $data; + + foreach ( @$result ) { + if ( /^#\s?Type/ ) { + $data.= "\n$_\n"; + } elsif ( /^ent\s+/ ) { + $data.= format_mac( $_ ); + } + } + ##################################### + # Write first valid adapter MAC to database + ##################################### + if ( !exists( $opt->{d} )) { + writemac( $node, $result ); + } + return( [[$node,$data,$Rc]] ); + } +} + +########################################################################## +# Insert colons in MAC addresses for Linux only +########################################################################## +sub format_mac { + + my $data = shift; + + if ( !xCAT::Utils->isAIX() ) { + ##################################### + # Get adapter mac + ##################################### + $data =~ /^(\S+\s+\S+\s+)(\S+)(\s+.*)$/; + my $mac = $2; + my $save = $mac; + ################################# + # Delineate MAC with colons + ################################# + $mac = lc($mac); + $mac =~ s/(\w{2})/$1:/g; + $mac =~ s/:$//; + $data =~ s/$save/$mac/; + } + return( "$data\n" ); +} + + +########################################################################## +# Write first valid adapter MAC to database +########################################################################## +sub writemac { + + my $name = shift; + my $data = shift; + my $value; + my $pingret; + my $ping_test; + my $mac; + my @fields; + + ##################################### + # Find first valid adapter + ##################################### + foreach ( @$data ) { + if ( /^ent\s+/ ) { + $value = $_; + ##################################### + # MAC not found in output + ##################################### + if ( !defined( $value )) { + return; + } + @fields = split /\s+/, $value; + $pingret = $fields[4]; + if ( $pingret eq "successful" ) { + $ping_test = 0; + last; + } + } + } + + ##################################### + # If no valid adapter, find the first one + ##################################### + if ( $pingret ne "successful" ) { + foreach ( @$data ) { + if ( /^ent\s+/ ) { + $value = $_; + $ping_test = 0; + last; + } elsif ( /^hea\s+/ || /^virtualio\s+/ ) { + $value = $_; + $ping_test = 1; + last; + } + } + } + + ##################################### + # MAC not found in output + ##################################### + if ( !defined( $value )) { + return; + } + ##################################### + # Get adapter mac + ##################################### + $value = format_mac( $value ); + @fields = split /\s+/, $value; + $mac = $fields[2]; + + ##################################### + # Write adapter mac to database + ##################################### + my $mactab = xCAT::Table->new( "mac", -create=>1, -autocommit=>1 ); + if ( !$mactab ) { + return( [[$name,"Error opening 'mac'",RC_ERROR]] ); + } + $mactab->setNodeAttribs( $name,{mac=>$mac} ); + $mactab->close(); +} + +1; + + + + + + + + + + diff --git a/perl-xCAT/xCAT/PPCcli.pm b/perl-xCAT/xCAT/PPCcli.pm index d83499a1e..37d48b1e8 100644 --- a/perl-xCAT/xCAT/PPCcli.pm +++ b/perl-xCAT/xCAT/PPCcli.pm @@ -52,6 +52,7 @@ my %powercmd = ( 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", + sms =>"chsysstate -r %s -m %s -o on --id %s -f %s -b sms", 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" }, diff --git a/xCAT-server/lib/perl/xCAT/PPC.pm b/xCAT-server/lib/perl/xCAT/PPC.pm index 30c8053c9..2b7013b57 100644 --- a/xCAT-server/lib/perl/xCAT/PPC.pm +++ b/xCAT-server/lib/perl/xCAT/PPC.pm @@ -44,8 +44,10 @@ my %modules = ( chvm => { hmc => "xCAT::PPCvm", }, rnetboot => { hmc => "xCAT::PPCboot", + fsp => "xCAT::FSPboot", }, getmacs => { hmc => "xCAT::PPCmac", + fsp => "xCAT::FSPmac", }, reventlog => { hmc => "xCAT::PPClog", }, @@ -162,7 +164,9 @@ sub process_command { if ( $hwtype eq "fsp" or $hwtype eq "bpa") { my $fsp_api = check_fsp_api($request); if($fsp_api == 0 && - ($request->{command} =~ /^(rpower)$/ || $request->{command} =~ /^rinv$/ || $request->{command} =~ /^rflash$/)) { + ($request->{command} =~ /^(rpower)$/ || $request->{command} =~ /^rinv$/ || $request->{command} =~ /^rflash$/ + || $request->{command} =~ /^getmacs$/ || $request->{command} =~ /^rnetboot$/ ) + ) { #support FSPpower, FSPinv and FSPrflash $request->{fsp_api} = 1; } @@ -1192,26 +1196,30 @@ sub invoke_cmd { # HMC and IVM-managed handler # Connect to list of remote servers ######################################## - foreach ( split /,/, $host ) { - if ( $power ne "hmc" ) { - @exp = xCAT::PPCcli::connect( $request, $hwtype, $_ ); - } else { - @exp = xCAT::PPCcli::connect( $request, $power, $_); - } - #################################### - # Successfully connected - #################################### - if ( ref($exp[0]) eq "Expect" ) { - last; - } - } - ######################################## - # Error connecting - ######################################## - if ( ref($exp[0]) ne "Expect" ) { - send_msg( $request, 1, $exp[0] ); - return; + if ( $request->{fsp_api} == 0 ) { + foreach ( split /,/, $host ) { + if ( $power ne "hmc" ) { + @exp = xCAT::PPCcli::connect( $request, $hwtype, $_ ); + } else { + @exp = xCAT::PPCcli::connect( $request, $power, $_); + } + #################################### + # Successfully connected + #################################### + if ( ref($exp[0]) eq "Expect" ) { + last; + } + } + + ######################################## + # Error connecting + ######################################## + if ( ref($exp[0]) ne "Expect" ) { + send_msg( $request, 1, $exp[0] ); + return; + } } + ######################################## # Process specific command ######################################## @@ -1220,7 +1228,9 @@ sub invoke_cmd { ######################################## # Close connection to remote server ######################################## - xCAT::PPCcli::disconnect( \@exp ); + if( $request->{fsp_api} == 0 ) { + xCAT::PPCcli::disconnect( \@exp ); + } ######################################## # Get verbose Expect output @@ -1662,8 +1672,8 @@ sub check_fsp_api # my $fsp_api = "/opt/xcat/sbin/fsp-api"; my $fsp_api = ($::XCATROOT) ? "$::XCATROOT/sbin/fsp-api" : "/opt/xcat/sbin/fsp-api"; -# my $libfsp = "/usr/lib/libfsp.a"; - my $libfsp = "/opt/xcat/lib/libfsp.a"; + my $libfsp = "/usr/lib/libfsp.a"; +# my $libfsp = "/opt/xcat/lib/libfsp.a"; # my $libfsp = ($::XCATROOT) ? "$::XCATROOT/lib/libfsp.a" : "/opt/xcat/lib/libfsp.a"; # my $hw_svr = "/opt/csm/csmbin/hdwr_svr"; diff --git a/xCAT-server/lib/xcat/plugins/fsp.pm b/xCAT-server/lib/xcat/plugins/fsp.pm index 2ac0d3afd..ec114e92f 100644 --- a/xCAT-server/lib/xcat/plugins/fsp.pm +++ b/xCAT-server/lib/xcat/plugins/fsp.pm @@ -18,7 +18,9 @@ sub handled_commands { lshwconn => 'nodehm:mgt', renergy => 'nodehm:mgt' , rinv => 'nodehm:mgt', - rflash => 'nodehm:mgt' + rflash => 'nodehm:mgt', + getmacs => 'nodehm:mgt', + rnetboot => 'nodehm:mgt' }; } diff --git a/xCAT-server/sbin/lpar_netboot.expect b/xCAT-server/sbin/lpar_netboot.expect index 260b9adb7..1a2525fb0 100644 --- a/xCAT-server/sbin/lpar_netboot.expect +++ b/xCAT-server/sbin/lpar_netboot.expect @@ -75,7 +75,7 @@ proc connect {} { # # PROCEDURE # -# Procedure to run the lssyscfg command +# Procedure to run the rpower command # test its return code and capture its output # proc run_lssyscfg {} { @@ -89,29 +89,18 @@ proc run_lssyscfg {} { global profile global rc global prompt + global tmp + global BINPATH set timeout 20 - send -i $ssh_spawn_id "lssyscfg -r lpar -m \"$manage\" --filter lpar_names=\"$node\" -F state; echo Rc=\$\?\r"; + + set runcmd [list exec $BINPATH/rpower $node state] + set rc [catch $runcmd msg] + nc_msg "$PROGRAM Status: run_lssyscg : partition status : $msg\n" + regexp "$node:\[ ]*(.*)" $msg tmp1 tmp + set msg $tmp + send_user "####msg:$msg#########" - expect { - -i $ssh_spawn_id \ - -re "echo.*echo.*\r\n(.*)\r\nRc=(\[0-9]*)\r\n(.*)" { - set rc $expect_out(2,string) - set msg $expect_out(1,string) - } - -re "echo.*\r\n(.*)\r\nRc=(\[0-9]*)\r\n(.*)" { - set rc $expect_out(2,string) - set msg $expect_out(1,string) - } - timeout { - send_user "$PROGRAM: Timeout waiting for command prompt\n" - exit 1 - } - eof { - send_user "$PROGRAM: ssh connection to terminated unexpectedly\n" - exit 1 - } - } # Slow down the requests speed to hcp, so that hcp will not busy on # query. Instead, hcp should put more time on other activities. @@ -121,7 +110,8 @@ proc run_lssyscfg {} { if { $rc } { send_user "$PROGRAM: Unable to determine machine state\n" - nc_msg "$PROGRAM Status: error from lssyscfg command\n" + nc_msg "$PROGRAM Status: error from rpower command\n" + send_user "Error : $msg\n" exit 1 @@ -1254,7 +1244,7 @@ proc set_disk_boot {} { # state 0, get SMS screen set done(0) 0 - regexp "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Select Boot Options(\r)" $expect_out(2,string) x0 x1 x2 command + regexp "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Select Boot Options(\r)" $expect_out(0,string) x0 x1 x2 command set cmd(0) "$command\r" set msg(0) "$PROGRAM Status: sending return to repaint SMS screen\n" set pattern(0) "(\n)(\[ ])(\[0-9])(\[.])(\[ ]+)Configure Boot Device Order(\r)" @@ -1345,6 +1335,15 @@ proc set_disk_boot {} { set cmd($state) "$expect_out(3,string)\r" } } + + -re "THE SELECTED DEVICES WERE NOT DETECTED IN THE SYSTEM" { + send_user "$PROGRAM Status: THE hard disk WERE NOT DETECTED IN THE SYSTEM!\n" + set rc 1 + #return + exit 1 + } + + timeout { send_user "$PROGRAM: Timeout\n" set rc 1 @@ -1827,8 +1826,8 @@ proc Firmware_Dump { device_path phandle } { # # Main MAIN main # -set BINPATH "/opt/hsc/bin" -set PROGRAM "lpar_netboot" +set BINPATH "/opt/xcat/bin" +set PROGRAM "lpar_netboot.expect" set CONSOLEBIN "/opt/xcat/bin/rcons" @@ -2057,6 +2056,12 @@ if {$discovery && $client_ip != ""} { nc_msg "$PROGRAM Status: using client IP if {$discovery && $gateway_ip != ""} { nc_msg "$PROGRAM Status: using gateway IP address of $gateway_ip\n" } if {$discovery && $macaddress != ""} { nc_msg "$PROGRAM Status: using macaddress of $macaddress\n" } if {$discovery && $phys_loc != ""} { nc_msg "$PROGRAM Status: using physical location code of $phys_loc\n" } + +nc_msg "node: $node\n" +nc_msg "name: $name\n" +set node $name + + set NODENAME $node ck_args @@ -2077,7 +2082,7 @@ set passwd $env(HCP_PASSWD) # Connect to the remote server # nc_msg "$PROGRAM Status: connecting to $hcp\n" -connect +#connect nc_msg "$PROGRAM Status: finished connecting to $hcp\n" # @@ -2118,7 +2123,7 @@ expect { exit 1 } eof { - send_user "$PROGRAM: ssh connection terminated unexpectedly, please make sure rcons $name works\n" + send_user "$PROGRAM: Please make sure rcons $name works\n" exit 1 } } @@ -2127,7 +2132,7 @@ send_user "# Checking for power off.\n" run_lssyscfg -if { ([string compare "$msg" "Off"] == 0) || ([string compare "$msg" "Not Activated"] == 0) } { +if { ([string compare "$msg" "Off"] == 0) || ([string compare "$msg" "off"] == 0) || ([string compare "$msg" "Not Activated"] == 0) } { send_user "# Power off complete.\n" } else { @@ -2138,35 +2143,18 @@ if { ([string compare "$msg" "Off"] == 0) || ([string compare "$msg" "Not Activa set cmd "0" if { $immed_flag } { - set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" --immed -n \"$node\"" + #set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" --immed -n \"$node\"" + set cmd [list exec $BINPATH/rpower $node off] } else { - set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" -n \"$node\"" + #set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" -n \"$node\"" + set cmd [list exec $BINPATH/rpower $node off] } set timeout 120 - send -i $ssh_spawn_id "$cmd; echo Rc=\$\?\r"; - - expect { - -i $ssh_spawn_id \ - -re "\r\n(.*)\r\n\r\nRc=(\[0-9]*)\r\n(.*)" { - set rc $expect_out(2,string) - set msg $expect_out(1,string) - } - -re "\r\nRc=(\[0-9])\r\n(.*)" { - set rc $expect_out(1,string) - } - timeout { - send_user "$PROGRAM: Timeout waiting for command prompt\n" - exit 1 - } - eof { - send_user "$PROGRAM: ssh connection to terminated unexpectedly\n" - exit 1 - } - } + set rc [catch $cmd msg] if { $rc } { send_user "$PROGRAM: Cannot power off $NODENAME\n" - nc_msg "$PROGRAM Status: error from chsysstate command\n" + nc_msg "$PROGRAM Status: error from rpower command\n" send_user "$PROGRAM: Error : $msg\n" exit 1 } @@ -2186,7 +2174,7 @@ if { ([string compare "$msg" "Off"] == 0) || ([string compare "$msg" "Not Activa # # separate the nodename from the query status # - if { ([string compare "$msg" "Off"] == 0) || ([string compare "$msg" "Not Activated"] == 0) } { + if { ([string compare "$msg" "Off"] == 0) || ([string compare "$msg" "off"] == 0) || ([string compare "$msg" "Not Activated"] == 0) } { send_user "# Power off complete.\n" set done 1 continue @@ -2195,7 +2183,7 @@ if { ([string compare "$msg" "Off"] == 0) || ([string compare "$msg" "Not Activa incr query_count if { $query_count > 300 } { send_user "$PROGRAM: Timed out waiting for power off of $NODENAME\n" - nc_msg "$PROGRAM Status: error from lssyscfg command : \"$msg\"\n" + nc_msg "$PROGRAM Status: error from rpower command : \"$msg\"\n" exit 1 } @@ -2209,71 +2197,42 @@ if { $set_boot_order > 1 } { send_user "$PROGRAM Status: Power on $NODENAME to SMS.\n" set timeout 120 while { ! $done } { - send -i $ssh_spawn_id "chsysstate -r lpar -o on -b sms -m \"$manage\" -n \"$node\" -f \"$profile\"; echo Rc=\$\?\r" - - expect { - -i $ssh_spawn_id \ - -re "\r\n(.*)\r\n\r\nRc=(\[0-9]*)\r\n(.*)" { - set rc $expect_out(2,string) - set msg $expect_out(1,string) - set done 1 - } - -re "\r\nRc=(\[0-9])\r\n(.*)" { - set rc $expect_out(1,string) - set done 1 - } - timeout { - if { $retry_count == 3 } { - send_user "$PROGRAM: Timeout waiting for command prompt\n" - exit 1 - } - sleep 1 - incr retry_count - } - eof { - if { $retry_count == 3 } { - send_user "$PROGRAM: ssh connection to terminated unexpectedly\n" - exit 1 - } - sleep 1 - incr retry_count + set cmd [list exec $BINPATH/rpower $node sms] + set rc [catch $cmd msg] + nc_msg "$PROGRAM Status: wait for power on\n" + + if { $rc } { + if { $retry_count == 3 } { + nc_msg "$PROGRAM Status: error from rpower command\n" + exit 1 } + sleep 1 + incr retry_count + } else { + set done 1 } + } } else { send_user "# Power on $NODENAME to Open Firmware.\n" set timeout 120 while { ! $done } { - send -i $ssh_spawn_id "chsysstate -r lpar -o on -b of -m \"$manage\" -n \"$node\" -f \"$profile\"; echo Rc=\$\?\r" - - expect { - -i $ssh_spawn_id \ - -re "\r\n(.*)\r\n\r\nRc=(\[0-9]*)\r\n(.*)" { - set rc $expect_out(2,string) - set msg $expect_out(1,string) - set done 1 + #send -i $ssh_spawn_id "chsysstate -r lpar -o on -b of -m \"$manage\" -n \"$node\" -f \"$profile\"; echo Rc=\$\?\r" + set cmd [list exec $BINPATH/rpower $node of] + set rc [catch $cmd msg] + nc_msg "$PROGRAM Status: wait for power on\n" + + if { $rc } { + if { $retry_count == 3 } { + nc_msg "$PROGRAM Status: error from rpower command\n" + exit 1 } - -re "\r\nRc=(\[0-9])\r\n(.*)" { - set rc $expect_out(1,string) - set done 1 - } - timeout { - if { $retry_count == 3 } { - send_user "$PROGRAM: Timeout waiting for command prompt\n" - exit 1 - } - sleep 1 - incr retry_count - } - eof { - if { $retry_count == 3 } { - send_user "$PROGRAM: ssh connection to terminated unexpectedly\n" - exit 1 - } - sleep 1 - incr retry_count - } - } + sleep 1 + incr retry_count + } else { + set done 1 + } + } } @@ -2281,7 +2240,7 @@ nc_msg "$PROGRAM Status: wait for power on\n" if { $rc } { send_user "$PROGRAM: Cannot power on $NODENAME\n" - nc_msg "$PROGRAM Status: error from chsysstate command\n" + nc_msg "$PROGRAM Status: error from rpower command\n" send_user "$PROGRAM: Error : $msg\n" exit 1 } @@ -2297,7 +2256,7 @@ while { ! $done } { # # separate the nodename from the query status # - if { ([string compare "$msg" "Open Firmware"] == 0) || ([string compare "$msg" "Open firmware"] == 0) } { + if { ([string compare "$msg" "Open Firmware"] == 0) || ([string compare "$msg" "Open firmware"] == 0) || ([string compare "$msg" "open-firmware"] == 0) } { send_user "# Power on complete.\n" set done 1 continue @@ -2306,7 +2265,7 @@ while { ! $done } { if { $query_count > 300 } { send_user "$PROGRAM: Timed out waiting for power on of $NODENAME\n" - nc_msg "$PROGRAM Status: error from lssyscfg command : \"$msg\" \n" + nc_msg "$PROGRAM Status: error from rpower command : \"$msg\" \n" exit 1 } @@ -2344,6 +2303,11 @@ while { ! $done } { nc_msg "$PROGRAM Status: at ok prompt\n" set done 1 } + -re "SMS(.*)Navigation Keys" { + nc_msg "$PROGRAM Status: SMS\n" + set done 1 + } + timeout { set command "\r" send_command @@ -2489,35 +2453,18 @@ if { $noboot } { # Display information for all supported adapters set cmd "0" if { $immed_flag } { - set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" --immed -n \"$node\"" + #set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" --immed -n \"$node\"" + set cmd [list exec $BINPATH/rpower $node off] } else { - set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" -n \"$node\"" + #set cmd "chsysstate -r lpar -o shutdown -m \"$manage\" -n \"$node\"" + set cmd [list exec $BINPATH/rpower $node off] } set timeout 120 - send -i $ssh_spawn_id "$cmd; echo Rc=\$\?\r"; - - expect { - -i $ssh_spawn_id \ - -re "\r\n(.*)\r\n\r\nRc=(\[0-9]*)\r\n(.*$prompt)" { - set rc $expect_out(2,string) - set msg $expect_out(1,string) - } - -re "\r\nRc=(\[0-9]*)\r\n(.*)" { - set rc $expect_out(1,string) - } - timeout { - send_user "$PROGRAM: Timeout waiting for command prompt\n" - exit 1 - } - eof { - send_user "$PROGRAM: ssh connection to terminated unexpectedly\n" - exit 1 - } - } - + set rc [catch $cmd msg] + if { $rc } { send_user "$PROGRAM: Cannot power off $NODENAME\n" - nc_msg "$PROGRAM Status: error from chsysstate command\n" + nc_msg "$PROGRAM Status: error from rpower command\n" send_user "$PROGRAM: Error : $msg\n" exit 1 }