cloudstack_ruby_client 0.1.0 → 0.1.1
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/lib/cloudstack_ruby_client.rb +6 -1
- data/lib/cloudstack_ruby_client/api/accounts_api.rb +59 -57
- data/lib/cloudstack_ruby_client/api/autoscale_api.rb +23 -21
- data/lib/cloudstack_ruby_client/api/configuration_api.rb +13 -11
- data/lib/cloudstack_ruby_client/api/firewall_api.rb +13 -11
- data/lib/cloudstack_ruby_client/api/infra_api.rb +40 -38
- data/lib/cloudstack_ruby_client/api/network_api.rb +112 -110
- data/lib/cloudstack_ruby_client/api/project_api.rb +13 -11
- data/lib/cloudstack_ruby_client/api/securitygroup_api.rb +10 -8
- data/lib/cloudstack_ruby_client/api/serviceoffering_api.rb +14 -12
- data/lib/cloudstack_ruby_client/api/snapshot_api.rb +10 -8
- data/lib/cloudstack_ruby_client/api/storage_api.rb +16 -14
- data/lib/cloudstack_ruby_client/api/systemvm_api.rb +22 -20
- data/lib/cloudstack_ruby_client/api/template_api.rb +31 -29
- data/lib/cloudstack_ruby_client/api/vm_api.rb +28 -26
- data/lib/cloudstack_ruby_client/api/volume_api.rb +12 -10
- data/lib/cloudstack_ruby_client/base_client.rb +11 -20
- data/lib/cloudstack_ruby_client/client.rb +43 -43
- data/lib/cloudstack_ruby_client/client_helper.rb +64 -17
- data/lib/cloudstack_ruby_client/version.rb +1 -1
- data/test/unit/accounts_test.rb +284 -0
- data/test/unit/autoscale_test.rb +134 -0
- data/test/unit/configuration_test.rb +55 -0
- data/test/unit/firewall_test.rb +77 -0
- data/test/unit/infra_test.rb +79 -22
- data/test/unit/network_test.rb +190 -0
- data/test/unit/project_test.rb +73 -0
- data/test/unit/securitygroup_test.rb +64 -0
- data/test/unit/serviceoffering_test.rb +69 -0
- data/test/unit/snapshot_test.rb +52 -0
- data/test/unit/storage_test.rb +76 -0
- data/test/unit/systemvm_test.rb +115 -0
- data/test/unit/template_test.rb +153 -0
- data/test/unit/vm_test.rb +151 -0
- data/test/unit/volume_test.rb +76 -0
- metadata +26 -3
- data/lib/cloudstack_ruby_client/api/config.rb +0 -15
@@ -1,13 +1,46 @@
|
|
1
1
|
class Module
|
2
|
+
|
3
|
+
MALFORMED_CMDS = {
|
4
|
+
/getvmpassword/i => 'getVMPassword'
|
5
|
+
}
|
6
|
+
|
7
|
+
#
|
8
|
+
# The following is malformed response title in ACS, should be fixed
|
9
|
+
#
|
10
|
+
MALFORMED_RESPONSES = {
|
11
|
+
/(create|list)counter/i => 'counterresponse',
|
12
|
+
/createcondition/i => 'conditionresponse',
|
13
|
+
/createautoscalepolicy/i => 'autoscalepolicyresponse',
|
14
|
+
/createautoscalevmprofile/i => 'autoscalevmprofileresponse',
|
15
|
+
/createautoscalevmgroup/i => 'autoscalevmgroupresponse',
|
16
|
+
/enableautoscalevmgroup/i => 'enableautoscalevmGroupresponse',
|
17
|
+
/disableautoscalevmgroup/i => 'disableautoscalevmGroupresponse',
|
18
|
+
/assignvirtualmachine/i => 'moveuservmresponse',
|
19
|
+
/resetsshkeyforvirtualmachine/i => 'resetSSHKeyforvirtualmachineresponse',
|
20
|
+
/restorevirtualmachine/i => 'restorevmresponse',
|
21
|
+
/activateproject/i => 'activaterojectresponse',
|
22
|
+
/listnetworkdevice/i => 'listnetworkdevice',
|
23
|
+
/listniciranvpdevicenetworks/i => 'listniciranvpdevicenetworks',
|
24
|
+
/cancelstoragemaintenance/i => 'cancelprimarystoragemaintenanceresponse',
|
25
|
+
/enablestoragemaintenance/i => 'prepareprimarystorageformaintenanceresponse',
|
26
|
+
/copyiso/i => 'copytemplateresponse',
|
27
|
+
/deleteiso/i => 'deleteisosresponse',
|
28
|
+
/listisopermissions/i => 'listtemplatepermissionsresponse'
|
29
|
+
}
|
30
|
+
|
2
31
|
def cmd_processor(*args)
|
3
32
|
args.each do |arg|
|
4
33
|
arga = arg.to_s.split('_')
|
5
34
|
meta_method = %Q{
|
6
|
-
def #{
|
35
|
+
def #{arg}(args={});
|
7
36
|
|
8
|
-
command = "#{
|
37
|
+
command = "#{
|
38
|
+
arga.each_with_index.map {|x, i|
|
39
|
+
i==0 ? x : x.capitalize
|
40
|
+
}.join('')
|
41
|
+
}";
|
9
42
|
|
10
|
-
resp_title = "#{arga
|
43
|
+
resp_title = "#{arga.join('')}response";
|
11
44
|
} +
|
12
45
|
|
13
46
|
#
|
@@ -15,27 +48,33 @@ class Module
|
|
15
48
|
#
|
16
49
|
|
17
50
|
%Q{
|
51
|
+
MALFORMED_RESPONSES.each do |k, v|;
|
52
|
+
if k =~ command;
|
53
|
+
resp_title = v;
|
54
|
+
end;
|
55
|
+
end;
|
18
56
|
|
19
|
-
|
20
|
-
|
57
|
+
MALFORMED_CMDS.each do |k, v|;
|
58
|
+
if k =~ command;
|
59
|
+
command = v;
|
60
|
+
end
|
21
61
|
end;
|
22
62
|
|
23
63
|
if /(list|create|delete)networkacl.*/i =~ command;
|
24
|
-
command.gsub! /acl/i, 'ACL'
|
64
|
+
command.gsub! /acl/i, 'ACL';
|
25
65
|
end;
|
26
66
|
|
27
|
-
if /.*ssh.*/i =~ command;
|
28
|
-
command.gsub! /ssh/i, 'SSH'
|
67
|
+
if /.*(ssh).*/i =~ command;
|
68
|
+
command.gsub! /ssh/i, 'SSH';
|
29
69
|
end;
|
30
70
|
|
31
71
|
if /(list|create|delete)lbstickinesspolic.*/i =~ command;
|
32
|
-
command.gsub! /lb/i, 'LB'
|
72
|
+
command.gsub! /lb/i, 'LB';
|
33
73
|
end;
|
34
74
|
|
35
75
|
if /.*vpc.*/i =~ command;
|
36
|
-
command.gsub! /vpc/i, 'VPC'
|
76
|
+
command.gsub! /vpc/i, 'VPC';
|
37
77
|
end;
|
38
|
-
|
39
78
|
} +
|
40
79
|
%Q{
|
41
80
|
params = {'command' => command};
|
@@ -44,20 +83,28 @@ class Module
|
|
44
83
|
response = request params;
|
45
84
|
|
46
85
|
if !response.is_a?(Net::HTTPOK);
|
86
|
+
if response.code =~ /(431|530)/ &&
|
87
|
+
(JSON.parse(response.body)[resp_title]['cserrorcode'] == 9999 ||
|
88
|
+
JSON.parse(response.body)[resp_title]['cserrorcode'] == 4350);
|
47
89
|
|
48
|
-
|
49
|
-
|
90
|
+
raise ArgumentError, JSON.parse(response.body)\
|
91
|
+
[resp_title]['errortext'];
|
50
92
|
|
51
|
-
raise ArgumentError, JSON.parse(response.body)[resp_title]['errortext'];
|
52
93
|
end;
|
53
|
-
|
54
|
-
|
94
|
+
|
95
|
+
if response.code == "432";
|
96
|
+
raise RuntimeError, JSON.parse(response.body)\
|
97
|
+
['errorresponse']['errortext'];
|
98
|
+
|
99
|
+
end;
|
100
|
+
|
101
|
+
puts 'Error ' + response.code + ':'
|
55
102
|
puts JSON.pretty_generate(JSON.parse(response.body));
|
56
103
|
exit 1;
|
57
104
|
end;
|
58
105
|
|
59
106
|
json = JSON.parse(response.body);
|
60
|
-
json[
|
107
|
+
json[resp_title]
|
61
108
|
end;
|
62
109
|
}
|
63
110
|
|
data/test/unit/accounts_test.rb
CHANGED
@@ -0,0 +1,284 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'yaml'
|
3
|
+
require_relative '../../lib/cloudstack_ruby_client'
|
4
|
+
|
5
|
+
class AccountsTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
config = YAML.load_file("test/config.yml")
|
9
|
+
_host = config['cloudstack']['host']
|
10
|
+
_port = config['cloudstack']['port']
|
11
|
+
_admin_port = config['cloudstack']['admin_port']
|
12
|
+
_api_key = config['cloudstack']['api_key']
|
13
|
+
_secret_key = config['cloudstack']['secret_key']
|
14
|
+
@client = CloudstackRubyClient::Client.new \
|
15
|
+
"http://#{_host}:#{_port}/client/api",
|
16
|
+
"#{_api_key}",
|
17
|
+
"#{_secret_key}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
# Do nothing here!
|
22
|
+
end
|
23
|
+
|
24
|
+
### Domain Testing ###
|
25
|
+
|
26
|
+
def test_list_domains
|
27
|
+
# expect_result = JSON.parse(
|
28
|
+
# '{"count":1 ,' +
|
29
|
+
# '"domain":[' +
|
30
|
+
# '{"id":"f45c793a-ff0d-11e2-b492-00256494eb2f",' +
|
31
|
+
# '"name":"ROOT",'+
|
32
|
+
# '"level":0,' +
|
33
|
+
# '"haschild":false,' +
|
34
|
+
# '"path":"ROOT"}' +
|
35
|
+
# ']' +
|
36
|
+
# '}')
|
37
|
+
# assert_equal(expect_result, @client.list_regions)
|
38
|
+
|
39
|
+
assert_equal(1, @client.list_domains['count'])
|
40
|
+
assert_equal('ROOT', @client.list_domains['domain'][0]['name'])
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_create_domain
|
44
|
+
assert_raise(ArgumentError) do
|
45
|
+
@client.create_domain
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_update_domain
|
50
|
+
assert_raise(ArgumentError) do
|
51
|
+
@client.update_domain
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_delete_domain
|
56
|
+
assert_raise(ArgumentError) do
|
57
|
+
@client.delete_domain
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_list_domain_children
|
62
|
+
assert_equal({}, @client.list_domain_children)
|
63
|
+
end
|
64
|
+
|
65
|
+
### Account Testing ###
|
66
|
+
|
67
|
+
def test_list_accounts
|
68
|
+
assert_equal(1, @client.list_accounts['count'])
|
69
|
+
assert_equal('admin', @client.list_accounts['account'][0]['name'])
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_create_account
|
73
|
+
assert_raise(ArgumentError) do
|
74
|
+
@client.create_account
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_update_account
|
79
|
+
assert_raise(ArgumentError) do
|
80
|
+
@client.update_account
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_delete_account
|
85
|
+
assert_raise(ArgumentError) do
|
86
|
+
@client.delete_account
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_disable_account
|
92
|
+
assert_raise(ArgumentError) do
|
93
|
+
@client.disable_account
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_enable_account
|
98
|
+
# NOTE: The cserror code is 4350 for enable_account
|
99
|
+
assert_raise(ArgumentError) do
|
100
|
+
@client.enable_account
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_lock_account
|
105
|
+
assert_raise(ArgumentError) do
|
106
|
+
@client.lock_account
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_add_account_to_project
|
111
|
+
assert_raise(ArgumentError) do
|
112
|
+
@client.add_account_to_project
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_delete_account_from_project
|
117
|
+
assert_raise(ArgumentError) do
|
118
|
+
@client.delete_account_from_project
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_list_project_accounts
|
123
|
+
assert_raise(ArgumentError) do
|
124
|
+
@client.list_project_accounts
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
### User Testing ###
|
129
|
+
|
130
|
+
def test_list_users
|
131
|
+
assert_equal(1, @client.list_users['count'])
|
132
|
+
assert_equal('admin', @client.list_users['user'][0]['username'])
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_create_user
|
136
|
+
assert_raise(ArgumentError) do
|
137
|
+
@client.create_user
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_update_user
|
142
|
+
assert_raise(ArgumentError) do
|
143
|
+
@client.update_user
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_delete_user
|
148
|
+
assert_raise(ArgumentError) do
|
149
|
+
@client.delete_user
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_lock_user
|
154
|
+
assert_raise(ArgumentError) do
|
155
|
+
@client.lock_user
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_disable_user
|
160
|
+
assert_raise(ArgumentError) do
|
161
|
+
@client.disable_user
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
def test_enable_user
|
167
|
+
assert_raise(ArgumentError) do
|
168
|
+
@client.enable_user
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_get_user
|
173
|
+
assert_raise(ArgumentError) do
|
174
|
+
@client.get_user
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_add_vpn_user
|
179
|
+
assert_raise(ArgumentError) do
|
180
|
+
@client.add_vpn_user
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_remove_vpn_user
|
185
|
+
assert_raise(ArgumentError) do
|
186
|
+
@client.remove_vpn_user
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_list_vpn_users
|
191
|
+
assert_equal({}, @client.list_vpn_users)
|
192
|
+
end
|
193
|
+
|
194
|
+
### Limit Test ###
|
195
|
+
|
196
|
+
def test_update_resource_limit
|
197
|
+
assert_raise(ArgumentError) do
|
198
|
+
@client.update_resource_limit
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_update_resource_count
|
203
|
+
assert_raise(ArgumentError) do
|
204
|
+
@client.update_resource_count
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_list_resource_limits
|
209
|
+
assert_equal('admin',
|
210
|
+
@client.list_resource_limits['resourcelimit'][0]['account'])
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_get_api_limit
|
214
|
+
assert_raise(RuntimeError) do
|
215
|
+
@client.get_api_limit
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_reset_api_limit
|
220
|
+
assert_raise(RuntimeError) do
|
221
|
+
@client.reset_api_limit
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
### Usage Testing ###
|
226
|
+
|
227
|
+
def test_add_traffic_type
|
228
|
+
assert_raise(ArgumentError) do
|
229
|
+
@client.add_traffic_type
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_delete_traffic_type
|
234
|
+
assert_raise(ArgumentError) do
|
235
|
+
@client.delete_traffic_type
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_list_traffic_types
|
240
|
+
assert_raise(ArgumentError) do
|
241
|
+
@client.list_traffic_types
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_update_traffic_type
|
246
|
+
assert_raise(ArgumentError) do
|
247
|
+
@client.update_traffic_type
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_list_traffic_type_implementors
|
252
|
+
assert_equal(12, @client.list_traffic_type_implementors['count'])
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_generate_usage_records
|
256
|
+
assert_raise(ArgumentError) do
|
257
|
+
@client.generate_usage_records
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_list_usage_records
|
262
|
+
assert_raise(ArgumentError) do
|
263
|
+
@client.list_usage_records
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_add_traffic_monitor
|
268
|
+
assert_raise(ArgumentError) do
|
269
|
+
@client.add_traffic_monitor
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_delete_traffic_monitor
|
274
|
+
assert_raise(ArgumentError) do
|
275
|
+
@client.delete_traffic_monitor
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_list_traffic_monitors
|
280
|
+
assert_raise(ArgumentError) do
|
281
|
+
@client.list_traffic_monitors
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'yaml'
|
3
|
+
require_relative '../../lib/cloudstack_ruby_client'
|
4
|
+
|
5
|
+
class AutoScaleTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
config = YAML.load_file("test/config.yml")
|
9
|
+
_host = config['cloudstack']['host']
|
10
|
+
_port = config['cloudstack']['port']
|
11
|
+
_admin_port = config['cloudstack']['admin_port']
|
12
|
+
_api_key = config['cloudstack']['api_key']
|
13
|
+
_secret_key = config['cloudstack']['secret_key']
|
14
|
+
@client = CloudstackRubyClient::Client.new \
|
15
|
+
"http://#{_host}:#{_port}/client/api",
|
16
|
+
"#{_api_key}",
|
17
|
+
"#{_secret_key}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
# Do nothing here!
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_create_counter
|
25
|
+
assert_raise(ArgumentError) do
|
26
|
+
@client.create_counter
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_create_condition
|
31
|
+
assert_raise(ArgumentError) do
|
32
|
+
@client.create_condition
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_create_auto_scale_policy
|
37
|
+
assert_raise(ArgumentError) do
|
38
|
+
@client.create_auto_scale_policy
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_create_auto_scale_vm_profile
|
43
|
+
assert_raise(ArgumentError) do
|
44
|
+
@client.create_auto_scale_vm_profile
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_create_auto_scale_vm_group
|
49
|
+
assert_raise(ArgumentError) do
|
50
|
+
@client.create_auto_scale_vm_group
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_delete_counter
|
55
|
+
assert_raise(ArgumentError) do
|
56
|
+
@client.delete_counter
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_delete_condition
|
61
|
+
assert_raise(ArgumentError) do
|
62
|
+
@client.delete_condition
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_delete_auto_scale_policy
|
67
|
+
assert_raise(ArgumentError) do
|
68
|
+
@client.delete_auto_scale_policy
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_delete_auto_scale_vm_profile
|
73
|
+
assert_raise(ArgumentError) do
|
74
|
+
@client.delete_auto_scale_vm_profile
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_delete_auto_scale_vm_group
|
79
|
+
assert_raise(ArgumentError) do
|
80
|
+
@client.delete_auto_scale_vm_group
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_list_counters
|
85
|
+
assert_equal(4, @client.list_counters['count'])
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_list_conditions
|
89
|
+
assert_equal({}, @client.list_conditions)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_list_auto_scale_policies
|
93
|
+
assert_equal({},@client.list_auto_scale_policies)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_list_auto_scale_vm_profiles
|
97
|
+
assert_equal({},@client.list_auto_scale_vm_profiles)
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def test_list_auto_scale_vm_groups
|
102
|
+
assert_equal({}, @client.list_auto_scale_vm_groups)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_enable_auto_scale_vm_group
|
106
|
+
assert_raise(ArgumentError) do
|
107
|
+
@client.enable_auto_scale_vm_group
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_disable_auto_scale_vm_group
|
112
|
+
assert_raise(ArgumentError) do
|
113
|
+
@client.disable_auto_scale_vm_group
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_update_auto_scale_policy
|
118
|
+
assert_raise(ArgumentError) do
|
119
|
+
@client.update_auto_scale_policy
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_update_auto_scale_vm_profile
|
124
|
+
assert_raise(ArgumentError) do
|
125
|
+
@client.update_auto_scale_vm_profile
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_update_auto_scale_vm_group
|
130
|
+
assert_raise(ArgumentError) do
|
131
|
+
@client.update_auto_scale_vm_group
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|