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 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, sec, log, nl = parse_args()
    if sec is None:
        sec = 'none'
    if not nl:
        brcdapi_log.open_log(log)
    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)
    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. Error message is:', True)
        brcdapi_log.log(brcdapi_auth.formatted_error_msg(session), True)
        return -1

    # Logout
    brcdapi_log.log('Login succeeded. Attempting logout', True)
    obj = brcdapi_rest.logout(session)
    if brcdapi_auth.is_error(obj):
        brcdapi_log.log('Logout failed. Error message is:', True)
        brcdapi_log.log(brcdapi_auth.formatted_error_msg(obj), True)
        return -1
    brcdapi_log.log('Logout succeeded.', True)
    return 1
Example #3
0
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()
Example #4
0
def _convert_ip_addr(obj):
    if isinstance(obj, dict):
        d = dict()
        for k, v in obj.items():
            d.update({k: _convert_ip_addr(v)})
        return d
    elif isinstance(obj, (list, tuple)):
        return [_convert_ip_addr(v) for v in obj]
    else:
        return brcdapi_util.mask_ip_addr(obj)
Example #5
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
Example #6
0
def get_batch(session, proj_obj, kpi_list, fid=None):
    """Processes a batch API requests. All chassis request are performed first, followed by processing of fid_rest_data

    If any warnings or errors are encountered, the log is updated and the appropriate flag bits for the proj_obj are
    set. Search for _project_warn in brcddb_common.py for additional information. Again, search for _project_warn in
    brcddb.classes for object methods to set and check these bits.
    :param session: Session object, or list of session objects, returned from brcdapi.pyfos_auth.login()
    :type session: dict
    :param proj_obj: Project object
    :type proj_obj: brcddb.classes.ProjectObj
    :param kpi_list: List of KPIs to request from the switches and chassis
    :type kpi_list: list
    :param fid: FID, or list of FIDs for logical switch level requests. If None, execute requests for all FIDs.
    :type fid: int, list, tuple, None
    :rtype: None
    """
    # Get the chassis object
    chassis_obj = get_chassis(session, proj_obj)
    if chassis_obj is None:
        brcdapi_log.log(brcdapi_util.mask_ip_addr(session.get('ip_addr')) + 'Chassis not found.', True)
        return

    kl = brcddb_util.convert_to_list(kpi_list)

    # Get all the chassis data
    for kpi in [kpi for kpi in kl if not brcdapi_util.uri_map[kpi]['fid']]:
        results_action(chassis_obj, get_rest(session, kpi, chassis_obj), kpi)

    # Figure out which logical switches to poll switch level data from.
    if chassis_obj.r_is_vf_enabled() and fid is not None:
        switch_list = list()
        for fab_id in brcddb_util.convert_to_list(fid):
            switch_obj = chassis_obj.r_switch_obj_for_fid(fab_id)
            if switch_obj is None:
                brcdapi_log.log('FID ' + str(fab_id) + ' not found', True)
            else:
                switch_list.append(switch_obj)
    else:
        switch_list = chassis_obj.r_switch_objects()

    # Now process all the switch (FID) level commands.
    for switch_obj in switch_list:
        for kpi in [kpi for kpi in kl if brcdapi_util.uri_map[kpi]['fid']]:
            results_action(switch_obj,
                           get_rest(session, kpi, switch_obj, brcddb_switch.switch_fid(switch_obj)), kpi)
Example #7
0
def _process_errors(session, uri, obj, wobj):
    """Checks for errors in the API response and adds alerts to the object if there is an error

    :param session: Session object returned from brcdapi.pyfos_auth.login()
    :type session: dict
    :param uri: URI, less the prefix
    :type uri: str
    :param obj: FOS API object
    :type obj: dict
    :param wobj: The brcddb class object we were working when the error occured
    :type wobj: brcddb.classes.project.ProjectObj, brcddb.classes.chassis.ChassisObj, brcddb.classes.switch.SwitchObj,\
        None
    """
    if not pyfos_auth.is_error(obj):
        return
    ip_addr = brcdapi_util.mask_ip_addr(session.get('ip_addr'))
    p1 = pyfos_auth.formatted_error_msg(obj)
    brcdapi_log.log(ip_addr + " Request FAILED:\n" + p1, True)
    if wobj is None:
        return
    proj_obj = wobj.r_project_obj()
    proj_obj.s_api_error_flag()
    error_table = dict(
        ProjectObj=dict(
            p0=ip_addr,
            al_num=al.ALERT_NUM.PROJ_FAILED_LOGIN if '/rest/login' in uri else al.ALERT_NUM.PROJ_CHASSIS_API_ERROR
        ),
        ChassisObj=dict(p0=brcddb_chassis.best_chassis_name(wobj), al_num=al.ALERT_NUM.PROJ_CHASSIS_API_ERROR),
        SwitchObj=dict(p0=brcddb_switch.best_switch_name(wobj), al_num=al.ALERT_NUM.PROJ_SWITCH_API_ERROR)
    )
    simple_type = brcddb_class_util.get_simple_class_type(wobj)
    if simple_type in error_table:
        p0 = error_table[simple_type]['p0']
        al_num = error_table[simple_type]['al_num']
    else:
        brcdapi_log.exception('Unknown object type: ' + str(type(wobj)))
        return
    proj_obj.s_add_alert(al.AlertTable.alertTbl, al_num, None, p0, p1)
Example #8
0
def _get_input():
    """Retrieves the command line input, reads the input Workbook, and validates the input

    :return ec: Error code from brcddb.brcddb_common
    :rtype ec: int
    :return sl: List of switches to poll as read from the input Workbook
    :rtype sl: list
    :return pl: List of project files to combine
    :rtype pl: list
    :return cfg_name: Name of zone configuration file to create
    :rtype cfg_name: str, None
    :return a_cfg: Activation flag. If True, activate the zone configuration specified by cfg_name
    :rtype a_cfg: bool
    :return t_flag: Test flag. If True, test only. Do not make any changes
    :rtype t_flag: bool
    :return scan_flag: Scan flag. If True, scan files and switches for fabric information
    :rtype scan_flag: bool
    :return addl_parms: Additional parameters (logging and debug flags) to pass to multi_capture.py
    :rtype addl_parms: list
    """
    global _DEBUG, __version__

    # Initialize the return variables
    ec = brcddb_common.EXIT_STATUS_OK
    addl_parms = list()

    # Get and validate the user input
    ip, user_id, pw, sec, fid, cfile, wwn, a_flag, scan_flag, d_flag, s_flag, log, nl = parse_args(
    )
    if s_flag:
        addl_parms.append('-sup')
        brcdapi_log.set_suppress_all()
    if nl:
        addl_parms.append('-nl')
    else:
        brcdapi_log.open_log(log)
    if log is not None:
        addl_parms.extend(['-log', log])
    if d_flag:
        addl_parms.append('-d')
        brcdapi_rest.verbose_debug = True
    buf = ''
    if isinstance(fid, int):
        buf = ' INVALID. Must be an integer in the range of 1-128' if fid < 0 or fid > 128 else ''
    ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list()
    ml.append('zone_merge.py version: ' + __version__)
    ml.append('IP address:            ' + brcdapi_util.mask_ip_addr(ip))
    ml.append('ID:                    ' + str(user_id))
    ml.append('HTTPS:                 ' + str(sec))
    ml.append('FID:                   ' + str(fid) + buf)
    ml.append('Input file:            ' + cfile)
    ml.append('WWN:                   ' + str(wwn))
    ml.append('Activate zone cfg:     ' + str(a_flag))
    ml.append('Scan:                  ' + str(scan_flag))
    brcdapi_log.log(ml, True)
    if len(buf) > 0:
        return brcddb_common.EXIT_STATUS_INPUT_ERROR
    if sec is None:
        sec = 'none'
    ml = list()
    if not scan_flag:
        if ip is None:
            ml.append('  IP address (-ip)')
        if user_id is None:
            ml.append('  User ID (-id)')
        if pw is None:
            ml.append('  Password (-pw)')
        if fid is None:
            ml.append('  FID (-fid)')
        if len(buf) > 0:
            ml.append('  FID ' + buf)
        if wwn is None:
            ml.append('  Fabric WWN (-wwn)')
        if len(ml) > 0:
            ml.insert(0, 'Missing the following required parameters:')
            ml.append('Use the -h option for additional help.')
            brcdapi_log.log(ml, True)
            ec = brcddb_common.EXIT_STATUS_INPUT_ERROR

    return ec, ip, user_id, pw, sec, scan_flag, fid, cfile, wwn, a_flag, scan_flag, addl_parms
def _get_input():
    """Parses the module load command line, performs basic parameter validation checks, and sets up the log file.

    :return ip_addr: IP address of switch
    :rtype ip_addr: str
    :return user_id: User login ID
    :rtype user_id: str
    :return pw: Login password
    :rtype pw: str
    :return sec: 'self' for self signed certificate (HTTPS) or 'none' (HTTP)
    :rtype sec: str
    """
    global _DEBUG_ip, _DEBUG_id, _DEBUG_pw, _DEBUG_s, _DEBUG_d, _DEBUG_log, _DEBUG_nl

    if _DEBUG:
        args_ip, args_id, args_pw, args_s, args_d, args_log, args_nl = \
            _DEBUG_ip, _DEBUG_id, _DEBUG_pw, _DEBUG_s, _DEBUG_d, _DEBUG_log, _DEBUG_nl
    else:
        buf = 'Displays the results from GET running/brocade-security/security-certificate. In addition to security '\
              'certificates, this URL also returns CSRs. Usually, this done to validate certificates so the CSRs '\
              'would be filtered out or ignored.'
        parser = argparse.ArgumentParser(description=buf)
        parser.add_argument('-ip', help='(Required) IP address', required=True)
        parser.add_argument('-id', help='(Required) User ID', required=True)
        parser.add_argument('-pw', help='(Required) Password', required=True)
        parser.add_argument(
            '-s',
            help="(Optional) Default is HTTP. Use self for HTTPS mode.",
            required=False)
        buf = '(Optional) Enable debug logging. Prints the formatted data structures (pprint) to the log and console.'
        parser.add_argument('-d',
                            help=buf,
                            action='store_true',
                            required=False)
        buf = '(Optional) Directory where log file is to be created. Default is to use the current directory. The log' \
              ' file name will always be "Log_xxxx" where xxxx is a time and date stamp.'
        parser.add_argument(
            '-log',
            help=buf,
            required=False,
        )
        buf = '(Optional) No parameters. When set, a log file is not created. The default is to create a log file.'
        parser.add_argument('-nl',
                            help=buf,
                            action='store_true',
                            required=False)

        args = parser.parse_args()
        args_ip, args_id, args_pw, args_s, args_d, args_log, args_nl = \
            args.ip, args.id, args.pw, args.s, args.d, args.log, args.nl

    # Set up the log file
    if not args_nl:
        brcdapi_log.open_log(args_log)
    if args_d:  # Verbose debug
        brcdapi_rest.verbose_debug = True

    # Condition the input
    if args_s is None:
        args_s = 'none'

    # User feedback about input.
    ml = ['WARNING: Debug mode is enabled'] if _DEBUG else list()
    ml.extend([
        'IP, -ip:                   ' +
        brcdapi_util.mask_ip_addr(args_ip, True),
        'ID, -id:                   ' + args_id,
        'Security, -sec:            ' + args_s, ''
    ])
    brcdapi_log.log(ml, True)

    return args_ip, args_id, args_pw, args_s
def _get_input():
    """Parses the module load command line

    :return ec: Error code. 0: OK, -1: Errors encountered
    :rtype ec: int
    :return ip: Switch IP address
    :rtype ip: str
    :return id: User ID
    :rtype id: str
    :return pw: User password
    :rtype ip: str
    :return sec: Secure method. None for HTTP, otherwise the certificate or 'self' if self signed
    :rtype sec: str, None
    :return content: Content for "running/brocade-chassis/management-interface-configuration".
    :rtype content: dict
    """
    global _DEBUG_ip, _DEBUG_id, _DEBUG_pw, _DEBUG_s, _DEBUG_r, _DEBUG_rest_en, _DEBUG_rest_dis
    global _DEBUG_https_en, _DEBUG_https_dis, _DEBUG_max_rest, _DEBUG_ka_en, _DEBUG_ka_en
    global _DEBUG_d, _DEBUG_log, _DEBUG_nl

    ec = 0

    if _DEBUG:
        args_ip, args_id, args_pw, args_s = _DEBUG_ip, _DEBUG_id, _DEBUG_pw, 'none' if _DEBUG_s is None else _DEBUG_s
        args_rest_en, args_rest_dis, args_https_en, args_https_dis = \
            _DEBUG_rest_en, _DEBUG_rest_dis, _DEBUG_https_en, _DEBUG_https_dis
        args_max_rest, args_ka_en, args_ka_dis = \
            _DEBUG_max_rest, _DEBUG_ka_en, _DEBUG_ka_dis
        args_d, args_log, args_nl = _DEBUG_d, _DEBUG_log, _DEBUG_nl
    else:
        buf = 'Useful as a programming example only on how to read and make chassis configuration changes via the '\
              '"running/brocade-chassis/management-interface-configuration" URI. If the only input is the login '\
              'credentials, the parameters are displayed and no other action taken.'
        parser = argparse.ArgumentParser(description=buf)
        parser.add_argument('-ip', help='(Required) IP address', required=True)
        parser.add_argument('-id', help='(Required) User ID', required=True)
        parser.add_argument('-pw', help='(Required) Password', required=True)
        parser.add_argument(
            '-s',
            help='(Optional) Default is HTTP. CA or "self" for HTTPS mode.',
            required=False)
        parser.add_argument(
            '-rest_en',
            help='(Optional) No parameters. Enables the Rest interface',
            action='store_true',
            required=False)
        parser.add_argument(
            '-rest_dis',
            help='(Optional) No parameters. Disables the Rest interface',
            action='store_true',
            required=False)
        parser.add_argument('-https_en',
                            help='(Optional) No parameters. Enable HTTPS',
                            action='store_true',
                            required=False)
        parser.add_argument('-https_dis',
                            help='(Optional) No parameters. Disable HTTPS',
                            action='store_true',
                            required=False)
        parser.add_argument(
            '-max_rest',
            help=
            '(Optional) Set the maximum number of REST sessions. Valid options are 1-10',
            required=False)
        parser.add_argument('-ka_en',
                            help='(Optional) No parameters. Enable keep-alive',
                            action='store_true',
                            required=False)
        parser.add_argument('-ka_dis',
                            help='(Optional) No parameters. Enable keep-alive',
                            action='store_true',
                            required=False)
        buf = '(Optional) Enable debug logging. Prints the formatted data structures (pprint) to the log and console.'
        parser.add_argument('-d',
                            help=buf,
                            action='store_true',
                            required=False)
        buf = '(Optional) Directory where log file is to be created. Default is to use the current directory. The log' \
              ' file name will always be "Log_xxxx" where xxxx is a time and date stamp.'
        parser.add_argument(
            '-log',
            help=buf,
            required=False,
        )
        buf = '(Optional) No parameters. When set, a log file is not created. The default is to create a log file.'
        parser.add_argument('-nl',
                            help=buf,
                            action='store_true',
                            required=False)

        args = parser.parse_args()
        args_ip, args_id, args_pw, args_s = args.ip, args.id, args.pw, 'none' if args.s is None else args.s
        args_rest_en, args_rest_dis, args_https_en, args_https_dis = \
            args.rest_en, args.rest_dis, args.https_en, args.https_dis
        args_max_rest, args_ka_en, args_ka_dis = args.max_rest, args.ka_en, args.ka_dis
        args_d, args_log, args_nl = args.d, args.log, args.nl

    # Set up the log file
    if not args_nl:
        brcdapi_log.open_log(args_log)
    if args_d:  # Verbose debug
        brcdapi_rest.verbose_debug = True

    rd = {
        'rest-enabled':
        True if args_rest_en else False if args_rest_dis else None,
        'https-protocol-enabled':
        True if args_https_en else False if args_https_dis else None,
        'max-rest-sessions':
        args_max_rest,
        'https-keep-alive-enabled':
        True if args_ka_en else False if args_ka_dis else None
    }

    # User feedback
    ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list()
    ml.append('IP, -ip:                      ' +
              brcdapi_util.mask_ip_addr(args_ip, True))
    ml.append('ID, -id:                      ' + args_id)
    ml.append('Security, -s:                 ' + args_s)
    ml.append('Enable Rest, -rest_en:        ' + str(args_rest_en))
    ml.append('Disable Rest, -rest_dis:      ' + str(args_rest_dis))
    ml.append('Enable HTTPS, -https_en:      ' + str(args_https_en))
    ml.append('Disable HTTPS, -https_en:     ' + str(args_https_dis))
    ml.append('Enable keep-alive, -ka_en:    ' + str(args_ka_en))
    ml.append('Disable keep-alive, -ka_dis:  ' + str(args_ka_dis))
    ml.append('Max Rest sessions, -max_rest: ' + str(args_max_rest))

    # Validate the input and set up the return dictionary
    if args_rest_en and args_rest_dis:
        ml.append('-rest_en and -rest_dis are mutually exclusive.')
        ec = -1
    if args_https_en and args_https_dis:
        ml.append('-https_en and -https_dis are mutually exclusive.')
        ec = -1
    if args_ka_en and args_ka_dis:
        ml.append('-ka_en and -ka_dis are mutually exclusive.')
        ec = -1
    if len(rd) == 0:
        ml.extend(['', 'No changes'])
    brcdapi_log.log(ml, True)

    return ec, args_ip, args_id, args_pw, args_s, rd
Example #11
0
def pseudo_main():
    """Basically the main().

    :return: Exit code
    :rtype: int
    """
    global _DEBUG

    # Get and validate command line input.
    ec = brcddb_common.EXIT_STATUS_OK
    ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list()
    ip, user_id, pw, sec, file, force, s_flag, echo, vd, 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'
    file = brcdapi_file.full_file_name(file, '.xlsx')
    if ip is not None:
        if user_id is None:
            ml.append('Missing user ID, -id')
            ec = brcddb_common.EXIT_STATUS_INPUT_ERROR
        if pw is None:
            ml.append('Missing password, -pw')
            ec = brcddb_common.EXIT_STATUS_INPUT_ERROR
    ml.append('File:       ' + file)
    ml.append(
        'IP address: ' +
        brcdapi_util.mask_ip_addr(ip) if isinstance(ip, str) else str(ip))
    ml.append('ID:         ' + str(user_id))
    ml.append('sec:        ' + sec)
    if len(ml) > 0:
        brcdapi_log.log(ml, True)
    if ec != brcddb_common.EXIT_STATUS_OK:
        return ec
    echo = False if echo is None else echo

    # Read in the Workbook, generate the portaddress --bind commands, and configure the switch(es)
    switch_d_list = [
        switch_d for switch_d in report_utils.parse_switch_file(file).values()
    ]
    session = proj_obj = None

    try:
        for switch_d in switch_d_list:
            switch_d.update(err_msgs=list())

            # Create the bind commands
            if switch_d['bind']:
                _bind_commands(switch_d)
                cli_l = switch_d['bind_commands'].copy()
                i = 0
                while i < len(cli_l):
                    cli_l.insert(i, '')
                    i += 16
                cli_l.insert(
                    0, '\n# Bind commands for FID ' + str(switch_d['fid']))
                cli_l.append('\n# End bind commands for FID ' +
                             str(switch_d['fid']))
                brcdapi_log.log(cli_l, True)

            # Create the logical switch
            if ip is not None and switch_d['switch_flag']:

                if session is None:  # Login
                    session = api_int.login(user_id, pw, ip, sec, proj_obj)
                    if fos_auth.is_error(session):
                        return brcddb_common.EXIT_STATUS_API_ERROR

                if proj_obj is None:  # Create a project object
                    proj_obj = brcddb_project.new(
                        'Create_LS',
                        datetime.datetime.now().strftime('%d %b %Y %H:%M:%S'))
                    proj_obj.s_python_version(sys.version)
                    proj_obj.s_description('Creating logical switches from ' +
                                           os.path.basename(__file__))

                api_int.get_batch(session, proj_obj, _basic_capture_kpi_l,
                                  None)
                if proj_obj.r_is_any_error():
                    switch_d['err_msgs'].append(
                        'Error reading logical switch information from chassis'
                    )
                    brcdapi_log.log(
                        switch_d['err_msgs'][len(switch_d['err_msgs']) - 1],
                        True)
                else:
                    ec = _configure_switch(user_id, pw, session, proj_obj,
                                           switch_d, force, echo)

    except BaseException as e:
        switch_d['err_msgs'].append(
            'Programming error encountered. Exception: ' + str(e))
        brcdapi_log.log(switch_d['err_msgs'][len(switch_d['err_msgs']) - 1],
                        True)
        ec = brcddb_common.EXIT_STATUS_ERROR

    # Logout and create and print a summary report
    if session is not None:
        obj = brcdapi_rest.logout(session)
        if fos_auth.is_error(obj):
            brcdapi_log.log(fos_auth.formatted_error_msg(obj), True)
            ec = brcddb_common.EXIT_STATUS_API_ERROR
    if ip is not None:
        _print_summary(switch_d_list)

    return ec
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
    """
    # Get and validate the input parameters. Add all input arguments to the log
    ip, user_id, pw, sec, cli_file, fid, t_flag, f_flag, b_flag, s_flag, vd, log, nl = parse_args(
    )
    if not nl:
        brcdapi_log.open_log(log)
    if vd:
        brcdapi_rest.verbose_debug = True
    content = {
        'fid': fid,
        'ip-addr': ip,
        'id': user_id,
        'pw': pw,
        'sec': sec,
        'force': False if f_flag is None else f_flag,
        'test': False if t_flag is None else t_flag,
        'bulk': False if b_flag is None else b_flag,
    }

    if s_flag:
        brcdapi_log.set_suppress_all()
    ml = list()
    if _DEBUG:
        ml.append('WARNING!!! Debug is enabled')
    ml.append('IP:          ' + brcdapi_util.mask_ip_addr(ip, True))
    ml.append('ID:          ' + user_id)
    ml.append('CLI file:    ' + cli_file)
    ml.append('FID:         ' + str(fid))
    ml.append('Test flag:   ' + str(t_flag))
    ml.append('Force flag:  ' + str(f_flag))
    ml.append('Bulk flag:   ' + str(b_flag))
    brcdapi_log.log(ml, True)

    # Read in the CLI file, condition the input strings and send it
    ml = list()
    try:
        file_contents = brcdapi_file.read_file(cli_file)
    except FileNotFoundError:
        ml.extend([
            '', 'File ' + cli_file +
            ' not found. Did you remember the file extension?'
        ])
    except PermissionError:
        ml.extend(['', 'You do not have permission to read ' + cli_file])
    if len(ml) > 0:
        brcdapi_log.log(ml, True)
        return brcddb_common.EXIT_STATUS_INPUT_ERROR

    content.update(changes=brcddb_util.parse_cli(file_contents))
    if t_flag:
        content.update(test=True)
    response = brcddb_zone.send_zoning(content)

    # General information
    ec = brcddb_common.EXIT_STATUS_OK
    total_changes = total_failures = total_io = i = 0
    for obj in response:
        if isinstance(
                obj, dict
        ):  # obj is None for blank or commented our lines in the input
            if obj.get('changed'):
                total_changes += 1
            if obj.get('fail'):
                total_failures += 1
                brcdapi_log.log(_format_fault(obj, i, file_contents), True)
                ec = brcddb_common.EXIT_STATUS_ERROR
            if obj.get('io'):
                total_io += 1
        i += 1
    ml = [
        '', 'Summary:', 'Total Changes  : ' + str(total_changes),
        'Total Failures : ' + str(total_failures),
        'Total I/O      : ' + str(total_io)
    ]
    brcdapi_log.log(ml, True)

    return ec
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, _DEFAULT_POLL_INTERVAL, _DEFAULT_MAX_SAMPLE, _proj_obj, _session, _out_f, _switch_obj
    global _base_switch_obj, __version__, _uris, _uris_2

    signal.signal(signal.SIGINT, _signal_handler)

    # Get user input
    ip, user_id, pw, sec, fid, pct, max_p, _out_f = _get_input()
    default_text = ' (default)'
    ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list()
    ml.append(os.path.basename(__file__) + ' version: ' + __version__)
    ml.append('IP Address:    ' + brcdapi_util.mask_ip_addr(ip))
    ml.append('User ID:       ' + user_id)
    ml.append('FID:           ' + str(fid))
    if max_p is None:
        max_p = _DEFAULT_MAX_SAMPLE
        ml.append('Samples:       ' + str(max_p) + default_text)
    else:
        ml.append('Samples:       ' + str(max_p))
    if pct is None:
        pct = _DEFAULT_POLL_INTERVAL
        ml.append('Poll Interval: ' + str(pct) + default_text)
    else:
        ml.append('Poll Interval: ' + str(pct) + ' (defaulting to ' +
                  str(_MIN_POLL) + ')' if pct < _MIN_POLL else '')
    ml.append('Output File:   ' + _out_f)
    brcdapi_log.log(ml, True)

    # Create project
    _proj_obj = brcddb_project.new(
        'Port_Stats',
        datetime.datetime.now().strftime('%d %b %Y %H:%M:%S'))
    _proj_obj.s_python_version(sys.version)
    _proj_obj.s_description('Port statistics')

    # Login
    _session = brcddb_int.login(user_id, pw, ip, sec, _proj_obj)
    if fos_auth.is_error(_session):
        brcdapi_log.log(fos_auth.formatted_error_msg(_session), True)
        return brcddb_common.EXIT_STATUS_ERROR

    try:  # I always put all code after login in a try/except in case of a code bug or network error, I still logout
        # Capture the initial switch and port information along with the first set of statistics.
        brcdapi_log.log('Capturing initial data', True)
        brcddb_int.get_batch(_session, _proj_obj, _uris,
                             fid)  # Captured data is put in _proj_obj
        chassis_obj = _proj_obj.r_chassis_obj(_session.get('chassis_wwn'))
        if chassis_obj.r_is_vf_enabled():
            if fid is None:
                fid = 128
            _base_switch_obj = chassis_obj.r_switch_obj_for_fid(fid)
        else:
            _base_switch_obj = chassis_obj.r_switch_objects()[0]
        if _base_switch_obj is None:
            brcdapi_log.log('Switch for FID ' + str(fid) + ' not found. ',
                            True)
            return _wrap_up(brcddb_common.EXIT_STATUS_ERROR)
        base_switch_wwn = _base_switch_obj.r_obj_key()
        if _base_switch_obj.r_fabric_key() is None:
            _base_switch_obj.s_fabric_key(
                base_switch_wwn
            )  # Fake out a fabric principal if we don't have one
            _proj_obj.s_add_fabric(base_switch_wwn)
        brcddb_int.get_batch(_session, _proj_obj, _uris_2,
                             fid)  # Captured data is put in _proj_obj
        time.sleep(
            5
        )  # Somewhat arbitrary time. Don't want a throttling delay if the poll interval is very short

        # Get the first sample
        stats_buf = 'brocade-interface/fibrechannel-statistics'
        last_time = time.time()
        last_stats = brcddb_int.get_rest(_session, stats_buf, _base_switch_obj,
                                         fid)
        for p in last_stats.get('fibrechannel-statistics'):
            _base_switch_obj.r_port_obj(p.get('name')).s_new_key(
                'fibrechannel-statistics', p)

        # Now start collecting the port and interface statistics
        for i in range(0, max_p):
            x = pct - (time.time() - last_time)
            time.sleep(_MIN_POLL if x < _MIN_POLL else x)
            switch_obj = _proj_obj.s_add_switch(base_switch_wwn + '-' + str(i))
            last_time = time.time()
            obj = brcddb_int.get_rest(_session,
                                      'brocade-interface/fibrechannel',
                                      switch_obj, fid)
            if not fos_auth.is_error(obj):
                for p in obj.get('fibrechannel'):
                    switch_obj.s_add_port(p.get('name')).s_new_key(
                        'fibrechannel', p)
                obj = brcddb_int.get_rest(_session, stats_buf, switch_obj, fid)
            if fos_auth.is_error(
                    obj
            ):  # We typically get here when the login times out or network fails.
                brcdapi_log.log(
                    'Error encountered. Data collection limited to ' + str(i) +
                    ' samples.', True)
                _wrap_up(brcddb_common.EXIT_STATUS_ERROR)
                return brcddb_common.EXIT_STATUS_ERROR
            obj = brcddb_int.get_rest(_session, stats_buf, switch_obj, fid)
            if fos_auth.is_error(
                    obj
            ):  # We typically get here when the login times out or network fails.
                brcdapi_log.log(
                    'Error encountered. Data collection limited to ' + str(i) +
                    ' samples.', True)
                _wrap_up(brcddb_common.EXIT_STATUS_ERROR)
                return brcddb_common.EXIT_STATUS_ERROR

            for p in _stats_diff(last_stats,
                                 obj).get('fibrechannel-statistics'):
                switch_obj.s_add_port(p.get('name')).s_new_key(
                    'fibrechannel-statistics', p)
            _switch_obj.append(switch_obj)
            last_stats = obj

        return _wrap_up(brcddb_common.EXIT_STATUS_OK)

    except BaseException as e:
        brcdapi_log.log([
            'Error capturing statistics. ' + _EXCEPTION_MSG,
            'Exception: ' + str(e)
        ], True)
        return _wrap_up(brcddb_common.EXIT_STATUS_ERROR)
def _get_project(sl, pl, addl_parms):
    """Reads or captures project data

    :param sl: List of switches to poll via the API
    :type sl: list
    :param pl: List of project files to combine
    :type pl: list
    :param addl_parms: Additional parameters (debug and logging) to be passed to capture.py.
    :type addl_parms: list
    :return rl: List of error messages
    :rtype: list
    :return proj_obj: Project object. None if there was an error obtaining the project object
    :rtype proj_obj: brcddb.classes.project.ProjObj, None
    """
    global _ZONE_KPI_FILE

    rl = list()  # Error messages

    # Create project
    proj_obj = brcddb_project.new(
        'zone_merge',
        datetime.datetime.now().strftime('%d %b %Y %H:%M:%S'))
    proj_obj.s_python_version(sys.version)
    proj_obj.s_description('Zone merge')

    # Get a unique folder name for multi_capture.py and combine.py
    folder_l = [f for f in os.listdir('.') if not isfile(f)]
    base_folder = '_zone_merge_work_folder_'
    i = 0
    work_folder = base_folder + str(i)
    while work_folder in folder_l:
        i += 1
        work_folder = base_folder + str(i)
    os.mkdir(work_folder)

    # Add the KPI file for the captures
    zone_kpi_file = work_folder + '/' + _ZONE_KPI_FILE
    f = open(zone_kpi_file, 'w')
    f.write('\n'.join(_kpis_for_capture) + '\n')
    f.close()

    # Start all the data captures for the switches to be polled so that multiple switches can be captured in parallel
    if len(sl) > 0:
        brcdapi_log.log('Collecting zoning data from switches', True)
    captured_d = dict()
    pid_l = list()
    for sub_d in sl:
        ip_addr = sub_d['ip']
        file_name = work_folder + '/switch_' + ip_addr.split(
            '.').pop() + '_' + str(len(pid_l))
        sub_d.update(file=file_name)
        file_name = brcdapi_file.full_file_name(file_name, '.json')
        d = captured_d.get(ip_addr)
        if d is None:
            sub_d_l = list()
            captured_d.update({ip_addr: dict(sub_d_l=sub_d_l, file=file_name)})
            params = [
                'python.exe', 'capture.py', '-ip', ip_addr, '-id', sub_d['id'],
                '-pw', sub_d['pw'], '-s', 'none' if sub_d['sec'] is None else
                sub_d['sec'], '-f', file_name, '-c', zone_kpi_file
            ] + addl_parms
            pid_l.append(
                dict(p=subprocess.Popen(params),
                     file_name=file_name,
                     ip=ip_addr))
        sub_d_l.append(sub_d)

    # Add the data read from this chassis to the project object
    for pid_d in pid_l:  # Wait for all captures to complete before continuing
        pid_d.update(s=pid_d['p'].wait())
        brcdapi_log.log(
            'Completed capture for ' + pid_d['file_name'] +
            '. Ending status: ' + str(pid_d['s']), True)
    for pid_d in pid_l:
        obj = brcdapi_file.read_dump(pid_d['file_name'])
        if obj is None:
            rl.append('Capture for ' + file_name + '. failed.')
        else:
            brcddb_copy.plain_copy_to_brcddb(obj, proj_obj)
            captured_d[pid_d['ip']].update(fab_keys=obj['_fabric_objs'].keys())
    if len(rl) > 0:
        return rl, proj_obj

    # Figure out the fabric WWN for all the FIDs for the polled switches
    for d in captured_d.values():
        fab_obj_l = [proj_obj.r_fabric_obj(k) for k in d['fab_keys']]
        for fab_obj in fab_obj_l:
            if fab_obj.r_get(
                    'zone_merge'
            ) is None:  # I can't think of a reason why it wouldn't be None
                fab_obj.s_new_key('zone_merge', dict(file=d['file']))
        for sub_d in d['sub_d_l']:
            found = False
            fid = sub_d['fid']
            if isinstance(
                    fid, int
            ):  # If the user is just running a scan, there won't be a fid
                for fab_obj in fab_obj_l:
                    if fid in brcddb_fabric.fab_fids(fab_obj):
                        s_buf = 'none' if sub_d['sec'] is None else sub_d['sec']
                        zm_d = fab_obj.r_get('zone_merge')
                        zm_d.update(fab_wwn=fab_obj.r_obj_key(),
                                    update=sub_d['update'],
                                    cfg=sub_d['cfg'],
                                    fid=sub_d['fid'],
                                    ip=sub_d['ip'],
                                    id=sub_d['id'],
                                    pw=sub_d['pw'],
                                    sec=s_buf)
                        fab_obj.s_new_key('zone_merge', zm_d)
                        found = True
                        break
                if not found:
                    rl.append('Could not find FID ' + str(fid) + ' in ' +
                              brcdapi_util.mask_ip_addr(sub_d['ip']))

    # Add in all the read in project files
    if len(pl) > 0:
        brcdapi_log.log('Reading project files', True)
    for sub_d in pl:
        file_name = brcdapi_file.full_file_name(sub_d['project_file'], '.json')
        obj = brcdapi_file.read_dump(file_name)
        brcddb_copy.plain_copy_to_brcddb(obj, proj_obj)
        for fab_obj in [
                proj_obj.r_fabric_obj(k) for k in obj['_fabric_objs'].keys()
        ]:
            if fab_obj.r_get(
                    'zone_merge'
            ) is None:  # It should be None. This is just future proofing.
                fab_obj.s_new_key('zone_merge', dict(file=file_name))
        fab_obj = proj_obj.r_fabric_obj(sub_d.get('fab_wwn'))
        if fab_obj is None:
            rl.append('Could not find fabric WWN ' +
                      str(sub_d.get('fab_wwn')) + ' in ' + file_name)
        else:
            fab_obj.r_get('zone_merge').update(fab_wwn=fab_obj.r_obj_key(),
                                               update=False,
                                               cfg=sub_d['cfg'])

    return rl, proj_obj