Boot server from snapshot
There is an option to boot a server from volume snapshot.
It requires that the parent volume is a bootable volume.
Boot that server will create a new volume to boot from.
Change-Id: If2a257b24f2d50a401d6804e983bcad55b5c89e8
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 2c8b618..9486b96 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -40,20 +40,23 @@
self.__class__.__name__ + '-volume-origin')
return self.create_volume(name=vol_name, imageRef=img_uuid)
- def _get_bdm(self, vol_id, delete_on_termination=False):
+ def _get_bdm(self, source_id, source_type, delete_on_termination=False):
# 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 = [{
'device_name': 'vda',
- 'volume_id': vol_id,
+ '{}_id'.format(source_type): source_id,
'delete_on_termination': str(int(delete_on_termination))}]
return {'block_device_mapping': bd_map}
- def _boot_instance_from_volume(self, vol_id, keypair=None,
- security_group=None,
- delete_on_termination=False):
+ def _boot_instance_from_resource(self, source_id,
+ source_type,
+ keypair=None,
+ security_group=None,
+ delete_on_termination=False):
create_kwargs = dict()
if keypair:
create_kwargs['key_name'] = keypair['name']
@@ -61,7 +64,10 @@
create_kwargs['security_groups'] = [
{'name': security_group['name']}]
create_kwargs.update(self._get_bdm(
- vol_id, delete_on_termination=delete_on_termination))
+ source_id,
+ source_type,
+ delete_on_termination=delete_on_termination))
+
return self.create_server(
image_id='',
wait_until='ACTIVE',
@@ -116,8 +122,11 @@
# create an instance from volume
LOG.info("Booting instance 1 from volume")
volume_origin = self._create_volume_from_image()
- instance_1st = self._boot_instance_from_volume(volume_origin['id'],
- keypair, security_group)
+ instance_1st = self._boot_instance_from_resource(
+ source_id=volume_origin['id'],
+ source_type='volume',
+ keypair=keypair,
+ security_group=security_group)
LOG.info("Booted first instance: %s", instance_1st)
# write content to volume on instance
@@ -131,8 +140,11 @@
self._delete_server(instance_1st)
# create a 2nd instance from volume
- instance_2nd = self._boot_instance_from_volume(volume_origin['id'],
- keypair, security_group)
+ instance_2nd = self._boot_instance_from_resource(
+ source_id=volume_origin['id'],
+ source_type='volume',
+ keypair=keypair,
+ security_group=security_group)
LOG.info("Booted second instance %s", instance_2nd)
# check the content of written file
@@ -152,8 +164,10 @@
size=snapshot['size'])
LOG.info("Booting third instance from snapshot")
server_from_snapshot = (
- self._boot_instance_from_volume(volume['id'],
- keypair, security_group))
+ self._boot_instance_from_resource(source_id=volume['id'],
+ source_type='volume',
+ keypair=keypair,
+ security_group=security_group))
LOG.info("Booted third instance %s", server_from_snapshot)
# check the content of written file
@@ -164,13 +178,49 @@
private_key=keypair['private_key'])
self.assertEqual(timestamp, timestamp3)
+ @test.idempotent_id('05795fb2-b2a7-4c9f-8fac-ff25aedb1489')
+ @test.services('compute', 'image', 'volume')
+ def test_create_server_from_volume_snapshot(self):
+ # Create a volume from an image
+ boot_volume = self._create_volume_from_image()
+
+ # Create a snapshot
+ boot_snapshot = self._create_snapshot_from_volume(boot_volume['id'])
+
+ # Create a server from a volume snapshot
+ server = self._boot_instance_from_resource(
+ source_id=boot_snapshot['id'],
+ source_type='snapshot',
+ delete_on_termination=True)
+
+ server_info = self.servers_client.show_server(server['id'])['server']
+
+ # The created volume when creating a server from a snapshot
+ created_volume = server_info['os-extended-volumes:volumes_attached']
+
+ created_volume_info = self.volumes_client.show_volume(
+ created_volume[0]['id'])['volume']
+
+ # Verify the server was created from the snapshot
+ self.assertEqual(
+ boot_volume['volume_image_metadata']['image_id'],
+ created_volume_info['volume_image_metadata']['image_id'])
+ self.assertEqual(boot_snapshot['id'],
+ created_volume_info['snapshot_id'])
+ self.assertEqual(server['id'],
+ created_volume_info['attachments'][0]['server_id'])
+ self.assertEqual(created_volume[0]['id'],
+ created_volume_info['attachments'][0]['volume_id'])
+
@test.idempotent_id('36c34c67-7b54-4b59-b188-02a2f458a63b')
@test.services('compute', 'volume', 'image')
def test_create_ebs_image_and_check_boot(self):
# create an instance from volume
volume_origin = self._create_volume_from_image()
- instance = self._boot_instance_from_volume(volume_origin['id'],
- delete_on_termination=True)
+ instance = self._boot_instance_from_resource(
+ source_id=volume_origin['id'],
+ source_type='volume',
+ delete_on_termination=True)
# create EBS image
image = self.create_server_snapshot(instance)
@@ -187,10 +237,10 @@
class TestVolumeBootPatternV2(TestVolumeBootPattern):
- def _get_bdm(self, vol_id, delete_on_termination=False):
+ def _get_bdm(self, source_id, source_type, delete_on_termination=False):
bd_map_v2 = [{
- 'uuid': vol_id,
- 'source_type': 'volume',
+ 'uuid': source_id,
+ 'source_type': source_type,
'destination_type': 'volume',
'boot_index': 0,
'delete_on_termination': delete_on_termination}]