NAME
    Storage::Nexsan::NMP - The great new way to mange Nexsan's
    programattically!

VERSION
    Version 0.05

SYNOPSIS
    This module ecapsulates version 2.30 of the Nexsan Management Protocol
    (NMP), written to automate some functions of the Nexsan storage device.

    As most commands are relatively atomic, each command will carp if it
    fails, unless specifically otherwise noted.

    This module covers only the following functions:

            Status
            System Information
            Firmware upgrade
            Shutdown
            Rolling Reboot of controllers
            Event Log count
            Turning off MAID
            Setting options via SETOPT/DAT files

    Further work will be done to implement the rest of the NMP as I require
    it, unless anyone wants to pitch in and help...

    Sample code snippet.

    use Storage::Nexsan::NMP;

    say "Connecting to Nexsan: $nexsan, Port: $port"; my %NexsanInfo =
    ConnectToNexsan ($nexsan, $port);

    my $sock = $NexsanInfo{sock};

    say "Nexsan Version: " . $NexsanInfo{NMP}{Major} . "." .
    $NexsanInfo{NMP}{Minor} . "." . $NexsanInfo{NMP}{Patch}; say "Nexsan
    Serial: " . $NexsanInfo{serial};

    #fill in the user and password details, then authenticate
    $NexsanInfo{username} = "ADMIN"; $NexsanInfo{password} = "password";

    AuthenticateNexsan (\%NexsanInfo);

    GetEventCount(\%NexsanInfo); #this will now be populated say "No Of
    Events: $NexsanInfo{eventCount}";

    ShowSystemNexsan(\%NexsanInfo);

    say "Status: $NexsanInfo{status}"; say "model: $NexsanInfo{model}"; say
    "firmware: $NexsanInfo{firmware}"; say "friendlyname
    $NexsanInfo{friendlyname}"; say "vendor: $NexsanInfo{vendor}"; say
    "productid $NexsanInfo{productid}"; say "enclosurenaaid:
    $NexsanInfo{enclosurenaaid}";

    unless (defined $firmware) { die "no firmware value passed\n"; }
    $NexsanInfo{firmwarefile} = $firmware;

    UploadFirmwareToNexsan(\%NexsanInfo);

    close($sock);

TODO
     * Rewrite the functions as OO - at the moment each function copies and pastes some standard functionality which is nasty and should be fixed, but out of TUITS..
     * apply some error checking for correct INI structure in SetOpt()
     * write a specific subroutine for the Powerlevel stanza (see notes in TurnOffMAIDInNexsan() )
     * write tests that tries functions not passing a $nexsan veriable
     * write tests that tries functions not passing a $port variable
     * write a test suite
     * write a Nexsan emulator that returns canned responses for the above test suite (definately in wish list territory here)

EXPORT
    A list of functions that can be exported. You can delete this section if
    you don't export anything, such as for a purely object-oriented module.

SUBROUTINES/METHODS
  ConnectToNexsan
    MUST be passed IP/fqdn of Nexsan & then MAY be passed port no

    Returns hash with following (example) information (thanks to
    Data::Dumper!);

    $VAR1 = 'banner';

    $VAR2 = '220 <237C2F1C> SATABeast2-059955A0-0 NMP V2.3.0 ready ';

    $VAR3 = 'serial';

    $VAR4 = '237C2F1C';

    $VAR5 = 'NMP';

    $VAR6 = { 'Minor' => '3', 'Major' => '2', 'Patch' => '0' }; $VAR7 =
    'sock';

  WriteLog
    internal (i.e. not exported) function that takes the %NexsanInfo hash,
    and prepends nexan name/ip and date/time to the ususal 'say' output.

    it assumes that ConnectToNexsan has been run, but nothing else.

  ConnectToNexsan
    Initial setup internal function used by all the utility functions to
    setup the telnet conenction

  AuthenticateNexsan
    Authenticates to the NMP, without which any command but QUIT will fail.

    MUST be passed hash containing socket, username and password pairs, e.g.

    $NexsanInfo{sock} $NexsanInfo{username} $NexsanInfo{password}

    croak's on failure of username or password to authenticate, as you can't
    do much without being logged in

  GetEventCount
            #MUST be passed a reference to a hash containing socket
        
            It will update the hash passed with a name:value pair called eventCount.
            It can be called as many times as you wish.

  ShowSystemNexsan
            MUST be passed an reference to a hash that contains a socket, and the AuthenticateNexsan 
                    subroutine must have been run beforehand to populate the other required hash's
        
            Populates hash with the following name:value pairs;
            Parameter                       Description
            <status>                        Status of the RAID system (“HEALTHY”, “FAULT”)
            <serial>                        Serial number of the RAID system (8 hexadecimal digits)
            <model>                         Model name of the RAID system
            <firmware>                      Firmware version of the RAID system
            <friendlyname>          User-defined friendly name of the RAID system
            <vendor>                        “T10 Vendor Identification” field as reported in SCSI INQUIRY data [NMP 2.2.0]
            <productid>                     “Product Identification” field as reported in SCSI INQUIRY data [NMP 2.2.0]
            <enclosurenaaid>        “Enclosure NAA identifier” field as reported in SCSI INQUIRY VPD page 0x83 identifier type 3 [NMP 2.2.0]

  UploadFirmwareToNexsan
            Uploads a firmware file to the Nexsan. Requires NMP 2.3.0 or later - and this routine
                    checks for that, although it is safe to issue this command to an earlier version, as 
                    it will safely reject the command, according to the developer. :-)
        
            MUST be passed an reference to a hash that contains a socket, and the AuthenticateNexsan 
                    subroutine must have been run beforehand to populate the other required hash's
            MUST have 
            MUST have firmware filename passed in the above hash in the above hash's firmwarefile 
                    name:value, e.g. $NexsanInfo->{firmware}->{filename} .
        
            NOTE: DOES NOT reboot the system after the upgrade; you need to use another function to do that!

  ShutdownNexsan
    To quote the NMP Reference Manual (v.2.3.0); "This command will perform
    a shutdown of the RAID system , the NMP connection will be closed. All
    cached data will be flushed to the disks, it is advised all host IO is
    stopped before this command is used. There are circumstances where
    shutdown is blocked (such as during a firmware update), these scenarios
    can be detected from the returned response."

  RollingRebootNexsan
    To quote the NMP Reference Manual (v.2.3.0); "This command will perform
    a rolling restart of the RAID system , the NMP connection will be
    closed. Each controller is restarted in turn and therefore should
    minimize the amount time the storage is inaccessible. There are
    circumstances where rolling restart is blocked (such as during a
    firmware update), these scenarios can be detected from the returned
    response."

  TurnOffMAIDOnNexsan
            #MUST be passed a reference to a hash containing socket
        
            This uses the SETOPT command to add the following MAID entry, as if it were uploaded 
            via a settings.dat file;
        
            [PowerConfig]
            PowerLevel1 = 2 ; 0, 2, 5 minutes
            PowerLevel2 = 0 ; 0, 10, 20, 30, 40, 50, 60 minutes
            PowerLevel3 = 0 ; 0, 15, 30, 60, 90, 120 minutes
            MaxSpareLevel = 2 ; 0, 1, 2, 3

            ASSUMPTION: that PowerLevel4 is not configured..

  importDatFile
    Import an .ini file (called .dat by Nexsan) that provides many
    confuguration options. The idea is that it can be used by another
    function to then upload a atandard config, replicating the behaviour of
    the GUI.

    Requires a filename scalar passed to it, and returns a hash reference,
    for e.g.;

    $HASH1 = { ActiveActive => { ActiveActiveMode => 'APAL' }, Cache => {
    AllowSCSIOverride => 'Disabled', Cache => 'Enabled', CacheTuning =>
    'Mixed', IgnoreForceUnitAccess => 'Enabled', Mirroring => 'Enabled',
    ReadStreamMode => 'Disabled', StreamingMode => 'Disabled' }, SYSLOG => {
    Facility => 'LOCAL0', SendToIP => '172.17.9.9', UDPPort => 514,
    WhenToSend => 'All' } };

  SetOpt
    using the importDatFile internal function, apply a number of Nexsan Dat
    file stanza's.

    The sub expects $NexsanInfo->{datfile} populated with the name of the
    dat file to import.

    Note: no error checking is done on the hash to see it contains a correct
    INI structure as it assumes that its been imported from an Nexsan
    created/modified DAT file. Given the SETOPT command if not passed the
    write information, this is relatively low risk

     TODO apply some error checking for correct INI structure, as above!
     TODO write a specific subroutine for the Powerlevel stanza 
            (see notes in TurnOffMAIDInNexsan)

AUTHOR
    John Constable, "<john.constable at sanger.ac.uk>"

BUGS
    Please report any bugs or feature requests to "bug-storage-nexsan-nmp at
    rt.cpan.org", or through the web interface at
    <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Storage-Nexsan-NMP>. I
    will be notified, and then you'll automatically be notified of progress
    on your bug as I make changes.

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

        perldoc Storage::Nexsan::NMP

    You can also look for information at:

    *   RT: CPAN's request tracker (report bugs here)

        <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Storage-Nexsan-NMP>

    *   AnnoCPAN: Annotated CPAN documentation

        <http://annocpan.org/dist/Storage-Nexsan-NMP>

    *   CPAN Ratings

        <http://cpanratings.perl.org/d/Storage-Nexsan-NMP>

    *   Search CPAN

        <http://search.cpan.org/dist/Storage-Nexsan-NMP/>

ACKNOWLEDGEMENTS
    James Peck at Nexsan dot com for helping approve the release of this and
    answering inumerable questions Carl Elkins at sanger dot ac dot uk for
    allowing me the time to write this

LICENSE AND COPYRIGHT
    Copyright 2011 John Constable.

    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.

