Skip to content

Commit

Permalink
v6.02
Browse files Browse the repository at this point in the history
  • Loading branch information
lgastevens committed Oct 9, 2023
1 parent 789a767 commit 49b8a3d
Show file tree
Hide file tree
Showing 20 changed files with 163 additions and 92 deletions.
8 changes: 5 additions & 3 deletions AcliPm/CommandProcessing.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::CommandProcessing;
our $Version = "1.09";
our $Version = "1.10";

use strict;
use warnings;
Expand Down Expand Up @@ -345,8 +345,8 @@ sub processCommonCommand { # Process a control/embedded command which exists on
foreach my $cnd (@{$alias->{$name}{SEL}}) {
cmdOutput($db, " IF " . $cnd->{CND} . "\n THEN:\n") unless $cnd->{CND} eq 1;
cmdOutput($db, " ELSE:\n") if $cnd->{CND} eq 1;
(my $cmd = $cnd->{CMD}) =~ s/\s*;\s*/;/g;
cmdOutput($db, " " . join("\n ", split(";", $cmd)) . "\n\n");
(my $cmd = quoteCurlyMask($cnd->{CMD}, ';')) =~ s/\s*;\s*/;/g;
cmdOutput($db, " " . join("\n ", map(quoteCurlyUnmask($_, ';'), split(";", $cmd))) . "\n\n");
}
}
if ($namepat && !$matchFlag) {
Expand Down Expand Up @@ -4311,6 +4311,8 @@ sub processEmbeddedCommand { # Process an embedded command available as if on co
cmdOutput($db, "show running ||ssid [<ssid-name-list>] grep on WLAN SSIDs\n");
cmdOutput($db, "show running ||ovsdb grep on ovsdb config context\n");
cmdOutput($db, "show running ||app grep on application config context\n");
cmdOutput($db, "show running ||dhcp-server [<subnet-list>] grep on dhcp-server config context\n");
cmdOutput($db, "show running ||dhcp-srv|dhcpsrv|dhcps [<snet-list>] same as above for dhcp-server grep\n");
cmdOutput($db, "show log [-i] unwrap logfile on: ERS stackables, ISW\n");
$command = '';
};
Expand Down
3 changes: 2 additions & 1 deletion AcliPm/ConnectDisconnect.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::ConnectDisconnect;
our $Version = "1.03";
our $Version = "1.04";

use strict;
use warnings;
Expand Down Expand Up @@ -166,6 +166,7 @@ sub connectToHost { # Connect to host
saveInputBuffer($term_io); # Will clear InputBuffQueue if set
$host_io->{LoopbackConnect} = undef;
$host_io->{SessionUpTime} = time + $host_io->{SessionTimeout}*60; # Reset session inactivity timer
$host_io->{KeepAliveUpTime} = time + $host_io->{KeepAliveTimer}*60; # Reset keepalive timer
$mode->{connect_stage} = 0;

if ($host_io->{ComPort} !~ /^(?:TELNET|SSH)$/) {
Expand Down
5 changes: 3 additions & 2 deletions AcliPm/GlobalDefaults.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::GlobalDefaults;
our $Version = "1.08";
our $Version = "1.09";

use strict;
use warnings;
Expand Down Expand Up @@ -42,7 +42,8 @@ our $UnrecognizedLogins = 1; # How many unrecognized logins to let user intera
our $VarRangeUnboundMax = 299; # When capturing > $var %n- ; max range of columns to capture
our $MaxSedPatterns = 20; # We want to limit this (this default can be overridden in acli.sed file)
our $CompleteLineMarker = "\x00"; # Marker we use for complete lines on which we have to cache the last \n
our $HighlightMarker = "\x00\x00"; # Marker where for highlight text, while applying sed output patterns
our $HighlightMarkerBeg = "\x01"; # Beginning marker for highlight text, while applying sed output patterns
our $HighlightMarkerEnd = "\x02"; # Ending marker for highlight text, while applying sed output patterns
our $PseudoDefaultSelection = 'voss'; # Pseudo default selection in %PseudoSelectionAttributes hash
our $DotActivityUnbufferThreshold = 3; # Number of consecutive only dots received from host which will make us switch to unbuffered mode

Expand Down
8 changes: 5 additions & 3 deletions AcliPm/GlobalMatchingPatterns.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::GlobalMatchingPatterns;
our $Version = "1.11";
our $Version = "1.12";

use strict;
use warnings;
Expand Down Expand Up @@ -150,7 +150,7 @@ our %Grep = (
'^(?:locale)', # level2
],
PassportERS => [
'^ *(?:interface |router \w+(?:\s+r\w+)?\s*$|router vrf|route-map (?:\"[\w\d\s\.\+<>-]+\"|[\w\d\.-]+) \d+\s*$|application|i-sid \d+|wireless|logical-intf isis \d+|mgmt [\dcvo]|ovsdb\s*$)', # level0
'^ *(?:interface |router \w+(?:\s+r\w+)?\s*$|router vrf|route-map (?:\"[\w\d\s\.\+<>-]+\"|[\w\d\.-]+) \d+\s*$|application|i-sid \d+|wireless|logical-intf isis \d+|mgmt [\dcvo]|ovsdb\s*$|(?:ip )?dhcp-server subnet)', # level0
'^ *(?:route-map (?:\"[\w\d\s\.\+<>-]+\"|[\w\d\.-]+) \d+\s*$)', # level1
],
Series200 => [
Expand All @@ -174,8 +174,9 @@ our %Grep = (
Mgmt => '^(?:mgmt [\dcvo]|interface mgmtEthernet|router vrf MgmtRouter)',
Ovsdb => '^ovsdb\s*$',
Application => '^application$',
DhcpSrv => '^(?:ip )?dhcp-server ',
},
CreateContext => '^(?:route-map |ip igmp profile |i-sid \d+|logical-intf isis \d+|ipv6 dhcp guard policy |ipv6 nd raguard policy |mgmt [\dcvo])',
CreateContext => '^(?:route-map |ip igmp profile |i-sid \d+|logical-intf isis \d+|ipv6 dhcp guard policy |ipv6 nd raguard policy |mgmt [\dcvo]|dhcp-server subnet)',
ExitInstance => '^ *(?:exit|back|end)\b',
DeltaPattern => { # These patterns can capture and add to the current grep search patterns
PassportERS => {
Expand Down Expand Up @@ -288,6 +289,7 @@ our %Grep = (
'^logical-intf isis \d+ vid (?:\d+[,\-])+\d+ primary-vid \d+ (?:port \d+/\d+(?:/\d+)?|mlt \d+)(?: name "?[\w\d\._ -]+"?)?\s*\n\n?exit\s*\n',
'^mgmt (?:\d )?(?:.+)?\n\n?exit\s*\n',
'^ovsdb\s*\n\n?exit\s*\n',
'^(?:ip )?dhcp-server subnet [\d\.\/]+\s*\n\n?exit\s*\n',
],
Series200 => [
'^line \w+\s*\n\n?exit\s*\n',
Expand Down
10 changes: 5 additions & 5 deletions AcliPm/HandleBufferedOutput.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::HandleBufferedOutput;
our $Version = "1.09";
our $Version = "1.10";

use strict;
use warnings;
Expand Down Expand Up @@ -1292,17 +1292,17 @@ sub handleBufferedOutput { # Handles how ACLI releases to screen buffered output
my @hlGrep;
if ($term_io->{HLgrep}) { # Highlight is snipped before sedPatternReplace
my $hlCount = 0;
my $hlMarker = $HighlightMarker . chr($hlCount);
while ($bohLine =~ s/$term_io->{HLgrep}/$hlMarker/) {
my $hlMarker = $HighlightMarkerBeg . $hlCount . $HighlightMarkerEnd;
while ($bohLine =~ s/$term_io->{HLgrep}/$hlMarker/ && length($&)) { # Check length of replacement, to avoid going into infinite loop with 'x?' pats
push(@hlGrep, $&);
$hlMarker = $HighlightMarker . chr(++$hlCount);
$hlMarker = $HighlightMarkerBeg . ++$hlCount . $HighlightMarkerEnd;
}
}
# This is where we apply sed output colour patterns
sedPatternReplace($host_io, $term_io->{SedColourPats}, \$bohLine) if %{$term_io->{SedColourPats}};
if (@hlGrep) { # and after sedPatternReplace highlight replacement is made
for my $i (0 .. $#hlGrep) {
my $hlMarker = $HighlightMarker . chr($i);
my $hlMarker = $HighlightMarkerBeg . $i . $HighlightMarkerEnd;
$bohLine =~ s/$hlMarker/$term_io->{HLon}$hlGrep[$i]$term_io->{HLoff}/
}
}
Expand Down
30 changes: 21 additions & 9 deletions AcliPm/HandleDeviceOutput.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::HandleDeviceOutput;
our $Version = "1.11";
our $Version = "1.12";

use strict;
use warnings;
Expand Down Expand Up @@ -1183,11 +1183,15 @@ sub handleDeviceOutput { # Handles reception of output from connectyed device
elsif ($mode->{dev_del} eq 'bs' || $mode->{dev_del} eq 'bt' || $mode->{dev_del} eq 'bx') { # Remove space+backspace sequences; used by device to delete a line of output
quit(1, "ERROR: backspace count not set in 'bs' dev_del mode", $db) unless $host_io->{BackspaceCount};
my $keepOutput;
if ($host_io->{Type} eq 'Ipanema' && $mode->{dev_del} eq 'bt' && $$outRef =~ s/^\cG\x0d\e\[\d+C([^\x00\x0d\n\cH\e]*)$/$1/) {
# Ipanema: eth<tab> get back bell + "-diag"; same for other ? commands
print "\cG" unless length $1;
$host_io->{BackspaceCount} = 3 - length $1; # The length will always need to be 3: \e\[19C\e\[K\x00\x00\x00
debugMsg(2,"PreAdjustingTabExpansion-ipanema:>", $outRef, "<\n");
if ($host_io->{Type} eq 'Ipanema' && $mode->{dev_del} eq 'bt') {
if ($$outRef =~ s/^\cG?\x0d\e\[\d+C([^\x00\x0d\n\cH\e]+)/$1/) {
# Ipanema: eth<tab> get back bell + "-diag"; same for other ? commands
print "\cG" unless length $1;
debugMsg(2,"PreAdjustingTabExpansion-ipanema:>", $outRef, "<\n");
}
if ($$outRef =~ s/^[^\x00\x0d\n\cH\e]*([^\x00\x0d\n\cH\e])\K\x0d\g{1}//) {
debugMsg(2,"PreAdjustingTabExpansion2-ipanema:>", $outRef, "<\n");
}
}
else {
print "\cG" if $$outRef =~ s/^\cG//; # Pass it on; PPCLI show sn<tab>
Expand Down Expand Up @@ -1262,6 +1266,9 @@ sub handleDeviceOutput { # Handles reception of output from connectyed device
}
debugMsg(2,"BackSpaceMode-OutputToCheckForBackspaces:\n>", $outRef, "<\n");
}
if ($host_io->{Type} eq 'Ipanema' && $mode->{dev_del} eq 'bt' && $$outRef =~ s/^\e\[A[^\x00\x0d\n\cH\e]+\e\[K\n//) {
debugMsg(2,"AvoidSafetyEscape-ipanema:>", $outRef, "<\n");
}
debugMsg(2,"BackspaceExpectedCount = $host_io->{BackspaceCount}\n");
my $bcntminus1 = $host_io->{BackspaceCount} - 1;
if ( (
Expand Down Expand Up @@ -1319,9 +1326,11 @@ sub handleDeviceOutput { # Handles reception of output from connectyed device
) || (
$host_io->{Type} eq 'Ipanema' &&
(
$$outRef =~ s/^\x0d\e\[K\e\[A$prompt->{Match}// ||
$$outRef =~ s/^\e\[$host_io->{BackspaceCount}D(?:\e\[K)?// ||
$$outRef =~ s/^\x0d\e\[19C\e\[K\x00{$host_io->{BackspaceCount}}// ||
$$outRef =~ s/^\cH{$host_io->{BackspaceCount}}\e\[K//
$$outRef =~ s/^\x0d\e\[\d+C\e\[K\x00{3,}// ||
$$outRef =~ s/^\cH{$host_io->{BackspaceCount}}\e\[K// ||
$$outRef =~ s/^\x0d$prompt->{Match}\e\[K//
)
)
) {
Expand Down Expand Up @@ -1563,6 +1572,9 @@ sub handleDeviceOutput { # Handles reception of output from connectyed device
elsif ($host_io->{Type} eq 'Wing' && $$outRef =~ s/^\e\[K//) { # Output might get preceded with \e[K if tab expansion was used in previous command
debugMsg(2,"Wing-tab-reformatting:\n>", $outRef, "<\n");
}
elsif ($host_io->{Type} eq 'Ipanema' && $$outRef =~ s/^[^\x00\x0d\n\cH\e]*([^\x00\x0d\n\cH\e])\K\x0d\g{1}//) {
debugMsg(2,"Ipanema-tab-reformatting:\n>", $outRef, "<\n");
}
my $tabSynMode = $TabSynMode{$host_io->{Type}}[$term_io->{AcliType}]&3;
debugMsg(2,"TabSynMode = ", \$tabSynMode, "\n");
if ($tabSynMode == 3) { # Ensure we have a prompt in the output + tail match (ERS & VSP)
Expand Down Expand Up @@ -1601,7 +1613,7 @@ sub handleDeviceOutput { # Handles reception of output from connectyed device
debugMsg(2,"ConvertingTab-to-Syntax with output:\n>", $outRef, "<\n");
redo; # Fall through to 'sx' processing below
}
if ($$outRef =~ s/\e.*$//) {
if ($host_io->{Type} eq 'ExtremeXOS' && $$outRef =~ s/\e.*$//) {
# On XOS, long commands, we see a \eE appended : configure lldp ports all advertise vendor-specific med policy application voice vlan Default E
debugMsg(2,"outRef after removing esc-E appended:\n>", $outRef, "<\n");
}
Expand Down
29 changes: 24 additions & 5 deletions AcliPm/InputProcessing.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::InputProcessing;
our $Version = "1.09";
our $Version = "1.10";

use strict;
use warnings;
Expand Down Expand Up @@ -525,6 +525,9 @@ sub prepGrepStructure { # Process grep string and setup grep structure according
push(@{$grep->{Instance}}, 'Vrf');
push(@{$grep->{RangeList}}, undef);
debugMsg(1,"-> Grep-Instance : set to Vrf\n");
# Allow Perl's metacharacters {}[]()^$.|*+?\ and backslash the rest
$grepString =~ s/([\/])/\\$1/g;
debugMsg(1,"-> Grep-String-after-backslashing : >", \$grepString, "<\n");
$grepString =~ s/^vrf\s+/vrf /i;
if ($grepString =~ s/^vrf ((?:[^,]+,)+[^,]+)$/vrf (?:$1)(?:\\s|\$)/i) {
$grepString =~ s/,/|/g;
Expand All @@ -533,9 +536,6 @@ sub prepGrepStructure { # Process grep string and setup grep structure according
$grepString =~ s/^vrf (.*)/vrf $1(?:\\s|\$)/i;
}
debugMsg(1,"-> Grep-String-Formatted : >", \$grepString, "<\n");
# Allow Perl's metacharacters {}[]()^$.|*+?\ and backslash the rest
$grepString =~ s/([\/])/\\$1/g;
debugMsg(1,"-> Grep-String-after-backslashing : >", \$grepString, "<\n");
}
elsif ($grepAdv && !$grepQuotes && $grepString =~ /^route-map(?:\s+((?:\S+,)*\S+))?$/i) { # Route-map
push(@{$grep->{Instance}}, 'RouteMap');
Expand All @@ -551,7 +551,7 @@ sub prepGrepStructure { # Process grep string and setup grep structure according
$grepString =~ s/^route-map .*$/route-map \.*?$matchString/i;
}
debugMsg(1,"-> Grep-String-Formatted : >", \$grepString, "<\n");
# Allow Perl's metacharacters {}[]()^$.|*+?\ and backslash the rest
# Allow Perl's metacharacters {}[]()^$.|*+?\ and backslash the rest - at the end so also applies to $matchString
$grepString =~ s/([\/])/\\$1/g;
debugMsg(1,"-> Grep-String-after-backslashing : >", \$grepString, "<\n");
}
Expand Down Expand Up @@ -658,6 +658,25 @@ sub prepGrepStructure { # Process grep string and setup grep structure according
}
debugMsg(1,"-> Grep-String-Formatted : >", \$grepString, "<\n");
}
elsif ($grepAdv && !$grepQuotes && $grepString =~ /^(?:dhcp-serv(?:er?)?|dhcp-?s(?:[er][rv]?)?)(?:\s+((?:\S+,)*\S+))?$/i) { # DHCP Server
push(@{$grep->{Instance}}, 'DhcpSrv');
push(@{$grep->{RangeList}}, undef);
debugMsg(1,"-> Grep-Instance : set to DhcpSrv\n");
my $matchString = defined $1 ? quoteCurlyUnmask($1, ' ') : '';
$matchString =~ s/[\'\"]//g; # Remove all and any quotes
$grepString =~ s/^(?:dhcp-serv(?:er?)?|dhcp-?s(?:[er][rv]?)?)/dhcp-server/i;
$grepString =~ s/^dhcp-server\s+/dhcp-server /i;
if ($grepString =~ s/^dhcp-server (?:[^,]+,)+[^,]+$/dhcp-server \.*?(?:$matchString)/i) {
$grepString =~ s/,/|/g;
}
else {
$grepString =~ s/^dhcp-server .*$/dhcp-server \.*?$matchString/i;
}
debugMsg(1,"-> Grep-String-Formatted : >", \$grepString, "<\n");
# Allow Perl's metacharacters {}[]()^$.|*+?\ and backslash the rest - at the end so also applies to $matchString
$grepString =~ s/([\/])/\\$1/g;
debugMsg(1,"-> Grep-String-after-backslashing : >", \$grepString, "<\n");
}
elsif ($grepAdv && !$grepQuotes && $host_io->{Type} eq 'WLAN9100' && $grepString =~ /^ssid(?:\s+(\S+))?$/i) { # SSID list or range
push(@{$grep->{Instance}}, 'Ssid');
push(@{$grep->{RangeList}}, undef);
Expand Down
6 changes: 3 additions & 3 deletions AcliPm/Logging.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::Logging;
our $Version = "1.02";
our $Version = "1.03";

use strict;
use warnings;
Expand All @@ -17,7 +17,7 @@ use AcliPm::GlobalDefaults;

sub closeLogFile { # Handles closing log file
my $script_io = shift;
printf { $script_io->{LogFH} } "\n=~=~=~=~=~=~=~=~=~=~= %s log %s =~=~=~=~=~=~=~=~=~=~=\n", $ScriptName, scalar localtime;
printf { $script_io->{LogFH} } "\n=~=~=~=~=~=~=~=~=~=~= %s CLOSE log %s =~=~=~=~=~=~=~=~=~=~=\n", $ScriptName, scalar localtime;
close $script_io->{LogFH};
$script_io->{LogFile} = $script_io->{LogFH} = undef;
}
Expand Down Expand Up @@ -78,7 +78,7 @@ sub openLogFile { # Handles opening log file
}
}
if ( open($script_io->{LogFH}, $script_io->{OverWrite}, $logfile) ) {
printf { $script_io->{LogFH} } "\n=~=~=~=~=~=~=~=~=~=~= %s log %s =~=~=~=~=~=~=~=~=~=~=\n", $ScriptName, scalar localtime;
printf { $script_io->{LogFH} } "\n=~=~=~=~=~=~=~=~=~=~= %s OPEN log %s =~=~=~=~=~=~=~=~=~=~=\n", $ScriptName, scalar localtime;
$script_io->{AutoLogFail} = 0 if $script_io->{AutoLog};
return 1; # File opened successfully
}
Expand Down
9 changes: 7 additions & 2 deletions AcliPm/ParseCommand.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::ParseCommand;
our $Version = "1.09";
our $Version = "1.10";

use strict;
use warnings;
Expand All @@ -14,6 +14,7 @@ use AcliPm::CommandStructures;
use AcliPm::DebugMessage;
use AcliPm::GlobalConstants;
use AcliPm::GlobalMatchingPatterns;
use AcliPm::MaskUnmaskChars;
use AcliPm::TabExpand;


Expand Down Expand Up @@ -566,7 +567,11 @@ sub mergeCommand { # Updates the parsed command hash with a new command update
# - apply forloop order: cmdParse, updateParsed(except if semicln list)

my @updatedParsed;
my @updatedCmdList = length $updatedCmd ? split(/[^\\]\K;\s*/, $updatedCmd) : (''); # Split the command into sections, if semicolon fragmented
my @updatedCmdList = ('');
if (length $updatedCmd) {
$updatedCmd = quoteCurlyMask($updatedCmd, ';'); # Mask semi-colons inside quotes/brackets/etc..
@updatedCmdList = map(quoteCurlyUnmask($_, ';'), split(/[^\\]\K;\s*/, $updatedCmd)); # Split the command into sections, if semicolon fragmented
}
my $colonMarkersExist = scalar @updatedCmdList && scalar grep {/:$/} @updatedCmdList;
debugMsg(4,"=mergeCommand: colonMarkersExist\n") if $colonMarkersExist;
my %turnIntoAppend;
Expand Down
2 changes: 1 addition & 1 deletion AcliPm/Version.pm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ACLI sub-module
package AcliPm::Version;
our $VERSION = "6.01"; # This version is the ACLI release version
our $VERSION = "6.02"; # This version is the ACLI release version

use strict;
use warnings;
Expand Down
17 changes: 17 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -1248,3 +1248,20 @@ Revision history for acli.pl
* Control ACLI> interface was not able to set debug level > 999
* More paging output with error patters was producing unexpected lines between --more-- prompts
* Script xmcacli (v1.17) updated with missing XMC family "200 Series" for Series200 support
6.02 2023-10-09
* Uses Control::CLI version 2.11 and Control::CLI::Extreme version 1.10
* More fixes around CLI tab expanson support for SD-WAN Ipanema family type
* Doing a highlight string (cmd ^ string) where there were more than 40 matches of that string in the output would
crash ACLI
* Doing a highlight string (cmd ^ string) with a string ending with '?' would hang ACLI
* Added new VOSS9.0 "ip dhcp-server" context for grep of show running config
* When reconnecting to a VOSS switch, which was factory defaulted and prompts to set the username password, the
keepalive function was kicking in and preventing user from actually providing the new password. As a workaround one
had to force a reconnect and then it was possible to provide the new password and login. Now the keepalive timer
is reset on every new connection, as should have always been the case.
* When logging to file, time stamp lines now indicate if logging file was closed or opened
* List variable assignment $var[] = (val1; val2) was not handled correctly if used in alias file
* Using serial port on Silicon Labs CP210x USB cable (for universal hardware USB port) was failing with error:
invalid COMMPROP block length= 66 at C:/Strawberry/perl/site/lib/Control/CLI.pm line 296
* Update script updated to be able to use HTTPS to fetch updates and now only fetches updates from github.com
* VOSS .tgz/.voss image files are highlighted now in ls output of switch file system
Loading

0 comments on commit 49b8a3d

Please sign in to comment.