testlab 1.13.0 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|