testlab 1.7.1 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/commands/container.rb +2 -3
- data/lib/testlab/container.rb +10 -8
- data/lib/testlab/container/io.rb +129 -9
- data/lib/testlab/version.rb +1 -1
- metadata +4 -4
data/lib/commands/container.rb
CHANGED
@@ -173,12 +173,11 @@ EOF
|
|
173
173
|
import.flag [:input]
|
174
174
|
|
175
175
|
import.action do |global_options, options, args|
|
176
|
-
if
|
176
|
+
if options[:name].nil?
|
177
177
|
help_now!('a name is required') if options[:name].nil?
|
178
|
-
help_now!('a filename is required') if options[:input].nil?
|
179
178
|
else
|
180
179
|
iterate_objects_by_name(options[:name], TestLab::Container) do |container|
|
181
|
-
container.import(options[:input])
|
180
|
+
container.import(options[:input] || "")
|
182
181
|
end
|
183
182
|
end
|
184
183
|
end
|
data/lib/testlab/container.rb
CHANGED
@@ -11,14 +11,14 @@ class TestLab
|
|
11
11
|
# container "server-west-1" do
|
12
12
|
# domain "west.zone"
|
13
13
|
#
|
14
|
-
# distro
|
15
|
-
# release
|
14
|
+
# distro "ubuntu"
|
15
|
+
# release "precise"
|
16
16
|
#
|
17
17
|
# user do
|
18
18
|
# username "deployer"
|
19
19
|
# password "deployer"
|
20
|
-
# uid
|
21
|
-
# gid
|
20
|
+
# uid 2600
|
21
|
+
# gid 2600
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
# interface do
|
@@ -31,14 +31,14 @@ class TestLab
|
|
31
31
|
#
|
32
32
|
# @example Multiple interfaces can be defined as well:
|
33
33
|
# container "dual-nic" do
|
34
|
-
# distro
|
35
|
-
# release
|
34
|
+
# distro "ubuntu"
|
35
|
+
# release "precise"
|
36
36
|
#
|
37
37
|
# user do
|
38
38
|
# username "deployer"
|
39
39
|
# password "deployer"
|
40
|
-
# uid
|
41
|
-
# gid
|
40
|
+
# uid 2600
|
41
|
+
# gid 2600
|
42
42
|
# end
|
43
43
|
#
|
44
44
|
# interface do
|
@@ -127,6 +127,8 @@ class TestLab
|
|
127
127
|
|
128
128
|
attribute :mounts, :default => Array.new
|
129
129
|
|
130
|
+
attribute :sc_url
|
131
|
+
|
130
132
|
attribute :aa_profile
|
131
133
|
attribute :cap_drop
|
132
134
|
|
data/lib/testlab/container/io.rb
CHANGED
@@ -2,8 +2,42 @@ class TestLab
|
|
2
2
|
class Container
|
3
3
|
|
4
4
|
module IO
|
5
|
+
require 'net/http'
|
6
|
+
require 'net/https' if RUBY_VERSION < '1.9'
|
5
7
|
require 'tempfile'
|
6
|
-
|
8
|
+
|
9
|
+
PBZIP2_MEMORY = 1024
|
10
|
+
READ_SIZE = ((64 * 1024) - 1)
|
11
|
+
TRANSFER_MESSAGE = "transferring '%s' at %0.2fMB/s -- %0.2fMB of %0.2fMB -- %d%% \r"
|
12
|
+
|
13
|
+
def progress_callback(action, args)
|
14
|
+
@total_size ||= 0
|
15
|
+
|
16
|
+
case action
|
17
|
+
when :open then
|
18
|
+
@start_time = Time.now
|
19
|
+
if (@total_size == 0)
|
20
|
+
@total_size = args[0].size
|
21
|
+
@total_size_mb = (@total_size.to_f / (1024 * 1024).to_f)
|
22
|
+
end
|
23
|
+
|
24
|
+
when :get, :put then
|
25
|
+
current_size = (args[1] + args[2].length)
|
26
|
+
current_size_mb = (current_size.to_f / (1024 * 1024).to_f)
|
27
|
+
|
28
|
+
elapsed = (Time.now - @start_time)
|
29
|
+
speed_mb = (current_size.to_f / elapsed.to_f) / (1024 * 1024).to_f
|
30
|
+
|
31
|
+
percentage_done = ((current_size * 100) / @total_size)
|
32
|
+
|
33
|
+
@ui.stdout.print(format_message(TRANSFER_MESSAGE.yellow % [File.basename(args[0].local), speed_mb, current_size_mb, @total_size_mb, percentage_done]))
|
34
|
+
|
35
|
+
when :finish
|
36
|
+
@ui.stdout.puts
|
37
|
+
@total_size = 0
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
7
41
|
|
8
42
|
# Export the container
|
9
43
|
#
|
@@ -44,10 +78,19 @@ ls -lah #{remote_file}
|
|
44
78
|
EOF
|
45
79
|
end
|
46
80
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
81
|
+
File.exists?(local_file) and FileUtils.rm_f(local_file)
|
82
|
+
|
83
|
+
@total_size = self.node.ssh.sftp.stat!(remote_file).size
|
84
|
+
@total_size_mb = (@total_size.to_f / (1024 * 1024).to_f)
|
85
|
+
|
86
|
+
self.node.download(remote_file, local_file, :on_progress => method(:progress_callback), :read_size => READ_SIZE)
|
87
|
+
|
88
|
+
self.node.bootstrap(<<-EOF)
|
89
|
+
set -x
|
90
|
+
set -e
|
91
|
+
|
92
|
+
rm -fv #{remote_file}
|
93
|
+
EOF
|
51
94
|
|
52
95
|
@ui.stdout.puts(format_message("Your shipping container is now exported and available at '#{local_file}'!".green.bold))
|
53
96
|
|
@@ -60,11 +103,21 @@ EOF
|
|
60
103
|
def import(local_file)
|
61
104
|
@ui.logger.debug { "Container Import: #{self.id} " }
|
62
105
|
|
106
|
+
if !File.exists?(local_file)
|
107
|
+
self.sc_url.nil? and raise ContainerError, "You failed to supply a filename or URL to import from!"
|
108
|
+
|
109
|
+
@ui.stdout.puts(format_message("Downloading shipping container for #{self.id}...".green.bold))
|
110
|
+
|
111
|
+
local_file = File.expand_path("#{self.id}.sc")
|
112
|
+
sc_download(local_file, self.sc_url, 16)
|
113
|
+
end
|
114
|
+
|
63
115
|
# Ensure we are not in ephemeral mode.
|
64
116
|
self.persistent
|
65
117
|
|
66
118
|
self.down
|
67
119
|
self.destroy
|
120
|
+
|
68
121
|
self.create
|
69
122
|
|
70
123
|
import_tempfile = Tempfile.new('import')
|
@@ -75,10 +128,8 @@ EOF
|
|
75
128
|
local_file = File.expand_path(local_file)
|
76
129
|
root_fs_path = self.lxc.fs_root.split(File::SEPARATOR).last
|
77
130
|
|
78
|
-
|
79
|
-
|
80
|
-
self.node.upload(local_file, remote_file)
|
81
|
-
end
|
131
|
+
self.node.exec(%(sudo rm -fv #{remote_file}), :silence => true, :ignore_exit_status => true)
|
132
|
+
self.node.upload(local_file, remote_file, :on_progress => method(:progress_callback), :read_size => READ_SIZE)
|
82
133
|
|
83
134
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Expand', :cyan)) do
|
84
135
|
self.node.bootstrap(<<-EOF)
|
@@ -92,6 +143,8 @@ cd #{self.lxc.container_root}
|
|
92
143
|
pbzip2 -vdcm#{PBZIP2_MEMORY} #{remote_file} | cpio -uid && rm -fv #{remote_file}
|
93
144
|
|
94
145
|
du -sh #{self.lxc.container_root}
|
146
|
+
|
147
|
+
rm -fv #{remote_file}
|
95
148
|
EOF
|
96
149
|
end
|
97
150
|
|
@@ -135,6 +188,73 @@ EOF
|
|
135
188
|
true
|
136
189
|
end
|
137
190
|
|
191
|
+
# Downloads a given shipping container image
|
192
|
+
#
|
193
|
+
# @return [Boolean] True if successful.
|
194
|
+
def sc_download(local_file, url, count)
|
195
|
+
(count <= 0) and raise ContainerError, "Too many redirects, aborting!"
|
196
|
+
|
197
|
+
uri = URI(url)
|
198
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
199
|
+
|
200
|
+
if (uri.scheme.downcase == 'https')
|
201
|
+
http.use_ssl = true
|
202
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # lets be really permissive for now
|
203
|
+
end
|
204
|
+
|
205
|
+
http.request_get(uri.path) do |response|
|
206
|
+
case response
|
207
|
+
when Net::HTTPNotFound then
|
208
|
+
raise ContainerError, "The supplied sc_url for this container was 404 Not Found!"
|
209
|
+
|
210
|
+
when Net::HTTPClientError then
|
211
|
+
raise ContainerError, "Client Error: #{response.inspect}"
|
212
|
+
|
213
|
+
when Net::HTTPRedirection then
|
214
|
+
location = response['location']
|
215
|
+
@ui.stdout.puts(format_message("REDIRECTED #{url} --> #{location}".black))
|
216
|
+
return sc_download(local_file, location, (count - 1))
|
217
|
+
|
218
|
+
when Net::HTTPOK then
|
219
|
+
tempfile = Tempfile.new(%(download-#{self.id}))
|
220
|
+
tempfile.binmode
|
221
|
+
|
222
|
+
current_size = 0
|
223
|
+
progress = 0
|
224
|
+
total_size = response['content-length'].to_i
|
225
|
+
total_size_mb = total_size.to_f / (1024 * 1024).to_f
|
226
|
+
|
227
|
+
start_time = Time.now
|
228
|
+
response.read_body do |chunk|
|
229
|
+
tempfile << chunk
|
230
|
+
|
231
|
+
current_size += chunk.size
|
232
|
+
current_size_mb = current_size.to_f / (1024 * 1024).to_f
|
233
|
+
|
234
|
+
new_progress = (current_size * 100) / total_size
|
235
|
+
unless new_progress == progress
|
236
|
+
elapsed = (Time.now - start_time)
|
237
|
+
speed_mb = (current_size.to_f / elapsed.to_f) / (1024 * 1024).to_f
|
238
|
+
@ui.stdout.print(format_message(TRANSFER_MESSAGE.yellow % [File.basename(local_file), speed_mb, current_size_mb, total_size_mb, new_progress]))
|
239
|
+
end
|
240
|
+
progress = new_progress
|
241
|
+
end
|
242
|
+
@ui.stdout.puts
|
243
|
+
|
244
|
+
tempfile.close
|
245
|
+
|
246
|
+
FileUtils.mkdir_p(File.dirname(local_file))
|
247
|
+
File.exists?(local_file) and File.unlink(local_file)
|
248
|
+
FileUtils.mv(tempfile.path, local_file, :force => true)
|
249
|
+
|
250
|
+
true
|
251
|
+
else
|
252
|
+
raise ContainerError, "Unknown HTTP response when attempt to download your shipping container!"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
|
138
258
|
end
|
139
259
|
|
140
260
|
end
|
data/lib/testlab/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: testlab
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gli
|
@@ -343,7 +343,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
343
343
|
version: '0'
|
344
344
|
segments:
|
345
345
|
- 0
|
346
|
-
hash:
|
346
|
+
hash: -2347575770462916440
|
347
347
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
348
348
|
none: false
|
349
349
|
requirements:
|
@@ -352,7 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
352
352
|
version: '0'
|
353
353
|
segments:
|
354
354
|
- 0
|
355
|
-
hash:
|
355
|
+
hash: -2347575770462916440
|
356
356
|
requirements: []
|
357
357
|
rubyforge_project:
|
358
358
|
rubygems_version: 1.8.25
|