diff --git a/trove/tests/int_tests.py b/trove/tests/int_tests.py index 091f708ec6..acd9ada7c0 100644 --- a/trove/tests/int_tests.py +++ b/trove/tests/int_tests.py @@ -142,10 +142,12 @@ instance_create_groups.extend([instance_create_group.GROUP, instance_delete_group.GROUP]) backup_groups = list(instance_create_groups) -backup_groups.extend([backup_group.GROUP]) +backup_groups.extend([backup_group.GROUP_BACKUP, + backup_group.GROUP_RESTORE]) -incremental_backup_groups = list(instance_create_groups) -incremental_backup_groups.extend([backup_group.GROUP_INCREMENTAL]) +backup_incremental_groups = list(backup_groups) +backup_incremental_groups.extend([backup_group.GROUP_INC_BACKUP, + backup_group.GROUP_INC_RESTORE]) configuration_groups = list(instance_create_groups) configuration_groups.extend([configuration_group.GROUP]) @@ -181,7 +183,7 @@ common_groups.extend([guest_log_groups, module_groups]) # Register: Component based groups register(["backup"], backup_groups) -register(["incremental_backup"], incremental_backup_groups) +register(["backup_incremental"], backup_incremental_groups) register(["cluster"], cluster_actions_groups) register(["configuration"], configuration_groups) register(["database"], database_actions_groups) @@ -208,10 +210,11 @@ register(["couchdb_supported"], common_groups, backup_groups, register(["postgresql_supported"], common_groups, backup_groups, database_actions_groups, configuration_groups, root_actions_groups, user_actions_groups, - incremental_backup_groups) + backup_incremental_groups) register(["mysql_supported", "percona_supported"], common_groups, backup_groups, configuration_groups, database_actions_groups, - replication_groups, root_actions_groups, user_actions_groups) + replication_groups, root_actions_groups, user_actions_groups, + backup_incremental_groups) register(["mariadb_supported"], common_groups, backup_groups, cluster_actions_groups, configuration_groups, database_actions_groups, replication_groups, root_actions_groups, diff --git a/trove/tests/scenario/groups/backup_group.py b/trove/tests/scenario/groups/backup_group.py index ebd10cddbf..d9be87e5ed 100644 --- a/trove/tests/scenario/groups/backup_group.py +++ b/trove/tests/scenario/groups/backup_group.py @@ -22,8 +22,22 @@ from trove.tests.scenario.runners import test_runners GROUP = "scenario.backup_restore_group" GROUP_BACKUP = "scenario.backup_group" -GROUP_BACKUP_LIST = "scenario.backup_list_group" +GROUP_BACKUP_CREATE = "scenario.backup_create_group" +GROUP_BACKUP_DELETE = "scenario.backup_delete_group" GROUP_RESTORE = "scenario.restore_group" +GROUP_RESTORE_CREATE = "scenario.restore_create_group" +GROUP_RESTORE_CREATE_WAIT = "scenario.restore_create_wait_group" +GROUP_RESTORE_DELETE = "scenario.restore_delete_group" +GROUP_RESTORE_DELETE_WAIT = "scenario.restore_delete_wait_group" + +GROUP_INC_BACKUP = "scenario.inc_backup_group" +GROUP_INC_BACKUP_CREATE = "scenario.inc_backup_create_group" +GROUP_INC_BACKUP_DELETE = "scenario.inc_backup_delete_group" +GROUP_INC_RESTORE = "scenario.inc_restore_group" +GROUP_INC_RESTORE_CREATE = "scenario.inc_restore_create_group" +GROUP_INC_RESTORE_CREATE_WAIT = "scenario.inc_restore_create_wait_group" +GROUP_INC_RESTORE_DELETE = "scenario.inc_restore_delete_group" +GROUP_INC_RESTORE_DELETE_WAIT = "scenario.inc_restore_delete_wait_group" GROUP_INCREMENTAL = "scenario.incremental_backup_restore_group" GROUP_INCREMENTAL_BACKUP = "scenario.incremental_backup_group" @@ -36,166 +50,354 @@ class BackupRunnerFactory(test_runners.RunnerFactory): _runner_cls = 'BackupRunner' -class IncrementalBackupRunnerFactory(test_runners.RunnerFactory): - - _runner_ns = 'backup_runners' - _runner_cls = 'IncrementalBackupRunner' - - -@test(depends_on_groups=[instance_create_group.GROUP], groups=[GROUP]) +@test(depends_on_groups=[instance_create_group.GROUP], + groups=[GROUP, GROUP_BACKUP, GROUP_BACKUP_CREATE]) class BackupGroup(TestGroup): - """Test Backup and Restore functionality.""" + """Test Backup functionality.""" def __init__(self): super(BackupGroup, self).__init__( BackupRunnerFactory.instance()) - @test(groups=[GROUP_BACKUP]) - def backup_create_instance_invalid(self): - """Ensure create backup fails with invalid instance id.""" - self.test_runner.run_backup_create_instance_invalid() - - @test(groups=[GROUP_BACKUP]) - def backup_create_instance_not_found(self): - """Ensure create backup fails with unknown instance id.""" - self.test_runner.run_backup_create_instance_not_found() - - @test(groups=[GROUP_BACKUP]) + @test def add_data_for_backup(self): """Add data to instance for restore verification.""" self.test_runner.run_add_data_for_backup() - @test(groups=[GROUP_BACKUP], - runs_after=[add_data_for_backup]) + @test(runs_after=[add_data_for_backup]) def verify_data_for_backup(self): """Verify data in instance.""" self.test_runner.run_verify_data_for_backup() - @test(groups=[GROUP_BACKUP], - runs_after=[verify_data_for_backup]) + @test(runs_after=[verify_data_for_backup]) + def save_backup_counts(self): + """Store the existing backup counts.""" + self.test_runner.run_save_backup_counts() + + @test(runs_after=[save_backup_counts]) def backup_create(self): """Check that create backup is started successfully.""" self.test_runner.run_backup_create() - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create]) + @test(depends_on=[backup_create]) def backup_delete_while_backup_running(self): """Ensure delete backup fails while it is running.""" self.test_runner.run_backup_delete_while_backup_running() - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create], + @test(depends_on=[backup_create], runs_after=[backup_delete_while_backup_running]) def restore_instance_from_not_completed_backup(self): """Ensure a restore fails while the backup is running.""" self.test_runner.run_restore_instance_from_not_completed_backup() - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create], + @test(depends_on=[backup_create], runs_after=[restore_instance_from_not_completed_backup]) def backup_create_another_backup_running(self): """Ensure create backup fails when another backup is running.""" self.test_runner.run_backup_create_another_backup_running() - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create], + @test(depends_on=[backup_create], runs_after=[backup_create_another_backup_running]) def instance_action_right_after_backup_create(self): """Ensure any instance action fails while backup is running.""" self.test_runner.run_instance_action_right_after_backup_create() - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create], - runs_after=[instance_action_right_after_backup_create]) - def backup_create_completed(self): - """Check that the backup completes successfully.""" - self.test_runner.run_backup_create_completed() - - @test(groups=[GROUP_BACKUP, GROUP_BACKUP_LIST], - depends_on=[backup_create_completed]) - def backup_list(self): - """Test list backups.""" - self.test_runner.run_backup_list() - - @test(groups=[GROUP_BACKUP, GROUP_BACKUP_LIST], - depends_on=[backup_create_completed]) - def backup_list_filter_datastore(self): - """Test list backups and filter by datastore.""" - self.test_runner.run_backup_list_filter_datastore() - - @test(groups=[GROUP_BACKUP, GROUP_BACKUP_LIST], - depends_on=[backup_create_completed]) - def backup_list_filter_different_datastore(self): - """Test list backups and filter by different datastore.""" - self.test_runner.run_backup_list_filter_different_datastore() - - @test(groups=[GROUP_BACKUP, GROUP_BACKUP_LIST], - depends_on=[backup_create_completed]) - def backup_list_filter_datastore_not_found(self): - """Test list backups and filter by unknown datastore.""" - self.test_runner.run_backup_list_filter_datastore_not_found() - - @test(groups=[GROUP_BACKUP, GROUP_BACKUP_LIST], - depends_on=[backup_create_completed]) - def backup_list_for_instance(self): - """Test backup list for instance.""" - self.test_runner.run_backup_list_for_instance() - - @test(groups=[GROUP_BACKUP, GROUP_BACKUP_LIST], - depends_on=[backup_create_completed]) - def backup_get(self): - """Test backup show.""" - self.test_runner.run_backup_get() - - @test(groups=[GROUP_BACKUP, GROUP_BACKUP_LIST], - depends_on=[backup_create_completed]) - def backup_get_unauthorized_user(self): - """Ensure backup show fails for an unauthorized user.""" - self.test_runner.run_backup_get_unauthorized_user() - - @test(groups=[GROUP_RESTORE], - depends_on=[backup_create_completed], - runs_after_groups=[GROUP_BACKUP_LIST]) - def restore_from_backup(self): - """Check that restoring an instance from a backup starts.""" - self.test_runner.run_restore_from_backup() - - @test(groups=[GROUP_RESTORE], - depends_on=[restore_from_backup]) - def restore_from_backup_completed(self): - """Wait until restoring an instance from a backup completes.""" - self.test_runner.run_restore_from_backup_completed() - - @test(groups=[GROUP_RESTORE], - depends_on=[restore_from_backup_completed]) - def verify_data_in_restored_instance(self): - """Verify data in restored instance.""" - self.test_runner.run_verify_data_in_restored_instance() - - @test(groups=[GROUP_RESTORE], - depends_on=[restore_from_backup_completed], - runs_after=[verify_data_in_restored_instance]) - def delete_restored_instance(self): - """Test deleting the restored instance.""" - self.test_runner.run_delete_restored_instance() - - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create_completed], - runs_after=[delete_restored_instance]) + @test def delete_unknown_backup(self): """Ensure deleting an unknown backup fails.""" self.test_runner.run_delete_unknown_backup() - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create_completed], - runs_after=[delete_unknown_backup]) + @test + def backup_create_instance_invalid(self): + """Ensure create backup fails with invalid instance id.""" + self.test_runner.run_backup_create_instance_invalid() + + @test + def backup_create_instance_not_found(self): + """Ensure create backup fails with unknown instance id.""" + self.test_runner.run_backup_create_instance_not_found() + + @test(depends_on=[backup_create], + runs_after=[delete_unknown_backup, backup_create_instance_invalid, + backup_create_instance_not_found]) + def backup_create_completed(self): + """Check that the backup completes successfully.""" + self.test_runner.run_backup_create_completed() + + @test(depends_on=[backup_create_completed]) + def instance_goes_active(self): + """Check that the instance goes active after the backup.""" + self.test_runner.run_instance_goes_active() + + @test(depends_on=[backup_create_completed]) + def backup_list(self): + """Test list backups.""" + self.test_runner.run_backup_list() + + @test(depends_on=[backup_create_completed]) + def backup_list_filter_datastore(self): + """Test list backups and filter by datastore.""" + self.test_runner.run_backup_list_filter_datastore() + + @test(depends_on=[backup_create_completed]) + def backup_list_filter_different_datastore(self): + """Test list backups and filter by different datastore.""" + self.test_runner.run_backup_list_filter_different_datastore() + + @test(depends_on=[backup_create_completed]) + def backup_list_filter_datastore_not_found(self): + """Test list backups and filter by unknown datastore.""" + self.test_runner.run_backup_list_filter_datastore_not_found() + + @test(depends_on=[backup_create_completed]) + def backup_list_for_instance(self): + """Test backup list for instance.""" + self.test_runner.run_backup_list_for_instance() + + @test(depends_on=[backup_create_completed]) + def backup_get(self): + """Test backup show.""" + self.test_runner.run_backup_get() + + @test(depends_on=[backup_create_completed]) + def backup_get_unauthorized_user(self): + """Ensure backup show fails for an unauthorized user.""" + self.test_runner.run_backup_get_unauthorized_user() + + +@test(depends_on_groups=[GROUP_BACKUP_CREATE], + groups=[GROUP, GROUP_INC_BACKUP, GROUP_INC_BACKUP_CREATE]) +class BackupIncGroup(TestGroup): + """Test Incremental Backup functionality.""" + + def __init__(self): + super(BackupIncGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def add_data_for_inc_backup_1(self): + """Add data to instance for inc backup 1.""" + self.test_runner.run_add_data_for_inc_backup_1() + + @test(depends_on=[add_data_for_inc_backup_1]) + def verify_data_for_inc_backup_1(self): + """Verify data in instance for inc backup 1.""" + self.test_runner.run_verify_data_for_inc_backup_1() + + @test(depends_on=[verify_data_for_inc_backup_1]) + def inc_backup_1(self): + """Run incremental backup 1.""" + self.test_runner.run_inc_backup_1() + + @test(depends_on=[inc_backup_1]) + def wait_for_inc_backup_1(self): + """Check that inc backup 1 completes successfully.""" + self.test_runner.run_wait_for_inc_backup_1() + + @test(depends_on=[wait_for_inc_backup_1]) + def add_data_for_inc_backup_2(self): + """Add data to instance for inc backup 2.""" + self.test_runner.run_add_data_for_inc_backup_2() + + @test(depends_on=[add_data_for_inc_backup_2]) + def verify_data_for_inc_backup_2(self): + """Verify data in instance for inc backup 2.""" + self.test_runner.run_verify_data_for_inc_backup_2() + + @test(depends_on=[wait_for_inc_backup_1], + runs_after=[verify_data_for_inc_backup_2]) + def instance_goes_active_inc_1(self): + """Check that the instance goes active after the inc 1 backup.""" + self.test_runner.run_instance_goes_active() + + @test(depends_on=[verify_data_for_inc_backup_2], + runs_after=[instance_goes_active_inc_1]) + def inc_backup_2(self): + """Run incremental backup 2.""" + self.test_runner.run_inc_backup_2() + + @test(depends_on=[inc_backup_2]) + def wait_for_inc_backup_2(self): + """Check that inc backup 2 completes successfully.""" + self.test_runner.run_wait_for_inc_backup_2() + + @test(depends_on=[wait_for_inc_backup_2]) + def instance_goes_active_inc_2(self): + """Check that the instance goes active after the inc 2 backup.""" + self.test_runner.run_instance_goes_active() + + +@test(depends_on_groups=[GROUP_BACKUP_CREATE], + groups=[GROUP, GROUP_RESTORE, GROUP_RESTORE_CREATE]) +class RestoreCreateGroup(TestGroup): + """Test Restore Create functionality.""" + + def __init__(self): + super(RestoreCreateGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def restore_from_backup(self): + """Check that restoring an instance from a backup starts.""" + self.test_runner.run_restore_from_backup() + + +@test(depends_on_groups=[GROUP_INC_BACKUP_CREATE], + groups=[GROUP, GROUP_INC_RESTORE, GROUP_INC_RESTORE_CREATE], + runs_after_groups=[GROUP_RESTORE_CREATE]) +class RestoreIncCreateGroup(TestGroup): + """Test Restore Incremental Create functionality.""" + + def __init__(self): + super(RestoreIncCreateGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def restore_from_inc_1_backup(self): + """Check that restoring an instance from inc 1 backup starts.""" + self.test_runner.run_restore_from_inc_1_backup() + + +@test(depends_on_groups=[GROUP_RESTORE_CREATE], + groups=[GROUP, GROUP_RESTORE, GROUP_RESTORE_CREATE_WAIT], + runs_after_groups=[GROUP_INC_RESTORE_CREATE]) +class RestoreCreateWaitGroup(TestGroup): + """Test Restore Create completes.""" + + def __init__(self): + super(RestoreCreateWaitGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def restore_from_backup_completed(self): + """Wait until restoring an instance from a backup completes.""" + self.test_runner.run_restore_from_backup_completed() + + @test(depends_on=[restore_from_backup_completed]) + def verify_data_in_restored_instance(self): + """Verify data in restored instance.""" + self.test_runner.run_verify_data_in_restored_instance() + + +@test(depends_on_groups=[GROUP_INC_RESTORE_CREATE], + groups=[GROUP, GROUP_INC_RESTORE, GROUP_INC_RESTORE_CREATE_WAIT], + runs_after_groups=[GROUP_RESTORE_CREATE]) +class RestoreIncCreateWaitGroup(TestGroup): + """Test Restore Incremental Create completes.""" + + def __init__(self): + super(RestoreIncCreateWaitGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def restore_from_inc_1_backup_completed(self): + """Wait until restoring an inst from inc 1 backup completes.""" + self.test_runner.run_restore_from_inc_1_backup_completed() + + @test(depends_on=[restore_from_inc_1_backup_completed]) + def verify_data_in_restored_inc_1_instance(self): + """Verify data in restored inc 1 instance.""" + self.test_runner.run_verify_data_in_restored_inc_1_instance() + + +@test(depends_on_groups=[GROUP_RESTORE_CREATE_WAIT], + groups=[GROUP, GROUP_RESTORE, GROUP_RESTORE_DELETE], + runs_after_groups=[GROUP_INC_RESTORE_CREATE_WAIT]) +class RestoreDeleteGroup(TestGroup): + """Test Restore Delete functionality.""" + + def __init__(self): + super(RestoreDeleteGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def delete_restored_instance(self): + """Test deleting the restored instance.""" + self.test_runner.run_delete_restored_instance() + + +@test(depends_on_groups=[GROUP_INC_RESTORE_CREATE_WAIT], + groups=[GROUP, GROUP_INC_RESTORE, GROUP_INC_RESTORE_DELETE], + runs_after_groups=[GROUP_RESTORE_DELETE]) +class RestoreIncDeleteGroup(TestGroup): + """Test Restore Incremental Delete functionality.""" + + def __init__(self): + super(RestoreIncDeleteGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def delete_restored_inc_1_instance(self): + """Test deleting the restored inc 1 instance.""" + self.test_runner.run_delete_restored_inc_1_instance() + + +@test(depends_on_groups=[GROUP_RESTORE_DELETE], + groups=[GROUP, GROUP_RESTORE, GROUP_RESTORE_DELETE_WAIT]) +class RestoreDeleteWaitGroup(TestGroup): + """Test Restore Delete completes.""" + + def __init__(self): + super(RestoreDeleteWaitGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def wait_for_restored_instance_delete(self): + """Wait until deleting the restored instance completes.""" + self.test_runner.run_wait_for_restored_instance_delete() + + +@test(depends_on_groups=[GROUP_INC_RESTORE_DELETE], + groups=[GROUP, GROUP_INC_RESTORE, GROUP_INC_RESTORE_DELETE_WAIT], + runs_after_groups=[GROUP_RESTORE_DELETE_WAIT]) +class RestoreIncDeleteWaitGroup(TestGroup): + """Test Restore Incremental Delete completes.""" + + def __init__(self): + super(RestoreIncDeleteWaitGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def wait_for_restored_inc_1_instance_delete(self): + """Wait until deleting the restored inc 1 instance completes.""" + self.test_runner.run_wait_for_restored_inc_1_instance_delete() + + +@test(depends_on_groups=[GROUP_INC_BACKUP_CREATE], + groups=[GROUP, GROUP_INC_BACKUP, GROUP_INC_BACKUP_DELETE], + runs_after_groups=[GROUP_INC_RESTORE_DELETE_WAIT]) +class BackupIncDeleteGroup(TestGroup): + """Test Backup Incremental Delete functionality.""" + + def __init__(self): + super(BackupIncDeleteGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test + def delete_inc_2_backup(self): + """Test deleting the inc 2 backup.""" + # We only delete the inc 2 backup, as the inc 1 should be deleted + # by the full backup delete. + self.test_runner.run_delete_inc_2_backup() + + +@test(depends_on_groups=[GROUP_BACKUP_CREATE], + groups=[GROUP, GROUP_BACKUP, GROUP_BACKUP_DELETE], + runs_after_groups=[GROUP_INC_BACKUP_DELETE, + GROUP_RESTORE_DELETE_WAIT]) +class BackupDeleteGroup(TestGroup): + """Test Backup Delete functionality.""" + + def __init__(self): + super(BackupDeleteGroup, self).__init__( + BackupRunnerFactory.instance()) + + @test def delete_backup_unauthorized_user(self): """Ensure deleting backup by an unauthorized user fails.""" self.test_runner.run_delete_backup_unauthorized_user() - @test(groups=[GROUP_BACKUP], - depends_on=[backup_create_completed], - runs_after=[delete_backup_unauthorized_user]) + @test(runs_after=[delete_backup_unauthorized_user]) def delete_backup(self): """Test deleting the backup.""" self.test_runner.run_delete_backup() @@ -205,42 +407,7 @@ class BackupGroup(TestGroup): """Test that backup children are deleted.""" self.test_runner.run_check_for_incremental_backup() - -@test(depends_on_groups=[instance_create_group.GROUP], - groups=[GROUP_INCREMENTAL]) -class IncrementalBackupGroup(TestGroup): - """Test Incremental Backup and Restore functionality.""" - - def __init__(self): - super(IncrementalBackupGroup, self).__init__( - IncrementalBackupRunnerFactory.instance()) - - @test(groups=[GROUP_INCREMENTAL_BACKUP]) - def backup_run_single_incremental(self): - """Run a full and a single incremental backup""" - self.test_runner.run_backup_incremental(increments=1) - - @test(groups=[GROUP_INCREMENTAL_BACKUP], - depends_on=[backup_run_single_incremental]) - def restore_from_incremental(self): - """Launch a restore from a single incremental backup""" - self.test_runner.run_restore_from_incremental(increment=1) - - @test(groups=[GROUP_INCREMENTAL_RESTORE], - depends_on=[restore_from_incremental]) - def restore_from_backup_completed(self): - """Wait until restoring an instance from an incr. backup completes.""" - self.test_runner.run_restore_from_backup_completed() - - @test(groups=[GROUP_INCREMENTAL_RESTORE], - depends_on=[restore_from_backup_completed]) - def verify_data_in_restored_instance(self): - """Verify data in restored instance.""" - self.test_runner.run_verify_data_in_restored_instance() - - @test(groups=[GROUP_INCREMENTAL_RESTORE], - depends_on=[restore_from_backup_completed], - runs_after=[verify_data_in_restored_instance]) - def delete_restored_instance(self): - """Test deleting the restored instance.""" - self.test_runner.run_delete_restored_instance() + @test + def remove_backup_data_from_instance(self): + """Remove the backup data from the original instance.""" + self.test_runner.run_remove_backup_data_from_instance() diff --git a/trove/tests/scenario/runners/backup_runners.py b/trove/tests/scenario/runners/backup_runners.py index 15770ac552..fef7ba596d 100644 --- a/trove/tests/scenario/runners/backup_runners.py +++ b/trove/tests/scenario/runners/backup_runners.py @@ -112,8 +112,7 @@ class BackupRunner(BackupRunnerMixin): self.TIMEOUT_BACKUP_CREATE = 60 * 30 self.TIMEOUT_BACKUP_DELETE = 120 - super(BackupRunner, self).__init__(sleep_time=20, - timeout=self.TIMEOUT_BACKUP_CREATE) + super(BackupRunner, self).__init__(timeout=self.TIMEOUT_BACKUP_CREATE) self.BACKUP_NAME = 'backup_test' self.BACKUP_DESC = 'test description' @@ -124,10 +123,13 @@ class BackupRunner(BackupRunnerMixin): self.backup_count_for_ds_prior_to_create = 0 self.backup_count_for_instance_prior_to_create = 0 - self.incremental_backup_info = None - self.restore_instance_id = 0 + self.backup_inc_1_info = None + self.backup_inc_2_info = None + self.data_types_added = [] + self.restore_instance_id = None self.restore_host = None - self.other_client = None + self.restore_inc_1_instance_id = None + self.restore_inc_1_host = None def run_backup_create_instance_invalid( self, expected_exception=exceptions.BadRequest, @@ -148,18 +150,25 @@ class BackupRunner(BackupRunnerMixin): def run_add_data_for_backup(self): self.backup_host = self.get_instance_host() - self.assert_add_data_for_backup(self.backup_host) + self.assert_add_data_for_backup(self.backup_host, DataType.large) - def assert_add_data_for_backup(self, host): + def assert_add_data_for_backup(self, host, data_type): """In order for this to work, the corresponding datastore - 'helper' class should implement the 'add_large_data' method. + 'helper' class should implement the 'add_actual_data' method. """ - self.test_helper.add_data(DataType.large, host) + self.test_helper.add_data(data_type, host) + self.data_types_added.append(data_type) - def run_backup_create(self): - self.assert_backup_create() + def run_verify_data_for_backup(self): + self.assert_verify_backup_data(self.backup_host, DataType.large) - def assert_backup_create(self): + def assert_verify_backup_data(self, host, data_type): + """In order for this to work, the corresponding datastore + 'helper' class should implement the 'verify_actual_data' method. + """ + self.test_helper.verify_data(data_type, host) + + def run_save_backup_counts(self): # Necessary to test that the count increases. self.backup_count_prior_to_create = len( self.auth_client.backups.list()) @@ -169,20 +178,26 @@ class BackupRunner(BackupRunnerMixin): self.backup_count_for_instance_prior_to_create = len( self.auth_client.instances.backups(self.instance_info.id)) + def run_backup_create(self): + self.backup_info = self.assert_backup_create( + self.BACKUP_NAME, self.BACKUP_DESC, self.instance_info.id) + + def assert_backup_create(self, name, desc, instance_id, parent_id=None): result = self.auth_client.backups.create( - self.BACKUP_NAME, self.instance_info.id, self.BACKUP_DESC) - self.backup_info = result - self.assert_equal(self.BACKUP_NAME, result.name, + name, instance_id, desc, parent_id=parent_id) + self.assert_equal(name, result.name, 'Unexpected backup name') - self.assert_equal(self.BACKUP_DESC, result.description, + self.assert_equal(desc, result.description, 'Unexpected backup description') - self.assert_equal(self.instance_info.id, result.instance_id, + self.assert_equal(instance_id, result.instance_id, 'Unexpected instance ID for backup') self.assert_equal('NEW', result.status, 'Unexpected status for backup') - instance = self.auth_client.instances.get( - self.instance_info.id) + if parent_id: + self.assert_equal(parent_id, result.parent_id, + 'Unexpected status for backup') + instance = self.auth_client.instances.get(instance_id) datastore_version = self.auth_client.datastore_versions.get( self.instance_info.dbaas_datastore, self.instance_info.dbaas_datastore_version) @@ -197,6 +212,7 @@ class BackupRunner(BackupRunnerMixin): 'Unexpected datastore version') self.assert_equal(datastore_version.id, result.datastore['version_id'], 'Unexpected datastore version id') + return result def run_restore_instance_from_not_completed_backup( self, expected_exception=exceptions.Conflict, @@ -243,6 +259,9 @@ class BackupRunner(BackupRunnerMixin): poll_until(_result_is_active, time_out=self.TIMEOUT_BACKUP_CREATE) + def run_instance_goes_active(self, expected_states=['BACKUP', 'ACTIVE']): + self._assert_instance_states(self.instance_info.id, expected_states) + def run_backup_list(self): backup_list = self.auth_client.backups.list() self.assert_backup_list( @@ -314,8 +333,119 @@ class BackupRunner(BackupRunnerMixin): self.assert_client_code(expected_http_code=expected_http_code, client=self.unauth_client) - def run_restore_from_backup(self): - self.assert_restore_from_backup(self.backup_info.id) + def run_add_data_for_inc_backup_1(self): + self.backup_host = self.get_instance_host() + self.assert_add_data_for_backup(self.backup_host, DataType.tiny) + + def run_verify_data_for_inc_backup_1(self): + self.assert_verify_backup_data(self.backup_host, DataType.tiny) + + def run_inc_backup_1(self): + suffix = '_inc_1' + self.backup_inc_1_info = self.assert_backup_create( + self.BACKUP_NAME + suffix, self.BACKUP_DESC + suffix, + self.instance_info.id, parent_id=self.backup_info.id) + + def run_wait_for_inc_backup_1(self): + self._verify_backup(self.backup_inc_1_info.id) + + def run_add_data_for_inc_backup_2(self): + self.backup_host = self.get_instance_host() + self.assert_add_data_for_backup(self.backup_host, DataType.tiny2) + + def run_verify_data_for_inc_backup_2(self): + self.assert_verify_backup_data(self.backup_host, DataType.tiny2) + + def run_inc_backup_2(self): + suffix = '_inc_2' + self.backup_inc_2_info = self.assert_backup_create( + self.BACKUP_NAME + suffix, self.BACKUP_DESC + suffix, + self.instance_info.id, parent_id=self.backup_inc_1_info.id) + + def run_wait_for_inc_backup_2(self): + self._verify_backup(self.backup_inc_2_info.id) + + def run_restore_from_backup(self, expected_http_code=200): + self.restore_instance_id = self.assert_restore_from_backup( + self.backup_info.id, expected_http_code=expected_http_code) + + def assert_restore_from_backup(self, backup_ref, suffix='', + expected_http_code=200): + result = self._restore_from_backup(backup_ref, suffix=suffix) + self.assert_client_code(expected_http_code) + self.assert_equal('BUILD', result.status, + 'Unexpected instance status') + return result.id + + def _restore_from_backup(self, backup_ref, suffix=''): + restore_point = {'backupRef': backup_ref} + result = self.auth_client.instances.create( + self.instance_info.name + '_restore' + suffix, + self.instance_info.dbaas_flavor_href, + self.instance_info.volume, + nics=self.instance_info.nics, + restorePoint=restore_point, + datastore=self.instance_info.dbaas_datastore, + datastore_version=self.instance_info.dbaas_datastore_version) + return result + + def run_restore_from_inc_1_backup(self, expected_http_code=200): + self.restore_inc_1_instance_id = self.assert_restore_from_backup( + self.backup_inc_1_info.id, '_inc_1', + expected_http_code=expected_http_code) + + def run_restore_from_backup_completed( + self, expected_states=['BUILD', 'ACTIVE']): + self.assert_restore_from_backup_completed( + self.restore_instance_id, expected_states) + self.restore_host = self.get_instance_host(self.restore_instance_id) + + def assert_restore_from_backup_completed( + self, instance_id, expected_states): + self._assert_instance_states(instance_id, expected_states) + + def run_restore_from_inc_1_backup_completed( + self, expected_states=['BUILD', 'ACTIVE']): + self.assert_restore_from_backup_completed( + self.restore_inc_1_instance_id, expected_states) + self.restore_inc_1_host = self.get_instance_host( + self.restore_inc_1_instance_id) + + def run_verify_data_in_restored_instance(self): + self.assert_verify_backup_data(self.restore_host, DataType.large) + + def run_verify_data_in_restored_inc_1_instance(self): + self.assert_verify_backup_data(self.restore_inc_1_host, DataType.large) + self.assert_verify_backup_data(self.restore_inc_1_host, DataType.tiny) + + def run_delete_restored_instance(self, expected_http_code=202): + self.assert_delete_restored_instance( + self.restore_instance_id, expected_http_code) + + def assert_delete_restored_instance( + self, instance_id, expected_http_code): + self.auth_client.instances.delete(instance_id) + self.assert_client_code(expected_http_code) + + def run_delete_restored_inc_1_instance(self, expected_http_code=202): + self.assert_delete_restored_instance( + self.restore_inc_1_instance_id, expected_http_code) + + def run_wait_for_restored_instance_delete(self, expected_state='SHUTDOWN'): + self.assert_restored_instance_deleted( + self.restore_instance_id, expected_state) + self.restore_instance_id = None + self.restore_host = None + + def assert_restored_instance_deleted(self, instance_id, expected_state): + self.assert_all_gone(instance_id, expected_state) + + def run_wait_for_restored_inc_1_instance_delete( + self, expected_state='SHUTDOWN'): + self.assert_restored_instance_deleted( + self.restore_inc_1_instance_id, expected_state) + self.restore_inc_1_instance_id = None + self.restore_inc_1_host = None def run_delete_unknown_backup( self, expected_exception=exceptions.NotFound, @@ -336,8 +466,10 @@ class BackupRunner(BackupRunnerMixin): self.assert_client_code(expected_http_code=expected_http_code, client=self.unauth_client) - def run_delete_backup(self, expected_http_code=202): - self.assert_delete_backup(self.backup_info.id, expected_http_code) + def run_delete_inc_2_backup(self, expected_http_code=202): + self.assert_delete_backup( + self.backup_inc_2_info.id, expected_http_code) + self.backup_inc_2_info = None def assert_delete_backup( self, backup_id, expected_http_code): @@ -345,68 +477,32 @@ class BackupRunner(BackupRunnerMixin): self.assert_client_code(expected_http_code) self._wait_until_backup_is_gone(backup_id) + def _wait_until_backup_is_gone(self, backup_id): + def _backup_is_gone(): + try: + self.auth_client.backups.get(backup_id) + return False + except exceptions.NotFound: + return True + + poll_until(_backup_is_gone, + time_out=self.TIMEOUT_BACKUP_DELETE) + + def run_delete_backup(self, expected_http_code=202): + self.assert_delete_backup(self.backup_info.id, expected_http_code) + def run_check_for_incremental_backup( self, expected_exception=exceptions.NotFound, expected_http_code=404): - if self.incremental_backup_info is None: + if self.backup_inc_1_info is None: raise SkipTest("Incremental Backup not created") self.assert_raises( expected_exception, expected_http_code, self.auth_client.backups.get, - self.incremental_backup_info.id) + self.backup_inc_1_info.id) + self.backup_inc_1_info = None - -class IncrementalBackupRunner(BackupRunnerMixin): - - def __init__(self): - self.TIMEOUT_BACKUP_CREATE = 60 * 30 - self.TIMEOUT_BACKUP_DELETE = 120 - - super(IncrementalBackupRunner, - self).__init__(sleep_time=20, timeout=self.TIMEOUT_BACKUP_CREATE) - - self.BACKUP_NAME = 'backup_test' - self.BACKUP_DESC = 'test description' - - self.INCREMENTAL_BACKUP_NAME = 'incremental_backup_test' - self.INCREMENTAL_BACKUP_DESC = 'incremental test description' - - self.backup_host = None - self.backup_info = None - self.backup_count_prior_to_create = 0 - self.backup_count_for_instance_prior_to_create = 0 - - self.incremental_backup_info = None - self.restore_instance_id = 0 - self.restore_host = None - self.other_client = None - - def run_backup_incremental(self, increments=1): - full_backup = self.auth_client.backups.create( - name=self.BACKUP_NAME, instance=self.instance_info.id, - description=self.BACKUP_DESC) - self.backup_info = full_backup - print("Verifying backup " + full_backup.id) - self._verify_backup(full_backup.id) - incr_id = full_backup.id - # TODO(atomic77) Modify add/verify data helpers to enable multiple - # calls to add that would be required to properly test multiple - # incremental backups - self.test_helper.add_data(DataType.large, self.get_instance_host()) - for i in range(0, increments): - iresult = self.auth_client.backups.create( - name=self.INCREMENTAL_BACKUP_NAME, - instance=self.instance_info.id, - description=self.INCREMENTAL_BACKUP_DESC, - parent_id=incr_id) - print("Verifying backup " + iresult.id) - self._verify_backup(iresult.id) - incr_id = iresult.id - self.incremental_backup_info = iresult - - def run_restore_from_incremental(self, increment=1): - result = self._restore_from_backup(self.incremental_backup_info.id) - self.assert_client_code(200) - self.assert_equal('BUILD', result.status, - 'Unexpected instance status') - self.restore_instance_id = result.id + def run_remove_backup_data_from_instance(self): + for data_type in self.data_types_added: + self.test_helper.remove_data(data_type, self.backup_host) + self.data_types_added = []