From 19ce3fc78f232923cfc079cf03911274037a05be Mon Sep 17 00:00:00 2001 From: nicholasyang Date: Fri, 14 Feb 2025 14:30:12 +0800 Subject: [PATCH] Dev: migration: check if the cluster is already migrated to SLES 16 (jsc#PED-8252) * should not run the migration if already migrated * should not tell users to run `crm cluster health sles16 --fix` if already migrated --- crmsh/migration.py | 60 +++++++++++++++++++++++---------- test/features/migration.feature | 4 ++- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/crmsh/migration.py b/crmsh/migration.py index 2a98319ff..eb5dd2dbe 100644 --- a/crmsh/migration.py +++ b/crmsh/migration.py @@ -92,6 +92,7 @@ def end(self): class CheckResultInteractiveHandler(CheckResultHandler): def __init__(self): self.has_problems = False + self.has_tips = False def log_info(self, fmt: str, *args): self.write_in_color(sys.stdout, constants.GREEN, '[INFO] ') @@ -108,6 +109,7 @@ def handle_problem(self, is_fatal: bool, title: str, details: typing.Iterable[st raise MigrationFailure('Unable to start migration.') def handle_tip(self, title: str, details: typing.Iterable[str]): + self.has_tips = True self.write_in_color(sys.stdout, constants.YELLOW, '[WARN] ') print(title) for line in details: @@ -129,12 +131,17 @@ def end(self): def migrate(): try: - if 0 != _check_impl(local=False, json='', summary=False): - raise MigrationFailure('Unable to start migration.') - logger.info('Starting migration...') - migrate_corosync_conf() - logger.info('Finished migration.') - return 0 + match _check_impl(local=False, json='', summary=False): + case 0: + logger.info("This cluster works on SLES 16. No migration is needed.") + return 0 + case 1: + logger.info('Starting migration...') + migrate_corosync_conf() + logger.info('Finished migration.') + return 0 + case _: + raise MigrationFailure('Unable to start migration.') except MigrationFailure as e: logger.error('%s', e) return 1 @@ -148,18 +155,26 @@ def check(args: typing.Sequence[str]) -> int: ret = _check_impl(parsed_args.local or parsed_args.json is not None, parsed_args.json, parsed_args.json is None) if not parsed_args.json: print('****** summary ******') - if ret == 0: - CheckResultInteractiveHandler.write_in_color(sys.stdout, constants.GREEN, '[INFO]') - sys.stdout.write(' Please run "crm cluster health sles16 --fix" on on any one of above nodes.\n') - CheckResultInteractiveHandler.write_in_color(sys.stdout, constants.GREEN, '[PASS]') - sys.stdout.write(' This cluster is good to migrate to SLES 16.\n') - else: - CheckResultInteractiveHandler.write_in_color(sys.stdout, constants.RED, '[FAIL]') - sys.stdout.write(' The pacemaker cluster stack can not migrate to SLES 16.\n') + match ret: + case 0: + CheckResultInteractiveHandler.write_in_color(sys.stdout, constants.GREEN, '[INFO]') + sys.stdout.write(' This cluster works on SLES 16. No migration is needed.\n') + case 1: + CheckResultInteractiveHandler.write_in_color(sys.stdout, constants.GREEN, '[INFO]') + sys.stdout.write(' Please run "crm cluster health sles16 --fix" on on any one of above nodes.\n') + CheckResultInteractiveHandler.write_in_color(sys.stdout, constants.GREEN, '[PASS]') + sys.stdout.write(' This cluster is good to migrate to SLES 16.\n') + case _: + CheckResultInteractiveHandler.write_in_color(sys.stdout, constants.RED, '[FAIL]') + sys.stdout.write(' The pacemaker cluster stack can not migrate to SLES 16.\n') return ret -def _check_impl(local: bool, json: str, summary: bool): +def _check_impl(local: bool, json: str, summary: bool) -> int: + """Return: + * 0 if the cluster is already on SLES 16. + * 1 if the cluster is good to migrate to SLES 16. + * 2 if the cluster is not good to migrate to SLES 16.""" assert not summary or not bool(json) assert local or not bool(json) ret = 0 @@ -189,10 +204,19 @@ def _check_impl(local: bool, json: str, summary: bool): handler.end() match handler: case CheckResultJsonHandler(): - ret = 0 if handler.json_result["pass"] else 1 + if not handler.json_result["pass"]: + ret = 2 + elif handler.json_result['tips']: + ret = 1 + else: + ret = 0 case CheckResultInteractiveHandler(): if handler.has_problems: + ret = 2 + elif handler.has_tips: ret = 1 + else: + ret = 0 if check_remote_yield: remote_ret = next(check_remote_yield) if remote_ret > ret: @@ -230,7 +254,7 @@ def run(self): sys.stdout.write('\n') ret = 255 case prun.ProcessResult() as result: - if result.returncode > 1: + if result.returncode > 2: print(result.stdout.decode('utf-8', 'backslashreplace')) handler.write_in_color( sys.stdout, constants.YELLOW, @@ -258,7 +282,7 @@ def run(self): handler.handle_tip(tip.get("title", ""), tip.get("descriptions")) handler.end() if not passed: - ret = 1 + ret = 2 yield ret diff --git a/test/features/migration.feature b/test/features/migration.feature index b6a60a923..0f2c52818 100644 --- a/test/features/migration.feature +++ b/test/features/migration.feature @@ -17,6 +17,8 @@ Feature: migration And Run "crm cluster stop --all" on "hanode2" And Try "crm cluster health sles16" on "hanode1" Then Expected return code is "0" + And Expected "[INFO] This cluster works on SLES 16. No migration is needed." in stdout + Scenario: Should run fixes. When Try "crm cluster health sles16 --fix" on "hanode1" @@ -87,7 +89,7 @@ Feature: migration """ And Run "crm cluster copy /etc/corosync/corosync.conf" on "hanode1" And Try "crm cluster health sles16" on "hanode1" - Then Expected return code is "0" + Then Expected return code is "1" And Expect stdout contains snippets ["[PASS] This cluster is good to migrate to SLES 16.", "[INFO] Please run \"crm cluster health sles16 --fix\" on on any one of above nodes.", "[WARN] Corosync transport \"udpu\" will be deprecated in corosync 3. Please use knet.", "----- localhost -----", "----- hanode2 -----"]. Scenario: Run fixes against corosync.conf generated in crmsh-4.6