NAME
    Net::Appliance::Session - Run command-line sessions to network
    appliances

VERSION
    This document refers to version 0.17 of Net::Appliance::Session.

SYNOPSIS
     use Net::Appliance::Session;
     my $s = Net::Appliance::Session->new('hostname.example');

     eval {
         $s->connect(Name => 'username', Password => 'loginpass');
         $s->begin_privileged('privilegedpass');
         print $s->cmd('show access-list');
         $s->end_privileged;
     };
     if ($@) {
         $e = Exception::Class->caught();
         ref $e ? $e->rethrow : die $e;
     }

     $s->close;

DESCRIPTION
    Use this module to establish an interactive command-line session with a
    network appliance. There is special support for moving into "privileged"
    mode and "configure" mode, with all other commands being sent through a
    generic call to your session object.

    There are other CPAN modules that cover similar ground, including
    Net::SSH and Net::Telnet::Cisco, but they are less robust or do not
    handle SSH properly. Objects created by this module are based upon
    Net::Telnet so the majority of your interaction will be with methods in
    that module. It is recommended that you read the Net::Telnet manual page
    for further details.

    This module natively supports connections via SSH, Telnet and a Serial
    Port. All commands can be overridden from the built-in Cisco defaults in
    order to support other target devices; the connection process (user
    log-in) is similarly configurable.

METHODS
    Objects created by this module are based upon Net::Telnet so the
    majority of your interaction will be with methods in that module.

  "Net::Appliance::Session->new"
    Like Net::Telnet you can supply either a single parameter to this method
    which is used for the target device hostname, or a list of named
    parameters as listed in the Net::Telnet documentation. Do not use
    "Net::Telnet"'s "Errmode" parameter, because it will be overridden by
    this module.

    The significant difference with this module is that the actual
    connection to the remote device is delayed until you "connect()".

    Named Parameters, passed as a hash to this constructor, are optional.
    Some are described in "TRANSPORTS" and "CONFIGURATION" below. Any others
    are passed directly to Net::Telnet (which dies on unknown parameters).

    This method returns a new "Net::Appliance::Session" object.

  "connect"
    When you instantiate a new Net::Appliance::Session object the module
    does not actually establish a connection with the target device. This
    behaviour is slightly different to Net::Telnet and is because the
    Transport may need to have login credentials before a connection is made
    (e.g. in the case of SSH). Use this method to establish that interactive
    session.

    Parameters to this method are determined by the Transport (SSH, Telnet,
    etc) that you are running. See the Net::Appliance::Session::Transport
    manual page for further details.

    In addition to logging in, "connect" will also disable paging in the
    output for its interactive session. This means that unlike
    Net::Telnet::Cisco no special page scraping logic is required in this
    module's code. This feature can be disabled (see "CONFIGURATION",
    below).

  "begin_privileged"
    To enter privileged mode on the device use this method. Of course you
    must be connected to the device using the "connect" method, first.

    All parameters are optional, and if none are given then the login
    password will be used as the privileged password.

    If one parameter is given then it is assumed to be the privileged
    password.

    If two parameters are given then they are assumed to be the privileged
    username and password, respectively.

    If more than two parameters are given then they are interepreted as a
    list of named parameters using the key names "Name" and "Password" for
    the privileged username and password, respectively.

  "end_privileged"
    To leave privileged mode and return to the unpriviledged shell then use
    this method.

  "in_privileged_mode"
    This method will return True if your interactive session is currently in
    privileged (or configure) mode, and False if it is not.

  "begin_configure"
    In order to enter configure mode, you must first have entered privileged
    mode, using the "begin_privileged" method described above.

    To enter configure mode on the device use this method.

  "end_configure"
    To leave configure mode and return to privileged mode the use this
    method.

  "in_configure_mode"
    This method will return True if your interactive session is currently in
    configure mode, and False if it is not.

  "cmd"
    Ordinarily, you might use this "Net::Telnet" method in scalar context to
    observe whether the command was successful on the target appliance.
    However, this module's version "die"s if it doesn't think everything
    went well. See "DIAGNOSTICS" for tips on managing this using an "eval{}"
    construct.

    The following error conditions are checked on your behalf:

    *   Incomplete command output, it was cut short for some reason

    *   Timeout waiting for command response

    *   EOF or other anomaly received in the command response

    *   Error message from your appliance in the response

    If any of these occurs then you will get an exception with appropriately
    populated fields. Otherwise, in array context this method returns the
    command response, just as "Net::Telnet" would. In scalar context the
    object itself returned.

    The only usable method arguments are "String", "Output" and "Timeout",
    plus as a special case, "Match". The "Match" named argument takes in an
    *array reference* a list of one or more strings representing valid Perl
    pattern match operators (e.g. "/foo/"). Therefore, the "cmd()" method
    can check against the default command prompt, built-in error strings,
    and also a custom response of your choice at the same time.

    Being overridden in this way means you should have less need for the
    "print()" and "waitfor()" methods of "Net::Telnet", although they are of
    course still available should you want them.

  "close"
    This "Net::Telnet" method has been overridden to automatically back out
    of configure and/or privilege mode, as well as re-enable paging mode on
    your behalf, as necessary.

  "error"
    Rather than following the "Net::Telnet" documentation, this method now
    creates and throws an exception, setting the field values for you. See
    "DIAGNOSTICS" below for more information, however under most
    circumstances it will be called automatically for you by the overridden
    "cmd()" method.

TRANSPORTS
    This module supports interactive connections to devices over SSH, Telnet
    and via a Serial Port. The default is to use SSH, so to select an
    alternative, pass an optional "Transport" parameter to the "new()"
    constructor:

     my $s = Net::Appliance::Session->new(
         Host      => 'hostname.example',
         Transport => 'Serial',
     );

    Whatever transport you are using, it is highly recommended that you read
    the relevant manual page. The Net::Appliance::Session::Transport manual
    is a good starting place.

CONFIGURATION
  Log-in
    In the default case, which is SSH to a Cisco IOS device, both a Username
    and Password are required and a full log-in is made (i.e. the device
    presents a Password prompt, and so on).

    However, some devices require no login. Examples of this might be a
    Public Route Server, or a device connected via a Serial Port. In that
    situation, use the following object method *before* calling "connect()":

   "do_login"
    Passing any False value to this method prevents "connect()" from
    expecting to have to negotiate a log-in to the device. Most Transports
    in that case do not require the Password parameter, although a Username
    might still be required. By default log-in negotiation is enabled.

  Paging
    In the default case, Net::Appliance::Session expects that command output
    paging is enabled on the device. This is where response to commands is
    "paged", having only (e.g.) 24 lines printed at a time, and you press
    the Enter or Space key to see more.

    With automated interaction this is useless, and error-prone, so
    Net::Appliance::Session by default will send a command to disable paging
    straight after it connects, and re-enable it as part of "close()".

    To override the pager management command itself, you will need to edit
    the phrasebook (see below). The following object methods alter other
    aspects of pager management:

   "do_paging"
    Passing any False value to this method prevents "connect()" and
    "close()" from respectively disabling and re-enabling paging on the
    device. By default paging management is enabled.

   "set_pager_disable_lines"
    Net::Appliance::Session assumes that the command to disable the pager
    just re-sets the number of paging lines. Pass this method a new value
    for that number, which has a default of zero in the module.

   "set_pager_enable_lines"
    Likewise, to re-enable paging Net::Appliance::Session will call the
    pager management command with a value for the number of output lines per
    page. Pass this method a value to override the default of 24.

  Command mode
    If your target device does not have the concept of "privileged exec" or
    "configure" mode, then just don't call the methods to change into those
    modes.

    However, there is a catch. If your device separates only configure mode,
    then when you try to call "begin_configure()" straight after a log-in,
    the module will complain, because it thinks you need to ask for a
    "begin_privileged" first. Also, when disconnecting,
    Net::Appliance::Session will attempt to step out of privileged and
    configure modes, so if they don't apply you will want to disable those
    steps.

    To alter all this behaviour, use the following object methods.

    If you are trying to subvert this module to just automate interaction
    with a CLI via SSH, Telnet or Serial Line on a strange kind of device,
    then these methods will be useful (as well as "do_paging", above).

   "do_privileged_mode"
    If you pass a False value to this method, then Net::Appliance::Session
    will believe you are in some kind of privileged mode as soon as you log
    in. The net effect is that you can now safely call "begin_configure()".
    The default is to actively gatekeep access to privileged mode.

   "do_configure_mode"
    By passing a False value to this method you also make
    Net::Appliance::Session believe you are in configure mode straight after
    entering privileged mode (or after log in if "do_privileged_mode" is
    also False). The default is to actively gatekeep access to configure
    mode.

  Commands and Prompts
    Various models of network device, either from one vendor such as Cisco
    or between vendors, will naturally use alternate command and command
    prompt syntax. Net::Appliance::Session does not hard-code any of these
    commands or pattern matches in its source. They are all loaded at
    run-time from an external phrasebook (a.k.a. dictionary), which you may
    of course override.

    The default operation of Net::Appliance::Session is to assume that the
    target is running a form of Cisco's IOS, so if this is the case you
    should not need to modify any settings.

    Limited support is also available, via the "Net::Appliance::Phrasebook"
    module, for the following operating systems:

     IOS     # the default
     Aironet # currently the same as the default

     CATOS   # for older, pre-IOS Cisco devices
     PIXOS   # for PIX OS-based devices (including FWSM Release 2.x)
     FWSM    # currently the same as 'PIXOS'
     FWSM3   # for FWSM Release 3.x devices (slightly different to FWSM 2.x)

    To select a phrasebook, pass an optional "Platform" parameter to the
    "new" method like so:

     my $s = Net::Appliance::Session->new(
         Host     => 'hostname.example',
         Platform => 'FWSM3',
     );

    If you want to add a new phrasebook, or override an existing one, there
    are two options. Either submit a patch to the maintaner of the
    "Net::Appliance::Phrasebook" module, or read the manual page for that
    module to find out how to use a local phrasebook rather than the builtin
    one via the "Source" parameter (which is accepted by this module and
    passed on verbatim).

     my $s = Net::Appliance::Session->new(
         Host     => 'hostname.example',
         Source   => '/path/to/file.yml',
         Platform => 'MYDEVICE',
     );

    In this way, you can fix bugs in the standard command set, adjust them
    for your own devices, or "port" this module onto a completely different
    appliance platform (that happens to provide an SSH, Telnet or Serial
    Port CLI).

    Some sanity checking takes place at certain points to make sure the
    phrasebook contains necessary phrases. If overriding the phrasebook,
    you'll need to provide at least the "basic_phrases" as set in this
    module's source code. If using Privileged and Configure mode, there are
    "privileged_phrases" and "configure_phrases" that will be required,
    also. Paging requires a "pager_cmd" phrase to be available. See the
    source code of Net::Appliance::Phrasebook for examples.

    If you fancy yourself as a bit of a cowboy, then there is an option to
    "new()" that disables this checking of phrasebook entries:

     my $s = Net::Appliance::Session->new(
         Host     => 'hostname.example',
         Platform => 'MYDEVICE',
         Source   => '/path/to/file.yml', # override phrasebook completely
         CheckPB  => 0, # squash errors about missing phrasebook entries
     );

    You better have read the source and checked what phrases you need before
    disabling "CheckPB". Don't say I didn't warn you.

DIAGNOSTICS
    Firstly, if you want to see a copy of everything sent to and received
    from the appliance, then something like the following will probably do
    what you want:

     $s->input_log(*STDOUT);

    All errors returned from Net::Appliance::Session methods are Perl
    exceptions, meaning that in effect "die()" is called and you will need
    to use "eval {}". The rationale behind this is that you should have
    taken care to script interactive sessions robustly, and tested them
    thoroughly, so if a prompt is not returned or you supply incorrect
    parameters then it's an exceptional error.

    Recommended practice is to wrap your interactive session in an eval
    block like so:

     eval {
         $s->begin_privileged('password');
         print $s->cmd('show version');
         # and so on...
     };
     if ( UNIVERSAL::isa($@,'Net::Appliance::Session::Exception') ) {
         print $@->message, "\n";  # fault description from Net::Appliance::Session
         print $@->errmsg, "\n";   # message from Net::Telnet
         print $@->lastline, "\n"; # last line of output from your appliance
         # perform any other cleanup as necessary
     }
     $s->close;

    Exceptions belong to the "Net::Appliance::Session::Exception" class if
    they result from errors internal to Net::Telnet such as lack of returned
    prompts, command timeouts, and so on.

    Alternatively exceptions will belong to "Net::Appliance::Session::Error"
    if you have been silly (for example missed a method parameter or tried
    to enter configure mode without having first entered privileged mode).

    All exception objects are created from "Exception::Class" and so
    stringify correctly and support methods as described in the manual page
    for that module.

    "Net::Appliance::Session::Exception" exception objects have two
    additional methods (a.k.a. fields), "errmsg" and "lastline" which
    contain output from Net::Telnet diagnostics.

INTERNALS
    The guts of this module are pretty tricky, although I would also hope
    elegant, in parts ;-) In particular, the following "Net::Telnet" method
    has been overridden to modify behaviour:

  "fhopen"
    The killer feature in "Net::Telnet" is that it allows you to swap out
    the builtin I/O target from a standard TELNET connection, to another
    filehandle of your choice. However, it does so in a rather intrusive way
    to the poor object, so this method is overridden to safeguard our
    instance's private data.

DEPENDENCIES
    Other than the contents of the standard Perl distribution, you will need
    the following:

    *   Exception::Class

    *   Net::Telnet

    *   IO::Pty

    *   UNIVERSAL::require

    *   Class::Accessor >= 0.25

    *   Class::Accessor::Fast::Contained

    *   Net::Appliance::Phrasebook >= 0.07

AUTHOR
    Oliver Gorwits "<oliver.gorwits@oucs.ox.ac.uk>"

ACKNOWLEDGEMENTS
    Parts of this module are based on the work of Robin Stevens and Roger
    Treweek. The SSH command spawning code was based on that in "Expect.pm"
    and is copyright Roland Giersig and/or Austin Schutz.

COPYRIGHT & LICENSE
    Copyright (c) The University of Oxford 2006. All Rights Reserved.

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

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
    Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

