def del_zonecfg(session, fid, zonecfg_name, echo=False): """Deletes a zone configuration :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param zonecfg_name: Name of zone configuration :type zonecfg_name: str :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ # Delete the zone configuration content = { 'defined-configuration': { 'cfg': [{ 'cfg-name': zonecfg_name, }] } } obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'DELETE', content, fid) _is_error(obj, 'Failed to delete zone configuration ' + zonecfg_name, echo) return obj
def disable_zonecfg(session, check_sum, fid, zonecfg_name, echo=False): """Enables a zone configuration. :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param check_sum: Zoning database checksum :type check_sum: int :param fid: Logical FID number to be created. Valid FISs are 1-128. Will return an error if the FID already exists :type fid: int :param zonecfg_name: Name of the zone configuration to enable :type zonecfg_name: str :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ content = { 'effective-configuration': { 'checksum': check_sum, 'cfg-action': 2 } } obj = brcdapi_rest.send_request(session, 'brocade-zone/effective-configuration', 'PATCH', content, fid) _is_error(obj, 'Failed to enable zone configuration ' + zonecfg_name, echo) return obj
def save(session, fid, check_sum, echo=False): """Saves the contents of the zoning transaction buffer :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 check_sum: Zoning checksum. See checksum() :type check_sum: int :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ content = { 'effective-configuration': { 'cfg-action': 1, 'checksum': check_sum } } obj = brcdapi_rest.send_request(session, 'brocade-zone/effective-configuration', 'PATCH', content, fid) _is_error(obj, 'Failed to save zone configuration test_zone_cfg', echo) return obj
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 create_aliases(session, fid, alias_list, echo=False): """Creates aliases. _sample_alias_list = [ {'name': 'Target_0', 'members': ['50:0c:00:11:0d:bb:42:00']}, {'name': 'Target_1', 'members': ['50:0c:00:11:0d:bb:42:01']}, ] :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param alias_list: List of dictionaries defining the aliases to create. See _sample_alias_list above. :type alias_list: list :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ build_alias_list = list() for alias_obj in alias_list: build_alias_list.append({ 'alias-name': alias_obj.get('name'), 'member-entry': { 'alias-entry-name': alias_obj.get('members') } }) content = {'defined-configuration': {'alias': build_alias_list}} obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'POST', content, fid) _is_error(obj, 'Failed to create aliases', echo) return obj
def del_zones(session, fid, zones, echo=False): """Deletes zones. :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param zones: List of zone names to delete :type zones: list :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ # Delete the zones content = { 'defined-configuration': { 'zone': [{ 'zone-name': zone } for zone in zones] } } obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'DELETE', content, fid) _is_error(obj, 'Failed to delete zone(s)', echo) return obj
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 _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 create_zonecfg(session, fid, zonecfg_name, zone_list, echo=False): """Add a zone configuration. :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param zonecfg_name: Name of zone configuration :type zonecfg_name: str :param zone_list: List of zone names to add to the zonecfg. :type zone_list: list :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ # Create the zone configuration content = { 'defined-configuration': { 'cfg': [{ 'cfg-name': zonecfg_name, 'member-zone': { 'zone-name': zone_list } }] } } obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'POST', content, fid) _is_error(obj, 'Failed to create zone configuration ' + zonecfg_name, echo) return obj
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 _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 del_aliases(session, fid, alias_list, echo=False): """Deletes aliases. Same as input parameters and return as create_aliases() but only 'name' is used in alias_list""" content = { 'defined-configuration': { 'alias': [{ 'alias-name': alias_obj.get('name') } for alias_obj in alias_list] } } obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'DELETE', content, fid) _is_error(obj, 'Failed to delete alias', echo) return obj
def clear_zone(session, fid, echo=False): """Clears the zone database :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ content = {'effective-configuration': {'cfg-action': 3}} obj = brcdapi_rest.send_request(session, 'brocade-zone/effective-configuration', 'PATCH', content, fid) _is_error(obj, 'Failed to set the default zone access', echo) return obj
def abort(session, fid, echo=False): """Aborts a zoning transaction :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: brcdapi_rest status object :rtype: dict """ obj = brcdapi_rest.send_request( session, 'brocade-zone/effective-configuration', 'PATCH', {'effective-configuration': { 'cfg-action': 4 }}, fid) _is_error(obj, 'Abort failed', echo) return obj
def default_zone(session, fid, access, echo=False): """Sets the default zone access method. Also saves pending changes :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param access: Access method. 0 - No Access, 1 - All Access :type access: int :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ content = {'effective-configuration': {'default-zone-access': access}} obj = brcdapi_rest.send_request(session, 'brocade-zone/effective-configuration', 'PATCH', content, fid) _is_error(obj, 'Failed to set the default zone access', echo) return obj
def replace_zoning(session, fab_obj, fid): """Replaces the zoning datbase in a fabric by clearing it and then PATCHing it with a new zoning database Relevant resource: 'zoning/defined-configuration' An error is returned if there is no zone database in in the fab_obj. Use clear_zoning() to clear out zoning. :param session: Login session object from brcdapi.brcdapi_rest.login() :type session: dict :param fab_obj: Fabric object whose zone database will be sent to the switch :type fab_obj: brcddb.classes.fabric.FabricObj :param fid: Fabric ID. If FID check is disabled, this must be the FID of the switch where the request is sent. :type fid: int :return: Object returned from FOS API :rtype: dict """ # Get the dict to be converted to JSON and sent to the switch content = build_all_zone_content(fab_obj) if content is None: return pyfos_auth.create_error( 400, 'No zone database in ' + brcddb_fabric.best_fab_name(obj.r_fabric_obj()), '') # Get the checksum - this is needed to save the configuration. checksum, obj = brcdapi_zone.checksum(session, fid, fab_obj) if pyfos_auth.is_error(obj): return obj # Clear the zone database obj = brcdapi_zone.clear_zone(session, fid) if not pyfos_auth.is_error(obj): # Send the zoning request obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'PATCH', content, fid) if not pyfos_auth.is_error(obj): return brcdapi_zone.save(session, fid, checksum) # If we got this far, something went wrong so abort the transaction. brcdapi_zone.abort(session, fid) return obj
def create_zones(session, fid, zone_list, echo=False): """Add zones to a fabric. _sample_zone_list = [ {'name': 'T0_S0', 'type': 0, 'members': ['Target_0', 'Server_0']}, {'name': 'T0_S1', 'type': 1, 'pmembers': ['Target_0'], 'members': ['Server_1', 'Server_2]}, ] :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param zone_list: List of dictionaries defining the zones to create. See _sample_zone_list for an example. :type zone_list: list :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ # Create the zones build_zone_list = list() for zone_obj in zone_list: d = dict() members = zone_obj.get('members') if isinstance(members, list): d.update({'entry-name': members}) members = zone_obj.get('pmembers') if isinstance(members, list): d.update({'principal-entry-name': members}) build_zone_list.append({ 'zone-name': zone_obj.get('name'), 'zone-type': zone_obj.get('type'), 'member-entry': d }) content = {'defined-configuration': {'zone': build_zone_list}} obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'POST', content, fid) _is_error(obj, 'Failed to create zones', echo) return obj
def _zonecfg_modify(session, fid, zonecfg_name, zone_list, method, echo=False): """Called by zonecfg_add() or zonecfg_remove(). All parameters the same except method :param method: 'DELETE' for remove or 'POST' to add members :type method: str """ # Test content = { 'defined-configuration': { 'cfg': [{ 'cfg-name': zonecfg_name, 'member-zone': { 'zone-name': zone_list } }] } } obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', method, content, fid) _is_error(obj, 'Failed to create zone configuration ' + zonecfg_name, echo) return obj
def clear_stats(session, fid, i_ports, i_ge_ports): """Clear all statistical counters associated with 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 i_ports: Port or list of FC ports for stats to be cleared on :type i_ports: list :param i_ge_ports: GE port or list of GE ports for stats to be cleared on :type i_ge_ports: list :return: brcdapi_rest status object :rtype: dict """ pl = [{ 'name': p, 'reset-statistics': 1 } for p in ports_to_list(i_ports) + ports_to_list(i_ge_ports)] if len(pl) > 0: content = {'fibrechannel-statistics': pl} return brcdapi_rest.send_request( session, 'brocade-interface/fibrechannel-statistics', 'PATCH', content, fid) return brcdapi_util.GOOD_STATUS_OBJ
def pseudo_main(): """Basically the main(). :return: Exit code :rtype: int """ global _DEBUG # Get and validate command line input ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list() ip, user_id, pw, sec, fid_str, vd, log, nl = parse_args() if not nl: brcdapi_log.open_log(log) if vd: brcdapi_rest.verbose_debug = True if fid_str.isdigit(): fid = int(fid_str) else: brcdapi_log.log('Invalid FID: ' + fid_str, True) return -1 brcdapi_log.log(ml, True) # Login brcdapi_log.log('Attempting login', True) session = brcdapi_rest.login(user_id, pw, ip, sec) if brcdapi_auth.is_error(session): brcdapi_log.log('Login failed', True) brcdapi_log.log(brcdapi_auth.formatted_error_msg(session), True) return -1 brcdapi_log.log('Login succeeded', True) ec = 0 try: # I always do a try in code development so that if there is a code bug, I still log out. # Get FC port list for this FID by reading the configurations kpi = 'running/brocade-interface/fibrechannel' obj = brcdapi_rest.get_request(session, kpi, fid) if brcdapi_auth.is_error(obj): brcdapi_log.log('Failed to read ' + kpi + ' for fid ' + str(fid), True) ec = -1 else: fc_plist = [port.get('name') for port in obj.get('fibrechannel')] pl = list() content = {'fibrechannel': pl} for p in fc_plist: d = { 'name': p, 'user-friendly-name': 'port_' + p.replace('/', '_'), # Name port "port_s_p" 'los-tov-mode-enabled': 2 # Enable LOS_TOV } # For other port configuration parameters, search the Rest API Guide or Yang models for # brocade-interface/fibrechannel pl.append(d) # PATCH only changes specified leaves in the content for this URI. It does not replace all resources obj = brcdapi_rest.send_request( session, 'running/brocade-interface/fibrechannel', 'PATCH', content, fid) if brcdapi_auth.is_error(obj): brcdapi_log.log('Error configuring ports for FID ' + str(fid), True) brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True) ec = -1 else: brcdapi_log.log( 'Successfully configured ports for FID ' + str(fid), True) except: # Bare because I don't care what went wrong at this point. I just want to log out no matter what happens. brcdapi_log.log('Encountered a programming error', True) ec = -1 # Logout obj = brcdapi_rest.logout(session) if brcdapi_auth.is_error(obj): brcdapi_log.log( 'Logout failed:\n' + brcdapi_auth.formatted_error_msg(obj), True) return ec
def default_port_config(session, fid, i_ports): """Disables and sets a list of FC ports to their factory default state :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 i_ports: List of ports in the API format of s/p. For a fixed port switch for example, port 12 is '0/12' :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 """ global default_port_config_d ports = ports_to_list(i_ports) if len(ports) == 0: return brcdapi_util.GOOD_STATUS_OBJ # Not all features are supported on all platforms. In most cases, even if you disable the unsupported feature, FOS # returns an error. To get around this, I read the port configuration and only add parameters to send to the switch # if they exist in the data returned from the switch # Read in the port configurations obj = brcdapi_rest.get_request(session, 'brocade-interface/fibrechannel', fid) if pyfos_auth.is_error(obj): brcdapi_log.log( 'Failed to read brocade-interface/fibrechannel for fid ' + str(fid), True) return obj # Put all the ports in a dictionary for easy lookup port_d = dict() for port in obj['fibrechannel']: port_d.update({port['name']: port}) # Figure out what ports to change pl = list() for port in ports: d = port_d.get(port) if d is None: brcdapi_log.exception('Port ' + port + ' not in FID ' + str(fid), True) continue port_content = collections.OrderedDict( ) # This may not need to be ordered. port_content['name'] = port for k, v in default_port_config_d.items(): if k in d: if k == 'speed': if d.get('auto-negotiate' ) is not None and d['auto-negotiate'] == 0: port_content[k] = 0 elif k == 'user-friendly-name': l = port.split('/') port_name = 'port' + l[1] if l[0] != '0': port_name = 'slot' + l[0] + ' ' + port_name if 'user-friendly-name' in d: if d['user-friendly-name'] != port_name: port_content[k] = port_name else: port_content[k] = port_name elif v != d[k]: port_content[k] = v if len(port_content.keys()) > 1: pl.append(port_content) # Now modify the port(s) if len(pl) > 0: return brcdapi_rest.send_request(session, 'brocade-interface/fibrechannel', 'PATCH', {'fibrechannel': pl}, fid) else: return brcdapi_util.GOOD_STATUS_OBJ
def create_ls(session, fid, name, did, idid, xisl, base, ficon, ports, ge_ports, es, ep, echo): """Create a logical switch. Includes options to set a few basic parameters :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number to be created. :type fid: int :param name: User friendly name for the switch. Use None for FOS default switch name :type name: None, str :param did: Domain ID Use None for FOS default DID. :type did: None, int :param idid: If True, sets the DID to be insistent :type idid: None, bool :param xisl: If True, sets the allow XISL bit. :type xisl: None, bool :param base: If True, set the switch type to be a base switch :type base: None, bool :param ficon: If True set the switch type to be a FICON switch :type ficon: None, bool :param ports: Dictionary of ports to add to the switch. Key: FID where the ports reside. Value: list of ports :type ports: None, dict :param ge_ports: Same as ports but for GE ports :type ge_ports: None, dict :param es: If True, enable the switch. Otherwise, the switch is left disabled. :type es: None, bool :param ep: If True, enables all the ports in the switch. Otherwise, they are left disabled. :type ep: None, bool :param echo: If True, step-by-step activity (each request) is echoed to STD_OUT :type echo: None, bool :return: Error code. 0 - Success, -1 - failure :rtype: int """ ec = 0 # Does the switch already exist? switch_list = brcdapi_switch.logical_switches(session, echo) if pyfos_auth.is_error(switch_list): brcdapi_log.log([ 'Error capturing switch list. Ports not added to FID ' + str(fid), pyfos_auth.formatted_error_msg(switch_list) ], True) return -1 fid_list = [switch_d['fabric-id'] for switch_d in switch_list] # Create the switch if it doesn't already exist if fid in fid_list: brcdapi_log.log('Modifying FID ' + str(fid)) else: 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) obj = brcdapi_switch.create_switch(session, fid, base, ficon, echo) if pyfos_auth.is_error(obj): brcdapi_log.exception([ 'Error creating FID ' + str(fid), pyfos_auth.formatted_error_msg(obj) ], True) return -1 # Set switch configuration parameters. Note: brocade-fibrechannel-switch/fibrechannel-switch requires the WWN and # must be an ordered dictionary. To save a little work, the ability to look up the WWN if it's not known and # setting up an ordered dictionary was built into one of the driver methods. sub_content = dict() if did is not None: if fid in fid_list: brcdapi_log.log( 'Cannot modify the domain ID in an existing switch.', True) else: sub_content.update({'domain-id': did}) if name is not None: sub_content.update({'user-friendly-name': name}) if ficon: sub_content.update({ 'in-order-delivery-enabled': True, 'dynamic-load-sharing': 'two-hop-lossless-dls' }) # I didn't bother with a fabric name or banner in the shell interface. I have no idea why the fabric name is set and # read in the switch parameters, but it is. if _DEBUG_FAB_NAME is not None: sub_content.update({'fabric-user-friendly-name': _DEBUG_FAB_NAME}) if _DEBUG_BANNER is not None: sub_content.update({'banner': _DEBUG_BANNER}) # If there is nothing to update, the library will do nothing and return good status. obj = brcdapi_switch.fibrechannel_switch(session, fid, sub_content, None, echo) if pyfos_auth.is_error(obj): brcdapi_log.exception([ 'Failed to configure FID ' + str(fid), pyfos_auth.formatted_error_msg(obj) ], True) ec = -1 # Set the fabric parameters. Note: Setting up fabric parameters is pretty straight forward so there is no driver # method for it. if fid in fid_list: brcdapi_log.log( 'Changing XISL use in an existing switch is not supported by this utility.', True) elif not xisl: # XISL (ability to use the base switch for ISLs) is enabled by default so we only need to disable it obj = brcdapi_rest.send_request( session, 'brocade-fibrechannel-configuration/switch-configuration', 'PATCH', {'switch-configuration': { 'xisl-enabled': False }}, fid) if pyfos_auth.is_error(obj): ml = [ 'Failed to disable XISL for FID ' + str(fid), pyfos_auth.formatted_error_msg(obj), 'Enabling and disabling of XISLs via the API was not supported until FOS v9.0.', 'Unless there are other error messages, all other operations are or will be completed as expected.' ] brcdapi_log.exception(ml, True) ec = -1 # Insistent domain ID is set automatically with FICON switches. The API returns an error if you try to set it. if idid and not ficon: obj = brcdapi_rest.send_request( session, 'brocade-fibrechannel-configuration/fabric', 'PATCH', {'fabric': { 'insistent-domain-id-enabled': True }}, fid) if pyfos_auth.is_error(obj): brcdapi_log.exception([ 'Failed to set insistent domain id for FID ' + str(fid), pyfos_auth.formatted_error_msg(obj) ], True) ec = -1 # Add the ports to the switch. This has to be done one FID at a time. tl = list( ports.keys() ) # The keys are the FIDs so this is the list of all FIDs that have ports to be moved. tl.extend([k for k in ge_ports.keys() if k not in tl]) # Add FIDs for GE ports for k in tl: # For every FID with ports to move obj = brcdapi_switch.add_ports(session, fid, k, ports.get(k), ge_ports.get(k), echo) if pyfos_auth.is_error(obj): brcdapi_log.log([ 'Error adding ports from FID ' + str(k), pyfos_auth.formatted_error_msg(obj) ], True) ec = -1 # Enable the switch if es is not None and es: obj = brcdapi_switch.fibrechannel_switch(session, fid, {'is-enabled-state': True}, None, echo) if pyfos_auth.is_error(obj): brcdapi_log.log([ 'Failed to enable FID ' + str(fid), pyfos_auth.formatted_error_msg(obj) ], True) ec = -1 # Enable the ports we just added if ep is not None and ep: for k in tl: obj = brcdapi_port.enable_port(session, fid, True, ports.get(k) + ge_ports.get(k), True) if pyfos_auth.is_error(obj): brcdapi_log.log([ 'Failed to enable ports on FID ' + str(fid), pyfos_auth.formatted_error_msg(obj) ], True) ec = -1 return ec
def pseudo_main(): """Basically the main(). :return: Exit code :rtype: int """ global _DEBUG # Get and validate command line input ec, ip, user_id, pw, sec, input_d = _get_input() if ec != 0: return ec # Login brcdapi_log.log('Attempting login', True) session = brcdapi_rest.login(user_id, pw, ip, sec) if fos_auth.is_error(session): brcdapi_log.log(fos_auth.formatted_error_msg(session), True) return -1 brcdapi_log.log('Login succeeded', True) ec = 0 uri = 'running/brocade-chassis/management-interface-configuration' try: # try/except so that no matter what happens, the logout code gets executed. # Display initial read (GET) of parameters brcdapi_log.log(['', 'Before Changes:'], True) obj = brcdapi_rest.get_request(session, uri) if fos_auth.is_error(obj): brcdapi_log.log(fos_auth.formatted_error_msg(obj), True) ec = -1 else: brcdapi_log.log(pprint.pformat(obj), True) if ec == 0: # Make the changes content_d = dict() for k, v in input_d.items(): if v is not None: content_d.update({k: v}) if len(content_d) == 0: brcdapi_log.log('No changes to make.', True) else: obj = brcdapi_rest.send_request( session, uri, 'PATCH', {'management-interface-configuration': content_d}) if fos_auth.is_error(obj): brcdapi_log.log(fos_auth.formatted_error_msg(obj), True) ec = -1 else: # Display read (GET) after changing parameters brcdapi_log.log(['', 'After Changes:'], True) obj = brcdapi_rest.get_request(session, uri) if fos_auth.is_error(obj): brcdapi_log.log(fos_auth.formatted_error_msg(obj), True) ec = -1 else: brcdapi_log.log(pprint.pformat(obj), True) except BaseException as e: brcdapi_log.exception( 'Programming error encountered. Exception is: ' + str(e), True) ec = -1 # Logout obj = brcdapi_rest.logout(session) if fos_auth.is_error(obj): brcdapi_log.log('Logout failed', True) ec = -1 else: brcdapi_log.log('Logout succeeded', True) return ec
def _config_fab_and_switch(session, switch_d, echo): """Add and remove ports from a logical switch :param session: Session object, or list of session objects, returned from brcdapi.fos_auth.login() :type session: dict :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 _switch_d_to_api # Load common use stuff into local variables ec = brcddb_common.EXIT_STATUS_OK fid = switch_d['fid'] idid = False if switch_d['switch_type'] == 'ficon' else switch_d['idid'] # Set switch configuration parameters. sub_content = dict() for k, v in _switch_d_to_api.items(): if switch_d[k] is not None: sub_content.update({v: switch_d[k]}) if switch_d['switch_type'] == 'ficon': sub_content.update({ 'in-order-delivery-enabled': True, 'dynamic-load-sharing': 'two-hop-lossless-dls' }) # Send the changes. obj = brcdapi_switch.fibrechannel_switch(session, fid, sub_content, None, echo) if fos_auth.is_error(obj): # in-order-delivery-enabled and dynamic-load-sharing not supported in pre-FOS 9.0 so just try it again sub_content.pop('in-order-delivery-enabled', None) sub_content.pop('dynamic-load-sharing', None) obj = brcdapi_switch.fibrechannel_switch(session, fid, sub_content, None, echo) if fos_auth.is_error(obj): brcdapi_log.log([ 'Failed to configure FID ' + str(fid), fos_auth.formatted_error_msg(obj) ], True) ec = brcddb_common.EXIT_STATUS_API_ERROR else: switch_d['err_msgs'].append( 'Failed to set in order delivery and dynamic load sharing') buf = 'In order delivery and dynamic load sharing not supported via the API in this version of FOS. '\ 'Remember to set these parameters manually.' brcdapi_log.log(buf, True) # Set the fabric parameters. # XISL (ability to use the base switch for ISLs) is enabled by default so we only need to disable it if not switch_d['xisl']: obj = brcdapi_rest.send_request( session, 'running/brocade-fibrechannel-configuration/switch-configuration', 'PATCH', {'switch-configuration': { 'xisl-enabled': False }}, fid) if fos_auth.is_error(obj): switch_d['err_msgs'].append('Failed to disable XISL') ml = [ 'Failed to disable XISL for FID ' + str(fid), fos_auth.formatted_error_msg(obj), 'Enabling and disabling of XISLs via the API was not supported until FOS v9.0.', 'Unless there are other error messages, all other operations are or will be completed as expected.' ] brcdapi_log.log(ml, True) ec = brcddb_common.EXIT_STATUS_API_ERROR if idid: obj = brcdapi_rest.send_request( session, 'running/brocade-fibrechannel-configuration/fabric', 'PATCH', {'fabric': { 'insistent-domain-id-enabled': True }}, fid) if fos_auth.is_error(obj): switch_d['err_msgs'].append('Failed to set insistent domain id') brcdapi_log.log([ 'Failed to set insistent domain id for FID ' + str(fid), fos_auth.formatted_error_msg(obj) ], True) ec = brcddb_common.EXIT_STATUS_API_ERROR return ec
def modify_zone(session, fid, zone, add_members, del_members, in_add_pmembers=None, in_del_pmembers=None, echo=False): """Adds and removes members from a zone. :param session: Session object returned from brcdapi.pyfos_auth.login() :type session: dict :param fid: Logical FID number :type fid: int :param zone: Name of zone to be modified :type zone: str :param add_members: Members to add to the zone :type add_members: list :param del_members: Members to delete from the zone :type del_members: list :param add_pmembers: Principal members to add to zone. Only relevant for peer zones :type add_pmembers: list :param del_pmembers: Principal members to delete from a zone. Only relevant for peer zones :type del_pmembers: list :param echo: If True, echoes any error messages to STD_OUT :type echo: bool :return: brcdapi_rest status object :rtype: dict """ add_pmembers = list() if in_add_pmembers is None else in_add_pmembers del_pmembers = list() if in_del_pmembers is None else in_del_pmembers # This method reads the zone to change, makes the modifications in a local object, and PATCHes the change. I'm # assuming the type of zone could be changed but this method is just changing the membership. See "Important Notes" control = { 'principal-entry-name': { 'add_mem': add_pmembers, 'del_mem': del_pmembers }, 'entry-name': { 'add_mem': add_members, 'del_mem': del_members }, } # Read in the current defined zone obj = brcdapi_rest.get_request( session, 'brocade-zone/defined-configuration/zone/zone-name/' + zone, fid) if _is_error(obj, 'Failed reading zone ' + zone, echo): return obj # Modify the zone d = obj.get('zone') if d is None: return pyfos_auth.create_error( brcdapi_util.HTTP_BAD_REQUEST, brcdapi_util.HTTP_REASON_MAL_FORMED_OBJ, 'Missing leaf "zone" in returned object for ' + zone) me = d.get('member-entry') if me is None: me = dict( ) # I'm not sure what FOS returns if all the members were deleted so this is just to be safe d.update({'member-entry': me}) for k, v in control.items(): ml = me.get(k) if len(v.get('add_mem')) + len(v.get('del_mem')) > 0: if ml is None: ml = list( ) # Just a safety net. Similar to 'member-entry' above. me.update( {k: ml} ) # If there are principle members to a non-peer zone, FOS returns an error for mem in v.get('add_mem'): ml.append(mem) for mem in v.get('del_mem'): try: ml.remove(mem) except: pyfos_auth.create_error( brcdapi_util.HTTP_BAD_REQUEST, 'Delete error', 'Member ' + mem + ' does not exist') content = {'defined-configuration': obj} obj = brcdapi_rest.send_request(session, 'brocade-zone/defined-configuration', 'PATCH', content, fid) _is_error(obj, 'Failed to create zones', echo) return obj