MINI Sh3ll
# flake8: noqa
import pytest
from ceph.deployment.inventory import Devices, Device
from ceph.deployment.drive_group import DriveGroupSpec, DeviceSelection, \
DriveGroupValidationError
from ceph.deployment import drive_selection
from ceph.deployment.service_spec import PlacementSpec
from ceph.tests.factories import InventoryFactory
from ceph.tests.utils import _mk_inventory, _mk_device
class TestMatcher(object):
""" Test Matcher base class
"""
def test_get_disk_key_3(self):
"""
virtual is False
key is found
retrun value of key is expected
"""
disk_map = Device(path='/dev/vdb', sys_api={'foo': 'bar'})
ret = drive_selection.Matcher('foo', 'bar')._get_disk_key(disk_map)
assert ret is disk_map.sys_api.get('foo')
def test_get_disk_key_4(self):
"""
virtual is False
key is not found
expect raise Exception
"""
disk_map = Device(path='/dev/vdb')
with pytest.raises(Exception):
drive_selection.Matcher('bar', 'foo')._get_disk_key(disk_map)
pytest.fail("No disk_key found for foo or None")
class TestSubstringMatcher(object):
def test_compare(self):
disk_dict = Device(path='/dev/vdb', sys_api=dict(model='samsung'))
matcher = drive_selection.SubstringMatcher('model', 'samsung')
ret = matcher.compare(disk_dict)
assert ret is True
def test_compare_false(self):
disk_dict = Device(path='/dev/vdb', sys_api=dict(model='nothing_matching'))
matcher = drive_selection.SubstringMatcher('model', 'samsung')
ret = matcher.compare(disk_dict)
assert ret is False
class TestEqualityMatcher(object):
def test_compare(self):
disk_dict = Device(path='/dev/vdb', sys_api=dict(rotates='1'))
matcher = drive_selection.EqualityMatcher('rotates', '1')
ret = matcher.compare(disk_dict)
assert ret is True
def test_compare_false(self):
disk_dict = Device(path='/dev/vdb', sys_api=dict(rotates='1'))
matcher = drive_selection.EqualityMatcher('rotates', '0')
ret = matcher.compare(disk_dict)
assert ret is False
class TestAllMatcher(object):
def test_compare(self):
disk_dict = Device(path='/dev/vdb')
matcher = drive_selection.AllMatcher('all', 'True')
ret = matcher.compare(disk_dict)
assert ret is True
def test_compare_value_not_true(self):
disk_dict = Device(path='/dev/vdb')
matcher = drive_selection.AllMatcher('all', 'False')
ret = matcher.compare(disk_dict)
assert ret is True
class TestSizeMatcher(object):
def test_parse_filter_exact(self):
""" Testing exact notation with 20G """
matcher = drive_selection.SizeMatcher('size', '20G')
assert isinstance(matcher.exact, tuple)
assert matcher.exact[0] == '20'
assert matcher.exact[1] == 'GB'
def test_parse_filter_exact_GB_G(self):
""" Testing exact notation with 20G """
matcher = drive_selection.SizeMatcher('size', '20GB')
assert isinstance(matcher.exact, tuple)
assert matcher.exact[0] == '20'
assert matcher.exact[1] == 'GB'
def test_parse_filter_high_low(self):
""" Testing high-low notation with 20G:50G """
matcher = drive_selection.SizeMatcher('size', '20G:50G')
assert isinstance(matcher.exact, tuple)
assert matcher.low[0] == '20'
assert matcher.high[0] == '50'
assert matcher.low[1] == 'GB'
assert matcher.high[1] == 'GB'
def test_parse_filter_max_high(self):
""" Testing high notation with :50G """
matcher = drive_selection.SizeMatcher('size', ':50G')
assert isinstance(matcher.exact, tuple)
assert matcher.high[0] == '50'
assert matcher.high[1] == 'GB'
def test_parse_filter_min_low(self):
""" Testing low notation with 20G: """
matcher = drive_selection.SizeMatcher('size', '50G:')
assert isinstance(matcher.exact, tuple)
assert matcher.low[0] == '50'
assert matcher.low[1] == 'GB'
def test_to_byte_GB(self):
""" Pretty nonesense test.."""
ret = drive_selection.SizeMatcher('size', '10G').to_byte(('10', 'GB'))
assert ret == 10 * 1e+9
def test_to_byte_MB(self):
""" Pretty nonesense test.."""
ret = drive_selection.SizeMatcher('size', '10M').to_byte(('10', 'MB'))
assert ret == 10 * 1e+6
def test_to_byte_TB(self):
""" Pretty nonesense test.."""
ret = drive_selection.SizeMatcher('size', '10T').to_byte(('10', 'TB'))
assert ret == 10 * 1e+12
def test_to_byte_PB(self):
""" Expect to raise """
with pytest.raises(ValueError):
drive_selection.SizeMatcher('size', '10P').to_byte(('10', 'PB'))
assert 'Unit \'P\' is not supported'
def test_compare_exact(self):
matcher = drive_selection.SizeMatcher('size', '20GB')
disk_dict = Device(path='/dev/vdb', sys_api=dict(size='20.00 GB'))
ret = matcher.compare(disk_dict)
assert ret is True
@pytest.mark.parametrize("test_input,expected", [
("1.00 GB", False),
("20.00 GB", True),
("50.00 GB", True),
("100.00 GB", True),
("101.00 GB", False),
("1101.00 GB", False),
])
def test_compare_high_low(self, test_input, expected):
matcher = drive_selection.SizeMatcher('size', '20GB:100GB')
disk_dict = Device(path='/dev/vdb', sys_api=dict(size=test_input))
ret = matcher.compare(disk_dict)
assert ret is expected
@pytest.mark.parametrize("test_input,expected", [
("1.00 GB", True),
("20.00 GB", True),
("50.00 GB", True),
("100.00 GB", False),
("101.00 GB", False),
("1101.00 GB", False),
])
def test_compare_high(self, test_input, expected):
matcher = drive_selection.SizeMatcher('size', ':50GB')
disk_dict = Device(path='/dev/vdb', sys_api=dict(size=test_input))
ret = matcher.compare(disk_dict)
assert ret is expected
@pytest.mark.parametrize("test_input,expected", [
("1.00 GB", False),
("20.00 GB", False),
("50.00 GB", True),
("100.00 GB", True),
("101.00 GB", True),
("1101.00 GB", True),
])
def test_compare_low(self, test_input, expected):
matcher = drive_selection.SizeMatcher('size', '50GB:')
disk_dict = Device(path='/dev/vdb', sys_api=dict(size=test_input))
ret = matcher.compare(disk_dict)
assert ret is expected
@pytest.mark.parametrize("test_input,expected", [
("1.00 GB", False),
("20.00 GB", False),
("50.00 GB", False),
("100.00 GB", False),
("101.00 GB", False),
("1101.00 GB", True),
("9.10 TB", True),
])
def test_compare_at_least_1TB(self, test_input, expected):
matcher = drive_selection.SizeMatcher('size', '1TB:')
disk_dict = Device(path='/dev/sdz', sys_api=dict(size=test_input))
ret = matcher.compare(disk_dict)
assert ret is expected
def test_compare_raise(self):
matcher = drive_selection.SizeMatcher('size', 'None')
disk_dict = Device(path='/dev/vdb', sys_api=dict(size='20.00 GB'))
with pytest.raises(Exception):
matcher.compare(disk_dict)
pytest.fail("Couldn't parse size")
@pytest.mark.parametrize("test_input,expected", [
("10G", ('10', 'GB')),
("20GB", ('20', 'GB')),
("10g", ('10', 'GB')),
("20gb", ('20', 'GB')),
])
def test_get_k_v(self, test_input, expected):
assert drive_selection.SizeMatcher('size', '10G')._get_k_v(test_input) == expected
@pytest.mark.parametrize("test_input,expected", [
("10G", ('GB')),
("10g", ('GB')),
("20GB", ('GB')),
("20gb", ('GB')),
("20TB", ('TB')),
("20tb", ('TB')),
("20T", ('TB')),
("20t", ('TB')),
("20MB", ('MB')),
("20mb", ('MB')),
("20M", ('MB')),
("20m", ('MB')),
])
def test_parse_suffix(self, test_input, expected):
assert drive_selection.SizeMatcher('size', '10G')._parse_suffix(test_input) == expected
@pytest.mark.parametrize("test_input,expected", [
("G", 'GB'),
("GB", 'GB'),
("TB", 'TB'),
("T", 'TB'),
("MB", 'MB'),
("M", 'MB'),
])
def test_normalize_suffix(self, test_input, expected):
assert drive_selection.SizeMatcher('10G', 'size')._normalize_suffix(test_input) == expected
def test_normalize_suffix_raises(self):
with pytest.raises(ValueError):
drive_selection.SizeMatcher('10P', 'size')._normalize_suffix("P")
pytest.fail("Unit 'P' not supported")
class TestDriveGroup(object):
@pytest.fixture(scope='class')
def test_fix(self, empty=None):
def make_sample_data(empty=empty,
data_limit=0,
wal_limit=0,
db_limit=0,
osds_per_device='',
disk_format='bluestore'):
raw_sample_bluestore = {
'service_type': 'osd',
'service_id': 'foo',
'placement': {'host_pattern': 'data*'},
'data_devices': {
'size': '30G:50G',
'model': '42-RGB',
'vendor': 'samsung',
'limit': data_limit
},
'wal_devices': {
'model': 'fast',
'limit': wal_limit
},
'db_devices': {
'size': ':20G',
'limit': db_limit
},
'db_slots': 5,
'wal_slots': 5,
'block_wal_size': '5G',
'block_db_size': '10G',
'objectstore': disk_format,
'osds_per_device': osds_per_device,
'encrypted': True,
}
raw_sample_filestore = {
'service_type': 'osd',
'service_id': 'foo',
'placement': {'host_pattern': 'data*'},
'objectstore': 'filestore',
'data_devices': {
'size': '30G:50G',
'model': 'foo',
'vendor': '1x',
'limit': data_limit
},
'journal_devices': {
'size': ':20G'
},
'journal_size': '5G',
'osds_per_device': osds_per_device,
'encrypted': True,
}
if disk_format == 'filestore':
raw_sample = raw_sample_filestore
else:
raw_sample = raw_sample_bluestore
if empty:
raw_sample = {
'service_type': 'osd',
'service_id': 'foo',
'placement': {'host_pattern': 'data*'},
'data_devices': {
'all': True
},
}
dgo = DriveGroupSpec.from_json(raw_sample)
if disk_format == 'filestore':
with pytest.raises(DriveGroupValidationError):
dgo.validate()
else:
dgo.validate()
return dgo
return make_sample_data
def test_encryption_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.encrypted is True
def test_encryption_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.encrypted is False
def test_db_slots_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.db_slots == 5
def test_db_slots_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.db_slots is None
def test_wal_slots_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.wal_slots == 5
def test_wal_slots_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.wal_slots is None
def test_block_wal_size_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.block_wal_size == '5G'
def test_block_wal_size_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.block_wal_size is None
def test_block_db_size_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.block_db_size == '10G'
def test_block_db_size_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.block_db_size is None
def test_data_devices_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.data_devices == DeviceSelection(
model='42-RGB',
size='30G:50G',
vendor='samsung',
limit=0,
)
def test_data_devices_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.db_devices is None
def test_db_devices_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.db_devices == DeviceSelection(
size=':20G',
limit=0,
)
def test_db_devices_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.db_devices is None
def test_wal_device_prop(self, test_fix):
test_fix = test_fix()
assert test_fix.wal_devices == DeviceSelection(
model='fast',
limit=0,
)
def test_journal_device_prop(self, test_fix):
test_fix = test_fix(disk_format='filestore')
assert test_fix.journal_devices == DeviceSelection(
size=':20G'
)
def test_wal_device_prop_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.wal_devices is None
def test_filestore_format_prop(self, test_fix):
test_fix = test_fix(disk_format='filestore')
assert test_fix.objectstore == 'filestore'
def test_bluestore_format_prop(self, test_fix):
test_fix = test_fix(disk_format='bluestore')
assert test_fix.objectstore == 'bluestore'
def test_default_format_prop(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.objectstore == 'bluestore'
def test_journal_size(self, test_fix):
test_fix = test_fix(disk_format='filestore')
assert test_fix.journal_size == '5G'
def test_osds_per_device(self, test_fix):
test_fix = test_fix(osds_per_device='3')
assert test_fix.osds_per_device == '3'
def test_osds_per_device_default(self, test_fix):
test_fix = test_fix()
assert test_fix.osds_per_device == ''
def test_journal_size_empty(self, test_fix):
test_fix = test_fix(empty=True)
assert test_fix.journal_size is None
@pytest.fixture
def inventory(self, available=True):
def make_sample_data(available=available,
data_devices=10,
wal_devices=0,
db_devices=2,
human_readable_size_data='50.00 GB',
human_readable_size_wal='20.00 GB',
size=5368709121,
human_readable_size_db='20.00 GB'):
factory = InventoryFactory()
inventory_sample = []
data_disks = factory.produce(
pieces=data_devices,
available=available,
size=size,
human_readable_size=human_readable_size_data)
wal_disks = factory.produce(
pieces=wal_devices,
human_readable_size=human_readable_size_wal,
rotational='0',
model='ssd_type_model',
size=size,
available=available)
db_disks = factory.produce(
pieces=db_devices,
human_readable_size=human_readable_size_db,
rotational='0',
size=size,
model='ssd_type_model',
available=available)
inventory_sample.extend(data_disks)
inventory_sample.extend(wal_disks)
inventory_sample.extend(db_disks)
return Devices(devices=inventory_sample)
return make_sample_data
class TestDriveSelection(object):
testdata = [
(
DriveGroupSpec(
placement=PlacementSpec(host_pattern='*'),
service_id='foobar',
data_devices=DeviceSelection(all=True)),
_mk_inventory(_mk_device() * 5),
['/dev/sda', '/dev/sdb', '/dev/sdc', '/dev/sdd', '/dev/sde'], []
),
(
DriveGroupSpec(
placement=PlacementSpec(host_pattern='*'),
service_id='foobar',
data_devices=DeviceSelection(all=True, limit=3),
db_devices=DeviceSelection(all=True)
),
_mk_inventory(_mk_device() * 5),
['/dev/sda', '/dev/sdb', '/dev/sdc'], ['/dev/sdd', '/dev/sde']
),
(
DriveGroupSpec(
placement=PlacementSpec(host_pattern='*'),
service_id='foobar',
data_devices=DeviceSelection(rotational=True),
db_devices=DeviceSelection(rotational=False)
),
_mk_inventory(_mk_device(rotational=False) + _mk_device(rotational=True)),
['/dev/sdb'], ['/dev/sda']
),
(
DriveGroupSpec(
placement=PlacementSpec(host_pattern='*'),
service_id='foobar',
data_devices=DeviceSelection(rotational=True),
db_devices=DeviceSelection(rotational=False)
),
_mk_inventory(_mk_device(rotational=True)*2 + _mk_device(rotational=False)),
['/dev/sda', '/dev/sdb'], ['/dev/sdc']
),
(
DriveGroupSpec(
placement=PlacementSpec(host_pattern='*'),
service_id='foobar',
data_devices=DeviceSelection(rotational=True),
db_devices=DeviceSelection(rotational=False)
),
_mk_inventory(_mk_device(rotational=True)*2),
['/dev/sda', '/dev/sdb'], []
),
]
@pytest.mark.parametrize("spec,inventory,expected_data,expected_db", testdata)
def test_disk_selection(self, spec, inventory, expected_data, expected_db):
sel = drive_selection.DriveSelection(spec, inventory)
assert [d.path for d in sel.data_devices()] == expected_data
assert [d.path for d in sel.db_devices()] == expected_db
OHA YOOOO