2011-10-15 10:34:50 +00:00
#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#
package xCAT::RemoteShellExp ;
#-----------------------------------------------------------------------------
= head1 RemoteShellExp
Uses perl Expect to set up ssh passwordless login on the input node list
Called from xdsh <nodelist> - K command
It works for node and devices ( such as QLogic Switch ) .
See man xdsh .
It works for root and non - root userids .
Environment Variables input to drive the setup:
DSH_REMOTE_CMD set to path to remote shell ( ssh )
root password must agree on all the nodes
XCAT_ROOT set to root of xCAT install
DSH_REMOTE_PASSWORD - to_user password for - s option required to sendkeys )
Note this is obtained in the xdsh client frontend .
SSH_SETUP_COMMAND - Command to be sent to the IB switch to setup SSH .
DSH_FROM_USERID_HOME - The home directory of the userid from
where the ssh keys will be obtained
to send
DSH_FROM_USERID - The userid from where the ssh keys will be obtained
to send
to the node , or generated and then obtained to send to the
node .
DSH_TO_USERID - The userid on the node where the ssh keys will be updated .
DSH_ENABLE_SSH - Node to node root passwordless ssh will be setup .
2011-10-17 16:32:11 +00:00
Usage: remoteshellexp
2011-10-15 10:34:50 +00:00
[ - t node list ] test ssh connection to the node
[ - k ] Generates the ssh keys needed , for the user on the MN .
[ - s node list ] copies the ssh keys to the nodes
exit 0 - good
exit 1 - abort
exit 2 - usage error
Examples:
$ rc = xCAT::RemoteShellExp - > remoteshellexp ( "k" , $ callback , $ remoteshellcmd ) ;
$ rc = xCAT::RemoteShellExp - > remoteshellexp ( "s" , $ callback , $ remoteshellcmd , $ nodes ) ;
$ rc = xCAT::RemoteShellExp - > remoteshellexp ( "t" , $ callback , $ remoteshellcmd , $ nodes ) ;
= cut
BEGIN
{
$ ::XCATROOT = $ ENV { 'XCATROOT' } ? $ ENV { 'XCATROOT' } : '/opt/xcat' ;
$ ::XCATDIR = $ ENV { 'XCATDIR' } ? $ ENV { 'XCATDIR' } : '/etc/xcat' ;
}
use lib "$::XCATROOT/lib/perl" ;
use xCAT::Utils ;
use Getopt::Long ;
use xCAT::MsgUtils ;
use Expect ;
use strict ;
#-----------------------------------------------------------------------------
sub remoteshellexp
{
my ( $ class , $ flag , $ callback , $ remoteshell , $ nodes ) = @ _ ;
my $ rc = 0 ;
$ ::CALLBACK = $ callback ;
if ( ! ( $ flag ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"No flag provide to remoteshellexp." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 2 ) ;
return 2 ;
}
if ( ( $ flag ne "k" ) && ( $ flag ne "t" ) && ( $ flag ne "s" ) ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"Invalid flag $flag provided." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 2 ;
}
# for -s flag must have nodes and a $to_userid password
my $ to_user_password ;
if ( $ ENV { 'DSH_REMOTE_PASSWORD' } ) {
$ to_user_password = $ ENV { 'DSH_REMOTE_PASSWORD' } ;
}
if ( $ flag eq "s" ) {
if ( ! $ to_user_password ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"The DSH_REMOTE_PASSWORD environment variable has not been set to the user id password on the node which will have their ssh keys updated (ususally root)." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 2 ;
}
if ( ! $ nodes ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"No nodes were input to update the user's ssh keys." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 2 ;
}
}
my $ ssh_setup_cmd ;
my $ from_userid ;
my $ to_userid ;
my $ home ;
my $ remotecopy ;
# if caller input a path to ssh remote command, use it
if ( $ ENV { 'DSH_REMOTE_CMD' } ) {
$ remoteshell = $ ENV { 'DSH_REMOTE_CMD' } ;
} else {
if ( ! $ remoteshell ) {
$ remoteshell = "/usr/bin/ssh" ;
}
}
# figure out path to scp
my ( $ path , $ ssh ) = split ( /ssh/ , $ remoteshell ) ;
$ remotecopy = $ path . "scp" ;
# if caller input the ssh setup command (such as for IB Switch)
if ( $ ENV { 'SSH_SETUP_COMMAND' } ) {
$ ssh_setup_cmd = $ ENV { 'SSH_SETUP_COMMAND' } ;
}
# set User on the Management node that has the ssh keys
# this id can be a local (non-root) id as well as root
if ( $ ENV { 'DSH_FROM_USERID' } ) {
$ from_userid = $ ENV { 'DSH_FROM_USERID' } ;
} else {
$ from_userid = "root" ;
}
# set User on the node where we will send the keys
# this id can be a local id as well as root
if ( $ ENV { 'DSH_TO_USERID' } ) {
$ to_userid = $ ENV { 'DSH_TO_USERID' } ;
} else {
$ to_userid = "root" ;
}
# set User home directory to find the ssh public key to send
# For non-root ids information may not be in /etc/passwd
# but elsewhere like LDAP
if ( $ ENV { 'DSH_FROM_USERID_HOME' } ) {
$ home = $ ENV { 'DSH_FROM_USERID_HOME' } ;
} else {
$ home = xCAT::Utils - > getHomeDir ( $ from_userid ) ;
}
# This indicates we will generate new ssh keys for the user,
# if they are not already there
my $ key = "$home/.ssh/id_rsa" ;
my $ key2 = "$home/.ssh/id_rsa.pub" ;
# Check to see if empty
if ( - z $ key ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"The $key file is empty. Remove it and rerun the command." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 1 ;
}
if ( - z $ key2 ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"The $key2 file is empty. Remove it and rerun the command." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 1 ;
}
if ( ( $ flag eq "k" ) && ( ! ( - e $ key ) ) )
{
# if the file size of the id_rsa key is 0, tell them to remove it
# and run the command again
$ rc = xCAT::RemoteShellExp - > gensshkeys ;
}
# send ssh keys to the nodes/devices, to setup passwordless ssh
if ( $ flag eq "s" )
{
if ( ! ( $ nodes ) ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"There are no nodes defined to update the ssh keys." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 1 ;
}
if ( $ ssh_setup_cmd ) { # setup ssh on devices
$ rc = xCAT::RemoteShellExp - > senddeviceskeys ( $ remoteshell , $ remotecopy , $ to_userid , $ to_user_password , $ home , $ ssh_setup_cmd , $ nodes ) ;
} else { #setup ssh on nodes
2011-10-17 13:09:20 +00:00
$ rc = xCAT::RemoteShellExp - > sendnodeskeys ( $ remoteshell , $ remotecopy , $ to_userid , $ to_user_password , $ home , $ nodes ) ;
2011-10-15 10:34:50 +00:00
}
}
# test ssh setup on the node
if ( $ flag eq "t" )
{
$ rc = xCAT::RemoteShellExp - > testkeys ( $ remoteshell , $ to_userid , $ nodes ) ;
}
return $ rc ;
}
#-----------------------------------------------------------------------------
= head3 gensshkeys
Generates new ssh keys for the input userid on the MN , if they do not
already exist . Test for id_rsa key existence .
= cut
#-----------------------------------------------------------------------------
sub gensshkeys
{
my ( $ class ) = @ _ ;
my $ keygen ;
my $ timeout = 10 ; # sets Expect default timeout, 0 accepts immediately
my $ keygen_sent = 0 ;
my $ prompt1 = 'Generating public/private rsa' ;
my $ prompt2 = 'Enter file.*:' ;
my $ prompt3 = 'Enter passphrase.*:' ;
my $ prompt4 = 'Enter same passphrase.*:' ;
my $ expect_log = undef ;
my $ debug = 0 ;
if ( $ ::VERBOSE )
{
$ debug = 1 ;
}
$ keygen = new Expect ;
# run /usr/bin/ssh-keygen -t rsa
# prompt1 = 'Generating public/private rsa';
# prompt2 = 'Enter file.*:';
# -re "\r"
# prompt3 = 'Enter passphrase.*:';
# -re "\r"
# prompt4 = 'Enter same passphrase.*:';
# -re "\r"
# disable command echoing
#$keygen->slave->stty(qw(sane -echo));
#
# exp_internal(1) sets exp_internal debugging
# to STDERR.
#
#$keygen->exp_internal(1);
$ keygen - > exp_internal ( $ debug ) ;
#
# log_stdout(0) prevent the program's output from being shown.
# turn on if debugging error
#$keygen->log_stdout(1);
$ keygen - > log_stdout ( $ debug ) ;
# Run the ssh key gen command
my $ spawncmd = "/usr/bin/ssh-keygen -t rsa" ;
unless ( $ keygen - > spawn ( $ spawncmd ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"Unable to run $spawncmd." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 1 ;
}
#
#ssh-keygen prompts starts here
#
my @ result = $ keygen - > expect (
$ timeout ,
[
$ prompt1 , # Generating public/private rsa
sub {
$ keygen - > send ( "\r" ) ;
$ keygen - > clear_accum ( ) ;
$ keygen - > exp_continue ( ) ;
}
] ,
[
$ prompt2 , # Enter file.*:
sub {
$ keygen - > send ( "\r" ) ;
$ keygen - > clear_accum ( ) ;
$ keygen - > exp_continue ( ) ;
}
] ,
[
$ prompt3 , # Enter passphrase.*
sub {
$ keygen - > send ( "\r" ) ;
$ keygen - > clear_accum ( ) ;
$ keygen - > exp_continue ( ) ;
}
] ,
[
$ prompt4 , # Enter same passphrase.
sub {
$ keygen - > send ( "\r" ) ;
$ keygen - > clear_accum ( ) ;
$ keygen - > exp_continue ( ) ;
}
]
) ; # end prompts
##########################################
# Expect error - report and quit
##########################################
if ( defined ( $ result [ 1 ] ) )
{
my $ msg = $ result [ 1 ] ;
$ keygen - > soft_close ( ) ;
if ( $ msg =~ /status 0/i ) { # no error
return 0 ;
} else {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = $ msg ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
return 1 ;
}
} else {
$ keygen - > soft_close ( ) ;
return 0 ;
}
}
#-----------------------------------------------------------------------------
= head3 testkeys
Test to see if the remoteshell setup worked
= cut
#-----------------------------------------------------------------------------
sub testkeys
{
my ( $ class , $ remoteshell , $ to_userid , $ nodes ) = @ _ ;
my $ testkeys ;
my $ timeout = 10 ; # sets Expect default timeout, 0 accepts immediately
my $ testkeys_sent = 0 ;
my $ prompt1 = 'Are you sure you want to continue connecting (yes/no)?' ;
my $ prompt2 = 'ssword:' ;
my $ prompt3 = 'Permission denied*' ;
my $ prompt4 = 'test.success' ;
my $ expect_log = undef ;
my $ debug = 0 ;
my $ rc = 1 ; # default to error
if ( $ ::VERBOSE )
{
$ debug = 1 ;
}
$ testkeys = new Expect ;
# run ssh <node> -l to_userid echo test.success
# possible return
# bad
## Are you sure you want to continue connecting (yes/no)?
## *ssword*
## Permission denied.
# Good
## test.success
# disable command echoing
#$testkeys->slave->stty(qw(sane -echo));
#
# exp_internal(1) sets exp_internal debugging
# to STDERR.
#
#$testkeys->exp_internal(1);
$ testkeys - > exp_internal ( $ debug ) ;
#
# log_stdout(0) prevent the program's output from being shown.
# turn on if debugging error
#$testkeys->log_stdout(1);
$ testkeys - > log_stdout ( $ debug ) ;
# Run the ssh key gen command
my $ spawncmd = "$remoteshell $nodes -l $to_userid echo test.success" ;
unless ( $ testkeys - > spawn ( $ spawncmd ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"Unable to run $spawncmd." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return 1 ;
}
#
#testkeys prompts starts here
#
my @ result = $ testkeys - > expect (
$ timeout ,
[
$ prompt1 , # Are you sure you want to ...
sub {
$ rc = 1 ;
$ testkeys - > hard_close ( ) ;
}
] ,
[
$ prompt2 , # *ssword*
sub {
$ rc = 1 ;
$ testkeys - > hard_close ( ) ;
}
] ,
[
$ prompt3 , # Permission denied
sub {
$ rc = 1 ;
$ testkeys - > hard_close ( ) ;
}
] ,
[
$ prompt4 , # test.success
sub {
$ rc = 0 ;
}
]
) ; # end prompts
##########################################
# Expect error - report and quit
##########################################
if ( defined ( $ result [ 1 ] ) )
{
my $ msg = $ result [ 1 ] ;
$ testkeys - > soft_close ( ) ;
if ( $ msg =~ /status 0/i ) { # no error
return 0 ;
} else {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = $ msg ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
return 1 ;
}
} else {
$ testkeys - > soft_close ( ) ;
return $ rc ;
}
}
#-------------------------------------------------------------------------------
= head3 sendnodeskeys
Setup the ssh keys on the nodes
= cut
#-----------------------------------------------------------------------------
sub sendnodeskeys
{
my ( $ class , $ remoteshell , $ remotecopy , $ to_userid , $ to_userpassword , $ home , $ nodes ) = @ _ ;
my $ sendkeys ;
my $ timeout = 10 ; # sets Expect default timeout, 0 accepts immediately
my $ sendkeys_sent = 0 ;
my $ prompt1 = 'Are you sure you want to continue connecting (yes/no)?' ;
my $ prompt2 = 'ssword:' ;
my $ prompt3 = 'Permission denied*' ;
my $ expect_log = undef ;
my $ debug = 0 ;
my $ rc = 0 ;
if ( $ ::VERBOSE )
{
$ debug = 1 ;
}
# For each node
# make a temporary directory on the node
# run scp <nodename> -l <to user> /bin/mkdir -p /tmp/$to_userid/.ssh
# xdsh has built an authorized_keys file for the node
# in $HOME/.ssh/tmp/authorized_keys
# copy to the node to the temp directory
# scp $HOME/.ssh/tmp/authorized_keys to_userid@<node>:/tmp/$to_userid/.ssh
# If you are going to enable ssh to ssh between nodes, then
# scp $HOME/.ssh/id_rsa to that temp directory on the node
# copy the script $HOME/.ssh/copy.sh to the node, it will do the
# the work of setting up the user's ssh keys and clean up
# ssh (run) copy.sh on the node
my @ nodelist = split ( /,/ , $ nodes ) ;
foreach my $ node ( @ nodelist ) {
$ sendkeys = new Expect ;
# disable command echoing
#$sendkeys->slave->stty(qw(sane -echo));
#
# exp_internal(1) sets exp_internal debugging
# to STDERR.
#
#$sendkeys->exp_internal(1);
$ sendkeys - > exp_internal ( $ debug ) ;
#
# log_stdout(0) prevent the program's output from being shown.
# turn on if debugging error
#$sendkeys->log_stdout(1);
$ sendkeys - > log_stdout ( $ debug ) ;
# command to make the temp directory on the node
my $ spawnmkdir =
"$remoteshell $node -l $to_userid /bin/mkdir -p /tmp/$to_userid/.ssh" ;
# command to copy the needed files to the node
# send mkdir command
unless ( $ sendkeys - > spawn ( $ spawnmkdir ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
2011-11-17 17:10:20 +00:00
"Unable to run $spawnmkdir on $node" ;
2011-10-15 10:34:50 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
2011-11-17 17:10:20 +00:00
next ;
2011-10-15 10:34:50 +00:00
}
#
#mkdir prompts starts here
#
my @ result = $ sendkeys - > expect (
$ timeout ,
[
$ prompt1 , # Are you sure you want to ...
sub {
$ sendkeys - > send ( "yes\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt2 , # *ssword*
sub {
$ sendkeys - > send ( "$to_userpassword\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt3 , # Permission denied
sub {
$ rc = 1 ;
2011-11-17 17:10:20 +00:00
$ sendkeys - > hard_close ( ) ;
2011-10-15 10:34:50 +00:00
}
] ,
) ; # end prompts
##########################################
# Expect error - report
##########################################
if ( defined ( $ result [ 1 ] ) )
{
my $ msg = $ result [ 1 ] ;
2011-11-17 17:10:20 +00:00
if ( $ msg =~ /status 0/i ) { # no error
2011-10-15 10:34:50 +00:00
$ rc = 0 ;
} else {
2011-11-17 17:10:20 +00:00
if ( $ msg =~ /2:EOF/i ) { # no error
$ rc = 0 ;
} else {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "mkdir:$node has error,$msg" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
$ rc = 1 ;
}
2011-10-15 10:34:50 +00:00
}
}
$ sendkeys - > soft_close ( ) ;
#
#copy files prompts starts here
#
$ sendkeys = new Expect ;
# disable command echoing
#$sendkeys->slave->stty(qw(sane -echo));
#
# exp_internal(1) sets exp_internal debugging
# to STDERR.
#
#$sendkeys->exp_internal(1);
$ sendkeys - > exp_internal ( $ debug ) ;
#
# log_stdout(0) prevent the program's output from being shown.
# turn on if debugging error
#$sendkeys->log_stdout(1);
$ sendkeys - > log_stdout ( $ debug ) ;
my $ spawncopyfiles ;
if ( $ ENV { 'DSH_ENABLE_SSH' } ) { # we will enable node to node ssh
$ spawncopyfiles =
"$remotecopy $home/.ssh/id_rsa $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh " ;
} else { # no node to node ssh ( don't send private key)
$ spawncopyfiles =
"$remotecopy $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh " ;
}
# send copy command
unless ( $ sendkeys - > spawn ( $ spawncopyfiles ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
2011-11-17 17:10:20 +00:00
"Unable to run $spawncopyfiles on $node." ;
2011-10-15 10:34:50 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
2011-11-17 17:10:20 +00:00
next ;
2011-10-15 10:34:50 +00:00
}
2012-02-02 12:36:23 +00:00
@ result = $ sendkeys - > expect (
2011-10-15 10:34:50 +00:00
$ timeout ,
[
$ prompt1 , # Are you sure you want to ...
sub {
$ sendkeys - > send ( "yes\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt2 , # *ssword*
sub {
$ sendkeys - > send ( "$to_userpassword\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt3 , # Permission denied
sub {
$ rc = 1 ;
2011-11-17 17:10:20 +00:00
$ sendkeys - > hard_close ( ) ;
2011-10-15 10:34:50 +00:00
}
] ,
) ; # end prompts
##########################################
# Expect error - report
##########################################
if ( defined ( $ result [ 1 ] ) )
{
my $ msg = $ result [ 1 ] ;
if ( $ msg =~ /status 0/i ) { # no error
$ rc = 0 ;
} else {
2011-11-17 17:10:20 +00:00
if ( $ msg =~ /2:EOF/i ) { # no error
$ rc = 0 ;
} else {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "copykeys:$node has error,$msg" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
$ rc = 1 ;
}
2011-10-15 10:34:50 +00:00
}
}
$ sendkeys - > soft_close ( ) ;
#
# ssh to the node to run the copy.sh to setup the keys starts here
#
$ sendkeys = new Expect ;
# disable command echoing
#$sendkeys->slave->stty(qw(sane -echo));
#
# exp_internal(1) sets exp_internal debugging
# to STDERR.
#
#$sendkeys->exp_internal(1);
$ sendkeys - > exp_internal ( $ debug ) ;
#
# log_stdout(0) prevent the program's output from being shown.
# turn on if debugging error
#$sendkeys->log_stdout(1);
$ sendkeys - > log_stdout ( $ debug ) ;
# command to run copy.sh
my $ spawnruncopy =
"$remoteshell $node -l $to_userid /tmp/$to_userid/.ssh/copy.sh" ;
# send mkdir command
unless ( $ sendkeys - > spawn ( $ spawnruncopy ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"Unable to run $spawnruncopy." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
next ; # go to next node
}
#
#run copy.sh prompts starts here
#
2012-02-02 12:36:23 +00:00
@ result = $ sendkeys - > expect (
2011-10-15 10:34:50 +00:00
$ timeout ,
[
$ prompt1 , # Are you sure you want to ...
sub {
$ sendkeys - > send ( "yes\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt2 , # *ssword*
sub {
$ sendkeys - > send ( "$to_userpassword\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt3 , # Permission denied
sub {
$ rc = 1 ;
2011-11-17 17:10:20 +00:00
$ sendkeys - > hard_close ( ) ;
2011-10-15 10:34:50 +00:00
}
] ,
) ; # end prompts
##########################################
# Expect error - report
##########################################
if ( defined ( $ result [ 1 ] ) )
{
my $ msg = $ result [ 1 ] ;
if ( $ msg =~ /status 0/i ) { # no error
$ rc = 0 ;
} else {
2011-11-17 17:10:20 +00:00
if ( $ msg =~ /2:EOF/i ) { # no error
$ rc = 0 ;
} else {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "copy.sh:$node has error,$msg" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
$ rc = 1 ;
}
2011-10-15 10:34:50 +00:00
}
}
$ sendkeys - > soft_close ( ) ;
} # end foreach node
return $ rc ;
}
#-------------------------------------------------------------------------------
= head3 senddeviceskeys
Setup the ssh keys on the nodes
= cut
#-----------------------------------------------------------------------------
sub senddeviceskeys
{
my ( $ class , $ remoteshell , $ remotecopy , $ to_userid , $ to_userpassword , $ home , $ ssh_setup_cmd , $ nodes ) = @ _ ;
my $ sendkeys ;
my $ timeout = 10 ; # sets Expect default timeout, 0 accepts immediately
my $ sendkeys_sent = 0 ;
my $ prompt1 = 'Are you sure you want to continue connecting (yes/no)?' ;
my $ prompt2 = 'ssword:' ;
my $ prompt3 = 'Permission denied*' ;
my $ expect_log = undef ;
my $ debug = 0 ;
my $ rc = 0 ;
if ( $ ::VERBOSE )
{
$ debug = 1 ;
}
# quote the setup command and key "sshKey add \"<key\""
my $ setupcmd = "\"" ;
$ setupcmd . = $ ssh_setup_cmd ;
$ setupcmd . = " " ;
# get the public key
my $ key = "\\" ;
$ key . = "\"" ;
$ key . = `cat $home/.ssh/tmp/authorized_keys ` ;
chop ( $ key ) ;
$ key . = "\\" ;
$ key . = "\"" ;
# add to the command
$ setupcmd . = $ key ;
$ setupcmd . = "\"" ;
# For each input device
my @ nodelist = split ( /,/ , $ nodes ) ;
foreach my $ node ( @ nodelist ) {
#
# ssh to the node to run the copy.sh to setup the keys starts here
#
$ sendkeys = new Expect ;
# disable command echoing
#$sendkeys->slave->stty(qw(sane -echo));
#
# exp_internal(1) sets exp_internal debugging
# to STDERR.
#
#$sendkeys->exp_internal(1);
$ sendkeys - > exp_internal ( $ debug ) ;
#
# log_stdout(0) prevent the program's output from being shown.
# turn on if debugging error
#$sendkeys->log_stdout(1);
$ sendkeys - > log_stdout ( $ debug ) ;
# command to send key to the device
# sshKey add "key"
my $ spawnaddkey =
"$remoteshell $node -l $to_userid $setupcmd " ;
# send mkdir command
unless ( $ sendkeys - > spawn ( $ spawnaddkey ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"Unable to run $spawnaddkey." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
next ; # go to next node
}
#
#run copy.sh prompts starts here
#
my @ result = $ sendkeys - > expect (
$ timeout ,
[
$ prompt1 , # Are you sure you want to ...
sub {
$ sendkeys - > send ( "yes\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt2 , # *ssword*
sub {
$ sendkeys - > send ( "$to_userpassword\r" ) ;
$ sendkeys - > clear_accum ( ) ;
$ sendkeys - > exp_continue ( ) ;
}
] ,
[
$ prompt3 , # Permission denied
sub {
$ rc = 1 ;
$ sendkeys - > soft_close ( ) ;
next ; # go to next node
}
] ,
) ; # end prompts
##########################################
# Expect error - report
##########################################
if ( defined ( $ result [ 1 ] ) )
{
my $ msg = $ result [ 1 ] ;
if ( $ msg =~ /status 0/i ) { # no error
$ rc = 0 ;
} else {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$node has error,$msg" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
$ rc = 1 ;
next ; # go to next node
}
}
$ sendkeys - > soft_close ( ) ;
} # end foreach node
return $ rc ;
}
1 ;