testlab 0.6.5 → 0.6.6
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/README.md +35 -32
- data/bin/tl +13 -640
- data/lib/commands/container.rb +292 -0
- data/lib/commands/network.rb +233 -0
- data/lib/commands/node.rb +182 -0
- data/lib/commands/testlab.rb +98 -0
- data/lib/testlab/container/actions.rb +15 -5
- data/lib/testlab/container/io.rb +69 -0
- data/lib/testlab/container/lifecycle.rb +6 -10
- data/lib/testlab/container/status.rb +1 -1
- data/lib/testlab/container.rb +2 -0
- data/lib/testlab/network/actions.rb +16 -0
- data/lib/testlab/network/lifecycle.rb +14 -20
- data/lib/testlab/network/status.rb +11 -5
- data/lib/testlab/network.rb +6 -6
- data/lib/testlab/node/actions.rb +16 -0
- data/lib/testlab/node/lifecycle.rb +15 -11
- data/lib/testlab/node/status.rb +1 -2
- data/lib/testlab/node.rb +1 -1
- data/lib/testlab/provisioner.rb +2 -1
- data/lib/testlab/provisioners/apt.rb +1 -1
- data/lib/testlab/provisioners/apt_cacher_ng.rb +2 -2
- data/lib/testlab/provisioners/bind.rb +1 -1
- data/lib/testlab/provisioners/chef_gem.rb +2 -2
- data/lib/testlab/provisioners/omnibus.rb +2 -2
- data/lib/testlab/provisioners/omnitruck.rb +2 -2
- data/lib/testlab/provisioners/raring.rb +1 -1
- data/lib/testlab/provisioners/resolv.rb +2 -2
- data/lib/testlab/provisioners/route.rb +51 -0
- data/lib/testlab/provisioners/shell.rb +1 -1
- data/lib/testlab/provisioners/templates/apt/bootstrap.erb +6 -1
- data/lib/testlab/provisioners/templates/apt_cacher_ng/bootstrap.erb +4 -1
- data/lib/testlab/provisioners/templates/raring/bootstrap.erb +9 -4
- data/lib/testlab/utility/logger.rb +87 -0
- data/lib/testlab/utility.rb +4 -2
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +28 -0
- data/spec/container_spec.rb +18 -12
- data/spec/network_spec.rb +4 -0
- data/spec/node_spec.rb +6 -19
- data/spec/provisioners/shell_spec.rb +2 -2
- data/spec/support/Labfile +3 -3
- data/testlab.gemspec +2 -2
- metadata +13 -6
@@ -0,0 +1,98 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Author: Zachary Patten <zachary AT jovelabs DOT com>
|
4
|
+
# Copyright: Copyright (c) Zachary Patten
|
5
|
+
# License: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
################################################################################
|
20
|
+
|
21
|
+
# LAB CREATE
|
22
|
+
#############
|
23
|
+
desc 'Create the test lab'
|
24
|
+
command :create do |create|
|
25
|
+
create.action do |global_options,options,args|
|
26
|
+
@testlab.create
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# LAB DESTROY
|
31
|
+
##############
|
32
|
+
desc 'Destroy the test lab'
|
33
|
+
command :destroy do |destroy|
|
34
|
+
destroy.action do |global_options,options,args|
|
35
|
+
@testlab.destroy
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# LAB ONLINE
|
40
|
+
#############
|
41
|
+
desc 'Online the test lab'
|
42
|
+
command :up do |up|
|
43
|
+
up.action do |global_options,options,args|
|
44
|
+
@testlab.up
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# LAB OFFLINE
|
49
|
+
##############
|
50
|
+
desc 'Offline the test lab'
|
51
|
+
command :down do |down|
|
52
|
+
down.action do |global_options,options,args|
|
53
|
+
@testlab.down
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# LAB SETUP
|
58
|
+
############
|
59
|
+
desc 'Setup the test lab infrastructure'
|
60
|
+
command :setup do |setup|
|
61
|
+
setup.action do |global_options,options,args|
|
62
|
+
@testlab.setup
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# LAB TEARDOWN
|
67
|
+
###############
|
68
|
+
desc 'Teardown the test lab infrastructure'
|
69
|
+
command :teardown do |teardown|
|
70
|
+
teardown.action do |global_options,options,args|
|
71
|
+
@testlab.teardown
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# LAB BUILD
|
76
|
+
############
|
77
|
+
desc 'Build the test lab infrastructure'
|
78
|
+
command :build do |build|
|
79
|
+
build.action do |global_options,options,args|
|
80
|
+
@testlab.build
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# LAB STATUS
|
85
|
+
#############
|
86
|
+
desc 'Display information on the status of the test lab'
|
87
|
+
command :status do |status|
|
88
|
+
status.action do |global_options,options,args|
|
89
|
+
@testlab.ui.stdout.puts("\nNODES:".green.bold)
|
90
|
+
commands[:node].commands[:status].execute({}, {}, [])
|
91
|
+
|
92
|
+
@testlab.ui.stdout.puts("\nNETWORKS:".green.bold)
|
93
|
+
commands[:network].commands[:status].execute({}, {}, [])
|
94
|
+
|
95
|
+
@testlab.ui.stdout.puts("\nCONTAINERS:".green.bold)
|
96
|
+
commands[:container].commands[:status].execute({}, {}, [])
|
97
|
+
end
|
98
|
+
end
|
@@ -15,10 +15,7 @@ class TestLab
|
|
15
15
|
(self.lxc.state != :not_created) and return false
|
16
16
|
|
17
17
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Create', :green)) do
|
18
|
-
|
19
|
-
self.arch ||= detect_arch
|
20
|
-
|
21
|
-
build_lxc_config(self.lxc.config)
|
18
|
+
configure
|
22
19
|
|
23
20
|
self.lxc.create(*create_args)
|
24
21
|
end
|
@@ -34,6 +31,8 @@ class TestLab
|
|
34
31
|
def destroy
|
35
32
|
@ui.logger.debug { "Container Destroy: #{self.id} " }
|
36
33
|
|
34
|
+
(self.lxc.state == :not_created) and return false
|
35
|
+
|
37
36
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
38
37
|
self.lxc.destroy(%(-f))
|
39
38
|
self.lxc_clone.destroy(%(-f))
|
@@ -53,6 +52,7 @@ class TestLab
|
|
53
52
|
(self.lxc.state == :running) and return false
|
54
53
|
|
55
54
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
55
|
+
configure
|
56
56
|
|
57
57
|
# ensure our container is in "static" mode
|
58
58
|
self.to_static
|
@@ -79,7 +79,7 @@ class TestLab
|
|
79
79
|
def down
|
80
80
|
@ui.logger.debug { "Container Down: #{self.id} " }
|
81
81
|
|
82
|
-
(self.lxc.state
|
82
|
+
(self.lxc.state != :running) and return false
|
83
83
|
|
84
84
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
85
85
|
self.lxc.stop
|
@@ -117,6 +117,16 @@ class TestLab
|
|
117
117
|
true
|
118
118
|
end
|
119
119
|
|
120
|
+
# Configure the container
|
121
|
+
def configure
|
122
|
+
self.domain ||= self.node.labfile.config[:domain]
|
123
|
+
self.arch ||= detect_arch
|
124
|
+
|
125
|
+
build_lxc_config(self.lxc.config)
|
126
|
+
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
120
130
|
end
|
121
131
|
|
122
132
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class TestLab
|
2
|
+
class Container
|
3
|
+
|
4
|
+
module IO
|
5
|
+
|
6
|
+
# Export the container
|
7
|
+
#
|
8
|
+
# @return [Boolean] True if successful.
|
9
|
+
def export(compression=9)
|
10
|
+
@ui.logger.debug { "Container Export: #{self.id} " }
|
11
|
+
|
12
|
+
(self.lxc.state == :not_created) and return false
|
13
|
+
|
14
|
+
self.down
|
15
|
+
|
16
|
+
sc_file = File.join("/", "tmp", "#{self.id}.sc")
|
17
|
+
local_file = File.join(Dir.pwd, File.basename(sc_file))
|
18
|
+
|
19
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Compress', :blue)) do
|
20
|
+
script = <<-EOF
|
21
|
+
set -x
|
22
|
+
find #{self.lxc.container_root} -print0 -depth | cpio -o0 | pbzip2 -#{compression} -vfcz > #{sc_file}
|
23
|
+
chown ${SUDO_USER}:${SUDO_USER} #{sc_file}
|
24
|
+
EOF
|
25
|
+
self.node.ssh.bootstrap(script)
|
26
|
+
end
|
27
|
+
|
28
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Export', :blue)) do
|
29
|
+
self.node.ssh.download(sc_file, local_file)
|
30
|
+
end
|
31
|
+
|
32
|
+
puts("Your shipping container is now exported and available at '#{local_file}'!")
|
33
|
+
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Import the container
|
38
|
+
#
|
39
|
+
# @return [Boolean] True if successful.
|
40
|
+
def import(local_file)
|
41
|
+
@ui.logger.debug { "Container Import: #{self.id} " }
|
42
|
+
|
43
|
+
self.down
|
44
|
+
self.destroy
|
45
|
+
|
46
|
+
sc_file = File.join("/", "tmp", "#{self.id}.sc")
|
47
|
+
|
48
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Import', :blue)) do
|
49
|
+
self.node.ssh.exec(%(sudo rm -fv #{sc_file}), :silence => true, :ignore_exit_status => true)
|
50
|
+
self.node.ssh.upload(local_file, sc_file)
|
51
|
+
end
|
52
|
+
|
53
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Expand', :blue)) do
|
54
|
+
script = <<-EOF
|
55
|
+
set -x
|
56
|
+
pbzip2 -vdc #{sc_file} | cpio -uid && rm -fv #{sc_file}
|
57
|
+
EOF
|
58
|
+
self.node.ssh.bootstrap(script)
|
59
|
+
end
|
60
|
+
|
61
|
+
puts("Your shipping container is now imported and available for use!")
|
62
|
+
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -13,15 +13,12 @@ class TestLab
|
|
13
13
|
def setup
|
14
14
|
@ui.logger.debug { "Container Setup: #{self.id} " }
|
15
15
|
|
16
|
-
self.create
|
17
|
-
self.up
|
18
|
-
|
19
16
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
20
17
|
|
21
18
|
self.provisioners.each do |provisioner|
|
22
|
-
@ui.logger.info { ">>>>>
|
19
|
+
@ui.logger.info { ">>>>> CONTAINER PROVISIONER SETUP: #{provisioner} <<<<<" }
|
23
20
|
p = provisioner.new(self.config, @ui)
|
24
|
-
p.respond_to?(:
|
21
|
+
p.respond_to?(:on_container_setup) and p.on_container_setup(self)
|
25
22
|
end
|
26
23
|
|
27
24
|
end
|
@@ -39,19 +36,18 @@ class TestLab
|
|
39
36
|
def teardown
|
40
37
|
@ui.logger.debug { "Container Teardown: #{self.id} " }
|
41
38
|
|
39
|
+
(self.lxc.state == :not_created) and return false
|
40
|
+
|
42
41
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
43
42
|
|
44
43
|
self.provisioners.each do |provisioner|
|
45
|
-
@ui.logger.info { ">>>>>
|
44
|
+
@ui.logger.info { ">>>>> CONTAINER PROVISIONER TEARDOWN: #{provisioner} <<<<<" }
|
46
45
|
p = provisioner.new(self.config, @ui)
|
47
|
-
p.respond_to?(:
|
46
|
+
p.respond_to?(:on_container_teardown) and p.on_container_teardown(self)
|
48
47
|
end
|
49
48
|
|
50
49
|
end
|
51
50
|
|
52
|
-
self.down
|
53
|
-
self.destroy
|
54
|
-
|
55
51
|
true
|
56
52
|
end
|
57
53
|
|
@@ -59,7 +59,7 @@ class TestLab
|
|
59
59
|
:distro => self.distro,
|
60
60
|
:release => self.release,
|
61
61
|
:interfaces => interfaces,
|
62
|
-
:provisioners => self.provisioners.map(&:to_s).collect{ |p| p.split('::').last }.join('
|
62
|
+
:provisioners => self.provisioners.map(&:to_s).collect{ |p| p.split('::').last }.join(','),
|
63
63
|
:node_id => self.node.id
|
64
64
|
}
|
65
65
|
end
|
data/lib/testlab/container.rb
CHANGED
@@ -77,6 +77,7 @@ class TestLab
|
|
77
77
|
autoload :ClassMethods, 'testlab/container/class_methods'
|
78
78
|
autoload :Generators, 'testlab/container/generators'
|
79
79
|
autoload :Interface, 'testlab/container/interface'
|
80
|
+
autoload :IO, 'testlab/container/io'
|
80
81
|
autoload :Lifecycle, 'testlab/container/lifecycle'
|
81
82
|
autoload :LXC, 'testlab/container/lxc'
|
82
83
|
autoload :MethodMissing, 'testlab/container/method_missing'
|
@@ -87,6 +88,7 @@ class TestLab
|
|
87
88
|
include TestLab::Container::Actions
|
88
89
|
include TestLab::Container::Generators
|
89
90
|
include TestLab::Container::Interface
|
91
|
+
include TestLab::Container::IO
|
90
92
|
include TestLab::Container::Lifecycle
|
91
93
|
include TestLab::Container::LXC
|
92
94
|
include TestLab::Container::MethodMissing
|
@@ -7,36 +7,52 @@ class TestLab
|
|
7
7
|
def create
|
8
8
|
@ui.logger.debug { "Network Create: #{self.id} " }
|
9
9
|
|
10
|
+
(self.state != :not_created) and return false
|
11
|
+
|
10
12
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Create', :green)) do
|
11
13
|
self.node.ssh.exec(%(sudo brctl addbr #{self.bridge}), :silence => true, :ignore_exit_status => true)
|
12
14
|
end
|
15
|
+
|
16
|
+
true
|
13
17
|
end
|
14
18
|
|
15
19
|
# Destroy the network
|
16
20
|
def destroy
|
17
21
|
@ui.logger.debug { "Network Destroy: #{self.id} " }
|
18
22
|
|
23
|
+
(self.state == :not_created) and return false
|
24
|
+
|
19
25
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
20
26
|
self.node.ssh.exec(%(sudo brctl delbr #{self.bridge}), :silence => true, :ignore_exit_status => true)
|
21
27
|
end
|
28
|
+
|
29
|
+
true
|
22
30
|
end
|
23
31
|
|
24
32
|
# Start the network
|
25
33
|
def up
|
26
34
|
@ui.logger.debug { "Network Up: #{self.id} " }
|
27
35
|
|
36
|
+
(self.state == :running) and return false
|
37
|
+
|
28
38
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
29
39
|
self.node.ssh.exec(%(sudo ifconfig #{self.bridge} #{self.ip} netmask #{self.netmask} up), :silence => true, :ignore_exit_status => true)
|
30
40
|
end
|
41
|
+
|
42
|
+
true
|
31
43
|
end
|
32
44
|
|
33
45
|
# Stop the network
|
34
46
|
def down
|
35
47
|
@ui.logger.debug { "Network Down: #{self.id} " }
|
36
48
|
|
49
|
+
(self.state != :running) and return false
|
50
|
+
|
37
51
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
38
52
|
self.node.ssh.exec(%(sudo ifconfig #{self.bridge} down), :silence => true, :ignore_exit_status => true)
|
39
53
|
end
|
54
|
+
|
55
|
+
true
|
40
56
|
end
|
41
57
|
|
42
58
|
end
|
@@ -7,11 +7,14 @@ class TestLab
|
|
7
7
|
def setup
|
8
8
|
@ui.logger.debug { "Network Setup: #{self.id} " }
|
9
9
|
|
10
|
-
self.create
|
11
|
-
self.up
|
12
|
-
|
13
10
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
14
|
-
|
11
|
+
|
12
|
+
self.provisioners.each do |provisioner|
|
13
|
+
@ui.logger.info { ">>>>> NETWORK PROVISIONER SETUP: #{provisioner} <<<<<" }
|
14
|
+
p = provisioner.new(self.config, @ui)
|
15
|
+
p.respond_to?(:on_node_teardown) and p.on_node_teardown(self)
|
16
|
+
end
|
17
|
+
|
15
18
|
end
|
16
19
|
|
17
20
|
true
|
@@ -22,25 +25,16 @@ class TestLab
|
|
22
25
|
@ui.logger.debug { "Network Teardown: #{self.id} " }
|
23
26
|
|
24
27
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
25
|
-
self.route and manage_route(:del)
|
26
|
-
end
|
27
|
-
|
28
|
-
self.down
|
29
|
-
self.destroy
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
self.provisioners.each do |provisioner|
|
30
|
+
@ui.logger.info { ">>>>> NETWORK PROVISIONER TEARDOWN: #{provisioner} <<<<<" }
|
31
|
+
p = provisioner.new(self.config, @ui)
|
32
|
+
p.respond_to?(:on_node_teardown) and p.on_node_teardown(self)
|
33
|
+
end
|
36
34
|
|
37
|
-
case RUBY_PLATFORM
|
38
|
-
when /darwin/ then
|
39
|
-
action = ((action == :del) ? :delete : :add)
|
40
|
-
command.exec(%(sudo route #{action} -net #{TestLab::Utility.network(self.address)} #{self.node.ip} #{TestLab::Utility.netmask(self.address)}))
|
41
|
-
when /linux/ then
|
42
|
-
command.exec(%(sudo route #{action} -net #{TestLab::Utility.network(self.address)} netmask #{TestLab::Utility.netmask(self.address)} gw #{self.node.ip}))
|
43
35
|
end
|
36
|
+
|
37
|
+
true
|
44
38
|
end
|
45
39
|
|
46
40
|
end
|
@@ -13,7 +13,8 @@ class TestLab
|
|
13
13
|
:interface => interface,
|
14
14
|
:broadcast => self.broadcast,
|
15
15
|
:network => self.network,
|
16
|
-
:netmask => self.netmask
|
16
|
+
:netmask => self.netmask,
|
17
|
+
:provisioners => self.provisioners.map(&:to_s).collect{ |p| p.split('::').last }.join(','),
|
17
18
|
}
|
18
19
|
end
|
19
20
|
|
@@ -42,11 +43,16 @@ class TestLab
|
|
42
43
|
|
43
44
|
# Network Bridge State
|
44
45
|
def state
|
45
|
-
|
46
|
-
if (
|
47
|
-
:
|
46
|
+
exit_code = self.node.ssh.exec(%(sudo brctl show #{self.bridge} 2>&1 | grep -i 'No such device'), :silence => true, :ignore_exit_status => true).exit_code
|
47
|
+
if (exit_code == 0)
|
48
|
+
:not_created
|
48
49
|
else
|
49
|
-
:
|
50
|
+
output = self.node.ssh.exec(%(sudo ifconfig #{self.bridge} 2>&1 | grep 'MTU'), :silence => true, :ignore_exit_status => true).output.strip
|
51
|
+
if ((output =~ /UP/) && (output =~ /RUNNING/))
|
52
|
+
:running
|
53
|
+
else
|
54
|
+
:stopped
|
55
|
+
end
|
50
56
|
end
|
51
57
|
end
|
52
58
|
|
data/lib/testlab/network.rb
CHANGED
@@ -7,7 +7,7 @@ class TestLab
|
|
7
7
|
#
|
8
8
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
9
9
|
class Network < ZTK::DSL::Base
|
10
|
-
STATUS_KEYS = %w(node_id id state interface network netmask broadcast).map(&:to_sym)
|
10
|
+
STATUS_KEYS = %w(node_id id state interface network netmask broadcast provisioners).map(&:to_sym)
|
11
11
|
|
12
12
|
# Sub-Modules
|
13
13
|
autoload :Actions, 'testlab/network/actions'
|
@@ -26,14 +26,14 @@ class TestLab
|
|
26
26
|
include TestLab::Utility::Misc
|
27
27
|
|
28
28
|
# Associations and Attributes
|
29
|
-
belongs_to :node,
|
30
|
-
has_many :interfaces,
|
29
|
+
belongs_to :node, :class_name => 'TestLab::Node'
|
30
|
+
has_many :interfaces, :class_name => 'TestLab::Interface'
|
31
|
+
|
32
|
+
attribute :provisioners, :default => Array.new
|
33
|
+
attribute :config, :default => Hash.new
|
31
34
|
|
32
35
|
attribute :address
|
33
36
|
attribute :bridge
|
34
|
-
attribute :route, :default => false
|
35
|
-
|
36
|
-
attribute :config
|
37
37
|
|
38
38
|
|
39
39
|
def initialize(*args)
|
data/lib/testlab/node/actions.rb
CHANGED
@@ -7,36 +7,52 @@ class TestLab
|
|
7
7
|
def create
|
8
8
|
@ui.logger.debug { "Node Create: #{self.id} " }
|
9
9
|
|
10
|
+
(self.state != :not_created) and return false
|
11
|
+
|
10
12
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Create', :green)) do
|
11
13
|
@provider.create
|
12
14
|
end
|
15
|
+
|
16
|
+
true
|
13
17
|
end
|
14
18
|
|
15
19
|
# Destroy the node
|
16
20
|
def destroy
|
17
21
|
@ui.logger.debug { "Node Destroy: #{self.id} " }
|
18
22
|
|
23
|
+
(self.state == :not_created) and return false
|
24
|
+
|
19
25
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
20
26
|
@provider.destroy
|
21
27
|
end
|
28
|
+
|
29
|
+
true
|
22
30
|
end
|
23
31
|
|
24
32
|
# Start the node
|
25
33
|
def up
|
26
34
|
@ui.logger.debug { "Node Up: #{self.id} " }
|
27
35
|
|
36
|
+
(self.state == :running) and return false
|
37
|
+
|
28
38
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
29
39
|
@provider.up
|
30
40
|
end
|
41
|
+
|
42
|
+
true
|
31
43
|
end
|
32
44
|
|
33
45
|
# Stop the node
|
34
46
|
def down
|
35
47
|
@ui.logger.debug { "Node Down: #{self.id} " }
|
36
48
|
|
49
|
+
(self.state != :running) and return false
|
50
|
+
|
37
51
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
38
52
|
@provider.down
|
39
53
|
end
|
54
|
+
|
55
|
+
true
|
40
56
|
end
|
41
57
|
|
42
58
|
end
|
@@ -13,17 +13,12 @@ class TestLab
|
|
13
13
|
def setup
|
14
14
|
@ui.logger.debug { "Node Setup: #{self.id} " }
|
15
15
|
|
16
|
-
self.create
|
17
|
-
self.up
|
18
|
-
|
19
16
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
20
17
|
|
21
|
-
global_provisioners = [self.provisioners, self.containers.map(&:provisioners)].flatten.compact.uniq
|
22
|
-
|
23
18
|
global_provisioners.each do |provisioner|
|
24
|
-
@ui.logger.info { ">>>>> NODE PROVISIONER: #{provisioner} <<<<<" }
|
19
|
+
@ui.logger.info { ">>>>> NODE PROVISIONER SETUP: #{provisioner} <<<<<" }
|
25
20
|
p = provisioner.new(self.config, @ui)
|
26
|
-
p.respond_to?(:
|
21
|
+
p.respond_to?(:on_node_setup) and p.on_node_setup(self)
|
27
22
|
end
|
28
23
|
|
29
24
|
end
|
@@ -35,16 +30,25 @@ class TestLab
|
|
35
30
|
def teardown
|
36
31
|
@ui.logger.debug { "Node Teardown: #{self.id} " }
|
37
32
|
|
33
|
+
(self.state == :not_created) and return false
|
34
|
+
|
38
35
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
39
|
-
# NOOP
|
40
|
-
end
|
41
36
|
|
42
|
-
|
43
|
-
|
37
|
+
global_provisioners.each do |provisioner|
|
38
|
+
@ui.logger.info { ">>>>> NODE PROVISIONER TEARDOWN: #{provisioner} <<<<<" }
|
39
|
+
p = provisioner.new(self.config, @ui)
|
40
|
+
p.respond_to?(:on_node_teardown) and p.on_node_teardown(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
44
|
|
45
45
|
true
|
46
46
|
end
|
47
47
|
|
48
|
+
def global_provisioners
|
49
|
+
[self.provisioners, self.containers.map(&:provisioners)].flatten.compact.uniq
|
50
|
+
end
|
51
|
+
|
48
52
|
end
|
49
53
|
|
50
54
|
end
|
data/lib/testlab/node/status.rb
CHANGED
@@ -16,8 +16,7 @@ class TestLab
|
|
16
16
|
:ip => @provider.ip,
|
17
17
|
:port => @provider.port,
|
18
18
|
:provider => @provider.class,
|
19
|
-
:
|
20
|
-
:net => self.networks.count
|
19
|
+
:provisioners => self.provisioners.map(&:to_s).collect{ |p| p.split('::').last }.join(',')
|
21
20
|
}
|
22
21
|
end
|
23
22
|
|
data/lib/testlab/node.rb
CHANGED
@@ -7,7 +7,7 @@ class TestLab
|
|
7
7
|
#
|
8
8
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
9
9
|
class Node < ZTK::DSL::Base
|
10
|
-
STATUS_KEYS = %w(id instance_id state user ip port provider
|
10
|
+
STATUS_KEYS = %w(id instance_id state user ip port provider provisioners).map(&:to_sym)
|
11
11
|
|
12
12
|
# Sub-Modules
|
13
13
|
autoload :Actions, 'testlab/node/actions'
|
data/lib/testlab/provisioner.rb
CHANGED
@@ -13,8 +13,9 @@ class TestLab
|
|
13
13
|
autoload :ChefGem, 'testlab/provisioners/chef_gem'
|
14
14
|
autoload :OmniBus, 'testlab/provisioners/omnibus'
|
15
15
|
autoload :OmniTruck, 'testlab/provisioners/omnitruck'
|
16
|
-
autoload :Resolv, 'testlab/provisioners/resolv'
|
17
16
|
autoload :Raring, 'testlab/provisioners/raring'
|
17
|
+
autoload :Resolv, 'testlab/provisioners/resolv'
|
18
|
+
autoload :Route, 'testlab/provisioners/route'
|
18
19
|
autoload :Shell, 'testlab/provisioners/shell'
|
19
20
|
|
20
21
|
class << self
|
@@ -26,7 +26,7 @@ class TestLab
|
|
26
26
|
# @param [TestLab::Container] container The container which we want to
|
27
27
|
# provision.
|
28
28
|
# @return [Boolean] True if successful.
|
29
|
-
def
|
29
|
+
def on_container_setup(container)
|
30
30
|
@ui.logger.debug { "APT Provisioner: Container #{container.id}" }
|
31
31
|
|
32
32
|
bootstrap_template = File.join(TestLab::Provisioner.template_dir, "apt", "bootstrap.erb")
|
@@ -27,7 +27,7 @@ class TestLab
|
|
27
27
|
#
|
28
28
|
# @param [TestLab::Node] node The node which we want to provision.
|
29
29
|
# @return [Boolean] True if successful.
|
30
|
-
def
|
30
|
+
def on_node_setup(node)
|
31
31
|
@ui.logger.debug { "APT-CacherNG Provisioner: Node #{node.id}" }
|
32
32
|
|
33
33
|
bootstrap_template = File.join(TestLab::Provisioner.template_dir, "apt_cacher_ng", "bootstrap.erb")
|
@@ -55,7 +55,7 @@ class TestLab
|
|
55
55
|
# @param [TestLab::Container] container The container which we want to
|
56
56
|
# provision.
|
57
57
|
# @return [Boolean] True if successful.
|
58
|
-
def
|
58
|
+
def on_container_setup(container)
|
59
59
|
@ui.logger.debug { "APT-CacherNG Provisioner: Container #{container.id}" }
|
60
60
|
|
61
61
|
# Ensure the container APT calls use apt-cacher-ng on the node
|
@@ -23,7 +23,7 @@ class TestLab
|
|
23
23
|
#
|
24
24
|
# @param [TestLab::Node] node The node which we want to provision.
|
25
25
|
# @return [Boolean] True if successful.
|
26
|
-
def
|
26
|
+
def on_node_setup(node)
|
27
27
|
@ui.logger.debug { "BIND Provisioner: Node #{node.id}" }
|
28
28
|
|
29
29
|
bind_setup(node.ssh)
|
@@ -26,7 +26,7 @@ class TestLab
|
|
26
26
|
# @param [TestLab::Container] container The container which we want to
|
27
27
|
# provision.
|
28
28
|
# @return [Boolean] True if successful.
|
29
|
-
def
|
29
|
+
def on_container_setup(container)
|
30
30
|
# NOOP
|
31
31
|
|
32
32
|
true
|
@@ -37,7 +37,7 @@ class TestLab
|
|
37
37
|
# This is a NO-OP currently.
|
38
38
|
#
|
39
39
|
# @return [Boolean] True if successful.
|
40
|
-
def
|
40
|
+
def on_container_teardown(container)
|
41
41
|
# NOOP
|
42
42
|
|
43
43
|
true
|
@@ -28,7 +28,7 @@ class TestLab
|
|
28
28
|
# @param [TestLab::Container] container The container which we want to
|
29
29
|
# provision.
|
30
30
|
# @return [Boolean] True if successful.
|
31
|
-
def
|
31
|
+
def on_container_setup(container)
|
32
32
|
omnibus_template = File.join(TestLab::Provisioner.template_dir, 'chef', 'omnibus.erb')
|
33
33
|
container.bootstrap(ZTK::Template.render(omnibus_template, @config))
|
34
34
|
end
|
@@ -38,7 +38,7 @@ class TestLab
|
|
38
38
|
# This is a NO-OP currently.
|
39
39
|
#
|
40
40
|
# @return [Boolean] True if successful.
|
41
|
-
def
|
41
|
+
def on_container_teardown(container)
|
42
42
|
# NOOP
|
43
43
|
|
44
44
|
true
|