testlab 1.0.1 → 1.1.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/README.md +1 -1
- data/bin/tl +5 -3
- data/features/support/Labfile.local +2 -8
- data/features/support/Labfile.vagrant +2 -5
- data/lib/testlab/container/actions.rb +1 -41
- data/lib/testlab/container/clone.rb +87 -0
- data/lib/testlab/container/configuration.rb +67 -0
- data/lib/testlab/container/io.rb +8 -8
- data/lib/testlab/container/lifecycle.rb +0 -40
- data/lib/testlab/container/lxc.rb +0 -143
- data/lib/testlab/container/provision.rb +49 -0
- data/lib/testlab/container/support.rb +47 -0
- data/lib/testlab/container.rb +10 -0
- data/lib/testlab/network/actions.rb +4 -4
- data/lib/testlab/network/lifecycle.rb +0 -28
- data/lib/testlab/network/provision.rb +37 -0
- data/lib/testlab/network/status.rb +2 -2
- data/lib/testlab/network.rb +2 -0
- data/lib/testlab/node/lifecycle.rb +0 -26
- data/lib/testlab/node/lxc.rb +1 -13
- data/lib/testlab/node/provision.rb +34 -0
- data/lib/testlab/node.rb +4 -0
- data/lib/testlab/provisioners/apt.rb +1 -0
- data/lib/testlab/provisioners/apt_cacher_ng.rb +5 -5
- data/lib/testlab/provisioners/bind.rb +35 -18
- data/lib/testlab/provisioners/chef/omni_bus.rb +3 -3
- data/lib/testlab/provisioners/chef/ruby_gem_client.rb +3 -3
- data/lib/testlab/provisioners/resolv.rb +14 -6
- data/lib/testlab/provisioners/route.rb +5 -2
- data/lib/testlab/provisioners/templates/apt/provision.erb +3 -0
- data/lib/testlab/provisioners/templates/bind/bind.erb +5 -2
- data/lib/testlab/provisioners/templates/raring/provision.erb +13 -10
- data/lib/testlab/provisioners/templates/resolv/resolv.conf.erb +4 -2
- data/lib/testlab/support/execution.rb +46 -0
- data/lib/testlab/support.rb +17 -0
- data/lib/testlab/user/lifecycle.rb +6 -6
- data/lib/testlab/utility/gli.rb +3 -3
- data/lib/testlab/utility/misc.rb +8 -0
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +1 -0
- metadata +10 -8
@@ -11,7 +11,7 @@ class TestLab
|
|
11
11
|
(self.state != :not_created) and return false
|
12
12
|
|
13
13
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Create', :green)) do
|
14
|
-
self.node.
|
14
|
+
self.node.bootstrap(<<-EOF, :ignore_exit_status => true)
|
15
15
|
set -x
|
16
16
|
grep '#{def_tag}' /etc/network/interfaces && exit 0
|
17
17
|
cat <<EOI | tee -a /etc/network/interfaces
|
@@ -45,7 +45,7 @@ brctl setfd #{self.bridge} 0
|
|
45
45
|
(self.state == :not_created) and return false
|
46
46
|
|
47
47
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
48
|
-
self.node.
|
48
|
+
self.node.bootstrap(<<-EOF, :ignore_exit_status => true)
|
49
49
|
set -x
|
50
50
|
sed -i '/#{def_tag}/,/#{end_tag}/d' /etc/network/interfaces
|
51
51
|
brctl delbr #{self.bridge}
|
@@ -65,7 +65,7 @@ brctl delbr #{self.bridge}
|
|
65
65
|
(self.state == :running) and return false
|
66
66
|
|
67
67
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
68
|
-
self.node.
|
68
|
+
self.node.bootstrap(<<-EOF, :ignore_exit_status => true)
|
69
69
|
set -x
|
70
70
|
ifconfig #{self.bridge} #{self.ip} netmask #{self.netmask} broadcast #{self.broadcast} up
|
71
71
|
EOF
|
@@ -84,7 +84,7 @@ ifconfig #{self.bridge} #{self.ip} netmask #{self.netmask} broadcast #{self.broa
|
|
84
84
|
(self.state != :running) and return false
|
85
85
|
|
86
86
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
87
|
-
self.node.
|
87
|
+
self.node.bootstrap(<<-EOF, :ignore_exit_status => true)
|
88
88
|
set -x
|
89
89
|
ifconfig #{self.bridge} down
|
90
90
|
EOF
|
@@ -3,34 +3,6 @@ class TestLab
|
|
3
3
|
|
4
4
|
module Lifecycle
|
5
5
|
|
6
|
-
# Network Provision
|
7
|
-
def provision
|
8
|
-
@ui.logger.debug { "Network Provision: #{self.id} " }
|
9
|
-
|
10
|
-
(self.node.state != :running) and return false
|
11
|
-
(self.state != :running) and return false
|
12
|
-
|
13
|
-
please_wait(:ui => @ui, :message => format_object_action(self, 'Provision', :green)) do
|
14
|
-
do_provisioner_callbacks(self, :provision, @ui)
|
15
|
-
end
|
16
|
-
|
17
|
-
true
|
18
|
-
end
|
19
|
-
|
20
|
-
# Network Deprovision
|
21
|
-
def deprovision
|
22
|
-
@ui.logger.debug { "Network Deprovision: #{self.id} " }
|
23
|
-
|
24
|
-
(self.node.state != :running) and return false
|
25
|
-
(self.state != :running) and return false
|
26
|
-
|
27
|
-
please_wait(:ui => @ui, :message => format_object_action(self, 'Deprovision', :red)) do
|
28
|
-
do_provisioner_callbacks(self, :deprovision, @ui)
|
29
|
-
end
|
30
|
-
|
31
|
-
true
|
32
|
-
end
|
33
|
-
|
34
6
|
# Build the network
|
35
7
|
def build
|
36
8
|
self.create
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class TestLab
|
2
|
+
class Network
|
3
|
+
|
4
|
+
module Provision
|
5
|
+
|
6
|
+
# Network Provision
|
7
|
+
def provision
|
8
|
+
@ui.logger.debug { "Network Provision: #{self.id} " }
|
9
|
+
|
10
|
+
(self.node.state != :running) and return false
|
11
|
+
(self.state != :running) and return false
|
12
|
+
|
13
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Provision', :green)) do
|
14
|
+
do_provisioner_callbacks(self, :provision, @ui)
|
15
|
+
end
|
16
|
+
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
# Network Deprovision
|
21
|
+
def deprovision
|
22
|
+
@ui.logger.debug { "Network Deprovision: #{self.id} " }
|
23
|
+
|
24
|
+
(self.node.state != :running) and return false
|
25
|
+
(self.state != :running) and return false
|
26
|
+
|
27
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Deprovision', :red)) do
|
28
|
+
do_provisioner_callbacks(self, :deprovision, @ui)
|
29
|
+
end
|
30
|
+
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -63,11 +63,11 @@ class TestLab
|
|
63
63
|
|
64
64
|
# Network Bridge State
|
65
65
|
def state
|
66
|
-
exit_code = self.node.
|
66
|
+
exit_code = self.node.exec(%(sudo brctl show #{self.bridge} 2>&1 | grep -i 'No such device'), :ignore_exit_status => true).exit_code
|
67
67
|
if (exit_code == 0)
|
68
68
|
:not_created
|
69
69
|
else
|
70
|
-
output = self.node.
|
70
|
+
output = self.node.exec(%(sudo ifconfig #{self.bridge} 2>&1 | grep 'MTU'), :ignore_exit_status => true).output.strip
|
71
71
|
if ((output =~ /UP/) || (output =~ /RUNNING/))
|
72
72
|
:running
|
73
73
|
else
|
data/lib/testlab/network.rb
CHANGED
@@ -14,11 +14,13 @@ class TestLab
|
|
14
14
|
autoload :Bind, 'testlab/network/bind'
|
15
15
|
autoload :ClassMethods, 'testlab/network/class_methods'
|
16
16
|
autoload :Lifecycle, 'testlab/network/lifecycle'
|
17
|
+
autoload :Provision, 'testlab/network/provision'
|
17
18
|
autoload :Status, 'testlab/network/status'
|
18
19
|
|
19
20
|
include TestLab::Network::Actions
|
20
21
|
include TestLab::Network::Bind
|
21
22
|
include TestLab::Network::Lifecycle
|
23
|
+
include TestLab::Network::Provision
|
22
24
|
include TestLab::Network::Status
|
23
25
|
|
24
26
|
extend TestLab::Network::ClassMethods
|
@@ -3,32 +3,6 @@ class TestLab
|
|
3
3
|
|
4
4
|
module Lifecycle
|
5
5
|
|
6
|
-
# Provision the node.
|
7
|
-
def provision
|
8
|
-
@ui.logger.debug { "Node Provision: #{self.id} " }
|
9
|
-
|
10
|
-
(self.state != :running) and return false
|
11
|
-
|
12
|
-
please_wait(:ui => @ui, :message => format_object_action(self, 'Provision', :green)) do
|
13
|
-
do_provisioner_callbacks(self, :provision, @ui)
|
14
|
-
end
|
15
|
-
|
16
|
-
true
|
17
|
-
end
|
18
|
-
|
19
|
-
# Deprovision the node.
|
20
|
-
def deprovision
|
21
|
-
@ui.logger.debug { "Node Deprovision: #{self.id} " }
|
22
|
-
|
23
|
-
(self.state != :running) and return false
|
24
|
-
|
25
|
-
please_wait(:ui => @ui, :message => format_object_action(self, 'Deprovision', :red)) do
|
26
|
-
do_provisioner_callbacks(self, :deprovision, @ui)
|
27
|
-
end
|
28
|
-
|
29
|
-
true
|
30
|
-
end
|
31
|
-
|
32
6
|
# Build the node
|
33
7
|
def build
|
34
8
|
self.create
|
data/lib/testlab/node/lxc.rb
CHANGED
@@ -4,18 +4,6 @@ class TestLab
|
|
4
4
|
module LXC
|
5
5
|
require 'lxc'
|
6
6
|
|
7
|
-
# Node Bootstrap
|
8
|
-
#
|
9
|
-
# Renders the supplied content into a file on the node and proceeds
|
10
|
-
# to execute it on the node as root.
|
11
|
-
#
|
12
|
-
# @param [String] content The content to render on the node and
|
13
|
-
# execute. This is generally a bash script of some sort for example.
|
14
|
-
# @return [String] The output of SSH bootstrap.
|
15
|
-
def bootstrap(content, options={})
|
16
|
-
self.ssh.bootstrap(content, options)
|
17
|
-
end
|
18
|
-
|
19
7
|
# Returns the LXC object for this Node
|
20
8
|
#
|
21
9
|
# This object is used to control containers on the node via it's provider
|
@@ -33,7 +21,7 @@ class TestLab
|
|
33
21
|
#
|
34
22
|
# @return [String] The output of 'uname -m'.
|
35
23
|
def arch
|
36
|
-
@arch ||= self.
|
24
|
+
@arch ||= self.exec(%(uname -m)).output.strip
|
37
25
|
end
|
38
26
|
|
39
27
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class TestLab
|
2
|
+
class Node
|
3
|
+
|
4
|
+
module Provision
|
5
|
+
|
6
|
+
# Provision the node.
|
7
|
+
def provision
|
8
|
+
@ui.logger.debug { "Node Provision: #{self.id} " }
|
9
|
+
|
10
|
+
(self.state != :running) and return false
|
11
|
+
|
12
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Provision', :green)) do
|
13
|
+
do_provisioner_callbacks(self, :provision, @ui)
|
14
|
+
end
|
15
|
+
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
# Deprovision the node.
|
20
|
+
def deprovision
|
21
|
+
@ui.logger.debug { "Node Deprovision: #{self.id} " }
|
22
|
+
|
23
|
+
(self.state != :running) and return false
|
24
|
+
|
25
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Deprovision', :red)) do
|
26
|
+
do_provisioner_callbacks(self, :deprovision, @ui)
|
27
|
+
end
|
28
|
+
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/testlab/node.rb
CHANGED
@@ -15,6 +15,7 @@ class TestLab
|
|
15
15
|
autoload :Lifecycle, 'testlab/node/lifecycle'
|
16
16
|
autoload :LXC, 'testlab/node/lxc'
|
17
17
|
autoload :MethodMissing, 'testlab/node/method_missing'
|
18
|
+
autoload :Provision, 'testlab/node/provision'
|
18
19
|
autoload :SSH, 'testlab/node/ssh'
|
19
20
|
autoload :Status, 'testlab/node/status'
|
20
21
|
|
@@ -22,11 +23,14 @@ class TestLab
|
|
22
23
|
include TestLab::Node::Lifecycle
|
23
24
|
include TestLab::Node::LXC
|
24
25
|
include TestLab::Node::MethodMissing
|
26
|
+
include TestLab::Node::Provision
|
25
27
|
include TestLab::Node::SSH
|
26
28
|
include TestLab::Node::Status
|
27
29
|
|
28
30
|
extend TestLab::Node::ClassMethods
|
29
31
|
|
32
|
+
include TestLab::Support::Execution
|
33
|
+
|
30
34
|
include TestLab::Utility::Misc
|
31
35
|
|
32
36
|
# Associations and Attributes
|
@@ -39,15 +39,15 @@ class TestLab
|
|
39
39
|
}
|
40
40
|
}
|
41
41
|
|
42
|
-
node.
|
42
|
+
node.file(:target => apt_conf_d_proxy_file, :chown => "root:root", :chmod => "0644") do |file|
|
43
43
|
file.puts(ZTK::Template.render(apt_conf_d_proxy_file_template, context))
|
44
44
|
end
|
45
45
|
|
46
|
-
node.
|
46
|
+
node.file(:target => apt_cacher_ng_security_conf_file, :chown => "root:root", :chmod => "0644") do |file|
|
47
47
|
file.puts(ZTK::Template.render(apt_cacher_ng_security_conf_template, context))
|
48
48
|
end
|
49
49
|
|
50
|
-
node.
|
50
|
+
node.exec(%(sudo service apt-cacher-ng restart))
|
51
51
|
|
52
52
|
true
|
53
53
|
end
|
@@ -75,12 +75,12 @@ class TestLab
|
|
75
75
|
|
76
76
|
@config[:apt][:cacher_ng] = { :proxy_url => "http://#{gateway_ip}:3142" }.merge(@config[:apt][:cacher_ng])
|
77
77
|
|
78
|
-
container.
|
78
|
+
container.file(:target => apt_conf_d_proxy_file, :chown => "root:root", :chmod => "0644") do |file|
|
79
79
|
file.puts(ZTK::Template.render(apt_conf_d_proxy_file_template, @config))
|
80
80
|
end
|
81
81
|
|
82
82
|
# Fix the APT sources since LXC mudges them when using apt-cacher-ng
|
83
|
-
container.
|
83
|
+
container.exec(%(sudo sed -i 's/127.0.0.1:3142\\///g' /etc/apt/sources.list))
|
84
84
|
end
|
85
85
|
|
86
86
|
private
|
@@ -15,7 +15,9 @@ class TestLab
|
|
15
15
|
@ui = (ui || TestLab.ui)
|
16
16
|
|
17
17
|
@config[:bind] ||= Hash.new
|
18
|
-
@config[:bind][:domain]
|
18
|
+
@config[:bind][:domain] ||= "tld.invalid"
|
19
|
+
@config[:bind][:forwarders] ||= %w(8.8.8.8 8.8.4.4)
|
20
|
+
|
19
21
|
|
20
22
|
@ui.logger.debug { "config(#{@config.inspect})" }
|
21
23
|
end
|
@@ -37,7 +39,21 @@ class TestLab
|
|
37
39
|
# @param [TestLab::Node] node The node which we want to deprovision.
|
38
40
|
# @return [Boolean] True if successful.
|
39
41
|
def on_node_deprovision(node)
|
40
|
-
|
42
|
+
@ui.logger.debug { "BIND Deprovisioner: Node #{node.id}" }
|
43
|
+
|
44
|
+
node.exec(%(sudo DEBIAN_FRONTEND="noninteractive" apt-get -y purge bind9))
|
45
|
+
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
# Bind: Container Up
|
50
|
+
#
|
51
|
+
# @param [TestLab::Node] node The container which just came online.
|
52
|
+
# @return [Boolean] True if successful.
|
53
|
+
def on_container_up(container)
|
54
|
+
@ui.logger.debug { "BIND Provisioner: Container #{container.id}" }
|
55
|
+
|
56
|
+
bind_reload(container.node)
|
41
57
|
|
42
58
|
true
|
43
59
|
end
|
@@ -53,13 +69,14 @@ class TestLab
|
|
53
69
|
|
54
70
|
true
|
55
71
|
end
|
72
|
+
alias :on_network_create :on_network_up
|
56
73
|
|
57
74
|
# Builds the main bind configuration sections
|
58
75
|
def build_bind_main_partial(file)
|
59
76
|
bind_conf_template = File.join(TestLab::Provisioner.template_dir, "bind", "bind.erb")
|
60
77
|
|
61
78
|
file.puts(ZTK::Template.do_not_edit_notice(:message => "TestLab v#{TestLab::VERSION} BIND Configuration", :char => '//'))
|
62
|
-
file.puts(ZTK::Template.render(bind_conf_template,
|
79
|
+
file.puts(ZTK::Template.render(bind_conf_template, @config))
|
63
80
|
end
|
64
81
|
|
65
82
|
def build_bind_records
|
@@ -82,7 +99,7 @@ class TestLab
|
|
82
99
|
end
|
83
100
|
|
84
101
|
# Builds the bind configuration sections for our zones
|
85
|
-
def build_bind_zone_partial(
|
102
|
+
def build_bind_zone_partial(node, file)
|
86
103
|
bind_zone_template = File.join(TestLab::Provisioner.template_dir, "bind", 'bind-zone.erb')
|
87
104
|
|
88
105
|
bind_records = build_bind_records
|
@@ -97,7 +114,7 @@ class TestLab
|
|
97
114
|
file.puts
|
98
115
|
file.puts(ZTK::Template.render(bind_zone_template, context))
|
99
116
|
|
100
|
-
build_bind_db(
|
117
|
+
build_bind_db(node, network.arpa, reverse_records[network.id])
|
101
118
|
end
|
102
119
|
|
103
120
|
TestLab::Container.domains.each do |domain|
|
@@ -108,40 +125,40 @@ class TestLab
|
|
108
125
|
file.puts
|
109
126
|
file.puts(ZTK::Template.render(bind_zone_template, context))
|
110
127
|
|
111
|
-
build_bind_db(
|
128
|
+
build_bind_db(node, domain, forward_records[domain])
|
112
129
|
end
|
113
130
|
end
|
114
131
|
|
115
|
-
def build_bind_db(
|
132
|
+
def build_bind_db(node, zone, records)
|
116
133
|
bind_db_template = File.join(TestLab::Provisioner.template_dir, "bind", 'bind-db.erb')
|
117
134
|
|
118
|
-
|
135
|
+
node.file(:target => %(/etc/bind/db.#{zone}), :chown => "bind:bind") do |file|
|
119
136
|
file.puts(ZTK::Template.do_not_edit_notice(:message => "TestLab v#{TestLab::VERSION} BIND DB: #{zone}", :char => ';'))
|
120
137
|
file.puts(ZTK::Template.render(bind_db_template, { :zone => zone, :records => records }))
|
121
138
|
end
|
122
139
|
end
|
123
140
|
|
124
141
|
# Builds the BIND configuration
|
125
|
-
def build_bind_conf(
|
126
|
-
|
142
|
+
def build_bind_conf(node)
|
143
|
+
node.file(:target => %(/etc/bind/named.conf), :chown => "bind:bind") do |file|
|
127
144
|
build_bind_main_partial(file)
|
128
|
-
build_bind_zone_partial(
|
145
|
+
build_bind_zone_partial(node, file)
|
129
146
|
end
|
130
147
|
end
|
131
148
|
|
132
|
-
def bind_install(
|
133
|
-
|
134
|
-
|
149
|
+
def bind_install(node)
|
150
|
+
node.exec(%(sudo DEBIAN_FRONTEND="noninteractive" apt-get -y install bind9))
|
151
|
+
node.exec(%(sudo rm -fv /etc/bind/{*.arpa,*.zone,*.conf*}))
|
135
152
|
end
|
136
153
|
|
137
154
|
def bind_reload(node)
|
138
|
-
node.
|
139
|
-
node.
|
155
|
+
node.exec(%(sudo chown -Rv bind:bind /etc/bind))
|
156
|
+
node.exec(%(sudo rndc reload))
|
140
157
|
end
|
141
158
|
|
142
159
|
def bind_provision(node)
|
143
|
-
bind_install(node
|
144
|
-
build_bind_conf(node
|
160
|
+
bind_install(node)
|
161
|
+
build_bind_conf(node)
|
145
162
|
bind_reload(node)
|
146
163
|
end
|
147
164
|
|
@@ -59,8 +59,8 @@ class TestLab
|
|
59
59
|
# @return [Boolean] True if successful.
|
60
60
|
def on_container_deprovision(container)
|
61
61
|
if @chef_server.state == :running
|
62
|
-
@chef_server.
|
63
|
-
@chef_server.
|
62
|
+
@chef_server.exec(%(knife node delete #{container.id} --yes), :ignore_exit_status => true)
|
63
|
+
@chef_server.exec(%(knife client delete #{container.id} --yes), :ignore_exit_status => true)
|
64
64
|
end
|
65
65
|
|
66
66
|
true
|
@@ -94,7 +94,7 @@ node_name #{@config[:chef][:client][:node_name].inspect}
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def validation_pem
|
97
|
-
@chef_server.
|
97
|
+
@chef_server.exec(%((cat ~/.chef/validation.pem || cat ~/.chef/chef-validator.pem) 2> /dev/null)).output.strip
|
98
98
|
end
|
99
99
|
|
100
100
|
end
|
@@ -60,8 +60,8 @@ class TestLab
|
|
60
60
|
# @return [Boolean] True if successful.
|
61
61
|
def on_container_deprovision(container)
|
62
62
|
if @chef_server.state == :running
|
63
|
-
@chef_server.
|
64
|
-
@chef_server.
|
63
|
+
@chef_server.exec(%(knife node delete #{container.id} --yes), :ignore_exit_status => true)
|
64
|
+
@chef_server.exec(%(knife client delete #{container.id} --yes), :ignore_exit_status => true)
|
65
65
|
end
|
66
66
|
|
67
67
|
true
|
@@ -95,7 +95,7 @@ node_name #{@config[:chef][:client][:node_name].inspect}
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def validation_pem
|
98
|
-
@chef_server.
|
98
|
+
@chef_server.exec(%((cat ~/.chef/validation.pem || cat ~/.chef/chef-validator.pem) 2> /dev/null)).output.strip
|
99
99
|
end
|
100
100
|
|
101
101
|
end
|
@@ -15,8 +15,12 @@ class TestLab
|
|
15
15
|
@ui = (ui || TestLab.ui)
|
16
16
|
|
17
17
|
@config[:resolv] ||= Hash.new
|
18
|
-
|
19
|
-
@config[:resolv][:
|
18
|
+
|
19
|
+
@config[:resolv][:servers] ||= Array.new
|
20
|
+
@config[:resolv][:servers].concat([TestLab::Network.ips])
|
21
|
+
|
22
|
+
@config[:resolv][:search] ||= Array.new
|
23
|
+
@config[:resolv][:search].concat([TestLab::Container.domains])
|
20
24
|
|
21
25
|
@ui.logger.debug { "config(#{@config.inspect})" }
|
22
26
|
end
|
@@ -28,7 +32,7 @@ class TestLab
|
|
28
32
|
def on_node_provision(node)
|
29
33
|
@ui.logger.debug { "RESOLV Provisioner: Node #{node.id}" }
|
30
34
|
|
31
|
-
@config[:resolv][:servers] =
|
35
|
+
@config[:resolv][:servers] = %w(127.0.0.1)
|
32
36
|
|
33
37
|
render_resolv_conf(node)
|
34
38
|
|
@@ -49,14 +53,18 @@ class TestLab
|
|
49
53
|
end
|
50
54
|
|
51
55
|
def render_resolv_conf(object)
|
52
|
-
|
53
|
-
|
54
|
-
object.ssh.file(:target => %(/etc/resolv.conf), :chown => "root:root") do |file|
|
56
|
+
object.file(:target => %(/etc/resolv.conf), :chown => "root:root") do |file|
|
55
57
|
file.puts(ZTK::Template.do_not_edit_notice(:message => "TestLab v#{TestLab::VERSION} RESOLVER Configuration"))
|
56
58
|
file.puts(ZTK::Template.render(resolv_conf_template, @config))
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
62
|
+
private
|
63
|
+
|
64
|
+
def resolv_conf_template
|
65
|
+
File.join(TestLab::Provisioner.template_dir, 'resolv', 'resolv.conf.erb')
|
66
|
+
end
|
67
|
+
|
60
68
|
end
|
61
69
|
|
62
70
|
end
|
@@ -9,6 +9,7 @@ class TestLab
|
|
9
9
|
#
|
10
10
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
11
11
|
class Route
|
12
|
+
include TestLab::Utility::Misc
|
12
13
|
|
13
14
|
def initialize(config={}, ui=nil)
|
14
15
|
@config = (config || Hash.new)
|
@@ -35,15 +36,17 @@ class TestLab
|
|
35
36
|
end
|
36
37
|
alias :on_network_down :on_network_deprovision
|
37
38
|
|
39
|
+
private
|
40
|
+
|
38
41
|
def manage_route(action, network)
|
39
42
|
command = ZTK::Command.new(:ui => @ui, :silence => true, :ignore_exit_status => true)
|
40
43
|
|
41
44
|
case RUBY_PLATFORM
|
42
45
|
when /darwin/ then
|
43
46
|
action = ((action == :del) ? :delete : :add)
|
44
|
-
command.exec(%(sudo route #{action} -net #{TestLab::Utility.network(network.address)} #{network.node.ip} #{TestLab::Utility.netmask(network.address)}))
|
47
|
+
command.exec(%(#{sudo} route #{action} -net #{TestLab::Utility.network(network.address)} #{network.node.ip} #{TestLab::Utility.netmask(network.address)}))
|
45
48
|
when /linux/ then
|
46
|
-
command.exec(%(sudo route #{action} -net #{TestLab::Utility.network(network.address)} netmask #{TestLab::Utility.netmask(network.address)} gw #{network.node.ip}))
|
49
|
+
command.exec(%(#{sudo} route #{action} -net #{TestLab::Utility.network(network.address)} netmask #{TestLab::Utility.netmask(network.address)} gw #{network.node.ip}))
|
47
50
|
end
|
48
51
|
end
|
49
52
|
|
@@ -12,5 +12,8 @@ apt-get -y install <%= @apt[:install].flatten.compact.join(' ') %>
|
|
12
12
|
<% if !@apt[:remove].nil? -%>
|
13
13
|
apt-get -y remove <%= @apt[:remove].flatten.compact.join(' ') %>
|
14
14
|
<% end -%>
|
15
|
+
<% if !@apt[:purge].nil? -%>
|
16
|
+
apt-get -y purge <%= @apt[:purge].flatten.compact.join(' ') %>
|
17
|
+
<% end -%>
|
15
18
|
|
16
19
|
touch /.testlab-apt-provision
|
@@ -10,11 +10,14 @@ options {
|
|
10
10
|
// Uncomment the following block, and insert the addresses replacing
|
11
11
|
// the all-0's placeholder.
|
12
12
|
|
13
|
+
<% if !@bind[:forwarders].nil? -%>
|
13
14
|
forwarders {
|
14
|
-
|
15
|
-
|
15
|
+
<% @bind[:forwarders].flatten.compact.uniq.each do |forwarder| -%>
|
16
|
+
<%= forwarder %>;
|
17
|
+
<% end -%>
|
16
18
|
};
|
17
19
|
|
20
|
+
<% end -%>
|
18
21
|
//========================================================================
|
19
22
|
// If BIND logs error messages about the root key being expired,
|
20
23
|
// you will need to update your keys. See https://www.isc.org/bind-keys
|
@@ -1,24 +1,27 @@
|
|
1
1
|
set -x
|
2
2
|
set -e
|
3
3
|
|
4
|
-
|
4
|
+
[[ -f /.testlab-raring-provision ]] && exit 0
|
5
5
|
|
6
|
-
|
7
|
-
# Update APT and ensure our required packages are installed
|
8
|
-
apt-get -y update
|
9
|
-
apt-get -y install lxc bridge-utils debootstrap yum iptables ntpdate ntp pbzip2
|
6
|
+
export DEBIAN_FRONTEND="noninteractive"
|
10
7
|
|
11
|
-
|
12
|
-
|
8
|
+
# Update APT and ensure our required packages are installed
|
9
|
+
apt-get -y update
|
10
|
+
apt-get -y install lxc bridge-utils debootstrap yum iptables iptables-persistent ntpdate ntp pbzip2
|
13
11
|
|
14
12
|
# Ensure the default lxc networking services are off
|
15
13
|
service lxc-net stop || (service lxc-net start ; service lxc-net stop)
|
14
|
+
echo "manual" | tee /etc/init/lxc-net.override
|
16
15
|
|
17
16
|
# Ensure NTP services are enabled and running
|
18
17
|
service ntp restart || service ntp start
|
19
18
|
|
20
|
-
# Enable
|
21
|
-
|
19
|
+
# Enable IPv4 forwarding
|
20
|
+
sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
|
21
|
+
sysctl -w net.ipv4.ip_forward=1
|
22
22
|
|
23
23
|
# Install an iptable NAT rule
|
24
|
-
|
24
|
+
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
25
|
+
iptables-save | tee /etc/iptables/rules.v4
|
26
|
+
|
27
|
+
touch /.testlab-raring-provision
|
@@ -2,8 +2,10 @@
|
|
2
2
|
domain <%= @resolv[:domain] %>
|
3
3
|
<% end -%>
|
4
4
|
<% if !@resolv[:search].nil? -%>
|
5
|
-
search <%= @resolv[:search] %>
|
5
|
+
search <%= @resolv[:search].flatten.compact.uniq.join(' ') %>
|
6
6
|
<% end -%>
|
7
|
-
<%
|
7
|
+
<% if !@resolv[:servers].nil? -%>
|
8
|
+
<% @resolv[:servers].flatten.compact.uniq.each do |server| -%>
|
8
9
|
nameserver <%= server %>
|
9
10
|
<% end -%>
|
11
|
+
<% end -%>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class TestLab
|
2
|
+
module Support
|
3
|
+
|
4
|
+
# Execution Support Module
|
5
|
+
#
|
6
|
+
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
7
|
+
module Execution
|
8
|
+
|
9
|
+
# Bootstrap
|
10
|
+
#
|
11
|
+
# Renders the supplied content into a file over the SSH connection and
|
12
|
+
# executes it as the 'root' user.
|
13
|
+
def bootstrap(content, options={})
|
14
|
+
ssh.bootstrap(content, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Execute
|
18
|
+
#
|
19
|
+
# Executes the supplied command over the SSH connection.
|
20
|
+
def exec(command, options={})
|
21
|
+
ssh.exec(command, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
# File
|
25
|
+
#
|
26
|
+
# Renders the supplied file over the SSH connection.
|
27
|
+
def file(options={}, &block)
|
28
|
+
ssh.file(options, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Uploads
|
32
|
+
#
|
33
|
+
# Uploads the supplied file over the SSH connection.
|
34
|
+
def upload(local, remote, options={})
|
35
|
+
ssh.upload(local, remote, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Download
|
39
|
+
def download(remote, local, options={})
|
40
|
+
ssh.download(remote, local, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|