diff --git a/rally-jobs/cinder.yaml b/rally-jobs/cinder.yaml index 694c5790b7..0afae91b72 100755 --- a/rally-jobs/cinder.yaml +++ b/rally-jobs/cinder.yaml @@ -684,6 +684,24 @@ failure_rate: max: 0 + CinderVolumeBackups.create_incremental_volume_backup: + - + args: + size: 1 + runner: + type: "constant" + times: 4 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + roles: + - "admin" + sla: + failure_rate: + max: 40 + CinderVolumes.create_and_restore_volume_backup: - args: diff --git a/rally/plugins/openstack/scenarios/cinder/volume_backups.py b/rally/plugins/openstack/scenarios/cinder/volume_backups.py new file mode 100644 index 0000000000..96ecadaeb6 --- /dev/null +++ b/rally/plugins/openstack/scenarios/cinder/volume_backups.py @@ -0,0 +1,56 @@ +# 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 rally import consts +from rally.plugins.openstack import scenario +from rally.plugins.openstack.scenarios.cinder import utils as cinder_utils +from rally.task import validation + + +"""Scenarios for Cinder Volume Backup.""" + + +@validation.number("size", minval=1, integer_only=True) +@validation.required_cinder_services("cinder-backup") +@validation.required_services(consts.Service.CINDER) +@validation.required_openstack(users=True) +@scenario.configure(context={"cleanup": ["cinder"]}, + name="CinderVolumeBackups." + "create_incremental_volume_backup") +class CreateIncrementalVolumeBackup(cinder_utils.CinderScenario): + def run(self, size, do_delete=True, create_volume_kwargs=None, + create_backup_kwargs=None): + """Create a incremental volume backup. + + The scenario first create a volume, the create a backup, the backup + is full backup. Because Incremental backup must be based on the + full backup. finally create a incremental backup. + + :param size: volume size in GB + :param do_delete: deletes backup and volume after creating if True + :param create_volume_kwargs: optional args to create a volume + :param create_backup_kwargs: optional args to create a volume backup + """ + create_volume_kwargs = create_volume_kwargs or {} + create_backup_kwargs = create_backup_kwargs or {} + + volume = self._create_volume(size, **create_volume_kwargs) + backup1 = self._create_backup(volume.id, **create_backup_kwargs) + + backup2 = self._create_backup(volume.id, incremental=True) + + if do_delete: + self._delete_backup(backup2) + self._delete_backup(backup1) + self._delete_volume(volume) diff --git a/samples/tasks/scenarios/cinder/create-incremental-volume-backup.json b/samples/tasks/scenarios/cinder/create-incremental-volume-backup.json new file mode 100644 index 0000000000..81f1074784 --- /dev/null +++ b/samples/tasks/scenarios/cinder/create-incremental-volume-backup.json @@ -0,0 +1,28 @@ +{ + "CinderVolumeBackups.create_incremental_volume_backup": [ + { + "args": { + "size": 1, + "create_volume_kwargs": {}, + "create_backup_kwargs": {} + }, + "runner": { + "type": "constant", + "times": 5, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "roles": ["admin"] + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/cinder/create-incremental-volume-backup.yaml b/samples/tasks/scenarios/cinder/create-incremental-volume-backup.yaml new file mode 100644 index 0000000000..73b9a49063 --- /dev/null +++ b/samples/tasks/scenarios/cinder/create-incremental-volume-backup.yaml @@ -0,0 +1,21 @@ +--- + CinderVolumeBackups.create_incremental_volume_backup: + - + args: + size: 1 + create_volume_kwargs: {} + create_backup_kwargs: {} + runner: + type: "constant" + times: 5 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + roles: + - "admin" + sla: + failure_rate: + max: 0 + diff --git a/tests/unit/plugins/openstack/scenarios/cinder/test_volume_backups.py b/tests/unit/plugins/openstack/scenarios/cinder/test_volume_backups.py new file mode 100644 index 0000000000..0755e2a3cb --- /dev/null +++ b/tests/unit/plugins/openstack/scenarios/cinder/test_volume_backups.py @@ -0,0 +1,41 @@ +# 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. + +import mock + +from rally.plugins.openstack.scenarios.cinder import volume_backups +from tests.unit import test + + +class CinderBackupTestCase(test.ScenarioTestCase): + + def test_create_incremental_volume_backup(self): + fake_volume = mock.MagicMock() + fake_backup = mock.MagicMock() + scenario = volume_backups.CreateIncrementalVolumeBackup(self.context) + scenario._create_volume = mock.MagicMock(return_value=fake_volume) + scenario._create_backup = mock.MagicMock(return_value=fake_backup) + scenario._delete_volume = mock.MagicMock() + scenario._delete_backup = mock.MagicMock() + + volume_kwargs = {"some_var": "zaq"} + backup_kwargs = {"incremental": True} + + scenario.run(1, do_delete=True, create_volume_kwargs=volume_kwargs, + create_backup_kwargs=backup_kwargs) + + self.assertEqual(2, scenario._create_backup.call_count) + scenario._create_volume.assert_called_once_with(1, **volume_kwargs) + scenario._delete_backup.assert_has_calls(fake_backup) + scenario._delete_volume.assert_called_once_with(fake_volume)