scenario test involving glance, cinder and nova functionalities
this is a new scenario test which tries to address a typical use case where an image is uploaded in glance, later cloned into a persistent volume in cinder, snapshotted and finally reused for new instances; there is no attempt to check the actual image contents as that would require ssh access Change-Id: I55f0e5fdfc5aba8eb6c8f427ab0e672bb7dcd715
This commit is contained in:
122
tempest/scenario/test_volume_snapshot_pattern.py
Normal file
122
tempest/scenario/test_volume_snapshot_pattern.py
Normal file
@@ -0,0 +1,122 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# 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 tempest.openstack.common import log as logging
|
||||
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
from tempest.scenario import manager
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestVolumeSnapshotPattern(manager.OfficialClientTest):
|
||||
|
||||
"""
|
||||
This test case attempts to reproduce the following steps:
|
||||
|
||||
* Create in Cinder some bootable volume importing a Glance image
|
||||
* Boot an instance from the bootable volume
|
||||
* Create a volume snapshot while the instance is running
|
||||
* Boot an additional instance from the new snapshot based volume
|
||||
"""
|
||||
|
||||
def _create_volume_from_image(self):
|
||||
img_uuid = self.config.compute.image_ref
|
||||
vol_name = rand_name('volume-origin')
|
||||
vol = self.volume_client.volumes.create(size=1,
|
||||
display_name=vol_name,
|
||||
imageRef=img_uuid)
|
||||
self.set_resource(vol.id, vol)
|
||||
self.status_timeout(self.volume_client.volumes,
|
||||
vol.id,
|
||||
'available')
|
||||
return vol
|
||||
|
||||
def _boot_instance_from_volume(self, vol_id):
|
||||
# NOTE(gfidente): the img_uuid here is only needed because
|
||||
# the novaclient requires it to be passed as arg
|
||||
img_uuid = self.config.compute.image_ref
|
||||
i_name = rand_name('instance')
|
||||
flavor_id = self.config.compute.flavor_ref
|
||||
# NOTE(gfidente): the syntax for block_device_mapping is
|
||||
# dev_name=id:type:size:delete_on_terminate
|
||||
# where type needs to be "snap" if the server is booted
|
||||
# from a snapshot, size instead can be safely left empty
|
||||
bd_map = {
|
||||
'vda': vol_id + ':::0'
|
||||
}
|
||||
create_kwargs = {
|
||||
'block_device_mapping': bd_map
|
||||
}
|
||||
i = self.compute_client.servers.create(name=i_name,
|
||||
image=img_uuid,
|
||||
flavor=flavor_id,
|
||||
**create_kwargs)
|
||||
self.set_resource(i.id, i)
|
||||
self.status_timeout(self.compute_client.servers,
|
||||
i.id,
|
||||
'ACTIVE')
|
||||
return i
|
||||
|
||||
def _create_snapshot_from_volume(self, vol_id):
|
||||
volume_snapshots = self.volume_client.volume_snapshots
|
||||
snap_name = rand_name('snapshot')
|
||||
snap = volume_snapshots.create(volume_id=vol_id,
|
||||
force=True,
|
||||
display_name=snap_name)
|
||||
self.set_resource(snap.id, snap)
|
||||
self.status_timeout(volume_snapshots,
|
||||
snap.id,
|
||||
'available')
|
||||
return snap
|
||||
|
||||
def _create_volume_from_snapshot(self, snap_id):
|
||||
vol_name = rand_name('volume')
|
||||
vol = self.volume_client.volumes.create(size=1,
|
||||
display_name=vol_name,
|
||||
snapshot_id=snap_id)
|
||||
self.set_resource(vol.id, vol)
|
||||
self.status_timeout(self.volume_client.volumes,
|
||||
vol.id,
|
||||
'available')
|
||||
return vol
|
||||
|
||||
def _stop_instances(self, instances):
|
||||
# NOTE(gfidente): two loops so we do not wait for the status twice
|
||||
for i in instances:
|
||||
self.compute_client.servers.stop(i)
|
||||
for i in instances:
|
||||
self.status_timeout(self.compute_client.servers,
|
||||
i.id,
|
||||
'SHUTOFF')
|
||||
|
||||
def _detach_volumes(self, volumes):
|
||||
# NOTE(gfidente): two loops so we do not wait for the status twice
|
||||
for v in volumes:
|
||||
self.volume_client.volumes.detach(v)
|
||||
for v in volumes:
|
||||
self.status_timeout(self.volume_client.volumes,
|
||||
v.id,
|
||||
'available')
|
||||
|
||||
def test_volume_snapshot_pattern(self):
|
||||
volume_origin = self._create_volume_from_image()
|
||||
i_origin = self._boot_instance_from_volume(volume_origin.id)
|
||||
snapshot = self._create_snapshot_from_volume(volume_origin.id)
|
||||
volume = self._create_volume_from_snapshot(snapshot.id)
|
||||
i = self._boot_instance_from_volume(volume.id)
|
||||
# NOTE(gfidente): ensure resources are in clean state for
|
||||
# deletion operations to succeed
|
||||
self._stop_instances([i_origin, i])
|
||||
self._detach_volumes([volume_origin, volume])
|
||||
Reference in New Issue
Block a user