Merge "Fix apply configuration on prepare"

This commit is contained in:
Jenkins 2016-01-28 01:24:13 +00:00 committed by Gerrit Code Review
commit 654eb0f96e
6 changed files with 176 additions and 15 deletions

View File

@ -260,6 +260,10 @@ class Manager(periodic_task.PeriodicTasks):
users, device_path, mount_point, backup_info,
config_contents, root_password, overrides,
cluster_config, snapshot)
if overrides:
LOG.info(_("Applying user-specified configuration "
"(called from 'prepare')."))
self.apply_overrides_on_prepare(context, overrides)
except Exception as ex:
self.prepare_error = True
LOG.exception(_("An error occurred preparing datastore: %s") %
@ -307,6 +311,10 @@ class Manager(periodic_task.PeriodicTasks):
ex.message)
raise
def apply_overrides_on_prepare(self, context, overrides):
self.update_overrides(context, overrides)
self.restart(context)
@abc.abstractmethod
def do_prepare(self, context, packages, databases, memory_mb, users,
device_path, mount_point, backup_info, config_contents,
@ -336,6 +344,14 @@ class Manager(periodic_task.PeriodicTasks):
LOG.info(_('No post_prepare work has been defined.'))
pass
#################
# Service related
#################
@abc.abstractmethod
def restart(self, context):
"""Restart the database service."""
pass
#####################
# File System related
#####################

View File

@ -222,7 +222,7 @@ class MySqlManager(manager.Manager):
self._perform_restore(backup_info, context,
mount_point + "/data", app)
LOG.debug("Securing MySQL now.")
app.secure(config_contents, overrides)
app.secure(config_contents)
enable_root_on_restore = (backup_info and
self.mysql_admin().is_root_enabled())
if root_password and not backup_info:

View File

@ -656,7 +656,7 @@ class BaseMySqlApp(object):
LOG.info(_("Finished installing MySQL server."))
self.start_mysql()
def secure(self, config_contents, overrides):
def secure(self, config_contents):
LOG.info(_("Generating admin password."))
admin_password = utils.generate_random_password()
clear_expired_password()
@ -669,7 +669,6 @@ class BaseMySqlApp(object):
self.stop_db()
self._reset_configuration(config_contents, admin_password)
self._apply_user_overrides(overrides)
self.start_mysql()
LOG.debug("MySQL secure complete.")

View File

@ -1358,7 +1358,7 @@ class MySqlAppTest(trove_testtools.TestCase):
@patch.object(utils, 'generate_random_password',
return_value='some_password')
@patch.object(dbaas_base, 'clear_expired_password')
def test_secure(self, auth_pwd_mock, clear_pwd_mock):
def test_secure(self, clear_pwd_mock, auth_pwd_mock):
self.mySqlApp.start_mysql = Mock()
self.mySqlApp.stop_db = Mock()
@ -1370,16 +1370,12 @@ class MySqlAppTest(trove_testtools.TestCase):
with patch.object(BaseDbStatus, 'prepare_completed') as patch_pc:
patch_pc.__get__ = Mock(return_value=True)
self.mySqlApp.secure('contents', 'overrides')
self.mySqlApp.secure('contents')
self.assertTrue(self.mySqlApp.stop_db.called)
reset_config_calls = [call('contents', auth_pwd_mock.return_value),
call('contents', auth_pwd_mock.return_value)]
self.mySqlApp._reset_configuration.has_calls(reset_config_calls)
self.mySqlApp._reset_configuration.assert_has_calls(
[call('contents', auth_pwd_mock.return_value)])
apply_overrides_calls = [call('overrides'),
call('overrides')]
self.mySqlApp._reset_configuration.has_calls(apply_overrides_calls)
self.assertTrue(self.mySqlApp.start_mysql.called)
self.assert_reported_status(rd_instance.ServiceStatuses.NEW)
@ -1470,7 +1466,7 @@ class MySqlAppTest(trove_testtools.TestCase):
self.mysql_starts_successfully()
sqlalchemy.create_engine = Mock()
self.assertRaises(IOError, self.mySqlApp.secure, "foo", None)
self.assertRaises(IOError, self.mySqlApp.secure, "foo")
self.assertTrue(self.mySqlApp.stop_db.called)
self.assertFalse(self.mySqlApp.start_mysql.called)
@ -1545,7 +1541,7 @@ class MySqlAppMockTest(trove_testtools.TestCase):
app._wait_for_mysql_to_be_really_alive = MagicMock(
return_value=True)
app.stop_db = MagicMock(return_value=None)
app.secure('foo', None)
app.secure('foo')
reset_config_calls = [call('foo', auth_pwd_mock.return_value)]
app._reset_configuration.assert_has_calls(reset_config_calls)
self.assertTrue(mock_execute.called)
@ -1570,7 +1566,7 @@ class MySqlAppMockTest(trove_testtools.TestCase):
app = MySqlApp(mock_status)
dbaas_base.clear_expired_password = \
MagicMock(return_value=None)
self.assertRaises(RuntimeError, app.secure, None, None)
self.assertRaises(RuntimeError, app.secure, None)
self.assertTrue(mock_execute.called)
# At least called twice
self.assertTrue(mock_execute.call_count >= 2)

View File

@ -1,4 +1,5 @@
# Copyright 2015 Tesora 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
@ -12,11 +13,14 @@
# License for the specific language governing permissions and limitations
# under the License.
import getpass
import os
from mock import ANY
from mock import DEFAULT
from mock import MagicMock
from mock import Mock
from mock import patch
from proboscis.asserts import assert_equal
from proboscis.asserts import assert_true
@ -30,6 +34,7 @@ from trove.tests.unittests import trove_testtools
class MockManager(manager.Manager):
def __init__(self):
super(MockManager, self).__init__('mysql')
self._app = MagicMock()
@ -50,6 +55,7 @@ class MockManager(manager.Manager):
class ManagerTest(trove_testtools.TestCase):
def setUp(self):
super(ManagerTest, self).setUp()
@ -312,3 +318,146 @@ class ManagerTest(trove_testtools.TestCase):
for key in os_mocks.keys():
assert_true(os_mocks[key].call_count == 1,
"%s not called" % key)
def test_prepare_single(self):
packages = Mock()
databases = Mock()
memory_mb = Mock()
users = Mock()
device_path = Mock()
mount_point = Mock()
backup_info = Mock()
config_contents = Mock()
root_password = Mock()
overrides = Mock()
snapshot = Mock()
self._assert_prepare(
self.context, packages, databases, memory_mb, users, device_path,
mount_point, backup_info, config_contents, root_password,
overrides, None, snapshot)
def test_prepare_cluster(self):
packages = Mock()
databases = Mock()
memory_mb = Mock()
users = Mock()
device_path = Mock()
mount_point = Mock()
backup_info = Mock()
config_contents = Mock()
root_password = Mock()
overrides = Mock()
cluster_config = Mock()
snapshot = Mock()
self._assert_prepare(
self.context, packages, databases, memory_mb, users, device_path,
mount_point, backup_info, config_contents, root_password,
overrides, cluster_config, snapshot)
def _assert_prepare(self, context, packages, databases, memory_mb, users,
device_path, mount_point, backup_info, config_contents,
root_password, overrides, cluster_config, snapshot):
is_error_expected = False
is_post_process_expected = cluster_config is not None
with patch.multiple(self.manager,
do_prepare=DEFAULT, post_prepare=DEFAULT,
apply_overrides_on_prepare=DEFAULT,
create_database=DEFAULT, create_user=DEFAULT):
self.manager.prepare(
context, packages, databases, memory_mb, users,
device_path, mount_point, backup_info, config_contents,
root_password, overrides, cluster_config, snapshot)
self.manager.status.begin_install.assert_called_once_with()
self.manager.do_prepare.assert_called_once_with(
context,
packages,
databases,
memory_mb,
users,
device_path,
mount_point,
backup_info,
config_contents,
root_password,
overrides,
cluster_config,
snapshot)
self.manager.apply_overrides_on_prepare.assert_called_once_with(
context,
overrides)
self.manager.status.end_install(
error_occurred=is_error_expected,
post_processing=is_post_process_expected)
self.manager.post_prepare.assert_called_once_with(
context,
packages,
databases,
memory_mb,
users,
device_path,
mount_point,
backup_info,
config_contents,
root_password,
overrides,
cluster_config,
snapshot)
if not is_post_process_expected:
self.manager.create_database.assert_called_once_with(
context,
databases)
self.manager.create_user.assert_called_once_with(
context,
users)
else:
self.assertEqual(0, self.manager.create_database.call_count)
self.assertEqual(0, self.manager.create_user.call_count)
def test_apply_overrides_on_prepare(self):
overrides = Mock()
with patch.multiple(self.manager,
update_overrides=DEFAULT, restart=DEFAULT):
self.manager.apply_overrides_on_prepare(self.context, overrides)
self.manager.update_overrides.assert_called_once_with(
self.context, overrides)
self.manager.restart.assert_called_once_with(self.context)
def test_apply_overrides_on_prepare_failure(self):
packages = Mock()
databases = Mock()
memory_mb = Mock()
users = Mock()
device_path = Mock()
mount_point = Mock()
backup_info = Mock()
config_contents = Mock()
root_password = Mock()
overrides = Mock()
cluster_config = Mock()
snapshot = Mock()
expected_failure = Exception("Error in 'apply_overrides_on_prepare'.")
with patch.multiple(
self.manager, do_prepare=DEFAULT,
apply_overrides_on_prepare=MagicMock(
side_effect=expected_failure
)):
self.assertRaisesRegexp(
Exception, "Error in 'apply_overrides_on_prepare'.",
self.manager.prepare,
self.context, packages, databases, memory_mb, users,
device_path, mount_point, backup_info, config_contents,
root_password, overrides, cluster_config, snapshot)
self.manager.status.begin_install.assert_called_once_with()
self.manager.status.end_install(
error_occurred=True,
post_processing=ANY)

View File

@ -37,6 +37,7 @@ from trove.guestagent.volume import VolumeDevice
class GuestAgentManagerTest(testtools.TestCase):
def setUp(self):
super(GuestAgentManagerTest, self).setUp()
self.context = TroveContext()
@ -282,7 +283,7 @@ class GuestAgentManagerTest(testtools.TestCase):
'/var/lib/mysql/data')
dbaas.MySqlApp.install_if_needed.assert_any_call(None)
# We don't need to make sure the exact contents are there
dbaas.MySqlApp.secure.assert_any_call(None, None)
dbaas.MySqlApp.secure.assert_any_call(None)
dbaas.MySqlApp.secure_root.assert_any_call(
secure_remote_root=not is_root_enabled)