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 +1 -1
- data/lib/help/helper.rb +14 -0
- data/lib/help/remote_command_handler.rb +18 -2
- data/lib/help/script_execution_state.rb +4 -0
- data/lib/help/state_transition_helper.rb +65 -12
- data/lib/scripts/ec2/copy_ami.rb +46 -10
- data/lib/scripts/ec2/copy_mswindows_ami.rb +6 -3
- data/lib/scripts/ec2/copy_mswindows_snapshot.rb +4 -4
- data/lib/scripts/ec2/copy_snapshot.rb +5 -4
- metadata +5 -4
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.
|
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.'
|
data/lib/help/helper.rb
ADDED
@@ -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
|
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
|
}
|
@@ -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}'
|
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
|
data/lib/scripts/ec2/copy_ami.rb
CHANGED
@@ -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
|
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
|
-
|
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],
|
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
|
-
|
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
|
-
|
237
|
-
|
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[:
|
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
|
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,
|
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
|
-
|
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
|
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
|
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
|
-
|
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:
|
4
|
+
hash: 79
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 14
|
9
|
-
-
|
10
|
-
version: 2.14.
|
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-
|
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
|