CloudyScripts 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +7 -7
- data/README.rdoc +27 -27
- data/Rakefile +50 -50
- data/lib/cloudyscripts.rb +26 -26
- data/lib/help/dm_crypt_helper.rb +53 -54
- data/lib/help/ec2_helper.rb +54 -54
- data/lib/help/remote_command_handler.rb +213 -203
- data/lib/help/script_execution_state.rb +108 -97
- data/lib/help/state_change_listener.rb +13 -13
- data/lib/help/state_transition_helper.rb +362 -0
- data/lib/scripts/ec2/ami2_ebs_conversion.rb +180 -477
- data/lib/scripts/ec2/dm_encrypt.rb +147 -205
- data/lib/scripts/ec2/download_snapshot.rb +153 -0
- data/lib/scripts/ec2/ec2_script.rb +101 -52
- metadata +4 -2
@@ -1,477 +1,180 @@
|
|
1
|
-
require "help/script_execution_state"
|
2
|
-
require "scripts/ec2/ec2_script"
|
3
|
-
require "help/remote_command_handler"
|
4
|
-
#require "help/dm_crypt_helper"
|
5
|
-
require "AWS"
|
6
|
-
|
7
|
-
class AWS::EC2::Base
|
8
|
-
def register_image_updated(options)
|
9
|
-
params = {}
|
10
|
-
params["Name"] = options[:name].to_s
|
11
|
-
params["BlockDeviceMapping.1.Ebs.SnapshotId"] = options[:snapshot_id].to_s
|
12
|
-
params["BlockDeviceMapping.1.DeviceName"] = options[:root_device_name].to_s
|
13
|
-
params["Description"] = options[:description].to_s
|
14
|
-
params["KernelId"] = options[:kernel_id].to_s
|
15
|
-
params["RamdiskId"] = options[:ramdisk_id].to_s
|
16
|
-
params["Architecture"] = options[:architecture].to_s
|
17
|
-
params["RootDeviceName"] = options[:root_device_name].to_s
|
18
|
-
return response_generator(:action => "RegisterImage", :params => params)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Creates a bootable EBS storage from an existing AMI.
|
23
|
-
#
|
24
|
-
|
25
|
-
class Ami2EbsConversion < Ec2Script
|
26
|
-
# Input parameters
|
27
|
-
# * aws_access_key => the Amazon AWS Access Key (see Your Account -> Security Credentials)
|
28
|
-
# * aws_secret_key => the Amazon AWS Secret Key
|
29
|
-
# * ami_id => the ID of the AMI to be converted
|
30
|
-
# * security_group_name => name of the security group to start
|
31
|
-
# * ssh_key_data => Key information for the security group that starts the AMI [if not set, use ssh_key_files]
|
32
|
-
# * ssh_key_files => Key information for the security group that starts the AMI
|
33
|
-
# * remote_command_handler => object that allows to connect via ssh and execute commands (optional)
|
34
|
-
# * ec2_api_handler => object that allows to access the EC2 API (optional)
|
35
|
-
# * ec2_api_server => server to connect to (option, default is us-east-1.ec2.amazonaws.com)
|
36
|
-
# * name => the name of the AMI to be created
|
37
|
-
# * description => description on AMI to be created (optional)
|
38
|
-
# * temp_device_name => [default /dev/sdj] device name used to attach the temporary storage; change this only if there's already a volume attacged as /dev/sdj (optional, default is /dev/sdj)
|
39
|
-
# * root_device_name"=> [default /dev/sda1] device name used for the root device (optional)
|
40
|
-
def initialize(input_params)
|
41
|
-
super(input_params)
|
42
|
-
end
|
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
|
-
end
|
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
|
-
@context[:kernel_id] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['kernelId']
|
182
|
-
@context[:ramdisk_id] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['ramdiskId']
|
183
|
-
@context[:architecture] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['architecture']
|
184
|
-
elsif state['code'].to_i != 0
|
185
|
-
@context[:script].post_message("instance in state #{state['name']}")
|
186
|
-
raise Exception.new('instance failed to start up')
|
187
|
-
else
|
188
|
-
@context[:script].post_message("instance still starting up...")
|
189
|
-
end
|
190
|
-
end
|
191
|
-
AmiStarted.new(@context)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# Ami started. Create a storage
|
196
|
-
class AmiStarted < Ami2EbsConversionState
|
197
|
-
def enter
|
198
|
-
create_storage()
|
199
|
-
end
|
200
|
-
|
201
|
-
private
|
202
|
-
|
203
|
-
def create_storage()
|
204
|
-
@context[:script].post_message("going to create a new EBS volume...")
|
205
|
-
@logger.debug "create volume in zone #{@context[:availability_zone]}"
|
206
|
-
res = @context[:ec2_api_handler].create_volume(:availability_zone => @context[:availability_zone], :size => "10")
|
207
|
-
@context[:volume_id] = res['volumeId']
|
208
|
-
started = false
|
209
|
-
while !started
|
210
|
-
sleep(5)
|
211
|
-
#TODO: check for timeout?
|
212
|
-
res = @context[:ec2_api_handler].describe_volumes(:volume_id => @context[:volume_id])
|
213
|
-
state = res['volumeSet']['item'][0]['status']
|
214
|
-
@logger.debug "volume state #{state}"
|
215
|
-
if state == 'available'
|
216
|
-
started = true
|
217
|
-
end
|
218
|
-
end
|
219
|
-
@context[:script].post_message("EBS volume #{@context[:volume_id]} is ready")
|
220
|
-
StorageCreated.new(@context)
|
221
|
-
end
|
222
|
-
|
223
|
-
end
|
224
|
-
|
225
|
-
# Storage created. Attach it.
|
226
|
-
class StorageCreated < Ami2EbsConversionState
|
227
|
-
def enter
|
228
|
-
attach_storage()
|
229
|
-
end
|
230
|
-
|
231
|
-
private
|
232
|
-
|
233
|
-
def attach_storage()
|
234
|
-
@context[:script].post_message("going to attach volume #{@context[:volume_id]} to instance #{@context[:instance_id]} on device #{@context[:temp_device_name]}...")
|
235
|
-
@logger.debug "attach volume #{@context[:volume_id]} to instance #{@context[:instance_id]} on device #{@context[:temp_device_name]}"
|
236
|
-
@context[:ec2_api_handler].attach_volume(:volume_id => @context[:volume_id],
|
237
|
-
:instance_id => @context[:instance_id],
|
238
|
-
:device => @context[:temp_device_name]
|
239
|
-
)
|
240
|
-
done = false
|
241
|
-
while !done
|
242
|
-
sleep(5)
|
243
|
-
#TODO: check for timeout?
|
244
|
-
res = @context[:ec2_api_handler].describe_volumes(:volume_id => @context[:volume_id])
|
245
|
-
state = res['volumeSet']['item'][0]['status']
|
246
|
-
@logger.debug "storage attaching: #{state}"
|
247
|
-
if state == 'in-use'
|
248
|
-
done = true
|
249
|
-
end
|
250
|
-
end
|
251
|
-
@context[:script].post_message("volume successfully attached")
|
252
|
-
StorageAttached.new(@context)
|
253
|
-
end
|
254
|
-
|
255
|
-
end
|
256
|
-
|
257
|
-
# Storage attached. Create a file-system and moun it
|
258
|
-
class StorageAttached < Ami2EbsConversionState
|
259
|
-
def enter
|
260
|
-
create_fs()
|
261
|
-
end
|
262
|
-
|
263
|
-
private
|
264
|
-
|
265
|
-
def create_fs()
|
266
|
-
@context[:script].post_message("going to create filesystem on #{@context[:dns_name]} to #{@context[:temp_device_name]}...")
|
267
|
-
@logger.debug "create filesystem on #{@context[:dns_name]} to #{@context[:temp_device_name]}"
|
268
|
-
connect()
|
269
|
-
@context[:remote_command_handler].create_filesystem("ext3", @context[:temp_device_name])
|
270
|
-
@context[:script].post_message("filesystem system successfully created")
|
271
|
-
FileSystemCreated.new(@context)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
# File system created. Mount it.
|
276
|
-
class FileSystemCreated < Ami2EbsConversionState
|
277
|
-
def enter
|
278
|
-
mount_fs()
|
279
|
-
end
|
280
|
-
|
281
|
-
private
|
282
|
-
|
283
|
-
def mount_fs()
|
284
|
-
@context[:path] = "/mnt/tmp_#{@context[:volume_id]}"
|
285
|
-
@context[:script].post_message("going to mount #{@context[:temp_device_name]} on #{@context[:path]}...")
|
286
|
-
@logger.debug "mount #{@context[:temp_device_name]} on #{@context[:path]}"
|
287
|
-
@context[:remote_command_handler].mkdir(@context[:path])
|
288
|
-
@context[:remote_command_handler].mount(@context[:temp_device_name], @context[:path])
|
289
|
-
sleep(2) #give mount some time
|
290
|
-
if !@context[:remote_command_handler].drive_mounted?(@context[:path])
|
291
|
-
raise Exception.new("drive #{@context[:path]} not mounted")
|
292
|
-
end
|
293
|
-
@context[:script].post_message("mount successful")
|
294
|
-
FileSystemMounted.new(@context)
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
# File system created and mounted. Copy the root partition.
|
299
|
-
class FileSystemMounted < Ami2EbsConversionState
|
300
|
-
def enter
|
301
|
-
copy()
|
302
|
-
end
|
303
|
-
|
304
|
-
private
|
305
|
-
|
306
|
-
def copy()
|
307
|
-
@context[:script].post_message("going to start copying files to #{@context[:path]}. This may take quite a time...")
|
308
|
-
@logger.debug "start copying to #{@context[:path]}"
|
309
|
-
start = Time.new.to_i
|
310
|
-
@context[:remote_command_handler].rsync("/", "#{@context[:path]}", "/mnt/")
|
311
|
-
@context[:remote_command_handler].rsync("/dev/", "#{@context[:path]}/dev/")
|
312
|
-
endtime = Time.new.to_i
|
313
|
-
@logger.info "copy took #{(endtime-start)}s"
|
314
|
-
@context[:script].post_message("copying is done (took #{endtime-start})s")
|
315
|
-
CopyDone.new(@context)
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
# Copy operation done. Unmount volume.
|
320
|
-
class CopyDone < Ami2EbsConversionState
|
321
|
-
def enter
|
322
|
-
unmount()
|
323
|
-
end
|
324
|
-
|
325
|
-
private
|
326
|
-
|
327
|
-
def unmount()
|
328
|
-
@context[:script].post_message("going to clean things up. Start with unmounting ...")
|
329
|
-
@logger.debug "unmount #{@context[:path]}"
|
330
|
-
@context[:remote_command_handler].umount(@context[:path])
|
331
|
-
sleep(2) #give umount some time
|
332
|
-
if @context[:remote_command_handler].drive_mounted?(@context[:path])
|
333
|
-
raise Exception.new("drive #{@context[:path]} not unmounted")
|
334
|
-
end
|
335
|
-
@context[:script].post_message("device unmounted")
|
336
|
-
VolumeUnmounted.new(@context)
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
# Volume unmounted. Detach it.
|
341
|
-
class VolumeUnmounted < Ami2EbsConversionState
|
342
|
-
def enter
|
343
|
-
detach()
|
344
|
-
end
|
345
|
-
|
346
|
-
private
|
347
|
-
|
348
|
-
def detach()
|
349
|
-
@context[:script].post_message("going to detach volume #{@context[:volume_id]}...")
|
350
|
-
@logger.debug "detach volume #{@context[:volume_id]}"
|
351
|
-
@context[:ec2_api_handler].detach_volume(:volume_id => @context[:volume_id],
|
352
|
-
:instance_id => @context[:instance_id]
|
353
|
-
)
|
354
|
-
done = false
|
355
|
-
while !done
|
356
|
-
sleep(3)
|
357
|
-
#TODO: check for timeout?
|
358
|
-
res = @context[:ec2_api_handler].describe_volumes(:volume_id => @context[:volume_id])
|
359
|
-
@logger.debug "volume detaching: #{res.inspect}"
|
360
|
-
if res['volumeSet']['item'][0]['status'] == 'available'
|
361
|
-
done = true
|
362
|
-
end
|
363
|
-
end
|
364
|
-
@context[:script].post_message("volume #{@context[:volume_id]} detached.")
|
365
|
-
VolumeDetached.new(@context)
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
|
370
|
-
# VolumeDetached. Create snaphot
|
371
|
-
class VolumeDetached < Ami2EbsConversionState
|
372
|
-
def enter
|
373
|
-
create_snapshot()
|
374
|
-
end
|
375
|
-
|
376
|
-
private
|
377
|
-
|
378
|
-
def create_snapshot()
|
379
|
-
@context[:script].post_message("going to create a snapshot...")
|
380
|
-
@logger.debug "create snapshot for volume #{@context[:volume_id]}"
|
381
|
-
res = @context[:ec2_api_handler].create_snapshot(:volume_id => @context[:volume_id])
|
382
|
-
@context[:snapshot_id] = res['snapshotId']
|
383
|
-
@logger.info "snapshot_id = #{@context[:snapshot_id]}"
|
384
|
-
done = false
|
385
|
-
while !done
|
386
|
-
sleep(5)
|
387
|
-
#TODO: check for timeout?
|
388
|
-
res = @context[:ec2_api_handler].describe_snapshots(:snapshot_id => @context[:snapshot_id])
|
389
|
-
@logger.debug "snapshot creating: #{res.inspect}"
|
390
|
-
if res['snapshotSet']['item'][0]['status'] == 'completed'
|
391
|
-
done = true
|
392
|
-
end
|
393
|
-
end
|
394
|
-
@context[:script].post_message("snapshot is done with ID=#{@context[:snapshot_id]}")
|
395
|
-
SnapshotCreated.new(@context)
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
# Snapshot created. Delete volume.
|
400
|
-
class SnapshotCreated < Ami2EbsConversionState
|
401
|
-
def enter
|
402
|
-
delete_volume()
|
403
|
-
end
|
404
|
-
|
405
|
-
private
|
406
|
-
|
407
|
-
def delete_volume
|
408
|
-
@context[:script].post_message("going to delete volume #{@context[:volume_id]} (no longer needed)...")
|
409
|
-
@logger.debug "delete volume #{@context[:volume_id]}"
|
410
|
-
res = @context[:ec2_api_handler].delete_volume(:volume_id => @context[:volume_id])
|
411
|
-
@context[:script].post_message("volume #{@context[:volume_id]} deleted")
|
412
|
-
VolumeDeleted.new(@context)
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
# Volume deleted. Register snapshot.
|
417
|
-
class VolumeDeleted < Ami2EbsConversionState
|
418
|
-
def enter
|
419
|
-
register()
|
420
|
-
end
|
421
|
-
|
422
|
-
private
|
423
|
-
|
424
|
-
def register()
|
425
|
-
@context[:script].post_message("going to register snapshot #{@context[:snapshot_id]}...")
|
426
|
-
@logger.debug "register snapshot #{@context[:snapshot_id]} as #{@context[:name]}"
|
427
|
-
res = @context[:ec2_api_handler].register_image_updated(:snapshot_id => @context[:snapshot_id],
|
428
|
-
:kernel_id => @context[:kernel_id], :architecture => @context[:architecture],
|
429
|
-
:root_device_name => @context[:root_device_name],
|
430
|
-
:description => @context[:description], :name => @context[:name],
|
431
|
-
:ramdisk_id => @context[:ramdisk_id]
|
432
|
-
)
|
433
|
-
@logger.debug "result of registration = #{res.inspect}"
|
434
|
-
@context[:result][:image_id] = res['imageId']
|
435
|
-
@logger.info "resulting image_id = #{@context[:result][:image_id]}"
|
436
|
-
@context[:script].post_message("snapshot #{@context[:snapshot_id]} successfully registered as AMI #{@context[:result][:image_id]} ")
|
437
|
-
SnapshotRegistered.new(@context)
|
438
|
-
end
|
439
|
-
end
|
440
|
-
|
441
|
-
# Snapshot registered. Shutdown instance.
|
442
|
-
class SnapshotRegistered < Ami2EbsConversionState
|
443
|
-
def enter
|
444
|
-
shut_down()
|
445
|
-
end
|
446
|
-
|
447
|
-
private
|
448
|
-
|
449
|
-
def shut_down()
|
450
|
-
@context[:script].post_message("going to shut down the temporary instance #{@context[:instance_id]}...")
|
451
|
-
@logger.debug "shutdown instance #{@context[:instance_id]}"
|
452
|
-
res = @context[:ec2_api_handler].terminate_instances(:instance_id => @context[:instance_id])
|
453
|
-
done = false
|
454
|
-
while done == false
|
455
|
-
sleep(5)
|
456
|
-
res = @context[:ec2_api_handler].describe_instances(:instance_id => @context[:instance_id])
|
457
|
-
state = res['reservationSet']['item'][0]['instancesSet']['item'][0]['instanceState']
|
458
|
-
@logger.debug "instance in state #{state['name']} (#{state['code']})"
|
459
|
-
if state['code'].to_i == 48
|
460
|
-
done = true
|
461
|
-
elsif state['code'].to_i != 32
|
462
|
-
raise Exception.new('instance failed to shut down')
|
463
|
-
end
|
464
|
-
end
|
465
|
-
@context[:script].post_message("instance #{@context[:instance_id]} is terminated")
|
466
|
-
Done.new(@context)
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
|
-
# Instance shutdown. Done.
|
471
|
-
class Done < Ami2EbsConversionState
|
472
|
-
def done?
|
473
|
-
true
|
474
|
-
end
|
475
|
-
end
|
476
|
-
|
477
|
-
end
|
1
|
+
require "help/script_execution_state"
|
2
|
+
require "scripts/ec2/ec2_script"
|
3
|
+
require "help/remote_command_handler"
|
4
|
+
#require "help/dm_crypt_helper"
|
5
|
+
require "AWS"
|
6
|
+
|
7
|
+
class AWS::EC2::Base
|
8
|
+
def register_image_updated(options)
|
9
|
+
params = {}
|
10
|
+
params["Name"] = options[:name].to_s
|
11
|
+
params["BlockDeviceMapping.1.Ebs.SnapshotId"] = options[:snapshot_id].to_s
|
12
|
+
params["BlockDeviceMapping.1.DeviceName"] = options[:root_device_name].to_s
|
13
|
+
params["Description"] = options[:description].to_s
|
14
|
+
params["KernelId"] = options[:kernel_id].to_s
|
15
|
+
params["RamdiskId"] = options[:ramdisk_id].to_s
|
16
|
+
params["Architecture"] = options[:architecture].to_s
|
17
|
+
params["RootDeviceName"] = options[:root_device_name].to_s
|
18
|
+
return response_generator(:action => "RegisterImage", :params => params)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Creates a bootable EBS storage from an existing AMI.
|
23
|
+
#
|
24
|
+
|
25
|
+
class Ami2EbsConversion < Ec2Script
|
26
|
+
# Input parameters
|
27
|
+
# * aws_access_key => the Amazon AWS Access Key (see Your Account -> Security Credentials)
|
28
|
+
# * aws_secret_key => the Amazon AWS Secret Key
|
29
|
+
# * ami_id => the ID of the AMI to be converted
|
30
|
+
# * security_group_name => name of the security group to start
|
31
|
+
# * ssh_key_data => Key information for the security group that starts the AMI [if not set, use ssh_key_files]
|
32
|
+
# * ssh_key_files => Key information for the security group that starts the AMI
|
33
|
+
# * remote_command_handler => object that allows to connect via ssh and execute commands (optional)
|
34
|
+
# * ec2_api_handler => object that allows to access the EC2 API (optional)
|
35
|
+
# * ec2_api_server => server to connect to (option, default is us-east-1.ec2.amazonaws.com)
|
36
|
+
# * name => the name of the AMI to be created
|
37
|
+
# * description => description on AMI to be created (optional)
|
38
|
+
# * temp_device_name => [default /dev/sdj] device name used to attach the temporary storage; change this only if there's already a volume attacged as /dev/sdj (optional, default is /dev/sdj)
|
39
|
+
# * root_device_name"=> [default /dev/sda1] device name used for the root device (optional)
|
40
|
+
def initialize(input_params)
|
41
|
+
super(input_params)
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_input_parameters()
|
45
|
+
if @input_params[:name] == nil
|
46
|
+
@input_params[:name] = "Boot EBS (for AMI #{@input_params[:ami_id]}) at #{Time.now.strftime('%d/%m/%Y %H.%M.%S')}"
|
47
|
+
else
|
48
|
+
end
|
49
|
+
if @input_params[:description] == nil
|
50
|
+
@input_params[:description] = @input_params[:name]
|
51
|
+
end
|
52
|
+
if @input_params[:temp_device_name] == nil
|
53
|
+
@input_params[:temp_device_name] = "/dev/sdj"
|
54
|
+
end
|
55
|
+
if @input_params[:root_device_name] == nil
|
56
|
+
@input_params[:root_device_name] = "/dev/sda1"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_initial_state()
|
61
|
+
Ami2EbsConversionState.load_state(@input_params)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Here begins the state machine implementation
|
67
|
+
class Ami2EbsConversionState < ScriptExecutionState
|
68
|
+
def self.load_state(context)
|
69
|
+
state = context[:initial_state] == nil ? InitialState.new(context) : context[:initial_state]
|
70
|
+
state
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
# Nothing done yet. Start by instantiating an AMI (in the right zone?)
|
76
|
+
# which serves to create
|
77
|
+
class InitialState < Ami2EbsConversionState
|
78
|
+
def enter
|
79
|
+
launch_instance()
|
80
|
+
AmiStarted.new(@context)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Ami started. Create a storage
|
85
|
+
class AmiStarted < Ami2EbsConversionState
|
86
|
+
def enter
|
87
|
+
create_volume()
|
88
|
+
StorageCreated.new(@context)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Storage created. Attach it.
|
93
|
+
class StorageCreated < Ami2EbsConversionState
|
94
|
+
def enter
|
95
|
+
attach_volume()
|
96
|
+
StorageAttached.new(@context)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Storage attached. Create a file-system and moun it
|
101
|
+
class StorageAttached < Ami2EbsConversionState
|
102
|
+
def enter
|
103
|
+
connect()
|
104
|
+
create_fs()
|
105
|
+
FileSystemCreated.new(@context)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# File system created. Mount it.
|
110
|
+
class FileSystemCreated < Ami2EbsConversionState
|
111
|
+
def enter
|
112
|
+
mount_fs()
|
113
|
+
FileSystemMounted.new(@context)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# File system created and mounted. Copy the root partition.
|
118
|
+
class FileSystemMounted < Ami2EbsConversionState
|
119
|
+
def enter
|
120
|
+
copy()
|
121
|
+
CopyDone.new(@context)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Copy operation done. Unmount volume.
|
126
|
+
class CopyDone < Ami2EbsConversionState
|
127
|
+
def enter
|
128
|
+
unmount_fs()
|
129
|
+
VolumeUnmounted.new(@context)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Volume unmounted. Detach it.
|
134
|
+
class VolumeUnmounted < Ami2EbsConversionState
|
135
|
+
def enter
|
136
|
+
detach_volume()
|
137
|
+
VolumeDetached.new(@context)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# VolumeDetached. Create snaphot
|
142
|
+
class VolumeDetached < Ami2EbsConversionState
|
143
|
+
def enter
|
144
|
+
create_snapshot()
|
145
|
+
SnapshotCreated.new(@context)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Snapshot created. Delete volume.
|
150
|
+
class SnapshotCreated < Ami2EbsConversionState
|
151
|
+
def enter
|
152
|
+
delete_volume()
|
153
|
+
VolumeDeleted.new(@context)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Volume deleted. Register snapshot.
|
158
|
+
class VolumeDeleted < Ami2EbsConversionState
|
159
|
+
def enter
|
160
|
+
register_snapshot()
|
161
|
+
SnapshotRegistered.new(@context)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Snapshot registered. Shutdown instance.
|
166
|
+
class SnapshotRegistered < Ami2EbsConversionState
|
167
|
+
def enter
|
168
|
+
shut_down_instance()
|
169
|
+
Done.new(@context)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Instance shutdown. Done.
|
174
|
+
class Done < Ami2EbsConversionState
|
175
|
+
def done?
|
176
|
+
true
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|