def port_obj_for_chpid(obj, seq, tag): """Returns the port object matching the rnid/sequence-numbber and rnid/tag. Used for finding CHPIDs :param obj: Object with port objects, obj.r_port_objects() :type obj: brcddb.classes.switch.SwitchObj, brcddb.classes.fabric.FabricObj, brcddb.classes.project.ProjectObj, brcddb.classes.chassis.ChassisObj :param seq: Serial number (sequence number) for CEC :type seq: str :param tag: CHPID tag :type tag: str :rturn: Port object where this CHPID is connected. None if not found :rtype: brcddb.classes.port.PortObj, None """ # The tag from the IOCP will never have '0x' prefix so below is just in case I ever use this for something else. test_tag = tag if '0x' in tag else '0x' + tag port_list = brcddb_search.match_test( obj.r_port_objects(), { 'l': ( dict(k='rnid/sequence-number', t='exact', v=seq, i=True), dict(k='rnid/tag', t='exact', v=test_tag, i=True), dict(k='rnid/flags', t='exact', v='0x10' ), # Indicates the RNID data is valid for a channel ), 'logic': 'and' # 'and' is the default logic so this is just for clarity for the reader }) return port_list[0] if len(port_list) > 0 else None
def _check_remote_sfps(obj_list, t_obj): """Checks remote SFP levels and adds appropriate alerts to port objects :param obj_list: List of port object :type obj_list: brcddb.classes.PortObj :param t_obj: Individual test item from the test_list passed to best_practice(). Not used :type t_obj: dict """ global _remote_rule_template, _alert_tbl for p_obj in brcddb_search.match_test(obj_list, bp_tables.is_online): v = p_obj.r_get('media-rdp/remote-media-voltage-alert/high-alarm') if v is None or v == 0: continue # Sometimes threshold data is all 0 when it's not valid. Just checking the voltage makes it easy # Check threshold levels for k, rules in _remote_rule_template.items(): try: v = p_obj.r_get(k) if v is None: continue for k1, rules_1 in rules.items(): tv = p_obj.r_get(k1) if rules_1.get('t') == '>=': if v >= tv: p_obj.s_add_alert(_alert_tbl, rules_1.get('a'), k1, v, tv) break else: if v <= tv: p_obj.s_add_alert(_alert_tbl, rules_1.get('a'), k1, v, tv) break except: pass # Remote data wasn't provided if we get here.
def _fc16_48_haa_p8(obj, t_obj): """Check to see if there is a pre-2015 FC16-32 blade with an SFP matching S/N HAA* in port 8 :param obj: Chassis 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: Alerts are applied to the ports found that meet this criteria so an empty list is always returned :rtype: list """ global _alert_tbl # Get all the ports number 8 in for FC16-32 blades matching P/N 60-1001945-* (built before 2016) temp_l = brcddb_util.convert_to_list(obj.r_get('brocade-fru/blade')) fru_list = brcddb_search.match(temp_l, 'part-number', '60-1001945-*', False, 'wild') temp_l = [str(fru.get('slot-number')) for fru in fru_list] # Get a list of ports we just figured out above that have an SFP matching S/N HAA* if len(temp_l) > 0: lt = [ {'k': 'media-rdp/serial-number', 'v': 'HAA*', 't': 'wild'}, {'k': 'fibrechannel/name', 'v': '[' + ','.join(temp_l) + ']/(8 | 32)', 't': 'regex-m'} ] ml = brcddb_search.match_test(obj.r_port_objects(), lt, 'and') for port_obj in ml: port_obj.s_add_alert(_alert_tbl, t_obj.get('m')) return list()
def _check_sfps(obj_list, t_obj): """Checks SFP levels and adds appropriate alerts to port objects :param obj_list: Port object :type obj_list: list :param t_obj: Individual test item from the test_list passed to best_practice(). Not used :type t_obj: dict """ global _rule_template, sfp_rules, _alert_tbl if sfp_rules is None or obj_list is None: return # Perform all the checks for the SFPs on the switch. enabled_ports = brcddb_search.match_test(obj_list, bp_tables.is_enabled) # SFP data is not valid for disabled ports for rule in sfp_rules: group = 'Unkonwn' if rule.get('Group') is None else rule.get('Group') try: pn_l = rule.get('Mfg. P/N') if pn_l is not None and pn_l != '': for pn in [p.strip() for p in pn_l.split(',')]: plist = brcddb_search.match_test(enabled_ports, {'k': 'media-rdp/part-number', 't': 'exact', 'v': pn}) if len(plist) > 0: online_plist = brcddb_search.match_test(plist, bp_tables.is_online) for k0, obj_0 in _rule_template.items(): for k1, obj_1 in obj_0.items(): val = float(rule.get(k1)) # The threshold to test against m = obj_1.get('a') # Alert number tlist = online_plist if obj_1.get('l') else plist for p_obj in brcddb_search.match_test(tlist, {'k': k0, 't': obj_1.get('t'), 'v': val}): p_obj.s_add_alert(_alert_tbl, m, k0, p_obj.r_get(k0), val) else: brcdapi_log.log('Missing P/N in ' + sfp_rules + ', Group: ' + str(group), True) except: brcdapi_log.exception('Invalid SFP rules file ' + sfp_rules + '. Group: ' + str(group), True) return return
def port_obj_for_addr(obj, addr): """Returns the port object for a port in a given fabric matching a link address. Used for finding control units :param obj: Object with port objects, obj.r_port_objects() :type obj: brcddb.classes.switch.SwitchObj, brcddb.classes.fabric.FabricObj, brcddb.classes.project.ProjectObj, brcddb.classes.chassis.ChassisObj :param addr: Hex FC address (format is 0x123400) :type addr: str :rturn: Port object matching the link address. None if not found :rtype: brcddb.classes.port.PortObj, None """ port_list = brcddb_search.match_test( obj.r_port_objects(), dict(k='fibrechannel/fcid-hex', t='exact', v=addr, i=True)) return port_list[0] if len(port_list) > 0 else None
def fab_obj_for_user_name(proj_obj, name): """Returns a list of fabric objects matching a user friendly name :param proj_obj: Project object :type proj_obj: brcddb.classes.project.ProjectObj :param fab_obj: List of brcddb fabric objects whose user friendly name matches name :type fab_obj: brcddb.classes.fabric.FabricObj """ sl = brcddb_search.match_test( proj_obj.r_switch_objects(), dict( k= 'brocade-fibrechannel-switch/fibrechannel-switch/fabric-user-friendly-name', v=name, t='exact', i=False)) return brcddb_util.remove_duplicates( [switch_obj.r_fabric_obj() for switch_obj in sl])
def _check_best_practice(obj_list, test_list): """Checks for defined conditions and adds an alert for every out of bounds condition. :param obj_list: A list of dictionaries or brcdapi objects to search. Must all be the same type :type obj_list: dict, list, tuple :param test_list: Pointer to table of best practice rules. See brcddb.app_data.bp_tables for details :type test_list: dict """ global _alert_tbl # Validate user input if len(obj_list) == 0: return if not isinstance(test_list, (list, tuple)): brcdapi_log.exception('Invalid test_list type, ' + str(type(test_list)), True) return # Spin through each item in the test_list and perform the specified test for t_obj in test_list: if 'skip' in t_obj and t_obj.get('skip'): continue special = t_obj.get('s') if special is not None: if special in _bp_special_case_tbl: _bp_special(obj_list, t_obj) elif special in _bp_special_list_case_tbl: _bp_special_list(obj_list, t_obj) else: brcdapi_log.exception( 'Unknown special test case: ' + str(special) + ', type: ' + str(type(special)), True) else: for obj in brcddb_search.match_test(obj_list, t_obj.get('l'), t_obj.get('logic')): # See documentation in brcddb.app_data.bp_tables for an explanation of 'm', 'p0', 'p0h', 'p1', & 'p1h' p0 = t_obj.get('p0h') if t_obj.get('p0h') is not None else obj.r_get(t_obj.get('p0')) p1 = t_obj.get('p1h') if t_obj.get('p1h') is not None else obj.r_get(t_obj.get('p1')) obj.s_add_alert(_alert_tbl, t_obj.get('m'), brcddb_util.convert_to_list(t_obj.get('l'))[0].get('k'), p0, p1)
def _fdmi_enabled(obj_list, t_obj): """Check to see if FDMI should be enabled on the attached device. :param obj_list: List of login objects, brcddb.classes.login.LoginObj, passed to best_practice() :type obj_list: list :param t_obj: Individual test item from the test_list passed to best_practice(). :type t_obj: dict :return: List of port objects, brcddb.classes.port.PortObj, matching the test criteria in t_obj :rtype: list """ ret_list = list() for obj in brcddb_search.match_test(obj_list, t_obj.get('l'), t_obj.get('logic')): port_obj = obj.r_port_obj() if port_obj is None: continue wwn = obj.r_obj_key() try: if port_obj.r_get('fibrechannel/neighbor/wwn')[1] == wwn: if obj.r_fabric_obj().r_fdmi_port_obj(wwn) is None: ret_list.append(port_obj) except: if obj.r_fabric_obj().r_fdmi_port_obj(wwn) is None: ret_list.append(port_obj) return ret_list
def _graphs(switch_obj, single_port_graph_in, stats_graph_in, graph_type): """Parses the graphing information from the command line into a list of machine readable dictionaries as follows: +-----------+---------------------------------------------------+ | key | Description | +===========+===================================================+ | stat | Only present if -gs was entered on the command | | | line. This is the fibrechannel-statistics to plot | +-----------+---------------------------------------------------+ | type | Graph type. See brcddb.report.graph.chart_types. | +-----------+---------------------------------------------------+ | port | Only present if -gp was entered on the command | | | line. This is the port number in s/p notation to | | | plot. | +-----------+---------------------------------------------------+ | params | If stat is not None, this is the list of ports | | | whose statistic is to be plotted. If port is not | | | None, this is the list of statistics for the port | | | to be plotted. | +-----------+---------------------------------------------------+ :param switch_obj: First switch object with list of ports :type switch_obj: brcddb.classes.switch.SwitchObj :param single_port_graph_in: Command line text for single port graphs :type single_port_graph_in: str :param stats_graph_in: Command line text for statistics graphs :type stats_graph_in: str :param graph_type: Type of graph :type graph_type: str :return graphs: List of dictionaries that define the graphs. See description of graph in _write_report() for details :rtype graphs: list :return messages: List of error and warning messages :rtype messages: list """ # Figure out the graph type and set up the return list of graphs ml = list() graphs = list() if graph_type is None: graph_type = 'line' elif graph_type not in report_graph.chart_types.keys(): ml.append('Invalid graph type: ' + graph_type + '. Defaulting to line') graph_type = 'line' # Single port, multiple statistics if isinstance(single_port_graph_in, str): for buf in single_port_graph_in.split(';'): temp_l = buf.split(',') if len(temp_l) > 1: port = temp_l.pop(0) if '/' not in port: port = '0/' + port if switch_obj.r_port_obj(port) is None: ml.append(port + ' not found. Skipping this port') else: graphs.append( dict(port=port, parms=temp_l, type=graph_type)) # statistic, multiple ports if isinstance(stats_graph_in, str): for buf in stats_graph_in.split(';'): temp_l = buf.split(',') if len(temp_l) > 1: statistic = 'fibrechannel-statistics/' + temp_l[0] to_graph = dict(stat=statistic, type=graph_type) temp_l = temp_l[1:] # If top or avg was specified for the ports, figure out the top (peak) ports for this statistic and the # top ports for the maximum sum for this statistic if 'top-' in temp_l[0].lower() or 'avg-' in temp_l[0].lower(): n = int(temp_l[0].split('-')[1]) switch_obj_l = [ o for o in switch_obj.r_project_obj().r_switch_objects() if '-' in o.r_obj_key() ] port_total_d = dict() port_peak_d = dict() port_obj_l = list() for port_obj in switch_obj_l.pop(0).r_port_objects(): port_stat = port_obj.r_get(statistic) if port_stat is None: ml.append(statistic + ' not found for port ' + port_obj.r_obj_key()) else: port_total_d.update( {port_obj.r_obj_key(): port_stat}) port_peak_d.update( {port_obj.r_obj_key(): port_stat}) port_obj_l.append(port_obj) for switch_obj in switch_obj_l: for port_obj in switch_obj.r_port_objects(): port_stat = port_obj.r_get(statistic) if port_stat is None: ml.append(statistic + ' not found for port ' + port_obj.r_obj_key()) else: port_key = port_obj.r_obj_key() if port_key in port_total_d: port_total_d[port_key] += port_stat if port_stat > port_peak_d[port_key]: port_peak_d[port_key] = port_stat for port_obj in port_obj_l: port_obj.s_new_key('_peak', port_peak_d[port_obj.r_obj_key()], True) port_obj.s_new_key('_total', port_total_d[port_obj.r_obj_key()], True) peak_ports = gen_util.sort_obj_num( port_obj_l, '_peak', True)[0:min(n, len(port_obj_l))] max_ports = gen_util.sort_obj_num( port_obj_l, '_total', True)[0:min(n, len(port_obj_l))] # Above sorts by port object. All we want is the port number if 'top' in temp_l[0]: to_graph.update(parms=[ port_obj.r_obj_key() for port_obj in peak_ports ]) else: to_graph.update(parms=[ port_obj.r_obj_key() for port_obj in max_ports ]) elif 'eport' in temp_l[0].lower().replace('-', ''): port_list = brcddb_search.match_test( switch_obj.r_port_objects, bp_tables.is_e_port) if len(port_list) == 0: ml.append('No E-Ports found') to_graph.update( parms=[port_obj.r_obj_key() for port_obj in port_list]) else: # It's a list of ports. Make sure they are valid and prepend '0/' if necessary port_list = list() for port in temp_l: mod_port = port if '/' in port else '0/' + port if switch_obj.r_port_obj(mod_port) is None: ml.append( 'Invalid port number or port not found in switch: ' + mod_port) else: port_list.append(mod_port) to_graph.update(parms=port_list) if len(to_graph['parms']) > 0: graphs.append(to_graph) else: ml.append('Missing parameter in ' + buf) return graphs, ml
def _f_ports(switch_obj): return [ p.r_obj_key() for p in brcddb_search.match_test( switch_obj.r_port_objects(), bp_tables.is_f_port) ]
def _test_act(obj): global _working_obj_l _working_obj_l = brcddb_search.match_test(_working_obj_l, obj)