CloudyScripts 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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