testlab 1.7.1 → 1.8.0
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/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
|