Application Integration
1748074 Members
5065 Online
108758 Solutions
New Discussion юеВ

Sample Python class for working with the Nimble Storage REST API

 
casey_crawford
New Member

Sample Python class for working with the Nimble Storage REST API

GitHub - caseycrawford/nimblestorage_python: Nimble Storage Python examples using API

At Capella University we recently introduced 6 individual CS700s (no grouping) connected by fiber channel. We use a much more robust Python class like this in our automated processes alongside UCS SDK and Custom Fabric MDS wrapper. This is a stripped down version I have been re-writing in my spare time to give other people a basic framework to start automating their Nimble Storage environments. You will find bugs! I will try to add and fix what I can, but would appreciate any contributions/fixes/logging.


The more people that rely and make operational demands of the Nimble Storage REST API, the more resources they will apply to the API development team(s).

Current Nimble RFE(s)

"Update initiator alias with API." - Allow Initiator's aliases to be renamed through the API (there is a workaround in the GUI). This would only be an issue for you if you are constantly recycling WWPNs (Cisco UCS blades).

"ALL/DETAIL endpoint for snapshots" - Get limited amounts of information about every snapshot on the array (instead of having to loop through every volume and running a query for each volume)

Bruce Kyro

Brian Knopp

Robert Regan

Thank you,

- Casey Crawford

9 REPLIES 9
Dave_Rich
Occasional Advisor

Re: Sample Python class for working with the Nimble Storage REST API

Beautiful work! I wish I would have found this a day earlier as I already started automating some of our tasks with python and writing  my own 'class'. I really need to jump to the next level here and start building classes for my work but alas, thank you for yours!

I will work on getting some of my code on a github to contribute here and now especially using your class, it will be a breeze!

Dave_Rich
Occasional Advisor

Re: Sample Python class for working with the Nimble Storage REST API

Casey,

After integrating your class into my work, I have my first suggestion. I dont know if this is the correct place or not but I will post here for now. Im comfortable with github but I have not contributed to a project in the past and I am unsure of the etiquette.

My discovery came after an attempt to retrieve all of our initiators for a given array and I noticed I was getting 'None' on the returns. After some digging through your code I have noticed that during most of the 'GET' functions where you are building the dictionaries, you iterate through the nimble JSON data and filter on a secondary key. In our arrays, pre 2.3 I believe, you were not required to have an 'alias' for the initiator, thus the reason for the 'None' results. Once switching the 'alias' key for 'iqn' or any number of other keys, I can get my results.

My suggestion would be to continue filtering on 'data' as I have done the exact same with my own work but dumping the entire data JSON dict into your corresponding dict to allow the user to access the entire dataset.

For example.


def initiator_read(self):


        request_json = self.query(request_type = 'read', request_endpoint = 'initiators/detail')


        for item in request_json['data']:


            self.dict_initiators[item['alias']] = item


this assumes the users arrays have an alias defined and limits the amount of returnable data to work with. I propose


def initiator_read(self):


        request_json = self.query(request_type = 'read', request_endpoint = 'initiators/detail')


        self.dict_initiators = request_json['data']


what do you think?

I have slightly modified your class to work this way for the code I want to publish. Im not sure how the approval for this works?

casey_crawford
New Member

Re: Re: Sample Python class for working with the Nimble Storage REST API

Right now I don't know if the class should only return/load Nimble's 'data' structure (as you suggested), or if it should be doing normalizing (human readable names) like I am dependent on right now in the automation i'm doing (or perhaps those dictionaries should be generated by other functions for 'initiator_dict_by_id', 'initiator_dict_by_alias')?

How about a mix of both for now? If your alias is None then it's placed into the dictionary by it's ID so at the very least you can generate a report of all of your initiators?


    def initiator_read(self):


        request_json = self.query(request_type = 'read', request_endpoint = 'initiators/detail')


        for item in request_json['data']:


            if item['alias'] == None:


                self.dict_initiators[item['id']] = item


            else:


                self.dict_initiators[item['alias']] = item


Added into github for you: https://github.com/caseycrawford/nimblestorage_python/commit/9ce55b9d3971bbaa35671bd67f2c1adcdedc4db9

Thank you for finding this bug... I am sure you're going to find more as you go on. I am completely open to any changes, additions... make any pull requests you think would help other Nimble customers.

- Casey Crawford

Dave_Rich
Occasional Advisor

Re: Re: Re: Sample Python class for working with the Nimble Storage REST API

That is the big question, to normalize or dump the raw data structure and a case can be made for each.

Another question/suggestion I have is in regards to your assigning the returned JSON to an internal class dictionary. This may be my ignorance here, but the only way I could find a way to get the data back to my script, was to hunt down the dictionary name you use and then reference that directly in my code as follows:


nimble.initiator_read()


print nimble.dict_initiators



Would it be possible to allow a return of all 'read' functions and still have the internal dictionary assignment for class function work? My sample code looks as follows and works fine:


for item in request_json['data']:


     if item['alias'] == None:


          self.dict_initiators[item['id']] = item


    else:


          self.dict_initiators[item['alias']] = item


return self.dict_initiators   



and that allows me to do this:


initiators = nimble.initiator_read()


print initiators



and lastly, for some reason (I have yet to dig hard) the new additional code you posted does not seem to be appending to the dictionary for my arrays and only returns the last iter of item.

Im trying to educate myself on how to work with people on their public Git so we dont have to keep the conversation going here. Or if you dont mind, we can... either or.

My first script is almost ready to publish here so Im trying to iron out these last bits in the class.

edit!

it only returns the last iter because ' == None' cannot be true because the 'alias' key is returning an empty string, not "None".

Recommending change as follows:


for item in request_json['data']:


     if not item['alias']:


          self.dict_initiators[item['id']] = item


     else:


          self.dict_initiators[item['alias']] = item


return self.dict_initiators


Works beautifully and I can grab my IQN

casey_crawford
New Member

Re: Re: Re: Sample Python class for working with the Nimble Storage REST API

I've updated the code to 'if not item['alias']' and it's up on github.

As for the internal data structure, we use it this way here at Capella so that if you start doing operations that same dictionary is constantly being updated/refreshed with the latest information (if you add 20 initiators, they will be in that dictionary at the end so you can do validation, etc).

In your workflow you would have to re-run initiators = nimble.initiator_read()

Either way we can still return the json dictionaries whenever it's ran-- that is not a problem. You might have to wait until later in the week unless you plan on doing it yourself and pushing it?

- Casey Crawford

Dave_Rich
Occasional Advisor

Re: Re: Re: Sample Python class for working with the Nimble Storage REST API

No thats fine, I like that they keep updating with your structure. Thanks for the quick responses so far! Eventually, I will learn the maze of public forking/contribution to projects I run my own gitlab and all that fun stuff but Im still a n00b when it comes to public work.

Thanks again!

davidbaril127
Advisor

Re: Sample Python class for working with the Nimble Storage REST API

Hi Casey,

Thank you for your work creating a Python class for the Nimble REST API.

Several months have gone by and I have been surprised that there have been no comments from Nimble related to an "official" Python class for the Nimble API ... perhaps not unlike the PowerShell Toolkit that Nimble created for Windows PowerShell users.

Has anyone heard any news about Python/REST API topics from Nimble?

I am planning on creating a relatively simple script to switch a Nimble volume from one Linux server to another Linux server to provide a poor-man's-failover capability.  I hope to use your Python class to jumpstart my work on that script.

Thanks again, Casey for taking the time to contribute your work.

Regards,

Dave B.

SKDineshkumar
Occasional Visitor

Re: Sample Python class for working with the Nimble Storage REST API

Thank you Casey for bringing up the Python class which is really really helpful.

Can someone help me find the endpoint for collecting the CPU utilization of the array?

Thanks,

Dineshkumar S

tonyp11
Occasional Collector

Re: Sample Python class for working with the Nimble Storage REST API

Did you happen to see the nimble.py that was included with openstack pike,queens,rocky,stein ?

https://github.com/NetApp/cinder/blob/master/cinder/volume/drivers/nimble.py