def _merge_zones(change_d, base_fab_obj, add_fab_obj):
    """Merges the zones from two fabrics

    :param change_d: Dictionary of alias changes as returned from brcddb.util.compare.compare()
    :type change_d: dict
    :param base_fab_obj: brcddb fabric object for the fabric we are adding the zones from add_fab_obj to
    :type base_fab_obj: brcddb.classes.fabric.FabricObj
    :param add_fab_obj: brcddb fabric object with the zones to be added to base_fab_obj
    :type add_fab_obj: brcddb.classes.fabric.FabricObj
    :return: Error message list. If empty, no errors encountered
    :rtype: list
    """
    # Basic prep
    rl = list()
    if change_d is None:
        return rl
    base_fab_name = brcddb_fabric.best_fab_name(base_fab_obj, True)
    add_fab_name = brcddb_fabric.best_fab_name(add_fab_obj, True)

    # Add what needs to be added or report differences
    for zone, change_obj in change_d.items():
        change_type = change_obj.get('r')
        if change_type is None or change_type == 'Changed':  # This is a simple pass/fail. No need to look further
            rl.append('Zone ' + zone + ' in ' + base_fab_name +
                      ' does not match the same zone in ' + add_fab_name)
        elif change_type == 'Added':
            add_obj = add_fab_obj.r_zone_obj(zone)
            base_fab_obj.s_add_zone(zone, add_obj.r_type(),
                                    add_obj.r_members(), add_obj.r_pmembers())

    return rl
Ejemplo n.º 2
0
def _project_page(wb, sheet_index, b_proj_obj, c_proj_obj, c_obj):
    """Recursively iterates through a list of changes from compare.compare() for fabric. Create fabric pages as needed

    :param wb: Workbook object
    :type wb: dict
    :param sheet_index: Starting sheet index
    :type sheet_index: int
    :param b_proj_obj: Project object for base (project we are comparing against). Typically the older project.
    :type b_proj_obj: brcddb.classes.project.ProjectObj
    :param c_proj_obj: Comparison project object. Typically the newer project.
    :type c_proj_obj: brcddb.classes.project.ProjectObj
    :param c_obj: This is the object from compare.compare() that we are working on
    :type c_obj: dict
    :return sheet_index: Next sheet index
    :rtype sheet_index: int
    :return tbl_contents: Table of contents for the fabrics
    :rtype. tbl_contents: list
    """
    # Set up the table of contents and sheet headers
    content = [
        dict(font='hdr_1', align='wrap', disp='Project changes'),
        dict(),
        dict(font='hdr_2', align='wrap', disp='Fabrics Added:'),
    ]

    # Add fabric changes
    for obj in [d for d in c_obj['_fabric_objs'].values() if d['r'] == 'Added']:
        content.append(dict(font='std', align='wrap',
                            disp=brcddb_fabric.best_fab_name(c_proj_obj.r_fabric_obj(obj.get('c')), True)))
    content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Fabrics Removed:')])
    for obj in [d for d in c_obj['_fabric_objs'].values() if d['r'] == 'Removed']:
        content.append(dict(font='std', align='wrap',
                            disp=brcddb_fabric.best_fab_name(b_proj_obj.r_fabric_obj(obj.get('b')), True)))

    # Add switch changes
    content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Switches Added:')])
    for obj in [d for d in c_obj['_switch_objs'].values() if d['r'] == 'Added']:
        content.append(dict(font='std', align='wrap',
                            disp=brcddb_switch.best_switch_name(c_proj_obj.r_switch_obj(obj.get('c')), True)))
    content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Switches Removed:')])
    for obj in [d for d in c_obj['_switch_objs'].values() if d['r'] == 'Removed']:
        content.append(dict(font='std', align='wrap',
                            disp=brcddb_switch.best_switch_name(b_proj_obj.r_switch_obj(obj.get('b')), True)))

    # Add chassis changes
    content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Chassis Added:')])
    for obj in [d for d in c_obj['_chassis_objs'].values() if d['r'] == 'Added']:
        content.append(dict(font='std', align='wrap',
                            disp=brcddb_chassis.best_chassis_name(c_proj_obj.r_chassis_obj(obj.get('c')), True)))
    content.extend([dict(), dict(font='hdr_2', align='wrap', disp='Chassis Removed:')])
    for obj in [d for d in c_obj['_chassis_objs'].values() if d['r'] == 'Removed']:
        content.append(dict(font='std', align='wrap',
                            disp=brcddb_chassis.best_chassis_name(b_proj_obj.r_chassis_obj(obj.get('b')), True)))

    # Sheet name and title
    sname = 'Project_Changes_' + str(sheet_index)
    report_utils.title_page(wb, None, sname, sheet_index, 'Project Changes', content, 80)

    return sheet_index+1, [dict(s=sname, d='Project Changes')]
Ejemplo n.º 3
0
def _fabric_add_to_content(obj, b_obj, c_obj, content):
    """Same as _basic_add_to_content() but assumes the data are WWNs and converts them to fabric names"""
    start = len(content)
    if obj is not None:
        proj_obj = obj.r_project_obj()
        for k, v in obj.items():
            b_buf = brcddb_fabric.best_fab_name(proj_obj.r_fabric_obj(v.get('b')), True)
            c_buf = brcddb_fabric.best_fab_name(proj_obj.r_fabric_obj(v.get('c')), True)
            _content_append(dict(font='std', align='wrap', disp=('', b_buf, c_buf, v.get('r'))), content)
    if len(content) == start:
        content.append(dict(merge=4, font='std', align='wrap', disp=('No changes',)))
Ejemplo n.º 4
0
def _fabric_ts(o, k):
    """Returns the title of the sheet, which is also used in the report summary page, and the sheet name

    :param o: brcddb class object from which the key, k, is to be retrieved. So far, this has only been a project object
    :type o: brcddb.classes.project.ProjectObj
    :param k: The key for the object to retrieve from o
    :type k: key, str
    :return title: Sheet title
    :rtype title: str
    :return name: Sheet name
    :rtype name: str
    """
    obj = o.r_fabric_obj(k)
    return brcddb_fabric.best_fab_name(obj, True), brcddb_fabric.best_fab_name(obj, False)
Ejemplo n.º 5
0
def _scan_fabrics(proj_obj):
    """Scan the project for each fabric and list the fabric WWN, FID , and zone configurations

    :param proj_obj: Project object
    :type proj_obj: brcddb.classes.project.ProjectObj
    :return: Status code
    :rtype: int
    """

    ec = brcddb_common.EXIT_STATUS_OK

    # Prepare the fabric display
    ml = ['', 'Fabric Scan (* indicates the effective zone config)', '']
    for fab_obj in proj_obj.r_fabric_objects():
        eff_zonecfg = fab_obj.r_defined_eff_zonecfg_key()
        ml.append(brcddb_fabric.best_fab_name(fab_obj, wwn=True))
        ml.append(
            '  FID:         ' +
            ', '.join([str(fid) for fid in brcddb_fabric.fab_fids(fab_obj)]))
        for buf in fab_obj.r_zonecfg_keys():
            if isinstance(eff_zonecfg, str) and eff_zonecfg == buf:
                ml.append('  Zone Config: ' + '*' + buf)
            elif buf != '_effective_zone_cfg':
                ml.append('  Zone Config: ' + buf)
        ml.append('')

    # Wrap up and print fabric information
    if len(ml) == 0:
        ml.append('No fabrics specified.')
        ec = brcddb_common.EXIT_STATUS_INPUT_ERROR
    brcdapi_log.log(ml, True)

    return ec
def _scan_fabrics(proj_obj):
    """Scan the project for each fabric and list the fabric WWN, FID , and zone configurations

    :param proj_obj: Project object
    :type proj_obj: brcddb.classes.project.ProjectObj
    :return: List of fabric detail messages
    :rtype: list
    """

    # Prepare the fabric display
    ml = ['', 'Fabric Scan (* indicates the effective zone config)', '']
    for fab_obj in proj_obj.r_fabric_objects():
        eff_zonecfg = fab_obj.r_defined_eff_zonecfg_key()
        ml.append('From: ' + fab_obj.r_get('zone_merge/file'))
        ml.append(brcddb_fabric.best_fab_name(fab_obj, wwn=True))
        ml.append(
            '  FID:         ' +
            ', '.join([str(fid) for fid in brcddb_fabric.fab_fids(fab_obj)]))
        for buf in fab_obj.r_zonecfg_keys():
            if isinstance(eff_zonecfg, str) and eff_zonecfg == buf:
                ml.append('  Zone Config: ' + '*' + buf)
            elif buf != '_effective_zone_cfg':
                ml.append('  Zone Config: ' + buf)
        ml.append('')

    return ml
Ejemplo n.º 7
0
def dup_wwn(proj_obj):
    """Searches all fabrics in the project for duplicate WWNs.
    :param proj_obj: Project object
    :type proj_obj: ProjectObj
    :return: List of login objects for the duplicate WWNS. None entry seperates multiple duplicates
    :rtype: list
    """
    dup_login = list()
    if not _DUP_WWN_CHECK:
        return dup_login
    dup_wwn = list()
    for fabObj in proj_obj.r_fabric_objects():
        other_fab_list = proj_obj.r_fabric_objects()
        other_fab_list.remove(fabObj)

        for wwn in fabObj.r_login_keys():
            dup_login_len = len(dup_login)
            for fobj in other_fab_list:
                if fobj.r_login_obj(wwn) is not None:
                    if wwn not in dup_wwn:
                        dup_wwn.append(wwn)
                        proj_obj.s_add_alert(al.AlertTable.alertTbl,
                                             al.ALERT_NUM.PROJ_DUP_LOGIN, None,
                                             wwn)
                    login_obj = fobj.r_login_obj(wwn)
                    if login_obj not in dup_login:
                        dup_login.append(login_obj)
                        login_obj.s_add_alert(
                            al.AlertTable.alertTbl,
                            al.ALERT_NUM.LOGIN_DUP_LOGIN, None,
                            brcddb_fabric.best_fab_name(fabObj))
                    login_obj = fabObj.r_login_obj(wwn)
                    if login_obj not in dup_login:
                        dup_login.append(login_obj)
                        login_obj.s_add_alert(
                            al.AlertTable.alertTbl,
                            al.ALERT_NUM.LOGIN_DUP_LOGIN, None,
                            brcddb_fabric.best_fab_name(fobj))
            if len(dup_login) > dup_login_len:
                dup_login.append(None)

    return dup_login
Ejemplo n.º 8
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
    """
    global _DEBUG, __version__, _ZONE_CHECK

    # Get and validate user input
    inf, outf, sfp_rules, iocp, custom_parms = _get_input()
    ml = ['WARNING!!! Debug is enabled'] if _DEBUG else list()
    ml.append('report.py version ' + __version__)
    ml.append('In file:  ' + inf)
    ml.append('Out file: ' + outf)
    ml.append('SFP rules file: ' + str(sfp_rules))
    if sfp_rules is not None:
        ml.append("The 'User Warning: Data Validation ...' can be ignored.")
        brcddb_bp.sfp_rules = report_utils.parse_sfp_file(sfp_rules)
    ml.append('custom_parms:     ' + str(custom_parms))
    brcdapi_log.log(ml, True)

    # Get the project object
    try:
        proj_obj = brcddb_project.read_from(inf)
    except FileNotFoundError:
        brcdapi_log.log('Input file, ' + inf + ', not found', True)
        return brcddb_common.EXIT_STATUS_ERROR
    if proj_obj is None:
        return brcddb_common.EXIT_STATUS_ERROR

    # Perform all pre-processing (parse IOCPs, build references, ...)
    brcdapi_log.log('Building cross references', True)
    brcddb_project.build_xref(proj_obj)
    brcddb_project.add_custom_search_terms(proj_obj)
    brcdapi_log.log('Performing mainframe checks', True)
    for file in brcapi_file.read_directory(iocp):
        brcddb_iocp.parse_iocp(proj_obj, iocp + '/' + file)
    brcddb_bp.best_practice(al.AlertTable.alertTbl, proj_obj)
    if _ZONE_CHECK:
        for obj in proj_obj.r_fabric_objects(
        ):  # Get a zone analysis on all fabrics
            brcdapi_log.log(
                'Performing zone analysis for fabric ' +
                brcddb_fabric.best_fab_name(obj), True)
            brcddb_fabric.zone_analysis(obj)

    # Generate the report
    brcddb_report.report(proj_obj, outf)
    _custom_report(proj_obj, custom_parms)
    return brcddb_common.EXIT_STATUS_ERROR if proj_obj.r_is_any_error(
    ) else brcddb_common.EXIT_STATUS_OK
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
def bp_page(wb, tc, sheet_name, sheet_i, sheet_title, obj, display,
            display_tbl):
    """Creates a best practice violation worksheet for the Excel report.

    :param wb: Workbook object
    :type wb: class
    :param tc: Table of context page. A link to this page is place in cell A1
    :type tc: str, None
    :param sheet_name: Sheet (tab) name
    :type sheet_name: str
    :param sheet_i: Sheet index where page is to be placed.
    :type sheet_i: int
    :param sheet_title: Title to be displayed in large font, hdr_1, at the top of the sheet
    :type sheet_title: str
    :param obj: Project or fabric object.
    :type obj: brcddb.classes.project.ProjectObj, brcddb.classes.fabric.FabricObj
    :param display: List of parameters to display.
    :type display: list, tuple
    :param display_tbl: Display control table. See brcddb.report.report_tables.display_tbl
    :rtype: None
    """
    # Validate the user input
    err_msg = list()
    if obj is None:
        err_msg.append('obj was not defined.')
    elif not bool('ProjectObj' in str(type(obj))
                  or 'FabricObj' in str(type(obj))):
        err_msg.append('Invalid object type: ' + str(type(obj)) + '.')
    if display is None:
        err_msg.append('display not defined.')
    if len(err_msg) > 0:
        brcdapi_log.exception(err_msg, True)
        return

    # Create the worksheet, add the headers, and set up the column widths
    sheet = wb.create_sheet(index=sheet_i, title=sheet_name)
    sheet.page_setup.paperSize = sheet.PAPERSIZE_LETTER
    sheet.page_setup.orientation = sheet.ORIENTATION_LANDSCAPE
    col = 1
    row = 1
    if isinstance(tc, str):
        cell = xl.get_column_letter(col) + str(row)
        sheet[cell].hyperlink = '#' + tc + '!A1'
        sheet[cell].font = report_fonts.font_type('link')
        sheet[cell] = 'Contents'
        col += 1
    cell = xl.get_column_letter(col) + str(row)
    sheet[cell].font = report_fonts.font_type('hdr_1')
    sheet[cell] = sheet_title
    sheet.freeze_panes = sheet['A3']
    col = 1
    row += 1
    for k in display:
        if k in display_tbl and 'dc' in display_tbl[
                k] and display_tbl[k]['dc'] is True:
            continue
        cell = xl.get_column_letter(col) + str(row)
        sheet[cell].font = report_fonts.font_type('bold')
        sheet[cell].border = report_fonts.border_type('thin')
        if k in display_tbl:
            if 'c' in display_tbl[k]:
                sheet.column_dimensions[xl.get_column_letter(
                    col)].width = display_tbl[k]['c']
            try:
                if display_tbl[k]['v']:
                    sheet[cell].alignment = report_fonts.align_type(
                        'wrap_vert_center')
                else:
                    sheet[cell].alignment = report_fonts.align_type('wrap')
            except:
                sheet[cell].alignment = report_fonts.align_type('wrap')
            if 'd' in display_tbl[k]:
                sheet[cell] = display_tbl[k]['d']
            else:
                sheet[
                    cell] = k  # This happens when a new key is introduced before the display tables have been updated
        else:
            sheet[
                cell] = k  # This happens when a new key is introduced before the display tables have been updated
        col += 1

    # Get a list of fabric objects and initialize alert_list
    if 'ProjectObj' in str(type(obj)):
        fab_list = obj.r_fabric_objects()
        chassis_list = obj.r_chassis_objects()
        switch_list = obj.r_switch_objects()
    else:
        fab_list = [obj]
        chassis_list = obj.r_project_obj().r_chassis_objects()
        switch_list = obj.r_project_obj().r_switch_objects()
    alert_list = list()

    # Get all the chassis alerts
    for tobj in chassis_list:
        tl = list()
        for sev in (al.ALERT_SEV.ERROR,
                    al.ALERT_SEV.WARN):  # Display errors first
            tl.extend(
                _add_alerts(tobj, 'Chassis', sev,
                            brcddb_chassis.best_chassis_name(tobj), ''))
        if len(tl) > 0:
            alert_list.append([''])
            alert_list.append(
                ['Chassis: ' + brcddb_chassis.best_chassis_name(tobj)])
            alert_list.extend(tl)

    # Get all the fabric alerts
    for fab_obj in fab_list:
        tl = list()
        for sev in (al.ALERT_SEV.ERROR,
                    al.ALERT_SEV.WARN):  # Display errors first
            tl.extend(
                _add_alerts(fab_obj, 'Fabric', sev,
                            brcddb_fabric.best_fab_name(fab_obj), ''))
            for tobj in fab_obj.r_zonecfg_objects():
                tl.extend(
                    _add_alerts(tobj, 'ZoneCfg', sev, tobj.r_obj_key(), ''))
            for tobj in fab_obj.r_zone_objects():
                tl.extend(_add_alerts(tobj, 'Zone', sev, tobj.r_obj_key(), ''))
            for tobj in fab_obj.r_alias_objects():
                tl.extend(_add_alerts(tobj, 'Alias', sev, tobj.r_obj_key(),
                                      ''))
            for tobj in fab_obj.r_login_objects():
                tl.extend(_add_alerts(tobj, 'Login', sev, tobj.r_obj_key(),
                                      ''))
            for tobj in fab_obj.r_fdmi_node_objects():
                tl.extend(
                    _add_alerts(tobj, 'FDMI_Node', sev, tobj.r_obj_key(), ''))
            for tobj in fab_obj.r_fdmi_port_objects():
                tl.extend(
                    _add_alerts(tobj, 'FDMI_Port', sev, tobj.r_obj_key(), ''))
        if len(tl) > 0:
            alert_list.append([''])
            alert_list.append(
                ['Fabric: ' + brcddb_fabric.best_fab_name(fab_obj, True)])
            alert_list.extend(tl)

    # Get all the switch and port alerts
    for switch_obj in switch_list:
        tl = list()
        for sev in (al.ALERT_SEV.ERROR,
                    al.ALERT_SEV.WARN):  # Display errors first
            tl.extend(
                _add_alerts(switch_obj, 'Switch', sev,
                            brcddb_switch.best_switch_name(switch_obj), ''))
            for tobj in switch_obj.r_port_objects():
                tl.extend(
                    _add_alerts(tobj, 'Port', sev,
                                brcddb_port.best_port_name(tobj),
                                tobj.r_obj_key()))
        if len(tl) > 0:
            alert_list.append([''])
            alert_list.append([
                'Switch: ' + brcddb_switch.best_switch_name(switch_obj, True)
            ])
            alert_list.extend(tl)

    # Now add the alerts to the worksheet

    # Set up the cell formatting
    border = report_fonts.border_type('thin')
    alignment = report_fonts.align_type('wrap')
    font = report_fonts.font_type('std')

    # Add all alerts to the worksheet
    for x in alert_list:
        row += 1
        col = 1
        if len(x) == 0:
            row += 1
        elif len(x) == 1:
            sheet.merge_cells(start_row=row,
                              start_column=1,
                              end_row=row,
                              end_column=len(display))
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].font = report_fonts.font_type('hdr_2')
            if len(x[0]) > 0:
                sheet[cell].fill = report_fonts.fill_type('lightblue')
            sheet[cell] = x[0]
        else:
            for k in display:
                cell = xl.get_column_letter(col) + str(row)
                sheet[cell].border = border
                sheet[cell].font = font
                sheet[cell].alignment = alignment
                sheet[cell] = bp_case[k](x)
                col += 1
Ejemplo n.º 11
0
def performance_dashboard(wb, tc, sheet_name, sheet_i, sheet_title, content):
    """Creates a dashboard worksheet for the Excel report.

    :param wb: Workbook object
    :type wb: class
    :param tc: Table of context page. A link to this page is place in cell A1
    :type tc: str, None
    :param sheet_name: Sheet (tab) name
    :type sheet_name: str
    :param sheet_i: Sheet index where page is to be placed.
    :type sheet_i: int
    :param sheet_title: Title to be displayed in large font, hdr_1, at the top of the sheet
    :type sheet_title: str
    :param content: Caller defined content. List of lists or tuples to add to the title page. For example:
            dashboard = collections.OrderedDict()
            dashboard['class-3-discards'] =     {'title' : 'Top 10 C3 Discards', 'port_list' : []}
            dashboard['in-crc-errors'] =        {'title' : 'Top 10 CRC With Good EOF', 'port_list' : []}
    :type content: list, tuple
    :rtype: None
    """

    hdr = collections.OrderedDict()
    # Key is the column header and value is the width
    hdr['Count'] = 14
    hdr['Fabric'] = 22
    hdr['Switch'] = 22
    hdr['Port'] = 7
    hdr['Type'] = 8
    hdr['Description'] = 117 - (hdr['Count'] + hdr['Switch'] + hdr['Switch'] +
                                hdr['Port'] + hdr['Type'])

    # Create the worksheet, add the title, and set up the column widths
    sheet = wb.create_sheet(index=sheet_i, title=sheet_name)
    sheet.page_setup.paperSize = sheet.PAPERSIZE_LETTER
    sheet.page_setup.orientation = sheet.ORIENTATION_LANDSCAPE
    col = 1
    row = 1
    for k, v in hdr.items():
        sheet.column_dimensions[xl.get_column_letter(col)].width = v
        col += 1
    max_col = col - 1
    col = 1
    if isinstance(tc, str):
        cell = xl.get_column_letter(col) + str(row)
        sheet[cell].hyperlink = '#' + tc + '!A1'
        sheet[cell].font = report_fonts.font_type('link')
        sheet[cell] = 'Contents'
        col += 1
    cell = xl.get_column_letter(col) + str(row)
    sheet.merge_cells(start_row=row,
                      start_column=col,
                      end_row=row,
                      end_column=max_col)
    sheet[cell].font = report_fonts.font_type('hdr_1')
    sheet[cell] = sheet_title
    row += 2

    # Now add each dashboard item
    border = report_fonts.border_type('thin')
    font = report_fonts.font_type('std')
    alignment = report_fonts.align_type('wrap')
    for statistic in content.keys():
        db = content.get(statistic)
        col = 1

        # The individual dashboard title
        sheet.merge_cells(start_row=row,
                          start_column=1,
                          end_row=row,
                          end_column=max_col)
        for i in range(col, max_col + 1):
            cell = xl.get_column_letter(i) + str(row)
            sheet[cell].border = border
        cell = xl.get_column_letter(col) + str(row)
        sheet[cell].font = report_fonts.font_type('hdr_2')
        sheet[cell].fill = report_fonts.fill_type('lightblue')
        sheet[cell] = db.get('title')
        col = 1
        row += 1

        # Now the individual dashboard headers
        for k in hdr.keys():
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].border = border
            sheet[cell].font = report_fonts.font_type('bold')
            sheet[cell] = k
            col += 1

        # Now add the dashboard content
        port_list = db.get('port_list')
        if len(port_list) == 0:
            row += 1
        for port_obj in port_list:
            # Statistic
            col = 1
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].border = border
            sheet[cell].font = font
            sheet[cell].alignment = alignment
            sheet[cell] = port_obj.r_get('fibrechannel-statistics/' +
                                         statistic)
            col += 1

            # Fabric
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].border = border
            sheet[cell].font = font
            sheet[cell].alignment = alignment
            sheet[cell] = brcddb_fabric.best_fab_name(
                port_obj.r_switch_obj().r_fabric_obj())
            col += 1

            # Switch
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].border = border
            sheet[cell].font = font
            sheet[cell].alignment = alignment
            sheet[cell] = brcddb_switch.best_switch_name(
                port_obj.r_switch_obj())
            col += 1

            # Port
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].border = border
            sheet[cell].font = font
            sheet[cell].alignment = alignment
            sheet[cell] = port_obj.r_obj_key()
            col += 1

            # Port Type
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].border = border
            sheet[cell].font = font
            sheet[cell].alignment = alignment
            sheet[cell] = port_obj.c_login_type()
            col += 1

            # Description - Try FDMI first, then name server
            cell = xl.get_column_letter(col) + str(row)
            sheet[cell].border = border
            sheet[cell].font = font
            sheet[cell].alignment = alignment
            sheet[cell] = brcddb_port.port_best_desc(port_obj)
            row += 1
        row += 1
Ejemplo n.º 12
0
def _fabric_ts(o, k):
    obj = o.r_fabric_obj(k)
    return brcddb_fabric.best_fab_name(obj, True), brcddb_fabric.best_fab_name(
        obj, False)
Ejemplo n.º 13
0
def _fabric_name(p_obj, wwn, flag=True):
    return brcddb_fabric.best_fab_name(p_obj.r_fabric_obj(wwn), flag)
Ejemplo n.º 14
0
def report(proj_obj, outf, remove_pages=None, add_pages=None):
    """Creates an Excel report. Sort of a SAN Health like report.

    :param proj_obj: Project object
    :type proj_obj: brcddb.classes.project.ProjectObj
    :param outf: Output file name
    :type outf: str
    :param remove_pages: List of default pages to remove. Done first so you can clear all then add pages.
    :type remove_pages: None, str, list
    :param add_pages: Pages, in addition to the defaults, to add to the report
    :type add_pages: None, str, list
    """
    global _report_pages

    # Figure out what pages to include in the report
    for key in brcddb_util.convert_to_list(remove_pages):
        d = _report_pages.get(key)
        if d is None:
            if key == 'all':
                for obj in _report_pages.values():
                    obj['s'] = False
                break
            else:
                brcdapi_log.log(key +
                                ' is unkonwn in remove page list. ignored')
        else:
            d['s'] = False
    for key in brcddb_util.convert_to_list(add_pages):
        d = _report_pages.get(key)
        if d is None:
            if key == 'all':
                for obj in _report_pages.values():
                    obj['s'] = True
                break
            else:
                brcdapi_log.log(key + ' is unkonwn in add page list. ignored')
        else:
            d['s'] = True
    """port_pages is used to determine how to display pages
    +-------+-------------------------------------------------------------------------------+
    |  key  | Description                                                                   |
    +=======+===============================================================================+
    |   c   | Key in the _report_pages table                                                |
    +-------+-------------------------------------------------------------------------------+
    |   s   | Sheet name prefix                                                             |
    +-------+-------------------------------------------------------------------------------+
    |  sc   | Number of columns to skip                                                     |
    +-------+-------------------------------------------------------------------------------+
    |   t   | The table used to control how the port data is displayed.                     |
    +-------+-------------------------------------------------------------------------------+
    |   d   | Text to display as a header on the worksheet.                                 |
    +-------+-------------------------------------------------------------------------------+
    |   l   | When true, displays all the logins. Otherwise, just the base WWN is reported. |
    +-------+-------------------------------------------------------------------------------+
    """
    port_pages = [
        dict(c='port_config',
             sc=1,
             s='_config',
             t=rt.Port.port_config_tbl,
             d='Port Configurations',
             l=False),
        dict(c='port_config_error',
             sc=1,
             s='_config_error',
             t=rt.Port.port_config_tbl,
             d='Port Configurations Error Summary',
             l=False),
        dict(c='port_stats',
             sc=1,
             s='_stats',
             t=rt.Port.port_stats_tbl,
             d='Port Statistics',
             l=False),
        dict(c='port_stats_error',
             sc=1,
             s='_stats_error',
             t=rt.Port.port_stats_tbl,
             d='Port Statistics Error Summary',
             l=False),
        dict(c='port_zone',
             sc=1,
             s='_zl',
             t=rt.Port.port_zone_tbl,
             d='Ports by Zone and Login',
             l=True),
        dict(c='port_zone_error',
             sc=1,
             s='_zl_error',
             t=rt.Port.port_zone_tbl,
             d='Ports by Zone and Login Error Summary',
             l=True),
        dict(c='port_sfp',
             sc=1,
             s='_sfp',
             t=rt.Port.port_sfp_tbl,
             d='SFP report',
             l=False),
        dict(c='port_sfp_error',
             sc=1,
             s='_sfp_error',
             t=rt.Port.port_sfp_tbl,
             d='SFP Error Summary',
             l=False),
        dict(c='port_rnid',
             sc=1,
             s='_ficon',
             t=rt.Port.port_rnid_tbl,
             d='Port RNID data',
             l=False),
    ]

    # tc_page = report_utils.valid_sheet_name.sub('', proj_obj.r_obj_key())[:29] + '_xx'
    tc_page = 'Table_of_Contents'
    tbl_contents = list()

    # Set up the workbook
    sheet_index = 0
    wb = report_utils.new_report()

    # Check project for duplicate WWNs
    tbl_contents.append(dict(h=True, d='Duplicate WWNs'))
    wl = brcddb_project.dup_wwn(proj_obj)
    if len(wl) > 0:
        sname = 'dup_wwns'
        report_login.login_page(wb, tc_page, sname, sheet_index,
                                'Duplicate WWNs', wl, dup_login_tbl,
                                rt.Login.login_display_tbl, False)
        tbl_contents.append(dict(sc=1, s=sname, d='Duplicate WWNs'))
        sheet_index += 1
    else:
        tbl_contents.append(dict(sc=1, d='No Duplicate WWNs Found'))

    # Project dashboard
    if _report_pages['proj_dashboard']['s']:
        tbl_contents.append(dict(h=True, d='Project Links'))
        sname = 'proj_dashboard'
        title = 'Project Dashboard'
        dashboard(proj_obj, tc_page, wb, sheet_index, sname, title)
        tbl_contents.append(dict(sc=1, s=sname, d=title))
        sheet_index += 1

    # Add all the chassis
    if _report_pages['chassis']['s']:
        tbl_contents.append(dict(h=True, d='Chassis'))
        for chassis_obj in proj_obj.r_chassis_objects():
            chassis_name = brcddb_chassis.best_chassis_name(chassis_obj)
            brcdapi_log.log('Processing chassis: ' + chassis_name, True)
            sname = report_utils.valid_sheet_name.sub(
                '', chassis_name.replace(' ',
                                         '_'))[:22] + '_' + str(sheet_index)
            report_chassis.chassis_page(wb, tc_page, sname, sheet_index,
                                        'Chassis Detail For: ' + chassis_name,
                                        chassis_obj,
                                        rt.Chassis.chassis_display_tbl)
            tbl_contents.append(dict(sc=1, s=sname, d=chassis_name))
            sheet_index += 1

    # Add all the fabrics
    for fab_obj in proj_obj.r_fabric_objects():
        fab_name = brcddb_fabric.best_fab_name(fab_obj)
        if len(fab_name) == 0:
            fab_name = 'Unknown Fabric'
        brcdapi_log.log('Processing fabric: ' + fab_name, True)
        tbl_contents.append(dict(h=True, d=fab_name))
        prefix = report_utils.valid_sheet_name.sub(
            '', fab_name.replace(' ', '_'))[:20] + '_' + str(sheet_index)

        # Fabric summary page
        if _report_pages['fabric_summary']['s']:
            brcdapi_log.log('    Building fabric summary page', True)
            sname = prefix + '_sum'
            report_fabric.fabric_page(wb, tc_page, sheet_index, sname,
                                      fab_name + ' Summary', fab_obj)
            tbl_contents.append(dict(sc=1, s=sname, d='Fabric Summary'))
            sheet_index += 1

        # Fabric Dashboard
        if _report_pages['fabric_dashboard']['s']:
            brcdapi_log.log('    Building fabric dashboard', True)
            sname = prefix + '_db'
            dashboard(fab_obj, tc_page, wb, sheet_index, sname,
                      fab_name + ' Dasboard')
            tbl_contents.append(dict(sc=1, s=sname, d='Fabric Dashboard'))
            sheet_index += 1

        # Switch page
        if _report_pages['switch']['s']:
            brcdapi_log.log('    Building switch detail page', True)
            sname = prefix + '_switch'
            report_switch.switch_page(wb, tc_page, sname, sheet_index,
                                      'Switch Detail For Fabric: ' + fab_name,
                                      fab_obj.r_switch_objects(),
                                      rt.Switch.switch_display_tbl)
            tbl_contents.append(dict(sc=1, s=sname, d='Switch Detail'))
            sheet_index += 1

        # Now the port pages
        brcdapi_log.log('    Building the port pages', True)
        port_list = brcddb_util.sort_ports(fab_obj.r_port_objects())
        for obj in port_pages:
            if _report_pages[obj['c']]['s']:
                sname = prefix + obj.get('s')
                report_port.port_page(wb, tc_page, sname, sheet_index,
                                      fab_name + ' ' + obj.get('d'), port_list,
                                      obj.get('t'), rt.Port.port_display_tbl,
                                      obj.get('l'))
                tbl_contents.append(dict(sc=1, s=sname, d=obj.get('d')))
                sheet_index += 1

        #  Zone Analysis Page
        if _report_pages['zone_page']['s']:
            brcdapi_log.log('    Building zone analysis page', True)
            sname = prefix + '_zone'
            report_zone.zone_page(fab_obj, tc_page, wb, sname, sheet_index,
                                  fab_name + ' Zone Analysis')
            tbl_contents.append(dict(sc=1, s=sname, d='Zone Analysis'))
            sheet_index += 1

        #  Taget Zone Page
        if _report_pages['t_zone_page']['s']:
            brcdapi_log.log('    Building target zone page', True)
            sname = prefix + '_tzone'
            report_zone.target_zone_page(fab_obj, tc_page, wb, sname,
                                         sheet_index,
                                         fab_name + ' Zone by Target')
            tbl_contents.append(dict(sc=1, s=sname, d='Zone by Target'))
            sheet_index += 1

        #  Alias Page
        if _report_pages['alias']['s']:
            brcdapi_log.log('    Building alias page', True)
            sname = prefix + '_alias'
            report_zone.alias_page(fab_obj, tc_page, wb, sname, sheet_index,
                                   fab_name + ' Alias Detail')
            tbl_contents.append(dict(sc=1, s=sname, d='Alias Detail'))
            sheet_index += 1

        #  Login Page
        if _report_pages['login']['s']:
            brcdapi_log.log('    Building login page', True)
            sname = prefix + '_login'
            report_login.login_page(wb, tc_page, sname, sheet_index,
                                    fab_name + ' Logins',
                                    fab_obj.r_login_objects(),
                                    rt.Login.login_tbl,
                                    rt.Login.login_display_tbl, True)
            tbl_contents.append(dict(sc=1, s=sname, d='Logins'))
            sheet_index += 1

    #  IOCP Page
    if _report_pages['iocp']['s']:
        iocp_objects = proj_obj.r_iocp_objects()
        if len(iocp_objects) > 0:
            brcdapi_log.log('Adding the IOCP pages', True)
            tbl_contents.append(dict(h=True, d='IOCPs'))
            for iocp_obj in iocp_objects:
                sname = report_utils.valid_sheet_name.sub(
                    '', iocp_obj.r_obj_key())[:22]
                report_iocp.iocp_page(iocp_obj, tc_page, wb, sname,
                                      sheet_index, sname)
                tbl_contents.append(dict(sc=1, s=sname, d=sname))
                sheet_index += 1

    # Add the Best Practice page
    if _report_pages['bp']['s']:
        sname = 'Best_Practice'
        fab_name = 'Best Practice Violations'  # Just borrowing fab_name for the title
        report_bp.bp_page(wb, tc_page, sname, 0, fab_name, proj_obj,
                          rt.BestPractice.bp_tbl,
                          rt.BestPractice.bp_display_tbl)
        tbl_contents.insert(0, dict(sc=1, s=sname, d=fab_name))
        tbl_contents.insert(0, dict(h=True, d=fab_name))

    # Add the missing chassis (chassis not polled) to the title & contents page
    i = 0
    tbl_contents.append(
        dict(h=True,
             merge=3,
             d='Missing chassis (discovered in fabrics but not polled)'))
    for chassis_obj in proj_obj.r_chassis_objects():
        if chassis_obj.r_get('brocade-chassis') is None:
            # Try to find a chassis name
            chassis_name = None
            for obj in chassis_obj.r_switch_objects():
                chassis_name = obj.r_get(
                    'brocade-fabric/fabric-switch/chassis-user-friendly-name')
                if chassis_name is not None:
                    break
            if chassis_name is None:
                chassis_name = 'Unknown'
            chassis_name += ' (' + chassis_obj.r_obj_key(
            ) + '). Known logical switches:'
            tbl_contents.append(dict(sc=1, d=chassis_name))
            for obj in chassis_obj.r_switch_objects():
                tbl_contents.append(
                    dict(sc=2, d=brcddb_switch.best_switch_name(obj, True)))
            i += 1
    if i == 0:
        tbl_contents.append(dict(sc=1, d='None'))

    # Insert the title & contents page
    proj_title_page(proj_obj,
                    None,
                    wb,
                    0,
                    tc_page,
                    'Contents',
                    contents=tbl_contents)

    # Save the report.
    report_utils.save_report(wb, outf)
def _merge_zone_db(proj_obj, new_zone_cfg, a_flag):
    """Merges the zones for the fabrics specified in fab_csv

    :param proj_obj: Project object
    :type proj_obj: brcddb.classes.project.ProjectObj
    :param new_zone_cfg: Name of zone configuration to add
    :type new_zone_cfg: str, None
    :param a_flag: If True, make new_zone_cfg the effective zone configuration
    :type a_flag: bool
    :return rl: Error message list. If empty, no errors encountered
    :rtype rl: list
    """
    rl = list()

    # Find a fabric to start with, base_fab_obj, and get a list of the remaining fabrics to add to it.
    fab_l = list()
    base_fab_obj = None
    new_zonecfg_obj = None
    for fab_obj in proj_obj.r_fabric_objects():
        zd = fab_obj.r_get(
            'zone_merge'
        )  # zd should never be None. This is just future proofing.
        if zd is None or zd.get('fab_wwn') is None:
            continue
        if base_fab_obj is None:
            base_fab_obj = brcddb_fabric.copy_fab_obj(fab_obj,
                                                      fab_key=None,
                                                      full_copy=False)
            if isinstance(new_zone_cfg, str):
                mem_l = list()
                if isinstance(zd['cfg'], str):
                    zonecfg_obj = fab_obj.r_zonecfg_obj(zd['cfg'])
                    if zonecfg_obj is None:
                        rl.append(
                            'Could not find ' + zd['cfg'] + ' in ' +
                            brcddb_fabric.best_fab_name(fab_obj, wwn=True))
                    else:
                        mem_l = zonecfg_obj.r_members()
                if isinstance(new_zone_cfg, str):
                    new_zonecfg_obj = base_fab_obj.s_add_zonecfg(
                        new_zone_cfg, mem_l)
            brcddb_util.add_to_obj(proj_obj, 'zone_merge/base_fab_obj',
                                   base_fab_obj)
        else:
            fab_l.append(fab_obj)
    if base_fab_obj is None:
        rl.append(
            'Could not find a fabric containing any of the specified zone configurations.'
        )
    if len(fab_l) < 1:
        rl.append('Could not find any fabrics to merge. Must have at least 2.')
    if len(rl) > 0:
        return rl

    # Merge the individual zone items
    for fab_obj in fab_l:
        change_count, change_d = brcddb_compare.compare(
            base_fab_obj, fab_obj, brcddb_control_tbl=_control_tables)
        for local_key, action in _merge_case.items():
            rl.extend(action(change_d.get(local_key), base_fab_obj, fab_obj))

        # Add the zones to the merged zone configuration
        zd = fab_obj.r_get(
            'zone_merge'
        )  # zd should never be None. This is just future proofing.
        if new_zonecfg_obj is None or zd is None or zd.get('cfg') is None:
            continue
        add_zonecfg_obj = fab_obj.r_zonecfg_obj(zd.get('cfg'))
        if add_zonecfg_obj is not None:
            new_zonecfg_obj.s_add_member(add_zonecfg_obj.r_members())

    # If the new zone configuration is to be enabled, set it as the effective zone configuration
    if a_flag:
        base_fab_obj.s_del_eff_zonecfg()
        base_fab_obj.s_add_eff_zonecfg(new_zonecfg_obj.r_members())

    return rl
def _patch_zone_db(proj_obj, eff_cfg):
    """Replaces the zoning in the fabric(s).

    :param proj_obj: Project object
    :type proj_obj: brcddb.classes.project.ProjectObj
    :param eff_cfg: Name of zone configuration to activate. None if no zone configuration to activate.
    :type eff_cfg: str, None
    :return: List of error messages. Empty list if no errors found
    :rtype: list()
    """
    rl = list()  # List of error messages to return
    base_fab_obj = proj_obj.r_get('zone_merge/base_fab_obj')
    if base_fab_obj is None:
        rl.append(
            'base_fab_obj is None')  # There is a code bug if this happens
        return rl

    update_count = 0
    for fab_obj in proj_obj.r_fabric_objects():

        # Get the login credentials
        ip_addr = fab_obj.r_get('zone_merge/ip')
        id = fab_obj.r_get('zone_merge/id')
        pw = fab_obj.r_get('zone_merge/pw')
        sec = fab_obj.r_get('zone_merge/sec')
        fid = fab_obj.r_get('zone_merge/fid')
        update = fab_obj.r_get('zone_merge/update')
        if ip_addr is None or id is None or pw is None or sec is None or fid is None or update is None or not update:
            continue

        # Login
        session = api_int.login(id, pw, ip_addr, sec, proj_obj)
        if fos_auth.is_error(session):
            rl.append(fos_auth.formatted_error_msg(session))
            return rl

        # Send the changes to the switch
        brcdapi_log.log(
            'Sending zone updates to ' +
            brcddb_fabric.best_fab_name(fab_obj, wwn=True), True)
        try:
            obj = api_zone.replace_zoning(session, base_fab_obj, fid)
            if fos_auth.is_error(obj):
                rl.append(fos_auth.formatted_error_msg(obj))
            else:
                update_count += 1
                if isinstance(eff_cfg, str):
                    obj = api_zone.enable_zonecfg(session, None, fid, eff_cfg)
                    if fos_auth.is_error(obj):
                        rl.append(fos_auth.formatted_error_msg(obj))
        except:
            rl.append('Software fault in api_zone.replace_zoning()')

        # Logout
        obj = brcdapi_rest.logout(session)
        if fos_auth.is_error(obj):
            rl.append(fos_auth.formatted_error_msg(obj))

        brcdapi_log.log(str(update_count) + ' switch(es) updated.', True)

    return rl