Network Change & Configuration Management

Reply

Using methods on the REST API that returns a 1 to many dictonary

Authority
Posts: 20
2365     1

I have a script I am working on that utilizes the device methods if_addrs and interfaces. The goal is to initially just format the export to make is human readable to get a list of interfaces, ip, descriptions etc from NetMRI. I am having some issues with how to handle formating the dictionary because the response using the methods is a 1 to many and nested. I am not getting the results I expected.

 

 

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#
import argparse
import netaddr
import os
import urllib3
import infoblox_netmri
import getpass
import sys
#
# We are using a cert that this box does not know about
# This disable trust warnings
#

class PasswordPromptAction(argparse.Action):
    def __init__(self,
             option_strings,
             dest=None,
             nargs=0,
             default=None,
             required=False,
             type=None,
             metavar=None,
             help=None):
        super(PasswordPromptAction, self).__init__(
             option_strings=option_strings,
             dest=dest,
             nargs=nargs,
             default=default,
             required=required,
             metavar=metavar,
             type=type,
             help=help)

    def __call__(self, parser, args, values, option_string=None):
        password = getpass.getpass()
        setattr(args, self.dest, password)


parser = argparse.ArgumentParser()
parser.add_argument("--usr", required=True, dest='user', help='Enter your NetMRI userID')
parser.add_argument("--pwd", required=True, dest='argpwd', action=PasswordPromptAction,  help='Hit enter and supply')
args = parser.parse_args()

urllib3.disable_warnings()

host = os.environ['NETMRI_HOST']
user = args.user
password = args.argpwd
use_ssl = os.environ['NETMRI_USE_SSL']
api_version = os.environ['NETMRI_API_VERSION']
ssl_verify = os.environ.get('NETMRI_SSL_VERIFY')

c = infoblox_netmri.InfobloxNetMRI(
    host=host,
    username=user,
    password=password,
    api_version=api_version,
    use_ssl=use_ssl,
    ssl_verify=ssl_verify
)


#
#

devices = c.api_request('devices/index/?methods=if_addrs%2Cinterfaces', {'timeout': 10, 'limit': 1000})

print devices.keys()

#print devices

FORMAT='%20s %20s %20s'
for d in devices['devices']:
  print FORMAT % (d['DeviceName'], d['DeviceIPDotted'], d['ifIPDotted'])

Re: Using methods on the REST API that returns a 1 to many dictonary

Adviser
Posts: 357
2365     1
Ah. It’s subtle, but for the 1-many you have to do it differently. I think the ”methods” only works for methods that return a scalar, though I can’t recall exactly. Can you print the keys in devices[’devices’] and see if there is an ’if_addrs’ key?

Anyway, related objects can be included using the ”include” parameter. That parameter should be listed in the docs, with the specific values that are allowed per model (object type).

The behavior for ”include” is different from ”methods”. In ”methods”, it will query the base objects and load them all into memory. It then loops through them and calls that method on the object and adds its value to the return, with a key that is the name of the method.

The ”include” is used for relationships. In this case, the return values are not simple strings, but instead complete objects or lists of objects. Internally, this means that we first query the base objects and load them into memory, then we collect all of their IDs and query the ”include” object table with those IDs. In short, if there are n objects to return and a single relationship, using ”methods” could result in n + 1 queries (one for the base, plus one for each time it loops and makes a method call). Using ”include” results in this case would result in only 2 queries: one for the base objects and one for all related objects. This is *much* faster.

In your case, you would end up with an ’if_addrs’ key in devices (NOT in devices[’devices’]). That is, it would be a peer to devices[’devices’] and would contain a list of all IfAddrs related to the set of devices in the current page.

John

Re: Using methods on the REST API that returns a 1 to many dictonary

Authority
Posts: 20
2365     1

That got me quite at bit further but I am not quite past the finish line yet. Here are the key with the different options.

 

So here are the print devices.keys() using the include for the REST call

devices = c.api_request('devices/index/?include=if_addrs%2Cinterfaces', {'timeout': 10, 'limit': 100})

 

[u'if_addrs', u'interfaces', u'devices', u'current', u'start', u'limit', u'total']

 

print devices.keys() using methods

devices = c.api_request('devices/index/?methods=if_addrs%2Cinterfaces', {'timeout': 10, 'limit': 100})

 

[u'devices', u'current', u'start', u'limit', u'total']

 

So the next question for me is the for loop with having keys for devices, interfaces and if_addrs keys how to I get a print format with data from each key. I have a SQL background and for some reason I cannot get dictionry herichy correct I think in terms of left joins.

 

for d in devices['devices']:
  print FORMAT % (d['DeviceName'], d['DeviceIPDotted'], d['ifIPDotted'])

Highlighted

Re: Using methods on the REST API that returns a 1 to many dictonary

Adviser
Posts: 357
2365     1
I was curious in the ”methods” case, what the keys look like for a single device.

For the ”include” case, you will find that, for example, devices[’interfaces’] will contain an array of interface objects. So, you want to loop through that array and create a dictionary with the DeviceID as the key, and an array of the interface objects as the value. That is, you’ll create a dictionary, and loop through every interface. For each one, you will create or update an array in the dictionary keyed by DeviceID, adding that Interface object to the array.

Then, when you are doing through the device list, you use the DeviceID to key into that array and list each interface for that device.

Since *addresses* are per interface, you can do the same for addresses, keying either by InterfaceID or DeviceID.

John
Showing results for 
Search instead for 
Do you mean 

Recommended for You