def _format_uri(kpi, fid): """Formats a full URI for a KPI. :param kpi: Rest KPI :type kpi: str :param fid: Fabric ID :type fid: int, None :return: Full URI :rtype: str """ l = kpi.split('/') if len(l) > 2: lookup_kpi = '/'.join(l[0:2]) remaining_l = l[2:] else: lookup_kpi = kpi remaining_l = list() try: buf = brcdapi_util.uri_map[lookup_kpi]['uri'] if len(remaining_l) > 0: buf += '/' + '/'.join(remaining_l) if brcdapi_util.uri_map[lookup_kpi]['fid']: buf += vfid_to_str(fid) return buf except: buf = '/rest/running/' + kpi + vfid_to_str(fid) brcdapi_log.log( 'ERROR: Unknown KPI: ' + lookup_kpi + '. Using best guess: ' + buf, True) brcdapi_log.flush() return buf
def _scan_fabrics(proj_obj): """Scan the project for each fabric and list the fabric WWN, FID , and zone configurations :param proj_obj: Project object :type proj_obj: brcddb.classes.project.ProjectObj :return: Status code :rtype: int """ ec = brcddb_common.EXIT_STATUS_OK # Prepare the fabric display ml = ['', 'Fabric Scan (* indicates the effective zone config)', ''] for fab_obj in proj_obj.r_fabric_objects(): eff_zonecfg = fab_obj.r_defined_eff_zonecfg_key() ml.append(brcddb_fabric.best_fab_name(fab_obj, wwn=True)) ml.append( ' FID: ' + ', '.join([str(fid) for fid in brcddb_fabric.fab_fids(fab_obj)])) for buf in fab_obj.r_zonecfg_keys(): if isinstance(eff_zonecfg, str) and eff_zonecfg == buf: ml.append(' Zone Config: ' + '*' + buf) elif buf != '_effective_zone_cfg': ml.append(' Zone Config: ' + buf) ml.append('') # Wrap up and print fabric information if len(ml) == 0: ml.append('No fabrics specified.') ec = brcddb_common.EXIT_STATUS_INPUT_ERROR brcdapi_log.log(ml, True) return ec
def _db_add(key_0, key_1, key_2, val): """Stubbed out method to add key value pairs to your database :param key_0: First key :type key_0: str :param key_1: Second key :type key_1: str :param key_2: Third key :type key_2: str :param val: Value associated with the keys :type val: str, int, float """ key_list = [key.replace(':', '_').replace('/', '_') for key in (key_0, key_1, key_2)] # If you are new to Python, above is equivalent to: # key_list = list() # for key in (key_0, key_1, key_2): # key_list.append(key.replace(':', '_').replace('/', '_')) # It's probably better to do the equivalent of the key.replace above with a compiled regex but for the few usec it # may save, this is good enough for a simple example. # You might want to make sure you are adding a valid value to your database. if not isinstance(val, (str, int, float)): brcdapi_log.log('Invalid value type, ' + str(type(val)) + ', for key: ' + '/'.join(key_list), True) return # It's probably a good idea to make sure the keys are valid as well. In this example, we're only going to convert # ':' (used in the switch WWN) and '/' (used in the port number) to an underscore, '_'. There may be other # characters, such as '-', that are not valid database keys that you will need to modify. brcdapi_log.log('Adding key: ' + '/'.join(key_list) + ', Value: ' + str(val), True)
def clear_stats(session, switch_obj): """Clear all statistical counters associated with a switch :param session: Session object returned from brcdapi.fos_auth.login() :type session: dict :param switch_obj: Switch object :type switch_obj: brcddb.classes.SwitchObj :return: Ending status code :rtype: int """ ec = brcddb_common.EXIT_STATUS_OK stats_list = [ dict(ports=switch_obj.r_port_keys(), content='fibrechannel-statistics'), dict(ports=switch_obj.r_ge_port_keys(), content='gigabitethernet-statistics') ] for stats in stats_list: if len(stats.get('ports')) > 0: pl = list() fid = brcddb_switch.switch_fid(switch_obj) content = {stats.get('content'): pl} for p in stats.get('ports'): d = dict() d.update({'name': p}) d.update({'reset-statistics': 1}) pl.append(d) obj = brcdapi_rest.send_request( session, 'running/brocade-interface/fibrechannel-statistics', 'PATCH', content, fid) if fos_auth.is_error(obj): brcdapi_log.log(fos_auth.obj_error_detail(obj), True) ec = brcddb_common.EXIT_STATUS_ERROR return ec
def _get_parameters(parms): """Returns a list of Excel column letters matching the list of parms :param parms: Parameters to plot as passed in from the command line with the -p option :type parms: None, str, list :return: List of columns matching the parameters :rtype: list """ global _invalid_parm_ref # Build a header to KPI reference table r_map = dict() for k, d in rt.Port.port_display_tbl.items(): if 'fibrechannel-statistics/' in k: v = d.get('d') if v is not None: r_map.update({v: k}) # Now figure out what to return r = list() for p in parms.split(','): v = r_map.get(p) if v is None: brcdapi_log.log(_invalid_parm_ref + p, True) else: r.append(v) return r
def _create_switch(session, chassis_obj, switch_d, echo): """Creates a logical switch :param session: Session object, or list of session objects, returned from brcdapi.fos_auth.login() :type session: dict :param chassis_obj: Chassis object :type chassis_obj: brcddb.classes.chassis.ChassisObj :param switch_d: Switch object as returned from report_utils.parse_switch_file() :type switch_d: dict :param echo: If True, echo switch configuration details to STD_OUT :type echo: bool """ global _basic_capture_kpi_l fid = switch_d['fid'] buf = 'Creating FID ' + str( fid ) + '. This will take about 20 sec per switch + 25 sec per group of 32 ports.' brcdapi_log.log(buf, True) base = True if switch_d['switch_type'] == 'base' else False ficon = True if switch_d['switch_type'] == 'ficon' else False obj = brcdapi_switch.create_switch(session, fid, base, ficon, echo) if fos_auth.is_error(obj): switch_d['err_msgs'].append('Error creating FID ' + str(fid)) brcdapi_log.log([ switch_d['err_msgs'][len(switch_d['err_msgs']) - 1], fos_auth.formatted_error_msg(obj) ], True) return brcddb_common.EXIT_STATUS_ERROR # re-read the chassis and logical switch data to pick up the switch we just created. session.pop('chassis_wwn', None) api_int.get_batch(session, chassis_obj.r_project_obj(), _basic_capture_kpi_l, None) return chassis_obj.r_switch_obj_for_fid(fid)
def _rules_to_keep(session, fid, maps_policy): """Get the current MAPS rules 'brocade-maps/rule' from specified policy and remove all the SFP rules. :param session: Session object returned from brcdapi.brcdapi_auth.login() :type session: dict :param fid: Fabric ID of the logical switch whose MAPS policy we want to modify. None if not VF enabled :type fid: None, str :param maps_policy: MAPS policy from 'brocade-maps/maps-policy' to keep :type maps_policy: dict :return: List of rule names to keep. None if error encountered :rtype: list """ global _sfp_groups # Get all the MAPS rules obj = api_int.get_rest(session, 'brocade-maps/rule', None, fid) if brcdapi_auth.is_error(obj): brcdapi_log.log('Failed to get MAPS rules.', True) # api_int.get_rest() logs detailed error message return None # Remove all old SFP rules and add the new rules rule_list = maps_policy.get('rule-list').get('rule') return [ rule.get('name') for rule in obj.get('rule') if rule.get('monitoring-system') not in _sfp_monitoring_system and rule.get('name') in rule_list ]
def _create_new_policy(session, fid, policy, rule_list, enable_flag=False): """Create a new MAPS policy. :param session: Session object returned from brcdapi.brcdapi_auth.login() :type session: dict :param fid: Fabric ID of the logical switch whose MAPS policy we want to modify. None if not VF enabled :type fid: None, str :param policy: Name of the MAPS policy to create :type policy: str :param rule_list: List of rule names for the MAPS policy :type rule_list: list :param enable_flag: If True, enables the policy :type enable_flag: bool :return: List of new rules :rtype: list """ new_content = { 'name': policy, 'rule-list': { 'rule': rule_list }, 'is-active-policy': enable_flag } # Now send the new MAPS policy to the switch obj = brcdapi_rest.send_request(session, 'runningbrocade-maps/maps-policy', 'POST', {'maps-policy': new_content}, fid) if brcdapi_auth.is_error(obj): brcdapi_log.log( 'Failed to set MAPS policy. API response:\n' + brcdapi_auth.formatted_error_msg(obj), True) brcdapi_log.log( 'This typically occurs when the policy already exists.', True) return brcddb_common.EXIT_STATUS_API_ERROR return brcddb_common.EXIT_STATUS_OK
def checksum(session, fid, echo=False): """Gets a zoning transaction checksum :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number for the fabric of interest :type fid: int :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: checksum :rtype: int, None :return: brcdapi_rest status object :rtype: dict """ # Get the checksum - this is needed to save the configuration. obj = brcdapi_rest.get_request(session, 'brocade-zone/effective-configuration', fid) if _is_error( obj, 'Failed to get zone data from "brocade-zone/effective-configuration"', echo): return None, obj try: return obj.get('effective-configuration').get('checksum'), obj except: brcdapi_log.log('Failed to get checksum', echo) brcdapi_log.exception(pprint.pformat(obj, indent=4), echo) return None, pyfos_auth.create_error( brcdapi_util.HTTP_INT_SERVER_ERROR, brcdapi_util.HTTP_REASON_UNEXPECTED_RESP, 'Missing effective-configuration/checksum')
def _retry(obj): """Determines if a request should be retried. :param obj: Object returned from _api_request() :type obj: dict :return retry_flag: True - request should be retried. False - request should not be retried. :rtype retry_flag: bool :return delay: Time, in seconds, to wait for retrying the request :rtype delay: int """ status = pyfos_auth.obj_status(obj) reason = pyfos_auth.obj_reason(obj) if isinstance( pyfos_auth.obj_reason(obj), str) else '' if isinstance(status, int) and status == 503 and isinstance( reason, str) and 'Service Unavailable' in reason: brcdapi_log.log( 'FOS API services unavailable. Will retry in ' + str(_SVC_UNAVAIL_WAIT) + ' seconds.', True) return True, _SVC_UNAVAIL_WAIT if status == brcdapi_util.HTTP_BAD_REQUEST and 'The Fabric is busy' in pyfos_auth.formatted_error_msg( obj): brcdapi_log.log('Fabric is busy. Will retry in ' + str(_FABRIC_BUSY_WAIT) + ' seconds.') return True, _FABRIC_BUSY_WAIT return False, 0
def _get_policy(session, fid, policy=None): """Get the specified MAPS policy. If None, return the active MAPS policy :param session: Session object returned from brcdapi.brcdapi_auth.login() :type session: dict :param fid: Fabric ID of the logical switch whose MAPS policy we want to modify. None if not VF enabled :type fid: None, int :param policy: Name of policy to look for. If None, returns the active policy :type policy: str, None :return: Active MAPS policy. None if no active MAPS policy :rtype: int """ # Get the policies obj = api_int.get_rest(session, 'brocade-maps/maps-policy', None, fid) if brcdapi_auth.is_error(obj): brcdapi_log.log('Failed to get MAPS policies.', True) # api_int.get_rest() logs detailed error message return brcddb_common.EXIT_STATUS_API_ERROR, None # Find the policy to return for maps_policy in obj.get('maps-policy'): if policy is None: if maps_policy.get('is-active-policy'): return brcddb_common.EXIT_STATUS_OK, maps_policy elif maps_policy.get('name') == policy: return brcddb_common.EXIT_STATUS_OK, maps_policy return brcddb_common.EXIT_STATUS_INPUT_ERROR, None # If we got this far, we didn't find the policy
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 port_enable_disable(session, fid, state, i_ports, echo=False): """Enables a port or list of ports. :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number for switch with ports. Use None if switch is not VF enabled. :type fid: int :param state: True - enable ports. False - disable ports :type state: bool :param i_ports: List of ports to enable or disable :type i_ports: tuple, list :return: The object returned from the API. If ports is an empty list, a made up good status is returned. :rtype: dict """ ports = ports_to_list(i_ports) if len(ports) == 0: return brcdapi_util.GOOD_STATUS_OBJ # Now enable/disable the port(s) buf = 'En' if state else 'Dis' brcdapi_log.log(buf + 'abling ' + str(len(ports)) + ' ports.', echo) return brcdapi_rest.send_request( session, 'brocade-interface/fibrechannel', 'PATCH', { 'fibrechannel': [{ 'name': p, 'is-enabled-state': state } for p in ports] }, fid)
def _setup_log(folder, no_log): """Demonstrate setup and provide examples on use of the logging methods :param folder: The folder to put log files in. If None, use the local directory :type folder: str, None :param no_log: If True, do not create a log file :type no_log: bool """ global _DEBUG_IP, _DEBUG_ID, _DEBUG_VERBOSE, __version__, _DEBUG_EXCEPTION # Set up the folder to use for logging. if not no_log: brcdapi_log.open_log(folder) # As an example, echo the module variables ml = [ 'Module : cli_poll_to_api', 'Version : ' + __version__, 'User ID : ' + _DEBUG_ID, 'Password : xxxxxx', 'IP address: ' + brcdapi_util.mask_ip_addr(_DEBUG_IP, keep_last=True) ] # Every call to brcdapi_log.log is preceded with a time stamp so this list gets onetime stamp brcdapi_log.log(ml, echo=True) if _DEBUG_VERBOSE: brcdapi_log.log('Verbose debug enabled', True) # This gets it's own time stampe # exception() precedes the message, or list of message, with a stack trace, calls log(), and flushes the file cache. if _DEBUG_EXCEPTION: buf = 'Ignore the preceding stack trace. It is only to illustrate the use of the brcdapi.log.expection() method' brcdapi_log.exception(buf, True)
def _db_add(key_0, key_1, key_2, val): """Stubbed out method to add key value pairs to your database. Derives a unique key from a hash of the 3 input keys :param key_0: First key (switch WWN in xx:xx:xx:xx:xx:xx:xx:xx notation) :type key_0: str :param key_1: Second key (port number in s/p notation) :type key_1: str :param key_2: Third key (value type such as CRC) :type key_2: str :param val: Value associated with the keys :type val: str, int, float """ # You might want to make sure you are adding a valid value to your database. if not isinstance(val, (str, int, float)): brcdapi_log.log( 'Invalid value type, ' + str(type(val)) + ', for database.', True) return # Verbose explanation of the next line of code: # key_list = list() - create a list to store the keys in # for key in (key_0, key_1, key_2): # clean_key = key.replace(':', '_').replace('/', '_') - Replace ':' and '/' with '_' # short_key = clean_key[11:] - removes the non-unique portion of WWN in the key # key_list.append(short_key) - Add the key to key_list # For the Python savvy, a compiled regex would be better than .replace() above but this is good enough for a simple # example. Using a regex probably won't save enough time to make researching it worthwhile so if you don't # understand this comment, just stick with using .replace(). key_list = [ key.replace(':', '_').replace('/', '_')[11:] for key in (key_0, key_1, key_2) ] unique_key = '_'.join( key_list) # Concatenates all items in key_list seperated by a '_' brcdapi_log.log('Adding key: ' + unique_key + ', Value: ' + str(val), True)
def _validate_obj_type(obj_l, obj_type): type_l = gen_util.remove_duplicates( [brcddb_class_util.get_simple_class_type(obj) for obj in obj_l]) if (len(type_l) == 1 and type_l[0] == obj_type) or len(type_l) == 0: return True brcdapi_log.log( 'Invalid report object type. Expected: ' + obj_type + '. Received: ' + ', '.join(type_l), True) return False
def _report_switch_act(obj, disp): global _wb, _working_obj_l if not _validate_obj_type(_working_obj_l, 'SwitchObj'): brcdapi_log.log('Invalid object type for "switch"', True) return brcdapi_log.log('Creating ' + obj['name'], True) report_switch.switch_page(_wb, None, obj['name'], obj.get('index'), obj.get('title'), _working_obj_l)
def _logout(session): """Logout and post message if the logout failed :param session: Session object returned from brcdapi.brcdapi_auth.login() :type session: dict """ obj = brcdapi_rest.logout(session) if brcdapi_auth.is_error(obj): brcdapi_log.log( 'Logout failed:\n' + brcdapi_auth.formatted_error_msg(obj), True)
def _compare(r_obj, ref, b_obj, c_obj, control_tbl): """Compares two dict, list, tuple, or brcddb.classes objects :param r_obj: Return object - Dictionary or list of changes :type r_obj: dict, list :param ref: Reference key. :type ref: str :param b_obj: Base object to compare against. :type b_obj: dict, list, tuple, brcddb.classes.* :param c_obj: Compare object :type c_obj: dict, list, tuple, brcddb.classes.* :param control_tbl: Control table. :type control_tbl: dict :return: Number of mismatches found :rtype: int """ global _obj_type_action, _REMOVED, _NEW, _MISMATCH, _INVALID_REF # Make sure we have a valid reference. if not isinstance(ref, str): brcdapi_log.exception('Invalid reference type: ' + str(type(ref)), True) _update_r_obj(r_obj, {'b': '', 'c': '', 'r': _INVALID_REF}) return 0 # Does the base object exist? if b_obj is None: _update_r_obj(r_obj, {'b': ref, 'c': '', 'r': _NEW}) return 1 # Does the compare object exist? if c_obj is None: _update_r_obj(r_obj, {'b': ref, 'c': '', 'r': _REMOVED}) return 1 # Are we comparing the same types? A mix of int and float is OK so that gets normalized to type 'num' b_type = class_util.get_simple_class_type(b_obj) if b_type is None: b_type = 'num' if isinstance(b_obj, (int, float)) else \ str(type(b_obj)).replace('<class ', '').replace('>', '').replace("\'", '') c_type = class_util.get_simple_class_type(c_obj) if c_type is None: c_type = 'num' if isinstance(c_obj, (int, float)) else \ str(type(c_obj)).replace('<class ', '').replace('>', '').replace("\'", '') if b_type != c_type: _update_r_obj(r_obj, {'b': b_type, 'c': c_type, 'r': _MISMATCH}) return 1 if b_type in _obj_type_action: return _obj_type_action[b_type](r_obj, ref, b_obj, c_obj, control_tbl) brcdapi_log.log('Unknown base object type: ' + b_type, True) _update_r_obj(r_obj, {'b': b_type, 'c': '', 'r': _INVALID_REF}) return 1
def _report_port_act(obj, disp): global _wb, _working_obj_l if not _validate_obj_type(_working_obj_l, 'PortObj'): brcdapi_log.log('Invalid object type for "port"', True) return brcdapi_log.log('Creating ' + obj['name'], True) report_port.port_page(_wb, None, obj['name'], obj.get('index'), obj.get('title'), brcddb_util.sort_ports(_working_obj_l), disp)
def _clear_dashboard(session, fid): """Clears the MAPS dashboard :return fid: Fabric ID :rtype fid: int """ content = {'clear-data': True} obj = brcdapi_rest.send_request(session, 'running/brocade-maps/dashboard-misc', 'PUT', content, fid) if brcdapi_auth.is_error(obj): brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True) return -1 return 0
def _print_disp(obj): global _working_obj_l disp = gen_util.convert_to_list(obj.get('disp')) to_print_l = list() for b_obj in _working_obj_l: for buf in disp: for d in gen_util.convert_to_list(obj.get('replace')): buf = buf.replace(d['t'], str(b_obj.r_get(d['r']))) to_print_l.append(buf) if len(to_print_l) > 0: brcdapi_log.log(to_print_l, True)
def _get_chassis_data(session): """Capture chassis data as would be returned from (not all chassis data is being captured): :param session: The session object returned from brcdapi.fos_auth.login() :type session: dict :return: FID list :rtype: list """ global _chassis_rest_data # Get all the chassis data # Note that in Gen 6 and above, the license ID, brocade-chassis/chassis/license-id, may not be the chassis WWN for kpi in _chassis_rest_data: # See comments with _chassis_rest_data above ml = ['', kpi ] # The first member as '' inserts a blank line before the KPI obj = brcdapi_rest.get_request(session, kpi) if brcdapi_auth.is_error(obj): ml.append(brcdapi_auth.formatted_error_msg(obj)) else: ml.append(pprint.pformat(obj)) brcdapi_log.log(ml, True) """This is essentially a hybrid of lscfg --show and switchshow. This is where all the logical switches and ports associated with those logical switches are reported. I broke this out from _chassis_rest_data because we need to pick out the fabric IDs of all the logical switches.""" kpi = 'running/brocade-fibrechannel-logical-switch/fibrechannel-logical-switch' ml = ['', kpi] obj = brcdapi_rest.get_request(session, kpi) if brcdapi_auth.is_error(obj): ml.append(brcdapi_auth.formatted_error_msg(obj)) brcdapi_log.log(ml, True) return list( ) # A return in the middle of a method is common in Python after an error is encountered. ml.append(pprint.pformat(obj)) """Normally, I would build a dictionary of the ports so I could treat them as objects and add port configuration, port statistics, and anything else port specific to the object. I don't recall how a non-VF enabled switch responds but I don't think 'fabric-id' is present in the response. If you are new to Python, there is a construct referred to as a list comprehension which allows you to build a list in a single line of code. The code that follows this comment is equivalent to: fid_list = list() for ls in obj['fibrechannel-logical-switch']: if ls.get('fabric-id') is not None: fid_list.append(ls.get('fabric-id')) return fid_list""" return [ ls.get('fabric-id') for ls in obj['fibrechannel-logical-switch'] if ls.get('fabric-id') is not None ]
def write_dump(obj, file): """Creates a file using json.dumps. Typical use is to convert a project object with brcddb_to_plain_copy to a plain Python dict. :param obj: Dictionary to write to file :type obj: dict, list :param file: Name of file to write to :type file: str :rtype: None """ brcdapi_log.log('CALL: brcddb_util.write_dump. File: ' + file) with open(file, 'w') as f: f.write(json.dumps(obj, sort_keys=True)) f.close()
def pseudo_main(): """Basically the main(). Did it this way so it can easily be used as a standalone module or called from another. :return: Exit code. See exist codes in brcddb.brcddb_common :rtype: int """ global _DEBUG, __version__, _ZONE_CHECK # Get and validate user input inf, outf, sfp_rules, iocp, custom_parms = _get_input() ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list() ml.append('report.py version ' + __version__) ml.append('In file: ' + inf) ml.append('Out file: ' + outf) ml.append('SFP rules file: ' + str(sfp_rules)) if sfp_rules is not None: ml.append("The 'User Warning: Data Validation ...' can be ignored.") brcddb_bp.sfp_rules = report_utils.parse_sfp_file(sfp_rules) ml.append('custom_parms: ' + str(custom_parms)) brcdapi_log.log(ml, True) # Get the project object try: proj_obj = brcddb_project.read_from(inf) except FileNotFoundError: brcdapi_log.log('Input file, ' + inf + ', not found', True) return brcddb_common.EXIT_STATUS_ERROR if proj_obj is None: return brcddb_common.EXIT_STATUS_ERROR # Perform all pre-processing (parse IOCPs, build references, ...) brcdapi_log.log('Building cross references', True) brcddb_project.build_xref(proj_obj) brcddb_project.add_custom_search_terms(proj_obj) brcdapi_log.log('Performing mainframe checks', True) for file in brcapi_file.read_directory(iocp): brcddb_iocp.parse_iocp(proj_obj, iocp + '/' + file) brcddb_bp.best_practice(al.AlertTable.alertTbl, proj_obj) if _ZONE_CHECK: for obj in proj_obj.r_fabric_objects( ): # Get a zone analysis on all fabrics brcdapi_log.log( 'Performing zone analysis for fabric ' + brcddb_fabric.best_fab_name(obj), True) brcddb_fabric.zone_analysis(obj) # Generate the report brcddb_report.report(proj_obj, outf) _custom_report(proj_obj, custom_parms) return brcddb_common.EXIT_STATUS_ERROR if proj_obj.r_is_any_error( ) else brcddb_common.EXIT_STATUS_OK
def _create_new_rules(session, fid, new_sfp_rules): """Create all new SFP rules :param session: Session object returned from brcdapi.brcdapi_auth.login() :type session: dict :param fid: Fabric ID of the logical switch whose MAPS policy we want to modify. None if not VF enabled :type fid: None, str :param new_sfp_rules: List of dictionaries of rules returned from report_utils.parse_sfp_file_for_rules() :type new_sfp_rules: list :return: List of new rules created. """ # Build the new rules content for the API POST request sum_new_rules = list() num_rules = len(new_sfp_rules) # After writing the code, I was getting HTTP connection timeouts so I had to batch the number of rules to add. i = 0 while i < num_rules: x = i + _MAX_RULE_BATCH if i + _MAX_RULE_BATCH <= num_rules else num_rules new_rules = new_sfp_rules[i:x] obj = brcdapi_rest.send_request(session, 'running/brocade-maps/rule', 'POST', dict(rule=new_rules), fid) if brcdapi_auth.is_error(obj): # If the rule already exists, you cannot use POST or PATCH to write over it and PUT is not supported. I'm # assuming you could DELETE then POST and I could also check to see if the rule is changing but this simple # example on how to modify a MAPS policy is already getting to complicated so I just post warnings. er_l = list() er_obj = dict(errors=dict(error=er_l)) if 'errors' in obj and isinstance(obj['errors'].get('error'), list): for d in obj['errors']['error']: buf = d.get('error-message') if buf is not None and buf == 'Rule name is present.' and isinstance( d.get('error-path'), str): brcdapi_log.log( 'Rule ' + d['error-path'].replace( '/rule/name/', '').replace('/', '') + ' already exists. Not changed.', True) else: er_l.append(d) if len(er_l) > 0: brcdapi_log.log( 'Failed to create rules. API response:' + brcdapi_auth.formatted_error_msg(er_obj), True) return sum_new_rules # If we get here, something is really wrong so just bail out # rule.get('name') should never be None in the line below. I'm just extra cautious sum_new_rules.extend([ rule.get('name') for rule in new_rules if rule.get('name') is not None ]) i = x return sum_new_rules
def _cert_detail_report(obj): """Generates a user friendly cert report. :param obj: Object returned from the API. :type obj: dict :rtype: None """ # For each certificate, display the full cert if present for cert_d in obj['security-certificate']: hexdump = cert_d.get('certificate-verbose') if isinstance(hexdump, str) and len(hexdump) > 0: buf = cert_d['certificate-entity'] + ', ' + cert_d[ 'certificate-type'] + ' Detail:' brcdapi_log.log(['', buf, '', hexdump], True)
def read_dump(file): """Reads in a file using json.load. Typical use is to read back in a project object file writen with write_dump and then convert back to a project object with plain_copy_to_brcddb_copy Python dict. :param file: Name of file to write to :type file: str :return: :rtype: dict, list, None """ brcdapi_log.log('CALL: brcddb_util.read_dump. File: ' + file) f = open(file, 'r') obj = json.load(f) f.close() return obj
def _report_act(obj): global _report_name, _report_display # Validate the users filter file if not isinstance(_report_name, str): brcdapi_log.log('"report" action found before "def_report" action.', True) return report_disp = None disp = obj.get('disp') if disp is not None: if not isinstance(disp, str): buf = 'Invalid "disp" type, ' + str(type( disp)) + ', in "report" action. The value associated with ' buf += '"disp" must be a string. Using default display tables.' brcdapi_log.log(buf, True) else: report_disp = _report_display.get(disp) if report_disp is None: buf = '"disp", ' + disp + ', in "report" action not found in "def_report". Using default display '\ 'tables.' brcdapi_log.log(buf, True) if _has_sheet_name(obj, 'worksheet'): obj_type = obj.get('type') if obj_type is not None and obj_type in _report_action_d: _report_action_d[obj_type](obj, report_disp) else: brcdapi_log.log( 'Invalid "type", "' + str(obj.get('type')) + '" in "report" action', True)
def pseudo_main(): """Basically the main(). Did it this way so it can easily be used as a standalone module or called from another. :return: Exit code. See exist codes in brcddb.brcddb_common :rtype: int """ ip, user_id, pw, outf, sec, s_flag, vd, c_file, fid, log, nl = parse_args() if vd: brcdapi_rest.verbose_debug = True if s_flag: brcdapi_log.set_suppress_all() if not nl: brcdapi_log.open_log(log) if sec is None: sec = 'none' fid_l = None if fid is None else fid.split(',') ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list() ml.append('IP: ' + brcdapi_util.mask_ip_addr(ip, True)) ml.append('ID: ' + user_id) ml.append('security: ' + sec) ml.append('Output file: ' + outf) ml.append('KPI file: ' + str(c_file)) ml.append('FID List: ' + str(fid)) brcdapi_log.log(ml, True) outf = brcdapi_file.full_file_name(outf, '.json') # Create project proj_obj = brcddb_project.new( "Captured_data", datetime.datetime.now().strftime('%d %b %Y %H:%M:%S')) proj_obj.s_python_version(sys.version) proj_obj.s_description("This is a test") # Login session = api_int.login(user_id, pw, ip, sec, proj_obj) if brcdapi_auth.is_error(session): return brcddb_common.EXIT_STATUS_API_ERROR # Collect the data try: api_int.get_batch(session, proj_obj, _kpi_list(session, c_file), fid_l) except BaseException as e: brcdapi_log.exception( 'Programming error encountered. Exception is: ' + str(e), True) # Logout obj = brcdapi_rest.logout(session) if brcdapi_auth.is_error(obj): brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True) # Dump the database to a file if _WRITE: brcdapi_log.log('Saving project to: ' + outf, True) plain_copy = dict() brcddb_copy.brcddb_to_plain_copy(proj_obj, plain_copy) brcdapi_file.write_dump(plain_copy, outf) brcdapi_log.log('Save complete', True) return proj_obj.r_exit_code()