1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
# This file is part of cloud-init. See LICENSE file for license information.
"""EC2 Image Base Class."""
from ..images import Image
from .snapshot import EC2Snapshot
from tests.cloud_tests import LOG
class EC2Image(Image):
"""EC2 backed image."""
platform_name = 'ec2'
def __init__(self, platform, config, image_ami):
"""Set up image.
@param platform: platform object
@param config: image configuration
@param image_ami: string of image ami ID
"""
super(EC2Image, self).__init__(platform, config)
self._img_instance = None
self.image_ami = image_ami
@property
def _instance(self):
"""Internal use only, returns a running instance"""
if not self._img_instance:
self._img_instance = self.platform.create_instance(
self.properties, self.config, self.features,
self.image_ami, user_data=None)
self._img_instance.start(wait=True, wait_for_cloud_init=True)
return self._img_instance
def destroy(self):
"""Delete the instance used to create a custom image."""
if self._img_instance:
LOG.debug('terminating backing instance %s',
self._img_instance.instance.instance_id)
self._img_instance.instance.terminate()
self._img_instance.instance.wait_until_terminated()
super(EC2Image, self).destroy()
def _execute(self, *args, **kwargs):
"""Execute command in image, modifying image."""
self._instance.start(wait=True)
return self._instance._execute(*args, **kwargs)
def push_file(self, local_path, remote_path):
"""Copy file at 'local_path' to instance at 'remote_path'."""
self._instance.start(wait=True)
return self._instance.push_file(local_path, remote_path)
def run_script(self, *args, **kwargs):
"""Run script in image, modifying image.
@return_value: script output
"""
self._instance.start(wait=True)
return self._instance.run_script(*args, **kwargs)
def snapshot(self):
"""Create snapshot of image, block until done.
Will return base image_ami if no instance has been booted, otherwise
will run the clean script, shutdown the instance, create a custom
AMI, and use that AMI once available.
"""
if not self._img_instance:
return EC2Snapshot(self.platform, self.properties, self.config,
self.features, self.image_ami,
delete_on_destroy=False)
if self.config.get('boot_clean_script'):
self._img_instance.run_script(self.config.get('boot_clean_script'))
self._img_instance.shutdown(wait=True)
LOG.debug('creating custom ami from instance %s',
self._img_instance.instance.instance_id)
response = self.platform.ec2_client.create_image(
Name='%s-%s' % (self.platform.tag, self.image_ami),
InstanceId=self._img_instance.instance.instance_id
)
image_ami_edited = response['ImageId']
# Create image and wait until it is in the 'available' state
image = self.platform.ec2_resource.Image(image_ami_edited)
image.wait_until_exists()
waiter = self.platform.ec2_client.get_waiter('image_available')
waiter.wait(ImageIds=[image.id])
image.reload()
return EC2Snapshot(self.platform, self.properties, self.config,
self.features, image_ami_edited)
# vi: ts=4 expandtab
|