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.
Files changed (44) hide show
  1. data/README.md +35 -32
  2. data/bin/tl +13 -640
  3. data/lib/commands/container.rb +292 -0
  4. data/lib/commands/network.rb +233 -0
  5. data/lib/commands/node.rb +182 -0
  6. data/lib/commands/testlab.rb +98 -0
  7. data/lib/testlab/container/actions.rb +15 -5
  8. data/lib/testlab/container/io.rb +69 -0
  9. data/lib/testlab/container/lifecycle.rb +6 -10
  10. data/lib/testlab/container/status.rb +1 -1
  11. data/lib/testlab/container.rb +2 -0
  12. data/lib/testlab/network/actions.rb +16 -0
  13. data/lib/testlab/network/lifecycle.rb +14 -20
  14. data/lib/testlab/network/status.rb +11 -5
  15. data/lib/testlab/network.rb +6 -6
  16. data/lib/testlab/node/actions.rb +16 -0
  17. data/lib/testlab/node/lifecycle.rb +15 -11
  18. data/lib/testlab/node/status.rb +1 -2
  19. data/lib/testlab/node.rb +1 -1
  20. data/lib/testlab/provisioner.rb +2 -1
  21. data/lib/testlab/provisioners/apt.rb +1 -1
  22. data/lib/testlab/provisioners/apt_cacher_ng.rb +2 -2
  23. data/lib/testlab/provisioners/bind.rb +1 -1
  24. data/lib/testlab/provisioners/chef_gem.rb +2 -2
  25. data/lib/testlab/provisioners/omnibus.rb +2 -2
  26. data/lib/testlab/provisioners/omnitruck.rb +2 -2
  27. data/lib/testlab/provisioners/raring.rb +1 -1
  28. data/lib/testlab/provisioners/resolv.rb +2 -2
  29. data/lib/testlab/provisioners/route.rb +51 -0
  30. data/lib/testlab/provisioners/shell.rb +1 -1
  31. data/lib/testlab/provisioners/templates/apt/bootstrap.erb +6 -1
  32. data/lib/testlab/provisioners/templates/apt_cacher_ng/bootstrap.erb +4 -1
  33. data/lib/testlab/provisioners/templates/raring/bootstrap.erb +9 -4
  34. data/lib/testlab/utility/logger.rb +87 -0
  35. data/lib/testlab/utility.rb +4 -2
  36. data/lib/testlab/version.rb +1 -1
  37. data/lib/testlab.rb +28 -0
  38. data/spec/container_spec.rb +18 -12
  39. data/spec/network_spec.rb +4 -0
  40. data/spec/node_spec.rb +6 -19
  41. data/spec/provisioners/shell_spec.rb +2 -2
  42. data/spec/support/Labfile +3 -3
  43. data/testlab.gemspec +2 -2
  44. metadata +13 -6
@@ -0,0 +1,292 @@
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
+ # CONTAINERS
22
+ #############
23
+ desc 'Manage containers'
24
+ arg_name 'Describe arguments to container here'
25
+ command :container do |c|
26
+
27
+ c.desc 'Container ID or Name'
28
+ c.arg_name 'container'
29
+ c.flag [:n, :name]
30
+
31
+ # CONTAINER CREATE
32
+ ###################
33
+ c.desc 'Create a container'
34
+ c.long_desc <<-EOF
35
+ Create a container. The container is created.
36
+ EOF
37
+ c.command :create do |create|
38
+ create.action do |global_options, options, args|
39
+ if options[:name].nil?
40
+ help_now!('a name is required') if options[:name].nil?
41
+ else
42
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
43
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you screateplied!"
44
+
45
+ container.create
46
+ end
47
+ end
48
+ end
49
+
50
+ # CONTAINER DESTROY
51
+ ####################
52
+ c.desc 'Destroy a container'
53
+ c.long_desc <<-EOF
54
+ Destroy a container. The container is stopped and destroyed.
55
+ EOF
56
+ c.command :destroy do |destroy|
57
+ destroy.action do |global_options, options, args|
58
+ if options[:name].nil?
59
+ help_now!('a name is required') if options[:name].nil?
60
+ else
61
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
62
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
63
+
64
+ container.destroy
65
+ end
66
+ end
67
+ end
68
+
69
+ # CONTAINER UP
70
+ ###############
71
+ c.desc 'Up a container'
72
+ c.long_desc <<-EOF
73
+ Up a container. The container is started and brought online.
74
+ EOF
75
+ c.command :up do |up|
76
+ up.action do |global_options, options, args|
77
+ if options[:name].nil?
78
+ help_now!('a name is required') if options[:name].nil?
79
+ else
80
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
81
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
82
+
83
+ container.up
84
+ end
85
+ end
86
+ end
87
+
88
+ # CONTAINER DOWN
89
+ #################
90
+ c.desc 'Down a container'
91
+ c.long_desc <<-EOF
92
+ Down a container. The container is stopped taking it offline.
93
+ EOF
94
+ c.command :down do |down|
95
+ down.action do |global_options, options, args|
96
+ if options[:name].nil?
97
+ help_now!('a name is required') if options[:name].nil?
98
+ else
99
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
100
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
101
+
102
+ container.down
103
+ end
104
+ end
105
+ end
106
+
107
+ # CONTAINER SETUP
108
+ ####################
109
+ c.desc 'Setup a container'
110
+ c.long_desc <<-EOF
111
+ Setup a container. The container is created, started and provisioned.
112
+ EOF
113
+ c.command :setup do |setup|
114
+ setup.action do |global_options, options, args|
115
+ if options[:name].nil?
116
+ help_now!('a name is required') if options[:name].nil?
117
+ else
118
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
119
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
120
+
121
+ container.setup
122
+ end
123
+ end
124
+ end
125
+
126
+ # CONTAINER TEARDOWN
127
+ ####################
128
+ c.desc 'Teardown a container'
129
+ c.long_desc <<-EOF
130
+ Teardown a container. The container is offlined and destroyed.
131
+ EOF
132
+ c.command :teardown do |teardown|
133
+ teardown.action do |global_options, options, args|
134
+ if options[:name].nil?
135
+ help_now!('a name is required') if options[:name].nil?
136
+ else
137
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
138
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
139
+
140
+ container.teardown
141
+ end
142
+ end
143
+ end
144
+
145
+ # CONTAINER STATUS
146
+ ###################
147
+ c.desc 'Display the status of container(s)'
148
+ c.long_desc <<-EOF
149
+ Displays the status of all containers or a single container if supplied via the ID parameter.
150
+ EOF
151
+ c.command :status do |status|
152
+ status.action do |global_options, options, args|
153
+ if options[:name].nil?
154
+ # No ID supplied; show everything
155
+ containers = @testlab.containers.delete_if{ |c| c.node.dead? }
156
+ if containers.count == 0
157
+ @testlab.ui.stderr.puts("You either have no containers defined or dead nodes!".yellow)
158
+ else
159
+ # ZTK::Report.new(:ui => @testlab.ui).spreadsheet(containers, TestLab::Container::STATUS_KEYS.reject{|k| k == :fqdn}) do |container|
160
+ ZTK::Report.new(:ui => @testlab.ui).list(containers, TestLab::Container::STATUS_KEYS) do |container|
161
+ # OpenStruct.new(container.status.reject{|k,v| k == :fqdn})
162
+ OpenStruct.new(container.status)
163
+ end
164
+ end
165
+ else
166
+ # ID supplied; show just that item
167
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
168
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
169
+
170
+ ZTK::Report.new(:ui => @testlab.ui).list(container, TestLab::Container::STATUS_KEYS) do |container|
171
+ OpenStruct.new(container.status)
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+ # CONTAINER SSH
178
+ ################
179
+ c.desc 'Open an SSH console to a container'
180
+ c.command :ssh do |ssh|
181
+
182
+ ssh.desc 'Specify an SSH Username to use'
183
+ ssh.arg_name 'username'
184
+ ssh.flag [:u, :user]
185
+
186
+ ssh.desc 'Specify an SSH Identity Key to use'
187
+ ssh.arg_name 'filename'
188
+ ssh.flag [:i, :identity]
189
+
190
+ ssh.action do |global_options, options, args|
191
+ help_now!('a name is required') if options[:name].nil?
192
+
193
+ container = @testlab.containers.select{ |n| n.id.to_sym == options[:name].to_sym }.first
194
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
195
+
196
+ ssh_options = Hash.new
197
+ ssh_options[:user] = options[:user]
198
+ ssh_options[:keys] = options[:identity]
199
+
200
+ container.ssh(ssh_options).console
201
+ end
202
+ end
203
+
204
+ # CONTAINER RECYCLE
205
+ ####################
206
+ c.desc 'Recycles a container'
207
+ c.long_desc <<-EOF
208
+ Recycles a container. The container is taken through a series of state changes to ensure it is pristine.
209
+
210
+ The containers is cycled in this order:
211
+
212
+ Teardown -> Down -> Destroy -> Create -> Up -> Setup
213
+ EOF
214
+ c.command :recycle do |recycle|
215
+ recycle.action do |global_options, options, args|
216
+ if options[:name].nil?
217
+ help_now!('a name is required') if options[:name].nil?
218
+ else
219
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
220
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
221
+
222
+ container.teardown
223
+ container.down
224
+ container.destroy
225
+
226
+ container.create
227
+ container.up
228
+ container.setup
229
+ end
230
+ end
231
+ end
232
+
233
+ # CONTAINER CLONE
234
+ ##################
235
+ c.desc 'Clone a container'
236
+ c.long_desc <<-EOF
237
+ Clone a container. The container is offlined and an ephemeral copy of it is started.
238
+ EOF
239
+ c.command :clone do |clone|
240
+ clone.action do |global_options, options, args|
241
+ if options[:name].nil?
242
+ help_now!('a name is required') if options[:name].nil?
243
+ else
244
+ container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first
245
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
246
+
247
+ container.clone
248
+ end
249
+ end
250
+ end
251
+
252
+ # CONTAINER EXPORT
253
+ ###################
254
+ c.desc 'Export a container to a shipping container (file)'
255
+ c.command :export do |export|
256
+
257
+ export.desc 'Specify the level of bzip2 compression to use (1-9)'
258
+ export.default_value 9
259
+ export.arg_name 'level'
260
+ export.flag [:c, :compression]
261
+
262
+ export.action do |global_options, options, args|
263
+ help_now!('a name is required') if options[:name].nil?
264
+
265
+ container = @testlab.containers.select{ |n| n.id.to_sym == options[:name].to_sym }.first
266
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
267
+
268
+ container.export(options[:compression])
269
+ end
270
+ end
271
+
272
+ # CONTAINER IMPORT
273
+ ###################
274
+ c.desc 'Import a shipping container (file)'
275
+ c.command :import do |import|
276
+
277
+ import.desc 'Specify the shipping container file to import.'
278
+ import.arg_name 'filename'
279
+ import.flag [:sc]
280
+
281
+ import.action do |global_options, options, args|
282
+ help_now!('a name is required') if options[:name].nil?
283
+ help_now!('a filename is required') if options[:sc].nil?
284
+
285
+ container = @testlab.containers.select{ |n| n.id.to_sym == options[:name].to_sym }.first
286
+ container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!"
287
+
288
+ container.import(options[:sc])
289
+ end
290
+ end
291
+
292
+ end
@@ -0,0 +1,233 @@
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
+ # NETWORKS
22
+ ###########
23
+ desc 'Manage networks'
24
+ arg_name 'Describe arguments to network here'
25
+ command :network do |c|
26
+
27
+ c.desc 'Network ID or Name'
28
+ c.arg_name 'network'
29
+ c.flag [:n, :name]
30
+
31
+ # NETWORK CREATE
32
+ #################
33
+ c.desc 'Create a network'
34
+ c.long_desc <<-EOF
35
+ Create a network. The network is created.
36
+ EOF
37
+ c.command :create do |create|
38
+ create.action do |global_options, options, args|
39
+ if options[:name].nil?
40
+ help_now!('a name is required') if options[:name].nil?
41
+ else
42
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
43
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you screateplied!"
44
+
45
+ network.create
46
+ end
47
+ end
48
+ end
49
+
50
+ # NETWORK DESTROY
51
+ #################
52
+ c.desc 'Destroy a network'
53
+ c.long_desc <<-EOF
54
+ Destroy a network. The network is destroyed.
55
+ EOF
56
+ c.command :destroy do |destroy|
57
+ destroy.action do |global_options, options, args|
58
+ if options[:name].nil?
59
+ help_now!('a name is required') if options[:name].nil?
60
+ else
61
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
62
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
63
+
64
+ network.destroy
65
+ end
66
+ end
67
+ end
68
+
69
+ # NETWORK UP
70
+ #############
71
+ c.desc 'Up a network'
72
+ c.long_desc <<-EOF
73
+ Up a network. The network is started and brought online.
74
+ EOF
75
+ c.command :up do |up|
76
+ up.action do |global_options, options, args|
77
+ if options[:name].nil?
78
+ help_now!('a name is required') if options[:name].nil?
79
+ else
80
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
81
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
82
+
83
+ network.up
84
+ end
85
+ end
86
+ end
87
+
88
+ # NETWORK DOWN
89
+ ###############
90
+ c.desc 'Down a network'
91
+ c.long_desc <<-EOF
92
+ Down a network. The network is stopped taking it offline.
93
+ EOF
94
+ c.command :down do |down|
95
+ down.action do |global_options, options, args|
96
+ if options[:name].nil?
97
+ help_now!('a name is required') if options[:name].nil?
98
+ else
99
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
100
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
101
+
102
+ network.down
103
+ end
104
+ end
105
+ end
106
+
107
+ # NETWORK SETUP
108
+ ################
109
+ c.desc 'Setup a network'
110
+ c.long_desc <<-EOF
111
+ Setup a network. The network is created, started and provisioned.
112
+ EOF
113
+ c.command :setup do |setup|
114
+ setup.action do |global_options, options, args|
115
+ if options[:name].nil?
116
+ help_now!('a name is required') if options[:name].nil?
117
+ else
118
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
119
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
120
+
121
+ network.setup
122
+ end
123
+ end
124
+ end
125
+
126
+ # NETWORK TEARDOWN
127
+ ###################
128
+ c.desc 'Teardown a network'
129
+ c.long_desc <<-EOF
130
+ Teardown a network. The network is offlined and destroyed.
131
+ EOF
132
+ c.command :teardown do |teardown|
133
+ teardown.action do |global_options, options, args|
134
+ if options[:name].nil?
135
+ help_now!('a name is required') if options[:name].nil?
136
+ else
137
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
138
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
139
+
140
+ network.teardown
141
+ end
142
+ end
143
+ end
144
+
145
+ # NETWORK STATUS
146
+ #################
147
+ c.desc 'Display the status of network(s)'
148
+ c.long_desc <<-EOF
149
+ Displays the status of all networks or a single network if supplied via the ID parameter.
150
+ EOF
151
+ c.command :status do |status|
152
+ status.action do |global_options, options, args|
153
+ if options[:name].nil?
154
+ # No ID supplied; show everything
155
+ networks = @testlab.networks.delete_if{|n| n.node.dead? }
156
+ if networks.count == 0
157
+ @testlab.ui.stderr.puts("You either have no networks defined or dead nodes!".yellow)
158
+ else
159
+ ZTK::Report.new(:ui => @testlab.ui).list(networks, TestLab::Network::STATUS_KEYS) do |network|
160
+ OpenStruct.new(network.status)
161
+ end
162
+ end
163
+ else
164
+ # ID supplied; show just that item
165
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
166
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
167
+
168
+ ZTK::Report.new(:ui => @testlab.ui).list(network, TestLab::Network::STATUS_KEYS) do |network|
169
+ OpenStruct.new(network.status)
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ # ROUTES
176
+ #########
177
+ c.desc 'Manage routes'
178
+ c.command :route do |route|
179
+
180
+ # ROUTE ADD
181
+ ############
182
+ route.desc 'Add routes to lab networks'
183
+ route.command :add do |add|
184
+ add.action do |global_options,options,args|
185
+ help_now!('a name is required') if options[:name].nil?
186
+
187
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
188
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
189
+
190
+ network.manage_route(:add)
191
+ @testlab.ui.stdout.puts("Added routes successfully!".green.bold)
192
+ @testlab.ui.stdout.puts %x(netstat -nr | grep '#{network.node.ip}').strip
193
+ end
194
+ end
195
+
196
+ # ROUTE DEL
197
+ ############
198
+ route.desc 'Delete routes to lab networks'
199
+ route.command :del do |del|
200
+ del.action do |global_options,options,args|
201
+ help_now!('a name is required') if options[:name].nil?
202
+
203
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
204
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
205
+
206
+ network.manage_route(:del)
207
+ @testlab.ui.stdout.puts("Deleted routes successfully!".red.bold)
208
+ @testlab.ui.stdout.puts %x(netstat -nr | grep '#{network.node.ip}').strip
209
+ end
210
+ end
211
+
212
+ # ROUTE SHOW
213
+ #############
214
+ route.desc 'Show routes to lab networks'
215
+ route.command :show do |show|
216
+ show.action do |global_options,options,args|
217
+ help_now!('a name is required') if options[:name].nil?
218
+
219
+ network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
220
+ network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
221
+
222
+ @testlab.ui.stdout.puts("TestLab routes:".green.bold)
223
+ case RUBY_PLATFORM
224
+ when /darwin/ then
225
+ @testlab.ui.stdout.puts %x(netstat -nrf inet | grep '#{network.node.ip}').strip
226
+ when /linux/ then
227
+ @testlab.ui.stdout.puts %x(netstat -nr | grep '#{network.node.ip}').strip
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ end
@@ -0,0 +1,182 @@
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
+ # NODES
22
+ ########
23
+ desc 'Manage nodes'
24
+ arg_name 'Describe arguments to node here'
25
+ command :node do |c|
26
+
27
+ c.desc 'Node ID or Name'
28
+ c.arg_name 'node'
29
+ c.flag [:n, :name]
30
+
31
+ # NODE CREATE
32
+ ##############
33
+ c.desc 'Create a node'
34
+ c.long_desc <<-EOF
35
+ Create a node. The node is created.
36
+ EOF
37
+ c.command :create do |create|
38
+ create.action do |global_options, options, args|
39
+ if options[:name].nil?
40
+ help_now!('a name is required') if options[:name].nil?
41
+ else
42
+ node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first
43
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you screateplied!"
44
+
45
+ node.create
46
+ end
47
+ end
48
+ end
49
+
50
+ # NODE DESTROY
51
+ ############
52
+ c.desc 'Destroy a node'
53
+ c.long_desc <<-EOF
54
+ Destroy a node. The node is stopped and destroyed.
55
+ EOF
56
+ c.command :destroy do |destroy|
57
+ destroy.action do |global_options, options, args|
58
+ if options[:name].nil?
59
+ help_now!('a name is required') if options[:name].nil?
60
+ else
61
+ node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first
62
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
63
+
64
+ node.destroy
65
+ end
66
+ end
67
+ end
68
+
69
+ # NODE UP
70
+ ##########
71
+ c.desc 'Up a node'
72
+ c.long_desc <<-EOF
73
+ Up a node. The node is started and brought online.
74
+ EOF
75
+ c.command :up do |up|
76
+ up.action do |global_options, options, args|
77
+ if options[:name].nil?
78
+ help_now!('a name is required') if options[:name].nil?
79
+ else
80
+ node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first
81
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
82
+
83
+ node.up
84
+ end
85
+ end
86
+ end
87
+
88
+ # NODE DOWN
89
+ ############
90
+ c.desc 'Down a node'
91
+ c.long_desc <<-EOF
92
+ Down a node. The node is stopped taking it offline.
93
+ EOF
94
+ c.command :down do |down|
95
+ down.action do |global_options, options, args|
96
+ if options[:name].nil?
97
+ help_now!('a name is required') if options[:name].nil?
98
+ else
99
+ node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first
100
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
101
+
102
+ node.down
103
+ end
104
+ end
105
+ end
106
+
107
+ # NODE SETUP
108
+ #############
109
+ c.desc 'Setup a node'
110
+ c.long_desc <<-EOF
111
+ Setup a node. The node is created, started and provisioned.
112
+ EOF
113
+ c.command :setup do |setup|
114
+ setup.action do |global_options, options, args|
115
+ if options[:name].nil?
116
+ help_now!('a name is required') if options[:name].nil?
117
+ else
118
+ node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first
119
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
120
+
121
+ node.setup
122
+ end
123
+ end
124
+ end
125
+
126
+ # NODE TEARDOWN
127
+ ################
128
+ c.desc 'Teardown a node'
129
+ c.long_desc <<-EOF
130
+ Teardown a node. The node is offlined and destroyed.
131
+ EOF
132
+ c.command :teardown do |teardown|
133
+ teardown.action do |global_options, options, args|
134
+ if options[:name].nil?
135
+ help_now!('a name is required') if options[:name].nil?
136
+ else
137
+ node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first
138
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
139
+
140
+ node.teardown
141
+ end
142
+ end
143
+ end
144
+
145
+ # NODE STATUS
146
+ ##############
147
+ c.desc 'Display the status of node(s)'
148
+ c.long_desc 'Displays the status of all nodes or a single node if supplied via the ID parameter.'
149
+ c.command :status do |status|
150
+ status.action do |global_options, options, args|
151
+ if options[:name].nil?
152
+ # No ID supplied; show everything
153
+ ZTK::Report.new(:ui => @testlab.ui).list(@testlab.nodes, TestLab::Node::STATUS_KEYS) do |node|
154
+ OpenStruct.new(node.status)
155
+ end
156
+ else
157
+ # ID supplied; show just that item
158
+ node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first
159
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
160
+
161
+ ZTK::Report.new(:ui => @testlab.ui).list(node, TestLab::Node::STATUS_KEYS) do |node|
162
+ OpenStruct.new(node.status)
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ # NODE SSH
169
+ ###########
170
+ c.desc 'Open an SSH console to a node'
171
+ c.command :ssh do |ssh|
172
+ ssh.action do |global_options,options,args|
173
+ help_now!('a name is required') if options[:name].nil?
174
+
175
+ node = @testlab.nodes.select{ |n| n.id.to_sym == options[:name].to_sym }.first
176
+ node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
177
+
178
+ node.ssh.console
179
+ end
180
+ end
181
+
182
+ end