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')]
def _page(wb, sheet_index, b_proj_obj, c_proj_obj, c_obj, page): """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 :param page: Page type: _fabric_objs, _chassis_objs, or _switch_objs :type page: str :return sheet_index: Next sheet index :rtype sheet_index: int :return tbl_contents: Table of contents for the fabrics :rtype. tbl_contents: list """ global _main_pages # Set up the table of contents and sheet headers tbl_contents = list() if not isinstance(c_obj, dict): return sheet_index, tbl_contents # This happens when there are no changes for base_key, f_obj in c_obj.items(): b_fab_obj = b_proj_obj.r_fabric_obj(base_key) c_fab_obj = c_proj_obj.r_fabric_obj(base_key) t_content = [dict(font='hdr_2', align='wrap', disp=('Key', 'Base Value', 'Compare Value', 'Change'))] obj_tbl = _action_table[page] # Add each individual item for the brcddb object to the sheet if b_fab_obj is not None and c_fab_obj is not None: # The principal fabric switch may not have been polled for k, cntl_tbl in obj_tbl.items(): obj = f_obj.get(k) if obj is not None: # obj can be None if code was upgraded and a new KPI was introduced and captured. This logic skips # reporting on anything new because we have no idea what the previous version would have been t_content.append(dict()) t_content.append(dict(font='hdr_2', merge=4, align='wrap', disp=cntl_tbl.get('t'))) cntl_tbl.get('f')(obj, b_fab_obj, c_fab_obj, t_content) # Add each item added to the brcddb object (these are the items from the API) t_content.append(dict()) t_content.append(dict(font='hdr_2', merge=4, align='wrap', disp='Added from RESTConf API')) for k1 in [key for key in f_obj.keys() if key not in obj_tbl]: _api_added_compares(f_obj, k1, list(), t_content) # Sheet name and title title, sname = _main_pages[page]['ts'](b_proj_obj, base_key) sname = sname.replace(' ', '_').replace(':', '').replace('-', '_') sname = sname[:28] + '_' + str(sheet_index) if len(sname) > 28 else sname + '_' + str(sheet_index) tbl_contents.append(dict(s=sname, d=title)) report_utils.title_page(wb, None, sname, sheet_index, title, _main_pages[page]['sc'](t_content), (42, 45, 45, 24)) sheet_index += 1 return sheet_index, tbl_contents
def _new_report(c, b_proj_obj, c_proj_obj, c_obj, r_name): """Generates an Excel comparison report :param c: Total number of changes. Typically the number of changes returned from brcddb.util.compare.compare() :type c: 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: Change object returned from brcddb.util.compare.compare() :type c_obj: dict :param r_name: Name of Excel workbook file :type r_name: str """ global _main_pages # Set up the workbook sheet_index = 0 wb = excel_util.new_report() # Setup the Project summary sheet with table of content title = b_proj_obj.r_obj_key() + ' Compared to ' + c_proj_obj.r_obj_key() tc_page = 'Project_Summary' t_content = [ dict(font='std', align='wrap', disp=('Total changes', c)), dict(), dict(font='hdr_2', align='wrap', disp=('Key', 'Base Value', 'Compare Value', 'Change')), ] # Add any added changes to the project objects for k, obj in c_obj.items(): if k not in _main_pages.keys() and k != '_project_obj': t_content.append(dict(font='std', align='wrap', disp=(k, obj.get('b'), obj.get('c'), obj.get('r')))) t_content.append(dict()) # Add the project change sheet sheet_index, tbl_contents = _project_page(wb, sheet_index, b_proj_obj, c_proj_obj, c_obj.get('_project_obj')) d = tbl_contents[0] td = dict(font='link', merge=4, align='wrap', disp=d.get('d')) td.update(hyper='#' + d.get('s') + '!A1') t_content.append(td) # Add all the chassis, switch and fabric sheets for k, p_obj in _main_pages.items(): t_content.append(dict()) t_content.append(dict(font='hdr_2', merge=4, align='wrap', disp=p_obj.get('t'))) sheet_index, tbl_contents = _page(wb, sheet_index, b_proj_obj, c_proj_obj, c_obj.get(k), k) for d in tbl_contents: td = dict(font='link', merge=4, align='wrap', disp=d.get('d')) if 's' in d: # Is there a link to a page? td.update(hyper='#' + d.get('s') + '!A1') t_content.append(td) # Add the project summary with table of contents and save the report. report_utils.title_page(wb, None, tc_page, 0, title, t_content, (24, 42, 42, 12)) excel_util.save_report(wb, r_name)
def _write_report(switch_obj, report, graph_list, ml): """Creates an Excel workbook with the port statistics differences. Operates off global data :param switch_obj: Base switch object with ports to write to report :type switch_obj: brcddb.classes.switch.SwitchObj :param report: Name of report (Excel file name) :type report: str :param graph_list: List of dictionaries as returned from _graphs :type graph_list: list :return: Status code. See brcddb.brcddb_common.EXIT_xxxx :rtype: int """ # Get the project and set up the workbook brcdapi_log.log( 'Generating Report: ' + report + '. This may take several seconds', True) proj_obj = switch_obj.r_project_obj() wb = excel_util.new_report() # Setup the Project summary sheet with table of content title = 'Port Performance' tc_page = 'Project_Summary' t_content = [ dict(new_row=False, merge=2, font='std', align='wrap', disp='Description'), dict(merge=2, font='std', align='wrap', disp=proj_obj.c_description()), dict(merge=2, new_row=False, font='std', align='wrap', disp='Data collected'), dict(merge=2, font='std', align='wrap', disp=proj_obj.r_date()), ] t_content_p = [ dict(merge=4, font='std', align='wrap', disp=''), dict(merge=4, font='hdr_2', align='wrap', disp='Collected Port Data'), dict(merge=4, font='std', align='wrap', disp=''), dict(new_row=False, font='hdr_2', align='wrap', disp='Port'), dict(new_row=False, font='hdr_2', align='wrap', disp='Name'), dict(new_row=False, font='hdr_2', align='wrap', disp='Type'), dict(new_row=False, font='hdr_2', align='wrap', disp='State'), dict(font='hdr_2', align='wrap', disp='Description'), ] t_content_g = [ dict(merge=4, font='std', align='wrap', disp=''), dict(merge=4, font='hdr_2', align='wrap', disp='Graphs'), dict(merge=4, font='std', align='wrap', disp=''), ] # Add the individual graphs and port sheets _add_ports(wb, tc_page, t_content_p, 0, switch_obj) ml.extend(_add_graphs(wb, tc_page, t_content_g, 0, switch_obj, graph_list)) ml = gen_util.remove_duplicates(ml) t_content.extend(t_content_g + t_content_p) # Add the table of contents and save the report. report_utils.title_page(wb, None, tc_page, 0, title, t_content, (12, 22, 16, 10, 64)) ml.append('Saving the report.') brcdapi_log.log(ml, True) excel_util.save_report(wb, report) return brcddb_common.EXIT_STATUS_OK
def proj_title_page(proj_obj, tc, wb, sheet_index, sheet_name, sheet_title, contents): """Creates the project title page :param proj_obj: Project object :type proj_obj: brcddb.classes.project.ProjectObj :param tc: Table of context page. A link to this page is place in cell A1 :type tc: str, None :param wb: Workbook object :type wb: dict :param sheet_index: Location for the title page. First sheet is 0 :type sheet_index: int :param sheet_name: Sheet (tab) name :type sheet_name: str :param sheet_title: Title for sheet :type sheet_title: str :param contents: List of objects {'s': sheet name, 'd': reference name (individual sheet titles)} :rtype: None """ t_content = [ dict(new_row=False, merge=2, font='std', align='wrap', disp='Description'), dict(font='std', align='wrap', disp=proj_obj.c_description()), dict(new_row=False, merge=2, font='std', align='wrap', disp='Data collected'), dict(font='std', align='wrap', disp=proj_obj.r_date()) ] # Add the table of contents for obj in contents: m = 3 # Number of cells to merge if obj.get('h') is not None and obj.get('h') is True: t_content.append(dict()) t_content.append( dict(merge=m, font='hdr_2', align='wrap', disp=obj.get('d'))) continue if obj.get('sc') is not None: for i in range(0, obj.get('sc')): t_content.append(dict(new_row=False, disp='')) # Column is blank m -= 1 if obj.get('s') is not None: t_content.append( dict(merge=m, font='link', align='wrap', disp=obj.get('d'), hyper='#' + obj.get('s') + '!A1')) else: buf = obj.get('font') if 'font' in obj else 'std' t_content.append( dict(merge=m, font=buf, align='wrap', disp=obj.get('d'))) report_utils.title_page(wb, tc, sheet_name, sheet_index, sheet_title, t_content, (4, 20, 62))