From 5e70d808a8449352dc71f7629dc96cae937c175f Mon Sep 17 00:00:00 2001 From: Yash Ajgaonkar Date: Tue, 30 Jul 2024 15:41:36 +0530 Subject: [PATCH] Added a new param for ros_ocp to support constant data generation --- README.md | 2 ++ nise/__init__.py | 2 +- nise/__main__.py | 7 ++++ nise/generators/ocp/ocp_generator.py | 54 ++++++++++++++++++---------- nise/report.py | 3 +- tests/test_report.py | 22 ++++++++++++ 6 files changed, 70 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 0b2970ce..370a3a5a 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,8 @@ The `make run-iqe` command by default will run the smoke tests. However, if you --insights-upload UPLOAD_URL optional, Use local directory path to populate a "local upload directory". --ros-ocp-info Optional, Generate ROS for Openshift data. + --constant-values-ros-ocp Optional, Generate constant values for ROS for OpenShift data only + when used with the ros-ocp-info parameter. OCI Report Options: --oci-bucket-name BUCKET_NAME optional, OCI bucket name. diff --git a/nise/__init__.py b/nise/__init__.py index 1baf204c..0eddf277 100644 --- a/nise/__init__.py +++ b/nise/__init__.py @@ -1,3 +1,3 @@ -__version__ = "4.6.4" +__version__ = "4.6.5" VERSION = __version__.split(".") diff --git a/nise/__main__.py b/nise/__main__.py index 8a949b1c..2031ce43 100644 --- a/nise/__main__.py +++ b/nise/__main__.py @@ -299,6 +299,13 @@ def add_ocp_parser_args(parser): action="store_true", help="Flag used to add the `daily_reports` marker to manifests.", ) + parser.add_argument( + "--constant-values-ros-ocp", + dest="constant_values_ros_ocp", + required=False, + action="store_true", + help="Flag to generate constant values for ROS for Openshift", + ) def add_oci_parser_args(parser): diff --git a/nise/generators/ocp/ocp_generator.py b/nise/generators/ocp/ocp_generator.py index a2164510..403a77ef 100644 --- a/nise/generators/ocp/ocp_generator.py +++ b/nise/generators/ocp/ocp_generator.py @@ -172,29 +172,40 @@ def get_owner_workload(pod, workload=None): return pod, ok, pod, wt -def generate_randomized_ros_usage(usage_dict, limit_value): - # if usage value is provided in yaml -> avg_value = +- 5% of that specified usage value - if usage_value := usage_dict.get("full_period"): - avg_value = min(round(uniform(usage_value * 0.95, usage_value * 1.05), 5), limit_value) - # if usage value is not specified in yaml -> random avg_usage from 10% to 100% of the limit - else: - avg_value = round(uniform(limit_value * 0.1, limit_value), 5) +def generate_randomized_ros_usage(usage_dict, limit_value, generate_constant_value=False): + if generate_constant_value: + # will generate constant values + if usage_value := usage_dict.get("full_period"): + avg_value = min(round(usage_value, 5), limit_value) + else: + avg_value = round(uniform(limit_value * 0.1, limit_value), 5) - # min value - random float derived from avg_value, - min_value = round(uniform(avg_value * 0.8, avg_value), 5) - # max_value - random float derived from avg_value, but max of limit_value - max_value = min(round(uniform(avg_value, avg_value * 1.2), 5), limit_value) + min_value = round(usage_value, 5) + max_value = min(round(usage_value, 5), limit_value) + else: + # This will generate randomised values + # if usage value is provided in yaml -> avg_value = +- 5% of that specified usage value + if usage_value := usage_dict.get("full_period"): + avg_value = min(round(uniform(usage_value * 0.95, usage_value * 1.05), 5), limit_value) + # if usage value is not specified in yaml -> random avg_usage from 10% to 100% of the limit + else: + avg_value = round(uniform(limit_value * 0.1, limit_value), 5) + # min value - random float derived from avg_value, + min_value = round(uniform(avg_value * 0.8, avg_value), 5) + # max_value - random float derived from avg_value, but max of limit_value + max_value = min(round(uniform(avg_value, avg_value * 1.2), 5), limit_value) return avg_value, min_value, max_value class OCPGenerator(AbstractGenerator): """Defines a abstract class for generators.""" - def __init__(self, start_date, end_date, attributes, ros_ocp_info=False): + def __init__(self, start_date, end_date, attributes, ros_ocp_info=False, constant_values_ros_ocp=False): """Initialize the generator.""" self._nodes = None self.ros_ocp_info = ros_ocp_info + self.constant_values_ros_ocp = constant_values_ros_ocp if attributes: self._nodes = attributes.get("nodes") @@ -405,11 +416,16 @@ def _gen_pods(self, namespaces): pod, specified_pod.get("workload") ) - cpu_usage_avg, cpu_usage_min, cpu_usage_max = generate_randomized_ros_usage(cpu_usage, cpu_limit) + cpu_usage_avg, cpu_usage_min, cpu_usage_max = generate_randomized_ros_usage( + cpu_usage, cpu_limit, generate_constant_value=self.constant_values_ros_ocp + ) memory_usage_gig_avg, memory_usage_gig_min, memory_usage_gig_max = generate_randomized_ros_usage( - memory_usage_gig, mem_limit_gig + memory_usage_gig, mem_limit_gig, generate_constant_value=self.constant_values_ros_ocp ) - memory_rss_ratio = 1 / round(uniform(1.01, 1.9), 2) + if self.constant_values_ros_ocp: + memory_rss_ratio = 1 / round(1, 2) + else: + memory_rss_ratio = 1 / round(uniform(1.01, 1.9), 2) cpu_throttle = choices([0, round(cpu_usage_avg / randint(10, 20), 5)], weights=(3, 1))[0] ros_ocp_data_pods[pod] = { @@ -479,9 +495,11 @@ def _gen_pods(self, namespaces): "pod_labels": self._gen_openshift_labels(), } owner_name, owner_kind, workload, workload_type = get_owner_workload(pod) - cpu_usage_avg, cpu_usage_min, cpu_usage_max = generate_randomized_ros_usage({}, cpu_limit) + cpu_usage_avg, cpu_usage_min, cpu_usage_max = generate_randomized_ros_usage( + {}, cpu_limit, generate_constant_value=self.constant_values_ros_ocp + ) memory_usage_gig_avg, memory_usage_gig_min, memory_usage_gig_max = generate_randomized_ros_usage( - {}, mem_limit_gig + {}, mem_limit_gig, generate_constant_value=self.constant_values_ros_ocp ) memory_rss_ratio = 1 / round(uniform(1.01, 1.9), 2) cpu_throttle = choices([0, round(cpu_usage_avg / randint(10, 20), 5)], weights=(3, 1))[0] @@ -737,7 +755,7 @@ def _randomize_ros_ocp_line_values(self, pod_in): def _update_ros_ocp_pod_data(self, row, start, end, **kwargs): """Update data with generator specific data.""" pod = kwargs.get("pod") - if pod: + if pod and not self.constant_values_ros_ocp: pod = self._randomize_ros_ocp_line_values(pod) row.update(pod) return row diff --git a/nise/report.py b/nise/report.py index 45447147..ecd8c6f0 100644 --- a/nise/report.py +++ b/nise/report.py @@ -849,6 +849,7 @@ def ocp_create_report(options): # noqa: C901 cluster_id = options.get("ocp_cluster_id") static_report_data = options.get("static_report_data") ros_ocp_info = options.get("ros_ocp_info") + constant_values_ros_ocp = options.get("constant_values_ros_ocp") if static_report_data: generators = _get_generators(static_report_data.get("generators")) @@ -881,7 +882,7 @@ def ocp_create_report(options): # noqa: C901 gen_start_date, gen_end_date = _create_generator_dates_from_yaml(attributes, month) - gen = generator_cls(gen_start_date, gen_end_date, attributes, ros_ocp_info) + gen = generator_cls(gen_start_date, gen_end_date, attributes, ros_ocp_info, constant_values_ros_ocp) for report_type in gen.ocp_report_generation.keys(): LOG.info(f"Generating data for {report_type} for {month}") for hour in gen.generate_data(report_type): diff --git a/tests/test_report.py b/tests/test_report.py index d3b60407..36d96305 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -975,6 +975,28 @@ def test_ocp_create_report(self): self.assertTrue(os.path.isfile(expected_month_output_file)) os.remove(expected_month_output_file) + def test_ocp_create_report_ros_ocp_constant_data_generation(self): + """Test the ocp report creation method with constant_values_ros_ocp enabled.""" + now = datetime.datetime.now().replace(microsecond=0, second=0, minute=0, hour=0) + one_day = datetime.timedelta(days=1) + yesterday = now - one_day + cluster_id = "11112222" + options = { + "start_date": yesterday, + "end_date": now, + "ocp_cluster_id": cluster_id, + "write_monthly": True, + "ros_ocp_info": True, + "constant_values_ros_ocp": True, + } + fix_dates(options, "ocp") + ocp_create_report(options) + for report_type in OCP_REPORT_TYPE_TO_COLS.keys(): + month_output_file_name = f"{calendar.month_name[now.month]}-{now.year}-{cluster_id}-{report_type}" + expected_month_output_file = f"{os.getcwd()}/{month_output_file_name}.csv" + self.assertTrue(os.path.isfile(expected_month_output_file)) + os.remove(expected_month_output_file) + def test_ocp_create_report_minio_upload(self): """Test the ocp report creation method.""" now = datetime.datetime.now().replace(microsecond=0, second=0, minute=0, hour=0)