0

I want to begin by saying that I am by no mean a python expert so I am sorry if I express myself in an incorrect way.

I am building a script that goes something like this:

from netmiko import ConnectHandler 

visw0102 = {
    'device_type': 'hp_comware',
    'ip': '192.168.0.241',
    'username': 'admin',
    'password': 'password'
}

visw0103 = {
    'device_type': 'hp_comware',
    'ip': '192.168.0.242',
    'username': 'admin',
    'password': 'password'
}

site1_switches = [visw0102, visw0103]

for switch in site1_switches:

... (rest of the script)

I am trying to get the current index name in the FOR loop by using the enumerate() function to get the index name of the site1_switches list but since that list is made of dictionary items, the dictionary keys are returned:

>>> for index, w in enumerate(switch):
...     print(w)
...
device_type
ip
username
password

Is there a way the get the actual index name (VISW010X) instead of values that are in the dictionaries?

Thank you

Edit: Nested dictionary was the answer here, thanks Life is complex

So I was able to get further. Here's the code now.

from netmiko import ConnectHandler 

site1_switches = {
    'visw0102' : {
        'device_type': 'hp_comware',
        'ip': '192.168.0.241',
        'username': 'admin',
        'password': 'password'
    },
    'visw0103' : {
        'device_type': 'hp_comware',
        'ip': '192.168.0.242',
        'username': 'admin',
        'password': 'password'
    }
}

for key, values in site1_switches.items():
    device_type = values.get('device_type', {})
    ip_address = values.get('ip', {})
    username = values.get('username', {})
    password = values.get('password', {})

for key in site1_switches.items():
    net_connect = ConnectHandler(**dict(key))     <- The ConnectHandler needs a dictionary

Now the problem is that the dictionary key seems to be converted to a tuple but the ConnectHandler module needs a dictionary to proceed.

Here's what I get:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: dictionary update sequence element #0 has length 8; 2 is required

I would need to find a way to convert the tuple to a dictionary but it seems that dict(key) doesn't work as it puts the tuple in the first dictionary key (or so it seems).

Anyway I can achieve that?

Thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Noct03
  • 37
  • 1
  • 7
  • Why are you doing this? for key in site1_switches.items(): net_connect = ConnectHandler(**dict(key)) – Life is complex Sep 25 '19 at 00:44
  • Did you try my ConnectHandler example? It is based on the documentation for the netmiko module. – Life is complex Sep 25 '19 at 00:45
  • Hi, thanks again. I might have misunderstood your code.Basicaly, I am doing this because I nood to loop through multiple switches (VISW0102, VISW0103, and more to come). My understanding was that what you suggested would only do it for a single switch. – Noct03 Sep 25 '19 at 11:33
  • No worries. Did you test the code in my answer? – Life is complex Sep 25 '19 at 11:37
  • Will do once I get to the office. I'll get back to you, Thanks again! – Noct03 Sep 25 '19 at 11:43
  • I tried your suggestion and it works but it only does the last entry in the dictionnary, so VISW0103. It skips over VISW0102 for some reason. Any idea why? – Noct03 Sep 25 '19 at 16:22
  • I'm unsure. Please post another question with your code, because your first question was answered. I will look for your new question. Thanks. – Life is complex Sep 25 '19 at 16:31
  • You are right, I'll do that. Thanks! – Noct03 Sep 25 '19 at 17:08
  • I opened another question. Here's the link: https://stackoverflow.com/questions/58106706/nested-dictionary-with-netmiko – Noct03 Sep 25 '19 at 21:25
  • I noted that the issue was with the indent. A simple mistake, which happens to everyone now and then. – Life is complex Sep 26 '19 at 02:42

2 Answers2

0

Have you considered using a nested dictionary?

site1_switches = {
'visw0102': {
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
}, 
'visw0103': {
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
}}

for key, value in site1_switches.items():
  print (key)
  # output
  visw0102
  visw0103

Here's another way to accomplish this.

for index, (key, value) in enumerate(site1_switches.items()):
  print(index, key, value)
  # output
  0 visw0102 {'device_type': 'hp_comware', 'ip': '192.168.0.241', 'username': 'admin', 'password': 'password'}
  1 visw0103 {'device_type': 'hp_comware', 'ip': '192.168.0.242', 'username': 'admin', 'password': 'password'}

A more complete solution

from netmiko import ConnectHandler 

# nested dictionary
site1_switches = {
'visw0102': {
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
}, 
'visw0103': {
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
}}

for key, values in site1_switches.items():
  device_type = values.get('device_type', {})
  ip_address = values.get('ip', {})
  username = values.get('username', {})
  password = values.get('password', {})
  print (f'{key}', {device_type}, {ip_address}, {username}, {password})
  # output 
  visw0102 {'hp_comware'} {'192.168.0.241'} {'admin'} {'password'}
  visw0103 {'hp_comware'} {'192.168.0.242'} {'admin'} {'password'}

  print (f'Establishing a connection to {key}')
  # output 
  Establishing a connection to visw0102

  # pseudo code based on ConnectHandler parameters
  switch_connect = ConnectHandler(device_type=device_type, host=ip_address, username=username, password=password)

  # checking that the connection has a prompt 
  switch_connect.find_prompt()

  # What you want to do goes here...
  # Example
  command_output = switch_connect.send_command('display current-configuration')
Life is complex
  • 15,374
  • 5
  • 29
  • 58
  • Thank you for your reply. I will five your solution a try and let you know. Thanks! – Noct03 Sep 24 '19 at 11:47
  • You're welcome. BTW I read through the netmiko documentation. The nested dictionary should work with the ConnectHandler as shown in my answer. – Life is complex Sep 24 '19 at 13:05
  • Thanks again, I think you put me on the right track. I can't post code on a comment so let me expand in my original comment. – Noct03 Sep 25 '19 at 00:00
0

Unfortunately, there doesn't seem to be a nice, succinct way of accessing the dictionary's name, but Get name of dictionary provides some possible workarounds:

Nesting your switch dictionaries within an overarching dictionary that maps names to dictionaries is one method.

site1_switches = {
    "visw0102": visw0102, 
    "visw0103": visw0103
}

Another would be to add a "name" key to each dictionary, so that you can access the names of each switch in site1_switches by switch['name']

visw0102 = {
    'name': 'visw0102',
    'device_type': 'hp_comware',
    'ip': '192.168.0.241',
    'username': 'admin',
    'password': 'password'
}

visw0103 = {
    'name': 'visw0103',
    'device_type': 'hp_comware',
    'ip': '192.168.0.242',
    'username': 'admin',
    'password': 'password'
}
Chubby Panda
  • 13
  • 1
  • 5
  • Thank you for your reply. I will give your first solution a try. Unfortunetely, I can't add items to the dictionnary as this is the way Netmiko expects them to be. Thanks! – Noct03 Sep 24 '19 at 11:45