The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Control::CLI::Extreme - Interact with CLI of Extreme Networking products over any of Telnet, SSH or Serial port

SYNOPSIS

        use Control::CLI::Extreme;

Connecting with Telnet

        # Create the object instance for Telnet
        $cli = new Control::CLI::Extreme('TELNET');
        # Connect to host
        $cli->connect(  Host            => 'hostname',
                        Username        => $username,
                        Password        => $password,
                     );

Connecting with SSH - password authentication

        # Create the object instance for SSH
        $cli = new Control::CLI::Extreme('SSH');
        # Connect to host
        $cli->connect(  Host            => 'hostname',
                        Username        => $username,
                        Password        => $password,
                     );

Connecting with SSH - publickey authentication

        # Create the object instance for SSH
        $cli = new Control::CLI::Extreme('SSH');
        # Connect to host
        $cli->connect(  Host            => 'hostname',
                        Username        => $username,
                        PublicKey       => '.ssh/id_dsa.pub',
                        PrivateKey      => '.ssh/id_dsa',
                        Passphrase      => $passphrase,
                     );

Connecting via Serial port

        # Create the object instance for Serial port e.g. /dev/ttyS0 or COM1
        $cli = new Control::CLI::Extreme('COM1');
        # Connect to host
        $cli->connect(  BaudRate        => 9600,
                        Parity          => 'none',
                        DataBits        => 8,
                        StopBits        => 1,
                        Handshake       => 'none',
                        Username        => $username,
                        Password        => $password,
                     );

Sending commands once connected and disconnecting

        $cli->enable;

        # Configuration commands
        $cli->return_result(1);
        $cli->cmd('config terminal') or die $cli->last_cmd_errmsg;
        $cli->cmd('no banner') or die $cli->last_cmd_errmsg;
        $cli->cmd('exit') or die $cli->last_cmd_errmsg;

        # Show commands
        $cli->device_more_paging(0);
        $cli->return_result(0);
        $config = $cli->cmd('show running-config');
        die $cli->last_cmd_errmsg unless $cli->last_cmd_success;
        print $config;

        $cli->disconnect;

Configuring multiple Extreme Networking products simultaneously in non-blocking mode

        use Control::CLI::Extreme qw(poll);             # Export class poll method

        sub hostError { # Prepend hostname before error its cli object generated
                my ($host, $errmsg) = @_;
                die "\n$host -> $errmsg"; 
        }

        sub bulkDo { # Repeat for all hosts
                my ($cliHashRef, $method, $argsRef) = @_;
        
                foreach my $host (keys %$cliHashRef) { # Call $method for every object
                        my $codeRef = $cliHashRef->{$host}->can($method);
                        $codeRef->($cliHashRef->{$host}, @$argsRef);
                }
                poll(   # Poll all objects for completion of $method
                        Object_list     =>      $cliHashRef,
                        Poll_code       =>      sub { local $| = 1; print '.' },
                );
                print " done!\n";
        
                if ($method =~ /^cmd/) { # Check that command was accepted
                        foreach my $host (keys %$cliHashRef) {
                                unless ($cliHashRef->{$host}->last_cmd_success) {
                                        print "\n- $host error:\n", $cliHashRef->{$host}->last_cmd_errmsg, "\n\n";
                                }
                        }
                }
        }

        # Create and Connect all the object instances
        foreach my $host (@DeviceIPs) {
                $cli{$host} = new Control::CLI::Extreme(
                        Use             => 'SSH',               # or TELNET (or lots of serial ports!)
                        Blocking        => 0,                   # Use non-blocking mode
                        Errmode         => [\&hostError, $host],# Error handler will add host-ip to msg
                );
                $cli{$host}->connect(
                        Host            =>      $host,
                        Username        =>      $username,
                        Password        =>      $password,
                );
        }
        print "Connecting to all hosts ";
        poll(   # Poll all objects for completion of connect
                Object_list     =>      \%cli,
                Poll_code       =>      sub { local $| = 1; print '.' },
        );
        print " done!\n";

        print "Entering PrivExec on all hosts ";
        bulkDo(\%cli, 'enable');

        print "Entering Config mode on all hosts ";
        bulkDo(\%cli, 'cmd', ['config terminal']);

        print "Pushing config command on all hosts ";
        bulkDo(\%cli, 'cmd', ['snmp-server contact Jack']);

        print "Disconnecting from all hosts ";
        bulkDo(\%cli, 'disconnect');

DESCRIPTION

Control::CLI::Extreme is a sub-class of Control::CLI allowing CLI interaction customized for Extreme (including ex-Avaya/ex Nortel Enterprise) Networking products over any of Telnet, SSH or Serial port. It is a drop in replacement for the Control::CLI::AvayaData module following the transfer of the Avaya Data business unit to Extreme Networks. This class supports all of Extreme Summit, Virtual Services Platform (VSP), Private Label Switches (APLS DSG BoxTypes), Ethernet Routing Switch (ERS) and ex-Nortel Enterprise (Bay Networks heritage) platforms. Currently supported devices:

  • VSP XA-1x00, 4x00, 7x00, 8x00, 9000

  • XOS Summit switches

  • Unified Hardware 5520

  • ERS models 2500, 3x00, 4x00, 5x00

  • Wireless Wing APs and Controllers

  • SLX Data Center switches

  • ISW industrial switches

  • Series200 models 210, 220

  • ERS/Passport models 1600, 8300, 8600, 8800

  • APLS DSG models 6248, 7648, 7480, 8032, 9032

  • SR models 2330, 4134

  • WLAN 91xx

  • WLAN(WC) 81x0

  • WLAN(WSS) 2350, 236x, 238x

  • BPS 2000, ES 460, ES 470

  • Baystack models 325, 425

  • Accelar/Passport models 1000, 1100, 1200

The devices supported by this module can have an inconsistent CLI (in terms of syntax, login sequences, terminal width-length-paging, prompts) and in some cases two separate CLI syntaxes are available on the same product. This class is written so that all the above products can be CLI scripted in a consistent way regardless of their underlying CLI variants. The CLI commands themselves might still vary across the different products though, even here, for certain common functions (like entering privExec mode or disabling terminal more paging) a generic method is provided by this class.

Control::CLI::Extreme is a sub-class of Control::CLI (which is required) and therefore the above functionality can also be performed in a consistent manner regardless of the underlying connection type which can be any of Telnet, SSH or Serial port connection. For SSH, only SSHv2 is supported with either password or publickey authentication. Furthermore this module leverages the non-blocking capaility of Control::CLI version 2.00 and is thus capable of operating in a non-blocking fashion for all its methods so that it can be used to drive multiple Extreme devices simultaneously without resorting to Perl threads (see examples directory).

Other refinements of this module over and above the basic functionality of Control::CLI are:

  • On the stackable BaystackERS products the connect & login methods will automatically steer through the banner and menu interface (if seen) to reach the desired CLI interface.

  • There is no need to set the prompt string in any of this module's methods since it knows exactly what to expect from any of the supported Extreme products. Furthermore the prompt string is automatically internally set to match the actual prompt of the connected device (rather than using a generic regular expression such as '*[#>]$'). This greatly reduces the risk that the generic regular expression might trigger on a fake prompt embedded in the output stream from the device.

  • The connect method of this module automatically takes care of login for Telnet and Serial port access (where authentication is not part of the actual connection, unlike SSH) and so provides a consistent scripting approach whether the underlying connection is SSH or either Telnet or Serial port.

  • Automatic handling of output paged with --more-- prompts, including the ability to retrieve an exact number of pages of output.

  • A number of attributes are made available to find out basic information about the connected Extreme device.

  • Ability to detect whether a CLI command generated an error on the remote host and ability to report success or failure of the issued command as well as the error message details.

Note that all the extra functionality that this module offers over and above Control::CLI, is only possible if connected to an Extreme (or ex Avaya/Nortel) device. To make sure that the connected device is supported, the family_type attribute can be inspected to make sure it is not set to 'generic'; see attribute().

In the syntax layout below, square brackets [] represent optional parameters. All Control::CLI::Extreme method arguments are case insensitive.

OBJECT CONSTRUCTOR

Used to create an object instance of Control::CLI::Extreme

new() - create a new Control::CLI::Extreme object
  $obj = new Control::CLI::Extreme ('TELNET'|'SSH'|'<COM_port_name>');

  $obj = new Control::CLI::Extreme (

        # same as in Control::CLI :
        Use                      => 'TELNET'|'SSH'|'<COM_port_name>',
        [Timeout                 => $secs,]
        [Connection_timeout      => $secs,]
        [Errmode                 => $errmode,]
        [Errmsg_format           => $msgFormat,]
        [Return_reference        => $flag,]
        [Prompt                  => $prompt,]
        [Username_prompt         => $usernamePrompt,]
        [Password_prompt         => $passwordPrompt,]
        [Input_log               => $fhOrFilename,]
        [Output_log              => $fhOrFilename,]
        [Dump_log                => $fhOrFilename,]
        [Blocking                => $flag,]
        [Prompt_credentials      => $flag,]
        [Read_attempts           => $numberOfReadAttemps,]
        [Readwait_timer          => $millisecs,]
        [Data_with_error         => $flag,]
        [Read_block_size         => $bytes,]
        [Output_record_separator => $ors,]
        [Terminal_type           => $string,]
        [Window_size             => [$width, $height],]
        [Report_query_status     => $flag,]
        [Debug                   => $debugFlag,]

        # added in Control::CLI::Extreme :
        [Return_result           => $flag,]
        [More_paging             => $numberOfPages,]
        [Cmd_confirm_prompt      => $string,]
        [Cmd_initiated_prompt    => $string,]
        [Cmd_feed_timeout        => $value,]
        [Console                 => $string,]
        [Wake_console            => $string,]
        [Debug_file              => $fhOrFilename,]
  );

This is the constructor for Control::CLI::Extreme objects. A new object is returned on success. On failure the error mode action defined by "errmode" argument is performed. If the "errmode" argument is not specified the default is to croak. See errmode() for a description of valid settings. The first parameter, or "use" argument, is required and should take value either "TELNET" or "SSH" (case insensitive) or the name of the Serial port such as "COM1" or "/dev/ttyS0". The other arguments are optional and are just shortcuts to methods of the same name. The Control::CLI::Extreme constructor accpets all arguments supported by the Control::CLI constructor (which are passed to it) and defines some new arguments specific to itself.

OBJECT METHODS

Methods which can be run on a previously created Control::CLI::Extreme instance

Main I/O Object Methods

connect() & connect_poll() - connect to host
  $ok = $obj->connect("$host[ $port]");

  ($ok, $output || $outputRef) = $obj->connect("$host[ $port]");

  $ok = $obj->connect(
        [Host                   => $host,]
        [Port                   => $port,]
        [Username               => $username,]
        [Password               => $password,]
        [PublicKey              => $publicKey,]
        [PrivateKey             => $privateKey,]
        [Passphrase             => $passphrase,]
        [Prompt_credentials     => $flag,]
        [BaudRate               => $baudRate,]
        [ForceBaud              => $flag,]
        [Parity                 => $parity,]
        [DataBits               => $dataBits,]
        [StopBits               => $stopBits,]
        [Handshake              => $handshake,]
        [Timeout                => $secs,]
        [Connection_timeout     => $secs,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Blocking               => $flag,]
        [Errmode                => $errmode,]
        [Terminal_type          => $string,]
        [Window_size            => [$width, $height],]
        [Callback               => \&codeRef,]
        [Atomic_connect         => $flag,]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

  ($ok, $output || $outputRef) = $obj->connect(
        [Host                   => $host,]
        [Port                   => $port,]
        [Username               => $username,]
        [Password               => $password,]
        [PublicKey              => $publicKey,]
        [PrivateKey             => $privateKey,]
        [Passphrase             => $passphrase,]
        [Prompt_credentials     => $flag,]
        [BaudRate               => $baudRate,]
        [ForceBaud              => $flag,]
        [Parity                 => $parity,]
        [DataBits               => $dataBits,]
        [StopBits               => $stopBits,]
        [Handshake              => $handshake,]
        [Timeout                => $secs,]
        [Connection_timeout     => $secs,]
        [Return_reference       => $flag,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Blocking               => $flag,]
        [Errmode                => $errmode,]
        [Terminal_type          => $string,]
        [Window_size            => [$width, $height],]
        [Callback               => \&codeRef,]
        [Atomic_connect         => $flag,]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

Polling method (only applicable in non-blocking mode):

  $ok = $obj->connect_poll();

  ($ok, $output || $outputRef) = $obj->connect_poll();

This method connects to the host device. The connection will use either Telnet, SSH or Serial port, depending on how the object was created with the new() constructor. On success a true (1) value is returned. On time-out or other connection failures the error mode action is performed. See errmode(). In the first & third forms only a success/failure value is returned in scalar context, while in the second & fourth forms, in list context, both the success/failure value is returned as well as any output received from the host device during the connect/login sequence; the latter is either the output itself or a reference to that output, depending on the object setting of return_reference or the argument override provided in this method.

This method overrides Control::CLI::connect() and calls both the Control::CLI::connect() method as well as the login() method from this class. This allows the connect() method to seamlessly handle connection and login for both SSH (which normally handles authentication as part of the connection process) and Telnet and Serial port access (for which authentication needs to be dealt with after connection). In short, by calling the connect() method it is not necessary to call the login() method afterwards.

In non-blocking mode (blocking disabled) the connect() method will immediately return with a false, but defined, value of 0. You will then need to call the connect_poll() method at regular intervals until it returns a true (1) value indicating that the connection and login is complete. Note that for this method to work (with TELNET or SSH) in non-blocking mode IO::Socket::IP needs to be installed (IO::Socket:INET will always produce a blocking TCP socket setup).

The "host" argument is required by both Telnet and SSH. All the other arguments are optional. If username/password or SSH Passphrase are not provided but are required and prompt_credentials is true, the method will automatically prompt the user for them; otherwise the error mode action is performed. The "errmode" argument is provided to override the global setting of the object error mode action. See errmode(). The "prompt_credentials" argument is provided to override the global setting of the parameter by the same name which is by default false. See prompt_credentials(). The "read_attempts" argument is simply fed to the login() method. See login(). The "connection_timeout" argument can be used to set a connection timeout when establishing Telnet and SSH TCP connections; this is fed to Control::CLI::connect(). Whereas the "timeout" argument is the normal timeout used for reading the connection once established; this is fed to login(). The "terminal_type" and "window_size" arguments are Control::CLI arguments and are not overrides, they will change the object parameter as these settings are only applied during a connection. It is not necessary to set these for Extreme devices. Which other arguments are used depends on the whether the object was created for Telnet, SSH or Serial port.

  • For Telnet, these arguments are used:

      $ok = $obj->connect("$host[ $port]");
    
      $ok = $obj->connect(
            Host                    => $host,
            [Port                   => $port,]
            [Username               => $username,]
            [Password               => $password,]
            [Prompt_credentials     => $flag,]
            [Timeout                => $secs,]
            [Connection_timeout     => $secs,]
            [Read_attempts          => $numberOfLoginReadAttemps,]
            [Data_with_error        => $flag,]
            [Wake_console           => $string,]
            [Blocking               => $flag,]
            [Errmode                => $errmode,]
            [Terminal_type          => $string,]
            [Window_size            => [$width, $height],]
            [Atomic_connect         => $flag,]
            [Non_recognized_login   => $flag,]
            [Generic_login          => $flag,]
      );

    If not specified, the default port number for Telnet is 23. The wake_console argument is only relevant when connecting to a Telnet port other than 23 (i.e. to a Terminal Server device) or if console() has been manually set; see console(). In which case, the login() method, which is called by connect(), will automatically send the wake_console string sequence to the attached device to alert it of the connection. The default sequence will work across all Extreme Networking products but can be overridden by using the wake_console argument. See wake_console(). Another reason to use the wake_console is when connecting via Telnet to an XOS switch which is configured with a 'before-login' banner which has to be acknowledged. In this case the XOS switch will not request a login until the user has hit a key. In this case make sure to set the Console argument to 1 in the object constructor (the default wake_console string '\n' will then be sent and there is no need to specify a different wake_console string in the connect() method).

  • For SSH, these arguments are used:

      $ok = $obj->connect("$host[ $port]");
    
      $ok = $obj->connect(
            Host                    => $host,
            [Port                   => $port,]
            [Username               => $username,]
            [Password               => $password,]
            [PublicKey              => $publicKey,]
            [PrivateKey             => $privateKey,]
            [Passphrase             => $passphrase,]
            [Prompt_credentials     => $flag,]
            [Timeout                => $secs,]
            [Connection_timeout     => $secs,]
            [Read_attempts          => $numberOfLoginReadAttemps,]
            [Data_with_error        => $flag,]
            [Wake_console           => $string,]
            [Blocking               => $flag,]
            [Errmode                => $errmode,]
            [Terminal_type          => $string,]
            [Window_size            => [$width, $height],]
            [Callback               => \&codeRef,]
            [Atomic_connect         => $flag,]
            [Non_recognized_login   => $flag,]
            [Generic_login          => $flag,]
      );

    If not specified, the default port number for SSH is 22. The wake_console argument is only relevant when connecting to a SSH port other than 22 (i.e. to a Terminal Server device) or if console() has been manually set; see console(). In which case, the login() method, which is called by connect(), will automatically send the wake_console string sequence to the attached device to alert it of the connection. The default sequence will work across all Extreme Networking products but can be overridden by using the wake_console argument. See wake_console().

    A username must always be provided for all SSH connections. If not provided and prompt_credentials is true then this method will prompt for it. Once the SSH conection is established, this method will attempt one of two possible authentication types, based on the accepted authentications of the remote host:

    • Publickey authentication : If the remote host accepts it and the method was supplied with public/private keys. The public/private keys need to be in OpenSSH format. If the private key is protected by a passphrase then this must also be provided or, if prompt_credentials is true, this method will prompt for the passphrase. If publickey authentication fails for any reason and password authentication is possible, then password authentication is attempted next; otherwise the error mode action is performed. See errmode().

    • Password authentication : If the remote host accepts either 'password' or 'keyboard-interactive' authentication methods. A password must be provided or, if prompt_credentials is true, this method will prompt for the password. If password authentication fails for any reason the error mode action is performed. See errmode(). VOSS VSP hosts can be configured for either 'password' or 'keyboard-interactive' authentication. Use of either of these SSH authentication methods (which both ultimately provide username & password credentials to the SSH server) remains completely transparent to the code using this class.

  • For Serial port, these arguments are used:

      $ok = $obj->connect(
            [BaudRate               => $baudRate,]
            [ForceBaud              => $flag,]
            [Parity                 => $parity,]
            [DataBits               => $dataBits,]
            [StopBits               => $stopBits,]
            [Handshake              => $handshake,]
            [Username               => $username,]
            [Password               => $password,]
            [Prompt_credentials     => $flag,]
            [Timeout                => $secs,]
            [Read_attempts          => $numberOfLoginReadAttemps,]
            [Data_with_error        => $flag,]
            [Wake_console           => $string,]
            [Blocking               => $flag,]
            [Errmode                => $errmode,]
            [Non_recognized_login   => $flag,]
            [Generic_login          => $flag,]
      );

    If arguments "baudrate", "parity", "databits", "stopbits" and "handshake" are not specified, the defaults are: Baud Rate = 9600, Data Bits = 8, Parity = none, Stop Bits = 1, Handshake = none. These default values will work on all Extreme Networking products with default settings. Allowed values for these arguments are the same allowed by Control::CLI::connect().

    On Windows systems the underlying Win32::SerialPort module can have issues with some serial ports, and fail to set the desired baudrate (see bug report https://rt.cpan.org/Ticket/Display.html?id=120068); if hitting that problem (and no official Win32::SerialPort fix is yet available) set the ForceBaud argument; this will force Win32::SerialPort into setting the desired baudrate even if it does not think the serial port supports it.

    For a serial connection, this method - or to be precise the login() method which is called by connect() - will automatically send the wake_console string sequence to the attached device to alert it of the connection. The default sequence will work across all Extreme Networking products but can be overridden by using the wake_console argument.

If using the connect() method in non-blocking mode, the following example illustrates how this works:

        $ok = $obj->connect(Host => $ip-address, Blocking => 0);
        until ($ok) { # This loop will be executed while $ok = 0
                
                <do other stuff here..>
        
                $ok = $obj->connect_poll;
        }

Or, if you have set an error mode action of 'return':

        $ok = $obj->connect(Host => $ip-address, Blocking => 0, Errmode => 'return');
        die $obj->errmsg unless defined $ok;    # Error connecting
        until ($ok) { # This loop will be executed while $ok = 0
                
                <do other stuff here..>
        
                $ok = $obj->connect_poll;
                die $obj->errmsg unless defined $ok;    # Error or timeout connecting
        }
login() & login_poll() - handle login for Telnet / Serial port; also set the host CLI prompt
  $ok = $obj->login(
        [Username               => $username,]
        [Password               => $password,]
        [Prompt_credentials     => $flag,]
        [Timeout                => $secs,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Blocking               => $flag,]
        [Errmode                => $errmode,]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

  ($ok, $output || $outputRef) = $obj->login(
        [Username               => $username,]
        [Password               => $password,]
        [Prompt_credentials     => $flag,]
        [Timeout                => $secs,]
        [Return_reference       => $flag,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Blocking               => $flag,]
        [Errmode                => $errmode,]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

Polling method (only applicable in non-blocking mode):

  $ok = $obj->login_poll();

  ($ok, $output || $outputRef) = $obj->login_poll();

This method handles login authentication for Telnet and Serial port access (also for SSH access in the case of the WLAN2300 WSS controllers, since they use no SSH authentication but instead use an interactive login once the SSH connection is established). For all connection types (including SSH) it also performs all the necessary steps to get to a CLI prompt; for instance on the Baystack / Stackable ERS platforms it will skip the Banner and/or Menu interface. Over a serial port connection or a ssh or telnet connection over a port other than default 22 or 23 respectively (indicating a Terminal Server connection) or if console() was manually set, it will automatically generate a wake_console sequence to wake up the attached device into producing either a login banner or CLI prompt. This sequence can be overridden by using the wake_console argument; setting this argument to the empty string will disable the wake_console sequence. Likewise use of console() can be used to control, force or disable the wake_console sequence; see wake_console() and console().

On success the method returns a true (1) value. On failure the error mode action is performed. See errmode(). In non-blocking mode (blocking disabled) the login() method will most likely immediately return with a false, but defined, value of 0. You will then need to call the login_poll() method at regular intervals until it returns a true (1) value indicating that the login is complete. In the first form only a success/failure value is returned in scalar context, while in the second form, in list context, both the success/failure value is returned as well as any output received from the host device during the login sequence; the latter is either the output itself or a reference to that output, depending on the object setting of return_reference or the argument override provided in this method. This method internally uses the readwait() method and by default sets the read_attemps for it to 10 (which is a safe value to ensure proper connection to any Extreme Networking device); the read_attempts argument provided by login() can be used to override that value. The non_recognized_login argument flag controls whether the method should immediately return when an initial login output sequence is not recognized or whether the method should keep trying to read login output until either a recognized login prompt is detected or expiry of the timeout. The generic_login argument flag disables extended discovery if it is desired to connect to non Extreme devices using this class.

Once a valid Extreme Networking CLI prompt is detected (using pre-configured pattern match strings), this method records the actual CLI prompt of the host device for the remainder of the session by automatically invoking the prompt() method with a new pattern match string based on the actual device CLI prompt. This ensures a more robust behaviour where the chances of triggering on a fake prompt embedded in the device output data is greatly reduced. At the same time this method will also set the --more-- prompt used by the device when paging output as well as a number of attributes depending on what family_type was detected for the host device. See attribute().

Note that this method is automatically invoked by the connect() method and therefore should seldom need to be invoked by itself. A possible reason to invoke this method on its own could be if initially connecting to, say, an ERS8800 device and from there initiating a telnet/ssh connection onto a Stackable device (i.e. telnet/ssh hopping); since we are connecting to a new device the login() method must be invoked to set the new prompts accordingly as well as re-setting all the device attributes. An example follows:

        # Initial connection could use Telnet or SSH, depending on how object was constructed
        # Connect to 1st device, e.g. via out-of-band mgmt
        $cli->connect(
                Host            => '<ERS8800 IP address>',
                Username        => 'rwa',
                Password        => 'rwa',
        );
        # From there connect to another device, perhaps on inband mgmt
        # NOTE: use print() not cmd() as there is no prompt coming back, but the login screen of the stackable
        $cli->print("telnet <Stackable IP address>");
        # Call login() to authenticate, detect the device, reset appropriate attributes 
        $cli->login(
                Username        => 'RW',
                Password        => 'RW',
        );
        # Execute commands on target stackable device
        $output = $cli->cmd("show running-config");
        print $output;
        [...]
        # If you want to return to the first device..
        # NOTE: use print() not cmd() as the next prompt will be from the ERS8800, not the stackable anymore
        $cli->print("logout");
        # Call login() to detect the device and reset appropriate attributes (no authentication needed though)
        $cli->login;
        # Now we are back on the 1st device
        $output = $cli->cmd("show sys info");
        print $output;
        [...]

If using the login() method in non-blocking mode, the following examples illustrate how this works:

  • If you do not care to retrieve the login sequence output:

            $ok = $obj->login(Username => "admin", Password => "pwd", Blocking => 0);
            until ($ok) { # This loop will be executed while $ok = 0
                    
                    <do other stuff here..>
            
                    $ok = $obj->login_poll;
            }
  • If you want to retrieve the login output sequence along the way (even in case of error/timeout):

            ($ok, $output) = $obj->login(Username => "admin", Password => "pwd", Blocking => 0, Errmode => 'return');
            die $obj->errmsg unless defined $ok;    # Login failed
            until ($ok) {
                    
                    <do other stuff here..>
            
                    ($ok, $partialOutput) = $obj->login_poll;
                    die $obj->errmsg unless defined $ok;    # Login failed or timeout
                    $output .= $partialOutput;
            }
            print "Complete login sequence output:\n", $output;
  • If you only want to retrieve the full login sequence output at the end:

            $ok = $obj->login(Username => "admin", Password => "pwd", Blocking => 0);
            until ($ok) {
                    
                    <do other stuff here..>
            
                    $ok = $obj->login_poll;
            }
            print "Complete login sequence output:\n", ($obj->login_poll)[1];
cmd() & cmd_poll() - Sends a CLI command to host and returns result or output

Backward compatible syntax:

  $result || $output || $outputRef = $obj->cmd($cliCommand);

  $result || $output || $outputRef = $obj->cmd(
        [Command                => $cliCommand,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_confirm_prompt     => $ynPrompt,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Return_reference       => $flag,]
        [Return_result          => $flag,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

New syntax (for non-blocking use):

  $ok = $obj->cmd(
        Poll_syntax             => 1,
        [Command                => $cliCommand,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_confirm_prompt     => $ynPrompt,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Return_reference       => $flag,]
        [Return_result          => $flag,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

  ($ok, $result || $output || $outputRef) = $obj->cmd($cliCommand);

  ($ok, $result || $output || $outputRef) = $obj->cmd(
        [Poll_syntax            => 1,]
        [Command                => $cliCommand,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_confirm_prompt     => $ynPrompt,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Return_reference       => $flag,]
        [Return_result          => $flag,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

Polling method (only applicable in non-blocking mode):

  $ok = $obj->cmd_poll();

  ($ok, $result || $output || $outputRef) = $obj->cmd_poll();

This method sends a CLI command to the host and returns once a new CLI prompt is received from the host. The output record separator - which is by default "\r" in this class; see output_record_separator() - is automatically appended to the command string. If no command string is provided then this method will simply send the output record separator and expect a new prompt back. Before sending the command to the host, any pending input data from host is read and flushed. The CLI prompt expected by the cmd() method is either the object prompt previously set by any of connect(), login() or prompt(); or it is the override prompt specified by the optional prompt method argument. If the reset_prompt flag is activated then the prompt match pattern is automatically reset using the same initial pattern match used by connect() & login() to match the prompt for the first time; this is useful when executing a CLI command which will cause the CLI prompt to change (such as changing the switch name). If the reset_prompt flag is set any prompt supplied via the argument will be ignored.

For backwards compatibility, in scalar context, the output data from the command is returned. The new syntax, in scalar context returns the poll status, while in list context, both the poll status together with the output data are returned. Note that to disambiguate the new scalar context syntax the 'poll_syntax' argument needs to be set (while this is not strictly necessary in list context). In non-blocking mode, the poll status will most likely immediately return with a false, but defined, value of 0. You will then need to call the cmd_poll() method at regular intervals until it returns a true (1) value indicating that the command has completed.

When this method is retrieving the output of the command and the output is generated over multiple pages of output, each page paused with a --more-- prompt, the cmd() method will retrieve as many pages as defined globally by more_paging(). If the optional "more_pages" argument is specified then this value will override the global setting of more_paging(). Either way, if a value of 0 is specified, space characters are automatically fed to obtain all output until the next CLI prompt is received. Note that for best script performance it is recommended to disable more paging on the host device using the appropriate CLI command or the device_more_paging() method. The optional 'more_prompt' argument can be used to override the object more_prompt string though this should seldom be necessary as the correct more prompt string is automatically set by connect() & login(). See more_prompt().

If the command produces a Y/N confirmation prompt as certain Extreme Networking device CLI commands do (for example "boot" or "reset") this method will automatically detect the confirmation prompt and feed a 'y' to it as you would expect when scripting the device. If, for some reason, you wanted to feed a 'n' then refer to cmd_prompted() method instead. The optional 'cmd_confirm_prompt' argument can be used to override the object match string defined for this; see also cmd_confirm_prompt().

This method will either return the result of the command or the output. If return_result is set for the object, or it is set via the override "return_result" argument provided in this method, then only the result of the command is returned. In this case a true (1) value is returned if the command was executed without generating any error messages on the host device. While a false (0) value is returned if the command generated some error messages on the host device. The error message can be obtained via the last_cmd_errmsg() method. See last_cmd_errmsg() and last_cmd_success(). This mode of operation is useful when sending configuration commands to the host device.

If instead return_result is not set then this method will return either a hard reference to the output generated by the CLI command or the output itself. This will depend on the setting of return_reference; see return_reference(); the global setting of return_reference can also be overridden using the method argument by the same name. Passing a refence to the output makes for much faster/efficient code, particularly if the output generated is large (for instance output of "show running-config"). The echoed command is automatically stripped from the output as well as the terminating CLI prompt (the last prompt received from the host device can be obtained with the last_prompt() method). This mode of operation is useful when sending show commands which retrieve information from the host device. Note that in this mode (return_result not set), sending a config command will result in either a null string or a reference pointing to a null string being returned, unless that command generated some error message on the host device. In this case the return_result mode should be used instead.

The progress_dots argument is provided as an override of the object method of the same name for the duration of this method; see progress_dots().

On I/O failure to the host device, the error mode action is performed. See errmode(). If, after expiry of the configured timeout - see timeout() -, output is no longer received from host and no valid CLI prompt has been seen, the method will send an additional carriage return character and automatically fall back on the initial generic prompt for a further 10% of the configured timeout. If even that prompt is not seen after this further timeout then the error mode action is performed. See errmode(). So even if the CLI prompt is changed by the issued command (e.g. changing the system-name or quitting the debug shell) this method should be able to recover since it will automatically revert to the initial generic prompt, but this will happen after expiry of the configured timeout. In this case, to avoid waiting expiry of timeout, set the reset_prompt argument. Here is an example showing how to revert to the normal CLI prompt when quitting the shell:

        $obj->cmd('priv');
        # Before entering the shell we need to set the prompt to match the shell prompt
        $obj->prompt('-> $');
        # Now enter the shell
        $obj->cmd('shell');
        $obj->cmd('spyReport');
        [...other shell cmds issued here...]
        # When done, logout from shell, and revert to standard CLI prompt
        $obj->cmd(Command => 'logout', Reset_prompt => 1);

Alternatively, since accessing the shell now requires a priv & shell password, if you only need to execute a few shell commands you can assume that the shell prompt is a prompt belonging to the shell command and use cmd_prompted() instead; the following example does the same thing as the previous example but does not need to change the prompt:

        # Enter the shell and execute shell commands all in one go
        $obj->cmd_prompted(
                        Command                 => 'priv',
                        Feed                    => $privPassword,
        );
        $obj->cmd_prompted(
                        Command                 => 'shell',
                        Cmd_initiated_prompt    => '(:|->) $',
                        Feed                    => $shellPassword,
                        Feed                    => 'spyReport',
                        Feed                    => 'logout',
        );

If the issued command returns no prompt (e.g. logout), consider using print() instead of cmd() or, if logging out, simply use the disconnect() method.

If the issued command produces a Y/N confirmation prompt but does not return a regular prompt (e.g. reset, boot) there are two possible approaches. On some Extreme Networking devices (e.g. PassportERS family_type) you can append '-y' to the command being sent to suppress the Y/N confirmation prompt, in which case you can simply do:

        $cli->print('reset -y');
        sleep 1; # Do not disconnect before switch has time to process last command...
        $cli->disconnect;

However, other Extreme Networking devices do not accept a '-y' appended to the reset/boot commands (e.g. BaystackERS family_type); on these devices use this sequence:

        $cli->print('reset');
        $cli->waitfor($cli->cmd_confirm_prompt);
        $cli->print('y');
        sleep 1; # Do not disconnect before switch has time to process last command...
        $cli->disconnect;

In non-blocking mode (blocking disabled) the cmd() method will most likely immediately return with a false, but defined, value of 0. You will then need to call the cmd_poll() method at regular intervals until it returns a true (1) value indicating that the command is complete. The following example illustrates:

  • If you do not care to retrieve any output from the command:

            $ok = $obj->cmd(Poll_syntax => 1, Command => "set command", Blocking => 0);
            until ($ok) { # This loop will be executed while $ok = 0
                    
                    <do other stuff here..>
            
                    $ok = $obj->cmd_poll;
            }
  • If you want to retrieve the command output sequence along the way:

            ($ok, $output) = $obj->cmd(Command => "show command", Blocking => 0, Errmode => 'return');
            die $obj->errmsg unless defined $ok;    # Login failed
            until ($ok) {
                    
                    <do other stuff here..>
            
                    ($ok, $partialOutput) = $obj->cmd_poll;
                    die $obj->errmsg unless defined $ok;    # Login failed or timeout
                    $output .= $partialOutput;
            }
            print "Complete command output:\n", $output;
  • If you only want to retrieve the command output at the end:

            $ok = $obj->cmd(Poll_syntax => 1, Command => "show command", Blocking => 0);
            until ($ok) {
                    
                    <do other stuff here..>
            
                    $ok = $obj->cmd_poll;
            }
            print "Complete command output:\n", ($obj->cmd_poll)[1];
cmd_prompted() - Sends a CLI command to host, feeds additional requested data and returns result or output

Backward compatible syntax:

  $result || $output || $outputRef = $obj->cmd_prompted($cliCommand, @feedData);

  $result || $output || $outputRef = $obj->cmd_prompted(
        [Command                => $cliCommand,]
        [Feed                   => $feedData1,
         [Feed                  => $feedData2,
          [Feed                 => $feedData3,
            ... ]]]
        [Feed_list              => \@arrayRef,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_initiated_prompt   => $cmdPrompt,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Return_reference       => $flag,]
        [Return_result          => $flag,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

New syntax (for non-blocking use):

  $ok = $obj->cmd_prompted(
        Poll_syntax             => 1,
        [Command                => $cliCommand,]
        [Feed                   => $feedData1,
         [Feed                  => $feedData2,
          [Feed                 => $feedData3,
            ... ]]]
        [Feed_list              => \@arrayRef,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_initiated_prompt   => $cmdPrompt,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Return_reference       => $flag,]
        [Return_result          => $flag,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

  ($ok, $result || $output || $outputRef) = $obj->cmd_prompted(
        [Poll_syntax            => 1,]
        [Command                => $cliCommand,]
        [Feed                   => $feedData1,
         [Feed                  => $feedData2,
          [Feed                 => $feedData3,
            ... ]]]
        [Feed_list              => \@arrayRef,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_initiated_prompt   => $cmdPrompt,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Return_reference       => $flag,]
        [Return_result          => $flag,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

Polling method (only applicable in non-blocking mode):

  $ok = $obj->cmd_poll();

  ($ok, $result || $output || $outputRef) = $obj->cmd_poll();

This method is identical to cmd() except that it will not automaticaly feed a 'y' to Y/N confirmation prompts but in a more general manner will detect any prompts generated by the issued CLI command (whether these are Y/N confirmation prompts or simply prompts for additional information the CLI command requires) and will feed whatever data has been provided to the method. In the first form of the backward compatible syntax, data can be provided as an array while in all other cases data is provided either as any number of "feed" arguments or via a "feed_list" array reference. In fact both "feed" and "feed_list" arguments can be provided, multiple times, in which case the data is chained in the same order in which it was provided to the method. Note that to disambiguate the new syntaxes, then either the "command" or "poll_syntax" arguments must be the first argument supplied, otherwise the first form of the backward compatible syntax is expected.

The prompt used to detect CLI command prompts can be set via the cmd_initiated_prompt() or via the override method argument by te same name. An example using cmd_prompted() is shown in the cmd() section above.

attribute() & attribute_poll() - Return device attribute value

Backward compatible syntax:

  $value = $obj->attribute($attribute);

  $value = $obj->attribute(
        Attribute               => $attribute,
        [Reload                 => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

New syntax (for non-blocking use):

  $ok = $obj->attribute(
        Poll_syntax             => 1,
        Attribute               => $attribute,
        [Reload                 => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

  ($ok, $value) = $obj->attribute($attribute);

  ($ok, $value) = $obj->attribute(
        [Poll_syntax            => 1,]
        Attribute               => $attribute,
        [Reload                 => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Polling method (only applicable in non-blocking mode):

  $ok = $obj->attribute_poll();

  ($ok, $value) = $obj->attribute_poll();

When connecting to an Extreme Networking device a certain number of attributes are automatically recorded if the information is readily available and does not require additional CLI commands. The attribute() method allows to retrieve the value of such attributes. If the attribute is already set, then the method simply returns its value. If on the other hand the requested attribute is not yet set, then in this case the method will issue the necessary CLI command to find the relevant information to set the attribute (or multiple attributes since in some cases a CLI command yields information for multiple attributes) and will then return its value. Any subsequent lookup for the same attribute name will no longer need to issue CLI commands. If the "reload" flag is true, then even if the attribute was already set the method will verify the setting on the connected device by re-issuing the necessary commands. In case of any IO failures while issuing CLI commands the error mode action is performed.

Once a connection is established (including login) the family_type attribute is always set. As long as it is set to a valid Extreme Networking product type, then all other global attributes are available as well as all the relevant attributes for the family type specified (a full list of available attributes is returned by specifying attribute all). Attributes for other product families different from the current value of family_type will be undefined. If the family_type attribute is not yet set or is set to generic then all other attributes, including the other Global ones, will be undefined.

Valid attributes and their possible values follow.

Global attributes which apply to any product family type:

  • family_type:

    • ExtremeXOS : ExtremeXOS Summit switch

    • BaystackERS : Any of Baystack, BPS, ES, Stackable ERS (ERS-2500, ERS-3x00, ERS-4x00, ERS-5x00), Stackable VSP (VSP-7000), WLAN8100

    • PassportERS : Any of Passport/ERS-1600, Passport/ERS-8x00, VOSS VSPs (VSP-9000, VSP-8000, VSP-7200, VSP-4000), APLS DSG BoxTypes

    • ISW : ISW industrial switches

    • Wing : Wireless Wing APs and Controllers

    • Series200 : Series200 switches

    • SLX : SLX Data Center switches

    • WLAN9100 : WLAN 91xx Access Points

    • SecureRouter : Any of the Secure Router 2330 & 4134 series

    • WLAN2300 : WLAN WSS2300 Controllers

    • Accelar : Any of the old Accelar 1000, 1100, 1200

    • generic : Not an Extreme Networking product; equivalent functionality to Control::CLI

  • model: Device model e.g. X460G2-24t-10G4, VSP-8284-XSQ, ERS-4526-GTX-PWR; The model naming will usually be in the format <VSP|ERS|ES|WC>-<number>-<type>-<subtype>. This attribute will remain undefined if connected to the Standby CPU of a PassportERS device. Typical ISW formatting is ISW_8-10/100P_4-SFP or ISW_4GbP_2GbT_2-SFP.

  • sysname: System name of the device. This attribute will remain undefined if connected to the Standby CPU of a PassportERS device.

  • base_mac: Base MAC address of the device in string format xx-xx-xx-xx-xx-xx. This is the base MAC address from which all other device MACs (VLAN, Port, etc) are derived. This attribute is useful for maintaining a unique reference for the device. This attribute will remain undefined if connected to the Standby CPU of a PassportERS device.

  • is_acli: Flag; true(1) for Cisco like acli mode which has PrivExec & Config modes; false(0) otherwise. So for family types BaystackERS, SecureRouter, WLAN2300, WLAN9100, ISW, Wing, Series200, SLX and PassportERS (the latter in acli mode) this flag is true. Whereas for family types ExtremeXOS, Accelar, generic and PassportERS (the latter in cli mode) this flag is false.

  • is_nncli: Flag; alias for above is_acli attribute as nncli is historically how this CLI mode was called in Nortel days

  • sw_version: Run time software version

  • fw_version: BootROM / Boot Monitor / Firmware / Linux verson, if applicable, undef otherwise

  • slots: Returns a list (array reference) of all valid slot numbers (or unit numbers in a stack) or interface types (in the case of ISW there are FastEthernet & GigabitEtherne interfaces); returns an empty list if the device ports have no slot number associated (e.g. a BaystackERS or ExtremeXOS switch in non-stacking/standalone mode) and undefined if no slot/port information could be retrieved from the device, e.g. if connected to the Standby CPU of a PassportERS device

  • ports: If the slots attribute is defined, this attribute returns an array (slots are numbers) or hash (slots are names; in the case of ISW, names 'FastEthernet' and 'GigabitEthernet') reference where the index/key is the slot number (valid slot/key numbers are provided by the slots attribute) and the array/hash elements are a list (array references) of valid ports for that particular slot. Note that for 40GbE/100GbE channelized ports the 10GbE/25GbE sub interfaces will be listed in port/subport fashion in this list; e.g. channelized ports 1/2/1-1/2/4 will be seen as ports 2/1,2/2,2/3,2/4 on the port list for slot 1. If the slots attribute is defined but empty (i.e. there is no slot number associated to available ports - e.g. a BaystackERS switch in standalone mode), this attribute returns a list (array reference) of valid port numbers for the device. (The test script for this class - extreme.cli.t - has an attribute method that shows how to decode the slot & port attributes).

  • baudrate: Console port configured baudrate. This attribute only works with devices where the baudrate is configurable or shown by the system (i.e. only PassportERS and BaystackERS devices with the exceptions of ERS-4000 units and standby CPU of a VSP9000/VSP8600). On these devices this attribute will return a defined value. On other devices where the baudrate is not configurable or not shown, an undef value is returned, and in this case it is safe to assume that the valid baudrate is 9600 (with the exception of ExtremeXOS X690 or X870 series switches where it is 115200)

  • max_baud: Maximum configurable value of baudrate on device's console port. This attribute only works with devices where the baudrate is configurable (i.e. only PassportERS and BaystackERS devices with the exceptions of ERS-4000 units andStandby CPU of a VSP9000). On these devices this attribute will return a defined value. On other devices where the baudrate is not configurable an undef value is returned, and in this case it is safe to assume that the only valid baudrate is the one returned by the baudrate attribute.

Attributes which only apply to PassportERS family type:

  • is_voss: Flag; true(1) if the device is a PassportERS VSP model (only model VSP-xxxx) or is an Extreme Product Label Switch (APLS) (is_apls is true); false(0) otherwise.

  • is_apls: Flag; true(1) if an Extreme Product Label Switch (APLS); false(0) otherwise.

  • apls_box_type: Box Type of an Extreme Product Label Switch (APLS); only set if is_apls is true, undefined otherwise.

  • brand_name: Brand Name of an Extreme Product Label Switch (APLS) or a VOSS VSP; only set if is_voss is true, undefined otherwise.

  • is_master_cpu: Flag; true(1) if connected to a Master CPU; false(0) otherwise

  • is_dual_cpu: Flag; true(1) if 2 CPUs are present in the chassis; false(0) otherwise

  • cpu_slot: Slot number of the CPU we are connected to

  • is_ha: Flag; true(1) if HA-mode is enabled; false(0) otherwise; undef if not applicable

  • stp_mode: Spanning tree operational mode; possible values: stpg (802.1D), rstp (802.1W), mstp (802.1S)

  • oob_ip: Out-of-band IP address of Master CPU (this attribute is only set when connected to the Master CPU)

  • oob_virt_ip: Out-of-band Virtual IP address (this attribute is only set when connected to the Master CPU)

  • oob_standby_ip: Out-of-band IP address of Standby CPU (this attribute is only set when connected to the Master CPU)

  • is_oob_connected: Flag; true(1) if the connection to the device is to either the oob_ip or oob_virt_ip IP address; false(0) otherwise (this attribute is only set when connected to the Master CPU; it will be undefined if connected to a Standby CPU)

Attributes which only apply to BaystackERS family type:

  • unit_number: Unit number we are connected to (Generaly the base unit, except when connecting via Serial) if a stack; undef otherwise

  • base_unit: Base unit number, if a stack; undef otherwise

  • switch_mode:

    • Switch : Standalone switch

    • Stack : Stack of switches

  • stack_size: Number of units in the stack, if a stack; undef otherwise

  • stp_mode: Spanning tree operational mode; possible values: stpg (802.1D), rstp (802.1W), mstp (802.1S)

  • mgmt_vlan: In-band management VLAN number

  • mgmt_ip: In-band management IP address

  • oob_ip: Out-of-band IP address (only defined on devices which have an OOB port and have an IP address configured on it)

  • is_oob_connected: Flag; true(1) if the connection to the device is to the oob_ip IP address; false(0) otherwise

Attributes which only apply to ExtremeXOS family type:

  • is_xos: Flag; true(1) if the device is an ExtremeXOS switch; false(0) otherwise.

  • unit_number: Unit number we are connected to (Generaly the master unit, except when connecting via Serial) if a stack; undef otherwise

  • master_unit: Master unit number, if a stack; undef otherwise

  • switch_mode:

    • Switch : Standalone switch

    • Stack : Stack of switches

  • stack_size: Number of units in the stack, if a stack; undef otherwise

  • stp_mode: Spanning tree operational mode; possible values: stpg (802.1D), rstp (802.1W), mstp (802.1S)

  • oob_ip: Out-of-band IP address (only defined on devices which have an OOB port and have an IP address configured on it)

  • is_oob_connected: Flag; true(1) if the connection to the device is to the oob_ip IP address; false(0) otherwise

Attributes which only apply to ISW family type:

  • is_isw: Flag; true(1) if the device is an ISW industrial switch; false(0) otherwise.

Attributes which only apply to Wing family type:

  • is_wing: Flag; true(1) if the device is a Wing AP or Controller; false(0) otherwise.

Attributes which only apply to Series200 family type:

  • unit_number: Unit number we are connected to (always the stack manager unit) if a stack; undef otherwise

  • manager_unit: Stack Manager unit number, if a stack; undef otherwise

  • switch_mode:

    • Switch : Standalone switch

    • Stack : Stack of switches

  • stack_size: Number of units in the stack, if a stack; undef otherwise

  • stp_mode: Spanning tree operational mode; possible values: stpg (802.1D), rstp (802.1W), mstp (802.1S), pvst, rpvst

  • oob_ip: Out-of-band IP address (only defined on devices which have an OOB port and have an IP address configured on it)

  • is_oob_connected: Flag; true(1) if the connection to the device is to the oob_ip IP address; false(0) otherwise

Attributes which only apply to SLX family type:

  • is_slx: Flag; true(1) if the device is an SLX switch.

  • is_slx_r: Flag; true(1) if the device is an SLX-R switch.

  • is_slx_s: Flag; true(1) if the device is an SLX-S switch.

  • is_slx_x: Flag; true(1) if the device is an SLX-X switch.

  • switch_type: Holds the numerical switch type of the SLX switch

  • is_active_mm: Flag; true(1) if connected to the Active Manager Module (MM); currently always true on SLX9850 chassis

  • is_dual_mm: Flag; true(1) if 2 Manager Module (MM) are present in the SLX9850 chassis; false(0) otherwise

  • mm_number: Slot number of the Manager Module (MM) we are connected to; 0 on non-9850 SLX

  • is_ha: Flag; true(1) if HA-mode is enabled; false(0) otherwise; undef if not applicable

  • stp_mode: Spanning tree operational mode; possible values: stpg (802.1D), rstp (802.1W), mstp (802.1S), pvst, rpvst

  • oob_ip: Out-of-band IP address of Active Manager Module (MM)

  • oob_virt_ip: Out-of-band Chassis Virtual IP address

  • oob_standby_ip: Out-of-band IP address of Standby Manager Module (MM)

  • is_oob_connected: Flag; true(1) if the connection to the device is to either the oob_ip or oob_virt_ip IP address; false(0) otherwise

Attributes which only apply to Accelar family type:

  • is_master_cpu: Flag; true(1) if connected to a Master CPU; false(0) otherwise

  • is_dual_cpu: Flag; true(1) if 2 CPUs are present in the chassis; false(0) otherwise

All available attributes on a given connection

  • all: Retuns a list (array reference) of all valid attributes for the current connection; this will include all Global attributes as well as all attributes corresponding to the family type specified by family_type. This is useful for iterating through all available attributes in a foreach loop.

In non-blocking mode (blocking disabled), if the attribute requested is not already set and thus CLI commands need to be sent to the connected device, the attribute() method will most likely immediately return with a false, but defined, value of 0. You will then need to call the attribute_poll() method at regular intervals until it returns a true (1) value indicating that the command is complete. The following example illustrates:

        ($ok, $value) = $obj->attribute(Attribute => $attribute, Blocking => 0);
        until ($ok) {
                
                <do other stuff here..>
        
                ($ok, $value) = $obj->attribute_poll;
        }
        print "Attribute $attribute value = ", $value, "\n" if defined $value;
        print "Attribute $attribute undefined\n" unless defined $value;
change_baudrate() & change_baudrate_poll() - Change baud rate on current serial connection

Changing only local serial port:

  $ok = $obj->change_baudrate(
        Local_side_only         => 1,
        [BaudRate               => $baudRate,]
        [ForceBaud              => $flag,]
        [Parity                 => $parity,]
        [DataBits               => $dataBits,]
        [StopBits               => $stopBits,]
        [Handshake              => $handshake,]
        [Errmode                => $errmode,]
  );

Changing host and serial port together (backward compatible syntax):

  $baudrate = $obj->change_baudrate($baudrate);

  $baudrate = $obj->change_baudrate(
        BaudRate                => $baudrate,
        [ForceBaud              => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Changing host and serial port together (new syntax for non-blocking use):

  $ok = $obj->change_baudrate(
        Poll_syntax             => 1,
        BaudRate                => $baudrate,
        [ForceBaud              => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

  ($ok, $baudrate) = $obj->change_baudrate($baudrate);

  ($ok, $baudrate) = $obj->change_baudrate(
        [Poll_syntax            => 1,]
        BaudRate                => $baudrate,
        [ForceBaud              => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Polling method (only applicable in non-blocking mode):

  $ok = $obj->change_baudrate_poll();

  ($ok, $baudrate) = $obj->change_baudrate_poll();

This method is only applicable to an already established Serial port connection and will return an error if the connection type is Telnet or SSH or if the object type is for Serial but no connection is yet established.

If the 'local_side_only' argument is set this method will simply call the Control::CLI method by the same name which will simply change the baudrate (and/or parity, databits, stopbits, handshake) of the current serial connection without trying to also change the baudrate on the device we are connected to. This is equivalent to simply calling SUPER::change_baudrate().

Without the 'local_side_only' argument set, this method combines the knowledge of the Extreme device type we are connected to by automatically changing the baudrate configuration on the attached device before actually changing the baudrate of the connection. Thus if the attribute family_type is not yet defined or is set to 'generic' then an error will be returned. From this point onwards, the behaviour of this method upon failure will depend on whether a specific baudrate was provided or whether the desired baudrate was specified as 'max'. In the former case any failure to set the requested baudrate will trigger the error mode action whereas in the latter case it is assumed that the desire is to try and maximise the connection baudrate if possible but that we do not want to generate an error if that is not possible.

The ability to change the baudrate configuration on the attached device is currently only available when the attribute family_type is either BaystackERS or PassportERS. For any other family_type (including 'generic', SecureRouter & WLAN2300) this method will simply return success in 'max' mode and the error mode action otherwise (there is no way to change the baudrate configuration on SecureRouter & WLAN2300 devices to a value other than 9600 baud; there is no knowledge on how to do so on 'generic' devices). Even on some BaystackERS or PassportERS devices it is not possible to change the baudrate (e.g. ERS-4x00, Passport-1600, Passport-8300 and some APLS switches) and again this method will simply return success in 'max' mode and the error mode action otherwise.

When changing the baudrate of the local connection this method calls Control::CLI::change_baudrate() which will restart the object serial connection with the new baudrate (in the background, the serial connection is actually disconnected and then re-connected) without losing the current CLI session. If there is a problem restarting the serial port connection at the new baudrate then the error mode action is performed (now also in 'max' mode) - see errmode(). If the baudrate was successfully changed the value of the new baudrate (a true value) is returned. The advantage of using this method to increase the baudrate to a higher value than 9600 is that when retrieving commands which generate a large amount of output, this can be read in a lot faster if the baudrate is increased.

Remember to restore the baudrate configuration of the attached device to default 9600 when done or anyone connecting to its serial port thereafter will have to guess the baudrate! To minimize the chance of this happening the disconnect & destroy methods for this class will automatically try to restore whatever baudrate was used when initially connecting to the device.

Supported baudrates for this method are:

  • BaystackERS: 9600, 19200, 38400 or 'max' (where 'max' = 38400)

  • PassportERS: 9600, 19200, 38400, 57600, 115200 or 'max' (where 'max' = 115200)

Follows an example:

        use Control::CLI;
        # Create the object instance for Serial port
        $cli = new Control::CLI('COM1');
        # Connect to switch
        $cli->connect(
                        Baudrate        => 9600,
                        Username        => $username,
                        Password        => $password,
                );
        # Get the config
        $output = $cli->cmd(
                        Command         => "show running-config",
                        Progress_dots   => 100,
                );
        # Increase the baudrate
        $maxBaudrate = $cli->change_baudrate('max');
        print "Baudrate increased to $maxBaudrate" if $maxBaudrate;
        # Get the config a 2nd time (4 times faster on BaystackERS; 12 times faster PassportERS)
        $output = $cli->cmd(
                        Command         => "show running-config",
                        Progress_dots   => 100,
                );
        # Restore the baudrate
        $cli->change_baudrate(9600);
        # Disconnect
        $cli->disconnect;

In non-blocking mode (blocking disabled), the change_baudrate() method will most likely immediately return with a false, but defined, value of 0. You will then need to call the change_baudrate_poll() method at regular intervals until it returns a true (1) value indicating that the change is complete. The following example illustrates:

        ($ok, $baudrate) = $obj->change_baudrate(BaudRate => $baudrate, Blocking => 0);
        until ($ok) {
                
                <do other stuff here..>
        
                ($ok, $baudrate) = $obj->change_baudrate_poll;
        }
        print "New baudrate = ", $baudrate, "\n";
enable() & enable_poll() - Enter PrivExec mode
  $ok = $obj->enable($enablePassword);

  $ok = $obj->enable(
        [Password               => $enablePassword,]
        [Prompt_credentials     => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

  $ok = $obj->enable_poll();    # Only applicable in non-blocking mode

This method checks whether the 'is_acli' attribute is set and, if so, whether the last prompt ends with '>'; if both conditions are true, it will flush any unread pending input from the device and will just send an 'enable' command to enter Priviledge Executive mode. If either of the above conditions are not met then this method will simply return a true (1) value. The method can take a password argument which only applies to the WLAN2300 series and in some older software versions of the ERS-8300 in NNCLI mode. If a password is required, but not supplied, this method will try supplying first a blank password, then the same password which was used to connect/login and finally, if prompt_credentials is true for the object, prompt for it. On I/O failure, the error mode action is performed. See errmode(). The optional "prompt_credentials" argument is provided to override the global setting of the parameter by the same name which is by default false. See prompt_credentials().

In non-blocking mode (blocking disabled), the enable() method will most likely immediately return with a false, but defined, value of 0. You will then need to call the enable_poll() method at regular intervals until it returns a true (1) value indicating that the change is complete. The following example illustrates:

        $ok = $obj->enable(Blocking => 0);
        until ($ok) {
                
                <do other stuff here..>
        
                $ok = $obj->enable_poll;
        }
device_more_paging() & device_more_paging_poll() - Enable/Disable more paging on host device
  $ok = $obj->device_more_paging($flag);

  $ok = $obj->device_more_paging(
        Enable                  => $flag,
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

  $ok = $obj->device_more_paging_poll();        # Only applicable in non-blocking mode

This method issues the necessary CLI commands to turn on/off --more-- paging on the connected device. It relies on the setting of family_type attribute - see attribute() - to send the appropriate commands. If an error occurs while sending the necessary CLI commands, then the error mode action is performed. See errmode(). Returns a true value (1) on success.

In non-blocking mode (blocking disabled), the device_more_paging() method will most likely immediately return with a false, but defined, value of 0. You will then need to call the device_more_paging_poll() method at regular intervals until it returns a true (1) value indicating that the change is complete. The following example illustrates:

        $ok = $obj->device_more_paging(Enable => 0, Blocking => 0);
        until ($ok) {
                
                <do other stuff here..>
        
                $ok = $obj->device_more_paging_poll;
        }
device_peer_cpu() & device_peer_cpu_poll() - Connect to peer CPU on ERS8x00 / VSP9000
  $ok = $obj->device_peer_cpu(
        [Username               => $username,]
        [Password               => $password,]
        [Prompt_credentials     => $flag,]
        [Blocking               => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

  $ok = $obj->device_peer_cpu_poll();   # Only applicable in non-blocking mode

This method, only applicable on ERS8x00 and VSP9000, will try to connect to the peer CPU. On success a true (1) value is returned otherwise the error mode action is performed. See errmode(). It should not normally be necessary to provide username/password since the credentials used to connect to the current CPU will automatically be used. If not so, or to override the cached ones, optional "username" & "password" arguments can be provided. Attributes 'cpu_slot' and 'is_master_cpu' are automatically updated once the connection to the peer CPU succeeds. See attribute().

In non-blocking mode (blocking disabled), the device_peer_cpu() method will most likely immediately return with a false, but defined, value of 0. You will then need to call the device_peer_cpu_poll() method at regular intervals until it returns a true (1) value indicating that the change is complete. The following example illustrates:

        $ok = $obj->device_peer_cpu(Blocking => 0);
        until ($ok) {
                
                <do other stuff here..>
        
                $ok = $obj->device_peer_cpu_poll;
        }

Methods to set/read Object variables

flush_credentials - flush the stored username, password, passphrase and enable password credentials
  $obj->flush_credentials;

The connect(), login() and enable() methods, if successful in authenticating, will automatically store the username/password/enable-password or SSH passphrase supplied to them. These can be retrieved via the username, password, passphrase and enable_password methods. If you do not want these to persist in memory once the authentication has completed, use this method to flush them. This method always returns 1.

prompt() - set the CLI prompt match pattern for this object
  $string = $obj->prompt;

  $prev = $obj->prompt($string);

This method sets the CLI prompt match patterns for this object. In the first form the current pattern match string is returned. In the second form a new pattern match string is set and the previous setting returned. If no prompt has yet been set (connection not yet established) undef is returned. The object CLI prompt pattern is automatically set by the connect(), login() and cmd(reset_prompt => 1) methods and normally does not need to be set manually unless the CLI prompt is expected to change. Once set, the object CLI prompt match pattern is only used by the cmd() and cmd_prompted() methods.

more_prompt() - set the CLI --More-- prompt match pattern for this object
  $string = $obj->more_prompt;

  $prev = $obj->more_prompt($string [, $delayPrompt]);

This method sets the CLI --More-- prompt match patterns for this object. In the first form the current pattern match string is returned. In the second form a new pattern match string is set and the previous setting returned (the $delayPrompt can be set as a subset of $string if $string accepts multiple patterns some of which are subsets of others). If no prompt has yet been set (connection not yet established) undef is returned. The object's CLI --More-- prompt pattern is automatically set by the connect() and login() methods based upon the device type detected during login. Normally there should be no need to set this manually. Once set, the object CLI --More-- prompt match patterns is only used by the cmd() and cmd_prompted() methods.

more_paging() - sets the number of pages to read when device output is paged by --more-- prompts
  $numberOfPages = $obj->more_paging;

  $prev = $obj->more_paging($numberOfPages);

When issuing CLI commands, using cmd() or cmd_prompted(), which generate large amount of output, the host device will automatically page the output with --more-- prompts where the user can either view the next page, by sending a Space character, or terminate the CLI command, by sending a q character. This method sets the number of pages of output that both cmd() and cmd_prompted() will retrieve before sending a q character and thus terminating the CLI command. Hence if more_paging is set to 1, only one page of output will be collected and a q character will be sent to the first --more-- prompt received. if more_paging is set to 2, two pages of output will be collected and a q character will be sent to the second --more-- prompt received. By default more_paging is set to 0, which means that the entire output of any issued command will be retrieved, by always feeding Space characters to every --more-- prompt encountered. Note however that for best performance, if the entire output of a command is required, it is best to disable --more-- paging direcly on the host device rather than letting cmd() or cmd_prompted() feed a Space to every --more-- prompt encountered; see device_more_paging(). This setting can also be overridden directly in cmd() or cmd_prompted() using the 'more_pages' argument. In the first form the current setting of more_paging is returned; in the second form a more_paging setting is configured and the previous setting returned.

progress_dots() - configure activity dots for cmd() and cmd_prompted() methods
  $prevBytesPerDot = $obj->progress_dots($bytesPerDot);

With this method it is possible to enable cmd() - and cmd_prompted() - to print activity dots (....) as input data is read from the host device. This is useful if the command sent to the host device returns large amount of data (e.g. "show tech") and/or it takes a long time for the host device to complete the command and return a CLI prompt. To enable the functionality set $bytesPerDot to a non zero value; this value will represent every how many bytes of input data read an activity dot will be printed. For example set a value of 1000. To disable the functionality simply configure it with a zero value. By default this functionality is disabled.

return_result() - set whether cmd methods should return output or the success/failure of the command
  $flag = $obj->return_result;

  $prev = $obj->return_result($flag);

This method gets or sets the setting for return_result for the object. This applies to the cmd() and cmd_prompted() methods and determines whether these methods should return the success or failure of the issued command (i.e. a true/false value) or instead the output generated by the command. By default return_result is false (0) and the output of the command is returned.

last_cmd_success() - Returns the result of the last command sent via a cmd method
  $result = $obj->last_cmd_success;

  $prev = $obj->last_cmd_success($result);

This method returns the outcome (true or false) of the last command sent to the host via any of the cmd() or cmd_prompted() methods. If the command generated no error messages on the host, then the command was successful and the result is true (1). If instead an error message was generated by the host, then the command is deemed unsuccesful and the result is false (0). The second form allows the outcome to be manually set. Note that the same information can be directly obtained from the above mentioned cmd methods by simply enabling the 'return_result' object parameter, or method argument. Note also that this functionality is only available if the host is detected as an Extreme Networking product, i.e. the family_type attribute is set to a value other than generic - see attribute(). If the family_type attribute is set to generic then this method will always return undef.

last_cmd_errmsg() - returns the last command error message received from connected host
  $msg = $obj->last_cmd_errmsg;

  $prev = $obj->last_cmd_errmsg($msg);

The first calling sequence returns the cmd error message associated with the object. Undef is returned if no error has been encountered yet. The second calling sequence sets the cmd error message for the object. If the attached device is detected as an Extreme Networking product, i.e. the family_type attribute is set to a value other than generic, and a command is issued to the host via cmd() or cmd_prompted(), and this command generates an error on the host, then the last_cmd_success will be set to false and the actual error message will be available via this method. The string returned will include the device prompt + command echoed back by the device (on the first line) and the error message and pointer on subsequent lines. The error message will be held until a new command generates a new error message. In general, only call this method after checking that the last_cmd_success() method returns a false value.

cmd_confirm_prompt() - set the Y/N confirm prompt expected from certain device CLI commands
  $string = $obj->cmd_confirm_prompt;

  $prev = $obj->cmd_confirm_prompt($string);

This method sets the Y/N confirm prompt used by the object instance to match confirmation prompts that Extreme Networking devices will generate on certain CLI commands. The cmd() method will use this patterm match to detect these Y/N confirmation prompts and automatically feed a 'Y' to them so that the command is executed as you would expect when scripting the device - see cmd(). In the event you want to feed a 'N' instead, refer to cmd_prompted(). The default prompt match pattern used is:

  '[\(\[] *(?:[yY](?:es)? *(?:[\\\/]|or) *[nN]o?|[nN]o? *(?:[\\\/]|or) *[yY](?:es)?|y - .+?, n - .+?, <cr> - .+?) *[\)\]](?: *[?:] *| )$'

The first form of this method allows reading the current setting; the latter will set the new Y/N prompt and return the previous setting.

cmd_initiated_prompt() - Set the prompt that certain device CLI commands will generate to request additional info
  $string = $obj->cmd_initiated_prompt;

  $prev = $obj->cmd_initiated_prompt($string);

This method sets the prompt used by the object instance to match the prompt that certain Extreme Networking device CLI commands will generate to request additional info. This is used exclusively by the cmd_prompted() method which is capable to detect these prompts and feed the required information to them. See cmd_prompted(). The default prompt match pattern used is:

  '[?:=]\h*(?:\(.+?\)\h*)?$'

This method can also be used if you wish to feed a 'N' to Y/N prompts, unlike what is automaticaly done by the cmd() method. The first form of this method allows reading the current setting; the latter will set the new prompt and return the previous setting.

cmd_feed_timeout() - Set the number of times we skip command prompts before giving up
  $value = $obj->cmd_feed_timeout;

  $prev = $obj->cmd_feed_timeout($value);

If a CLI command is found to generate a prompt for additional data - i.e. a match was found for string defined by cmd_initiated_prompt() - and no data was provided to feed to the command (either because of insufficient feed data in cmp_promted() or if using cmd() which cannot supply any feed data) the cmd methods will automatically feed a carriage return to such prompts in the hope of getting to the next CLI prompt and return. If however these command prompts for additional data were indefinite, the cmd methods would never return. This method sets a limit to the number of times that an empty carriage return is fed to these prompts for more data for which we have no data to feed. When that happens the cmd method will timeout and the error mode action is performed. The same value will also set an upper limit to how many times a 'y' is fed to Y/N confirm prompts for the same command in the cmd() method. The default value is set to 10.

console() - Enable or Disable object console mode, wich triggers sending the wake_console string on connection/login
  $value = $obj->console;

  $prev = $obj->console($flag);

When connecting to the serial console port of a device it is necessary to send some characters to trigger the device at the other end to respond. These characters are defined in wake_console() and are automatically sent when the object console mode is true. By default the object console is undefined, and automatically updates itself to true when connecting via Serial, or Telnet (with port other than 23) or SSH (with port other than 22). The latter two generally represent connection to some terminal server deivce. To prevent the object console mode from auto updating following connection, you may set it with this method to a defined false value (0); this will result in wake_console being permanently disabled. Alternatively, to force wake_console to be sent even on regular Telnet/SSH connections, you may set it with this method to a true value. This approach is needed when connecting via Telnet to an XOS switch which is configured with a 'before-login' banner which has to be acknowledged. In this case the XOS switch will not request a login until the user has hit a key; setting this method to 1 (or setting the Console argument to 1 in the object constructor) will ensure that the XOS banner is acknowledged and the login will not time-out.

wake_console() - Set the character sequence to send to wake up device when connecting to console port
  $string = $obj->wake_console;

  $prev = $obj->wake_console($string);

When connecting to the serial console port of a device it is necessary to send some characters to trigger the device at the other end to respond. These characters can be defined using this method. By default the wake string is "\n". The wake string is sent when the console mode of the connection is true - see console(). By default this happens when connecting via Serial port as well as via Telnet (with port other than 23) or via SSH (with port other than 22), i.e. via a Terminal Server device. See Setting the wake sequence to the empty string, will disable it.

no_refresh_cmd() - set pattern and send character to automatically come out of refreshed commands
  $pattern = $obj->no_refresh_cmd;

  $prev = $obj->no_refresh_cmd($pattern, $sendCharacter);

Some commands on some devices endlessly refresh the output requested (e.g. commands showing statistics on ExtremeXOS). This is not desireable when scripting the CLI using the cmd() methods as these commands would result in cmd() the methods never returning, as output keeps being read indefinitely and no final CLI prompt is ever seen. This method is used to set a pattern to detect the such refreshing commands from their output, as well as a send character to send to the host in order to break out immediately from the refresh cycle. Suitable patterns for ExtremeXOS and PassportERS family types are automatically setup by the connect() and login() methods based upon the device type detected during login. Normally there should be no need to set this manually. This method can also be used to disable the automatically set pattern, by simply calling the method with $pattern set to the empty string. Once set, these patterns are only used by the cmd() and cmd_prompted() methods.

debug() - set debugging
  $debugLevel = $obj->debug;

  $prev = $obj->debug($debugLevel);

Enables debugging for the object methods and on underlying modules. In the first form the current debug level is returned; in the second form a debug level is configured and the previous setting returned. By default debugging is disabled. To disable debugging set the debug level to 0. The following debug levels are defined:

  • 0 : No debugging

  • bit 1 : Control::CLI - Debugging activated for for polling methods + readwait() and enables carping on Win32/Device::SerialPort. This level also resets Win32/Device::SerialPort constructor $quiet flag only when supplied in Control::CLI::new()

  • bit 2 : Control::CLI - Debugging is activated on underlying Net::SSH2 and Win32::SerialPort / Device::SerialPort; there is no actual debugging for Net::Telnet

  • bit 4 : Control::CLI::Extreme - Basic debugging

  • bit 8 : Control::CLI::Extreme - Extended debugging of login() & cmd() methods

debug_file() - set debug output file
  $fh = $obj->debug_file;

  $fh = $obj->debug_file($fh);

  $fh = $obj->debug_file($fileName);

This method starts or stops logging debug messages to a file. If no argument is given, the log filehandle is returned. An empty string indicates logging is off. If an open filehandle is given, it is used for logging and returned. Otherwise, the argument is assumed to be the name of a file, the file is opened for logging and a filehandle to it is returned. If the file can't be opened for writing, the error mode action is performed. To stop logging debug messages to a file, call this method with an empty string as the argument. Note that if no debug_file is defined all debug messages will be printed to STDOUT. To set or stop debugging use the debug() method.

Methods to access Object read-only variables

config_context - read configuration context of last prompt
  $configContext = $obj->config_context;

Returns the configuration context included in the last prompt received from the host device. For example if the last prompt received from the device was 'switch(config-if)#' this method will return 'config-if'. While if the last prompt was in the form 'switch/config/ip#' this method will return '/config/ip'. If the device was not in config mode at the last prompt, this method returns an empty string ''.

enable_password - read enable password provided
  $enablePassword = $obj->enable_password;

Returns the last enable password which was successfully used in the enable() method, or undef otherwise. Of the supported family types only the WLAN2300 requires a password to access privExec mode.

Methods overridden from Control::CLI

connect() & connect_poll() - connect to host
login() & login_poll() - handle login for Telnet / Serial port
cmd() & cmd_poll() - Sends a CLI command to host and returns output data
change_baudrate() - Change baud rate on current serial connection
prompt() - set the CLI prompt match pattern for this object
disconnect() - disconnect from host

Methods inherited from Control::CLI

read() - read block of data from object
readwait() - read in data initially in blocking mode, then perform subsequent non-blocking reads for more
waitfor() & waitfor_poll() - wait for pattern in the input stream
put() - write data to object
print() - write data to object with trailing output_record_separator
printlist() - write multiple lines to object each with trailing output_record_separator
input_log() - log all input sent to host
output_log() - log all output received from host
dump_log() - log hex and ascii for both input and output stream
eof - end-of-file indicator
break - send the break signal
close - disconnect from host
poll - poll object(s) for completion
debug() - set debugging

Error Handling Methods inherited from Control::CLI

errmode() - define action to be performed on error/timeout
errmsg() - last generated error message for the object
errmsg_format() - set the format to be used for object error messages
error() - perform the error mode action

Methods to set/read Object variables inherited from Control::CLI

timeout() - set I/O time-out interval
connection_timeout() - set Telnet and SSH connection time-out interval
read_block_size() - set read_block_size for either SSH or Serial port
blocking() - set blocking mode for read methods and polling capable methods
read_attempts() - set number of read attempts used in readwait() method
readwait_timer() - set the polling timer used in readwait() method
data_with_error() - set the readwait() method behaviour in case a read error occurs after some data was read
return_reference() - set whether read methods should return a hard reference or not
output_record_separator() - set the Output Record Separator automatically appended by print & cmd methods (Note that unlike Control::CLI this class will default to "\r")
prompt_credentials() - set whether connect() and login() methods should be able to prompt for credentials
username_prompt() - set the login() username prompt match pattern for this object
password_prompt() - set the login() password prompt match pattern for this object
terminal_type() - set the terminal type for the connection
window_size() - set the terminal window size for the connection
report_query_status() - set if read methods should automatically respond to Query Device Status escape sequences

Methods to access Object read-only variables inherited from Control::CLI

parent - return parent object
ssh_channel - return ssh channel object
ssh_authentication - return ssh authentication type performed
connection_type - return connection type for object
host - return the host for the connection
port - return the TCP port / COM port for the connection
last_prompt - returns the last CLI prompt received from host
username - read username provided
password - read password provided
passphrase - read passphrase provided
handshake - read handshake used by current serial connection
baudrate - read baudrate used by current serial connection
parity - read parity used by current serial connection
databits - read databits used by current serial connection
stopbits - read stopbits used by current serial connection

Methods for modules sub-classing Control::CLI::Extreme inherited from Control::CLI

poll_struct() - sets up the polling data structure for non-blocking capable methods
poll_struct_cache() - caches selected poll structure keys, if a nested polled method is called
poll_struct_restore() - restores previously cached poll structure keys, if a nested polled method was called
poll_reset() - resets poll structure
poll_return() - return status and optional output while updating poll structure
poll_sleep() - performs a sleep in blocking or non-blocking mode
poll_open_socket() - opens TCP socket in blocking or non-blocking mode
poll_read() - performs a non-blocking poll read and handles timeout in non-blocking polling mode
poll_readwait() - performs a non-blocking poll readwait and handles timeout in non-blocking polling mode
poll_waitfor() - performs a non-blocking poll for waitfor()

Methods for modules sub-classing overridden from Control::CLI

poll_connect() - performs a non-blocking poll for connect()
poll_login() - performs a non-blocking poll for login()
poll_cmd() - performs a non-blocking poll for cmd()
poll_change_baudrate() - performs a non-blocking poll for change_baudrate()
debugMsg() - prints out a debug message

Methods for modules sub-classing Control::CLI::Extreme

poll_connect() - performs a non-blocking poll for connect()
  $ok = $obj->poll_connect($pkgsub,
        [Host                   => $host,]
        [Port                   => $port,]
        [Username               => $username,]
        [Password               => $password,]
        [PublicKey              => $publicKey,]
        [PrivateKey             => $privateKey,]
        [Passphrase             => $passphrase,]
        [Prompt_credentials     => $flag,]
        [BaudRate               => $baudRate,]
        [Parity                 => $parity,]
        [DataBits               => $dataBits,]
        [StopBits               => $stopBits,]
        [Handshake              => $handshake,]
        [Login_Timeout          => $secs,]
        [Connection_timeout     => $secs,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Errmode                => $errmode,]
        [Terminal_type          => $string,]
        [Window_size            => [$width, $height],]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

  ($ok, $outputref) = $obj->poll_connect($pkgsub,
        [Host                   => $host,]
        [Port                   => $port,]
        [Username               => $username,]
        [Password               => $password,]
        [PublicKey              => $publicKey,]
        [PrivateKey             => $privateKey,]
        [Passphrase             => $passphrase,]
        [Prompt_credentials     => $flag,]
        [BaudRate               => $baudRate,]
        [Parity                 => $parity,]
        [DataBits               => $dataBits,]
        [StopBits               => $stopBits,]
        [Handshake              => $handshake,]
        [Login_Timeout          => $secs,]
        [Connection_timeout     => $secs,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Errmode                => $errmode,]
        [Terminal_type          => $string,]
        [Window_size            => [$width, $height],]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

Normally this is the internal method used by connect() and connect_poll() methods. Arguments after $ok will only be defined if $ok is true(1).

poll_login() - performs a non-blocking poll for login()
  $ok = $obj->poll_login($pkgsub,
        [Username               => $username,]
        [Password               => $password,]
        [Prompt_credentials     => $flag,]
        [Timeout                => $secs,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Errmode                => $errmode,]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

  ($ok, $outputref) = $obj->poll_login($pkgsub,
        [Username               => $username,]
        [Password               => $password,]
        [Prompt_credentials     => $flag,]
        [Timeout                => $secs,]
        [Read_attempts          => $numberOfLoginReadAttemps,]
        [Data_with_error        => $flag,]
        [Wake_console           => $string,]
        [Errmode                => $errmode,]
        [Non_recognized_login   => $flag,]
        [Generic_login          => $flag,]
  );

Normally this is the internal method used by login() and login_poll() methods. Arguments after $ok will only be defined if $ok is true(1).

poll_cmd() - performs a non-blocking poll for cmd()
  $ok = $obj->poll_cmd($pkgsub, $cliCommand);

  $ok = $obj->poll_cmd($pkgsub,
        [Command                => $cliCommand,]
        [Feed_list              => \@arrayRef,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_confirm_prompt     => $ynPrompt,]
        [Cmd_initiated_prompt   => $cmdPrompt,]
        [Timeout                => $secs,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

  ($ok, $outputref[, $resultref]) = $obj->poll_cmd($pkgsub, $cliCommand);

  ($ok, $outputref[, $resultref]) = $obj->poll_cmd($pkgsub,
        [Command                => $cliCommand,]
        [Feed_list              => \@arrayRef,]
        [Prompt                 => $prompt,]
        [Reset_prompt           => $flag,]
        [More_prompt            => $morePrompt,]
        [More_pages             => $numberOfPages,]
        [Cmd_confirm_prompt     => $ynPrompt,]
        [Cmd_initiated_prompt   => $cmdPrompt,]
        [Timeout                => $secs,]
        [Progress_dots          => $bytesPerDot,]
        [Errmode                => $errmode,]
  );

Normally this is the internal method used by cmd(), cmd_prompted() and cmd_poll() methods. Arguments after $ok will only be defined if $ok is true(1).

poll_attribute() - performs a non-blocking poll for attribute()
  $ok = $obj->poll_attribute($pkgsub, $attribute);

  $ok = $obj->poll_attribute($pkgsub,
        [Attribute               => $attribute,]
        [Reload                 => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

  ($ok, $valueref) = $obj->poll_attribute($pkgsub, $attribute);

  ($ok, $valueref) = $obj->poll_attribute($pkgsub,
        [Attribute               => $attribute,]
        [Reload                 => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Normally this is the internal method used by attribute() and attribute_poll() methods. Arguments after $ok will only be defined if $ok is true(1).

poll_change_baudrate() - performs a non-blocking poll for change_baudrate()
  $ok = $obj->poll_change_baudrate($pkgsub, $baudrate);

  $ok = $obj->poll_change_baudrate($pkgsub,
        [BaudRate               => $baudRate,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

  ($ok, $baudrateref) = $obj->poll_change_baudrate($pkgsub, $baudrate);

  ($ok, $baudrateref) = $obj->poll_change_baudrate($pkgsub,
        [BaudRate               => $baudRate,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Normally this is the internal method used by change_baudrate() and change_baudrate_poll() methods. Arguments after $ok will only be defined if $ok is true(1).

poll_enable() - performs a non-blocking poll for enable()
  $ok = $obj->poll_enable($pkgsub, $password);

  $ok = $obj->poll_enable($pkgsub,
        [Password               => $enablePassword,]
        [Prompt_credentials     => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Normally this is the internal method used by enable() and enable_poll() methods.

poll_device_more_paging() - performs a non-blocking poll for device_more_paging()
  $ok = $obj->poll_device_more_paging($pkgsub, $flag);

  $ok = $obj->poll_device_more_paging($pkgsub,
        [Enable                 => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Normally this is the internal method used by device_more_paging() and device_more_paging_poll() methods.

poll_device_peer_cpu() - performs a non-blocking poll for device_peer_cpu()
  $ok = $obj->poll_device_peer_cpu($pkgsub,
        [Username               => $username,]
        [Password               => $password,]
        [Prompt_credentials     => $flag,]
        [Timeout                => $secs,]
        [Errmode                => $errmode,]
  );

Normally this is the internal method used by device_peer_cpu() and device_peer_cpu_poll() methods.

cmdPrivExec() - send a command requiring PrivExec mode
  ($ok, $outputref, $resultref) = $obj->cmdPrivExec($pkgsub, $cmdcli, $cmdnncli, $morePages);

If the connected device is in ACLI mode this method will enter PrivExec mode, if not already in that mode, and then send $cmdnncli; after sending the command, if PrivExec mode was enabled, then this method will disable it to leave the device in exactly the same mode it was found in. If instead the connected device is not in ACLI mode then it will simply send $cmdcli. Arguments after $ok will only be defined if $ok is true(1).

cmdConfig() - send a command requiring Config mode
  ($ok, $outputref, $resultref) = $obj->cmdConfig($pkgsub, $cmdcli, $cmdnncli);

If the connected device is in ACLI mode this method will enter PrivExec mode and then Config mode, if not already in that mode, and then send $cmdnncli; after sending the command, if PrivExec mode and/or Config mode were enabled, then this method will come out of them to leave the device in exactly the same mode it was found in. If instead the connected device is not in ACLI mode then 'config ' is prepended to $cmdcli (if it is not already beginning with 'config ' string) and the resulting command is sent. Arguments after $ok will only be defined if $ok is true(1).

discoverDevice() - discover the family type of connected device
  ($ok, $familyType) = $obj->discoverDevice($pkgsub);

This method will issue CLI commands to the attached device and based on the output received will determine what family type it belongs to. Arguments after $ok will only be defined if $ok is true(1).

debugMsg() - prints out a debug message
  $obj->debugMsg($msgLevel, $string1 [, $stringRef [,$string2]]);

A logical AND is performed between $msgLevel and the object debug level - see debug(); if the result is true, then the message is printed. The message can be provided in 3 chunks: $string1 is always present, followed by an optional string reference (to dump large amout of data) and $string2. If a debug file was set - see debug_file() - then the messages are printed to that file instead of STDOUT.

The above methods are exposed so that sub classing modules can leverage the functionality within new methods themselves implementing polling. These newer methods would have already set up a polling structure of their own. When calling poll_login() directly for the 1st time, it will detect an already existing poll structure and add itself to it (as well as caching some of it's keys; see poll_struct_cache). It will also read in the arguments provided at this point. On subsequent calls, the arguments provided are ignored and the method simply polls the progress of the current task.

CLASS METHODS inherited from Control::CLI

Class Methods which are not tied to an object instance. The Control::CLI::Extreme class expressly imports all of Control::CLI's class methods into itself. However by default Control::CLI::Extreme class does not import anything when it is use-ed. The following list is a sub-set of those Control::CLI class methods. These should be called using their fully qualified package name or else they can be expressly imported when loading this module:

        # Import useTelnet, useSsh, useSerial & useIPv6
        use Control::CLI::Extreme qw(:use);

        # Import promptClear, promptHide & promptCredential
        use Control::CLI::Extreme qw(:prompt);

        # Import parseMethodArgs suppressMethodArgs
        use Control::CLI qw(:args);

        # Import validCodeRef callCodeRef
        use Control::CLI qw(:coderef);

        # Import all of Control::CLI class methods
        use Control::CLI::Extreme qw(:all);

        # Import just poll()
        use Control::CLI::Extreme qw(poll);
useTelnet - can Telnet be used ?
useSsh - can SSH be used ?
useSerial - can Serial port be used ?
useIPv6 - can IPv6 be used with Telnet or SSH ?
poll() - poll objects for completion
promptClear() - prompt for username in clear text
promptHide() - prompt for password in hidden text
promptCredential() - prompt for credential using either prompt class methods or code reference
passphraseRequired() - check if private key requires passphrase
parseMethodArgs() - parse arguments passed to a method against list of valid arguments
suppressMethodArgs() - parse arguments passed to a method and suppress selected arguments
parse_errmode() - parse a new value for the error mode and return it if valid or undef otherwise
stripLastLine() - strip and return last incomplete line from string reference provided
validCodeRef() - validates reference as either a code ref or an array ref where first element is a code ref
callCodeRef() - calls the code ref provided (which should be a code ref or an array ref where first element is a code ref)

AUTHOR

Ludovico Stevens <lstevens@cpan.org>

BUGS

Please report any bugs or feature requests to bug-control-cli-extreme at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Control-CLI-Extreme. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

DISCLAIMER

Note that this module is in no way supported or endorsed by Extreme Inc.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Control::CLI::Extreme

You can also look for information at:

LICENSE AND COPYRIGHT

Copyright 2020 Ludovico Stevens.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.