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.
Files changed (41) hide show
  1. data/README.md +1 -1
  2. data/bin/tl +5 -3
  3. data/features/support/Labfile.local +2 -8
  4. data/features/support/Labfile.vagrant +2 -5
  5. data/lib/testlab/container/actions.rb +1 -41
  6. data/lib/testlab/container/clone.rb +87 -0
  7. data/lib/testlab/container/configuration.rb +67 -0
  8. data/lib/testlab/container/io.rb +8 -8
  9. data/lib/testlab/container/lifecycle.rb +0 -40
  10. data/lib/testlab/container/lxc.rb +0 -143
  11. data/lib/testlab/container/provision.rb +49 -0
  12. data/lib/testlab/container/support.rb +47 -0
  13. data/lib/testlab/container.rb +10 -0
  14. data/lib/testlab/network/actions.rb +4 -4
  15. data/lib/testlab/network/lifecycle.rb +0 -28
  16. data/lib/testlab/network/provision.rb +37 -0
  17. data/lib/testlab/network/status.rb +2 -2
  18. data/lib/testlab/network.rb +2 -0
  19. data/lib/testlab/node/lifecycle.rb +0 -26
  20. data/lib/testlab/node/lxc.rb +1 -13
  21. data/lib/testlab/node/provision.rb +34 -0
  22. data/lib/testlab/node.rb +4 -0
  23. data/lib/testlab/provisioners/apt.rb +1 -0
  24. data/lib/testlab/provisioners/apt_cacher_ng.rb +5 -5
  25. data/lib/testlab/provisioners/bind.rb +35 -18
  26. data/lib/testlab/provisioners/chef/omni_bus.rb +3 -3
  27. data/lib/testlab/provisioners/chef/ruby_gem_client.rb +3 -3
  28. data/lib/testlab/provisioners/resolv.rb +14 -6
  29. data/lib/testlab/provisioners/route.rb +5 -2
  30. data/lib/testlab/provisioners/templates/apt/provision.erb +3 -0
  31. data/lib/testlab/provisioners/templates/bind/bind.erb +5 -2
  32. data/lib/testlab/provisioners/templates/raring/provision.erb +13 -10
  33. data/lib/testlab/provisioners/templates/resolv/resolv.conf.erb +4 -2
  34. data/lib/testlab/support/execution.rb +46 -0
  35. data/lib/testlab/support.rb +17 -0
  36. data/lib/testlab/user/lifecycle.rb +6 -6
  37. data/lib/testlab/utility/gli.rb +3 -3
  38. data/lib/testlab/utility/misc.rb +8 -0
  39. data/lib/testlab/version.rb +1 -1
  40. data/lib/testlab.rb +1 -0
  41. 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.ssh.bootstrap(<<-EOF, :ignore_exit_status => true)
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.ssh.bootstrap(<<-EOF, :ignore_exit_status => true)
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.ssh.bootstrap(<<-EOF, :ignore_exit_status => true)
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.ssh.bootstrap(<<-EOF, :ignore_exit_status => true)
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.ssh.exec(%(sudo brctl show #{self.bridge} 2>&1 | grep -i 'No such device'), :ignore_exit_status => true).exit_code
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.ssh.exec(%(sudo ifconfig #{self.bridge} 2>&1 | grep 'MTU'), :ignore_exit_status => true).output.strip
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
@@ -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
@@ -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.ssh.exec(%(uname -m)).output.strip
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
@@ -17,6 +17,7 @@ class TestLab
17
17
  @config[:apt] ||= Hash.new
18
18
  @config[:apt][:install] ||= Array.new
19
19
  @config[:apt][:remove] ||= Array.new
20
+ @config[:apt][:purge] ||= Array.new
20
21
 
21
22
  @ui.logger.debug { "config(#{@config.inspect})" }
22
23
  end
@@ -39,15 +39,15 @@ class TestLab
39
39
  }
40
40
  }
41
41
 
42
- node.ssh.file(:target => apt_conf_d_proxy_file, :chown => "root:root", :chmod => "0644") do |file|
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.ssh.file(:target => apt_cacher_ng_security_conf_file, :chown => "root:root", :chmod => "0644") do |file|
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.ssh.exec(%(sudo service apt-cacher-ng restart))
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.ssh.file(:target => apt_conf_d_proxy_file, :chown => "root:root", :chmod => "0644") do |file|
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.ssh.exec(%(sudo sed -i 's/127.0.0.1:3142\\///g' /etc/apt/sources.list))
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] ||= "default.zone"
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
- node.ssh.exec(%(DEBIAN_FRONTEND="noninteractive" sudo apt-get -y purge bind9))
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(ssh, file)
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(ssh, network.arpa, reverse_records[network.id])
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(ssh, domain, forward_records[domain])
128
+ build_bind_db(node, domain, forward_records[domain])
112
129
  end
113
130
  end
114
131
 
115
- def build_bind_db(ssh, zone, records)
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
- ssh.file(:target => %(/etc/bind/db.#{zone}), :chown => "bind:bind") do |file|
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(ssh)
126
- ssh.file(:target => %(/etc/bind/named.conf), :chown => "bind:bind") do |file|
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(ssh, file)
145
+ build_bind_zone_partial(node, file)
129
146
  end
130
147
  end
131
148
 
132
- def bind_install(ssh)
133
- ssh.exec(%(DEBIAN_FRONTEND="noninteractive" sudo apt-get -y install bind9))
134
- ssh.exec(%(sudo rm -fv /etc/bind/{*.arpa,*.zone,*.conf*}))
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.ssh.exec(%(sudo chown -Rv bind:bind /etc/bind))
139
- node.ssh.exec(%(sudo rndc reload))
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.ssh)
144
- build_bind_conf(node.ssh)
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.ssh.exec(%(knife node delete #{container.id} --yes), :ignore_exit_status => true)
63
- @chef_server.ssh.exec(%(knife client delete #{container.id} --yes), :ignore_exit_status => true)
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.ssh.exec(%((cat ~/.chef/validation.pem || cat ~/.chef/chef-validator.pem) 2> /dev/null)).output.strip
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.ssh.exec(%(knife node delete #{container.id} --yes), :ignore_exit_status => true)
64
- @chef_server.ssh.exec(%(knife client delete #{container.id} --yes), :ignore_exit_status => true)
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.ssh.exec(%((cat ~/.chef/validation.pem || cat ~/.chef/chef-validator.pem) 2> /dev/null)).output.strip
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
- @config[:resolv][:servers] ||= [TestLab::Network.ips, '8.8.8.8', '8.8.4.4'].flatten.compact.uniq
19
- @config[:resolv][:search] ||= TestLab::Container.domains.join(' ')
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] = ['127.0.0.1', '8.8.8.8', '8.8.4.4']
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
- resolv_conf_template = File.join(TestLab::Provisioner.template_dir, "resolv", "resolv.conf.erb")
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
- 8.8.8.8;
15
- 8.8.4.4;
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
- export DEBIAN_FRONTEND="noninteractive"
4
+ [[ -f /.testlab-raring-provision ]] && exit 0
5
5
 
6
- if [ ! -f /.testlab-raring-provision ]; then
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
- touch /.testlab-raring-provision
12
- fi
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 ipv4 forwarding
21
- (sysctl net.ipv4.ip_forward | grep "net.ipv4.ip_forward = 1") || sysctl -w net.ipv4.ip_forward=1
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
- (iptables -t nat --list -v | grep "MASQUERADE all -- any eth0 anywhere anywhere") || iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
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
- <% @resolv[:servers].each do |server| -%>
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