Fix inconsistent usage of mount_point

Reasons:
- multiple datastores;
- inconsistent usage of mount_point at
taskmanager and guestagent;

Changes:
- oslo groups;
- mount point per datastore;
- guest API not changed.

Change-Id: I8044789c6ab2ed837ff0e1b16183dfeafbf955bb
Closes-Bug: #1248212
This commit is contained in:
Denis Makogon 2014-02-27 12:25:11 +02:00 committed by Ed Cranford
parent 89f517f736
commit ea51b7e625
24 changed files with 646 additions and 577 deletions

View File

@ -69,3 +69,4 @@ backup_aes_cbc_key = "default_aes_cbc_key"
backup_use_snet = False
backup_chunk_size = 65536
backup_segment_max_size = 2147483648

View File

@ -59,7 +59,6 @@ network_label_regex = ^private$
trove_volume_support = True
block_device_mapping = vdb
device_path = /dev/vdb
mount_point = /var/lib/mysql
# Maximum volume size for an instance
max_accepted_volume_size = 10
max_instances_per_user = 5

View File

@ -84,7 +84,6 @@ trove_volume_support = True
nova_volume_service_type = volume
nova_volume_service_name = Volume Service
device_path = /dev/vdb
mount_point = /var/lib/mysql
max_accepted_volume_size = 25
max_instances_per_user = 55
max_volumes_per_user = 100
@ -180,4 +179,3 @@ paste.app_factory = trove.common.api:app_factory
#Add this filter to log request and response for debugging
[filter:debug]
paste.filter_factory = trove.common.wsgi:Debug

View File

@ -116,7 +116,6 @@ common_opts = [
cfg.BoolOpt('use_nova_server_volume', default=False),
cfg.BoolOpt('use_heat', default=False),
cfg.StrOpt('device_path', default='/dev/vdb'),
cfg.StrOpt('mount_point', default='/var/lib/mysql'),
cfg.StrOpt('default_datastore', default=None,
help="The default datastore id or name to use if one is not "
"provided by the user. If the default value is None, the field "
@ -276,7 +275,10 @@ mysql_opts = [
' in the security group (only applicable '
'if trove_security_groups_support is True)'),
cfg.StrOpt('backup_strategy', default='InnoBackupEx',
help='Default strategy to perform backups.')
help='Default strategy to perform backups.'),
cfg.StrOpt('mount_point', default='/var/lib/mysql',
help="Filesystem path for mounting "
"volumes if volume support is enabled"),
]
# Percona
@ -293,7 +295,10 @@ percona_opts = [
' in the security group (only applicable '
'if trove_security_groups_support is True)'),
cfg.StrOpt('backup_strategy', default='InnoBackupEx',
help='Default strategy to perform backups.')
help='Default strategy to perform backups.'),
cfg.StrOpt('mount_point', default='/var/lib/mysql',
help="Filesystem path for mounting "
"volumes if volume support is enabled"),
]
# Redis
@ -309,6 +314,11 @@ redis_opts = [
help='List of UDP ports and/or port ranges to open'
' in the security group (only applicable '
'if trove_security_groups_support is True)'),
cfg.StrOpt('backup_strategy', default=None,
help='Default strategy to perform backups.'),
cfg.StrOpt('mount_point', default='/var/lib/redis',
help="Filesystem path for mounting "
"volumes if volume support is enabled"),
]
# Cassandra
@ -326,6 +336,9 @@ cassandra_opts = [
'if trove_security_groups_support is True)'),
cfg.StrOpt('backup_strategy', default=None,
help='Default strategy to perform backups.'),
cfg.StrOpt('mount_point', default='/var/lib/cassandra',
help="Filesystem path for mounting "
"volumes if volume support is enabled"),
]
#Couchbase
@ -345,6 +358,9 @@ couchbase_opts = [
'if trove_security_groups_support is True)'),
cfg.StrOpt('backup_strategy', default=None,
help='Default strategy to perform backups.'),
cfg.StrOpt('mount_point', default='/var/lib/couchbase',
help="Filesystem path for mounting "
"volumes if volume support is enabled"),
]
CONF = cfg.CONF

View File

@ -268,7 +268,7 @@ class API(proxy.RpcProxy):
LOG.debug(_("Check Volume Info on Instance %s"), self.id)
# self._check_for_hearbeat()
return self._call("get_filesystem_stats", AGENT_LOW_TIMEOUT,
fs_path=CONF.mount_point)
fs_path=None)
def update_guest(self):
"""Make a synchronous call to update the guest agent."""

View File

@ -86,7 +86,9 @@ class BackupAgent(object):
})
# Store the size of the filesystem before the backup.
stats = get_filesystem_volume_stats(CONF.mount_point)
mount_point = CONF.get('mysql' if not CONF.datastore_manager
else CONF.datastore_manager).mount_point
stats = get_filesystem_volume_stats(mount_point)
backup = {
'backup_id': backup_id,
'size': stats.get('used', 0.0),

View File

@ -19,7 +19,6 @@ from trove.common import cfg
from trove.common import exception
from trove.guestagent import volume
from trove.guestagent.datastore.cassandra import service
from trove.guestagent.datastore.cassandra import system
from trove.openstack.common import periodic_task
from trove.openstack.common import log as logging
from trove.openstack.common.gettextutils import _
@ -30,6 +29,7 @@ LOG = logging.getLogger(__name__)
USAGE_SLEEP_TIME = CONF.usage_sleep_time # seconds.
USAGE_TIMEOUT = CONF.usage_timeout # seconds.
ERROR_MSG = _("Not supported")
MANAGER = CONF.datastore_manager
class Manager(periodic_task.PeriodicTasks):
@ -48,8 +48,9 @@ class Manager(periodic_task.PeriodicTasks):
def get_filesystem_stats(self, context, fs_path):
"""Gets the filesystem stats for the path given. """
return dbaas.get_filesystem_volume_stats(
system.CASSANDRA_MOUNT_POINT)
mount_point = CONF.get(
'mysql' if not MANAGER else MANAGER).mount_point
return dbaas.get_filesystem_volume_stats(mount_point)
def start_db_with_conf_changes(self, context, config_contents):
self.app.start_db_with_conf_changes(config_contents)
@ -67,7 +68,7 @@ class Manager(periodic_task.PeriodicTasks):
self.appStatus.begin_install()
LOG.info("Installing cassandra")
self.app.install_if_needed(packages)
self.app.init_storage_structure()
self.app.init_storage_structure(mount_point)
if config_contents:
LOG.info(_("Config processing"))
self.app.write_config(config_contents)
@ -75,11 +76,11 @@ class Manager(periodic_task.PeriodicTasks):
if device_path:
device = volume.VolumeDevice(device_path)
device.format()
if os.path.exists(system.CASSANDRA_MOUNT_POINT):
if os.path.exists(mount_point):
#rsync exiting data
device.migrate_data(system.CASSANDRA_MOUNT_POINT)
device.migrate_data(mount_point)
#mount the volume
device.mount(system.CASSANDRA_MOUNT_POINT)
device.mount(mount_point)
LOG.debug(_("Mounting new volume."))
self.app.restart()

View File

@ -58,8 +58,13 @@ class CassandraApp(object):
utils.execute_with_timeout(system.DISABLE_CASSANDRA_ON_BOOT,
shell=True)
def init_storage_structure(self):
utils.execute_with_timeout(system.INIT_FS, shell=True)
def init_storage_structure(self, mount_point):
try:
cmd = system.INIT_FS % mount_point
utils.execute_with_timeout(cmd, shell=True)
except exception.ProcessExecutionError as e:
LOG.error(_("Error while initiating storage structure."))
LOG.error(e)
def start_db(self, update_db=False):
self._enable_db_on_boot()

View File

@ -20,13 +20,11 @@ LOG = logging.getLogger(__name__)
CONF = cfg.CONF
CASSANDRA_DATA_DIR = "/var/lib/cassandra/data"
CASSANDRA_MOUNT_POINT = "/var/lib/cassandra"
CASSANDRA_CONF = "/etc/cassandra/cassandra.yaml"
CASSANDRA_TEMP_CONF = "/tmp/cassandra.yaml"
CASSANDRA_TEMP_DIR = "/tmp/cassandra"
INIT_FS = "sudo mkdir -p %s" % CASSANDRA_MOUNT_POINT
INIT_FS = "sudo mkdir -p %s"
ENABLE_CASSANDRA_ON_BOOT = "sudo update-rc.d cassandra enable"
DISABLE_CASSANDRA_ON_BOOT = "sudo update-rc.d cassandra disable"

View File

@ -17,7 +17,6 @@ from trove.common import cfg
from trove.common import exception
from trove.guestagent import dbaas
from trove.guestagent import volume
from trove.guestagent.datastore.couchbase import system
from trove.guestagent.datastore.couchbase import service
from trove.openstack.common import log as logging
from trove.openstack.common import periodic_task
@ -27,6 +26,7 @@ from trove.openstack.common.gettextutils import _
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
ERROR_MSG = _("Not supported")
MANAGER = CONF.datastore_manager
class Manager(periodic_task.PeriodicTasks):
@ -64,7 +64,7 @@ class Manager(periodic_task.PeriodicTasks):
if device_path:
device = volume.VolumeDevice(device_path)
device.format()
device.mount(system.COUCHBASE_MOUNT_POINT)
device.mount(mount_point)
LOG.debug(_('Mounted the volume.'))
self.app.install_if_needed(packages)
LOG.info(_('Securing couchbase now.'))
@ -91,10 +91,10 @@ class Manager(periodic_task.PeriodicTasks):
self.app.stop_db(do_not_start_on_reboot=do_not_start_on_reboot)
def get_filesystem_stats(self, context, fs_path):
"""
Gets file system stats from the provided fs_path.
"""
return dbaas.get_filesystem_volume_stats(system.COUCHBASE_MOUNT_POINT)
"""Gets the filesystem stats for the path given. """
mount_point = CONF.get(
'mysql' if not MANAGER else MANAGER).mount_point
return dbaas.get_filesystem_volume_stats(mount_point)
def update_attributes(self, context, username, hostname, user_attrs):
raise exception.TroveError(ERROR_MSG)

View File

@ -58,12 +58,13 @@ class CouchbaseApp(object):
def initial_setup(self):
self.ip_address = operating_system.get_ip_address()
mount_point = CONF.get('couchbase').mount_point
try:
LOG.info(_('Couchbase Server change data dir path'))
utils.execute_with_timeout(system.cmd_own_data_dir, shell=True)
utils.execute_with_timeout(
(system.cmd_node_init
% {'data_path': system.COUCHBASE_MOUNT_POINT,
% {'data_path': mount_point,
'IP': self.ip_address}), shell=True)
utils.execute_with_timeout(
system.cmd_rm_old_data_dir, shell=True)

View File

@ -12,10 +12,11 @@
# 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 trove.common import cfg
CONF = cfg.CONF
TIME_OUT = 1200
COUCHBASE_CONF_DIR = '/etc/couchbase'
COUCHBASE_MOUNT_POINT = '/var/lib/couchbase'
SERVICE_CANDIDATES = ["couchbase-server"]
cmd_couchbase_status = ('sudo /opt/couchbase/bin/couchbase-cli server-info '
'-c %(IP)s:8091 -u Administrator -p password')
@ -28,7 +29,7 @@ cmd_cluster_init = ('sudo /opt/couchbase/bin/couchbase-cli cluster-init '
'--cluster-init-port=8091')
cmd_kill = 'sudo pkill -9 couchbase-server'
cmd_own_data_dir = ('sudo chown couchbase:couchbase %s' %
COUCHBASE_MOUNT_POINT)
CONF.get('couchbase').mount_point)
cmd_rm_old_data_dir = 'sudo rm -rf /opt/couchbase/var/lib/couchbase/data'
""" For optimal couchbase operations, swappiness of vm should be set to 0.
Reference link: http://docs.couchbase.com/couchbase-manual-2

View File

@ -32,6 +32,7 @@ from trove.openstack.common import periodic_task
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
MANAGER = CONF.datastore_manager
class Manager(periodic_task.PeriodicTasks):
@ -116,16 +117,16 @@ class Manager(periodic_task.PeriodicTasks):
app.stop_db()
device = volume.VolumeDevice(device_path)
device.format()
if os.path.exists(CONF.mount_point):
if os.path.exists(mount_point):
#rsync exiting data
device.migrate_data(CONF.mount_point)
device.migrate_data(mount_point)
#mount the volume
device.mount(mount_point)
LOG.debug(_("Mounted the volume."))
app.start_mysql()
if backup_info:
self._perform_restore(backup_info, context,
CONF.mount_point, app)
mount_point, app)
LOG.info(_("Securing mysql now."))
app.secure(config_contents, overrides)
enable_root_on_restore = (backup_info and
@ -161,8 +162,10 @@ class Manager(periodic_task.PeriodicTasks):
app.stop_db(do_not_start_on_reboot=do_not_start_on_reboot)
def get_filesystem_stats(self, context, fs_path):
"""Gets the filesystem stats for the path given """
return dbaas.get_filesystem_volume_stats(fs_path)
"""Gets the filesystem stats for the path given. """
mount_point = CONF.get(
'mysql' if not MANAGER else MANAGER).mount_point
return dbaas.get_filesystem_volume_stats(mount_point)
def create_backup(self, context, backup_info):
"""

View File

@ -18,7 +18,6 @@ from trove.guestagent import dbaas
from trove.guestagent import volume
from trove.guestagent.datastore.redis.service import RedisAppStatus
from trove.guestagent.datastore.redis.service import RedisApp
from trove.guestagent.datastore.redis import system
from trove.openstack.common import log as logging
from trove.openstack.common.gettextutils import _
from trove.openstack.common import periodic_task
@ -26,6 +25,7 @@ from trove.openstack.common import periodic_task
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
MANAGER = CONF.datastore_manager
class Manager(periodic_task.PeriodicTasks):
@ -77,7 +77,7 @@ class Manager(periodic_task.PeriodicTasks):
if device_path:
device = volume.VolumeDevice(device_path)
device.format()
device.mount(system.REDIS_BASE_DIR)
device.mount(mount_point)
LOG.debug(_('Mounted the volume.'))
app.install_if_needed(packages)
LOG.info(_('Securing redis now.'))
@ -111,10 +111,10 @@ class Manager(periodic_task.PeriodicTasks):
app.stop_db(do_not_start_on_reboot=do_not_start_on_reboot)
def get_filesystem_stats(self, context, fs_path):
"""
Gets file system stats from the provided fs_path.
"""
return dbaas.get_filesystem_volume_stats(fs_path)
"""Gets the filesystem stats for the path given. """
mount_point = CONF.get(
'mysql' if not MANAGER else MANAGER).mount_point
return dbaas.get_filesystem_volume_stats(mount_point)
def create_backup(self, context, backup_info):
"""

View File

@ -29,7 +29,6 @@ REDIS_CMD_DISABLE = 'update-rc.d redis-server disable'
REDIS_CMD_START = 'service redis-server start || /bin/true'
REDIS_CMD_STOP = 'service redis-server stop || /bin/true'
REDIS_PACKAGE = 'redis-server'
REDIS_BASE_DIR = '/var/lib/redis'
if OS is 'redhat':
REDIS_BIN = '/usr/libexec/redis-server'

View File

@ -369,7 +369,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
self._log_and_raise(e, msg, err)
device_path = CONF.device_path
mount_point = CONF.mount_point
mount_point = CONF.get(datastore_manager).mount_point
volume_info = {'device_path': device_path, 'mount_point': mount_point}
LOG.debug(_("end _create_server_volume for id: %s") % self.id)
return volume_info
@ -441,7 +441,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
self._log_and_raise(e, msg, err)
device_path = CONF.device_path
mount_point = CONF.mount_point
mount_point = CONF.get(datastore_manager).mount_point
volume_info = {'device_path': device_path, 'mount_point': mount_point}
LOG.debug(_("end _create_server_volume_heat for id: %s") % self.id)
@ -454,7 +454,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
LOG.debug(_("begin _create_server_volume_individually for id: %s") %
self.id)
server = None
volume_info = self._build_volume_info(volume_size)
volume_info = self._build_volume_info(datastore_manager,
volume_size=volume_size)
block_device_mapping = volume_info['block_device']
try:
server = self._create_server(flavor_id, image_id, security_groups,
@ -472,24 +473,26 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
self.id)
return volume_info
def _build_volume_info(self, volume_size=None):
def _build_volume_info(self, datastore_manager, volume_size=None):
volume_info = None
volume_support = CONF.trove_volume_support
LOG.debug(_("trove volume support = %s") % volume_support)
if volume_support:
try:
volume_info = self._create_volume(volume_size)
volume_info = self._create_volume(
volume_size, datastore_manager)
except Exception as e:
msg = _("Error provisioning volume for instance: %s") % self.id
err = inst_models.InstanceTasks.BUILDING_ERROR_VOLUME
self._log_and_raise(e, msg, err)
else:
LOG.debug(_("device_path = %s") % CONF.device_path)
LOG.debug(_("mount_point = %s") % CONF.mount_point)
LOG.debug(_("mount_point = %s") %
CONF.get(datastore_manager).mount_point)
volume_info = {
'block_device': None,
'device_path': CONF.device_path,
'mount_point': CONF.mount_point,
'mount_point': CONF.get(datastore_manager).mount_point,
'volumes': None,
}
return volume_info
@ -501,7 +504,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
self.update_db(task_status=task_status)
raise TroveError(message=message)
def _create_volume(self, volume_size):
def _create_volume(self, volume_size, datastore_manager):
LOG.info("Entering create_volume")
LOG.debug(_("begin _create_volume for id: %s") % self.id)
volume_client = create_cinder_client(self.context)
@ -522,9 +525,9 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
if v_ref.status in ['error']:
raise VolumeCreationFailure()
LOG.debug(_("end _create_volume for id: %s") % self.id)
return self._build_volume(v_ref)
return self._build_volume(v_ref, datastore_manager)
def _build_volume(self, v_ref):
def _build_volume(self, v_ref, datastore_manager):
LOG.debug(_("Created volume %s") % v_ref)
# The mapping is in the format:
# <id>:[<type>]:[<size(GB)>]:[<delete_on_terminate>]
@ -538,7 +541,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
LOG.debug("volume = %s" % created_volumes)
device_path = CONF.device_path
mount_point = CONF.mount_point
mount_point = CONF.get(datastore_manager).mount_point
LOG.debug(_("device_path = %s") % device_path)
LOG.debug(_("mount_point = %s") % mount_point)
@ -979,6 +982,11 @@ class ResizeVolumeAction(ConfigurationMixin):
self.old_size = int(old_size)
self.new_size = int(new_size)
def get_mount_point(self):
mount_point = CONF.get(
self.instance.datastore_version.manager).mount_point
return mount_point
def _fail(self, orig_func):
LOG.exception(_("%(func)s encountered an error when attempting to "
"resize the volume for instance %(id)s. Setting service "
@ -1023,8 +1031,9 @@ class ResizeVolumeAction(ConfigurationMixin):
def _unmount_volume(self):
LOG.debug(_("Unmounting the volume on instance %(id)s") % {
'id': self.instance.id})
mount_point = self.get_mount_point()
self.instance.guest.unmount_volume(device_path=CONF.device_path,
mount_point=CONF.mount_point)
mount_point=mount_point)
LOG.debug(_("Successfully unmounted the volume %(vol_id)s for "
"instance %(id)s") % {'vol_id': self.instance.volume_id,
'id': self.instance.id})
@ -1073,8 +1082,9 @@ class ResizeVolumeAction(ConfigurationMixin):
def _resize_fs(self):
LOG.debug(_("Resizing the filesystem for instance %(id)s") % {
'id': self.instance.id})
mount_point = self.get_mount_point()
self.instance.guest.resize_fs(device_path=CONF.device_path,
mount_point=CONF.mount_point)
mount_point=mount_point)
LOG.debug(_("Successfully resized volume %(vol_id)s filesystem for "
"instance %(id)s") % {'vol_id': self.instance.volume_id,
'id': self.instance.id})
@ -1083,8 +1093,9 @@ class ResizeVolumeAction(ConfigurationMixin):
def _mount_volume(self):
LOG.debug(_("Mount the volume on instance %(id)s") % {
'id': self.instance.id})
mount_point = self.get_mount_point()
self.instance.guest.mount_volume(device_path=CONF.device_path,
mount_point=CONF.mount_point)
mount_point=mount_point)
LOG.debug(_("Successfully mounted the volume %(vol_id)s on instance "
"%(id)s") % {'vol_id': self.instance.volume_id,
'id': self.instance.id})

View File

@ -0,0 +1,140 @@
# 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.
import os
import testtools
from mock import Mock
from mockito import verify, when, unstub, any, mock
from trove.common.context import TroveContext
from trove.common.instance import ServiceStatuses
from trove.guestagent import volume
from trove.guestagent.common import operating_system
from trove.guestagent.datastore.cassandra import service as cass_service
from trove.guestagent.datastore.cassandra import manager as cass_manager
from trove.guestagent import pkg
class GuestAgentCassandraDBManagerTest(testtools.TestCase):
def setUp(self):
super(GuestAgentCassandraDBManagerTest, self).setUp()
self.real_status = cass_service.CassandraAppStatus.set_status
class FakeInstanceServiceStatus(object):
status = ServiceStatuses.NEW
def save(self):
pass
cass_service.CassandraAppStatus.set_status = Mock(
return_value=FakeInstanceServiceStatus())
self.context = TroveContext()
self.manager = cass_manager.Manager()
self.pkg = cass_service.packager
self.real_db_app_status = cass_service.CassandraAppStatus
self.origin_os_path_exists = os.path.exists
self.origin_format = volume.VolumeDevice.format
self.origin_migrate_data = volume.VolumeDevice.migrate_data
self.origin_mount = volume.VolumeDevice.mount
self.origin_stop_db = cass_service.CassandraApp.stop_db
self.origin_start_db = cass_service.CassandraApp.start_db
self.origin_install_db = cass_service.CassandraApp._install_db
self.original_get_ip = operating_system.get_ip_address
self.orig_make_host_reachable = (
cass_service.CassandraApp.make_host_reachable)
def tearDown(self):
super(GuestAgentCassandraDBManagerTest, self).tearDown()
cass_service.packager = self.pkg
cass_service.CassandraAppStatus.set_status = self.real_db_app_status
os.path.exists = self.origin_os_path_exists
volume.VolumeDevice.format = self.origin_format
volume.VolumeDevice.migrate_data = self.origin_migrate_data
volume.VolumeDevice.mount = self.origin_mount
cass_service.CassandraApp.stop_db = self.origin_stop_db
cass_service.CassandraApp.start_db = self.origin_start_db
cass_service.CassandraApp._install_db = self.origin_install_db
operating_system.get_ip_address = self.original_get_ip
cass_service.CassandraApp.make_host_reachable = (
self.orig_make_host_reachable)
unstub()
def test_update_status(self):
mock_status = mock()
self.manager.appStatus = mock_status
self.manager.update_status(self.context)
verify(mock_status).update()
def test_prepare_pkg(self):
self._prepare_dynamic(['cassandra'])
def test_prepare_no_pkg(self):
self._prepare_dynamic([])
def test_prepare_db_not_installed(self):
self._prepare_dynamic([], is_db_installed=False)
def test_prepare_db_not_installed_no_package(self):
self._prepare_dynamic([],
is_db_installed=True)
def _prepare_dynamic(self, packages,
config_content=any(), device_path='/dev/vdb',
is_db_installed=True, backup_id=None,
is_root_enabled=False,
overrides=None):
# covering all outcomes is starting to cause trouble here
if not backup_id:
backup_info = {'id': backup_id,
'location': 'fake-location',
'type': 'InnoBackupEx',
'checksum': 'fake-checksum',
}
mock_status = mock()
self.manager.appStatus = mock_status
when(mock_status).begin_install().thenReturn(None)
mock_app = mock()
self.manager.app = mock_app
when(mock_app).install_if_needed(packages).thenReturn(None)
(when(pkg.Package).pkg_is_installed(any()).
thenReturn(is_db_installed))
when(mock_app).init_storage_structure(any()).thenReturn(None)
when(mock_app).write_config(config_content).thenReturn(None)
when(mock_app).make_host_reachable().thenReturn(None)
when(mock_app).restart().thenReturn(None)
when(os.path).exists(any()).thenReturn(True)
when(volume.VolumeDevice).format().thenReturn(None)
when(volume.VolumeDevice).migrate_data(any()).thenReturn(None)
when(volume.VolumeDevice).mount().thenReturn(None)
# invocation
self.manager.prepare(context=self.context, packages=packages,
config_contents=config_content,
databases=None,
memory_mb='2048', users=None,
device_path=device_path,
mount_point="/var/lib/cassandra",
backup_info=backup_info,
overrides=None)
# verification/assertion
verify(mock_status).begin_install()
verify(mock_app).install_if_needed(packages)
verify(mock_app).init_storage_structure(any())
verify(mock_app).make_host_reachable()
verify(mock_app).restart()

View File

@ -0,0 +1,95 @@
# 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.
import testtools
from mock import Mock
from mockito import verify, when, unstub, any, mock
from trove.common.context import TroveContext
from trove.guestagent import volume
from trove.guestagent.common import operating_system
from trove.guestagent.datastore.couchbase import service as couch_service
from trove.guestagent.datastore.couchbase import manager as couch_manager
class GuestAgentCouchbaseManagerTest(testtools.TestCase):
def setUp(self):
super(GuestAgentCouchbaseManagerTest, self).setUp()
self.context = TroveContext()
self.manager = couch_manager.Manager()
self.packages = 'couchbase-server'
self.origin_CouchbaseAppStatus = couch_service.CouchbaseAppStatus
self.origin_format = volume.VolumeDevice.format
self.origin_mount = volume.VolumeDevice.mount
self.origin_stop_db = couch_service.CouchbaseApp.stop_db
self.origin_start_db = couch_service.CouchbaseApp.start_db
operating_system.get_ip_address = Mock()
def tearDown(self):
super(GuestAgentCouchbaseManagerTest, self).tearDown()
couch_service.CouchbaseAppStatus = self.origin_CouchbaseAppStatus
volume.VolumeDevice.format = self.origin_format
volume.VolumeDevice.mount = self.origin_mount
couch_service.CouchbaseApp.stop_db = self.origin_stop_db
couch_service.CouchbaseApp.start_db = self.origin_start_db
unstub()
def test_update_status(self):
mock_status = mock()
self.manager.appStatus = mock_status
self.manager.update_status(self.context)
verify(mock_status).update()
def test_prepare_device_path_true(self):
self._prepare_dynamic()
def _prepare_dynamic(self, device_path='/dev/vdb', is_db_installed=True,
backup_info=None):
mock_status = mock()
self.manager.appStatus = mock_status
when(mock_status).begin_install().thenReturn(None)
when(volume.VolumeDevice).format().thenReturn(None)
when(volume.VolumeDevice).mount().thenReturn(None)
when(couch_service.CouchbaseApp).install_if_needed().thenReturn(None)
when(couch_service.CouchbaseApp).complete_install_or_restart(
any()).thenReturn(None)
#invocation
self.manager.prepare(self.context, self.packages, None, 2048,
None, device_path=device_path,
mount_point='/var/lib/couchbase',
backup_info=backup_info)
#verification/assertion
verify(mock_status).begin_install()
verify(couch_service.CouchbaseApp).install_if_needed(self.packages)
verify(couch_service.CouchbaseApp).complete_install_or_restart()
def test_restart(self):
mock_status = mock()
self.manager.appStatus = mock_status
when(couch_service.CouchbaseApp).restart().thenReturn(None)
#invocation
self.manager.restart(self.context)
#verification/assertion
verify(couch_service.CouchbaseApp).restart()
def test_stop_db(self):
mock_status = mock()
self.manager.appStatus = mock_status
when(couch_service.CouchbaseApp).stop_db(
do_not_start_on_reboot=False).thenReturn(None)
#invocation
self.manager.stop_db(self.context)
#verification/assertion
verify(couch_service.CouchbaseApp).stop_db(
do_not_start_on_reboot=False)

View File

@ -25,7 +25,6 @@ from mockito import verify
from mockito import contains
from mockito import never
from mockito import matchers
from mockito import inorder, verifyNoMoreInteractions
import sqlalchemy
import testtools
from testtools.matchers import Is
@ -792,25 +791,6 @@ class MySqlAppMockTest(testtools.TestCase):
super(MySqlAppMockTest, self).tearDown()
unstub()
def test_secure_with_mycnf_error(self):
mock_conn = mock_sql_connection()
when(mock_conn).execute(any()).thenReturn(None)
when(utils).execute_with_timeout("sudo", any(str), "stop").thenReturn(
None)
# skip writing the file for now
when(os.path).isfile(any()).thenReturn(False)
mock_status = mock()
when(mock_status).wait_for_real_status_to_change_to(
any(), any(), any()).thenReturn(True)
app = MySqlApp(mock_status)
when(dbaas).clear_expired_password().thenReturn(None)
self.assertRaises(TypeError, app.secure, None, None)
verify(mock_conn, atleast=2).execute(any())
inorder.verify(mock_status).wait_for_real_status_to_change_to(
rd_instance.ServiceStatuses.SHUTDOWN, any(), any())
verifyNoMoreInteractions(mock_status)
def test_secure_keep_root(self):
mock_conn = mock_sql_connection()

View File

@ -1,497 +0,0 @@
# 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.
import os
import testtools
from mock import Mock
from mockito import verify, when, unstub, any, mock, never
from testtools.matchers import Is, Equals, Not
from trove.common.context import TroveContext
from trove.common.instance import ServiceStatuses
from trove.guestagent import volume
from trove.guestagent.common import operating_system
from trove.guestagent.datastore.cassandra import service as cass_service
from trove.guestagent.datastore.cassandra import manager as cass_manager
from trove.guestagent.datastore.mysql.manager import Manager
import trove.guestagent.datastore.mysql.service as dbaas
from trove.guestagent.datastore.couchbase import service as couch_service
from trove.guestagent.datastore.couchbase import manager as couch_manager
from trove.guestagent.datastore.redis.manager import Manager as RedisManager
import trove.guestagent.datastore.redis.service as redis_service
import trove.guestagent.datastore.redis.system as redis_system
from trove.guestagent import backup
from trove.guestagent.volume import VolumeDevice
from trove.guestagent import pkg
class GuestAgentManagerTest(testtools.TestCase):
def setUp(self):
super(GuestAgentManagerTest, self).setUp()
self.context = TroveContext()
self.manager = Manager()
self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
self.origin_os_path_exists = os.path.exists
self.origin_format = volume.VolumeDevice.format
self.origin_migrate_data = volume.VolumeDevice.migrate_data
self.origin_mount = volume.VolumeDevice.mount
self.origin_stop_mysql = dbaas.MySqlApp.stop_db
self.origin_start_mysql = dbaas.MySqlApp.start_mysql
self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
self.origin_os_path_exists = os.path.exists
def tearDown(self):
super(GuestAgentManagerTest, self).tearDown()
dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
os.path.exists = self.origin_os_path_exists
volume.VolumeDevice.format = self.origin_format
volume.VolumeDevice.migrate_data = self.origin_migrate_data
volume.VolumeDevice.mount = self.origin_mount
dbaas.MySqlApp.stop_db = self.origin_stop_mysql
dbaas.MySqlApp.start_mysql = self.origin_start_mysql
pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
os.path.exists = self.origin_os_path_exists
unstub()
def test_update_status(self):
mock_status = mock()
when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
self.manager.update_status(self.context)
verify(dbaas.MySqlAppStatus).get()
verify(mock_status).update()
def test_create_database(self):
when(dbaas.MySqlAdmin).create_database(['db1']).thenReturn(None)
self.manager.create_database(self.context, ['db1'])
verify(dbaas.MySqlAdmin).create_database(['db1'])
def test_create_user(self):
when(dbaas.MySqlAdmin).create_user(['user1']).thenReturn(None)
self.manager.create_user(self.context, ['user1'])
verify(dbaas.MySqlAdmin).create_user(['user1'])
def test_delete_database(self):
databases = ['db1']
when(dbaas.MySqlAdmin).delete_database(databases).thenReturn(None)
self.manager.delete_database(self.context, databases)
verify(dbaas.MySqlAdmin).delete_database(databases)
def test_delete_user(self):
user = ['user1']
when(dbaas.MySqlAdmin).delete_user(user).thenReturn(None)
self.manager.delete_user(self.context, user)
verify(dbaas.MySqlAdmin).delete_user(user)
def test_grant_access(self):
username = "test_user"
hostname = "test_host"
databases = ["test_database"]
when(dbaas.MySqlAdmin).grant_access(username,
hostname,
databases).thenReturn(None)
self.manager.grant_access(self.context,
username,
hostname,
databases)
verify(dbaas.MySqlAdmin).grant_access(username, hostname, databases)
def test_list_databases(self):
when(dbaas.MySqlAdmin).list_databases(None, None,
False).thenReturn(['database1'])
databases = self.manager.list_databases(self.context)
self.assertThat(databases, Not(Is(None)))
self.assertThat(databases, Equals(['database1']))
verify(dbaas.MySqlAdmin).list_databases(None, None, False)
def test_list_users(self):
when(dbaas.MySqlAdmin).list_users(None, None,
False).thenReturn(['user1'])
users = self.manager.list_users(self.context)
self.assertThat(users, Equals(['user1']))
verify(dbaas.MySqlAdmin).list_users(None, None, False)
def test_get_users(self):
username = ['user1']
hostname = ['host']
when(dbaas.MySqlAdmin).get_user(username,
hostname).thenReturn(['user1'])
users = self.manager.get_user(self.context, username, hostname)
self.assertThat(users, Equals(['user1']))
verify(dbaas.MySqlAdmin).get_user(username, hostname)
def test_enable_root(self):
when(dbaas.MySqlAdmin).enable_root().thenReturn('user_id_stuff')
user_id = self.manager.enable_root(self.context)
self.assertThat(user_id, Is('user_id_stuff'))
verify(dbaas.MySqlAdmin).enable_root()
def test_is_root_enabled(self):
when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(True)
is_enabled = self.manager.is_root_enabled(self.context)
self.assertThat(is_enabled, Is(True))
verify(dbaas.MySqlAdmin).is_root_enabled()
def test_create_backup(self):
when(backup).backup(self.context, 'backup_id_123').thenReturn(None)
# entry point
Manager().create_backup(self.context, 'backup_id_123')
# assertions
verify(backup).backup(self.context, 'backup_id_123')
def test_prepare_device_path_true(self):
self._prepare_dynamic()
def test_prepare_device_path_false(self):
self._prepare_dynamic(device_path=None)
def test_prepare_mysql_not_installed(self):
self._prepare_dynamic(is_mysql_installed=False)
def test_prepare_mysql_from_backup(self):
self._prepare_dynamic(backup_id='backup_id_123abc')
def test_prepare_mysql_from_backup_with_root(self):
self._prepare_dynamic(backup_id='backup_id_123abc',
is_root_enabled=True)
def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
backup_id=None, is_root_enabled=False,
overrides=None):
# covering all outcomes is starting to cause trouble here
COUNT = 1 if device_path else 0
backup_info = None
if backup_id is not None:
backup_info = {'id': backup_id,
'location': 'fake-location',
'type': 'InnoBackupEx',
'checksum': 'fake-checksum',
}
# TODO(juice): this should stub an instance of the MySqlAppStatus
mock_status = mock()
when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
when(mock_status).begin_install().thenReturn(None)
when(VolumeDevice).format().thenReturn(None)
when(VolumeDevice).migrate_data(any()).thenReturn(None)
when(VolumeDevice).mount().thenReturn(None)
when(dbaas.MySqlApp).stop_db().thenReturn(None)
when(dbaas.MySqlApp).start_mysql().thenReturn(None)
when(dbaas.MySqlApp).install_if_needed(any()).thenReturn(None)
when(backup).restore(self.context,
backup_info,
'/var/lib/mysql').thenReturn(None)
when(dbaas.MySqlApp).secure(any()).thenReturn(None)
when(dbaas.MySqlApp).secure_root(any()).thenReturn(None)
(when(pkg.Package).pkg_is_installed(any()).
thenReturn(is_mysql_installed))
when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(is_root_enabled)
when(dbaas.MySqlAdmin).create_user().thenReturn(None)
when(dbaas.MySqlAdmin).create_database().thenReturn(None)
when(os.path).exists(any()).thenReturn(True)
# invocation
self.manager.prepare(context=self.context,
packages=None,
memory_mb='2048',
databases=None,
users=None,
device_path=device_path,
mount_point='/var/lib/mysql',
backup_info=backup_info,
overrides=overrides)
# verification/assertion
verify(mock_status).begin_install()
verify(VolumeDevice, times=COUNT).format()
verify(dbaas.MySqlApp, times=COUNT).stop_db()
verify(VolumeDevice, times=COUNT).migrate_data(
any())
if backup_info:
verify(backup).restore(self.context, backup_info, '/var/lib/mysql')
verify(dbaas.MySqlApp).install_if_needed(any())
# We dont need to make sure the exact contents are there
verify(dbaas.MySqlApp).secure(any(), overrides)
verify(dbaas.MySqlAdmin, never).create_database()
verify(dbaas.MySqlAdmin, never).create_user()
verify(dbaas.MySqlApp).secure_root(secure_remote_root=any())
class RedisGuestAgentManagerTest(testtools.TestCase):
def setUp(self):
super(RedisGuestAgentManagerTest, self).setUp()
self.context = TroveContext()
self.manager = RedisManager()
self.packages = 'redis-server'
self.origin_RedisAppStatus = redis_service.RedisAppStatus
self.origin_stop_redis = redis_service.RedisApp.stop_db
self.origin_start_redis = redis_service.RedisApp.start_redis
self.origin_install_redis = redis_service.RedisApp._install_redis
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_redis = self.origin_start_redis
redis_service.RedisApp._install_redis = self.origin_install_redis
unstub()
def test_update_status(self):
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
self.manager.update_status(self.context)
verify(redis_service.RedisAppStatus).get()
verify(mock_status).update()
def test_prepare_device_path_true(self):
self._prepare_dynamic()
def test_prepare_device_path_false(self):
self._prepare_dynamic(device_path=None)
def test_prepare_redis_not_installed(self):
self._prepare_dynamic(is_redis_installed=False)
def _prepare_dynamic(self, device_path='/dev/vdb', is_redis_installed=True,
backup_info=None, is_root_enabled=False):
# covering all outcomes is starting to cause trouble here
dev_path = 1 if device_path else 0
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
when(mock_status).begin_install().thenReturn(None)
when(VolumeDevice).format().thenReturn(None)
when(VolumeDevice).mount().thenReturn(None)
when(redis_service.RedisApp).start_redis().thenReturn(None)
when(redis_service.RedisApp).install_if_needed().thenReturn(None)
when(backup).restore(self.context, backup_info).thenReturn(None)
when(redis_service.RedisApp).write_config(any()).thenReturn(None)
when(redis_service.RedisApp).complete_install_or_restart(
any()).thenReturn(None)
self.manager.prepare(self.context, self.packages,
None, '2048',
None, device_path=device_path,
mount_point='/var/lib/redis',
backup_info=backup_info)
verify(redis_service.RedisAppStatus, times=2).get()
verify(mock_status).begin_install()
verify(VolumeDevice, times=dev_path).mount(redis_system.REDIS_BASE_DIR)
verify(redis_service.RedisApp).install_if_needed(self.packages)
verify(redis_service.RedisApp).write_config(None)
verify(redis_service.RedisApp).complete_install_or_restart()
def test_restart(self):
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
when(redis_service.RedisApp).restart().thenReturn(None)
self.manager.restart(self.context)
verify(redis_service.RedisAppStatus).get()
verify(redis_service.RedisApp).restart()
def test_stop_db(self):
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
when(redis_service.RedisApp).stop_db(do_not_start_on_reboot=
False).thenReturn(None)
self.manager.stop_db(self.context)
verify(redis_service.RedisAppStatus).get()
verify(redis_service.RedisApp).stop_db(do_not_start_on_reboot=False)
class GuestAgentCassandraDBManagerTest(testtools.TestCase):
def setUp(self):
super(GuestAgentCassandraDBManagerTest, self).setUp()
self.real_status = cass_service.CassandraAppStatus.set_status
class FakeInstanceServiceStatus(object):
status = ServiceStatuses.NEW
def save(self):
pass
cass_service.CassandraAppStatus.set_status = Mock(
return_value=FakeInstanceServiceStatus())
self.context = TroveContext()
self.manager = cass_manager.Manager()
self.pkg = cass_service.packager
self.real_db_app_status = cass_service.CassandraAppStatus
self.origin_os_path_exists = os.path.exists
self.origin_format = volume.VolumeDevice.format
self.origin_migrate_data = volume.VolumeDevice.migrate_data
self.origin_mount = volume.VolumeDevice.mount
self.origin_stop_db = cass_service.CassandraApp.stop_db
self.origin_start_db = cass_service.CassandraApp.start_db
self.origin_install_db = cass_service.CassandraApp._install_db
self.original_get_ip = operating_system.get_ip_address
self.orig_make_host_reachable = (
cass_service.CassandraApp.make_host_reachable)
def tearDown(self):
super(GuestAgentCassandraDBManagerTest, self).tearDown()
cass_service.packager = self.pkg
cass_service.CassandraAppStatus.set_status = self.real_db_app_status
os.path.exists = self.origin_os_path_exists
volume.VolumeDevice.format = self.origin_format
volume.VolumeDevice.migrate_data = self.origin_migrate_data
volume.VolumeDevice.mount = self.origin_mount
cass_service.CassandraApp.stop_db = self.origin_stop_db
cass_service.CassandraApp.start_db = self.origin_start_db
cass_service.CassandraApp._install_db = self.origin_install_db
operating_system.get_ip_address = self.original_get_ip
cass_service.CassandraApp.make_host_reachable = (
self.orig_make_host_reachable)
def test_update_status(self):
mock_status = mock()
self.manager.appStatus = mock_status
self.manager.update_status(self.context)
verify(mock_status).update()
def test_prepare_pkg(self):
self._prepare_dynamic(['cassandra'])
def test_prepare_no_pkg(self):
self._prepare_dynamic([])
def test_prepare_db_not_installed(self):
self._prepare_dynamic([], is_db_installed=False)
def test_prepare_db_not_installed_no_package(self):
self._prepare_dynamic([],
is_db_installed=True)
def _prepare_dynamic(self, packages,
config_content=any(), device_path='/dev/vdb',
is_db_installed=True, backup_id=None,
is_root_enabled=False,
overrides=None):
# covering all outcomes is starting to cause trouble here
if not backup_id:
backup_info = {'id': backup_id,
'location': 'fake-location',
'type': 'InnoBackupEx',
'checksum': 'fake-checksum',
}
mock_status = mock()
self.manager.appStatus = mock_status
when(mock_status).begin_install().thenReturn(None)
mock_app = mock()
self.manager.app = mock_app
when(mock_app).install_if_needed(packages).thenReturn(None)
(when(pkg.Package).pkg_is_installed(any()).
thenReturn(is_db_installed))
when(mock_app).init_storage_structure().thenReturn(None)
when(mock_app).write_config(config_content).thenReturn(None)
when(mock_app).make_host_reachable().thenReturn(None)
when(mock_app).restart().thenReturn(None)
when(os.path).exists(any()).thenReturn(True)
when(volume.VolumeDevice).format().thenReturn(None)
when(volume.VolumeDevice).migrate_data(any()).thenReturn(None)
when(volume.VolumeDevice).mount().thenReturn(None)
# invocation
self.manager.prepare(context=self.context, packages=packages,
config_contents=config_content,
databases=None,
memory_mb='2048', users=None,
device_path=device_path,
mount_point="/var/lib/cassandra",
backup_info=backup_info,
overrides=None)
# verification/assertion
verify(mock_status).begin_install()
verify(mock_app).install_if_needed(packages)
verify(mock_app).init_storage_structure()
verify(mock_app).make_host_reachable()
verify(mock_app).restart()
class GuestAgentCouchbaseManagerTest(testtools.TestCase):
def setUp(self):
super(GuestAgentCouchbaseManagerTest, self).setUp()
self.context = TroveContext()
self.manager = couch_manager.Manager()
self.packages = 'couchbase-server'
self.origin_CouchbaseAppStatus = couch_service.CouchbaseAppStatus
self.origin_format = volume.VolumeDevice.format
self.origin_mount = volume.VolumeDevice.mount
self.origin_stop_db = couch_service.CouchbaseApp.stop_db
self.origin_start_db = couch_service.CouchbaseApp.start_db
operating_system.get_ip_address = Mock()
def tearDown(self):
super(GuestAgentCouchbaseManagerTest, self).tearDown()
couch_service.CouchbaseAppStatus = self.origin_CouchbaseAppStatus
volume.VolumeDevice.format = self.origin_format
volume.VolumeDevice.mount = self.origin_mount
couch_service.CouchbaseApp.stop_db = self.origin_stop_db
couch_service.CouchbaseApp.start_db = self.origin_start_db
unstub()
def test_update_status(self):
mock_status = mock()
self.manager.appStatus = mock_status
self.manager.update_status(self.context)
verify(mock_status).update()
def test_prepare_device_path_true(self):
self._prepare_dynamic()
def _prepare_dynamic(self, device_path='/dev/vdb', is_db_installed=True,
backup_info=None):
mock_status = mock()
self.manager.appStatus = mock_status
when(mock_status).begin_install().thenReturn(None)
when(volume.VolumeDevice).format().thenReturn(None)
when(volume.VolumeDevice).mount().thenReturn(None)
when(couch_service.CouchbaseApp).install_if_needed().thenReturn(None)
when(couch_service.CouchbaseApp).complete_install_or_restart(
any()).thenReturn(None)
#invocation
self.manager.prepare(self.context, self.packages, None, 2048,
None, device_path=device_path,
mount_point='/var/lib/couchbase',
backup_info=backup_info)
#verification/assertion
verify(mock_status).begin_install()
verify(couch_service.CouchbaseApp).install_if_needed(self.packages)
verify(couch_service.CouchbaseApp).complete_install_or_restart()
def test_restart(self):
mock_status = mock()
self.manager.appStatus = mock_status
when(couch_service.CouchbaseApp).restart().thenReturn(None)
#invocation
self.manager.restart(self.context)
#verification/assertion
verify(couch_service.CouchbaseApp).restart()
def test_stop_db(self):
mock_status = mock()
self.manager.appStatus = mock_status
when(couch_service.CouchbaseApp).stop_db(
do_not_start_on_reboot=False).thenReturn(None)
#invocation
self.manager.stop_db(self.context)
#verification/assertion
verify(couch_service.CouchbaseApp).stop_db(
do_not_start_on_reboot=False)

View File

@ -0,0 +1,219 @@
# 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.
import os
import testtools
from mockito import verify, when, unstub, any, mock, never
from testtools.matchers import Is, Equals, Not
from trove.common.context import TroveContext
from trove.guestagent import volume
from trove.guestagent.datastore.mysql.manager import Manager
import trove.guestagent.datastore.mysql.service as dbaas
from trove.guestagent import backup
from trove.guestagent.volume import VolumeDevice
from trove.guestagent import pkg
class GuestAgentManagerTest(testtools.TestCase):
def setUp(self):
super(GuestAgentManagerTest, self).setUp()
self.context = TroveContext()
self.manager = Manager()
self.origin_MySqlAppStatus = dbaas.MySqlAppStatus
self.origin_os_path_exists = os.path.exists
self.origin_format = volume.VolumeDevice.format
self.origin_migrate_data = volume.VolumeDevice.migrate_data
self.origin_mount = volume.VolumeDevice.mount
self.origin_stop_mysql = dbaas.MySqlApp.stop_db
self.origin_start_mysql = dbaas.MySqlApp.start_mysql
self.origin_pkg_is_installed = pkg.Package.pkg_is_installed
self.origin_os_path_exists = os.path.exists
def tearDown(self):
super(GuestAgentManagerTest, self).tearDown()
dbaas.MySqlAppStatus = self.origin_MySqlAppStatus
os.path.exists = self.origin_os_path_exists
volume.VolumeDevice.format = self.origin_format
volume.VolumeDevice.migrate_data = self.origin_migrate_data
volume.VolumeDevice.mount = self.origin_mount
dbaas.MySqlApp.stop_db = self.origin_stop_mysql
dbaas.MySqlApp.start_mysql = self.origin_start_mysql
pkg.Package.pkg_is_installed = self.origin_pkg_is_installed
os.path.exists = self.origin_os_path_exists
unstub()
def test_update_status(self):
mock_status = mock()
when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
self.manager.update_status(self.context)
verify(dbaas.MySqlAppStatus).get()
verify(mock_status).update()
def test_create_database(self):
when(dbaas.MySqlAdmin).create_database(['db1']).thenReturn(None)
self.manager.create_database(self.context, ['db1'])
verify(dbaas.MySqlAdmin).create_database(['db1'])
def test_create_user(self):
when(dbaas.MySqlAdmin).create_user(['user1']).thenReturn(None)
self.manager.create_user(self.context, ['user1'])
verify(dbaas.MySqlAdmin).create_user(['user1'])
def test_delete_database(self):
databases = ['db1']
when(dbaas.MySqlAdmin).delete_database(databases).thenReturn(None)
self.manager.delete_database(self.context, databases)
verify(dbaas.MySqlAdmin).delete_database(databases)
def test_delete_user(self):
user = ['user1']
when(dbaas.MySqlAdmin).delete_user(user).thenReturn(None)
self.manager.delete_user(self.context, user)
verify(dbaas.MySqlAdmin).delete_user(user)
def test_grant_access(self):
username = "test_user"
hostname = "test_host"
databases = ["test_database"]
when(dbaas.MySqlAdmin).grant_access(username,
hostname,
databases).thenReturn(None)
self.manager.grant_access(self.context,
username,
hostname,
databases)
verify(dbaas.MySqlAdmin).grant_access(username, hostname, databases)
def test_list_databases(self):
when(dbaas.MySqlAdmin).list_databases(None, None,
False).thenReturn(['database1'])
databases = self.manager.list_databases(self.context)
self.assertThat(databases, Not(Is(None)))
self.assertThat(databases, Equals(['database1']))
verify(dbaas.MySqlAdmin).list_databases(None, None, False)
def test_list_users(self):
when(dbaas.MySqlAdmin).list_users(None, None,
False).thenReturn(['user1'])
users = self.manager.list_users(self.context)
self.assertThat(users, Equals(['user1']))
verify(dbaas.MySqlAdmin).list_users(None, None, False)
def test_get_users(self):
username = ['user1']
hostname = ['host']
when(dbaas.MySqlAdmin).get_user(username,
hostname).thenReturn(['user1'])
users = self.manager.get_user(self.context, username, hostname)
self.assertThat(users, Equals(['user1']))
verify(dbaas.MySqlAdmin).get_user(username, hostname)
def test_enable_root(self):
when(dbaas.MySqlAdmin).enable_root().thenReturn('user_id_stuff')
user_id = self.manager.enable_root(self.context)
self.assertThat(user_id, Is('user_id_stuff'))
verify(dbaas.MySqlAdmin).enable_root()
def test_is_root_enabled(self):
when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(True)
is_enabled = self.manager.is_root_enabled(self.context)
self.assertThat(is_enabled, Is(True))
verify(dbaas.MySqlAdmin).is_root_enabled()
def test_create_backup(self):
when(backup).backup(self.context, 'backup_id_123').thenReturn(None)
# entry point
Manager().create_backup(self.context, 'backup_id_123')
# assertions
verify(backup).backup(self.context, 'backup_id_123')
def test_prepare_device_path_true(self):
self._prepare_dynamic()
def test_prepare_device_path_false(self):
self._prepare_dynamic(device_path=None)
def test_prepare_mysql_not_installed(self):
self._prepare_dynamic(is_mysql_installed=False)
def test_prepare_mysql_from_backup(self):
self._prepare_dynamic(backup_id='backup_id_123abc')
def test_prepare_mysql_from_backup_with_root(self):
self._prepare_dynamic(backup_id='backup_id_123abc',
is_root_enabled=True)
def _prepare_dynamic(self, device_path='/dev/vdb', is_mysql_installed=True,
backup_id=None, is_root_enabled=False,
overrides=None):
# covering all outcomes is starting to cause trouble here
COUNT = 1 if device_path else 0
backup_info = None
if backup_id is not None:
backup_info = {'id': backup_id,
'location': 'fake-location',
'type': 'InnoBackupEx',
'checksum': 'fake-checksum',
}
# TODO(juice): this should stub an instance of the MySqlAppStatus
mock_status = mock()
when(dbaas.MySqlAppStatus).get().thenReturn(mock_status)
when(mock_status).begin_install().thenReturn(None)
when(VolumeDevice).format().thenReturn(None)
when(VolumeDevice).migrate_data(any()).thenReturn(None)
when(VolumeDevice).mount().thenReturn(None)
when(dbaas.MySqlApp).stop_db().thenReturn(None)
when(dbaas.MySqlApp).start_mysql().thenReturn(None)
when(dbaas.MySqlApp).install_if_needed(any()).thenReturn(None)
when(backup).restore(self.context,
backup_info,
'/var/lib/mysql').thenReturn(None)
when(dbaas.MySqlApp).secure(any()).thenReturn(None)
when(dbaas.MySqlApp).secure_root(any()).thenReturn(None)
(when(pkg.Package).pkg_is_installed(any()).
thenReturn(is_mysql_installed))
when(dbaas.MySqlAdmin).is_root_enabled().thenReturn(is_root_enabled)
when(dbaas.MySqlAdmin).create_user().thenReturn(None)
when(dbaas.MySqlAdmin).create_database().thenReturn(None)
when(os.path).exists(any()).thenReturn(True)
# invocation
self.manager.prepare(context=self.context,
packages=None,
memory_mb='2048',
databases=None,
users=None,
device_path=device_path,
mount_point='/var/lib/mysql',
backup_info=backup_info,
overrides=overrides)
# verification/assertion
verify(mock_status).begin_install()
verify(VolumeDevice, times=COUNT).format()
verify(dbaas.MySqlApp, times=COUNT).stop_db()
verify(VolumeDevice, times=COUNT).migrate_data(
any())
if backup_info:
verify(backup).restore(self.context, backup_info, '/var/lib/mysql')
verify(dbaas.MySqlApp).install_if_needed(any())
# We dont need to make sure the exact contents are there
verify(dbaas.MySqlApp).secure(any(), overrides)
verify(dbaas.MySqlAdmin, never).create_database()
verify(dbaas.MySqlAdmin, never).create_user()
verify(dbaas.MySqlApp).secure_root(secure_remote_root=any())

View File

@ -447,11 +447,6 @@ class PkgRPMRemoveTestCase(testtools.TestCase):
self.assertRaises(pkg.PkgNotFoundError, self.pkg.pkg_remove,
self.pkgName, 5000)
def test_success_remove(self):
# test
pexpect.spawn.expect = Mock(return_value=2)
self.assertTrue(self.pkg.pkg_remove(self.pkgName, 5000) is None)
def test_timeout_error(self):
# test timeout error
pexpect.spawn.expect = Mock(side_effect=pexpect.

View File

@ -0,0 +1,97 @@
# 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.
import testtools
from mockito import verify, when, unstub, any, mock
from trove.common.context import TroveContext
from trove.guestagent.datastore.redis.manager import Manager as RedisManager
import trove.guestagent.datastore.redis.service as redis_service
from trove.guestagent import backup
from trove.guestagent.volume import VolumeDevice
class RedisGuestAgentManagerTest(testtools.TestCase):
def setUp(self):
super(RedisGuestAgentManagerTest, self).setUp()
self.context = TroveContext()
self.manager = RedisManager()
self.packages = 'redis-server'
self.origin_RedisAppStatus = redis_service.RedisAppStatus
self.origin_stop_redis = redis_service.RedisApp.stop_db
self.origin_start_redis = redis_service.RedisApp.start_redis
self.origin_install_redis = redis_service.RedisApp._install_redis
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_redis = self.origin_start_redis
redis_service.RedisApp._install_redis = self.origin_install_redis
unstub()
def test_update_status(self):
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
self.manager.update_status(self.context)
verify(redis_service.RedisAppStatus).get()
verify(mock_status).update()
def test_prepare_redis_not_installed(self):
self._prepare_dynamic(is_redis_installed=False)
def _prepare_dynamic(self, device_path='/dev/vdb', is_redis_installed=True,
backup_info=None, is_root_enabled=False,
mount_point='var/lib/redis'):
# covering all outcomes is starting to cause trouble here
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
when(mock_status).begin_install().thenReturn(None)
when(VolumeDevice).format().thenReturn(None)
when(VolumeDevice).mount().thenReturn(None)
when(redis_service.RedisApp).start_redis().thenReturn(None)
when(redis_service.RedisApp).install_if_needed().thenReturn(None)
when(backup).restore(self.context, backup_info).thenReturn(None)
when(redis_service.RedisApp).write_config(any()).thenReturn(None)
when(redis_service.RedisApp).complete_install_or_restart(
any()).thenReturn(None)
self.manager.prepare(self.context, self.packages,
None, '2048',
None, device_path=device_path,
mount_point='/var/lib/redis',
backup_info=backup_info)
verify(redis_service.RedisAppStatus, times=2).get()
verify(mock_status).begin_install()
verify(VolumeDevice).format()
verify(redis_service.RedisApp).install_if_needed(self.packages)
verify(redis_service.RedisApp).write_config(None)
verify(redis_service.RedisApp).complete_install_or_restart()
def test_restart(self):
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
when(redis_service.RedisApp).restart().thenReturn(None)
self.manager.restart(self.context)
verify(redis_service.RedisAppStatus).get()
verify(redis_service.RedisApp).restart()
def test_stop_db(self):
mock_status = mock()
when(redis_service.RedisAppStatus).get().thenReturn(mock_status)
when(redis_service.RedisApp).stop_db(do_not_start_on_reboot=
False).thenReturn(None)
self.manager.stop_db(self.context)
verify(redis_service.RedisAppStatus).get()
verify(redis_service.RedisApp).stop_db(do_not_start_on_reboot=False)

View File

@ -316,6 +316,11 @@ class ResizeVolumeTest(testtools.TestCase):
self.old_vol_size,
self.new_vol_size)
class FakeGroup():
def __init__(self):
self.mount_point = 'var/lib/mysql'
taskmanager_models.CONF.get = Mock(return_value=FakeGroup())
def tearDown(self):
super(ResizeVolumeTest, self).tearDown()