From 5977dacc6160a68bba6fc4fd91c4bfa17f330520 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Sun, 23 Aug 2020 15:06:46 +0200 Subject: [PATCH] `verdi status`: distinguish database schema version incompatible (#4319) If `verdi status` was called for a profile whose database schema version is incompatible with the current code, a generic error was thrown that no connection could be made to PostgreSQL. The connection is often fine, it is just that AiiDA prohibits it until the database is made compatible. Often one simply has to migrate the database after installing a newer version of the code. This case is no caught separately and the user is pointed to `verdi database migrate`. --- aiida/cmdline/commands/cmd_status.py | 15 ++++++++++----- tests/cmdline/commands/test_status.py | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/aiida/cmdline/commands/cmd_status.py b/aiida/cmdline/commands/cmd_status.py index d0615a7898..1aa6dbf825 100644 --- a/aiida/cmdline/commands/cmd_status.py +++ b/aiida/cmdline/commands/cmd_status.py @@ -8,14 +8,15 @@ # For further information please visit http://www.aiida.net # ########################################################################### """`verdi status` command.""" +import enum import sys -import enum import click from aiida.cmdline.commands.cmd_verdi import verdi from aiida.cmdline.utils import echo from aiida.common.log import override_log_level +from aiida.common.exceptions import IncompatibleDatabaseSchema from ..utils.echo import ExitCode @@ -51,7 +52,7 @@ class ServiceStatus(enum.IntEnum): @click.option('--no-rmq', is_flag=True, help='Do not check RabbitMQ status') def verdi_status(no_rmq): """Print status of AiiDA services.""" - # pylint: disable=broad-except,too-many-statements + # pylint: disable=broad-except,too-many-statements,too-many-branches from aiida.cmdline.utils.daemon import get_daemon_status, delete_stale_pid_file from aiida.common.utils import Capturing from aiida.manage.external.rmq import get_rmq_url @@ -93,8 +94,13 @@ def verdi_status(no_rmq): with override_log_level(): # temporarily suppress noisy logging backend = manager.get_backend() backend.cursor() - except Exception: - print_status(ServiceStatus.DOWN, 'postgres', 'Unable to connect as {}@{}:{}'.format(*database_data)) + except IncompatibleDatabaseSchema: + message = 'Database schema version is incompatible with the code: run `verdi database migrate`.' + print_status(ServiceStatus.DOWN, 'postgres', message) + exit_code = ExitCode.CRITICAL + except Exception as exc: + message = 'Unable to connect as {}@{}:{}'.format(*database_data) + print_status(ServiceStatus.DOWN, 'postgres', message, exception=exc) exit_code = ExitCode.CRITICAL else: print_status(ServiceStatus.UP, 'postgres', 'Connected as {}@{}:{}'.format(*database_data)) @@ -123,7 +129,6 @@ def verdi_status(no_rmq): print_status(ServiceStatus.UP, 'daemon', daemon_status) else: print_status(ServiceStatus.WARNING, 'daemon', daemon_status) - exit_code = ExitCode.SUCCESS # A daemon that is not running is not a failure except Exception as exc: print_status(ServiceStatus.ERROR, 'daemon', 'Error getting daemon status', exception=exc) diff --git a/tests/cmdline/commands/test_status.py b/tests/cmdline/commands/test_status.py index 6c81c39b12..4818be3d39 100644 --- a/tests/cmdline/commands/test_status.py +++ b/tests/cmdline/commands/test_status.py @@ -45,3 +45,18 @@ def test_status_no_rmq(run_cli_command): for string in ['config', 'profile', 'postgres', 'daemon']: assert string in result.output + + +def test_database_incompatible(run_cli_command, monkeypatch): + """Test `verdi status` when database schema version is incompatible with that of the code.""" + from aiida.manage.manager import get_manager + + def get_backend(): + from aiida.common.exceptions import IncompatibleDatabaseSchema + raise IncompatibleDatabaseSchema() + + monkeypatch.setattr(get_manager(), 'get_backend', get_backend) + + result = run_cli_command(cmd_status.verdi_status, raises=True) + assert 'Database schema version is incompatible with the code: run `verdi database migrate`.' in result.output + assert result.exit_code is ExitCode.CRITICAL