blob: 8cce46cce2abdecbcb5fcb10fa1157fdf84b0daf [file] [log] [blame]
Chip Bolingf5af85d2019-02-12 15:36:17 -06001#
2# Copyright 2018 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import structlog
18
19from pyvoltha.adapters.common.pon_resource_manager.resource_manager import PONResourceManager
20from pyvoltha.common.utils.registry import registry
21# from voltha.core.config.config_backend import ConsulStore
22# from voltha.core.config.config_backend import EtcdStore
23from pyvoltha.adapters.common.kvstore.kvstore import create_kv_client
24from adtran_resource_manager import AdtranPONResourceManager
25
26
27class AdtranOltResourceMgr(object):
28
29 GEMPORT_IDS = "gemport_ids"
30 ALLOC_IDS = "alloc_ids"
31 BASE_PATH_KV_STORE = "adtran_olt/{}" # adtran_olt/<device_id>
32
33 def __init__(self, device_id, host_and_port, extra_args, device_info):
34 self.log = structlog.get_logger(id=device_id,
35 ip=host_and_port)
36 self.device_id = device_id
37 self.host_and_port = host_and_port
38 self.extra_args = extra_args
39 self.device_info = device_info
40 self.args = registry('main').get_args()
41 self._path_prefix = AdtranOltResourceMgr.BASE_PATH_KV_STORE.format(device_id)
42
43 # KV store's IP Address and PORT
44 # host, port = '127.0.0.1', 8500
45 if self.args.backend == 'etcd':
46 host, port = self.args.etcd.split(':', 1)
47 self.kv_store = create_kv_client('etcd', host, port)
48 # self.kv_store = EtcdStore(host, port,
49 # AdtranOltResourceMgr.BASE_PATH_KV_STORE.format(device_id))
50 elif self.args.backend == 'consul':
51 host, port = self.args.consul.split(':', 1)
52 self.kv_store = create_kv_client('consul', host, port)
53 # self.kv_store = ConsulStore(host, port,
54 # AdtranOltResourceMgr.BASE_PATH_KV_STORE.format(device_id))
55 else:
56 self.log.error('Invalid-backend')
57 raise Exception("Invalid-backend-for-kv-store")
58
59 self.resource_mgr = AdtranPONResourceManager(
60 self.device_info.technology,
61 self.extra_args,
62 self.device_id, self.args.backend,
63 host, port
64 )
65 # Tech profiles uses this resource manager to retrieve information on a per-interface
66 # basis
67 self.resource_managers = {intf_id: self.resource_mgr for intf_id in device_info.intf_ids}
68
69 # Flag to indicate whether information fetched from device should
70 # be used to initialize PON Resource Ranges
71 self.use_device_info = False
72
73 self.initialize_device_resource_range_and_pool()
74
75 def __del__(self):
76 self.log.info("clearing-device-resource-pool")
77 for key, resource_mgr in self.resource_mgrs.iteritems():
78 resource_mgr.clear_device_resource_pool()
79
80 def get_onu_id(self, pon_intf_id):
81 onu_id = self.resource_mgr.get_resource_id(pon_intf_id,
82 PONResourceManager.ONU_ID,
83 onu_id=None,
84 num_of_id=1)
85 if onu_id is not None:
86 pon_intf_onu_id = (pon_intf_id, onu_id)
87 self.resource_mgr.init_resource_map(pon_intf_onu_id)
88
89 return onu_id
90
91 def free_onu_id(self, pon_intf_id, onu_id):
92 self.resource_mgr.free_resource_id(pon_intf_id,
93 PONResourceManager.ONU_ID,
94 onu_id)
95 pon_intf_onu_id = (pon_intf_id, onu_id)
96 self.resource_mgr.remove_resource_map(pon_intf_onu_id)
97
98 def get_alloc_id(self, pon_intf_onu_id):
99 # Derive the pon_intf from the pon_intf_onu_id tuple
100 pon_intf = pon_intf_onu_id[0]
101 onu_id = pon_intf_onu_id[1]
102 alloc_id_list = self.resource_mgr.get_current_alloc_ids_for_onu(pon_intf_onu_id)
103
104 if alloc_id_list and len(alloc_id_list) > 0:
105 # Since we support only one alloc_id for the ONU at the moment,
106 # return the first alloc_id in the list, if available, for that
107 # ONU.
108 return alloc_id_list[0]
109
110 alloc_id_list = self.resource_mgr.get_resource_id(pon_intf,
111 PONResourceManager.ALLOC_ID,
112 onu_id=onu_id,
113 num_of_id=1)
114 if alloc_id_list and len(alloc_id_list) == 0:
115 self.log.error("no-alloc-id-available")
116 return None
117
118 # update the resource map on KV store with the list of alloc_id
119 # allocated for the pon_intf_onu_id tuple
120 self.resource_mgr.update_alloc_ids_for_onu(pon_intf_onu_id,
121 alloc_id_list)
122
123 # Since we request only one alloc id, we refer the 0th
124 # index
125 alloc_id = alloc_id_list[0]
126
127 return alloc_id
128
129 def get_gemport_id(self, pon_intf_onu_id, num_of_id=1):
130 # TODO: Remove this if never used
131 # Derive the pon_intf and onu_id from the pon_intf_onu_id tuple
132 pon_intf = pon_intf_onu_id[0]
133 onu_id = pon_intf_onu_id[1]
134 uni_id = pon_intf_onu_id[2]
135 assert False, 'unused function'
136
137 # gemport_id_list = self.resource_managers[pon_intf].get_current_gemport_ids_for_onu(
138 # pon_intf_onu_id)
139 # if gemport_id_list and len(gemport_id_list) > 0:
140 # return gemport_id_list
141 #
142 # gemport_id_list = self.resource_mgrs[pon_intf].get_resource_id(
143 # pon_intf_id=pon_intf,
144 # resource_type=PONResourceManager.GEMPORT_ID,
145 # num_of_id=num_of_id
146 # )
147 #
148 # if gemport_id_list and len(gemport_id_list) == 0:
149 # self.log.error("no-gemport-id-available")
150 # return None
151 #
152 # # update the resource map on KV store with the list of gemport_id
153 # # allocated for the pon_intf_onu_id tuple
154 # self.resource_managers[pon_intf].update_gemport_ids_for_onu(pon_intf_onu_id,
155 # gemport_id_list)
156 #
157 # self.update_gemports_ponport_to_onu_map_on_kv_store(gemport_id_list,
158 # pon_intf, onu_id, uni_id)
159 # return gemport_id_list
160
161 def free_pon_resources_for_onu(self, pon_intf_id_onu_id):
162 """ Typically called on ONU delete """
163
164 pon_intf_id = pon_intf_id_onu_id[0]
165 onu_id = pon_intf_id_onu_id[1]
166 try:
167 alloc_ids = self.resource_mgr.get_current_alloc_ids_for_onu(pon_intf_id_onu_id)
168 if alloc_ids is not None:
169 self.resource_mgr.free_resource_id(pon_intf_id,
170 PONResourceManager.ALLOC_ID,
171 alloc_ids, onu_id=onu_id)
172 except:
173 pass
174
175 try:
176 gemport_ids = self.resource_mgr.get_current_gemport_ids_for_onu(pon_intf_id_onu_id)
177 if gemport_ids is not None:
178 self.resource_mgr.free_resource_id(pon_intf_id,
179 PONResourceManager.GEMPORT_ID,
180 gemport_ids)
181 except:
182 pass
183
184 try:
185 self.resource_mgr.free_resource_id(pon_intf_id,
186 PONResourceManager.ONU_ID,
187 onu_id)
188 except:
189 pass
190
191 # Clear resource map associated with (pon_intf_id, gemport_id) tuple.
192 self.resource_mgr.remove_resource_map(pon_intf_id_onu_id)
193
194 # Clear the ONU Id associated with the (pon_intf_id, gemport_id) tuple.
195 if gemport_ids is not None:
196 for gemport_id in gemport_ids:
197 try:
198 self.kv_store.delete(self._make_path(str((pon_intf_id, gemport_id))))
199 # del self.kv_store[str((pon_intf_id, gemport_id))]
200 except:
201 pass
202
203 def initialize_device_resource_range_and_pool(self):
204 if not self.use_device_info:
205 status = self.resource_mgr.init_resource_ranges_from_kv_store()
206 if not status:
207 self.log.error("failed-to-load-resource-range-from-kv-store")
208 # When we have failed to read the PON Resource ranges from KV
209 # store, use the information selected as the default.
210 self.use_device_info = True
211
212 if self.use_device_info:
213 self.log.info("using-device-info-to-init-pon-resource-ranges")
214 self.resource_mgr.init_default_pon_resource_ranges(
215 onu_id_start_idx=self.device_info.onu_id_start,
216 onu_id_end_idx=self.device_info.onu_id_end,
217 alloc_id_start_idx=self.device_info.alloc_id_start,
218 alloc_id_end_idx=self.device_info.alloc_id_end,
219 gemport_id_start_idx=self.device_info.gemport_id_start,
220 gemport_id_end_idx=self.device_info.gemport_id_end,
221 num_of_pon_ports=self.device_info.pon_ports,
222 intf_ids=self.device_info.intf_ids
223 )
224
225 # After we have initialized resource ranges, initialize the
226 # resource pools accordingly.
227 self.resource_mgr.init_device_resource_pool()
228
229 def get_current_gemport_ids_for_onu(self, pon_intf_onu_id):
230 pon_intf_id = pon_intf_onu_id[0]
231 return self.resource_managers[pon_intf_id].get_current_gemport_ids_for_onu(pon_intf_onu_id)
232
233 def get_current_alloc_ids_for_onu(self, pon_intf_onu_id):
234 pon_intf_id = pon_intf_onu_id[0]
235 alloc_ids = self.resource_managers[pon_intf_id].get_current_alloc_ids_for_onu(pon_intf_onu_id)
236 if alloc_ids is None:
237 return None
238 # We support only one tcont at the moment
239 return alloc_ids[0]
240
241 def update_gemports_ponport_to_onu_map_on_kv_store(self, gemport_list, pon_port, onu_id, uni_id):
242 for gemport in gemport_list:
243 pon_intf_gemport = (pon_port, gemport)
244 # This information is used when packet_indication is received and
245 # we need to derive the ONU Id for which the packet arrived based
246 # on the pon_intf and gemport available in the packet_indication
247 # self.kv_store[str(pon_intf_gemport)] = ' '.join(map(str, (onu_id, uni_id)))
Chip Bolingd2d7a4d2019-03-14 14:34:56 -0500248 self.kv_store.put(self._make_path(str(pon_intf_gemport)), ' '.join(map(str, (onu_id, uni_id))))
Chip Bolingf5af85d2019-02-12 15:36:17 -0600249
250 def get_onu_uni_from_ponport_gemport(self, pon_port, gemport):
251 pon_intf_gemport = (pon_port, gemport)
252 #return tuple(map(int, self.kv_store[str(pon_intf_gemport)].split(' ')))
253 return tuple(map(int, self.kv_store.get(self._make_path(str(pon_intf_gemport))).split(' ')))
254
255 def get_flow_id(self, pon_intf_id, onu_id, uni_id, flow_store_cookie, flow_category=None):
256 pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
257 try:
258 flow_ids = self.resource_managers[pon_intf_id]. \
259 get_current_flow_ids_for_onu(pon_intf_onu_id)
260 if flow_ids is not None:
261 for flow_id in flow_ids:
262 flows = self.get_flow_id_info(pon_intf_id, onu_id, uni_id, flow_id)
263 assert (isinstance(flows, list))
264 for flow in flows:
265
266 if flow_category is not None and \
267 'flow_category' in flow and \
268 flow['flow_category'] == flow_category:
269 return flow_id
270 if flow['flow_store_cookie'] == flow_store_cookie:
271 return flow_id
272 except Exception as e:
273 self.log.error("error-retrieving-flow-info", e=e)
274
275 flow_id = self.resource_managers[pon_intf_id].get_resource_id(
276 pon_intf_onu_id[0], PONResourceManager.FLOW_ID)
277 if flow_id is not None:
278 self.resource_managers[pon_intf_id].update_flow_id_for_onu(
279 pon_intf_onu_id, flow_id
280 )
281
282 return flow_id
283
284 def get_flow_id_info(self, pon_intf_id, onu_id, uni_id, flow_id):
285 pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
286 return self.resource_managers[pon_intf_id].get_flow_id_info(pon_intf_onu_id, flow_id)
287
288 def get_current_flow_ids_for_uni(self, pon_intf_id, onu_id, uni_id):
289 pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
290 return self.resource_managers[pon_intf_id].get_current_flow_ids_for_onu(pon_intf_onu_id)
291
292 def update_flow_id_info_for_uni(self, pon_intf_id, onu_id, uni_id, flow_id, flow_data):
293 pon_intf_onu_id = (pon_intf_id, onu_id, uni_id)
294 return self.resource_managers[pon_intf_id].update_flow_id_info_for_onu(
295 pon_intf_onu_id, flow_id, flow_data)