testlab 0.6.5 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
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