mu 5.7.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/Mu_Gem.html +1591 -0
  2. data/bin/mu +11 -0
  3. data/lib/mu.rb +65 -0
  4. data/lib/mu/api/ddt.rb +233 -0
  5. data/lib/mu/api/homepage.rb +54 -0
  6. data/lib/mu/api/muapi.rb +231 -0
  7. data/lib/mu/api/netconfig.rb +233 -0
  8. data/lib/mu/api/scale.rb +199 -0
  9. data/lib/mu/api/system.rb +40 -0
  10. data/lib/mu/client.rb +31 -0
  11. data/lib/mu/command.rb +28 -0
  12. data/lib/mu/command/api.rb +95 -0
  13. data/lib/mu/command/cmd_appid.rb +486 -0
  14. data/lib/mu/command/cmd_cli.rb +151 -0
  15. data/lib/mu/command/cmd_ddt.rb +449 -0
  16. data/lib/mu/command/cmd_homepage.rb +146 -0
  17. data/lib/mu/command/cmd_muapi.rb +361 -0
  18. data/lib/mu/command/cmd_netconfig.rb +262 -0
  19. data/lib/mu/command/cmd_runscale.rb +533 -0
  20. data/lib/mu/command/cmd_runscenario.rb +258 -0
  21. data/lib/mu/command/cmd_runverify.rb +336 -0
  22. data/lib/mu/command/cmd_scale.rb +333 -0
  23. data/lib/mu/command/cmd_system.rb +127 -0
  24. data/lib/mu/command/curl.rb +246 -0
  25. data/lib/mu/command/help.rb +29 -0
  26. data/lib/mu/curl/error.rb +54 -0
  27. data/lib/mu/curl/verify.rb +137 -0
  28. data/lib/mu/helper.rb +55 -0
  29. data/lib/mu/http_helper.rb +232 -0
  30. data/rdoc/classes/Mu.html +305 -0
  31. data/rdoc/classes/Mu/Client.html +265 -0
  32. data/rdoc/classes/Mu/Command.html +208 -0
  33. data/rdoc/classes/Mu/Command/API.html +524 -0
  34. data/rdoc/classes/Mu/Command/Cmd_appid.html +934 -0
  35. data/rdoc/classes/Mu/Command/Cmd_cli.html +515 -0
  36. data/rdoc/classes/Mu/Command/Cmd_ddt.html +1169 -0
  37. data/rdoc/classes/Mu/Command/Cmd_homepage.html +489 -0
  38. data/rdoc/classes/Mu/Command/Cmd_muapi.html +968 -0
  39. data/rdoc/classes/Mu/Command/Cmd_netconfig.html +743 -0
  40. data/rdoc/classes/Mu/Command/Cmd_runscale.html +970 -0
  41. data/rdoc/classes/Mu/Command/Cmd_runscenario.html +530 -0
  42. data/rdoc/classes/Mu/Command/Cmd_runverify.html +621 -0
  43. data/rdoc/classes/Mu/Command/Cmd_scale.html +939 -0
  44. data/rdoc/classes/Mu/Command/Cmd_system.html +426 -0
  45. data/rdoc/classes/Mu/Command/Curl.html +524 -0
  46. data/rdoc/classes/Mu/Command/Help.html +166 -0
  47. data/rdoc/classes/Mu/Curl.html +116 -0
  48. data/rdoc/classes/Mu/Curl/Error.html +157 -0
  49. data/rdoc/classes/Mu/Curl/Error/Authorize.html +178 -0
  50. data/rdoc/classes/Mu/Curl/Error/Connect.html +149 -0
  51. data/rdoc/classes/Mu/Curl/Error/DNS.html +113 -0
  52. data/rdoc/classes/Mu/Curl/Error/Region.html +160 -0
  53. data/rdoc/classes/Mu/Curl/Error/Status.html +149 -0
  54. data/rdoc/classes/Mu/Curl/Error/Timeout.html +149 -0
  55. data/rdoc/classes/Mu/Curl/Verify.html +282 -0
  56. data/rdoc/classes/Mu/Curl/Verify/Request.html +227 -0
  57. data/rdoc/classes/Mu/Curl/Verify/Response.html +187 -0
  58. data/rdoc/classes/Mu/Curl/Verify/Result.html +188 -0
  59. data/rdoc/classes/Mu/Ddt.html +914 -0
  60. data/rdoc/classes/Mu/Helper.html +308 -0
  61. data/rdoc/classes/Mu/Homepage.html +377 -0
  62. data/rdoc/classes/Mu/HttpHelper.html +639 -0
  63. data/rdoc/classes/Mu/Muapi.html +816 -0
  64. data/rdoc/classes/Mu/Netconfig.html +781 -0
  65. data/rdoc/classes/Mu/Scale.html +832 -0
  66. data/rdoc/classes/Mu/System.html +281 -0
  67. data/rdoc/classes/Object.html +148 -0
  68. data/rdoc/classes/TCTestMu.html +1793 -0
  69. data/rdoc/classes/Test.html +107 -0
  70. data/rdoc/classes/Test/Unit.html +107 -0
  71. data/rdoc/classes/Test/Unit/TestCase.html +113 -0
  72. data/rdoc/created.rid +1 -0
  73. data/rdoc/files/lib/mu/api/ddt_rb.html +101 -0
  74. data/rdoc/files/lib/mu/api/homepage_rb.html +101 -0
  75. data/rdoc/files/lib/mu/api/muapi_rb.html +101 -0
  76. data/rdoc/files/lib/mu/api/netconfig_rb.html +101 -0
  77. data/rdoc/files/lib/mu/api/scale_rb.html +101 -0
  78. data/rdoc/files/lib/mu/api/system_rb.html +101 -0
  79. data/rdoc/files/lib/mu/client_rb.html +101 -0
  80. data/rdoc/files/lib/mu/command/api_rb.html +101 -0
  81. data/rdoc/files/lib/mu/command/cmd_appid_rb.html +119 -0
  82. data/rdoc/files/lib/mu/command/cmd_cli_rb.html +108 -0
  83. data/rdoc/files/lib/mu/command/cmd_ddt_rb.html +117 -0
  84. data/rdoc/files/lib/mu/command/cmd_homepage_rb.html +115 -0
  85. data/rdoc/files/lib/mu/command/cmd_muapi_rb.html +116 -0
  86. data/rdoc/files/lib/mu/command/cmd_netconfig_rb.html +116 -0
  87. data/rdoc/files/lib/mu/command/cmd_runscale_rb.html +119 -0
  88. data/rdoc/files/lib/mu/command/cmd_runscenario_rb.html +115 -0
  89. data/rdoc/files/lib/mu/command/cmd_runverify_rb.html +117 -0
  90. data/rdoc/files/lib/mu/command/cmd_scale_rb.html +115 -0
  91. data/rdoc/files/lib/mu/command/cmd_system_rb.html +116 -0
  92. data/rdoc/files/lib/mu/command/curl_rb.html +101 -0
  93. data/rdoc/files/lib/mu/command/help_rb.html +101 -0
  94. data/rdoc/files/lib/mu/command_rb.html +107 -0
  95. data/rdoc/files/lib/mu/curl/error_rb.html +101 -0
  96. data/rdoc/files/lib/mu/curl/verify_rb.html +101 -0
  97. data/rdoc/files/lib/mu/helper_rb.html +101 -0
  98. data/rdoc/files/lib/mu/http_helper_rb.html +101 -0
  99. data/rdoc/files/lib/mu_rb.html +121 -0
  100. data/rdoc/files/test/helper_rb.html +112 -0
  101. data/rdoc/files/test/tc_test_mu_rb.html +111 -0
  102. data/rdoc/fr_class_index.html +68 -0
  103. data/rdoc/fr_file_index.html +55 -0
  104. data/rdoc/fr_method_index.html +374 -0
  105. data/rdoc/index.html +24 -0
  106. data/rdoc/rdoc-style.css +208 -0
  107. data/test/data/app_id_stats.csv +1 -0
  108. data/test/data/data_cgi.msl +94 -0
  109. data/test/data/data_cgi.xml +322 -0
  110. data/test/data/default_test.csv +3 -0
  111. data/test/data/ftp_with_channel.xml +1643 -0
  112. data/test/data/irc.xml +3837 -0
  113. data/test/data/scale_configuration.json +25 -0
  114. data/test/data/test_data_cgi_error.xml +35 -0
  115. data/test/helper.rb +18 -0
  116. data/test/tc_test_mu.rb +716 -0
  117. metadata +322 -0
@@ -0,0 +1,31 @@
1
+ class Mu
2
+ class Client
3
+ attr_reader :mu
4
+
5
+ def initialize user, apik, host=''
6
+ scheme = host.index('localhost') ? 'http' : 'https'
7
+ @mu = RestClient::Resource.new "#{scheme}://#{host}", \
8
+ :headers => {
9
+ :x_api_user => user,
10
+ :x_api_key => apik,
11
+ :x_api_version => ::Mu::Version
12
+ }
13
+ end
14
+
15
+ def curl data
16
+ JSON.parse mu['/api/1/curl'].post(data.to_json)
17
+ end
18
+
19
+ def login
20
+ JSON.parse mu['/account/login/api'].get
21
+ end
22
+
23
+ def job_status job_id
24
+ JSON.parse mu["/api/1/jobs/#{job_id}/status"].get
25
+ end
26
+
27
+ def abort_job job_id
28
+ JSON.parse mu["/api/1/jobs/#{job_id}/abort"].put('')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ #require 'test/unit/assertions'
2
+
3
+ # The default template string contains what was sent and received. Strip
4
+ # these out since we don't need them
5
+ =begin
6
+ class Test::Unit::Assertions::AssertionMessage
7
+ alias :old_template :template
8
+
9
+ def template
10
+ @template_string = ''
11
+ @parameters = []
12
+ old_template
13
+ end
14
+ end
15
+ =end
16
+
17
+ class Mu
18
+ class Command
19
+ #include Test::Unit::Assertions
20
+ include Helper
21
+
22
+ @@mu_ip = ENV['MU_IP']
23
+ @@mu_admin_user = ENV['MU_ADMIN_USER']
24
+ @@mu_admin_pass = ENV['MU_ADMIN_PASS']
25
+ end
26
+ end # Mu
27
+
28
+ Dir["#{File.dirname(__FILE__)}/command/*.rb"].each { |c| require c }
@@ -0,0 +1,95 @@
1
+ class Mu
2
+ class Command
3
+ class API < Command
4
+ attr_accessor :credentials
5
+
6
+ def cmd_init argv
7
+ FileUtils.rm credentials_file rescue nil
8
+ API.client
9
+
10
+ msg "You are now ready to use mu!"
11
+ msg "Try mu help to learn more about the commands."
12
+ end
13
+
14
+ def client
15
+ get_credentials
16
+ Mu::Client.new(user, password, host)
17
+ end
18
+
19
+ def user
20
+ get_credentials
21
+ @credentials[0]
22
+ end
23
+
24
+ def password
25
+ get_credentials
26
+ @credentials[1]
27
+ end
28
+
29
+ def host
30
+ ENV['MU_IP'] || ''
31
+ end
32
+
33
+ def credentials_file
34
+ end
35
+
36
+ def get_credentials
37
+ return if @credentials
38
+ unless @credentials = read_credentials
39
+ @credentials = ask_for_credentials
40
+ save_credentials
41
+ end
42
+ @credentials
43
+ end
44
+
45
+ def read_credentials
46
+ File.exists?(credentials_file) and File.read(credentials_file).split("\n")
47
+ end
48
+
49
+ def ask_for_credentials
50
+ msg "Enter your credentials."
51
+ print "User-ID: "
52
+ user = ask
53
+ print "API-Key: "
54
+ apik = ask
55
+ apik2 = Mu::Client.new(user, apik, host).login['api_key']
56
+ if not apik2
57
+ error "Authentication failed"
58
+ exit 1
59
+ end
60
+
61
+ [ user, apik2 ]
62
+ end
63
+
64
+ def save_credentials
65
+ write_credentials
66
+ end
67
+
68
+ def write_credentials
69
+ FileUtils.mkdir_p(File.dirname(credentials_file))
70
+ File.open(credentials_file, 'w') do |f|
71
+ f.puts self.credentials
72
+ end
73
+ set_credentials_permissions
74
+ end
75
+
76
+ def set_credentials_permissions
77
+ FileUtils.chmod 0700, File.dirname(credentials_file)
78
+ FileUtils.chmod 0600, credentials_file
79
+ end
80
+
81
+ def self.instance
82
+ @instance ||= API.new
83
+ end
84
+
85
+ def self.client
86
+ self.instance.client
87
+ end
88
+
89
+ private
90
+ def initialize
91
+ end
92
+ end
93
+ Api = API
94
+ end # Command
95
+ end # Mu
@@ -0,0 +1,486 @@
1
+ # runs Mu Studio multi-host app_id msl files in Studio Scale, in client/server passthrough
2
+ # mode, collapsing all hosts in the scenario to two. Runs either a single msl file or
3
+ # a directory of msl files, and has command-line options to specify the Mu parameters,
4
+ # the interfaces to use, and the pattern in which to run
5
+ require 'mu/api/scale'
6
+ class Mu
7
+ class Command
8
+ class Cmd_appid < Command
9
+
10
+ attr_accessor :api, :params, :hosts, :addr_indexes, :hash
11
+
12
+ # displays command-line help
13
+ def cmd_help argv
14
+ help
15
+ end
16
+
17
+ # returns a boolean indicating whether the scale test is running or not
18
+ # * argv = command-line arguments
19
+ def cmd_running? argv
20
+ if @api.nil?
21
+ msg "false"
22
+ return
23
+ end
24
+
25
+ status = @api.status
26
+ if !status.nil?
27
+ if !status["status"].nil?
28
+ msg status["status"]["running"]
29
+ end
30
+ else
31
+ msg "false"
32
+ end
33
+ end
34
+
35
+ # runs a single Studio Scale test
36
+ # * argv = command-line arguments, requires a scenario (-s) argument
37
+ def cmd_run_file argv
38
+ setup argv
39
+
40
+ if not @hash['scenario']
41
+ raise "*** Error: scenario required, using -s option"
42
+ else
43
+ scenario = @hash['scenario']
44
+ end
45
+
46
+ if !File.exists?(scenario)
47
+ raise "*** Error: Scenario file #{scenario} was not found"
48
+ end
49
+
50
+ File.delete("app_id_status.json") if File.exists?("app_id_status.json")
51
+ File.delete("app_id_stats.csv") if File.exists?("app_id_stats.csv")
52
+
53
+ @api = Scale.new(@@mu_ip, @@mu_admin_user, @@mu_admin_pass)
54
+ @api.configure("pattern", @cmd_line_pattern)
55
+ @params = {}
56
+ @params["msl"] = scenario
57
+ @params["hosts"] = @cmd_line_hosts
58
+ run(scenario)
59
+ @api.release
60
+ end
61
+
62
+ # runs through a directory of msl files and executes a Studio Scale test for each one
63
+ # * argv = command-line arguments, require a directory (-d) argument
64
+ # * optional -r argument for recursive directory search (default is a flat directory)
65
+ def cmd_run_dir argv
66
+ setup argv
67
+
68
+ if not @hash['dir']
69
+ raise "*** Error: directory required, using -d option"
70
+ else
71
+ dir = @hash['dir']
72
+ end
73
+
74
+ File.delete("app_id_status.json") if File.exists?("app_id_status.json")
75
+ File.delete("app_id_stats.csv") if File.exists?("app_id_stats.csv")
76
+
77
+ @api = Scale.new(@@mu_ip, @@mu_admin_user, @@mu_admin_pass)
78
+ @api.configure("pattern", @cmd_line_pattern)
79
+ @params = {}
80
+ @params["dir"] = dir
81
+ @params["hosts"] = @cmd_line_hosts
82
+ Dir.chdir(@params["dir"])
83
+ File.delete("app_id_status.json") if File.exists?("app_id_status.json")
84
+ if @hash['recursive'].nil?
85
+ files = Dir.glob("*.msl")
86
+ else
87
+ files = Dir.glob("**/*.msl")
88
+ end
89
+ if !files.empty?
90
+ files.sort.each do | f |
91
+ run(f)
92
+ output_csv(f)
93
+ sleep 2
94
+ end
95
+ else
96
+ msg "no msl files found in #{dir}"
97
+ end
98
+ @api.release
99
+ end
100
+
101
+ private
102
+
103
+ def setup argv
104
+ parse_cli argv
105
+ @params = {}
106
+
107
+ if @hash['test']
108
+ @verify_only = true
109
+ else
110
+ @verify_only = false
111
+ end
112
+
113
+ if not @hash['pattern']
114
+ @cmd_line_pattern = "{ \"iterations\": 1, \"intervals\": [ {\"iterations\":1, \"end\":100, \"start\":1, \"duration\":20 } ] }"
115
+ else
116
+ @cmd_line_pattern = @hash['pattern']
117
+ end
118
+
119
+ if not @hash['interfaces']
120
+ @cmd_line_hosts = "b1,b2"
121
+ else
122
+ @cmd_line_hosts = @hash['interfaces']
123
+ end
124
+
125
+ if not @hash['testset']
126
+ @testset = ""
127
+ else
128
+ @testset = @hash['testset']
129
+ end
130
+
131
+ end
132
+
133
+ def run(msl)
134
+ if !File.exists?(msl)
135
+ return "file not found: #{msl}"
136
+ end
137
+
138
+ @api.configure("musl", File.read(msl))
139
+
140
+ unless @testset.empty?
141
+ if @testset.include?("/") # assume it is the full path in this case
142
+ csv_file = @testset
143
+ else
144
+ csv_file = @params["dir"] + "/" + @testset
145
+ end
146
+ @api.configure("csv", File.read(csv_file))
147
+ end
148
+
149
+ set_global_hosts
150
+ all_hosts = get_all_hosts_from_musl(msl)
151
+ @hosts_config = map_all_hosts_to_json(all_hosts)
152
+ @api.configure("hosts", @hosts_config)
153
+ msg "verifying #{msl} ..."
154
+ response = @api.verify
155
+ # sleep 3
156
+ v = parse_verify_response(response)
157
+ if v.nil?
158
+ msg "error in verify"
159
+ return
160
+ end
161
+ if @verify_only
162
+ msg v
163
+ return
164
+ end
165
+ msg "starting #{msl} ..."
166
+ @api.start
167
+ start_time = Time.now.to_i
168
+ while true
169
+ sleep 5
170
+ status = @api.status
171
+ if !status.nil?
172
+ if !status["status"].nil?
173
+ if status["status"]["running"] == false
174
+ msg "running = #{status["status"]["running"]}", Logger::DEBUG
175
+ r = parse_status(status)
176
+ dump_status(status, msl)
177
+ return
178
+ else
179
+ r = parse_status(status)
180
+ end
181
+ else # status['status'].nil? ... no bonafide status was returned
182
+ time_now = Time.now.to_i
183
+ if time_now - start_time > 20
184
+ # puts "\nError: timing out after 20 seconds. Test had failed to start or verify"
185
+ break
186
+ end
187
+ end
188
+ end
189
+ end
190
+ ensure
191
+ msg "stopping #{msl} ..."
192
+ end
193
+
194
+ def set_global_hosts
195
+ @hosts = Array.new
196
+ @addr_indexes = Array.new
197
+ hosts = @params["hosts"]
198
+ if !hosts.nil?
199
+ p = hosts.split(",")
200
+ p.each do | h |
201
+ if h.include?("-") # b1-1000,b2-1 to indicate addr_count
202
+ q = h.split("-")
203
+ @hosts << q[0]
204
+ @addr_indexes << q[1]
205
+ else # default to the 1st addr index
206
+ @hosts << h
207
+ @addr_indexes << 1
208
+ end
209
+ end
210
+ else
211
+ @hosts = ['b1','b2']
212
+ @addr_indexes = [1,1]
213
+ end
214
+ end
215
+
216
+ def dump_status(status, msl)
217
+ filename = "app_id_status.json"
218
+ f = File.open(filename, "a")
219
+ status["filename"] = msl
220
+ str = JSON.pretty_generate(status)
221
+ f.write(",") if !File.zero?(f) # if appending, we need to insert a comma
222
+ f.write(str)
223
+ f.close
224
+ end
225
+
226
+ def output_csv(msl_file)
227
+ filename = "app_id_stats.csv"
228
+ f = File.open(filename, "a")
229
+ doc = "#{msl_file},#{@executed},#{@errors.to_i},#{@timeouts.to_i},#{@client_tx_bytes},#{@client_tx_msgs},#{@client_rx_bytes},#{@client_rx_msgs},#{@server_tx_bytes},#{@server_tx_msgs},#{@server_rx_bytes},#{@server_rx_msgs}\n"
230
+ File.open(filename, 'a') {|f| f.write(doc) }
231
+ end
232
+
233
+ # finds all the hosts in the musl file
234
+ def get_all_hosts_from_musl(msl)
235
+ f = IO.read(msl)
236
+ hosts = f.scan(/host_\d+/)
237
+ hosts.uniq!
238
+ return hosts
239
+ end
240
+
241
+ # maps host_0 to the client interface
242
+ # maps all other hosts to the server interface
243
+ def map_all_hosts_to_json(hosts=[])
244
+ new_hosts = Array.new
245
+ hosts.each_with_index do | h, i |
246
+ if i == 0
247
+ new_hosts << @hosts[0] + "/*,#{@addr_indexes[0]}"
248
+ else
249
+ new_hosts << @hosts[1] + "/*,#{@addr_indexes[1]}"
250
+ end
251
+ end
252
+
253
+ hosts_config = {}
254
+
255
+ # assign hosts to consecutive string keys, host_0, host_1, etc ...
256
+ new_hosts.each_with_index do | h, i |
257
+ hosts_config["host_#{i}"] = h # new_hosts[i]
258
+ end
259
+
260
+ # convert keys to symbols
261
+ new_hosts_config = {}
262
+ hosts_config.each_key { |k| new_hosts_config[k.to_sym] = hosts_config[k] }
263
+
264
+ return new_hosts_config
265
+ end
266
+
267
+ def parse_verify_response(response)
268
+ if response.nil? # || response.empty?
269
+ msg "*** error = no response received from /verify ***\n\n"
270
+ return nil
271
+ end
272
+ begin
273
+ msg JSON.pretty_generate(response), Logger::DEBUG
274
+ if !response["status"].nil?
275
+ if response["status"]["error"] == true
276
+ @error = response["status"]["error"]
277
+ @reason = response["status"]["reason"]
278
+ dump_status(response)
279
+ msg "*** Error = #{@error}, reason = #{@reason} ***\n\n"
280
+ return nil
281
+ end
282
+ end
283
+ msg "*** verify: okay ***", Logger::DEBUG
284
+ return "*** verify: okay ***"
285
+ rescue
286
+ # could nbe json parse error
287
+ return nil
288
+ end
289
+ end
290
+
291
+ def parse_status(status)
292
+ return nil if status.nil?
293
+ msg JSON.pretty_generate(status), Logger::DEBUG
294
+ @reported_volume = 0
295
+ if !status["status"]["error"].nil?
296
+ if status["status"]["error"] == true
297
+ @error = status["status"]["error"]
298
+ @reason = status["status"]["reason"]
299
+ # puts "*** Error = #{@error}, reason = #{@reason} ***\n\n"
300
+ return nil
301
+ end
302
+ end
303
+
304
+ @stats_summary = status["status"]["statistics"]["summary"]
305
+ @duration = @stats_summary["duration"]
306
+ @instances = @stats_summary["instances"]
307
+ @total_instances = @instances["total"]
308
+ @executed = @instances["executed"]
309
+ @timeouts = @instances["timeouts"]
310
+ @errors = @instances["errors"]
311
+ @asserts_failed = @stats_summary["asserts"]["failed"]
312
+ @server = @stats_summary["server"]
313
+ @server_tx_bytes = @server["tx"]["bytes"]
314
+ @server_tx_msgs = @server["tx"]["msgs"]
315
+ @server_rx_bytes = @server["rx"]["bytes"]
316
+ @server_rx_msgs = @server["rx"]["msgs"]
317
+ @client = @stats_summary["client"]
318
+ @client_tx_bytes = @client["tx"]["bytes"]
319
+ @client_tx_msgs = @client["tx"]["msgs"]
320
+ @client_rx_bytes = @client["rx"]["bytes"]
321
+ @client_rx_msgs = @client["rx"]["msgs"]
322
+ @scenarios = status["status"]["statistics"]["scenarios"]
323
+ @scenarios.each do | scenario |
324
+ @reported_volume = @reported_volume + scenario["volume"]
325
+ end
326
+
327
+ msg ""
328
+ msg "duration: #{format_float(2, @duration)}"
329
+ msg "concurrency: #{@reported_volume}"
330
+ msg "tests/sec: #{format_float(2, @executed.to_f / @duration)}" if @duration.to_i > 0
331
+ msg "passed: #{@executed}"
332
+ msg "errors: #{@errors}"
333
+ msg "timeouts: #{@timeouts}"
334
+ msg "client tx bytes/sec #{format_float(2, @client_tx_bytes.to_f / @duration)}" if @duration.to_i > 0
335
+ msg "client tx msgs/sec #{format_float(2, @client_tx_msgs.to_f / @duration)}" if @duration.to_i > 0
336
+ msg "client rx bytes/sec #{format_float(2, @client_rx_bytes.to_f / @duration)}" if @duration.to_i > 0
337
+ msg "client rx msgs/sec #{format_float(2, @client_rx_msgs.to_f / @duration)}" if @duration.to_i > 0
338
+ msg "server tx bytes/sec #{format_float(2, @server_tx_bytes.to_f / @duration)}" if @duration.to_i > 0
339
+ msg "server tx msgs/sec #{format_float(2, @server_tx_msgs.to_f / @duration)}" if @duration.to_i > 0
340
+ msg "server rx bytes/sec #{format_float(2, @server_rx_bytes.to_f / @duration)}" if @duration.to_i > 0
341
+ msg "server rx msgs/sec #{format_float(2, @server_rx_msgs.to_f / @duration)}" if @duration.to_i > 0
342
+ msg ""
343
+ end
344
+
345
+ def parse_cli argv
346
+ @hash = Hash.new
347
+ while not argv.empty?
348
+ break if argv.first[0,1] != '-'
349
+
350
+ k = argv.shift
351
+
352
+ if [ '-c', '--csv' ].member? k
353
+ @hash['testset'] = shift(k, argv)
354
+ next
355
+ end
356
+
357
+ if [ '-d', '--dir' ].member? k
358
+ @hash['dir'] = shift(k, argv)
359
+ next
360
+ end
361
+
362
+ if [ '-i', '--interfaces' ].member? k
363
+ @hash['interfaces'] = shift(k, argv)
364
+ next
365
+ end
366
+
367
+ if [ '-h', '--help' ].member? k
368
+ help
369
+ exit
370
+ end
371
+
372
+ if [ '-m', '--mu_string' ].member? k
373
+ mu_string = shift(k, argv)
374
+ if mu_string =~ /(.+?):(.+?)@(.*)/
375
+ @@mu_admin_user = $1
376
+ @@mu_admin_pass = $2
377
+ @@mu_ip = $3
378
+ end
379
+ next
380
+ end
381
+
382
+ if [ '-o', '--output'].member? k
383
+ $stdout.reopen(shift(k, argv), "w")
384
+ next
385
+ end
386
+
387
+ if [ '-p', '--pattern' ].member? k
388
+ patterns = Array.new
389
+ pattern_string = shift(k, argv)
390
+ pstrings = pattern_string.split(",")
391
+ pstrings.each do | p |
392
+ if p =~ /(.+?)-(.+?):(.*)/ # e.g. 1-10000:60
393
+ start_vol = $1
394
+ end_vol = $2
395
+ duration = $3
396
+ patterns << "{\"iterations\":1, \"end\":#{end_vol}, \"start\":#{start_vol}, \"duration\":#{duration} }"
397
+ end
398
+ end
399
+ ps = "{ \"iterations\": 1, \"intervals\": ["
400
+ patterns.each do | p |
401
+ ps = ps + p + ","
402
+ end
403
+ ps = ps[0..ps.length-2] # remove final comma
404
+ ps = ps + "] }"
405
+ @hash['pattern'] = ps
406
+ next
407
+ end
408
+
409
+ if [ '-r', '--recursive'].member? k
410
+ @hash['recursive'] = true
411
+ next
412
+ end
413
+
414
+ if [ '-s', '--scenario' ].member? k
415
+ @hash['scenario'] = shift(k, argv)
416
+ next
417
+ end
418
+
419
+ if [ '-t', '--test' ].member? k
420
+ @hash['test'] = true
421
+ next
422
+ end
423
+
424
+ if [ '-v', '--verbose' ].member? k
425
+ $log.level = Logger::DEBUG
426
+ next
427
+ end
428
+
429
+ raise ArgumentError, "Unknown option #{k}"
430
+ end
431
+
432
+ hash
433
+ end
434
+
435
+ def help
436
+ helps = [
437
+ { :short => '-c', :long => '--csv', :value => '<string>', :help => 'name of the csv testset to run' },
438
+ { :short => '-d', :long => '--dir', :value => '<string>', :help => 'directory containing msl files, required for run_dir' },
439
+ { :short => '-h', :long => '--help', :value => '', :help => 'help on command line options' },
440
+ { :short => '-i', :long => '--interfaces', :value => '<string>', :help => 'comma-separated list of interfaces, e.g. b1,b2 or b1-1000:0,b2 for ip range and offset' },
441
+ { :short => '-m', :long => '--mu_string', :value => '<string>', :help => 'user, password, mu_ip in the form of admin:admin@10.9.8.7' },
442
+ { :short => '-o', :long => '--output', :value => '<string>', :help => 'output logging to this file' },
443
+ { :short => '-p', :long => '--pattern', :value => '<string>', :help => 'pattern in the form of comma-separated concurrency_start-end:duration strings, e.g. 1-10000:60,10000-1:30. Duration is in seconds' },
444
+ { :short => '-r', :long => '--recursive', :value => '', :help => 'for run_dir, recurse through sub-directories' },
445
+ { :short => '-s', :long => '--scenario', :value => '<string>', :help => 'msl file, required for run_msl' },
446
+ { :short => '-t', :long => '--test', :value => '', :help => 'do verify only' },
447
+ { :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' }
448
+ ]
449
+
450
+ cmds = [
451
+ "mu cmd_appid:help",
452
+ "mu cmd_appid:run_file -s <file>",
453
+ "mu cmd_appid:run_dir -d <dir> [-r]",
454
+ "mu cmd_appid:running?"
455
+ ]
456
+
457
+ max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
458
+ max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
459
+ puts
460
+ puts "Usage: mu cmd_appid:<command> <options>"
461
+ puts
462
+ helps.each do |h|
463
+ puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
464
+ end
465
+ puts
466
+ puts "Available Commands"
467
+ puts
468
+ cmds.each do | c |
469
+ puts c
470
+ end
471
+ puts
472
+ puts "Outputs"
473
+ puts
474
+ puts "app_id_stats.csv"
475
+ puts "scenario_name , passed , errors , timeouts,"
476
+ puts "client tx bytes/sec , client tx msgs/sec , client rx bytes/sec , client rx msgs/src,"
477
+ puts "server tx bytes/sec , server tx msgs/sec , server rx bytes/sec , server rx msgs/src"
478
+ puts
479
+ puts "app_id_status.json"
480
+ puts "contains the last status json object returned from polling, per scenario"
481
+ end
482
+
483
+ end
484
+ end # Command
485
+ end # Mu
486
+