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.
- benchmark_runner/benchmark_operator/benchmark_operator_workloads_operations.py +1 -1
- benchmark_runner/common/clouds/BareMetal/bare_metal_operations.py +33 -18
- benchmark_runner/common/grafana/update_grafana_latest_value_mappings.py +34 -7
- benchmark_runner/common/oc/oc.py +103 -32
- benchmark_runner/common/ocp_resources/create_cnv.py +3 -3
- benchmark_runner/common/ocp_resources/create_lso.py +13 -2
- benchmark_runner/common/ocp_resources/create_nhc_far.py +51 -0
- benchmark_runner/common/ocp_resources/create_ocp_resource.py +9 -5
- benchmark_runner/common/ocp_resources/lso/template/01_delete_disks_template.sh +12 -0
- benchmark_runner/common/ocp_resources/lso/template/04_subscription_template.yaml +4 -0
- benchmark_runner/common/ocp_resources/nhc_far/template/04_far_subscription_template.yaml +11 -0
- benchmark_runner/common/ocp_resources/nhc_far/template/05_nhc_far_template.yaml +60 -0
- benchmark_runner/common/template_operations/templates/hammerdb/internal_data/hammerdb_vm_template.yaml +5 -1
- benchmark_runner/common/template_operations/templates/hammerdb/internal_data/mariadb_template.yaml +1 -1
- benchmark_runner/common/template_operations/templates/hammerdb/internal_data/mssql_template.yaml +1 -1
- benchmark_runner/common/template_operations/templates/hammerdb/internal_data/postgres_template.yaml +1 -1
- benchmark_runner/jupyterlab/templates/summary_report/summary_report_operations.py +1 -1
- benchmark_runner/krkn_hub/krknhub_workloads.py +5 -1
- benchmark_runner/main/environment_variables.py +18 -4
- benchmark_runner/workloads/bootstorm_vm.py +28 -18
- benchmark_runner/workloads/workloads_operations.py +6 -2
- {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/METADATA +3 -2
- {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/RECORD +29 -28
- {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/WHEEL +1 -1
- benchmark_runner/common/ocp_resources/create_nhc_snr.py +0 -42
- benchmark_runner/common/ocp_resources/nhc_snr/template/04_snr_subscription_template.yaml +0 -11
- benchmark_runner/common/ocp_resources/nhc_snr/template/05_nhc_snr_template.yaml +0 -41
- /benchmark_runner/common/ocp_resources/{nhc_snr → nhc_far}/template/01_namespace_template.yaml +0 -0
- /benchmark_runner/common/ocp_resources/{nhc_snr → nhc_far}/template/02_operator_group_template.yaml +0 -0
- /benchmark_runner/common/ocp_resources/{nhc_snr → nhc_far}/template/03_nhc_subscription_template.yaml +0 -0
- {benchmark_runner-1.0.813.dist-info → benchmark_runner-1.0.909.dist-info}/licenses/LICENSE +0 -0
- {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
|
|
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
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
|
46
|
-
if
|
|
47
|
-
#
|
|
48
|
-
|
|
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
|
|
92
|
-
if not self.value_mappings.get(
|
|
93
|
-
|
|
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):
|
benchmark_runner/common/oc/oc.py
CHANGED
|
@@ -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
|
-
|
|
105
|
-
|
|
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
|
-
|
|
108
|
-
|
|
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
|
|
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
|
|
120
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
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'{
|
|
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=
|
|
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
|
-
#
|
|
948
|
-
upgrade_versions = self.run(f"{self._cli} get csv -n {namespace} -o json | jq -r '.items[] | select(.metadata.name | test(\"
|
|
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
|
|
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
|
|
1594
|
-
|
|
1595
|
-
f"oc get
|
|
1596
|
-
|
|
1597
|
-
|
|
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
|
|
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}/
|
|
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}/
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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 '
|
|
95
|
-
|
|
96
|
-
|
|
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()
|
|
@@ -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
|