diff --git a/trove/tests/int_tests.py b/trove/tests/int_tests.py index 5384a8eacb..ee9b06f06c 100644 --- a/trove/tests/int_tests.py +++ b/trove/tests/int_tests.py @@ -41,6 +41,7 @@ from trove.tests.scenario.groups import guest_log_group from trove.tests.scenario.groups import instance_actions_group from trove.tests.scenario.groups import instance_create_group from trove.tests.scenario.groups import instance_delete_group +from trove.tests.scenario.groups import instance_error_create_group from trove.tests.scenario.groups import module_group from trove.tests.scenario.groups import negative_cluster_actions_group from trove.tests.scenario.groups import replication_group @@ -142,6 +143,9 @@ instance_create_groups = list(base_groups) instance_create_groups.extend([instance_create_group.GROUP, instance_delete_group.GROUP]) +instance_error_create_groups = list(base_groups) +instance_error_create_groups.extend([instance_error_create_group.GROUP]) + backup_groups = list(instance_create_groups) backup_groups.extend([groups.BACKUP, groups.BACKUP_INST]) @@ -183,7 +187,8 @@ 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_groups]) +common_groups.extend([guest_log_groups, instance_error_create_groups, + module_groups]) # Register: Component based groups register(["backup"], backup_groups) @@ -195,6 +200,7 @@ 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(["instance_error_create"], instance_error_create_groups) register(["module"], module_groups) register(["module_create"], module_create_groups) register(["replication"], replication_groups) diff --git a/trove/tests/scenario/groups/__init__.py b/trove/tests/scenario/groups/__init__.py index fbd8970550..bdfa608c2e 100644 --- a/trove/tests/scenario/groups/__init__.py +++ b/trove/tests/scenario/groups/__init__.py @@ -76,6 +76,13 @@ INST_DELETE = "scenario.inst_delete_grp" INST_DELETE_WAIT = "scenario.inst_delete_wait_grp" +# Instance Error Create Group +INST_ERROR_CREATE = "scenario.inst_error_create_grp" +INST_ERROR_CREATE_WAIT = "scenario.inst_error_create_wait_grp" +INST_ERROR_DELETE = "scenario.inst_error_delete_grp" +INST_ERROR_DELETE_WAIT = "scenario.inst_error_delete_wait_grp" + + # Module Group MODULE_CREATE = "scenario.module_create_grp" MODULE_DELETE = "scenario.module_delete_grp" diff --git a/trove/tests/scenario/groups/database_actions_group.py b/trove/tests/scenario/groups/database_actions_group.py index 1262d055ca..ccd2fa6195 100644 --- a/trove/tests/scenario/groups/database_actions_group.py +++ b/trove/tests/scenario/groups/database_actions_group.py @@ -180,4 +180,4 @@ class DatabaseActionsInstDeleteWaitGroup(TestGroup): @test def wait_for_delete_initialized_instance(self): """Wait for the initialized instance to delete.""" - self.instance_create_runner.run_wait_for_error_init_delete() + self.instance_create_runner.run_wait_for_init_delete() diff --git a/trove/tests/scenario/groups/instance_create_group.py b/trove/tests/scenario/groups/instance_create_group.py index 958a925180..46a0356b57 100644 --- a/trove/tests/scenario/groups/instance_create_group.py +++ b/trove/tests/scenario/groups/instance_create_group.py @@ -55,16 +55,6 @@ class InstanceCreateGroup(TestGroup): """Create an instance with initial properties.""" self.test_runner.run_initialized_instance_create() - @test(runs_after=[create_initialized_instance]) - def create_error_instance(self): - """Create an instance in error state.""" - self.test_runner.run_create_error_instance() - - @test(runs_after=[create_error_instance]) - def create_error2_instance(self): - """Create another instance in error state.""" - self.test_runner.run_create_error2_instance() - @test(depends_on_groups=[groups.INST_CREATE], groups=[GROUP, groups.INST_CREATE_WAIT], @@ -77,27 +67,6 @@ class InstanceCreateWaitGroup(TestGroup): InstanceCreateRunnerFactory.instance()) @test - def wait_for_error_instances(self): - """Wait for the error instances to fail.""" - self.test_runner.run_wait_for_error_instances() - - @test(depends_on=[wait_for_error_instances]) - def validate_error_instance(self): - """Validate the error instance fault message.""" - self.test_runner.run_validate_error_instance() - - @test(depends_on=[wait_for_error_instances], - runs_after=[validate_error_instance]) - def validate_error2_instance(self): - """Validate the error2 instance fault message as admin.""" - self.test_runner.run_validate_error2_instance() - - @test(runs_after=[validate_error_instance, validate_error2_instance]) - def delete_error_instances(self): - """Delete the error instances.""" - self.test_runner.run_delete_error_instances() - - @test(runs_after=[delete_error_instances]) def wait_for_instances(self): """Waiting for all instances to become active.""" self.test_runner.run_wait_for_created_instances() @@ -129,6 +98,7 @@ class InstanceInitDeleteGroup(TestGroup): @test(depends_on_groups=[groups.INST_INIT_DELETE], + runs_after_groups=[groups.INST_ERROR_DELETE], groups=[GROUP, groups.INST_INIT_DELETE_WAIT]) class InstanceInitDeleteWaitGroup(TestGroup): """Test that Initialized Instance Delete Completes.""" @@ -138,11 +108,11 @@ class InstanceInitDeleteWaitGroup(TestGroup): InstanceCreateRunnerFactory.instance()) @test - def wait_for_error_init_delete(self): - """Wait for the initialized and error instances to be gone.""" - self.test_runner.run_wait_for_error_init_delete() + def wait_for_init_delete(self): + """Wait for the initialized instance to be gone.""" + self.test_runner.run_wait_for_init_delete() - @test(runs_after=[wait_for_error_init_delete]) + @test(runs_after=[wait_for_init_delete]) def delete_initial_configuration(self): """Delete the initial configuration group.""" self.test_runner.run_initial_configuration_delete() diff --git a/trove/tests/scenario/groups/instance_error_create_group.py b/trove/tests/scenario/groups/instance_error_create_group.py new file mode 100644 index 0000000000..888caf32a6 --- /dev/null +++ b/trove/tests/scenario/groups/instance_error_create_group.py @@ -0,0 +1,108 @@ +# Copyright 2016 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 import PRE_INSTANCES +from trove.tests.scenario import groups +from trove.tests.scenario.groups.test_group import TestGroup +from trove.tests.scenario.runners import test_runners + + +GROUP = "scenario.instance_error_create_group" + + +class InstanceErrorCreateRunnerFactory(test_runners.RunnerFactory): + + _runner_ns = 'instance_error_create_runners' + _runner_cls = 'InstanceErrorCreateRunner' + + +@test(depends_on_groups=["services.initialize"], + runs_after_groups=[PRE_INSTANCES, groups.INST_CREATE], + groups=[GROUP, groups.INST_ERROR_CREATE]) +class InstanceErrorCreateGroup(TestGroup): + """Test Instance Error Create functionality.""" + + def __init__(self): + super(InstanceErrorCreateGroup, self).__init__( + InstanceErrorCreateRunnerFactory.instance()) + + @test + def create_error_instance(self): + """Create an instance in error state.""" + self.test_runner.run_create_error_instance() + + @test(runs_after=[create_error_instance]) + def create_error2_instance(self): + """Create another instance in error state.""" + self.test_runner.run_create_error2_instance() + + +@test(depends_on_groups=[groups.INST_ERROR_CREATE], + groups=[GROUP, groups.INST_ERROR_CREATE_WAIT], + runs_after_groups=[groups.MODULE_CREATE, groups.CFGGRP_CREATE]) +class InstanceErrorCreateWaitGroup(TestGroup): + """Test that Instance Error Create Completes.""" + + def __init__(self): + super(InstanceErrorCreateWaitGroup, self).__init__( + InstanceErrorCreateRunnerFactory.instance()) + + @test + def wait_for_error_instances(self): + """Wait for the error instances to fail.""" + self.test_runner.run_wait_for_error_instances() + + @test(depends_on=[wait_for_error_instances]) + def validate_error_instance(self): + """Validate the error instance fault message.""" + self.test_runner.run_validate_error_instance() + + @test(depends_on=[wait_for_error_instances], + runs_after=[validate_error_instance]) + def validate_error2_instance(self): + """Validate the error2 instance fault message as admin.""" + self.test_runner.run_validate_error2_instance() + + +@test(depends_on_groups=[groups.INST_ERROR_CREATE_WAIT], + groups=[GROUP, groups.INST_ERROR_DELETE]) +class InstanceErrorDeleteGroup(TestGroup): + """Test Instance Error Delete functionality.""" + + def __init__(self): + super(InstanceErrorDeleteGroup, self).__init__( + InstanceErrorCreateRunnerFactory.instance()) + + @test + def delete_error_instances(self): + """Delete the error instances.""" + self.test_runner.run_delete_error_instances() + + +@test(depends_on_groups=[groups.INST_ERROR_DELETE], + groups=[GROUP, groups.INST_ERROR_DELETE_WAIT]) +class InstanceErrorDeleteWaitGroup(TestGroup): + """Test that Instance Error Delete Completes.""" + + def __init__(self): + super(InstanceErrorDeleteWaitGroup, self).__init__( + InstanceErrorCreateRunnerFactory.instance()) + + @test + def wait_for_error_delete(self): + """Wait for the error instances to be gone.""" + self.test_runner.run_wait_for_error_delete() diff --git a/trove/tests/scenario/groups/module_group.py b/trove/tests/scenario/groups/module_group.py index e116c6fa1e..4e58c380bd 100644 --- a/trove/tests/scenario/groups/module_group.py +++ b/trove/tests/scenario/groups/module_group.py @@ -286,6 +286,7 @@ class ModuleCreateGroup(TestGroup): @test(depends_on_groups=[groups.INST_CREATE_WAIT, groups.MODULE_CREATE], + runs_after_groups=[groups.INST_ERROR_DELETE], groups=[GROUP, groups.MODULE_INST, groups.MODULE_INST_CREATE]) class ModuleInstCreateGroup(TestGroup): """Test Module Instance Create functionality.""" diff --git a/trove/tests/scenario/groups/user_actions_group.py b/trove/tests/scenario/groups/user_actions_group.py index 4c44478b9b..db13e72c20 100644 --- a/trove/tests/scenario/groups/user_actions_group.py +++ b/trove/tests/scenario/groups/user_actions_group.py @@ -269,4 +269,4 @@ class UserActionsInstDeleteWaitGroup(TestGroup): @test def wait_for_delete_initialized_instance(self): """Wait for the initialized instance to delete.""" - self.instance_create_runner.run_wait_for_error_init_delete() + self.instance_create_runner.run_wait_for_init_delete() diff --git a/trove/tests/scenario/runners/instance_create_runners.py b/trove/tests/scenario/runners/instance_create_runners.py index ca0107e70a..bfb3ad8e42 100644 --- a/trove/tests/scenario/runners/instance_create_runners.py +++ b/trove/tests/scenario/runners/instance_create_runners.py @@ -28,8 +28,6 @@ class InstanceCreateRunner(TestRunner): def __init__(self): super(InstanceCreateRunner, self).__init__() - self.error_inst_id = None - self.error2_inst_id = None self.init_inst_id = None self.init_inst_dbs = None self.init_inst_users = None @@ -228,84 +226,6 @@ class InstanceCreateRunner(TestRunner): return instance_info - def run_create_error_instance( - self, expected_states=['BUILD', 'ERROR'], expected_http_code=200): - if self.is_using_existing_instance: - raise SkipTest("Using an existing instance.") - - name = self.instance_info.name + '_error' - flavor = self.get_instance_flavor(fault_num=1) - volume_size = self.instance_info.volume_size - - inst = self.assert_instance_create( - name, flavor, volume_size, [], [], None, None, - CONFIG.dbaas_datastore, CONFIG.dbaas_datastore_version, - expected_states, expected_http_code, create_helper_user=False) - self.assert_client_code(expected_http_code) - self.error_inst_id = inst.id - - def run_create_error2_instance( - self, expected_states=['BUILD', 'ERROR'], expected_http_code=200): - if self.is_using_existing_instance: - raise SkipTest("Using an existing instance.") - - name = self.instance_info.name + '_error2' - flavor = self.get_instance_flavor(fault_num=2) - volume_size = self.instance_info.volume_size - - inst = self.assert_instance_create( - name, flavor, volume_size, [], [], None, None, - CONFIG.dbaas_datastore, CONFIG.dbaas_datastore_version, - expected_states, expected_http_code, create_helper_user=False) - self.assert_client_code(expected_http_code) - self.error2_inst_id = inst.id - - def run_wait_for_error_instances(self, expected_states=['ERROR']): - error_ids = [] - if self.error_inst_id: - error_ids.append(self.error_inst_id) - if self.error2_inst_id: - error_ids.append(self.error2_inst_id) - - if error_ids: - self.assert_all_instance_states( - error_ids, expected_states, fast_fail_status=[]) - - def run_validate_error_instance(self): - if not self.error_inst_id: - raise SkipTest("No error instance created.") - - instance = self.get_instance(self.error_inst_id) - with CheckInstance(instance._info) as check: - check.fault() - - err_msg = "disk is too small for requested image" - self.assert_true(err_msg in instance.fault['message'], - "Message '%s' does not contain '%s'" % - (instance.fault['message'], err_msg)) - - def run_validate_error2_instance(self): - if not self.error2_inst_id: - raise SkipTest("No error2 instance created.") - - instance = self.get_instance( - self.error2_inst_id, client=self.admin_client) - with CheckInstance(instance._info) as check: - check.fault(is_admin=True) - - err_msg = "Quota exceeded for ram" - self.assert_true(err_msg in instance.fault['message'], - "Message '%s' does not contain '%s'" % - (instance.fault['message'], err_msg)) - - def run_delete_error_instances(self, expected_http_code=202): - if self.error_inst_id: - self.auth_client.instances.delete(self.error_inst_id) - self.assert_client_code(expected_http_code) - if self.error2_inst_id: - self.auth_client.instances.delete(self.error2_inst_id) - self.assert_client_code(expected_http_code) - def run_wait_for_created_instances( self, expected_states=['BUILD', 'ACTIVE']): instances = [self.instance_info.id] @@ -393,12 +313,8 @@ class InstanceCreateRunner(TestRunner): else: raise SkipTest("Cleanup is not required.") - def run_wait_for_error_init_delete(self, expected_states=['SHUTDOWN']): + def run_wait_for_init_delete(self, expected_states=['SHUTDOWN']): delete_ids = [] - if self.error_inst_id: - delete_ids.append(self.error_inst_id) - if self.error2_inst_id: - delete_ids.append(self.error2_inst_id) if self.init_inst_id: delete_ids.append(self.init_inst_id) if delete_ids: diff --git a/trove/tests/scenario/runners/instance_error_create_runners.py b/trove/tests/scenario/runners/instance_error_create_runners.py new file mode 100644 index 0000000000..279763a0c1 --- /dev/null +++ b/trove/tests/scenario/runners/instance_error_create_runners.py @@ -0,0 +1,118 @@ +# Copyright 2016 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 SkipTest + +from trove.tests.scenario.runners.test_runners import CheckInstance +from trove.tests.scenario.runners.test_runners import TestRunner + + +class InstanceErrorCreateRunner(TestRunner): + + def __init__(self): + super(InstanceErrorCreateRunner, self).__init__(sleep_time=1) + self.error_inst_id = None + self.error2_inst_id = None + + def run_create_error_instance(self, expected_http_code=200): + if self.is_using_existing_instance: + raise SkipTest("Using an existing instance.") + + name = self.instance_info.name + '_error' + flavor = self.get_instance_flavor(fault_num=1) + + inst = self.auth_client.instances.create( + name, + self.get_flavor_href(flavor), + self.instance_info.volume, + nics=self.instance_info.nics, + datastore=self.instance_info.dbaas_datastore, + datastore_version=self.instance_info.dbaas_datastore_version) + self.assert_client_code(expected_http_code) + self.error_inst_id = inst.id + + def run_create_error2_instance(self, expected_http_code=200): + if self.is_using_existing_instance: + raise SkipTest("Using an existing instance.") + + name = self.instance_info.name + '_error2' + flavor = self.get_instance_flavor(fault_num=2) + + inst = self.auth_client.instances.create( + name, + self.get_flavor_href(flavor), + self.instance_info.volume, + nics=self.instance_info.nics, + datastore=self.instance_info.dbaas_datastore, + datastore_version=self.instance_info.dbaas_datastore_version) + self.assert_client_code(expected_http_code) + self.error2_inst_id = inst.id + + def run_wait_for_error_instances(self, expected_states=['ERROR']): + error_ids = [] + if self.error_inst_id: + error_ids.append(self.error_inst_id) + if self.error2_inst_id: + error_ids.append(self.error2_inst_id) + + if error_ids: + self.assert_all_instance_states( + error_ids, expected_states, fast_fail_status=[]) + + def run_validate_error_instance(self): + if not self.error_inst_id: + raise SkipTest("No error instance created.") + + instance = self.get_instance(self.error_inst_id) + with CheckInstance(instance._info) as check: + check.fault() + + err_msg = "disk is too small for requested image" + self.assert_true(err_msg in instance.fault['message'], + "Message '%s' does not contain '%s'" % + (instance.fault['message'], err_msg)) + + def run_validate_error2_instance(self): + if not self.error2_inst_id: + raise SkipTest("No error2 instance created.") + + instance = self.get_instance( + self.error2_inst_id, client=self.admin_client) + with CheckInstance(instance._info) as check: + check.fault(is_admin=True) + + err_msg = "Quota exceeded for ram" + self.assert_true(err_msg in instance.fault['message'], + "Message '%s' does not contain '%s'" % + (instance.fault['message'], err_msg)) + + def run_delete_error_instances(self, expected_http_code=202): + if self.error_inst_id: + self.auth_client.instances.delete(self.error_inst_id) + self.assert_client_code(expected_http_code) + if self.error2_inst_id: + self.auth_client.instances.delete(self.error2_inst_id) + self.assert_client_code(expected_http_code) + + def run_wait_for_error_delete(self, expected_states=['SHUTDOWN']): + delete_ids = [] + if self.error_inst_id: + delete_ids.append(self.error_inst_id) + if self.error2_inst_id: + delete_ids.append(self.error2_inst_id) + if delete_ids: + self.assert_all_gone(delete_ids, expected_states[-1]) + else: + raise SkipTest("Cleanup is not required.")