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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
import sys
import logging
import os
import time
from aws_controller import AwsController, InstanceRunFailedError
from remote_executor import RemoteExecutor, RemoteCommandFailedError
from remote_executor import AuthenticationException
def iso_timestamp():
return time.strftime("%Y%m%dT%H%M%SZ", time.gmtime())
DEFAULT_AMI_TYPE = "build-slave"
class LinaroAMI:
"""Main class which contains all the command methods.
Represents the placeholder for all the custom AMI tool features.
Constructor keyword arguments:
config_file -- configuration file path.
username -- username for EC2 instances SSH connection.
options -- options forwarded from the command line tool.
aws_access_key_id -- AWS key ID (default None).
aws_secret_access_key -- AWS secret key (default None).
"""
def __init__(self, config, aws_controller, remote_executor, username,
key_filename=None,
options={}, aws_access_key_id=None,
aws_secret_access_key=None):
self.log = logging.getLogger("linaro-ami")
self.username = username
self.key_filename = key_filename
self.options = options
self.aws_access_key_id = aws_access_key_id
self.aws_secret_access_key = aws_secret_access_key
self.config = config
self.aws = aws_controller
self.executor = remote_executor
def has_ami(self, ami_name):
""" Check if config object has a specific section. """
return self.config.has_section(ami_name)
def command_create(self, ami_name):
""" Create command.
It finds the configuration for the ami_name and creates the custom AMI
based on the parameters provided.
"""
self.log.info("Starting instance to create AMI...")
self.aws.connect()
instance = None
base_ami = self.config.get(ami_name, "base_ami")
instance_type = self.config.get(ami_name, "instance_type")
script_fetch = self.config.get(ami_name, "init_script_fetch")
if self.options.key:
key_autocreate = False
key_name = self.options.key
else:
self.log.warn("Trying to use auto-created key. This is not recommended, use --key= if any issues.")
key_autocreate = True
key_name = self.config.get(ami_name, "key_name")
try:
if key_autocreate:
self.aws.import_key_pair(key_name, self.executor.get_public_key())
instance = self.aws.run_instance_and_wait(base_ami,
key_name, instance_type)
self.log.info("Started instance: %s (%s)", instance.public_dns_name, instance.id)
for i in xrange(20):
try:
self.executor.connect(instance.public_dns_name, self.username, self.key_filename)
break
except AuthenticationException, e:
if i == 19:
raise e
self.log.debug("Could not login to instance so far, retrying")
time.sleep(2)
self.log.debug("Connected to instance")
self.log.info("Installing version control systems.")
install_command_output = self.executor.execute(self.config.get(
"DEFAULT", "vcs_install"))
self.log.debug(install_command_output)
self.log.info("Cloning slave init repo.")
fetch_command_output = self.executor.execute(script_fetch + " slave-init")
self.log.debug(fetch_command_output)
script_command = "sudo bash slave-init/" + self.config.get(
ami_name, "init_script")
self.log.info("Executing slave init script: " + \
script_command)
script_command_output = self.executor.execute(script_command)
self.log.debug(script_command_output)
self.log.info("Slave init script finished successfully.")
# Stop instance so create_image() doesn't restart it.
self.aws.stop_instance_and_wait(instance.id)
self.log.info("Creating AMI.")
descr = self.config.get(ami_name, "description")
if self.options.descr:
descr += " | " + self.options.descr
ami_id = self.aws.create_image(
instance.id, ami_name + "-" + iso_timestamp(),
descr)
self.aws.create_tags([ami_id],
{"Name": ami_name, "Type": DEFAULT_AMI_TYPE})
return ami_id
except RemoteCommandFailedError, e:
self.log.exception("linaro-ami create:")
except Exception, e:
self.log.exception("linaro-ami create:")
finally:
if key_autocreate:
self.aws.delete_key_pair(key_name)
self.executor.close()
if instance:
self.aws.terminate_instance(instance.id)
def command_list(self):
""" List command. """
self.aws.connect()
print "Name ID Created Status"
print "Description"
print "-" * 30
results = []
for image in self.aws.list_images():
if self.options.type and image.tags.get(
"Type") != self.options.type:
continue
results.append((image.tags.get("Name", "*" +
image.name),
image.id,
self.aws.get_image_creation_time(image),
image.state,
image.description))
def ami_cmp(a, b):
c = cmp(a[0], b[0])
if c == 0:
c = cmp(a[2], b[2])
return c
results.sort(ami_cmp)
for r in results:
print "%s %s %s %s" % r[0:4]
print r[-1]
print "-" * 30
def command_delete(self):
raise NotImplementedError
|