def _switch_from_list_match_case(switch_obj, obj, uri): switch_wwn = switch_obj.r_obj_key() element = uri.split('/').pop() i = 0 for s_obj in brcddb_util.convert_to_list(obj.get(element)): fos_switch_wwn = s_obj.get('switch-wwn') if fos_switch_wwn is not None and fos_switch_wwn == switch_wwn: _update_brcddb_obj_from_list(switch_obj, brcddb_util.convert_to_list(obj.get(element))[i], uri) return i += 1
def _chassis_fru_check(obj, t_obj): """Check temperature sensors and H/W faults. :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(). :type t_obj: dict :return: List of alert dictionaries {'a': alert number, 'p0': p0, 'p1': p1, 'k': '_isl_map'} :rtype: list """ global _alert_tbl r_list = list() # Blades for d in brcddb_util.convert_to_list(obj.r_get('brocade-fru/blade')): v = str(d.get('blade-state')) if 'ault' in v: # Sometimes it's 'fault' and sometimes it's 'Fault'. r_list.append({'a': t_obj.get('m'), 'p0': 'blade: ' + str(d.get('slot-number')), 'p1': v, 'k': None}) # Fans for d in brcddb_util.convert_to_list(obj.r_get('brocade-fru/fan')): v = str(d.get('operational-state')) if v.upper() != 'OK': r_list.append({'a': t_obj.get('m'), 'p0': 'Fan: ' + str(d.get('unit-number')), 'p1': v, 'k': None}) # Power Supply for d in brcddb_util.convert_to_list(obj.r_get('brocade-fru/power-supply')): v = str(d.get('operational-state')) if v.upper() != 'OK': r_list.append({'a': t_obj.get('m'), 'p0': 'Power Supply: ' + str(d.get('unit-number')), 'p1': v, 'k': None}) # Temp Sensor for d in brcddb_util.convert_to_list(obj.r_get('brocade-fru/sensor')): v = str(d.get('state')) if v.upper() != 'ABSENT': if v.upper() != 'OK': p0 = 'Temp Sensor ID: ' + str(d.get('id')) + \ str(d.get('slot-number')) if d.get('slot-number') is not None else '' r_list.append({'a': t_obj.get('m'), 'p0': p0, 'p1': v, 'k': None}) v1 = d.get('temperature') if isinstance(v1, (int, float)): if v1 >= HIGH_TEMP_WARN: a = al.ALERT_NUM.CHASSIS_TEMP_ERROR if v1 >= HIGH_TEMP_ERROR else al.ALERT_NUM.CHASSIS_TEMP_WARN p0 = '' if d.get('slot-number') is None else 'Slot: ' + str(d.get('slot-number')) + ' ' p0 += '' if d.get('id') is None else 'ID: ' + str(d.get('id')) r_list.append({'a': a , 'p0': p0, 'p1': v1, 'k': None}) return r_list
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 _switch_from_list_case(switch_obj, obj, uri): try: _update_brcddb_obj_from_list(switch_obj, brcddb_util.convert_to_list(obj.get(uri.split('/').pop()))[0], uri) if switch_obj.r_is_principal(): switch_obj.r_project_obj().s_add_fabric(switch_obj.r_obj_key()) except: pass
def add_rest_port_data(switch_obj, pobj, flag_obj=None, skip_list=list()): """Adds port statistics from rest request 'brocade-interface/fibrechannel-statistics' to each port object :param switch_obj: Switch object :type switch_obj: SwitchObj :param pobj: Object returned from the FOS Rest API :type pobj: dict :param flag_obj: Not used. Must be here for methods that call rest add methods from a table. :type flag_obj: None :param skip_list: Keys to skip :type skip_list: (list, tuple) :return: None :rtype: None """ sl = ['name', 'enabled-state'] sl.extend(skip_list) for k in pobj.keys(): for pdict in brcddb_util.convert_to_list(pobj.get(k)): if k == 'media-rdp': # The media name is in the format type/s/p, but for everything else, it's just s/p, which is how the key # is created for the port object in the switch object. By splitting on '/', removing the first list # element, and joining the rest with '/', I end up with just s/p. port_obj = switch_obj.s_add_port('/'.join(pdict.get('name').split('/')[1:])) else: port_obj = switch_obj.s_add_port(pdict.get('name')) v = dict() port_obj.s_new_key(k, v) brcddb_copy.object_copy(pdict, v, port_obj, sl) # Make sure there is a login object for every login found fab_obj = switch_obj.r_fabric_obj() if fab_obj is not None: for wwn in port_obj.r_login_keys(): fab_obj.s_add_login(wwn)
def _add_switch_to_chassis_int(chassis_obj, switch, uri, switch_wwn): switch_obj = chassis_obj.s_add_switch(switch_wwn) _update_brcddb_obj_from_list(switch_obj, switch, uri) # Add the ports try: for port in brcddb_util.convert_to_list(switch.get('port-member-list').get('port-member')): switch_obj.s_add_port(port) except: pass # Add the GE ports try: for port in brcddb_util.convert_to_list(switch.get('ge-port-member-list').get('port-member')): switch_obj.s_add_ge_port(port) except: pass
def get_batch(session, proj_obj, kpi_list, fid=None): """Processes a batch API requests. All chassis request are performed first, followed by processing of fid_rest_data If any warnings or errors are encountered, the log is updated and the appropriate flag bits for the proj_obj are set. Search for _project_warn in brcddb_common.py for additional information. Again, search for _project_warn in brcddb.classes for object methods to set and check these bits. :param session: Session object, or list of session objects, returned from brcdapi.pyfos_auth.login() :type session: dict :param proj_obj: Project object :type proj_obj: brcddb.classes.ProjectObj :param kpi_list: List of KPIs to request from the switches and chassis :type kpi_list: list :param fid: FID, or list of FIDs for logical switch level requests. If None, execute requests for all FIDs. :type fid: int, list, tuple, None :rtype: None """ # Get the chassis object chassis_obj = get_chassis(session, proj_obj) if chassis_obj is None: brcdapi_log.log(brcdapi_util.mask_ip_addr(session.get('ip_addr')) + 'Chassis not found.', True) return kl = brcddb_util.convert_to_list(kpi_list) # Get all the chassis data for kpi in [kpi for kpi in kl if not brcdapi_util.uri_map[kpi]['fid']]: results_action(chassis_obj, get_rest(session, kpi, chassis_obj), kpi) # Figure out which logical switches to poll switch level data from. if chassis_obj.r_is_vf_enabled() and fid is not None: switch_list = list() for fab_id in brcddb_util.convert_to_list(fid): switch_obj = chassis_obj.r_switch_obj_for_fid(fab_id) if switch_obj is None: brcdapi_log.log('FID ' + str(fab_id) + ' not found', True) else: switch_list.append(switch_obj) else: switch_list = chassis_obj.r_switch_objects() # Now process all the switch (FID) level commands. for switch_obj in switch_list: for kpi in [kpi for kpi in kl if brcdapi_util.uri_map[kpi]['fid']]: results_action(switch_obj, get_rest(session, kpi, switch_obj, brcddb_switch.switch_fid(switch_obj)), kpi)
def _fabric_fdmi_hba_case(objx, obj, uri): fab_obj = objx.r_fabric_obj() for obj in brcddb_util.convert_to_list(obj.get('hba')): try: for wwn in obj.get('hba-port-list').get('wwn'): fab_obj.s_add_fdmi_port(wwn) except: pass _update_brcddb_obj(fab_obj.s_add_fdmi_node(obj.get('hba-id')), obj, uri)
def _add_ls_switch_to_chassis_case(chassis_obj, obj, uri): existing_switch_wwns = chassis_obj.r_switch_keys() for switch in brcddb_util.convert_to_list(obj.get(uri.split('/').pop())): wwn = switch.get('switch-wwn') if wwn in existing_switch_wwns: continue # The switch is already there. This method is not intended to modify an existing switch object switch_obj = chassis_obj.s_add_switch(wwn) _update_brcddb_obj_from_list(switch_obj, switch, uri) try: for port in brcddb_util.convert_to_list(switch.get('port-member-list').get('port-member')): switch_obj.s_add_port(port) except: pass try: for port in brcddb_util.convert_to_list(switch.get('ge-port-member-list').get('port-member')): switch_obj.s_add_ge_port(port) except: pass
def _fdmi_port_obj_for_login(obj): """Returns the FDMI port object in a list for a login obj. See _obj_self() for parameter detail.""" fab_obj = obj.r_fabric_obj() if fab_obj is None: return list() return [ mem for mem in brcddb_util.convert_to_list( fab_obj.r_fdmi_port_obj(obj.r_obj_key())) if mem is not None ]
def _fdmi_port_for_fdmi_node(obj): """Returns a list of FDMI port objects for a zonecfg. See _obj_self() for parameter detail.""" fab_obj = obj.r_fabric_obj() if fab_obj is None: return list() return [ mem for mem in brcddb_util.convert_to_list( fab_obj.r_fdmi_port_obj(obj.r_obj_key())) if mem is not None ]
def s_switch_trunk_case(switch_obj, k): # Not used yet rl = list() for obj in brcddb_util.convert_to_list(switch_obj.r_get(k)): port_obj = switch_obj.r_port_object_for_index(obj.get('source-port')) ps_name = 'Index: ' + obj.get('source-port') if port_obj is None else port_obj.r_obj_key() d_switch_obj = switch_obj.r_project_obj().r_switch_obj(obj.get('neighbor-wwn')) port_obj = None if d_switch_obj is None else d_switch_obj.r_port_object_for_index(obj.get('destination-port')) pd_name = 'Index: ' + str(obj.get('destination-port')) if port_obj is None else port_obj.r_obj_key() rl.append('From ' + ps_name + ' to ' + obj.get('neighbor-switch-name') + ' ' + pd_name) return '\n'.join(rl)
def _defined_zonecfg_case(objx, obj, uri): fab_obj = objx.r_fabric_obj() if fab_obj is None: return # The switch is not in a fabric if it's disabled. We also get here if the principal switch is unkonwn dobj = obj.get('defined-configuration') if dobj is not None: for zobj in brcddb_util.convert_to_list(dobj.get('cfg')): zonecfg_obj = fab_obj.s_add_zonecfg(zobj.get('cfg-name'), zobj.get('member-zone').get('zone-name')) _update_brcddb_obj(zonecfg_obj, zobj, uri) for zobj in brcddb_util.convert_to_list(dobj.get('zone')): if 'member-entry' in zobj: mem_list = zobj.get('member-entry').get('entry-name') pmem_list = zobj.get('member-entry').get('principal-entry-name') else: mem_list = None pmem_list = None zone_obj = fab_obj.s_add_zone(zobj.get('zone-name'), zobj.get('zone-type'), mem_list, pmem_list) for zobj in brcddb_util.convert_to_list(dobj.get('alias')): mem_list = zobj.get('member-entry').get('alias-entry-name') if 'member-entry' in zobj else None alais_obj = fab_obj.s_add_alias(zobj.get('alias-name'), mem_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 maps_dashboard_alerts(proj_obj): """Looks through the MAPS alerts dashboard and adds an alert to the associated object. **WARNING:** As of 21 April 2019, there was not a reliable means of correlating MAPS alerts in the dashbaoard to a specific object. This just parses the dashboard for some obvious ones. An RFE was submitted :param proj_obj: Project object :type proj_obj: brcddb.classes.project.ProjectObj """ for switch_obj in proj_obj.r_switch_objects(): for dash_obj in brcddb_util.convert_to_list( switch_obj.r_get('brocade-maps/dashboard-rule')): if dash_obj.get('category') in _maps_category: _maps_category[dash_obj.get('category')](switch_obj, dash_obj) else: _unknown_category(switch_obj, dash_obj)
def _add_fab_switch_to_chassis_case(chassis_obj, obj, uri): proj_obj = chassis_obj.r_project_obj() fab_obj = None sl = list() for switch in brcddb_util.convert_to_list(obj.get(uri.split('/').pop())): c_obj = proj_obj.s_add_chassis(switch.get('chassis-wwn')) s_wwn = switch.get('name') switch_obj = c_obj.s_add_switch(s_wwn) sl.append(switch_obj) _update_brcddb_obj_from_list(switch_obj, switch, uri) if switch.get('principal'): fab_obj = proj_obj.s_add_fabric(s_wwn) if fab_obj is not None: for switch_obj in sl: switch_obj.s_fabric_key(fab_obj.r_obj_key()) fab_obj.s_add_switch(switch_obj.r_obj_key())
def _bp_special_list(obj_list, t_obj): """Processes special best practice tests. Similar to _bp_special() but the associated methods return a list of all objects matching the test criteria and the same alert is applied to :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 t_obj: Best practice rules. See brcddb.app_data.bp_tables for details :type t_obj: dict """ global _alert_tbl anum = t_obj.get('m') k = brcddb_util.convert_to_list(t_obj.get('l'))[0].get('k') p0 = t_obj.get('p0') p1 = t_obj.get('p1') for obj in _bp_special_list_case_tbl[t_obj.get('s')](obj_list, t_obj): obj.s_add_alert(_alert_tbl, anum, k, obj.r_get(p0), obj.r_get(p1))
def _effective_zonecfg_case(objx, obj, uri): if 'effective-configuration' in obj: # None when there is no zone configuration enabled fab_obj = objx.r_fabric_obj() if fab_obj is None: return # This happens when the principal switch in the fabric is unknown. dobj = obj.get('effective-configuration') if not isinstance(dobj, dict): return _update_brcddb_obj_from_list(fab_obj, dobj, uri, ['enabled-zone']) for zobj in brcddb_util.convert_to_list(dobj.get('enabled-zone')): if 'member-entry' in zobj: zone_obj = fab_obj.s_add_eff_zone(zobj.get('zone-name'), zobj.get('zone-type'), zobj.get('member-entry').get('entry-name'), zobj.get('member-entry').get('principal-entry-name')) else: # I don't know how there can be items in the enabled-zone without a 'member-entry'. Just in case ... zone_obj = fab_obj.s_add_eff_zone(zobj.get('zone-name')) _update_brcddb_obj(zone_obj, zobj, uri) fab_obj.s_add_eff_zonecfg(fab_obj.r_eff_zone_keys())
def _switch_port_case(objx, obj, uri): """Parses port data into the switch object :param objx: Switch object :type objx: brcddb.classes.switch.SwitchObj :param obj: Object returned from the API :type obj: dict """ tl = uri.split('/') leaf = tl[len(tl)-1] for port in brcddb_util.convert_to_list(obj.get(leaf)): port_obj = _port_case_case[leaf](objx, port) if port_obj is not None: d = port_obj.r_get(leaf) if d is None: port_obj.s_new_key(leaf, dict()) d = port_obj.r_get(leaf) for k, v in port.items(): d.update({k: v})
def port_obj_for_wwn(obj, wwn): """Returns the port object for a logged in WWN :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 index: Port index :type index: int :return: Port object. None if not found :rtype: brcddb.classes.port.PortObj, None """ if not brcddb_util.is_wwn(wwn): return None for port_obj in obj.r_port_objects(): for port_wwn in brcddb_util.convert_to_list( port_obj.r_get('fibrechannel/neighbor/wwn')): if port_wwn is not None and port_wwn == wwn: return port_obj return None # If we got this far, we didn't find it.
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 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 match_test(obj_list, test_obj, logic=None): """Performs a pre-defined complex test using match() and test_threshold. Any key collected from the API and put into an object can be evaluated for an exact match, a regex match, a regex search, and wild card match on str value types. Numbers can use comparitive operators >, <, >=, <=, !=, and ==. Types bool can only be evaluated for True or False. :param obj_list: A list of dictionaries or brcddb objects to search :type obj_list: dict, list, tuple :param test_obj: Pre-defined test. See comments below. :type test_obj: dict, list, tuple :param logic: Logic to apply to items in 'l'. May be 'and', 'or', 'nand', or 'nor'. If None, default is 'and' :type logic: str or None :return: Subset of obj_list whose objects meet the test criteria :rtype: list """ # test_obj (pre-defined test) dict or list/tuple of dict that defines the logical tests to perform: # # 'skip' Optional. Bool. Default is False. If True, effectively comments out the test case. # # 'l' Optional. Same as test_obj. When specified, iteratively calls match_test(). This is useful for complex # matches. You can nest these as deep as Python allows which is much deeper than any useful search you can # dream of. # # 'k' Required. str. This is the key for the value in the object from the obj_list to test for the match to # what is specifed in 'v' # # 'v' Required if 's' not specified. (str, int, float, bool). This is the value to compare against. The value # type must be consistent with the type of value associated with obj.get('k'). # # 's' Optional. str. NOT YET IMPLEMENTED. Same as 'v' except this is a referenced value. The most common use # is to compare against MAPS policies. Only 'v' or 's' is compared. If both are present, 's' is ignored. # # 't' Required. str. This is the type of comparison (test) to make. Comparison types may be: # int types: '>', '<', '<=', '>=', '!=', '==', and, for sloppy programmers, '='. # str types: 'exact' exact match # 'wild' Uses Pythons standard fnmatch library for wild card matching. # 'regex-m' Uses Pythons standard re library (re) for regex matching # 'regex-s' Uses Pythons standard re library (re) for regex searching # 'bool' True/False test # 'i' Optional. Bool. Only relevant to str matching. Possible values are: # True - ignore case. # False - Default. match case. # # 'logic' Optionial. Logic to apply to items in 'l'. Although the logic is moot for single items in 'l', 'and' is # the most effecient to process the logic. Defined as follows: # 'and' Default. All tests specified in 'l' must evaluate True # 'or' Any test specified in 'l' must evaluate True # 'nand' Opposite of 'and'. # 'nor' Opposfite of 'or' w_list = list() if obj_list is None else [obj_list] if not isinstance(obj_list, (list, tuple)) else obj_list lg = 'and' if logic is None else logic t_list = brcddb_util.convert_to_list(test_obj) # This is the list of objects to test against o_list = list() # This is the NAND and OR list when 'nand' or 'or' logic is specified for t_obj in t_list: m_list = list() if len(w_list) == 0: break if 'l' in t_obj: m_list = match_test(w_list, t_obj.get('l'), t_obj.get('logic')) if 'k' in t_obj and 't' in t_obj and 'v' in t_obj: ic = False if t_obj.get('i') is None else t_obj.get('i') # Perform the test and put results in m_list if t_obj.get('t') in ('bool', 'wild', 'regex-m', 'regex-s', 'exact'): m_list = match(w_list, t_obj.get('k'), t_obj.get('v'), ic, t_obj.get('t')) elif t_obj.get('t') in ('>', '<', '<=', '>=', '==', '=', '!='): m_list = test_threshold(w_list, t_obj.get('k'), t_obj.get('t'), t_obj.get('v')) else: brcdapi_log.exception('Invalid search key, ' + t_obj.get('t'), True) return list() # Apply the test logic if lg == 'and': # All tests must evaluate True so modify w_list to only contain objects for tests that evaluated True w_list = m_list elif lg == 'nand': w_list = [obj for obj in w_list if obj not in m_list] elif lg == 'or': # Any test that evaluates True means the object should be included in the return list and there is no # point in performing additional tests so remove it from w_list. o_list.extend(m_list) elif lg == 'nor': # All tests must evaluate False so remove any test that evaluates True from w_list. w_list = [obj for obj in w_list if obj not in m_list] else: brcdapi_log.exception('Invalid logic, ' + lg, True) return list() if lg == 'or': # if lg == 'nand' or lg == 'or': w_list = o_list return list(w_list)
def match(search_objects, search_key, in_search_term, ignore_case=False, stype='exact'): """Performs a regex match/search or wild card search in dict or brcddb class object(s). If search_key is a list of more than one, OR logic applies. Performs an iteritive search on any list, tuple, dict, or brcddb object found after the last search key. If a list is encountered, an iteritive search is performed on the list. If the search keys have not been exhausted, then the remaining search keys are applied to the iteritive searches. **WARNING:** Circular references will result in Python stack overflow issues. Since all brcddb objects have a link back to the main project object, at least one key must be used to avoid this circular reference :param search_objects: Required. These are the objects to search in. Usually a list :type search_objects: str, tuple, list, dict or any brcddb object :param search_key: Required. The key, or list of keys, in the objects in search_objects to match against. OR logic :type search_key: str, list, tuple :param in_search_term: Required. This is what to look for. :type in_search_term: str, list, tuple, bool :param ignore_case: Default is False. If True, ignores case in search_term. Not that keys are always case sensitive :type ignore_case: bool :param stype: Valid options are: 'exact', 'wild', 'regex-m', or 'regex-s' ('-m' for match and -s for search) :param stype: str :return return_list: List of matching the search criteria - subset of search_objects :rtype: list """ # Summary of wild card strings (search the web for 'python fnmatch.fnmatch' for additional informaiton): # * matches everything # ? matches any single character # [seq] matches any character in seq # [!seq] matches any character not in seq # Summary of ReGex strings (search the web for 'regex' for additional information: # abc… Letters # 123… Digits # \d Any Digit # \D Any Non - digit character # . Any Character # \. Period # [abc] Only a, b, or c # [ ^ abc] Not a, b, nor c # [a - z] Characters a to z # [0 - 9] Numbers 0 to 9 # \w Any Alphanumeric character # \W Any Non - alphanumeric character # {m} m Repetitions # {m, n} m to n Repetitions # * Zero or more repetitions # + One or more repetitions # ? Optional character # \s Any Whitespace # \S Any Non - whitespace character # ^ …$ Starts and ends # (…) Capture Group # (a(bc)) Capture Sub - group # (.*) Capture all # (abc | def ) Matches abc or def # Programmers tip: The Python re and fmatch are quite effecient. In order to search for anything in any data # structure, this method does not make use of list comprehensions. If you need something more effecient, create # a seperate method for a more specific purpose and leave this as a general purpose search and match method. return_list = list() search_term = in_search_term.lower() if ignore_case else in_search_term # Validate user input if not isinstance(search_term, (str, list, tuple, bool)): brcdapi_log.exception('Invalid search_term type: ' + str(type(search_term)), True) return return_list if isinstance(stype, str): if stype in ('regex-m', 'regex-s'): regex_obj = re.compile(search_term, re.IGNORECASE) if ignore_case else re.compile(search_term) elif stype not in ('wild', 'exact', 'bool'): brcdapi_log.exception('Invalid search type: ' + stype, True) return return_list else: brcdapi_log.exception('Search type must be str. Search type is: ' + str(type(stype)), True) return return_list search_key_list = brcddb_util.convert_to_list(search_key) obj_list = brcddb_util.convert_to_list(search_objects) for obj in obj_list: for sk in search_key_list: sub_obj = brcddb_util.get_key_val(obj, sk) if sub_obj is not None: if isinstance(sub_obj, dict): if len(match(sub_obj, list(sub_obj.keys()), search_term, ignore_case, stype)) > 0: return_list.append(obj) elif isinstance(sub_obj, (str, list, tuple)): for buf in brcddb_util.convert_to_list(sub_obj): # Any match within that list is a match if isinstance(buf, str): test_buf = buf.lower() if ignore_case else buf if stype == 'regex-m': if regex_obj.match(test_buf): return_list.append(obj) break elif stype == 'regex-s': if regex_obj.search(test_buf): return_list.append(obj) break elif stype == 'exact': if search_term == test_buf: return_list.append(obj) break elif stype == 'wild': if fnmatch.fnmatch(test_buf, search_term): return_list.append(obj) break elif stype == 'bool': if isinstance(buf, bool) and isinstance(search_term, bool): if bool({search_term: buf}): return_list.append(obj) break elif isinstance(buf, dict): if len(match([buf.get(k) for k in buf], None, search_term, ignore_case, stype)) > 0: return_list.append(obj) break elif isinstance(buf, (list, tuple)): if len(match(buf, None, search_term, ignore_case, stype)) > 0: return_list.append(obj) break elif isinstance(sub_obj, bool): if (search_term and sub_obj) or (not search_term and not sub_obj): return_list.append(obj) break if len(return_list) > 0 and 'brcddb' in str(type(return_list[0])): return brcddb_util.remove_duplicates(return_list) else: return return_list
def _fabric_obj(obj): """Returns a list of fabric objects associated with obj. See _obj_self() for parameter detail.""" try: return obj.r_fabric_objects() except: return brcddb_util.convert_to_list(obj.r_fabric_obj())
def _project_obj(obj): """Returns the project object associated with obj in a list. See _obj_self() for parameter detail.""" return brcddb_util.convert_to_list(obj.r_project_obj())
def _login_obj_for_fdmi(obj): """Returns a the switch object in a list for an FDMI node or port obj. See _obj_self() for parameter detail.""" fab_obj = obj.r_fabric_obj() if fab_obj is None: return list() return brcddb_util.convert_to_list(fab_obj.r_login_obj(obj.r_obj_key()))
def _zonecfg_obj(obj): """Returns a list of zone configuration objects associated with obj. See _obj_self() for parameter detail.""" try: return obj.r_zonecfg_objects() except: return brcddb_util.convert_to_list(obj.r_zonecfg_obj())
def _fabric_ns_case(objx, obj, uri): fab_obj = objx.r_fabric_obj() for ns_obj in brcddb_util.convert_to_list(obj.get('fibrechannel-name-server')): login_obj = fab_obj.s_add_login(ns_obj.get('port-name')) _update_brcddb_obj(login_obj, ns_obj, uri)
def _fabric_fdmi_port_case(objx, obj, uri): fab_obj = objx.r_fabric_obj() for obj in brcddb_util.convert_to_list(obj.get('port')): _update_brcddb_obj(fab_obj.s_add_fdmi_port(obj.get('port-name')), obj, uri)