def _isl_redundant(obj, t_obj): """Check to see if there are at least two ISLs between switch pairs. Ignores connections to AMP :param obj: Switch object from the object list, obj_list, passed to best_practice() :type obj: brcddb.classes.switch.switch_obj :param t_obj: Individual test item from the test_list passed to best_practice(). Not used :type t_obj: dict :return: List of alert dictionaries {'a': alert number, 'p0': p0, 'p1': p1, 'k': '_isl_map'} :rtype: list """ r_list = list() # Validate input obj_type = brcddb_class_util.get_simple_class_type(obj) if obj_type is None: obj_type = str(type(obj)) if obj_type != 'SwitchObj': brcdapi_log.exception('Invalid object type. Expected switch_obj. Received: ' + obj_type, True) return r_list proj_obj = obj.r_project_obj() isl_map = obj.c_trunk_map() for k in isl_map.keys(): switch_pair = isl_map.get(k) if _amp_in_switch_pair(obj, k, switch_pair): continue if len(list(switch_pair.keys())) == 1: r_list.append({'a': t_obj.get('m'), 'p0': brcddb_switch.best_switch_name(obj), 'p1': brcddb_switch.best_switch_name(proj_obj.r_switch_obj(k)), 'k': 'trunk'}) return r_list
def _project_page(wb, sheet_index, b_proj_obj, c_proj_obj, c_obj): """Recursively iterates through a list of changes from compare.compare() for fabric. Create fabric pages as needed :param wb: Workbook object :type wb: dict :param sheet_index: Starting sheet index :type sheet_index: int :param b_proj_obj: Project object for base (project we are comparing against). Typically the older project. :type b_proj_obj: brcddb.classes.project.ProjectObj :param c_proj_obj: Comparison project object. Typically the newer project. :type c_proj_obj: brcddb.classes.project.ProjectObj :param c_obj: This is the object from compare.compare() that we are working on :type c_obj: dict :return sheet_index: Next sheet index :rtype sheet_index: int :return tbl_contents: Table of contents for the fabrics :rtype. tbl_contents: list """ # Set up the table of contents and sheet headers content = [ dict(font='hdr_1', align='wrap', disp='Project changes'), dict(), dict(font='hdr_2', align='wrap', disp='Fabrics Added:'), ] # Add fabric changes for obj in [d for d in c_obj['_fabric_objs'].values() if d['r'] == 'Added']: content.append(dict(font='std', align='wrap', disp=brcddb_fabric.best_fab_name(c_proj_obj.r_fabric_obj(obj.get('c')), True))) content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Fabrics Removed:')]) for obj in [d for d in c_obj['_fabric_objs'].values() if d['r'] == 'Removed']: content.append(dict(font='std', align='wrap', disp=brcddb_fabric.best_fab_name(b_proj_obj.r_fabric_obj(obj.get('b')), True))) # Add switch changes content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Switches Added:')]) for obj in [d for d in c_obj['_switch_objs'].values() if d['r'] == 'Added']: content.append(dict(font='std', align='wrap', disp=brcddb_switch.best_switch_name(c_proj_obj.r_switch_obj(obj.get('c')), True))) content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Switches Removed:')]) for obj in [d for d in c_obj['_switch_objs'].values() if d['r'] == 'Removed']: content.append(dict(font='std', align='wrap', disp=brcddb_switch.best_switch_name(b_proj_obj.r_switch_obj(obj.get('b')), True))) # Add chassis changes content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Chassis Added:')]) for obj in [d for d in c_obj['_chassis_objs'].values() if d['r'] == 'Added']: content.append(dict(font='std', align='wrap', disp=brcddb_chassis.best_chassis_name(c_proj_obj.r_chassis_obj(obj.get('c')), True))) content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Chassis Removed:')]) for obj in [d for d in c_obj['_chassis_objs'].values() if d['r'] == 'Removed']: content.append(dict(font='std', align='wrap', disp=brcddb_chassis.best_chassis_name(b_proj_obj.r_chassis_obj(obj.get('b')), True))) # Sheet name and title sname = 'Project_Changes_' + str(sheet_index) report_utils.title_page(wb, None, sname, sheet_index, 'Project Changes', content, 80) return sheet_index+1, [dict(s=sname, d='Project Changes')]
def _switch_add_to_content(obj, b_obj, c_obj, content): """Same as _basic_add_to_content() except obj is a list of switch change objects""" start = len(content) for change_obj in [t_obj for t_obj in obj if t_obj.get('r') is not None]: b_buf = brcddb_switch.best_switch_name(b_obj.r_project_obj().r_switch_obj(change_obj.get('b')), True) c_buf = brcddb_switch.best_switch_name(c_obj.r_project_obj().r_switch_obj(change_obj.get('c')), True) _content_append(dict(font='std', align='wrap', disp=('', b_buf, c_buf, change_obj.get('r'))), content) if len(content) == start: content.append(dict(merge=4, font='std', align='wrap', disp=('No changes',)))
def _print_summary(switch_d_list): """Enable switch :param switch_d_list: List of switch dictionaries :type switch_d_list: list """ ml = ['\nSummary', '_______'] for switch_d in switch_d_list: ml.append('\nFID: ' + str(switch_d.get('fid'))) ml.append( ' Switch Name: ' + brcddb_switch.best_switch_name(switch_d.get('switch_obj'), True)) ml.append(' Switch Created: ' + str(switch_d.get('created'))) try: ml.append(' Ports Added: ' + str(len(switch_d['ports'].keys()))) ml.append(' Ports Removed: ' + str(len(switch_d['remove_ports']))) ml.append(' Online Ports Not Moved: ' + str(len(switch_d['online_ports']))) ml.append(' Ports Not Found: ' + str(len(switch_d['not_found_ports']))) except: pass # We should never get here but I'm not changing working code. err_msgs = gen_util.convert_to_list(switch_d.get('err_msgs')) if len(err_msgs) > 0: ml.append(' Error Messages: ') ml.extend([' ' + buf for buf in err_msgs]) brcdapi_log.log(ml, True)
def _isl_bw(obj, t_obj): """Check to see that all trunk masters logged in at the same speed :param obj: Switch object from the object list, obj_list, passed to best_practice() :type obj: brcddb.classes.switch.switch_obj :param t_obj: Individual test item from the test_list passed to best_practice(). Not used :type t_obj: dict :return: List of alert dictionaries {'a': alert number, 'p0': p0, 'p1': p1, 'k': '_isl_map'} :rtype: list """ r_list = list() # Validate input obj_type = brcddb_class_util.get_simple_class_type(obj) if obj_type is None: obj_type = str(type(obj)) if obj_type != 'SwitchObj': brcdapi_log.exception('Invalid object type. Expected switch_obj. Received: ' + obj_type, True) return r_list proj_obj = obj.r_project_obj() isl_map = obj.c_trunk_map() for k in isl_map.keys(): switch_pair = isl_map.get(k) if _amp_in_switch_pair(obj, k, switch_pair): continue speeds = list() for k1 in switch_pair.keys(): try: s = switch_pair.get(k1)[0][0].r_get('fibrechannel/speed') if s is not None: speeds.append(s) except: pass # We get here if all switches in the project were not polled if len(brcddb_util.remove_duplicates(speeds)) > 1: r_list.append({'a': t_obj.get('m'), 'p0': brcddb_switch.best_switch_name(obj), 'p1': brcddb_switch.best_switch_name(proj_obj.r_switch_obj(k)), 'k': 'trunk'}) return r_list
def _isl_fru(obj, t_obj): """Check to see if the trunks land on different FRUs. Ignores connections to AMP and fixed port switches :param obj: Switch object from the object list, obj_list, passed to best_practice() :type obj: brcddb.classes.switch.switch_obj :param t_obj: Individual test item from the test_list passed to best_practice(). Not used :type t_obj: dict :return: List of alert dictionaries {'a': alert number, 'p0': p0, 'p1': p1, 'k': '_isl_map'} :rtype: list """ r_list = list() # Validate input obj_type = brcddb_class_util.get_simple_class_type(obj) if obj_type is None: obj_type = str(type(obj)) if obj_type != 'SwitchObj': brcdapi_log.exception('Invalid object type. Expected switch_obj. Received: ' + obj_type, True) return r_list proj_obj = obj.r_project_obj() isl_map = obj.c_trunk_map() for k in isl_map.keys(): switch_pair = isl_map.get(k) if _amp_in_switch_pair(obj, k, switch_pair): continue slots = list() for k1 in switch_pair.keys(): tl = switch_pair.get(k1) for trunk in tl: if trunk[0] is not None: slots.append(trunk[0].r_obj_key().split('/')[0]) if len(brcddb_util.remove_duplicates(slots)) == 1 and slots[0] != '0': r_list.append({'a': t_obj.get('m'), 'p0': brcddb_switch.best_switch_name(obj), 'p1': brcddb_switch.best_switch_name(proj_obj.r_switch_obj(k)), 'k': 'trunk'}) return r_list
def _isl_num_links(obj, t_obj): """Check to see if the number of ISL in each trunk group is the same :param obj: Switch object from the object list, obj_list, passed to best_practice() :type obj: brcddb.classes.switch.switch_obj :param t_obj: Individual test item from the test_list passed to best_practice(). Not used :type t_obj: dict :return: List of alert dictionaries {'a': alert number, 'p0': p0, 'p1': p1, 'k': '_isl_map'} :rtype: list """ r_list = list() # Validate input obj_type = brcddb_class_util.get_simple_class_type(obj) if obj_type is None: obj_type = str(type(obj)) if obj_type != 'SwitchObj': brcdapi_log.exception('Invalid object type. Expected switch_obj. Received: ' + obj_type, True) return r_list proj_obj = obj.r_project_obj() isl_map = obj.c_trunk_map() for k in isl_map.keys(): switch_pair = isl_map.get(k) if _amp_in_switch_pair(obj, k, switch_pair): continue isls_per_trunk = list() for k1 in switch_pair.keys(): tl = switch_pair.get(k1) for trunk in tl: isls_per_trunk.append(len(trunk)) if len(brcddb_util.remove_duplicates(isls_per_trunk)) > 1: r_list.append({'a': t_obj.get('m'), 'p0': brcddb_switch.best_switch_name(obj), 'p1': brcddb_switch.best_switch_name(proj_obj.r_switch_obj(k)), 'k': 'trunk'}) return r_list
def _fabric_switch_case(switch_obj, obj, uri): proj_obj = switch_obj.r_project_obj() tl = uri.split('/') leaf = tl[len(tl)-1] wwn_ref = 'switch-wwn' if leaf == 'fibrechannel-logical-switch' else 'name' for switch in brcddb_util.convert_to_list(obj.get('fibrechannel-switch')): wwn = switch.get(wwn_ref) if brcddb_util.is_wwn(wwn): # Yes, got bit by a bad WWN once s_obj = proj_obj.s_add_switch(wwn) if switch.get('principal'): fab_obj = proj_obj.s_add_fabric(wwn) _update_brcddb_obj_from_list(switch_obj, switch, uri) else: brcdapi_log.log('Bad switch WWN, , returned from ' + uri + ' for switch ' + brcddb_switch.best_switch_name(switch_obj), True)
def _process_errors(session, uri, obj, wobj): """Checks for errors in the API response and adds alerts to the object if there is an error :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param uri: URI, less the prefix :type uri: str :param obj: FOS API object :type obj: dict :param wobj: The brcddb class object we were working when the error occured :type wobj: brcddb.classes.project.ProjectObj, brcddb.classes.chassis.ChassisObj, brcddb.classes.switch.SwitchObj,\ None """ if not pyfos_auth.is_error(obj): return ip_addr = brcdapi_util.mask_ip_addr(session.get('ip_addr')) p1 = pyfos_auth.formatted_error_msg(obj) brcdapi_log.log(ip_addr + " Request FAILED:\n" + p1, True) if wobj is None: return proj_obj = wobj.r_project_obj() proj_obj.s_api_error_flag() error_table = dict( ProjectObj=dict( p0=ip_addr, al_num=al.ALERT_NUM.PROJ_FAILED_LOGIN if '/rest/login' in uri else al.ALERT_NUM.PROJ_CHASSIS_API_ERROR ), ChassisObj=dict(p0=brcddb_chassis.best_chassis_name(wobj), al_num=al.ALERT_NUM.PROJ_CHASSIS_API_ERROR), SwitchObj=dict(p0=brcddb_switch.best_switch_name(wobj), al_num=al.ALERT_NUM.PROJ_SWITCH_API_ERROR) ) simple_type = brcddb_class_util.get_simple_class_type(wobj) if simple_type in error_table: p0 = error_table[simple_type]['p0'] al_num = error_table[simple_type]['al_num'] else: brcdapi_log.exception('Unknown object type: ' + str(type(wobj))) return proj_obj.s_add_alert(al.AlertTable.alertTbl, al_num, None, p0, p1)
def port_best_desc(port_obj): """Finds the first descriptor for what's attached to the port in this order: 1 If E-Port, the upstream switch & port 2 FDMI Node descriptor 3 FDMI Port descriptor 4 Name server node descriptor 5 Name server port descriptor :param port_obj: Port Object :type port_obj: brcddb.classes.port.PortObj :return: desc :rtype: str """ if port_obj is None: return 'Unknown' wwn_list = brcddb_util.convert_to_list( port_obj.r_get('fibrechannel/neighbor/wwn')) if len(wwn_list) == 0: return '' # Try E-Port fab_obj = port_obj.r_fabric_obj() if fab_obj is None: return '' if port_obj.c_login_type() in ('E-Port', 'AE-Port'): brcddb_util.build_login_port_map(fab_obj.r_project_obj()) pobj = fab_obj.r_get('_port_map').get(wwn_list[0]) return '' if pobj is None else brcddb_switch.best_switch_name( pobj.r_switch_obj()) + ' port ' + pobj.r_obj_key() # Try Node, then port login_obj = fab_obj.r_login_obj(wwn_list[0]) if login_obj is None: return '' buf = brcddb_login.login_best_node_desc(login_obj) if len(buf) > 2: return buf return brcddb_login.login_best_port_desc(login_obj)
def _switch_ts(o, k): # Similar to _fabric_ts() obj = o.r_switch_obj(k) return brcddb_switch.best_switch_name(obj, True), brcddb_switch.best_switch_name(obj, False)
def l_switch_name_and_wwn_case(login_obj): return brcddb_switch.best_switch_name(login_obj.r_switch_obj(), True)
def _switch_name(p_obj, wwn, flag=True): return brcddb_switch.best_switch_name(p_obj.r_switch_obj(wwn), flag)
def report(proj_obj, outf, remove_pages=None, add_pages=None): """Creates an Excel report. Sort of a SAN Health like report. :param proj_obj: Project object :type proj_obj: brcddb.classes.project.ProjectObj :param outf: Output file name :type outf: str :param remove_pages: List of default pages to remove. Done first so you can clear all then add pages. :type remove_pages: None, str, list :param add_pages: Pages, in addition to the defaults, to add to the report :type add_pages: None, str, list """ global _report_pages # Figure out what pages to include in the report for key in brcddb_util.convert_to_list(remove_pages): d = _report_pages.get(key) if d is None: if key == 'all': for obj in _report_pages.values(): obj['s'] = False break else: brcdapi_log.log(key + ' is unkonwn in remove page list. ignored') else: d['s'] = False for key in brcddb_util.convert_to_list(add_pages): d = _report_pages.get(key) if d is None: if key == 'all': for obj in _report_pages.values(): obj['s'] = True break else: brcdapi_log.log(key + ' is unkonwn in add page list. ignored') else: d['s'] = True """port_pages is used to determine how to display pages +-------+-------------------------------------------------------------------------------+ | key | Description | +=======+===============================================================================+ | c | Key in the _report_pages table | +-------+-------------------------------------------------------------------------------+ | s | Sheet name prefix | +-------+-------------------------------------------------------------------------------+ | sc | Number of columns to skip | +-------+-------------------------------------------------------------------------------+ | t | The table used to control how the port data is displayed. | +-------+-------------------------------------------------------------------------------+ | d | Text to display as a header on the worksheet. | +-------+-------------------------------------------------------------------------------+ | l | When true, displays all the logins. Otherwise, just the base WWN is reported. | +-------+-------------------------------------------------------------------------------+ """ port_pages = [ dict(c='port_config', sc=1, s='_config', t=rt.Port.port_config_tbl, d='Port Configurations', l=False), dict(c='port_config_error', sc=1, s='_config_error', t=rt.Port.port_config_tbl, d='Port Configurations Error Summary', l=False), dict(c='port_stats', sc=1, s='_stats', t=rt.Port.port_stats_tbl, d='Port Statistics', l=False), dict(c='port_stats_error', sc=1, s='_stats_error', t=rt.Port.port_stats_tbl, d='Port Statistics Error Summary', l=False), dict(c='port_zone', sc=1, s='_zl', t=rt.Port.port_zone_tbl, d='Ports by Zone and Login', l=True), dict(c='port_zone_error', sc=1, s='_zl_error', t=rt.Port.port_zone_tbl, d='Ports by Zone and Login Error Summary', l=True), dict(c='port_sfp', sc=1, s='_sfp', t=rt.Port.port_sfp_tbl, d='SFP report', l=False), dict(c='port_sfp_error', sc=1, s='_sfp_error', t=rt.Port.port_sfp_tbl, d='SFP Error Summary', l=False), dict(c='port_rnid', sc=1, s='_ficon', t=rt.Port.port_rnid_tbl, d='Port RNID data', l=False), ] # tc_page = report_utils.valid_sheet_name.sub('', proj_obj.r_obj_key())[:29] + '_xx' tc_page = 'Table_of_Contents' tbl_contents = list() # Set up the workbook sheet_index = 0 wb = report_utils.new_report() # Check project for duplicate WWNs tbl_contents.append(dict(h=True, d='Duplicate WWNs')) wl = brcddb_project.dup_wwn(proj_obj) if len(wl) > 0: sname = 'dup_wwns' report_login.login_page(wb, tc_page, sname, sheet_index, 'Duplicate WWNs', wl, dup_login_tbl, rt.Login.login_display_tbl, False) tbl_contents.append(dict(sc=1, s=sname, d='Duplicate WWNs')) sheet_index += 1 else: tbl_contents.append(dict(sc=1, d='No Duplicate WWNs Found')) # Project dashboard if _report_pages['proj_dashboard']['s']: tbl_contents.append(dict(h=True, d='Project Links')) sname = 'proj_dashboard' title = 'Project Dashboard' dashboard(proj_obj, tc_page, wb, sheet_index, sname, title) tbl_contents.append(dict(sc=1, s=sname, d=title)) sheet_index += 1 # Add all the chassis if _report_pages['chassis']['s']: tbl_contents.append(dict(h=True, d='Chassis')) for chassis_obj in proj_obj.r_chassis_objects(): chassis_name = brcddb_chassis.best_chassis_name(chassis_obj) brcdapi_log.log('Processing chassis: ' + chassis_name, True) sname = report_utils.valid_sheet_name.sub( '', chassis_name.replace(' ', '_'))[:22] + '_' + str(sheet_index) report_chassis.chassis_page(wb, tc_page, sname, sheet_index, 'Chassis Detail For: ' + chassis_name, chassis_obj, rt.Chassis.chassis_display_tbl) tbl_contents.append(dict(sc=1, s=sname, d=chassis_name)) sheet_index += 1 # Add all the fabrics for fab_obj in proj_obj.r_fabric_objects(): fab_name = brcddb_fabric.best_fab_name(fab_obj) if len(fab_name) == 0: fab_name = 'Unknown Fabric' brcdapi_log.log('Processing fabric: ' + fab_name, True) tbl_contents.append(dict(h=True, d=fab_name)) prefix = report_utils.valid_sheet_name.sub( '', fab_name.replace(' ', '_'))[:20] + '_' + str(sheet_index) # Fabric summary page if _report_pages['fabric_summary']['s']: brcdapi_log.log(' Building fabric summary page', True) sname = prefix + '_sum' report_fabric.fabric_page(wb, tc_page, sheet_index, sname, fab_name + ' Summary', fab_obj) tbl_contents.append(dict(sc=1, s=sname, d='Fabric Summary')) sheet_index += 1 # Fabric Dashboard if _report_pages['fabric_dashboard']['s']: brcdapi_log.log(' Building fabric dashboard', True) sname = prefix + '_db' dashboard(fab_obj, tc_page, wb, sheet_index, sname, fab_name + ' Dasboard') tbl_contents.append(dict(sc=1, s=sname, d='Fabric Dashboard')) sheet_index += 1 # Switch page if _report_pages['switch']['s']: brcdapi_log.log(' Building switch detail page', True) sname = prefix + '_switch' report_switch.switch_page(wb, tc_page, sname, sheet_index, 'Switch Detail For Fabric: ' + fab_name, fab_obj.r_switch_objects(), rt.Switch.switch_display_tbl) tbl_contents.append(dict(sc=1, s=sname, d='Switch Detail')) sheet_index += 1 # Now the port pages brcdapi_log.log(' Building the port pages', True) port_list = brcddb_util.sort_ports(fab_obj.r_port_objects()) for obj in port_pages: if _report_pages[obj['c']]['s']: sname = prefix + obj.get('s') report_port.port_page(wb, tc_page, sname, sheet_index, fab_name + ' ' + obj.get('d'), port_list, obj.get('t'), rt.Port.port_display_tbl, obj.get('l')) tbl_contents.append(dict(sc=1, s=sname, d=obj.get('d'))) sheet_index += 1 # Zone Analysis Page if _report_pages['zone_page']['s']: brcdapi_log.log(' Building zone analysis page', True) sname = prefix + '_zone' report_zone.zone_page(fab_obj, tc_page, wb, sname, sheet_index, fab_name + ' Zone Analysis') tbl_contents.append(dict(sc=1, s=sname, d='Zone Analysis')) sheet_index += 1 # Taget Zone Page if _report_pages['t_zone_page']['s']: brcdapi_log.log(' Building target zone page', True) sname = prefix + '_tzone' report_zone.target_zone_page(fab_obj, tc_page, wb, sname, sheet_index, fab_name + ' Zone by Target') tbl_contents.append(dict(sc=1, s=sname, d='Zone by Target')) sheet_index += 1 # Alias Page if _report_pages['alias']['s']: brcdapi_log.log(' Building alias page', True) sname = prefix + '_alias' report_zone.alias_page(fab_obj, tc_page, wb, sname, sheet_index, fab_name + ' Alias Detail') tbl_contents.append(dict(sc=1, s=sname, d='Alias Detail')) sheet_index += 1 # Login Page if _report_pages['login']['s']: brcdapi_log.log(' Building login page', True) sname = prefix + '_login' report_login.login_page(wb, tc_page, sname, sheet_index, fab_name + ' Logins', fab_obj.r_login_objects(), rt.Login.login_tbl, rt.Login.login_display_tbl, True) tbl_contents.append(dict(sc=1, s=sname, d='Logins')) sheet_index += 1 # IOCP Page if _report_pages['iocp']['s']: iocp_objects = proj_obj.r_iocp_objects() if len(iocp_objects) > 0: brcdapi_log.log('Adding the IOCP pages', True) tbl_contents.append(dict(h=True, d='IOCPs')) for iocp_obj in iocp_objects: sname = report_utils.valid_sheet_name.sub( '', iocp_obj.r_obj_key())[:22] report_iocp.iocp_page(iocp_obj, tc_page, wb, sname, sheet_index, sname) tbl_contents.append(dict(sc=1, s=sname, d=sname)) sheet_index += 1 # Add the Best Practice page if _report_pages['bp']['s']: sname = 'Best_Practice' fab_name = 'Best Practice Violations' # Just borrowing fab_name for the title report_bp.bp_page(wb, tc_page, sname, 0, fab_name, proj_obj, rt.BestPractice.bp_tbl, rt.BestPractice.bp_display_tbl) tbl_contents.insert(0, dict(sc=1, s=sname, d=fab_name)) tbl_contents.insert(0, dict(h=True, d=fab_name)) # Add the missing chassis (chassis not polled) to the title & contents page i = 0 tbl_contents.append( dict(h=True, merge=3, d='Missing chassis (discovered in fabrics but not polled)')) for chassis_obj in proj_obj.r_chassis_objects(): if chassis_obj.r_get('brocade-chassis') is None: # Try to find a chassis name chassis_name = None for obj in chassis_obj.r_switch_objects(): chassis_name = obj.r_get( 'brocade-fabric/fabric-switch/chassis-user-friendly-name') if chassis_name is not None: break if chassis_name is None: chassis_name = 'Unknown' chassis_name += ' (' + chassis_obj.r_obj_key( ) + '). Known logical switches:' tbl_contents.append(dict(sc=1, d=chassis_name)) for obj in chassis_obj.r_switch_objects(): tbl_contents.append( dict(sc=2, d=brcddb_switch.best_switch_name(obj, True))) i += 1 if i == 0: tbl_contents.append(dict(sc=1, d='None')) # Insert the title & contents page proj_title_page(proj_obj, None, wb, 0, tc_page, 'Contents', contents=tbl_contents) # Save the report. report_utils.save_report(wb, outf)
def p_switch_name_and_wwn_case(port_obj, k, wwn): return brcddb_switch.best_switch_name(port_obj.r_switch_obj(), True)
def performance_dashboard(wb, tc, sheet_name, sheet_i, sheet_title, content): """Creates a dashboard worksheet for the Excel report. :param wb: Workbook object :type wb: class :param tc: Table of context page. A link to this page is place in cell A1 :type tc: str, None :param sheet_name: Sheet (tab) name :type sheet_name: str :param sheet_i: Sheet index where page is to be placed. :type sheet_i: int :param sheet_title: Title to be displayed in large font, hdr_1, at the top of the sheet :type sheet_title: str :param content: Caller defined content. List of lists or tuples to add to the title page. For example: dashboard = collections.OrderedDict() dashboard['class-3-discards'] = {'title' : 'Top 10 C3 Discards', 'port_list' : []} dashboard['in-crc-errors'] = {'title' : 'Top 10 CRC With Good EOF', 'port_list' : []} :type content: list, tuple :rtype: None """ hdr = collections.OrderedDict() # Key is the column header and value is the width hdr['Count'] = 14 hdr['Fabric'] = 22 hdr['Switch'] = 22 hdr['Port'] = 7 hdr['Type'] = 8 hdr['Description'] = 117 - (hdr['Count'] + hdr['Switch'] + hdr['Switch'] + hdr['Port'] + hdr['Type']) # Create the worksheet, add the title, and set up the column widths sheet = wb.create_sheet(index=sheet_i, title=sheet_name) sheet.page_setup.paperSize = sheet.PAPERSIZE_LETTER sheet.page_setup.orientation = sheet.ORIENTATION_LANDSCAPE col = 1 row = 1 for k, v in hdr.items(): sheet.column_dimensions[xl.get_column_letter(col)].width = v col += 1 max_col = col - 1 col = 1 if isinstance(tc, str): cell = xl.get_column_letter(col) + str(row) sheet[cell].hyperlink = '#' + tc + '!A1' sheet[cell].font = report_fonts.font_type('link') sheet[cell] = 'Contents' col += 1 cell = xl.get_column_letter(col) + str(row) sheet.merge_cells(start_row=row, start_column=col, end_row=row, end_column=max_col) sheet[cell].font = report_fonts.font_type('hdr_1') sheet[cell] = sheet_title row += 2 # Now add each dashboard item border = report_fonts.border_type('thin') font = report_fonts.font_type('std') alignment = report_fonts.align_type('wrap') for statistic in content.keys(): db = content.get(statistic) col = 1 # The individual dashboard title sheet.merge_cells(start_row=row, start_column=1, end_row=row, end_column=max_col) for i in range(col, max_col + 1): cell = xl.get_column_letter(i) + str(row) sheet[cell].border = border cell = xl.get_column_letter(col) + str(row) sheet[cell].font = report_fonts.font_type('hdr_2') sheet[cell].fill = report_fonts.fill_type('lightblue') sheet[cell] = db.get('title') col = 1 row += 1 # Now the individual dashboard headers for k in hdr.keys(): cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = report_fonts.font_type('bold') sheet[cell] = k col += 1 # Now add the dashboard content port_list = db.get('port_list') if len(port_list) == 0: row += 1 for port_obj in port_list: # Statistic col = 1 cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = font sheet[cell].alignment = alignment sheet[cell] = port_obj.r_get('fibrechannel-statistics/' + statistic) col += 1 # Fabric cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = font sheet[cell].alignment = alignment sheet[cell] = brcddb_fabric.best_fab_name( port_obj.r_switch_obj().r_fabric_obj()) col += 1 # Switch cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = font sheet[cell].alignment = alignment sheet[cell] = brcddb_switch.best_switch_name( port_obj.r_switch_obj()) col += 1 # Port cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = font sheet[cell].alignment = alignment sheet[cell] = port_obj.r_obj_key() col += 1 # Port Type cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = font sheet[cell].alignment = alignment sheet[cell] = port_obj.c_login_type() col += 1 # Description - Try FDMI first, then name server cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = font sheet[cell].alignment = alignment sheet[cell] = brcddb_port.port_best_desc(port_obj) row += 1 row += 1
def _switch_ts(o, k): obj = o.r_switch_obj(k) return brcddb_switch.best_switch_name( obj, True), brcddb_switch.best_switch_name(obj, False)
def _tzone_switch_case(obj, obj2, zone_l): return brcddb_switch.best_switch_name(obj.r_switch_obj())
def s_switch_name_case(switch_obj, k=None): return brcddb_switch.best_switch_name(switch_obj, False)
def s_switch_name_and_wwn_case(switch_obj, k=None): return brcddb_switch.best_switch_name(switch_obj, True)
def _add_switch(switch_obj, display): """Adds switch detail to the worksheet. :param switch_obj: Switch object :type switch_obj: brcddb.classes.switch.SwitchObj :param display: List of keys to display. Find next instance of switch_key_case. Much less complex than port_page() :type display: dict :rtype: None """ global row, sheet, hdr, switch_key_case # Add the headers col = 1 row += 2 sheet.merge_cells(start_row=row, start_column=col, end_row=row, end_column=len(hdr)) cell = xl.get_column_letter(col) + str(row) sheet[cell].font = report_fonts.font_type('hdr_2') sheet[cell] = brcddb_switch.best_switch_name(switch_obj, True) row += 1 for k in hdr.keys(): cell = xl.get_column_letter(col) + str(row) sheet[cell].font = report_fonts.font_type('bold') sheet[cell] = k col += 1 # Add the MAPS dashboard _maps_dashboard(switch_obj) # Add the switch details border = report_fonts.border_type('thin') alignment = report_fonts.align_type('wrap') row += 1 for k in display: font = report_utils.font_type_for_key(switch_obj, k) col = 1 row += 1 # Comments cell = xl.get_column_letter(col) + str(row) sheet[cell].font = font sheet[cell].border = border sheet[cell].alignment = alignment sheet[cell] = report_utils.comments_for_alerts(switch_obj, k) # Key description col += 1 cell = xl.get_column_letter(col) + str(row) sheet[cell].font = font sheet[cell].border = border sheet[cell].alignment = alignment sheet[cell] = display[k] if k in display else k # Value col += 1 cell = xl.get_column_letter(col) + str(row) sheet[cell].font = font sheet[cell].border = border sheet[cell].alignment = alignment v = switch_obj.r_get(k) if k in switch_key_case: sheet[cell] = switch_key_case[k](switch_obj, k) elif k in brcddb_common.switch_conversion_tbl: sheet[cell] = '' if v is None else brcddb_common.switch_conversion_tbl[k][v] else: if isinstance(v, bool): sheet[cell] = 'Yes' if v else 'No' else: sheet[cell] = v if isinstance(v, (str, int, float)) else '' if v is None else str(v)
def l_switch_name_case(login_obj): return brcddb_switch.best_switch_name(login_obj.r_switch_obj(), False)
def _mem_switch_case(obj, mem, wwn, port_obj): return '' if port_obj is None else brcddb_switch.best_switch_name( port_obj.r_switch_obj())
def bp_page(wb, tc, sheet_name, sheet_i, sheet_title, obj, display, display_tbl): """Creates a best practice violation worksheet for the Excel report. :param wb: Workbook object :type wb: class :param tc: Table of context page. A link to this page is place in cell A1 :type tc: str, None :param sheet_name: Sheet (tab) name :type sheet_name: str :param sheet_i: Sheet index where page is to be placed. :type sheet_i: int :param sheet_title: Title to be displayed in large font, hdr_1, at the top of the sheet :type sheet_title: str :param obj: Project or fabric object. :type obj: brcddb.classes.project.ProjectObj, brcddb.classes.fabric.FabricObj :param display: List of parameters to display. :type display: list, tuple :param display_tbl: Display control table. See brcddb.report.report_tables.display_tbl :rtype: None """ # Validate the user input err_msg = list() if obj is None: err_msg.append('obj was not defined.') elif not bool('ProjectObj' in str(type(obj)) or 'FabricObj' in str(type(obj))): err_msg.append('Invalid object type: ' + str(type(obj)) + '.') if display is None: err_msg.append('display not defined.') if len(err_msg) > 0: brcdapi_log.exception(err_msg, True) return # Create the worksheet, add the headers, and set up the column widths sheet = wb.create_sheet(index=sheet_i, title=sheet_name) sheet.page_setup.paperSize = sheet.PAPERSIZE_LETTER sheet.page_setup.orientation = sheet.ORIENTATION_LANDSCAPE col = 1 row = 1 if isinstance(tc, str): cell = xl.get_column_letter(col) + str(row) sheet[cell].hyperlink = '#' + tc + '!A1' sheet[cell].font = report_fonts.font_type('link') sheet[cell] = 'Contents' col += 1 cell = xl.get_column_letter(col) + str(row) sheet[cell].font = report_fonts.font_type('hdr_1') sheet[cell] = sheet_title sheet.freeze_panes = sheet['A3'] col = 1 row += 1 for k in display: if k in display_tbl and 'dc' in display_tbl[ k] and display_tbl[k]['dc'] is True: continue cell = xl.get_column_letter(col) + str(row) sheet[cell].font = report_fonts.font_type('bold') sheet[cell].border = report_fonts.border_type('thin') if k in display_tbl: if 'c' in display_tbl[k]: sheet.column_dimensions[xl.get_column_letter( col)].width = display_tbl[k]['c'] try: if display_tbl[k]['v']: sheet[cell].alignment = report_fonts.align_type( 'wrap_vert_center') else: sheet[cell].alignment = report_fonts.align_type('wrap') except: sheet[cell].alignment = report_fonts.align_type('wrap') if 'd' in display_tbl[k]: sheet[cell] = display_tbl[k]['d'] else: sheet[ cell] = k # This happens when a new key is introduced before the display tables have been updated else: sheet[ cell] = k # This happens when a new key is introduced before the display tables have been updated col += 1 # Get a list of fabric objects and initialize alert_list if 'ProjectObj' in str(type(obj)): fab_list = obj.r_fabric_objects() chassis_list = obj.r_chassis_objects() switch_list = obj.r_switch_objects() else: fab_list = [obj] chassis_list = obj.r_project_obj().r_chassis_objects() switch_list = obj.r_project_obj().r_switch_objects() alert_list = list() # Get all the chassis alerts for tobj in chassis_list: tl = list() for sev in (al.ALERT_SEV.ERROR, al.ALERT_SEV.WARN): # Display errors first tl.extend( _add_alerts(tobj, 'Chassis', sev, brcddb_chassis.best_chassis_name(tobj), '')) if len(tl) > 0: alert_list.append(['']) alert_list.append( ['Chassis: ' + brcddb_chassis.best_chassis_name(tobj)]) alert_list.extend(tl) # Get all the fabric alerts for fab_obj in fab_list: tl = list() for sev in (al.ALERT_SEV.ERROR, al.ALERT_SEV.WARN): # Display errors first tl.extend( _add_alerts(fab_obj, 'Fabric', sev, brcddb_fabric.best_fab_name(fab_obj), '')) for tobj in fab_obj.r_zonecfg_objects(): tl.extend( _add_alerts(tobj, 'ZoneCfg', sev, tobj.r_obj_key(), '')) for tobj in fab_obj.r_zone_objects(): tl.extend(_add_alerts(tobj, 'Zone', sev, tobj.r_obj_key(), '')) for tobj in fab_obj.r_alias_objects(): tl.extend(_add_alerts(tobj, 'Alias', sev, tobj.r_obj_key(), '')) for tobj in fab_obj.r_login_objects(): tl.extend(_add_alerts(tobj, 'Login', sev, tobj.r_obj_key(), '')) for tobj in fab_obj.r_fdmi_node_objects(): tl.extend( _add_alerts(tobj, 'FDMI_Node', sev, tobj.r_obj_key(), '')) for tobj in fab_obj.r_fdmi_port_objects(): tl.extend( _add_alerts(tobj, 'FDMI_Port', sev, tobj.r_obj_key(), '')) if len(tl) > 0: alert_list.append(['']) alert_list.append( ['Fabric: ' + brcddb_fabric.best_fab_name(fab_obj, True)]) alert_list.extend(tl) # Get all the switch and port alerts for switch_obj in switch_list: tl = list() for sev in (al.ALERT_SEV.ERROR, al.ALERT_SEV.WARN): # Display errors first tl.extend( _add_alerts(switch_obj, 'Switch', sev, brcddb_switch.best_switch_name(switch_obj), '')) for tobj in switch_obj.r_port_objects(): tl.extend( _add_alerts(tobj, 'Port', sev, brcddb_port.best_port_name(tobj), tobj.r_obj_key())) if len(tl) > 0: alert_list.append(['']) alert_list.append([ 'Switch: ' + brcddb_switch.best_switch_name(switch_obj, True) ]) alert_list.extend(tl) # Now add the alerts to the worksheet # Set up the cell formatting border = report_fonts.border_type('thin') alignment = report_fonts.align_type('wrap') font = report_fonts.font_type('std') # Add all alerts to the worksheet for x in alert_list: row += 1 col = 1 if len(x) == 0: row += 1 elif len(x) == 1: sheet.merge_cells(start_row=row, start_column=1, end_row=row, end_column=len(display)) cell = xl.get_column_letter(col) + str(row) sheet[cell].font = report_fonts.font_type('hdr_2') if len(x[0]) > 0: sheet[cell].fill = report_fonts.fill_type('lightblue') sheet[cell] = x[0] else: for k in display: cell = xl.get_column_letter(col) + str(row) sheet[cell].border = border sheet[cell].font = font sheet[cell].alignment = alignment sheet[cell] = bp_case[k](x) col += 1
def p_switch_name_case(port_obj, k, wwn): return brcddb_switch.best_switch_name(port_obj.r_switch_obj(), False)
def _fabric_summary(fabric_obj): """Adds a fabric summary to the worksheet. :param fabric_obj: Fabric object :type fabric_obj: brcddb.classes.fabric.FabricObj :rtype: None """ global _row, _sheet, _hdr border = report_fonts.border_type('thin') alignment = report_fonts.align_type('wrap') font = report_fonts.font_type('bold') # Add the headers _row += 2 col = 1 for k in _hdr.keys(): cell = xl.get_column_letter(col) + str(_row) _sheet[cell].alignment = alignment _sheet[cell].border = border _sheet[cell].font = font _sheet[cell] = k col += 1 _row += 1 # Setup the common cell attributes font = report_fonts.font_type('std') switch_obj_l = fabric_obj.r_switch_objects() row = _row for switch_obj in switch_obj_l: for col in range(1, len(_hdr) + 1): cell = xl.get_column_letter(col) + str(row) _sheet[cell].alignment = alignment _sheet[cell].border = border _sheet[cell].font = font row += 1 # Add the switch summary for switch_obj in switch_obj_l: col = 1 # Switch name buf = brcddb_switch.best_switch_name(switch_obj, False) if switch_obj.r_is_principal(): buf = '*' + buf cell = xl.get_column_letter(col) + str(_row) _sheet[cell] = buf col += 1 # Switch WWN cell = xl.get_column_letter(col) + str(_row) _sheet[cell] = switch_obj.r_obj_key() col += 1 # Switch DID cell = xl.get_column_letter(col) + str(_row) buf = switch_obj.r_get('brocade-fabric/fabric-switch/domain-id') _sheet[cell] = switch_obj.r_get('brocade-fibrechannel-switch/fibrechannel-switch/domain-id') if buf is None \ else buf col += 1 # Switch FID cell = xl.get_column_letter(col) + str(_row) _sheet[cell] = brcddb_switch.switch_fid(switch_obj) col += 1 # Firmware version cell = xl.get_column_letter(col) + str(_row) buf = switch_obj.r_get('brocade-fabric/fabric-switch/firmware-version') _sheet[cell] = switch_obj.r_get('brocade-fibrechannel-switch/fibrechannel-switch/firmware-version') if \ buf is None else buf _row += 1 # Pincipal switch footnote col = 1 _sheet.merge_cells(start_row=_row, start_column=col, end_row=_row, end_column=len(_hdr)) cell = xl.get_column_letter(col) + str(_row) _sheet[cell].font = font _sheet[cell] = '* indicates principal switch'
def _alias_mem_switch_case(obj, mem): try: return brcddb_switch.best_switch_name( obj.r_fabric_obj().r_login_obj(mem).r_switch_obj(), False) except: return ''