mirror of
https://github.com/ceph/ceph
synced 2026-08-02 07:03:18 +00:00
mgr/ssh -> mgr/cephadm
Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
parent
f466b3a149
commit
cd1c05acbb
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@ -13,13 +13,13 @@
|
||||
/src/pybind/mgr/orchestrator_cli @ceph/orchestrators
|
||||
/src/pybind/mgr/orchestrator.py @ceph/orchestrators
|
||||
/src/pybind/mgr/rook @ceph/orchestrators
|
||||
/src/pybind/mgr/ssh @ceph/orchestrators
|
||||
/src/pybind/mgr/cephadm @ceph/orchestrators
|
||||
/src/pybind/mgr/test_orchestrator @ceph/orchestrators
|
||||
/src/python-common/ceph/deployment @ceph/orchestrators
|
||||
/qa/workunits/cephadm/test_cephadm.sh @ceph/orchestrators
|
||||
/qa/tasks/ceph2.py @ceph/orchestrators
|
||||
/qa/tasks/mgr/test_orchestrator_cli.py @ceph/orchestrators
|
||||
/qa/tasks/mgr/test_ssh_orchestrator.py @ceph/orchestrators
|
||||
/qa/tasks/mgr/test_cephadm_orchestrator.py @ceph/orchestrators
|
||||
/doc/mgr/orchestrator_cli.rst @ceph/orchestrators
|
||||
/doc/mgr/orchestrator_modules.rst @ceph/orchestrators
|
||||
|
||||
|
||||
26
ceph.spec.in
26
ceph.spec.in
@ -486,7 +486,7 @@ Recommends: ceph-mgr-diskprediction-local = %{_epoch_prefix}%{version}-%{release
|
||||
Recommends: ceph-mgr-diskprediction-cloud = %{_epoch_prefix}%{version}-%{release}
|
||||
Recommends: ceph-mgr-rook = %{_epoch_prefix}%{version}-%{release}
|
||||
Recommends: ceph-mgr-k8sevents = %{_epoch_prefix}%{version}-%{release}
|
||||
Recommends: ceph-mgr-ssh = %{_epoch_prefix}%{version}-%{release}
|
||||
Recommends: ceph-mgr-cephadm = %{_epoch_prefix}%{version}-%{release}
|
||||
Recommends: python%{_python_buildid}-influxdb
|
||||
%endif
|
||||
%if 0%{?rhel} == 7
|
||||
@ -596,8 +596,8 @@ Requires: python%{_python_buildid}-PyYAML
|
||||
ceph-mgr-k8sevents is a ceph-mgr plugin that sends every ceph-events
|
||||
to kubernetes' events API
|
||||
|
||||
%package mgr-ssh
|
||||
Summary: Ceph Manager plugin for SSH-based orchestration
|
||||
%package mgr-cephadm
|
||||
Summary: Ceph Manager plugin for cephadm-based orchestration
|
||||
BuildArch: noarch
|
||||
%if 0%{?suse_version}
|
||||
Group: System/Filesystems
|
||||
@ -611,9 +611,9 @@ Requires: openssh
|
||||
%if 0%{?rhel} || 0%{?fedora}
|
||||
Requires: openssh-clients
|
||||
%endif
|
||||
%description mgr-ssh
|
||||
ceph-mgr-ssh is a ceph-mgr module for orchestration functions using
|
||||
direct SSH connections for management operations.
|
||||
%description mgr-cephadm
|
||||
ceph-mgr-cephadm is a ceph-mgr module for orchestration functions using
|
||||
the integrated cephadm deployment tool management operations.
|
||||
|
||||
%package fuse
|
||||
Summary: Ceph fuse-based client
|
||||
@ -1040,7 +1040,7 @@ Group: Development/Libraries/Python
|
||||
%{?python_provide:%python_provide python-ceph-common}
|
||||
%description -n python-ceph-common
|
||||
This package contains data structures, classes and functions used by Ceph.
|
||||
It also contains utilities used for the SSH orchestrator.
|
||||
It also contains utilities used for the cephadm orchestrator.
|
||||
%endif
|
||||
|
||||
%package -n python%{python3_pkgversion}-ceph-common
|
||||
@ -1051,7 +1051,7 @@ Group: Development/Libraries/Python
|
||||
%{?python_provide:%python_provide python%{python3_pkgversion}-ceph-common}
|
||||
%description -n python%{python3_pkgversion}-ceph-common
|
||||
This package contains data structures, classes and functions used by Ceph.
|
||||
It also contains utilities used for the SSH orchestrator.
|
||||
It also contains utilities used for the cephadm orchestrator.
|
||||
|
||||
%if 0%{with cephfs_shell}
|
||||
%package -n cephfs-shell
|
||||
@ -1513,7 +1513,7 @@ fi
|
||||
%pre -n cephadm
|
||||
# create user
|
||||
if ! getent passwd | grep -q '^cephadm:'; then
|
||||
useradd -r -s /bin/bash -c "cephadm user for mgr/ssh" -m cephadm
|
||||
useradd -r -s /bin/bash -c "cephadm user for mgr/cephadm" -m cephadm
|
||||
fi
|
||||
# set up (initially empty) .ssh/authorized_keys file
|
||||
if ! test -d /home/cephadm/.ssh; then
|
||||
@ -1819,15 +1819,15 @@ if [ $1 -eq 1 ] ; then
|
||||
/usr/bin/systemctl try-restart ceph-mgr.target >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%files mgr-ssh
|
||||
%{_datadir}/ceph/mgr/ssh
|
||||
%files mgr-cephadm
|
||||
%{_datadir}/ceph/mgr/cephadm
|
||||
|
||||
%post mgr-ssh
|
||||
%post mgr-cephadm
|
||||
if [ $1 -eq 1 ] ; then
|
||||
/usr/bin/systemctl try-restart ceph-mgr.target >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%postun mgr-ssh
|
||||
%postun mgr-cephadm
|
||||
if [ $1 -eq 1 ] ; then
|
||||
/usr/bin/systemctl try-restart ceph-mgr.target >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
1
debian/ceph-mgr-cephadm.install
vendored
Normal file
1
debian/ceph-mgr-cephadm.install
vendored
Normal file
@ -0,0 +1 @@
|
||||
usr/share/ceph/mgr/cephadm
|
||||
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
# vim: set noet ts=8:
|
||||
# postinst script for ceph-mgr-ssh
|
||||
# postinst script for ceph-mgr-cephadm
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
@ -39,5 +39,3 @@ esac
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
1
debian/ceph-mgr-ssh.install
vendored
1
debian/ceph-mgr-ssh.install
vendored
@ -1 +0,0 @@
|
||||
usr/share/ceph/mgr/ssh
|
||||
2
debian/cephadm.postinst
vendored
2
debian/cephadm.postinst
vendored
@ -25,7 +25,7 @@ case "$1" in
|
||||
# 1. create user if not existing
|
||||
if ! getent passwd | grep -q "^cephadm:"; then
|
||||
echo -n "Adding system user cephadm.."
|
||||
adduser --quiet --system --disabled-password --gecos 'Ceph-dameon user for mgr/ssh' --shell /bin/bash cephadm 2>/dev/null || true
|
||||
adduser --quiet --system --disabled-password --gecos 'Ceph-dameon user for cephadm' --shell /bin/bash cephadm 2>/dev/null || true
|
||||
echo "..done"
|
||||
fi
|
||||
|
||||
|
||||
12
debian/control
vendored
12
debian/control
vendored
@ -227,7 +227,7 @@ Recommends: ceph-mgr-dashboard,
|
||||
ceph-mgr-diskprediction-cloud,
|
||||
ceph-mgr-rook,
|
||||
ceph-mgr-k8sevents,
|
||||
ceph-mgr-ssh
|
||||
ceph-mgr-cephadm
|
||||
Suggests: python-influxdb
|
||||
Replaces: ceph (<< 0.93-417),
|
||||
Breaks: ceph (<< 0.93-417),
|
||||
@ -326,7 +326,7 @@ Description: kubernetes events plugin for ceph-mgr
|
||||
ceph related events to the kubernetes events API, and track all events
|
||||
that occur within the rook-ceph namespace.
|
||||
|
||||
Package: ceph-mgr-ssh
|
||||
Package: ceph-mgr-cephadm
|
||||
Architecture: all
|
||||
Depends: ceph-mgr (= ${binary:Version}),
|
||||
cephadm,
|
||||
@ -334,12 +334,12 @@ Depends: ceph-mgr (= ${binary:Version}),
|
||||
${misc:Depends},
|
||||
${python:Depends},
|
||||
openssh-client
|
||||
Description: ssh orchestrator plugin for ceph-mgr
|
||||
Description: cephadm orchestrator plugin for ceph-mgr
|
||||
Ceph is a massively scalable, open-source, distributed
|
||||
storage system that runs on commodity hardware and delivers object,
|
||||
block and file system storage.
|
||||
.
|
||||
This package contains the SSH plugin for ceph-mgr's orchestration
|
||||
This package contains the CEPHADM plugin for ceph-mgr's orchestration
|
||||
functionality, to allow ceph-mgr to perform orchestration functions
|
||||
over a standard SSH connection.
|
||||
|
||||
@ -1249,7 +1249,7 @@ Description: Python 2 utility libraries for Ceph
|
||||
block and file system storage.
|
||||
.
|
||||
This package contains data structures, classes and functions used by Ceph.
|
||||
It also contains utilities used for the SSH orchestrator.
|
||||
It also contains utilities used for the cephadm orchestrator.
|
||||
|
||||
Package: python3-ceph-common
|
||||
Architecture: all
|
||||
@ -1262,7 +1262,7 @@ Description: Python 3 utility libraries for Ceph
|
||||
block and file system storage.
|
||||
.
|
||||
This package contains data structures, classes and functions used by Ceph.
|
||||
It also contains utilities used for the SSH orchestrator.
|
||||
It also contains utilities used for the cephadm orchestrator.
|
||||
|
||||
Package: libcephfs-java
|
||||
Section: java
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
================
|
||||
SSH orchestrator
|
||||
================
|
||||
====================
|
||||
cephadm orchestrator
|
||||
====================
|
||||
|
||||
The SSH orchestrator is an orchestrator module that does not rely on a separate
|
||||
The cephadm orchestrator is an orchestrator module that does not rely on a separate
|
||||
system such as Rook or Ansible, but rather manages nodes in a cluster by
|
||||
establishing an SSH connection and issuing explicit management commands.
|
||||
|
||||
Orchestrator modules only provide services to other modules, which in turn
|
||||
provide user interfaces. To try out the SSH module, you might like
|
||||
provide user interfaces. To try out the cephadm module, you might like
|
||||
to use the :ref:`Orchestrator CLI <orchestrator-cli-module>` module.
|
||||
|
||||
Requirements
|
||||
@ -18,22 +18,22 @@ Requirements
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The SSH orchestrator can be configured to use an SSH configuration file. This is
|
||||
The cephadm orchestrator can be configured to use an SSH configuration file. This is
|
||||
useful for specifying private keys and other SSH connection options.
|
||||
|
||||
::
|
||||
|
||||
# ceph config set mgr mgr/ssh/ssh_config_file /path/to/config
|
||||
# ceph config set mgr mgr/cephadm/ssh_config_file /path/to/config
|
||||
|
||||
An SSH configuration file can be provided without requiring an accessible file
|
||||
system path as the method above does.
|
||||
|
||||
::
|
||||
|
||||
# ceph ssh set-ssh-config -i /path/to/config
|
||||
# ceph cephadm set-ssh-config -i /path/to/config
|
||||
|
||||
To clear this value use the command:
|
||||
|
||||
::
|
||||
|
||||
# ceph ssh clear-ssh-config
|
||||
# ceph cephadm clear-ssh-config
|
||||
@ -41,9 +41,9 @@ sensible.
|
||||
Telemetry module <telemetry>
|
||||
Iostat module <iostat>
|
||||
Crash module <crash>
|
||||
Insights module <insights>
|
||||
Orchestrator CLI module <orchestrator_cli>
|
||||
Cephadm orchestrator <cephadm>
|
||||
Rook module <rook>
|
||||
DeepSea module <deepsea>
|
||||
Insights module <insights>
|
||||
Ansible module <ansible>
|
||||
SSH orchestrator <ssh>
|
||||
|
||||
@ -41,7 +41,7 @@ ceph:
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- ceph-fuse
|
||||
- libcephfs2
|
||||
- libcephfs-devel
|
||||
|
||||
@ -15,4 +15,4 @@ tasks:
|
||||
- No standby daemons available
|
||||
- cephfs_test_runner:
|
||||
modules:
|
||||
- tasks.mgr.test_ssh_orchestrator
|
||||
- tasks.mgr.test_cephadm_orchestrator
|
||||
@ -20,7 +20,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
- ceph-mgr
|
||||
- libcephfs2
|
||||
|
||||
@ -17,7 +17,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
- ceph-mgr
|
||||
- libcephfs2
|
||||
|
||||
@ -16,7 +16,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
- ceph-mgr
|
||||
- libcephfs2
|
||||
|
||||
@ -17,7 +17,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- install.upgrade:
|
||||
|
||||
@ -16,7 +16,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- install.upgrade:
|
||||
|
||||
@ -17,7 +17,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- install.upgrade:
|
||||
|
||||
@ -17,7 +17,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- install.upgrade:
|
||||
|
||||
@ -15,7 +15,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- print: "**** done install mimic"
|
||||
|
||||
@ -12,7 +12,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- print: "**** done installing mimic"
|
||||
|
||||
@ -9,7 +9,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- print: "**** done install mimic"
|
||||
|
||||
@ -15,7 +15,7 @@ tasks:
|
||||
- ceph-mgr-diskprediction-local
|
||||
- ceph-mgr-diskprediction-cloud
|
||||
- ceph-mgr-rook
|
||||
- ceph-mgr-ssh
|
||||
- ceph-mgr-cephadm
|
||||
- cephadm
|
||||
extra_packages: ['librados2']
|
||||
- print: "**** done install nautilus"
|
||||
|
||||
@ -15,8 +15,8 @@ class TestOrchestratorCli(MgrTestCase):
|
||||
def setUp(self):
|
||||
super(TestOrchestratorCli, self).setUp()
|
||||
self._load_module("orchestrator_cli")
|
||||
self._load_module("ssh")
|
||||
self._orch_cmd("set", "backend", "ssh")
|
||||
self._load_module("cephadm")
|
||||
self._orch_cmd("set", "backend", "cephadm")
|
||||
|
||||
def test_host_ls(self):
|
||||
self._orch_cmd("host", "add", "osd0")
|
||||
@ -1243,14 +1243,14 @@ def command_bootstrap():
|
||||
|
||||
# ssh
|
||||
if not args.skip_ssh:
|
||||
logger.info('Enabling ssh module...')
|
||||
cli(['mgr', 'module', 'enable', 'ssh'])
|
||||
logger.info('Enabling cephadm module...')
|
||||
cli(['mgr', 'module', 'enable', 'cephadm'])
|
||||
logger.info('Setting orchestrator backend to ssh...')
|
||||
cli(['orchestrator', 'set', 'backend', 'ssh'])
|
||||
cli(['orchestrator', 'set', 'backend', 'cephadm'])
|
||||
|
||||
logger.info('Generating ssh key...')
|
||||
cli(['ssh', 'generate-key'])
|
||||
ssh_pub = cli(['ssh', 'get-pub-key'])
|
||||
cli(['cephadm', 'generate-key'])
|
||||
ssh_pub = cli(['cephadm', 'get-pub-key'])
|
||||
|
||||
with open(args.output_pub_ssh_key, 'w') as f:
|
||||
f.write(ssh_pub)
|
||||
|
||||
@ -437,7 +437,7 @@ std::vector<Option> get_global_options() {
|
||||
.add_see_also("mon_host"),
|
||||
|
||||
Option("container_image", Option::TYPE_STR, Option::LEVEL_BASIC)
|
||||
.set_description("container image (used by ssh orchestrator)")
|
||||
.set_description("container image (used by cephadm orchestrator)")
|
||||
.set_flag(Option::FLAG_STARTUP)
|
||||
.set_default("ceph/daemon-base:latest-master-devel"),
|
||||
|
||||
|
||||
@ -202,7 +202,7 @@ void MonCapGrant::expand_profile(const EntityName& name) const
|
||||
profile_grants.push_back(MonCapGrant("auth", MON_CAP_R | MON_CAP_X));
|
||||
profile_grants.push_back(MonCapGrant("config-key", MON_CAP_R | MON_CAP_W));
|
||||
profile_grants.push_back(MonCapGrant("config", MON_CAP_R | MON_CAP_W));
|
||||
// ssh orchestrator provisions new daemon keys
|
||||
// cephadm orchestrator provisions new daemon keys
|
||||
profile_grants.push_back(MonCapGrant("auth get-or-create"));
|
||||
profile_grants.push_back(MonCapGrant("auth rm"));
|
||||
// tell commands (this is a bit of a kludge)
|
||||
|
||||
@ -12,23 +12,23 @@ In the following I'll use the `vstart` method.
|
||||
|
||||
::
|
||||
|
||||
# ../src/vstart.sh -n --ssh
|
||||
# ../src/vstart.sh -n --cephadm
|
||||
|
||||
*Note that when you specify `--ssh` you have to have passwordless ssh access to localhost*
|
||||
*Note that when you specify `--cephadm` you have to have passwordless ssh access to localhost*
|
||||
|
||||
It will add your ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub to `mgr/ssh/ssh_identity_{key, pub}`
|
||||
and add your $HOSTNAME to the list of known hosts.
|
||||
|
||||
This will also enable the ssh mgr module and enable it as the orchestrator backend.
|
||||
This will also enable the cephadm mgr module and enable it as the orchestrator backend.
|
||||
|
||||
*Optional:*
|
||||
|
||||
While the above is sufficient for most operations, you may want to add a second host to the mix.
|
||||
There is `Vagrantfile` for creating a minimal cluster in `src/pybind/mgr/ssh/`.
|
||||
There is `Vagrantfile` for creating a minimal cluster in `src/pybind/mgr/cephadm/`.
|
||||
|
||||
If you wish to extend the one-node-localhost cluster to i.e. test more sophisticated OSD deployments you can follow the next steps:
|
||||
|
||||
From within the `src/pybind/mgr/ssh` directory.
|
||||
From within the `src/pybind/mgr/cephadm` directory.
|
||||
|
||||
|
||||
1) Spawn VMs
|
||||
@ -43,12 +43,12 @@ mon0, mgr0, osd0
|
||||
NUM_DAEMONS can be used to increase the number of VMs created. (defaults to 1)
|
||||
|
||||
If will also come with the necessary packages preinstalled as well as your ~/.ssh/id_rsa.pub key
|
||||
injected. (to users root and vagrant; the SSH-orchestrator currently connects as root)
|
||||
injected. (to users root and vagrant; the cephadm-orchestrator currently connects as root)
|
||||
|
||||
|
||||
2) Update the ssh-config
|
||||
|
||||
The SSH-orchestrator needs to understand how to connect to the new node. Most likely the VM isn't reachable with the default settings used:
|
||||
The cephadm orchestrator needs to understand how to connect to the new node. Most likely the VM isn't reachable with the default settings used:
|
||||
|
||||
```
|
||||
Host *
|
||||
@ -67,7 +67,7 @@ Now set the newly created config for Ceph.
|
||||
|
||||
::
|
||||
|
||||
# ceph ssh set-ssh-config -i <path_to_ssh_conf>
|
||||
# ceph cephadm set-ssh-config -i <path_to_ssh_conf>
|
||||
|
||||
|
||||
3) Add the new host
|
||||
@ -3,4 +3,4 @@ import os
|
||||
if 'UNITTEST' in os.environ:
|
||||
import tests
|
||||
|
||||
from .module import SSHOrchestrator
|
||||
from .module import CephadmOrchestrator
|
||||
@ -88,7 +88,7 @@ class AsyncCompletion(orchestrator.Completion):
|
||||
many=False, # type: bool
|
||||
):
|
||||
|
||||
assert SSHOrchestrator.instance is not None
|
||||
assert CephadmOrchestrator.instance is not None
|
||||
self.many = many
|
||||
if name is None and on_complete is not None:
|
||||
name = on_complete.__name__
|
||||
@ -128,24 +128,24 @@ class AsyncCompletion(orchestrator.Completion):
|
||||
self.fail(e)
|
||||
|
||||
def run(value):
|
||||
assert SSHOrchestrator.instance
|
||||
assert CephadmOrchestrator.instance
|
||||
if self.many:
|
||||
if not value:
|
||||
logger.info('calling map_async without values')
|
||||
callback([])
|
||||
if six.PY3:
|
||||
SSHOrchestrator.instance._worker_pool.map_async(_callback, value,
|
||||
CephadmOrchestrator.instance._worker_pool.map_async(_callback, value,
|
||||
callback=callback,
|
||||
error_callback=error_callback)
|
||||
else:
|
||||
SSHOrchestrator.instance._worker_pool.map_async(_callback, value,
|
||||
CephadmOrchestrator.instance._worker_pool.map_async(_callback, value,
|
||||
callback=callback)
|
||||
else:
|
||||
if six.PY3:
|
||||
SSHOrchestrator.instance._worker_pool.apply_async(_callback, (value,),
|
||||
CephadmOrchestrator.instance._worker_pool.apply_async(_callback, (value,),
|
||||
callback=callback, error_callback=error_callback)
|
||||
else:
|
||||
SSHOrchestrator.instance._worker_pool.apply_async(_callback, (value,),
|
||||
CephadmOrchestrator.instance._worker_pool.apply_async(_callback, (value,),
|
||||
callback=callback)
|
||||
return self.ASYNC_RESULT
|
||||
|
||||
@ -229,7 +229,7 @@ def trivial_result(val):
|
||||
return AsyncCompletion(value=val, name='trivial_result')
|
||||
|
||||
|
||||
class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
class CephadmOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
|
||||
_STORE_HOST_PREFIX = "host"
|
||||
|
||||
@ -271,7 +271,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SSHOrchestrator, self).__init__(*args, **kwargs)
|
||||
super(CephadmOrchestrator, self).__init__(*args, **kwargs)
|
||||
self._cluster_fsid = self.get('mon_map')['fsid']
|
||||
|
||||
self.config_notify()
|
||||
@ -288,7 +288,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
|
||||
self._reconfig_ssh()
|
||||
|
||||
SSHOrchestrator.instance = self
|
||||
CephadmOrchestrator.instance = self
|
||||
self.all_progress_references = list() # type: List[orchestrator.ProgressReference]
|
||||
|
||||
# load inventory
|
||||
@ -325,7 +325,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
del self.service_cache[h]
|
||||
|
||||
def shutdown(self):
|
||||
self.log.error('ssh: shutdown')
|
||||
self.log.error('shutdown')
|
||||
self._worker_pool.close()
|
||||
self._worker_pool.join()
|
||||
|
||||
@ -430,7 +430,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
|
||||
def available(self):
|
||||
"""
|
||||
The SSH orchestrator is always available.
|
||||
The cephadm orchestrator is always available.
|
||||
"""
|
||||
return self.can_run()
|
||||
|
||||
@ -459,7 +459,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
unregistered_hosts))))
|
||||
|
||||
@orchestrator._cli_write_command(
|
||||
prefix='ssh set-ssh-config',
|
||||
prefix='cephadm set-ssh-config',
|
||||
desc='Set the ssh_config file (use -i <ssh_config>)')
|
||||
def _set_ssh_config(self, inbuf=None):
|
||||
"""
|
||||
@ -474,7 +474,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
return 0, "", ""
|
||||
|
||||
@orchestrator._cli_write_command(
|
||||
prefix='ssh clear-ssh-config',
|
||||
prefix='cephadm clear-ssh-config',
|
||||
desc='Clear the ssh_config file')
|
||||
def _clear_ssh_config(self):
|
||||
"""
|
||||
@ -485,7 +485,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
return 0, "", ""
|
||||
|
||||
@orchestrator._cli_write_command(
|
||||
'ssh generate-key',
|
||||
'cephadm generate-key',
|
||||
desc='Generate a cluster SSH key (if not present)')
|
||||
def _generate_key(self):
|
||||
if not self.ssh_pub or not self.ssh_key:
|
||||
@ -513,7 +513,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
return 0, '', ''
|
||||
|
||||
@orchestrator._cli_write_command(
|
||||
'ssh clear-key',
|
||||
'cephadm clear-key',
|
||||
desc='Clear cluster SSH key')
|
||||
def _clear_key(self):
|
||||
self.set_store('ssh_identity_key', None)
|
||||
@ -522,7 +522,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
return 0, '', ''
|
||||
|
||||
@orchestrator._cli_read_command(
|
||||
'ssh get-pub-key',
|
||||
'cephadm get-pub-key',
|
||||
desc='Show SSH public key for connecting to cluster hosts')
|
||||
def _get_pub_key(self):
|
||||
if self.ssh_pub:
|
||||
@ -531,13 +531,13 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
return -errno.ENOENT, '', 'No cluster SSH key defined'
|
||||
|
||||
@orchestrator._cli_read_command(
|
||||
'ssh get-user',
|
||||
'cephadm get-user',
|
||||
desc='Show user for SSHing to cluster hosts')
|
||||
def _get_user(self):
|
||||
return 0, self.ssh_user, ''
|
||||
|
||||
@orchestrator._cli_read_command(
|
||||
'ssh check-host',
|
||||
'cephadm check-host',
|
||||
'name=host,type=CephString',
|
||||
'Check whether we can access and manage a remote host')
|
||||
def _check_host(self, host):
|
||||
@ -548,7 +548,7 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
return 0, 'host ok', err
|
||||
|
||||
@orchestrator._cli_write_command(
|
||||
'ssh prepare-host',
|
||||
'cephadm prepare-host',
|
||||
'name=host,type=CephString',
|
||||
'Try to prepare a host for remote management')
|
||||
def _prepare_host(self, host):
|
||||
46
src/pybind/mgr/cephadm/tests/fixtures.py
Normal file
46
src/pybind/mgr/cephadm/tests/fixtures.py
Normal file
@ -0,0 +1,46 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
import pytest
|
||||
|
||||
from cephadm import CephadmOrchestrator
|
||||
from tests import mock
|
||||
|
||||
|
||||
def set_store(self, k, v):
|
||||
if v is None:
|
||||
del self._store[k]
|
||||
else:
|
||||
self._store[k] = v
|
||||
|
||||
|
||||
def get_store(self, k):
|
||||
return self._store[k]
|
||||
|
||||
|
||||
def get_store_prefix(self, prefix):
|
||||
return {
|
||||
k: v for k, v in self._store.items()
|
||||
if k.startswith(prefix)
|
||||
}
|
||||
|
||||
def get_ceph_option(_, key):
|
||||
return __file__
|
||||
|
||||
@pytest.yield_fixture()
|
||||
def cephadm_module():
|
||||
with mock.patch("cephadm.module.CephadmOrchestrator.get_ceph_option", get_ceph_option),\
|
||||
mock.patch("cephadm.module.CephadmOrchestrator._configure_logging", lambda *args: None),\
|
||||
mock.patch("cephadm.module.CephadmOrchestrator.set_store", set_store),\
|
||||
mock.patch("cephadm.module.CephadmOrchestrator.get_store", get_store),\
|
||||
mock.patch("cephadm.module.CephadmOrchestrator.get_store_prefix", get_store_prefix):
|
||||
CephadmOrchestrator._register_commands('')
|
||||
m = CephadmOrchestrator.__new__ (CephadmOrchestrator)
|
||||
m._root_logger = mock.MagicMock()
|
||||
m._store = {
|
||||
'ssh_config': '',
|
||||
'ssh_identity_key': '',
|
||||
'ssh_identity_pub': '',
|
||||
'inventory': {},
|
||||
}
|
||||
m.__init__('cephadm', 0, 0)
|
||||
yield m
|
||||
174
src/pybind/mgr/cephadm/tests/test_cephadm.py
Normal file
174
src/pybind/mgr/cephadm/tests/test_cephadm.py
Normal file
@ -0,0 +1,174 @@
|
||||
import json
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
|
||||
from ceph.deployment.drive_group import DriveGroupSpec, DeviceSelection
|
||||
|
||||
try:
|
||||
from typing import Any
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from orchestrator import ServiceDescription, raise_if_exception, Completion, InventoryNode, \
|
||||
StatelessServiceSpec, PlacementSpec, RGWSpec, parse_host_specs
|
||||
from ..module import CephadmOrchestrator
|
||||
from tests import mock
|
||||
from .fixtures import cephadm_module
|
||||
|
||||
|
||||
"""
|
||||
TODOs:
|
||||
There is really room for improvement here. I just quickly assembled theses tests.
|
||||
I general, everything should be testes in Teuthology as well. Reasons for
|
||||
also testing this here is the development roundtrip time.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
def _run_cephadm(ret):
|
||||
def foo(*args, **kwargs):
|
||||
return ret, '', 0
|
||||
return foo
|
||||
|
||||
def mon_command(*args, **kwargs):
|
||||
return 0, '', ''
|
||||
|
||||
|
||||
class TestSSH(object):
|
||||
def _wait(self, m, c):
|
||||
# type: (CephadmOrchestrator, Completion) -> Any
|
||||
m.process([c])
|
||||
m.process([c])
|
||||
|
||||
for _ in range(30):
|
||||
if c.is_finished:
|
||||
raise_if_exception(c)
|
||||
return c.result
|
||||
time.sleep(0.1)
|
||||
assert False, "timeout" + str(c._state)
|
||||
|
||||
@contextmanager
|
||||
def _with_host(self, m, name):
|
||||
self._wait(m, m.add_host(name))
|
||||
yield
|
||||
self._wait(m, m.remove_host(name))
|
||||
|
||||
def test_get_unique_name(self, cephadm_module):
|
||||
existing = [
|
||||
ServiceDescription(service_instance='mon.a')
|
||||
]
|
||||
new_mon = cephadm_module.get_unique_name(existing, 'mon')
|
||||
assert new_mon.startswith('mon.')
|
||||
assert new_mon != 'mon.a'
|
||||
|
||||
def test_host(self, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
assert self._wait(cephadm_module, cephadm_module.get_hosts()) == [InventoryNode('test')]
|
||||
c = cephadm_module.get_hosts()
|
||||
assert self._wait(cephadm_module, c) == []
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
def test_service_ls(self, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
c = cephadm_module.describe_service()
|
||||
assert self._wait(cephadm_module, c) == []
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
def test_device_ls(self, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
c = cephadm_module.get_inventory()
|
||||
assert self._wait(cephadm_module, c) == [InventoryNode('test')]
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.send_command")
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._get_connection")
|
||||
def test_mon_update(self, _send_command, _get_connection, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
c = cephadm_module.update_mons(1, [parse_host_specs('test:0.0.0.0=a')])
|
||||
assert self._wait(cephadm_module, c) == ["(Re)deployed mon.a on host 'test'"]
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.send_command")
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._get_connection")
|
||||
def test_mgr_update(self, _send_command, _get_connection, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
c = cephadm_module.update_mgrs(1, [parse_host_specs('test:0.0.0.0')])
|
||||
[out] = self._wait(cephadm_module, c)
|
||||
assert "(Re)deployed mgr." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.send_command")
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._get_connection")
|
||||
def test_create_osds(self, _send_command, _get_connection, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
dg = DriveGroupSpec('test', DeviceSelection(paths=['']))
|
||||
c = cephadm_module.create_osds(dg)
|
||||
assert self._wait(cephadm_module, c) == "Created osd(s) on host 'test'"
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.send_command")
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._get_connection")
|
||||
def test_mds(self, _send_command, _get_connection, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
ps = PlacementSpec(nodes=['test'])
|
||||
c = cephadm_module.add_mds(StatelessServiceSpec('name', ps))
|
||||
[out] = self._wait(cephadm_module, c)
|
||||
assert "(Re)deployed mds.name." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.send_command")
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._get_connection")
|
||||
def test_rgw(self, _send_command, _get_connection, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
ps = PlacementSpec(nodes=['test'])
|
||||
c = cephadm_module.add_rgw(RGWSpec('realm', 'zone', ps))
|
||||
[out] = self._wait(cephadm_module, c)
|
||||
assert "(Re)deployed rgw.realm.zone." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm(
|
||||
json.dumps([
|
||||
dict(
|
||||
name='rgw.myrgw.foobar',
|
||||
style='cephadm',
|
||||
fsid='fsid',
|
||||
container_id='container_id',
|
||||
version='version',
|
||||
state='running',
|
||||
)
|
||||
])
|
||||
))
|
||||
def test_remove_rgw(self, cephadm_module):
|
||||
cephadm_module._cluster_fsid = "fsid"
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
c = cephadm_module.remove_rgw('myrgw')
|
||||
out = self._wait(cephadm_module, c)
|
||||
assert out == ["Removed rgw.myrgw.foobar from host 'test'"]
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.send_command")
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._get_connection")
|
||||
def test_rbd_mirror(self, _send_command, _get_connection, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
ps = PlacementSpec(nodes=['test'])
|
||||
c = cephadm_module.add_rbd_mirror(StatelessServiceSpec('name', ps))
|
||||
[out] = self._wait(cephadm_module, c)
|
||||
assert "(Re)deployed rbd-mirror." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.send_command")
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("cephadm.module.CephadmOrchestrator._get_connection")
|
||||
def test_blink_device_light(self, _send_command, _get_connection, cephadm_module):
|
||||
with self._with_host(cephadm_module, 'test'):
|
||||
c = cephadm_module.blink_device_light('ident', True, [('test', '')])
|
||||
assert self._wait(cephadm_module, c) == ['Set ident light for test: on']
|
||||
@ -11,13 +11,13 @@ import pytest
|
||||
|
||||
|
||||
from orchestrator import raise_if_exception, Completion
|
||||
from .fixtures import ssh_module
|
||||
from ..module import trivial_completion, async_completion, async_map_completion, SSHOrchestrator
|
||||
from .fixtures import cephadm_module
|
||||
from ..module import trivial_completion, async_completion, async_map_completion, CephadmOrchestrator
|
||||
|
||||
|
||||
class TestCompletion(object):
|
||||
def _wait(self, m, c):
|
||||
# type: (SSHOrchestrator, Completion) -> Any
|
||||
# type: (CephadmOrchestrator, Completion) -> Any
|
||||
m.process([c])
|
||||
m.process([c])
|
||||
|
||||
@ -28,11 +28,11 @@ class TestCompletion(object):
|
||||
time.sleep(0.1)
|
||||
assert False, "timeout" + str(c._state)
|
||||
|
||||
def test_trivial(self, ssh_module):
|
||||
def test_trivial(self, cephadm_module):
|
||||
@trivial_completion
|
||||
def run(x):
|
||||
return x+1
|
||||
assert self._wait(ssh_module, run(1)) == 2
|
||||
assert self._wait(cephadm_module, run(1)) == 2
|
||||
|
||||
@pytest.mark.parametrize("input", [
|
||||
((1, ), ),
|
||||
@ -40,12 +40,12 @@ class TestCompletion(object):
|
||||
(("hallo", ), ),
|
||||
(("hallo", "foo"), ),
|
||||
])
|
||||
def test_async(self, input, ssh_module):
|
||||
def test_async(self, input, cephadm_module):
|
||||
@async_completion
|
||||
def run(*args):
|
||||
return str(args)
|
||||
|
||||
assert self._wait(ssh_module, run(*input)) == str(input)
|
||||
assert self._wait(cephadm_module, run(*input)) == str(input)
|
||||
|
||||
@pytest.mark.parametrize("input,expected", [
|
||||
([], []),
|
||||
@ -55,16 +55,16 @@ class TestCompletion(object):
|
||||
(list(range(5)), [str((x, )) for x in range(5)]),
|
||||
([(1, 2), (3, 4)], ["(1, 2)", "(3, 4)"]),
|
||||
])
|
||||
def test_async_map(self, input, expected, ssh_module):
|
||||
def test_async_map(self, input, expected, cephadm_module):
|
||||
@async_map_completion
|
||||
def run(*args):
|
||||
return str(args)
|
||||
|
||||
c = run(input)
|
||||
self._wait(ssh_module, c)
|
||||
self._wait(cephadm_module, c)
|
||||
assert c.result == expected
|
||||
|
||||
def test_async_self(self, ssh_module):
|
||||
def test_async_self(self, cephadm_module):
|
||||
class Run(object):
|
||||
def __init__(self):
|
||||
self.attr = 1
|
||||
@ -74,7 +74,7 @@ class TestCompletion(object):
|
||||
assert self.attr == 1
|
||||
return x + 1
|
||||
|
||||
assert self._wait(ssh_module, Run().run(1)) == 2
|
||||
assert self._wait(cephadm_module, Run().run(1)) == 2
|
||||
|
||||
@pytest.mark.parametrize("input,expected", [
|
||||
([], []),
|
||||
@ -84,7 +84,7 @@ class TestCompletion(object):
|
||||
(list(range(5)), [str((x, )) for x in range(5)]),
|
||||
([(1, 2), (3, 4)], ["(1, 2)", "(3, 4)"]),
|
||||
])
|
||||
def test_async_map_self(self, input, expected, ssh_module):
|
||||
def test_async_map_self(self, input, expected, cephadm_module):
|
||||
class Run(object):
|
||||
def __init__(self):
|
||||
self.attr = 1
|
||||
@ -95,17 +95,17 @@ class TestCompletion(object):
|
||||
return str(args)
|
||||
|
||||
c = Run().run(input)
|
||||
self._wait(ssh_module, c)
|
||||
self._wait(cephadm_module, c)
|
||||
assert c.result == expected
|
||||
|
||||
def test_then1(self, ssh_module):
|
||||
def test_then1(self, cephadm_module):
|
||||
@async_map_completion
|
||||
def run(x):
|
||||
return x+1
|
||||
|
||||
assert self._wait(ssh_module, run([1,2]).then(str)) == '[2, 3]'
|
||||
assert self._wait(cephadm_module, run([1,2]).then(str)) == '[2, 3]'
|
||||
|
||||
def test_then2(self, ssh_module):
|
||||
def test_then2(self, cephadm_module):
|
||||
@async_map_completion
|
||||
def run(x):
|
||||
time.sleep(0.1)
|
||||
@ -117,10 +117,10 @@ class TestCompletion(object):
|
||||
|
||||
c = run([1,2]).then(async_str)
|
||||
|
||||
self._wait(ssh_module, c)
|
||||
self._wait(cephadm_module, c)
|
||||
assert c.result == '[2, 3]'
|
||||
|
||||
def test_then3(self, ssh_module):
|
||||
def test_then3(self, cephadm_module):
|
||||
@async_map_completion
|
||||
def run(x):
|
||||
time.sleep(0.1)
|
||||
@ -131,10 +131,10 @@ class TestCompletion(object):
|
||||
|
||||
c = run([1,2]).then(async_str)
|
||||
|
||||
self._wait(ssh_module, c)
|
||||
self._wait(cephadm_module, c)
|
||||
assert c.result == '[2, 3]'
|
||||
|
||||
def test_then4(self, ssh_module):
|
||||
def test_then4(self, cephadm_module):
|
||||
@async_map_completion
|
||||
def run(x):
|
||||
time.sleep(0.1)
|
||||
@ -145,11 +145,11 @@ class TestCompletion(object):
|
||||
|
||||
c = run([1,2]).then(async_str)
|
||||
|
||||
self._wait(ssh_module, c)
|
||||
self._wait(cephadm_module, c)
|
||||
assert c.result == '[2, 3]hello'
|
||||
|
||||
@pytest.mark.skip(reason="see limitation of async_map_completion")
|
||||
def test_then5(self, ssh_module):
|
||||
def test_then5(self, cephadm_module):
|
||||
@async_map_completion
|
||||
def run(x):
|
||||
time.sleep(0.1)
|
||||
@ -157,14 +157,13 @@ class TestCompletion(object):
|
||||
|
||||
c = run([1,2])
|
||||
|
||||
self._wait(ssh_module, c)
|
||||
self._wait(cephadm_module, c)
|
||||
assert c.result == "['2', '3']"
|
||||
|
||||
def test_raise(self, ssh_module):
|
||||
def test_raise(self, cephadm_module):
|
||||
@async_completion
|
||||
def run(x):
|
||||
raise ZeroDivisionError()
|
||||
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
self._wait(ssh_module, run(1))
|
||||
|
||||
self._wait(cephadm_module, run(1))
|
||||
@ -27,7 +27,7 @@ class OrchestratorCli(orchestrator.OrchestratorClientMixin, MgrModule):
|
||||
'type': 'str',
|
||||
'default': None,
|
||||
'desc': 'Orchestrator backend',
|
||||
'enum_allowed': ['ssh', 'rook', 'ansible', 'deepsea',
|
||||
'enum_allowed': ['cephadm', 'rook', 'ansible', 'deepsea',
|
||||
'test_orchestrator'],
|
||||
'runtime': True,
|
||||
},
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
import pytest
|
||||
|
||||
from ssh import SSHOrchestrator
|
||||
from tests import mock
|
||||
|
||||
|
||||
def set_store(self, k, v):
|
||||
if v is None:
|
||||
del self._store[k]
|
||||
else:
|
||||
self._store[k] = v
|
||||
|
||||
|
||||
def get_store(self, k):
|
||||
return self._store[k]
|
||||
|
||||
|
||||
def get_store_prefix(self, prefix):
|
||||
return {
|
||||
k: v for k, v in self._store.items()
|
||||
if k.startswith(prefix)
|
||||
}
|
||||
|
||||
def get_ceph_option(_, key):
|
||||
return __file__
|
||||
|
||||
@pytest.yield_fixture()
|
||||
def ssh_module():
|
||||
with mock.patch("ssh.module.SSHOrchestrator.get_ceph_option", get_ceph_option),\
|
||||
mock.patch("ssh.module.SSHOrchestrator._configure_logging", lambda *args: None),\
|
||||
mock.patch("ssh.module.SSHOrchestrator.set_store", set_store),\
|
||||
mock.patch("ssh.module.SSHOrchestrator.get_store", get_store),\
|
||||
mock.patch("ssh.module.SSHOrchestrator.get_store_prefix", get_store_prefix):
|
||||
SSHOrchestrator._register_commands('')
|
||||
m = SSHOrchestrator.__new__ (SSHOrchestrator)
|
||||
m._root_logger = mock.MagicMock()
|
||||
m._store = {
|
||||
'ssh_config': '',
|
||||
'ssh_identity_key': '',
|
||||
'ssh_identity_pub': '',
|
||||
'inventory': {},
|
||||
}
|
||||
m.__init__('ssh', 0, 0)
|
||||
yield m
|
||||
@ -1,176 +0,0 @@
|
||||
import json
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
|
||||
from ceph.deployment.drive_group import DriveGroupSpec, DeviceSelection
|
||||
|
||||
try:
|
||||
from typing import Any
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from orchestrator import ServiceDescription, raise_if_exception, Completion, InventoryNode, \
|
||||
StatelessServiceSpec, PlacementSpec, RGWSpec, parse_host_specs
|
||||
from ..module import SSHOrchestrator
|
||||
from tests import mock
|
||||
from .fixtures import ssh_module
|
||||
|
||||
|
||||
"""
|
||||
TODOs:
|
||||
There is really room for improvement here. I just quickly assembled theses tests.
|
||||
I general, everything should be testes in Teuthology as well. Reasons for
|
||||
also testing this here is the development roundtrip time.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
def _run_cephadm(ret):
|
||||
def foo(*args, **kwargs):
|
||||
return ret, '', 0
|
||||
return foo
|
||||
|
||||
def mon_command(*args, **kwargs):
|
||||
return 0, '', ''
|
||||
|
||||
|
||||
class TestSSH(object):
|
||||
def _wait(self, m, c):
|
||||
# type: (SSHOrchestrator, Completion) -> Any
|
||||
m.process([c])
|
||||
m.process([c])
|
||||
|
||||
for _ in range(30):
|
||||
if c.is_finished:
|
||||
raise_if_exception(c)
|
||||
return c.result
|
||||
time.sleep(0.1)
|
||||
assert False, "timeout" + str(c._state)
|
||||
|
||||
@contextmanager
|
||||
def _with_host(self, m, name):
|
||||
self._wait(m, m.add_host(name))
|
||||
yield
|
||||
self._wait(m, m.remove_host(name))
|
||||
|
||||
def test_get_unique_name(self, ssh_module):
|
||||
existing = [
|
||||
ServiceDescription(service_instance='mon.a')
|
||||
]
|
||||
new_mon = ssh_module.get_unique_name(existing, 'mon')
|
||||
assert new_mon.startswith('mon.')
|
||||
assert new_mon != 'mon.a'
|
||||
|
||||
def test_host(self, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
assert self._wait(ssh_module, ssh_module.get_hosts()) == [InventoryNode('test')]
|
||||
c = ssh_module.get_hosts()
|
||||
assert self._wait(ssh_module, c) == []
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
def test_service_ls(self, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
c = ssh_module.describe_service()
|
||||
assert self._wait(ssh_module, c) == []
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
def test_device_ls(self, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
c = ssh_module.get_inventory()
|
||||
assert self._wait(ssh_module, c) == [InventoryNode('test')]
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
@mock.patch("ssh.module.SSHOrchestrator.send_command")
|
||||
@mock.patch("ssh.module.SSHOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("ssh.module.SSHOrchestrator._get_connection")
|
||||
def test_mon_update(self, _send_command, _get_connection, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
c = ssh_module.update_mons(1, [parse_host_specs('test:0.0.0.0=a')])
|
||||
assert self._wait(ssh_module, c) == ["(Re)deployed mon.a on host 'test'"]
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('[]'))
|
||||
@mock.patch("ssh.module.SSHOrchestrator.send_command")
|
||||
@mock.patch("ssh.module.SSHOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("ssh.module.SSHOrchestrator._get_connection")
|
||||
def test_mgr_update(self, _send_command, _get_connection, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
c = ssh_module.update_mgrs(1, [parse_host_specs('test:0.0.0.0')])
|
||||
[out] = self._wait(ssh_module, c)
|
||||
assert "(Re)deployed mgr." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("ssh.module.SSHOrchestrator.send_command")
|
||||
@mock.patch("ssh.module.SSHOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("ssh.module.SSHOrchestrator._get_connection")
|
||||
def test_create_osds(self, _send_command, _get_connection, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
dg = DriveGroupSpec('test', DeviceSelection(paths=['']))
|
||||
c = ssh_module.create_osds(dg)
|
||||
assert self._wait(ssh_module, c) == "Created osd(s) on host 'test'"
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("ssh.module.SSHOrchestrator.send_command")
|
||||
@mock.patch("ssh.module.SSHOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("ssh.module.SSHOrchestrator._get_connection")
|
||||
def test_mds(self, _send_command, _get_connection, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
ps = PlacementSpec(nodes=['test'])
|
||||
c = ssh_module.add_mds(StatelessServiceSpec('name', ps))
|
||||
[out] = self._wait(ssh_module, c)
|
||||
assert "(Re)deployed mds.name." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("ssh.module.SSHOrchestrator.send_command")
|
||||
@mock.patch("ssh.module.SSHOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("ssh.module.SSHOrchestrator._get_connection")
|
||||
def test_rgw(self, _send_command, _get_connection, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
ps = PlacementSpec(nodes=['test'])
|
||||
c = ssh_module.add_rgw(RGWSpec('realm', 'zone', ps))
|
||||
[out] = self._wait(ssh_module, c)
|
||||
assert "(Re)deployed rgw.realm.zone." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm(
|
||||
json.dumps([
|
||||
dict(
|
||||
name='rgw.myrgw.foobar',
|
||||
style='cephadm',
|
||||
fsid='fsid',
|
||||
container_id='container_id',
|
||||
version='version',
|
||||
state='running',
|
||||
)
|
||||
])
|
||||
))
|
||||
def test_remove_rgw(self, ssh_module):
|
||||
ssh_module._cluster_fsid = "fsid"
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
c = ssh_module.remove_rgw('myrgw')
|
||||
out = self._wait(ssh_module, c)
|
||||
assert out == ["Removed rgw.myrgw.foobar from host 'test'"]
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("ssh.module.SSHOrchestrator.send_command")
|
||||
@mock.patch("ssh.module.SSHOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("ssh.module.SSHOrchestrator._get_connection")
|
||||
def test_rbd_mirror(self, _send_command, _get_connection, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
ps = PlacementSpec(nodes=['test'])
|
||||
c = ssh_module.add_rbd_mirror(StatelessServiceSpec('name', ps))
|
||||
[out] = self._wait(ssh_module, c)
|
||||
assert "(Re)deployed rbd-mirror." in out
|
||||
assert " on host 'test'" in out
|
||||
|
||||
@mock.patch("ssh.module.SSHOrchestrator._run_cephadm", _run_cephadm('{}'))
|
||||
@mock.patch("ssh.module.SSHOrchestrator.send_command")
|
||||
@mock.patch("ssh.module.SSHOrchestrator.mon_command", mon_command)
|
||||
@mock.patch("ssh.module.SSHOrchestrator._get_connection")
|
||||
def test_blink_device_light(self, _send_command, _get_connection, ssh_module):
|
||||
with self._with_host(ssh_module, 'test'):
|
||||
c = ssh_module.blink_device_light('ident', True, [('test', '')])
|
||||
assert self._wait(ssh_module, c) == ['Set ident light for test: on']
|
||||
|
||||
|
||||
@ -5,11 +5,11 @@ skipsdist = true
|
||||
[testenv]
|
||||
setenv = UNITTEST = true
|
||||
deps = -r requirements.txt
|
||||
commands = pytest -v --cov --cov-append --cov-report=term --doctest-modules {posargs:mgr_util.py tests/ ssh/}
|
||||
commands = pytest -v --cov --cov-append --cov-report=term --doctest-modules {posargs:mgr_util.py tests/ cephadm/}
|
||||
|
||||
[testenv:mypy]
|
||||
basepython = python3
|
||||
deps =
|
||||
-r requirements.txt
|
||||
mypy
|
||||
commands = mypy --config-file=../../mypy.ini orchestrator.py ssh/module.py rook/module.py
|
||||
commands = mypy --config-file=../../mypy.ini orchestrator.py cephadm/module.py rook/module.py
|
||||
@ -152,7 +152,7 @@ redirect=0
|
||||
smallmds=0
|
||||
short=0
|
||||
ec=0
|
||||
ssh=0
|
||||
cephadm=0
|
||||
parallel=true
|
||||
hitset=""
|
||||
overwrite_conf=1
|
||||
@ -237,7 +237,7 @@ usage=$usage"\t--crimson: use crimson-osd instead of ceph-osd\n"
|
||||
usage=$usage"\t--osd-args: specify any extra osd specific options\n"
|
||||
usage=$usage"\t--bluestore-devs: comma-separated list of blockdevs to use for bluestore\n"
|
||||
usage=$usage"\t--inc-osd: append some more osds into existing vcluster\n"
|
||||
usage=$usage"\t--ssh: enable ssh orchestrator with ~/.ssh/id_rsa[.pub]\n"
|
||||
usage=$usage"\t--cephadm: enable cephadm orchestrator with ~/.ssh/id_rsa[.pub]\n"
|
||||
usage=$usage"\t--no-parallel: dont start all OSDs in parallel\n"
|
||||
|
||||
usage_exit() {
|
||||
@ -299,8 +299,8 @@ case $1 in
|
||||
--msgr21 )
|
||||
msgr="21"
|
||||
;;
|
||||
--ssh )
|
||||
ssh=1
|
||||
--cephadm )
|
||||
cephadm=1
|
||||
;;
|
||||
--no-parallel )
|
||||
parallel=false
|
||||
@ -999,12 +999,12 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$ssh" -eq 1 ]; then
|
||||
debug echo Enabling ssh orchestrator
|
||||
if [ "$cephadm" -eq 1 ]; then
|
||||
debug echo Enabling cephadm orchestrator
|
||||
ceph_adm config-key set mgr/ssh/ssh_identity_key -i ~/.ssh/id_rsa
|
||||
ceph_adm config-key set mgr/ssh/ssh_identity_pub -i ~/.ssh/id_rsa.pub
|
||||
ceph_adm mgr module enable ssh
|
||||
ceph_adm orchestrator set backend ssh
|
||||
ceph_adm mgr module enable cephadm
|
||||
ceph_adm orchestrator set backend cephadm
|
||||
ceph_adm orchestrator host add $HOSTNAME
|
||||
fi
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user