testlab 1.13.0 → 1.14.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/testlab.rb +17 -0
- data/lib/testlab.rb +28 -0
- data/lib/testlab/container/actions.rb +0 -4
- data/lib/testlab/container/io.rb +0 -2
- data/lib/testlab/container/provision.rb +0 -2
- data/lib/testlab/node.rb +2 -0
- data/lib/testlab/node/doctor.rb +62 -0
- data/lib/testlab/node/status.rb +1 -47
- data/lib/testlab/version.rb +1 -1
- metadata +5 -4
data/lib/commands/testlab.rb
CHANGED
@@ -209,3 +209,20 @@ command :status do |status|
|
|
209
209
|
commands[:container].commands[:status].execute({}, {}, [])
|
210
210
|
end
|
211
211
|
end
|
212
|
+
|
213
|
+
|
214
|
+
# LAB DOCTOR
|
215
|
+
#############
|
216
|
+
desc 'Check the health of the lab'
|
217
|
+
long_desc <<-EOF
|
218
|
+
Attempts to analyze the health of the lab and report any issues.
|
219
|
+
EOF
|
220
|
+
command :doctor do |doctor|
|
221
|
+
doctor.action do |global_options, options, args|
|
222
|
+
if @testlab.doctor == true
|
223
|
+
@testlab.ui.stdout.puts("Everything is OK".green.bold)
|
224
|
+
else
|
225
|
+
@testlab.ui.stdout.puts(format_message("OH NOES! SOMETHING IS SCREWED UP!".red.bold))
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
data/lib/testlab.rb
CHANGED
@@ -159,6 +159,14 @@ class TestLab
|
|
159
159
|
#
|
160
160
|
# @return [Boolean] True if successful.
|
161
161
|
def boot
|
162
|
+
|
163
|
+
# Raise how many files we can have open to the hard limit.
|
164
|
+
rlimit_nofile = Process.getrlimit(Process::RLIMIT_NOFILE)
|
165
|
+
if rlimit_nofile[0] != rlimit_nofile[1]
|
166
|
+
self.ui.logger.info { "Changing maximum open file descriptors from #{rlimit_nofile[0].inspect} to #{rlimit_nofile[1].inspect}" }
|
167
|
+
Process.setrlimit(Process::RLIMIT_NOFILE, rlimit_nofile[1])
|
168
|
+
end
|
169
|
+
|
162
170
|
@labfile = TestLab::Labfile.load(labfile_path)
|
163
171
|
@labfile.testlab = self
|
164
172
|
|
@@ -351,6 +359,26 @@ class TestLab
|
|
351
359
|
true
|
352
360
|
end
|
353
361
|
|
362
|
+
# Test Lab Doctor
|
363
|
+
#
|
364
|
+
# Attempts to analyze the lab for issues.
|
365
|
+
#
|
366
|
+
# @return [Boolean] True if everything is OK; false otherwise.
|
367
|
+
def doctor
|
368
|
+
results = Array.new
|
369
|
+
|
370
|
+
if ((rlimit_nofile = Process.getrlimit(Process::RLIMIT_NOFILE)[0]) < 1024)
|
371
|
+
@ui.stderr.puts(format_message("The maximum number of file handles is set to #{rlimit_nofile}! Please raise it to 1024 or higher!".red.bold))
|
372
|
+
results << false
|
373
|
+
end
|
374
|
+
|
375
|
+
results << nodes.all? do |node|
|
376
|
+
node.doctor
|
377
|
+
end
|
378
|
+
|
379
|
+
results.flatten.compact.all?
|
380
|
+
end
|
381
|
+
|
354
382
|
# Node Method Proxy
|
355
383
|
#
|
356
384
|
# Iterates all of the lab nodes, sending the supplied method name and arguments
|
@@ -13,7 +13,6 @@ class TestLab
|
|
13
13
|
@ui.logger.debug { "Container Create: #{self.id}" }
|
14
14
|
|
15
15
|
self.node.alive? or return false
|
16
|
-
self.node.ok?
|
17
16
|
|
18
17
|
persistent_operation_check(:create)
|
19
18
|
|
@@ -37,7 +36,6 @@ class TestLab
|
|
37
36
|
@ui.logger.debug { "Container Destroy: #{self.id}" }
|
38
37
|
|
39
38
|
self.node.alive? or return false
|
40
|
-
self.node.ok?
|
41
39
|
|
42
40
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
43
41
|
self.lxc.destroy(%(-f))
|
@@ -58,7 +56,6 @@ class TestLab
|
|
58
56
|
@ui.logger.debug { "Container Up: #{self.id}" }
|
59
57
|
|
60
58
|
self.node.alive? or return false
|
61
|
-
self.node.ok?
|
62
59
|
|
63
60
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
64
61
|
configure
|
@@ -104,7 +101,6 @@ class TestLab
|
|
104
101
|
@ui.logger.debug { "Container Down: #{self.id}" }
|
105
102
|
|
106
103
|
self.node.alive? or return false
|
107
|
-
self.node.ok?
|
108
104
|
|
109
105
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
110
106
|
|
data/lib/testlab/container/io.rb
CHANGED
@@ -60,7 +60,6 @@ class TestLab
|
|
60
60
|
@ui.logger.debug { "Container Export: #{self.id} " }
|
61
61
|
|
62
62
|
self.node.alive? or return false
|
63
|
-
self.node.ok?
|
64
63
|
|
65
64
|
(self.state == :not_created) and raise ContainerError, 'You must create a container before you can export it!'
|
66
65
|
|
@@ -115,7 +114,6 @@ EOF
|
|
115
114
|
@ui.logger.debug { "Container Import: #{self.id}" }
|
116
115
|
|
117
116
|
self.node.alive? or return false
|
118
|
-
self.node.ok?
|
119
117
|
|
120
118
|
import_tempfile = Tempfile.new('import')
|
121
119
|
remote_filename = File.basename(import_tempfile.path.dup)
|
@@ -13,7 +13,6 @@ class TestLab
|
|
13
13
|
@ui.logger.debug { "Container Provision: #{self.id} " }
|
14
14
|
|
15
15
|
self.node.alive? or return false
|
16
|
-
self.node.ok?
|
17
16
|
|
18
17
|
please_wait(:ui => @ui, :message => format_object_action(self, :provision, :green)) do
|
19
18
|
do_provisioner_callbacks(self, :provision, @ui)
|
@@ -32,7 +31,6 @@ class TestLab
|
|
32
31
|
@ui.logger.debug { "Container Deprovision: #{self.id} " }
|
33
32
|
|
34
33
|
self.node.alive? or return false
|
35
|
-
self.node.ok?
|
36
34
|
|
37
35
|
persistent_operation_check(:deprovision)
|
38
36
|
|
data/lib/testlab/node.rb
CHANGED
@@ -12,6 +12,7 @@ class TestLab
|
|
12
12
|
# Sub-Modules
|
13
13
|
autoload :Actions, 'testlab/node/actions'
|
14
14
|
autoload :ClassMethods, 'testlab/node/class_methods'
|
15
|
+
autoload :Doctor, 'testlab/node/doctor'
|
15
16
|
autoload :LXC, 'testlab/node/lxc'
|
16
17
|
autoload :MethodMissing, 'testlab/node/method_missing'
|
17
18
|
autoload :Provision, 'testlab/node/provision'
|
@@ -19,6 +20,7 @@ class TestLab
|
|
19
20
|
autoload :Status, 'testlab/node/status'
|
20
21
|
|
21
22
|
include TestLab::Node::Actions
|
23
|
+
include TestLab::Node::Doctor
|
22
24
|
include TestLab::Node::LXC
|
23
25
|
include TestLab::Node::MethodMissing
|
24
26
|
include TestLab::Node::Provision
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class TestLab
|
2
|
+
class Node
|
3
|
+
|
4
|
+
module Doctor
|
5
|
+
|
6
|
+
# Node Doctor
|
7
|
+
#
|
8
|
+
# Attempts to analyze the current node and report any issues.
|
9
|
+
#
|
10
|
+
# @result [Boolean] True if everything is OK; false otherwise.
|
11
|
+
def doctor
|
12
|
+
if self.dead?
|
13
|
+
@ui.stderr.puts(format_message("The node #{self.id.inspect} is dead! (Did you forget to up or build the node?)".red.bold))
|
14
|
+
return false
|
15
|
+
end
|
16
|
+
|
17
|
+
if !self.lxc.installed?
|
18
|
+
@ui.stderr.puts(format_message("LXC does not appear to be installed on your TestLab node! (Did you forget to provision or build the node?)".red.bold))
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
result = true
|
23
|
+
|
24
|
+
# make sure the node has some free space
|
25
|
+
free_space_percent = (self.exec(%(df -P /), :ignore_exit_status => true).output.split("\n")[1].split[-2].to_i rescue nil)
|
26
|
+
if free_space_percent.nil?
|
27
|
+
@ui.stderr.puts(format_message("ERROR: We could not determine how much free space node #{self.id.inspect} has!".red.bold))
|
28
|
+
result = false
|
29
|
+
elsif (free_space_percent >= 90)
|
30
|
+
@ui.stderr.puts(format_message("WARNING: Your TestLab node #{self.id.inspect} is using #{free_space_percent}% of its available disk space!".red.bold))
|
31
|
+
result = false
|
32
|
+
end
|
33
|
+
|
34
|
+
# get the names of all of the defined containers
|
35
|
+
my_container_names = self.containers.map(&:id)
|
36
|
+
|
37
|
+
# ephemeral containers parent containers have a "-master" suffix; we need to remove these from the results or we will complain about them
|
38
|
+
node_container_names = self.lxc.containers.map(&:name).delete_if do |node_container_name|
|
39
|
+
my_container_names.any?{ |my_container_name| "#{my_container_name}-master" == node_container_name }
|
40
|
+
end
|
41
|
+
|
42
|
+
unknown_container_names = (node_container_names - my_container_names)
|
43
|
+
unknown_running_container_names = self.lxc.containers.select{ |c| (unknown_container_names.include?(c.name) && (c.state == :running)) }.map(&:name)
|
44
|
+
|
45
|
+
if unknown_container_names.count > 0
|
46
|
+
if unknown_running_container_names.count > 0
|
47
|
+
@ui.stderr.puts(format_message("WARNING: You have *running* containers on your TestLab node #{self.id.inspect} which are not defined in your Labfile!".red.bold))
|
48
|
+
@ui.stderr.puts(format_message(">>> You may need to manually stop the following containers: #{unknown_running_container_names.join(', ')}".red.bold))
|
49
|
+
result = false
|
50
|
+
end
|
51
|
+
|
52
|
+
@ui.stderr.puts(format_message("WARNING: You have containers on your TestLab node #{self.id.inspect} which are not defined in your Labfile!".red.bold))
|
53
|
+
@ui.stderr.puts(format_message(">>> You may need to manually remove the following containers: #{unknown_container_names.join(', ')}".red.bold))
|
54
|
+
end
|
55
|
+
|
56
|
+
result
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/testlab/node/status.rb
CHANGED
@@ -8,7 +8,7 @@ class TestLab
|
|
8
8
|
# @return [Hash] A hash detailing the status of the node.
|
9
9
|
def status
|
10
10
|
{
|
11
|
-
:ok => self.
|
11
|
+
:ok => self.doctor.inspect,
|
12
12
|
:id => self.id,
|
13
13
|
:instance_id => @provider.instance_id,
|
14
14
|
:state => @provider.state,
|
@@ -21,52 +21,6 @@ class TestLab
|
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
24
|
-
def ok?
|
25
|
-
self.dead? and return false
|
26
|
-
|
27
|
-
result = true
|
28
|
-
|
29
|
-
if !self.lxc.installed?
|
30
|
-
# @ui.stderr.puts(format_message("ERROR: "))
|
31
|
-
raise NodeError, "LXC does not appear to be installed on your TestLab node! (Did you forget to provision or build the node?)"
|
32
|
-
# result = false
|
33
|
-
end
|
34
|
-
|
35
|
-
# make sure the node has some free space
|
36
|
-
free_space_percent = (self.exec(%(df -P /), :ignore_exit_status => true).output.split("\n")[1].split[-2].to_i rescue nil)
|
37
|
-
if free_space_percent.nil?
|
38
|
-
@ui.stderr.puts(format_message("ERROR: We could not determine how much free space node #{self.id.inspect} has!".red.bold))
|
39
|
-
result = false
|
40
|
-
elsif (free_space_percent >= 90)
|
41
|
-
@ui.stderr.puts(format_message("WARNING: Your TestLab node #{self.id.inspect} is using #{free_space_percent}% of its available disk space!".red.bold))
|
42
|
-
result = false
|
43
|
-
end
|
44
|
-
|
45
|
-
# get the names of all of the defined containers
|
46
|
-
my_container_names = self.containers.map(&:id)
|
47
|
-
|
48
|
-
# ephemeral containers parent containers have a "-master" suffix; we need to remove these from the results or we will complain about them
|
49
|
-
node_container_names = self.lxc.containers.map(&:name).delete_if do |node_container_name|
|
50
|
-
my_container_names.any?{ |my_container_name| "#{my_container_name}-master" == node_container_name }
|
51
|
-
end
|
52
|
-
|
53
|
-
unknown_container_names = (node_container_names - my_container_names)
|
54
|
-
unknown_running_container_names = self.lxc.containers.select{ |c| (unknown_container_names.include?(c.name) && (c.state == :running)) }.map(&:name)
|
55
|
-
|
56
|
-
if unknown_container_names.count > 0
|
57
|
-
if unknown_running_container_names.count > 0
|
58
|
-
@ui.stderr.puts(format_message("WARNING: You have *running* containers on your TestLab node #{self.id.inspect} which are not defined in your Labfile!".red.bold))
|
59
|
-
@ui.stderr.puts(format_message(">>> You may need to manually stop the following containers: #{unknown_running_container_names.join(', ')}".red.bold))
|
60
|
-
result = false
|
61
|
-
end
|
62
|
-
|
63
|
-
@ui.stderr.puts(format_message("WARNING: You have containers on your TestLab node #{self.id.inspect} which are not defined in your Labfile!".red.bold))
|
64
|
-
@ui.stderr.puts(format_message(">>> You may need to manually remove the following containers: #{unknown_container_names.join(', ')}".red.bold))
|
65
|
-
end
|
66
|
-
|
67
|
-
result
|
68
|
-
end
|
69
|
-
|
70
24
|
end
|
71
25
|
|
72
26
|
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.14.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-12-
|
12
|
+
date: 2013-12-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gli
|
@@ -266,6 +266,7 @@ files:
|
|
266
266
|
- lib/testlab/node.rb
|
267
267
|
- lib/testlab/node/actions.rb
|
268
268
|
- lib/testlab/node/class_methods.rb
|
269
|
+
- lib/testlab/node/doctor.rb
|
269
270
|
- lib/testlab/node/lxc.rb
|
270
271
|
- lib/testlab/node/method_missing.rb
|
271
272
|
- lib/testlab/node/provision.rb
|
@@ -350,7 +351,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
350
351
|
version: '0'
|
351
352
|
segments:
|
352
353
|
- 0
|
353
|
-
hash: -
|
354
|
+
hash: -2303575706409532818
|
354
355
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
355
356
|
none: false
|
356
357
|
requirements:
|
@@ -359,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
359
360
|
version: '0'
|
360
361
|
segments:
|
361
362
|
- 0
|
362
|
-
hash: -
|
363
|
+
hash: -2303575706409532818
|
363
364
|
requirements: []
|
364
365
|
rubyforge_project:
|
365
366
|
rubygems_version: 1.8.25
|