CloudyScripts 2.14.58 → 2.14.60

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