cluster by putting them in a standard ini-style configuration file
and using the ``--config *<config-file>*`` option.
+* You can choose the ssh user cephadm will use to connect to hosts by
+ using the ``--ssh-user *<user>*`` option. The ssh key will be added
+ to ``/home/*<user>*/.ssh/authorized_keys``. This user will require
+ passwordless sudo access.
+
Enable Ceph CLI
===============
ceph mgr fail
+Configuring a different SSH user
+----------------------------------
+
+Cephadm must be able to log into all the Ceph cluster nodes as an user
+that has enough privileges to download container images, start containers
+and execute commands without prompting for a password. If you do not want
+to use the "root" user (default option in cephadm), you must provide
+cephadm the name of the user that is going to be used to perform all the
+cephadm operations. Use the command::
+
+ ceph cephadm set-user <user>
+
+Prior to running this the cluster ssh key needs to be added to this users
+authorized_keys file and non-root users must have passwordless sudo access.
+
Customizing the SSH configuration
---------------------------------
| [--dashboard-crt DASHBOARD_CRT]
| [--ssh-config SSH_CONFIG]
| [--ssh-private-key SSH_PRIVATE_KEY]
-| [--ssh-public-key SSH_PUBLIC_KEY] [--skip-mon-network]
+| [--ssh-public-key SSH_PUBLIC_KEY]
+| [--ssh-user SSH_USER] [--skip-mon-network]
| [--skip-dashboard] [--dashboard-password-noupdate]
| [--no-minimize-config] [--skip-ping-check]
| [--skip-pull] [--skip-firewalld] [--allow-overwrite]
* [--ssh-config SSH_CONFIG] SSH config
* [--ssh-private-key SSH_PRIVATE_KEY] SSH private key
* [--ssh-public-key SSH_PUBLIC_KEY] SSH public key
+* [--ssh-user SSH_USER] set user for SSHing to cluster hosts, passwordless sudo will be needed for non-root users'
* [--skip-mon-network] set mon public_network based on bootstrap mon ip
* [--skip-dashboard] do not enable the Ceph Dashboard
* [--dashboard-password-noupdate] stop forced dashboard password change
import logging
import os
import platform
+import pwd
import random
import re
import select
# ssh
if not args.skip_ssh:
+ cli(['config-key', 'set', 'mgr/cephadm/ssh_user', args.ssh_user])
+
logger.info('Enabling cephadm module...')
cli(['mgr', 'module', 'enable', 'cephadm'])
wait_for_mgr_restart()
f.write(ssh_pub)
logger.info('Wrote public SSH key to to %s' % args.output_pub_ssh_key)
- logger.info('Adding key to root@localhost\'s authorized_keys...')
- if not os.path.exists('/root/.ssh'):
- os.mkdir('/root/.ssh', 0o700)
- auth_keys_file = '/root/.ssh/authorized_keys'
+ logger.info('Adding key to %s@localhost\'s authorized_keys...' % args.ssh_user)
+ try:
+ s_pwd = pwd.getpwnam(args.ssh_user)
+ except KeyError as e:
+ raise Error('Cannot find uid/gid for ssh-user: %s' % (args.ssh_user))
+ ssh_uid = s_pwd.pw_uid
+ ssh_gid = s_pwd.pw_gid
+ ssh_dir = os.path.join(s_pwd.pw_dir, '.ssh')
+
+ if not os.path.exists(ssh_dir):
+ makedirs(ssh_dir, ssh_uid, ssh_gid, 0o700)
+
+ auth_keys_file = '%s/authorized_keys' % ssh_dir
add_newline = False
+
if os.path.exists(auth_keys_file):
with open(auth_keys_file, 'r') as f:
f.seek(0, os.SEEK_END)
f.seek(f.tell()-1, os.SEEK_SET) # go to last char
if f.read() != '\n':
add_newline = True
+
with open(auth_keys_file, 'a') as f:
+ os.fchown(f.fileno(), ssh_uid, ssh_gid) # just in case we created it
os.fchmod(f.fileno(), 0o600) # just in case we created it
if add_newline:
f.write('\n')
ssh_key = '/etc/ceph/ceph.pub'
if args.ssh_public_key:
ssh_key = args.ssh_public_key.name
- out, err, code = call_throws(['ssh-copy-id', '-f', '-i', ssh_key, 'root@%s' % split[1]])
+ out, err, code = call_throws(['ssh-copy-id', '-f', '-i', ssh_key, '%s@%s' % (args.ssh_user, split[1])])
mounts = {}
mounts[pathify(args.apply_spec)] = '/tmp/spec.yml:z'
'--ssh-public-key',
type=argparse.FileType('r'),
help='SSH public key')
+ parser_bootstrap.add_argument(
+ '--ssh-user',
+ default='root',
+ help='set user for SSHing to cluster hosts, passwordless sudo will be needed for non-root users')
parser_bootstrap.add_argument(
'--skip-mon-network',
self._ssh_options = None
if self.mode == 'root':
- self.ssh_user = 'root'
+ self.ssh_user = self.get_store('ssh_user', default='root')
elif self.mode == 'cephadm-package':
self.ssh_user = 'cephadm'
def _get_user(self):
return 0, self.ssh_user, ''
+ @orchestrator._cli_read_command(
+ 'cephadm set-user',
+ 'name=user,type=CephString',
+ 'Set user for SSHing to cluster hosts, passwordless sudo will be needed for non-root users')
+ def set_ssh_user(self, user):
+ current_user = self.ssh_user
+
+ self.set_store('ssh_user', user)
+ self._reconfig_ssh()
+
+ host = self.cache.get_hosts()[0]
+ r = self._check_host(host)
+ if r is not None:
+ #connection failed reset user
+ self.set_store('ssh_user', current_user)
+ self._reconfig_ssh()
+ return -errno.EINVAL, '', 'ssh connection %s@%s failed' % (user, host)
+
+ msg = 'ssh user set to %s' % user
+ if user != 'root':
+ msg += ' sudo will be used'
+ self.log.info(msg)
+ return 0, msg, ''
+
@orchestrator._cli_read_command(
'cephadm check-host',
'name=host,type=CephString '
conn = remoto.Connection(
n,
logger=child_logger,
- ssh_options=self._ssh_options)
+ ssh_options=self._ssh_options,
+ sudo=True if self.ssh_user != 'root' else False)
r = conn.import_module(remotes)
self._cons[host] = conn, r
self.offline_hosts.add(host)
self._reset_con(host)
- user = 'root' if self.mode == 'root' else 'cephadm'
+ user = self.ssh_user if self.mode == 'root' else 'cephadm'
msg = f'''Failed to connect to {host} ({addr}).
Check that the host is reachable and accepts connections using the cephadm SSH key
host, remotes.PYTHONS, remotes.PATH))
try:
out, err, code = remoto.process.check(
- conn,
- [python, '-u'],
- stdin=script.encode('utf-8'))
+ conn,
+ [python, '-u'],
+ stdin=script.encode('utf-8'))
except RuntimeError as e:
self._reset_con(host)
if error_ok: