Apr-09-2019, 08:26 PM
When I print output from a dictionary, I get the following output as shown under "NOW LISTING".
to be honest I cannot understand at what point the data got these multiple [[[. It seems a list inside of a list but I do not know why.
Question: based on this, how would you retrieve value thru this data structure? Or should I fix the origin of these behavior? I am pasting code below.
******************* NOW LISTING ***********************
defaultdict(<class 'list'>, {'PSE2': ['0/7/CPU0', '1/0/CPU0', '1/2/CPU0'], 'IF_PSE1': [['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'IF_PSE2': [['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'NODE': [[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]})
to be honest I cannot understand at what point the data got these multiple [[[. It seems a list inside of a list but I do not know why.
Question: based on this, how would you retrieve value thru this data structure? Or should I fix the origin of these behavior? I am pasting code below.
******************* NOW LISTING ***********************
defaultdict(<class 'list'>, {'PSE2': ['0/7/CPU0', '1/0/CPU0', '1/2/CPU0'], 'IF_PSE1': [['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'IF_PSE2': [['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'NODE': [[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]})
import paramiko import copy import os import sys import re import getpass import time import json from collections import defaultdict #User and Password is Cisco CEC USERNAME = 'admin' TARGET_SERVER = '10.1.1.1' TOLERANCE = 400 MGROUP = "224.0.0.0/24" def olist(raw_show_data): #Separate the output for the respective show commands executed olist_data = raw_show_data.split('#show') #Separate data from 3 show commands given (show mrib route, show mfib route rate, show platform) #print(olist_data[1]) #print(olist_data[2]) #print(olist_data[3]) #==>delete this:using bogus data for now olist_data[1] = """TenGigE0/5/0/1.999 Flags: Outgoing Interface List TenGigE0/5/0/21.201 Flags: F NS, Up: 01:06:23 TenGigE0/7/0/3.1 >>> CRS-X interface ( 1st PSE)""" #1) Analyze 'show platform' and determine if it is 1 PSE or 2 PSE architecture var_dict = {} show_platform_str = olist_data[3].strip() show_platform_list = show_platform_str.split('\n') #Create a dictionary to organize all Nodes which are PSE-2 architecture. Dictionary if_dic will contain list of outgoing interfaces(o-list) which are on PSE2 or PSE1 var_dict = defaultdict(list) for element in show_platform_list: match =re.findall(r'(FP-X|MSC-X|SPC-X)',element) if match: #The first element on each line is the Node#: break_element = element.split(' ') #Build a list of all Node# which are PSE2 var_dict['PSE2'].append(break_element[0]) #2)Analyze the outgoing interfaces on show mrib route #Only consider outgoing interface lists (o-list): #A dict to organize interface status olist_dic = {} raw_int_data = olist_data[1].split('Outgoing Interface List') raw_int_out = raw_int_data[1] #Get list of interfaces match_int = re.findall(r'(TenGig[A-Za-z0-9\/\.]+)', raw_int_out) if match_int: for entry in match_int: raw_int_ids = entry.split('/') #Get the interface port ID raw_portids = raw_int_ids[3].partition(".") port_id = raw_portids[0] #Get the interface CPU/Node position port_cpu_pos = (raw_int_ids[0]+"/"+raw_int_ids[1]) match = re.findall(r'(\d\/\d)',port_cpu_pos) #Copy dictinary so that I can interate and modify the original one. temp_var_dict = var_dict.copy() for k, v in temp_var_dict.items(): match = str(match) match = match.strip("[]") match = match.strip("''") result = [index for index, value in enumerate(v) if match in value] result = str(result) result = result.strip("[]") result = result.strip("'") #====> IF I print(var_dict), at this point I have no error ********* if result == "0": #It means a match between interface on RP PSE2 model was found; Interface position is on PSE2 architecture print (f'PSE-2 Line cards:{v} Interfaces on PSE2:{entry} Interface PortID:{port_id}') port_id = int(port_id) print(port_id) if port_id >= 19: #print(f'interface:{entry} portID={port_id} CPU_POS={port_cpu_pos} REPLICATION=YES') if_info = [entry,'PSE2=YES',port_id,port_cpu_pos,'REPLICATION=YES'] var_dict['IF_PSE2'].append(if_info) #===> *** This is the point that if i attempt to print var_dict, I get the Error during olist(): dictionary changed size during iteration else: #print(f'interface:{entry},portID={port_id} CPU_POS={port_cpu_pos} REPLICATION=NO') if_info = [entry,'PSE2=YES',port_id,port_cpu_pos,'REPLICATION=NO'] var_dict['IF_PSE2'].append(if_info) else: #it means the interface is on single PSE. No replication is applicable. Just check threshold between incoming and outgoing rate. if_info = [entry,'PSE2=NO',int(port_id),port_cpu_pos,'REPLICATION=NO'] var_dict['IF_PSE1'].append(if_info) #3) Retrieve Incoming and Outgoing rate #==>To be deleted: This is a temporary hardcoded value for testing. olist_data[2] = """RP/0/RP0/CPU0:R7-P1#show mfib route rate 230.207.200.1 IP Multicast Forwarding Rates (Source Address, Group Address) Incoming rate: pps/bps (Incoming node) Outgoing rate: Node: (Outgoing node) : pps/bps (50.50.50.2,230.207.200.1) Incoming rate : 1013 / 8127181 (0/5/CPU0) Outgoing rate : Node : 0/5/CPU0 : 1974 / 15828597. >> it shows double as O-list is on 2 PSE’s. Node : 0/9/CPU0 : 993 / 7966755 Incoming rate : 9999 / 8127181 (0/5/CPU0) Outgoing rate : Node : 0/5/CPU0 : 198 / 15828597. >> it shows double as O-list is on 2 PSE’s. Node : 0/9/CPU0 : 992 / 7966755 """ #Format olist_data[2] under_Outgoing = False list_node = olist_data[2].split('\n') for entry in list_node: in_rate = re.findall(r'Incoming\srate\s:\s(\d+)\s\/\s\d+', entry) if in_rate: #Incoming Rate information found. Save it to Node dictionary: save_rate = in_rate outgoing = re.findall(r'(Outgoing rate:)', entry) if outgoing: #That means it is under the "Outgoing rate:" section. under_Outgoing = True else: under_Outgoing = False if entry.strip().startswith('Node'): cpu_node_pos = re.findall(r'(\d\/\d)',entry) if cpu_node_pos: #cpu_node_pos = cpu_node_pos.strip() pass node = re.findall(r'Node\s:\s.*?\s:\s(\d+)\s/\s\d+',entry) if node: #Now save data: incoming rate, outgoing rate, CPU_pos_info, mcast_group node_data = [save_rate, node, cpu_node_pos] var_dict['NODE'].append(node_data) #print(f'Incoming Rate:{save_rate} Outgoing Rate:{node} CPU_INFO:{cpu_node_pos}') return var_dict def ssh_nodes(myuser, nodepass, host,mcastgroup): print(f'* Connecting to node for username:{USERNAME}') remote_conn_pre = paramiko.SSHClient() remote_conn_pre remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy()) host = host.strip() remote_conn_pre.connect(host, username=myuser,password=nodepass,look_for_keys=False,allow_agent=False) print(f'* SSH connection established to {host}') remote_conn = remote_conn_pre.invoke_shell() remote_conn.send('terminal length 0\n') remote_conn.send('show mrib route %s \n' %(mcastgroup)) time.sleep(15) remote_conn.send('show mfib route rate %s \n' %(mcastgroup)) time.sleep(15) remote_conn.send('show platform \n') time.sleep(15) output=remote_conn.recv(65535) time.sleep(10) remote_conn.close() output_str = output.decode('utf-8') return output_str def get_credentials(): #Assuming USERNAME is already entered inputpass = getpass.getpass() inputpass = inputpass.strip('\n') return inputpass def verify_threshold(node_PS_if_list): print(f'******************* NOW LISTING ***********************') print(node_PS_if_list) def main(): try: #Get secure password from user. Username is a global variable USERNAME node_pass = get_credentials() except Exception as err: print(f'Error during get_credentials() call: {err}') try: get_platform_data = ssh_nodes(USERNAME, node_pass, TARGET_SERVER, MGROUP) except Exception as err: print (f'Error during get_platform_data:{err}') try: get_analysis_int = olist(get_platform_data) except Exception as err: print(f'Error during olist(): {err}') try: verify_threshold(get_analysis_int) except Exception as err: print(f'Error during verify_threshold(): {err}') sys.exit(0) if __name__ == '__main__': main() #===end====================