ec2_amitools 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +54 -0
- data/bin/console +14 -0
- data/bin/ec2-ami-tools-version +6 -0
- data/bin/ec2-bundle-image +6 -0
- data/bin/ec2-bundle-vol +6 -0
- data/bin/ec2-delete-bundle +6 -0
- data/bin/ec2-download-bundle +6 -0
- data/bin/ec2-migrate-bundle +6 -0
- data/bin/ec2-migrate-manifest +6 -0
- data/bin/ec2-unbundle +6 -0
- data/bin/ec2-upload-bundle +6 -0
- data/bin/setup +8 -0
- data/etc/ec2/amitools/cert-ec2-cn-north-1.pem +28 -0
- data/etc/ec2/amitools/cert-ec2-gov.pem +17 -0
- data/etc/ec2/amitools/cert-ec2.pem +23 -0
- data/etc/ec2/amitools/mappings.csv +9 -0
- data/lib/ec2/amitools/bundle.rb +251 -0
- data/lib/ec2/amitools/bundle_base.rb +58 -0
- data/lib/ec2/amitools/bundleimage.rb +94 -0
- data/lib/ec2/amitools/bundleimageparameters.rb +42 -0
- data/lib/ec2/amitools/bundlemachineparameters.rb +60 -0
- data/lib/ec2/amitools/bundleparameters.rb +120 -0
- data/lib/ec2/amitools/bundlevol.rb +240 -0
- data/lib/ec2/amitools/bundlevolparameters.rb +164 -0
- data/lib/ec2/amitools/crypto.rb +379 -0
- data/lib/ec2/amitools/decryptmanifest.rb +20 -0
- data/lib/ec2/amitools/defaults.rb +12 -0
- data/lib/ec2/amitools/deletebundle.rb +212 -0
- data/lib/ec2/amitools/deletebundleparameters.rb +78 -0
- data/lib/ec2/amitools/downloadbundle.rb +161 -0
- data/lib/ec2/amitools/downloadbundleparameters.rb +84 -0
- data/lib/ec2/amitools/exception.rb +86 -0
- data/lib/ec2/amitools/fileutil.rb +219 -0
- data/lib/ec2/amitools/format.rb +127 -0
- data/lib/ec2/amitools/instance-data.rb +97 -0
- data/lib/ec2/amitools/manifest_wrapper.rb +132 -0
- data/lib/ec2/amitools/manifestv20070829.rb +361 -0
- data/lib/ec2/amitools/manifestv20071010.rb +403 -0
- data/lib/ec2/amitools/manifestv3.rb +331 -0
- data/lib/ec2/amitools/mapids.rb +148 -0
- data/lib/ec2/amitools/migratebundle.rb +222 -0
- data/lib/ec2/amitools/migratebundleparameters.rb +173 -0
- data/lib/ec2/amitools/migratemanifest.rb +225 -0
- data/lib/ec2/amitools/migratemanifestparameters.rb +118 -0
- data/lib/ec2/amitools/minimalec2.rb +116 -0
- data/lib/ec2/amitools/parameter_exceptions.rb +34 -0
- data/lib/ec2/amitools/parameters_base.rb +168 -0
- data/lib/ec2/amitools/region.rb +93 -0
- data/lib/ec2/amitools/s3toolparameters.rb +183 -0
- data/lib/ec2/amitools/showversion.rb +12 -0
- data/lib/ec2/amitools/syschecks.rb +27 -0
- data/lib/ec2/amitools/tool_base.rb +224 -0
- data/lib/ec2/amitools/unbundle.rb +107 -0
- data/lib/ec2/amitools/unbundleparameters.rb +65 -0
- data/lib/ec2/amitools/uploadbundle.rb +361 -0
- data/lib/ec2/amitools/uploadbundleparameters.rb +108 -0
- data/lib/ec2/amitools/util.rb +532 -0
- data/lib/ec2/amitools/version.rb +33 -0
- data/lib/ec2/amitools/xmlbuilder.rb +237 -0
- data/lib/ec2/amitools/xmlutil.rb +55 -0
- data/lib/ec2/common/constants.rb +16 -0
- data/lib/ec2/common/curl.rb +110 -0
- data/lib/ec2/common/headers.rb +95 -0
- data/lib/ec2/common/headersv4.rb +173 -0
- data/lib/ec2/common/http.rb +333 -0
- data/lib/ec2/common/s3support.rb +231 -0
- data/lib/ec2/common/signature.rb +68 -0
- data/lib/ec2/oem/LICENSE.txt +58 -0
- data/lib/ec2/oem/open4.rb +399 -0
- data/lib/ec2/platform/base/architecture.rb +26 -0
- data/lib/ec2/platform/base/constants.rb +54 -0
- data/lib/ec2/platform/base/pipeline.rb +181 -0
- data/lib/ec2/platform/base.rb +57 -0
- data/lib/ec2/platform/current.rb +55 -0
- data/lib/ec2/platform/linux/architecture.rb +35 -0
- data/lib/ec2/platform/linux/constants.rb +23 -0
- data/lib/ec2/platform/linux/fstab.rb +99 -0
- data/lib/ec2/platform/linux/identity.rb +16 -0
- data/lib/ec2/platform/linux/image.rb +811 -0
- data/lib/ec2/platform/linux/mtab.rb +74 -0
- data/lib/ec2/platform/linux/pipeline.rb +40 -0
- data/lib/ec2/platform/linux/rsync.rb +114 -0
- data/lib/ec2/platform/linux/tar.rb +124 -0
- data/lib/ec2/platform/linux/uname.rb +50 -0
- data/lib/ec2/platform/linux.rb +83 -0
- data/lib/ec2/platform/solaris/architecture.rb +28 -0
- data/lib/ec2/platform/solaris/constants.rb +30 -0
- data/lib/ec2/platform/solaris/fstab.rb +43 -0
- data/lib/ec2/platform/solaris/identity.rb +16 -0
- data/lib/ec2/platform/solaris/image.rb +327 -0
- data/lib/ec2/platform/solaris/mtab.rb +29 -0
- data/lib/ec2/platform/solaris/pipeline.rb +40 -0
- data/lib/ec2/platform/solaris/rsync.rb +24 -0
- data/lib/ec2/platform/solaris/tar.rb +36 -0
- data/lib/ec2/platform/solaris/uname.rb +21 -0
- data/lib/ec2/platform/solaris.rb +38 -0
- data/lib/ec2/platform.rb +69 -0
- data/lib/ec2/version.rb +8 -0
- data/lib/ec2_amitools +1 -0
- data/lib/ec2_amitools.rb +7 -0
- metadata +184 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'ec2/amitools/crypto'
|
12
|
+
|
13
|
+
USAGE = "Usage: decryptmanifest private-key-path"
|
14
|
+
|
15
|
+
if ARGV.size < 1
|
16
|
+
puts USAGE
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
puts Crypto::decryptasym( $stdin.read, ARGV[0] )
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
EC2_HOME = ENV['EC2_AMITOOL_HOME'] || ENV['EC2_HOME']
|
12
|
+
EC2_X509_CERT = '#{EC2_HOME}/etc/ec2/amitools/cert-ec2.pem'
|
@@ -0,0 +1,212 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'ec2/amitools/crypto'
|
12
|
+
require 'ec2/amitools/exception'
|
13
|
+
require 'ec2/amitools/deletebundleparameters'
|
14
|
+
require 'net/https'
|
15
|
+
require 'rexml/document'
|
16
|
+
require 'tempfile'
|
17
|
+
require 'uri'
|
18
|
+
require 'ec2/common/s3support'
|
19
|
+
require 'ec2/amitools/tool_base'
|
20
|
+
|
21
|
+
DELETE_BUNDLE_NAME = 'ec2-delete-bundle'
|
22
|
+
|
23
|
+
#------------------------------------------------------------------------------#
|
24
|
+
|
25
|
+
DELETE_BUNDLE_MANUAL=<<TEXT
|
26
|
+
#{DELETE_BUNDLE_NAME} is a command line tool to delete a bundled Amazon Image from S3 storage.
|
27
|
+
An Amazon Image may be one of the following:
|
28
|
+
- Amazon Machine Image (AMI)
|
29
|
+
- Amazon Kernel Image (AKI)
|
30
|
+
- Amazon Ramdisk Image (ARI)
|
31
|
+
|
32
|
+
#{DELETE_BUNDLE_NAME} will delete a bundled AMI specified by either its manifest file or the
|
33
|
+
prefix of the bundled AMI filenames.
|
34
|
+
|
35
|
+
#{DELETE_BUNDLE_NAME} will:
|
36
|
+
- delete the manifest and parts from the s3 bucket
|
37
|
+
- remove the bucket if and only if it is empty and you request its deletion
|
38
|
+
TEXT
|
39
|
+
|
40
|
+
#------------------------------------------------------------------------------#
|
41
|
+
|
42
|
+
RETRY_WAIT_PERIOD = 5
|
43
|
+
|
44
|
+
#------------------------------------------------------------------------------#
|
45
|
+
|
46
|
+
class DeleteFileError < AMIToolExceptions::EC2FatalError
|
47
|
+
def initialize(file, reason)
|
48
|
+
super(5,"Could not delete file '#{file}': #{reason}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class BundleDeleter < AMITool
|
53
|
+
#----------------------------------------------------------------------------#
|
54
|
+
|
55
|
+
# Delete the specified file.
|
56
|
+
def delete(bucket, key, retry_delete)
|
57
|
+
retry_s3(retry_delete) do
|
58
|
+
begin
|
59
|
+
response = @s3_conn.delete(bucket, key)
|
60
|
+
return if response.success?
|
61
|
+
raise "HTTP DELETE returned #{response.code}"
|
62
|
+
rescue => e
|
63
|
+
raise TryFailed.new("Failed to delete \"#{key}\": #{e.message}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
#----------------------------------------------------------------------------#
|
69
|
+
|
70
|
+
# Return a list of bundle part filenames from the manifest.
|
71
|
+
def get_part_filenames(manifest)
|
72
|
+
parts = []
|
73
|
+
manifest_doc = REXML::Document.new(manifest).root
|
74
|
+
REXML::XPath.each(manifest_doc, 'image/parts/part/filename/text()') do |part|
|
75
|
+
parts << part.to_s
|
76
|
+
end
|
77
|
+
return parts
|
78
|
+
end
|
79
|
+
|
80
|
+
#------------------------------------------------------------------------------#
|
81
|
+
|
82
|
+
def uri2string(uri)
|
83
|
+
s = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}"
|
84
|
+
# Remove the trailing '/'.
|
85
|
+
return (s[-1..-1] == "/" ? s[0..-2] : s)
|
86
|
+
end
|
87
|
+
|
88
|
+
#------------------------------------------------------------------------------#
|
89
|
+
|
90
|
+
def get_file_list_from_s3(bucket, keyprefix, prefix)
|
91
|
+
s3prefix = keyprefix+prefix
|
92
|
+
files_to_delete = []
|
93
|
+
response = @s3_conn.list_bucket(bucket, s3prefix)
|
94
|
+
unless response.success?
|
95
|
+
raise "unable to list contents of bucket #{bucket}: HTTP #{response.code} response: #{response.body}"
|
96
|
+
end
|
97
|
+
REXML::XPath.each(REXML::Document.new(response.body), "//Key/text()") do |entry|
|
98
|
+
entry = entry.to_s
|
99
|
+
if entry[0,s3prefix.length] == s3prefix
|
100
|
+
test_str = entry[(s3prefix.length)..-1]
|
101
|
+
if (test_str =~ /^\.part\.[0-9]+$/ or
|
102
|
+
test_str =~ /^\.manifest(\.xml)?$/)
|
103
|
+
files_to_delete << entry[(keyprefix.length)..-1]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
files_to_delete
|
108
|
+
end
|
109
|
+
|
110
|
+
#------------------------------------------------------------------------------#
|
111
|
+
|
112
|
+
def make_s3_connection(s3_url, user, pass, method, sigv, region)
|
113
|
+
EC2::Common::S3Support.new(s3_url, user, pass, method, @debug, sigv, region)
|
114
|
+
end
|
115
|
+
|
116
|
+
#------------------------------------------------------------------------------#
|
117
|
+
|
118
|
+
def delete_bundle(url, bucket, keyprefix, user, pass, manifest, prefix, yes, clear, retry_stuff, sigv, region)
|
119
|
+
begin
|
120
|
+
# Get the S3 URL.
|
121
|
+
s3_uri = URI.parse(url)
|
122
|
+
s3_url = uri2string(s3_uri)
|
123
|
+
retry_delete = retry_stuff
|
124
|
+
v2_bucket = EC2::Common::S3Support::bucket_name_s3_v2_safe?(bucket)
|
125
|
+
@s3_conn = make_s3_connection(s3_url, user, pass, (v2_bucket ? nil : :path), sigv, region)
|
126
|
+
|
127
|
+
files_to_delete = []
|
128
|
+
|
129
|
+
if manifest
|
130
|
+
# Get list of files to delete from the AMI manifest.
|
131
|
+
xml = String.new
|
132
|
+
manifest_path = manifest
|
133
|
+
File.open(manifest_path) { |f| xml << f.read }
|
134
|
+
files_to_delete << File::basename(manifest)
|
135
|
+
get_part_filenames( xml ).each do |part_info|
|
136
|
+
files_to_delete << part_info
|
137
|
+
end
|
138
|
+
else
|
139
|
+
files_to_delete = get_file_list_from_s3(bucket, keyprefix, prefix)
|
140
|
+
end
|
141
|
+
|
142
|
+
if files_to_delete.empty?
|
143
|
+
$stdout.puts "No files to delete."
|
144
|
+
else
|
145
|
+
$stdout.puts "Deleting files:"
|
146
|
+
files_to_delete.each { |file| $stdout.puts(" - #{file}") }
|
147
|
+
continue = yes
|
148
|
+
unless continue
|
149
|
+
begin
|
150
|
+
$stdout.print "Continue [y/N]: "
|
151
|
+
$stdout.flush
|
152
|
+
Timeout::timeout(PROMPT_TIMEOUT) do
|
153
|
+
continue = gets.strip =~ /^y/i
|
154
|
+
end
|
155
|
+
rescue Timeout::Error
|
156
|
+
$stdout.puts "\nNo response given, skipping the files."
|
157
|
+
continue = false
|
158
|
+
end
|
159
|
+
end
|
160
|
+
if continue
|
161
|
+
files_to_delete.each do |file|
|
162
|
+
delete(bucket, keyprefix+file, retry_delete)
|
163
|
+
$stdout.puts "Deleted #{file}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
if clear
|
169
|
+
$stdout.puts "Attempting to delete bucket #{bucket}..."
|
170
|
+
@s3_conn.delete(bucket)
|
171
|
+
end
|
172
|
+
rescue EC2::Common::HTTP::Error => e
|
173
|
+
$stderr.puts e.backtrace if @debug
|
174
|
+
raise S3Error.new(e.message)
|
175
|
+
end
|
176
|
+
$stdout.puts "#{DELETE_BUNDLE_NAME} complete."
|
177
|
+
end
|
178
|
+
|
179
|
+
#------------------------------------------------------------------------------#
|
180
|
+
# Overrides
|
181
|
+
#------------------------------------------------------------------------------#
|
182
|
+
|
183
|
+
def get_manual()
|
184
|
+
DELETE_BUNDLE_MANUAL
|
185
|
+
end
|
186
|
+
|
187
|
+
def get_name()
|
188
|
+
DELETE_BUNDLE_NAME
|
189
|
+
end
|
190
|
+
|
191
|
+
def main(p)
|
192
|
+
delete_bundle(p.url,
|
193
|
+
p.bucket,
|
194
|
+
p.keyprefix,
|
195
|
+
p.user,
|
196
|
+
p.pass,
|
197
|
+
p.manifest,
|
198
|
+
p.prefix,
|
199
|
+
p.yes,
|
200
|
+
p.clear,
|
201
|
+
p.retry,
|
202
|
+
p.sigv,
|
203
|
+
p.region)
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
#------------------------------------------------------------------------------#
|
209
|
+
# Script entry point. Execute only if this file is being executed.
|
210
|
+
if __FILE__ == $0 || $0.match(/bin\/ec2-delete-bundle/)
|
211
|
+
BundleDeleter.new().run(DeleteBundleParameters)
|
212
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'ec2/amitools/s3toolparameters'
|
12
|
+
|
13
|
+
#------------------------------------------------------------------------------#
|
14
|
+
|
15
|
+
class DeleteBundleParameters < S3ToolParameters
|
16
|
+
|
17
|
+
MANIFEST_DESCRIPTION = "The path to the unencrypted manifest file."
|
18
|
+
PREFIX_DESCRIPTION = "The bundled AMI part filename prefix."
|
19
|
+
RETRY_DESCRIPTION = "Automatically retry failed deletes. Use with caution."
|
20
|
+
YES_DESCRIPTION = "Automatically answer 'y' without asking."
|
21
|
+
CLEAR_DESCRIPTION = "Delete the bucket if empty. Not done by default."
|
22
|
+
|
23
|
+
attr_accessor :manifest,
|
24
|
+
:prefix,
|
25
|
+
:retry,
|
26
|
+
:yes,
|
27
|
+
:clear
|
28
|
+
|
29
|
+
#----------------------------------------------------------------------------#
|
30
|
+
|
31
|
+
def mandatory_params()
|
32
|
+
super()
|
33
|
+
end
|
34
|
+
|
35
|
+
#----------------------------------------------------------------------------#
|
36
|
+
|
37
|
+
def optional_params()
|
38
|
+
super()
|
39
|
+
|
40
|
+
on('-m', '--manifest PATH', String, MANIFEST_DESCRIPTION) do |manifest|
|
41
|
+
assert_file_exists(manifest, '--manifest')
|
42
|
+
@manifest = manifest
|
43
|
+
end
|
44
|
+
|
45
|
+
on('-p', '--prefix PREFIX', String, PREFIX_DESCRIPTION) do |prefix|
|
46
|
+
assert_good_key(prefix, '--prefix')
|
47
|
+
@prefix = prefix
|
48
|
+
end
|
49
|
+
|
50
|
+
on('--clear', CLEAR_DESCRIPTION) do
|
51
|
+
@clear = true
|
52
|
+
end
|
53
|
+
|
54
|
+
on('--retry', RETRY_DESCRIPTION) do
|
55
|
+
@retry = true
|
56
|
+
end
|
57
|
+
|
58
|
+
on('-y', '--yes', YES_DESCRIPTION) do
|
59
|
+
@yes = true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#----------------------------------------------------------------------------#
|
64
|
+
|
65
|
+
def validate_params()
|
66
|
+
super()
|
67
|
+
raise MissingMandatory.new('--manifest or --prefix') unless @manifest or @prefix
|
68
|
+
raise InvalidCombination.new('--prefix', '--manifest') if (@prefix and @manifest)
|
69
|
+
end
|
70
|
+
|
71
|
+
#----------------------------------------------------------------------------#
|
72
|
+
|
73
|
+
def set_defaults()
|
74
|
+
super()
|
75
|
+
@clear ||= false
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'ec2/amitools/crypto'
|
12
|
+
require 'ec2/common/s3support'
|
13
|
+
require 'ec2/amitools/downloadbundleparameters'
|
14
|
+
require 'ec2/amitools/exception'
|
15
|
+
require 'ec2/amitools/manifestv20071010'
|
16
|
+
require 'getoptlong'
|
17
|
+
require 'net/http'
|
18
|
+
require 'rexml/document'
|
19
|
+
require 'ec2/amitools/tool_base'
|
20
|
+
|
21
|
+
# Download AMI downloads the specified AMI from S3.
|
22
|
+
|
23
|
+
#------------------------------------------------------------------------------#
|
24
|
+
|
25
|
+
DOWNLOAD_BUNDLE_NAME = 'ec2-download-bundle'
|
26
|
+
DOWNLOAD_BUNDLE_MANUAL =<<TEXT
|
27
|
+
#{DOWNLOAD_BUNDLE_NAME} is a command line tool to download a bundled Amazon Image from
|
28
|
+
S3 storage. An Amazon Image may be one of the following:
|
29
|
+
- Amazon Machine Image (AMI)
|
30
|
+
- Amazon Kernel Image (AKI)
|
31
|
+
- Amazon Ramdisk Image (ARI)
|
32
|
+
|
33
|
+
#{DOWNLOAD_BUNDLE_NAME} downloads and decrypts the manifest, then fetches all
|
34
|
+
the parts referenced in the manifest.
|
35
|
+
TEXT
|
36
|
+
|
37
|
+
class BundleDownloader < AMITool
|
38
|
+
|
39
|
+
def download_manifest(s3_conn, bucket, manifest_name, manifest_path, privatekey, retry_download=false)
|
40
|
+
$stdout.puts "Downloading manifest #{manifest_name} from #{bucket} to #{manifest_path} ..."
|
41
|
+
download_file(s3_conn, bucket, manifest_name, manifest_path, retry_download)
|
42
|
+
encrypted_manifest = File::open(manifest_path) { |f| f.read() }
|
43
|
+
plaintext_manifest = nil
|
44
|
+
if (encrypted_manifest !~ /^\s*<\?/)
|
45
|
+
$stdout.puts "Decrypting manifest ..."
|
46
|
+
plaintext_manifest = Crypto::decryptasym(encrypted_manifest, privatekey)
|
47
|
+
File::open(manifest_path+'.plaintext', 'w') { |f| f.write(plaintext_manifest) }
|
48
|
+
else
|
49
|
+
plaintext_manifest = encrypted_manifest
|
50
|
+
end
|
51
|
+
plaintext_manifest
|
52
|
+
end
|
53
|
+
|
54
|
+
#----------------------------------------------------------------------------#
|
55
|
+
|
56
|
+
def download_part(s3_conn, bucket, part, part_path, retry_download=false)
|
57
|
+
$stdout.puts "Downloading part #{part} to #{part_path} ..."
|
58
|
+
download_file(s3_conn, bucket, part, part_path, retry_download)
|
59
|
+
end
|
60
|
+
|
61
|
+
#----------------------------------------------------------------------------#
|
62
|
+
|
63
|
+
def download_file(s3_conn, bucket, file, file_path, retry_download=false)
|
64
|
+
retry_s3(retry_download) do
|
65
|
+
begin
|
66
|
+
s3_conn.get(bucket, file, file_path)
|
67
|
+
return
|
68
|
+
rescue => e
|
69
|
+
raise TryFailed.new("Failed to download \"#{file}\": #{e.message}")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#----------------------------------------------------------------------------#
|
75
|
+
|
76
|
+
def get_part_filenames(manifest_xml)
|
77
|
+
manifest = ManifestV20071010.new(manifest_xml)
|
78
|
+
manifest.parts.collect { |part| part.filename }.sort
|
79
|
+
end
|
80
|
+
|
81
|
+
#----------------------------------------------------------------------------#
|
82
|
+
|
83
|
+
def uri2string( uri )
|
84
|
+
s = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}"
|
85
|
+
# Remove the trailing '/'.
|
86
|
+
return ( s[-1..-1] == "/" ? s[0..-2] : s )
|
87
|
+
end
|
88
|
+
|
89
|
+
#----------------------------------------------------------------------------#
|
90
|
+
|
91
|
+
def make_s3_connection(s3_url, user, pass, bucket, sigv, region)
|
92
|
+
s3_uri = URI.parse(s3_url)
|
93
|
+
s3_url = uri2string(s3_uri)
|
94
|
+
v2_bucket = EC2::Common::S3Support::bucket_name_s3_v2_safe?(bucket)
|
95
|
+
EC2::Common::S3Support.new(s3_url, user, pass, (v2_bucket ? nil : :path), @debug, sigv, region)
|
96
|
+
end
|
97
|
+
|
98
|
+
#----------------------------------------------------------------------------#
|
99
|
+
|
100
|
+
# Main method.
|
101
|
+
def download_bundle(url,
|
102
|
+
user,
|
103
|
+
pass,
|
104
|
+
bucket,
|
105
|
+
keyprefix,
|
106
|
+
directory,
|
107
|
+
manifest,
|
108
|
+
privatekey,
|
109
|
+
retry_stuff,
|
110
|
+
sigv,
|
111
|
+
region)
|
112
|
+
begin
|
113
|
+
s3_conn = make_s3_connection(url, user, pass, bucket, sigv, region)
|
114
|
+
# Download and decrypt manifest.
|
115
|
+
manifest_path = File.join(directory, manifest)
|
116
|
+
manifest_xml = download_manifest(s3_conn, bucket, keyprefix+manifest, manifest_path, privatekey, retry_stuff)
|
117
|
+
|
118
|
+
# Download AMI parts.
|
119
|
+
get_part_filenames(manifest_xml).each do |filename|
|
120
|
+
download_part(s3_conn, bucket, keyprefix+filename, File::join(directory, filename), retry_stuff)
|
121
|
+
$stdout.puts "Downloaded #{filename} from #{bucket}"
|
122
|
+
end
|
123
|
+
rescue EC2::Common::HTTP::Error => e
|
124
|
+
$stderr.puts e.backtrace if @debug
|
125
|
+
raise S3Error.new(e.message)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
#------------------------------------------------------------------------------#
|
130
|
+
# Overrides
|
131
|
+
#------------------------------------------------------------------------------#
|
132
|
+
|
133
|
+
def get_manual()
|
134
|
+
DOWNLOAD_BUNDLE_MANUAL
|
135
|
+
end
|
136
|
+
|
137
|
+
def get_name()
|
138
|
+
DOWNLOAD_BUNDLE_NAME
|
139
|
+
end
|
140
|
+
|
141
|
+
def main(p)
|
142
|
+
download_bundle(p.url,
|
143
|
+
p.user,
|
144
|
+
p.pass,
|
145
|
+
p.bucket,
|
146
|
+
p.keyprefix,
|
147
|
+
p.directory,
|
148
|
+
p.manifest,
|
149
|
+
p.privatekey,
|
150
|
+
p.retry,
|
151
|
+
p.sigv,
|
152
|
+
p.region)
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
#------------------------------------------------------------------------------#
|
158
|
+
# Script entry point. Execute only if this file is being executed.
|
159
|
+
if __FILE__ == $0 || $0.match(/bin\/ec2-download-bundle/)
|
160
|
+
BundleDownloader.new().run(DownloadBundleParameters)
|
161
|
+
end
|