lorj 1.0.9 → 1.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/example/students_1/process/students.rb +1 -1
- data/example/students_1/student_v1.md +2 -0
- data/example/students_1/students.rb +2 -1
- data/example/students_2/process/students.rb +1 -1
- data/example/students_2/students.rb +4 -2
- data/example/students_3/controller/yaml_students_def.rb +1 -1
- data/example/students_3/process/students.rb +1 -1
- data/example/students_3/student_v3.md +5 -3
- data/example/students_3/students.rb +5 -3
- data/example/students_4/controller/yaml_students_def.rb +1 -1
- data/example/students_4/process/students/definition/students.rb +1 -1
- data/example/students_4/students.rb +5 -3
- data/example/students_5/controller/yaml_students.rb +1 -1
- data/example/students_5/process/students.rb +1 -1
- data/example/students_5/student_v5.md +4 -4
- data/example/students_5/students.rb +8 -7
- data/example/yaml_students/students.rb +4 -4
- data/lib/core/core.rb +110 -64
- data/lib/core/core_internal.rb +110 -15
- data/lib/core/core_object_data.rb +4 -4
- data/lib/core/core_process_setup.rb +3 -30
- data/lib/core/lorj_data.rb +1 -1
- data/lib/core/lorj_keypath.rb +3 -1
- data/lib/core/process.rb +67 -0
- data/lib/lorj/version.rb +2 -1
- data/lib/lorj.rb +3 -4
- data/lib/lorj_account.rb +6 -5
- data/lib/lorj_config.rb +3 -2
- data/lib/providers/templates/compute.rb +1 -1
- data/lorj-spec/controllers/mock/mock.rb +144 -0
- data/lorj-spec/data.yaml +0 -0
- data/lorj-spec/process/mock2_process.rb +48 -0
- data/lorj-spec/process/mock_process.rb +48 -0
- data/lorj-spec/providers/mock2/mock2.rb +0 -0
- data/lorj.gemspec +2 -4
- data/spec/05_lorj_keypath_spec.rb +78 -0
- data/spec/20_lorj_meta_spec.rb +1 -1
- data/spec/21_lorj_processes_spec.rb +115 -0
- metadata +27 -42
- data/lib/core_process/cloud/process/common.rb +0 -60
- data/lib/core_process/cloud/process/connection.rb +0 -92
- data/lib/core_process/cloud/process/external_network.rb +0 -90
- data/lib/core_process/cloud/process/flavor.rb +0 -97
- data/lib/core_process/cloud/process/images.rb +0 -99
- data/lib/core_process/cloud/process/internet_network.rb +0 -33
- data/lib/core_process/cloud/process/internet_server.rb +0 -29
- data/lib/core_process/cloud/process/keypairs.rb +0 -332
- data/lib/core_process/cloud/process/network.rb +0 -107
- data/lib/core_process/cloud/process/public_ip.rb +0 -102
- data/lib/core_process/cloud/process/router.rb +0 -267
- data/lib/core_process/cloud/process/rules.rb +0 -120
- data/lib/core_process/cloud/process/security_groups.rb +0 -120
- data/lib/core_process/cloud/process/server.rb +0 -126
- data/lib/core_process/cloud/process/server_log.rb +0 -34
- data/lib/core_process/cloud/process/subnetwork.rb +0 -96
- data/lib/core_process/cloud_process.rb +0 -30
- data/lib/prc_base_config.rb +0 -300
- data/lib/prc_core_config.rb +0 -1258
- data/lib/prc_section_config.rb +0 -90
- data/lib/providers/hpcloud/compute.rb +0 -105
- data/lib/providers/hpcloud/hpcloud.rb +0 -462
- data/lib/providers/hpcloud/network.rb +0 -115
- data/lib/providers/hpcloud/security_groups.rb +0 -68
- data/lib/providers/openstack/openstack.rb +0 -410
- data/lib/providers/openstack/openstack_create.rb +0 -205
- data/lib/providers/openstack/openstack_delete.rb +0 -28
- data/lib/providers/openstack/openstack_get.rb +0 -39
- data/lib/providers/openstack/openstack_process.rb +0 -26
- data/lib/providers/openstack/openstack_query.rb +0 -96
- data/lib/providers/openstack/openstack_update.rb +0 -35
- data/lib/rh.rb +0 -426
- data/spec/01_hash_rh_spec.rb +0 -282
- data/spec/02_prc_base_config_spec.rb +0 -227
- data/spec/03_prc_section_config_spec.rb +0 -196
- data/spec/04_prc_core_config_spec.rb +0 -325
@@ -1,205 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
# Defined Openstack object create.
|
18
|
-
class OpenstackController
|
19
|
-
def create_security_groups(hParams)
|
20
|
-
required?(hParams, :network_connection)
|
21
|
-
required?(hParams, :tenants)
|
22
|
-
required?(hParams, :security_group)
|
23
|
-
|
24
|
-
service = hParams[:network_connection]
|
25
|
-
|
26
|
-
service.security_groups.create(:name => hParams[:security_group],
|
27
|
-
:tenant_id => hParams[:tenants].id)
|
28
|
-
end
|
29
|
-
|
30
|
-
def create_network(hParams)
|
31
|
-
required?(hParams, :network_connection)
|
32
|
-
required?(hParams, :network_name)
|
33
|
-
|
34
|
-
hParams[:network_connection].networks.create(hParams[:hdata])
|
35
|
-
end
|
36
|
-
|
37
|
-
def create_subnetwork(hParams)
|
38
|
-
required?(hParams, :network_connection)
|
39
|
-
required?(hParams, :network)
|
40
|
-
|
41
|
-
netconn = hParams[:network_connection]
|
42
|
-
netconn.subnets.create(
|
43
|
-
:network_id => hParams[:network].id,
|
44
|
-
:name => hParams[:subnetwork_name],
|
45
|
-
:cidr => get_next_subnet(netconn),
|
46
|
-
:ip_version => '4'
|
47
|
-
)
|
48
|
-
end
|
49
|
-
|
50
|
-
def create_rule(hParams)
|
51
|
-
required?(hParams, :network_connection)
|
52
|
-
required?(hParams, :security_groups)
|
53
|
-
hParams[:network_connection].security_group_rules.create(hParams[:hdata])
|
54
|
-
end
|
55
|
-
|
56
|
-
def create_router(hParams)
|
57
|
-
required?(hParams, :network_connection)
|
58
|
-
required?(hParams, :router_name)
|
59
|
-
|
60
|
-
# Forcelly used admin_status_up to true. Coming from HPCloud.
|
61
|
-
# But not sure if we need it or not.
|
62
|
-
# hParams[:hdata] = hParams[:hdata].merge(:admin_state_up => true)
|
63
|
-
|
64
|
-
hParams[:network_connection].routers.create(hParams[:hdata])
|
65
|
-
end
|
66
|
-
|
67
|
-
def create_router_interface(hParams)
|
68
|
-
required?(hParams, :network_connection)
|
69
|
-
required?(hParams, :router)
|
70
|
-
required?(hParams, :subnetwork)
|
71
|
-
|
72
|
-
service = hParams[:network_connection]
|
73
|
-
router = hParams[:router]
|
74
|
-
result = service.add_router_interface(router.id, hParams[:subnetwork].id)
|
75
|
-
fail if result.status != 200
|
76
|
-
result
|
77
|
-
end
|
78
|
-
|
79
|
-
def create_keypairs(hParams)
|
80
|
-
required?(hParams, :compute_connection)
|
81
|
-
required?(hParams, :keypair_name)
|
82
|
-
required?(hParams, :public_key)
|
83
|
-
|
84
|
-
# API:
|
85
|
-
# https://github.com/fog/fog/blob/master/lib/fog/openstack/docs/compute.md
|
86
|
-
service = hParams[:compute_connection]
|
87
|
-
service.key_pairs.create(:name => hParams[:keypair_name],
|
88
|
-
:public_key => hParams[:public_key])
|
89
|
-
end
|
90
|
-
|
91
|
-
def create_server(hParams)
|
92
|
-
[:compute_connection, :image,
|
93
|
-
:network, :flavor, :keypairs,
|
94
|
-
:security_groups, :server_name].each do |required_param|
|
95
|
-
required?(hParams, required_param)
|
96
|
-
end
|
97
|
-
|
98
|
-
options = {
|
99
|
-
:name => hParams[:server_name],
|
100
|
-
:flavor_ref => hParams[:flavor].id,
|
101
|
-
:image_ref => hParams[:image].id,
|
102
|
-
:key_name => hParams[:keypairs].name,
|
103
|
-
:security_groups => [hParams[:security_groups].name],
|
104
|
-
:nics => [{ :net_id => hParams[:network].id }]
|
105
|
-
}
|
106
|
-
|
107
|
-
if hParams[:user_data]
|
108
|
-
options[:user_data_encoded] =
|
109
|
-
Base64.strict_encode64(hParams[:user_data])
|
110
|
-
end
|
111
|
-
options[:metadata] = hParams[:meta_data] if hParams[:meta_data]
|
112
|
-
|
113
|
-
compute_connect = hParams[:compute_connection]
|
114
|
-
|
115
|
-
server = compute_connect.servers.create(options)
|
116
|
-
compute_connect.servers.get(server.id) if server
|
117
|
-
end
|
118
|
-
|
119
|
-
def create_public_ip(hParams)
|
120
|
-
required?(hParams, :compute_connection)
|
121
|
-
required?(hParams, :server)
|
122
|
-
|
123
|
-
compute_connect = hParams[:compute_connection]
|
124
|
-
server = hParams[:server]
|
125
|
-
|
126
|
-
while server.state != 'ACTIVE'
|
127
|
-
sleep(5)
|
128
|
-
server = compute_connect.servers.get(server.id)
|
129
|
-
end
|
130
|
-
|
131
|
-
addresses = compute_connect.addresses.all
|
132
|
-
address = nil
|
133
|
-
# Search for an available IP
|
134
|
-
addresses.each do |elem|
|
135
|
-
if elem.fixed_ip.nil?
|
136
|
-
address = elem
|
137
|
-
break
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
address = allocate_new_ip(compute_connect) if address.nil?
|
142
|
-
if address.nil?
|
143
|
-
controller_error("No Public IP to assign to server '%s'", server.name)
|
144
|
-
end
|
145
|
-
|
146
|
-
address.server = server # associate the server
|
147
|
-
address.reload
|
148
|
-
# This function needs to returns a list of object.
|
149
|
-
# This list must support the each function.
|
150
|
-
address
|
151
|
-
end
|
152
|
-
|
153
|
-
def allocate_new_ip(compute_connect)
|
154
|
-
# Create a new public IP to add in the pool.
|
155
|
-
pools = compute_connect.addresses.get_address_pools
|
156
|
-
controller_error('No IP Pool found') if pools.length == 0
|
157
|
-
# TODO: Be able to support choice of pool at setup time.
|
158
|
-
if pools.length > 1
|
159
|
-
Lorj.warning('Several pools found. Selecting the first one.')
|
160
|
-
end
|
161
|
-
compute_connect.addresses.create 'pool' => pools[0]['name']
|
162
|
-
end
|
163
|
-
|
164
|
-
def get_next_subnet(oNetworkConnect)
|
165
|
-
subnet_values = []
|
166
|
-
subnets = oNetworkConnect.subnets.all
|
167
|
-
|
168
|
-
subnets.each do|s|
|
169
|
-
subnet_values.push(s.cidr)
|
170
|
-
end
|
171
|
-
|
172
|
-
gap = false
|
173
|
-
count = 0
|
174
|
-
range_used = []
|
175
|
-
new_subnet = 0
|
176
|
-
new_cidr = ''
|
177
|
-
|
178
|
-
subnet_values = subnet_values.sort!
|
179
|
-
|
180
|
-
subnet_values.each do|value|
|
181
|
-
range_used.push(value[5])
|
182
|
-
end
|
183
|
-
|
184
|
-
range_used.each do |n|
|
185
|
-
if count.to_i == n.to_i
|
186
|
-
else
|
187
|
-
new_subnet = count
|
188
|
-
gap = true
|
189
|
-
break
|
190
|
-
end
|
191
|
-
count += 1
|
192
|
-
end
|
193
|
-
|
194
|
-
if gap
|
195
|
-
new_cidr = format('10.0.%s.0/24', count)
|
196
|
-
else
|
197
|
-
max_value = range_used.max
|
198
|
-
new_subnet = max_value.to_i + 1
|
199
|
-
new_cidr = format('10.0.%s.0/24', new_subnet)
|
200
|
-
end
|
201
|
-
new_cidr
|
202
|
-
rescue => e
|
203
|
-
Logging.error("%s\n%s", e.message, e.backtrace.join("\n"))
|
204
|
-
end
|
205
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
# Defined Openstack object delete.
|
18
|
-
class OpenstackController
|
19
|
-
def delete_server(hParams)
|
20
|
-
required?(hParams, :compute_connection)
|
21
|
-
required?(hParams, :server)
|
22
|
-
|
23
|
-
compute_connect = hParams[:compute_connection]
|
24
|
-
server = hParams[:server]
|
25
|
-
|
26
|
-
compute_connect.servers.get(server.id).destroy
|
27
|
-
end
|
28
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
# Defined Openstack object get.
|
18
|
-
class OpenstackController
|
19
|
-
def self.def_get(connection, name, property_name = nil)
|
20
|
-
property_name = property_name.nil? ? "#{name}s" : property_name.to_s
|
21
|
-
define_method("get_#{name}") do |hParams, sUniqId|
|
22
|
-
required?(hParams, connection)
|
23
|
-
hParams[connection].send(property_name).get(sUniqId)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def_get :compute_connection, :server
|
28
|
-
|
29
|
-
def_get :compute_connection, :image
|
30
|
-
|
31
|
-
def_get :network_connection, :network
|
32
|
-
|
33
|
-
def_get :compute_connection, :keypairs, :key_pairs
|
34
|
-
|
35
|
-
def get_server_log(hParams, sUniqId)
|
36
|
-
required?(hParams, :server)
|
37
|
-
hParams[:server].console(sUniqId)
|
38
|
-
end
|
39
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
# Specific openstack process added to the application process.
|
18
|
-
class OpenstackProcess
|
19
|
-
def openstack_get_tenant(sObjectType, hParams)
|
20
|
-
tenant_name = hParams[:tenant]
|
21
|
-
query = { :name => tenant_name }
|
22
|
-
PrcLib.state("searching for tenant '%s'", tenant_name)
|
23
|
-
list = query_single(sObjectType, query, tenant_name)
|
24
|
-
return list[0] if list.length > 0
|
25
|
-
end
|
26
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
# Defined Openstack object query.
|
18
|
-
class OpenstackController
|
19
|
-
def self.def_basic_query(connection, name, property_name = nil)
|
20
|
-
property_name = property_name.nil? ? name.to_s + 's' : property_name.to_s
|
21
|
-
|
22
|
-
define_method("query_#{name}") do |hParams, _query|
|
23
|
-
required?(hParams, connection)
|
24
|
-
hParams[connection].send(property_name).all
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Implementation of API supporting query Hash
|
29
|
-
def self.def_simple_query(connection, name, property_name = nil)
|
30
|
-
property_name = property_name.nil? ? name.to_s + 's' : property_name.to_s
|
31
|
-
|
32
|
-
define_method("query_#{name}") do |hParams, query|
|
33
|
-
required?(hParams, connection)
|
34
|
-
hParams[connection].send(property_name).all query
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Implementation of API NOT supporting query Hash
|
39
|
-
# The function will filter itself.
|
40
|
-
def self.def_complex_query(connection, name, property_name = nil)
|
41
|
-
property_name = property_name.nil? ? name.to_s + 's' : property_name.to_s
|
42
|
-
|
43
|
-
define_method("query_#{name}") do |hParams, query|
|
44
|
-
required?(hParams, connection)
|
45
|
-
|
46
|
-
key_pairs = hParams[connection].send(property_name).all
|
47
|
-
results = []
|
48
|
-
key_pairs.each do |sElem|
|
49
|
-
selected = true
|
50
|
-
attributes = sElem.instance_variable_get(:@attributes)
|
51
|
-
query.each do |key, value|
|
52
|
-
if attributes[key] != value
|
53
|
-
selected = false
|
54
|
-
break
|
55
|
-
end
|
56
|
-
end
|
57
|
-
results.push sElem if selected
|
58
|
-
end
|
59
|
-
results
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def_simple_query :compute_connection, :tenant
|
64
|
-
|
65
|
-
def_simple_query :compute_connection, :image
|
66
|
-
|
67
|
-
def_simple_query :compute_connection, :flavor
|
68
|
-
|
69
|
-
def_simple_query :compute_connection, :server
|
70
|
-
|
71
|
-
def_simple_query :network_connection, :network
|
72
|
-
|
73
|
-
def_simple_query :network_connection, :subnetwork, :subnets
|
74
|
-
|
75
|
-
def_simple_query :network_connection, :router
|
76
|
-
|
77
|
-
def_simple_query :network_connection, :port
|
78
|
-
|
79
|
-
# def_simple_query :network_connection, :security_groups, :security_groups
|
80
|
-
|
81
|
-
def_simple_query :network_connection, :rule, :security_group_rules
|
82
|
-
|
83
|
-
def_complex_query :compute_connection, :keypairs, :key_pairs
|
84
|
-
|
85
|
-
def_complex_query :compute_connection, :public_ip, :addresses
|
86
|
-
|
87
|
-
def_complex_query :compute_connection, :tenants, :tenants
|
88
|
-
|
89
|
-
def query_security_groups(hParams, query)
|
90
|
-
required?(hParams, :network_connection)
|
91
|
-
required?(hParams, :tenants)
|
92
|
-
|
93
|
-
query[:tenant_id] = hParams[:tenants].id
|
94
|
-
hParams[:network_connection].send(:security_groups).all query
|
95
|
-
end
|
96
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
# Define Openstack update controller
|
18
|
-
class OpenstackController
|
19
|
-
def update_router(obj_to_save, _hParams)
|
20
|
-
router = obj_to_save[:object]
|
21
|
-
# The optional external_gateway_info must be a The network_id for the
|
22
|
-
# external gateway. It cannot be a Hash
|
23
|
-
# See API : http://developer.openstack.org/api-ref-networking-v2.html
|
24
|
-
router.external_gateway_info = router.external_gateway_info['network_id']
|
25
|
-
# Save will restore the Hash.
|
26
|
-
begin
|
27
|
-
router.save
|
28
|
-
true
|
29
|
-
rescue => e
|
30
|
-
Lorj.error "OpenStack: Router save error.\n%s\n%s",
|
31
|
-
e.message, e.backtrace.join("\n")
|
32
|
-
false
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|