CloudyScripts 2.14.58 → 2.14.60

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
@@ -13,7 +13,7 @@ require 'rake/testtask'
13
13
  spec = Gem::Specification.new do |s|
14
14
  s.name = 'CloudyScripts'
15
15
  #s.version = '2.14.54' #<number cloud-stacks supported>.<number cloud-scripts>.<counting releases>
16
- s.version = '2.14.58' #<number cloud-stacks supported>.<number cloud-scripts>.<counting releases>
16
+ s.version = '2.14.60' #<number cloud-stacks supported>.<number cloud-scripts>.<counting releases>
17
17
  s.has_rdoc = true
18
18
  s.extra_rdoc_files = ['README.rdoc', 'LICENSE']
19
19
  s.summary = 'Scripts to facilitate programming for infrastructure clouds.'
@@ -0,0 +1,14 @@
1
+ #
2
+ # Function that can be used in the whole library
3
+ #
4
+
5
+
6
+ # Check if string is not more than 255 character and contains wide char
7
+ def check_string_alnum(str)
8
+ if str.match(/^[0-9a-z\-\_\ ]{1,255}$/i)
9
+ return true
10
+ else
11
+ return false
12
+ end
13
+ return true
14
+ end
@@ -69,13 +69,29 @@ class RemoteCommandHandler
69
69
  get_output("uname -r").strip
70
70
  end
71
71
 
72
+ # Return all the partitions of a device
73
+ def get_device_partition(device)
74
+ get_output("ls #{device}*").strip
75
+ end
76
+
77
+ # Get the partition table of a device
78
+ def get_partition_table(device)
79
+ get_output("sfdisk -d #{device}")
80
+ end
81
+
82
+ # GSet the partition table of a device
83
+ def set_partition_table(device, partition_table)
84
+ push_data = "\"" + partition_table.gsub(/\/dev\/(s|xv)d[a-z]/, "#{device}") + "\""
85
+ remote_execute("sfdisk -f #{device}", push_data, nil)
86
+ end
87
+
72
88
  # Get root partition label
73
89
  def get_root_device()
74
90
  #get_output("cat /etc/mtab | grep -E '[[:blank:]]+\/[[:blank:]]+' | cut -d ' ' -f 1").strip
75
91
  get_output("mount | grep -E '[[:blank:]]+\/[[:blank:]]+' | cut -d ' ' -f 1").strip
76
92
  end
77
93
 
78
- # Get partition label
94
+ # Get the device of a specific partition
79
95
  def get_partition_device(part)
80
96
  #get_output("cat /etc/mtab | grep -E '[[:blank:]]+" + "#{part}" + "[[:blank:]]+' | cut -d ' ' -f 1").strip
81
97
  get_output("mount | grep -E '[[:blank:]]+" + "#{part}" + "[[:blank:]]+' | cut -d ' ' -f 1").strip
@@ -351,7 +367,7 @@ class RemoteCommandHandler
351
367
 
352
368
  def upload(ip, user, key_data, local_file, destination_file, timeout = 60)
353
369
  Timeout::timeout(timeout) {
354
- Net::SCP.start(ip, user, {:key_data => [key_data], :timeout => timeout}) do |scp|
370
+ Net::SCP.start(ip, user, {:key_data => [key_data], :timeout => timeout, :paranoid => false, :verbose => :warn}) do |scp|
355
371
  scp.upload!(local_file, destination_file)
356
372
  end
357
373
  }
@@ -74,6 +74,10 @@ class ScriptExecutionState
74
74
  s.sub(/.*\:\:/,'')
75
75
  end
76
76
 
77
+ def get_superclass_name
78
+ self.class.name.split('::').first()
79
+ end
80
+
77
81
  private
78
82
 
79
83
  # Notifies all listeners of state changes
@@ -535,7 +535,7 @@ module StateTransitionHelper
535
535
  # * image_id => ID of the AMI created and registered
536
536
  def register_snapshot(snapshot_id, name, root_device_name, description, kernel_id, ramdisk_id, architecture)
537
537
  post_message("going to register snapshot #{snapshot_id}...")
538
- @logger.debug "register snapshot #{snapshot_id} as #{name} using AKI '#{kernel_id}' ARI '#{ramdisk_id}' and arch '#{architecture}'"
538
+ @logger.debug "register snapshot #{snapshot_id} as #{name} using AKI '#{kernel_id}', ARI '#{ramdisk_id}', arch '#{architecture}' and RootDevice '#{root_device_name}'"
539
539
  res = ec2_handler().register_image_updated(:snapshot_id => snapshot_id,
540
540
  :kernel_id => kernel_id, :architecture => architecture,
541
541
  :root_device_name => root_device_name,
@@ -705,6 +705,70 @@ module StateTransitionHelper
705
705
  post_message("#{msg}")
706
706
  end
707
707
 
708
+ # Get partition count
709
+ def get_partition_count(device)
710
+ post_message("Checking partition on device '#{device}'...")
711
+ #XXX: detect new kernel that have /dev/xvdX device node instead of /dev/sdX
712
+ if device =~ /\/dev\/sd[a-z]/
713
+ if !remote_handler().file_exists?(device)
714
+ post_message("'#{device}' device node not found, checking for new kernel support...")
715
+ @logger.debug "'#{device}' device node not found, checking for new kernel support"
716
+ new_device = device.gsub('sd', 'xvd')
717
+ if remote_handler().file_exists?(new_device)
718
+ post_message("'#{new_device}' device node found")
719
+ @logger.debug "'#{new_device}' device node found"
720
+ device = new_device
721
+ end
722
+ end
723
+ end
724
+ parts = remote_handler().get_device_partition(device).split(/[[:space:]]+/)
725
+ @logger.debug "Found '#{parts}' on device '#{device}'"
726
+ return parts.size()
727
+ end
728
+
729
+ # Get partition table
730
+ def get_partition_table(device)
731
+ post_message("Retrieving the partition table of device '#{device}'...")
732
+ #XXX: detect new kernel that have /dev/xvdX device node instead of /dev/sdX
733
+ if device =~ /\/dev\/sd[a-z]/
734
+ if !remote_handler().file_exists?(device)
735
+ post_message("'#{device}' device node not found, checking for new kernel support...")
736
+ @logger.debug "'#{device}' device node not found, checking for new kernel support"
737
+ new_device = device.gsub('sd', 'xvd')
738
+ if remote_handler().file_exists?(new_device)
739
+ post_message("'#{new_device}' device node found")
740
+ @logger.debug "'#{new_device}' device node found"
741
+ device = new_device
742
+ end
743
+ end
744
+ end
745
+ partition_table = remote_handler().get_partition_table(device)
746
+ # remove ^M char
747
+ partition_table.gsub!("\015", "")
748
+ @logger.debug "Found the following partition table on device '#{device}'\n#{partition_table}"
749
+ return partition_table
750
+ end
751
+
752
+ # Set partition table
753
+ def set_partition_table(device, partition_table)
754
+ post_message("Setting the partition table of device '#{device}'...")
755
+ #XXX: detect new kernel that have /dev/xvdX device node instead of /dev/sdX
756
+ if device =~ /\/dev\/sd[a-z]/
757
+ if !remote_handler().file_exists?(device)
758
+ post_message("'#{device}' device node not found, checking for new kernel support...")
759
+ @logger.debug "'#{device}' device node not found, checking for new kernel support"
760
+ new_device = device.gsub('sd', 'xvd')
761
+ if remote_handler().file_exists?(new_device)
762
+ post_message("'#{new_device}' device node found")
763
+ @logger.debug "'#{new_device}' device node found"
764
+ device = new_device
765
+ end
766
+ end
767
+ end
768
+ remote_handler().set_partition_table(device, partition_table.gsub(/\/dev\/(s|xv)d[a-z]/, "#{device}"))
769
+ @logger.debug "Partition table set on device '#{device}'"
770
+ end
771
+
708
772
  # Get root partition
709
773
  def get_root_device_name()
710
774
  post_message("Retrieving '/' root device name...")
@@ -1296,18 +1360,7 @@ module StateTransitionHelper
1296
1360
  return region
1297
1361
  end
1298
1362
 
1299
- # Check if string is not more than 255 character and contains wide char
1300
- def check_string_alnum(str)
1301
- if str.match(/^[0-9a-z\-\_\ ]{1,255}$/i)
1302
- return 0
1303
- else
1304
- return 1
1305
- end
1306
- return 1
1307
- end
1308
-
1309
1363
  #setting/retrieving handlers
1310
-
1311
1364
  def remote_handler()
1312
1365
  if @remote_handler == nil
1313
1366
  if @context[:remote_command_handler] == nil
@@ -4,6 +4,8 @@ require "help/remote_command_handler"
4
4
  require "help/dm_crypt_helper"
5
5
  require "help/ec2_helper"
6
6
  require "AWS"
7
+ require "help/helper"
8
+
7
9
 
8
10
  # Copy a given snapshot to another region
9
11
  # * start up instance in source-region, create a snapshot from the mounted EBS
@@ -65,8 +67,8 @@ class CopyAmi < Ec2Script
65
67
  if @input_params[:target_ssh_username] == nil
66
68
  @input_params[:target_ssh_username] = "root"
67
69
  end
68
- if @input_params[:description] == nil || check_string_alnum(@input_params[:description])
69
- @input_params[:description] = "Created by Cloudy_Scripts - copy_ami"
70
+ if @input_params[:description] == nil || !check_string_alnum(@input_params[:description])
71
+ @input_params[:description] = "Created by CloudyScripts - #{self.class.name}"
70
72
  end
71
73
  end
72
74
 
@@ -107,10 +109,11 @@ class CopyAmi < Ec2Script
107
109
  end
108
110
  end
109
111
 
110
- # Source is started. Create a snapshot on the volume that is linked to the instance.
112
+ # Source is started. Create a snapshot on the volume that is linked to the instance.
111
113
  class SourceInstanceLaunchedState < CopyAmiState
112
114
  def enter()
113
- @context[:snapshot_id] = create_snapshot(@context[:ebs_volume_id], "Cloudy_Scripts Snapshot for copying AMIs")
115
+ @context[:snapshot_id] = create_snapshot(@context[:ebs_volume_id],
116
+ "Created by CloudyScripts - #{self.get_superclass_name()} from #{@context[:ebs_volume_id]}")
114
117
  AmiSnapshotCreatedState.new(@context)
115
118
  end
116
119
  end
@@ -132,13 +135,31 @@ class CopyAmi < Ec2Script
132
135
  os_letter = root_device_name.split('/')[2].gsub('sd', '').gsub('xvd', '').gsub(/[0-9]/, '')
133
136
  aws_device_letter = device.split('/')[2].gsub('sd', '').gsub('xvd', '').gsub(/[0-9]/, '')
134
137
  if !aws_letter.eql?(os_letter)
135
- post_message("Detected specific kernel with shift between AWS and Kernel OS for device naming")
138
+ post_message("Detected specific kernel with shift between AWS and Kernel OS for device naming: '#{aws_root_device}' vs '#{root_device_name}'")
136
139
  end
137
140
  while !aws_letter.eql?(os_letter)
138
141
  aws_letter.succ!
139
142
  aws_device_letter.succ!
140
143
  end
141
- device = "/dev/sd#{aws_device_letter}"
144
+
145
+ device = "/dev/sd#{aws_device_letter}"
146
+ # detect root partition vs root volume: simply check if we have several /dev/sdx* entries
147
+ parts_count = get_partition_count(device)
148
+ if parts_count >= 2
149
+ # retrieve partition table, in order to restore it in the target region
150
+ post_message("Detected specific volume with a valid partition table on device '#{device}'...")
151
+ partition_table = get_partition_table(device)
152
+ @context[:partition_table] = partition_table
153
+ #XXX: HANDLE at a LOWER LEVEL
154
+ # update partition table with device
155
+ # s/device/@context[:temp_device_name]/ on partition table
156
+ #@context[:partition_table] = partition_table.gsub("#{device}", "#{@context[:temp_device_name]}")
157
+ # retrieve the root partition number
158
+ os_nb = root_device_name.split('/')[2].gsub('sd', '').gsub('xvd', '').gsub(/[a-z]/, '')
159
+ device = device + os_nb
160
+ @context[:root_partition_nb] = os_nb
161
+ post_message("Using root partition: '#{device}'...")
162
+ end
142
163
  post_message("Using AWS name '#{@context[:temp_device_name]}' and OS name '#{device}'")
143
164
  mount_fs(mount_point, device)
144
165
  # get root partition label and filesystem type
@@ -176,6 +197,17 @@ class CopyAmi < Ec2Script
176
197
  mount_point = "/mnt/tmp_#{@context[:target_volume_id]}"
177
198
  attach_volume(@context[:target_volume_id], @context[:target_instance_id], device)
178
199
  connect(@context[:target_dns_name], @context[:target_ssh_username], nil, @context[:target_ssh_keydata])
200
+ # check if we need to create a partition table
201
+ if !(@context[:partition_table] == nil)
202
+ post_message("Creating a partition table on device '#{device}'...")
203
+ set_partition_table(device, @context[:partition_table])
204
+ #XXX: HANDLE at a LOWER LEVEL
205
+ # before adding partition table, adjust device name
206
+ #set_partition_table(device, @context[:partition_table].gsub(/\/dev\/(s|xv)d[a-z]/, "#{@context[:temp_device_name]}"))
207
+ # adjust partition to mount
208
+ device = device + @context[:root_partition_nb]
209
+ end
210
+ # make root partition
179
211
  create_labeled_fs(@context[:target_dns_name], device, @context[:fs_type], @context[:label])
180
212
  mount_fs(mount_point, device)
181
213
  disconnect()
@@ -233,8 +265,8 @@ class CopyAmi < Ec2Script
233
265
  class DataCopiedState < CopyAmiState
234
266
  def enter()
235
267
  remote_region()
236
- #@context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id], "Created by Cloudy_Scripts - copy_ami")
237
- @context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id], @context[:description])
268
+ @context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id],
269
+ "Created by CloudyScripts - #{self.get_superclass_name()} from #{@context[:target_volume_id]}")
238
270
  TargetSnapshotCreatedState.new(@context)
239
271
  end
240
272
  end
@@ -246,9 +278,13 @@ class CopyAmi < Ec2Script
246
278
  # Get Amazon Kernel Image ID
247
279
  aki = get_aws_kernel_image_aki(@context[:source_availability_zone], @context[:kernel_id],
248
280
  @context[:target_availability_zone])
281
+ device = @context[:root_device_name]
282
+ if !(@context[:partition_table] == nil)
283
+ device.gsub!(/[0-9]/, '')
284
+ post_message("Using BlockDevice for snapshot registration rather than RootDevice '#{device}' due to a valid partition table on device...")
285
+ end
249
286
  @context[:result][:image_id] = register_snapshot(@context[:new_snapshot_id], @context[:name],
250
- @context[:root_device_name], @context[:description], aki,
251
- nil, @context[:architecture])
287
+ device, @context[:description], aki, nil, @context[:architecture])
252
288
  AmiRegisteredState.new(@context)
253
289
  end
254
290
  end
@@ -4,6 +4,8 @@ require "help/remote_command_handler"
4
4
  require "help/dm_crypt_helper"
5
5
  require "help/ec2_helper"
6
6
  require "AWS"
7
+ require "help/helper"
8
+
7
9
 
8
10
  # Copy a given snapshot to another region
9
11
  # * start up instance in source-region, create a snapshot from the mounted EBS
@@ -102,8 +104,8 @@ class CopyMsWindowsAmi < Ec2Script
102
104
  if @input_params[:fs_type] == nil
103
105
  @input_params[:fs_type] = "ext3"
104
106
  end
105
- if @input_params[:description] == nil || check_string_alnum(@input_params[:description])
106
- @input_params[:description] = "Created by Cloudy_Scripts - copy_mswindows_ami"
107
+ if @input_params[:description] == nil || !check_string_alnum(@input_params[:description])
108
+ @input_params[:description] = "Created by CloudyScripts - #{self.class.name}"
107
109
  end
108
110
  end
109
111
 
@@ -173,7 +175,8 @@ class CopyMsWindowsAmi < Ec2Script
173
175
  stop_instance(instance_id)
174
176
  post_message("Instance '#{instance_id}' stopped, creating snapshot")
175
177
  ebs_volume_id = ec2_helper.get_attached_volumes(instance_id)[0]['volumeId']
176
- @context[:snapshot_id] = create_snapshot(ebs_volume_id, "Cloudy_Scripts Snapshot for copying AMIs")
178
+ @context[:snapshot_id] = create_snapshot(ebs_volume_id,
179
+ "Created by CloudyScripts - #{self.class.name} from #{ebs_volume_id}")
177
180
 
178
181
  InitialStateDone.new(@context)
179
182
  end
@@ -4,7 +4,8 @@ require "help/remote_command_handler"
4
4
  require "help/dm_crypt_helper"
5
5
  require "help/ec2_helper"
6
6
  require "AWS"
7
- #require 'pp'
7
+ require "help/helper"
8
+
8
9
 
9
10
  # Copy a given snapshot to another region
10
11
  # * start up instance in source-region, create a snapshot from the mounted EBS
@@ -83,8 +84,8 @@ class CopyMsWindowsSnapshot < Ec2Script
83
84
  if @input_params[:fs_type] == nil
84
85
  @input_params[:fs_type] = "ext3"
85
86
  end
86
- if @input_params[:description] == nil || check_string_alnum(@input_params[:description])
87
- @input_params[:description] = "Created by Cloudy_Scripts - copy_mswindows_snapshot"
87
+ if @input_params[:description] == nil || !check_string_alnum(@input_params[:description])
88
+ @input_params[:description] = "Created by CloudyScripts - #{self.class.name}"
88
89
  end
89
90
  if @input_params[:compression] != nil && (@input_params[:compression] =~ /^on$/i)
90
91
  @input_params[:compression] = true
@@ -376,7 +377,6 @@ class CopyMsWindowsSnapshot < Ec2Script
376
377
  def enter()
377
378
  remote_region()
378
379
  detach_volume(@context[:target_volume_id], @context[:target_instance_id])
379
- #@context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id], "Created by CloudyScripts - copy_mswindows_ami")
380
380
  @context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id], @context[:description])
381
381
  @context[:result][:snapshot_id] = @context[:new_snapshot_id]
382
382
 
@@ -4,6 +4,8 @@ require "help/remote_command_handler"
4
4
  require "help/dm_crypt_helper"
5
5
  require "help/ec2_helper"
6
6
  require "AWS"
7
+ require "help/helper"
8
+
7
9
 
8
10
  # Copy a given snapshot to another region
9
11
  # * start up instance in source-region, create volume from snapshot, attach volume, and mount it
@@ -49,8 +51,8 @@ class CopySnapshot< Ec2Script
49
51
  if @input_params[:target_ssh_username] == nil
50
52
  @input_params[:target_ssh_username] = "root"
51
53
  end
52
- if @input_params[:description] == nil || check_string_alnum(@input_params[:description])
53
- @input_params[:description] = "Created by Cloudy_Scripts - copy_snapshot"
54
+ if @input_params[:description] == nil || !check_string_alnum(@input_params[:description])
55
+ @input_params[:description] = "Created by CloudyScripts - #{self.class.name}"
54
56
  end
55
57
  end
56
58
 
@@ -194,8 +196,7 @@ class CopySnapshot< Ec2Script
194
196
  class DataCopiedState < CopySnapshotState
195
197
  def enter()
196
198
  remote_region()
197
- #@context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id], "Created by Cloudy_Scripts - copy_snapshot")
198
- @context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id], @context[:description])
199
+ @context[:new_snapshot_id] = create_snapshot(@context[:target_volume_id], @context[:description])
199
200
  @context[:result][:snapshot_id] = @context[:new_snapshot_id]
200
201
  SnapshotCreatedState.new(@context)
201
202
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: CloudyScripts
3
3
  version: !ruby/object:Gem::Version
4
- hash: 67
4
+ hash: 79
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 14
9
- - 58
10
- version: 2.14.58
9
+ - 60
10
+ version: 2.14.60
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matthias Jung
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-07-13 00:00:00 +00:00
18
+ date: 2012-07-26 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -274,6 +274,7 @@ files:
274
274
  - lib/help/v_cloud_transition_helper.rb
275
275
  - lib/help/v_cloud_api_handler.rb
276
276
  - lib/help/remote_command_handler.rb
277
+ - lib/help/helper.rb
277
278
  - lib/help/state_change_listener.rb
278
279
  - lib/cloudyscripts.rb
279
280
  has_rdoc: true