Ievgeniia Zadorozhna | 9664b42 | 2023-03-28 21:09:46 +0300 | [diff] [blame] | 1 | import csv |
| 2 | import datetime |
| 3 | import logging |
| 4 | import os |
| 5 | import time |
Ievgeniia Zadorozhna | 97dfde4 | 2022-06-17 20:05:09 +0300 | [diff] [blame] | 6 | |
Ievgeniia Zadorozhna | 9664b42 | 2023-03-28 21:09:46 +0300 | [diff] [blame] | 7 | from jinja2 import Environment, FileSystemLoader |
| 8 | import pandas as pd |
| 9 | |
| 10 | import utils |
| 11 | |
| 12 | logger = logging.getLogger(__name__) |
Ievgeniia Zadorozhna | 8402302 | 2021-12-30 13:00:41 +0200 | [diff] [blame] | 13 | |
| 14 | |
Ievgeniia Zadorozhna | 9664b42 | 2023-03-28 21:09:46 +0300 | [diff] [blame] | 15 | def get_tests_configuration_data(): |
| 16 | """ |
| 17 | Gets the values from the config file and generates the dictionary with the |
| 18 | human-readable configuration. |
| 19 | """ |
| 20 | config = utils.get_configuration() |
| 21 | glance_test_file_size = config.get("IMAGE_SIZE_MB", 9000) |
| 22 | image = config.get('image_name', 'cvp.ubuntu.2004') |
| 23 | ext_net = config.get('external_network') or '' |
| 24 | utility_single_thread = "iperf3" # not configurable, just for info |
| 25 | utility_multiple_threads = str( |
| 26 | config.get('multiple_threads_iperf_utility', 10)) |
| 27 | iperf_time = int(config.get('iperf_time', 60)) |
Ievgeniia Zadorozhna | 8402302 | 2021-12-30 13:00:41 +0200 | [diff] [blame] | 28 | |
Ievgeniia Zadorozhna | 9664b42 | 2023-03-28 21:09:46 +0300 | [diff] [blame] | 29 | tests_data = { |
| 30 | "File size in the Glance test": "{} MB".format(glance_test_file_size), |
| 31 | "Image used in the vm2vm tests": image, |
| 32 | "Floating network used": ext_net, |
| 33 | "Network performance tool used for " |
| 34 | "single thread tests": utility_single_thread, |
| 35 | "Network performance tool used for " |
| 36 | "multiple threads tests": utility_multiple_threads, |
| 37 | "iperf time in seconds " |
| 38 | "to transmit for each test (iperf -t)": iperf_time |
| 39 | } |
| 40 | return tests_data |
Ievgeniia Zadorozhna | 8402302 | 2021-12-30 13:00:41 +0200 | [diff] [blame] | 41 | |
Ievgeniia Zadorozhna | 9664b42 | 2023-03-28 21:09:46 +0300 | [diff] [blame] | 42 | |
| 43 | def create_test_result_table_csv_file(text_table_rows, test_name): |
| 44 | """ |
| 45 | Gets the text-table and saves to the separate CSV file. |
| 46 | """ |
| 47 | dir_path = 'reports' |
| 48 | if not os.path.exists(dir_path): |
| 49 | os.makedirs(dir_path) |
| 50 | csv_name = "{}.csv".format(test_name) |
| 51 | csv_report_path = "{}/{}".format(dir_path, csv_name) |
| 52 | with open(csv_report_path, 'w', newline='') as csvfile: |
| 53 | writer = csv.writer(csvfile) |
| 54 | writer.writerows(text_table_rows) |
| 55 | |
| 56 | |
| 57 | def read_csv_files_to_dataframes(csv_files_list): |
| 58 | """ |
| 59 | The pandas module reads the list of the CSV files and saves them to the |
| 60 | dataframe objects. Returns the dictionary with DFs, title and time for |
| 61 | each result table. |
| 62 | """ |
| 63 | df_tables = [] |
| 64 | for csv_file in csv_files_list: |
| 65 | # Read the CSVs to the DataFrames |
| 66 | df = pd.read_csv(csv_file) |
| 67 | # Get the file age (to prevent the cases when there are some old CSV |
| 68 | # files, the tests are executed later, got the error, but the test |
| 69 | # report is generated from the old files). |
| 70 | # Also, if the tests are executed one by one in different time, all |
| 71 | # results are collected with the proper age of each file. |
| 72 | executed_at = os.path.getctime(csv_file) |
| 73 | df_tables.append({ |
| 74 | 'df': df, # the results table of a test case |
| 75 | 'title': csv_file[8:-4], # remove "reports/", ".csv" to get names |
| 76 | 'executed_at': time.ctime(executed_at) # time of test execution |
| 77 | }) |
| 78 | return df_tables |
| 79 | |
| 80 | |
| 81 | def convert_csvs_to_single_html_report(): |
| 82 | """ |
| 83 | Generates the single HTML report from the CSV files at reports/ dir. |
| 84 | Uses the template and CSS styles from the templates/. |
| 85 | """ |
| 86 | dir_path = 'reports/' |
| 87 | if not os.path.exists(dir_path): |
| 88 | logger.warning("Could not generate the HTML report since there is no " |
| 89 | "{} folder.".format(dir_path)) |
| 90 | return |
| 91 | datetime_now = datetime.datetime.now() |
| 92 | timestamp = datetime_now.strftime("%d%m%Y_%H%M%S") |
| 93 | report_file = "spt_report_{}.html".format(timestamp) |
| 94 | csv_files = ["{}{}".format(dir_path, f) |
| 95 | for f in sorted(os.listdir(path=dir_path)) |
| 96 | if f.endswith('.csv')] |
| 97 | if not csv_files: |
| 98 | logger.warning("Could not generate the HTML report since the CSV files" |
| 99 | " are absent in the {} folder.".format(dir_path)) |
| 100 | return |
| 101 | |
| 102 | env = Environment(loader=FileSystemLoader('.')) |
| 103 | template = env.get_template('templates/template.j2') |
| 104 | |
| 105 | tests_config_data = get_tests_configuration_data() |
| 106 | human_timestamp = datetime_now.strftime("%Y-%m-%d %H:%M:%S") |
| 107 | df_tables = read_csv_files_to_dataframes(csv_files) |
| 108 | html = template.render( |
| 109 | tables=df_tables, |
| 110 | tests_config_data=tests_config_data, |
| 111 | human_timestamp=human_timestamp |
| 112 | ) |
| 113 | |
| 114 | with open(report_file, 'w') as f: |
| 115 | f.write(html) |
| 116 | logger.info("The HTML report {} is created.".format(report_file)) |