blob: 64232d7e9c301857b62232bdfe4964f7e4644855 [file] [log] [blame]
Girish Gowdru1e77ea02018-09-24 09:10:35 -07001#
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 common.pon_resource_manager.resource_manager import PONResourceManager
20from voltha.registry import registry
21from voltha.core.config.config_backend import ConsulStore
22from voltha.core.config.config_backend import EtcdStore
23
24
25class OpenOltResourceMgr(object):
26 GEMPORT_IDS = "gemport_ids"
27 ALLOC_IDS = "alloc_ids"
28 BASE_PATH_KV_STORE = "openolt/{}" # openolt/<device_id>
29
30 def __init__(self, device_id, host_and_port, extra_args, device_info):
31 self.log = structlog.get_logger(id=device_id,
32 ip=host_and_port)
33 self.device_id = device_id
34 self.host_and_port = host_and_port
35 self.extra_args = extra_args
36 self.device_info = device_info
37 self.args = registry('main').get_args()
38
39 # KV store's IP Address and PORT
40 host, port = '127.0.0.1', 8500
41 if self.args.backend == 'etcd':
42 host, port = self.args.etcd.split(':', 1)
43 self.kv_store = EtcdStore(host, port,
44 OpenOltResourceMgr.BASE_PATH_KV_STORE.format(device_id))
45 elif self.args.backend == 'consul':
46 host, port = self.args.consul.split(':', 1)
47 self.kv_store = ConsulStore(host, port,
48 OpenOltResourceMgr.BASE_PATH_KV_STORE.format(device_id))
49 else:
50 self.log.error('Invalid-backend')
51 raise Exception("Invalid-backend-for-kv-store")
52
53 self.resource_mgr = PONResourceManager(
54 self.device_info.technology,
55 self.extra_args,
56 self.device_id, self.args.backend,
57 host, port
58 )
59
60 # Flag to indicate whether information fetched from device should
61 # be used to intialize PON Resource Ranges
62 self.use_device_info = False
63
64 self.initialize_device_resource_range_and_pool()
65
66 def __del__(self):
67 self.log.info("clearing-device-resource-pool")
68 self.resource_mgr.clear_device_resource_pool()
69
70 def get_onu_id(self, pon_intf_id):
71 onu_id = self.resource_mgr.get_resource_id(
72 pon_intf_id, PONResourceManager.ONU_ID, 1)
73
74 if onu_id is not None:
75 pon_intf_onu_id = (pon_intf_id, onu_id)
76 self.resource_mgr.init_resource_map(
77 pon_intf_onu_id)
78
79 return onu_id
80
81 def get_alloc_id(self, pon_intf_onu_id):
82 # Derive the pon_intf from the pon_intf_onu_id tuple
83 pon_intf = pon_intf_onu_id[0]
84 alloc_id_list = self.resource_mgr.get_current_alloc_ids_for_onu(
85 pon_intf_onu_id)
86
87 if alloc_id_list and len(alloc_id_list) > 0:
88 # Since we support only one alloc_id for the ONU at the moment,
89 # return the first alloc_id in the list, if available, for that
90 # ONU.
91 return alloc_id_list[0]
92
93 alloc_id_list = self.resource_mgr.get_resource_id(
94 pon_intf_id=pon_intf,
95 resource_type=PONResourceManager.ALLOC_ID,
96 num_of_id=1
97 )
98 if alloc_id_list and len(alloc_id_list) == 0:
99 self.log.error("no-alloc-id-available")
100 return None
101
102 # update the resource map on KV store with the list of alloc_id
103 # allocated for the pon_intf_onu_id tuple
104 self.resource_mgr.update_alloc_ids_for_onu(pon_intf_onu_id,
105 alloc_id_list)
106
107 # Since we request only one alloc id, we refer the 0th
108 # index
109 alloc_id = alloc_id_list[0]
110
111 return alloc_id
112
113 def get_gemport_id(self, pon_intf_onu_id):
114 # Derive the pon_intf and onu_id from the pon_intf_onu_id tuple
115 pon_intf = pon_intf_onu_id[0]
116 onu_id = pon_intf_onu_id[1]
117
118 gemport_id_list = self.resource_mgr.get_current_gemport_ids_for_onu(
119 pon_intf_onu_id)
120 if gemport_id_list and len(gemport_id_list) > 0:
121 # Since we support only one gemport_id for the ONU at the moment,
122 # return the first gemport_id in the list, if available, for that
123 # ONU.
124 return gemport_id_list[0]
125
126 gemport_id_list = self.resource_mgr.get_resource_id(
127 pon_intf_id=pon_intf,
128 resource_type=PONResourceManager.GEMPORT_ID,
129 num_of_id=1
130 )
131
132 if gemport_id_list and len(gemport_id_list) == 0:
133 self.log.error("no-gemport-id-available")
134 return None
135
136 # update the resource map on KV store with the list of gemport_id
137 # allocated for the pon_intf_onu_id tuple
138 self.resource_mgr.update_gemport_ids_for_onu(pon_intf_onu_id,
139 gemport_id_list)
140
141 # We currently use only one gemport
142 gemport = gemport_id_list[0]
143
144 pon_intf_gemport = (pon_intf, gemport)
145 # This information is used when packet_indication is received and
146 # we need to derive the ONU Id for which the packet arrived based
147 # on the pon_intf and gemport available in the packet_indication
148 self.kv_store[str(pon_intf_gemport)] = str(onu_id)
149
150 return gemport
151
152 def free_onu_id(self, pon_intf_id, onu_id):
153 result = self.resource_mgr.free_resource_id(
154 pon_intf_id, PONResourceManager.ONU_ID, onu_id)
155
156 pon_intf_onu_id = (pon_intf_id, onu_id)
157 self.resource_mgr.remove_resource_map(
158 pon_intf_onu_id)
159
160 def free_pon_resources_for_onu(self, pon_intf_id_onu_id):
161
162 alloc_ids = \
163 self.resource_mgr.get_current_alloc_ids_for_onu(pon_intf_id_onu_id)
164 pon_intf_id = pon_intf_id_onu_id[0]
165 onu_id = pon_intf_id_onu_id[1]
166 self.resource_mgr.free_resource_id(pon_intf_id,
167 PONResourceManager.ALLOC_ID,
168 alloc_ids)
169
170 gemport_ids = \
171 self.resource_mgr.get_current_gemport_ids_for_onu(pon_intf_id_onu_id)
172 self.resource_mgr.free_resource_id(pon_intf_id,
173 PONResourceManager.GEMPORT_ID,
174 gemport_ids)
175
176 self.resource_mgr.free_resource_id(pon_intf_id,
177 PONResourceManager.ONU_ID,
178 onu_id)
179
180 # Clear resource map associated with (pon_intf_id, gemport_id) tuple.
181 self.resource_mgr.remove_resource_map(pon_intf_id_onu_id)
182
183 # Clear the ONU Id associated with the (pon_intf_id, gemport_id) tuple.
184 for gemport_id in gemport_ids:
185 del self.kv_store[str((pon_intf_id, gemport_id))]
186
187 def initialize_device_resource_range_and_pool(self):
188 if not self.use_device_info:
189 status = self.resource_mgr.init_resource_ranges_from_kv_store()
190 if not status:
191 self.log.error("failed-to-load-resource-range-from-kv-store")
192 # When we have failed to read the PON Resource ranges from KV
193 # store, use the information fetched from device.
194 self.use_device_info = True
195
196 if self.use_device_info:
197 self.log.info("using-device-info-to-init-pon-resource-ranges")
198 self.resource_mgr.init_default_pon_resource_ranges(
199 self.device_info.onu_id_start,
200 self.device_info.onu_id_end,
201 self.device_info.alloc_id_start,
202 self.device_info.alloc_id_end,
203 self.device_info.gemport_id_start,
204 self.device_info.gemport_id_end,
205 self.device_info.pon_ports
206 )
207
208 # After we have initialized resource ranges, initialize the
209 # resource pools accordingly.
210 self.resource_mgr.init_device_resource_pool()
211