pythonlistdictionarycheck-mk

mapping a list to a dict when the keys are weird


I want to process LLDP data from a TP-Link switch in an inventory plugin for Check_MK. The TP-Link switch doesn't use the standard SNMP OIDs for LLDP and their custom MIB has a weird quirk. Instead of having an index at the end of the OIDs they put it in the middle of the OID.

[[[u'1.1.99353.1', u'Te1/0/25'], [u'1.2.99353.1', u'1'], [u'1.3.99353.1', u'MAC address'], [u'1.4.99353.1', u'00:zzzzzzz'], [u'1.5.99353.1', u'MAC address'], [u'1.6.99353.1', u'00:zzzzzzzz'], [u'1.7.99353.1', u'120'], [u'1.8.99353.1', u'Port 25'], [u'1.9.99353.1', u'THE_HOST_NAME'], [u'1.11.99353.1', u'Bridge Router'], [u'1.12.99353.1', u'Bridge Router'], [u'shortened', u'for brevity']]

So on planet normal, I would expect things like 99353.8 and 99353.9 or maybe 99353.1.8 and 99353.1.9. What they do here (1.X.99353.1) is odd. I am not sure what to do with it. All I know is I have to normalize it and I'm too stupid to do that.

This is what I would like to make from it:

{
    l_id : 99353.1  # from the "index"
    l_ifname   : u'Te1/0/25'      # from 1.1
    r_ifname   : u'Port 25'       # from 1.8
    r_hostname : u'THE_HOST_NAME' # from 1.9.
}

Mapping this (only a subset of the list, while splitting up the key-to-be is completely above my skill level. I would like to avoid spending half a day to produce something ugly with a pile of for-loops. especially since this should go upstream to a community project and I don't want anyone to hurt their eyes.

Is there some smart approach that lets me break this into 2-3 smaller problems?


Solution

  • You can use string.split to make a dict of the indexes:

    list_ = [[u'1.1.99353.1', u'Te1/0/25'], [u'1.2.99353.1', u'1'], [u'1.3.99353.1', u'MAC address'], [u'1.4.99353.1', u'00:zzzzzzz'], [u'1.5.99353.1', u'MAC address'], [u'1.6.99353.1', u'00:zzzzzzzz'], [u'1.7.99353.1', u'120'], [u'1.8.99353.1', u'Port 25'], [u'1.9.99353.1', u'THE_HOST_NAME'], [u'1.11.99353.1', u'Bridge Router'], [u'1.12.99353.1', u'Bridge Router'], [u'shortened', u'for brevity']]
    
    
    dict_ = {key.split(".")[1]: val for key, val in list_[:-1]}
    

    which gives you

    {'1': 'Te1/0/25',
     '11': 'Bridge Router',
     '12': 'Bridge Router',
     '2': '1',
     '3': 'MAC address',
     '4': '00:zzzzzzz',
     '5': 'MAC address',
     '6': '00:zzzzzzzz',
     '7': '120',
     '8': 'Port 25',
     '9': 'THE_HOST_NAME'}
    

    From there it's easy to make the dictionary you're after

    output = {
         "l_id": list_[0][0].split(".", 2)[-1],
         "l_ifname": dict_["1"],
         "l_rname": dict_["8"],
         "r_hostname": dict_["9"],
    }