Merge "Fix CinderVolumes.create_volume_and_clone"
This commit is contained in:
commit
1fa65f107d
17
rally-jobs/cinder.yaml
Normal file → Executable file
17
rally-jobs/cinder.yaml
Normal file → Executable file
@ -666,3 +666,20 @@
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
-
|
||||
args:
|
||||
size:
|
||||
min: 1
|
||||
max: 1
|
||||
nested_level: 2
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 1
|
||||
concurrency: 1
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
22
rally/plugins/openstack/scenarios/cinder/volumes.py
Normal file → Executable file
22
rally/plugins/openstack/scenarios/cinder/volumes.py
Normal file → Executable file
@ -551,22 +551,34 @@ class CinderVolumes(cinder_utils.CinderScenario,
|
||||
@validation.required_services(consts.Service.CINDER)
|
||||
@validation.required_openstack(users=True)
|
||||
@scenario.configure(context={"cleanup": ["cinder"]})
|
||||
def create_volume_and_clone(self, size, image=None, **kwargs):
|
||||
def create_volume_and_clone(self, size, image=None, nested_level=1,
|
||||
**kwargs):
|
||||
"""Create a volume, then clone it to another volume.
|
||||
|
||||
This creates a volume, then clone it to anothor volume,
|
||||
and then clone the new volume to next volume...
|
||||
1. create source volume (from image)
|
||||
2. clone source volume to volume1
|
||||
3. clone volume1 to volume2
|
||||
4. clone volume2 to volume3
|
||||
5. ...
|
||||
|
||||
:param size: volume size (integer, in GB) or
|
||||
dictionary, must contain two values:
|
||||
min - minimum size volumes will be created as;
|
||||
max - maximum size volumes will be created as.
|
||||
:param image: image to be used to create initial volume
|
||||
:param nested_level: amount of nested levels
|
||||
:param kwargs: optional args to create volumes
|
||||
"""
|
||||
if image:
|
||||
kwargs["imageRef"] = image
|
||||
|
||||
vol1 = self._create_volume(size, **kwargs)
|
||||
source_vol = self._create_volume(size, **kwargs)
|
||||
|
||||
kwargs.pop("imageRef", None)
|
||||
with atomic.ActionTimer(self, "cinder.clone_volume"):
|
||||
self._create_volume(size, source_volid=vol1.id,
|
||||
atomic_action=False, **kwargs)
|
||||
for i in range(nested_level):
|
||||
with atomic.ActionTimer(self, "cinder.clone_volume"):
|
||||
source_vol = self._create_volume(source_vol.size,
|
||||
source_volid=source_vol.id,
|
||||
atomic_action=False, **kwargs)
|
||||
|
3
samples/tasks/scenarios/cinder/create-volume-and-clone.json
Normal file → Executable file
3
samples/tasks/scenarios/cinder/create-volume-and-clone.json
Normal file → Executable file
@ -21,7 +21,8 @@
|
||||
"size": {
|
||||
"min": 1,
|
||||
"max": 5
|
||||
}
|
||||
},
|
||||
"nested_level": 3
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
|
1
samples/tasks/scenarios/cinder/create-volume-and-clone.yaml
Normal file → Executable file
1
samples/tasks/scenarios/cinder/create-volume-and-clone.yaml
Normal file → Executable file
@ -16,6 +16,7 @@
|
||||
size:
|
||||
min: 1
|
||||
max: 5
|
||||
nested_level: 3
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 3
|
||||
|
46
tests/unit/plugins/openstack/scenarios/cinder/test_volumes.py
Normal file → Executable file
46
tests/unit/plugins/openstack/scenarios/cinder/test_volumes.py
Normal file → Executable file
@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
|
||||
from rally.plugins.openstack.scenarios.cinder import volumes
|
||||
@ -26,6 +27,7 @@ class fake_type(object):
|
||||
name = "fake"
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CinderServersTestCase(test.ScenarioTestCase):
|
||||
|
||||
def _get_context(self):
|
||||
@ -495,30 +497,28 @@ class CinderServersTestCase(test.ScenarioTestCase):
|
||||
self.assertFalse(scenario._delete_volume.called)
|
||||
self.assertFalse(scenario._delete_backup.called)
|
||||
|
||||
def test_create_volume_and_clone(self):
|
||||
fake_volumes = [mock.Mock(), mock.Mock()]
|
||||
@ddt.data({},
|
||||
{"nested_level": 2},
|
||||
{"image": "img"})
|
||||
@ddt.unpack
|
||||
def test_create_volume_and_clone(self, nested_level=1,
|
||||
image=None):
|
||||
create_volumes_count = nested_level + 1
|
||||
fake_volumes = [mock.Mock(size=1) for i in range(create_volumes_count)]
|
||||
scenario = volumes.CinderVolumes(self.context)
|
||||
scenario._create_volume = mock.MagicMock(side_effect=fake_volumes)
|
||||
|
||||
scenario.create_volume_and_clone(1, fakearg="fake")
|
||||
scenario._create_volume.assert_has_calls([
|
||||
mock.call(1, fakearg="fake"),
|
||||
mock.call(1, source_volid=fake_volumes[0].id, atomic_action=False,
|
||||
fakearg="fake")])
|
||||
scenario.create_volume_and_clone(1, image=image,
|
||||
nested_level=nested_level,
|
||||
fakearg="fake")
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"cinder.clone_volume")
|
||||
|
||||
def test_create_volume_and_clone_from_image(self):
|
||||
fake_volumes = [mock.Mock(), mock.Mock()]
|
||||
scenario = volumes.CinderVolumes(self.context)
|
||||
scenario._create_volume = mock.MagicMock(side_effect=fake_volumes)
|
||||
|
||||
scenario.create_volume_and_clone(1, image="image_id", fakearg="fake")
|
||||
scenario._create_volume.assert_has_calls([
|
||||
mock.call(1, fakearg="fake", imageRef="image_id"),
|
||||
mock.call(1, source_volid=fake_volumes[0].id, atomic_action=False,
|
||||
fakearg="fake")])
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"cinder.clone_volume")
|
||||
expected = [mock.call(1, imageRef=image, fakearg="fake")
|
||||
if image else mock.call(1, fakearg="fake")]
|
||||
for i in range(nested_level):
|
||||
expected.append(mock.call(fake_volumes[i].size,
|
||||
source_volid=fake_volumes[i].id,
|
||||
atomic_action=False, fakearg="fake")
|
||||
)
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"cinder.clone_volume")
|
||||
scenario._create_volume.assert_has_calls(expected)
|
||||
|
Loading…
x
Reference in New Issue
Block a user