testlab 0.6.5 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +35 -32
- data/bin/tl +13 -640
- data/lib/commands/container.rb +292 -0
- data/lib/commands/network.rb +233 -0
- data/lib/commands/node.rb +182 -0
- data/lib/commands/testlab.rb +98 -0
- data/lib/testlab/container/actions.rb +15 -5
- data/lib/testlab/container/io.rb +69 -0
- data/lib/testlab/container/lifecycle.rb +6 -10
- data/lib/testlab/container/status.rb +1 -1
- data/lib/testlab/container.rb +2 -0
- data/lib/testlab/network/actions.rb +16 -0
- data/lib/testlab/network/lifecycle.rb +14 -20
- data/lib/testlab/network/status.rb +11 -5
- data/lib/testlab/network.rb +6 -6
- data/lib/testlab/node/actions.rb +16 -0
- data/lib/testlab/node/lifecycle.rb +15 -11
- data/lib/testlab/node/status.rb +1 -2
- data/lib/testlab/node.rb +1 -1
- data/lib/testlab/provisioner.rb +2 -1
- data/lib/testlab/provisioners/apt.rb +1 -1
- data/lib/testlab/provisioners/apt_cacher_ng.rb +2 -2
- data/lib/testlab/provisioners/bind.rb +1 -1
- data/lib/testlab/provisioners/chef_gem.rb +2 -2
- data/lib/testlab/provisioners/omnibus.rb +2 -2
- data/lib/testlab/provisioners/omnitruck.rb +2 -2
- data/lib/testlab/provisioners/raring.rb +1 -1
- data/lib/testlab/provisioners/resolv.rb +2 -2
- data/lib/testlab/provisioners/route.rb +51 -0
- data/lib/testlab/provisioners/shell.rb +1 -1
- data/lib/testlab/provisioners/templates/apt/bootstrap.erb +6 -1
- data/lib/testlab/provisioners/templates/apt_cacher_ng/bootstrap.erb +4 -1
- data/lib/testlab/provisioners/templates/raring/bootstrap.erb +9 -4
- data/lib/testlab/utility/logger.rb +87 -0
- data/lib/testlab/utility.rb +4 -2
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +28 -0
- data/spec/container_spec.rb +18 -12
- data/spec/network_spec.rb +4 -0
- data/spec/node_spec.rb +6 -19
- data/spec/provisioners/shell_spec.rb +2 -2
- data/spec/support/Labfile +3 -3
- data/testlab.gemspec +2 -2
- metadata +13 -6
@@ -0,0 +1,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
|