mu 5.7.9 → 5.7.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,7 +59,7 @@ class Mu
59
59
  # Get har object and hosts
60
60
  har_file = @options.har_files[0]
61
61
  @har = Har.new har_file, @options, @ignores
62
- msl_file = File.open(@options.scenario,'w')
62
+ msl_file = File.open(@options.scenario,'w')
63
63
  created_musl = @har.generate msl_file
64
64
  msl_file.write created_musl
65
65
  msl_file.close
@@ -131,9 +131,9 @@ class Mu
131
131
  @options.strip_large_content = true
132
132
  @options.large_content_size = size
133
133
  end
134
- @opts.on( '--endpoint', 'One way communication' ) do
135
- @options.endpoint = true
136
- end
134
+ #@opts.on( '--endpoint', 'One way communication' ) do
135
+ # @options.endpoint = true
136
+ #end
137
137
  @opts.on( '-s', '--scenario [FILENAME]', 'Specify the msl filename to be created' ) do |scenario|
138
138
  @options.scenario = scenario
139
139
  end
@@ -15,79 +15,6 @@ class Mu
15
15
  help
16
16
  end
17
17
 
18
- # sets up, executes, and closes a Studio Scale test
19
- # * argv = command-line arguments , requires a scenario (-s) argument
20
- def cmd_run_file argv
21
- puts "\n***WARNING***\nThe following commands will be deprecated in a future release:"
22
- puts "cmd_runscale:run_file, cmd_runscale:run_dir, cmd_appid\n"
23
- puts "Please use 'cmd_runscale:run_files'"
24
- setup argv
25
-
26
- if not @hash['scenario']
27
- msg "scenario required", Logger::ERROR
28
- return help
29
- else
30
- if @hash['scenario'].include?(".msl")
31
- scenario = @hash['scenario']
32
- else # TODO: eventually, xml and mus file may be supported by scale api
33
- msg "only .msl files are currently supported", Logger::ERROR
34
- return help
35
- end
36
- end
37
-
38
- if not File.readable?(scenario)
39
- msg "*** Error: can't read scenario file #{scenario}", Logger::ERROR
40
- return
41
- end
42
-
43
- @api = Scale.new(@@mu_ip, @@mu_admin_user, @@mu_admin_pass)
44
- @api.configure("pattern", @cmd_line_pattern)
45
- @params = {}
46
- @params["dir"] = @dir
47
- @params["msl"] = scenario
48
- @params["hosts"] = @cmd_line_hosts
49
- run(scenario)
50
- @api.release
51
- end
52
-
53
- # sets up, executes, and closes a Studio Scale test for each scenario (.msl file) found in the specified directory
54
- # * argv = command-line arguments, requires a directory (-d) argument
55
- # * optional -r argument for recursive directory search (default is a flat directory)
56
- def cmd_run_dir argv
57
- puts "\n***WARNING***\nThe following commands will be deprecated in a future release:"
58
- puts "cmd_runscale:run_file, cmd_runscale:run_dir, cmd_appid\n"
59
- puts "Please use 'cmd_runscale:run_files'"
60
- setup argv
61
-
62
- if not @hash['dir']
63
- return help
64
- else
65
- @dir = @hash['dir']
66
- end
67
-
68
- msg "Clean up existing stats files: app_id_status.json, app_id_stats.csv", Logger::INFO
69
- File.delete("app_id_status.json") if File.exists?("app_id_status.json")
70
- File.delete("app_id_stats.csv") if File.exists?("app_id_stats.csv")
71
-
72
- @api = Scale.new(@@mu_ip, @@mu_admin_user, @@mu_admin_pass)
73
- @api.configure("pattern", @cmd_line_pattern)
74
- @params = {}
75
- @params["dir"] = @dir
76
- @params["hosts"] = @cmd_line_hosts
77
- recursive = (@hash['recursive'].nil?) ? "": "**"
78
- files = Dir.glob(File.join(@dir,recursive,"*.msl"))
79
- if !files.empty?
80
- files.sort.each do | f |
81
- run(f)
82
- output_csv(f)
83
- sleep 2
84
- end
85
- else
86
- msg "no msl files found in #{@dir}", Logger::ERROR
87
- end
88
- @api.release
89
- end
90
-
91
18
  # sets up, executes, and closes a Studio Scale test for one scenario or each scenario (.msl file) found in the specified directory
92
19
  # * argv = command-line arguments
93
20
  # * optional -s scenario file
@@ -606,19 +533,12 @@ class Mu
606
533
  cmds = [
607
534
  "mu cmd_runscale:help",
608
535
  "mu cmd_runscale:run_files -s <scenario>|-d <scenario_directory> --recursive -i <hosts, e.g. a1,dell-9> -p <pattern, e.g. 1-1000:30>",
609
- "mu cmd_runscale:run_file -s <scenario> -i <hosts, e.g. a1,dell-9> -p <pattern, e.g. 1-1000:30>",
610
- "mu cmd_runscale:run_dir -d <scenario_directory>",
611
536
  "mu cmd_runscale:running?"
612
537
  ]
613
538
 
614
539
  max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
615
540
  max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
616
- puts
617
- puts "Usage: mu cmd_runscale:<command> <options>"
618
- puts "\n***WARNING***\nThe following commands will be deprecated in a future release:"
619
- puts "cmd_runscale:run_file, cmd_runscale:run_dir, cmd_appid\n"
620
- puts "Please use 'cmd_runscale:run_files'"
621
- puts
541
+
622
542
  helps.each do |h|
623
543
  puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
624
544
  end
@@ -6,7 +6,6 @@ class Help < Command
6
6
  puts "Usage: mu <command>:<option>"
7
7
  helps = [
8
8
  { :cmd => 'mu help', :help => "Display this help" },
9
- { :cmd => 'mu cmd_appid:help', :help => 'Show help on using the appid application for running multi-host msl files at scale'},
10
9
  { :cmd => 'mu cmd_cli:help', :help => 'Show help on using the Mu CLI Api through the command-line' },
11
10
  { :cmd => 'mu cmd_ddt:help', :help => 'Show help on using the Studio Verify Api through the command-line' },
12
11
  { :cmd => 'mu cmd_homepage:help', :help => 'Show help on using the Homepage Api through the command-line' },
@@ -1,7 +1,6 @@
1
1
  # To change this template, choose Tools | Templates
2
2
  # and open the template in the editor.
3
3
  require 'mu/maker'
4
- require 'mu/xmlizable'
5
4
 
6
5
  class Har
7
6
  HTTP_CONTENT_LENGTH_HEADER = 'Content-Length'
@@ -48,10 +47,6 @@ class Har
48
47
 
49
48
  HTTP_CONTENT_SLICE_SIZE = 1024
50
49
 
51
- MSL_ESCAPES = XMLizable::ESCAPES.dup
52
- MSL_ESCAPES['"'.ord] = %q{\"}
53
- MSL_ESCAPES["'".ord] = %q{\'}
54
-
55
50
 
56
51
  attr_reader :har_file
57
52
  attr_accessor :entries,:hosts,:har,:har_hosts
@@ -64,6 +59,7 @@ class Har
64
59
  begin
65
60
  @har = JSON File.read(@har_file)
66
61
  rescue Exception=>e
62
+ puts "There was an error reading the JSON har file, probably a parsing problem"
67
63
  raise e
68
64
  end
69
65
 
@@ -186,8 +182,7 @@ class Har
186
182
  # If this is a Cookie header, try and map the cookie
187
183
  # value to a step variable preceding this step
188
184
  if ('cookie' === header['name'].downcase)
189
- #value = header['value']
190
- value = XMLizable.escape(header['value'], MSL_ESCAPES)
185
+ value = self.escape(header['value'])
191
186
  for j in 0..cookies.length
192
187
  cookie = cookies[j]
193
188
 
@@ -298,7 +293,7 @@ class Har
298
293
  end # end steps.client_send
299
294
 
300
295
  # Skip the server side if the command line option included --endpint
301
- unless @options.endpoint
296
+ #unless @options.endpoint
302
297
  steps.server_receive("sr#{entry_count}", "cs#{entry_count}") do ||
303
298
  #return nil
304
299
  end
@@ -319,7 +314,7 @@ class Har
319
314
  build_payload ss, entry_count, res, scenario
320
315
  end unless @options.ignore_payload
321
316
  end # end server_send
322
- end
317
+ #end
323
318
 
324
319
  # If the endpoint option is chosen only include cs 'client send' values instead of ss 'server send' values
325
320
  receive_side = @options.endpoint ? 'cs' : 'ss'
@@ -419,7 +414,7 @@ class Har
419
414
  end
420
415
  cs_send.literal_no_format("\"");
421
416
  else
422
- cs_send.literal_no_format("\"" + XMLizable.escape(payload, MSL_ESCAPES) + "\"")
417
+ cs_send.literal_no_format("\"" + self.escape(payload) + "\"")
423
418
  end
424
419
 
425
420
 
@@ -446,4 +441,28 @@ class Har
446
441
  not @content_transfer_encoding.to_s == 'binary' and
447
442
  not @mu_content_transfer_encoding.to_s == 'binary'
448
443
  end
444
+
445
+ ESCAPES= Array.new 256 do |i|
446
+ case i
447
+ when 9; "\\t".freeze
448
+ when 13; "\\r".freeze
449
+ when 92; "\\\\".freeze
450
+ when 10; "\\n".freeze
451
+ when 32..126; i.chr.freeze
452
+ else ; ('\x%02x' % i).freeze
453
+ end
454
+ end
455
+ ESCAPES['"'.ord] = %q{\"}
456
+ ESCAPES["'".ord] = %q{\'}
457
+ ESCAPES.freeze
458
+
459
+ # Takes input and a table that maps ascii codes to their representation
460
+ def escape input, escapes=nil
461
+ escapes ||= ESCAPES
462
+ output = []
463
+ input.each_byte do |i|
464
+ output << escapes[i]
465
+ end
466
+ output.join
467
+ end
449
468
  end
@@ -85,10 +85,6 @@ class Maker
85
85
  def escape text
86
86
  text.gsub(/\\/, '\\\\').gsub(/\r/, '\\r').gsub(/\n/, '\\n').gsub(/"/, '\\"')
87
87
  end
88
-
89
- def escape_payload text
90
- text.gsub(/\\/, '\\\\\\').gsub(/\r/, '\\r').gsub(/\n/, '\\n').gsub(/"/, '\\"')
91
- end
92
88
 
93
89
  def attrs kvs = {}
94
90
  return '' if kvs.empty?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mu
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.7.9
4
+ version: 5.7.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-04-08 00:00:00.000000000 -07:00
12
+ date: 2011-04-12 00:00:00.000000000 -07:00
13
13
  default_executable: mu
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
17
- requirement: &3242700 !ruby/object:Gem::Requirement
17
+ requirement: &18971320 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 1.0.0
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *3242700
25
+ version_requirements: *18971320
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: jeweler
28
- requirement: &3241120 !ruby/object:Gem::Requirement
28
+ requirement: &18969320 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ~>
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 1.5.1
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *3241120
36
+ version_requirements: *18969320
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rcov
39
- requirement: &3239300 !ruby/object:Gem::Requirement
39
+ requirement: &18968360 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *3239300
47
+ version_requirements: *18968360
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: nokogiri
50
- requirement: &3237320 !ruby/object:Gem::Requirement
50
+ requirement: &18964500 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: 1.4.4
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *3237320
58
+ version_requirements: *18964500
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: rest-client
61
- requirement: &3236020 !ruby/object:Gem::Requirement
61
+ requirement: &18963660 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: 1.6.1
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *3236020
69
+ version_requirements: *18963660
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: mime-types
72
- requirement: &3234040 !ruby/object:Gem::Requirement
72
+ requirement: &18958760 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: '1.16'
78
78
  type: :runtime
79
79
  prerelease: false
80
- version_requirements: *3234040
80
+ version_requirements: *18958760
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: json_pure
83
- requirement: &3228980 !ruby/object:Gem::Requirement
83
+ requirement: &18957600 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ! '>='
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: 1.4.6
89
89
  type: :runtime
90
90
  prerelease: false
91
- version_requirements: *3228980
91
+ version_requirements: *18957600
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: hexy
94
- requirement: &3225480 !ruby/object:Gem::Requirement
94
+ requirement: &18956640 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ! '>='
@@ -99,7 +99,7 @@ dependencies:
99
99
  version: 0.1.1
100
100
  type: :runtime
101
101
  prerelease: false
102
- version_requirements: *3225480
102
+ version_requirements: *18956640
103
103
  description: general purpose mu gem
104
104
  email: bwilkerson@mudynamics.com
105
105
  executables:
@@ -117,7 +117,6 @@ files:
117
117
  - lib/mu/client.rb
118
118
  - lib/mu/command.rb
119
119
  - lib/mu/command/api.rb
120
- - lib/mu/command/cmd_appid.rb
121
120
  - lib/mu/command/cmd_cli.rb
122
121
  - lib/mu/command/cmd_ddt.rb
123
122
  - lib/mu/command/cmd_homepage.rb
@@ -136,9 +135,7 @@ files:
136
135
  - lib/mu/har.rb
137
136
  - lib/mu/helper.rb
138
137
  - lib/mu/http_helper.rb
139
- - lib/mu/libxml.rb
140
138
  - lib/mu/maker.rb
141
- - lib/mu/xmlizable.rb
142
139
  - bin/mu
143
140
  has_rdoc: true
144
141
  homepage: http://www.mudynamics.com
@@ -156,7 +153,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
153
  version: '0'
157
154
  segments:
158
155
  - 0
159
- hash: -3112838323153453610
156
+ hash: -973453883911657948
160
157
  required_rubygems_version: !ruby/object:Gem::Requirement
161
158
  none: false
162
159
  requirements:
@@ -1,531 +0,0 @@
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
- puts "\n***WARNING***\nThe following commands will be deprecated in a future release:"
39
- puts "cmd_runscale:run_file, cmd_runscale:run_dir, cmd_appid\n"
40
- puts "Please use 'cmd_runscale:run_files'"
41
- setup argv
42
-
43
- if not @hash['scenario']
44
- raise "*** Error: scenario required, using -s option"
45
- else
46
- scenario = @hash['scenario']
47
- end
48
-
49
- if !File.exists?(scenario)
50
- raise "*** Error: Scenario file #{scenario} was not found"
51
- end
52
-
53
- File.delete("app_id_status.json") if File.exists?("app_id_status.json")
54
- File.delete("app_id_stats.csv") if File.exists?("app_id_stats.csv")
55
-
56
- @api = Scale.new(@@mu_ip, @@mu_admin_user, @@mu_admin_pass)
57
- @api.configure("pattern", @cmd_line_pattern)
58
- @params = {}
59
- @params["msl"] = scenario
60
- @params["hosts"] = @cmd_line_hosts
61
- run(scenario)
62
- @api.release
63
- end
64
-
65
- # runs through a directory of msl files and executes a Studio Scale test for each one
66
- # * argv = command-line arguments, require a directory (-d) argument
67
- # * optional -r argument for recursive directory search (default is a flat directory)
68
- def cmd_run_dir argv
69
- puts "\n***WARNING***\nThe following commands will be deprecated in a future release:"
70
- puts "cmd_runscale:run_file, cmd_runscale:run_dir, cmd_appid\n"
71
- puts "Please use 'cmd_runscale:run_files'"
72
- setup argv
73
-
74
- if not @hash['dir']
75
- raise "*** Error: directory required, using -d option"
76
- else
77
- dir = @hash['dir']
78
- end
79
-
80
- File.delete("app_id_status.json") if File.exists?("app_id_status.json")
81
- File.delete("app_id_stats.csv") if File.exists?("app_id_stats.csv")
82
-
83
- @api = Scale.new(@@mu_ip, @@mu_admin_user, @@mu_admin_pass)
84
- @api.configure("pattern", @cmd_line_pattern)
85
- @params = {}
86
- @params["dir"] = dir
87
- @params["hosts"] = @cmd_line_hosts
88
- Dir.chdir(@params["dir"])
89
- File.delete("app_id_status.json") if File.exists?("app_id_status.json")
90
- if @hash['recursive'].nil?
91
- files = Dir.glob("*.msl")
92
- else
93
- files = Dir.glob("**/*.msl")
94
- end
95
- if !files.empty?
96
- files.sort.each do | f |
97
- run(f)
98
- output_csv(f)
99
- sleep 2
100
- end
101
- else
102
- msg "no msl files found in #{dir}"
103
- end
104
- @api.release
105
- end
106
-
107
- private
108
-
109
- def setup argv
110
- parse_cli argv
111
- @params = {}
112
- @peak_throughput = 0.0
113
-
114
- if @hash['test']
115
- @verify_only = true
116
- else
117
- @verify_only = false
118
- end
119
-
120
- if not @hash['pattern']
121
- @cmd_line_pattern = "{ \"iterations\": 1, \"intervals\": [ {\"iterations\":1, \"end\":100, \"start\":1, \"duration\":20 } ] }"
122
- else
123
- @cmd_line_pattern = @hash['pattern']
124
- end
125
-
126
- if not @hash['interfaces']
127
- @cmd_line_hosts = "b1,b2"
128
- else
129
- @cmd_line_hosts = @hash['interfaces']
130
- end
131
-
132
- if not @hash['testset']
133
- @testset = ""
134
- else
135
- @testset = @hash['testset']
136
- end
137
-
138
- if not @hash['delay']
139
- @delay = 0
140
- else
141
- @delay = @hash['delay'].to_i
142
- end
143
-
144
- if not @hash['no_verify']
145
- @no_verify = false
146
- else
147
- @no_verify = true
148
- end
149
-
150
- end
151
-
152
- def run(msl)
153
- if !File.exists?(msl)
154
- return "file not found: #{msl}"
155
- end
156
-
157
- @api.configure("musl", File.read(msl))
158
-
159
- unless @testset.empty?
160
- if @testset.include?("/") # assume it is the full path in this case
161
- csv_file = @testset
162
- else
163
- csv_file = @params["dir"] + "/" + @testset
164
- end
165
- @api.configure("csv", File.read(csv_file))
166
- end
167
-
168
- set_global_hosts
169
- all_hosts = get_all_hosts_from_musl(msl)
170
- @hosts_config = map_all_hosts_to_json(all_hosts)
171
- @api.configure("hosts", @hosts_config)
172
- @api.configure("delay", @delay)
173
- if @no_verify == false # don't do verify if no_verify==true
174
- msg "verifying #{msl} ..."
175
- response = @api.verify
176
- # sleep 3
177
- v = parse_verify_response(response)
178
- if v.nil?
179
- msg "error in verify"
180
- return
181
- end
182
- if @verify_only
183
- msg v
184
- return
185
- end
186
- end
187
- msg "starting #{msl} ..."
188
- @api.start
189
- start_time = Time.now.to_i
190
- while true
191
- sleep 5
192
- status = @api.status
193
- if !status.nil?
194
- if !status["status"].nil?
195
- if status["status"]["running"] == false
196
- msg "running = #{status["status"]["running"]}", Logger::DEBUG
197
- r = parse_status(status)
198
- dump_status(status, msl)
199
- return
200
- else
201
- r = parse_status(status)
202
- end
203
- else # status['status'].nil? ... no bonafide status was returned
204
- time_now = Time.now.to_i
205
- if time_now - start_time > 20
206
- # puts "\nError: timing out after 20 seconds. Test had failed to start or verify"
207
- break
208
- end
209
- end
210
- end
211
- end
212
- ensure
213
- msg "stopping #{msl} ..."
214
- end
215
-
216
- def set_global_hosts
217
- @hosts = Array.new
218
- @addr_indexes = Array.new
219
- hosts = @params["hosts"]
220
- if !hosts.nil?
221
- p = hosts.split(",")
222
- p.each do | h |
223
- if h.include?("-") # b1-1000,b2-1 to indicate addr_count
224
- q = h.split("-")
225
- @hosts << q[0]
226
- @addr_indexes << q[1]
227
- else # default to the 1st addr index
228
- @hosts << h
229
- @addr_indexes << 1
230
- end
231
- end
232
- else
233
- @hosts = ['b1','b2']
234
- @addr_indexes = [1,1]
235
- end
236
- end
237
-
238
- def dump_status(status, msl)
239
- filename = "app_id_status.json"
240
- f = File.open(filename, "a")
241
- status["filename"] = msl
242
- str = JSON.pretty_generate(status)
243
- f.write(",") if !File.zero?(f) # if appending, we need to insert a comma
244
- f.write(str)
245
- f.close
246
- end
247
-
248
- def output_csv(msl_file)
249
- filename = "app_id_stats.csv"
250
- 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"
251
- File.open(filename, File::RDWR|File::TRUNC|File::CREAT) {|f| f.write(doc) }
252
- end
253
-
254
- # finds all the hosts in the musl file
255
- def get_all_hosts_from_musl(msl)
256
- f = IO.read(msl)
257
- hosts = f.scan(/host_\d+/)
258
- hosts.uniq!
259
- return hosts
260
- end
261
-
262
- # maps host_0 to the client interface
263
- # maps all other hosts to the server interface
264
- def map_all_hosts_to_json(hosts=[])
265
- new_hosts = Array.new
266
- hosts.each_with_index do | h, i |
267
- if i == 0
268
- new_hosts << @hosts[0] + "/*,#{@addr_indexes[0]}"
269
- else
270
- new_hosts << @hosts[1] + "/*,#{@addr_indexes[1]}"
271
- end
272
- end
273
-
274
- hosts_config = {}
275
-
276
- # assign hosts to consecutive string keys, host_0, host_1, etc ...
277
- new_hosts.each_with_index do | h, i |
278
- hosts_config["host_#{i}"] = h # new_hosts[i]
279
- end
280
-
281
- # convert keys to symbols
282
- new_hosts_config = {}
283
- hosts_config.each_key { |k| new_hosts_config[k.to_sym] = hosts_config[k] }
284
-
285
- return new_hosts_config
286
- end
287
-
288
- def parse_verify_response(response)
289
- if response.nil? # || response.empty?
290
- msg "*** error = no response received from /verify ***\n\n"
291
- return nil
292
- end
293
- begin
294
- msg JSON.pretty_generate(response), Logger::DEBUG
295
- if !response["status"].nil?
296
- if response["status"]["error"] == true
297
- @error = response["status"]["error"]
298
- @reason = response["status"]["reason"]
299
- dump_status(response)
300
- msg "*** Error = #{@error}, reason = #{@reason} ***\n\n"
301
- return nil
302
- end
303
- end
304
- msg "*** verify: okay ***", Logger::DEBUG
305
- return "*** verify: okay ***"
306
- rescue
307
- # could nbe json parse error
308
- return nil
309
- end
310
- end
311
-
312
- def parse_status(status)
313
- return nil if status.nil?
314
- msg JSON.pretty_generate(status), Logger::DEBUG
315
- @reported_volume = 0
316
- if !status["status"]["error"].nil?
317
- if status["status"]["error"] == true
318
- @error = status["status"]["error"]
319
- @reason = status["status"]["reason"]
320
- # puts "*** Error = #{@error}, reason = #{@reason} ***\n\n"
321
- return nil
322
- end
323
- end
324
-
325
- @stats_summary = status["status"]["statistics"]["summary"]
326
- @duration = @stats_summary["duration"]
327
- @instances = @stats_summary["instances"]
328
- @total_instances = @instances["total"]
329
- @executed = @instances["executed"]
330
- @timeouts = @instances["timeouts"]
331
- @errors = @instances["errors"]
332
- @asserts_failed = @stats_summary["asserts"]["failed"]
333
- @server = @stats_summary["server"]
334
- @server_tx_bytes = @server["tx"]["bytes"]
335
- @server_tx_msgs = @server["tx"]["msgs"]
336
- @server_rx_bytes = @server["rx"]["bytes"]
337
- @server_rx_msgs = @server["rx"]["msgs"]
338
- @client = @stats_summary["client"]
339
- @client_tx_bytes = @client["tx"]["bytes"]
340
- @client_tx_msgs = @client["tx"]["msgs"]
341
- @client_rx_bytes = @client["rx"]["bytes"]
342
- @client_rx_msgs = @client["rx"]["msgs"]
343
- @scenarios = status["status"]["statistics"]["scenarios"]
344
- @scenarios.each do | scenario |
345
- @reported_volume = @reported_volume + scenario["volume"]
346
- end
347
-
348
- bits1 = (@client_tx_bytes.to_i + @client_rx_bytes.to_i) * 8
349
- dur1 = @duration.to_f
350
- thruput = format_float(2, bits1.to_f / dur1)
351
-
352
- if thruput.to_f > @peak_throughput
353
- @peak_throughput = thruput.to_f
354
- end
355
-
356
- msg ""
357
- msg "duration: #{format_float(2, @duration)}"
358
- msg "concurrency: #{@reported_volume}"
359
- msg "tests/sec: #{format_float(2, @executed.to_f / @duration)}" if @duration.to_i > 0
360
- msg "bits/sec: #{thruput}" if @duration.to_i > 0
361
- msg "passed: #{@executed}"
362
- msg "errors: #{@errors}"
363
- msg "timeouts: #{@timeouts}"
364
- msg "client tx bytes/sec #{format_float(2, @client_tx_bytes.to_f / @duration)}" if @duration.to_i > 0
365
- msg "client tx msgs/sec #{format_float(2, @client_tx_msgs.to_f / @duration)}" if @duration.to_i > 0
366
- msg "client rx bytes/sec #{format_float(2, @client_rx_bytes.to_f / @duration)}" if @duration.to_i > 0
367
- msg "client rx msgs/sec #{format_float(2, @client_rx_msgs.to_f / @duration)}" if @duration.to_i > 0
368
- msg "server tx bytes/sec #{format_float(2, @server_tx_bytes.to_f / @duration)}" if @duration.to_i > 0
369
- msg "server tx msgs/sec #{format_float(2, @server_tx_msgs.to_f / @duration)}" if @duration.to_i > 0
370
- msg "server rx bytes/sec #{format_float(2, @server_rx_bytes.to_f / @duration)}" if @duration.to_i > 0
371
- msg "server rx msgs/sec #{format_float(2, @server_rx_msgs.to_f / @duration)}" if @duration.to_i > 0
372
- msg ""
373
- end
374
-
375
- def parse_cli argv
376
- @hash = Hash.new
377
- while not argv.empty?
378
- break if argv.first[0,1] != '-'
379
-
380
- k = argv.shift
381
-
382
- if [ '-c', '--csv' ].member? k
383
- @hash['testset'] = shift(k, argv)
384
- next
385
- end
386
-
387
- if [ '-d', '--dir' ].member? k
388
- @hash['dir'] = shift(k, argv)
389
- next
390
- end
391
-
392
- if [ '-i', '--interfaces' ].member? k
393
- @hash['interfaces'] = shift(k, argv)
394
- next
395
- end
396
-
397
- if [ '-h', '--help' ].member? k
398
- help
399
- exit
400
- end
401
-
402
- if [ '-l', '--delay' ].member? k
403
- @hash['delay'] = shift(k, argv)
404
- next
405
- end
406
-
407
- if [ '-m', '--mu_string' ].member? k
408
- mu_string = shift(k, argv)
409
- if mu_string =~ /(.+?):(.+?)@(.*)/
410
- @@mu_admin_user = $1
411
- @@mu_admin_pass = $2
412
- @@mu_ip = $3
413
- end
414
- next
415
- end
416
-
417
- if [ '-n', '--no_verify' ].member? k
418
- @hash['no_verify'] = true
419
- next
420
- end
421
-
422
- if [ '-o', '--output'].member? k
423
- $stdout.reopen(shift(k, argv), "w")
424
- next
425
- end
426
-
427
- if [ '-p', '--pattern' ].member? k
428
- patterns = Array.new
429
- pattern_string = shift(k, argv)
430
- pstrings = pattern_string.split(",")
431
- pstrings.each do | p |
432
- if p =~ /(.+?)-(.+?):(.*)/ # e.g. 1-10000:60
433
- start_vol = $1
434
- end_vol = $2
435
- duration = $3
436
- patterns << "{\"iterations\":1, \"end\":#{end_vol}, \"start\":#{start_vol}, \"duration\":#{duration} }"
437
- end
438
- end
439
- ps = "{ \"iterations\": 1, \"intervals\": ["
440
- patterns.each do | p |
441
- ps = ps + p + ","
442
- end
443
- ps = ps[0..ps.length-2] # remove final comma
444
- ps = ps + "] }"
445
- @hash['pattern'] = ps
446
- next
447
- end
448
-
449
- if [ '-r', '--recursive'].member? k
450
- @hash['recursive'] = true
451
- next
452
- end
453
-
454
- if [ '-s', '--scenario' ].member? k
455
- @hash['scenario'] = shift(k, argv)
456
- next
457
- end
458
-
459
- if [ '-t', '--test' ].member? k
460
- @hash['test'] = true
461
- next
462
- end
463
-
464
- if [ '-v', '--verbose' ].member? k
465
- $log.level = Logger::DEBUG
466
- next
467
- end
468
-
469
- raise ArgumentError, "Unknown option #{k}"
470
- end
471
-
472
- hash
473
- end
474
-
475
- def help
476
- helps = [
477
- { :short => '-c', :long => '--csv', :value => '<string>', :help => 'name of the csv testset to run' },
478
- { :short => '-d', :long => '--dir', :value => '<string>', :help => 'directory containing msl files, required for run_dir' },
479
- { :short => '-h', :long => '--help', :value => '', :help => 'help on command line options' },
480
- { :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' },
481
- { :short => '-l', :long => '--delay', :value => '<string>', :help => 'intra-scenario delay value' },
482
- { :short => '-m', :long => '--mu_string', :value => '<string>', :help => 'user, password, mu_ip in the form of admin:admin@10.9.8.7' },
483
- { :short => '-n', :long => '--no_verify', :value => '', :help => 'do not do verify before start' },
484
- { :short => '-o', :long => '--output', :value => '<string>', :help => 'output logging to this file' },
485
- { :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' },
486
- { :short => '-r', :long => '--recursive', :value => '', :help => 'for run_dir, recurse through sub-directories' },
487
- { :short => '-s', :long => '--scenario', :value => '<string>', :help => 'msl file, required for run_msl' },
488
- { :short => '-t', :long => '--test', :value => '', :help => 'do verify only' },
489
- { :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' }
490
- ]
491
-
492
- cmds = [
493
- "mu cmd_appid:help",
494
- "mu cmd_appid:run_file -s <file>",
495
- "mu cmd_appid:run_dir -d <dir> [-r]",
496
- "mu cmd_appid:running?"
497
- ]
498
-
499
- max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
500
- max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
501
- puts "\n***WARNING***\nThe following commands will be deprecated in a future release:"
502
- puts "cmd_runscale:run_file, cmd_runscale:run_dir, cmd_appid\n"
503
- puts "Please use 'cmd_runscale:run_files'"
504
- puts
505
- puts "Usage: mu cmd_appid:<command> <options>"
506
- puts
507
- helps.each do |h|
508
- puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
509
- end
510
- puts
511
- puts "Available Commands"
512
- puts
513
- cmds.each do | c |
514
- puts c
515
- end
516
- puts
517
- puts "Outputs"
518
- puts
519
- puts "app_id_stats.csv"
520
- puts "scenario_name , passed , errors , timeouts,"
521
- puts "client tx bytes/sec , client tx msgs/sec , client rx bytes/sec , client rx msgs/src,"
522
- puts "server tx bytes/sec , server tx msgs/sec , server rx bytes/sec , server rx msgs/src"
523
- puts
524
- puts "app_id_status.json"
525
- puts "contains the last status json object returned from polling, per scenario"
526
- end
527
-
528
- end
529
- end # Command
530
- end # Mu
531
-