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
    ]
Example #2
0
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')
Example #3
0
def get_chassis(session, proj_obj):
    """Gets the  chassis object and objects for all logical switches in the chassis.

    :param session: Session object returned from brcdapi.pyfos_auth.login()
    :type session: dict
    :param proj_obj: The project object
    :type proj_obj: brcddb.classes.project.ProjectObj
    :return: Chassis object
    :rtype: brcddb.classes.ChassisObj
    """
    # See if we already got it
    if 'chassis_wwn' in session:
        chassis_obj = proj_obj.r_chassis_obj(session.get('chassis_wwn'))
        if chassis_obj is not None:
            return chassis_obj

    # Go get it
    uri = 'brocade-chassis/chassis'
    obj = brcdapi_rest.get_request(session, uri, None)
    if pyfos_auth.is_error(obj):
        return None
    try:
        wwn = obj.get('chassis').get('chassis-wwn')
        chassis_obj = proj_obj.s_add_chassis(wwn)
        results_action(chassis_obj, obj, uri)
        session.update(dict(chassis_wwn=wwn))
        # Get all the switches in this chassis
        if chassis_obj.r_is_vf_enabled():  # Get all the logical switches in this chassis
            uri = 'brocade-fibrechannel-logical-switch/fibrechannel-logical-switch'
            obj = brcdapi_rest.get_request(session, uri, None)
            if pyfos_auth.is_error(obj):
                _process_errors(session, uri, obj, chassis_obj)
                fid_l = list()
            else:
                results_action(chassis_obj, obj, uri)
                fid_l = [d.get('fabric-id') for d in obj.get('fibrechannel-logical-switch')]
        else:
            fid_l = [None]
        for fid in fid_l:
            uri = 'brocade-fabric/fabric-switch'
            obj = brcdapi_rest.get_request(session, uri, fid)
            _process_errors(session, uri, obj, chassis_obj)
            results_action(chassis_obj, obj, uri)
        return chassis_obj
    except:
        _process_errors(session, uri, session, proj_obj)
        return None
Example #4
0
def login(user_id, pw, ip_addr, https='none', proj_obj=None):
    """Log in and capture a list of supported modules.

    :param user_id: User ID
    :type user_id: str
    :param pw: Password
    :type pw: str
    :param ip_addr: IP address
    :type ip_addr: str
    :param https: If 'CA' or 'self', uses https to login. Otherwise, http.
    :type https: None, str
    :param proj_obj: Project object
    :type proj_obj: brcddb.classes.project.ProjectObj, None
    :return: session
    :rtype: dict
    """
    # Attempt to log in
    tip = brcdapi_util.mask_ip_addr(ip_addr, True)
    session = brcdapi_rest.login(user_id, pw, ip_addr, https)
    if pyfos_auth.is_error(session):
        brcdapi_log.log(tip + ' Login failed', True)
        _process_errors(session, '/rest/login', session, proj_obj)
        return session
    else:
        brcdapi_log.log(tip + ' Login succeeded', True)

    # Figure out what modules this FOS version supports
    # Step 1: Read all the module information from FOS
    uri = 'brocade-module-version'
    obj = brcdapi_rest.get_request(session, uri)
    if pyfos_auth.is_error(obj):
        brcdapi_log.log(tip + ' ERROR: ' + uri + '\n' + pyfos_auth.formatted_error_msg(obj), True)
        return session

    # Step 2: Parse the module information and add it to the session object
    kpi_list = list()
    for mod_obj in obj.get(uri).get('module'):
        name = mod_obj.get('name')
        if name is None:
            brcdapi_log.exception("'name' mising in brocade-module-version", True)
            continue
        kpi_list.append(name)
        try:  # I think 'object' will always be there, just empty when there are no objects. Try/Except just in case.
            for mod_object in mod_obj.get('objects').get('object'):
                kpi_list.append(name + '/' + mod_object)
        except:
            pass
    session.update(dict(supported_uris=kpi_list))

    return session
def pseudo_main():
    """Basically the main(). Did it this way so it can easily be modified to be called from another script.

    :return: Exit code. See exit codes in brcddb.brcddb_common
    :rtype: int
    """
    # Get the command line input
    ip_addr, user_id, pw, sec = _get_input()

    # Login
    brcdapi_log.log('Attempting login', True)
    session = brcdapi_rest.login(user_id, pw, ip_addr, sec)
    if fos_auth.is_error(session):
        brcdapi_log.log('Login failed. Error message is:', True)
        brcdapi_log.log(fos_auth.formatted_error_msg(session), True)
        return -1
    brcdapi_log.log([
        'Login succeeded', 'Getting certificates. This will take about 30 sec.'
    ], True)

    try:  # This try is to ensure the logout code gets executed regardless of what happened.
        # Get the certificates from the API
        cert_obj = brcdapi_rest.get_request(
            session, 'running/brocade-security/security-certificate')
    except BaseException as e:
        brcdapi_log.exception(
            'Unexpected error encountered. Exception is: ' + str(e), True)

    # Logout
    brcdapi_log.log('Attempting logout', True)
    obj = brcdapi_rest.logout(session)
    if fos_auth.is_error(obj):
        brcdapi_log.log('Logout failed. Error message is:', True)
        brcdapi_log.log(fos_auth.formatted_error_msg(obj), True)
        return -1
    brcdapi_log.log('Logout succeeded.', True)

    # Display the certificates
    if fos_auth.is_error(cert_obj):
        brcdapi_log.exception(
            'Failed to capture certificates.' +
            fos_auth.formatted_error_msg(cert_obj), True)
        return -1
    _cert_detail_report(cert_obj)
    _cert_summary_report(cert_obj)

    return 0
Example #6
0
def get_rest(session, uri, wobj=None, fid=None):
    """Wraps loging around a call to brcdapi_rest.get_request()

    :param session: Session object returned from brcdapi.pyfos_auth.login()
    :type session: dict
    :param uri: URI, less the prefix
    :type uri: str
    :param wobj: Working object
    :type: ProjectObj, FabricObj, SwitchObj, ChassisObj
    :param fid: Fabric ID
    :type fid: int, None
    :return: obj
    :rtype: dict
    """
    brcdapi_log.log('GET: ' + uri + brcdapi_rest.vfid_to_str(fid), True)
    obj = brcdapi_rest.get_request(session, uri, fid)
    _process_errors(session, uri, obj, wobj)
    return obj
def _get_switch_data(session, fid):
    """Capture switch, fabric, and port data as would be returned from (not all data is being captured):

    :param session: The session object returned from brcdapi.fos_auth.login()
    :type session: dict
    :param fid: Fabric ID to execute the switch level commands against. Use None for non-VF enabled switches
    :type fid: int, None
    """
    global _switch_rest_data

    for kpi in _switch_rest_data:  # See comments with _switch_rest_data above
        ml = ['', kpi
              ]  # The first member as '' inserts a blank line before the KPI
        obj = brcdapi_rest.get_request(session, kpi, fid)
        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)
def get_ge_port_list(session, fid):
    """Returns the list of GE ports in a logical switch

    :param session: Session object returned from brcdapi.brcdapi_auth.login()
    :type session: dict
    :param fid: Logical switch FID number
    :type fid: int
    :return: List of GE ports
    :rtype: list
    """
    obj = brcdapi_rest.get_request(
        session,
        'running/brocade-fibrechannel-logical-switch/fibrechannel-logical-switch/fabric-id/'
        + str(fid))
    if brcdapi_auth.is_error(obj):
        brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True)
        return list()
    if 'fibrechannel-logical-switch' in obj and 'ge-port-member-list' in obj[
            'fibrechannel-logical-switch']:
        pl = obj['fibrechannel-logical-switch']['ge-port-member-list'].get(
            'port-member')
        return list() if pl is None else pl
    return list()
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:
            # Get the port lists
            fc_plist = [port.get('name') for port in obj.get('fibrechannel')]

            # Disable all ports and set to the default configuration.
            brcdapi_log.log(
                'Disabling all ports of fid: ' + str(fid) +
                ' and setting to default configuration', True)
            obj = brcdapi_port.default_port_config(session, fid, fc_plist)
            if brcdapi_auth.is_error(obj):
                brcdapi_log.log(
                    'Set ports to default for FID ' + str(fid) + ' failed',
                    True)
                brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True)
                ec = -1
            else:
                brcdapi_log.log(
                    'Successfully set all ports for FID ' + str(fid) +
                    ' to the default configuration', True)

    except:
        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 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
Example #11
0
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
def pseudo_main():
    """Basically the main(). Did it this way to use with IDE
    :return: Exit code
    :rtype: int
    """
    ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list()
    ip, user_id, pw, sec, fids, vd, log, nl = parse_args()
    if vd:
        brcdapi_rest.verbose_debug = True
    if sec is None:
        sec = 'none'
    if not nl:
        brcdapi_log.open_log(log)
    fl = [int(f) for f in fids.split(',')]
    ml.append('FIDs: ' + fids)
    brcdapi_log.log(ml, True)

    # Login
    session = brcdapi_rest.login(user_id, pw, ip, sec)
    if brcdapi_auth.is_error(session):
        brcdapi_log.log(
            'Login failed:\n' + brcdapi_auth.formatted_error_msg(session),
            True)
        return -1

    # Get the Chassis data
    brcdapi_log.log('Chassis Data\n------------', True)
    for uri in _chassis_rest_data:
        brcdapi_log.log('URI: ' + uri, True)
        try:
            obj = brcdapi_rest.get_request(session, uri)
            if brcdapi_auth.is_error(
                    obj):  # Set breakpoint here to inspect response
                brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True)
        except BaseException as e:
            brcdapi_log.exception(
                ['Error requesting ' + uri, 'Exception: ' + str(e)], True)

    # Get the Switch data
    for vf_id in fl:
        brcdapi_log.log(
            'Switch data. FID: ' + str(vf_id) + '\n---------------------',
            True)
        for buf in fid_rest_data:
            brcdapi_log.log('URI: ' + buf, True)
            try:
                obj = brcdapi_rest.get_request(session, buf, vf_id)
                if brcdapi_auth.is_error(
                        obj):  # Set breakpoint here to inspect response
                    brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj),
                                    True)
            except BaseException as e:
                brcdapi_log.exception(
                    ['Error requesting ' + buf, 'Exception: ' + str(e)], True)

    # 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 -1

    return 0
Example #13
0
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 pseudo_main():
    """Basically the main(). Did it this way to use with IDE
    :return: Exit code
    :rtype: int
    """
    global _DEBUG

    # Get the 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 vd:
        brcdapi_rest.verbose_debug = True
    if sec is None:
        sec = 'none'
    if not nl:
        brcdapi_log.open_log(log)
    ml.append('FID: ' + fid_str)
    try:
        fid = int(fid_str)
    except ValueError:
        brcdapi_log.log(
            'Invalid FID, -f. FID must be an integer between 1-128')
    brcdapi_log.log(ml, True)

    # Login
    session = brcdapi_rest.login(user_id, pw, ip, sec)
    if brcdapi_auth.is_error(session):
        brcdapi_log.log(
            'Login failed:\n' + brcdapi_auth.formatted_error_msg(session),
            True)
        return -1

    ec = 0  # Error code. 0: No errors. -1: error encountered
    port_info_d = dict()  # Will use this to store basic port information
    port_stats_d = dict()  # Will use this to store port statistics in

    # You may want to put better error checking in your code as well as use a more efficient code. A verbose coding
    # style was used here for readability.
    try:
        # Get the switch WWN
        brcdapi_log.log('Capturing chassis Data', True)
        uri = 'running/brocade-fibrechannel-logical-switch/fibrechannel-logical-switch'
        obj = brcdapi_rest.get_request(session, uri)
        if brcdapi_auth.is_error(obj):
            brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True)
            ec = -1
        else:
            # Find the switch with the matching FID
            switch_wwn = None
            for switch_obj in obj['fibrechannel-logical-switch']:
                if switch_obj['fabric-id'] == fid:
                    switch_wwn = switch_obj['switch-wwn']
                    break
            if switch_wwn is None:
                brcdapi_log.log(
                    'Logical switch for FID ' + str(fid) + 'not found', True)
                ec = -1

        # Get some basic port information
        if ec == 0:  # Make sure we didn't encountered any errors above
            # It's common to keep track of other port information, such as the user friendly name and FC address. Below
            # captures this basic port information.
            brcdapi_log.log('Capturing basic port information.', True)
            uri = 'running/brocade-interface/fibrechannel'
            port_info = brcdapi_rest.get_request(session, uri, fid)
            if brcdapi_auth.is_error(port_info):
                brcdapi_log.log(brcdapi_auth.formatted_error_msg(port_info),
                                True)
                ec = -1
            else:
                # To make it easier to match the port information with the port statistics, we're going to create a
                # a dictionary using the port name (port number) as the key
                for port_obj in port_info['fibrechannel']:
                    port_info_d.update({port_obj['name']: port_obj})

        # Capture the port statistics
        if ec == 0:  # Make sure we didn't encountered any errors above
            brcdapi_log.log('Capturing port statistics', True)
            uri = 'running/brocade-interface/fibrechannel-statistics'
            port_stats = brcdapi_rest.get_request(session, uri, fid)
            if brcdapi_auth.is_error(port_stats):
                brcdapi_log.log(brcdapi_auth.formatted_error_msg(port_stats),
                                True)
                ec = -1
            else:
                # We could just add each port to the database here but since it's common to capture additional
                # information, such as determining the login alias(es), we'll add it to a dictionary as was done with
                # the basic port information
                for port_obj in port_stats['fibrechannel-statistics']:
                    port_stats_d.update({port_obj['name']: port_obj})

        # Add all the ports to the database
        if ec == 0:  # Make sure we didn't encountered any errors above
            brcdapi_log.log('Adding key value pairs to the database.', True)
            for port_num, port_obj in port_info_d.items():
                sub_key = 'fcid-hex'  # Just using the FC address for this example
                _db_add(switch_wwn, port_num, sub_key, port_obj[sub_key])
                for k, v in port_stats_d[port_num].items():
                    _db_add(switch_wwn, port_num, k, v)

    except:  # Bare because I don't care what went wrong. I just want to logout
        # The brcdapi_log.exception() method precedes the passed message parameter with a stack trace
        brcdapi_log.exception(
            'Unknown programming error occured while processing: ' + uri, True)

    # 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 -1

    return 0
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