diff --git a/releasenotes/notes/add_limit_args_for_admin_authorize-2fe6945515dd34a7.yaml b/releasenotes/notes/add_limit_args_for_admin_authorize-2fe6945515dd34a7.yaml new file mode 100644 index 000000000..94ad14626 --- /dev/null +++ b/releasenotes/notes/add_limit_args_for_admin_authorize-2fe6945515dd34a7.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + The Admin Authorize command can now be targeted at + specific nodes using '--limit'. It can also take a + custom static-inventory using '--static-inventory'. +fixes: + - | + Fixes Admin Authorize to work with Ephemeral Heat. diff --git a/tripleoclient/tests/v1/test_overcloud_admin.py b/tripleoclient/tests/v1/test_overcloud_admin.py index 2f0eb15e1..5e736a507 100644 --- a/tripleoclient/tests/v1/test_overcloud_admin.py +++ b/tripleoclient/tests/v1/test_overcloud_admin.py @@ -13,32 +13,56 @@ 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 + @mock.patch('tripleoclient.utils.parse_ansible_inventory', + autospec=True) + @mock.patch('tripleoclient.utils.get_key') + @mock.patch('tripleoclient.utils.get_default_working_dir') + @mock.patch('tripleoclient.utils.run_ansible_playbook', + autospec=True) + def test_admin_authorize(self, + mock_playbook, + mock_dir, + mock_key, + mock_inventory): + arglist = ['--limit', 'overcloud'] + verifylist = [('limit_hosts', 'overcloud')] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + mock_dir.return_value = "/home/stack/overcloud-deploy" + ansible_dir = "{}/config-download/overcloud".format( + mock_dir.return_value + ) + inventory = "{}/tripleo-ansible-inventory.yaml".format( + ansible_dir + ) + + mock_key.return_value = '/home/stack/.ssh/id_rsa_tripleo' + mock_inventory.return_value = ['overcloud-novacompute-0', + 'overcloud-dellcompute-0', + 'overcloud-controller-0'] self.cmd.take_action(parsed_args) - mock_get_host_and_enable_ssh_admin.assert_called_once_with( - mock_stack, - parsed_args.overcloud_ssh_network, - parsed_args.overcloud_ssh_user, - mock.ANY, - parsed_args.overcloud_ssh_port_timeout, - self.cmd.working_dir, - mock.ANY + mock_playbook.assert_called_once_with( + playbook='cli-enable-ssh-admin.yaml', + inventory=inventory, + workdir=ansible_dir, + key=parsed_args.overcloud_ssh_key, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + ssh_user=parsed_args.overcloud_ssh_user, + extra_vars={ + "ANSIBLE_PRIVATE_KEY_FILE": '/home/stack/.ssh/id_rsa_tripleo', + "ssh_servers": ['overcloud-novacompute-0', + 'overcloud-dellcompute-0', + 'overcloud-controller-0'] + }, + ansible_timeout=parsed_args.overcloud_ssh_port_timeout ) diff --git a/tripleoclient/utils.py b/tripleoclient/utils.py index 69d52ca56..64a3f5fe4 100644 --- a/tripleoclient/utils.py +++ b/tripleoclient/utils.py @@ -49,6 +49,8 @@ import yaml import ansible_runner +from ansible.parsing.dataloader import DataLoader +from ansible.inventory.manager import InventoryManager from heatclient.common import event_utils from heatclient.common import template_utils from heatclient.common import utils as heat_utils @@ -3160,3 +3162,16 @@ def get_parameter_file(path): LOG.warning('File %s was not found during export' % path) return file_data + + +def parse_ansible_inventory(inventory_file, group): + """ Retrieve a list of hosts from a defined ansible inventory file. + :param inventory: Ansible inventory file + :param group: The group to return hosts from, default will be 'all' + :return: list of hosts in the inventory matching the pattern + """ + + inventory = InventoryManager(loader=DataLoader(), + sources=[inventory_file]) + + return(inventory.get_hosts(pattern=group)) diff --git a/tripleoclient/v1/overcloud_admin.py b/tripleoclient/v1/overcloud_admin.py index 52fc0cd98..2640ed3ce 100644 --- a/tripleoclient/v1/overcloud_admin.py +++ b/tripleoclient/v1/overcloud_admin.py @@ -13,6 +13,7 @@ # under the License. # +import os from oslo_config import cfg from oslo_log import log as logging @@ -22,7 +23,7 @@ from osc_lib import utils from tripleoclient import command from tripleoclient import constants from tripleoclient import utils as oooutils -from tripleoclient.workflows import deployment +from tripleoclient.constants import ANSIBLE_TRIPLEO_PLAYBOOKS CONF = cfg.CONF @@ -70,11 +71,22 @@ class Authorize(command.Command): default=constants.ENABLE_SSH_ADMIN_SSH_PORT_TIMEOUT ) parser.add_argument( - '--working-dir', + '--static-inventory', + dest='static_inventory', action='store', - help=_('The working directory for the deployment where all ' - 'input, output, and generated files will be stored.\n' - 'Defaults to "$HOME/overcloud-deploy/"') + default=None, + help=_('Path to an existing ansible inventory to ' + 'use. If not specified, one will be ' + 'generated in ' + '~/tripleo-ansible-inventory.yaml') + ) + parser.add_argument( + '--limit', + dest='limit_hosts', + action='store', + default='all', + help=_('Define which hosts or group of hosts to ' + 'run the Admin Authorize tasks against.') ) return parser @@ -83,21 +95,36 @@ class Authorize(command.Command): logging.register_options(CONF) logging.setup(CONF, '') self.log.debug("take_action({})".format(parsed_args)) - clients = self.app.client_manager - stack = oooutils.get_stack(clients.orchestration, parsed_args.stack) + ansible_dir = os.path.join(oooutils.get_default_working_dir( + parsed_args.stack + ), + 'config-download', + parsed_args.stack) - if not parsed_args.working_dir: - self.working_dir = oooutils.get_default_working_dir( - parsed_args.stack) + if not parsed_args.static_inventory: + inventory = os.path.join(ansible_dir, + 'tripleo-ansible-inventory.yaml') else: - self.working_dir = parsed_args.working_dir + inventory = parsed_args.static_inventory - deployment.get_hosts_and_enable_ssh_admin( - stack, - parsed_args.overcloud_ssh_network, - parsed_args.overcloud_ssh_user, - self.get_key_pair(parsed_args), - parsed_args.overcloud_ssh_port_timeout, - working_dir=self.working_dir, - verbosity=oooutils.playbook_verbosity(self=self) + key_file = oooutils.get_key(parsed_args.stack) + + if not parsed_args.limit_hosts: + hosts = parsed_args.stack + else: + hosts = parsed_args.limit_hosts + + oooutils.run_ansible_playbook( + playbook='cli-enable-ssh-admin.yaml', + inventory=inventory, + workdir=ansible_dir, + key=parsed_args.overcloud_ssh_key, + playbook_dir=ANSIBLE_TRIPLEO_PLAYBOOKS, + ssh_user=parsed_args.overcloud_ssh_user, + extra_vars={ + "ANSIBLE_PRIVATE_KEY_FILE": key_file, + "ssh_servers": oooutils.parse_ansible_inventory( + inventory, hosts) + }, + ansible_timeout=parsed_args.overcloud_ssh_port_timeout )