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 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.9'
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.'
@@ -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 !remote_execute("cryptsetup isLuks #{device}")
163
- raise Exception.new("device #{device} is already used differently")
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.9
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-29 00:00:00 +01:00
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