13
13
import datetime
14
14
import pprint
15
15
import re
16
+ from contextlib import contextmanager
16
17
from functools import cached_property
17
18
import json
19
+ from typing import Iterator , Any
18
20
from unittest import SkipTest
19
21
20
22
import yaml
@@ -62,6 +64,13 @@ def tearDown(self) -> None:
62
64
63
65
super ().tearDown ()
64
66
67
+ @contextmanager
68
+ def logged_subtest (self , action : str ,
69
+ trace_id : str | None = None , metadata : dict [str , Any ] | None = None ) -> Iterator [None ]:
70
+ with self .actions_log .action_scope (action , self .node .name , trace_id , metadata ):
71
+ with self .subTest (msg = action ):
72
+ yield
73
+
65
74
# since this logic id depended on code run by SCT to mark uuid as test, since commit 617026aa, this code it run in the background
66
75
# and not being waited for, so we need to compensate for it here with retries
67
76
@retrying (n = 15 , sleep_time = 10 , allowed_exceptions = (AssertionError ,))
@@ -71,6 +80,7 @@ def check_scylla_version_in_housekeepingdb(self, prev_id: int, expected_status_c
71
80
Validate reported version
72
81
prev_id: check if new version is created
73
82
"""
83
+ self .actions_log .info ("Validating scylla version in housekeepingdb" , target = self .node .name )
74
84
assert self .node .uuid , "Node UUID wasn't created"
75
85
76
86
row = self .housekeeping .get_most_recent_record (query = f"SELECT id, version, ip, statuscode "
@@ -104,7 +114,7 @@ def check_scylla_version_in_housekeepingdb(self, prev_id: int, expected_status_c
104
114
assert row [0 ] > prev_id , f"New row wasn't saved in { self .CHECK_VERSION_TABLE } "
105
115
else :
106
116
assert row [0 ] == prev_id , f"New row was saved in { self .CHECK_VERSION_TABLE } unexpectedly"
107
-
117
+ self . actions_log . info ( "Scylla version in housekeepingdb is validated" , target = self . node . name )
108
118
return row [0 ] if row else 0
109
119
110
120
@property
@@ -134,10 +144,10 @@ def run_cassandra_stress(self, args: str):
134
144
transport_str = c_s_transport_str (
135
145
self .params .get ('peer_verification' ), self .params .get ('client_encrypt_mtls' ))
136
146
stress_cmd += f" -transport '{ transport_str } '"
137
-
138
- result = self .node .remoter .run (stress_cmd )
139
- assert "java.io.IOException" not in result .stdout
140
- assert "java.io.IOException" not in result .stderr
147
+ with self . actions_log . action_scope ( "running cassandra-stress" , target = self . node . name , metadata = { "stress_cmd" : stress_cmd }):
148
+ result = self .node .remoter .run (stress_cmd )
149
+ assert "java.io.IOException" not in result .stdout
150
+ assert "java.io.IOException" not in result .stderr
141
151
142
152
def check_scylla (self ):
143
153
self .node .run_nodetool ("status" )
@@ -223,6 +233,8 @@ def verify_snitch(self, backend_name: str):
223
233
"""
224
234
if not self .params .get ("use_preinstalled_scylla" ):
225
235
self .log .info ("Skipping verifying the snitch due to the 'use_preinstalled_scylla' being set to False" )
236
+ self .actions_log .info (
237
+ "Skipping verifying the snitch due to the 'use_preinstalled_scylla' being set to False" , target = self .node .name )
226
238
return
227
239
228
240
describecluster_snitch = self .get_describecluster_info ().snitch
@@ -234,13 +246,13 @@ def verify_snitch(self, backend_name: str):
234
246
snitch_matches_describecluster = [pattern .search (describecluster_snitch ) for pattern in snitch_patterns ]
235
247
snitch_matches_scylla_yaml = [pattern .search (scylla_yaml_snitch ) for pattern in snitch_patterns ]
236
248
237
- with self .subTest ('verify snitch against describecluster output' ):
249
+ with self .logged_subtest ('verify snitch against describecluster output' ):
238
250
self .assertTrue (any (snitch_matches_describecluster ),
239
251
msg = f"Expected snitch matches for describecluster to not be empty, but was. Snitch "
240
252
f"matches: { snitch_matches_describecluster } "
241
253
)
242
254
243
- with self .subTest ('verify snitch against scylla.yaml configuration' ):
255
+ with self .logged_subtest ('verify snitch against scylla.yaml configuration' ):
244
256
self .assertTrue (any (snitch_matches_scylla_yaml ),
245
257
msg = f"Expected snitch matches for scylla yaml to not be empty, but was. Snitch "
246
258
f"matches: { snitch_matches_scylla_yaml } "
@@ -263,6 +275,7 @@ def verify_docker_latest_match_release(self) -> None:
263
275
264
276
def verify_nvme_write_cache (self ) -> None :
265
277
if self .write_back_cache is None or self .node .parent_cluster .is_additional_data_volume_used ():
278
+ self .actions_log .info ("Skipped verifying NVMe write cache" , target = self .node .name )
266
279
return
267
280
expected_write_cache_value = "write back" if self .write_back_cache else "write through"
268
281
@@ -323,11 +336,11 @@ def test_scylla_service(self):
323
336
backend = self .params .get ("cluster_backend" )
324
337
325
338
if backend == "aws" :
326
- with self .subTest ("check ENA support" ):
339
+ with self .logged_subtest ("check ENA support" ):
327
340
assert self .node .ena_support , "ENA support is not enabled"
328
341
329
342
if backend in ["gce" , "aws" , "azure" ] and self .params .get ("use_preinstalled_scylla" ):
330
- with self .subTest ("check Scylla IO Params" ):
343
+ with self .logged_subtest ("check Scylla IO Params" ):
331
344
try :
332
345
if self .node .db_node_instance_type in ["t3.micro" ]:
333
346
self .skipTest (
@@ -342,57 +355,58 @@ def test_scylla_service(self):
342
355
)
343
356
except SkipTest as exc :
344
357
self .log .info ("Skipping IOTuneValidation due to %s" , exc .args )
358
+ self .actions_log .info ("Skipped IOTuneValidation" , target = self .node .name )
345
359
except Exception : # noqa: BLE001
346
360
self .log .error ("IOTuneValidator failed" , exc_info = True )
347
361
TestFrameworkEvent (source = {self .__class__ .__name__ },
348
362
message = "Error during IOTune params validation." ,
349
363
severity = Severity .ERROR ).publish ()
350
364
351
- with self .subTest ("verify write cache for NVMe devices" ):
365
+ with self .logged_subtest ("verify write cache for NVMe devices" ):
352
366
self .verify_nvme_write_cache ()
353
367
354
368
if (backend != "docker" and not self .params .get ("nonroot_offline_install" )
355
369
and self .node .db_node_instance_type != "t3.micro" ):
356
- with self .subTest ("verify XFS online discard enabled" ):
370
+ with self .logged_subtest ("verify XFS online discard enabled" ):
357
371
self .verify_xfs_online_discard_enabled ()
358
372
359
373
if backend == "gce" :
360
- with self .subTest ("verify users" ):
374
+ with self .logged_subtest ("verify users" ):
361
375
self .verify_users ()
362
376
363
377
expected_housekeeping_status_code = 'cr' if backend == "docker" else 'r'
364
378
365
379
if self .params .get ("use_preinstalled_scylla" ) and backend != "docker" :
366
- with self .subTest ("check the cluster name" ):
380
+ with self .logged_subtest ("check the cluster name" ):
367
381
self .check_cluster_name ()
368
382
369
- with self .subTest ('verify snitch' ):
383
+ with self .logged_subtest ('verify snitch' ):
370
384
self .verify_snitch (backend_name = backend )
371
385
372
- with self .subTest ('verify node health' ):
386
+ with self .logged_subtest ('verify node health' ):
373
387
self .verify_node_health ()
374
388
375
- with self .subTest ("check Scylla server after installation" ):
389
+ with self .logged_subtest ("check Scylla server after installation" ):
376
390
self .check_scylla ()
377
391
378
- with self .subTest ("check cqlsh installation" ):
392
+ with self .logged_subtest ("check cqlsh installation" ):
379
393
self .check_cqlsh ()
380
394
381
- with self .subTest ("check node_exporter liveness" ):
395
+ with self .logged_subtest ("check node_exporter liveness" ):
382
396
node_info_service = NodeLoadInfoServices ().get (self .node )
383
397
assert node_info_service .cpu_load_5
384
398
assert node_info_service .get_node_boot_time_seconds ()
385
399
386
- with self .subTest ( "check scylla_doctor results " ):
387
- if self .params . get ( "run_scylla_doctor " ):
400
+ if self .params . get ( "run_scylla_doctor " ):
401
+ with self .logged_subtest ( "check scylla_doctor results " ):
388
402
self .run_scylla_doctor ()
389
- else :
390
- self .log .info ("Running scylla-doctor is disabled" )
403
+ else :
404
+ self .log .info ("Running scylla-doctor is disabled" )
391
405
392
406
# We don't install any time sync service in docker, so the test is unnecessary:
393
407
# https://github.com/scylladb/scylla/tree/master/dist/docker/etc/supervisord.conf.d
394
408
if backend != "docker" :
395
- with self .subTest ("check if scylla unnecessarily installed a time synchronization service" ):
409
+ with self .logged_subtest ("check if scylla unnecessarily installed a time synchronization service" ):
396
410
# Checks https://github.com/scylladb/scylla/issues/8339
397
411
# If the instance already has systemd-timesyncd
398
412
is_timesyncd_service_installed = self .check_service_existence (service_name = "systemd-timesyncd" )
@@ -443,24 +457,24 @@ def test_scylla_service(self):
443
457
# backend=backend)
444
458
445
459
version_id_after_stop = 0
446
- with self .subTest ("check Scylla server after stop/start" ):
460
+ with self .logged_subtest ("check Scylla server after stop/start" ):
447
461
self .node .stop_scylla (verify_down = True )
448
462
self .node .start_scylla (verify_up = True )
449
-
450
463
# Scylla service has been stopped/started after installation and re-configuration.
451
464
# So we don't need to stop and to start it again
452
465
self .check_scylla ()
453
466
454
467
if not self .node .is_nonroot_install :
455
468
self .log .info ("Validate version after stop/start" )
456
- self .check_housekeeping_service_status (backend = backend )
457
- version_id_after_stop = self .check_scylla_version_in_housekeepingdb (
458
- prev_id = 0 ,
459
- expected_status_code = expected_housekeeping_status_code ,
460
- new_row_expected = False ,
461
- backend = backend )
462
-
463
- with self .subTest ("check Scylla server after restart" ):
469
+ with self .actions_log .action_scope ("Validate version after stop/start" ):
470
+ self .check_housekeeping_service_status (backend = backend )
471
+ version_id_after_stop = self .check_scylla_version_in_housekeepingdb (
472
+ prev_id = 0 ,
473
+ expected_status_code = expected_housekeeping_status_code ,
474
+ new_row_expected = False ,
475
+ backend = backend )
476
+
477
+ with self .logged_subtest ("check Scylla server after restart" ):
464
478
self .node .restart_scylla (verify_up_after = True )
465
479
self .check_scylla ()
466
480
@@ -473,35 +487,41 @@ def test_scylla_service(self):
473
487
backend = backend )
474
488
475
489
if backend != 'docker' :
476
- with self .subTest ("Check the output of perftune.py" ):
490
+ with self .logged_subtest ("Check the output of perftune.py" ):
477
491
perftune_checker = PerftuneOutputChecker (self .node )
478
492
perftune_checker .compare_perftune_results ()
479
493
480
494
if backend == 'docker' :
481
- with self .subTest ("Check docker latest tags" ):
495
+ with self .logged_subtest ("Check docker latest tags" ):
482
496
self .verify_docker_latest_match_release ()
483
497
484
498
def run_scylla_doctor (self ):
485
499
if self .params .get ('client_encrypt' ) and SkipPerIssues ("https://github.com/scylladb/field-engineering/issues/2280" , self .params ):
486
500
self .log .info ("Scylla Doctor test is skipped for encrypted environment due to issue field-engineering#2280" )
501
+ self .actions_log .info (
502
+ "Scylla Doctor test is skipped for encrypted environment due to issue field-engineering#2280" )
487
503
return
488
504
489
505
if self .db_cluster .nodes [0 ].is_nonroot_install and \
490
506
SkipPerIssues ("https://github.com/scylladb/scylla-cluster-tests/issues/10540" , self .params ):
491
507
self .log .info ("Scylla Doctor test is skipped for non-root test due to issue field-engineering#2254. " )
508
+ self .actions_log .info (
509
+ "Scylla Doctor test is skipped for non-root test due to issue field-engineering#2254." )
492
510
return
493
511
494
512
if self .node .parent_cluster .cluster_backend == "docker" :
495
- self .log .info ("Scylla Doctor check in SCT isn't yet support for docker backend" )
513
+ self .log .info ("Scylla Doctor check in SCT isn't yet supported for docker backend" )
514
+ self .actions_log .info ("Scylla Doctor check in SCT isn't yet supported for docker backend" )
496
515
return
497
516
498
517
for node in self .db_cluster .nodes :
499
- scylla_doctor = ScyllaDoctor (node , self .test_config , bool (self .params .get ('unified_package' )))
500
- scylla_doctor .install_scylla_doctor ()
501
- scylla_doctor .argus_collect_sd_package ()
502
- scylla_doctor .run_scylla_doctor_and_collect_results ()
503
- scylla_doctor .analyze_vitals ()
504
- scylla_doctor .analyze_and_verify_results ()
518
+ with self .actions_log .action_scope ("installing and running Scylla Doctor" , target = node .name ):
519
+ scylla_doctor = ScyllaDoctor (node , self .test_config , bool (self .params .get ('unified_package' )))
520
+ scylla_doctor .install_scylla_doctor ()
521
+ scylla_doctor .argus_collect_sd_package ()
522
+ scylla_doctor .run_scylla_doctor_and_collect_results ()
523
+ scylla_doctor .analyze_vitals ()
524
+ scylla_doctor .analyze_and_verify_results ()
505
525
506
526
def get_email_data (self ):
507
527
self .log .info ("Prepare data for email" )
0 commit comments