How to query the NetAPP ONTAP API without using the SDK

netappstorage

I have a bunch of NetApp filers, which I've been accessing via ssh with public-private key pairs.

I would like to extend what I'm doing – we're repeatedly hitting limitations where e.g. ssh is failing to complete commands (disconnnect before execute) and formatting of output from the commands we're running is 'human readable' which means it's annoying to machine parse.

So I'd like to query the API and for various reasons I'd like to do so using 'off the shelf' modules from CPAN, rather than the NetApp SDK.

Can this be done, and if so how?

(I had pondered whether this was a better fit for Stack Overflow, but concluded that it was probably more relevant to sysadmin than perl scripting).

Best Answer

The basics are pretty simple - there's two things you need to copy with:

  • XML
  • http(s)

From CPAN, there are various modules that can do this. I like LWP and XML::Twig.

  • First you need to look up what API you need to access. Usual options will be DFM or filer and various api requests are available. (You may need to download the SDK from: http://mysupport.netapp.com/NOW/download/software/nmsdk/5.3/)
  • Assemble some XML as the request.
  • Send the request
  • Decode the response (XML).

It goes a bit like this:

#!/usr/local/bin/perl

use strict;
use warnings;

use XML::Twig;
use LWP::UserAgent;

my $filer     = 'filername';
my $vfiler    = 'vfilername';
my $user      = 'api-user';
my $pass      = 'api-pass';
my $api_call  = 'volume-list-info';
my %api_param = ( volume => 'vfiler_vol0' );

my $API = '/servlets/netapp.servlets.admin.XMLrequest_filer';
my $url = "https://$filer/$API";

my $xml_request = XML::Twig->new();
$xml_request->set_root(
    XML::Twig::Elt->new(
        'netapp',
        {   version => '1.7',
            vfiler  => $vfiler,
            xmlns   => 'http://www.netapp.com/filer/admin'
        },
    )
);
my $req = $xml_request->root->insert_new_elt($api_call);

foreach my $key ( keys %api_param ) {
    $req->insert_new_elt( $key, $api_param{$key} );
}

$xml_request->set_doctype('netapp SYSTEM "file:/etc/netapp_filer.dtd"');
$xml_request->set_xml_version('1.0');
$xml_request->set_encoding('utf-8');


my $agent = LWP::UserAgent->new(
    ssl_opts => {
        verify_hostname => 0,
        SSL_version     => 'SSLv3'
    }
);

my $request = HTTP::Request->new( POST => $url );
$request->content( $xml_request->sprint );
$request->authorization_basic( $user, $pass );

my $results = $agent->request($request);
if ( $results->is_success ) {

    #do nothing yet
}
else {
    print "Request error:", $results->status_line;
    die;
}
my $results_twig = XML::Twig->new( pretty_print => 'indented' );
$results_twig->parse( $results->content );

#dump the whole thing
$results_twig->print;

print some values selectively. 
foreach my $vol ( $results_twig -> root -> children('volume-info') ) {
    print $vol -> first_child_text('name'), " "; 
    print $vol -> first_child_text('state'),"\n";
}