diff --git a/doc/source/cli/trove-status.rst b/doc/source/cli/trove-status.rst index aa01f2d4f8..0e30e5b49e 100644 --- a/doc/source/cli/trove-status.rst +++ b/doc/source/cli/trove-status.rst @@ -75,4 +75,8 @@ Upgrade **11.0.0 (Stein)** - * Placeholder to be filled in with checks as they are added in Stein. + * Checks if any Trove instance with assigned task is running. + The assigned tasks may fail during the upgrade process due to transient + unavailability of Trove control plane. + Upgrade should be postponed until all instances are in the Active state. + diff --git a/trove/cmd/status.py b/trove/cmd/status.py index da00f675e2..c17bcff8ab 100644 --- a/trove/cmd/status.py +++ b/trove/cmd/status.py @@ -18,17 +18,38 @@ from oslo_config import cfg from oslo_upgradecheck import upgradecheck from trove.common.i18n import _ +from trove import db +from trove.instance.models import DBInstance +from trove.instance.tasks import InstanceTasks class Checks(upgradecheck.UpgradeCommands): - """Various upgrade checks should be added as separate methods in this class and added to _upgrade_checks tuple. """ - def _check_placeholder(self): - # This is just a placeholder for upgrade checks, it should be - # removed when the actual checks are added + def _check_instances_with_running_tasks(self): + """Finds Trove instances with running tasks. + + Such instances need to communicate with Trove control plane to report + status. This may rise issues if Trove services are unavailable, e.g. + Trove guest agent may be left in a failed state due to communication + issues. + """ + + db_api = db.get_db_api() + db_api.configure_db(cfg.CONF) + + query = DBInstance.query() + query = query.filter(DBInstance.task_status != InstanceTasks.NONE) + query = query.filter_by(deleted=False) + instances_with_tasks = query.count() + + if instances_with_tasks: + return upgradecheck.Result( + upgradecheck.Code.WARNING, + _("Instances with running tasks exist.")) + return upgradecheck.Result(upgradecheck.Code.SUCCESS) # The format of the check functions is to return an @@ -39,14 +60,15 @@ class Checks(upgradecheck.UpgradeCommands): # in the returned Result's "details" attribute. The # summary will be rolled up at the end of the check() method. _upgrade_checks = ( - # In the future there should be some real checks added here - (_('Placeholder'), _check_placeholder), + (_("instances_with_running_tasks"), + _check_instances_with_running_tasks), ) def main(): return upgradecheck.main( - cfg.CONF, project='trove', upgrade_command=Checks()) + cfg.CONF, project="trove", upgrade_command=Checks()) + if __name__ == '__main__': sys.exit(main()) diff --git a/trove/tests/unittests/cmd/test_status.py b/trove/tests/unittests/cmd/test_status.py index 0b3ca1e4b9..7a94d74ebc 100644 --- a/trove/tests/unittests/cmd/test_status.py +++ b/trove/tests/unittests/cmd/test_status.py @@ -12,19 +12,38 @@ # License for the specific language governing permissions and limitations # under the License. +from mock import Mock +from mock import patch from oslo_upgradecheck.upgradecheck import Code from trove.cmd import status from trove.tests.unittests import trove_testtools -class TestUpgradeChecks(trove_testtools.TestCase): - +@patch("trove.cmd.status.db.get_db_api") +@patch("trove.cmd.status.DBInstance") +class TestUpgradeChecksInstancesWithTasks(trove_testtools.TestCase): def setUp(self): - super(TestUpgradeChecks, self).setUp() + super(TestUpgradeChecksInstancesWithTasks, self).setUp() self.cmd = status.Checks() + self.fake_db_api = Mock() - def test__check_placeholder(self): - check_result = self.cmd._check_placeholder() - self.assertEqual( - Code.SUCCESS, check_result.code) + def test__check_no_instances_with_tasks(self, mock_instance, + fake_get_db_api): + fake_get_db_api.return_value = self.fake_db_api + + mock_instance.query.return_value.filter.return_value.filter_by.\ + return_value.count.return_value = 0 + + check_result = self.cmd._check_instances_with_running_tasks() + self.assertEqual(Code.SUCCESS, check_result.code) + + def test__check_instances_with_tasks(self, mock_instance, + fake_get_db_api): + fake_get_db_api.return_value = self.fake_db_api + + mock_instance.query.return_value.filter.return_value.filter_by.\ + return_value.count.return_value = 1 + + check_result = self.cmd._check_instances_with_running_tasks() + self.assertEqual(Code.WARNING, check_result.code)