blob: 8fa177e8644fc7d3966226eccf1304a9ff20658a [file] [log] [blame]
Giulio Fidenteb3c3cb92013-08-06 12:19:10 +02001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from tempest.openstack.common import log as logging
16
17from tempest.common.utils.data_utils import rand_name
18from tempest.scenario import manager
19
20LOG = logging.getLogger(__name__)
21
22
23class TestVolumeSnapshotPattern(manager.OfficialClientTest):
24
25 """
26 This test case attempts to reproduce the following steps:
27
28 * Create in Cinder some bootable volume importing a Glance image
29 * Boot an instance from the bootable volume
30 * Create a volume snapshot while the instance is running
31 * Boot an additional instance from the new snapshot based volume
32 """
33
34 def _create_volume_from_image(self):
35 img_uuid = self.config.compute.image_ref
36 vol_name = rand_name('volume-origin')
Ken'ichi Ohmichi70672df2013-08-19 18:35:19 +090037 return self.create_volume(name=vol_name, imageRef=img_uuid)
Giulio Fidenteb3c3cb92013-08-06 12:19:10 +020038
39 def _boot_instance_from_volume(self, vol_id):
Giulio Fidenteb3c3cb92013-08-06 12:19:10 +020040 # NOTE(gfidente): the syntax for block_device_mapping is
41 # dev_name=id:type:size:delete_on_terminate
42 # where type needs to be "snap" if the server is booted
43 # from a snapshot, size instead can be safely left empty
44 bd_map = {
45 'vda': vol_id + ':::0'
46 }
47 create_kwargs = {
48 'block_device_mapping': bd_map
49 }
Ken'ichi Ohmichi61f272b2013-08-15 15:58:53 +090050 return self.create_server(self.compute_client,
51 create_kwargs=create_kwargs)
Giulio Fidenteb3c3cb92013-08-06 12:19:10 +020052
53 def _create_snapshot_from_volume(self, vol_id):
54 volume_snapshots = self.volume_client.volume_snapshots
55 snap_name = rand_name('snapshot')
56 snap = volume_snapshots.create(volume_id=vol_id,
57 force=True,
58 display_name=snap_name)
59 self.set_resource(snap.id, snap)
60 self.status_timeout(volume_snapshots,
61 snap.id,
62 'available')
63 return snap
64
65 def _create_volume_from_snapshot(self, snap_id):
66 vol_name = rand_name('volume')
Ken'ichi Ohmichi70672df2013-08-19 18:35:19 +090067 return self.create_volume(name=vol_name, snapshot_id=snap_id)
Giulio Fidenteb3c3cb92013-08-06 12:19:10 +020068
69 def _stop_instances(self, instances):
70 # NOTE(gfidente): two loops so we do not wait for the status twice
71 for i in instances:
72 self.compute_client.servers.stop(i)
73 for i in instances:
74 self.status_timeout(self.compute_client.servers,
75 i.id,
76 'SHUTOFF')
77
78 def _detach_volumes(self, volumes):
79 # NOTE(gfidente): two loops so we do not wait for the status twice
80 for v in volumes:
81 self.volume_client.volumes.detach(v)
82 for v in volumes:
83 self.status_timeout(self.volume_client.volumes,
84 v.id,
85 'available')
86
87 def test_volume_snapshot_pattern(self):
88 volume_origin = self._create_volume_from_image()
89 i_origin = self._boot_instance_from_volume(volume_origin.id)
90 snapshot = self._create_snapshot_from_volume(volume_origin.id)
91 volume = self._create_volume_from_snapshot(snapshot.id)
92 i = self._boot_instance_from_volume(volume.id)
93 # NOTE(gfidente): ensure resources are in clean state for
94 # deletion operations to succeed
95 self._stop_instances([i_origin, i])
96 self._detach_volumes([volume_origin, volume])