summaryrefslogtreecommitdiffstats
path: root/src/ceph-volume/ceph_volume/tests/devices/lvm/test_migrate.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ceph-volume/ceph_volume/tests/devices/lvm/test_migrate.py2299
1 files changed, 2299 insertions, 0 deletions
diff --git a/src/ceph-volume/ceph_volume/tests/devices/lvm/test_migrate.py b/src/ceph-volume/ceph_volume/tests/devices/lvm/test_migrate.py
new file mode 100644
index 000000000..4c86d0ca1
--- /dev/null
+++ b/src/ceph-volume/ceph_volume/tests/devices/lvm/test_migrate.py
@@ -0,0 +1,2299 @@
+import pytest
+from mock.mock import patch
+from ceph_volume import process
+from ceph_volume.api import lvm as api
+from ceph_volume.devices.lvm import migrate
+from ceph_volume.util.device import Device
+from ceph_volume.util import system
+
+class TestGetClusterName(object):
+
+ mock_volumes = []
+ def mock_get_lvs(self, *args, **kwargs):
+ return self.mock_volumes.pop(0)
+
+ def test_cluster_found(self, monkeypatch):
+ tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data,ceph.osd_fsid=1234,ceph.cluster_name=name_of_the_cluster'
+ vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='',
+ lv_path='/dev/VolGroup/lv1', lv_tags=tags)
+ self.mock_volumes = []
+ self.mock_volumes.append([vol])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+ monkeypatch.setattr(process, 'call', lambda x, **kw: ('', '', 0))
+
+ result = migrate.get_cluster_name(osd_id='0', osd_fsid='1234')
+ assert "name_of_the_cluster" == result
+
+ def test_cluster_not_found(self, monkeypatch, capsys):
+ self.mock_volumes = []
+ self.mock_volumes.append([])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+ monkeypatch.setattr(process, 'call', lambda x, **kw: ('', '', 0))
+
+ with pytest.raises(SystemExit) as error:
+ migrate.get_cluster_name(osd_id='0', osd_fsid='1234')
+ stdout, stderr = capsys.readouterr()
+ expected = 'Unexpected error, terminating'
+ assert expected in str(error.value)
+ expected = 'Unable to find any LV for source OSD: id:0 fsid:1234'
+ assert expected in stderr
+
+class TestFindAssociatedDevices(object):
+
+ mock_volumes = []
+ def mock_get_lvs(self, *args, **kwargs):
+ return self.mock_volumes.pop(0)
+
+ mock_single_volumes = {}
+ def mock_get_single_lv(self, *args, **kwargs):
+ p = kwargs['filters']['lv_path']
+ return self.mock_single_volumes[p]
+
+ def test_lv_is_matched_id(self, monkeypatch):
+ tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data,ceph.osd_fsid=1234'
+ vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='',
+ lv_path='/dev/VolGroup/lv1', lv_tags=tags)
+ self.mock_volumes = []
+ self.mock_volumes.append([vol])
+ self.mock_volumes.append([vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([])
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': vol}
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+ monkeypatch.setattr(process, 'call', lambda x, **kw: ('', '', 0))
+
+ result = migrate.find_associated_devices(osd_id='0', osd_fsid='1234')
+ assert len(result) == 1
+ assert result[0][0].path == '/dev/VolGroup/lv1'
+ assert result[0][0].lvs == [vol]
+ assert result[0][1] == 'block'
+
+ def test_lv_is_matched_id2(self, monkeypatch):
+ tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data,ceph.osd_fsid=1234'
+ vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=tags)
+ tags2 = 'ceph.osd_id=0,ceph.journal_uuid=xx,ceph.type=wal,ceph.osd_fsid=1234'
+ vol2 = api.Volume(lv_name='volume2', lv_uuid='z', vg_name='vg',
+ lv_path='/dev/VolGroup/lv2', lv_tags=tags2)
+ self.mock_volumes = []
+ self.mock_volumes.append([vol])
+ self.mock_volumes.append([vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([vol2])
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': vol, '/dev/VolGroup/lv2': vol2}
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+ monkeypatch.setattr(process, 'call', lambda x, **kw: ('', '', 0))
+
+ result = migrate.find_associated_devices(osd_id='0', osd_fsid='1234')
+ assert len(result) == 2
+ for d in result:
+ if d[1] == 'block':
+ assert d[0].path == '/dev/VolGroup/lv1'
+ assert d[0].lvs == [vol]
+ elif d[1] == 'wal':
+ assert d[0].path == '/dev/VolGroup/lv2'
+ assert d[0].lvs == [vol2]
+ else:
+ assert False
+
+ def test_lv_is_matched_id3(self, monkeypatch):
+ tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data,ceph.osd_fsid=1234'
+ vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=tags)
+ tags2 = 'ceph.osd_id=0,ceph.journal_uuid=xx,ceph.type=wal,ceph.osd_fsid=1234'
+ vol2 = api.Volume(lv_name='volume2', lv_uuid='z', vg_name='vg',
+ lv_path='/dev/VolGroup/lv2', lv_tags=tags2)
+ tags3 = 'ceph.osd_id=0,ceph.journal_uuid=xx,ceph.type=db,ceph.osd_fsid=1234'
+ vol3 = api.Volume(lv_name='volume3', lv_uuid='z', vg_name='vg',
+ lv_path='/dev/VolGroup/lv3', lv_tags=tags3)
+
+ self.mock_volumes = []
+ self.mock_volumes.append([vol])
+ self.mock_volumes.append([vol])
+ self.mock_volumes.append([vol3])
+ self.mock_volumes.append([vol2])
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': vol,
+ '/dev/VolGroup/lv2': vol2,
+ '/dev/VolGroup/lv3': vol3}
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+ monkeypatch.setattr(process, 'call', lambda x, **kw: ('', '', 0))
+
+ result = migrate.find_associated_devices(osd_id='0', osd_fsid='1234')
+ assert len(result) == 3
+ for d in result:
+ if d[1] == 'block':
+ assert d[0].path == '/dev/VolGroup/lv1'
+ assert d[0].lvs == [vol]
+ elif d[1] == 'wal':
+ assert d[0].path == '/dev/VolGroup/lv2'
+ assert d[0].lvs == [vol2]
+ elif d[1] == 'db':
+ assert d[0].path == '/dev/VolGroup/lv3'
+ assert d[0].lvs == [vol3]
+ else:
+ assert False
+
+ def test_lv_is_not_matched(self, monkeypatch, capsys):
+ self.mock_volumes = [None]
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+ monkeypatch.setattr(process, 'call', lambda x, **kw: ('', '', 0))
+
+ with pytest.raises(SystemExit) as error:
+ migrate.find_associated_devices(osd_id='1', osd_fsid='1234')
+ stdout, stderr = capsys.readouterr()
+ expected = 'Unexpected error, terminating'
+ assert expected in str(error.value)
+ expected = 'Unable to find any LV for source OSD: id:1 fsid:1234'
+ assert expected in stderr
+
+class TestVolumeTagTracker(object):
+ mock_single_volumes = {}
+ def mock_get_single_lv(self, *args, **kwargs):
+ p = kwargs['filters']['lv_path']
+ return self.mock_single_volumes[p]
+
+ mock_process_input = []
+ def mock_process(self, *args, **kwargs):
+ self.mock_process_input.append(args[0]);
+ return ('', '', 0)
+
+ def test_init(self, monkeypatch):
+ source_tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data,ceph.osd_fsid=1234'
+ source_db_tags = 'ceph.osd_id=0,journal_uuid=x,ceph.type=db, osd_fsid=1234'
+ source_wal_tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=wal'
+ target_tags="ceph.a=1,ceph.b=2,c=3,ceph.d=4" # 'c' to be bypassed
+ devices=[]
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv2', lv_tags=source_db_tags)
+ wal_vol = api.Volume(lv_name='volume3', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv3', lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol}
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ data_device = Device(path = '/dev/VolGroup/lv1')
+ db_device = Device(path = '/dev/VolGroup/lv2')
+ wal_device = Device(path = '/dev/VolGroup/lv3')
+ devices.append([data_device, 'block'])
+ devices.append([db_device, 'db'])
+ devices.append([wal_device, 'wal'])
+
+ target = api.Volume(lv_name='target_name', lv_tags=target_tags,
+ lv_path='/dev/VolGroup/lv_target')
+ t = migrate.VolumeTagTracker(devices, target);
+
+ assert 3 == len(t.old_target_tags)
+
+ assert data_device == t.data_device
+ assert 4 == len(t.old_data_tags)
+ assert 'data' == t.old_data_tags['ceph.type']
+
+ assert db_device == t.db_device
+ assert 2 == len(t.old_db_tags)
+ assert 'db' == t.old_db_tags['ceph.type']
+
+ assert wal_device == t.wal_device
+ assert 3 == len(t.old_wal_tags)
+ assert 'wal' == t.old_wal_tags['ceph.type']
+
+ def test_update_tags_when_lv_create(self, monkeypatch):
+ source_tags = \
+ 'ceph.osd_id=0,ceph.journal_uuid=x,' \
+ 'ceph.type=data,ceph.osd_fsid=1234'
+ source_db_tags = \
+ 'ceph.osd_id=0,journal_uuid=x,ceph.type=db,' \
+ 'osd_fsid=1234'
+
+ devices=[]
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv2', lv_tags=source_db_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ data_device = Device(path = '/dev/VolGroup/lv1')
+ db_device = Device(path = '/dev/VolGroup/lv2')
+ devices.append([data_device, 'block'])
+ devices.append([db_device, 'db'])
+
+ target = api.Volume(lv_name='target_name', lv_tags='',
+ lv_uuid='wal_uuid',
+ lv_path='/dev/VolGroup/lv_target')
+ t = migrate.VolumeTagTracker(devices, target);
+
+ self.mock_process_input = []
+ t.update_tags_when_lv_create('wal')
+
+ assert 3 == len(self.mock_process_input)
+
+ assert ['lvchange',
+ '--addtag', 'ceph.wal_uuid=wal_uuid',
+ '--addtag', 'ceph.wal_device=/dev/VolGroup/lv_target',
+ '/dev/VolGroup/lv1'] == self.mock_process_input[0]
+
+ assert self.mock_process_input[1].sort() == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=0',
+ '--addtag', 'ceph.journal_uuid=x',
+ '--addtag', 'ceph.type=wal',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.wal_uuid=wal_uuid',
+ '--addtag', 'ceph.wal_device=/dev/VolGroup/lv_target',
+ '/dev/VolGroup/lv_target'].sort()
+
+ assert ['lvchange',
+ '--addtag', 'ceph.wal_uuid=wal_uuid',
+ '--addtag', 'ceph.wal_device=/dev/VolGroup/lv_target',
+ '/dev/VolGroup/lv2'] == self.mock_process_input[2]
+
+ def test_remove_lvs(self, monkeypatch):
+ source_tags = \
+ 'ceph.osd_id=0,ceph.journal_uuid=x,' \
+ 'ceph.type=data,ceph.osd_fsid=1234,ceph.wal_uuid=aaaaa'
+ source_db_tags = \
+ 'ceph.osd_id=0,journal_uuid=x,ceph.type=db,' \
+ 'osd_fsid=1234,ceph.wal_device=aaaaa'
+ source_wal_tags = \
+ 'ceph.wal_uuid=uuid,ceph.wal_device=device,' \
+ 'ceph.osd_id=0,ceph.type=wal'
+
+ devices=[]
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv2', lv_tags=source_db_tags)
+ wal_vol = api.Volume(lv_name='volume3', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv3', lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ data_device = Device(path = '/dev/VolGroup/lv1')
+ db_device = Device(path = '/dev/VolGroup/lv2')
+ wal_device = Device(path = '/dev/VolGroup/lv3')
+ devices.append([data_device, 'block'])
+ devices.append([db_device, 'db'])
+ devices.append([wal_device, 'wal'])
+
+ target = api.Volume(lv_name='target_name', lv_tags='',
+ lv_path='/dev/VolGroup/lv_target')
+ t = migrate.VolumeTagTracker(devices, target);
+
+ device_to_remove = devices.copy()
+
+ self.mock_process_input = []
+ t.remove_lvs(device_to_remove, 'db')
+
+ assert 3 == len(self.mock_process_input)
+ assert ['lvchange',
+ '--deltag', 'ceph.wal_uuid=uuid',
+ '--deltag', 'ceph.wal_device=device',
+ '--deltag', 'ceph.osd_id=0',
+ '--deltag', 'ceph.type=wal',
+ '/dev/VolGroup/lv3'] == self.mock_process_input[0]
+ assert ['lvchange',
+ '--deltag', 'ceph.wal_uuid=aaaaa',
+ '/dev/VolGroup/lv1'] == self.mock_process_input[1]
+ assert ['lvchange',
+ '--deltag', 'ceph.wal_device=aaaaa',
+ '/dev/VolGroup/lv2'] == self.mock_process_input[2]
+
+ def test_replace_lvs(self, monkeypatch):
+ source_tags = \
+ 'ceph.osd_id=0,ceph.type=data,ceph.osd_fsid=1234,'\
+ 'ceph.wal_uuid=wal_uuid,ceph.db_device=/dbdevice'
+ source_db_tags = \
+ 'ceph.osd_id=0,ceph.type=db,ceph.osd_fsid=1234'
+ source_wal_tags = \
+ 'ceph.wal_uuid=uuid,ceph.wal_device=device,' \
+ 'ceph.osd_id=0,ceph.type=wal'
+
+ devices=[]
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='datauuid', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2', lv_uuid='dbuuid', vg_name='vg',
+ lv_path='/dev/VolGroup/lv2', lv_tags=source_db_tags)
+ wal_vol = api.Volume(lv_name='volume3', lv_uuid='waluuid', vg_name='vg',
+ lv_path='/dev/VolGroup/lv3', lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ data_device = Device(path = '/dev/VolGroup/lv1')
+ db_device = Device(path = '/dev/VolGroup/lv2')
+ wal_device = Device(path = '/dev/VolGroup/lv3')
+ devices.append([data_device, 'block'])
+ devices.append([db_device, 'db'])
+ devices.append([wal_device, 'wal'])
+
+ target = api.Volume(lv_name='target_name',
+ lv_uuid='ttt',
+ lv_tags='ceph.tag_to_remove=aaa',
+ lv_path='/dev/VolGroup/lv_target')
+ t = migrate.VolumeTagTracker(devices, target);
+
+ self.mock_process_input = []
+ t.replace_lvs(devices, 'db')
+
+ assert 5 == len(self.mock_process_input)
+
+ assert ['lvchange',
+ '--deltag', 'ceph.osd_id=0',
+ '--deltag', 'ceph.type=db',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '/dev/VolGroup/lv2'] == self.mock_process_input[0]
+ assert ['lvchange',
+ '--deltag', 'ceph.wal_uuid=uuid',
+ '--deltag', 'ceph.wal_device=device',
+ '--deltag', 'ceph.osd_id=0',
+ '--deltag', 'ceph.type=wal',
+ '/dev/VolGroup/lv3'] == self.mock_process_input[1]
+ assert ['lvchange',
+ '--deltag', 'ceph.db_device=/dbdevice',
+ '--deltag', 'ceph.wal_uuid=wal_uuid',
+ '/dev/VolGroup/lv1'] == self.mock_process_input[2]
+
+ assert ['lvchange',
+ '--addtag', 'ceph.db_uuid=ttt',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv_target',
+ '/dev/VolGroup/lv1'] == self.mock_process_input[3]
+
+ assert self.mock_process_input[4].sort() == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=0',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.type=db',
+ '--addtag', 'ceph.db_uuid=ttt',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv_target',
+ '/dev/VolGroup/lv_target'].sort()
+
+ def test_undo(self, monkeypatch):
+ source_tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data,ceph.osd_fsid=1234'
+ source_db_tags = 'ceph.osd_id=0,journal_uuid=x,ceph.type=db, osd_fsid=1234'
+ source_wal_tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=wal'
+ target_tags=""
+ devices=[]
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv2', lv_tags=source_db_tags)
+ wal_vol = api.Volume(lv_name='volume3', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/lv3', lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ data_device = Device(path = '/dev/VolGroup/lv1')
+ db_device = Device(path = '/dev/VolGroup/lv2')
+ wal_device = Device(path = '/dev/VolGroup/lv3')
+ devices.append([data_device, 'block'])
+ devices.append([db_device, 'db'])
+ devices.append([wal_device, 'wal'])
+
+ target = api.Volume(lv_name='target_name', lv_tags=target_tags,
+ lv_path='/dev/VolGroup/lv_target')
+ t = migrate.VolumeTagTracker(devices, target);
+
+ target.tags['ceph.a'] = 'aa';
+ target.tags['ceph.b'] = 'bb';
+
+ data_vol.tags['ceph.journal_uuid'] = 'z';
+
+ db_vol.tags.pop('ceph.type')
+
+ wal_vol.tags.clear()
+
+ assert 2 == len(target.tags)
+ assert 4 == len(data_vol.tags)
+ assert 1 == len(db_vol.tags)
+
+ self.mock_process_input = []
+ t.undo()
+
+ assert 0 == len(target.tags)
+ assert 4 == len(data_vol.tags)
+ assert 'x' == data_vol.tags['ceph.journal_uuid']
+
+ assert 2 == len(db_vol.tags)
+ assert 'db' == db_vol.tags['ceph.type']
+
+ assert 3 == len(wal_vol.tags)
+ assert 'wal' == wal_vol.tags['ceph.type']
+
+ assert 6 == len(self.mock_process_input)
+ assert 'lvchange' in self.mock_process_input[0]
+ assert '--deltag' in self.mock_process_input[0]
+ assert 'ceph.journal_uuid=z' in self.mock_process_input[0]
+ assert '/dev/VolGroup/lv1' in self.mock_process_input[0]
+
+ assert 'lvchange' in self.mock_process_input[1]
+ assert '--addtag' in self.mock_process_input[1]
+ assert 'ceph.journal_uuid=x' in self.mock_process_input[1]
+ assert '/dev/VolGroup/lv1' in self.mock_process_input[1]
+
+ assert 'lvchange' in self.mock_process_input[2]
+ assert '--deltag' in self.mock_process_input[2]
+ assert 'ceph.osd_id=0' in self.mock_process_input[2]
+ assert '/dev/VolGroup/lv2' in self.mock_process_input[2]
+
+ assert 'lvchange' in self.mock_process_input[3]
+ assert '--addtag' in self.mock_process_input[3]
+ assert 'ceph.type=db' in self.mock_process_input[3]
+ assert '/dev/VolGroup/lv2' in self.mock_process_input[3]
+
+ assert 'lvchange' in self.mock_process_input[4]
+ assert '--addtag' in self.mock_process_input[4]
+ assert 'ceph.type=wal' in self.mock_process_input[4]
+ assert '/dev/VolGroup/lv3' in self.mock_process_input[4]
+
+ assert 'lvchange' in self.mock_process_input[5]
+ assert '--deltag' in self.mock_process_input[5]
+ assert 'ceph.a=aa' in self.mock_process_input[5]
+ assert 'ceph.b=bb' in self.mock_process_input[5]
+ assert '/dev/VolGroup/lv_target' in self.mock_process_input[5]
+
+class TestNew(object):
+
+ mock_volume = None
+ def mock_get_lv_by_fullname(self, *args, **kwargs):
+ return self.mock_volume
+
+ mock_process_input = []
+ def mock_process(self, *args, **kwargs):
+ self.mock_process_input.append(args[0]);
+ return ('', '', 0)
+
+ mock_single_volumes = {}
+ def mock_get_single_lv(self, *args, **kwargs):
+ p = kwargs['filters']['lv_path']
+ return self.mock_single_volumes[p]
+
+ mock_volumes = []
+ def mock_get_lvs(self, *args, **kwargs):
+ return self.mock_volumes.pop(0)
+
+ def test_newdb_non_root(self):
+ with pytest.raises(Exception) as error:
+ migrate.NewDB(argv=[
+ '--osd-id', '1',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_db']).main()
+ expected = 'This command needs to be executed with sudo or as root'
+ assert expected in str(error.value)
+
+ @patch('os.getuid')
+ def test_newdb_not_target_lvm(self, m_getuid, capsys):
+ m_getuid.return_value = 0
+ with pytest.raises(SystemExit) as error:
+ migrate.NewDB(argv=[
+ '--osd-id', '1',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_db']).main()
+ stdout, stderr = capsys.readouterr()
+ expected = 'Unable to attach new volume : vgname/new_db'
+ assert expected in str(error.value)
+ expected = 'Target path vgname/new_db is not a Logical Volume'
+ assert expected in stderr
+
+
+ @patch('os.getuid')
+ def test_newdb_already_in_use(self, m_getuid, monkeypatch, capsys):
+ m_getuid.return_value = 0
+
+ self.mock_volume = api.Volume(lv_name='volume1',
+ lv_uuid='y',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags='ceph.osd_id=5') # this results in set used_by_ceph
+ monkeypatch.setattr(api, 'get_lv_by_fullname', self.mock_get_lv_by_fullname)
+
+ with pytest.raises(SystemExit) as error:
+ migrate.NewDB(argv=[
+ '--osd-id', '1',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_db']).main()
+ stdout, stderr = capsys.readouterr()
+ expected = 'Unable to attach new volume : vgname/new_db'
+ assert expected in str(error.value)
+ expected = 'Target Logical Volume is already used by ceph: vgname/new_db'
+ assert expected in stderr
+
+ @patch('os.getuid')
+ def test_newdb(self, m_getuid, monkeypatch, capsys):
+ m_getuid.return_value = 0
+
+ source_tags = \
+ 'ceph.osd_id=0,ceph.type=data,ceph.osd_fsid=1234,'\
+ 'ceph.wal_uuid=wal_uuid,ceph.db_device=/dbdevice'
+ source_wal_tags = \
+ 'ceph.wal_uuid=uuid,ceph.wal_device=device,' \
+ 'ceph.osd_id=0,ceph.type=wal'
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv3': wal_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ self.mock_volume = api.Volume(lv_name='target_volume1', lv_uuid='y',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/target_volume',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ #find_associated_devices will call get_lvs() 4 times
+ # and it this needs results to be arranged that way
+ self.mock_volumes = []
+ self.mock_volumes.append([data_vol, wal_vol])
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([wal_vol])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph_cluster')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+
+ migrate.NewDB(argv=[
+ '--osd-id', '1',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_db']).main()
+
+ n = len(self.mock_process_input)
+ assert n >= 5
+
+ assert self.mock_process_input[n - 5] == [
+ 'lvchange',
+ '--deltag', 'ceph.db_device=/dbdevice',
+ '/dev/VolGroup/lv1']
+ assert self.mock_process_input[n - 4] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=y',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/lv1']
+
+ assert self.mock_process_input[n - 3].sort() == [
+ 'lvchange',
+ '--addtag', 'ceph.wal_uuid=uuid',
+ '--addtag', 'ceph.osd_id=0',
+ '--addtag', 'ceph.type=db',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.db_uuid=y',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/target_volume'].sort()
+
+ assert self.mock_process_input[n - 2] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=y',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/lv3']
+
+ assert self.mock_process_input[n - 1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph_cluster-1',
+ '--dev-target', '/dev/VolGroup/target_volume',
+ '--command', 'bluefs-bdev-new-db']
+
+ def test_newdb_active_systemd(self, is_root, monkeypatch, capsys):
+ source_tags = \
+ 'ceph.osd_id=0,ceph.type=data,ceph.osd_fsid=1234,'\
+ 'ceph.wal_uuid=wal_uuid,ceph.db_device=/dbdevice'
+ source_wal_tags = \
+ 'ceph.wal_uuid=uuid,ceph.wal_device=device,' \
+ 'ceph.osd_id=0,ceph.type=wal'
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv3': wal_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ self.mock_volume = api.Volume(lv_name='target_volume1', lv_uuid='y',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/target_volume',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: True)
+
+ #find_associated_devices will call get_lvs() 4 times
+ # and it this needs results to be arranged that way
+ self.mock_volumes = []
+ self.mock_volumes.append([data_vol, wal_vol])
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([wal_vol])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph_cluster')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+
+ m = migrate.NewDB(argv=[
+ '--osd-id', '1',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_db'])
+
+ with pytest.raises(SystemExit) as error:
+ m.main()
+
+ stdout, stderr = capsys.readouterr()
+
+ assert 'Unable to attach new volume for OSD: 1' == str(error.value)
+ assert '--> OSD ID is running, stop it with: systemctl stop ceph-osd@1' == stderr.rstrip()
+ assert not stdout
+
+ def test_newdb_no_systemd(self, is_root, monkeypatch):
+ source_tags = \
+ 'ceph.osd_id=0,ceph.type=data,ceph.osd_fsid=1234,'\
+ 'ceph.wal_uuid=wal_uuid,ceph.db_device=/dbdevice'
+ source_wal_tags = \
+ 'ceph.wal_uuid=uuid,ceph.wal_device=device,' \
+ 'ceph.osd_id=0,ceph.type=wal'
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv3': wal_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ self.mock_volume = api.Volume(lv_name='target_volume1', lv_uuid='y',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/target_volume',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ #find_associated_devices will call get_lvs() 4 times
+ # and it this needs results to be arranged that way
+ self.mock_volumes = []
+ self.mock_volumes.append([data_vol, wal_vol])
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([wal_vol])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph_cluster')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+
+ migrate.NewDB(argv=[
+ '--osd-id', '1',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_db',
+ '--no-systemd']).main()
+
+ n = len(self.mock_process_input)
+ assert n >= 5
+
+ assert self.mock_process_input[n - 5] == [
+ 'lvchange',
+ '--deltag', 'ceph.db_device=/dbdevice',
+ '/dev/VolGroup/lv1']
+ assert self.mock_process_input[n - 4] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=y',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/lv1']
+
+ assert self.mock_process_input[n - 3].sort() == [
+ 'lvchange',
+ '--addtag', 'ceph.wal_uuid=uuid',
+ '--addtag', 'ceph.osd_id=0',
+ '--addtag', 'ceph.type=db',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.db_uuid=y',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/target_volume'].sort()
+
+ assert self.mock_process_input[n - 2] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=y',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/lv3']
+
+ assert self.mock_process_input[n - 1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph_cluster-1',
+ '--dev-target', '/dev/VolGroup/target_volume',
+ '--command', 'bluefs-bdev-new-db']
+
+ @patch('os.getuid')
+ def test_newwal(self, m_getuid, monkeypatch, capsys):
+ m_getuid.return_value = 0
+
+ source_tags = \
+ 'ceph.osd_id=0,ceph.type=data,ceph.osd_fsid=1234'
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='datauuid', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ self.mock_volume = api.Volume(lv_name='target_volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/target_volume',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname', self.mock_get_lv_by_fullname)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active", lambda id: False)
+
+ #find_associated_devices will call get_lvs() 4 times
+ # and it this needs results to be arranged that way
+ self.mock_volumes = []
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name', lambda osd_id, osd_fsid: 'cluster')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+
+ migrate.NewWAL(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_wal']).main()
+
+ n = len(self.mock_process_input)
+ assert n >= 3
+
+ assert self.mock_process_input[n - 3] == [
+ 'lvchange',
+ '--addtag', 'ceph.wal_uuid=y',
+ '--addtag', 'ceph.wal_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/lv1']
+
+ assert self.mock_process_input[n - 2].sort() == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=0',
+ '--addtag', 'ceph.type=wal',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.wal_uuid=y',
+ '--addtag', 'ceph.wal_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/target_volume'].sort()
+
+ assert self.mock_process_input[n - 1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/cluster-2',
+ '--dev-target', '/dev/VolGroup/target_volume',
+ '--command', 'bluefs-bdev-new-wal']
+
+ def test_newwal_active_systemd(self, is_root, monkeypatch, capsys):
+ source_tags = \
+ 'ceph.osd_id=0,ceph.type=data,ceph.osd_fsid=1234'
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='datauuid', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ self.mock_volume = api.Volume(lv_name='target_volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/target_volume',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname', self.mock_get_lv_by_fullname)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active", lambda id: True)
+
+ #find_associated_devices will call get_lvs() 4 times
+ # and it this needs results to be arranged that way
+ self.mock_volumes = []
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name', lambda osd_id, osd_fsid: 'cluster')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+
+ m = migrate.NewWAL(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_wal'])
+
+ with pytest.raises(SystemExit) as error:
+ m.main()
+
+ stdout, stderr = capsys.readouterr()
+
+ assert 'Unable to attach new volume for OSD: 2' == str(error.value)
+ assert '--> OSD ID is running, stop it with: systemctl stop ceph-osd@2' == stderr.rstrip()
+ assert not stdout
+
+ def test_newwal_no_systemd(self, is_root, monkeypatch):
+ source_tags = \
+ 'ceph.osd_id=0,ceph.type=data,ceph.osd_fsid=1234'
+
+ data_vol = api.Volume(lv_name='volume1', lv_uuid='datauuid', vg_name='vg',
+ lv_path='/dev/VolGroup/lv1', lv_tags=source_tags)
+
+ self.mock_single_volumes = {'/dev/VolGroup/lv1': data_vol}
+
+ monkeypatch.setattr(migrate.api, 'get_single_lv', self.mock_get_single_lv)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ self.mock_volume = api.Volume(lv_name='target_volume1', lv_uuid='y', vg_name='vg',
+ lv_path='/dev/VolGroup/target_volume',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname', self.mock_get_lv_by_fullname)
+
+ #find_associated_devices will call get_lvs() 4 times
+ # and it this needs results to be arranged that way
+ self.mock_volumes = []
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([data_vol])
+ self.mock_volumes.append([])
+ self.mock_volumes.append([])
+
+ monkeypatch.setattr(migrate.api, 'get_lvs', self.mock_get_lvs)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name', lambda osd_id, osd_fsid: 'cluster')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+
+ migrate.NewWAL(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--target', 'vgname/new_wal',
+ '--no-systemd']).main()
+
+ n = len(self.mock_process_input)
+ assert n >= 3
+
+ assert self.mock_process_input[n - 3] == [
+ 'lvchange',
+ '--addtag', 'ceph.wal_uuid=y',
+ '--addtag', 'ceph.wal_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/lv1']
+
+ assert self.mock_process_input[n - 2].sort() == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=0',
+ '--addtag', 'ceph.type=wal',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.wal_uuid=y',
+ '--addtag', 'ceph.wal_device=/dev/VolGroup/target_volume',
+ '/dev/VolGroup/target_volume'].sort()
+
+ assert self.mock_process_input[n - 1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/cluster-2',
+ '--dev-target', '/dev/VolGroup/target_volume',
+ '--command', 'bluefs-bdev-new-wal']
+
+class TestMigrate(object):
+
+ def test_invalid_osd_id_passed(self, is_root):
+ with pytest.raises(SystemExit):
+ migrate.Migrate(argv=['--osd-fsid', '123', '--from', 'data', '--target', 'foo', '--osd-id', 'foo']).main()
+
+ mock_volume = None
+ def mock_get_lv_by_fullname(self, *args, **kwargs):
+ return self.mock_volume
+
+ mock_process_input = []
+ def mock_process(self, *args, **kwargs):
+ self.mock_process_input.append(args[0])
+ return ('', '', 0)
+
+ mock_single_volumes = {}
+ def mock_get_single_lv(self, *args, **kwargs):
+ p = kwargs['filters']['lv_path']
+ return self.mock_single_volumes[p]
+
+ mock_volumes = []
+ def mock_get_lvs(self, *args, **kwargs):
+ return self.mock_volumes.pop(0)
+
+ def test_get_source_devices(self, monkeypatch):
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = api.Volume(lv_name='volume2', lv_uuid='y',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags='ceph.osd_id=5,ceph.osd_type=db')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+
+ argv = [
+ '--osd-id', '2',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--from', 'data', 'wal',
+ '--target', 'vgname/new_wal'
+ ]
+ m = migrate.Migrate(argv=argv)
+ m.args = m.make_parser('ceph-volume lvm migation', 'help').parse_args(argv)
+ res_devices = m.get_source_devices(devices)
+
+ assert 2 == len(res_devices)
+ assert devices[0] == res_devices[0]
+ assert devices[2] == res_devices[1]
+
+ argv = [
+ '--osd-id', '2',
+ '--osd-fsid', '55BD4219-16A7-4037-BC20-0F158EFCC83D',
+ '--from', 'db', 'wal', 'data',
+ '--target', 'vgname/new_wal'
+ ]
+ m = migrate.Migrate(argv=argv)
+ m.args = m.make_parser('ceph-volume lvm migation', 'help').parse_args(argv)
+ res_devices = m.get_source_devices(devices)
+
+ assert 3 == len(res_devices)
+ assert devices[0] == res_devices[0]
+ assert devices[1] == res_devices[1]
+ assert devices[2] == res_devices[2]
+
+
+ def test_migrate_without_args(self, capsys):
+ help_msg = """
+Moves BlueFS data from source volume(s) to the target one, source
+volumes (except the main (i.e. data or block) one) are removed on
+success. LVM volumes are permitted for Target only, both already
+attached or new logical one. In the latter case it is attached to OSD
+replacing one of the source devices. Following replacement rules apply
+(in the order of precedence, stop on the first match):
+* if source list has DB volume - target device replaces it.
+* if source list has WAL volume - target device replace it.
+* if source list has slow volume only - operation is not permitted,
+ requires explicit allocation via new-db/new-wal command.
+
+Example calls for supported scenarios:
+
+ Moves BlueFS data from main device to LV already attached as DB:
+
+ ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data --target vgname/db
+
+ Moves BlueFS data from shared main device to LV which will be attached
+ as a new DB:
+
+ ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data --target vgname/new_db
+
+ Moves BlueFS data from DB device to new LV, DB is replaced:
+
+ ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from db --target vgname/new_db
+
+ Moves BlueFS data from main and DB devices to new LV, DB is replaced:
+
+ ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data db --target vgname/new_db
+
+ Moves BlueFS data from main, DB and WAL devices to new LV, WAL is
+ removed and DB is replaced:
+
+ ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data db wal --target vgname/new_db
+
+ Moves BlueFS data from main, DB and WAL devices to main device, WAL
+ and DB are removed:
+
+ ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from db wal --target vgname/data
+
+"""
+ m = migrate.Migrate(argv=[])
+ m.main()
+ stdout, stderr = capsys.readouterr()
+ assert help_msg in stdout
+ assert not stderr
+
+
+ @patch('os.getuid')
+ def test_migrate_data_db_to_new_db(self, m_getuid, monkeypatch):
+ m_getuid.return_value = 0
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = api.Volume(lv_name='volume2_new', lv_uuid='new-db-uuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2_new',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'data', 'db', 'wal',
+ '--target', 'vgname/new_wal'])
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 5
+
+ assert self. mock_process_input[n-5] == [
+ 'lvchange',
+ '--deltag', 'ceph.osd_id=2',
+ '--deltag', 'ceph.type=db',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '--deltag', 'ceph.cluster_name=ceph',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv2']
+
+ assert self. mock_process_input[n-4] == [
+ 'lvchange',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-3] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-2] == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=2',
+ '--addtag', 'ceph.type=db',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.cluster_name=ceph',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv2_new']
+
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/dev/VolGroup/lv2_new',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block.db']
+
+ def test_migrate_data_db_to_new_db_active_systemd(self, is_root, monkeypatch, capsys):
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = api.Volume(lv_name='volume2_new', lv_uuid='new-db-uuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2_new',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: True)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'data', 'db', 'wal',
+ '--target', 'vgname/new_wal'])
+
+ with pytest.raises(SystemExit) as error:
+ m.main()
+
+ stdout, stderr = capsys.readouterr()
+
+ assert 'Unable to migrate devices associated with OSD ID: 2' == str(error.value)
+ assert '--> OSD is running, stop it with: systemctl stop ceph-osd@2' == stderr.rstrip()
+ assert not stdout
+
+ def test_migrate_data_db_to_new_db_no_systemd(self, is_root, monkeypatch):
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = api.Volume(lv_name='volume2_new', lv_uuid='new-db-uuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2_new',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'data', 'db', 'wal',
+ '--target', 'vgname/new_wal',
+ '--no-systemd'])
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 5
+
+ assert self. mock_process_input[n-5] == [
+ 'lvchange',
+ '--deltag', 'ceph.osd_id=2',
+ '--deltag', 'ceph.type=db',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '--deltag', 'ceph.cluster_name=ceph',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv2']
+
+ assert self. mock_process_input[n-4] == [
+ 'lvchange',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-3] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-2] == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=2',
+ '--addtag', 'ceph.type=db',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.cluster_name=ceph',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv2_new']
+
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/dev/VolGroup/lv2_new',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block.db']
+
+ @patch('os.getuid')
+ def test_migrate_data_db_to_new_db_skip_wal(self, m_getuid, monkeypatch):
+ m_getuid.return_value = 0
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = api.Volume(lv_name='volume2_new', lv_uuid='new-db-uuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2_new',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'data', 'db',
+ '--target', 'vgname/new_wal'])
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 7
+
+ assert self. mock_process_input[n-7] == [
+ 'lvchange',
+ '--deltag', 'ceph.osd_id=2',
+ '--deltag', 'ceph.type=db',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '--deltag', 'ceph.cluster_name=ceph',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv2']
+
+ assert self. mock_process_input[n-6] == [
+ 'lvchange',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-5] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-4] == [
+ 'lvchange',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv3']
+
+ assert self. mock_process_input[n-3] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv3']
+
+ assert self. mock_process_input[n-2] == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=2',
+ '--addtag', 'ceph.type=db',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.cluster_name=ceph',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv2_new']
+
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/dev/VolGroup/lv2_new',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block.db']
+
+ @patch('os.getuid')
+ def test_migrate_data_db_wal_to_new_db(self, m_getuid, monkeypatch):
+ m_getuid.return_value = 0
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_wal_tags = 'ceph.osd_id=0,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = api.Volume(lv_name='volume2_new', lv_uuid='new-db-uuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2_new',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'data', 'db', 'wal',
+ '--target', 'vgname/new_wal'])
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 6
+
+ assert self. mock_process_input[n-6] == [
+ 'lvchange',
+ '--deltag', 'ceph.osd_id=2',
+ '--deltag', 'ceph.type=db',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '--deltag', 'ceph.cluster_name=ceph',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '/dev/VolGroup/lv2']
+
+ assert self. mock_process_input[n-5] == [
+ 'lvchange',
+ '--deltag', 'ceph.osd_id=0',
+ '--deltag', 'ceph.type=wal',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '--deltag', 'ceph.cluster_name=ceph',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv3']
+
+ assert self. mock_process_input[n-4] == [
+ 'lvchange',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-3] == [
+ 'lvchange',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv1']
+
+ assert self. mock_process_input[n-2] == [
+ 'lvchange',
+ '--addtag', 'ceph.osd_id=2',
+ '--addtag', 'ceph.type=db',
+ '--addtag', 'ceph.osd_fsid=1234',
+ '--addtag', 'ceph.cluster_name=ceph',
+ '--addtag', 'ceph.db_uuid=new-db-uuid',
+ '--addtag', 'ceph.db_device=/dev/VolGroup/lv2_new',
+ '/dev/VolGroup/lv2_new']
+
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/dev/VolGroup/lv2_new',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block.db',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block.wal']
+
+ @patch('os.getuid')
+ def test_dont_migrate_data_db_wal_to_new_data(self,
+ m_getuid,
+ monkeypatch,
+ capsys):
+ m_getuid.return_value = 0
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = api.Volume(lv_name='volume2_new', lv_uuid='new-db-uuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2_new',
+ lv_tags='')
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'data',
+ '--target', 'vgname/new_data'])
+
+ with pytest.raises(SystemExit) as error:
+ m.main()
+ stdout, stderr = capsys.readouterr()
+ expected = 'Unable to migrate to : vgname/new_data'
+ assert expected in str(error.value)
+ expected = 'Unable to determine new volume type,'
+ ' please use new-db or new-wal command before.'
+ assert expected in stderr
+
+ @patch('os.getuid')
+ def test_dont_migrate_db_to_wal(self,
+ m_getuid,
+ monkeypatch,
+ capsys):
+ m_getuid.return_value = 0
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = wal_vol
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'db',
+ '--target', 'vgname/wal'])
+
+ with pytest.raises(SystemExit) as error:
+ m.main()
+ stdout, stderr = capsys.readouterr()
+ expected = 'Unable to migrate to : vgname/wal'
+ assert expected in str(error.value)
+ expected = 'Migrate to WAL is not supported'
+ assert expected in stderr
+
+ @patch('os.getuid')
+ def test_migrate_data_db_to_db(self,
+ m_getuid,
+ monkeypatch,
+ capsys):
+ m_getuid.return_value = 0
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = db_vol
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'db', 'data',
+ '--target', 'vgname/db'])
+
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 1
+ for s in self.mock_process_input:
+ print(s)
+
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/var/lib/ceph/osd/ceph-2/block.db',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block']
+
+ def test_migrate_data_db_to_db_active_systemd(self, is_root, monkeypatch, capsys):
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = db_vol
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: True)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'db', 'data',
+ '--target', 'vgname/db'])
+
+ with pytest.raises(SystemExit) as error:
+ m.main()
+
+ stdout, stderr = capsys.readouterr()
+
+ assert 'Unable to migrate devices associated with OSD ID: 2' == str(error.value)
+ assert '--> OSD is running, stop it with: systemctl stop ceph-osd@2' == stderr.rstrip()
+ assert not stdout
+
+ def test_migrate_data_db_to_db_no_systemd(self, is_root, monkeypatch):
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = db_vol
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'db', 'data',
+ '--target', 'vgname/db',
+ '--no-systemd'])
+
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 1
+ for s in self.mock_process_input:
+ print(s)
+
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/var/lib/ceph/osd/ceph-2/block.db',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block']
+
+ @patch('os.getuid')
+ def test_migrate_data_wal_to_db(self,
+ m_getuid,
+ monkeypatch,
+ capsys):
+ m_getuid.return_value = 0
+
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = db_vol
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: False)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'db', 'data', 'wal',
+ '--target', 'vgname/db'])
+
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 1
+ for s in self.mock_process_input:
+ print(s)
+
+ assert self. mock_process_input[n-4] == [
+ 'lvchange',
+ '--deltag', 'ceph.osd_id=2',
+ '--deltag', 'ceph.type=wal',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '--deltag', 'ceph.cluster_name=ceph',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv3']
+ assert self. mock_process_input[n-3] == [
+ 'lvchange',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv1']
+ assert self. mock_process_input[n-2] == [
+ 'lvchange',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv2']
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/var/lib/ceph/osd/ceph-2/block.db',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block.wal']
+
+ def test_migrate_data_wal_to_db_active_systemd(self, is_root, monkeypatch, capsys):
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = db_vol
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr("ceph_volume.systemd.systemctl.osd_is_active",
+ lambda id: True)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'db', 'data', 'wal',
+ '--target', 'vgname/db'])
+
+ with pytest.raises(SystemExit) as error:
+ m.main()
+
+ stdout, stderr = capsys.readouterr()
+
+ assert 'Unable to migrate devices associated with OSD ID: 2' == str(error.value)
+ assert '--> OSD is running, stop it with: systemctl stop ceph-osd@2' == stderr.rstrip()
+ assert not stdout
+
+ def test_migrate_data_wal_to_db_no_systemd(self, is_root, monkeypatch):
+ source_tags = 'ceph.osd_id=2,ceph.type=data,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_db_tags = 'ceph.osd_id=2,ceph.type=db,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+ source_wal_tags = 'ceph.osd_id=2,ceph.type=wal,ceph.osd_fsid=1234,' \
+ 'ceph.cluster_name=ceph,ceph.db_uuid=dbuuid,ceph.db_device=db_dev,' \
+ 'ceph.wal_uuid=waluuid,ceph.wal_device=wal_dev'
+
+ data_vol = api.Volume(lv_name='volume1',
+ lv_uuid='datauuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv1',
+ lv_tags=source_tags)
+ db_vol = api.Volume(lv_name='volume2',
+ lv_uuid='dbuuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv2',
+ lv_tags=source_db_tags)
+
+ wal_vol = api.Volume(lv_name='volume3',
+ lv_uuid='waluuid',
+ vg_name='vg',
+ lv_path='/dev/VolGroup/lv3',
+ lv_tags=source_wal_tags)
+
+ self.mock_single_volumes = {
+ '/dev/VolGroup/lv1': data_vol,
+ '/dev/VolGroup/lv2': db_vol,
+ '/dev/VolGroup/lv3': wal_vol,
+ }
+ monkeypatch.setattr(migrate.api, 'get_single_lv',
+ self.mock_get_single_lv)
+
+ self.mock_volume = db_vol
+ monkeypatch.setattr(api, 'get_lv_by_fullname',
+ self.mock_get_lv_by_fullname)
+
+ self.mock_process_input = []
+ monkeypatch.setattr(process, 'call', self.mock_process)
+
+ devices = []
+ devices.append([Device('/dev/VolGroup/lv1'), 'block'])
+ devices.append([Device('/dev/VolGroup/lv2'), 'db'])
+ devices.append([Device('/dev/VolGroup/lv3'), 'wal'])
+
+ monkeypatch.setattr(migrate, 'find_associated_devices',
+ lambda osd_id, osd_fsid: devices)
+
+ monkeypatch.setattr(migrate, 'get_cluster_name',
+ lambda osd_id, osd_fsid: 'ceph')
+ monkeypatch.setattr(system, 'chown', lambda path: 0)
+ m = migrate.Migrate(argv=[
+ '--osd-id', '2',
+ '--osd-fsid', '1234',
+ '--from', 'db', 'data', 'wal',
+ '--target', 'vgname/db',
+ '--no-systemd'])
+
+ m.main()
+
+ n = len(self.mock_process_input)
+ assert n >= 1
+ for s in self.mock_process_input:
+ print(s)
+
+ assert self. mock_process_input[n-4] == [
+ 'lvchange',
+ '--deltag', 'ceph.osd_id=2',
+ '--deltag', 'ceph.type=wal',
+ '--deltag', 'ceph.osd_fsid=1234',
+ '--deltag', 'ceph.cluster_name=ceph',
+ '--deltag', 'ceph.db_uuid=dbuuid',
+ '--deltag', 'ceph.db_device=db_dev',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv3']
+ assert self. mock_process_input[n-3] == [
+ 'lvchange',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv1']
+ assert self. mock_process_input[n-2] == [
+ 'lvchange',
+ '--deltag', 'ceph.wal_uuid=waluuid',
+ '--deltag', 'ceph.wal_device=wal_dev',
+ '/dev/VolGroup/lv2']
+ assert self. mock_process_input[n-1] == [
+ 'ceph-bluestore-tool',
+ '--path', '/var/lib/ceph/osd/ceph-2',
+ '--dev-target', '/var/lib/ceph/osd/ceph-2/block.db',
+ '--command', 'bluefs-bdev-migrate',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block',
+ '--devs-source', '/var/lib/ceph/osd/ceph-2/block.wal']