CloudyScripts 0.0.9 → 0.0.10
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/Rakefile +1 -1
- data/lib/help/dm_crypt_helper.rb +2 -2
- data/lib/help/progress_message_listener.rb +14 -0
- data/lib/scripts/ec2/ami2_ebs_conversion.rb +32 -1
- data/lib/scripts/ec2/dm_encrypt.rb +11 -0
- data/lib/scripts/ec2/ec2_script.rb +11 -0
- metadata +3 -2
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ require 'rake/testtask'
|
|
12
12
|
|
13
13
|
spec = Gem::Specification.new do |s|
|
14
14
|
s.name = 'CloudyScripts'
|
15
|
-
s.version = '0.0.
|
15
|
+
s.version = '0.0.10'
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.extra_rdoc_files = ['README.rdoc', 'LICENSE']
|
18
18
|
s.summary = 'Scripts to facilitate programming for infrastructure clouds.'
|
data/lib/help/dm_crypt_helper.rb
CHANGED
@@ -159,8 +159,8 @@ class DmCryptHelper < RemoteCommandHandler
|
|
159
159
|
# * device: device to be encrypted
|
160
160
|
# * path: path to which the encrypted device is mounted
|
161
161
|
def encrypt_storage(name, password, device, path)
|
162
|
-
if
|
163
|
-
raise Exception.new("device #{device} is already
|
162
|
+
if remote_execute("cryptsetup isLuks #{device}")
|
163
|
+
raise Exception.new("device #{device} is already a configured device")
|
164
164
|
end
|
165
165
|
if file_exists?(device)
|
166
166
|
if !file_exists?("/dev/mapper/#{name}")
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Defines a template for a class that allows to be notified
|
2
|
+
# about messages during script execution.A listener must be
|
3
|
+
# registered via #Ec2Script::register_state_change_listener.
|
4
|
+
# New messages are passed via the method #new_message.
|
5
|
+
|
6
|
+
class ProgressMessageListener
|
7
|
+
# Method called when a state changes. Note: calls are synchronous, the
|
8
|
+
# listener should return quickly and handle more complicated routines
|
9
|
+
# in a different thread. The level corresponds to the logger.LEVEL and
|
10
|
+
# allows to signal the importance of a message
|
11
|
+
def new_message(message, level = Logger::INFO)
|
12
|
+
raise Exception.new("ProgressMessageListener: new message notification not implemented")
|
13
|
+
end
|
14
|
+
end
|
@@ -58,6 +58,7 @@ class Ami2EbsConversion < Ec2Script
|
|
58
58
|
if @input_params[:root_device_name] == nil
|
59
59
|
@input_params[:root_device_name] = "/dev/sda1"
|
60
60
|
end
|
61
|
+
@input_params[:script] = self
|
61
62
|
# start state machine
|
62
63
|
current_state = Ami2EbsConversionState.load_state(@input_params)
|
63
64
|
@state_change_listeners.each() {|listener|
|
@@ -106,6 +107,7 @@ class Ami2EbsConversion < Ec2Script
|
|
106
107
|
end
|
107
108
|
|
108
109
|
def connect
|
110
|
+
@context[:script].post_message("connecting to #{@context[:dns_name]}...")
|
109
111
|
if @context[:remote_command_handler] == nil
|
110
112
|
@context[:remote_command_handler] = RemoteCommandHandler.new
|
111
113
|
end
|
@@ -140,6 +142,7 @@ class Ami2EbsConversion < Ec2Script
|
|
140
142
|
raise Exception.new("connection attempts stopped")
|
141
143
|
end
|
142
144
|
@context[:result][:os] = @context[:remote_command_handler].retrieve_os()
|
145
|
+
@context[:script].post_message("connected to #{@context[:dns_name]}. OS installed is #{@context[:result][:os]}")
|
143
146
|
@logger.info "connected to #{@context[:dns_name]}"
|
144
147
|
end
|
145
148
|
|
@@ -155,28 +158,34 @@ class Ami2EbsConversion < Ec2Script
|
|
155
158
|
private
|
156
159
|
|
157
160
|
def startup_ami()
|
161
|
+
@context[:script].post_message("starting up a new instance for AMI #{@context[:ami_id]}...")
|
158
162
|
@logger.debug "start up AMI #{@context[:ami_id]}"
|
159
163
|
res = @context[:ec2_api_handler].run_instances(:image_id => @context[:ami_id],
|
160
164
|
:security_group => @context[:security_group_name], :key_name => @context[:key_name])
|
161
165
|
instance_id = res['instancesSet']['item'][0]['instanceId']
|
162
166
|
@context[:instance_id] = instance_id
|
163
167
|
@logger.info "started instance #{instance_id}"
|
168
|
+
@context[:script].post_message("started instance #{instance_id}. wait until it is ready...")
|
164
169
|
#availability_zone , key_name/group_name
|
165
170
|
started = false
|
166
171
|
while started == false
|
167
172
|
sleep(5)
|
168
173
|
res = @context[:ec2_api_handler].describe_instances(:instance_id => @context[:instance_id])
|
169
174
|
state = res['reservationSet']['item'][0]['instancesSet']['item'][0]['instanceState']
|
170
|
-
@logger.info "instance in state #{state['name']} (#{state['code']})"
|
175
|
+
@logger.info "instance is in state #{state['name']} (#{state['code']})"
|
171
176
|
if state['code'].to_i == 16
|
172
177
|
started = true
|
178
|
+
@context[:script].post_message("instance is up and running")
|
173
179
|
@context[:dns_name] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['dnsName']
|
174
180
|
@context[:availability_zone] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['placement']['availabilityZone']
|
175
181
|
@context[:kernel_id] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['kernelId']
|
176
182
|
@context[:ramdisk_id] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['ramdiskId']
|
177
183
|
@context[:architecture] = res['reservationSet']['item'][0]['instancesSet']['item'][0]['architecture']
|
178
184
|
elsif state['code'].to_i != 0
|
185
|
+
@context[:script].post_message("instance in state #{state['name']}")
|
179
186
|
raise Exception.new('instance failed to start up')
|
187
|
+
else
|
188
|
+
@context[:script].post_message("instance still starting up...")
|
180
189
|
end
|
181
190
|
end
|
182
191
|
AmiStarted.new(@context)
|
@@ -192,6 +201,7 @@ class Ami2EbsConversion < Ec2Script
|
|
192
201
|
private
|
193
202
|
|
194
203
|
def create_storage()
|
204
|
+
@context[:script].post_message("going to create a new EBS volume...")
|
195
205
|
@logger.debug "create volume in zone #{@context[:availability_zone]}"
|
196
206
|
res = @context[:ec2_api_handler].create_volume(:availability_zone => @context[:availability_zone], :size => "10")
|
197
207
|
@context[:volume_id] = res['volumeId']
|
@@ -206,6 +216,7 @@ class Ami2EbsConversion < Ec2Script
|
|
206
216
|
started = true
|
207
217
|
end
|
208
218
|
end
|
219
|
+
@context[:script].post_message("EBS volume #{@context[:volume_id]} is ready")
|
209
220
|
StorageCreated.new(@context)
|
210
221
|
end
|
211
222
|
|
@@ -220,6 +231,7 @@ class Ami2EbsConversion < Ec2Script
|
|
220
231
|
private
|
221
232
|
|
222
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]}...")
|
223
235
|
@logger.debug "attach volume #{@context[:volume_id]} to instance #{@context[:instance_id]} on device #{@context[:temp_device_name]}"
|
224
236
|
@context[:ec2_api_handler].attach_volume(:volume_id => @context[:volume_id],
|
225
237
|
:instance_id => @context[:instance_id],
|
@@ -236,6 +248,7 @@ class Ami2EbsConversion < Ec2Script
|
|
236
248
|
done = true
|
237
249
|
end
|
238
250
|
end
|
251
|
+
@context[:script].post_message("volume successfully attached")
|
239
252
|
StorageAttached.new(@context)
|
240
253
|
end
|
241
254
|
|
@@ -250,9 +263,11 @@ class Ami2EbsConversion < Ec2Script
|
|
250
263
|
private
|
251
264
|
|
252
265
|
def create_fs()
|
266
|
+
@context[:script].post_message("going to create filesystem on #{@context[:dns_name]} to #{@context[:temp_device_name]}...")
|
253
267
|
@logger.debug "create filesystem on #{@context[:dns_name]} to #{@context[:temp_device_name]}"
|
254
268
|
connect()
|
255
269
|
@context[:remote_command_handler].create_filesystem("ext3", @context[:temp_device_name])
|
270
|
+
@context[:script].post_message("filesystem system successfully created")
|
256
271
|
FileSystemCreated.new(@context)
|
257
272
|
end
|
258
273
|
end
|
@@ -267,6 +282,7 @@ class Ami2EbsConversion < Ec2Script
|
|
267
282
|
|
268
283
|
def mount_fs()
|
269
284
|
@context[:path] = "/mnt/tmp_#{@context[:volume_id]}"
|
285
|
+
@context[:script].post_message("going to mount #{@context[:temp_device_name]} on #{@context[:path]}...")
|
270
286
|
@logger.debug "mount #{@context[:temp_device_name]} on #{@context[:path]}"
|
271
287
|
@context[:remote_command_handler].mkdir(@context[:path])
|
272
288
|
@context[:remote_command_handler].mount(@context[:temp_device_name], @context[:path])
|
@@ -274,6 +290,7 @@ class Ami2EbsConversion < Ec2Script
|
|
274
290
|
if !@context[:remote_command_handler].drive_mounted?(@context[:path])
|
275
291
|
raise Exception.new("drive #{@context[:path]} not mounted")
|
276
292
|
end
|
293
|
+
@context[:script].post_message("mount successful")
|
277
294
|
FileSystemMounted.new(@context)
|
278
295
|
end
|
279
296
|
end
|
@@ -287,12 +304,14 @@ class Ami2EbsConversion < Ec2Script
|
|
287
304
|
private
|
288
305
|
|
289
306
|
def copy()
|
307
|
+
@context[:script].post_message("going to start copying files to #{@context[:path]}. This may take quite a time...")
|
290
308
|
@logger.debug "start copying to #{@context[:path]}"
|
291
309
|
start = Time.new.to_i
|
292
310
|
@context[:remote_command_handler].rsync("/", "#{@context[:path]}", "/mnt/")
|
293
311
|
@context[:remote_command_handler].rsync("/dev/", "#{@context[:path]}/dev/")
|
294
312
|
endtime = Time.new.to_i
|
295
313
|
@logger.info "copy took #{(endtime-start)}s"
|
314
|
+
@context[:script].post_message("copying is done (took #{endtime-start})s")
|
296
315
|
CopyDone.new(@context)
|
297
316
|
end
|
298
317
|
end
|
@@ -306,12 +325,14 @@ class Ami2EbsConversion < Ec2Script
|
|
306
325
|
private
|
307
326
|
|
308
327
|
def unmount()
|
328
|
+
@context[:script].post_message("going to clean things up. Start with unmounting ...")
|
309
329
|
@logger.debug "unmount #{@context[:path]}"
|
310
330
|
@context[:remote_command_handler].umount(@context[:path])
|
311
331
|
sleep(2) #give umount some time
|
312
332
|
if @context[:remote_command_handler].drive_mounted?(@context[:path])
|
313
333
|
raise Exception.new("drive #{@context[:path]} not unmounted")
|
314
334
|
end
|
335
|
+
@context[:script].post_message("device unmounted")
|
315
336
|
VolumeUnmounted.new(@context)
|
316
337
|
end
|
317
338
|
end
|
@@ -325,6 +346,7 @@ class Ami2EbsConversion < Ec2Script
|
|
325
346
|
private
|
326
347
|
|
327
348
|
def detach()
|
349
|
+
@context[:script].post_message("going to detach volume #{@context[:volume_id]}...")
|
328
350
|
@logger.debug "detach volume #{@context[:volume_id]}"
|
329
351
|
@context[:ec2_api_handler].detach_volume(:volume_id => @context[:volume_id],
|
330
352
|
:instance_id => @context[:instance_id]
|
@@ -339,6 +361,7 @@ class Ami2EbsConversion < Ec2Script
|
|
339
361
|
done = true
|
340
362
|
end
|
341
363
|
end
|
364
|
+
@context[:script].post_message("volume #{@context[:volume_id]} detached.")
|
342
365
|
VolumeDetached.new(@context)
|
343
366
|
end
|
344
367
|
end
|
@@ -353,6 +376,7 @@ class Ami2EbsConversion < Ec2Script
|
|
353
376
|
private
|
354
377
|
|
355
378
|
def create_snapshot()
|
379
|
+
@context[:script].post_message("going to create a snapshot...")
|
356
380
|
@logger.debug "create snapshot for volume #{@context[:volume_id]}"
|
357
381
|
res = @context[:ec2_api_handler].create_snapshot(:volume_id => @context[:volume_id])
|
358
382
|
@context[:snapshot_id] = res['snapshotId']
|
@@ -367,6 +391,7 @@ class Ami2EbsConversion < Ec2Script
|
|
367
391
|
done = true
|
368
392
|
end
|
369
393
|
end
|
394
|
+
@context[:script].post_message("snapshot is done with ID=#{@context[:snapshot_id]}")
|
370
395
|
SnapshotCreated.new(@context)
|
371
396
|
end
|
372
397
|
end
|
@@ -380,8 +405,10 @@ class Ami2EbsConversion < Ec2Script
|
|
380
405
|
private
|
381
406
|
|
382
407
|
def delete_volume
|
408
|
+
@context[:script].post_message("going to delete volume #{@context[:volume_id]} (no longer needed)...")
|
383
409
|
@logger.debug "delete volume #{@context[:volume_id]}"
|
384
410
|
res = @context[:ec2_api_handler].delete_volume(:volume_id => @context[:volume_id])
|
411
|
+
@context[:script].post_message("volume #{@context[:volume_id]} deleted")
|
385
412
|
VolumeDeleted.new(@context)
|
386
413
|
end
|
387
414
|
end
|
@@ -395,6 +422,7 @@ class Ami2EbsConversion < Ec2Script
|
|
395
422
|
private
|
396
423
|
|
397
424
|
def register()
|
425
|
+
@context[:script].post_message("going to register snapshot #{@context[:snapshot_id]}...")
|
398
426
|
@logger.debug "register snapshot #{@context[:snapshot_id]} as #{@context[:name]}"
|
399
427
|
res = @context[:ec2_api_handler].register_image_updated(:snapshot_id => @context[:snapshot_id],
|
400
428
|
:kernel_id => @context[:kernel_id], :architecture => @context[:architecture],
|
@@ -405,6 +433,7 @@ class Ami2EbsConversion < Ec2Script
|
|
405
433
|
@logger.debug "result of registration = #{res.inspect}"
|
406
434
|
@context[:result][:image_id] = res['imageId']
|
407
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]} ")
|
408
437
|
SnapshotRegistered.new(@context)
|
409
438
|
end
|
410
439
|
end
|
@@ -418,6 +447,7 @@ class Ami2EbsConversion < Ec2Script
|
|
418
447
|
private
|
419
448
|
|
420
449
|
def shut_down()
|
450
|
+
@context[:script].post_message("going to shut down the temporary instance #{@context[:instance_id]}...")
|
421
451
|
@logger.debug "shutdown instance #{@context[:instance_id]}"
|
422
452
|
res = @context[:ec2_api_handler].terminate_instances(:instance_id => @context[:instance_id])
|
423
453
|
done = false
|
@@ -432,6 +462,7 @@ class Ami2EbsConversion < Ec2Script
|
|
432
462
|
raise Exception.new('instance failed to shut down')
|
433
463
|
end
|
434
464
|
end
|
465
|
+
@context[:script].post_message("instance #{@context[:instance_id]} is terminated")
|
435
466
|
Done.new(@context)
|
436
467
|
end
|
437
468
|
end
|
@@ -45,6 +45,7 @@ class DmEncrypt < Ec2Script
|
|
45
45
|
@input_params[:ec2_api_handler] = AWS::EC2::Base.new(:access_key_id => @input_params[:aws_access_key],
|
46
46
|
:secret_access_key => @input_params[:aws_secret_key], :server => @input_params[:ec2_api_server])
|
47
47
|
end
|
48
|
+
@input_params[:script] = self
|
48
49
|
# start state machine
|
49
50
|
current_state = DmEncryptState.load_state(@input_params)
|
50
51
|
@state_change_listeners.each() {|listener|
|
@@ -102,6 +103,7 @@ class DmEncrypt < Ec2Script
|
|
102
103
|
private
|
103
104
|
|
104
105
|
def connect()
|
106
|
+
@context[:script].post_message("going to connect to #{@context[:ip_address]}...")
|
105
107
|
@logger.debug "InitialState.connect"
|
106
108
|
if @context[:ssh_key_file] != nil
|
107
109
|
@context[:remote_command_handler].connect_with_keyfile(@context[:ip_address], @context[:ssh_key_file])
|
@@ -111,6 +113,7 @@ class DmEncrypt < Ec2Script
|
|
111
113
|
raise Exception.new("no key information specified")
|
112
114
|
end
|
113
115
|
@context[:result][:os] = @context[:remote_command_handler].retrieve_os()
|
116
|
+
@context[:script].post_message("connection successful, OS = #{@context[:result][:os]}")
|
114
117
|
ConnectedState.new(@context)
|
115
118
|
end
|
116
119
|
end
|
@@ -123,8 +126,10 @@ class DmEncrypt < Ec2Script
|
|
123
126
|
|
124
127
|
private
|
125
128
|
def install_tools
|
129
|
+
@context[:script].post_message("check if the system has the cryptset-package installed")
|
126
130
|
@logger.debug "ConnectedState.install_tools"
|
127
131
|
if !tools_installed?
|
132
|
+
@context[:script].post_message("cryptset-package not installed. Going to install it...")
|
128
133
|
TOOLS.each() {|tool|
|
129
134
|
@context[:remote_command_handler].install(tool)
|
130
135
|
}
|
@@ -133,6 +138,7 @@ class DmEncrypt < Ec2Script
|
|
133
138
|
raise Exception.new("dm-crypt module missing")
|
134
139
|
end
|
135
140
|
if tools_installed?
|
141
|
+
@context[:script].post_message("cryptset-package is available")
|
136
142
|
@logger.debug "system says that tools are installed"
|
137
143
|
ToolInstalledState.new(@context)
|
138
144
|
else
|
@@ -158,9 +164,12 @@ class DmEncrypt < Ec2Script
|
|
158
164
|
|
159
165
|
private
|
160
166
|
def create_encrypted_volume
|
167
|
+
@context[:script].post_message("going to encrypt device #{@context[:device]} "+
|
168
|
+
"named '#{@context[:device_name]}' and mount it as #{@context[:storage_path]}...")
|
161
169
|
@logger.debug "ToolInstalledState.create_encrypted_volume"
|
162
170
|
@context[:remote_command_handler].encrypt_storage(@context[:device_name],
|
163
171
|
@context[:paraphrase], @context[:device], @context[:storage_path])
|
172
|
+
@context[:script].post_message("device #{@context[:device]} is encrypted and mounted")
|
164
173
|
MountedAndActivatedState.new(@context)
|
165
174
|
end
|
166
175
|
|
@@ -179,8 +188,10 @@ class DmEncrypt < Ec2Script
|
|
179
188
|
|
180
189
|
private
|
181
190
|
def cleanup()
|
191
|
+
@context[:script].post_message("disconnecting...")
|
182
192
|
@logger.debug "MountedAndActivatedState.cleanup"
|
183
193
|
@context[:remote_command_handler].disconnect()
|
194
|
+
@context[:script].post_message("done")
|
184
195
|
DoneState.new(@context)
|
185
196
|
end
|
186
197
|
|
@@ -9,6 +9,7 @@ class Ec2Script
|
|
9
9
|
def initialize(input_params)
|
10
10
|
@input_params = input_params
|
11
11
|
@state_change_listeners = []
|
12
|
+
@progress_message_listeners = []
|
12
13
|
if input_params[:logger] == nil
|
13
14
|
@logger = Logger.new(STDOUT)
|
14
15
|
@logger .level = Logger::WARN
|
@@ -22,6 +23,10 @@ class Ec2Script
|
|
22
23
|
@state_change_listeners << listener
|
23
24
|
end
|
24
25
|
|
26
|
+
def register_progress_message_listener(listener)
|
27
|
+
@progress_message_listeners << listener
|
28
|
+
end
|
29
|
+
|
25
30
|
def start_script
|
26
31
|
raise Exception.new("must be implemented")
|
27
32
|
end
|
@@ -37,5 +42,11 @@ class Ec2Script
|
|
37
42
|
raise Exception.new("must be implemented")
|
38
43
|
end
|
39
44
|
|
45
|
+
def post_message(message, level = Logger::DEBUG)
|
46
|
+
@progress_message_listeners.each() {|listener|
|
47
|
+
listener.new_message(message, level)
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
40
51
|
end
|
41
52
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: CloudyScripts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthias Jung
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01
|
12
|
+
date: 2010-02-01 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- lib/cloudyscripts.rb
|
49
49
|
- lib/help/dm_crypt_helper.rb
|
50
50
|
- lib/help/ec2_helper.rb
|
51
|
+
- lib/help/progress_message_listener.rb
|
51
52
|
- lib/help/remote_command_handler.rb
|
52
53
|
- lib/help/script_execution_state.rb
|
53
54
|
- lib/help/state_change_listener.rb
|