From e10b1bd6b646ccf946cb03225f745f7e196bcd93 Mon Sep 17 00:00:00 2001 From: Guillaume Abrioux Date: Tue, 1 Jul 2025 07:15:18 +0000 Subject: [PATCH] ceph-volume: add seastore OSDs support This adds the seastore OSD objectstore support to ceph-volume. Fixes: https://tracker.ceph.com/issues/71414 Signed-off-by: Guillaume Abrioux (cherry picked from commit 1b83235849fd875aac1f46b714a63f2c1e8ce836) --- src/ceph-volume/ceph_volume/activate/main.py | 4 +- .../ceph_volume/devices/lvm/batch.py | 4 +- .../ceph_volume/devices/lvm/zap.py | 3 +- .../ceph_volume/objectstore/__init__.py | 14 +- .../objectstore/baseobjectstore.py | 91 +++++- .../ceph_volume/objectstore/bluestore.py | 109 ------ .../objectstore/{lvmbluestore.py => lvm.py} | 19 +- .../objectstore/{rawbluestore.py => raw.py} | 4 +- .../tests/api/{test_lvm.py => test_api.py} | 0 src/ceph-volume/ceph_volume/tests/conftest.py | 23 +- .../tests/devices/lvm/test_activate.py | 54 +-- .../tests/devices/raw/test_prepare.py | 8 +- .../tests/objectstore/test_baseobjectstore.py | 37 ++- .../tests/objectstore/test_bluestore.py | 27 -- .../{test_lvmbluestore.py => test_lvm.py} | 309 +++++++++--------- .../{test_rawbluestore.py => test_raw.py} | 38 +-- .../ceph_volume/tests/util/test_prepare.py | 63 ++-- src/ceph-volume/ceph_volume/util/disk.py | 18 +- src/cephadm/cephadmlib/daemons/ceph.py | 4 + src/pybind/mgr/cephadm/module.py | 2 +- src/pybind/mgr/cephadm/services/osd.py | 9 + src/pybind/mgr/cephadm/tests/test_cephadm.py | 12 +- .../ceph/deployment/translate.py | 4 +- .../ceph/tests/test_drive_group.py | 29 +- 24 files changed, 450 insertions(+), 435 deletions(-) delete mode 100644 src/ceph-volume/ceph_volume/objectstore/bluestore.py rename src/ceph-volume/ceph_volume/objectstore/{lvmbluestore.py => lvm.py} (97%) rename src/ceph-volume/ceph_volume/objectstore/{rawbluestore.py => raw.py} (99%) rename src/ceph-volume/ceph_volume/tests/api/{test_lvm.py => test_api.py} (100%) delete mode 100644 src/ceph-volume/ceph_volume/tests/objectstore/test_bluestore.py rename src/ceph-volume/ceph_volume/tests/objectstore/{test_lvmbluestore.py => test_lvm.py} (75%) rename src/ceph-volume/ceph_volume/tests/objectstore/{test_rawbluestore.py => test_raw.py} (86%) diff --git a/src/ceph-volume/ceph_volume/activate/main.py b/src/ceph-volume/ceph_volume/activate/main.py index 76fba733f0fb7..9f9b3d5a57f94 100644 --- a/src/ceph-volume/ceph_volume/activate/main.py +++ b/src/ceph-volume/ceph_volume/activate/main.py @@ -3,8 +3,8 @@ import argparse from ceph_volume import terminal -from ceph_volume.objectstore.lvmbluestore import LvmBlueStore as LVMActivate -from ceph_volume.objectstore.rawbluestore import RawBlueStore as RAWActivate +from ceph_volume.objectstore.lvm import Lvm as LVMActivate +from ceph_volume.objectstore.raw import Raw as RAWActivate from ceph_volume.devices.simple.activate import Activate as SimpleActivate diff --git a/src/ceph-volume/ceph_volume/devices/lvm/batch.py b/src/ceph-volume/ceph_volume/devices/lvm/batch.py index f9ecf4bb5d9ba..8f766923bd19f 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/batch.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/batch.py @@ -373,6 +373,7 @@ class Batch(object): def _execute(self, plan: List["OSD"]) -> None: defaults = common.get_default_args() global_args = [ + 'objectstore', 'bluestore', 'dmcrypt', 'with_tpm', @@ -417,8 +418,7 @@ class Batch(object): return plan requested_osds = self.args.osds_per_device * len(phys_devs) + len(lvm_devs) - if self.args.objectstore == 'bluestore': - fast_type = 'block_db' + fast_type = 'block_db' fast_allocations = self.fast_allocations(fast_devices, requested_osds, num_osds, diff --git a/src/ceph-volume/ceph_volume/devices/lvm/zap.py b/src/ceph-volume/ceph_volume/devices/lvm/zap.py index fea5346df1522..69d5c14f871b0 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/zap.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/zap.py @@ -23,7 +23,8 @@ def zap_device(path: str) -> None: Args: path (str): The path to the device to zap. """ - zap_bluestore(path) + if disk.has_bluestore_label(path): + zap_bluestore(path) wipefs(path) zap_data(path) diff --git a/src/ceph-volume/ceph_volume/objectstore/__init__.py b/src/ceph-volume/ceph_volume/objectstore/__init__.py index faef2ae6231ba..5b1a55f33ddb7 100644 --- a/src/ceph-volume/ceph_volume/objectstore/__init__.py +++ b/src/ceph-volume/ceph_volume/objectstore/__init__.py @@ -1,13 +1,19 @@ -from . import lvmbluestore -from . import rawbluestore +from . import lvm +from . import raw from typing import Any, Dict +from enum import Enum +class ObjectStore(str, Enum): + bluestore: str = 'bluestore' + seastore: str = 'seastore' + mapping: Dict[str, Any] = { 'LVM': { - 'bluestore': lvmbluestore.LvmBlueStore + ObjectStore.bluestore: lvm.Lvm, + ObjectStore.seastore: lvm.Lvm }, 'RAW': { - 'bluestore': rawbluestore.RawBlueStore + ObjectStore.bluestore: raw.Raw } } diff --git a/src/ceph-volume/ceph_volume/objectstore/baseobjectstore.py b/src/ceph-volume/ceph_volume/objectstore/baseobjectstore.py index 7afc571d0a044..863819e736a56 100644 --- a/src/ceph-volume/ceph_volume/objectstore/baseobjectstore.py +++ b/src/ceph-volume/ceph_volume/objectstore/baseobjectstore.py @@ -32,12 +32,18 @@ class BaseObjectStore: self.osd_id: str = '' self.osd_fsid: str = '' self.cephx_lockbox_secret: str = '' - self.objectstore: str = '' + self.objectstore: str = getattr(args, "objectstore", '') self.osd_mkfs_cmd: List[str] = [] self.block_device_path: str = '' self.dmcrypt_key: str = encryption_utils.create_dmcrypt_key() self.with_tpm: int = int(getattr(self.args, 'with_tpm', False)) self.method: str = '' + self.osd_path: str = '' + self.key: Optional[str] = None + self.block_device_path: str = '' + self.wal_device_path: str = '' + self.db_device_path: str = '' + self.block_lv: Optional[Volume] = None if getattr(self.args, 'dmcrypt', False): self.encrypted = 1 if not self.with_tpm: @@ -68,7 +74,41 @@ class BaseObjectStore: raise NotImplementedError() def add_objectstore_opts(self) -> None: - raise NotImplementedError() + """ + Create the files for the OSD to function. A normal call will look like: + + ceph-osd --cluster ceph --mkfs --mkkey -i 0 \ + --monmap /var/lib/ceph/osd/ceph-0/activate.monmap \ + --osd-data /var/lib/ceph/osd/ceph-0 \ + --osd-uuid 8d208665-89ae-4733-8888-5d3bfbeeec6c \ + --keyring /var/lib/ceph/osd/ceph-0/keyring \ + --setuser ceph --setgroup ceph + + In some cases it is required to use the keyring, when it is passed + in as a keyword argument it is used as part of the ceph-osd command + """ + + if self.wal_device_path: + self.osd_mkfs_cmd.extend( + ['--bluestore-block-wal-path', self.wal_device_path] + ) + system.chown(self.wal_device_path) + + if self.db_device_path: + self.osd_mkfs_cmd.extend( + ['--bluestore-block-db-path', self.db_device_path] + ) + system.chown(self.db_device_path) + + if self.get_osdspec_affinity(): + self.osd_mkfs_cmd.extend(['--osdspec-affinity', + self.get_osdspec_affinity()]) + + def unlink_bs_symlinks(self) -> None: + for link_name in ['block', 'block.db', 'block.wal']: + link_path = os.path.join(self.osd_path, link_name) + if os.path.exists(link_path): + os.unlink(os.path.join(self.osd_path, link_name)) def prepare_osd_req(self, tmpfs: bool = True) -> None: # create the directory @@ -116,10 +156,8 @@ class BaseObjectStore: ] if self.cephx_secret is not None: self.osd_mkfs_cmd.extend(['--keyfile', '-']) - try: - self.add_objectstore_opts() - except NotImplementedError: - logger.info("No specific objectstore options to add.") + + self.add_objectstore_opts() self.osd_mkfs_cmd.extend(self.supplementary_command) return self.osd_mkfs_cmd @@ -154,6 +192,20 @@ class BaseObjectStore: raise RuntimeError('Command failed with exit code %s: %s' % (returncode, ' '.join(cmd))) + mapping: Dict[str, Any] = {'raw': ['data', 'block_db', 'block_wal'], + 'lvm': ['ceph.block_device', 'ceph.db_device', 'ceph.wal_device']} + if self.args.dmcrypt: + for dev_type in mapping[self.method]: + if self.method == 'raw': + path = self.args.__dict__.get(dev_type, None) + else: + if self.block_lv is not None: + path = self.block_lv.tags.get(dev_type, None) + else: + raise RuntimeError('Unexpected error while running bluestore mkfs.') + if path is not None: + encryption_utils.CephLuks2(path).config_luks2({'subsystem': f'ceph_fsid={self.osd_fsid}'}) + def activate(self) -> None: raise NotImplementedError() @@ -179,3 +231,30 @@ class BaseObjectStore: device, '--unlock-key-file', temp_file_name, '--tpm2-pcrs', '9+12', '--wipe-slot', 'tpm2'] process.call(cmd, run_on_host=True, show_command=True) + + def add_label(self, key: str, + value: str, + device: str) -> None: + """Add a label to a BlueStore device. + Args: + key (str): The name of the label being added. + value (str): Value of the label being added. + device (str): The path of the BlueStore device. + Raises: + RuntimeError: If `ceph-bluestore-tool` command doesn't success. + """ + + command: List[str] = ['ceph-bluestore-tool', + 'set-label-key', + '-k', + key, + '-v', + value, + '--dev', + device] + + _, err, rc = process.call(command, + terminal_verbose=True, + show_command=True) + if rc: + raise RuntimeError(f"Can't add BlueStore label '{key}' to device {device}: {err}") \ No newline at end of file diff --git a/src/ceph-volume/ceph_volume/objectstore/bluestore.py b/src/ceph-volume/ceph_volume/objectstore/bluestore.py deleted file mode 100644 index 9039b29651ec7..0000000000000 --- a/src/ceph-volume/ceph_volume/objectstore/bluestore.py +++ /dev/null @@ -1,109 +0,0 @@ -import logging -import os -from .baseobjectstore import BaseObjectStore -from ceph_volume.util import system -from ceph_volume.util.encryption import CephLuks2 -from ceph_volume import process -from typing import Any, Dict, List, Optional, TYPE_CHECKING - -if TYPE_CHECKING: - import argparse - from ceph_volume.api.lvm import Volume - -logger = logging.getLogger(__name__) - - -class BlueStore(BaseObjectStore): - def __init__(self, args: "argparse.Namespace") -> None: - super().__init__(args) - self.args: "argparse.Namespace" = args - self.objectstore = 'bluestore' - self.osd_id: str = '' - self.osd_fsid: str = '' - self.osd_path: str = '' - self.key: Optional[str] = None - self.block_device_path: str = '' - self.wal_device_path: str = '' - self.db_device_path: str = '' - self.block_lv: Optional[Volume] = None - - def add_objectstore_opts(self) -> None: - """ - Create the files for the OSD to function. A normal call will look like: - - ceph-osd --cluster ceph --mkfs --mkkey -i 0 \ - --monmap /var/lib/ceph/osd/ceph-0/activate.monmap \ - --osd-data /var/lib/ceph/osd/ceph-0 \ - --osd-uuid 8d208665-89ae-4733-8888-5d3bfbeeec6c \ - --keyring /var/lib/ceph/osd/ceph-0/keyring \ - --setuser ceph --setgroup ceph - - In some cases it is required to use the keyring, when it is passed - in as a keyword argument it is used as part of the ceph-osd command - """ - - if self.wal_device_path: - self.osd_mkfs_cmd.extend( - ['--bluestore-block-wal-path', self.wal_device_path] - ) - system.chown(self.wal_device_path) - - if self.db_device_path: - self.osd_mkfs_cmd.extend( - ['--bluestore-block-db-path', self.db_device_path] - ) - system.chown(self.db_device_path) - - if self.get_osdspec_affinity(): - self.osd_mkfs_cmd.extend(['--osdspec-affinity', - self.get_osdspec_affinity()]) - - def unlink_bs_symlinks(self) -> None: - for link_name in ['block', 'block.db', 'block.wal']: - link_path = os.path.join(self.osd_path, link_name) - if os.path.exists(link_path): - os.unlink(os.path.join(self.osd_path, link_name)) - - - def add_label(self, key: str, - value: str, - device: str) -> None: - """Add a label to a BlueStore device. - Args: - key (str): The name of the label being added. - value (str): Value of the label being added. - device (str): The path of the BlueStore device. - Raises: - RuntimeError: If `ceph-bluestore-tool` command doesn't success. - """ - - command: List[str] = ['ceph-bluestore-tool', - 'set-label-key', - '-k', - key, - '-v', - value, - '--dev', - device] - - _, err, rc = process.call(command, - terminal_verbose=True, - show_command=True) - if rc: - raise RuntimeError(f"Can't add BlueStore label '{key}' to device {device}: {err}") - - def osd_mkfs(self) -> None: - super().osd_mkfs() - mapping: Dict[str, Any] = {'raw': ['data', 'block_db', 'block_wal'], - 'lvm': ['ceph.block_device', 'ceph.db_device', 'ceph.wal_device']} - if self.args.dmcrypt: - for dev_type in mapping[self.method]: - if self.method == 'raw': - path = self.args.__dict__.get(dev_type, None) - else: - if self.block_lv is not None: - path = self.block_lv.tags.get(dev_type, None) - else: - raise RuntimeError('Unexpected error while running bluestore mkfs.') - if path is not None: - CephLuks2(path).config_luks2({'subsystem': f'ceph_fsid={self.osd_fsid}'}) diff --git a/src/ceph-volume/ceph_volume/objectstore/lvmbluestore.py b/src/ceph-volume/ceph_volume/objectstore/lvm.py similarity index 97% rename from src/ceph-volume/ceph_volume/objectstore/lvmbluestore.py rename to src/ceph-volume/ceph_volume/objectstore/lvm.py index a9fd578a2051c..204f2b954e14d 100644 --- a/src/ceph-volume/ceph_volume/objectstore/lvmbluestore.py +++ b/src/ceph-volume/ceph_volume/objectstore/lvm.py @@ -9,7 +9,7 @@ from ceph_volume.util import system, disk from ceph_volume.systemd import systemctl from ceph_volume.devices.lvm.common import rollback_osd from ceph_volume.devices.lvm.listing import direct_report -from .bluestore import BlueStore +from .baseobjectstore import BaseObjectStore from typing import Dict, Any, Optional, List, TYPE_CHECKING if TYPE_CHECKING: @@ -19,7 +19,7 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) -class LvmBlueStore(BlueStore): +class Lvm(BaseObjectStore): def __init__(self, args: "argparse.Namespace") -> None: super().__init__(args) self.method = 'lvm' @@ -59,6 +59,7 @@ class LvmBlueStore(BlueStore): self.block_lv = self.prepare_data_device('block', self.osd_fsid) self.block_device_path = self.block_lv.__dict__['lv_path'] + self.tags['ceph.objectstore'] = self.objectstore self.tags['ceph.block_device'] = self.block_lv.__dict__['lv_path'] self.tags['ceph.block_uuid'] = self.block_lv.__dict__['lv_uuid'] self.tags['ceph.cephx_lockbox_secret'] = self.cephx_lockbox_secret @@ -392,12 +393,14 @@ class LvmBlueStore(BlueStore): # ``prime-osd-dir`` can succeed even if permissions are # somehow messed up. system.chown(self.osd_path) - prime_command = [ - 'ceph-bluestore-tool', '--cluster=%s' % conf.cluster, - 'prime-osd-dir', '--dev', osd_lv_path, - '--path', self.osd_path, '--no-mon-config'] - - process.run(prime_command) + objectstore = osd_block_lv.tags.get('ceph.objectstore', 'bluestore') + if objectstore == 'bluestore': + prime_command = [ + 'ceph-bluestore-tool', '--cluster=%s' % conf.cluster, + 'prime-osd-dir', '--dev', osd_lv_path, + '--path', self.osd_path, '--no-mon-config'] + + process.run(prime_command) # always re-do the symlink regardless if it exists, so that the block, # block.wal, and block.db devices that may have changed can be mapped # correctly every time diff --git a/src/ceph-volume/ceph_volume/objectstore/rawbluestore.py b/src/ceph-volume/ceph_volume/objectstore/raw.py similarity index 99% rename from src/ceph-volume/ceph_volume/objectstore/rawbluestore.py rename to src/ceph-volume/ceph_volume/objectstore/raw.py index 3065342c7a91f..33e79d34c151c 100644 --- a/src/ceph-volume/ceph_volume/objectstore/rawbluestore.py +++ b/src/ceph-volume/ceph_volume/objectstore/raw.py @@ -1,7 +1,7 @@ import logging import json import os -from .bluestore import BlueStore +from .baseobjectstore import BaseObjectStore from ceph_volume import terminal, decorators, conf, process from ceph_volume.util import system, disk from ceph_volume.util import prepare as prepare_utils @@ -17,7 +17,7 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) -class RawBlueStore(BlueStore): +class Raw(BaseObjectStore): def __init__(self, args: "argparse.Namespace") -> None: super().__init__(args) self.method = 'raw' diff --git a/src/ceph-volume/ceph_volume/tests/api/test_lvm.py b/src/ceph-volume/ceph_volume/tests/api/test_api.py similarity index 100% rename from src/ceph-volume/ceph_volume/tests/api/test_lvm.py rename to src/ceph-volume/ceph_volume/tests/api/test_api.py diff --git a/src/ceph-volume/ceph_volume/tests/conftest.py b/src/ceph-volume/ceph_volume/tests/conftest.py index a58e190b936f1..fb01656f097fc 100644 --- a/src/ceph-volume/ceph_volume/tests/conftest.py +++ b/src/ceph-volume/ceph_volume/tests/conftest.py @@ -6,8 +6,9 @@ from ceph_volume.api import lvm from ceph_volume.util import disk from ceph_volume.util import device from ceph_volume.util.constants import ceph_disk_guids -from ceph_volume import conf, configuration, objectstore -from ceph_volume.objectstore.rawbluestore import RawBlueStore +from ceph_volume import conf, configuration +from ceph_volume.objectstore.baseobjectstore import BaseObjectStore +from ceph_volume.objectstore.raw import Raw from typing import Any, Dict, List, Optional, Callable @@ -39,15 +40,15 @@ class Factory(object): def factory() -> Callable[..., argparse.Namespace]: return argparse.Namespace -def objectstore_bluestore_factory(**kw): - o = objectstore.bluestore.BlueStore([]) +def objectstore_factory(**kw): + o = BaseObjectStore([]) for k, v in kw.items(): setattr(o, k, v) return o @pytest.fixture -def objectstore_bluestore(): - return objectstore_bluestore_factory +def objectstore(): + return objectstore_factory @pytest.fixture @@ -524,11 +525,11 @@ raw_direct_report_data = { @pytest.fixture def mock_lvm_direct_report(monkeypatch): - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.direct_report', lambda: lvm_direct_report_data) + monkeypatch.setattr('ceph_volume.objectstore.lvm.direct_report', lambda: lvm_direct_report_data) @pytest.fixture def mock_raw_direct_report(monkeypatch): - monkeypatch.setattr('ceph_volume.objectstore.rawbluestore.direct_report', lambda x: raw_direct_report_data) + monkeypatch.setattr('ceph_volume.objectstore.raw.direct_report', lambda x: raw_direct_report_data) @pytest.fixture def fake_lsblk_all(monkeypatch: Any) -> Callable: @@ -541,8 +542,8 @@ def fake_lsblk_all(monkeypatch: Any) -> Callable: return apply @pytest.fixture -def rawbluestore(factory: type[Factory]) -> RawBlueStore: +def rawbluestore(factory: type[Factory]) -> Raw: args = factory(devices=['/dev/foo']) - with patch('ceph_volume.objectstore.rawbluestore.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])): - r = RawBlueStore(args) # type: ignore + with patch('ceph_volume.objectstore.raw.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])): + r = Raw(args) # type: ignore return r diff --git a/src/ceph-volume/ceph_volume/tests/devices/lvm/test_activate.py b/src/ceph-volume/ceph_volume/tests/devices/lvm/test_activate.py index 6e2541fda2cbc..ba30ff4cd6183 100644 --- a/src/ceph-volume/ceph_volume/tests/devices/lvm/test_activate.py +++ b/src/ceph-volume/ceph_volume/tests/devices/lvm/test_activate.py @@ -3,7 +3,7 @@ from copy import deepcopy from ceph_volume.devices.lvm import activate from ceph_volume.api import lvm as api from ceph_volume.tests.conftest import Capture -from ceph_volume import objectstore +from ceph_volume.objectstore import lvm #from ceph_volume.util.prepare import create_key from unittest.mock import patch, call from argparse import Namespace @@ -37,20 +37,20 @@ class TestActivate(object): volumes = [] volumes.append(FooVolume) monkeypatch.setattr(api, 'get_lvs', lambda **kwargs: volumes) - monkeypatch.setattr(objectstore.lvmbluestore.LvmBlueStore, + monkeypatch.setattr(lvm.Lvm, '_activate', capture) args = Args(osd_id=None, osd_fsid='1234', bluestore=True) a = activate.Activate([]) - a.objectstore = objectstore.lvmbluestore.LvmBlueStore(args=args) + a.objectstore = lvm.Lvm(args=args) a.objectstore.activate() assert capture.calls[0]['args'][0] == [FooVolume] def test_osd_id_no_osd_fsid(self, m_create_key, is_root): args = Args(osd_id=42, osd_fsid=None) a = activate.Activate([]) - a.objectstore = objectstore.lvmbluestore.LvmBlueStore(args=args) + a.objectstore = lvm.Lvm(args=args) with pytest.raises(RuntimeError) as result: a.objectstore.activate() assert result.value.args[0] == 'could not activate osd.42, please provide the osd_fsid too' @@ -58,7 +58,7 @@ class TestActivate(object): def test_no_osd_id_no_osd_fsid(self, m_create_key, is_root): args = Args(osd_id=None, osd_fsid=None) a = activate.Activate([]) - a.objectstore = objectstore.lvmbluestore.LvmBlueStore(args=args) + a.objectstore = lvm.Lvm(args=args) with pytest.raises(RuntimeError) as result: a.objectstore.activate() assert result.value.args[0] == 'Please provide both osd_id and osd_fsid' @@ -70,8 +70,8 @@ class TestActivate(object): monkeypatch.setattr('ceph_volume.util.system.path_is_mounted', lambda *a, **kw: True) monkeypatch.setattr('ceph_volume.util.system.chown', lambda *a, **kw: True) monkeypatch.setattr('ceph_volume.process.run', lambda *a, **kw: True) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'enable_volume', fake_enable) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'start_osd', fake_start_osd) + monkeypatch.setattr(lvm.systemctl, 'enable_volume', fake_enable) + monkeypatch.setattr(lvm.systemctl, 'start_osd', fake_start_osd) DataVolume = api.Volume( lv_name='data', lv_path='/dev/vg/data', @@ -83,7 +83,7 @@ class TestActivate(object): args = Args(osd_id=None, osd_fsid='1234', no_systemd=True, bluestore=True) a = activate.Activate([]) - a.objectstore = objectstore.lvmbluestore.LvmBlueStore(args=args) + a.objectstore = lvm.Lvm(args=args) a.objectstore.activate() assert fake_enable.calls == [] assert fake_start_osd.calls == [] @@ -95,8 +95,8 @@ class TestActivate(object): monkeypatch.setattr('ceph_volume.util.system.path_is_mounted', lambda *a, **kw: True) monkeypatch.setattr('ceph_volume.util.system.chown', lambda *a, **kw: True) monkeypatch.setattr('ceph_volume.process.run', lambda *a, **kw: True) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'enable_volume', fake_enable) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'start_osd', fake_start_osd) + monkeypatch.setattr(lvm.systemctl, 'enable_volume', fake_enable) + monkeypatch.setattr(lvm.systemctl, 'start_osd', fake_start_osd) DataVolume = api.Volume( lv_name='data', lv_path='/dev/vg/data', @@ -109,7 +109,7 @@ class TestActivate(object): args = Args(osd_id=None, osd_fsid='1234', no_systemd=False, bluestore=True) a = activate.Activate([]) - a.objectstore = objectstore.lvmbluestore.LvmBlueStore(args=args) + a.objectstore = lvm.Lvm(args) a.objectstore.activate() assert fake_enable.calls != [] assert fake_start_osd.calls != [] @@ -121,8 +121,8 @@ class TestActivate(object): monkeypatch.setattr('ceph_volume.util.system.path_is_mounted', lambda *a, **kw: True) monkeypatch.setattr('ceph_volume.util.system.chown', lambda *a, **kw: True) monkeypatch.setattr('ceph_volume.process.run', lambda *a, **kw: True) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'enable_volume', fake_enable) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'start_osd', fake_start_osd) + monkeypatch.setattr(lvm.systemctl, 'enable_volume', fake_enable) + monkeypatch.setattr(lvm.systemctl, 'start_osd', fake_start_osd) DataVolume = api.Volume( lv_name='data', lv_path='/dev/vg/data', @@ -135,7 +135,7 @@ class TestActivate(object): args = Args(osd_id=None, osd_fsid='1234', no_systemd=True, bluestore=True, auto_detect_objectstore=True) a = activate.Activate([]) - a.objectstore = objectstore.lvmbluestore.LvmBlueStore(args=args) + a.objectstore = lvm.Lvm(args) a.objectstore.activate() assert fake_enable.calls == [] assert fake_start_osd.calls == [] @@ -149,8 +149,8 @@ class TestActivate(object): monkeypatch.setattr('ceph_volume.util.system.chown', lambda *a, **kw: True) monkeypatch.setattr('ceph_volume.process.run', lambda *a, **kw: True) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'enable_volume', fake_enable) - monkeypatch.setattr(objectstore.lvmbluestore.systemctl, 'start_osd', fake_start_osd) + monkeypatch.setattr(lvm.systemctl, 'enable_volume', fake_enable) + monkeypatch.setattr(lvm.systemctl, 'start_osd', fake_start_osd) DataVolume = api.Volume( lv_name='data', lv_path='/dev/vg/data', @@ -163,15 +163,15 @@ class TestActivate(object): args = Args(osd_id=None, osd_fsid='1234', no_systemd=False, bluestore=True, auto_detect_objectstore=False) a = activate.Activate([]) - a.objectstore = objectstore.lvmbluestore.LvmBlueStore(args=args) + a.objectstore = lvm.Lvm(args=args) a.objectstore.activate() assert fake_enable.calls != [] assert fake_start_osd.calls != [] @patch('ceph_volume.util.prepare.create_key', return_value='fake-secret') -@patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.activate_all') -@patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.activate') +@patch('ceph_volume.objectstore.lvm.Lvm.activate_all') +@patch('ceph_volume.objectstore.lvm.Lvm.activate') class TestActivateFlags(object): def test_default_objectstore(self, m_activate, m_activate_all, m_create_key, capture): @@ -192,7 +192,7 @@ class TestActivateFlags(object): class TestActivateAll(object): def test_does_not_detect_osds(self, m_create_key, capsys, is_root, monkeypatch): - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.direct_report', lambda: {}) + monkeypatch.setattr('ceph_volume.objectstore.lvm.direct_report', lambda: {}) args = ['--all'] activation = activate.Activate(args) activation.main() @@ -201,8 +201,8 @@ class TestActivateAll(object): assert 'Verify OSDs are present with ' in err def test_detects_running_osds(self, m_create_key, capsys, is_root, capture, monkeypatch): - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.direct_report', lambda: direct_report) - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.systemctl.osd_is_active', lambda x: True) + monkeypatch.setattr('ceph_volume.objectstore.lvm.direct_report', lambda: direct_report) + monkeypatch.setattr('ceph_volume.objectstore.lvm.systemctl.osd_is_active', lambda x: True) args = ['--all'] activation = activate.Activate(args) activation.main() @@ -210,10 +210,10 @@ class TestActivateAll(object): assert 'a8789a96ce8b process is active. Skipping activation' in err assert 'b8218eaa1634 process is active. Skipping activation' in err - @patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.activate') + @patch('ceph_volume.objectstore.lvm.Lvm.activate') def test_detects_osds_to_activate_systemd(self, m_activate, m_create_key, is_root, monkeypatch): - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.direct_report', lambda: direct_report) - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.systemctl.osd_is_active', lambda x: False) + monkeypatch.setattr('ceph_volume.objectstore.lvm.direct_report', lambda: direct_report) + monkeypatch.setattr('ceph_volume.objectstore.lvm.systemctl.osd_is_active', lambda x: False) args = ['--all', '--bluestore'] a = activate.Activate(args) a.main() @@ -241,9 +241,9 @@ class TestActivateAll(object): ] m_activate.assert_has_calls(calls) - @patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.activate') + @patch('ceph_volume.objectstore.lvm.Lvm.activate') def test_detects_osds_to_activate_no_systemd(self, m_activate, m_create_key, is_root, monkeypatch): - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.direct_report', lambda: direct_report) + monkeypatch.setattr('ceph_volume.objectstore.lvm.direct_report', lambda: direct_report) args = ['--all', '--no-systemd', '--bluestore'] a = activate.Activate(args) a.main() diff --git a/src/ceph-volume/ceph_volume/tests/devices/raw/test_prepare.py b/src/ceph-volume/ceph_volume/tests/devices/raw/test_prepare.py index 1442761140b2f..248121b936455 100644 --- a/src/ceph-volume/ceph_volume/tests/devices/raw/test_prepare.py +++ b/src/ceph-volume/ceph_volume/tests/devices/raw/test_prepare.py @@ -1,7 +1,7 @@ import pytest from ceph_volume.devices import raw from unittest.mock import patch, MagicMock -from ceph_volume import objectstore +from ceph_volume.objectstore.raw import Raw class TestRaw(object): @@ -27,7 +27,7 @@ class TestPrepare(object): def _setup(self, **kw): args = kw.get('args', []) self.p = raw.prepare.Prepare([]) - self.p.objectstore = objectstore.rawbluestore.RawBlueStore(args=args) + self.p.objectstore = Raw(args=args) for k, v in kw.items(): setattr(self.p.objectstore, k, v) @@ -105,8 +105,8 @@ class TestPrepare(object): m_luks_format.assert_called_with(self.p.objectstore.dmcrypt_key, '/dev/wal-foo') assert self.p.objectstore.__dict__['wal_device_path'] == '/dev/mapper/ceph-789-foo-wal-dmcrypt' - @patch('ceph_volume.objectstore.rawbluestore.rollback_osd') - @patch('ceph_volume.objectstore.rawbluestore.RawBlueStore.prepare') + @patch('ceph_volume.objectstore.raw.rollback_osd') + @patch('ceph_volume.objectstore.raw.Raw.prepare') @patch('ceph_volume.util.arg_validators.ValidRawDevice.__call__') def test_safe_prepare_exception_raised(self, m_valid_device, m_prepare, m_rollback_osd, m_create_key): m_valid_device.return_value = '/dev/foo' diff --git a/src/ceph-volume/ceph_volume/tests/objectstore/test_baseobjectstore.py b/src/ceph-volume/ceph_volume/tests/objectstore/test_baseobjectstore.py index 3e1dc7cfa1c00..3233fafdbacf0 100644 --- a/src/ceph-volume/ceph_volume/tests/objectstore/test_baseobjectstore.py +++ b/src/ceph-volume/ceph_volume/tests/objectstore/test_baseobjectstore.py @@ -48,10 +48,6 @@ class TestBaseObjectStore: with pytest.raises(NotImplementedError): BaseObjectStore([]).safe_prepare(args=None) - def test_add_objectstore_opts(self): - with pytest.raises(NotImplementedError): - BaseObjectStore([]).add_objectstore_opts() - @patch('ceph_volume.util.prepare.create_osd_path') @patch('ceph_volume.util.prepare.link_block') @patch('ceph_volume.util.prepare.get_monmap') @@ -117,8 +113,9 @@ class TestBaseObjectStore: '--setuser', 'ceph', '--setgroup', 'ceph'] - def test_osd_mkfs_ok(self, monkeypatch, fake_call): - bo = BaseObjectStore([]) + def test_osd_mkfs_ok(self, monkeypatch, fake_call, objectstore): + args = objectstore(dmcrypt=False) + bo = BaseObjectStore(args) bo.get_osd_path = lambda: '/var/lib/ceph/osd/ceph-123/' bo.build_osd_mkfs_cmd = lambda: ['ceph-osd', '--mkfs', 'some', 'fake', 'args'] monkeypatch.setattr(system, 'chown', lambda path: 0) @@ -149,8 +146,9 @@ class TestBaseObjectStore: @patch('time.sleep', Mock()) @patch('ceph_volume.process.call', return_value=([], [], 11)) - def test_osd_mkfs_fails_EWOULDBLOCK(self, m_call, monkeypatch): - bo = BaseObjectStore([]) + def test_osd_mkfs_fails_EWOULDBLOCK(self, m_call, monkeypatch, objectstore): + args = objectstore(dmcrypt=False) + bo = BaseObjectStore(args) bo.get_osd_path = lambda: '/var/lib/ceph/osd/ceph-123/' bo.build_osd_mkfs_cmd = lambda: ['ceph-osd', '--mkfs', 'some', 'fake', 'args'] monkeypatch.setattr(system, 'chown', lambda path: 0) @@ -160,3 +158,26 @@ class TestBaseObjectStore: def test_activate(self): with pytest.raises(NotImplementedError): BaseObjectStore([]).activate() + + @patch('ceph_volume.objectstore.baseobjectstore.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])) + def setup_method(self, m_create_key): + self.b = BaseObjectStore([]) + self.b.osd_mkfs_cmd = ['binary', 'arg1'] + + def test_add_objectstore_opts_wal_device_path(self, monkeypatch): + monkeypatch.setattr('ceph_volume.util.system.chown', lambda path: 0) + self.b.wal_device_path = '/dev/nvme0n1' + self.b.add_objectstore_opts() + assert self.b.osd_mkfs_cmd == ['binary', 'arg1', '--bluestore-block-wal-path', '/dev/nvme0n1'] + + def test_add_objectstore_opts_db_device_path(self, monkeypatch): + monkeypatch.setattr('ceph_volume.util.system.chown', lambda path: 0) + self.b.db_device_path = '/dev/ssd1' + self.b.add_objectstore_opts() + assert self.b.osd_mkfs_cmd == ['binary', 'arg1', '--bluestore-block-db-path', '/dev/ssd1'] + + def test_add_objectstore_opts_osdspec_affinity(self, monkeypatch): + monkeypatch.setattr('ceph_volume.util.system.chown', lambda path: 0) + self.b.get_osdspec_affinity = lambda: 'foo' + self.b.add_objectstore_opts() + assert self.b.osd_mkfs_cmd == ['binary', 'arg1', '--osdspec-affinity', 'foo'] \ No newline at end of file diff --git a/src/ceph-volume/ceph_volume/tests/objectstore/test_bluestore.py b/src/ceph-volume/ceph_volume/tests/objectstore/test_bluestore.py deleted file mode 100644 index 57dab86f9ea64..0000000000000 --- a/src/ceph-volume/ceph_volume/tests/objectstore/test_bluestore.py +++ /dev/null @@ -1,27 +0,0 @@ -from unittest.mock import patch, Mock -from ceph_volume.objectstore.bluestore import BlueStore - - -class TestBlueStore: - @patch('ceph_volume.objectstore.baseobjectstore.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])) - def setup_method(self, m_create_key): - self.b = BlueStore([]) - self.b.osd_mkfs_cmd = ['binary', 'arg1'] - - def test_add_objectstore_opts_wal_device_path(self, monkeypatch): - monkeypatch.setattr('ceph_volume.util.system.chown', lambda path: 0) - self.b.wal_device_path = '/dev/nvme0n1' - self.b.add_objectstore_opts() - assert self.b.osd_mkfs_cmd == ['binary', 'arg1', '--bluestore-block-wal-path', '/dev/nvme0n1'] - - def test_add_objectstore_opts_db_device_path(self, monkeypatch): - monkeypatch.setattr('ceph_volume.util.system.chown', lambda path: 0) - self.b.db_device_path = '/dev/ssd1' - self.b.add_objectstore_opts() - assert self.b.osd_mkfs_cmd == ['binary', 'arg1', '--bluestore-block-db-path', '/dev/ssd1'] - - def test_add_objectstore_opts_osdspec_affinity(self, monkeypatch): - monkeypatch.setattr('ceph_volume.util.system.chown', lambda path: 0) - self.b.get_osdspec_affinity = lambda: 'foo' - self.b.add_objectstore_opts() - assert self.b.osd_mkfs_cmd == ['binary', 'arg1', '--osdspec-affinity', 'foo'] \ No newline at end of file diff --git a/src/ceph-volume/ceph_volume/tests/objectstore/test_lvmbluestore.py b/src/ceph-volume/ceph_volume/tests/objectstore/test_lvm.py similarity index 75% rename from src/ceph-volume/ceph_volume/tests/objectstore/test_lvmbluestore.py rename to src/ceph-volume/ceph_volume/tests/objectstore/test_lvm.py index 06e0f366d6199..f23bfd0876e15 100644 --- a/src/ceph-volume/ceph_volume/tests/objectstore/test_lvmbluestore.py +++ b/src/ceph-volume/ceph_volume/tests/objectstore/test_lvm.py @@ -1,22 +1,23 @@ import pytest from argparse import Namespace from unittest.mock import patch, Mock, MagicMock, call -from ceph_volume.objectstore.lvmbluestore import LvmBlueStore +from ceph_volume.objectstore.lvm import Lvm from ceph_volume.api.lvm import Volume from ceph_volume.util import system, disk from typing import Callable -class TestLvmBlueStore: - @patch('ceph_volume.objectstore.lvmbluestore.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])) +class TestLvm: + @patch('ceph_volume.objectstore.lvm.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])) def setup_method(self, m_create_key): - self.lvm_bs = LvmBlueStore([]) + self.lvm = Lvm([]) @patch('ceph_volume.conf.cluster', 'ceph') @patch('ceph_volume.api.lvm.get_single_lv') - @patch('ceph_volume.objectstore.lvmbluestore.prepare_utils.create_id', Mock(return_value='111')) + @patch('ceph_volume.objectstore.lvm.prepare_utils.create_id', Mock(return_value='111')) def test_pre_prepare_lv(self, m_get_single_lv, factory): - args = factory(cluster_fsid='abcd', + args = factory(objectstore='seastore', + cluster_fsid='abcd', osd_fsid='abc123', crush_device_class='ssd', osd_id='111', @@ -26,15 +27,16 @@ class TestLvmBlueStore: vg_name='vg_foo', lv_tags='', lv_uuid='fake-uuid') - self.lvm_bs.encrypted = True - self.lvm_bs.dmcrypt_key = 'fake-dmcrypt-key' - self.lvm_bs.args = args - self.lvm_bs.pre_prepare() - assert self.lvm_bs.secrets['dmcrypt_key'] == 'fake-dmcrypt-key' - assert self.lvm_bs.secrets['crush_device_class'] == 'ssd' - assert self.lvm_bs.osd_id == '111' - assert self.lvm_bs.block_device_path == '/fake-path' - assert self.lvm_bs.tags == {'ceph.osd_fsid': 'abc123', + self.lvm.encrypted = True + self.lvm.dmcrypt_key = 'fake-dmcrypt-key' + self.lvm.args = args + self.lvm.objectstore = 'seastore' + self.lvm.pre_prepare() + assert self.lvm.secrets['dmcrypt_key'] == 'fake-dmcrypt-key' + assert self.lvm.secrets['crush_device_class'] == 'ssd' + assert self.lvm.osd_id == '111' + assert self.lvm.block_device_path == '/fake-path' + assert self.lvm.tags == {'ceph.osd_fsid': 'abc123', 'ceph.osd_id': '111', 'ceph.cluster_fsid': 'abcd', 'ceph.cluster_name': 'ceph', @@ -43,15 +45,17 @@ class TestLvmBlueStore: 'ceph.block_device': '/fake-path', 'ceph.block_uuid': 'fake-uuid', 'ceph.cephx_lockbox_secret': '', + 'ceph.objectstore': 'seastore', 'ceph.encrypted': True, 'ceph.vdo': '0', 'ceph.with_tpm': 0} @patch('ceph_volume.conf.cluster', 'ceph') @patch('ceph_volume.api.lvm.get_single_lv') - @patch('ceph_volume.objectstore.lvmbluestore.prepare_utils.create_id', Mock(return_value='111')) + @patch('ceph_volume.objectstore.lvm.prepare_utils.create_id', Mock(return_value='111')) def test_pre_prepare_lv_with_dmcrypt_and_tpm(self, m_get_single_lv, factory): - args = factory(cluster_fsid='abcd', + args = factory(objectstore='seastore', + cluster_fsid='abcd', osd_fsid='abc123', crush_device_class='ssd', osd_id='111', @@ -63,16 +67,17 @@ class TestLvmBlueStore: vg_name='vg_foo', lv_tags='', lv_uuid='fake-uuid') - self.lvm_bs.encrypted = True - self.lvm_bs.with_tpm = True - self.lvm_bs.dmcrypt_key = 'fake-dmcrypt-key-tpm2' - self.lvm_bs.args = args - self.lvm_bs.pre_prepare() - assert 'dmcrypt_key' not in self.lvm_bs.secrets.keys() - assert self.lvm_bs.secrets['crush_device_class'] == 'ssd' - assert self.lvm_bs.osd_id == '111' - assert self.lvm_bs.block_device_path == '/fake-path' - assert self.lvm_bs.tags == {'ceph.osd_fsid': 'abc123', + self.lvm.encrypted = True + self.lvm.with_tpm = True + self.lvm.dmcrypt_key = 'fake-dmcrypt-key-tpm2' + self.lvm.args = args + self.lvm.objectstore = 'seastore' + self.lvm.pre_prepare() + assert 'dmcrypt_key' not in self.lvm.secrets.keys() + assert self.lvm.secrets['crush_device_class'] == 'ssd' + assert self.lvm.osd_id == '111' + assert self.lvm.block_device_path == '/fake-path' + assert self.lvm.tags == {'ceph.osd_fsid': 'abc123', 'ceph.osd_id': '111', 'ceph.cluster_fsid': 'abcd', 'ceph.cluster_name': 'ceph', @@ -82,42 +87,47 @@ class TestLvmBlueStore: 'ceph.block_uuid': 'fake-uuid', 'ceph.cephx_lockbox_secret': '', 'ceph.encrypted': True, + 'ceph.objectstore': 'seastore', 'ceph.vdo': '0', 'ceph.with_tpm': 1} - @patch('ceph_volume.objectstore.lvmbluestore.prepare_utils.create_id', Mock(return_value='111')) + @patch('ceph_volume.conf.cluster', 'ceph') + @patch('ceph_volume.objectstore.lvm.prepare_utils.create_id', Mock(return_value='111')) def test_pre_prepare_no_lv(self, factory): args = factory(cluster_fsid='abcd', + objectstore='seastore', osd_fsid='abc123', crush_device_class='ssd', osd_id='111', data='/dev/foo', dmcrypt_key='fake-dmcrypt-key') - self.lvm_bs.prepare_data_device = lambda x, y: Volume(lv_name='lv_foo', - lv_path='/fake-path', - vg_name='vg_foo', - lv_tags='', - lv_uuid='fake-uuid') - self.lvm_bs.encrypted = True - self.lvm_bs.dmcrypt_key = 'fake-dmcrypt-key' - self.lvm_bs.args = args - self.lvm_bs.pre_prepare() - assert self.lvm_bs.secrets['dmcrypt_key'] == 'fake-dmcrypt-key' - assert self.lvm_bs.secrets['crush_device_class'] == 'ssd' - assert self.lvm_bs.osd_id == '111' - assert self.lvm_bs.block_device_path == '/fake-path' - assert self.lvm_bs.tags == {'ceph.osd_fsid': 'abc123', - 'ceph.osd_id': '111', - 'ceph.cluster_fsid': 'abcd', - 'ceph.cluster_name': None, - 'ceph.crush_device_class': 'ssd', - 'ceph.osdspec_affinity': '', - 'ceph.block_device': '/fake-path', - 'ceph.block_uuid': 'fake-uuid', - 'ceph.cephx_lockbox_secret': '', - 'ceph.encrypted': True, - 'ceph.vdo': '0', - 'ceph.with_tpm': 0} + self.lvm.prepare_data_device = lambda x, y: Volume(lv_name='lv_foo', + lv_path='/fake-path', + vg_name='vg_foo', + lv_tags='', + lv_uuid='fake-uuid') + self.lvm.encrypted = True + self.lvm.dmcrypt_key = 'fake-dmcrypt-key' + self.lvm.args = args + self.lvm.objectstore = 'seastore' + self.lvm.pre_prepare() + assert self.lvm.secrets['dmcrypt_key'] == 'fake-dmcrypt-key' + assert self.lvm.secrets['crush_device_class'] == 'ssd' + assert self.lvm.osd_id == '111' + assert self.lvm.block_device_path == '/fake-path' + assert self.lvm.tags == {'ceph.osd_fsid': 'abc123', + 'ceph.osd_id': '111', + 'ceph.cluster_fsid': 'abcd', + 'ceph.cluster_name': 'ceph', + 'ceph.crush_device_class': 'ssd', + 'ceph.osdspec_affinity': '', + 'ceph.block_device': '/fake-path', + 'ceph.block_uuid': 'fake-uuid', + 'ceph.cephx_lockbox_secret': '', + 'ceph.encrypted': True, + 'ceph.vdo': '0', + 'ceph.with_tpm': 0, + 'ceph.objectstore': 'seastore'} @patch('ceph_volume.util.disk.is_partition', Mock(return_value=True)) @patch('ceph_volume.api.lvm.create_lv') @@ -127,22 +137,22 @@ class TestLvmBlueStore: args = factory(data='/dev/foo1', data_slots=1, data_size=102400) - self.lvm_bs.args = args + self.lvm.args = args m_create_lv.return_value = Volume(lv_name='lv_foo', lv_path='/fake-path', vg_name='vg_foo', lv_tags='', lv_uuid='abcd') - assert self.lvm_bs.prepare_data_device('block', 'abcd') == m_create_lv.return_value - assert self.lvm_bs.args.data_size == 102400 + assert self.lvm.prepare_data_device('block', 'abcd') == m_create_lv.return_value + assert self.lvm.args.data_size == 102400 @patch('ceph_volume.util.disk.is_device', Mock(return_value=False)) @patch('ceph_volume.util.disk.is_partition', Mock(return_value=False)) def test_prepare_data_device_fails(self, factory): args = factory(data='/dev/foo') - self.lvm_bs.args = args + self.lvm.args = args with pytest.raises(RuntimeError) as error: - self.lvm_bs.prepare_data_device('block', 'abcd') + self.lvm.prepare_data_device('block', 'abcd') assert ('Cannot use device (/dev/foo). ' 'A vg/lv path or an existing device is needed') == str(error.value) @@ -150,25 +160,24 @@ class TestLvmBlueStore: @patch('ceph_volume.api.lvm.get_single_lv') def test_safe_prepare(self, m_get_single_lv, factory): args = factory(data='vg_foo/lv_foo') - self.lvm_bs.args = args + self.lvm.args = args m_get_single_lv.return_value = Volume(lv_name='lv_foo', lv_path='/fake-path', vg_name='vg_foo', lv_tags='', lv_uuid='fake-uuid') - self.lvm_bs.prepare = MagicMock() - self.lvm_bs.safe_prepare() - assert self.lvm_bs.prepare.called + self.lvm.prepare = MagicMock() + self.lvm.safe_prepare() + assert self.lvm.prepare.called - @patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.prepare', Mock(side_effect=Exception)) + @patch('ceph_volume.objectstore.lvm.Lvm.prepare', Mock(side_effect=Exception)) @patch('ceph_volume.api.lvm.is_ceph_device', Mock(return_value=False)) - # @patch('ceph_volume.devices.lvm.common.rollback_osd') - @patch('ceph_volume.objectstore.lvmbluestore.rollback_osd') + @patch('ceph_volume.objectstore.lvm.rollback_osd') @patch('ceph_volume.api.lvm.get_single_lv') def test_safe_prepare_raises_exception(self, m_get_single_lv, m_rollback_osd, factory): args = factory(data='/dev/foo') - self.lvm_bs.args = args - self.lvm_bs.osd_id = '111' + self.lvm.args = args + self.lvm.osd_id = '111' m_get_single_lv.return_value = Volume(lv_name='lv_foo', lv_path='/fake-path', vg_name='vg_foo', @@ -176,13 +185,13 @@ class TestLvmBlueStore: lv_uuid='fake-uuid') m_rollback_osd.return_value = MagicMock() with pytest.raises(Exception): - self.lvm_bs.safe_prepare() + self.lvm.safe_prepare() assert m_rollback_osd.mock_calls == [call('111')] - @patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.pre_prepare', Mock(return_value=None)) - @patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.prepare_dmcrypt', MagicMock()) + @patch('ceph_volume.objectstore.lvm.Lvm.pre_prepare', Mock(return_value=None)) + @patch('ceph_volume.objectstore.lvm.Lvm.prepare_dmcrypt', MagicMock()) @patch('ceph_volume.objectstore.baseobjectstore.BaseObjectStore.prepare_osd_req', MagicMock()) - @patch('ceph_volume.objectstore.bluestore.BlueStore.osd_mkfs', MagicMock()) + @patch('ceph_volume.objectstore.baseobjectstore.BaseObjectStore.osd_mkfs', MagicMock()) @patch('ceph_volume.util.disk.is_partition', Mock(return_value=True)) @patch('ceph_volume.objectstore.baseobjectstore.BaseObjectStore.get_ptuuid', Mock(return_value='c6798f59-01')) @patch('ceph_volume.api.lvm.Volume.set_tags', MagicMock()) @@ -205,55 +214,55 @@ class TestLvmBlueStore: block_db_slots=1, with_tpm=False ) - self.lvm_bs.args = args - self.lvm_bs.block_lv = MagicMock() - self.lvm_bs.secrets['dmcrypt_key'] = 'fake-secret' - self.lvm_bs.prepare() - assert self.lvm_bs.wal_device_path == '/dev/foo1' - assert self.lvm_bs.db_device_path == '/dev/foo2' - assert self.lvm_bs.block_lv.set_tags.mock_calls == [call({ + self.lvm.args = args + self.lvm.block_lv = MagicMock() + self.lvm.secrets['dmcrypt_key'] = 'fake-secret' + self.lvm.prepare() + assert self.lvm.wal_device_path == '/dev/foo1' + assert self.lvm.db_device_path == '/dev/foo2' + assert self.lvm.block_lv.set_tags.mock_calls == [call({ 'ceph.type': 'block', })] - assert not self.lvm_bs.prepare_dmcrypt.called - assert self.lvm_bs.osd_mkfs.called - assert self.lvm_bs.prepare_osd_req.called + assert not self.lvm.prepare_dmcrypt.called + assert self.lvm.osd_mkfs.called + assert self.lvm.prepare_osd_req.called def test_prepare_dmcrypt(self): - self.lvm_bs.secrets = {'dmcrypt_key': 'fake-secret'} - self.lvm_bs.tags = {'ceph.block_uuid': 'block-uuid1', + self.lvm.secrets = {'dmcrypt_key': 'fake-secret'} + self.lvm.tags = {'ceph.block_uuid': 'block-uuid1', 'ceph.db_uuid': 'db-uuid2', 'ceph.wal_uuid': 'wal-uuid3', 'ceph.with_tpm': 0} - self.lvm_bs.block_device_path = '/dev/sdb' - self.lvm_bs.db_device_path = '/dev/sdc' - self.lvm_bs.wal_device_path = '/dev/sdb' - self.lvm_bs.luks_format_and_open = lambda *a: f'/dev/mapper/{a[2]["ceph."+a[1]+"_uuid"]}' - self.lvm_bs.prepare_dmcrypt() - assert self.lvm_bs.block_device_path == '/dev/mapper/block-uuid1' - assert self.lvm_bs.db_device_path == '/dev/mapper/db-uuid2' - assert self.lvm_bs.wal_device_path == '/dev/mapper/wal-uuid3' - - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.luks_open') - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.luks_format') + self.lvm.block_device_path = '/dev/sdb' + self.lvm.db_device_path = '/dev/sdc' + self.lvm.wal_device_path = '/dev/sdb' + self.lvm.luks_format_and_open = lambda *a: f'/dev/mapper/{a[2]["ceph."+a[1]+"_uuid"]}' + self.lvm.prepare_dmcrypt() + assert self.lvm.block_device_path == '/dev/mapper/block-uuid1' + assert self.lvm.db_device_path == '/dev/mapper/db-uuid2' + assert self.lvm.wal_device_path == '/dev/mapper/wal-uuid3' + + @patch('ceph_volume.objectstore.lvm.encryption_utils.luks_open') + @patch('ceph_volume.objectstore.lvm.encryption_utils.luks_format') def test_luks_format_and_open(self, m_luks_format, m_luks_open): - result = self.lvm_bs.luks_format_and_open('/dev/foo', + result = self.lvm.luks_format_and_open('/dev/foo', 'block', {'ceph.block_uuid': 'block-uuid1'}) assert result == '/dev/mapper/block-uuid1' - @patch('ceph_volume.objectstore.lvmbluestore.LvmBlueStore.enroll_tpm2', Mock(return_value=MagicMock())) - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.luks_open') - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.luks_format') + @patch('ceph_volume.objectstore.lvm.Lvm.enroll_tpm2', Mock(return_value=MagicMock())) + @patch('ceph_volume.objectstore.lvm.encryption_utils.luks_open') + @patch('ceph_volume.objectstore.lvm.encryption_utils.luks_format') def test_luks_format_and_open_with_tpm(self, m_luks_format, m_luks_open): - self.lvm_bs.with_tpm = True - result = self.lvm_bs.luks_format_and_open('/dev/foo', + self.lvm.with_tpm = True + result = self.lvm.luks_format_and_open('/dev/foo', 'block', {'ceph.block_uuid': 'block-uuid1'}) assert result == '/dev/mapper/block-uuid1' - self.lvm_bs.enroll_tpm2.assert_called_once() + self.lvm.enroll_tpm2.assert_called_once() def test_luks_format_and_open_not_device(self): - result = self.lvm_bs.luks_format_and_open('', + result = self.lvm.luks_format_and_open('', 'block', {}) assert result == '' @@ -282,8 +291,8 @@ class TestLvmBlueStore: block_wal=None, block_wal_size='0', block_wal_slots=None) - self.lvm_bs.args = args - self.lvm_bs.setup_metadata_devices() + self.lvm.args = args + self.lvm.setup_metadata_devices() assert m_create_lv.mock_calls == [call(name_prefix='osd-db', uuid='d83fa1ca-bd68-4c75-bdc2-464da58e8abd', vg=None, @@ -317,8 +326,8 @@ class TestLvmBlueStore: block_wal=None, block_wal_size='0', block_wal_slots=None) - self.lvm_bs.args = args - self.lvm_bs.setup_metadata_devices() + self.lvm.args = args + self.lvm.setup_metadata_devices() assert m_set_tags.mock_calls == [call({ 'ceph.type': 'db', 'ceph.vdo': '0', @@ -344,8 +353,8 @@ class TestLvmBlueStore: block_wal=None, block_wal_size='0', block_wal_slots=None) - self.lvm_bs.args = args - self.lvm_bs.setup_metadata_devices() + self.lvm.args = args + self.lvm.setup_metadata_devices() m_create_lv.assert_not_called() m_set_tags.assert_not_called() @@ -355,16 +364,16 @@ class TestLvmBlueStore: vg_name='vg_foo', lv_tags='ceph.type=block,ceph.block_uuid=fake-block-uuid', lv_uuid='fake-block-uuid')] - assert self.lvm_bs.get_osd_device_path(lvs, 'block') == '/fake-path' + assert self.lvm.get_osd_device_path(lvs, 'block') == '/fake-path' - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.luks_open', MagicMock()) + @patch('ceph_volume.objectstore.lvm.encryption_utils.luks_open', MagicMock()) def test_get_osd_device_path_lv_block_encrypted(self): lvs = [Volume(lv_name='lv_foo', lv_path='/fake-path', vg_name='vg_foo', lv_tags='ceph.type=block,ceph.block_uuid=fake-block-uuid,ceph.encrypted=1', lv_uuid='fake-block-uuid')] - assert self.lvm_bs.get_osd_device_path(lvs, 'block') == '/dev/mapper/fake-block-uuid' + assert self.lvm.get_osd_device_path(lvs, 'block') == '/dev/mapper/fake-block-uuid' def test_get_osd_device_path_lv_db(self): lvs = [Volume(lv_name='lv_foo-block', @@ -377,7 +386,7 @@ class TestLvmBlueStore: vg_name='vg_foo_db', lv_tags='ceph.type=db,ceph.block_uuid=fake-block-uuid,ceph.db_uuid=fake-db-uuid', lv_uuid='fake-db-uuid')] - assert self.lvm_bs.get_osd_device_path(lvs, 'db') == '/fake-db-path' + assert self.lvm.get_osd_device_path(lvs, 'db') == '/fake-db-path' def test_get_osd_device_path_no_device_uuid(self): lvs = [Volume(lv_name='lv_foo-block', @@ -390,10 +399,10 @@ class TestLvmBlueStore: vg_name='vg_foo_db', lv_tags='ceph.type=db,ceph.block_uuid=fake-block-uuid', lv_uuid='fake-db-uuid')] - assert not self.lvm_bs.get_osd_device_path(lvs, 'db') + assert not self.lvm.get_osd_device_path(lvs, 'db') @patch('ceph_volume.util.disk.get_device_from_partuuid') - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.luks_open', MagicMock()) + @patch('ceph_volume.objectstore.lvm.encryption_utils.luks_open', MagicMock()) def test_get_osd_device_path_phys_encrypted(self, m_get_device_from_partuuid): m_get_device_from_partuuid.return_value = '/dev/sda1' lvs = [Volume(lv_name='lv_foo-block', @@ -401,7 +410,7 @@ class TestLvmBlueStore: vg_name='vg_foo', lv_tags='ceph.type=block,ceph.block_uuid=fake-block-uuid,ceph.db_uuid=fake-db-uuid,ceph.osd_id=0,ceph.osd_fsid=abcd,ceph.cluster_name=ceph,ceph.encrypted=1', lv_uuid='fake-block-uuid')] - assert self.lvm_bs.get_osd_device_path(lvs, 'db') == '/dev/mapper/fake-db-uuid' + assert self.lvm.get_osd_device_path(lvs, 'db') == '/dev/mapper/fake-db-uuid' @patch('ceph_volume.util.disk.get_device_from_partuuid') def test_get_osd_device_path_phys(self, m_get_device_from_partuuid): @@ -411,7 +420,7 @@ class TestLvmBlueStore: vg_name='vg_foo', lv_tags='ceph.type=block,ceph.block_uuid=fake-block-uuid,ceph.db_uuid=fake-db-uuid,ceph.osd_id=0,ceph.osd_fsid=abcd,ceph.cluster_name=ceph', lv_uuid='fake-block-uuid')] - self.lvm_bs.get_osd_device_path(lvs, 'db') + self.lvm.get_osd_device_path(lvs, 'db') @patch('ceph_volume.util.disk.get_device_from_partuuid') def test_get_osd_device_path_phys_raises_exception(self, m_get_device_from_partuuid): @@ -422,7 +431,7 @@ class TestLvmBlueStore: lv_tags='ceph.type=block,ceph.block_uuid=fake-block-uuid,ceph.db_uuid=fake-db-uuid,ceph.osd_id=0,ceph.osd_fsid=abcd,ceph.cluster_name=ceph', lv_uuid='fake-block-uuid')] with pytest.raises(RuntimeError): - self.lvm_bs.get_osd_device_path(lvs, 'db') + self.lvm.get_osd_device_path(lvs, 'db') def test__activate_raises_exception(self): lvs = [Volume(lv_name='lv_foo-db', @@ -431,12 +440,12 @@ class TestLvmBlueStore: lv_tags='ceph.type=db,ceph.db_uuid=fake-db-uuid', lv_uuid='fake-db-uuid')] with pytest.raises(RuntimeError) as error: - self.lvm_bs._activate(lvs) + self.lvm._activate(lvs) assert str(error.value) == 'could not find a bluestore OSD to activate' - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.write_lockbox_keyring', MagicMock()) - @patch('ceph_volume.objectstore.lvmbluestore.encryption_utils.get_dmcrypt_key', MagicMock()) - @patch('ceph_volume.objectstore.lvmbluestore.prepare_utils.create_osd_path') + @patch('ceph_volume.objectstore.lvm.encryption_utils.write_lockbox_keyring', MagicMock()) + @patch('ceph_volume.objectstore.lvm.encryption_utils.get_dmcrypt_key', MagicMock()) + @patch('ceph_volume.objectstore.lvm.prepare_utils.create_osd_path') @patch('ceph_volume.terminal.success') @pytest.mark.parametrize("encrypted", ["ceph.encrypted=0", "ceph.encrypted=1"]) def test__activate(self, @@ -463,7 +472,7 @@ class TestLvmBlueStore: vg_name='vg_foo_wal', lv_tags=f'ceph.type=wal,ceph.block_uuid=fake-block-uuid,ceph.wal_uuid=fake-wal-uuid,ceph.db_uuid=fake-db-uuid,ceph.osd_id=0,ceph.osd_fsid=abcd,ceph.cluster_name=ceph,{encrypted},ceph.cephx_lockbox_secret=abcd', lv_uuid='fake-wal-uuid')] - self.lvm_bs._activate(lvs) + self.lvm._activate(lvs) if encrypted == "ceph.encrypted=0": assert fake_run.calls == [{'args': (['ceph-bluestore-tool', '--cluster=ceph', 'prime-osd-dir', '--dev', '/fake-block-path', @@ -515,10 +524,10 @@ class TestLvmBlueStore: factory, fake_run): args = factory(no_systemd=True) - self.lvm_bs.args = args - self.lvm_bs.activate = MagicMock() - self.lvm_bs.activate_all() - assert self.lvm_bs.activate.mock_calls == [call(args, + self.lvm.args = args + self.lvm.activate = MagicMock() + self.lvm.activate_all() + assert self.lvm.activate.mock_calls == [call(args, osd_id='1', osd_fsid='824f7edf-371f-4b75-9231-4ab62a32d5c0'), call(args, @@ -533,10 +542,10 @@ class TestLvmBlueStore: fake_run, monkeypatch, capsys): - monkeypatch.setattr('ceph_volume.objectstore.lvmbluestore.direct_report', lambda: {}) + monkeypatch.setattr('ceph_volume.objectstore.lvm.direct_report', lambda: {}) args = factory(no_systemd=True) - self.lvm_bs.args = args - self.lvm_bs.activate_all() + self.lvm.args = args + self.lvm.activate_all() stdout, stderr = capsys.readouterr() assert "Was unable to find any OSDs to activate" in stderr assert "Verify OSDs are present with" in stderr @@ -549,10 +558,10 @@ class TestLvmBlueStore: factory, fake_run): args = factory(no_systemd=False) - self.lvm_bs.args = args - self.lvm_bs.activate = MagicMock() - self.lvm_bs.activate_all() - assert self.lvm_bs.activate.mock_calls == [] + self.lvm.args = args + self.lvm.activate = MagicMock() + self.lvm.activate_all() + assert self.lvm.activate.mock_calls == [] @patch('ceph_volume.api.lvm.get_lvs') def test_activate_osd_id_and_fsid(self, @@ -568,10 +577,10 @@ class TestLvmBlueStore: lv_tags=f'ceph.osd_id={args.osd_id},ceph.osd_fsid={args.osd_fsid}', lv_uuid='fake-uuid')] m_get_lvs.return_value = lvs - self.lvm_bs.args = args - self.lvm_bs._activate = MagicMock() - self.lvm_bs.activate() - assert self.lvm_bs._activate.mock_calls == [call(lvs, True, False)] + self.lvm.args = args + self.lvm._activate = MagicMock() + self.lvm.activate() + assert self.lvm._activate.mock_calls == [call(lvs, True, False)] assert m_get_lvs.mock_calls == [call(tags={'ceph.osd_id': '1', 'ceph.osd_fsid': '824f7edf'})] @@ -589,10 +598,10 @@ class TestLvmBlueStore: lv_tags='', lv_uuid='fake-uuid')] m_get_lvs.return_value = lvs - self.lvm_bs.args = args - self.lvm_bs._activate = MagicMock() - self.lvm_bs.activate() - assert self.lvm_bs._activate.mock_calls == [call(lvs, True, False)] + self.lvm.args = args + self.lvm._activate = MagicMock() + self.lvm.activate() + assert self.lvm._activate.mock_calls == [call(lvs, True, False)] assert m_get_lvs.mock_calls == [call(tags={'ceph.osd_fsid': '824f7edf'})] def test_activate_osd_id_and_not_fsid(self, @@ -601,10 +610,10 @@ class TestLvmBlueStore: args = factory(no_systemd=True, osd_id='1', osd_fsid=None) - self.lvm_bs.args = args - self.lvm_bs._activate = MagicMock() + self.lvm.args = args + self.lvm._activate = MagicMock() with pytest.raises(RuntimeError) as error: - self.lvm_bs.activate() + self.lvm.activate() assert str(error.value) == 'could not activate osd.1, please provide the osd_fsid too' def test_activate_not_osd_id_and_not_fsid(self, @@ -613,10 +622,10 @@ class TestLvmBlueStore: args = factory(no_systemd=True, osd_id=None, osd_fsid=None) - self.lvm_bs.args = args - self.lvm_bs._activate = MagicMock() + self.lvm.args = args + self.lvm._activate = MagicMock() with pytest.raises(RuntimeError) as error: - self.lvm_bs.activate() + self.lvm.activate() assert str(error.value) == 'Please provide both osd_id and osd_fsid' @patch('ceph_volume.api.lvm.get_lvs') @@ -629,8 +638,8 @@ class TestLvmBlueStore: no_systemd=True) lvs = [] m_get_lvs.return_value = lvs - self.lvm_bs.args = args - self.lvm_bs._activate = MagicMock() + self.lvm.args = args + self.lvm._activate = MagicMock() with pytest.raises(RuntimeError) as error: - self.lvm_bs.activate() + self.lvm.activate() assert str(error.value) == 'could not find osd.1 with osd_fsid 824f7edf' \ No newline at end of file diff --git a/src/ceph-volume/ceph_volume/tests/objectstore/test_rawbluestore.py b/src/ceph-volume/ceph_volume/tests/objectstore/test_raw.py similarity index 86% rename from src/ceph-volume/ceph_volume/tests/objectstore/test_rawbluestore.py rename to src/ceph-volume/ceph_volume/tests/objectstore/test_raw.py index 0c51628c129ca..f49b09829d250 100644 --- a/src/ceph-volume/ceph_volume/tests/objectstore/test_rawbluestore.py +++ b/src/ceph-volume/ceph_volume/tests/objectstore/test_raw.py @@ -1,13 +1,13 @@ import pytest from unittest.mock import patch, Mock, MagicMock, call -from ceph_volume.objectstore.rawbluestore import RawBlueStore +from ceph_volume.objectstore.raw import Raw from ceph_volume.util import system -class TestRawBlueStore: - @patch('ceph_volume.objectstore.rawbluestore.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])) +class TestRaw: + @patch('ceph_volume.objectstore.raw.prepare_utils.create_key', Mock(return_value=['AQCee6ZkzhOrJRAAZWSvNC3KdXOpC2w8ly4AZQ=='])) def setup_method(self, m_create_key): - self.raw_bs = RawBlueStore([]) + self.raw_bs = Raw([]) def test_prepare_dmcrypt(self, device_info, @@ -26,7 +26,7 @@ class TestRawBlueStore: assert self.raw_bs.db_device_path == "/dev/mapper/ceph--foo0-db-dmcrypt" assert self.raw_bs.wal_device_path == "/dev/mapper/ceph--foo0-wal-dmcrypt" - @patch('ceph_volume.objectstore.rawbluestore.RawBlueStore.enroll_tpm2', Mock(return_value=MagicMock())) + @patch('ceph_volume.objectstore.raw.Raw.enroll_tpm2', Mock(return_value=MagicMock())) def test_prepare_dmcrypt_with_tpm(self, device_info, fake_call, @@ -46,8 +46,8 @@ class TestRawBlueStore: assert self.raw_bs.wal_device_path == "/dev/mapper/ceph--foo0-wal-dmcrypt" assert self.raw_bs.enroll_tpm2.mock_calls == [call('/dev/foo0'), call('/dev/foo1'), call('/dev/foo2')] - @patch('ceph_volume.objectstore.rawbluestore.rollback_osd') - @patch('ceph_volume.objectstore.rawbluestore.RawBlueStore.prepare') + @patch('ceph_volume.objectstore.raw.rollback_osd') + @patch('ceph_volume.objectstore.raw.Raw.prepare') def test_safe_prepare_raises_exception(self, m_prepare, m_rollback_osd, @@ -62,7 +62,7 @@ class TestRawBlueStore: self.raw_bs.safe_prepare() assert m_rollback_osd.mock_calls == [call('1')] - @patch('ceph_volume.objectstore.rawbluestore.RawBlueStore.prepare', MagicMock()) + @patch('ceph_volume.objectstore.raw.Raw.prepare', MagicMock()) def test_safe_prepare(self, factory, capsys): @@ -73,8 +73,8 @@ class TestRawBlueStore: assert "prepare successful for: /dev/foo" in stderr @patch.dict('os.environ', {'CEPH_VOLUME_DMCRYPT_SECRET': 'dmcrypt-key'}) - @patch('ceph_volume.objectstore.rawbluestore.prepare_utils.create_id') - @patch('ceph_volume.objectstore.rawbluestore.system.generate_uuid') + @patch('ceph_volume.objectstore.raw.prepare_utils.create_id') + @patch('ceph_volume.objectstore.raw.system.generate_uuid') def test_prepare(self, m_generate_uuid, m_create_id, is_root, factory): m_generate_uuid.return_value = 'fake-uuid' m_create_id.return_value = MagicMock() @@ -94,13 +94,13 @@ class TestRawBlueStore: assert self.raw_bs.prepare_dmcrypt.called @patch('ceph_volume.conf.cluster', 'ceph') - @patch('ceph_volume.objectstore.rawbluestore.prepare_utils.link_wal') - @patch('ceph_volume.objectstore.rawbluestore.prepare_utils.link_db') - @patch('ceph_volume.objectstore.rawbluestore.prepare_utils.link_block') + @patch('ceph_volume.objectstore.raw.prepare_utils.link_wal') + @patch('ceph_volume.objectstore.raw.prepare_utils.link_db') + @patch('ceph_volume.objectstore.raw.prepare_utils.link_block') @patch('os.path.exists') @patch('os.unlink') - @patch('ceph_volume.objectstore.rawbluestore.prepare_utils.create_osd_path') - @patch('ceph_volume.objectstore.rawbluestore.process.run') + @patch('ceph_volume.objectstore.raw.prepare_utils.create_osd_path') + @patch('ceph_volume.objectstore.raw.process.run') def test__activate(self, m_run, m_create_osd_path, @@ -157,10 +157,10 @@ class TestRawBlueStore: 'type': 'bluestore'}, tmpfs=True)] - @patch('ceph_volume.objectstore.rawbluestore.encryption_utils.rename_mapper', Mock(return_value=MagicMock())) + @patch('ceph_volume.objectstore.raw.encryption_utils.rename_mapper', Mock(return_value=MagicMock())) @patch('ceph_volume.util.disk.get_bluestore_header') - @patch('ceph_volume.objectstore.rawbluestore.encryption_utils.luks_close', Mock(return_value=MagicMock())) - @patch('ceph_volume.objectstore.rawbluestore.encryption_utils.luks_open', Mock(return_value=MagicMock())) + @patch('ceph_volume.objectstore.raw.encryption_utils.luks_close', Mock(return_value=MagicMock())) + @patch('ceph_volume.objectstore.raw.encryption_utils.luks_open', Mock(return_value=MagicMock())) def test_activate_dmcrypt_tpm(self, m_bs_header, rawbluestore, fake_lsblk_all, mock_raw_direct_report, is_root) -> None: m_bs_header.return_value = { "/dev/mapper/activating-sdb": { @@ -203,7 +203,7 @@ class TestRawBlueStore: mock_luks2_4.is_ceph_encrypted = True mock_luks2_4.is_tpm2_enrolled = True mock_luks2_4.osd_fsid = 'abcd' - with patch('ceph_volume.objectstore.rawbluestore.encryption_utils.CephLuks2', side_effect=[mock_luks2_1, + with patch('ceph_volume.objectstore.raw.encryption_utils.CephLuks2', side_effect=[mock_luks2_1, mock_luks2_2, mock_luks2_3, mock_luks2_4]): diff --git a/src/ceph-volume/ceph_volume/tests/util/test_prepare.py b/src/ceph-volume/ceph_volume/tests/util/test_prepare.py index 854eab707660e..414e2f4d1e1b2 100644 --- a/src/ceph-volume/ceph_volume/tests/util/test_prepare.py +++ b/src/ceph-volume/ceph_volume/tests/util/test_prepare.py @@ -5,7 +5,7 @@ from ceph_volume.util import prepare from ceph_volume.util.prepare import system from ceph_volume import conf from ceph_volume.tests.conftest import Factory -from ceph_volume import objectstore +from ceph_volume.objectstore.baseobjectstore import BaseObjectStore from unittest.mock import patch @@ -118,13 +118,14 @@ class TestFormatDevice(object): assert expected == fake_run.calls[0]['args'][0] -class TestOsdMkfsBluestore(object): +class TestOsdMkfs(object): def setup_method(self): conf.cluster = 'ceph' - def test_keyring_is_added(self, fake_call, monkeypatch): + def test_keyring_is_added(self, fake_call, monkeypatch, factory): + args = factory(dmcrypt=False) monkeypatch.setattr(system, 'chown', lambda path: True) - o = objectstore.baseobjectstore.BaseObjectStore([]) + o = BaseObjectStore(args) o.osd_id = '1' o.osd_fsid = 'asdf' o.osd_mkfs() @@ -133,34 +134,33 @@ class TestOsdMkfsBluestore(object): def test_keyring_is_not_added(self, fake_call, monkeypatch, factory): args = factory(dmcrypt=False) monkeypatch.setattr(system, 'chown', lambda path: True) - o = objectstore.bluestore.BlueStore([]) - o.args = args + o = BaseObjectStore(args) o.osd_id = '1' o.osd_fsid = 'asdf' o.osd_mkfs() assert '--keyfile' not in fake_call.calls[0]['args'][0] - def test_wal_is_added(self, fake_call, monkeypatch, objectstore_bluestore, factory): - args = factory(dmcrypt=False) + def test_wal_is_added(self, fake_call, monkeypatch, objectstore, factory): + args = factory(objecstore='bluestore', + osd_id='1', + osd_fid='asdf', + wal_device_path='/dev/smm1', + cephx_secret='foo', + dmcrypt=False) monkeypatch.setattr(system, 'chown', lambda path: True) - bs = objectstore_bluestore(objecstore='bluestore', - osd_id='1', - osd_fid='asdf', - wal_device_path='/dev/smm1', - cephx_secret='foo', - dmcrypt=False) - bs.args = args - bs.osd_mkfs() + o = BaseObjectStore(args) + o.wal_device_path = '/dev/smm1' + o.osd_mkfs() assert '--bluestore-block-wal-path' in fake_call.calls[2]['args'][0] assert '/dev/smm1' in fake_call.calls[2]['args'][0] def test_db_is_added(self, fake_call, monkeypatch, factory): args = factory(dmcrypt=False) monkeypatch.setattr(system, 'chown', lambda path: True) - bs = objectstore.bluestore.BlueStore([]) - bs.args = args - bs.db_device_path = '/dev/smm2' - bs.osd_mkfs() + o = BaseObjectStore(args) + o.args = args + o.db_device_path = '/dev/smm2' + o.osd_mkfs() assert '--bluestore-block-db-path' in fake_call.calls[2]['args'][0] assert '/dev/smm2' in fake_call.calls[2]['args'][0] @@ -288,28 +288,29 @@ class TestNormalizeFlags(object): assert ','.join(result) == 'auto,discard,exec,rw' @patch('ceph_volume.util.prepare.create_key', return_value='fake-secret') -class TestMkfsBluestore(object): +class TestMkfs(object): - def test_non_zero_exit_status(self, m_create_key, stub_call, monkeypatch, objectstore_bluestore): + def test_non_zero_exit_status(self, m_create_key, stub_call, monkeypatch, objectstore): conf.cluster = 'ceph' monkeypatch.setattr('ceph_volume.util.prepare.system.chown', lambda x: True) stub_call(([], [], 1)) - bs = objectstore_bluestore(osd_id='1', - osd_fsid='asdf-1234', - cephx_secret='keyring') + o = objectstore(osd_id='1', + osd_fsid='asdf-1234', + cephx_secret='keyring') with pytest.raises(RuntimeError) as error: - bs.osd_mkfs() + o.osd_mkfs() assert "Command failed with exit code 1" in str(error.value) - def test_non_zero_exit_formats_command_correctly(self, m_create_key, stub_call, monkeypatch, objectstore_bluestore): + def test_non_zero_exit_formats_command_correctly(self, m_create_key, stub_call, monkeypatch, objectstore): conf.cluster = 'ceph' monkeypatch.setattr('ceph_volume.util.prepare.system.chown', lambda x: True) stub_call(([], [], 1)) - bs = objectstore_bluestore(osd_id='1', - osd_fsid='asdf-1234', - cephx_secret='keyring') + o = objectstore(osd_id='1', + objectstore='bluestore', + osd_fsid='asdf-1234', + cephx_secret='keyring') with pytest.raises(RuntimeError) as error: - bs.osd_mkfs() + o.osd_mkfs() expected = ' '.join([ 'ceph-osd', '--cluster', diff --git a/src/ceph-volume/ceph_volume/util/disk.py b/src/ceph-volume/ceph_volume/util/disk.py index 654f49b61b479..51712f54be8a6 100644 --- a/src/ceph-volume/ceph_volume/util/disk.py +++ b/src/ceph-volume/ceph_volume/util/disk.py @@ -873,7 +873,7 @@ def get_devices(_sys_block_path='/sys/block', device=''): device_facts[diskname] = metadata return device_facts -def has_bluestore_label(device_path): +def has_bluestore_label(device_path: str) -> bool: isBluestore = False bluestoreDiskSignature = 'bluestore block device' # 22 bytes long @@ -890,6 +890,22 @@ def has_bluestore_label(device_path): return isBluestore +def has_seastore_label(device_path: str) -> bool: + is_seastore = False + seastore_disk_signature = b'seastore block device\n' # 23 bytes including newline + + try: + with open(device_path, "rb") as fd: + signature = fd.read(len(seastore_disk_signature)) + if signature == seastore_disk_signature: + is_seastore = True + except IsADirectoryError: + print(f'{device_path} is a directory, skipping.') + except Exception as e: + print(f'Error reading {device_path}: {e}') + + return is_seastore + def get_lvm_mappers(sys_block_path: str = '/sys/block') -> List[str]: """ Retrieve a list of Logical Volume Manager (LVM) device mappers. diff --git a/src/cephadm/cephadmlib/daemons/ceph.py b/src/cephadm/cephadmlib/daemons/ceph.py index c31a355d7eb41..dfa4bb84c76d3 100644 --- a/src/cephadm/cephadmlib/daemons/ceph.py +++ b/src/cephadm/cephadmlib/daemons/ceph.py @@ -94,6 +94,10 @@ class Ceph(ContainerDaemonForm): if 'rgw_exit_timeout_secs' in config_json: stop_timeout = config_json['rgw_exit_timeout_secs'] ctr.args = ctr.args + [f'--stop-timeout={stop_timeout}'] + if self.identity.daemon_type == 'osd' and config_json is not None: + if 'objectstore' in config_json: + objectstore = config_json['objectstore'] + ctr.args = ctr.args + [f'--osd-objectstore={objectstore}'] return ctr _uid_gid: Optional[Tuple[int, int]] = None diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index 1d3f7e96a694a..515958061c917 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -2981,7 +2981,7 @@ Then run the following: placement=PlacementSpec(host_pattern=host), data_devices=DeviceSelection(paths=devices), unmanaged=False, - objectstore="bluestore" + objectstore=drive_group.objectstore ) self.log.info(f"Creating OSDs with service ID: {drive_group.service_id} on {host}:{device_list}") diff --git a/src/pybind/mgr/cephadm/services/osd.py b/src/pybind/mgr/cephadm/services/osd.py index ae35a897b4df9..60a399149f9f9 100644 --- a/src/pybind/mgr/cephadm/services/osd.py +++ b/src/pybind/mgr/cephadm/services/osd.py @@ -397,6 +397,15 @@ class OSDService(CephService): if not is_failed_deploy: super().post_remove(daemon, is_failed_deploy=is_failed_deploy) + def generate_config(self, daemon_spec: CephadmDaemonDeploySpec) -> Tuple[Dict[str, Any], List[str]]: + config, parent_deps = super().generate_config(daemon_spec) + if daemon_spec.service_name in self.mgr.spec_store: + svc_spec = cast(DriveGroupSpec, self.mgr.spec_store[daemon_spec.service_name].spec) + + if hasattr(svc_spec, 'objectstore') and svc_spec.objectstore: + config['objectstore'] = svc_spec.objectstore + return config, parent_deps + class OsdIdClaims(object): """ diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index bcfd1e4b65fcc..21d1671c24c12 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -1132,7 +1132,7 @@ class TestCephadm(object): _run_cephadm.assert_any_call( 'test', 'osd', 'ceph-volume', ['--config-json', '-', '--', 'lvm', 'batch', - '--no-auto', '/dev/sdb', '--yes', '--no-systemd'], + '--no-auto', '/dev/sdb', '--objectstore', 'bluestore', '--yes', '--no-systemd'], env_vars=['CEPH_VOLUME_OSDSPEC_AFFINITY=foo'], error_ok=True, stdin='{"config": "", "keyring": ""}') _run_cephadm.assert_any_call( @@ -1178,7 +1178,7 @@ class TestCephadm(object): 'test', 'osd', 'ceph-volume', ['--config-json', '-', '--', 'lvm', 'batch', '--no-auto', '/dev/sdb', '--db-devices', '/dev/sdc', - '--wal-devices', '/dev/sdd', '--yes', '--no-systemd'], + '--wal-devices', '/dev/sdd', '--objectstore', 'bluestore', '--yes', '--no-systemd'], env_vars=['CEPH_VOLUME_OSDSPEC_AFFINITY=noncollocated'], error_ok=True, stdin='{"config": "", "keyring": ""}', ) @@ -1266,15 +1266,15 @@ class TestCephadm(object): "devices, preview, exp_commands", [ # no preview and only one disk, prepare is used due the hack that is in place. - (['/dev/sda'], False, ["lvm batch --no-auto /dev/sda --yes --no-systemd"]), + (['/dev/sda'], False, ["lvm batch --no-auto /dev/sda --objectstore bluestore --yes --no-systemd"]), # no preview and multiple disks, uses batch (['/dev/sda', '/dev/sdb'], False, - ["CEPH_VOLUME_OSDSPEC_AFFINITY=test.spec lvm batch --no-auto /dev/sda /dev/sdb --yes --no-systemd"]), + ["CEPH_VOLUME_OSDSPEC_AFFINITY=test.spec lvm batch --no-auto /dev/sda /dev/sdb --objectstore bluestore --yes --no-systemd"]), # preview and only one disk needs to use batch again to generate the preview - (['/dev/sda'], True, ["lvm batch --no-auto /dev/sda --yes --no-systemd --report --format json"]), + (['/dev/sda'], True, ["lvm batch --no-auto /dev/sda --objectstore bluestore --yes --no-systemd --report --format json"]), # preview and multiple disks work the same (['/dev/sda', '/dev/sdb'], True, - ["CEPH_VOLUME_OSDSPEC_AFFINITY=test.spec lvm batch --no-auto /dev/sda /dev/sdb --yes --no-systemd --report --format json"]), + ["CEPH_VOLUME_OSDSPEC_AFFINITY=test.spec lvm batch --no-auto /dev/sda /dev/sdb --objectstore bluestore --yes --no-systemd --report --format json"]), ] ) @mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}')) diff --git a/src/python-common/ceph/deployment/translate.py b/src/python-common/ceph/deployment/translate.py index 9dfe7cfcf8187..3a75cd34bb8e8 100644 --- a/src/python-common/ceph/deployment/translate.py +++ b/src/python-common/ceph/deployment/translate.py @@ -107,7 +107,7 @@ class to_ceph_volume(object): cmds.append(cmd) dev_counter += 1 - elif self.spec.objectstore == 'bluestore': + elif self.spec.objectstore in ['bluestore', 'seastore']: # for lvm batch we can just do all devices in one command cmd = "lvm batch --no-auto {}".format(" ".join(data_devices)) @@ -126,6 +126,8 @@ class to_ceph_volume(object): if d != self.NO_CRUSH: cmd += " --crush-device-class {}".format(d) + + cmd += " --objectstore {}".format(self.spec.objectstore) cmds.append(cmd) for i in range(len(cmds)): diff --git a/src/python-common/ceph/tests/test_drive_group.py b/src/python-common/ceph/tests/test_drive_group.py index cd4a238af0d59..5252fcb689b2b 100644 --- a/src/python-common/ceph/tests/test_drive_group.py +++ b/src/python-common/ceph/tests/test_drive_group.py @@ -163,7 +163,7 @@ def test_ceph_volume_command_0(): inventory = _mk_inventory(_mk_device()*2) sel = drive_selection.DriveSelection(spec, inventory) cmds = translate.to_ceph_volume(sel, []).run() - assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' + assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --objectstore bluestore --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' def test_ceph_volume_command_1(): @@ -177,7 +177,7 @@ def test_ceph_volume_command_1(): sel = drive_selection.DriveSelection(spec, inventory) cmds = translate.to_ceph_volume(sel, []).run() assert all(cmd == ('lvm batch --no-auto /dev/sda /dev/sdb ' - '--db-devices /dev/sdc /dev/sdd --yes --no-systemd') for cmd in cmds), f'Expected {cmd} in {cmds}' + '--db-devices /dev/sdc /dev/sdd --objectstore bluestore --yes --no-systemd') for cmd in cmds), f'Expected {cmd} in {cmds}' def test_ceph_volume_command_2(): @@ -195,7 +195,7 @@ def test_ceph_volume_command_2(): sel = drive_selection.DriveSelection(spec, inventory) cmds = translate.to_ceph_volume(sel, []).run() assert all(cmd == ('lvm batch --no-auto /dev/sda /dev/sdb ' - '--db-devices /dev/sdc /dev/sdd --wal-devices /dev/sde /dev/sdf ' + '--db-devices /dev/sdc /dev/sdd --wal-devices /dev/sde /dev/sdf --objectstore bluestore ' '--yes --no-systemd') for cmd in cmds), f'Expected {cmd} in {cmds}' @@ -216,7 +216,7 @@ def test_ceph_volume_command_3(): cmds = translate.to_ceph_volume(sel, []).run() assert all(cmd == ('lvm batch --no-auto /dev/sda /dev/sdb ' '--db-devices /dev/sdc /dev/sdd ' - '--wal-devices /dev/sde /dev/sdf --dmcrypt ' + '--wal-devices /dev/sde /dev/sdf --objectstore bluestore --dmcrypt ' '--yes --no-systemd') for cmd in cmds), f'Expected {cmd} in {cmds}' @@ -240,7 +240,7 @@ def test_ceph_volume_command_4(): cmds = translate.to_ceph_volume(sel, []).run() assert all(cmd == ('lvm batch --no-auto /dev/sda /dev/sdb ' '--db-devices /dev/sdc /dev/sdd --wal-devices /dev/sde /dev/sdf ' - '--block-wal-size 500M --block-db-size 500M --dmcrypt ' + '--block-wal-size 500M --block-db-size 500M --objectstore bluestore --dmcrypt ' '--osds-per-device 3 --yes --no-systemd') for cmd in cmds), f'Expected {cmd} in {cmds}' @@ -286,7 +286,7 @@ def test_ceph_volume_command_7(): inventory = _mk_inventory(_mk_device(rotational=True)*2) sel = drive_selection.DriveSelection(spec, inventory) cmds = translate.to_ceph_volume(sel, ['0', '1']).run() - assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --osd-ids 0 1 --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' + assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --objectstore bluestore --osd-ids 0 1 --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' def test_ceph_volume_command_8(): @@ -304,7 +304,7 @@ def test_ceph_volume_command_8(): ) sel = drive_selection.DriveSelection(spec, inventory) cmds = translate.to_ceph_volume(sel, []).run() - assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --db-devices /dev/sdc --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' + assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --db-devices /dev/sdc --objectstore bluestore --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' def test_ceph_volume_command_9(): @@ -317,7 +317,7 @@ def test_ceph_volume_command_9(): inventory = _mk_inventory(_mk_device()*2) sel = drive_selection.DriveSelection(spec, inventory) cmds = translate.to_ceph_volume(sel, []).run() - assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --data-allocate-fraction 0.8 --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' + assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --objectstore bluestore --data-allocate-fraction 0.8 --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' @pytest.mark.parametrize("test_input_base", @@ -340,7 +340,7 @@ def test_ceph_volume_command_10(test_input_base): drive = drive_selection.DriveSelection(spec, spec.data_devices.paths) cmds = translate.to_ceph_volume(drive, []).run() - assert all(cmd == 'lvm batch --no-auto /dev/sda --crush-device-class ssd --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' + assert all(cmd == 'lvm batch --no-auto /dev/sda --crush-device-class ssd --objectstore bluestore --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' @pytest.mark.parametrize("test_input1", @@ -365,8 +365,7 @@ def test_ceph_volume_command_11(test_input1): spec.validate() drive = drive_selection.DriveSelection(spec, spec.data_devices.paths) cmds = translate.to_ceph_volume(drive, []).run() - - assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --crush-device-class hdd --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' + assert all(cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --crush-device-class hdd --objectstore bluestore --yes --no-systemd' for cmd in cmds), f'Expected {cmd} in {cmds}' @pytest.mark.parametrize("test_input2", @@ -393,8 +392,8 @@ def test_ceph_volume_command_12(test_input2): cmds = translate.to_ceph_volume(drive, []).run() expected_cmds = [ - 'lvm batch --no-auto /dev/sdb --crush-device-class ssd --yes --no-systemd', - 'lvm batch --no-auto /dev/sda --crush-device-class hdd --yes --no-systemd', + 'lvm batch --no-auto /dev/sdb --crush-device-class ssd --objectstore bluestore --yes --no-systemd', + 'lvm batch --no-auto /dev/sda --crush-device-class hdd --objectstore bluestore --yes --no-systemd', ] assert len(cmds) == len(expected_cmds), f"Expected {expected_cmds} got {cmds}" assert all(cmd in cmds for cmd in expected_cmds), f'Expected {expected_cmds} got {cmds}' @@ -423,8 +422,8 @@ def test_ceph_volume_command_13(test_input3): cmds = translate.to_ceph_volume(drive, []).run() expected_cmds = [ - 'lvm batch --no-auto /dev/sdb --yes --no-systemd', - 'lvm batch --no-auto /dev/sda --crush-device-class hdd --yes --no-systemd', + 'lvm batch --no-auto /dev/sdb --objectstore bluestore --yes --no-systemd', + 'lvm batch --no-auto /dev/sda --crush-device-class hdd --objectstore bluestore --yes --no-systemd', ] assert len(cmds) == len(expected_cmds), f"Expected {expected_cmds} got {cmds}" assert all(cmd in cmds for cmd in expected_cmds), f'Expected {expected_cmds} got {cmds}' -- 2.39.5