Enable users to start/stop Crimson OSD's

This patchset modifies the add-disk action so that it now
can optionally start a Crimson OSD daemon.

Change-Id: I59bf4e41f1f56c6bda2352b5613289ff73113342
Depends-On: If58bde4d5445ed5de420abc007db6bf8b8e43269
This commit is contained in:
Luciano Lo Giudice 2022-09-05 17:13:55 -03:00
parent 0b8a583892
commit dbe3ee52bc
5 changed files with 98 additions and 3 deletions

View File

@ -59,6 +59,16 @@ add-disk:
The size of the partitions to create for the caching devices. If left
unspecified, then the full size of the devices will be split evenly
across partitions.
use-crimson:
type: boolean
description: |
Whether to use the Crimson implementation for the new OSD. Note that
this is an experimental feature, and the charm doesn't provide any
lifecycle support for OSD's that run on Crimson.
i-really-mean-it:
type: boolean
description: |
Must be set when 'use-crimson' is True.
required:
- osd-devices
blacklist-add-disk:

View File

@ -14,8 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
import psutil
import shutil
import subprocess
import sys
sys.path.append('lib')
@ -24,6 +27,7 @@ sys.path.append('hooks')
import charmhelpers.contrib.storage.linux.ceph as ch_ceph
import charmhelpers.core.hookenv as hookenv
from charmhelpers.core.hookenv import function_fail
from charmhelpers.fetch import apt_install
from charmhelpers.core.unitdata import kv
from utils import (PartitionIter, device_size, DeviceError)
@ -32,8 +36,51 @@ import ceph_hooks
import charms_ceph.utils
CRIMSON_PACKAGES = ['crimson-osd', 'libc-ares2', 'libcrypto++-dev',
'libyaml-cpp-dev']
CRIMSON_SYSTEMD_FILE = '/lib/systemd/system/crimson-osd@.service'
def get_osd_from_device(device):
"""Given a device, return the OSD ID that it maps to."""
output = subprocess.check_output(['ceph-volume', 'lvm', 'list',
'--format=json'])
devmap = json.loads(output.decode('utf8'))
for osd_id, data in devmap.items():
for elem in data:
if device in elem.get('devices', []):
return osd_id
def start_crimson_osd(osd_id, device):
"""An OSD was started with the classic daemon, but Crimson was
requested. As such, stop the current one and launch the correct daemon."""
if osd_id is None:
osd_id = get_osd_from_device(device)
charms_ceph.utils.stop_osd(osd_id)
charms_ceph.utils.disable_osd(osd_id)
unit_name = (
'/run/systemd/system/ceph-osd.target.wants/ceph-osd@{}.service'
.format(osd_id))
if os.path.exists(unit_name):
os.remove(unit_name)
if not os.path.exists(CRIMSON_SYSTEMD_FILE):
apt_install(CRIMSON_PACKAGES, fatal=True)
shutil.copy('files/systemd/crimson-osd@.service', CRIMSON_SYSTEMD_FILE)
subprocess.check_call(['systemctl', 'daemon-reload'])
subprocess.check_call(['systemctl', 'enable',
'crimson-osd@{}'.format(osd_id)])
subprocess.check_call(['systemctl', 'start',
'crimson-osd@{}'.format(osd_id)])
def add_device(request, device_path, bucket=None,
osd_id=None, part_iter=None):
osd_id=None, part_iter=None, use_crimson=False):
"""Add a new device to be used by the OSD unit.
:param request: A broker request to notify monitors of changes.
@ -71,6 +118,10 @@ def add_device(request, device_path, bucket=None,
hookenv.config('bluestore'),
hookenv.config('osd-encrypt-keymanager'),
osd_id)
if use_crimson:
start_crimson_osd(osd_id, effective_dev)
# Make it fast!
if hookenv.config('autotune'):
charms_ceph.utils.tune_dev(device_path)
@ -152,6 +203,11 @@ def validate_partition_size(psize, devices, caches):
if __name__ == "__main__":
crimson = hookenv.action_get('use-crimson')
if crimson and not hookenv.action_get('i-really-mean-it'):
function_fail('Need to pass i-really-mean-it for Crimson OSDs')
sys.exit(1)
request = ch_ceph.CephBrokerRq()
devices = get_devices('osd-devices')
caches = get_devices('cache-devices') or cache_storage()
@ -184,7 +240,8 @@ if __name__ == "__main__":
request = add_device(request=request,
device_path=dev,
bucket=hookenv.action_get("bucket"),
osd_id=osd_id, part_iter=part_iter)
osd_id=osd_id, part_iter=part_iter,
use_crimson=crimson)
except Exception:
errors.append(dev)

View File

@ -0,0 +1,9 @@
[Unit]
Description=Ceph object storage daemon crimson-osd.%i
[Service]
Environment=CLUSTER=ceph
ExecStart=/usr/bin/crimson-osd -i %i
ExecStop=/usr/bin/kill -QUIT $MAINPID
User=ceph
Group=ceph

View File

@ -79,7 +79,7 @@ deps = -r{toxinidir}/requirements.txt
[testenv:pep8]
basepython = python3
deps = flake8==3.9.2
charm-tools==2.8.3
charm-tools==2.8.4
commands = flake8 {posargs} hooks unit_tests tests actions lib files
charm-proof

View File

@ -103,3 +103,22 @@ class AddDiskActionTests(CharmTestCase):
self.assertTrue(add_disk.validate_osd_id(elem))
for elem in ('osd.-1', '-3', '???', -100, 3.4, {}):
self.assertFalse(add_disk.validate_osd_id(elem))
@mock.patch.object(add_disk.charms_ceph.utils, 'disable_osd')
@mock.patch.object(add_disk.charms_ceph.utils, 'stop_osd')
@mock.patch.object(add_disk.subprocess, 'check_output')
@mock.patch.object(add_disk.subprocess, 'check_call')
@mock.patch.object(add_disk, 'apt_install')
@mock.patch.object(add_disk.shutil, 'copy')
@mock.patch.object(add_disk.os.path, 'exists')
def test_crimson_osd(self, os_path_exists, shcopy, apt_install,
check_call, check_output, stop_osd, disable_osd):
os_path_exists.return_value = False
check_output.return_value = b'{"1": [{"devices": ["/dev/vdc"]}]}'
self.assertIsNone(add_disk.get_osd_from_device("/dev/vda"))
add_disk.start_crimson_osd(None, '/dev/vdc')
stop_osd.assert_called_with("1")
check_call.assert_any_call(['systemctl', 'start', 'crimson-osd@1'])
shcopy.assert_called()
apt_install.assert_called()