332 lines
13 KiB
Python
332 lines
13 KiB
Python
# Copyright 2016 Mirantis, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
"""Unit tests for the Storage helper module."""
|
|
|
|
import functools
|
|
from unittest import mock
|
|
|
|
import ddt
|
|
|
|
from manila import exception
|
|
from manila.share import configuration
|
|
from manila.share.drivers.container import storage_helper
|
|
from manila import test
|
|
from manila.tests import fake_share as base_fake_share
|
|
from manila.tests.share.drivers.container.fakes import fake_share
|
|
|
|
|
|
@ddt.ddt
|
|
class LVMHelperTestCase(test.TestCase):
|
|
"""Tests ContainerShareDriver"""
|
|
|
|
def setUp(self):
|
|
super(LVMHelperTestCase, self).setUp()
|
|
self.share = fake_share()
|
|
self.fake_conf = configuration.Configuration(None)
|
|
self.fake_conf.container_volume_mount_path = "/tmp/shares"
|
|
self.LVMHelper = storage_helper.LVMHelper(configuration=self.fake_conf)
|
|
self.context = mock.Mock()
|
|
|
|
def fake_exec_sync(self, *args, **kwargs):
|
|
kwargs['execute_arguments'].append(args)
|
|
try:
|
|
ret_val = kwargs['ret_val']
|
|
except KeyError:
|
|
ret_val = None
|
|
return ret_val
|
|
|
|
def test_lvmhelper_setup_explodes_in_gore_on_no_config_supplied(self):
|
|
self.assertRaises(exception.ManilaException,
|
|
storage_helper.LVMHelper,
|
|
None)
|
|
|
|
@ddt.data("62.50g 72.50g", " 72.50g 62.50g\n", " <62.50g <72.50g\n")
|
|
def test_get_share_server_pools(self, ret_vgs):
|
|
expected_result = [{'reserved_percentage': 0,
|
|
'pool_name': 'manila_docker_volumes',
|
|
'total_capacity_gb': 72.5,
|
|
'free_capacity_gb': 62.5}]
|
|
self.mock_object(self.LVMHelper, "_execute",
|
|
mock.Mock(return_value=(ret_vgs, 0)))
|
|
|
|
result = self.LVMHelper.get_share_server_pools()
|
|
|
|
self.assertEqual(expected_result, result)
|
|
|
|
def test__get_lv_device(self):
|
|
fake_share_name = 'fakeshareid'
|
|
self.assertEqual("/dev/manila_docker_volumes/%s" % fake_share_name,
|
|
self.LVMHelper._get_lv_device(fake_share_name))
|
|
|
|
def test__get_lv_folder(self):
|
|
fake_share_name = 'fakeshareid'
|
|
self.assertEqual("/tmp/shares/%s" % fake_share_name,
|
|
self.LVMHelper._get_lv_folder(fake_share_name))
|
|
|
|
def test_provide_storage(self):
|
|
actual_arguments = []
|
|
fake_share_name = 'fakeshareid'
|
|
expected_arguments = [
|
|
('lvcreate', '-p', 'rw', '-L', '1G', '-n', 'fakeshareid',
|
|
'manila_docker_volumes'),
|
|
('mkfs.ext4', '/dev/manila_docker_volumes/fakeshareid'),
|
|
]
|
|
self.LVMHelper._execute = functools.partial(
|
|
self.fake_exec_sync, execute_arguments=actual_arguments,
|
|
ret_val='')
|
|
|
|
self.LVMHelper.provide_storage(fake_share_name, 1)
|
|
|
|
self.assertEqual(expected_arguments, actual_arguments)
|
|
|
|
@ddt.data(None, exception.ProcessExecutionError)
|
|
def test__try_to_unmount_device(self, side_effect):
|
|
device = {}
|
|
mock_warning = self.mock_object(storage_helper.LOG, 'warning')
|
|
mock_execute = self.mock_object(self.LVMHelper, '_execute',
|
|
mock.Mock(side_effect=side_effect))
|
|
self.LVMHelper._try_to_unmount_device(device)
|
|
|
|
mock_execute.assert_called_once_with(
|
|
"umount", device, run_as_root=True
|
|
)
|
|
if side_effect is not None:
|
|
mock_warning.assert_called_once()
|
|
|
|
def test_remove_storage(self):
|
|
fake_share_name = 'fakeshareid'
|
|
fake_device = {}
|
|
|
|
mock_get_lv_device = self.mock_object(
|
|
self.LVMHelper, '_get_lv_device',
|
|
mock.Mock(return_value=fake_device))
|
|
mock_try_to_umount = self.mock_object(self.LVMHelper,
|
|
'_try_to_unmount_device')
|
|
mock_execute = self.mock_object(self.LVMHelper, '_execute')
|
|
|
|
self.LVMHelper.remove_storage(fake_share_name)
|
|
|
|
mock_get_lv_device.assert_called_once_with(
|
|
fake_share_name
|
|
)
|
|
mock_try_to_umount.assert_called_once_with(fake_device)
|
|
mock_execute.assert_called_once_with(
|
|
'lvremove', '-f', '--autobackup', 'n', fake_device,
|
|
run_as_root=True
|
|
)
|
|
|
|
def test_remove_storage_lvremove_failed(self):
|
|
fake_share_name = 'fakeshareid'
|
|
|
|
def fake_execute(*args, **kwargs):
|
|
if 'lvremove' in args:
|
|
raise exception.ProcessExecutionError()
|
|
|
|
self.mock_object(storage_helper.LOG, "warning")
|
|
self.mock_object(self.LVMHelper, "_execute", fake_execute)
|
|
|
|
self.LVMHelper.remove_storage(fake_share_name)
|
|
|
|
self.assertTrue(storage_helper.LOG.warning.called)
|
|
|
|
@ddt.data(None, exception.ProcessExecutionError)
|
|
def test_rename_storage(self, side_effect):
|
|
fake_old_share_name = 'fake_old_name'
|
|
fake_new_share_name = 'fake_new_name'
|
|
fake_new_device = "/dev/new_device"
|
|
fake_old_device = "/dev/old_device"
|
|
|
|
mock_get_lv_device = self.mock_object(
|
|
self.LVMHelper, '_get_lv_device',
|
|
mock.Mock(side_effect=[fake_old_device, fake_new_device]))
|
|
mock_try_to_umount = self.mock_object(self.LVMHelper,
|
|
'_try_to_unmount_device')
|
|
|
|
mock_execute = self.mock_object(self.LVMHelper, '_execute',
|
|
mock.Mock(side_effect=side_effect))
|
|
|
|
if side_effect is None:
|
|
self.LVMHelper.rename_storage(fake_old_share_name,
|
|
fake_new_share_name)
|
|
else:
|
|
self.assertRaises(exception.ProcessExecutionError,
|
|
self.LVMHelper.rename_storage,
|
|
fake_old_share_name, fake_new_share_name)
|
|
mock_try_to_umount.assert_called_once_with(fake_old_device)
|
|
mock_execute.mock_assert_called_once_with(
|
|
"lvrename", "--autobackup", "n", fake_old_device, fake_new_device,
|
|
run_as_root=True
|
|
)
|
|
mock_get_lv_device.assert_has_calls([
|
|
mock.call(fake_old_share_name),
|
|
mock.call(fake_new_share_name)
|
|
])
|
|
|
|
def test_extend_share(self):
|
|
actual_arguments = []
|
|
expected_arguments = [
|
|
('lvextend', '-L', 'shareG', '-n',
|
|
'/dev/manila_docker_volumes/fakeshareid'),
|
|
('e2fsck', '-f', '-y', '/dev/manila_docker_volumes/fakeshareid'),
|
|
('resize2fs', '/dev/manila_docker_volumes/fakeshareid'),
|
|
]
|
|
fake_share_name = 'fakeshareid'
|
|
self.LVMHelper._execute = functools.partial(
|
|
self.fake_exec_sync, execute_arguments=actual_arguments,
|
|
ret_val='')
|
|
|
|
self.LVMHelper.extend_share(fake_share_name, 'share', 3)
|
|
|
|
self.assertEqual(expected_arguments, actual_arguments)
|
|
|
|
def test_get_size(self):
|
|
share_name = 'fakeshareid'
|
|
fake_old_device = {}
|
|
|
|
mock_get_lv_device = self.mock_object(
|
|
self.LVMHelper, '_get_lv_device',
|
|
mock.Mock(return_value=fake_old_device))
|
|
mock_execute = self.mock_object(self.LVMHelper, '_execute',
|
|
mock.Mock(return_value=[1, "args"]))
|
|
|
|
result = self.LVMHelper.get_size(share_name)
|
|
|
|
mock_execute.assert_called_once_with(
|
|
"lvs", "-o", "lv_size", "--noheadings", "--nosuffix", "--units",
|
|
"g", fake_old_device, run_as_root=True
|
|
)
|
|
mock_get_lv_device.assert_called_once_with(share_name)
|
|
self.assertEqual(result, 1)
|
|
|
|
@ddt.data({'source_host': 'host@back1#vg1', 'dest_host': 'host@back2#vg2',
|
|
'compatible': False},
|
|
{'source_host': 'host@back1#vg1', 'dest_host': 'host@back2#vg1',
|
|
'compatible': True},
|
|
{'source_host': 'host@back1#vg1', 'dest_host': 'host@back1#vg1',
|
|
'compatible': True})
|
|
@ddt.unpack
|
|
def test_migration_check_compatibility(
|
|
self, source_host, dest_host, compatible):
|
|
mock_exception_log = self.mock_object(storage_helper.LOG, 'exception')
|
|
|
|
source_share = base_fake_share.fake_share_instance(host=source_host)
|
|
dest_share = base_fake_share.fake_share_instance(host=dest_host)
|
|
|
|
migration_compatibility = self.LVMHelper.migration_check_compatibility(
|
|
self.context, source_share, dest_share, share_server=None,
|
|
destination_share_server=None)
|
|
|
|
expected_compatibility = {
|
|
'compatible': compatible,
|
|
'writable': True,
|
|
'nondisruptive': False,
|
|
'preserve_metadata': True,
|
|
'preserve_snapshots': False,
|
|
}
|
|
self.assertDictEqual(expected_compatibility, migration_compatibility)
|
|
if not compatible:
|
|
mock_exception_log.assert_called_once()
|
|
|
|
def test_migration_continue(self):
|
|
end1Phase = self.LVMHelper.migration_continue(
|
|
self.context, None, None, None, None, share_server=None,
|
|
destination_share_server=None)
|
|
self.assertTrue(end1Phase)
|
|
|
|
def test_migration_get_progress(self):
|
|
progress = self.LVMHelper.migration_get_progress(
|
|
self.context, None, None, None, None, share_server=None,
|
|
destination_share_server=None)
|
|
expected_progress = {
|
|
'total_progress': 100,
|
|
}
|
|
self.assertDictEqual(expected_progress, progress)
|
|
|
|
@ddt.data({'source_host': 'host@back1', 'dest_host': 'host@back1',
|
|
'shares_specs': {}},
|
|
{'source_host': 'host@back1', 'dest_host': 'host@back2#vg1',
|
|
'shares_specs': {'shares_req_spec': [
|
|
{'share_instance_properties': {'host': 'host@back1#vg2'}}
|
|
]}})
|
|
@ddt.unpack
|
|
def test_share_server_migration_check_compatibility_false(
|
|
self, source_host, dest_host, shares_specs):
|
|
not_compatible = {
|
|
'compatible': False,
|
|
'writable': None,
|
|
'nondisruptive': None,
|
|
'preserve_snapshots': None,
|
|
'migration_cancel': None,
|
|
'migration_get_progress': None
|
|
}
|
|
mock_error_log = self.mock_object(storage_helper.LOG, 'error')
|
|
|
|
source_server = {'id': 'fake_id', 'host': source_host}
|
|
migration_compatibility = (
|
|
self.LVMHelper.share_server_migration_check_compatibility(
|
|
self.context, source_server, dest_host, None, None,
|
|
shares_specs))
|
|
|
|
self.assertDictEqual(not_compatible, migration_compatibility)
|
|
mock_error_log.assert_called_once()
|
|
|
|
@ddt.data({'source_host': 'host@back1', 'dest_host': 'host@back2#vg1',
|
|
'shares_specs': {'shares_req_spec': [
|
|
{'share_instance_properties': {'host': 'host@back1#vg1'}}
|
|
]}},
|
|
{'source_host': 'host@back1', 'dest_host': 'host@back2',
|
|
'shares_specs': {'shares_req_spec': [
|
|
{'share_instance_properties': {'host': 'host@back1#vg1'}}
|
|
]}})
|
|
@ddt.unpack
|
|
def test_share_server_migration_check_compatibility_true(
|
|
self, source_host, dest_host, shares_specs):
|
|
compatible = {
|
|
'compatible': True,
|
|
'writable': True,
|
|
'nondisruptive': False,
|
|
'preserve_snapshots': False,
|
|
'migration_cancel': True,
|
|
'migration_get_progress': True
|
|
}
|
|
|
|
source_server = {'id': 'fake_id', 'host': source_host}
|
|
migration_compatibility = (
|
|
self.LVMHelper.share_server_migration_check_compatibility(
|
|
self.context, source_server, dest_host, None, None,
|
|
shares_specs))
|
|
|
|
self.assertDictEqual(compatible, migration_compatibility)
|
|
|
|
def test_share_server_migration_continue(self):
|
|
end1Phase = self.LVMHelper.share_server_migration_continue(
|
|
self.context, None, None, None, None)
|
|
self.assertTrue(end1Phase)
|
|
|
|
def test_share_server_migration_get_progess(self):
|
|
progress = self.LVMHelper.share_server_migration_get_progress(
|
|
self.context, None, None, None, None)
|
|
expected_progress = {
|
|
'total_progress': 100,
|
|
}
|
|
self.assertDictEqual(expected_progress, progress)
|
|
|
|
def test_get_share_pool_name(self):
|
|
fake_vg_name = 'fake_vg'
|
|
self.LVMHelper.configuration.container_volume_group = fake_vg_name
|
|
|
|
vg_name = self.LVMHelper.get_share_pool_name('fake_share_id')
|
|
self.assertEqual(vg_name, fake_vg_name)
|