Files
trove/trove/tests/unittests/guestagent/test_redis_manager.py
T
Petr Malik c45eb67018 Unittests patch 'CONF.datastore_manager'
Unittests do not have 'CONF.datastore_manager' set (None).

As the result all datastore manager/app tests that access
configuration by the manager name get the default 'mysql' values.
Apart from not testing the production configuration this
also makes it difficult to test dynamically looked up
datastore-specific properties which do not exist in the mysql
group at all.

This patch set adds a helper method for patching any given
configuration property and also adds a simple interface for
patching the manager name to the base TestCase.

All existing manager/app tests were updated to properly patch the manager
property.
The base test patches the manager name to 'mysql' so that
all unittests run with this manager unless explicitly overriden.

It's now safe to remove the manager parameter from the
'cfg.get_configuration_property()' function. It was there
to work around this issue in unittests.

Change-Id: I903a0fb1ede8ad6614d2b5a8fc1a256f74412496
2016-05-27 21:15:35 +00:00

329 lines
14 KiB
Python

# Copyright 2012 OpenStack Foundation
#
# 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.
from mock import DEFAULT, MagicMock, patch
from trove.guestagent import backup
from trove.guestagent.common import configuration
from trove.guestagent.common.configuration import ImportOverrideStrategy
from trove.guestagent.common import operating_system
from trove.guestagent.datastore.experimental.redis import (
service as redis_service)
from trove.guestagent.datastore.experimental.redis.manager import (
Manager as RedisManager)
from trove.guestagent.volume import VolumeDevice
from trove.tests.unittests.guestagent.test_datastore_manager import \
DatastoreManagerTest
class RedisGuestAgentManagerTest(DatastoreManagerTest):
@patch.object(redis_service.RedisApp, '_build_admin_client')
@patch.object(ImportOverrideStrategy, '_initialize_import_directory')
def setUp(self, *args, **kwargs):
super(RedisGuestAgentManagerTest, self).setUp('redis')
self.patch_ope = patch('os.path.expanduser')
self.mock_ope = self.patch_ope.start()
self.addCleanup(self.patch_ope.stop)
self.replication_strategy = 'RedisSyncReplication'
self.patch_rs = patch(
'trove.guestagent.strategies.replication.get_strategy',
return_value=self.replication_strategy)
self.mock_rs = self.patch_rs.start()
self.addCleanup(self.patch_rs.stop)
self.manager = RedisManager()
self.packages = 'redis-server'
self.origin_RedisAppStatus = redis_service.RedisAppStatus
self.origin_start_redis = redis_service.RedisApp.start_db
self.origin_stop_redis = redis_service.RedisApp.stop_db
self.origin_install_redis = redis_service.RedisApp._install_redis
self.origin_install_if_needed = \
redis_service.RedisApp.install_if_needed
self.origin_format = VolumeDevice.format
self.origin_mount = VolumeDevice.mount
self.origin_mount_points = VolumeDevice.mount_points
self.origin_restore = backup.restore
self.patch_repl = patch(
'trove.guestagent.strategies.replication.get_instance')
self.mock_repl = self.patch_repl.start()
self.addCleanup(self.patch_repl.stop)
self.patch_gfvs = patch(
'trove.guestagent.dbaas.get_filesystem_volume_stats')
self.mock_gfvs_class = self.patch_gfvs.start()
self.addCleanup(self.patch_gfvs.stop)
def tearDown(self):
super(RedisGuestAgentManagerTest, self).tearDown()
redis_service.RedisAppStatus = self.origin_RedisAppStatus
redis_service.RedisApp.stop_db = self.origin_stop_redis
redis_service.RedisApp.start_db = self.origin_start_redis
redis_service.RedisApp._install_redis = self.origin_install_redis
redis_service.RedisApp.install_if_needed = \
self.origin_install_if_needed
VolumeDevice.format = self.origin_format
VolumeDevice.mount = self.origin_mount
VolumeDevice.mount_points = self.origin_mount_points
backup.restore = self.origin_restore
def test_update_status(self):
mock_status = MagicMock()
self.manager._app.status = mock_status
self.manager.update_status(self.context)
mock_status.update.assert_any_call()
def test_prepare_redis_not_installed(self):
self._prepare_dynamic(is_redis_installed=False)
def test_prepare_redis_with_snapshot(self):
snapshot = {'replication_strategy': self.replication_strategy,
'dataset': {'dataset_size': 1.0},
'config': None}
self._prepare_dynamic(snapshot=snapshot)
@patch.object(redis_service.RedisApp, 'get_working_dir',
MagicMock(return_value='/var/lib/redis'))
def test_prepare_redis_from_backup(self):
self._prepare_dynamic(backup_id='backup_id_123abc')
@patch.multiple(redis_service.RedisApp,
apply_initial_guestagent_configuration=DEFAULT,
restart=DEFAULT,
install_if_needed=DEFAULT)
@patch.object(operating_system, 'chown')
@patch.object(configuration.ConfigurationManager, 'save_configuration')
def _prepare_dynamic(self, save_configuration_mock, chown_mock,
apply_initial_guestagent_configuration, restart,
install_if_needed,
device_path='/dev/vdb', is_redis_installed=True,
backup_info=None, is_root_enabled=False,
mount_point='var/lib/redis', backup_id=None,
snapshot=None):
backup_info = None
if backup_id is not None:
backup_info = {'id': backup_id,
'location': 'fake-location',
'type': 'RedisBackup',
'checksum': 'fake-checksum',
}
# covering all outcomes is starting to cause trouble here
mock_status = MagicMock()
self.manager._app.status = mock_status
self.manager._build_admin_client = MagicMock(return_value=MagicMock())
redis_service.RedisApp.stop_db = MagicMock(return_value=None)
redis_service.RedisApp.start_db = MagicMock(return_value=None)
mock_status.begin_install = MagicMock(return_value=None)
VolumeDevice.format = MagicMock(return_value=None)
VolumeDevice.mount = MagicMock(return_value=None)
VolumeDevice.mount_points = MagicMock(return_value=[])
backup.restore = MagicMock(return_value=None)
mock_replication = MagicMock()
mock_replication.enable_as_slave = MagicMock()
self.mock_repl.return_value = mock_replication
self.manager.prepare(self.context, self.packages,
None, '2048',
None, device_path=device_path,
mount_point=mount_point,
backup_info=backup_info,
overrides=None,
cluster_config=None,
snapshot=snapshot)
mock_status.begin_install.assert_any_call()
VolumeDevice.format.assert_any_call()
install_if_needed.assert_any_call(self.packages)
save_configuration_mock.assert_any_call(None)
apply_initial_guestagent_configuration.assert_called_once_with()
chown_mock.assert_any_call(mount_point, 'redis', 'redis', as_root=True)
if backup_info:
backup.restore.assert_called_once_with(self.context,
backup_info,
'/var/lib/redis')
else:
redis_service.RedisApp.restart.assert_any_call()
if snapshot:
self.assertEqual(1, mock_replication.enable_as_slave.call_count)
else:
self.assertEqual(0, mock_replication.enable_as_slave.call_count)
@patch.object(redis_service.RedisApp, 'restart')
def test_restart(self, redis_mock):
self.manager.restart(self.context)
redis_mock.assert_any_call()
@patch.object(redis_service.RedisApp, 'stop_db')
def test_stop_db(self, redis_mock):
self.manager.stop_db(self.context)
redis_mock.assert_any_call(do_not_start_on_reboot=False)
@patch.object(ImportOverrideStrategy, '_initialize_import_directory')
@patch.object(backup, 'backup')
@patch.object(configuration.ConfigurationManager, 'parse_configuration',
MagicMock(return_value={'dir': '/var/lib/redis',
'dbfilename': 'dump.rdb'}))
@patch.object(operating_system, 'chown')
@patch.object(operating_system, 'create_directory')
def test_create_backup(self, *mocks):
backup.backup = MagicMock(return_value=None)
RedisManager().create_backup(self.context, 'backup_id_123')
backup.backup.assert_any_call(self.context, 'backup_id_123')
def test_backup_required_for_replication(self):
mock_replication = MagicMock()
mock_replication.backup_required_for_replication = MagicMock()
self.mock_repl.return_value = mock_replication
self.manager.backup_required_for_replication(self.context)
self.assertEqual(
1, mock_replication.backup_required_for_replication.call_count)
def test_attach_replica(self):
mock_replication = MagicMock()
mock_replication.enable_as_slave = MagicMock()
self.mock_repl.return_value = mock_replication
snapshot = {'replication_strategy': self.replication_strategy,
'dataset': {'dataset_size': 1.0}}
self.manager.attach_replica(self.context, snapshot, None)
self.assertEqual(1, mock_replication.enable_as_slave.call_count)
def test_detach_replica(self):
mock_replication = MagicMock()
mock_replication.detach_slave = MagicMock()
self.mock_repl.return_value = mock_replication
self.manager.detach_replica(self.context)
self.assertEqual(1, mock_replication.detach_slave.call_count)
def test_enable_as_master(self):
mock_replication = MagicMock()
mock_replication.enable_as_master = MagicMock()
self.mock_repl.return_value = mock_replication
self.manager.enable_as_master(self.context, None)
self.assertEqual(mock_replication.enable_as_master.call_count, 1)
def test_demote_replication_master(self):
mock_replication = MagicMock()
mock_replication.demote_master = MagicMock()
self.mock_repl.return_value = mock_replication
self.manager.demote_replication_master(self.context)
self.assertEqual(1, mock_replication.demote_master.call_count)
@patch.object(redis_service.RedisApp, 'make_read_only')
def test_make_read_only(self, redis_mock):
self.manager.make_read_only(self.context, 'ON')
redis_mock.assert_any_call('ON')
def test_cleanup_source_on_replica_detach(self):
mock_replication = MagicMock()
mock_replication.cleanup_source_on_replica_detach = MagicMock()
self.mock_repl.return_value = mock_replication
snapshot = {'replication_strategy': self.replication_strategy,
'dataset': {'dataset_size': '1.0'}}
self.manager.cleanup_source_on_replica_detach(self.context, snapshot)
self.assertEqual(
1, mock_replication.cleanup_source_on_replica_detach.call_count)
def test_get_replication_snapshot(self):
snapshot_id = None
log_position = None
master_ref = 'my_master'
used_size = 1.0
total_size = 2.0
mock_replication = MagicMock()
mock_replication.enable_as_master = MagicMock()
mock_replication.snapshot_for_replication = MagicMock(
return_value=(snapshot_id, log_position))
mock_replication.get_master_ref = MagicMock(
return_value=master_ref)
self.mock_repl.return_value = mock_replication
self.mock_gfvs_class.return_value = (
{'used': used_size, 'total': total_size})
expected_replication_snapshot = {
'dataset': {
'datastore_manager': self.manager.manager,
'dataset_size': used_size,
'volume_size': total_size,
'snapshot_id': snapshot_id
},
'replication_strategy': self.replication_strategy,
'master': master_ref,
'log_position': log_position
}
snapshot_info = None
replica_source_config = None
replication_snapshot = (
self.manager.get_replication_snapshot(self.context, snapshot_info,
replica_source_config))
self.assertEqual(expected_replication_snapshot, replication_snapshot)
self.assertEqual(1, mock_replication.enable_as_master.call_count)
self.assertEqual(
1, mock_replication.snapshot_for_replication.call_count)
self.assertEqual(1, mock_replication.get_master_ref.call_count)
def test_get_replica_context(self):
master_ref = {
'host': '1.2.3.4',
'port': 3306
}
expected_info = {
'master': master_ref,
}
mock_replication = MagicMock()
mock_replication.get_replica_context = MagicMock(
return_value=expected_info)
self.mock_repl.return_value = mock_replication
replica_info = self.manager.get_replica_context(self.context)
self.assertEqual(1, mock_replication.get_replica_context.call_count)
self.assertEqual(expected_info, replica_info)
def test_get_last_txn(self):
expected_host = '10.0.0.2'
self.manager._get_master_host = MagicMock(return_value=expected_host)
expected_txn_id = 199
repl_info = {'role': 'master', 'master_repl_offset': expected_txn_id}
self.manager._get_repl_info = MagicMock(return_value=repl_info)
(host, txn_id) = self.manager.get_last_txn(self.context)
self.manager._get_master_host.assert_any_call()
self.manager._get_repl_info.assert_any_call()
self.assertEqual(expected_host, host)
self.assertEqual(expected_txn_id, txn_id)
def test_get_latest_txn_id(self):
expected_txn_id = 199
repl_info = {'role': 'master', 'master_repl_offset': expected_txn_id}
self.manager._get_repl_info = MagicMock(return_value=repl_info)
latest_txn_id = self.manager.get_latest_txn_id(self.context)
self.assertEqual(expected_txn_id, latest_txn_id)
self.manager._get_repl_info.assert_any_call()
def test_wait_for_txn(self):
expected_txn_id = 199
repl_info = {'role': 'master', 'master_repl_offset': expected_txn_id}
self.manager._get_repl_info = MagicMock(return_value=repl_info)
self.manager.wait_for_txn(self.context, expected_txn_id)
self.manager._get_repl_info.assert_any_call()