Control-CLI-Extreme
view release on metacpan or search on metacpan
lib/Control/CLI/Extreme.pm view on Meta::CPAN
($args{username}, $args{password}, $args{read_attempts}, $args{wake_console},
$args{prompt_credentials}, $args{data_with_error}, $args{timeout}, $args{errmode}) = @_;
}
# In which case we need to setup the poll structure for them here (the main poll structure remains unchanged)
$self->{POLL}{$pollsub} = { # Populate structure with method arguments/storage
# Set method argument keys
username => defined $args{username} ? $args{username} : $self->{USERNAME},
password => defined $args{password} ? $args{password} : $self->{PASSWORD},
prompt_credentials => defined $args{prompt_credentials} ? $args{prompt_credentials} : $self->{prompt_credentials},
read_attempts => defined $args{read_attempts} ? $args{read_attempts} : $LoginReadAttempts,
data_with_error => defined $args{data_with_error} ? $args{data_with_error} : $self->{data_with_error},
wake_console => defined $args{wake_console} ? $args{wake_console} : $self->{$Package}{wake_console},
non_recognized_login => defined $args{non_recognized_login} ? $args{non_recognized_login} : $NonRecognizedLogin,
generic_login => defined $args{generic_login} ? $args{generic_login} : $GenericLogin,
# Declare method storage keys which will be used
stage => 0,
login_attempted => undef,
password_sent => undef,
login_error => '',
family_type => undef,
cpu_slot => undef,
detectionFromPrompt => undef,
# Declare keys to be set if method called from another polled method
errmode => $args{errmode},
};
# Cache poll structure keys which this method will use
$self->poll_struct_cache($pollsub, $args{timeout});
}
my $login = $self->{POLL}{$pollsub};
local $self->{errmode} = $login->{errmode} if defined $login->{errmode};
return $self->poll_return($self->error("$pkgsub: No connection to login to")) if $self->eof;
my $usernamePrompt = $self->username_prompt;
my $passwordPrompt = $self->password_prompt;
if ($login->{stage} < 1) { # Initial loginstage & setup - do only once
$login->{stage}++; # Ensure we don't come back here in non-blocking mode
if ($self->{LOGINSTAGE}) {
$login->{family_type} = $self->{$Package}{ATTRIB}{'family_type'}; # Might be already set from previous login attempt
}
else { # Flush all attributes, as we assume we are connecting to a new device
$self->{$Package}{ATTRIB} = undef;
$self->{$Package}{ATTRIBFLAG} = undef;
}
# Handle resuming previous login attempt
if ($self->{LOGINSTAGE} eq 'username' && $login->{username}) { # Resume login from where it was left
$self->print(line => $login->{username}, errmode => 'return')
or return $self->poll_return($self->error("$pkgsub: Unable to send username // ".$self->errmsg));
$self->{LOGINSTAGE} = '';
$login->{login_attempted} = 1;
}
elsif ($self->{LOGINSTAGE} eq 'password' && $login->{password}) { # Resume login from where it was left
$self->print(line => $login->{password}, errmode => 'return')
or return $self->poll_return($self->error("$pkgsub: Unable to send password // ".$self->errmsg));
$self->{LOGINSTAGE} = '';
$login->{login_attempted} = 1;
}
elsif ($self->console && $login->{wake_console}) {
$self->debugMsg(8,"\nlogin() Sending wake_console sequence >$login->{wake_console}<\n");
$self->put(string => $login->{wake_console}, errmode => 'return') # Bring connection into life
or return $self->poll_return($self->error("$pkgsub: Unable to send bring alive character sequence // ".$self->errmsg));
}
}
if ($login->{stage} < 2) { # Main login loop
my ($pattern, $patdepth, $deepest);
my ($promptType, $capturedPrompt, $switchName, $cliType, $configContext);
LOGINLOOP: while (1) {
# Wait until we have read in all available data
my $ok = $self->poll_readwait($pkgsub, 1, $login->{read_attempts}, $ReadwaitTimer, $login->{login_error}.'Failed reading login prompt', $login->{data_with_error});
return $self->poll_return($ok) unless $ok; # Come out if error (if errmode='return'), or if nothing to read in non-blocking mode
$self->debugMsg(8,"\nlogin() Connection input to process:\n>", \$self->{POLL}{read_buffer}, "<\n");
$self->{POLL}{output_buffer} .= $self->{POLL}{read_buffer}; # This buffer preserves all the output, in case it is requested
$self->{POLL}{local_buffer} = $self->{POLL}{read_buffer} =~ /\n/ ? '' : stripLastLine(\$self->{POLL}{local_buffer}); # Flush or keep lastline
$self->{POLL}{local_buffer} .= $self->{POLL}{read_buffer}; # If read was single line, this buffer appends it to lastline from previous read
# Pattern matching; try and detect patterns, and record their depth in the input stream
$pattern = '';
$deepest = -1;
foreach my $key (keys %LoginPatterns) {
if (($patdepth = rindex($self->{POLL}{read_buffer}, $LoginPatterns{$key})) >= 0) { # We have a match
$self->debugMsg(8,"\nlogin() Matched pattern $key @ depth $patdepth\n");
unless ($login->{family_type}) { # Only if family type not already detected
# If a banner is seen, try and extract attributes from it also
if ($key eq 'banner' || $key eq 'menu' || $key eq 'submenu') {
$login->{family_type} = $Prm{bstk};
$self->debugMsg(8,"login() Detected family_type = $login->{family_type}\n");
$self->_setFamilyTypeAttrib($login->{family_type}, is_nncli => 1);
if ($key eq 'banner') {
$self->{POLL}{read_buffer} =~ /\*\*\* ((?:[^\*\n]+?) (?:Switch|Controller|Platform) (?:WC)?\d+.*?)\s+/ &&
$self->_setModelAttrib($1);
$self->{POLL}{read_buffer} =~ /FW:([\d\.]+)\s+SW:v([\d\.]+)/ && do {
$self->_setAttrib('fw_version', $1);
$self->_setAttrib('sw_version', $2);
};
}
}
elsif ($key eq 'srbanner') {
$login->{family_type} = $Prm{sr};
$self->debugMsg(8,"login() Detected family_type = $login->{family_type}\n");
$self->_setFamilyTypeAttrib($login->{family_type}, is_nncli => 1);
$self->{POLL}{read_buffer} =~ /\((Secure Router \d+)\)/ && $self->_setModelAttrib($1);
$self->{POLL}{read_buffer} =~ /Version: (.+)/ && $self->_setAttrib('sw_version', $1);
}
elsif ($key eq 'xlrbanner') {
$login->{family_type} = $Prm{xlr};
$self->debugMsg(8,"login() Detected family_type = $login->{family_type}\n");
$self->_setFamilyTypeAttrib($login->{family_type}, is_nncli => 0);
$self->{POLL}{read_buffer} =~ /\* Software Release (?i:v|REL)?(.+?) / && $self->_setAttrib('sw_version', $1);
}
elsif ($key eq 'ersbanner' || $key eq 'passportbanner' || $key eq 'pp1600banner') {
$login->{family_type} = $Prm{pers};
$self->debugMsg(8,"login() Detected family_type = $login->{family_type}\n");
$self->_setFamilyTypeAttrib($login->{family_type}, is_nncli => 0);
$self->{POLL}{read_buffer} =~ /\* Software Release (?i:v|REL)?(.+?) / && $self->_setAttrib('sw_version', $1);
}
elsif ($key eq 'vspbanner' || $key eq 'fabengbanner') {
$login->{family_type} = $Prm{pers};
$self->debugMsg(8,"login() Detected family_type = $login->{family_type}\n");
$self->_setFamilyTypeAttrib($login->{family_type}, is_nncli => 1);
$self->{POLL}{read_buffer} =~ /(?:Software(?: Release)?|Fabric Engine) Build (.+?) / && $self->_setAttrib('sw_version', $1);
( run in 1.558 second using v1.01-cache-2.11-cpan-39bf76dae61 )