Software Development Kit (SDK) and API Discussions

Example: How to use perf-object-get-instances to get specific statistics in Perl

chayashida
9,101 Views

I was wrestling with the NetApp Management SDK and Perl, and having lots of problems finding documentation and examples in one place. Since I did all the work, I thought I'd share what I found.

I am a competent Perl programmer, and I learned object-oriented programming (C++) in school, but I was having a lot of problems with the NetApp Manageability SDK. I was able to find a list of APIs and ONTAP APIs on the web site, but didn't have a good starting point.

I wanted to get specific NFS version 3 statistics, but not have the filer return all the information and be forced to parse through all the data. I wanted only the following statistics:

  • nfsv3_ops
  • nfsv3_read_latency
  • nfsv3_read_ops
  • nfsv3_write_latency
  • nfsv3_write_ops

From the ONTAP API documentation, I found that perf-objects-get-instances took the following arguments:

Input Name
Type
Description
counterscounter[] optionalList of counters whose values will be retrieved. This element can be used to limit data collection to a specified subset of the counters of instances of the object. If this element is absent, values of all counters will be retrieved.
instancesinstance[] optionalList of the instance names for which to get counter values. This element can be used to limit data collection to a specific subject of the instances of the object. In Data ONTAP 7-Mode, counter values of all instances of the object will be retrieved when this element is absent. In Data ONTAP Cluster-Mode, either instances or instance-uuids input must be provided. The API errors out if both of these inputs are provided or neither of these inputs is provided, or if more than 500 instances are requested.
objectnamestringName of the object to get counter values for.

I was able to get all the data using the invoke() method:

...

my $filer = NaServer -> new ($server, $majorversion, $minorversion);

$filer -> set_style ('HOSTS');

my $result = NaElement -> new ();

$result = $filer -> invoke ('perf-object-get-instances', 'objectname', 'nfsv3');

print $result -> sprintf()

...

When I searched online, I found a lot of people had the same problem. Instead of limiting the results they were receiving, they were iterating through the results and only taking the data that they needed. That's not what I wanted to do. I thought it was too inefficient, especially if my script was going to be called frequently. It also didn't feel right.

The problem was that I couldn't figure out how to pass the arguments for the counter[] array or the instance[] array. (I didn't need the instance[] array in this case, but I assumed that the mechanics were the same.) I was looking for Perl-ish ways to pass the variables.

These did NOT work:

  • Anonymous arrays

...

my $result = NaElement -> new ();

$result = $filer -> invoke ('perf-object-get-instances', 'counters', [ 'nfsv3_ops', 'nfsv3_read_latency', 'nfsv3_read_ops', 'nfsv3_write_latency', 'nfs_write_ops' ], 'objectname', 'nfsv3');

...

  • References to arrays

...

my @counters = ('nfsv3_ops', 'nfsv3_read_latency', 'nfsv3_read_ops', 'nfsv3_write_latency', 'nfs_write_ops');

my $result = NaElement -> new ();

$result = $filer -> invoke ('perf-object-get-instances', 'counters', \@counters, 'objectname', 'nfsv3');

...

I found a similar post, but for Ruby, here: https://communities.netapp.com/message/85133

I don't know Ruby, but reading that post helped me figure out that I needed to create an object.

Here's code that works:

...

my $filer = NaServer -> new ($server, $majorversion, $minorversion);

 

$filer -> set_style ('HOSTS');

 

my $command = NaElement -> new ('perf-object-get-instances');

 

my $counters = NaElement -> new ('counters');

$counters -> child_add_string('counter', 'nfsv3_ops');

$counters -> child_add_string('counter', 'nfsv3_read_latency');

$counters -> child_add_string('counter', 'nfsv3_read_ops');

$counters -> child_add_string('counter', 'nfsv3_write_latency');

$counters -> child_add_string('counter', 'nfsv3_write_ops');

$command -> child_add($counters);

 

$command -> child_add_string ('objectname', 'nfsv3');

   

my $result = NaElement -> new ();

$result = $filer -> invoke_elem ($command);

 

print $result -> sprintf(); # Outputs XML-formatted results

...

Basically, what you are doing is building a $command object that will run the perf-object-get-instances command.

After the main object was created, I created another object, $counters. I started adding the data I wanted to the $counters object. Each statistic I wanted was added to the $counters object, as a type/statistic pair. After the $counters object was complete, I added it as a child to the $command object.

Since I didn't have any instances that I wanted to add, I didn't have to create an $instances object. If I did want one, I would have created another NaElement object and configured it in the same way.

Finally, I needed to add the object name at the end. In this case, I'm not adding another NaElement object. This time, it's just a string. I added a string of type objectname with the value nfsv3.

When I actually run the command, I need to use the invoke_elem() method instead of the invoke() method that was in the previous script.

Anyway, I took the time to write this up in the hopes that it will help someone else. (I suspect that I'll probably forget how to do this, and I'll be the one that's going online to look for this solution. )

So, if you got this far, I hope this helps.

Chris Hayashida

4 REPLIES 4

kunalm
9,101 Views

Chris

This is very useful. Thanks for the brilliant contribution.

Moving it to more visible area in communities.

-Kunal

VIEMEARD
9,101 Views

Hi Chris,

I am also grappling with similar issues

Do you know if there is a description of what each of the NFS counters mean ? I.e when we poll the nfsv3_ops counter, it is increasing until no NFS clients are connected. Is it sufficient to assume then that nfsv3_ops is a count of total ops done until the point in time when that call was made to read the counter ?

Regards,

--

Gagan Grewal

DOUGLASSIGGINS
9,101 Views

I found this information very useful for digging the nfsv3 latencies out. However without the information from:

https://communities.netapp.com/servlet/JiveServlet/previewBody/1044-102-1-1022/Performance_Management_DesignGuide.pdf

Check out page 12-13. That will detail how to use these counters. You will need the 'avg base' counters to figure the latencies out.

$counters -> child_add_string('counter', 'nfsv3_ops');

$counters -> child_add_string('counter', 'nfsv3_read_latency');

$counters -> child_add_string('counter', 'nfsv3_avg_read_latency_base');

$counters -> child_add_string('counter', 'nfsv3_read_ops');

$counters -> child_add_string('counter', 'nfsv3_write_latency');

$counters -> child_add_string('counter', 'nfsv3_avg_write_latency_base');

$counters -> child_add_string('counter', 'nfsv3_write_ops');

chayashida
9,101 Views

Hi Doug,

Thanks for replying to this for me. I didn't have e-mail notifications turned on, so I didn't see Gagan's question.

Gagan,

I was porting another script that used the NFS counters, so I just copied the SNMP information verbatim. I don't know much about the counters, but I hope Doug's answer helps you.

Chris

Public