This is the second post in this series. If you missed Part 1, you can find it here.

Dissecting ConnectHandler

Let’s continue our ConnectHandler investigation. When we look at the code, the first thing we if statement:

1
2
3
4
5
if kwargs["device_type"] not in platforms:
    raise ValueError(
        "Unsupported device_type: "
        "currently supported platforms are: {}".format(platforms_str)
    )

The if statement tells us that we’re looking for the device_type key in the kwargs dictionary. Once we find it, we then check if it exists in platforms.

But what happens if we provide an invalid device_type? Judging by the code, Netmiko should raises a ValueError exception and print an informative message. But let’s take a look just to be sure:

Here’s our code:

1
2
3
4
5
6
7
8
9
from netmiko import ConnectHandler

linux = {
    'device_type': 'This-Is-A-Fake-Device-Type',
    'host':   '127.0.0.1',
    'username': 'will',
}

ConnectHandler(**linux)

And here’s our output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Traceback (most recent call last):
  File "/home/wrobinson/Development/netmiko-blog/run.py", line 9, in <module>
    ConnectHandler(**linux)
  File "/home/wrobinson/Development/netmiko-blog/netmiko/ssh_dispatcher.py", line 262, in ConnectHandler
    "currently supported platforms are: {}".format(platforms_str)
ValueError: Unsupported device_type: currently supported platforms are: 
a10
accedian
alcatel_aos
alcatel_sros
apresia_aeos
arista_eos
aruba_os
avaya_ers
avaya_vsp
brocade_fastiron
brocade_netiron
brocade_nos

# and so on...

Process finished with exit code 1

Great! The code worked as expected. Before we move on though, what do you think will happen if we don’t pass in a device_type at all? Let’s have a look.

Here’s our code:

1
2
3
4
5
6
7
8
from netmiko import ConnectHandler

linux = {
    'host':   '127.0.0.1',
    'username': 'will',
}

ConnectHandler(**linux)

And here’s our output:

1
2
3
4
5
6
7
8
Traceback (most recent call last):
  File "/home/wrobinson/Development/netmiko-blog/run.py", line 9, in <module>
    ConnectHandler(**linux)
  File "/home/wrobinson/Development/netmiko-blog/netmiko/ssh_dispatcher.py", line 259, in ConnectHandler
    if kwargs["device_type"] not in platforms:
KeyError: 'device_type'

Process finished with exit code 1

This time we get a KeyError exception. That’s because Netmiko is referencing a key (device_type) that doesn’t exist in our dictionary (kwargs).

Now, this error message isn’t very user friendly. What can we do to clean it up? If your answer is a try/except block, you’re right!

Here’s our code:

1
2
3
4
5
6
7
8
9
10
11
12
13
from netmiko import ConnectHandler
import sys

linux = {
    'host':   '127.0.0.1',
    'username': 'will',
}

try:
    ConnectHandler(**linux)

except KeyError:
    sys.exit('Error: "device_type" must be passed to ConnectHandler')

And here’s our output:

1
2
3
Error: "device_type" must be passed to ConnectHandler

Process finished with exit code 1

Excellent! That’s much nicer, isn’t it?

Having a look at the above code raises two questions:

  1. As mentioned above, we know that Netmiko checks if our device_type is listed in the platforms variable. But where does platforms come from?
  2. We can see that the exception message prints the platforms_str variable. But where does platforms_str come from?

The answers are quite involved, so let’s cover them off in the next post in this series.

Review

Before we wrap up, let’s first review what we’ve learned in this post:

  • Netmiko will raise a ValueError if we pass in an invalid device_type
  • We can “catch” exceptions using try/except blocks
    • After catching an exception, we can control what happens next
  • Trying to access a non-existant dictionary key (e.g kwargs["invalid_key"]) results in a KeyError exception being raised
    • Bonus points: If you want to return a default value when a key doesn’t exist, you could use get instead. e.g kwargs.get("device_type", "linux"). Using this method, linux will be returned instead of a KeyError exception being raised

Update: Part 3 has been published.


As always, if you have any questions or have a topic that you would like me to discuss, please feel free to post a comment at the bottom of this blog entry, e-mail at will@oznetnerd.com, or drop me a message on Reddit (OzNetNerd).

Note: The opinions expressed in this blog are my own and not those of my employer.

Leave a comment