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,262 @@
1
+ # Use these commands to access the legacy REST API for configuring Mu interfaces, network hosts, and routes
2
+ require 'mu/api/netconfig'
3
+ class Mu
4
+ class Command
5
+ class Cmd_netconfig < Command
6
+
7
+ attr_accessor :host, :username, :password, :api
8
+
9
+ # displays command-line help
10
+ def cmd_help argv
11
+ help
12
+ end
13
+
14
+ # returns a json representation of the specified element
15
+ # * argv = command-line arguments, requires an element (-e) argument, such as 'interfaces', 'hosts' or 'routes' or 'interfaces/a1' or 'hosts/dell-9'
16
+ def cmd_get argv
17
+ setup argv
18
+ e = @hash['element']
19
+ response = @api.get(e)
20
+ msg JSON.pretty_generate(response)
21
+ return response
22
+ end
23
+
24
+ # modifies a network element
25
+ # * argv = command-line arguments, requires a json configuration (-j) and the element (-e) to modify, such as 'interfaces', 'hosts' or 'routes' or 'interfaces/a1' or 'hosts/dell-9'
26
+ def cmd_modify argv
27
+ setup argv
28
+ json = @hash['json']
29
+ e = @hash['element']
30
+ response = @api.modify(json, e)
31
+ msg response
32
+ return response
33
+ end
34
+
35
+
36
+ # creates a new network element
37
+ # * argv = command-line arguments, requires a json configuration (-j) and the element (-e) to modify, such as 'interfaces', 'hosts' or 'routes'
38
+ def cmd_create argv
39
+ setup argv
40
+ json = @hash['json']
41
+ e = @hash['element']
42
+ response = @api.create(json, e)
43
+ msg response
44
+ return response
45
+ end
46
+
47
+ # deletes an existing network element
48
+ # * argv = command-line arguments, requires a json configuration (-j) and the element (-e) to modify, such as 'interfaces', 'hosts' or 'routes' or 'interfaces/a1' or 'hosts/dell-9'
49
+ def cmd_delete argv
50
+ setup argv
51
+ e = @hash['element']
52
+ response = @api.delete(e)
53
+ msg response
54
+ return response
55
+ end
56
+
57
+ # restores the network configuration from a file
58
+ # * argv = command-line arguments, requires a path to a json configuration file (-f) , and a boolean (-b true|false) argument indicating whether or not existing elements should be cleared
59
+ def cmd_restore argv
60
+ setup argv
61
+ filepath = @hash['filepath']
62
+ clear_existing = to_boolean(@hash['boolean'])
63
+ response = @api.restore(filepath, clear_existing)
64
+ msg response
65
+ return response
66
+ end
67
+
68
+ # clears existing network configuration hosts
69
+ # * argv = command-line arguments
70
+ def cmd_clear_hosts argv
71
+ setup argv
72
+ response = @api.clear_hosts
73
+ msg JSON.pretty_generate(response)
74
+ return response
75
+ end
76
+
77
+ # resolves network configuration hosts
78
+ # * argv = command-line arguments, requires the name (-n) of the host to resolve (determines its ip address and adds it to the network configuration)
79
+ def cmd_resolve_hosts argv
80
+ setup argv
81
+ name = @hash['name']
82
+ response = @api.resolve_hosts(name)
83
+ msg response
84
+ return response
85
+ end
86
+
87
+ # clears existing network interfaces
88
+ # * argv = command-line arguments, require the names of the interfaces to clear (-i name)
89
+ def cmd_clear_interface argv
90
+ setup argv
91
+ interface = @hash['interfaces']
92
+ response = @api.clear_interface(interface)
93
+ msg response
94
+ return response
95
+ end
96
+
97
+ # clears existing vlan configurations
98
+ # * argv = command-line arguments
99
+ def cmd_clear_vlans argv
100
+ setup argv
101
+ response = @api.clear_vlans
102
+ msg response
103
+ return response
104
+ end
105
+
106
+ # clears existing network routes
107
+ # * argv = command-line arguments
108
+ def cmd_clear_routes argv
109
+ setup argv
110
+ response = @api.clear_routes
111
+ msg response
112
+ return response
113
+ end
114
+
115
+
116
+ # saves the network configuration to a file
117
+ # * argv = command-line arguments, requires the element (-e element, such as 'interfaces', or -e all) to save, and a file name (-f) to save the settings to
118
+ def cmd_save argv
119
+ setup argv
120
+ e = @hash['elements']
121
+ filepath = @hash['filepath'] || "config.json"
122
+ response = @api.save(e, filepath)
123
+ msg response
124
+ return response
125
+ end
126
+
127
+ private
128
+
129
+ def setup argv
130
+ parse_cli argv
131
+ @host = (@@mu_ip.nil?) ? "127.0.0.1" : @@mu_ip
132
+ @username = (@@mu_admin_user.nil?) ? "admin" : @@mu_admin_user
133
+ @password = (@@mu_admin_pass.nil?) ? "admin" : @@mu_admin_pass
134
+ @response = nil
135
+ @element = "" # sticky variable will hold a default element, the last element specified
136
+ @api = Netconfig.new(@host, @username, @password)
137
+ msg "Created Netconfig API object to :#{@host}", Logger::DEBUG
138
+ end
139
+
140
+ def parse_cli argv
141
+ args = Array.new
142
+ @hash = {}
143
+ while not argv.empty?
144
+ args << argv.shift if argv.first[0,1] != '-'
145
+
146
+ k = argv.shift
147
+
148
+ if [ '-b', '--boolean' ].member? k
149
+ @hash['boolean'] = shift(k, argv)
150
+ next
151
+ end
152
+
153
+ if [ '-e', '--element' ].member? k
154
+ @hash['element'] = shift(k, argv)
155
+ next
156
+ end
157
+
158
+ if [ '-f', '--filepath' ].member? k
159
+ @hash['filepath'] = shift(k, argv)
160
+ next
161
+ end
162
+
163
+ if [ '-h', '--help' ].member? k
164
+ help
165
+ exit
166
+ end
167
+
168
+ if [ '-i', '--interfaces' ].member? k
169
+ @hash['interfaces'] = shift(k, argv)
170
+ next
171
+ end
172
+
173
+ if [ '-j', '--json' ].member? k
174
+ @hash['json'] = shift(k, argv)
175
+ next
176
+ end
177
+
178
+ if [ '-m', '--mu_string' ].member? k
179
+ mu_string = shift(k, argv)
180
+ if mu_string =~ /(.+?):(.+?)@(.*)/
181
+ @@mu_admin_user = $1
182
+ @@mu_admin_pass = $2
183
+ @@mu_ip = $3
184
+ end
185
+ next
186
+ end
187
+
188
+ if [ '-n', '--name' ].member? k
189
+ @hash['name'] = shift(k, argv)
190
+ next
191
+ end
192
+
193
+ if [ '-o', '--output' ].member? k
194
+ $stdout.reopen(shift(k, argv), "w")
195
+ next
196
+ end
197
+
198
+ if [ '-r', '--routes' ].member? k
199
+ @hash['routes'] = shift(k, argv)
200
+ next
201
+ end
202
+
203
+ if [ '-v', '--verbose' ].member? k
204
+ $log.level = Logger::DEBUG
205
+ next
206
+ end
207
+ end
208
+
209
+ args
210
+ end
211
+
212
+ def help
213
+ helps = [
214
+ { :short => '-b', :long => '--boolean', :value => '<string>', :help => 'boolean arg' },
215
+ { :short => '-e', :long => '--element', :value => '<string>', :help => 'http string' },
216
+ { :short => '-f', :long => '--filepath', :value => '<string>', :help => 'filepath' },
217
+ { :short => '-h', :long => '--help', :value => '', :help => 'help on command line options' },
218
+ { :short => '-i', :long => '--interfaces', :value => '<string>', :help => 'interfaces/hosts' },
219
+ { :short => '-j', :long => '--json', :value => '<string>', :help => 'json object' },
220
+ { :short => '-m', :long => '--mu_string', :value => '<string>', :help => 'user, password, mu_ip in the form of admin:admin@10.9.8.7' },
221
+ { :short => '-n', :long => '--name', :value => '<string>', :help => 'host name' },
222
+ { :short => '-o', :long => '--output', :value => '<string>', :help => 'output logging to this file' },
223
+ { :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' }
224
+ ]
225
+
226
+ cmds = [
227
+ "mu cmd_netconfig:clear_hosts",
228
+ "mu cmd_netconfig:clear_interfaces -i <interfaces>",
229
+ "mu cmd_netconfig:clear_routes",
230
+ "mu cmd_netconfig:clear_vlans",
231
+ "mu cmd_netconfig:create -j <json> -e <element>",
232
+ "mu cmd_netconfig:delete -e <element>",
233
+ "mu cmd_netconfig:get -e <element>",
234
+ "mu cmd_netconfig:help",
235
+ "mu cmd_netconfig:modify -j <json> -e <element>",
236
+ "mu cmd_netconfig:resolve_hosts -n <name>",
237
+ "mu cmd_netconfig:restore -f <filepath> [-b <clear_existing>]",
238
+ "mu cmd_netconfig:save -e <element> -f <filepath>",
239
+ ]
240
+
241
+ max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
242
+ max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
243
+ puts
244
+ puts "Usage: mu cmd_netconfig <options>"
245
+ puts
246
+ helps.each do |h|
247
+ puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
248
+ end
249
+ puts
250
+ puts "Available Commands"
251
+ puts
252
+ cmds.each do | c |
253
+ puts c
254
+ end
255
+ puts
256
+ end
257
+
258
+ end
259
+ end # Command
260
+ end # Mu
261
+
262
+
@@ -0,0 +1,533 @@
1
+ # Runs Mu Studio scenario msl files in Studio Scale, requiring that all interfaces and
2
+ # hosts used in the scenario are specified on the command-line through the –i option.
3
+ # Runs either a single msl file or a directory of msl files, and has command-line options
4
+ # to specify the Mu parameters, 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_runscale < Command
9
+
10
+ attr_accessor :api, :params, :hosts, :addr_indexes, :offset_indexes
11
+
12
+ # displays command-line help
13
+ # * argv = command-line arguments
14
+ def cmd_help argv
15
+ help
16
+ end
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
+ setup argv
22
+
23
+ if not @hash['scenario']
24
+ msg "scenario required"
25
+ return help
26
+ else
27
+ if @hash['scenario'].include?(".msl")
28
+ scenario = @hash['scenario']
29
+ else # TODO: eventually, xml and mus file may be supported by scale api
30
+ msg "only .msl files are currently supported"
31
+ return help
32
+ end
33
+ end
34
+
35
+ if not @hash['dir']
36
+ @dir = ""
37
+ path = scenario
38
+ else
39
+ @dir = @hash['dir']
40
+ path = @dir + "/" + scenario
41
+ end
42
+
43
+ if !File.exists?(path)
44
+ raise "*** Error: File #{path} does not exist"
45
+ end
46
+
47
+ @api = Scale.new(@@mu_ip, @@mu_admin_user, @@mu_admin_pass)
48
+ @api.configure("pattern", @cmd_line_pattern)
49
+ @params = {}
50
+ @params["dir"] = @dir
51
+ @params["msl"] = scenario
52
+ @params["hosts"] = @cmd_line_hosts
53
+ run(scenario)
54
+ @api.release
55
+ end
56
+
57
+ # sets up, executes, and closes a Studio Scale test for each scenario (.msl file) found in the specified directory
58
+ # * argv = command-line arguments, requires a directory (-d) argument
59
+ # * optional -r argument for recursive directory search (default is a flat directory)
60
+ def cmd_run_dir argv
61
+ setup argv
62
+
63
+ if not @hash['dir']
64
+ return help
65
+ else
66
+ @dir = @hash['dir']
67
+ end
68
+
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
+ Dir.chdir(@params["dir"])
78
+ File.delete("app_id_status.json") if File.exists?("app_id_status.json")
79
+ if @hash['recursive'].nil?
80
+ files = Dir.glob("*.msl")
81
+ else
82
+ files = Dir.glob("**/*.msl")
83
+ end
84
+ if !files.empty?
85
+ files.sort.each do | f |
86
+ run(f)
87
+ output_csv(f)
88
+ sleep 2
89
+ end
90
+ else
91
+ msg "no msl files found in #{@dir}"
92
+ end
93
+ @api.release
94
+ end
95
+
96
+ private
97
+
98
+ def setup argv
99
+ parse_cli argv
100
+ @params = {}
101
+
102
+ if @hash['test']
103
+ @verify_only = true
104
+ else
105
+ @verify_only = false
106
+ end
107
+
108
+ if not @hash['testset']
109
+ @testset = ""
110
+ else
111
+ @testset = @hash['testset']
112
+ end
113
+
114
+ if not @hash['pattern']
115
+ @cmd_line_pattern = "{ \"iterations\": 1, \"intervals\": [ {\"iterations\":1, \"end\":100, \"start\":1, \"duration\":20 } ] }"
116
+ else
117
+ @cmd_line_pattern = @hash['pattern']
118
+ end
119
+
120
+ if not @hash['interfaces']
121
+ @cmd_line_hosts = "b1,b2"
122
+ else
123
+ @cmd_line_hosts = @hash['interfaces']
124
+ end
125
+
126
+ end
127
+
128
+ def run(scenario)
129
+ # assume the scenario and testset files are in dir unless they contain '/'
130
+ # in which case they are assumed to be absolute paths
131
+ if scenario.include?("/")
132
+ musl_file = scenario
133
+ else
134
+ musl_file = @params["dir"] + "/" + scenario
135
+ end
136
+ # msg musl_file, Logger::DEBUG
137
+ @api.configure("musl", File.read(musl_file))
138
+
139
+ unless @testset.empty?
140
+ if @testset.include?("/")
141
+ csv_file = @testset
142
+ else
143
+ csv_file = @params["dir"] + "/" + @testset
144
+ end
145
+ @api.configure("csv", File.read(csv_file))
146
+ end
147
+
148
+ File.delete("app_id_status.json") if File.exists?("app_id_status.json")
149
+ File.delete("app_id_stats.csv") if File.exists?("app_id_stats.csv")
150
+
151
+ configure_hosts
152
+
153
+ msg "verifying #{scenario} ..."
154
+ response = @api.verify
155
+ msg response, Logger::DEBUG
156
+ # sleep 3
157
+ v = parse_verify_response(response)
158
+ msg "#{v}", Logger::DEBUG
159
+ if v.nil?
160
+ msg "error in verify"
161
+ return
162
+ end
163
+ if @verify_only
164
+ msg v
165
+ return
166
+ end
167
+ msg "starting #{scenario} ..."
168
+ @api.start
169
+ start_time = Time.now.to_i
170
+ while true
171
+ sleep 5
172
+ status = @api.status
173
+ if !status.nil?
174
+ if !status["status"].nil?
175
+ if status["status"]["running"] == false
176
+ msg "running = #{status["status"]["running"]}", Logger::DEBUG
177
+ r = parse_status(status)
178
+ dump_status(status, musl_file)
179
+ return
180
+ else
181
+ r = parse_status(status)
182
+ end
183
+ else # status['status'].nil? ... no bonafide status was returned
184
+ time_now = Time.now.to_i
185
+ if time_now - start_time > 20
186
+ # puts "\nError: timing out after 20 seconds. Test had failed to start or verify"
187
+ break
188
+ end
189
+ end
190
+ end
191
+ end
192
+ ensure
193
+ msg "stopping #{scenario} ..."
194
+ end
195
+
196
+ def cmd_running?
197
+ if @api.nil?
198
+ msg "false"
199
+ return
200
+ end
201
+
202
+ status = @api.status
203
+ if !status.nil?
204
+ if !status["status"].nil?
205
+ msg status["status"]["running"]
206
+ end
207
+ else
208
+ msg "false"
209
+ end
210
+ end
211
+
212
+ def configure_hosts
213
+ @hosts = Array.new
214
+ @addr_indexes = Array.new
215
+ @offset_indexes = Array.new
216
+ hosts = @params["hosts"]
217
+ if !hosts.nil?
218
+ p = hosts.split(",")
219
+ p.each do | h |
220
+ if h.include?("-") # b1-1000,b2-1 to indicate addr_count
221
+ q = h.split("-")
222
+ @hosts << q[0]
223
+ if q[1].include?(":") # -1000:20 to indicate offset within range
224
+ r = q[1].split(":")
225
+ @addr_indexes << r[0]
226
+ @offset_indexes << r[1]
227
+ else
228
+ @addr_indexes << q[1]
229
+ @offset_indexes << 1
230
+ end
231
+ else # default to the 1st addr index
232
+ @hosts << h
233
+ @addr_indexes << 1
234
+ @offset_indexes << 1
235
+ end
236
+ end
237
+ else
238
+ @hosts = ['b1','b2']
239
+ @addr_indexes = [1,1]
240
+ @offset_indexes = [1,1]
241
+ end
242
+
243
+ set_hosts_byname(@hosts, @addr_indexes, @offset_indexes)
244
+ end
245
+
246
+ def set_hosts_byname(hosts=@hosts, count=[1,1], offset=[1,1], v4=true)
247
+ new_hosts = Array.new
248
+ str = ""
249
+ hosts.each_with_index do |n, i|
250
+ if n.match(/^[ab][1-4]$/) or n.include?(".") # possible vlan
251
+ if count[i] == 1 or count[i].nil?
252
+ str = "#{n}/*"
253
+ else
254
+ str = "#{n}/*,#{count[i]},#{offset[i]}"
255
+ end
256
+ msg "using host #{str}", Logger::DEBUG
257
+ else
258
+ @net = Netconfig.new
259
+ @net.setup(@hosts, @username, @password)
260
+ if v4
261
+ addr = @net.get("hosts/#{n}")['v4_addr']
262
+ else
263
+ addr = @net.get("hosts/#{n}")['v6_addr']
264
+ end
265
+ str = "#{addr}"
266
+ msg "using host #{str}", Logger::DEBUG
267
+ end
268
+ new_hosts << str
269
+ end
270
+ set_hosts(new_hosts)
271
+ end
272
+
273
+ # expects full strings: e.g. b1/12.89.0.1 ...
274
+ def set_hosts(hosts=["b1","b2"])
275
+ host_params = {}
276
+
277
+ # assign hosts to consecutive string keys, host_0, host_1, etc ...
278
+ hosts.each_with_index do | h, i |
279
+ host_params["host_#{i}"] = hosts[i]
280
+ end
281
+
282
+ # convert keys to symbols
283
+ # host_params.each_key { |k| host_params[k.to_sym] = host_params[k] }
284
+ new_host_params = {}
285
+ host_params.each_key { |k| new_host_params[k.to_sym] = host_params[k] }
286
+
287
+ =begin
288
+ # add default host, set to host_1 if it exists, unless specified on the command-line
289
+ if @hash['default_host'].nil?
290
+ new_host_params[:default_host] = new_host_params[:host_1] unless new_host_params[:host_1].nil?
291
+ else
292
+ new_host_params[:default_host] = @hash['default_host'] if !@hash['default_host'].nil?
293
+ end
294
+ =end
295
+
296
+ @api.configure("hosts", new_host_params)
297
+
298
+ end
299
+
300
+ def dump_status(status, msl)
301
+ filename = "app_id_status.json"
302
+ f = File.open(filename, "a")
303
+ status["filename"] = msl
304
+ str = JSON.pretty_generate(status)
305
+ f.write(",") if !File.zero?(f) # if appending, we need to insert a comma
306
+ f.write(str)
307
+ f.close
308
+ end
309
+
310
+ def output_csv(msl_file)
311
+ filename = "app_id_stats.csv"
312
+ f = File.open(filename, "a")
313
+ 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"
314
+ File.open(filename, 'a') {|f| f.write(doc) }
315
+ end
316
+
317
+ def parse_verify_response(response)
318
+ if response.nil? # || response.empty?
319
+ msg "*** error = no response received from /verify ***\n\n"
320
+ return nil
321
+ end
322
+ begin
323
+ msg JSON.pretty_generate(response), Logger::DEBUG
324
+ if !response["status"].nil?
325
+ if response["status"]["error"] == true
326
+ @error = response["status"]["error"]
327
+ @reason = response["status"]["reason"]
328
+ dump_status(response)
329
+ msg "*** Error = #{@error}, reason = #{@reason} ***\n\n"
330
+ return nil
331
+ end
332
+ end
333
+ msg "*** verify: okay ***", Logger::DEBUG
334
+ return "*** verify: okay ***"
335
+ rescue => e
336
+ msg e, Logger::DEBUG
337
+ return nil
338
+ end
339
+ end
340
+
341
+ def parse_status(status)
342
+ return nil if status.nil?
343
+ @reported_volume = 0
344
+ if !status["status"]["error"].nil?
345
+ if status["status"]["error"] == true
346
+ @error = status["status"]["error"]
347
+ @reason = status["status"]["reason"]
348
+ msg "*** Error = #{@error}, reason = #{@reason} ***\n\n"
349
+ return nil
350
+ end
351
+ end
352
+
353
+ @stats_summary = status["status"]["statistics"]["summary"]
354
+ @duration = @stats_summary["duration"]
355
+ @instances = @stats_summary["instances"]
356
+ @total_instances = @instances["total"]
357
+ @executed = @instances["executed"]
358
+ @timeouts = @instances["timeouts"]
359
+ @errors = @instances["errors"]
360
+ @asserts_failed = @stats_summary["asserts"]["failed"]
361
+ @server = @stats_summary["server"]
362
+ @server_tx_bytes = @server["tx"]["bytes"]
363
+ @server_tx_msgs = @server["tx"]["msgs"]
364
+ @server_rx_bytes = @server["rx"]["bytes"]
365
+ @server_rx_msgs = @server["rx"]["msgs"]
366
+ @client = @stats_summary["client"]
367
+ @client_tx_bytes = @client["tx"]["bytes"]
368
+ @client_tx_msgs = @client["tx"]["msgs"]
369
+ @client_rx_bytes = @client["rx"]["bytes"]
370
+ @client_rx_msgs = @client["rx"]["msgs"]
371
+ @scenarios = status["status"]["statistics"]["scenarios"]
372
+ @scenarios.each do | scenario |
373
+ @reported_volume = @reported_volume + scenario["volume"]
374
+ end
375
+
376
+ msg ""
377
+ msg "duration: #{format_float(2, @duration)}"
378
+ msg "concurrency: #{@reported_volume}"
379
+ msg "tests/sec: #{format_float(2, @executed.to_f / @duration)}" if @duration.to_i > 0
380
+ msg "passed: #{@executed}"
381
+ msg "errors: #{@errors}"
382
+ msg "timeouts: #{@timeouts}"
383
+ msg "client tx bytes/sec #{format_float(2, @client_tx_bytes.to_f / @duration)}" if @duration.to_i > 0
384
+ msg "client tx msgs/sec #{format_float(2, @client_tx_msgs.to_f / @duration)}" if @duration.to_i > 0
385
+ msg "client rx bytes/sec #{format_float(2, @client_rx_bytes.to_f / @duration)}" if @duration.to_i > 0
386
+ msg "client rx msgs/sec #{format_float(2, @client_rx_msgs.to_f / @duration)}" if @duration.to_i > 0
387
+ msg "server tx bytes/sec #{format_float(2, @server_tx_bytes.to_f / @duration)}" if @duration.to_i > 0
388
+ msg "server tx msgs/sec #{format_float(2, @server_tx_msgs.to_f / @duration)}" if @duration.to_i > 0
389
+ msg "server rx bytes/sec #{format_float(2, @server_rx_bytes.to_f / @duration)}" if @duration.to_i > 0
390
+ msg "server rx msgs/sec #{format_float(2, @server_rx_msgs.to_f / @duration)}" if @duration.to_i > 0
391
+ msg ""
392
+ end
393
+
394
+ def parse_cli argv
395
+ @hash = Hash.new
396
+ while not argv.empty?
397
+ break if argv.first[0,1] != '-'
398
+
399
+ k = argv.shift
400
+
401
+ if [ '-c', '--csv' ].member? k
402
+ @hash['testset'] = shift(k, argv)
403
+ next
404
+ end
405
+
406
+ if [ '-d', '--dir' ].member? k
407
+ @hash['dir'] = shift(k, argv)
408
+ next
409
+ end
410
+
411
+ if [ '-f', '--default_host' ].member? k
412
+ @hash['default_host'] = shift(k, argv)
413
+ next
414
+ end
415
+
416
+ if [ '-i', '--interfaces' ].member? k
417
+ @hash['interfaces'] = shift(k, argv)
418
+ next
419
+ end
420
+
421
+ if [ '-h', '--help' ].member? k
422
+ help
423
+ exit
424
+ end
425
+
426
+ if [ '-m', '--mu_string' ].member? k
427
+ mu_string = shift(k, argv)
428
+ if mu_string =~ /(.+?):(.+?)@(.*)/
429
+ @@mu_admin_user = $1
430
+ @@mu_admin_pass = $2
431
+ @@mu_ip = $3
432
+ end
433
+ next
434
+ end
435
+
436
+ if [ '-o', '--output' ].member? k
437
+ $stdout.reopen(shift(k, argv), "w")
438
+ next
439
+ end
440
+
441
+ if [ '-p', '--pattern' ].member? k
442
+ patterns = Array.new
443
+ pattern_string = shift(k, argv)
444
+ pstrings = pattern_string.split(",")
445
+ pstrings.each do | p |
446
+ if p =~ /(.+?)-(.+?):(.*)/ # e.g. 1-10000:60
447
+ start_vol = $1
448
+ end_vol = $2
449
+ duration = $3
450
+ patterns << "{\"iterations\":1, \"end\":#{end_vol}, \"start\":#{start_vol}, \"duration\":#{duration} }"
451
+ end
452
+ end
453
+ ps = "{ \"iterations\": 1, \"intervals\": ["
454
+ patterns.each do | p |
455
+ ps = ps + p + ","
456
+ end
457
+ ps = ps[0..ps.length-2] # remove final comma
458
+ ps = ps + "] }"
459
+ @hash['pattern'] = ps
460
+ next
461
+ end
462
+
463
+ if [ '-r', '--recursive'].member? k
464
+ @hash['recursive'] = true
465
+ next
466
+ end
467
+
468
+
469
+ if [ '-s', '--scenario' ].member? k
470
+ @hash['scenario'] = shift(k, argv)
471
+ next
472
+ end
473
+
474
+ if [ '-t', '--test' ].member? k
475
+ @hash['test'] = true
476
+ next
477
+ end
478
+
479
+ if [ '-v', '--verbose' ].member? k
480
+ $log.level = Logger::DEBUG
481
+ next
482
+ end
483
+
484
+ raise ArgumentError, "Unknown option #{k}"
485
+ end
486
+
487
+ @hash
488
+ end
489
+
490
+ def help
491
+ helps = [
492
+ { :short => '-c', :long => '--csv', :value => '<string>', :help => 'name of the csv testset to run' },
493
+ { :short => '-d', :long => '--dir', :value => '<string>', :help => 'directory containing the scenario file' },
494
+ { :short => '-f', :long => '--default_host', :value => '<string>', :help => 'default_host setting' },
495
+ { :short => '-h', :long => '--help', :value => '', :help => 'help on command line options' },
496
+ { :short => '-i', :long => '--interfaces', :value => '<string>', :help => 'comma-separated list of interfaces, e.g. b1,b2 or b1-1000,b2 for ip range' },
497
+ { :short => '-m', :long => '--mu_string', :value => '<string>', :help => 'user, password, mu_ip in the form of admin:admin@10.9.8.7' },
498
+ { :short => '-o', :long => '--output', :value => '<string>', :help => 'output logging to this file' },
499
+ { :short => '-p', :long => '--pattern', :value => '<string>', :help => 'pattern in the form of comma-separated concurrency_start-end:duration patterns, e.g. 1-100:60,100-100:60,100-1:60' },
500
+ { :short => '-r', :long => '--recursive', :value => '', :help => 'for run_dir, recurse through sub-directories' },
501
+ { :short => '-s', :long => '--scenario', :value => '<string>', :help => 'scenario file to run' },
502
+ { :short => '-t', :long => '--test', :value => '', :help => 'do verify only' },
503
+ { :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' }
504
+ ]
505
+
506
+ cmds = [
507
+ "mu cmd_runscale:help",
508
+ "mu cmd_runscale:run_file -s <scenario> -i <hosts, e.g. a1,dell-9> -p <pattern, e.g. 1-1000:30>",
509
+ "mu cmd_runscale:run_dir -d <scenario_directory>",
510
+ "mu cmd_runscale:running?"
511
+ ]
512
+
513
+ max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
514
+ max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
515
+ puts
516
+ puts "Usage: mu cmd_runscale:<command> <options>"
517
+ puts
518
+ helps.each do |h|
519
+ puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
520
+ end
521
+ puts
522
+ puts "Available Commands"
523
+ puts
524
+ cmds.each do | c |
525
+ puts c
526
+ end
527
+ puts
528
+ end
529
+
530
+ end
531
+ end # Command
532
+ end # Mu
533
+