def fabricshow_extract(switch_params_lst, report_data_lst): """ Function to extract from principal switch configuration list of switches in fabric including AG switches """ # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['fabricshow', 'ag_principal'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking fabricshow_lst, ag_principal_lst = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [ report_steps_dct[data_name][1] for data_name in data_names ] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): print( '\nEXTRACTING FABRICS INFORMATION FROM SUPPORTSHOW CONFIGURATION FILES ...\n' ) # extract switch parameters names from init file switch_columns = columns_import('switch', max_title, 'columns') # number of switches to check switch_num = len(switch_params_lst) # list to store only REQUIRED switch parameters # collecting data for all switches during looping fabricshow_lst = [] ag_principal_lst = [] # data imported from init file to extract values from config file *_, comp_keys, match_keys, comp_dct = data_extract_objects( 'fabricshow', max_title) ag_params = columns_import('fabricshow', max_title, 'ag_params') # switch_params_lst [[switch_params_sw1], [switch_params_sw1]] # checking each switch for switch level parameters for i, switch_params_data in enumerate(switch_params_lst): # data unpacking from iter param # dictionary with parameters for the current switch switch_params_data_dct = dict( zip(switch_columns, switch_params_data)) switch_info_keys = [ 'configname', 'chassis_name', 'chassis_wwn', 'switch_index', 'SwitchName', 'switchWwn', 'switchRole', 'Fabric_ID', 'FC_Router', 'switchMode' ] switch_info_lst = [ switch_params_data_dct[key] for key in switch_info_keys ] ls_mode_on = True if switch_params_data_dct[ 'LS_mode'] == 'ON' else False sshow_file, _, _, switch_index, switch_name, _, switch_role = switch_info_lst[: 7] # current operation information string info = f'[{i+1} of {switch_num}]: {switch_name} fabric environment. Switch role: {switch_role}' print(info, end=" ") collected = {'fabricshow': False, 'ag_principal': False} # switch_params_data_dct.get('FC_Router') == 'ON' # print('collected', collected) # check config of Principal switch only if switch_role == 'Principal': # principal_switch_lst contains sshow_file, chassis_name, chassis_wwn, switch_index, switch_name, switch_fid principal_switch_lst = [ *switch_info_lst[:6], *switch_info_lst[7:9] ] # search control dictionary. continue to check sshow_file until all parameters groups are found with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # fabricshow section start if re.search( r'^(SWITCHCMD /fabos/cliexec/)?fabricshow\s*:$', line): # when section is found corresponding collected dict values changed to True collected['fabricshow'] = True if ls_mode_on: while not re.search( fr'^CURRENT CONTEXT -- {switch_index} *, \d+$', line): line = file.readline() if not line: break while not re.search( r'^(real [\w.]+)|(\*\* SS CMD END \*\*)$', line): line = file.readline() # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # match_keys ['fabricshow_match'] # 'fabricshow_match' if match_dct[match_keys[0]]: fabricshow_lst.append( line_to_list(comp_dct[comp_keys[0]], line, *principal_switch_lst)) if not line: break # ag_principal section start # switchcmd_agshow_comp if re.search(comp_dct[comp_keys[4]], line): collected['ag_principal'] = True # if switch in LS mode switch to required LS number if ls_mode_on: while not re.search( fr'^CURRENT CONTEXT -- {switch_index} *, \d+$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[10]], line): match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # ag_num_match if match_dct[match_keys[5]]: # dictionary to store all DISCOVERED switch ports information # collecting data only for the logical switch in current loop # Access Gateway common information dictionary ag_info_dct = {} # Attached F-Port information dictionary ag_attach_dct = {} # Access Gateway F-Port information dictionary ag_fport_dct = {} # Domaid ID, port_ID, port_index dictionary did_port_dct = {} # move cursor to one line down to get inside while loop line = file.readline() # ag_switchcmd_end_comp while not re.search( comp_dct[comp_keys[9]], line): match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # ag_info_match if match_dct[match_keys[6]]: ag_info_dct[match_dct[ match_keys[6]].group( 1).rstrip()] = match_dct[ match_keys[6]].group( 2).rstrip() # ag_attached_match elif match_dct[match_keys[7]]: # if Attached F-Port information dictionary is empty than create dictionary with N-Port ID(s) as keys and empty lists as values # if ag_attach_dct has been already created (not empty) then it's preserved ag_attach_dct = ag_attach_dct or dict( (n_portid, []) for n_portid in ag_info_dct['N-Port ID(s)']. split(',')) # extracting attached F-port data from line to list ag_attach_lst = line_to_list( comp_dct[comp_keys[7]], line) # getting port_ID of N-port from port_id of F-port n_portid = ag_attach_lst[ 0][:-2] + '00' # adding current line F-port information to Attached F-Port information dictionary if n_portid in ag_attach_dct.keys( ): ag_attach_dct[n_portid].append( ag_attach_lst) # ag_fport_match elif match_dct[match_keys[8]]: # create Access Gateway F-Port information dictionary ag_fport_dct = ag_fport_dct or dict( (n_portid, []) for n_portid in ag_info_dct['N-Port ID(s)']. split(',')) # extracting access gateway F-port data from line to list ag_fport_lst = line_to_list( comp_dct[comp_keys[8]], line) # getting port_ID of N-port from port_id of F-port n_portid = ag_fport_lst[ 1][:-2] + '00' # adding current line F-port information to Access Gateway F-Port information dictionary if n_portid in ag_fport_dct.keys(): ag_fport_dct[n_portid].append( ag_fport_lst) line = file.readline() if not line: break # list of N-ports extracted from N-Port ID(s) line n_portids_lst = ag_info_dct[ 'N-Port ID(s)'].split(',') # (domain_id, n_portid) did_port_lst = [ (int(n_portid[:4], 0), n_portid) for n_portid in n_portids_lst ] # creating dictionary with n_portid as keys and (domain_id, n_portid) as values did_port_dct = { port[1]: list(port) for port in did_port_lst } # change values representation in dictionaries # before {n_portid: [(port_id_1, port_wwn_1, f-port_num_1)], [(port_id_2, port_wwn_2, f-port_num_2)]} # after {n_portid: [(port_id_1, port_id_2), (port_wwn_1, port_wwn_2), (f-port_num_1, f-port_num_1)] ag_attach_dct = { n_portid: list(zip(*ag_attach_dct[n_portid])) for n_portid in n_portids_lst if ag_attach_dct.get(n_portid) } ag_fport_dct = { n_portid: list(zip(*ag_fport_dct[n_portid])) for n_portid in n_portids_lst if ag_fport_dct.get(n_portid) } # add connected switch port_index to did_port_dct extracted from ag_attach_dct # (domain_id, n_portid, n_port_index) # if no port_index then add None for n_portid in n_portids_lst: if ag_attach_dct.get(n_portid): did_port_dct[n_portid].append( ag_attach_dct[n_portid][2][0]) else: did_port_dct[n_portid].append(None) # for each element of list convert tuples to strings # if no data extracted for the n_portid then add None for each parameter for n_portid in n_portids_lst: if ag_attach_dct.get(n_portid): ag_attach_dct[n_portid] = [ ', '.join(v) for v in ag_attach_dct[n_portid] ] else: ag_attach_dct[n_portid] = [None ] * 3 for n_portid in n_portids_lst: if ag_fport_dct.get(n_portid): ag_fport_dct[n_portid] = [ ', '.join(v) for v in ag_fport_dct[n_portid] ] else: ag_fport_dct[n_portid] = [None] * 3 # getting data from ag_info_dct in required order ag_info_lst = [ ag_info_dct.get(param, None) for param in ag_params ] # appending list with only REQUIRED ag info for the current loop iteration to the list with all ag switch info for n_portid in n_portids_lst: ag_principal_lst.append([ *principal_switch_lst[:-1], *ag_info_lst, *did_port_dct[n_portid], *ag_attach_dct[n_portid], *ag_fport_dct[n_portid] ]) else: line = file.readline() if not line: break # ag_principal section end status_info('ok', max_title, len(info)) else: status_info('skip', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, fabricshow_lst, ag_principal_lst) else: fabricshow_lst, ag_principal_lst = verify_data(report_data_lst, data_names, *data_lst) return fabricshow_lst, ag_principal_lst
def portinfo_extract(switch_params_lst, report_data_lst): """Function to extract switch port information""" # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['sfpshow', 'portcfgshow'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking sfpshow_lst, portcfgshow_lst = data_lst # when any data from data_lst was not saved (file not found) or # force extract flag is on then re-extract data from configuration files force_run = verify_force_run(data_names, data_lst, report_steps_dct, max_title) # # data force extract check # # list of keys for each data from data_lst representing if it is required # # to re-collect or re-analyze data even they were obtained on previous iterations # force_extract_keys_lst = [report_steps_dct[data_name][1] for data_name in data_names] # # print data which were loaded but for which force extract flag is on # force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # # when any of data_lst was not saved or # # force extract flag is on then re-extract data from configueation files # if not all(data_lst) or any(force_extract_keys_lst): if force_run: print('\nEXTRACTING SWITCH PORTS SFP, PORTCFG INFORMATION FROM SUPPORTSHOW CONFIGURATION FILES ...\n') # extract chassis parameters names from init file switch_columns = columns_import('switch', max_title, 'columns') # number of switches to check switch_num = len(switch_params_lst) # data imported from init file to extract values from config file params, params_add, comp_keys, match_keys, comp_dct = data_extract_objects('portinfo', max_title) portcfg_params = columns_import('portinfo', max_title, 'portcfg_params') # dictionary to save portcfg ALL information for all ports in fabric portcfgshow_dct = dict((key, []) for key in portcfg_params) # list to store only REQUIRED switch parameters # collecting sfpshow data for all switches ports during looping sfpshow_lst = [] # list to save portcfg information for all ports in fabric portcfgshow_lst = [] # switch_params_lst [[switch_params_sw1], [switch_params_sw1]] # checking each switch for switch level parameters for i, switch_params_data in enumerate(switch_params_lst): # data unpacking from iter param # dictionary with parameters for the current switch switch_params_data_dct = dict(zip(switch_columns, switch_params_data)) switch_info_keys = ['configname', 'chassis_name', 'chassis_wwn', 'switch_index', 'SwitchName', 'switchWwn'] switch_info_lst = [switch_params_data_dct.get(key) for key in switch_info_keys] ls_mode_on = True if switch_params_data_dct['LS_mode'] == 'ON' else False sshow_file, _, _, switch_index, switch_name, *_ = switch_info_lst # current operation information string info = f'[{i+1} of {switch_num}]: {switch_name} ports sfp and cfg' print(info, end =" ") # search control dictionary. continue to check sshow_file until all parameters groups are found collected = {'sfpshow': False, 'portcfgshow': False} with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # sfpshow section start if re.search(r'^(SWITCHCMD )?(/fabos/cliexec/)?sfpshow +-all *: *$', line) and not collected['sfpshow']: collected['sfpshow'] = True if ls_mode_on: while not re.search(fr'^CURRENT CONTEXT -- {switch_index} *, \d+$',line): line = file.readline() if not line: break while not re.search(r'^(real [\w.]+)|(\*\* SS CMD END \*\*)$',line): line = file.readline() match_dct ={match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys)} if match_dct[match_keys[0]]: # dictionary to store all DISCOVERED switch ports information # collecting data only for the logical switch in current loop sfpshow_dct = {} _, slot_num, port_num = line_to_list(comp_dct[comp_keys[0]], line) # if switch has no slots then all ports have slot 0 slot_num = '0' if not slot_num else slot_num while not re.match('\r?\n', line): line = file.readline() match_dct ={match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys)} # power_match if match_dct[match_keys[1]]: sfp_power_lst = line_to_list(comp_dct[comp_keys[1]], line) # cut off RX or TX Power sfp_power_value_unit = sfp_power_lst[1:] for v, k in zip(sfp_power_value_unit[::2], sfp_power_value_unit[1::2]): if k == 'uWatts': k = 'uW' key = sfp_power_lst[0] + '_' + k sfpshow_dct[key] = v # transceiver_match elif match_dct[match_keys[2]]: sfpshow_dct[match_dct[match_keys[2]].group(1).rstrip()] = match_dct[match_keys[2]].group(2).rstrip() # no_sfp_match elif match_dct[match_keys[3]]: sfpshow_dct['Vendor Name'] = 'No SFP module' # not_available_match elif match_dct[match_keys[4]]: sfpshow_dct[match_dct[match_keys[4]].group(1).rstrip()] = match_dct[match_keys[4]].group(2).rstrip() # sfp_info_match elif match_dct[match_keys[5]]: sfpshow_dct[match_dct[match_keys[5]].group(1).rstrip()] = match_dct[match_keys[5]].group(2).rstrip() if not line: break # additional values which need to be added to the dictionary with all DISCOVERED parameters during current loop iteration # values axtracted in manual mode. if change values order change keys order in init.xlsx "chassis_params_add" column sfpshow_port_values = [*switch_info_lst, slot_num, port_num] # adding additional parameters and values to the sfpshow_dct update_dct(params_add, sfpshow_port_values, sfpshow_dct) # appending list with only REQUIRED port info for the current loop iteration to the list with all fabrics port info sfpshow_lst.append([sfpshow_dct.get(param, None) for param in params]) # sfpshow section end # portcfgshow section start if re.search(r'^(SWITCHCMD )?(/fabos/cliexec/)?portcfgshow *: *$', line) and not collected['portcfgshow']: collected['portcfgshow'] = True if ls_mode_on: while not re.search(fr'^CURRENT CONTEXT -- {switch_index} *, \d+$',line): line = file.readline() if not line: break while not re.search(r'^(real [\w.]+)|(\*\* SS CMD END \*\*)$|No ports found in switch',line): line = file.readline() match_dct ={match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys)} # 'slot_port_line_match' if match_dct[match_keys[6]]: # dictionary to store all DISCOVERED switch ports information portcfgshow_tmp_dct = {} # extract slot and port numbers slot_num, port_nums_str = line_to_list(comp_dct[comp_keys[6]], line) port_nums_lst = port_nums_str.split() port_nums = len(port_nums_lst) # list with switch and slot information switch_info_slot_lst = switch_info_lst.copy() switch_info_slot_lst.append(slot_num) # adding switch and slot information for each port to dictionary for portcfg_param, switch_info_value in zip(portcfg_params[:7], switch_info_slot_lst): portcfgshow_tmp_dct[portcfg_param] = [switch_info_value for i in range(port_nums)] # adding port numbers to dictionary portcfgshow_tmp_dct[portcfg_params[7]] = port_nums_lst while not re.match('\r?\n', line): line = file.readline() match_dct ={match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys)} # portcfg_match if match_dct[match_keys[7]]: # extract param name and values for each port and adding to dictionary param_name, param_values_str = line_to_list(comp_dct[comp_keys[7]], line) portcfgshow_tmp_dct[param_name] = param_values_str.split() if not line: break # saving portcfg information of REQUIRED parameters from dictionary with DISCOVERED parameters for portcfg_param in portcfg_params: portcfgshow_dct[portcfg_param].extend(portcfgshow_tmp_dct.get(portcfg_param, [None for i in range(port_nums)])) # portcfgshow section end status_info('ok', max_title, len(info)) # after check all config files create list of lists from dictionary. each nested list contains portcfg information for one port for portcfg_param in portcfg_params: portcfgshow_lst.append(portcfgshow_dct.get(portcfg_param)) portcfgshow_lst = list(zip(*portcfgshow_lst)) # save extracted data to json file save_data(report_data_lst, data_names, sfpshow_lst, portcfgshow_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: sfpshow_lst, portcfgshow_lst = verify_data(report_data_lst, data_names, *data_lst) return sfpshow_lst, portcfgshow_lst
def sensor_extract(chassis_params_lst, report_data_lst): """Function to extract sensor information""" # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['sensor'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking sensor_lst, = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [ report_steps_dct[data_name][1] for data_name in data_names ] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): print('\nEXTRACTING ENVIRONMENT DATA ...\n') # # extract chassis parameters names from init file # switch_columns = columns_import('switch', max_title, 'columns') # extract chassis parameters names from init file chassis_columns = columns_import('chassis', max_title, 'columns') # number of switches to check switch_num = len(chassis_params_lst) # data imported from init file to extract values from config file *_, comp_keys, match_keys, comp_dct = data_extract_objects( 'sensor', max_title) # lists to store only REQUIRED infromation # collecting data for all switches ports during looping sensor_lst = [] # chassis_params_fabric_lst [[chassis_params_sw1], [chassis_params_sw1]] # checking each chassis for switch level parameters for i, chassis_params_data in enumerate(chassis_params_lst): # data unpacking from iter param # dictionary with parameters for the current chassis chassis_params_data_dct = dict( zip(chassis_columns, chassis_params_data)) chassis_info_keys = ['configname', 'chassis_name', 'chassis_wwn'] chassis_info_lst = [ chassis_params_data_dct.get(key) for key in chassis_info_keys ] sshow_file, chassis_name, _ = chassis_info_lst # current operation information string info = f'[{i+1} of {switch_num}]: {chassis_name} sensor readings' print(info, end=" ") # search control dictionary. continue to check sshow_file until all parameters groups are found collected = {'sensor': False} with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # sensor section start # switchcmd_sensorshow_comp if re.search(comp_dct[comp_keys[0]], line) and not collected['sensor']: collected['sensor'] = True # switchcmd_end_comp while not re.search(comp_dct[comp_keys[2]], line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # islshow_match if match_dct[match_keys[1]]: sensor_reading = line_to_list( comp_dct[comp_keys[1]], line, *chassis_info_lst) # appending list with only REQUIRED port info for the current loop iteration # to the list with all ISL port info sensor_lst.append(sensor_reading) if not line: break # sensor section end status_info('ok', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, sensor_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: sensor_lst = verify_data(report_data_lst, data_names, *data_lst) return sensor_lst
def blade_system_extract(blade_folder, report_data_lst): """Function to extract blade systems information""" # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['blade_interconnect', 'blade_servers', 'blade_vc'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking module_comprehensive_lst, blades_comprehensive_lst, blade_vc_comprehensive_lst = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [ report_steps_dct[data_name][1] for data_name in data_names ] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): # lists to store only REQUIRED infromation # collecting data for all blades during looping # list containing enclosure, blade and hba information for all blade systems blades_comprehensive_lst = [] # list containing enclosure and interconnect modules information for all blade systems module_comprehensive_lst = [] # list containing virtual connect ports information for all blade systems blade_vc_comprehensive_lst = [] if blade_folder: print('\nEXTRACTING BLADES SYSTEM INFORMATION ...\n') # collects files in folder with txt extension txt_files = find_files(blade_folder, max_title, filename_extension='txt') log_files = find_files(blade_folder, max_title, filename_extension='log') blade_configs_lst = txt_files + log_files # number of files to check configs_num = len(blade_configs_lst) if configs_num: # data imported from init file to extract values from config file enclosure_params, _, comp_keys, match_keys, comp_dct = data_extract_objects( 'blades', max_title) module_params = columns_import('blades', max_title, 'module_params') blade_params = columns_import('blades', max_title, 'blade_params') for i, blade_config in enumerate(blade_configs_lst): # file name with extension configname_wext = os.path.basename(blade_config) # remove extension from filename configname, _ = os.path.splitext(configname_wext) # Active Onboard Administrator IP address oa_ip = None # interconnect modules number module_num = 0 # current operation information string info = f'[{i+1} of {configs_num}]: {configname} system.' print(info, end=" ") # search control dictionary. continue to check file until all parameters groups are found collected = { 'enclosure': False, 'oa_ip': False, 'module': False, 'servers': False, 'vc': False } # if blade_lst remains empty after file checkimng than status_info shows NO_DATA for current file blade_lst = [] enclosure_vc_lst = [] with open(blade_config, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # enclosure section start if re.search( r'>SHOW ENCLOSURE INFO|^ +ENCLOSURE INFORMATION$', line): enclosure_dct = {} collected['enclosure'] = True # while not reach empty line while not re.search(r'Serial Number', line): line = file.readline() # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # name_value_pair_match if match_dct[match_keys[0]]: result = match_dct[match_keys[0]] enclosure_dct[result.group(1).strip( )] = result.group(2).strip() if not line: break # rename Description key to Enclosure Type key for VC if enclosure_dct.get('Description'): enclosure_dct[ 'Enclosure Type'] = enclosure_dct.pop( 'Description') # creating list with REQUIRED enclosure information only enclosure_lst = [ enclosure_dct.get(param) for param in enclosure_params ] # enclosure section end # vc fabric connection section start elif re.search(r'FABRIC INFORMATION', line): info_type = 'Type VC' print(info_type, end=" ") info = info + " " + info_type line = file.readline() collected['vc'] = True while not re.search( r'FC-CONNECTION INFORMATION', line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # vc_port_match if match_dct[match_keys[14]]: vc_port = line_to_list( comp_dct[comp_keys[14]], line, *enclosure_lst) enclosure_vc_lst.append(vc_port) blade_vc_comprehensive_lst.append( vc_port) line = file.readline() else: line = file.readline() if not line: break # vc fabric connection section end # active onboard administrator ip section start elif re.search(r'>SHOW TOPOLOGY *$', line): info_type = 'Type Blade Enclosure' print(info_type, end=" ") info = info + " " + info_type line = file.readline() collected['oa_ip'] = True while not re.search(r'^>SHOW', line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # oa_ip_match if match_dct[match_keys[1]]: oa_ip = match_dct[match_keys[1]].group( 1) line = file.readline() break else: line = file.readline() if not line: break # active onboard administrator ip section end # interconnect modules section start elif re.search(r'>SHOW INTERCONNECT INFO ALL', line): line = file.readline() collected['modules'] = True while not re.search(r'^>SHOW', line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # module_type_num_match if match_dct[match_keys[2]]: module_dct = {} module_lst = [] module = match_dct[match_keys[2]] # interconnect module slot number module_slot = module.group(1) # interconnect module type (Ethernet, FC) module_type = module.group(2).rstrip() line = file.readline() # module_section_end_comp while not re.search( comp_dct[comp_keys[3]], line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # name_value_pair_match if match_dct[match_keys[0]]: result = match_dct[ match_keys[0]] name = result.group(1).strip() value = result.group(2).strip() # if value is empty string use None if value == '': value = None module_dct[name] = value line = file.readline() else: line = file.readline() if not line: break # creating list with REQUIRED interconnect module information only module_lst = [ module_dct.get(param) for param in module_params ] # add current module information to list containing all modules infromation # oa_ip added as None and extracted later in the file module_comprehensive_lst.append([ *enclosure_lst, oa_ip, module_slot, module_type, *module_lst ]) # based on module's number oa_ip is added to module_comprehensive_lst after extraction module_num += 1 else: line = file.readline() if not line: break # interconnect modules section end # blade server, hba and flb section start elif re.search(r'>SHOW SERVER INFO ALL', line): line = file.readline() collected['servers'] = True while not re.search(r'^>SHOW', line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # blade_server_num_match if match_dct[match_keys[4]]: blade_dct = {} blade_lst = [] hba_lst = [] result = match_dct[match_keys[4]] blade_dct[result.group( 1)] = result.group(2) # blade_num = result.group(2) # print("Blade number:", blade_num) line = file.readline() # server_section_end_comp while not re.search( comp_dct[comp_keys[11]], line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # mezzanin hba section start # mezzanine_model_match if match_dct[match_keys[6]]: result = match_dct[ match_keys[6]] hba_description = result.group( 1) hba_model = result.group(2) line = file.readline() # mezzanine_wwn_comp while re.search( comp_dct[comp_keys[7]], line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key]. match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # mezzanine_wwn_match result = match_dct[ match_keys[7]] wwnp = result.group(1) hba_lst.append([ hba_description, hba_model, wwnp ]) line = file.readline() # mezzanin hba section end # flex flb hba section start # flb_model_match and flex_ethernet_match elif match_dct[match_keys[ 8]] or match_dct[ match_keys[15]]: if match_dct[match_keys[8]]: result = match_dct[ match_keys[8]] flex_description = result.group( 1) if re.search( comp_dct[ comp_keys[13]], line): flex_model = re.search( comp_dct[ comp_keys[13]], line).group(1) else: flex_model = None elif match_dct[match_keys[15]]: result = match_dct[ match_keys[15]] flex_description = result.group( 1) flex_model = result.group( 1) line = file.readline() # wwn_mac_line_comp while re.search( comp_dct[comp_keys[9]], line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key]. match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # flb_wwn_match if match_dct[ match_keys[10]]: result = match_dct[ match_keys[10]] wwnp = result.group(1) hba_lst.append([ flex_description, flex_model, wwnp ]) line = file.readline() # flex flb hba section end # blade server section start # blade_server_info_match elif match_dct[match_keys[5]]: result = match_dct[ match_keys[5]] # name = result.group(1) + result.group(2) if result.group(2) else result.group(1) name = result.group(1).rstrip() value = result.group( 3).rstrip() # to avoid Type parameter overwrire # add parameter only if parameter has not been added to blade dictionary before if not blade_dct.get(name): blade_dct[name] = value line = file.readline() # blade server section end # if none of matches found for current blade server than next line else: line = file.readline() if not line: break # unpopulated blade slots have 'Server Blade Type' line but populated have 'Type' line # add 'Server Blade Type' parameter for populated slots for consistency if blade_dct.get('Type'): blade_dct[ 'Server Blade Type'] = blade_dct.pop( 'Type') # creating list with REQUIRED blade server information only blade_lst = [ blade_dct.get(param) for param in blade_params ] # if hba or flex cards installed in blade server if len(hba_lst): # add line for each hba to blades_comprehensive_lst for hba in hba_lst: blades_comprehensive_lst.append( [ *enclosure_lst, *blade_lst, *hba ]) # if no nba add one line with enclosure and blade info only else: blades_comprehensive_lst.append([ *enclosure_lst, *blade_lst, None, None ]) # if no blade_server_num_match found in >SHOW SERVER INFO ALL section than next line else: line = file.readline() if not line: break # blade server, hba and flb section end # adding OA IP to module_comprehensive_lst based on interconnect modules number for num in range(-1, -module_num - 1, -1): module_comprehensive_lst[num][3] = oa_ip # show status blades information extraction from file if blade_lst or enclosure_vc_lst: status_info('ok', max_title, len(info)) else: status_info('no data', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, module_comprehensive_lst, blades_comprehensive_lst, blade_vc_comprehensive_lst) else: # current operation information string info = f'Collecting enclosure, interconnect modules, blade servers, hba' print(info, end=" ") status_info('skip', max_title, len(info)) # save empty data to json file save_data(report_data_lst, data_names, module_comprehensive_lst, blades_comprehensive_lst, blade_vc_comprehensive_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: module_comprehensive_lst, blades_comprehensive_lst, blade_vc_comprehensive_lst = verify_data( report_data_lst, data_names, *data_lst) return module_comprehensive_lst, blades_comprehensive_lst, blade_vc_comprehensive_lst
def fcr_extract(switch_params_lst, report_data_lst): """Function to extract fabrics routing information""" # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = [ 'fcrfabric', 'fcrproxydev', 'fcrphydev', 'lsan', 'fcredge', 'fcrresource' ] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking fcrfabric_lst, fcrproxydev_lst, fcrphydev_lst, lsan_lst, \ fcredge_lst, fcrresource_lst = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [ report_steps_dct[data_name][1] for data_name in data_names ] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): print( '\nEXTRACTING FABRICS ROUTING INFORMATION FROM SUPPORTSHOW CONFIGURATION FILES ...\n' ) # extract switch parameters names from init file switch_columns = columns_import('switch', max_title, 'columns') # number of switches to check switch_num = len(switch_params_lst) # lists to store only REQUIRED switch parameters # collecting data for all switches during looping fcrfabric_lst = [] fcrproxydev_lst = [] fcrphydev_lst = [] lsan_lst = [] fcredge_lst = [] fcrresource_lst = [] # dictionary to collect fcr device data # first element of list is regular expression pattern number, # second - list to collect data, third is index in line to which slice extracted list fcrdev_dct = { 'fcrproxydev': [5, fcrproxydev_lst, None], 'fcrphydev': [6, fcrphydev_lst, -3] } # data imported from init file to extract values from config file params, _, comp_keys, match_keys, comp_dct = data_extract_objects( 'fcr', max_title) # switch_params_lst [[switch_params_sw1], [switch_params_sw1]] # checking each switch for switch level parameters for i, switch_params_data in enumerate(switch_params_lst): # dictionary with parameters for the current switch switch_params_data_dct = dict( zip(switch_columns, switch_params_data)) switch_info_keys = [ 'configname', 'chassis_name', 'chassis_wwn', 'switch_index', 'SwitchName', 'switchWwn', 'switchRole', 'Fabric_ID', 'FC_Router' ] switch_info_lst = [ switch_params_data_dct.get(key) for key in switch_info_keys ] ls_mode_on = True if switch_params_data_dct[ 'LS_mode'] == 'ON' else False # data unpacking from iter param sshow_file, *_, switch_name, _, switch_role, fid, fc_router = switch_info_lst # current operation information string info = f'[{i+1} of {switch_num}]: {switch_name} fabric routing. FC Routing: {fc_router}' print(info, end=" ") # search control dictionary. continue to check sshow_file until all parameters groups are found collected = {'fcrfabric': False, 'fcrproxydev': False, 'fcrphydev': False, 'lsanzone': False, 'fcredge': False, 'fcrresource': False} \ if switch_role == 'Principal' else {'fcredge': False, 'fcrresource': False} # check config of FC routers only if fc_router == 'ON': # fcrouter_info_lst contains sshow_file, chassis_name, switch_index, switch_name, switch_fid fcrouter_info_lst = [*switch_info_lst[:6], switch_info_lst[7]] with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # check configs of Principal switches only if switch_role == 'Principal': # fcrfabricshow section start # switchcmd_fcrfabricshow if re.search(comp_dct[comp_keys[0]], line) and not collected['fcrfabric']: collected['fcrfabric'] = True if ls_mode_on: while not re.search( fr'^BASE +SWITCH +CONTEXT *-- *FID: *{fid}$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[4]], line): line = file.readline() # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # fc_router_match' if match_dct[match_keys[1]]: fcrouter_params_lst = line_to_list( comp_dct[comp_keys[1]], line) # check if line is empty while not re.match('\r?\n', line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # fcr_info_match if match_dct[match_keys[2]]: fcrouter_name = match_dct[ match_keys[2]].group(1) # fcr_exports_match if match_dct[match_keys[3]]: fcrfabric_lst.append( line_to_list( comp_dct[comp_keys[3]], line, *fcrouter_info_lst, fcrouter_name, *fcrouter_params_lst)) if not line: break if not line: break # fcrfabricshow section end # fcrproxydev and fcrphydev checked in a loop over dictionary keys coz data representation is similar # fcrdevshow section start for fcrdev_type in fcrdev_dct.keys(): re_num, fcrdev_lst, slice_index = fcrdev_dct[ fcrdev_type] # switchcmd_fcrproxydevshow_comp if re.search( comp_dct[comp_keys[re_num]], line) and not collected[fcrdev_type]: collected[fcrdev_type] = True if ls_mode_on: while not re.search( fr'^BASE +SWITCH +CONTEXT *-- *FID: *{fid} *$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search( comp_dct[comp_keys[4]], line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # fcrdevshow_match if match_dct[match_keys[7]]: fcrdev_lst.append( line_to_list( comp_dct[comp_keys[7]], line, *fcrouter_info_lst) [:slice_index]) if not line: break # fcrdevshow section end # lsanzoneshow section start if re.search(comp_dct[comp_keys[8]], line) and not collected['lsanzone']: collected['lsanzone'] = True if ls_mode_on: while not re.search( fr'^BASE +SWITCH +CONTEXT *-- *FID: *{fid} *$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[4]], line): match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # lsan_name_match if match_dct[match_keys[9]]: # switch_info and current connected device wwnp lsan_name = line_to_list( comp_dct[comp_keys[9]], line) # move cursor to one line down to get inside while loop line = file.readline() # lsan_switchcmd_end_comp while not re.search( comp_dct[comp_keys[11]], line): # line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # lsan_members_match if match_dct[match_keys[10]]: lsan_member = line_to_list( comp_dct[comp_keys[10]], line) lsan_lst.append([ *fcrouter_info_lst, *lsan_name, *lsan_member ]) # line = file.readline() # else: # line = file.readline() line = file.readline() if not line: break else: line = file.readline() if not line: break # lsanzoneshow section end # fcredge and fcrresource checked for Principal and Subordinate routers # fcredgeshow section start if re.search(comp_dct[comp_keys[12]], line) and not collected['fcredge']: collected['fcredge'] = True if ls_mode_on: while not re.search( fr'^BASE +SWITCH +CONTEXT *-- *FID: *{fid} *$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[4]], line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # fcredgeshow_match if match_dct[match_keys[13]]: # fcredge_lst.append(line_to_list(comp_dct[comp_keys[13]], line, *fcrouter_info_lst, switch_wwn)) fcredge_lst.append( line_to_list(comp_dct[comp_keys[13]], line, *fcrouter_info_lst)) if not line: break # fcredgeshow section end # fcrresourceshow section start if re.search(comp_dct[comp_keys[14]], line) and not collected['fcrresource']: collected['fcrresource'] = True fcrresource_dct = {} if ls_mode_on: while not re.search( fr'^BASE +SWITCH +CONTEXT *-- *FID: *{fid} *$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[4]], line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # fcredgeshow_match if match_dct[match_keys[15]]: fcrresource_dct[match_dct[match_keys[15]].group(1).rstrip()] = \ [match_dct[match_keys[15]].group(2), match_dct[match_keys[15]].group(3)] if not line: break # each value of dictionary is list of two elements # itertools.chain makes flat tmp_lst list from all lists in dictionary tmp_lst = list( itertools.chain(*[ fcrresource_dct.get(param ) if fcrresource_dct. get(param) else [None, None] for param in params ])) fcrresource_lst.append( [*fcrouter_info_lst, *tmp_lst]) # fcrresourceshow section end status_info('ok', max_title, len(info)) else: status_info('skip', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, fcrfabric_lst, fcrproxydev_lst, fcrphydev_lst, lsan_lst, fcredge_lst, fcrresource_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: fcrfabric_lst, fcrproxydev_lst, fcrphydev_lst, lsan_lst, fcredge_lst, fcrresource_lst = verify_data( report_data_lst, data_names, *data_lst) return fcrfabric_lst, fcrproxydev_lst, fcrphydev_lst, lsan_lst, fcredge_lst, fcrresource_lst
def interswitch_connection_extract(switch_params_lst, report_data_lst): """Function to extract interswitch connection information""" # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['isl', 'trunk', 'porttrunkarea'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking isl_lst, trunk_lst, porttrunkarea_lst = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [ report_steps_dct[data_name][1] for data_name in data_names ] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): print( '\nEXTRACTING INTERSWITCH CONNECTION INFORMATION (ISL, TRUNK, TRUNKAREA) ...\n' ) # extract chassis parameters names from init file switch_columns = columns_import('switch', max_title, 'columns') # number of switches to check switch_num = len(switch_params_lst) # data imported from init file to extract values from config file *_, comp_keys, match_keys, comp_dct = data_extract_objects( 'isl', max_title) # lists to store only REQUIRED infromation # collecting data for all switches ports during looping isl_lst = [] trunk_lst = [] porttrunkarea_lst = [] # switch_params_lst [[switch_params_sw1], [switch_params_sw1]] # checking each switch for switch level parameters for i, switch_params_data in enumerate(switch_params_lst): # data unpacking from iter param # dictionary with parameters for the current switch switch_params_data_dct = dict( zip(switch_columns, switch_params_data)) switch_info_keys = [ 'configname', 'chassis_name', 'chassis_wwn', 'switch_index', 'SwitchName', 'switchWwn', 'switchRole', 'Fabric_ID', 'FC_Router', 'switchMode' ] switch_info_lst = [ switch_params_data_dct.get(key) for key in switch_info_keys ] ls_mode_on = True if switch_params_data_dct[ 'LS_mode'] == 'ON' else False sshow_file, _, _, switch_index, switch_name, *_, switch_mode = switch_info_lst # current operation information string info = f'[{i+1} of {switch_num}]: {switch_name} isl, trunk and trunk area ports. Switch mode: {switch_mode}' print(info, end=" ") # search control dictionary. continue to check sshow_file until all parameters groups are found collected = {'isl': False, 'trunk': False, 'trunkarea': False} if switch_mode == 'Native': with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # isl section start # switchcmd_islshow_comp if re.search(comp_dct[comp_keys[0]], line) and not collected['isl']: collected['isl'] = True if ls_mode_on: while not re.search( fr'^CURRENT CONTEXT -- {switch_index} *, \d+$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[2]], line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # islshow_match if match_dct[match_keys[1]]: isl_port = line_to_list( comp_dct[comp_keys[1]], line, *switch_info_lst[:-1]) # portcfg parameters if isl_port[-1]: isl_port[-1] = isl_port[-1].replace( ' ', ', ') # appending list with only REQUIRED port info for the current loop iteration # to the list with all ISL port info isl_lst.append(isl_port) if not line: break # isl section end # trunk section start # switchcmd_trunkshow_comp if re.search(comp_dct[comp_keys[3]], line) and not collected['trunk']: collected['trunk'] = True if ls_mode_on: while not re.search( fr'^CURRENT CONTEXT -- {switch_index} *, \d+$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[2]], line): match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # trunkshow_match if match_dct[match_keys[4]]: trunk_port = line_to_list( comp_dct[comp_keys[4]], line, *switch_info_lst[:-1]) # if trunk line has trunk number then remove ":" from trunk number if trunk_port[9]: trunk_port[9] = trunk_port[9].strip( ':') trunk_num = trunk_port[9] # if trunk line has no number then use number from previous line else: trunk_port[9] = trunk_num # appending list with only REQUIRED trunk info for the current loop iteration # to the list with all trunk port info trunk_lst.append(trunk_port) line = file.readline() if not line: break # trunk section end # porttrunkarea section start # switchcmd_trunkarea_comp if re.search(comp_dct[comp_keys[5]], line) and not collected['trunkarea']: collected['trunkarea'] = True if ls_mode_on: while not re.search( fr'^CURRENT CONTEXT -- {switch_index} *, \d+$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[2]], line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # 'porttrunkarea_match' if match_dct[match_keys[6]]: porttrunkarea_port_lst = line_to_list( comp_dct[comp_keys[6]], line, *switch_info_lst[:6]) # for No_light ports port and slot numbers are '--' if porttrunkarea_port_lst[11] == '--': porttrunkarea_port_lst[10] = '--' # if switch has no slots than slot number is 0 for idx in [6, 10]: if not porttrunkarea_port_lst[idx]: porttrunkarea_port_lst[idx] = str( 0) porttrunkarea_lst.append( porttrunkarea_port_lst) if not line: break # porttrunkarea section end status_info('ok', max_title, len(info)) # if switch in Access Gateway mode then skip else: status_info('skip', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, isl_lst, trunk_lst, porttrunkarea_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: isl_lst, trunk_lst, porttrunkarea_lst = verify_data( report_data_lst, data_names, *data_lst) return isl_lst, trunk_lst, porttrunkarea_lst
def connected_devices_extract(switch_params_lst, report_data_lst): """Function to extract connected devices information (fdmi, nsshow, nscamshow) """ # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['fdmi', 'nsshow', 'nscamshow'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking fdmi_lst, nsshow_lst, nscamshow_lst = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [ report_steps_dct[data_name][1] for data_name in data_names ] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): print( '\nEXTRACTING INFORMATION ABOUT CONNECTED DEVICES (FDMI, NSSHOW, NSCAMSHOW) ...\n' ) # extract chassis parameters names from init file switch_columns = columns_import('switch', max_title, 'columns') # number of switches to check switch_num = len(switch_params_lst) # data imported from init file to extract values from config file params, params_add, comp_keys, match_keys, comp_dct = data_extract_objects( 'connected_dev', max_title) nsshow_params, nsshow_params_add = columns_import( 'connected_dev', max_title, 'nsshow_params', 'nsshow_params_add') # lists to store only REQUIRED infromation # collecting data for all switches ports during looping fdmi_lst = [] # lists with local Name Server (NS) information nsshow_lst = [] nscamshow_lst = [] # dictionary with required to collect nsshow data # first element of list is regular expression pattern number, second - list to collect data nsshow_dct = { 'nsshow': [5, nsshow_lst], 'nscamshow': [6, nscamshow_lst] } # switch_params_lst [[switch_params_sw1], [switch_params_sw1]] # checking each switch for switch level parameters for i, switch_params_data in enumerate(switch_params_lst): # data unpacking from iter param # dictionary with parameters for the current chassis switch_params_data_dct = dict( zip(switch_columns, switch_params_data)) switch_info_keys = [ 'configname', 'chassis_name', 'chassis_wwn', 'switch_index', 'SwitchName', 'switchWwn', 'switchMode' ] switch_info_lst = [ switch_params_data_dct.get(key) for key in switch_info_keys ] ls_mode_on = True if switch_params_data_dct[ 'LS_mode'] == 'ON' else False sshow_file, *_, switch_index, switch_name, _, switch_mode = switch_info_lst # current operation information string info = f'[{i+1} of {switch_num}]: {switch_name} connected devices' print(info, end=" ") # search control dictionary. continue to check sshow_file until all parameters groups are found # Name Server service started only in Native mode collected = {'fdmi': False, 'nsshow': False, 'nscamshow': False} \ if switch_params_data_dct.get('switchMode') == 'Native' else {'fdmi': False} with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # fdmi section start # switchcmd_fdmishow_comp if re.search(comp_dct[comp_keys[0]], line): collected['fdmi'] = True if ls_mode_on: while not re.search( fr'^CURRENT CONTEXT -- {switch_index} *, \d+$', line): line = file.readline() if not line: break # local_database_comp while not re.search(comp_dct[comp_keys[4]], line): match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # wwnp_match if match_dct[match_keys[1]]: # dictionary to store all DISCOVERED switch ports information # collecting data only for the logical switch in current loop fdmi_dct = {} # switch_info and current connected device wwnp switch_wwnp = line_to_list( comp_dct[comp_keys[1]], line, *switch_info_lst[:6]) # move cursor to one line down to get inside while loop line = file.readline() # wwnp_local_comp while not re.search(comp_dct[comp_keys[3]], line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # fdmi_port_match if match_dct[match_keys[2]]: fdmi_dct[match_dct[match_keys[ 2]].group(1).rstrip()] = match_dct[ match_keys[2]].group( 2).rstrip() if not line: break # adding additional parameters and values to the fdmi_dct update_dct(params_add, switch_wwnp, fdmi_dct) # appending list with only REQUIRED port info for the current loop iteration to the list with all fabrics port info fdmi_lst.append([ fdmi_dct.get(param, None) for param in params ]) else: line = file.readline() if not line: break # fdmi section end # only switches in Native mode have Name Server service started if switch_mode == 'Native': # nsshow section start for nsshow_type in nsshow_dct.keys(): # unpacking re number and list to save REQUIRED params re_num, ns_lst = nsshow_dct[nsshow_type] # switchcmd_nsshow_comp, switchcmd_nscamshow_comp if re.search(comp_dct[comp_keys[re_num]], line): collected[nsshow_type] = True if ls_mode_on: while not re.search( fr'^CURRENT CONTEXT -- {switch_index} *, \d+$', line): line = file.readline() if not line: break # switchcmd_end_comp while not re.search(comp_dct[comp_keys[9]], line): # line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # port_pid__match if match_dct[match_keys[7]]: # dictionary to store all DISCOVERED switch ports information # collecting data only for the logical switch in current loop nsshow_port_dct = {} # switch_info and current connected device wwnp switch_pid = line_to_list( comp_dct[comp_keys[7]], line, *switch_info_lst[:6]) # move cursor to one line down to get inside while loop line = file.readline() # pid_switchcmd_end_comp while not re.search( comp_dct[comp_keys[8]], line): match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # nsshow_port_match if match_dct[match_keys[2]]: nsshow_port_dct[match_dct[ match_keys[2]].group( 1 ).rstrip()] = match_dct[ match_keys[2]].group( 2).rstrip() line = file.readline() if not line: break # adding additional parameters and values to the fdmi_dct update_dct(nsshow_params_add, switch_pid, nsshow_port_dct) # appending list with only REQUIRED port info for the current loop iteration to the list with all fabrics port info ns_lst.append([ nsshow_port_dct.get( nsshow_param, None) for nsshow_param in nsshow_params ]) else: line = file.readline() if not line: break # nsshow section end status_info('ok', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, fdmi_lst, nsshow_lst, nscamshow_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: fdmi_lst, nsshow_lst, nscamshow_lst = verify_data( report_data_lst, data_names, *data_lst) return fdmi_lst, nsshow_lst, nscamshow_lst
def switch_params_configshow_extract(chassis_params_fabric_lst, report_data_lst): """Function to extract switch parameters""" # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['switch_parameters', 'switchshow_ports'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking switch_params_lst, switchshow_ports_lst = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [report_steps_dct[data_name][1] for data_name in data_names] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): print('\nEXTRACTING SWITCH PARAMETERS FROM SUPPORTSHOW CONFIGURATION FILES ...\n') # extract chassis parameters names from init file chassis_columns = columns_import('chassis', max_title, 'columns') # number of switches to check switch_num = len(chassis_params_fabric_lst) # list to store only REQUIRED switch parameters # collecting data for all switches during looping switch_params_lst = [] # list to store switch ports details switchshow_ports_lst = [] # data imported from init file to extract values from config file switch_params, params_add, comp_keys, match_keys, comp_dct = data_extract_objects('switch', max_title) # chassis_params_fabric_lst [[chassis_params_sw1], [chassis_params_sw1]] # checking each chassis for switch level parameters for i, chassis_params_data in enumerate(chassis_params_fabric_lst): # data unpacking from iter param # dictionary with parameters for the current chassis chassis_params_data_dct = dict(zip(chassis_columns, chassis_params_data)) sshow_file = chassis_params_data_dct['configname'] chassis_name = chassis_params_data_dct['chassis_name'] chassis_wwn = chassis_params_data_dct['chassis_wwn'] # num_ls = int(chassis_params_data_dct["Number_of_LS"]) if not chassis_params_data_dct["Number_of_LS"] in ['0', None] else 1 # when num of logical switches is 0 or None than mode is Non-VF otherwise VF ls_mode_on = (True if not chassis_params_data_dct["Number_of_LS"] in ['0', None] else False) ls_mode = ('ON' if not chassis_params_data_dct["Number_of_LS"] in ['0', None] else 'OFF') # logical switches indexes. if switch is in Non-VF mode then ls_id is 0 ls_ids = chassis_params_data_dct['LS_IDs'].split(', ') if chassis_params_data_dct['LS_IDs'] else ['0'] # current operation information string info = f'[{i+1} of {switch_num}]: {chassis_params_data_dct["chassis_name"]} switch parameters. Number of LS: {chassis_params_data_dct["Number_of_LS"]}' print(info, end =" ") # check each logical switch in chassis for i in ls_ids: # search control dictionary. continue to check sshow_file until all parameters groups are found collected = {'configshow': False, 'switchshow': False} # dictionary to store all DISCOVERED switch parameters # collecting data only for the logical switch in current loop switch_params_dct = {} with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # configshow section start if re.search(fr'^\[Switch Configuration Begin *: *{i}\]$', line) and not collected['configshow']: # when section is found corresponding collected dict values changed to True collected['configshow'] = True while not re.search(fr'^\[Switch Configuration End : {i}\]$',line): line = file.readline() # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct ={match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys)} # match_keys ['switch_configall_match', 'switch_switchshow_match'] if match_dct[match_keys[0]]: switch_params_dct[match_dct[match_keys[0]].group(1).rstrip()] = match_dct[match_keys[0]].group(3).rstrip() if not line: break # config section end # switchshow section start if re.search(r'^(SWITCHCMD /fabos/bin/)?switchshow *:$', line) and not collected['switchshow']: collected['switchshow'] = True if ls_mode_on: while not re.search(fr'^CURRENT CONTEXT -- {i} *, \d+$',line): line = file.readline() if not line: break while not re.search(r'^real [\w.]+$',line): line = file.readline() match_dct ={match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys)} # 'switch_switchshow_match' if match_dct[match_keys[1]]: switch_params_dct[match_dct[match_keys[1]].group(1).rstrip()] = match_dct[match_keys[1]].group(2).rstrip() # 'ls_attr_match' if match_dct[match_keys[2]]: ls_attr = comp_dct[comp_keys[2]].findall(line)[0] for k, v in zip(ls_attr[::2], ls_attr[1::2]): switch_params_dct[k] = v # 'switchshow_portinfo_match' if match_dct[match_keys[3]]: switchinfo_lst = [sshow_file, chassis_name, chassis_wwn, str(i), switch_params_dct.get('switchName', None), switch_params_dct.get('switchWwn', None), switch_params_dct.get('switchState', None), switch_params_dct.get('switchMode', None) ] switchshow_port_lst = line_to_list(comp_dct[comp_keys[3]], line, *switchinfo_lst) # if switch has no slots than slot number is 0 if not switchshow_port_lst[9]: switchshow_port_lst[9] = str(0) switchshow_ports_lst.append(switchshow_port_lst) if not line: break # switchshow section end # additional values which need to be added to the switch params dictionary # switch_params_add order ('configname', 'chassis_name', 'switch_index', 'ls_mode') # values axtracted in manual mode. if change values order change keys order in init.xlsx switch tab "params_add" column switch_params_values = (sshow_file, chassis_name, chassis_wwn, str(i), ls_mode) if switch_params_dct: # adding additional parameters and values to the switch_params_switch_dct update_dct(params_add, switch_params_values, switch_params_dct) # creating list with REQUIRED chassis parameters for the current switch. # if no value in the switch_params_dct for the parameter then None is added # and appending this list to the list of all switches switch_params_fabric_lst switch_params_lst.append([switch_params_dct.get(switch_param, None) for switch_param in switch_params]) status_info('ok', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, switch_params_lst, switchshow_ports_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: switch_params_lst, switchshow_ports_lst = verify_data(report_data_lst, data_names, *data_lst) return switch_params_lst, switchshow_ports_lst
def parse_config(config_3par, params, params_add, comp_keys, match_keys, comp_dct): """Function to parse 3PAR config file""" # file name configname = os.path.basename(config_3par) # search control dictionary. continue to check file until all parameters groups are found collected = {'system': False, 'ip': False, 'port': False, 'host': False} # initialize structures to store collected data for current storage # dictionary to store all DISCOVERED parameters showsys_dct = {} showsys_lst = [] # if lists remains empty after file parsing than status_info shows NO_DATA for current file port_lst = [] host_lst = [] # Storage IP address ip_addr = None with open(config_3par, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # showsys section start if re.search(comp_dct['showsys_header'], line) and not collected['system']: collected['system'] = True # while not reach empty line while not re.search(comp_dct['section_end'], line): line = file.readline() # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys) } # name_value_pair_match if match_dct['parameter_value_pair']: result = match_dct['parameter_value_pair'] showsys_dct[result.group(1).strip()] = result.group( 2).strip() if not line: break # showsys section end # port section start elif re.search(comp_dct['showport_header'], line) and not collected['port']: collected['port'] = True while not re.search(comp_dct['section_end'], line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys) } # port_line_match if match_dct['port_line']: port_line = line_to_list(comp_dct['port_line'], line, configname) port_lst.append(port_line) line = file.readline() if not line: break # port section end # host section start elif re.search(comp_dct['showhost_header'], line) and not collected['host']: collected['host'] = True while not re.search(comp_dct['section_end'], line): # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip(comp_keys, match_keys) } # port_line_match if match_dct['host_line']: host_line = line_to_list(comp_dct['host_line'], line, configname) host_lst.append(host_line) line = file.readline() if not line: break # host section end # ip_address section start elif re.search(comp_dct['ip_address'], line) and not collected['ip']: collected['ip'] = True ip_addr = re.search(comp_dct['ip_address'], line).group(1) # ip_address section end # additional values which need to be added to the switch params dictionary # switch_params_add order ('configname', 'chassis_name', 'switch_index', 'ls_mode') # values axtracted in manual mode. if change values order change keys order in init.xlsx switch tab "params_add" column showsys_values = (configname, ip_addr) if showsys_dct: # adding additional parameters and values to the parameters dct update_dct(params_add, showsys_values, showsys_dct) # creating list with REQUIRED parameters for the current system. # if no value in the dct for the parameter then None is added # and appending this list to the list of all systems showsys_lst.append([showsys_dct.get(param) for param in params]) return showsys_lst, port_lst, host_lst
def portcmdshow_extract(chassis_params_fabric_lst, report_data_lst): """Function to extract portshow, portloginshow, portstatsshow information""" # report_data_lst contains information: # customer_name, dir_report, dir to save obtained data, max_title, report_steps_dct *_, max_title, report_steps_dct = report_data_lst # names to save data obtained after current module execution data_names = ['portcmd'] # service step information print(f'\n\n{report_steps_dct[data_names[0]][3]}\n') # load data if they were saved on previos program execution iteration data_lst = load_data(report_data_lst, *data_names) # unpacking from the loaded list with data # pylint: disable=unbalanced-tuple-unpacking portshow_lst, = data_lst # data force extract check # list of keys for each data from data_lst representing if it is required # to re-collect or re-analyze data even they were obtained on previous iterations force_extract_keys_lst = [ report_steps_dct[data_name][1] for data_name in data_names ] # print data which were loaded but for which force extract flag is on force_extract_check(data_names, data_lst, force_extract_keys_lst, max_title) # when any of data_lst was not saved or # force extract flag is on then re-extract data from configueation files if not all(data_lst) or any(force_extract_keys_lst): print( '\nEXTRACTING PORTSHOW, PORTLOGINSHOW, PORTSTATSSHOW INFORMATION FROM SUPPORTSHOW CONFIGURATION FILES ...\n' ) # extract chassis parameters names from init file chassis_columns = columns_import('chassis', max_title, 'columns') # number of switches to check switch_num = len(chassis_params_fabric_lst) # list to store only REQUIRED switch parameters # collecting data for all switches during looping portshow_lst = [] # data imported from init file to extract values from config file portcmd_params, params_add, comp_keys, match_keys, comp_dct = data_extract_objects( 'portcmd', max_title) # chassis_params_fabric_lst [[chassis_params_sw1], [chassis_params_sw1]] # checking each chassis for switch level parameters for i, chassis_params_data in enumerate(chassis_params_fabric_lst): # data unpacking from iter param # dictionary with parameters for the current chassis chassis_params_data_dct = dict( zip(chassis_columns, chassis_params_data)) sshow_file = chassis_params_data_dct['configname'] chassis_name = chassis_params_data_dct['chassis_name'] chassis_wwn = chassis_params_data_dct['chassis_wwn'] # current operation information string info = f'[{i+1} of {switch_num}]: {chassis_params_data_dct["chassis_name"]} switch portshow, portloginshow and statsshow' print(info, end=" ") # search control dictionary. continue to check sshow_file until all parameters groups are found collected = {'portshow': False} with open(sshow_file, encoding='utf-8', errors='ignore') as file: # check file until all groups of parameters extracted while not all(collected.values()): line = file.readline() if not line: break # sshow_port section start if re.search(r'^\| Section: SSHOW_PORT \|$', line): # when section is found corresponding collected dict values changed to True collected['portshow'] = True while not re.search(r'^\| ... rebuilt finished *\|$', line): line = file.readline() if not line: break # dictionary with match names as keys and match result of current line with all imported regular expressions as values match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # portFcPortCmdShow section start if match_dct[match_keys[0]]: # dictionary to store all DISCOVERED parameters # collecting data only for the chassis in current loop portcmd_dct = {} # connected devices wwns in portshow section connected_wwn_lst = [] # list to store connected devices port_id and wwn pairs in portlogin section portid_wwn_lst = [] port_index = None slot_port_lst = line_to_list( comp_dct[comp_keys[0]], line) while not re.search(r'^portshow +(\d{1,4})$', line): line = file.readline() if not line: break match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # portshow section start if match_dct[match_keys[1]]: port_index = match_dct[ match_keys[1]].group(1) while not re.search( fr'^portloginshow +{int(port_index)}$', line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # portshow_params_match if match_dct[match_keys[2]]: portshow_attr, = comp_dct[ comp_keys[2]].findall(line) # portstate parameter has special processing rule if portshow_attr[0] == 'portState': portcmd_dct[ 'portState'] = portshow_attr[ 2] # portshow_attr can contain up to 3 parameter name and value pairs # parameters name on even positions in the portshow_attr and values on odd else: for k, v in zip( portshow_attr[::2], portshow_attr[1::2]): portcmd_dct[k] = v # portscn_match has two parameter name and value pairs if match_dct[match_keys[6]]: portscn_line = line_to_list( comp_dct[comp_keys[6]], line) for k, v in zip( portscn_line[::2], portscn_line[1::2]): portcmd_dct[k] = v # portdistance_match if match_dct[match_keys[7]]: portdistance_line = line_to_list( comp_dct[comp_keys[7]], line) portcmd_dct[portdistance_line[ 0]] = portdistance_line[1] # device_connected_wwn_match if match_dct[match_keys[8]]: connected_wwn = line_to_list( comp_dct[comp_keys[8]], line) connected_wwn_lst.append( (portcmd_dct.get('portId'), connected_wwn)) if not line: break # portshow section end # portlogin section start if re.match( fr'^portloginshow +{int(port_index)}$', line): while not re.search( fr'^portregshow +{int(port_index)}$', line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # connected_wwn_match if match_dct[match_keys[3]]: # first value in tuple unpacking is fe or fd and not required _, port_id, wwn = line_to_list( comp_dct[comp_keys[3]], line) # port_id = '0x' + port_id portid_wwn_lst.append( (port_id, wwn)) if not line: break # sorting connected devices list by port_ids if len(portid_wwn_lst) != 0: portid_wwn_lst = sorted(portid_wwn_lst) # if portlogin empty then use connected devices from portshow section # applied for E-ports elif len(connected_wwn_lst) != 0: portid_wwn_lst = connected_wwn_lst.copy( ) # adding port_id and None wwn if no device is connected or slave trunk link else: portid_wwn_lst.append( [portcmd_dct.get('portId'), None]) # portlogin section end while not re.match( fr'^portstatsshow +{int(port_index)}$', line): line = file.readline() if not line: break # portstatsshow section start if re.match( fr'^portstatsshow +{int(port_index)}$', line): while not re.search( fr'^(portstats64show|portcamshow) +{int(port_index)}$', line): line = file.readline() match_dct = { match_key: comp_dct[comp_key].match(line) for comp_key, match_key in zip( comp_keys, match_keys) } # port information without virtual channel numbers if match_dct[match_keys[4]]: portcmd_dct[match_dct[ match_keys[4]].group( 1).rstrip()] = match_dct[ match_keys[4]].group(2) # port information with virtual channel numbers elif match_dct[match_keys[5]]: line_values = line_to_list( comp_dct[comp_keys[5]], line) param_name, start_vc = line_values[ 0:2] for i, value in enumerate( line_values[3:]): param_name_vc = param_name + '_' + str( int(start_vc) + i) portcmd_dct[ param_name_vc] = value if not line: break # portstatsshow section end # portFcPortCmdShow section end # additional values which need to be added to the dictionary with all DISCOVERED parameters during current loop iteration # chassis_slot_port_values order (configname, chassis_name, port_index, slot_num, port_num, port_ids and wwns of connected devices) # values axtracted in manual mode. if change values order change keys order in init.xlsx "chassis_params_add" column for port_id, connected_wwn in portid_wwn_lst: chassis_slot_port_values = [ sshow_file, chassis_name, chassis_wwn, port_index, *slot_port_lst, port_id, connected_wwn ] # print('chassis_slot_port_values', chassis_slot_port_values) # adding or changing data from chassis_slot_port_values to the DISCOVERED dictionary update_dct(params_add, chassis_slot_port_values, portcmd_dct) # adding data to the REQUIRED list for each device connected to the port portshow_lst.append([ portcmd_dct.get(portcmd_param, None) for portcmd_param in portcmd_params ]) # print('portshow_lst', portshow_lst) # sshow_port section end status_info('ok', max_title, len(info)) # save extracted data to json file save_data(report_data_lst, data_names, portshow_lst) # verify if loaded data is empty after first iteration and replace information string with empty list else: portshow_lst = verify_data(report_data_lst, data_names, *data_lst) return portshow_lst