mu 5.7.2.3
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/Mu_Gem.html +1591 -0
- data/bin/mu +11 -0
- data/lib/mu.rb +65 -0
- data/lib/mu/api/ddt.rb +233 -0
- data/lib/mu/api/homepage.rb +54 -0
- data/lib/mu/api/muapi.rb +231 -0
- data/lib/mu/api/netconfig.rb +233 -0
- data/lib/mu/api/scale.rb +199 -0
- data/lib/mu/api/system.rb +40 -0
- data/lib/mu/client.rb +31 -0
- data/lib/mu/command.rb +28 -0
- data/lib/mu/command/api.rb +95 -0
- data/lib/mu/command/cmd_appid.rb +486 -0
- data/lib/mu/command/cmd_cli.rb +151 -0
- data/lib/mu/command/cmd_ddt.rb +449 -0
- data/lib/mu/command/cmd_homepage.rb +146 -0
- data/lib/mu/command/cmd_muapi.rb +361 -0
- data/lib/mu/command/cmd_netconfig.rb +262 -0
- data/lib/mu/command/cmd_runscale.rb +533 -0
- data/lib/mu/command/cmd_runscenario.rb +258 -0
- data/lib/mu/command/cmd_runverify.rb +336 -0
- data/lib/mu/command/cmd_scale.rb +333 -0
- data/lib/mu/command/cmd_system.rb +127 -0
- data/lib/mu/command/curl.rb +246 -0
- data/lib/mu/command/help.rb +29 -0
- data/lib/mu/curl/error.rb +54 -0
- data/lib/mu/curl/verify.rb +137 -0
- data/lib/mu/helper.rb +55 -0
- data/lib/mu/http_helper.rb +232 -0
- data/rdoc/classes/Mu.html +305 -0
- data/rdoc/classes/Mu/Client.html +265 -0
- data/rdoc/classes/Mu/Command.html +208 -0
- data/rdoc/classes/Mu/Command/API.html +524 -0
- data/rdoc/classes/Mu/Command/Cmd_appid.html +934 -0
- data/rdoc/classes/Mu/Command/Cmd_cli.html +515 -0
- data/rdoc/classes/Mu/Command/Cmd_ddt.html +1169 -0
- data/rdoc/classes/Mu/Command/Cmd_homepage.html +489 -0
- data/rdoc/classes/Mu/Command/Cmd_muapi.html +968 -0
- data/rdoc/classes/Mu/Command/Cmd_netconfig.html +743 -0
- data/rdoc/classes/Mu/Command/Cmd_runscale.html +970 -0
- data/rdoc/classes/Mu/Command/Cmd_runscenario.html +530 -0
- data/rdoc/classes/Mu/Command/Cmd_runverify.html +621 -0
- data/rdoc/classes/Mu/Command/Cmd_scale.html +939 -0
- data/rdoc/classes/Mu/Command/Cmd_system.html +426 -0
- data/rdoc/classes/Mu/Command/Curl.html +524 -0
- data/rdoc/classes/Mu/Command/Help.html +166 -0
- data/rdoc/classes/Mu/Curl.html +116 -0
- data/rdoc/classes/Mu/Curl/Error.html +157 -0
- data/rdoc/classes/Mu/Curl/Error/Authorize.html +178 -0
- data/rdoc/classes/Mu/Curl/Error/Connect.html +149 -0
- data/rdoc/classes/Mu/Curl/Error/DNS.html +113 -0
- data/rdoc/classes/Mu/Curl/Error/Region.html +160 -0
- data/rdoc/classes/Mu/Curl/Error/Status.html +149 -0
- data/rdoc/classes/Mu/Curl/Error/Timeout.html +149 -0
- data/rdoc/classes/Mu/Curl/Verify.html +282 -0
- data/rdoc/classes/Mu/Curl/Verify/Request.html +227 -0
- data/rdoc/classes/Mu/Curl/Verify/Response.html +187 -0
- data/rdoc/classes/Mu/Curl/Verify/Result.html +188 -0
- data/rdoc/classes/Mu/Ddt.html +914 -0
- data/rdoc/classes/Mu/Helper.html +308 -0
- data/rdoc/classes/Mu/Homepage.html +377 -0
- data/rdoc/classes/Mu/HttpHelper.html +639 -0
- data/rdoc/classes/Mu/Muapi.html +816 -0
- data/rdoc/classes/Mu/Netconfig.html +781 -0
- data/rdoc/classes/Mu/Scale.html +832 -0
- data/rdoc/classes/Mu/System.html +281 -0
- data/rdoc/classes/Object.html +148 -0
- data/rdoc/classes/TCTestMu.html +1793 -0
- data/rdoc/classes/Test.html +107 -0
- data/rdoc/classes/Test/Unit.html +107 -0
- data/rdoc/classes/Test/Unit/TestCase.html +113 -0
- data/rdoc/created.rid +1 -0
- data/rdoc/files/lib/mu/api/ddt_rb.html +101 -0
- data/rdoc/files/lib/mu/api/homepage_rb.html +101 -0
- data/rdoc/files/lib/mu/api/muapi_rb.html +101 -0
- data/rdoc/files/lib/mu/api/netconfig_rb.html +101 -0
- data/rdoc/files/lib/mu/api/scale_rb.html +101 -0
- data/rdoc/files/lib/mu/api/system_rb.html +101 -0
- data/rdoc/files/lib/mu/client_rb.html +101 -0
- data/rdoc/files/lib/mu/command/api_rb.html +101 -0
- data/rdoc/files/lib/mu/command/cmd_appid_rb.html +119 -0
- data/rdoc/files/lib/mu/command/cmd_cli_rb.html +108 -0
- data/rdoc/files/lib/mu/command/cmd_ddt_rb.html +117 -0
- data/rdoc/files/lib/mu/command/cmd_homepage_rb.html +115 -0
- data/rdoc/files/lib/mu/command/cmd_muapi_rb.html +116 -0
- data/rdoc/files/lib/mu/command/cmd_netconfig_rb.html +116 -0
- data/rdoc/files/lib/mu/command/cmd_runscale_rb.html +119 -0
- data/rdoc/files/lib/mu/command/cmd_runscenario_rb.html +115 -0
- data/rdoc/files/lib/mu/command/cmd_runverify_rb.html +117 -0
- data/rdoc/files/lib/mu/command/cmd_scale_rb.html +115 -0
- data/rdoc/files/lib/mu/command/cmd_system_rb.html +116 -0
- data/rdoc/files/lib/mu/command/curl_rb.html +101 -0
- data/rdoc/files/lib/mu/command/help_rb.html +101 -0
- data/rdoc/files/lib/mu/command_rb.html +107 -0
- data/rdoc/files/lib/mu/curl/error_rb.html +101 -0
- data/rdoc/files/lib/mu/curl/verify_rb.html +101 -0
- data/rdoc/files/lib/mu/helper_rb.html +101 -0
- data/rdoc/files/lib/mu/http_helper_rb.html +101 -0
- data/rdoc/files/lib/mu_rb.html +121 -0
- data/rdoc/files/test/helper_rb.html +112 -0
- data/rdoc/files/test/tc_test_mu_rb.html +111 -0
- data/rdoc/fr_class_index.html +68 -0
- data/rdoc/fr_file_index.html +55 -0
- data/rdoc/fr_method_index.html +374 -0
- data/rdoc/index.html +24 -0
- data/rdoc/rdoc-style.css +208 -0
- data/test/data/app_id_stats.csv +1 -0
- data/test/data/data_cgi.msl +94 -0
- data/test/data/data_cgi.xml +322 -0
- data/test/data/default_test.csv +3 -0
- data/test/data/ftp_with_channel.xml +1643 -0
- data/test/data/irc.xml +3837 -0
- data/test/data/scale_configuration.json +25 -0
- data/test/data/test_data_cgi_error.xml +35 -0
- data/test/helper.rb +18 -0
- data/test/tc_test_mu.rb +716 -0
- metadata +322 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Verifies a Mu Studio scenario xml template
|
|
2
|
+
require 'mu/api/ddt'
|
|
3
|
+
class Mu
|
|
4
|
+
class Command
|
|
5
|
+
class Cmd_runscenario < Command
|
|
6
|
+
|
|
7
|
+
attr_accessor :host, :username, :password, :ddt_api, :errors
|
|
8
|
+
|
|
9
|
+
# displays command-line help
|
|
10
|
+
# * argv = command-line arguments
|
|
11
|
+
def cmd_help argv
|
|
12
|
+
help
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# verifies a Mu Studio scenario
|
|
16
|
+
# * argv = command-line arguments, requires a scenario (-s) argument, which must be an xml scenario template to be loaded onto the Mu
|
|
17
|
+
def cmd_run argv
|
|
18
|
+
args = parse_cli argv
|
|
19
|
+
setup
|
|
20
|
+
|
|
21
|
+
if not args['scenario']
|
|
22
|
+
msg "scenario required"
|
|
23
|
+
return help
|
|
24
|
+
else
|
|
25
|
+
if args['scenario'].include?(".xml")
|
|
26
|
+
scenario = args['scenario']
|
|
27
|
+
else # TODO: eventually, msl files may be supported by this api
|
|
28
|
+
msg "only .xml files are currently supported"
|
|
29
|
+
return help
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if not args['dir']
|
|
34
|
+
dir = "."
|
|
35
|
+
else
|
|
36
|
+
dir = args['dir']
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if scenario.include?("/")
|
|
40
|
+
filename = scenario
|
|
41
|
+
else
|
|
42
|
+
filename = dir + "/" + scenario
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if not args['interfaces']
|
|
46
|
+
@interfaces = Array.new
|
|
47
|
+
else
|
|
48
|
+
@interfaces = args['interfaces'].split(",")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@errors = Array.new
|
|
52
|
+
hosts_array = Array.new
|
|
53
|
+
roles_array = Array.new
|
|
54
|
+
|
|
55
|
+
begin
|
|
56
|
+
msg "new session"
|
|
57
|
+
@ddt_api.new_session
|
|
58
|
+
msg filename, Logger::DEBUG
|
|
59
|
+
f = File.open(filename)
|
|
60
|
+
doc = Nokogiri::XML(f)
|
|
61
|
+
response = @http.post_xml("templates/import", doc)
|
|
62
|
+
msg "response from post(#{filename}):\n#{response}", Logger::DEBUG
|
|
63
|
+
scenario_name = doc.xpath("//scenario")[0].attribute('name')
|
|
64
|
+
hosts = doc.xpath("//hosts/host")
|
|
65
|
+
uuid = doc.xpath("//scenario")[0].attribute('uuid')
|
|
66
|
+
roles = doc.xpath("//hosts/host/role")
|
|
67
|
+
ids = doc.xpath("//hosts/host/id")
|
|
68
|
+
channels = doc.xpath("//steps/channel")
|
|
69
|
+
type = doc.xpath("//hosts/host/type")[0].text
|
|
70
|
+
|
|
71
|
+
if !@interfaces.empty?
|
|
72
|
+
if @interfaces.size != hosts.size
|
|
73
|
+
msg "Error. The number of hosts/interfaces specified on the command-line does not equal the number
|
|
74
|
+
of hosts in the template. #{@interfaces.size} != #{hosts.size}"
|
|
75
|
+
return
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
msg @ddt_api.load_scenario(uuid)
|
|
80
|
+
|
|
81
|
+
roles.each_with_index do | r, i |
|
|
82
|
+
content = r.text
|
|
83
|
+
if @interfaces.empty?
|
|
84
|
+
begin
|
|
85
|
+
host = content.match(/\(.*\)/).to_s
|
|
86
|
+
host = host[1, host.index(".") - 1].downcase
|
|
87
|
+
hosts_array << host
|
|
88
|
+
rescue => e
|
|
89
|
+
msg e
|
|
90
|
+
msg "expected to find host name embedded in role, e.g. 'client (A1.V4)'"
|
|
91
|
+
end
|
|
92
|
+
else
|
|
93
|
+
hosts_array << @interfaces[i]
|
|
94
|
+
end
|
|
95
|
+
roles_array << content # use the whole name for the role
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
msg @ddt_api.set_hosts(roles_array, hosts_array, type)
|
|
99
|
+
|
|
100
|
+
# if there are channels in the scenario, bind them
|
|
101
|
+
if channels.size > 0
|
|
102
|
+
channel_roles = Array.new
|
|
103
|
+
channel_names = Array.new
|
|
104
|
+
arg_channels = args['channel'].split(",")
|
|
105
|
+
arg_channels.each do | c |
|
|
106
|
+
channel_roles << "channel" # role is always "channel"
|
|
107
|
+
channel_names << c
|
|
108
|
+
end
|
|
109
|
+
msg @ddt_api.set_channels(channel_roles, channel_names)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# verify the scenario
|
|
113
|
+
msg @ddt_api.setup_test
|
|
114
|
+
response = @ddt_api.run
|
|
115
|
+
if response == ""
|
|
116
|
+
msg "==> #{scenario_name} run returned without status"
|
|
117
|
+
@errors << "#{scenario_name}: status = #{response}"
|
|
118
|
+
else
|
|
119
|
+
doc = Nokogiri::XML(response)
|
|
120
|
+
status = doc.xpath("//status")[0].content
|
|
121
|
+
msg "==> #{scenario_name}: status = #{status}"
|
|
122
|
+
if status == 'failed'
|
|
123
|
+
# on error, add to the errors array
|
|
124
|
+
@errors << "#{scenario_name}: status = #{status}"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
@ddt_api.teardown_test
|
|
129
|
+
@ddt_api.close_session
|
|
130
|
+
|
|
131
|
+
# clear the hosts and roles array for the next iteration
|
|
132
|
+
roles_array.clear
|
|
133
|
+
hosts_array.clear
|
|
134
|
+
end # if !exclude_list.include? and hosts.length
|
|
135
|
+
# if there were errors, print them out and fail the test
|
|
136
|
+
estr = ""
|
|
137
|
+
if @errors.size > 0
|
|
138
|
+
@errors.each do | e |
|
|
139
|
+
estr = estr + e + "\n"
|
|
140
|
+
msg estr
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
ensure
|
|
144
|
+
teardown
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
def setup
|
|
150
|
+
@host = (@@mu_ip.nil?) ? "127.0.0.1" : @@mu_ip
|
|
151
|
+
@username = (@@mu_admin_user.nil?) ? "admin" : @@mu_admin_user
|
|
152
|
+
@password = (@@mu_admin_pass.nil?) ? "admin" : @@mu_admin_pass
|
|
153
|
+
@ddt_api = Ddt.new(@host, @username, @password)
|
|
154
|
+
@docroot ="/api/v3/"
|
|
155
|
+
@http = HttpHelper.new(@host, @username, @password, @docroot)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def teardown
|
|
159
|
+
unless @ddt_api.nil?
|
|
160
|
+
@ddt_api.close_all_sessions
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def parse_cli argv
|
|
165
|
+
hash = Hash.new
|
|
166
|
+
while not argv.empty?
|
|
167
|
+
break if argv.first[0,1] != '-'
|
|
168
|
+
|
|
169
|
+
k = argv.shift
|
|
170
|
+
|
|
171
|
+
if [ '-c', '--channel' ].member? k
|
|
172
|
+
hash['channel'] = shift(k, argv)
|
|
173
|
+
next
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
if [ '-d', '--dir' ].member? k
|
|
177
|
+
hash['dir'] = shift(k, argv)
|
|
178
|
+
next
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if [ '-h', '--help' ].member? k
|
|
182
|
+
help
|
|
183
|
+
exit
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
if [ '-i', '--interfaces' ].member? k
|
|
187
|
+
hash['interfaces'] = shift(k, argv)
|
|
188
|
+
next
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
if [ '-m', '--mu_string' ].member? k
|
|
192
|
+
mu_string = shift(k, argv)
|
|
193
|
+
if mu_string =~ /(.+?):(.+?)@(.*)/
|
|
194
|
+
@@mu_admin_user = $1
|
|
195
|
+
@@mu_admin_pass = $2
|
|
196
|
+
@@mu_ip = $3
|
|
197
|
+
end
|
|
198
|
+
next
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
if [ '-o', '--output' ].member? k
|
|
202
|
+
$stdout.reopen(shift(k, argv), "w")
|
|
203
|
+
next
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
if [ '-s', '--scenario' ].member? k
|
|
207
|
+
hash['scenario'] = shift(k, argv)
|
|
208
|
+
next
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
if [ '-v', '--verbose' ].member? k
|
|
212
|
+
$log.level = Logger::DEBUG
|
|
213
|
+
next
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
raise ArgumentError, "Unknown option #{k}"
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
hash
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def help
|
|
223
|
+
helps = [
|
|
224
|
+
{ :short => '-c', :long => '--channel', :value => '<string>', :help => 'channel name' },
|
|
225
|
+
{ :short => '-d', :long => '--dir', :value => '<string>', :help => 'directory containing the scenario file' },
|
|
226
|
+
{ :short => '-h', :long => '--help', :value => '', :help => 'help on command line options' },
|
|
227
|
+
{ :short => '-i', :long => '--interfaces', :value => '<string>', :help => 'comma-separated list of interfaces/hosts, e.g. b1,dell-server' },
|
|
228
|
+
{ :short => '-m', :long => '--mu_string', :value => '<string>', :help => 'user, password, mu_ip in the form of admin:admin@10.9.8.7' },
|
|
229
|
+
{ :short => '-o', :long => '--output', :value => '<string>', :help => 'output logging to this file' },
|
|
230
|
+
{ :short => '-s', :long => '--scenario', :value => '<string>', :help => 'scenario file to run' },
|
|
231
|
+
{ :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' }
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
cmds = [
|
|
235
|
+
"mu cmd_runscenario:help",
|
|
236
|
+
"mu cmd_runscenario:run -s <scenario> -i <hosts>"
|
|
237
|
+
]
|
|
238
|
+
|
|
239
|
+
max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
|
|
240
|
+
max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
|
|
241
|
+
puts
|
|
242
|
+
puts "Usage: mu cmd_runscenario:<command> <options>"
|
|
243
|
+
puts
|
|
244
|
+
helps.each do |h|
|
|
245
|
+
puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
|
|
246
|
+
end
|
|
247
|
+
puts
|
|
248
|
+
puts "Available Commands"
|
|
249
|
+
puts
|
|
250
|
+
cmds.each do | c |
|
|
251
|
+
puts c
|
|
252
|
+
end
|
|
253
|
+
puts
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
end
|
|
257
|
+
end # Command
|
|
258
|
+
end # Mu
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Runs a Studio Verify test, given a Mu Studio Scenario and Test Set.
|
|
2
|
+
# The Scenario template must be in Mu Studio XML format. The
|
|
3
|
+
# Test Set template can be in either the Mu Studio XML format or CSV
|
|
4
|
+
require 'mu/api/ddt'
|
|
5
|
+
class Mu
|
|
6
|
+
class Command
|
|
7
|
+
class Cmd_runverify < Command
|
|
8
|
+
|
|
9
|
+
attr_accessor :host, :username, :password, :ddt_api, :errors
|
|
10
|
+
|
|
11
|
+
# displays command-line help
|
|
12
|
+
def cmd_help argv
|
|
13
|
+
help
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# sets up, executes, and closes a Studio Verify session
|
|
17
|
+
# * argv = command-line arguments, requires a scenario (-s) argument, which must be an xml scenario template to be loaded onto the Mu
|
|
18
|
+
# * and a testset (-t) argument of an xml test set template to be loaded on the Mu
|
|
19
|
+
# * .msl and .csv files are not currently supported
|
|
20
|
+
def cmd_run argv
|
|
21
|
+
args = parse_cli argv
|
|
22
|
+
setup
|
|
23
|
+
|
|
24
|
+
if not args['scenario']
|
|
25
|
+
msg "scenario required"
|
|
26
|
+
return help
|
|
27
|
+
else
|
|
28
|
+
if args['scenario'].include?(".xml")
|
|
29
|
+
scenario = args['scenario']
|
|
30
|
+
else # TODO: eventually, msl files may be supported by this api
|
|
31
|
+
msg "only .xml files are currently supported"
|
|
32
|
+
return help
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if not args['testset']
|
|
37
|
+
msg "testset required"
|
|
38
|
+
return help
|
|
39
|
+
else
|
|
40
|
+
testset = args['testset']
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if not args['dir']
|
|
44
|
+
dir = "."
|
|
45
|
+
else
|
|
46
|
+
dir = args['dir']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if scenario.include?("/")
|
|
50
|
+
scenario_filename = scenario
|
|
51
|
+
else
|
|
52
|
+
scenario_filename = dir + "/" + scenario
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if testset.include?("/")
|
|
56
|
+
testset_filename = testset
|
|
57
|
+
else
|
|
58
|
+
testset_filename = dir + "/" + testset
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if not args['interfaces']
|
|
62
|
+
@interfaces = Array.new # initialize an empty array
|
|
63
|
+
else
|
|
64
|
+
@interfaces = args['interfaces'].split(",")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if not args['options']
|
|
68
|
+
@options = Array.new # initialize an empty array
|
|
69
|
+
else
|
|
70
|
+
@options = args['options'].split(",")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if not args['channels']
|
|
74
|
+
@arg_channels = Array.new # initialize an empty array
|
|
75
|
+
else
|
|
76
|
+
@arg_channels = args['channels'].split(",")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
@errors = Array.new
|
|
80
|
+
hosts_array = Array.new
|
|
81
|
+
roles_array = Array.new
|
|
82
|
+
|
|
83
|
+
begin
|
|
84
|
+
msg @ddt_api.new_session
|
|
85
|
+
|
|
86
|
+
if File.extname(testset_filename) == ".xml"
|
|
87
|
+
msg testset_filename, Logger::DEBUG
|
|
88
|
+
f = File.open(testset_filename)
|
|
89
|
+
doc = Nokogiri::XML(f)
|
|
90
|
+
response = @http.post_xml("templates/import", doc)
|
|
91
|
+
msg "response from post(#{testset_filename}):\n#{response}", Logger::DEBUG
|
|
92
|
+
testset_uuid = doc.xpath("//ddt_set")[0].attribute('uuid')
|
|
93
|
+
elsif File.extname(testset_filename) == ".csv"
|
|
94
|
+
doc = Nokogiri::XML(@ddt_api.csv_import(testset_filename))
|
|
95
|
+
testset_uuid = doc.xpath("//message")[0].content
|
|
96
|
+
else
|
|
97
|
+
raise "Testset filename extension must be either .xml or .csv, but filename is #{testset}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
msg scenario_filename, Logger::DEBUG
|
|
101
|
+
f = File.open(scenario_filename)
|
|
102
|
+
doc = Nokogiri::XML(f)
|
|
103
|
+
response = @http.post_xml("templates/import", doc)
|
|
104
|
+
msg "response from post(#{scenario_filename}):\n#{response}", Logger::DEBUG
|
|
105
|
+
|
|
106
|
+
scenario_name = doc.xpath("//scenario")[0].attribute('name')
|
|
107
|
+
hosts = doc.xpath("//hosts/host")
|
|
108
|
+
scenario_uuid = doc.xpath("//scenario")[0].attribute('uuid')
|
|
109
|
+
roles = doc.xpath("//hosts/host/role")
|
|
110
|
+
ids = doc.xpath("//hosts/host/id")
|
|
111
|
+
channels = doc.xpath("//steps/channel")
|
|
112
|
+
type = doc.xpath("//hosts/host/type")[0].text
|
|
113
|
+
|
|
114
|
+
if !@interfaces.empty?
|
|
115
|
+
if @interfaces.size != hosts.size
|
|
116
|
+
msg "Error. The number of hosts/interfaces specified on the command-line does not equal the number
|
|
117
|
+
of hosts in the template. #{@interfaces.size} != #{hosts.size}"
|
|
118
|
+
return
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
msg @ddt_api.load_scenario(scenario_uuid)
|
|
123
|
+
|
|
124
|
+
roles.each_with_index do | r, i |
|
|
125
|
+
content = r.content
|
|
126
|
+
if @interfaces.empty?
|
|
127
|
+
begin
|
|
128
|
+
host = content.match(/\(.*\)/).to_s
|
|
129
|
+
host = host[1, host.index(".") - 1].downcase
|
|
130
|
+
hosts_array << host
|
|
131
|
+
rescue => e
|
|
132
|
+
puts e
|
|
133
|
+
puts "no hosts were specified, and none were found embedded in the role, e.g. 'client (A1.V4)'"
|
|
134
|
+
end
|
|
135
|
+
else
|
|
136
|
+
hosts_array << @interfaces[i]
|
|
137
|
+
end
|
|
138
|
+
roles_array << content # use the whole name for the role
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
msg @ddt_api.set_hosts(roles_array, hosts_array, type)
|
|
142
|
+
|
|
143
|
+
# if there are channels in the scenario, bind them
|
|
144
|
+
if channels.size > 0
|
|
145
|
+
if @arg_channels.size != channels.size
|
|
146
|
+
msg "Error. The number of channels specified on the command-line does not equal the number
|
|
147
|
+
of channels in the template. #{@arg_channels.size} != #{channels.size}"
|
|
148
|
+
return
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
channel_roles = Array.new
|
|
152
|
+
channel_names = Array.new
|
|
153
|
+
@arg_channels.each do | c |
|
|
154
|
+
channel_roles << "channel" # role is always "channel"
|
|
155
|
+
channel_names << c
|
|
156
|
+
end
|
|
157
|
+
msg @ddt_api.set_channels(channel_roles, channel_names)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# if there are options specified on the command-line, set them
|
|
161
|
+
if !@options.empty?
|
|
162
|
+
option_names = Array.new
|
|
163
|
+
option_values = Array.new
|
|
164
|
+
@options.each do | o |
|
|
165
|
+
opts = o.split(":")
|
|
166
|
+
option_names << opts[0]
|
|
167
|
+
option_values << opts[1]
|
|
168
|
+
end
|
|
169
|
+
msg @ddt_api.set_options(option_names, option_values)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# verify the scenario
|
|
173
|
+
msg @ddt_api.setup_test
|
|
174
|
+
response = @ddt_api.run
|
|
175
|
+
if response == ""
|
|
176
|
+
msg "==> #{scenario_name} run returned without status"
|
|
177
|
+
@errors << "#{scenario_name}: status = #{response}"
|
|
178
|
+
else
|
|
179
|
+
doc = Nokogiri::XML(response)
|
|
180
|
+
status = doc.xpath("//status")[0].content
|
|
181
|
+
msg "==> #{scenario_name}: status = #{status}"
|
|
182
|
+
if status == 'failed'
|
|
183
|
+
# on error, add to the errors array
|
|
184
|
+
@errors << "#{scenario_name}: status = #{status}"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
msg @ddt_api.run_testset(testset_uuid)
|
|
189
|
+
results = @ddt_api.collect_results # will wait until 'Done' is returned by status
|
|
190
|
+
msg "results = #{results}"
|
|
191
|
+
if results.to_s.include?("FAILED")
|
|
192
|
+
@errors << "test failed"
|
|
193
|
+
|
|
194
|
+
msg @ddt_api.teardown_test
|
|
195
|
+
msg @ddt_api.close_session
|
|
196
|
+
|
|
197
|
+
# clear the hosts and roles array for the next iteration
|
|
198
|
+
roles_array.clear
|
|
199
|
+
hosts_array.clear
|
|
200
|
+
end # if !exclude_list.include? and hosts.length
|
|
201
|
+
end
|
|
202
|
+
ensure
|
|
203
|
+
teardown
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
private
|
|
207
|
+
|
|
208
|
+
def setup
|
|
209
|
+
@host = (@@mu_ip.nil?) ? "127.0.0.1" : @@mu_ip
|
|
210
|
+
@username = (@@mu_admin_user.nil?) ? "admin" : @@mu_admin_user
|
|
211
|
+
@password = (@@mu_admin_pass.nil?) ? "admin" : @@mu_admin_pass
|
|
212
|
+
@ddt_api = Ddt.new(@host, @username, @password)
|
|
213
|
+
@docroot ="/api/v3/"
|
|
214
|
+
@http = HttpHelper.new(@host, @username, @password, @docroot)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def teardown
|
|
218
|
+
unless @ddt_api.nil?
|
|
219
|
+
@ddt_api.close_all_sessions
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def output_results(filename, doc)
|
|
224
|
+
f = File.open(filename, "a")
|
|
225
|
+
# doc = "#{msl_file},#{@executed},#{@errors.to_i},#{@timeouts.to_i}\n"
|
|
226
|
+
File.open(filename, 'a') {|f| f.write(doc) }
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def parse_cli argv
|
|
230
|
+
hash = Hash.new
|
|
231
|
+
while not argv.empty?
|
|
232
|
+
break if argv.first[0,1] != '-'
|
|
233
|
+
|
|
234
|
+
k = argv.shift
|
|
235
|
+
|
|
236
|
+
if [ '-c', '--channels' ].member? k
|
|
237
|
+
hash['channels'] = shift(k, argv)
|
|
238
|
+
next
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
if [ '-d', '--dir' ].member? k
|
|
242
|
+
hash['dir'] = shift(k, argv)
|
|
243
|
+
next
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
if [ '-i', '--interfaces' ].member? k
|
|
247
|
+
hash['interfaces'] = shift(k, argv)
|
|
248
|
+
next
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
if [ '-h', '--help' ].member? k
|
|
252
|
+
help
|
|
253
|
+
exit
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
if [ '-m', '--mu_string' ].member? k
|
|
257
|
+
mu_string = shift(k, argv)
|
|
258
|
+
if mu_string =~ /(.+?):(.+?)@(.*)/
|
|
259
|
+
@@mu_admin_user = $1
|
|
260
|
+
@@mu_admin_pass = $2
|
|
261
|
+
@@mu_ip = $3
|
|
262
|
+
end
|
|
263
|
+
next
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
if [ '-o', '--output' ].member? k
|
|
267
|
+
$stdout.reopen(shift(k, argv), "w")
|
|
268
|
+
next
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
if [ '-p', '--options' ].member? k
|
|
272
|
+
hash['options'] = shift(k, argv)
|
|
273
|
+
next
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
if [ '-s', '--scenario' ].member? k
|
|
277
|
+
hash['scenario'] = shift(k, argv)
|
|
278
|
+
next
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
if [ '-t', '--testset' ].member? k
|
|
282
|
+
hash['testset'] = shift(k, argv)
|
|
283
|
+
next
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
if [ '-v', '--verbose' ].member? k
|
|
287
|
+
$log.level = Logger::DEBUG
|
|
288
|
+
next
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
raise ArgumentError, "Unknown option #{k}"
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
hash
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def help
|
|
298
|
+
helps = [
|
|
299
|
+
{ :short => '-c', :long => '--channels', :value => '<string>', :help => 'comma-separated list of channel hosts' },
|
|
300
|
+
{ :short => '-d', :long => '--dir', :value => '<string>', :help => 'directory containing the scenario file' },
|
|
301
|
+
{ :short => '-h', :long => '--help', :value => '', :help => 'help on command line options' },
|
|
302
|
+
{ :short => '-i', :long => '--interfaces', :value => '<string>', :help => 'comma-separated list of interfaces/hosts, e.g. b1,dell-server' },
|
|
303
|
+
{ :short => '-m', :long => '--mu_string', :value => '<string>', :help => 'user, password, mu_ip in the form of admin:admin@10.9.8.7' },
|
|
304
|
+
{ :short => '-o', :long => '--output', :value => '<string>', :help => 'output logging to this file' },
|
|
305
|
+
{ :short => '-p', :long => '--options', :value => '<string>', :help => 'comma-separated list of of options name:value pairs' },
|
|
306
|
+
{ :short => '-s', :long => '--scenario', :value => '<string>', :help => 'name of scenario file to run' },
|
|
307
|
+
{ :short => '-t', :long => '--testset', :value => '<string>', :help => 'name of testset to run' },
|
|
308
|
+
{ :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' }
|
|
309
|
+
]
|
|
310
|
+
|
|
311
|
+
cmds = [
|
|
312
|
+
"mu cmd_runverify:help",
|
|
313
|
+
"mu cmd_runverify:run -s <scenario> -t <testset> -i <hosts>"
|
|
314
|
+
]
|
|
315
|
+
|
|
316
|
+
max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
|
|
317
|
+
max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
|
|
318
|
+
puts
|
|
319
|
+
puts "Usage: mu cmd_runverify:<command> <options>"
|
|
320
|
+
puts
|
|
321
|
+
helps.each do |h|
|
|
322
|
+
puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
|
|
323
|
+
end
|
|
324
|
+
puts
|
|
325
|
+
puts "Available Commands"
|
|
326
|
+
puts
|
|
327
|
+
cmds.each do | c |
|
|
328
|
+
puts c
|
|
329
|
+
end
|
|
330
|
+
puts
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
end
|
|
334
|
+
end # Command
|
|
335
|
+
end # Mu
|
|
336
|
+
|