This is part four in a series of using python and the RESTful API to automate the configuration of the HP IMC network management station. Like with all things, it’s easier to learn something when you’re able to find a good reason to use those skills. I decided to extend my python skills by figuring out how to use python to configure my NMS using the RESTful API.
If you’re interested, check out the other posts in this series
Adding Custom Views
In this post, we’re going to use the RESTful API to programatically add a custom view, and then add devices to that custom view. For those of you who don’t know, a custom view is simply a logical grouping of devices. In IMC custom views also form the basis of the topology maps. In fact, a custom view and a topology map are essentially the same object internally, The difference is just whether you chose to look at it as a list of devices in the normal interface or chose to look at it in the typical topology/visio format which we all know and might-not-love.
Why might we want to add a custom view programatically you ask? While, the answer to that might be simply that we’re lazy and it’s easier and faster. Or it might be that you don’t want to have to look through all the different devices, or, as in my case, that you simply want an excuse to extend your python skills. Whatever you’re reasons are, custom views are something that just don’t get used enough in my opinion.
Custom views are a great way to be able to zoom in on the status of a specific branch, a geographic area, maybe a logical grouping of devices that support a specific application? It really doesn’t matter and the best part is that a single device can exist in multiple custom views at the same time, so there’s really no limit to how you put these views together. It all depends on what makes sense to you.
The Code
This code is a little bit more complicated than some of the other examples we’ve looked at. We’re actually going to be using multiple functions together, but the logic should be pretty easy to follow. I’m sure there are better ways to do this, but this seems to work for me. I’m sure I’ll be back here in a year going “Why did I write it that way!?!?!?!?!?” but for now, I hope it’s simple enough for someone else to follow and possibly get inspired.
The main function is really just calling the other functions which we will break down below
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
# checks to see if the imc credentials are already available | |
if auth == None or url == None: | |
imc_creds() | |
view_name = create_new_view() | |
view_list = get_custom_views() | |
view_id = get_view_id(view_name) | |
dev_list = filter_dev_category() | |
add_device_to_view(dev_list, view_id) |
Step 1 – Create the Custom View
In this code, we’re going to simply use this small function that I created to gather the name of the custom view ( the view_name variable ) and then use that to create the JSON payload ( the payload variable ). The other part of the JSON payload is the autoAddDevType variable which is hard-coded to 0. This could be used to have the system automatically add new devices of a given type, but I”m in interested in doing the automation myself here. The last part of this code will be used as the input for another function, which is the return of the view name. You can see in the main function in the the view_name = create_new_view() line.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def create_new_view(): | |
view_name = input("Please input the name of the new view: ") | |
add_view_url = "/imcrs/plat/res/view/custom?resPrivilegeFilter=false&desc=false&total=false" | |
f_url = url + add_view_url | |
payload = '''{ "name": "''' + view_name + '''", "autoAddDevType" : "0"}''' | |
r = requests.post(f_url, data=payload, auth=auth, | |
headers=headers) # creates the URL using the payload variable as the contents | |
r.status_code | |
if r.status_code == 201: | |
return view_name | |
else: | |
print("An Error has occured") |
Step 2 – Get Custom Views
For the next part, we are going to need to figure out what Id was assigned to this new view, to do this we’re going to have to go through a couple of steps. The first one is to ask the NMS to send us a list of all the known custom views. The following function will request the list, which will be returned as a JSON array, and then convert it over into a python list of dictionaries so we can work with it natively as a python object. You can see this in the main function in the view_list = get_custom_views() line
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def get_custom_views(): | |
# checks to see if the imc credentials are already available | |
if auth == None or url == None: | |
imc_creds() | |
get_custom_view_url = '/imcrs/plat/res/view/custom?resPrivilegeFilter=false&desc=false&total=false' | |
f_url = url + get_custom_view_url | |
# creates the URL using the payload variable as the contents | |
r = requests.get(f_url, auth=auth, headers=headers) | |
if r.status_code == 200: | |
view_list = (json.loads(r.text))["customView"] | |
return view_list | |
else: | |
print("An Error has occured") |
Now that we have the view_list which is the list of all the views, we’re going to have to find the ID for the new view that we just created. We do that by by using the get_view_id() function using the view_name as the input. Essentially, this will look through each of the views in the view_list that was returned above and let us know when the ‘name’ value is equal to the view_name value that we captured above. Once it’s equal, we then return the ‘symbolId’ which is the internal unique numeric value assigned to this particular custom view. This is the number we’re going to use to identify the view that that we want to add devices to. Make sense? Now that we’ve got this number, we’re going to assign it to the object view_id for use later on.
Note: I actually could have added the devices directly to the view in the original add_custom_view code code above, but then I’d have to write the modify function later if I ever wanted to change or add new devices to the view. I’m trying to follow the DRY ( Don’t Repeat Yourself ) advice here so I just write the modify here and I can then leverage it later without having to re-write the code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def get_view_id(view_name): | |
view_list = get_custom_views() | |
for i in view_list: | |
if i['name'].lower() == view_name.lower(): | |
view_id = i['symbolId'] | |
return i['symbolId'] |
Step 3 – Generate the Device List
We’re not going to spend too much time on this part as I’m essentially re-using the code from the Changing Device Categories blog. It’s pretty straight forward. I’m using some user-put to gather a list of devices that we want to add to this specific view and then capture it in the dev_list object. What’s cool about doing it this way is that the returned list will search through all the IP addresses assigned to your devices, not just the managed address which might come up in the NMS interface where you would normally perform this step. There are ways around that as well, but that’s another blog.
Step 4 – Add Devices to Existing Custom View
This last step is where things come together. We’re going to run the add_device_to_view(dev_list, view_id) function which is using the dev_list generated in step 3 and the view_id that we captured at the end of step 2 as the inputs. Essentially, we’re just saying here “ add all the devices I want to the view I just created “.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def add_device_to_view(dev_list, view_id): | |
modify_custom_view_url = '''/imcrs/plat/res/view/custom/'''+ str(view_id) | |
device_list = [] | |
for i in dev_list: | |
dev_id = {'id': i['id'] } | |
device_list.append(dev_id) | |
payload = '''{"device":'''+ json.dumps(device_list) + '''}''' | |
f_url = url+modify_custom_view_url | |
r = requests.put(f_url, data = payload, auth=auth, headers=headers) #creates the URL using the payload variable as the contents | |
r.status_code | |
if r.status_code == 204: | |
print ("Device Succesfully Added") | |
else: | |
print ("An Error has occured") |
Wrapping it Up
So this is just an example of how you can tie a few pieces of code together to help automate something that might otherwise take you a lot of manual labour. In this case, just a bunch of mouse clicks and depending on the fact that you were able to manually identify all the devices you wanted to add to a specific view. Personally, I’d rather leave the hard work to the computers and move on to something that requires my brain.