Create Ceph pools/cephx keys before overcloud deploy

Add new parameters --ceph-client-username, --ceph-client-key,
--skip-cephx-keys, and --ansible-extra-vars to 'openstack
overcloud ceph deploy' so that the user may create pools
and cephx keys for OpenStack to access them on the deployed
Ceph cluster. This is optional as 'openstack overcloud deploy'
will create the pools/cephx keys later, however the same
Ansible can now be called to do it earlier.

The --ansible-extra-vars option can override any variable
in tripleo-ansible when 'openstack overcloud ceph deploy'
is called. If the tripleo_cephadm_pools variable is set,
then cephx keys will be generated and exported to the
--output deployed_ceph.yaml. The user may also pass their
own cephx key and client username.

Depends-On: Ib87a8a5a550676b32302c0cc9c447f8b9fe3a149
Change-Id: Ic37d7123c30b559b1ff41e1d93ce7c7673b85a92
This commit is contained in:
John Fulton 2022-04-14 14:40:43 -04:00
parent a0dd1801e1
commit d58fa71baf
4 changed files with 163 additions and 0 deletions

View File

@ -2808,3 +2808,24 @@ class TestCheckDeployBackups(TestCase):
self.assertIn(
'Deploy backup files disk usage 90.00% exceeds 50% percent',
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

@ -61,6 +61,7 @@ class TestOvercloudCephDeploy(fakes.FakePlaybookExecution):
verbosity=3,
skip_tags='cephadm_ssh_user',
reproduce_command=False,
extra_vars_file=mock.ANY,
extra_vars={
"baremetal_deployed_path": mock.ANY,
"deployed_ceph_tht_path": mock.ANY,
@ -106,6 +107,7 @@ class TestOvercloudCephDeploy(fakes.FakePlaybookExecution):
verbosity=3,
skip_tags='cephadm_ssh_user',
reproduce_command=False,
extra_vars_file=mock.ANY,
extra_vars={
"deployed_ceph_tht_path": mock.ANY,
"working_dir": mock.ANY,
@ -144,6 +146,24 @@ class TestOvercloudCephDeploy(fakes.FakePlaybookExecution):
self.assertRaises(osc_lib_exc.CommandError,
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):
def setUp(self):

View File

@ -3493,3 +3493,23 @@ def check_deploy_backups(
"percent of disk size. Consider deleting some "
"older deploy backups.".format(fs_usage, disk_usage_percent))
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 os
import re
import uuid
import yaml
from osc_lib import exceptions as oscexc
from osc_lib.i18n import _
from osc_lib import utils
from tripleo_common.utils import passwords
from tripleoclient import command
from tripleoclient import constants
from tripleoclient import utils as oooutils
@ -198,6 +202,54 @@ class OvercloudCephDeploy(command.Command):
parser.add_argument('--force', default=False,
action='store_true',
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('--ceph-vip',
help=_(
"Path to an existing Ceph services/network "
@ -341,6 +393,7 @@ class OvercloudCephDeploy(command.Command):
"stack_name": parsed_args.stack,
"tripleo_cephadm_standalone": parsed_args.standalone
}
extra_vars_file = None
# optional paths to pass to playbook
if parsed_args.ceph_spec is None and \
parsed_args.baremetal_env is None:
@ -442,6 +495,52 @@ class OvercloudCephDeploy(command.Command):
if parsed_args.cephadm_extra_args and parsed_args.force:
extra_vars['tripleo_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))
if parsed_args.daemons:
if not os.path.exists(parsed_args.daemons):
raise oscexc.CommandError(
@ -547,6 +646,7 @@ class OvercloudCephDeploy(command.Command):
verbosity=oooutils.playbook_verbosity(self=self),
reproduce_command=False,
extra_vars=hosts_extra_vars,
extra_vars_file=extra_vars_file,
)
else:
self.log.debug("Not updating /etc/hosts because "
@ -567,6 +667,7 @@ class OvercloudCephDeploy(command.Command):
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=oooutils.playbook_verbosity(self=self),
extra_vars=reg_extra_vars,
extra_vars_file=extra_vars_file,
reproduce_command=False,
)
else:
@ -588,6 +689,7 @@ class OvercloudCephDeploy(command.Command):
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=oooutils.playbook_verbosity(self=self),
extra_vars=extra_vars,
extra_vars_file=extra_vars_file,
reproduce_command=False,
skip_tags=','.join(skip_tags),
)