diff --git a/perl-xCAT/xCAT/MacMap.pm b/perl-xCAT/xCAT/MacMap.pm index fb5619711..201e31b21 100644 --- a/perl-xCAT/xCAT/MacMap.pm +++ b/perl-xCAT/xCAT/MacMap.pm @@ -154,7 +154,14 @@ sub refresh_table { $self->{switches} = {}; foreach $entry (@entries) { if (defined($entry->{switch}) and $entry->{switch} ne "" and defined($entry->{port}) and $entry->{port} ne "") { - $self->{switches}->{$entry->{switch}}->{$entry->{port}}=$entry->{node}; + if ( !$self->{switches}->{$entry->{switch}}->{$entry->{port}}) + { + $self->{switches}->{$entry->{switch}}->{$entry->{port}} = $entry->{node}; + } + else + { + $self->{switches}->{$entry->{switch}}->{$entry->{port}} .= ",$entry->{node}"; + } } else { xCAT::MsgUtils->message("S","xCAT Table error:".$entry->{node}."Has missing or invalid switch.switch and/or switch.port fields"); } diff --git a/perl-xCAT/xCAT/PPC.pm b/perl-xCAT/xCAT/PPC.pm index db89039d3..32b343af7 100644 --- a/perl-xCAT/xCAT/PPC.pm +++ b/perl-xCAT/xCAT/PPC.pm @@ -335,7 +335,7 @@ sub resolve_hcp { my $request = shift; my $noderange = shift; my @nodegroup = (); - my $tab = ($request->{hwtype} eq "fsp") ? "ppcdirect" : "ppchcp"; + my $tab = ($request->{hwtype} eq "fsp" or $request->{hwtype} eq "bpa") ? "ppcdirect" : "ppchcp"; my $db = xCAT::Table->new( $tab ); #################################### @@ -391,7 +391,7 @@ sub preprocess_nodes { # Direct-attached FSP ######################################## if (( $request->{command} =~ /^(rscan|rspconfig)$/ ) or - ( $request->{hwtype} eq "fsp" )) { + ( $request->{hwtype} eq "fsp" or $request->{hwtype} eq "bpa")) { my $result = resolve_hcp( $request, $noderange ); return( $result ); } @@ -817,7 +817,7 @@ sub invoke_cmd { ######################################## # Direct-attached FSP handler ######################################## - if ( $hwtype eq "fsp" ) { + if ( $hwtype eq "fsp" or $hwtype eq "bpa") { #################################### # Dynamically load FSP module @@ -1013,7 +1013,7 @@ sub preprocess_request { # get the HCPs for the LPARs in order to figure out which service # nodes to send the requests to ################################################################### - my $hcptab_name = ($package eq "fsp") ? "ppcdirect" : "ppchcp"; + my $hcptab_name = ($package eq "fsp" or $package eq "bpa") ? "ppcdirect" : "ppchcp"; my $hcptab = xCAT::Table->new( $hcptab_name ); unless ($hcptab ) { $callback->({data=>["Cannot open $hcptab_name table"]}); @@ -1298,5 +1298,76 @@ sub sshcmds_on_hmc return ([0, undef, \@data]); } +########################################################################## +# logon asm and update configuration +########################################################################## +sub updconf_in_asm +{ + my $ip = shift; + my $target_dev = shift; + my @cmds = @_; + + eval { require xCAT::PPCfsp }; + if ( $@ ) { + return ([1,@cmds]); + } + + my %handled; + for my $cmd (@cmds) + { + if ( $cmd =~ /(.+?)=(.*)/) + { + my ($command,$value) = ($1,$2); + $handled{$command} = $value; + } + } + + my %request = ( + ppcretry => 1, + verbose => 0, + ppcmaxp => 64, + ppctimeout => 0, + fsptimeout => 0, + ppcretry => 3, + maxssh => 10, + arg => \@cmds, + method => \%handled, + command => 'rspconfig', + hwtype => lc($target_dev->{'type'}), + ); + + my $valid_ip; + my @exp; + foreach my $individual_ip ( split /,/, $ip ) { + ################################ + # Get userid and password + ################################ + my @cred = xCAT::PPCdb::credentials( $individual_ip, lc($target_dev->{'type'})); + $request{$individual_ip}{cred} = \@cred; + $request{node} = [$individual_ip]; + + @exp = xCAT::PPCfsp::connect(\%request, $individual_ip); +#################################### +# Successfully connected +#################################### + if ( ref($exp[0]) eq "LWP::UserAgent" ) { + $valid_ip = $individual_ip; + last; + } + } + +#################################### +# Error connecting +#################################### + if ( ref($exp[0]) ne "LWP::UserAgent" ) { + return ([1,@cmds]); + } + my $result = xCAT::PPCfsp::handler( $valid_ip, \%request, \@exp ); + my $RC = shift( @$result); + my @data; + push @data, @$result[0]; + + return ([0, undef, \@data]); +} 1; diff --git a/perl-xCAT/xCAT/PPCcfg.pm b/perl-xCAT/xCAT/PPCcfg.pm index e0a7a74af..8658b892b 100644 --- a/perl-xCAT/xCAT/PPCcfg.pm +++ b/perl-xCAT/xCAT/PPCcfg.pm @@ -35,13 +35,18 @@ sub parse_args { "date", "autopower", "sysdump", - "spdump" + "spdump", + "network" + ); + my @bpa = ( + "network" ); my @ppc = ( "sshcfg" ); my %rsp = ( fsp => \@fsp, + bpa => \@bpa, ivm => \@ppc, hmc => \@ppc ); @@ -183,6 +188,16 @@ sub parse_option { return( "Invalid argument '$value'" ); } } + if ( $command eq 'network'){ + my ( $adapter_name, $ip, $host, $gateway, $netmask) = + split /,/, $value; + return ( "Network interface name is required") if ( ! $adapter_name); + return ( "Invalide network interface name $adapter_name") if ( $adapter_name !~ /^eth\d$/); + return undef if ( $ip eq '*'); + return ( "Invalid IP address format") if ( $ip and $ip !~ /\d+\.\d+\.\d+\.\d+/); + return ( "Invalid netmask format") if ( $netmask and $netmask !~ /\d+\.\d+\.\d+\.\d+/); + } + return undef; } diff --git a/perl-xCAT/xCAT/PPCdb.pm b/perl-xCAT/xCAT/PPCdb.pm index f80a9a709..e41772ad6 100644 --- a/perl-xCAT/xCAT/PPCdb.pm +++ b/perl-xCAT/xCAT/PPCdb.pm @@ -12,7 +12,8 @@ use xCAT::GlobalDef; my %logon = ( hmc => ["hscroot","abc123"], ivm => ["padmin", "padmin"], - fsp => ["admin", "admin"] + fsp => ["admin", "admin"], + bpa => ["admin", "admin"] ); ########################################### @@ -21,9 +22,19 @@ my %logon = ( my %hcptab = ( hmc => "ppchcp", ivm => "ppchcp", - fsp => "ppcdirect" + fsp => "ppcdirect", + bpa => "ppcdirect" ); +########################################### +# The default groups of hcp +########################################### +my %defaultgrp = ( + hmc => "hmc", + ivm => "ivm", + fsp => "fsp", + bpa => "bpa" +); ########################################################################## @@ -301,7 +312,15 @@ sub credentials { $tab = xCAT::Table->new( $hcptab{$hwtype} ); if ( $tab ) { my ($ent) = $tab->getAttribs( {hcp=>$server}, qw(username password)); - if ( $ent ) { + if ( $ent){ + if (defined($ent->{password})) { $pass = $ent->{password}; } + if (defined($ent->{username})) { $user = $ent->{username}; } + } + ############################################################## + # If no user/passwd found, check if there is a default group + ############################################################## + elsif( ($ent) = $tab->getAttribs( {hcp=>$defaultgrp{$hwtype}}, qw(username password))) + { if (defined($ent->{password})) { $pass = $ent->{password}; } if (defined($ent->{username})) { $user = $ent->{username}; } } @@ -312,10 +331,3 @@ sub credentials { 1; - - - - - - - diff --git a/perl-xCAT/xCAT/PPCfsp.pm b/perl-xCAT/xCAT/PPCfsp.pm index cc179b846..64c32e485 100644 --- a/perl-xCAT/xCAT/PPCfsp.pm +++ b/perl-xCAT/xCAT/PPCfsp.pm @@ -33,7 +33,8 @@ my %cmds = ( date => ["Time Of Day", \&date], autopower => ["Auto Power Restart", \&autopower], sysdump => ["System Dump", \&sysdump], - spdump => ["Service Processor Dump", \&spdump] }, + spdump => ["Service Processor Dump", \&spdump], + network => ["Network Configuration", \&netcfg]}, ); @@ -1554,11 +1555,273 @@ sub all_clear { return( $result ); } +########################################################################## +# Gets and set network configuration +########################################################################## +sub netcfg +{ + my $exp = shift; + my $request = shift; + my $id = shift; + + ###################################### + # Parsing arg + ###################################### + my $set_config = 0; + my ($inc_name, $inc_ip, $inc_host, $inc_gateway, $inc_netmask) = (); + my $real_inc_name = undef; + if ( $request->{'method'}->{'network'}) + { + $set_config = 1; + } + + my $interfaces = undef; + my $form = undef; + + my $res = get_netcfg( $exp, $request, $id, \$interfaces, \$form); + + return $res if ( $res->[0] == RC_ERROR); + + my $output = ""; + ####################################### + # Set configuration + ####################################### + if ( $set_config) + { + return set_netcfg( $exp, $request, $interfaces, $form); + } + ####################################### + # Get configuration and format output + ####################################### + else + { + return format_netcfg( $interfaces); + } + +} + +########################################################################## +# Gets network configuration +########################################################################## +sub get_netcfg +{ + my $exp = shift; + my $request = shift; + my $id = shift; + my $interfaces = shift; + my $form = shift; + my $ua = @$exp[0]; + my $server = @$exp[1]; + ###################################### + # Get Network Configuration URL + ###################################### + my $url = "https://$server/cgi-bin/cgi?form=$id"; + my $res = $ua->get( $url ); + + ################################## + # Return error + ################################## + if ( !$res->is_success() ) { + return( [RC_ERROR,$res->status_line] ); + } + + ################################## + # Get "Network Configuraiton" form + ################################## + $$form = HTML::Form->parse( $res->content, $res->base ); + + ################################## + # Return error + ################################## + if ( !defined( $$form )) { + return( [RC_ERROR,"'Network Configuration' form not found"] ); + } + + ################################## + # For some P6 machines + ################################## + if ( $$form->find_input('ip', 'radio', 1)) + { + my $ipv4Radio = $$form->find_input('ip', 'radio', 1); + if (!$ipv4Radio) + { + print "Cannot find IPv4 option\n"; + exit; + } + #$ipv4Radio->check(); + + my $data = $$form->click('submit'); + $res = $ua->request( $data); + $$form = HTML::Form->parse( $res->content, $res->base ); + if ( !defined( $$form )) { + return( [RC_ERROR,"'Network Configuration' form not found"] ); + } + } + + ####################################### + # Parse the form to get the inc input + ####################################### + my $has_found_all = 0; + my $i = 0; + while ( not $has_found_all) + { + my $input = $$form->find_input( "interface$i", 'checkbox'); + if ( ! $input) + { + $has_found_all = 1; + } + else + { + $$interfaces->{"interface$i"}->{'selected'} = $input; + $$interfaces->{"interface$i"}->{'type'} = $$form->find_input("ip$i", 'option'); + $$interfaces->{"interface$i"}->{'hostname'} = $$form->find_input("host$i", 'text'); + $$interfaces->{"interface$i"}->{'ip'} = $$form->find_input("static_ip$i", 'text'); + $$interfaces->{"interface$i"}->{'gateway'} = $$form->find_input("gateway$i", 'text'); + $$interfaces->{"interface$i"}->{'netmask'} = $$form->find_input("subnet$i", 'text'); + #we do not support dns yet, just in case of future support + $$interfaces->{"interface$i"}->{'dns0'} = $$form->find_input("dns0$i", 'text'); + $$interfaces->{"interface$i"}->{'dns1'} = $$form->find_input("dns1$i", 'text'); + $$interfaces->{"interface$i"}->{'dns2'} = $$form->find_input("dns2$i", 'text'); + $i++; + } + } + return ( [RC_ERROR,"Cannot find any network interface on $server"]) if ( ! $$interfaces); + + return ( [SUCCESS, undef]); +} + +########################################################################## +# Set network configuration +########################################################################## +sub set_netcfg +{ + my $exp = shift; + my $request = shift; + my $interfaces = shift; + my $form = shift; + my $ua = @$exp[0]; + + my $real_inc_name; + my ($inc_name, $inc_ip, $inc_host, $inc_gateway, $inc_netmask) = split /,/, $request->{'method'}->{'network'}; + + chomp ($inc_name, $inc_ip, $inc_host, $inc_gateway, $inc_netmask); + if ( $inc_name =~ /^eth(\d)$/) + { + $real_inc_name = "interface$1"; + } + elsif ( $inc_name =~/(\d+)\.(\d+)\.(\d+)\.(\d+)/) + { + for my $inc (keys %$interfaces) + { + if ($interfaces->{ $inc}->{'ip'}->value() eq $inc_name) + { + $real_inc_name = $inc; + last; + } + } + } + else + { + return( [RC_ERROR, "Incorrect network interface name $inc_name"] ); + } + + return ( [RC_ERROR,"Cannot find interface $inc_name"]) if ( ! exists ($$interfaces{ $real_inc_name})); + + $interfaces->{ $real_inc_name}->{'selected'}->check(); + + if ( $interfaces->{ $real_inc_name}->{'type'}) + { + $interfaces->{ $real_inc_name}->{'type'}->value('Static'); + } + else + { + return ( [RC_ERROR,"Cannot set this interface to static type"]); + } + my @set_entries = (); + if ( $inc_ip ) + { + return ( [RC_ERROR,"Cannot set IP address to $inc_ip"]) if (! $interfaces->{ $real_inc_name}->{'ip'}); + $interfaces->{ $real_inc_name}->{'ip'}->value( $inc_ip); + push @set_entries, 'IP address'; + } + if ( $inc_host) + { + return ( [RC_ERROR,"Cannot set hostname to $inc_host"]) if (! $interfaces->{ $real_inc_name}->{'hostname'}); + $interfaces->{ $real_inc_name}->{'hostname'}->value( $inc_host); + push @set_entries, 'hostname'; + } + if ( $inc_gateway) + { + return ( [RC_ERROR,"Cannot set gateway to $inc_gateway"]) if (! $interfaces->{ $real_inc_name}->{'gateway'}); + $interfaces->{ $real_inc_name}->{'gateway'}->value( $inc_gateway); + push @set_entries, 'gateway'; + } + if ( $inc_netmask) + { + return ( [RC_ERROR,"Cannot set netmask to $inc_netmask"]) if (! $interfaces->{ $real_inc_name}->{'netmask'}); + $interfaces->{ $real_inc_name}->{'netmask'}->value( $inc_netmask); + push @set_entries, 'netmask'; + } + + #Click "Continue" button + my $data = $form->click('save'); + my $res = $ua->request( $data); + if (!$res->is_success()) + { + return ( [RC_ERROR, "Failed to set " . join ',', @set_entries]); + } + + #Go to the confirm page + $form = HTML::Form->parse( $res->content, $res->base ); +# $data = $form->click('submit'); + $res = $ua->request( $data); + if ($res->is_success()) + { + return ( [SUCCESS, "Success to set " . join ',', @set_entries]); + } + else + { + return ( [RC_ERROR, "Failed to set " . join ',', @set_entries]); + } +} + +########################################################################## +# Format the output of network configuration +########################################################################## +sub format_netcfg +{ + my $interfaces = shift; + my $output = undef; + for my $inc ( sort keys %$interfaces) + { +#improve needed: need to make the output consistent to MM + $output .= "\n\t" . $inc . ":\n"; + $output =~ s/interface(\d)/eth$1/; + # There are 2 possible value for $type, + # 1 means "Dynamic", 2 means "Static" + # Now to find the correct type name + my @possible_values = $interfaces->{$inc}->{'type'}->possible_values(); + my @possible_names = $interfaces->{$inc}->{'type'}->value_names(); + my %value_names = {}; + for ( my $i = 0; $i < scalar( @possible_values); $i++) + { + $value_names{ @possible_values[$i]} = @possible_names[$i]; + } + my $type = $interfaces->{$inc}->{'type'} ? $value_names{ $interfaces->{$inc}->{'type'}->value()} : undef;; + $type = "Static" if ( $type == 2); + my $ip = $interfaces->{$inc}->{'ip'} ? $interfaces->{$inc}->{'ip'}->value() : undef; + my $hostname = $interfaces->{$inc}->{'hostname'} ? $interfaces->{$inc}->{'hostname'}->value() : undef; + my $gateway = $interfaces->{$inc}->{'gateway'} ? $interfaces->{$inc}->{'gateway'}->value() : undef; + my $netmask = $interfaces->{$inc}->{'netmask'} ? $interfaces->{$inc}->{'netmask'}->value() : undef; + + $output .= "\t\tIP Type: " . $type . "\n"; + $output .= "\t\tIP Address: " . $ip . "\n"; + $output .= "\t\tHostname: " . $hostname . "\n"; + $output .= "\t\tGateway: " . $gateway . "\n"; + $output .= "\t\tNetmask: " . $netmask . "\n"; + } + return( [SUCCESS,$output] ); +} 1; - - - - - diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index 4f638e5f6..ddb5bde51 100644 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -116,7 +116,7 @@ my %usage = ( rmvm [-h|--help|-v|--version]", "lsslp" => "Usage: lsslp [-h|--help|-v|--version] - lsslp [-V|--verbose][-i ip[,ip..]][-w][-r|-x|-z][-s BPA|MM|IVM|RSA|FSP|HMC] + lsslp [-V|--verbose][-i ip[,ip..]][-w][-u] [-r|-x|-z][-s BPA|MM|IVM|RSA|FSP|HMC] [-t tries][-m][-e cmd][-c [timeout[timeout,..]]]", "rflash" => "Usage: rflash [ -h|--help|-v|--version]