benchmark-runner 1.0.813__py3-none-any.whl → 1.0.909__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. benchmark_runner/benchmark_operator/benchmark_operator_workloads_operations.py +1 -1
  2. benchmark_runner/common/clouds/BareMetal/bare_metal_operations.py +33 -18
  3. benchmark_runner/common/grafana/update_grafana_latest_value_mappings.py +34 -7
  4. benchmark_runner/common/oc/oc.py +103 -32
  5. benchmark_runner/common/ocp_resources/create_cnv.py +3 -3
  6. benchmark_runner/common/ocp_resources/create_lso.py +13 -2
  7. benchmark_runner/common/ocp_resources/create_nhc_far.py +51 -0
  8. benchmark_runner/common/ocp_resources/create_ocp_resource.py +9 -5
  9. benchmark_runner/common/ocp_resources/lso/template/01_delete_disks_template.sh +12 -0
  10. benchmark_runner/common/ocp_resources/lso/template/04_subscription_template.yaml +4 -0
  11. benchmark_runner/common/ocp_resources/nhc_far/template/04_far_subscription_template.yaml +11 -0
  12. benchmark_runner/common/ocp_resources/nhc_far/template/05_nhc_far_template.yaml +60 -0
  13. benchmark_runner/common/template_operations/templates/hammerdb/internal_data/hammerdb_vm_template.yaml +5 -1
  14. benchmark_runner/common/template_operations/templates/hammerdb/internal_data/mariadb_template.yaml +1 -1
  15. benchmark_runner/common/template_operations/templates/hammerdb/internal_data/mssql_template.yaml +1 -1
  16. benchmark_runner/common/template_operations/templates/hammerdb/internal_data/postgres_template.yaml +1 -1
  17. benchmark_runner/jupyterlab/templates/summary_report/summary_report_operations.py +1 -1
  18. benchmark_runner/krkn_hub/krknhub_workloads.py +5 -1
  19. benchmark_runner/main/environment_variables.py +18 -4
  20. benchmark_runner/workloads/bootstorm_vm.py +28 -18
  21. benchmark_runner/workloads/workloads_operations.py +6 -2
  22. {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/METADATA +3 -2
  23. {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/RECORD +29 -28
  24. {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/WHEEL +1 -1
  25. benchmark_runner/common/ocp_resources/create_nhc_snr.py +0 -42
  26. benchmark_runner/common/ocp_resources/nhc_snr/template/04_snr_subscription_template.yaml +0 -11
  27. benchmark_runner/common/ocp_resources/nhc_snr/template/05_nhc_snr_template.yaml +0 -41
  28. /benchmark_runner/common/ocp_resources/{nhc_snr → nhc_far}/template/01_namespace_template.yaml +0 -0
  29. /benchmark_runner/common/ocp_resources/{nhc_snr → nhc_far}/template/02_operator_group_template.yaml +0 -0
  30. /benchmark_runner/common/ocp_resources/{nhc_snr → nhc_far}/template/03_nhc_subscription_template.yaml +0 -0
  31. {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/licenses/LICENSE +0 -0
  32. {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/top_level.txt +0 -0
@@ -462,7 +462,7 @@ class BenchmarkOperatorWorkloadsOperations:
462
462
  :return:
463
463
  """
464
464
  workload_name = self._workload.split('_')
465
- if workload_name[0] in self._workloads_odf_pvc:
465
+ if workload_name[0] in self._workloads_odf_pvc and '_lso' not in self._workload:
466
466
  if not self._oc.is_odf_installed():
467
467
  raise ODFNotInstalled(workload=self._workload)
468
468
 
@@ -42,6 +42,8 @@ class BareMetalOperations:
42
42
  self._upgrade_ocp_version = self._environment_variables_dict.get('upgrade_ocp_version', '')
43
43
  self._upgrade_channel = self._environment_variables_dict.get('upgrade_channel', '')
44
44
  self._timeout = int(self._environment_variables_dict.get('timeout', ''))
45
+ self._must_gather_log = self._environment_variables_dict.get('must_gather_log', '')
46
+ self._run_artifacts_path = self._environment_variables_dict.get('run_artifacts_path', '')
45
47
  if user:
46
48
  self._user = user
47
49
  self._provision_kubeadmin_password_path = self._environment_variables_dict.get('provision_kubeadmin_password_path', '')
@@ -107,14 +109,17 @@ class BareMetalOperations:
107
109
  current_wait_time = 0
108
110
  logger.info(f'Waiting until the upgrade to version {self._upgrade_ocp_version} starts...')
109
111
  oc.wait_for_ocp_upgrade_start(upgrade_version=self._upgrade_ocp_version)
110
- while self._timeout <= 0 or current_wait_time <= self._timeout and oc.upgrade_in_progress():
112
+ while (self._timeout <= 0 or current_wait_time <= self._timeout) and oc.upgrade_in_progress():
111
113
  logger.info(f'Waiting till OCP upgrade complete, waiting {int(current_wait_time / 60)} minutes')
112
114
  # sleep for x seconds
113
115
  time.sleep(sleep_time)
114
116
  current_wait_time += sleep_time
115
- if f'Cluster version is {self._upgrade_ocp_version}' == oc.get_cluster_status():
117
+ if oc.get_upgrade_version() == self._upgrade_ocp_version:
118
+ logger.info(f"OCP successfully upgraded to {oc.get_upgrade_version()}")
116
119
  return True
117
120
  else:
121
+ if self._must_gather_log:
122
+ oc.generate_ocp_must_gather(destination_path=self._run_artifacts_path)
118
123
  raise OCPUpgradeFailed(status=oc.get_cluster_status())
119
124
 
120
125
  def _install_ocp_cmd(self):
@@ -283,24 +288,34 @@ class BareMetalOperations:
283
288
  else:
284
289
  return True
285
290
 
286
- def is_cluster_upgraded(self, oc: OC, cnv_version: str, odf_version: str, lso_version: str):
291
+ def is_cluster_upgraded(self, oc: OC, cnv_version: str = None, odf_version: str = None,
292
+ lso_version: str = None) -> bool:
287
293
  """
288
- This method checks if cluster/operators upgraded successfully
289
- @param oc:
290
- @param cnv_version:
291
- @param odf_version:
292
- @param lso_version:
293
- @return:
294
+ Checks if the cluster and the specified operators were successfully upgraded.
295
+
296
+ :param oc: OC client instance
297
+ :param cnv_version: (Optional) Target CNV operator version
298
+ :param odf_version: (Optional) Target ODF operator version
299
+ :param lso_version: (Optional) Target LSO operator version
300
+ :return: True if the upgrade (cluster + specified operators) is successful, otherwise False
294
301
  """
295
- # check cluster version upgrade
296
- if oc.get_upgrade_version() == self._upgrade_ocp_version:
297
- lso_upgraded = oc.wait_for_operator_installation(operator='lso', version=lso_version, namespace='openshift-local-storage')
298
- odf_upgraded = oc.wait_for_operator_installation(operator='odf', version=odf_version, namespace='openshift-storage')
299
- cnv_upgraded = oc.wait_for_operator_installation(operator='cnv', version=cnv_version, namespace='openshift-cnv')
300
- # check operators versions upgrade
301
- if cnv_upgraded and lso_upgraded and odf_upgraded:
302
- return True
303
- return False
302
+ if oc.get_upgrade_version() != self._upgrade_ocp_version:
303
+ return False
304
+
305
+ # Operator details mapping: short_key -> (version, namespace, operator_name_prefix)
306
+ operators_to_check = {
307
+ "cnv": (cnv_version, "openshift-cnv", "kubevirt-hyperconverged-operator"),
308
+ "odf": (odf_version, "openshift-storage", "odf-operator"),
309
+ "lso": (lso_version, "openshift-local-storage", "local-storage-operator"),
310
+ }
311
+
312
+ upgrade_checks = [
313
+ oc.wait_for_operator_installation(operator_name=operator_name, version=ver, namespace=ns)
314
+ for _, (ver, ns, operator_name) in operators_to_check.items()
315
+ if ver # only include if a version was specified
316
+ ]
317
+
318
+ return all(upgrade_checks) if upgrade_checks else True
304
319
 
305
320
  @logger_time_stamp
306
321
  def verify_upgrade_complete(self, oc: OC):
@@ -26,6 +26,30 @@ class UpdateGrafanaLatestValueMappings:
26
26
  self.main_libsonnet_path = main_libsonnet_path
27
27
  self.value_mappings = self.get_value_mappings()
28
28
 
29
+ @staticmethod
30
+ def _normalize_version_for_grafana(version: str) -> str:
31
+ """
32
+ Normalizes a version string for Grafana, then strips all non-digit characters.
33
+
34
+ Examples:
35
+ '4.14.0-ec.2' -> '414002'
36
+ '4.15.0-rc.3' -> '415013'
37
+ '4.15.5' -> '4155'
38
+
39
+ Returns:
40
+ A normalized numeric string, replacing '-ec.' with '0' and '-rc.' with '1' if present;
41
+ otherwise returns the version string with all non-digit characters removed.
42
+ """
43
+ qualifiers = {'-ec.': '0', '-rc.': '1'}
44
+ for qualifier, replacement in qualifiers.items():
45
+ if qualifier in version:
46
+ replaced = version.replace(qualifier, replacement)
47
+ digits_only = ''.join(c for c in replaced if c.isdigit())
48
+ return digits_only
49
+
50
+ # No qualifier found; return only digits from the original version
51
+ return ''.join(c for c in version if c.isdigit())
52
+
29
53
  def get_last_elasticsearch_versions(self, last_es_fetch_days=LAST_ES_FETCH_DAYS):
30
54
  """
31
55
  This method fetches new versions from ElasticSearch
@@ -42,10 +66,11 @@ class UpdateGrafanaLatestValueMappings:
42
66
  display_versions = ['ocp_version', 'cnv_version', 'kata_version', 'kata_rpm_version', 'odf_version']
43
67
  for id in ids:
44
68
  data = self.elasticsearch.get_elasticsearch_index_by_id(index='ci-status', id=id)
45
- for version, value in data['_source'].items():
46
- if version in display_versions and value not in new_versions.values() and len(value) < self.MAX_VERSION_LEN:
47
- # Display only numbers in the Grafana panel, removing characters
48
- new_versions[value.translate(str.maketrans('', '', '.-rcef'))] = value
69
+ for resource, version in data['_source'].items():
70
+ if resource in display_versions and version not in new_versions.values() and len(version) < self.MAX_VERSION_LEN:
71
+ # Normalize version for Grafana panel if it contains non-digit characters
72
+ normalized = self._normalize_version_for_grafana(version)
73
+ new_versions[normalized] = version
49
74
 
50
75
  return new_versions
51
76
 
@@ -88,9 +113,11 @@ class UpdateGrafanaLatestValueMappings:
88
113
  max_index, max_key = sorted_mapping[-1][1]['index'], sorted_mapping[-1][0]
89
114
 
90
115
  num = 1
91
- for key, value in last_versions.items():
92
- if not self.value_mappings.get(key):
93
- self.value_mappings[key] = {"index": int(max_index) + num, "text": value}
116
+ for version_key, version in last_versions.items():
117
+ if not self.value_mappings.get(version_key) or self.value_mappings[version_key]['text'] != version:
118
+ # Normalize version for Grafana panel
119
+ normalized = self._normalize_version_for_grafana(version)
120
+ self.value_mappings[normalized] = {"index": int(max_index) + num, "text": version}
94
121
  num += 1
95
122
 
96
123
  def update_main_libsonnet(self):
@@ -42,6 +42,8 @@ class OC(SSH):
42
42
  self.__kata_csv = self.__environment_variables_dict.get('kata_csv', '')
43
43
  self.__worker_disk_prefix = self.__environment_variables_dict.get('worker_disk_prefix', '')
44
44
  self.__worker_disk_ids = self.__environment_variables_dict.get('worker_disk_ids', '')
45
+ self.__skip_all_namespaces_operators_list = ast.literal_eval(self.__environment_variables_dict.get('skip_all_namespaces_operators_list', ''))
46
+ self.__skip_operators_pattern_list = "|".join(self.__skip_all_namespaces_operators_list)
45
47
  if self.__worker_disk_ids:
46
48
  self.__worker_disk_ids = ast.literal_eval(self.__worker_disk_ids)
47
49
  self._cli = self.__environment_variables_dict.get('cli', '')
@@ -50,6 +52,10 @@ class OC(SSH):
50
52
  else:
51
53
  self._kubeadmin_password = self.__environment_variables_dict.get('kubeadmin_password', '')
52
54
  self._kubeconfig_path = self.__environment_variables_dict.get('kubeconfig_path', '')
55
+ self._must_gather_log = self.__environment_variables_dict.get('must_gather_log', '')
56
+ self._run_artifacts_path = self.__environment_variables_dict.get('run_artifacts_path', '')
57
+ self._cnv_version = self.__environment_variables_dict.get('cnv_version', '')
58
+ self._odf_version = self.__environment_variables_dict.get('odf_version', '')
53
59
  # Singleton Login class
54
60
  SingletonOCLogin(self)
55
61
 
@@ -89,8 +95,9 @@ class OC(SSH):
89
95
  @param upgrade_channel: upgrade channel candidate or stable, default stable
90
96
  @return:
91
97
  """
98
+ # default stable
99
+ upgrade_channel = upgrade_channel or 'stable'
92
100
  ocp_channel = '.'.join(upgrade_ocp_version.split('.')[:2])
93
-
94
101
  # see: https://access.redhat.com/articles/7031404
95
102
  if ocp_channel == "4.16":
96
103
  patch_command = f"{self._cli} -n openshift-config patch cm admin-acks --patch '{{\"data\":{{\"ack-4.15-kube-1.29-api-removals-in-4.16\":\"true\"}}}}' --type=merge"
@@ -101,25 +108,37 @@ class OC(SSH):
101
108
 
102
109
  def upgrade_in_progress(self):
103
110
  """
104
- This method returns True when an upgrade is in progress and False when it is not.
105
- @return: bool
111
+ Checks whether an OpenShift upgrade is in progress by inspecting the 'Progressing' status condition.
112
+ Retries on transient failures.
113
+
114
+ @return: bool - True if upgrade is in progress, False otherwise.
106
115
  """
107
- status = self.run(f"{self._cli} get clusterversion version -o jsonpath='{{.status.conditions[?(@.type==\"Progressing\")].status}}'")
108
- return status == 'True'
116
+ for i in range(1, self.RETRIES + 1):
117
+ try:
118
+ status = self.run(f"{self._cli} get clusterversion version -o jsonpath='{{.status.conditions[?(@.type==\"Progressing\")].status}}'").strip()
119
+ return status == 'True'
120
+ except Exception as e:
121
+ logger.warning(f"[upgrade_in_progress] attempt {i}/{self.RETRIES} failed: {e}")
122
+ time.sleep(self.DELAY)
123
+
124
+ return False
109
125
 
110
126
  @logger_time_stamp
111
127
  def wait_for_ocp_upgrade_start(self, upgrade_version: str, timeout: int = SHORT_TIMEOUT):
112
128
  """
113
- This method waits for ocp upgrade to start
114
- :param upgrade_version:
115
- :param timeout:
116
- :return:
129
+ This method waits for the OCP upgrade to start.
130
+ :param upgrade_version: The target OCP version.
131
+ :param timeout: Timeout in seconds (waits indefinitely if <= 0).
132
+ :return: True if upgrade starts within timeout, else raises UpgradeNotStartTimeout.
117
133
  """
118
134
  current_wait_time = 0
119
- while timeout <= 0 or current_wait_time <= timeout and not self.upgrade_in_progress():
120
- # sleep for x seconds
135
+ while timeout <= 0 or current_wait_time <= timeout:
136
+ if self.upgrade_in_progress():
137
+ return True
121
138
  time.sleep(OC.SLEEP_TIME)
122
139
  current_wait_time += OC.SLEEP_TIME
140
+
141
+ # Final check after timeout
123
142
  if self.upgrade_in_progress():
124
143
  return True
125
144
  else:
@@ -139,34 +158,36 @@ class OC(SSH):
139
158
  """
140
159
  return self.run(f"{self._cli} get clusterversion version -o jsonpath='{{.status.conditions[?(@.type==\"Progressing\")].message}}'")
141
160
 
142
- def get_operator_version(self, namespace):
161
+ def get_operator_version(self, namespace: str, operator_name: str = None):
143
162
  """
144
163
  This method returns the operator version from the specified namespace.
145
164
  @param namespace: str - The namespace to search for the operator version.
165
+ @param operator_name: str - The name of the operator to search for.
146
166
  @return: major version
147
167
  """
148
- version = self.run(f"{self._cli} get csv -n {namespace} -o jsonpath='{{.items[0].spec.version}}'")
168
+ cmd = f"""{self._cli} get csv -n {namespace} -o json | jq -r '.items[] | select(.metadata.name | startswith("{operator_name}")) | .spec.version'"""
169
+ version = self.run(cmd)
149
170
  return '.'.join(version.split('.')[:2])
150
171
 
151
- def wait_for_operator_installation(self, operator: str, version: str, namespace: str, timeout: int = SHORT_TIMEOUT):
172
+ def wait_for_operator_installation(self, operator_name: str, version: str, namespace: str, timeout: int = int(environment_variables.environment_variables_dict['timeout'])):
152
173
  """
153
174
  This method waits till operator version is installed successfully
154
- @param operator:
175
+ @param operator_name:
155
176
  @param version:
156
177
  @param timeout:
157
178
  @param namespace:
158
179
  @return:
159
180
  """
160
181
  current_wait_time = 0
161
- while timeout <= 0 or current_wait_time <= timeout and not self.get_operator_version(namespace) == version:
182
+ while timeout <= 0 or current_wait_time <= timeout and not self.get_operator_version(namespace, operator_name) == version:
162
183
  # sleep for x seconds
163
184
  time.sleep(OC.SLEEP_TIME)
164
185
  current_wait_time += OC.SLEEP_TIME
165
- if self.get_operator_version(namespace) == version:
166
- logger.info(f'{operator} operator version: {version} in namespace: {namespace} has been installed successfully')
186
+ if self.get_operator_version(namespace, operator_name) == version:
187
+ logger.info(f'{operator_name} operator version: {version} in namespace: {namespace} has been installed successfully')
167
188
  return True
168
189
  else:
169
- raise OperatorInstallationTimeout(operator=operator, version=version, namespace=namespace)
190
+ raise OperatorInstallationTimeout(operator=operator_name, version=version, namespace=namespace)
170
191
 
171
192
  def healthcheck(self, action: str):
172
193
  """
@@ -186,6 +207,20 @@ class OC(SSH):
186
207
  """
187
208
  return self.run(f"{self._cli} get csv -n openshift-cnv -o json | jq -r '.items[] | select(.metadata.name | startswith(\"kubevirt-hyperconverged-operator\")) | .spec.version'")
188
209
 
210
+ def get_nhc_version(self):
211
+ """
212
+ This method returns Node Health Check Operator version
213
+ :return:
214
+ """
215
+ return self.run(f"""{self._cli} get csv -n openshift-workload-availability -o json | jq -r '.items[] | select(.metadata.name | startswith("node-healthcheck-operator")) | .spec.version'""")
216
+
217
+ def get_far_version(self):
218
+ """
219
+ This method returns Fence Agents Remediation Operator version
220
+ :return:
221
+ """
222
+ return self.run(f"""{self._cli} get csv -n openshift-workload-availability -o json | jq -r '.items[] | select(.metadata.name | startswith("fence-agents-remediation")) | .spec.version'""")
223
+
189
224
  def get_odf_version(self):
190
225
  """
191
226
  This method returns the ODF version by extracting it from the csv name.
@@ -517,6 +552,9 @@ class OC(SSH):
517
552
  time.sleep(wait_time)
518
553
  current_wait_time += wait_time
519
554
  logger.info(f"oc get nodes:\n{self.run('oc get nodes')}")
555
+ if self._must_gather_log:
556
+ self.generate_must_gather(run_artifacts_path=self._run_artifacts_path, cnv_version=self._cnv_version,
557
+ odf_version=self._odf_version)
520
558
  raise NodeNotReady(nodes_status=nodes_status)
521
559
 
522
560
  @typechecked
@@ -944,8 +982,8 @@ class OC(SSH):
944
982
  current_wait_time = 0
945
983
 
946
984
  while timeout <= 0 or current_wait_time <= timeout:
947
- # Filter out node-healthcheck-operator and self-node-remediation during CSV verification because they exist in all namespaces
948
- upgrade_versions = self.run(f"{self._cli} get csv -n {namespace} -o json | jq -r '.items[] | select(.metadata.name | test(\"node-healthcheck-operator|self-node-remediation\") | not) | .spec.version'".splitlines()
985
+ # Skip all namespaces operators during CSV verification because they exist in all namespaces
986
+ upgrade_versions = self.run(f"{self._cli} get csv -n {namespace} -o json | jq -r '.items[] | select(.metadata.name | test(\"{self.__skip_operators_pattern_list}\") | not) | .spec.version'".splitlines()
949
987
  ).splitlines()
950
988
  count_upgrade_version = sum(1 for actual_upgrade_version in upgrade_versions if
951
989
  '.'.join(actual_upgrade_version.split('.')[0:2]) == upgrade_version)
@@ -1521,6 +1559,29 @@ class OC(SSH):
1521
1559
  results_list.append(line.strip().split(':')[data_index:])
1522
1560
  return results_list
1523
1561
 
1562
+ @typechecked
1563
+ @logger_time_stamp
1564
+ def generate_ocp_must_gather(self, destination_path: str = '/tmp'):
1565
+ """
1566
+ Generates OpenShift must-gather and stores it in the destination path.
1567
+
1568
+ :param destination_path: The directory where the must-gather logs will be stored. Default is '/tmp'.
1569
+ :return: The result of the run command.
1570
+ :raises: RuntimeError if the command fails.
1571
+ """
1572
+ folder_path = os.path.join(destination_path, "must-gather")
1573
+
1574
+ try:
1575
+ command = f'oc adm must-gather --dest-dir={folder_path}'
1576
+ self.run(command)
1577
+ except Exception as e:
1578
+ if os.path.exists(folder_path):
1579
+ try:
1580
+ shutil.rmtree(folder_path)
1581
+ except Exception as remove_error:
1582
+ raise RuntimeError(f"Failed to remove folder {folder_path}: {remove_error}")
1583
+ raise RuntimeError(f"Failed to generate OCP must-gather logs for version: {e}")
1584
+
1524
1585
  @typechecked
1525
1586
  @logger_time_stamp
1526
1587
  def generate_odf_must_gather(self, destination_path: str = '/tmp', odf_version: str = None):
@@ -1582,21 +1643,32 @@ class OC(SSH):
1582
1643
  raise RuntimeError(f"Failed to remove folder {folder_path}: {remove_error}")
1583
1644
  raise RuntimeError(f"Failed to generate CNV must-gather logs for version {cnv_version}: {e}")
1584
1645
 
1585
- def save_to_yaml(self, vm_name, output_dir='/tmp', namespace: str = environment_variables.environment_variables_dict['namespace']):
1646
+ def generate_must_gather(self, run_artifacts_path, cnv_version, odf_version):
1647
+ """
1648
+ This method generates must gather and saves it in the run artifacts path
1649
+ """
1650
+ self.generate_ocp_must_gather(destination_path=run_artifacts_path)
1651
+ self.generate_cnv_must_gather(destination_path=run_artifacts_path, cnv_version=cnv_version)
1652
+ self.generate_odf_must_gather(destination_path=run_artifacts_path, odf_version=odf_version)
1653
+
1654
+ def save_to_yaml(self, vm_name, vm_access, output_dir='/tmp', namespace: str = environment_variables.environment_variables_dict['namespace']):
1586
1655
  """
1587
1656
  This method save pod and vm into yaml per namespace
1588
1657
  :param vm_name:
1658
+ :param vm_access: True is vm accessible, if not there is no pod launcher
1589
1659
  :param namespace:
1590
1660
  :param output_dir:
1591
1661
  :return:
1592
1662
  """
1593
- self.run(f"oc get vmi '{vm_name}' -n '{namespace}' -o yaml > '{output_dir}/{vm_name}.yaml'")
1594
- pod_name = self.run(
1595
- f"oc get pod -n '{namespace}' -o jsonpath=\"{{.items[?(@.metadata.generateName=='virt-launcher-{vm_name}-')].metadata.name}}\""
1596
- )
1597
- self.run(f"oc get pod '{pod_name}' -n '{namespace}' -o yaml > '{output_dir}/{pod_name}.yaml'")
1663
+ self.run(f"oc get vm '{vm_name}' -n '{namespace}' -o yaml > '{output_dir}/vm-{vm_name}.yaml'")
1664
+ if vm_access:
1665
+ self.run(f"oc get vmi '{vm_name}' -n '{namespace}' -o yaml > '{output_dir}/vmi-{vm_name}.yaml'")
1666
+ pod_name = self.run(
1667
+ f"oc get pod -n '{namespace}' -o jsonpath=\"{{.items[?(@.metadata.generateName=='virt-launcher-{vm_name}-')].metadata.name}}\""
1668
+ )
1669
+ self.run(f"oc get pod '{pod_name}' -n '{namespace}' -o yaml > '{output_dir}/{pod_name}.yaml'")
1598
1670
 
1599
- def save_describe_yml(self, vm_name, vm_access, output_dir='/tmp', namespace: str = environment_variables.environment_variables_dict['namespace']):
1671
+ def save_describe_yaml(self, vm_name, vm_access, output_dir='/tmp', namespace: str = environment_variables.environment_variables_dict['namespace']):
1600
1672
  """
1601
1673
  This method save pod and vm into yaml per namespace
1602
1674
  :param vm_name:
@@ -1605,11 +1677,10 @@ class OC(SSH):
1605
1677
  :param output_dir:
1606
1678
  :return:
1607
1679
  """
1680
+ self.run(f"oc describe vm '{vm_name}' -n '{namespace}' > '{output_dir}/describe-vm-{vm_name}.yaml'")
1608
1681
  if vm_access:
1609
- self.run(f"oc describe vmi '{vm_name}' -n '{namespace}' > '{output_dir}/describe_vmi_{vm_name}.yaml'")
1682
+ self.run(f"oc describe vmi '{vm_name}' -n '{namespace}' > '{output_dir}/describe-vmi-{vm_name}.yaml'")
1610
1683
  pod_name = self.run(
1611
1684
  f'oc get pod -n {namespace} -o jsonpath="{{.items[?(@.metadata.generateName==\'virt-launcher-{vm_name}-\')].metadata.name}}"'
1612
1685
  )
1613
- self.run(f"oc describe pod '{pod_name}' -n '{namespace}' > '{output_dir}/describe_pod_{pod_name}.yaml'")
1614
- else:
1615
- self.run(f"oc describe vm '{vm_name}' -n '{namespace}' > '{output_dir}/describe_vm_{vm_name}.yaml'")
1686
+ self.run(f"oc describe pod '{pod_name}' -n '{namespace}' > '{output_dir}/describe-pod-{pod_name}.yaml'")
@@ -42,18 +42,18 @@ class CreateCNV(CreateOCPResourceOperations):
42
42
  if cnv_nightly_channel:
43
43
  # wait till get the patch
44
44
  self.wait_for_ocp_resource_create(operator=resource,
45
- verify_cmd="oc get InstallPlan -n openshift-cnv -o jsonpath={.items[0].metadata.name}",
45
+ verify_cmd="oc get installplan -n openshift-cnv -o json | jq -r '.items[] | select(.spec.clusterServiceVersionNames[] | startswith(\"kubevirt-hyperconverged-operator\")) | .metadata.name'",
46
46
  status="install-")
47
47
  self.apply_patch(namespace='openshift-cnv', operator='cnv')
48
48
  # stable channel
49
49
  else:
50
50
  self.wait_for_ocp_resource_create(operator='cnv',
51
- verify_cmd="oc get csv -n openshift-cnv -o jsonpath='{.items[0].status.phase}'",
51
+ verify_cmd="""oc get csv -n openshift-cnv -o json | jq -r '.items[] | select(.metadata.name | startswith("kubevirt-hyperconverged-operator")) | .status.phase'""",
52
52
  status='Succeeded')
53
53
  # for second script wait for refresh status
54
54
  if '02_hyperconverge.yaml' in resource:
55
55
  # Wait that till succeeded
56
56
  self.wait_for_ocp_resource_create(operator='cnv',
57
- verify_cmd="oc get csv -n openshift-cnv -o jsonpath='{.items[0].status.phase}'",
57
+ verify_cmd = """oc get csv -n openshift-cnv -o json | jq -r '.items[] | select(.metadata.name | startswith("kubevirt-hyperconverged-operator")) | .status.phase'""",
58
58
  status='Succeeded')
59
59
  return True
@@ -10,11 +10,14 @@ class CreateLSO(CreateOCPResourceOperations):
10
10
  """
11
11
  This class is created Local Storage operator
12
12
  """
13
- def __init__(self, oc: OC, path: str, resource_list: list):
13
+ def __init__(self, oc: OC, path: str, resource_list: list, lso_node: str, lso_disk_id: str, ceph_version: str):
14
14
  super().__init__(oc)
15
15
  self.__oc = oc
16
16
  self.__path = path
17
17
  self.__resource_list = resource_list
18
+ self.__lso_node = lso_node
19
+ self.__lso_disk_id = lso_disk_id
20
+ self.__ceph_version = ceph_version
18
21
 
19
22
  @logger_time_stamp
20
23
  def create_lso(self, upgrade_version: str):
@@ -29,7 +32,15 @@ class CreateLSO(CreateOCPResourceOperations):
29
32
  else:
30
33
  for resource in self.__resource_list:
31
34
  logger.info(f'run {resource}')
32
- self.__oc.create_async(yaml=os.path.join(self.__path, resource))
35
+ if resource.endswith('.sh'):
36
+ if '01_delete_disks.sh' == resource and self.__lso_disk_id:
37
+ disk = f'/dev/disk/by-id/{self.__lso_disk_id}'
38
+ delete_node_disk = f""" podman run --authfile /var/lib/kubelet/config.json --rm --privileged --device "$(readlink -e '{disk}')" --entrypoint ceph-bluestore-tool quay.io/ceph/ceph:v{self.__ceph_version} zap-device --dev "$(readlink -e '{disk}')" --yes-i-really-really-mean-it """
39
+ logger.info(f'{self.__lso_node}: {delete_node_disk}')
40
+ self.__oc.run(cmd=f'chmod +x {os.path.join(self.__path, resource)}; {self.__path}/{resource} "{self.__lso_node}" "{delete_node_disk}"')
41
+ else:
42
+ logger.info(f'run {resource}')
43
+ self.__oc.create_async(yaml=os.path.join(self.__path, resource))
33
44
 
34
45
  # verify once after create all resource files
35
46
  self.wait_for_ocp_resource_create(operator='lso',
@@ -0,0 +1,51 @@
1
+ import os
2
+
3
+ from benchmark_runner.common.oc.oc import OC
4
+ from benchmark_runner.common.logger.logger_time_stamp import logger_time_stamp, logger
5
+ from benchmark_runner.common.ocp_resources.create_ocp_resource_operations import CreateOCPResourceOperations
6
+
7
+
8
+ class CreateNHCFAR(CreateOCPResourceOperations):
9
+ """
10
+ This class is created node-health-check and fence-agents-remediation operators
11
+ """
12
+
13
+ def __init__(self, oc: OC, path: str, resource_list: list):
14
+ super().__init__(oc)
15
+ self.__oc = oc
16
+ self.__path = path
17
+ self.__resource_list = resource_list
18
+
19
+ @logger_time_stamp
20
+ def create_nhc_far(self):
21
+ """
22
+ This method creates node-health-check and fence-agents-remediation operators
23
+ :return:
24
+ """
25
+ for resource in self.__resource_list:
26
+ logger.info(f'run {resource}')
27
+ self.__oc.create_async(yaml=os.path.join(self.__path, resource))
28
+
29
+ if '03_nhc_subscription.yaml' in resource:
30
+ self.wait_for_ocp_resource_create(operator='nhc',
31
+ verify_cmd=f"oc get csv -n openshift-workload-availability -o json | jq -r '.items[] | select(.metadata.name | startswith(\"node-healthcheck-operator\")) | .status.phase'",
32
+ status='Succeeded')
33
+ if '04_far_subscription.yaml' in resource:
34
+ self.wait_for_ocp_resource_create(operator='far',
35
+ verify_cmd=f"oc get csv -n openshift-workload-availability -o json | jq -r '.items[] | select(.metadata.name | startswith(\"fence-agents-remediation\")) | .status.phase'",
36
+ status='Succeeded')
37
+ if '05_nhc_far.yaml' in resource:
38
+ # Wait for NHC to be enabled using a retries mechanism
39
+ for _ in range(self.__oc.RETRIES):
40
+ try:
41
+ self.wait_for_ocp_resource_create(
42
+ operator='nhc_far',
43
+ verify_cmd="oc get nhc -A -o jsonpath='{range .items[*]}{.status.phase}{\"\\n\"}{end}'",
44
+ status='Enabled',
45
+ timeout=600
46
+ )
47
+ break
48
+ except:
49
+ # rerun latest resource creation, if nhc is not enabled
50
+ self.__oc.create_async(yaml=os.path.join(self.__path, resource))
51
+ return True
@@ -8,7 +8,7 @@ from benchmark_runner.common.ocp_resources.create_lso import CreateLSO
8
8
  from benchmark_runner.common.ocp_resources.create_odf import CreateODF
9
9
  from benchmark_runner.common.ocp_resources.create_kata import CreateKata
10
10
  from benchmark_runner.common.ocp_resources.create_cnv import CreateCNV
11
- from benchmark_runner.common.ocp_resources.create_nhc_snr import CreateNHCSNR
11
+ from benchmark_runner.common.ocp_resources.create_nhc_far import CreateNHCFAR
12
12
  from benchmark_runner.common.ocp_resources.create_custom import CreateCustom
13
13
  from benchmark_runner.common.ocp_resources.migrate_infra import MigrateInfra
14
14
 
@@ -24,6 +24,10 @@ class CreateOCPResource:
24
24
  self.__oc.populate_additional_template_variables(self.__environment_variables_dict)
25
25
  self.__worker_disk_prefix = self.__environment_variables_dict.get('worker_disk_prefix', '')
26
26
  self.__worker_disk_ids = self.__environment_variables_dict.get('worker_disk_ids', '')
27
+ self.__worker_disk_ids = self.__environment_variables_dict.get('worker_disk_ids', '')
28
+ self.__lso_disk_id = self.__environment_variables_dict.get('lso_disk_id', '')
29
+ self.__lso_node = self.__environment_variables_dict.get('lso_node', '')
30
+ self.__ceph_version = self.__environment_variables_dict.get('ceph_version', '')
27
31
  if self.__worker_disk_ids:
28
32
  if self.__worker_disk_ids:
29
33
  # Solved GitHub Actions issue that env variable detect as string instead of dict/ list -skip for Jenkins
@@ -80,7 +84,7 @@ class CreateOCPResource:
80
84
  self.remove_resource_files(path=os.path.join(self.__dir_path, resource))
81
85
  resource_files = self.get_sorted_resources(resource=resource)
82
86
  if 'lso' == resource:
83
- create_lso = CreateLSO(self.__oc, path=os.path.join(self.__dir_path, resource), resource_list=resource_files)
87
+ create_lso = CreateLSO(self.__oc, path=os.path.join(self.__dir_path, resource), resource_list=resource_files, lso_node=self.__lso_node, lso_disk_id=self.__lso_disk_id, ceph_version=self.__ceph_version)
84
88
  create_lso.create_lso(upgrade_version)
85
89
  elif 'odf' == resource:
86
90
  create_odf = CreateODF(self.__oc, path=os.path.join(self.__dir_path, resource), resource_list=resource_files, worker_disk_ids=self.__worker_disk_ids, worker_disk_prefix=self.__worker_disk_prefix)
@@ -91,9 +95,9 @@ class CreateOCPResource:
91
95
  elif 'cnv' == resource:
92
96
  create_cnv = CreateCNV(self.__oc, path=os.path.join(self.__dir_path, resource), resource_list=resource_files)
93
97
  create_cnv.create_cnv()
94
- elif 'nhc_snr' == resource:
95
- create_nhc_snr = CreateNHCSNR(self.__oc, path=os.path.join(self.__dir_path, resource), resource_list=resource_files)
96
- create_nhc_snr.create_nhc_snr()
98
+ elif 'nhc_far' == resource:
99
+ create_nhc_far = CreateNHCFAR(self.__oc, path=os.path.join(self.__dir_path, resource), resource_list=resource_files)
100
+ create_nhc_far.create_nhc_far()
97
101
  elif 'infra' == resource:
98
102
  create_infra = MigrateInfra(self.__oc, path=os.path.join(self.__dir_path, resource), resource_list=resource_files)
99
103
  create_infra.migrate_infra()
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env sh
2
+
3
+ while (($# >= 2)); do
4
+ node="$1"
5
+ delete_disk_command="$2"
6
+
7
+ echo "Executing deletion on node: $node"
8
+
9
+ oc debug "node/$node" -- chroot /host sh -c "$delete_disk_command"
10
+
11
+ shift 2
12
+ done
@@ -7,6 +7,10 @@ spec:
7
7
  channel: "stable"
8
8
  installPlanApproval: Automatic
9
9
  name: local-storage-operator
10
+ {%- if upgrade_ocp_version %}
11
+ source: redhat-operators
12
+ {%- else %}
10
13
  source: redhat-operators-v{{ lso_version | replace('.', '') }} # <-- Modify the name of the redhat-operators catalogsource if not default
14
+ {%- endif %}
11
15
  sourceNamespace: openshift-marketplace
12
16
 
@@ -0,0 +1,11 @@
1
+ apiVersion: operators.coreos.com/v1alpha1
2
+ kind: Subscription
3
+ metadata:
4
+ name: fence-agents-remediation-subscription
5
+ namespace: openshift-workload-availability
6
+ spec:
7
+ channel: stable
8
+ name: fence-agents-remediation
9
+ source: redhat-operators
10
+ sourceNamespace: openshift-marketplace
11
+ package: fence-agents-remediation