blob: db9fe35ce5f63b2f80837795261b42f4e8f1a2e9 [file] [log] [blame]
Shad Ansari2825d012018-02-22 23:57:46 +00001#
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
17"""
18Openolt adapter.
19"""
Shad Ansari2825d012018-02-22 23:57:46 +000020from zope.interface import implementer
Shad Ansarif9d2d102018-06-13 02:15:26 +000021import structlog
Shad Ansari2825d012018-02-22 23:57:46 +000022
23from openolt_device import OpenoltDevice
24from voltha.adapters.interface import IAdapterInterface
25from voltha.protos import third_party
26from voltha.protos.adapter_pb2 import Adapter
27from voltha.protos.adapter_pb2 import AdapterConfig
28from voltha.protos.common_pb2 import LogLevel
Scott Bakerd3190952018-09-04 15:47:28 -070029from voltha.protos.common_pb2 import OperationResp
Shad Ansari2825d012018-02-22 23:57:46 +000030from voltha.protos.device_pb2 import DeviceType, DeviceTypes
Shad Ansari2825d012018-02-22 23:57:46 +000031from voltha.registry import registry
Shad Ansaricd20a6d2018-10-02 14:36:33 +000032from voltha.adapters.openolt.openolt_flow_mgr import OpenOltFlowMgr
33from voltha.adapters.openolt.openolt_alarms import OpenOltAlarmMgr
34from voltha.adapters.openolt.openolt_statistics import OpenOltStatisticsMgr
Shad Ansaricd20a6d2018-10-02 14:36:33 +000035from voltha.adapters.openolt.openolt_platform import OpenOltPlatform
Girish Gowdru1e77ea02018-09-24 09:10:35 -070036from voltha.adapters.openolt.openolt_resource_manager import OpenOltResourceMgr
Shad Ansari134947d2019-02-14 23:45:03 -080037from voltha.adapters.openolt.openolt_data_model import OpenOltDataModel
Shad Ansari2825d012018-02-22 23:57:46 +000038
39_ = third_party
40log = structlog.get_logger()
41
Shad Ansarif9d2d102018-06-13 02:15:26 +000042
Shad Ansaricd20a6d2018-10-02 14:36:33 +000043OpenOltDefaults = {
44 'support_classes': {
45 'platform': OpenOltPlatform,
Shad Ansarid5577972019-02-22 09:35:03 -080046 'data_model': OpenOltDataModel,
Girish Gowdru1e77ea02018-09-24 09:10:35 -070047 'resource_mgr': OpenOltResourceMgr,
Shad Ansaricd20a6d2018-10-02 14:36:33 +000048 'flow_mgr': OpenOltFlowMgr,
49 'alarm_mgr': OpenOltAlarmMgr,
50 'stats_mgr': OpenOltStatisticsMgr,
Shad Ansaricd20a6d2018-10-02 14:36:33 +000051 }
52}
53
Shad Ansari78de2be2018-10-12 22:13:54 +000054
Shad Ansari2825d012018-02-22 23:57:46 +000055@implementer(IAdapterInterface)
56class OpenoltAdapter(object):
57 name = 'openolt'
58
59 supported_device_types = [
60 DeviceType(
61 id=name,
62 adapter=name,
Nicolas Palpacuer0c7c3162018-08-08 11:27:57 -040063 accepts_bulk_flow_update=True,
64 accepts_direct_logical_flows_update=True
Shad Ansari2825d012018-02-22 23:57:46 +000065 )
66 ]
67
68 def __init__(self, adapter_agent, config):
69 self.adapter_agent = adapter_agent
70 self.config = config
71 self.descriptor = Adapter(
72 id=self.name,
73 vendor='OLT white box vendor',
74 version='0.1',
75 config=AdapterConfig(log_level=LogLevel.INFO)
76 )
77 log.debug('openolt.__init__', adapter_agent=adapter_agent)
78 self.devices = dict() # device_id -> OpenoltDevice()
79 self.interface = registry('main').get_args().interface
80 self.logical_device_id_to_root_device_id = dict()
Shad Ansari5dbc9c82018-05-10 03:29:31 +000081 self.num_devices = 0
Shad Ansari2825d012018-02-22 23:57:46 +000082
83 def start(self):
84 log.info('started', interface=self.interface)
85
86 def stop(self):
87 log.info('stopped', interface=self.interface)
88
89 def adapter_descriptor(self):
90 log.debug('get descriptor', interface=self.interface)
91 return self.descriptor
92
93 def device_types(self):
Shad Ansarif9d2d102018-06-13 02:15:26 +000094 log.debug('get device_types', interface=self.interface,
95 items=self.supported_device_types)
Shad Ansari2825d012018-02-22 23:57:46 +000096 return DeviceTypes(items=self.supported_device_types)
97
98 def health(self):
99 log.debug('get health', interface=self.interface)
100 raise NotImplementedError()
101
102 def change_master_state(self, master):
Shad Ansarif9d2d102018-06-13 02:15:26 +0000103 log.debug('change_master_state', interface=self.interface,
104 master=master)
Shad Ansari2825d012018-02-22 23:57:46 +0000105 raise NotImplementedError()
106
107 def adopt_device(self, device):
108 log.info('adopt-device', device=device)
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000109
Shad Ansari2825d012018-02-22 23:57:46 +0000110 kwargs = {
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000111 'support_classes': OpenOltDefaults['support_classes'],
Shad Ansari2825d012018-02-22 23:57:46 +0000112 'adapter_agent': self.adapter_agent,
Shad Ansari4f9a9732019-03-08 16:47:08 -0800113 'device_id': device.id,
114 'host_and_port': device.host_and_port,
115 'extra_args': device.extra_args
Shad Ansari2825d012018-02-22 23:57:46 +0000116 }
117 try:
118 self.devices[device.id] = OpenoltDevice(**kwargs)
119 except Exception as e:
120 log.error('Failed to adopt OpenOLT device', error=e)
Matteo Scandolobf5ae0c2018-11-15 18:12:54 -0800121 # TODO set status to ERROR so that is clear something went wrong
Shad Ansari2825d012018-02-22 23:57:46 +0000122 del self.devices[device.id]
123 raise
Shad Ansari5dbc9c82018-05-10 03:29:31 +0000124 else:
125 self.num_devices += 1
Shad Ansari2825d012018-02-22 23:57:46 +0000126
127 def reconcile_device(self, device):
128 log.info('reconcile-device', device=device)
Nicolas Palpacuer253461f2018-06-01 12:01:45 -0400129 kwargs = {
Girish Gowdru1e77ea02018-09-24 09:10:35 -0700130 'support_classes': OpenOltDefaults['support_classes'],
Nicolas Palpacuer253461f2018-06-01 12:01:45 -0400131 'adapter_agent': self.adapter_agent,
132 'device': device,
133 'device_num': self.num_devices + 1,
134 'reconciliation': True
135 }
136 try:
137 reconciled_device = OpenoltDevice(**kwargs)
Shad Ansarif9d2d102018-06-13 02:15:26 +0000138 log.debug('reconciled-device-recreated',
139 device_id=reconciled_device.device_id)
Nicolas Palpacuer253461f2018-06-01 12:01:45 -0400140 self.devices[device.id] = reconciled_device
141 except Exception as e:
Shad Ansarif9d2d102018-06-13 02:15:26 +0000142 log.error('Failed to reconcile OpenOLT device', error=e,
143 exception_type=type(e).__name__)
Nicolas Palpacuer253461f2018-06-01 12:01:45 -0400144 del self.devices[device.id]
145 raise
146 else:
147 self.num_devices += 1
148 # Invoke the children reconciliation which would setup the
149 # basic children data structures
150 self.adapter_agent.reconcile_child_devices(device.id)
151 return device
Shad Ansari2825d012018-02-22 23:57:46 +0000152
153 def abandon_device(self, device):
154 log.info('abandon-device', device=device)
155 raise NotImplementedError()
156
157 def disable_device(self, device):
158 log.info('disable-device', device=device)
Jonathan Davis0f917a22018-05-30 14:39:45 -0400159 handler = self.devices[device.id]
160 handler.disable()
Shad Ansari2825d012018-02-22 23:57:46 +0000161
162 def reenable_device(self, device):
163 log.info('reenable-device', device=device)
Jonathan Davis0f917a22018-05-30 14:39:45 -0400164 handler = self.devices[device.id]
165 handler.reenable()
Shad Ansari2825d012018-02-22 23:57:46 +0000166
167 def reboot_device(self, device):
168 log.info('reboot_device', device=device)
Nicolas Palpacuerfd365ac2018-08-02 11:37:37 -0400169 handler = self.devices[device.id]
170 handler.reboot()
Shad Ansari2825d012018-02-22 23:57:46 +0000171
172 def download_image(self, device, request):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400173 log.info('image_download - Not implemented yet', device=device,
174 request=request)
Shad Ansari2825d012018-02-22 23:57:46 +0000175 raise NotImplementedError()
176
177 def get_image_download_status(self, device, request):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400178 log.info('get_image_download - Not implemented yet', device=device,
179 request=request)
Shad Ansari2825d012018-02-22 23:57:46 +0000180 raise NotImplementedError()
181
182 def cancel_image_download(self, device, request):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400183 log.info('cancel_image_download - Not implemented yet', device=device)
Shad Ansari2825d012018-02-22 23:57:46 +0000184 raise NotImplementedError()
185
186 def activate_image_update(self, device, request):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400187 log.info('activate_image_update - Not implemented yet',
188 device=device, request=request)
Shad Ansari2825d012018-02-22 23:57:46 +0000189 raise NotImplementedError()
190
191 def revert_image_update(self, device, request):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400192 log.info('revert_image_update - Not implemented yet',
193 device=device, request=request)
Shad Ansari2825d012018-02-22 23:57:46 +0000194 raise NotImplementedError()
195
196 def self_test_device(self, device):
Shad Ansarif9d2d102018-06-13 02:15:26 +0000197 # from voltha.protos.voltha_pb2 import SelfTestResponse
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400198 log.info('Not implemented yet')
Shad Ansari2825d012018-02-22 23:57:46 +0000199 raise NotImplementedError()
200
201 def delete_device(self, device):
202 log.info('delete-device', device=device)
Jonathan Davis0f917a22018-05-30 14:39:45 -0400203 handler = self.devices[device.id]
204 handler.delete()
205 del self.devices[device.id]
Matteo Scandoloa171b6e2018-09-14 16:48:24 -0700206 del self.logical_device_id_to_root_device_id[device.parent_id]
Nicolas Palpacuer0d44e682018-08-06 10:30:26 -0400207 return device
Shad Ansari2825d012018-02-22 23:57:46 +0000208
209 def get_device_details(self, device):
210 log.debug('get_device_details', device=device)
211 raise NotImplementedError()
212
213 def update_flows_bulk(self, device, flows, groups):
214 log.info('bulk-flow-update', device_id=device.id,
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400215 number_of_flows=len(flows.items), number_of_groups=len(
Shad Ansari78de2be2018-10-12 22:13:54 +0000216 groups.items))
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400217 log.debug('flows and grousp details', flows=flows, groups=groups)
Shad Ansari2825d012018-02-22 23:57:46 +0000218 assert len(groups.items) == 0, "Cannot yet deal with groups"
219 handler = self.devices[device.id]
220 return handler.update_flow_table(flows.items)
221
222 def update_flows_incrementally(self, device, flow_changes, group_changes):
Shad Ansarif9d2d102018-06-13 02:15:26 +0000223 log.debug('update_flows_incrementally', device=device,
224 flow_changes=flow_changes, group_changes=group_changes)
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400225 log.info('This device does not allow this, therefore it is Not '
226 'implemented')
Shad Ansari2825d012018-02-22 23:57:46 +0000227 raise NotImplementedError()
228
Nicolas Palpacuer0c7c3162018-08-08 11:27:57 -0400229 def update_logical_flows(self, device_id, flows_to_add, flows_to_remove,
230 groups, device_rules_map):
231
232 log.info('logical-flows-update', flows_to_add=len(flows_to_add),
Shad Ansari78de2be2018-10-12 22:13:54 +0000233 flows_to_remove=len(flows_to_remove))
Nicolas Palpacuer0c7c3162018-08-08 11:27:57 -0400234 log.debug('logical-flows-details', flows_to_add=flows_to_add,
235 flows_to_remove=flows_to_remove)
236 assert len(groups) == 0, "Cannot yet deal with groups"
237 handler = self.devices[device_id]
238 handler.update_logical_flows(flows_to_add, flows_to_remove,
239 device_rules_map)
240
Shad Ansari2825d012018-02-22 23:57:46 +0000241 def update_pm_config(self, device, pm_configs):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400242 log.info('update_pm_config - Not implemented yet', device=device,
Shad Ansari78de2be2018-10-12 22:13:54 +0000243 pm_configs=pm_configs)
Shad Ansari2825d012018-02-22 23:57:46 +0000244 raise NotImplementedError()
245
246 def send_proxied_message(self, proxy_address, msg):
Zack Williams18357ed2018-11-14 10:41:08 -0700247 log.debug('send-proxied-message',
248 proxy_address=proxy_address,
249 proxied_msg=msg)
Shad Ansari2825d012018-02-22 23:57:46 +0000250 handler = self.devices[proxy_address.device_id]
251 handler.send_proxied_message(proxy_address, msg)
252
253 def receive_proxied_message(self, proxy_address, msg):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400254 log.debug('receive_proxied_message - Not implemented',
255 proxy_address=proxy_address,
Zack Williams18357ed2018-11-14 10:41:08 -0700256 proxied_msg=msg)
Shad Ansari2825d012018-02-22 23:57:46 +0000257 raise NotImplementedError()
258
259 def receive_packet_out(self, logical_device_id, egress_port_no, msg):
260 log.debug('packet-out', logical_device_id=logical_device_id,
261 egress_port_no=egress_port_no, msg_len=len(msg))
Shad Ansarif9d2d102018-06-13 02:15:26 +0000262
Shad Ansari42db7342018-04-25 21:39:46 +0000263 def ldi_to_di(ldi):
264 di = self.logical_device_id_to_root_device_id.get(ldi)
265 if di is None:
266 logical_device = self.adapter_agent.get_logical_device(ldi)
267 di = logical_device.root_device_id
268 self.logical_device_id_to_root_device_id[ldi] = di
269 return di
270
Matteo Scandoloa171b6e2018-09-14 16:48:24 -0700271 try:
272 device_id = ldi_to_di(logical_device_id)
273 handler = self.devices[device_id]
274 handler.packet_out(egress_port_no, msg)
275 except Exception as e:
276 log.error('packet-out:exception', e=e.message)
Shad Ansari2825d012018-02-22 23:57:46 +0000277
278 def receive_inter_adapter_message(self, msg):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400279 log.info('rx_inter_adapter_msg - Not implemented')
Shad Ansari2825d012018-02-22 23:57:46 +0000280 raise NotImplementedError()
281
282 def suppress_alarm(self, filter):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400283 log.info('suppress_alarm - Not implemented yet', filter=filter)
Shad Ansari2825d012018-02-22 23:57:46 +0000284 raise NotImplementedError()
285
286 def unsuppress_alarm(self, filter):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400287 log.info('unsuppress_alarm - Not implemented yet', filter=filter)
Shad Ansari2825d012018-02-22 23:57:46 +0000288 raise NotImplementedError()
289
290 # PON Mgnt APIs #
291 def create_interface(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400292 log.debug('create-interface - Not implemented - We do not use this',
293 data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000294 raise NotImplementedError()
295
296 def update_interface(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400297 log.debug('update-interface - Not implemented - We do not use this',
298 data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000299 raise NotImplementedError()
300
301 def remove_interface(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400302 log.debug('remove-interface - Not implemented - We do not use this',
303 data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000304 raise NotImplementedError()
305
306 def receive_onu_detect_state(self, proxy_address, state):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400307 log.debug('receive-onu-detect-state - Not implemented - We do not '
308 'use this', proxy_address=proxy_address,
Shad Ansarif9d2d102018-06-13 02:15:26 +0000309 state=state)
Shad Ansari2825d012018-02-22 23:57:46 +0000310 raise NotImplementedError()
311
312 def create_tcont(self, device, tcont_data, traffic_descriptor_data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400313 log.info('create-tcont - Not implemented - We do not use this',
314 tcont_data=tcont_data,
Shad Ansari2825d012018-02-22 23:57:46 +0000315 traffic_descriptor_data=traffic_descriptor_data)
316 raise NotImplementedError()
317
318 def update_tcont(self, device, tcont_data, traffic_descriptor_data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400319 log.info('update-tcont - Not implemented - We do not use this',
320 tcont_data=tcont_data,
Shad Ansari2825d012018-02-22 23:57:46 +0000321 traffic_descriptor_data=traffic_descriptor_data)
322 raise NotImplementedError()
323
324 def remove_tcont(self, device, tcont_data, traffic_descriptor_data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400325 log.info('remove-tcont - Not implemented - We do not use this',
326 tcont_data=tcont_data,
Shad Ansari2825d012018-02-22 23:57:46 +0000327 traffic_descriptor_data=traffic_descriptor_data)
328 raise NotImplementedError()
329
330 def create_gemport(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400331 log.info('create-gemport - Not implemented - We do not use this',
332 data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000333 raise NotImplementedError()
334
335 def update_gemport(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400336 log.info('update-gemport - Not implemented - We do not use this',
337 data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000338 raise NotImplementedError()
339
340 def remove_gemport(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400341 log.info('remove-gemport - Not implemented - We do not use this',
342 data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000343 raise NotImplementedError()
344
345 def create_multicast_gemport(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400346 log.info('create-mcast-gemport - Not implemented - We do not use '
347 'this', data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000348 raise NotImplementedError()
349
350 def update_multicast_gemport(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400351 log.info('update-mcast-gemport - Not implemented - We do not use '
352 'this', data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000353 raise NotImplementedError()
354
355 def remove_multicast_gemport(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400356 log.info('remove-mcast-gemport - Not implemented - We do not use '
357 'this', data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000358 raise NotImplementedError()
359
360 def create_multicast_distribution_set(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400361 log.info('create-mcast-distribution-set - Not implemented - We do '
362 'not use this', data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000363 raise NotImplementedError()
364
365 def update_multicast_distribution_set(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400366 log.info('update-mcast-distribution-set - Not implemented - We do '
367 'not use this', data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000368 raise NotImplementedError()
369
370 def remove_multicast_distribution_set(self, device, data):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400371 log.info('remove-mcast-distribution-set - Not implemented - We do '
372 'not use this', data=data)
Shad Ansari2825d012018-02-22 23:57:46 +0000373 raise NotImplementedError()
Jonathan Davisb45bb372018-07-19 15:05:15 -0400374
Jonathan Davisb45bb372018-07-19 15:05:15 -0400375 def delete_child_device(self, parent_device_id, child_device):
Nicolas Palpacuer324dcae2018-08-02 11:12:22 -0400376 log.info('delete-child_device', parent_device_id=parent_device_id,
377 child_device=child_device)
Jonathan Davisb45bb372018-07-19 15:05:15 -0400378 handler = self.devices[parent_device_id]
Nicolas Palpacuer131790b2018-08-20 09:59:34 -0400379 if handler is not None:
380 handler.delete_child_device(child_device)
381 else:
382 log.error('Could not find matching handler',
Shad Ansari78de2be2018-10-12 22:13:54 +0000383 looking_for_device_id=parent_device_id,
Nicolas Palpacuer131790b2018-08-20 09:59:34 -0400384 available_handlers=self.devices.keys())
Nicolas Palpacuer30027f42018-09-06 15:55:54 -0400385
386 # This is currently not part of the Iadapter interface
387 def collect_stats(self, device_id):
388 log.info('collect_stats', device_id=device_id)
Shad Ansari78de2be2018-10-12 22:13:54 +0000389 handler = self.devices[device_id]
Nicolas Palpacuer30027f42018-09-06 15:55:54 -0400390 if handler is not None:
391 handler.trigger_statistics_collection()
392 else:
393 log.error('Could not find matching handler',
394 looking_for_device_id=device_id,
395 available_handlers=self.devices.keys())
Scott Bakerd3190952018-09-04 15:47:28 -0700396
397 def simulate_alarm(self, device, request):
398 log.info('simulate_alarm', device=device, request=request)
399
400 if device.id not in self.devices:
401 log.error("Device does not exist", device_id=device.id)
402 return OperationResp(code=OperationResp.OPERATION_FAILURE,
Shad Ansari78de2be2018-10-12 22:13:54 +0000403 additional_info="Device %s does not exist"
404 % device.id)
Scott Bakerd3190952018-09-04 15:47:28 -0700405
406 handler = self.devices[device.id]
407
408 handler.simulate_alarm(request)
409
410 return OperationResp(code=OperationResp.OPERATION_SUCCESS)