more on xdsh to ethernet switches
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@14356 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
8d9f8e6608
commit
d3a3b4d526
@ -1228,6 +1228,7 @@ sub fork_fanout_dsh
|
||||
|
||||
# execute and remove the /tmp file build which is a copy of the
|
||||
# input -E file
|
||||
#print "Command=@dsh_command\n";
|
||||
|
||||
@process_info = xCAT::DSHCore->fork_output($user_target, @dsh_command);
|
||||
if ($process_info[0] == -2)
|
||||
@ -1876,10 +1877,10 @@ sub stream_error
|
||||
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
|
||||
}
|
||||
|
||||
# my $rsp = {};
|
||||
# $rsp->{error}->[0] =
|
||||
# "$user_target remote command had return code $$target_properties{'target-rc'}";
|
||||
# xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
#my $rsp = {};
|
||||
#$rsp->{error}->[0] =
|
||||
# "$user_target remote command had return code $$target_properties{'target-rc'}";
|
||||
#xCAT::MsgUtils->message("E", $rsp, $::CALLBACK);
|
||||
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] =
|
||||
@ -2248,40 +2249,42 @@ sub config_dsh
|
||||
if ($$options{'devicetype'})
|
||||
{
|
||||
$ENV{'DEVICETYPE'} = $$options{'devicetype'};
|
||||
my $devicepath = $$options{'devicetype'};
|
||||
$devicepath =~ s/::/\//g;
|
||||
my $devicename = $$options{'devicetype'};
|
||||
$devicename =~ s/::/\//g;
|
||||
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "Processing $devicepath device type";
|
||||
$rsp->{data}->[0] = "Processing $devicename device type";
|
||||
$dsh_trace && xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
|
||||
|
||||
# process the config file
|
||||
|
||||
$devicepath = "/var/opt/xcat/" . $devicepath . "/config";
|
||||
|
||||
# Get configuration from $::XCATDEVCFGDIR
|
||||
# used for QLogic and Mellanox
|
||||
if (-e $devicepath)
|
||||
{
|
||||
my $deviceconf = get_config($devicepath);
|
||||
|
||||
# Get all dsh section configuration
|
||||
foreach my $entry (keys %{$$deviceconf{'xdsh'}})
|
||||
{
|
||||
# process the config file. check /var/opt/xcat/... first, if the config
|
||||
# file is not found, goto /opt/xcat/share/devicetype
|
||||
my $devicepath = "/var/opt/xcat/" . $devicename . "/config";
|
||||
if (! -e $devicepath) {
|
||||
$devicepath="$::XCATROOT/share/xcat/devicetype/" . $devicename . "/config";
|
||||
}
|
||||
# Get configuration from $::XCATDEVCFGDIR
|
||||
# used for QLogic and Mellanox
|
||||
if (-e $devicepath)
|
||||
{
|
||||
my $deviceconf = get_config($devicepath);
|
||||
|
||||
# Get all dsh section configuration
|
||||
foreach my $entry (keys %{$$deviceconf{'xdsh'}})
|
||||
{
|
||||
my $value = $$deviceconf{'xdsh'}{$entry};
|
||||
if ($value)
|
||||
{
|
||||
$$options{$entry} = $value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
my $rsp = {};
|
||||
$rsp->{error}->[0] = "EMsgMISSING_DEV_CFG";
|
||||
xCAT::MsgUtils->message('E', $rsp, $::CALLBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
!$$options{'node-rsh'}
|
||||
@ -4080,10 +4083,15 @@ sub parse_and_run_dsh
|
||||
if (defined $options{'devicetype'})
|
||||
{
|
||||
$ENV{'DEVICETYPE'} = $options{'devicetype'};
|
||||
my $devicepath = $options{'devicetype'};
|
||||
$devicepath =~ s/::/\//g;
|
||||
$devicepath = "/var/opt/xcat/" . $devicepath . "/config";
|
||||
if (-e $devicepath)
|
||||
my $devicename = $options{'devicetype'};
|
||||
$devicename =~ s/::/\//g;
|
||||
my $devicepath = "/var/opt/xcat/" . $devicename . "/config";
|
||||
# go to backup directory if the config file
|
||||
# cannot be found under /var/opt/xcat/...
|
||||
if (! -e $devicepath) {
|
||||
$devicepath="$::XCATROOT/share/xcat/devicetype/" . $devicename . "/config";
|
||||
}
|
||||
if (-e $devicepath)
|
||||
{
|
||||
my $deviceconf = get_config($devicepath);
|
||||
|
||||
|
@ -23,7 +23,7 @@ use xCAT::MsgUtils;
|
||||
A command array for the ssh command with the appropriate
|
||||
arguments as defined in the $config hash table
|
||||
=cut
|
||||
#####################################################
|
||||
#####################################################
|
||||
sub remote_shell_command {
|
||||
my ( $class, $config, $exec_path ) = @_;
|
||||
|
||||
@ -51,6 +51,23 @@ sub remote_shell_command {
|
||||
return @command;
|
||||
}
|
||||
|
||||
##################################################################
|
||||
=head3
|
||||
run_remote_shell_api
|
||||
|
||||
This routine tried ssh then telnet to logon to a node and
|
||||
run a sequence of commands.
|
||||
Arguments:
|
||||
$node - node name
|
||||
$user - user login name
|
||||
$passed - user login password
|
||||
$cmds - a list of commands seperated by semicolon.
|
||||
Returns:
|
||||
[error code, output]
|
||||
error code: 0 sucess
|
||||
non-zero: failed. the output contains the error message.
|
||||
=cut
|
||||
#########################################################################
|
||||
sub run_remote_shell_api {
|
||||
require xCAT::SSHInteract;
|
||||
my $node=shift;
|
||||
@ -58,9 +75,13 @@ sub run_remote_shell_api {
|
||||
my $passwd=shift;
|
||||
my $args = join(" ", @_);
|
||||
my $t;
|
||||
my $prompt='.*[\>\#\$]$';
|
||||
my $more_prompt='(.*key to continue.*|--More--\s*$)';
|
||||
my $verbose=0;
|
||||
my $output;
|
||||
|
||||
if(0) {
|
||||
print "start SSH session...\n";
|
||||
eval {
|
||||
$output="start SSH session...\n";
|
||||
$t = new xCAT::SSHInteract(
|
||||
-username=>$user,
|
||||
-password=>$passwd,
|
||||
@ -69,108 +90,206 @@ sub run_remote_shell_api {
|
||||
-output_record_separator=>"\r",
|
||||
Timeout=>5,
|
||||
Errmode=>'return',
|
||||
Prompt=>'/.*[\>\#]$/',
|
||||
Prompt=>"/$prompt/",
|
||||
);
|
||||
};
|
||||
my $errmsg=$@;
|
||||
$errmsg =~ s/ at (.*) line (\d)+//g;
|
||||
print "$errmsg\n";
|
||||
$output.="$errmsg\n";
|
||||
|
||||
my $rc=1;
|
||||
if (not $t) {#ssh failed.. fallback to a telnet attempt
|
||||
print "start Telnet session...\n";
|
||||
$output.="start Telnet session...\n";
|
||||
require Net::Telnet;
|
||||
$t = new Net::Telnet(
|
||||
Timeout=>5,
|
||||
Errmode=>'return',
|
||||
Prompt=>'/.*[\>\#]$/',
|
||||
Prompt=>"/$prompt/",
|
||||
);
|
||||
$rc = $t->open($node);
|
||||
if ($rc) {
|
||||
my $pw_tried=0;
|
||||
my $login_done=0;
|
||||
my ($prematch, $match)= $t->waitfor(Match => '/login[: ]*$/i',
|
||||
Match => '/username[: ]*$/i',
|
||||
Match => '/password[: ]*$/i',
|
||||
Match => "/$prompt/",
|
||||
Errmode => "return");
|
||||
if (($match =~ /username[: ]*$/i) || ($match =~ /login[: ]*$/i )) {
|
||||
if ($verbose) {
|
||||
print "1. prematch=$prematch\n match=$match\n";
|
||||
}
|
||||
if ($match =~ /$prompt/) {
|
||||
$login_done=1;
|
||||
} elsif (($match =~ /username[: ]*$/i) || ($match =~ /login[: ]*$/i )) {
|
||||
# user name
|
||||
if ($user) {
|
||||
if (! $t->put(String => "$user\n",
|
||||
Errmode => "return")) {
|
||||
print "login disconnected\n";
|
||||
return [1, "login disconnected"];
|
||||
$output.="login disconnected\n";
|
||||
return [1, $output];
|
||||
}
|
||||
} else {
|
||||
print "Username is required.\n";
|
||||
return [1, "Username is required."];
|
||||
$output.="Username is required.\n";
|
||||
return [1, $output];
|
||||
}
|
||||
} elsif ($match =~ /password[: ]*$/i) {
|
||||
if ($passwd) {
|
||||
$pw_tried=1;
|
||||
if (! $t->put(String => "$passwd\n",
|
||||
Errmode => "return")) {
|
||||
print "login disconnected\n";
|
||||
return [1, "login disconnected"];
|
||||
$output.="Login disconnected\n";
|
||||
return [1, $output];
|
||||
}
|
||||
} else {
|
||||
print "password is required.\n";
|
||||
return [1, "Passwordis required."];
|
||||
$output.="Password is required.\n";
|
||||
return [1, $output];
|
||||
}
|
||||
}
|
||||
|
||||
($prematch, $match)= $t->waitfor(Match => '/login[: ]*$/i',
|
||||
|
||||
if (!$login_done) {
|
||||
($prematch, $match)= $t->waitfor(Match => '/login[: ]*$/i',
|
||||
Match => '/username[: ]*$/i',
|
||||
Match => '/password[: ]*$/i',
|
||||
Match => "/$prompt/",
|
||||
Errmode => "return");
|
||||
|
||||
if (($match =~ /username[: ]*$/i) || ($match =~ /login[: ]*$/i )) {
|
||||
print "Incorrect username.\n";
|
||||
return [1, "Incorrect username."];
|
||||
} elsif ($match =~ /password[: ]*$/i) {
|
||||
if ($pw_tried) {
|
||||
print "Incorrect password.\n";
|
||||
return [1, "Incorrect password."];
|
||||
if ($verbose) {
|
||||
print "2. prematch=$prematch\n match=$match\n";
|
||||
}
|
||||
if ($passwd) {
|
||||
if (! $t->put(String => "$passwd\n",
|
||||
Errmode => "return")) {
|
||||
print "login disconnected\n";
|
||||
return [1, "login disconnected"];
|
||||
if ($match =~ /$prompt/) {
|
||||
$login_done=1;
|
||||
} elsif (($match =~ /username[: ]*$/i) || ($match =~ /login[: ]*$/i )) {
|
||||
$output.="Incorrect username.\n";
|
||||
return [1, $output];
|
||||
} elsif ($match =~ /password[: ]*$/i) {
|
||||
if ($pw_tried) {
|
||||
$output.="Incorrect password.\n";
|
||||
return [1, $output];
|
||||
}
|
||||
if ($passwd) {
|
||||
if (! $t->put(String => "$passwd\n",
|
||||
Errmode => "return")) {
|
||||
$output.="Login disconnected\n";
|
||||
return [1, $output];
|
||||
}
|
||||
} else {
|
||||
$output.="Password is required.\n";
|
||||
return [1, $output];
|
||||
}
|
||||
}
|
||||
|
||||
if (!login_done) {
|
||||
#Wait for command prompt
|
||||
($prematch, $match) = $t->waitfor(Match => '/login[: ]*$/i',
|
||||
Match => '/username[: ]*$/i',
|
||||
Match => '/password[: ]*$/i',
|
||||
Match => "/$prompt/",
|
||||
Errmode => "return");
|
||||
if ($verbose) {
|
||||
print "3. prematch=$prematch\n match=$match\n";
|
||||
}
|
||||
|
||||
if ($match =~ /$prompt/) {
|
||||
$login_done=1;
|
||||
} elsif ($match =~ /login[: ]*$/i or $match =~ /username[: ]*$/i or $match =~ /password[: ]*$/i) {
|
||||
$output.="Login failed: bad login name or password\n";
|
||||
return [1, $output];
|
||||
} else {
|
||||
if ($t->errmsg) {
|
||||
$output.= $t->errmsg . "\n";
|
||||
return [1, $output];
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print "password is required.\n";
|
||||
return [1, "Passwordis required."];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#Wait for command prompt
|
||||
($prematch, $match) = $t->waitfor(Match => '/login[: ]*$/i',
|
||||
Match => '/username[: ]*$/i',
|
||||
Match => '/password[: ]*$/i',
|
||||
Match => '/\>/',
|
||||
Errmode => "return");
|
||||
|
||||
#print "prematch=$prematch, match=$match\n";
|
||||
if ($match =~ /login[: ]*$/i or $match =~ /username[: ]*$/i or $match =~ /password[: ]*$/i) {
|
||||
print "login failed: bad login name or password\n";
|
||||
return [1, "login failed: bad login name or password"];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$rc) {
|
||||
print "Error: " . $t->errmsg . "\n";
|
||||
return([1, $t->errmsg]);
|
||||
$output.=$t->errmsg . "\n";
|
||||
return [1, $output];
|
||||
}
|
||||
|
||||
$rc = 0;
|
||||
my $output;
|
||||
my $try_more=0;
|
||||
my @cmd_array=split(';', $args);
|
||||
|
||||
foreach my $cmd (@cmd_array) {
|
||||
#my @data = $t->cmd($cmd);
|
||||
my @data= $t->cmd(String =>$cmd);
|
||||
$output .= "command:$cmd\n@data\n";
|
||||
print "command:$cmd\n@data\n";
|
||||
if ($verbose) {
|
||||
print "command:$cmd\n";
|
||||
}
|
||||
while (1) {
|
||||
if ($try_more) {
|
||||
#This is for second and consequent pages.
|
||||
#if the user disables the paging, then this code will never run.
|
||||
#To disable paging (which is recommended),
|
||||
#they need to add a command before any other commands
|
||||
#For Cisco switch: terminal length 0
|
||||
#For BNT switch: terminal-length 0
|
||||
#For example:
|
||||
# xdsh <swname> --type EthSwitch "terminal length 0;show vlan"
|
||||
if (! $t->put(String => " ",
|
||||
Errmode => "return")) {
|
||||
$output.="Command $cmd failed: " . $t->errmsg() . "\n";
|
||||
return [1, $output];
|
||||
}
|
||||
if ($verbose) {
|
||||
my $lastline=$t->lastline();
|
||||
print "---lastline=$lastline\n";
|
||||
}
|
||||
($prematch, $match) = $t->waitfor(Match => "/$more_prompt/",
|
||||
Match => "/$prompt/",
|
||||
Errmode => "return",
|
||||
Timeout=>3);
|
||||
} else {
|
||||
# for the first page which may contian all
|
||||
if (! $t->put(String => "$cmd\n",
|
||||
Errmode => "return")) {
|
||||
$output.="Command $cmd failed." . $t->errmsg() . "\n";
|
||||
return [1, $output];
|
||||
}
|
||||
if ($verbose) {
|
||||
my $lastline=$t->lastline();
|
||||
print "lastline=$lastline\n";
|
||||
}
|
||||
($prematch, $match) = $t->waitfor(Match => "/$more_prompt/",
|
||||
Match => "/$prompt/",
|
||||
Match => '/password:\s*$/i',
|
||||
Errmode => "return",
|
||||
Timeout=>3);
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
print "-----prematch=$prematch\nmatch=$match\n";
|
||||
}
|
||||
|
||||
my $error=$t->errmsg();
|
||||
if ($error) {
|
||||
$output.="Command $cmd failed: $error\n";
|
||||
return [1, $output];
|
||||
}
|
||||
|
||||
# remove the first line
|
||||
if ($try_more) {
|
||||
my @data=split("\n", $prematch);
|
||||
shift @data;
|
||||
#shift @data;
|
||||
#shift @data;
|
||||
$prematch=join("\n", @data);
|
||||
#add a newline at the end if not there
|
||||
my $lastchar=substr($prematch, -1, 1);
|
||||
if ($lastchar ne "\n") {
|
||||
$prematch .= "\n";
|
||||
}
|
||||
}
|
||||
$output .= $prematch;
|
||||
|
||||
if ($match =~ /$more_prompt/i) {
|
||||
$try_more=1;
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
$t->close();
|
||||
return [0, $output];
|
||||
@ -178,4 +297,6 @@ sub run_remote_shell_api {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
@ -28,6 +28,13 @@ if (!GetOptions(
|
||||
|
||||
my $node = $ARGV[0];
|
||||
|
||||
xCAT::RShellAPI::run_remote_shell_api($node, $username, $passwd, @ARGV[1 .. $#ARGV]);
|
||||
my $output =xCAT::RShellAPI::run_remote_shell_api($node, $username, $passwd, @ARGV[1 .. $#ARGV]);
|
||||
my $rc=0;
|
||||
my $data;
|
||||
if ($output && (@$output > 1)) {
|
||||
$rc=$output->[0];
|
||||
$data=$output->[1];
|
||||
}
|
||||
|
||||
exit 0;
|
||||
print "$data";
|
||||
exit $rc;
|
||||
|
@ -1,5 +1,5 @@
|
||||
[main]
|
||||
ssh-setup-command=
|
||||
[xdsh]
|
||||
pre-command=NULL
|
||||
pre-command=terminal-length 0;
|
||||
post-command=NULL
|
5
xCAT-server/share/xcat/devicetype/EthSwitch/Cisco/config
Normal file
5
xCAT-server/share/xcat/devicetype/EthSwitch/Cisco/config
Normal file
@ -0,0 +1,5 @@
|
||||
[main]
|
||||
ssh-setup-command=
|
||||
[xdsh]
|
||||
pre-command=terminal length 0;
|
||||
post-command=NULL
|
11
xCAT-server/share/xcat/devicetype/EthSwitch/config
Normal file
11
xCAT-server/share/xcat/devicetype/EthSwitch/config
Normal file
@ -0,0 +1,11 @@
|
||||
#This is a configuration file for running xdsh again ethernet switches.
|
||||
#If the switch type is not defined, you can create a subdirctory for that
|
||||
#type of switch. For example, for cisco swith, create a subdirectory
|
||||
# called "Cisco" under EthSwitch. copy this config file there. And
|
||||
#put the command that disables the paging in pre-command
|
||||
#pre-command=terminal lenth 0;
|
||||
[main]
|
||||
ssh-setup-command=
|
||||
[xdsh]
|
||||
pre-command=NULL
|
||||
post-command=NULL
|
Loading…
Reference in New Issue
Block a user