Merge "Add support for configuration groups in int-tests"

This commit is contained in:
Jenkins 2016-02-01 17:55:50 +00:00 committed by Gerrit Code Review
commit 45d1936e32
6 changed files with 837 additions and 31 deletions

View File

@ -34,6 +34,7 @@ from trove.tests.api import users
from trove.tests.api import versions
from trove.tests.scenario.groups import backup_group
from trove.tests.scenario.groups import cluster_actions_group
from trove.tests.scenario.groups import configuration_group
from trove.tests.scenario.groups import database_actions_group
from trove.tests.scenario.groups import guest_log_group
from trove.tests.scenario.groups import instance_actions_group
@ -120,6 +121,7 @@ proboscis.register(groups=["blackbox_mgmt"],
#
# Group designations for datastore agnostic int-tests
#
# Base groups for all other groups
base_groups = [
GROUP_SERVICES_INITIALIZE,
flavors.GROUP,
@ -127,12 +129,12 @@ base_groups = [
GROUP_SETUP
]
# cluster groups
# Cluster-based groups
cluster_actions_groups = list(base_groups)
cluster_actions_groups.extend([cluster_actions_group.GROUP,
negative_cluster_actions_group.GROUP])
# instance groups
# Single-instance based groups
instance_create_groups = list(base_groups)
instance_create_groups.extend([instance_create_group.GROUP,
instance_delete_group.GROUP])
@ -140,8 +142,8 @@ instance_create_groups.extend([instance_create_group.GROUP,
backup_groups = list(instance_create_groups)
backup_groups.extend([backup_group.GROUP])
user_actions_groups = list(instance_create_groups)
user_actions_groups.extend([user_actions_group.GROUP])
configuration_groups = list(instance_create_groups)
configuration_groups.extend([configuration_group.GROUP])
database_actions_groups = list(instance_create_groups)
database_actions_groups.extend([database_actions_group.GROUP])
@ -155,40 +157,45 @@ instance_actions_groups.extend([instance_actions_group.GROUP])
replication_groups = list(instance_create_groups)
replication_groups.extend([replication_group.GROUP])
user_actions_groups = list(instance_create_groups)
user_actions_groups.extend([user_actions_group.GROUP])
# groups common to all datastores
common_groups = list(instance_actions_groups)
common_groups.extend([guest_log_groups])
# Module based groups
# Register: Module based groups
register(["backup"], backup_groups)
register(["cluster"], cluster_actions_groups)
register(["configuration"], configuration_groups)
register(["database"], database_actions_groups)
register(["guest_log"], guest_log_groups)
register(["instance", "instance_actions"], instance_actions_groups)
register(["instance_create"], instance_create_groups)
register(["user"], user_actions_groups)
register(["replication"], replication_groups)
register(["user"], user_actions_groups)
# Datastore based groups - these should contain all functionality
# currently supported by the datastore
# Register: Datastore based groups
# These should contain all functionality currently supported by the datastore
register(["db2_supported"], common_groups,
database_actions_groups, user_actions_groups)
register(["cassandra_supported"], common_groups,
backup_groups)
register(["couchbase_supported"], common_groups)
backup_groups, configuration_groups)
register(["couchbase_supported"], common_groups, backup_groups)
register(["couchdb_supported"], common_groups)
register(["postgresql_supported"], common_groups,
backup_groups, database_actions_groups, user_actions_groups)
register(["mongodb_supported"], common_groups,
backup_groups, cluster_actions_groups,
database_actions_groups, user_actions_groups)
register(["mysql_supported", "mariadb_supported", "percona_supported"],
backup_groups, database_actions_groups, configuration_groups,
user_actions_groups)
register(["mariadb_supported", "mysql_supported", "percona_supported"],
common_groups,
backup_groups, database_actions_groups,
backup_groups, configuration_groups, database_actions_groups,
replication_groups, user_actions_groups)
register(["mongodb_supported"], common_groups,
backup_groups, cluster_actions_groups, configuration_groups,
database_actions_groups, user_actions_groups)
register(["pxc_supported"], common_groups,
cluster_actions_groups)
register(["redis_supported"], common_groups,
backup_groups, replication_groups)
register(["vertica_supported"], common_groups,
cluster_actions_groups)
register(["pxc_supported"], common_groups,
cluster_actions_groups)
register(["db2_supported"], common_groups,
database_actions_groups, user_actions_groups)

View File

@ -0,0 +1,232 @@
# 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
# 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 proboscis import test
from trove.tests.scenario.groups import instance_create_group
from trove.tests.scenario.groups.test_group import TestGroup
GROUP = "scenario.configuration_group"
@test(depends_on_groups=[instance_create_group.GROUP], groups=[GROUP])
class ConfigurationGroup(TestGroup):
def __init__(self):
super(ConfigurationGroup, self).__init__(
'configuration_runners', 'ConfigurationRunner')
@test
def create_bad_group(self):
"""Ensure a group with bad entries fails create."""
self.test_runner.run_create_bad_group()
@test
def create_invalid_groups(self):
"""Ensure a group with invalid entries fails create."""
self.test_runner.run_create_invalid_groups()
@test
def delete_non_existent_group(self):
"""Ensure delete non-existent group fails."""
self.test_runner.run_delete_non_existent_group()
@test
def delete_bad_group_id(self):
"""Ensure delete bad group fails."""
self.test_runner.run_delete_bad_group_id()
@test
def attach_non_existent_group(self):
"""Ensure attach non-existent group fails."""
self.test_runner.run_attach_non_existent_group()
def attach_non_existent_group_to_non_existent_inst(self):
"""Ensure attach non-existent group to non-existent inst fails."""
self.test_runner.run_attach_non_existent_group_to_non_existent_inst()
@test
def detach_group_with_none_attached(self):
"""Test detach with none attached."""
self.test_runner.run_detach_group_with_none_attached()
@test
def create_dynamic_group(self):
"""Create a group with only dynamic entries."""
self.test_runner.run_create_dynamic_group()
@test
def create_non_dynamic_group(self):
"""Create a group with only non-dynamic entries."""
self.test_runner.run_create_non_dynamic_group()
@test(depends_on=[create_dynamic_group])
def attach_dynamic_group_to_non_existent_inst(self):
"""Ensure attach dynamic group to non-existent inst fails."""
self.test_runner.run_attach_dynamic_group_to_non_existent_inst()
@test(depends_on=[create_non_dynamic_group])
def attach_non_dynamic_group_to_non_existent_inst(self):
"""Ensure attach non-dynamic group to non-existent inst fails."""
self.test_runner.run_attach_non_dynamic_group_to_non_existent_inst()
@test(depends_on=[create_dynamic_group, create_non_dynamic_group])
def list_configuration_groups(self):
"""Test list configuration groups."""
self.test_runner.run_list_configuration_groups()
@test(depends_on=[create_dynamic_group])
def dynamic_configuration_show(self):
"""Test show on dynamic group."""
self.test_runner.run_dynamic_configuration_show()
@test(depends_on=[create_non_dynamic_group])
def non_dynamic_configuration_show(self):
"""Test show on non-dynamic group."""
self.test_runner.run_non_dynamic_configuration_show()
@test(depends_on=[create_dynamic_group])
def dynamic_conf_get_unauthorized_user(self):
"""Ensure show dynamic fails with unauthorized user."""
self.test_runner.run_dynamic_conf_get_unauthorized_user()
@test(depends_on=[create_non_dynamic_group])
def non_dynamic_conf_get_unauthorized_user(self):
"""Ensure show non-dynamic fails with unauthorized user."""
self.test_runner.run_non_dynamic_conf_get_unauthorized_user()
@test(depends_on=[create_dynamic_group],
runs_after=[list_configuration_groups])
def list_dynamic_inst_conf_groups_before(self):
"""Count list instances for dynamic group before attach."""
self.test_runner.run_list_dynamic_inst_conf_groups_before()
@test(depends_on=[create_dynamic_group],
runs_after=[list_dynamic_inst_conf_groups_before,
attach_non_existent_group,
detach_group_with_none_attached])
def attach_dynamic_group(self):
"""Test attach dynamic group."""
self.test_runner.run_attach_dynamic_group()
@test(depends_on=[attach_dynamic_group])
def list_dynamic_inst_conf_groups_after(self):
"""Test list instances for dynamic group after attach."""
self.test_runner.run_list_dynamic_inst_conf_groups_after()
@test(depends_on=[attach_dynamic_group],
runs_after=[list_dynamic_inst_conf_groups_after])
def attach_dynamic_group_again(self):
"""Ensure attaching dynamic group again fails."""
self.test_runner.run_attach_dynamic_group_again()
@test(depends_on=[attach_dynamic_group],
runs_after=[attach_dynamic_group_again])
def delete_attached_dynamic_group(self):
"""Ensure deleting attached dynamic group fails."""
self.test_runner.run_delete_attached_dynamic_group()
@test(depends_on=[attach_dynamic_group],
runs_after=[delete_attached_dynamic_group])
def update_dynamic_group(self):
"""Test update dynamic group."""
self.test_runner.run_update_dynamic_group()
@test(depends_on=[create_dynamic_group],
runs_after=[update_dynamic_group])
def detach_dynamic_group(self):
"""Test detach dynamic group."""
self.test_runner.run_detach_dynamic_group()
@test(depends_on=[create_non_dynamic_group],
runs_after=[detach_dynamic_group])
def list_non_dynamic_inst_conf_groups_before(self):
"""Count list instances for non-dynamic group before attach."""
self.test_runner.run_list_non_dynamic_inst_conf_groups_before()
@test(depends_on=[create_non_dynamic_group],
runs_after=[list_non_dynamic_inst_conf_groups_before,
attach_non_existent_group])
def attach_non_dynamic_group(self):
"""Test attach non-dynamic group."""
self.test_runner.run_attach_non_dynamic_group()
@test(depends_on=[attach_non_dynamic_group])
def list_non_dynamic_inst_conf_groups_after(self):
"""Test list instances for non-dynamic group after attach."""
self.test_runner.run_list_non_dynamic_inst_conf_groups_after()
@test(depends_on=[attach_non_dynamic_group],
runs_after=[list_non_dynamic_inst_conf_groups_after])
def attach_non_dynamic_group_again(self):
"""Ensure attaching non-dynamic group again fails."""
self.test_runner.run_attach_non_dynamic_group_again()
@test(depends_on=[attach_non_dynamic_group],
runs_after=[attach_non_dynamic_group_again])
def delete_attached_non_dynamic_group(self):
"""Ensure deleting attached non-dynamic group fails."""
self.test_runner.run_delete_attached_non_dynamic_group()
@test(depends_on=[attach_non_dynamic_group],
runs_after=[delete_attached_non_dynamic_group])
def update_non_dynamic_group(self):
"""Test update non-dynamic group."""
self.test_runner.run_update_non_dynamic_group()
@test(depends_on=[attach_non_dynamic_group],
runs_after=[update_non_dynamic_group])
def detach_non_dynamic_group(self):
"""Test detach non-dynamic group."""
self.test_runner.run_detach_non_dynamic_group()
@test(runs_after=[create_dynamic_group, create_non_dynamic_group,
update_dynamic_group, update_non_dynamic_group])
def create_instance_with_conf(self):
"""Test create instance with conf group."""
self.test_runner.run_create_instance_with_conf()
@test(depends_on=[create_instance_with_conf],
runs_after=[create_dynamic_group, create_non_dynamic_group,
update_dynamic_group, update_non_dynamic_group])
def wait_for_conf_instance(self):
"""Test create instance with conf group completes."""
self.test_runner.run_wait_for_conf_instance()
@test(depends_on=[wait_for_conf_instance])
def delete_conf_instance(self):
"""Test delete instance with conf group."""
self.test_runner.run_delete_conf_instance()
@test(depends_on=[create_dynamic_group],
runs_after=[list_configuration_groups, detach_dynamic_group,
dynamic_configuration_show,
dynamic_conf_get_unauthorized_user,
attach_dynamic_group_to_non_existent_inst,
delete_conf_instance])
def delete_dynamic_group(self):
"""Test delete dynamic group."""
self.test_runner.run_delete_dynamic_group()
@test(depends_on=[create_non_dynamic_group],
runs_after=[list_configuration_groups, detach_non_dynamic_group,
non_dynamic_configuration_show,
non_dynamic_conf_get_unauthorized_user,
attach_non_dynamic_group_to_non_existent_inst,
delete_conf_instance])
def delete_non_dynamic_group(self):
"""Test delete non-dynamic group."""
self.test_runner.run_delete_non_dynamic_group()

View File

@ -16,6 +16,7 @@
from proboscis import test
from trove.tests.scenario.groups import backup_group
from trove.tests.scenario.groups import configuration_group
from trove.tests.scenario.groups import database_actions_group
from trove.tests.scenario.groups import instance_actions_group
from trove.tests.scenario.groups import instance_create_group
@ -30,6 +31,7 @@ GROUP = "scenario.instance_delete_group"
@test(depends_on_groups=[instance_create_group.GROUP],
groups=[GROUP],
runs_after_groups=[backup_group.GROUP_BACKUP,
configuration_group.GROUP,
database_actions_group.GROUP,
instance_actions_group.GROUP,
replication_group.GROUP,

View File

@ -58,22 +58,40 @@ class TestGroup(object):
"""Try to load a datastore specific class if it exists; use the
default otherwise.
"""
try:
# This is for overridden Runner classes
impl = self._build_class_path(module_name, class_prefix, base_name)
return Strategy.get_strategy(impl, namespace)
except ImportError:
pass
try:
# This is for overridden Runner classes
impl = self._build_class_path(module_name,
class_prefix, base_name)
cls = self._load_class('runner', impl, namespace)
if not cls:
# This is for overridden Helper classes
module = module_name.replace('test', class_prefix.lower())
impl = self._build_class_path(module, class_prefix, base_name,
strip_test=True)
return Strategy.get_strategy(impl, namespace)
except ImportError:
cls = self._load_class('helper', impl, namespace)
if not cls:
# Just import the base class
impl = self._build_class_path(module_name, '', base_name)
return Strategy.get_strategy(impl, namespace)
cls = self._load_class(None, impl, namespace)
return cls
def _load_class(self, load_type, impl, namespace):
cls = None
if not load_type or load_type in impl.lower():
try:
cls = Strategy.get_strategy(impl, namespace)
except ImportError as ie:
# Only fail silently if it's something we expect,
# such as a missing override class. Anything else
# shouldn't be suppressed.
l_msg = ie.message.lower()
if load_type not in l_msg or (
'no module named' not in l_msg and
'cannot be found' not in l_msg):
raise
return cls
def _build_class_path(self, module_name, class_prefix, class_base,
strip_test=False):

View File

@ -124,6 +124,18 @@ class TestHelper(object):
self._build_data_fns()
#################
# Utility methods
#################
def get_class_name(self):
"""Builds a string of the expected class name, plus the actual one
being used if it's not the same.
"""
class_name_str = "'%s'" % self._expected_override_name
if self._expected_override_name != self.__class__.__name__:
class_name_str += ' (using %s)' % self.__class__.__name__
return class_name_str
################
# Client related
################
@ -135,7 +147,9 @@ class TestHelper(object):
return self.create_client(host, *args, **kwargs)
def create_client(self, host, *args, **kwargs):
"""Create a datastore client."""
"""Create a datastore client. This is datastore specific, so this
method should be overridden if datastore access is desired.
"""
raise SkipTest('No client defined')
def get_helper_credentials(self):
@ -336,6 +350,7 @@ class TestHelper(object):
def get_invalid_groups(self):
"""Return a list of configuration groups with invalid values.
An empty list indicates that no 'invalid' tests should be run.
"""
return []

View File

@ -0,0 +1,532 @@
# 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
# 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 datetime import datetime
import json
from proboscis import SkipTest
from trove.common.utils import generate_uuid
from trove.tests.config import CONFIG
from trove.tests.scenario.runners.test_runners import TestRunner
from trove.tests.util.check import CollectionCheck
from trove.tests.util.check import TypeCheck
from trove.tests.util import create_dbaas_client
from trove.tests.util.users import Requirements
from troveclient.compat import exceptions
class ConfigurationRunner(TestRunner):
def __init__(self):
super(ConfigurationRunner, self).__init__(sleep_time=10)
self.dynamic_group_name = 'dynamic_test_group'
self.dynamic_group_id = None
self.dynamic_inst_count = 0
self.non_dynamic_group_name = 'non_dynamic_test_group'
self.non_dynamic_group_id = None
self.non_dynamic_inst_count = 0
self.initial_group_count = 0
self.additional_group_count = 0
self.other_client = None
self.config_id_for_inst = None
self.config_inst_id = None
def run_create_bad_group(self,
expected_exception=exceptions.UnprocessableEntity,
expected_http_code=422):
bad_group = {'unknown_datastore_key': 'bad_value'}
self.assert_action_on_conf_group_failure(
bad_group, expected_exception, expected_http_code)
def assert_action_on_conf_group_failure(
self, group_values, expected_exception, expected_http_code):
json_def = json.dumps(group_values)
self.assert_raises(
expected_exception, expected_http_code,
self.auth_client.configurations.create,
'conf_group',
json_def,
'Group with Bad or Invalid entries',
datastore=self.instance_info.dbaas_datastore,
datastore_version=self.instance_info.dbaas_datastore_version)
def run_create_invalid_groups(
self, expected_exception=exceptions.UnprocessableEntity,
expected_http_code=422):
invalid_groups = self.test_helper.get_invalid_groups()
if invalid_groups:
for invalid_group in invalid_groups:
self.assert_action_on_conf_group_failure(
invalid_group,
expected_exception, expected_http_code)
elif invalid_groups is None:
raise SkipTest("No invalid configuration values defined in %s." %
self.test_helper.get_class_name())
else:
raise SkipTest("Datastore has no invalid configuration values.")
def run_delete_non_existent_group(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
self.assert_group_delete_failure(
None, expected_exception, expected_http_code)
def run_delete_bad_group_id(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
self.assert_group_delete_failure(
generate_uuid(), expected_exception, expected_http_code)
def run_attach_non_existent_group(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
self.assert_instance_modify_failure(
self.instance_info.id, generate_uuid(),
expected_exception, expected_http_code)
def run_attach_non_existent_group_to_non_existent_inst(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
self.assert_instance_modify_failure(
generate_uuid(), generate_uuid(),
expected_exception, expected_http_code)
def run_detach_group_with_none_attached(self,
expected_states=['ACTIVE'],
expected_http_code=202):
self.assert_instance_modify(
self.instance_info.id, None,
expected_states, expected_http_code)
# run again, just to make sure
self.assert_instance_modify(
self.instance_info.id, None,
expected_states, expected_http_code)
def run_create_dynamic_group(self, expected_http_code=200):
self.initial_group_count = len(self.auth_client.configurations.list())
values = self.test_helper.get_dynamic_group()
if values:
self.dynamic_group_id = self.assert_create_group(
self.dynamic_group_name,
'a fully dynamic group should not require restart',
values, expected_http_code)
self.additional_group_count += 1
elif values is None:
raise SkipTest("No dynamic group defined in %s." %
self.test_helper.get_class_name())
else:
raise SkipTest("Datastore has no dynamic configuration values.")
def assert_create_group(self, name, description, values,
expected_http_code):
json_def = json.dumps(values)
result = self.auth_client.configurations.create(
name,
json_def,
description,
datastore=self.instance_info.dbaas_datastore,
datastore_version=self.instance_info.dbaas_datastore_version)
self.assert_client_code(expected_http_code)
with TypeCheck('Configuration', result) as configuration:
configuration.has_field('name', basestring)
configuration.has_field('description', basestring)
configuration.has_field('values', dict)
configuration.has_field('datastore_name', basestring)
configuration.has_field('datastore_version_id', unicode)
configuration.has_field('datastore_version_name', basestring)
self.assert_equal(name, result.name)
self.assert_equal(description, result.description)
self.assert_equal(values, result.values)
return result.id
def run_create_non_dynamic_group(self, expected_http_code=200):
values = self.test_helper.get_non_dynamic_group()
if values:
self.non_dynamic_group_id = self.assert_create_group(
self.non_dynamic_group_name,
'a group containing non-dynamic properties should always '
'require restart',
values, expected_http_code)
self.additional_group_count += 1
elif values is None:
raise SkipTest("No non-dynamic group defined in %s." %
self.test_helper.get_class_name())
else:
raise SkipTest("Datastore has no non-dynamic configuration "
"values.")
def run_attach_dynamic_group_to_non_existent_inst(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
if self.dynamic_group_id:
self.assert_instance_modify_failure(
generate_uuid(), self.dynamic_group_id,
expected_exception, expected_http_code)
def run_attach_non_dynamic_group_to_non_existent_inst(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
if self.non_dynamic_group_id:
self.assert_instance_modify_failure(
generate_uuid(), self.non_dynamic_group_id,
expected_exception, expected_http_code)
def run_list_configuration_groups(self):
configuration_list = self.auth_client.configurations.list()
self.assert_configuration_list(
configuration_list,
self.initial_group_count + self.additional_group_count)
def assert_configuration_list(self, configuration_list, expected_count):
self.assert_equal(expected_count, len(configuration_list),
'Unexpected number of configurations found')
if expected_count:
configuration_names = [conf.name for conf in configuration_list]
if self.dynamic_group_id:
self.assert_true(
self.dynamic_group_name in configuration_names)
if self.non_dynamic_group_id:
self.assert_true(
self.non_dynamic_group_name in configuration_names)
def run_dynamic_configuration_show(self):
if self.dynamic_group_id:
self.assert_configuration_show(self.dynamic_group_id,
self.dynamic_group_name)
else:
raise SkipTest("No dynamic group created.")
def assert_configuration_show(self, config_id, config_name):
result = self.auth_client.configurations.get(config_id)
self.assert_equal(config_id, result.id, "Unexpected config id")
self.assert_equal(config_name, result.name, "Unexpected config name")
# check the result field types
with TypeCheck("configuration", result) as check:
check.has_field("id", basestring)
check.has_field("name", basestring)
check.has_field("description", basestring)
check.has_field("values", dict)
check.has_field("created", basestring)
check.has_field("updated", basestring)
check.has_field("instance_count", int)
# check for valid timestamps
self.assert_true(self._is_valid_timestamp(result.created),
'Created timestamp %s is invalid' % result.created)
self.assert_true(self._is_valid_timestamp(result.updated),
'Updated timestamp %s is invalid' % result.updated)
with CollectionCheck("configuration_values", result.values) as check:
# check each item has the correct type according to the rules
for (item_key, item_val) in result.values.iteritems():
print("item_key: %s" % item_key)
print("item_val: %s" % item_val)
param = (
self.auth_client.configuration_parameters.get_parameter(
self.instance_info.dbaas_datastore,
self.instance_info.dbaas_datastore_version,
item_key))
if param.type == 'integer':
check.has_element(item_key, int)
if param.type == 'string':
check.has_element(item_key, basestring)
if param.type == 'boolean':
check.has_element(item_key, bool)
def _is_valid_timestamp(self, time_string):
try:
datetime.strptime(time_string, "%Y-%m-%dT%H:%M:%S")
except ValueError:
return False
return True
def run_non_dynamic_configuration_show(self):
if self.non_dynamic_group_id:
self.assert_configuration_show(self.non_dynamic_group_id,
self.non_dynamic_group_name)
else:
raise SkipTest("No non-dynamic group created.")
def run_dynamic_conf_get_unauthorized_user(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
self.assert_conf_get_unauthorized_user(self.dynamic_group_id,
expected_exception,
expected_http_code)
def assert_conf_get_unauthorized_user(
self, config_id, expected_exception=exceptions.NotFound,
expected_http_code=404):
self._create_other_client()
self.assert_raises(
expected_exception, None,
self.other_client.configurations.get, config_id)
# we're using a different client, so we'll check the return code
# on it explicitly, instead of depending on 'assert_raises'
self.assert_client_code(expected_http_code, client=self.other_client)
def _create_other_client(self):
if not self.other_client:
requirements = Requirements(is_admin=False)
other_user = CONFIG.users.find_user(
requirements, black_list=[self.instance_info.user.auth_user])
self.other_client = create_dbaas_client(other_user)
def run_non_dynamic_conf_get_unauthorized_user(
self, expected_exception=exceptions.NotFound,
expected_http_code=404):
self.assert_conf_get_unauthorized_user(self.dynamic_group_id,
expected_exception,
expected_http_code)
def run_list_dynamic_inst_conf_groups_before(self):
if self.dynamic_group_id:
self.dynamic_inst_count = len(
self.auth_client.configurations.instances(
self.dynamic_group_id))
def assert_conf_instance_list(self, group_id, expected_count):
conf_instance_list = self.auth_client.configurations.instances(
group_id)
self.assert_equal(expected_count, len(conf_instance_list),
'Unexpected number of configurations found')
if expected_count:
conf_instance_ids = [inst.id for inst in conf_instance_list]
self.assert_true(
self.instance_info.id in conf_instance_ids)
def run_attach_dynamic_group(
self, expected_states=['ACTIVE'], expected_http_code=202):
if self.dynamic_group_id:
self.assert_instance_modify(
self.instance_info.id, self.dynamic_group_id,
expected_states, expected_http_code)
def run_list_dynamic_inst_conf_groups_after(self):
if self.dynamic_group_id:
self.assert_conf_instance_list(self.dynamic_group_id,
self.dynamic_inst_count + 1)
def run_attach_dynamic_group_again(
self, expected_exception=exceptions.BadRequest,
expected_http_code=400):
# The exception here should probably be UnprocessableEntity or
# something else other than BadRequest as the request really is
# valid.
if self.dynamic_group_id:
self.assert_instance_modify_failure(
self.instance_info.id, self.dynamic_group_id,
expected_exception, expected_http_code)
def run_delete_attached_dynamic_group(
self, expected_exception=exceptions.BadRequest,
expected_http_code=400):
# The exception here should probably be UnprocessableEntity or
# something else other than BadRequest as the request really is
# valid.
if self.dynamic_group_id:
self.assert_group_delete_failure(
self.dynamic_group_id, expected_exception, expected_http_code)
def run_update_dynamic_group(
self, expected_states=['ACTIVE'], expected_http_code=202):
if self.dynamic_group_id:
values = json.dumps(self.test_helper.get_dynamic_group())
self.assert_update_group(
self.instance_info.id, self.dynamic_group_id, values,
expected_states, expected_http_code)
def assert_update_group(
self, instance_id, group_id, values,
expected_states, expected_http_code, restart_inst=False):
self.auth_client.configurations.update(group_id, values)
self.assert_instance_action(
instance_id, expected_states, expected_http_code)
if restart_inst:
self._restart_instance(instance_id)
def run_detach_dynamic_group(
self, expected_states=['ACTIVE'], expected_http_code=202):
if self.dynamic_group_id:
self.assert_instance_modify(
self.instance_info.id, None,
expected_states, expected_http_code)
def run_list_non_dynamic_inst_conf_groups_before(self):
if self.non_dynamic_group_id:
self.non_dynamic_inst_count = len(
self.auth_client.configurations.instances(
self.non_dynamic_group_id))
def run_attach_non_dynamic_group(
self, expected_states=['RESTART_REQUIRED'],
expected_http_code=202):
if self.non_dynamic_group_id:
self.assert_instance_modify(
self.instance_info.id, self.non_dynamic_group_id,
expected_states, expected_http_code, restart_inst=True)
def run_list_non_dynamic_inst_conf_groups_after(self):
if self.non_dynamic_group_id:
self.assert_conf_instance_list(self.non_dynamic_group_id,
self.non_dynamic_inst_count + 1)
def run_attach_non_dynamic_group_again(
self, expected_exception=exceptions.BadRequest,
expected_http_code=400):
if self.non_dynamic_group_id:
self.assert_instance_modify_failure(
self.instance_info.id, self.non_dynamic_group_id,
expected_exception, expected_http_code)
def run_delete_attached_non_dynamic_group(
self, expected_exception=exceptions.BadRequest,
expected_http_code=400):
if self.non_dynamic_group_id:
self.assert_group_delete_failure(
self.non_dynamic_group_id, expected_exception,
expected_http_code)
def run_update_non_dynamic_group(
self, expected_states=['RESTART_REQUIRED'],
expected_http_code=202):
if self.non_dynamic_group_id:
values = json.dumps(self.test_helper.get_non_dynamic_group())
self.assert_update_group(
self.instance_info.id, self.non_dynamic_group_id, values,
expected_states, expected_http_code, restart_inst=True)
def run_detach_non_dynamic_group(
self, expected_states=['RESTART_REQUIRED'],
expected_http_code=202):
if self.non_dynamic_group_id:
self.assert_instance_modify(
self.instance_info.id, None, expected_states,
expected_http_code, restart_inst=True)
def assert_instance_modify(
self, instance_id, group_id, expected_states, expected_http_code,
restart_inst=False):
self.auth_client.instances.modify(instance_id, configuration=group_id)
self.assert_instance_action(
instance_id, expected_states, expected_http_code)
# Verify the group has been attached.
instance = self.get_instance(instance_id)
if group_id:
group = self.auth_client.configurations.get(group_id)
self.assert_equal(
group.id, instance.configuration['id'],
"Attached group does not have the expected ID")
self.assert_equal(
group.name, instance.configuration['name'],
"Attached group does not have the expected name")
else:
self.assert_false(
hasattr(instance, 'configuration'),
"The configuration group was not detached from the instance.")
if restart_inst:
self._restart_instance(instance_id)
def assert_instance_modify_failure(
self, instance_id, group_id, expected_exception,
expected_http_code):
self.assert_raises(
expected_exception, expected_http_code,
self.auth_client.instances.modify,
instance_id, configuration=group_id)
def run_delete_dynamic_group(self, expected_http_code=202):
if self.dynamic_group_id:
self.assert_group_delete(self.dynamic_group_id,
expected_http_code)
def assert_group_delete(self, group_id, expected_http_code):
self.auth_client.configurations.delete(group_id)
self.assert_client_code(expected_http_code)
def run_delete_non_dynamic_group(self, expected_http_code=202):
if self.non_dynamic_group_id:
self.assert_group_delete(self.non_dynamic_group_id,
expected_http_code)
def assert_group_delete_failure(self, group_id, expected_exception,
expected_http_code):
self.assert_raises(
expected_exception, expected_http_code,
self.auth_client.configurations.delete, group_id)
def _restart_instance(
self, instance_id, expected_states=['REBOOT', 'ACTIVE'],
expected_http_code=202):
self.auth_client.instances.restart(instance_id)
self.assert_instance_action(instance_id, expected_states,
expected_http_code)
def run_create_instance_with_conf(self):
self.config_id_for_inst = (
self.dynamic_group_id or self.non_dynamic_group_id)
if self.config_id_for_inst:
self.config_inst_id = self.assert_create_instance_with_conf(
self.config_id_for_inst)
else:
raise SkipTest("No groups (dynamic or non-dynamic) defined in %s."
% self.test_helper.get_class_name())
def assert_create_instance_with_conf(self, config_id):
# test that a new instance will apply the configuration on create
result = self.auth_client.instances.create(
"TEST_" + str(datetime.now()) + "_config",
self.instance_info.dbaas_flavor_href,
self.instance_info.volume,
[], [], availability_zone="nova",
configuration=config_id)
self.assert_client_code(200)
self.assert_equal("BUILD", result.status, 'Unexpected inst status')
return result.id
def run_wait_for_conf_instance(
# we can't specify all the states here, as it may go active
# before this test runs
self, final_state=['ACTIVE'],
expected_http_code=200):
if self.config_inst_id:
self.assert_instance_action(self.config_inst_id, final_state,
expected_http_code)
inst = self.auth_client.instances.get(self.config_inst_id)
self.assert_equal(self.config_id_for_inst,
inst.configuration['id'])
else:
raise SkipTest("No instance created with a configuration group.")
def run_delete_conf_instance(
self, expected_states=['SHUTDOWN'],
expected_http_code=202):
if self.config_inst_id:
self.assert_delete_conf_instance(
self.config_inst_id, expected_states, expected_http_code)
else:
raise SkipTest("No instance created with a configuration group.")
def assert_delete_conf_instance(
self, instance_id, expected_state, expected_http_code):
self.auth_client.instances.delete(instance_id)
self.assert_client_code(expected_http_code)
self.assert_all_gone(instance_id, expected_state)