diff --git a/setup.cfg b/setup.cfg index aa67856b0..733cf2076 100644 --- a/setup.cfg +++ b/setup.cfg @@ -50,6 +50,7 @@ openstack.tripleoclient.v1 = tripleo_config_generate_ansible = tripleoclient.v1.tripleo_config:GenerateAnsibleConfig tripleo_deploy = tripleoclient.v1.tripleo_deploy:Deploy tripleo_upgrade = tripleoclient.v1.tripleo_upgrade:Upgrade + overcloud_admin_authorize = tripleoclient.v1.overcloud_admin:Authorize overcloud_netenv_validate = tripleoclient.v1.overcloud_netenv_validate:ValidateOvercloudNetenv overcloud_config_download = tripleoclient.v1.overcloud_config:DownloadConfig overcloud_container_image_upload = tripleoclient.v1.container_image:UploadImage diff --git a/tripleoclient/tests/v1/test_overcloud_admin.py b/tripleoclient/tests/v1/test_overcloud_admin.py new file mode 100644 index 000000000..a42b5cec8 --- /dev/null +++ b/tripleoclient/tests/v1/test_overcloud_admin.py @@ -0,0 +1,42 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock + +from tripleoclient.tests.v1 import test_plugin +from tripleoclient import utils +from tripleoclient.v1 import overcloud_admin +from tripleoclient.workflows import deployment + + +@mock.patch.object(utils, 'get_stack', autospec=True) +@mock.patch.object(deployment, 'get_hosts_and_enable_ssh_admin', autospec=True) +class TestAdminAuthorize(test_plugin.TestPluginV1): + def setUp(self): + super(TestAdminAuthorize, self).setUp() + self.cmd = overcloud_admin.Authorize(self.app, None) + self.app.client_manager = mock.Mock() + + def test_ok(self, mock_get_host_and_enable_ssh_admin, mock_get_stack): + arglist = [] + parsed_args = self.check_parser(self.cmd, arglist, []) + mock_stack = mock.Mock() + mock_get_stack.return_value = mock_stack + + self.cmd.take_action(parsed_args) + mock_get_host_and_enable_ssh_admin.assert_called_once_with( + self.cmd.log, + self.app.client_manager, + mock_stack, + parsed_args.overcloud_ssh_network, + parsed_args.overcloud_ssh_user, + parsed_args.overcloud_ssh_key) diff --git a/tripleoclient/v1/overcloud_admin.py b/tripleoclient/v1/overcloud_admin.py new file mode 100644 index 000000000..6bf59a782 --- /dev/null +++ b/tripleoclient/v1/overcloud_admin.py @@ -0,0 +1,73 @@ +# Copyright 2018 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +import os + +from oslo_config import cfg +from oslo_log import log as logging + +from osc_lib.i18n import _ +from osc_lib import utils + +from tripleoclient import command +from tripleoclient import utils as oooutils +from tripleoclient.workflows import deployment + +CONF = cfg.CONF +logging.register_options(CONF) +logging.setup(CONF, '') + + +class Authorize(command.Command): + "Deploy the ssh keys needed by Mistral." + + log = logging.getLogger(__name__ + ".AdminAuthorize") + + def get_parser(self, prog_name): + parser = super(Authorize, self).get_parser(prog_name) + + parser.add_argument('--stack', dest='stack', + help=_('Name or ID of heat stack ' + '(default=Env: OVERCLOUD_STACK_NAME)'), + default=utils.env('OVERCLOUD_STACK_NAME', + default='overcloud')) + + parser.add_argument( + '--overcloud-ssh-user', + default='heat-admin', + help=_('User for ssh access to overcloud nodes') + ) + parser.add_argument( + '--overcloud-ssh-key', + default=os.path.join( + os.path.expanduser('~'), '.ssh', 'id_rsa'), + help=_('Key path for ssh access to overcloud nodes.') + ) + parser.add_argument( + '--overcloud-ssh-network', + help=_('Network name to use for ssh access to overcloud nodes.'), + default='ctlplane' + ) + + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action({})".format(parsed_args)) + clients = self.app.client_manager + stack = oooutils.get_stack(clients.orchestration, parsed_args.stack) + deployment.get_hosts_and_enable_ssh_admin( + self.log, clients, stack, + parsed_args.overcloud_ssh_network, + parsed_args.overcloud_ssh_user, + parsed_args.overcloud_ssh_key) diff --git a/tripleoclient/workflows/deployment.py b/tripleoclient/workflows/deployment.py index 317524d7d..6c9a44625 100644 --- a/tripleoclient/workflows/deployment.py +++ b/tripleoclient/workflows/deployment.py @@ -178,8 +178,24 @@ def wait_for_ssh_port(host): def get_hosts_and_enable_ssh_admin(log, clients, stack, overcloud_ssh_network, overcloud_ssh_user, overcloud_ssh_key): hosts = get_overcloud_hosts(stack, overcloud_ssh_network) - enable_ssh_admin(log, clients, stack.stack_name, hosts, - overcloud_ssh_user, overcloud_ssh_key) + if [host for host in hosts if host]: + + try: + enable_ssh_admin(log, clients, stack.stack_name, hosts, + overcloud_ssh_user, overcloud_ssh_key) + except subprocess.CalledProcessError as e: + if e.returncode == 255: + log.error("Couldn't not import keys to one of {}. " + "Check if the user/ip are corrects.\n".format(hosts)) + else: + log.error("Unknown error. " + "Original message is:\n{}".format(hosts, e.message)) + + else: + raise exceptions.DeploymentError("Cannot find any hosts on '{}'" + " in network '{}'" + .format(stack.stack_name, + overcloud_ssh_network)) def enable_ssh_admin(log, clients, plan_name, hosts, ssh_user, ssh_key):