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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
# File 'lib/vagrant-aws/action/run_instance.rb', line 20
def call(env)
env[:metrics] ||= {}
region = env[:machine].provider_config.region
region_config = env[:machine].provider_config.get_region_config(region)
ami = region_config.ami
availability_zone = region_config.availability_zone
instance_type = region_config.instance_type
keypair = region_config.keypair_name
private_ip_address = region_config.private_ip_address
security_groups = region_config.security_groups
subnet_id = region_config.subnet_id
tags = region_config.tags
user_data = region_config.user_data
block_device_mapping = region_config.block_device_mapping
elastic_ip = region_config.elastic_ip
terminate_on_shutdown = region_config.terminate_on_shutdown
iam_instance_profile_arn = region_config.iam_instance_profile_arn
iam_instance_profile_name = region_config.iam_instance_profile_name
monitoring = region_config.monitoring
ebs_optimized = region_config.ebs_optimized
source_dest_check = region_config.source_dest_check
associate_public_ip = region_config.associate_public_ip
kernel_id = region_config.kernel_id
tenancy = region_config.tenancy
if !keypair
env[:ui].warn(I18n.t("vagrant_aws.launch_no_keypair"))
end
if subnet_id && !elastic_ip
env[:ui].warn(I18n.t("vagrant_aws.launch_vpc_warning"))
end
env[:ui].info(I18n.t("vagrant_aws.launching_instance"))
env[:ui].info(" -- Type: #{instance_type}")
env[:ui].info(" -- AMI: #{ami}")
env[:ui].info(" -- Region: #{region}")
env[:ui].info(" -- Availability Zone: #{availability_zone}") if availability_zone
env[:ui].info(" -- Keypair: #{keypair}") if keypair
env[:ui].info(" -- Subnet ID: #{subnet_id}") if subnet_id
env[:ui].info(" -- IAM Instance Profile ARN: #{iam_instance_profile_arn}") if iam_instance_profile_arn
env[:ui].info(" -- IAM Instance Profile Name: #{iam_instance_profile_name}") if iam_instance_profile_name
env[:ui].info(" -- Private IP: #{private_ip_address}") if private_ip_address
env[:ui].info(" -- Elastic IP: #{elastic_ip}") if elastic_ip
env[:ui].info(" -- User Data: yes") if user_data
env[:ui].info(" -- Security Groups: #{security_groups.inspect}") if !security_groups.empty?
env[:ui].info(" -- User Data: #{user_data}") if user_data
env[:ui].info(" -- Block Device Mapping: #{block_device_mapping}") if block_device_mapping
env[:ui].info(" -- Terminate On Shutdown: #{terminate_on_shutdown}")
env[:ui].info(" -- Monitoring: #{monitoring}")
env[:ui].info(" -- EBS optimized: #{ebs_optimized}")
env[:ui].info(" -- Source Destination check: #{source_dest_check}")
env[:ui].info(" -- Assigning a public IP address in a VPC: #{associate_public_ip}")
env[:ui].info(" -- VPC tenancy specification: #{tenancy}")
options = {
:availability_zone => availability_zone,
:flavor_id => instance_type,
:image_id => ami,
:key_name => keypair,
:private_ip_address => private_ip_address,
:subnet_id => subnet_id,
:iam_instance_profile_arn => iam_instance_profile_arn,
:iam_instance_profile_name => iam_instance_profile_name,
:tags => tags,
:user_data => user_data,
:block_device_mapping => block_device_mapping,
:instance_initiated_shutdown_behavior => terminate_on_shutdown == true ? "terminate" : nil,
:monitoring => monitoring,
:ebs_optimized => ebs_optimized,
:associate_public_ip => associate_public_ip,
:kernel_id => kernel_id,
:tenancy => tenancy
}
if !security_groups.empty?
security_group_key = options[:subnet_id].nil? ? :groups : :security_group_ids
options[security_group_key] = security_groups
env[:ui].warn(I18n.t("vagrant_aws.warn_ssh_access")) unless allows_ssh_port?(env, security_groups, subnet_id)
end
begin
server = env[:aws_compute].servers.create(options)
rescue Fog::Compute::AWS::NotFound => e
if e.message =~ /subnet ID/
raise Errors::FogError,
:message => "Subnet ID not found: #{subnet_id}"
end
raise
rescue Fog::Compute::AWS::Error => e
raise Errors::FogError, :message => e.message
rescue Excon::Errors::HTTPStatusError => e
raise Errors::InternalFogError,
:error => e.message,
:response => e.response.body
end
env[:machine].id = server.id
env[:metrics]["instance_ready_time"] = Util::Timer.time do
tries = region_config.instance_ready_timeout / 2
env[:ui].info(I18n.t("vagrant_aws.waiting_for_ready"))
begin
retryable(:on => Fog::Errors::TimeoutError, :tries => tries) do
next if env[:interrupted]
server.wait_for(2, region_config.instance_check_interval) { ready? }
end
rescue Fog::Errors::TimeoutError
terminate(env)
raise Errors::InstanceReadyTimeout,
timeout: region_config.instance_ready_timeout
end
end
@logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
if elastic_ip
domain = subnet_id ? 'vpc' : 'standard'
do_elastic_ip(env, domain, server, elastic_ip)
end
if !source_dest_check.nil?
if server.vpc_id.nil?
env[:ui].warn(I18n.t("vagrant_aws.source_dest_checks_no_vpc"))
else
begin
attrs = {
"SourceDestCheck.Value" => source_dest_check
}
env[:aws_compute].modify_instance_attribute(server.id, attrs)
rescue Fog::Compute::AWS::Error => e
raise Errors::FogError, :message => e.message
end
end
end
if !env[:interrupted]
env[:metrics]["instance_ssh_time"] = Util::Timer.time do
env[:ui].info(I18n.t("vagrant_aws.waiting_for_ssh"))
network_ready_retries = 0
network_ready_retries_max = 10
while true
break if env[:interrupted]
begin
break if env[:machine].communicate.ready?
rescue Exception => e
if network_ready_retries < network_ready_retries_max then
network_ready_retries += 1
@logger.warn(I18n.t("vagrant_aws.waiting_for_ssh, retrying"))
else
raise e
end
end
sleep 2
end
end
@logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
env[:ui].info(I18n.t("vagrant_aws.ready"))
end
terminate(env) if env[:interrupted]
@app.call(env)
end
|