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.
@@ -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
 
@@ -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
@@ -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.ok?.inspect,
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
@@ -1,6 +1,6 @@
1
1
  class TestLab
2
2
  unless const_defined?(:VERSION)
3
3
  # TestLab Gem Version
4
- VERSION = "1.13.0"
4
+ VERSION = "1.14.0"
5
5
  end
6
6
  end
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.13.0
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-13 00:00:00.000000000 Z
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: -3460081152239272666
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: -3460081152239272666
363
+ hash: -2303575706409532818
363
364
  requirements: []
364
365
  rubyforge_project:
365
366
  rubygems_version: 1.8.25