From ee445d27e7268f54c0511768a11c3e460b15198d Mon Sep 17 00:00:00 2001 From: Jan Provaznik Date: Wed, 26 Aug 2015 10:54:41 +0200 Subject: [PATCH] Fix pre-deployment hypervisor check Take into account hypervisor check and stop deployment if it fails. A new exception DeploymentError is used to abort deployment if pre-heat checks fail. This exception is used also in a followup patch which adds checking of available nodes. Change-Id: If62268d6e181ce607c474fb3b65b4ca577e70c3d --- rdomanager_oscplugin/exceptions.py | 5 ++ .../overcloud_deploy/test_overcloud_deploy.py | 42 ++++++++-- rdomanager_oscplugin/v1/overcloud_deploy.py | 77 ++++++++++--------- 3 files changed, 80 insertions(+), 44 deletions(-) diff --git a/rdomanager_oscplugin/exceptions.py b/rdomanager_oscplugin/exceptions.py index 9b25d1268..a123784cd 100644 --- a/rdomanager_oscplugin/exceptions.py +++ b/rdomanager_oscplugin/exceptions.py @@ -34,3 +34,8 @@ class UnknownService(Exception): class NotFound(Exception): """Resource not found""" pass + + +class DeploymentError(Exception): + """Deployment failed""" + pass diff --git a/rdomanager_oscplugin/tests/v1/overcloud_deploy/test_overcloud_deploy.py b/rdomanager_oscplugin/tests/v1/overcloud_deploy/test_overcloud_deploy.py index cbe587db4..81d9557d2 100644 --- a/rdomanager_oscplugin/tests/v1/overcloud_deploy/test_overcloud_deploy.py +++ b/rdomanager_oscplugin/tests/v1/overcloud_deploy/test_overcloud_deploy.py @@ -22,6 +22,7 @@ from openstackclient.common import exceptions as oscexc from openstackclient.tests import utils as oscutils from tuskarclient.v2.plans import Plan +from rdomanager_oscplugin import exceptions from rdomanager_oscplugin.tests.v1.overcloud_deploy import fakes from rdomanager_oscplugin.tests.v1.utils import ( generate_overcloud_passwords_mock) @@ -114,7 +115,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertTrue(result) args, kwargs = orchestration_client.stacks.update.call_args @@ -258,7 +260,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertTrue(result) args, kwargs = orchestration_client.stacks.create.call_args @@ -401,7 +404,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertTrue(result) args, kwargs = orchestration_client.stacks.update.call_args @@ -485,7 +489,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertTrue(result) parameters = { 'Cinder-Storage-1::SnmpdReadonlyUserPassword': "PASSWORD", @@ -598,7 +603,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertTrue(result) parameters = { 'Cinder-Storage-1::SnmpdReadonlyUserPassword': "PASSWORD", @@ -716,7 +722,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertTrue(result) parameters = { 'Cinder-Storage-1::SnmpdReadonlyUserPassword': "PASSWORD", @@ -823,7 +830,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertFalse(result) self.assertFalse(mock_deploy_tht.called) self.assertFalse(mock_deploy_tuskar.called) @@ -858,7 +866,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) - self.cmd.take_action(parsed_args) + result = self.cmd.take_action(parsed_args) + self.assertTrue(result) self.assertTrue(mock_deploy_tht.called) self.assertTrue(mock_oc_endpoint.called) self.assertTrue(mock_create_ocrc.called) @@ -908,3 +917,20 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): self.assertRaises(oscexc.CommandError, self.cmd._validate_args, parsed_args) + + @mock.patch('rdomanager_oscplugin.utils.check_hypervisor_stats', + autospec=True) + def test_pre_heat_deploy_failed(self, mock_check_hypervisor_stats): + clients = self.app.client_manager + orchestration_client = clients.rdomanager_oscplugin.orchestration() + orchestration_client.stacks.get.return_value = None + mock_check_hypervisor_stats.return_value = None + arglist = ['--templates'] + verifylist = [ + ('templates', '/usr/share/openstack-tripleo-heat-templates/') + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + self.assertFalse(result) + self.assertRaises(exceptions.DeploymentError, + self.cmd._pre_heat_deploy) diff --git a/rdomanager_oscplugin/v1/overcloud_deploy.py b/rdomanager_oscplugin/v1/overcloud_deploy.py index ebef30fa7..d3d1f8e59 100644 --- a/rdomanager_oscplugin/v1/overcloud_deploy.py +++ b/rdomanager_oscplugin/v1/overcloud_deploy.py @@ -34,6 +34,7 @@ from os_cloud_config.utils import clients from six.moves import configparser from tuskarclient.common import utils as tuskarutils +from rdomanager_oscplugin import exceptions from rdomanager_oscplugin import utils TRIPLEO_HEAT_TEMPLATES = "/usr/share/openstack-tripleo-heat-templates/" @@ -463,8 +464,9 @@ class DeployOvercloud(command.Command): self.log.debug("Checking hypervisor stats") if utils.check_hypervisor_stats(compute_client) is None: - print("Expected hypervisor stats not met", file=sys.stderr) - return + raise exceptions.DeploymentError( + "Expected hypervisor stats not met") + return True def _deploy_tripleo_heat_templates(self, stack, parsed_args): """Deploy the fixed templates in TripleO Heat Templates""" @@ -881,44 +883,47 @@ class DeployOvercloud(command.Command): stack = self._get_stack(orchestration_client, parsed_args.stack) stack_create = stack is None - self._validate_args(parsed_args) + try: + self._pre_heat_deploy() - self._pre_heat_deploy() + if parsed_args.rhel_reg: + if parsed_args.reg_method == 'satellite': + sat_required_args = (parsed_args.reg_org and + parsed_args.reg_sat_url and + parsed_args.reg_activation_key) + if not sat_required_args: + raise exceptions.DeploymentError( + "ERROR: In order to use satellite registration, " + "you must specify --reg-org, --reg-sat-url, and " + "--reg-activation-key.") + else: + portal_required_args = (parsed_args.reg_org and + parsed_args.reg_activation_key) + if not portal_required_args: + raise exceptions.DeploymentError( + "ERROR: In order to use portal registration, you " + "must specify --reg-org, and " + "--reg-activation-key.") - if parsed_args.rhel_reg: - if parsed_args.reg_method == 'satellite': - sat_required_args = (parsed_args.reg_org and - parsed_args.reg_sat_url and - parsed_args.reg_activation_key) - if not sat_required_args: - print(("ERROR: In order to use satellite registration, " - "you must specify --reg-org, --reg-sat-url, and " - "--reg-activation-key."), file=sys.stderr) - return + if parsed_args.templates: + self._deploy_tripleo_heat_templates(stack, parsed_args) else: - portal_required_args = (parsed_args.reg_org and - parsed_args.reg_activation_key) - if not portal_required_args: - print(("ERROR: In order to use portal registration, you " - "must specify --reg-org, and " - "--reg-activation-key."), file=sys.stderr) - return + self._deploy_tuskar(stack, parsed_args) - if parsed_args.templates: - self._deploy_tripleo_heat_templates(stack, parsed_args) - else: - self._deploy_tuskar(stack, parsed_args) + # Get a new copy of the stack after stack update/create. If it was + # a create then the previous stack object would be None. + stack = self._get_stack(orchestration_client, parsed_args.stack) - # Get a new copy of the stack after stack update/create. If it was a - # create then the previous stack object would be None. - stack = self._get_stack(orchestration_client, parsed_args.stack) + self._create_overcloudrc(stack, parsed_args) + self._create_tempest_deployer_input() - self._create_overcloudrc(stack, parsed_args) - self._create_tempest_deployer_input() + if stack_create: + self._deploy_postconfig(stack, parsed_args) - if stack_create: - self._deploy_postconfig(stack, parsed_args) - - overcloud_endpoint = self._get_overcloud_endpoint(stack) - print("Overcloud Endpoint: {0}".format(overcloud_endpoint)) - print("Overcloud Deployed") + overcloud_endpoint = self._get_overcloud_endpoint(stack) + print("Overcloud Endpoint: {0}".format(overcloud_endpoint)) + print("Overcloud Deployed") + return True + except exceptions.DeploymentError as err: + print("Deployment failed: ", err, file=sys.stderr) + return False