Merge "Create Ceph pools/cephx keys before overcloud deploy" into stable/wallaby

This commit is contained in:
Zuul 2022-05-25 18:00:40 +00:00 committed by Gerrit Code Review
commit f18eec5ca3
4 changed files with 162 additions and 0 deletions

View File

@ -2711,3 +2711,24 @@ class TestCheckDeployBackups(TestCase):
self.assertIn( self.assertIn(
'Deploy backup files disk usage 90.00% exceeds 50% percent', 'Deploy backup files disk usage 90.00% exceeds 50% percent',
mock_log.warning.call_args_list[0][0][0]) mock_log.warning.call_args_list[0][0][0])
class TestGetCephadmKeys(TestCase):
def test_get_cephadm_keys(self):
user = 'openstack'
key = 'AQC+vYNXgDAgAhAAc8UoYt+OTz5uhV7ItLdwUw=='
pools = ['foo', 'bar']
keys = utils.get_tripleo_cephadm_keys(user,
key,
pools)
expected = [
{'name': 'client.openstack',
'key': key,
'mode': '0600',
'caps': {
'mgr': 'allow *',
'mon': 'profile rbd',
'osd': 'profile rbd pool=foo, profile rbd pool=bar'}}]
self.assertEqual(keys, expected)

View File

@ -60,6 +60,7 @@ class TestOvercloudCephDeploy(fakes.FakePlaybookExecution):
verbosity=3, verbosity=3,
skip_tags='cephadm_ssh_user', skip_tags='cephadm_ssh_user',
reproduce_command=False, reproduce_command=False,
extra_vars_file=mock.ANY,
extra_vars={ extra_vars={
"baremetal_deployed_path": mock.ANY, "baremetal_deployed_path": mock.ANY,
"deployed_ceph_tht_path": mock.ANY, "deployed_ceph_tht_path": mock.ANY,
@ -85,6 +86,24 @@ class TestOvercloudCephDeploy(fakes.FakePlaybookExecution):
self.assertRaises(osc_lib_exc.CommandError, self.assertRaises(osc_lib_exc.CommandError,
self.cmd.take_action, parsed_args) self.cmd.take_action, parsed_args)
@mock.patch('tripleoclient.utils.get_ceph_networks', autospect=True)
@mock.patch('tripleoclient.utils.TempDirs', autospect=True)
@mock.patch('os.path.abspath', autospect=True)
@mock.patch('os.path.exists', autospect=True)
@mock.patch('tripleoclient.utils.run_ansible_playbook', autospec=True)
def test_overcloud_deploy_ceph_ansible_no_force(self,
mock_playbook,
mock_abspath,
mock_path_exists,
mock_tempdirs,
mock_get_ceph_networks):
arglist = ['deployed-metal.yaml', '--yes',
'--ansible-extra-vars', 'foo.yml',
'--output', 'deployed-ceph.yaml']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.assertRaises(osc_lib_exc.CommandError,
self.cmd.take_action, parsed_args)
class TestOvercloudCephUserDisable(fakes.FakePlaybookExecution): class TestOvercloudCephUserDisable(fakes.FakePlaybookExecution):
def setUp(self): def setUp(self):

View File

@ -3350,3 +3350,23 @@ def check_deploy_backups(
"percent of disk size. Consider deleting some " "percent of disk size. Consider deleting some "
"older deploy backups.".format(fs_usage, disk_usage_percent)) "older deploy backups.".format(fs_usage, disk_usage_percent))
print(backup_table, file=sys.stdout) print(backup_table, file=sys.stdout)
def get_tripleo_cephadm_keys(username, key, pools):
"""Get a tripleo_cephadm_keys structure to be passed to
the tripleo-ansible role tripleo_cephadm. Assumes only
one key will be created to write to all pools.
:param username: string, e.g. 'openstack'
:param key: string for cephx secret key, e.g. 'AQC+...w=='
:param pools: list of pool names, e.g. ['vms', 'images']
:return a list containing a single dictionary
"""
return [dict(
name='client.' + username,
key=key,
mode='0600',
caps=dict(
mgr='allow *',
mon='profile rbd',
osd=', '.join(list(
map(lambda x: 'profile rbd pool=' + x, pools)))))]

View File

@ -15,12 +15,16 @@
import logging import logging
import os import os
import re
import uuid import uuid
import yaml
from osc_lib import exceptions as oscexc from osc_lib import exceptions as oscexc
from osc_lib.i18n import _ from osc_lib.i18n import _
from osc_lib import utils from osc_lib import utils
from tripleo_common.utils import passwords
from tripleoclient import command from tripleoclient import command
from tripleoclient import constants from tripleoclient import constants
from tripleoclient import utils as oooutils from tripleoclient import utils as oooutils
@ -188,6 +192,54 @@ class OvercloudCephDeploy(command.Command):
parser.add_argument('--force', default=False, parser.add_argument('--force', default=False,
action='store_true', action='store_true',
help=_("Run command regardless of consequences.")) help=_("Run command regardless of consequences."))
parser.add_argument('--ansible-extra-vars',
help=_(
"Path to an existing Ansible vars file which "
"can override any variable in "
"tripleo-ansible. If "
"'--ansible-extra-vars vars.yaml' is passed, "
"then 'ansible-playbook -e @vars.yaml ...' is "
"used to call tripleo-ansible Ceph roles. "
"Warning: requires --force as not all "
"options ensure a functional deployment."))
parser.add_argument('--ceph-client-username',
help=_(
"Name of the cephx user. E.g. if "
"'openstack' is used, then "
"'ceph auth get client.openstack' will "
"return a working user with key and "
"capabilities on the deployed Ceph cluster. "
"Ignored unless tripleo_cephadm_pools is set "
"via --ansible-extra-vars. "
"If this parameter is not set and "
"tripleo_cephadm_keys is set via "
"--ansible-extra-vars, then "
"'openstack' will be used. "
"Used to set CephClientUserName in --output."),
default='openstack'),
parser.add_argument('--ceph-client-key',
help=_(
"Value of the cephx key. E.g. "
"'AQC+vYNXgDAgAhAAc8UoYt+OTz5uhV7ItLdwUw=='. "
"Ignored unless tripleo_cephadm_pools is set "
"via --ansible-extra-vars. "
"If this parameter is not set and "
"tripleo_cephadm_keys is set via "
"--ansible-extra-vars, then a random "
"key will be generated. "
"Used to set CephClientKey in --output."),
default='')
parser.add_argument('--skip-cephx-keys', default=False,
action='store_true',
help=_("Do not create cephx keys even if "
"tripleo_cephadm_pools is set via "
"--ansible-extra-vars. If this option "
"is used, then even the defaults of "
"--ceph-client-key and "
"--ceph-client-username are ignored, "
"but the pools defined via "
"--ansible-extra-vars "
"are still created."))
parser.add_argument('--single-host-defaults', default=False, parser.add_argument('--single-host-defaults', default=False,
action='store_true', action='store_true',
help=_("Adjust configuration defaults to suit " help=_("Adjust configuration defaults to suit "
@ -318,6 +370,7 @@ class OvercloudCephDeploy(command.Command):
"working_dir": working_dir, "working_dir": working_dir,
"stack_name": parsed_args.stack, "stack_name": parsed_args.stack,
} }
extra_vars_file = None
# optional paths to pass to playbook # optional paths to pass to playbook
if parsed_args.roles_data: if parsed_args.roles_data:
if not os.path.exists(parsed_args.roles_data): if not os.path.exists(parsed_args.roles_data):
@ -386,6 +439,52 @@ class OvercloudCephDeploy(command.Command):
if parsed_args.cephadm_extra_args and parsed_args.force: if parsed_args.cephadm_extra_args and parsed_args.force:
extra_vars['tripleo_cephadm_extra_args'] = \ extra_vars['tripleo_cephadm_extra_args'] = \
parsed_args.cephadm_extra_args parsed_args.cephadm_extra_args
if parsed_args.ansible_extra_vars and not parsed_args.force:
raise oscexc.CommandError(
"--ansible-extra-vars requires --force.")
if parsed_args.ansible_extra_vars and parsed_args.force:
if not os.path.exists(parsed_args.ansible_extra_vars):
raise oscexc.CommandError(
"Ansible vars file not found --ansible-extra-vars %s."
% os.path.abspath(parsed_args.ansible_extra_vars))
else:
# utils.run_ansible_playbook() assums extra_vars_file is a dict
with open(os.path.abspath(parsed_args.ansible_extra_vars),
'r') as f:
extra_vars_file = yaml.safe_load(f)
if (not parsed_args.skip_cephx_keys and
'tripleo_cephadm_pools' in extra_vars_file and # noqa
'tripleo_cephadm_keys' not in extra_vars_file): # noqa
# create tripleo_cephadm_keys and add it to extra_vars
self.log.debug("Generating tripleo_cephadm_keys")
if len(parsed_args.ceph_client_key) == 0:
parsed_args.ceph_client_key = \
passwords.create_cephx_key()
cephx = re.compile(r"^[a-zA-Z0-9+/]{38}==$")
if not cephx.match(parsed_args.ceph_client_key):
msg = ("'%s' is not a valid cephx key"
% str(parsed_args.ceph_client_key))
raise oscexc.CommandError(msg)
extra_vars['tripleo_cephadm_keys'] = \
oooutils.get_tripleo_cephadm_keys(
parsed_args.ceph_client_username,
parsed_args.ceph_client_key,
list(map(lambda x: x.get('name', ''),
extra_vars_file['tripleo_cephadm_pools']))
)
# pass CLI args to THT via --output deployed_ceph.yaml
extra_vars['ceph_client_key'] = parsed_args.ceph_client_key
extra_vars['ceph_client_username'] =\
parsed_args.ceph_client_username
else:
self.log.debug("Not generating tripleo_cephadm_keys. "
"Either --skip-cephx-keys was used, "
"or tripleo_cephadm_pools was not "
"in %s, or tripleo_cephadm_keys was "
"in %s." % (
(parsed_args.ansible_extra_vars,)*2))
# optional container vars to pass to playbook # optional container vars to pass to playbook
keys = ['ceph_namespace', 'ceph_image', 'ceph_tag'] keys = ['ceph_namespace', 'ceph_image', 'ceph_tag']
push_sub_keys = ['ceph_namespace'] push_sub_keys = ['ceph_namespace']
@ -481,6 +580,7 @@ class OvercloudCephDeploy(command.Command):
verbosity=oooutils.playbook_verbosity(self=self), verbosity=oooutils.playbook_verbosity(self=self),
reproduce_command=False, reproduce_command=False,
extra_vars=hosts_extra_vars, extra_vars=hosts_extra_vars,
extra_vars_file=extra_vars_file,
) )
else: else:
self.log.debug("Not updating /etc/hosts because " self.log.debug("Not updating /etc/hosts because "
@ -501,6 +601,7 @@ class OvercloudCephDeploy(command.Command):
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS, playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=oooutils.playbook_verbosity(self=self), verbosity=oooutils.playbook_verbosity(self=self),
extra_vars=reg_extra_vars, extra_vars=reg_extra_vars,
extra_vars_file=extra_vars_file,
reproduce_command=False, reproduce_command=False,
) )
else: else:
@ -522,6 +623,7 @@ class OvercloudCephDeploy(command.Command):
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS, playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=oooutils.playbook_verbosity(self=self), verbosity=oooutils.playbook_verbosity(self=self),
extra_vars=extra_vars, extra_vars=extra_vars,
extra_vars_file=extra_vars_file,
reproduce_command=False, reproduce_command=False,
skip_tags=','.join(skip_tags), skip_tags=','.join(skip_tags),
) )