blob: e25b42ab3a88ae310d6d9791f0a1c4540204e8b7 [file] [log] [blame]
Chip Bolingf5af85d2019-02-12 15:36:17 -06001#
2# Copyright 2019-present ADTRAN, Inc.
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"""
17ADTRAN OLT Adapter.
18"""
19import structlog
20from twisted.internet import reactor, defer
21
22from pyvoltha.adapters.iadapter import OltAdapter
23from pyvoltha.protos import third_party
24from pyvoltha.protos.common_pb2 import AdminState
Chip Bolingd2d7a4d2019-03-14 14:34:56 -050025from pyvoltha.protos.health_pb2 import HealthStatus
Chip Bolingf5af85d2019-02-12 15:36:17 -060026from adtran_olt_handler import AdtranOltHandler
27
28
29_ = third_party
30log = structlog.get_logger()
31
32
33class AdtranOltAdapter(OltAdapter):
34 name = 'adtran_olt'
35
36 def __init__(self, core_proxy, adapter_proxy, config):
37 super(AdtranOltAdapter, self).__init__(core_proxy=core_proxy,
38 adapter_proxy=adapter_proxy,
39 config=config,
40 device_handler_class=AdtranOltHandler,
41 name=AdtranOltAdapter.name,
42 vendor='ADTRAN, Inc.',
43 version='2.0.0',
44 device_type=AdtranOltAdapter.name,
45 accepts_bulk_flow_update=True,
Chip Bolingd2d7a4d2019-03-14 14:34:56 -050046 accepts_add_remove_flow_updates=True)
Chip Bolingf5af85d2019-02-12 15:36:17 -060047
48 log.debug('adtran_olt.__init__')
49
50 def health(self):
51 """
52 Return a 3-state health status using the voltha.HealthStatus message.
53
54 :return: Deferred or direct return with voltha.HealthStatus message
55 """
56 # TODO: Currently this is always healthy for every adapter.
57 # If we decide not to modify this, delete this method and use base class method
Chip Bolingf5af85d2019-02-12 15:36:17 -060058 return HealthStatus(state=HealthStatus.HEALTHY)
59
60 def abandon_device(self, device):
61 """
62 Make sure the adapter no longer looks after device. This is called
63 if device ownership is taken over by another Voltha instance.
64
65 :param device: A Voltha.Device object
66 :return: (Deferred) Shall be fired to acknowledge abandonment.
67 """
68 log.info('abandon-device', device=device)
69 raise NotImplementedError()
70
71 def adopt_device(self, device):
72 """
73 Make sure the adapter looks after given device. Called when a device
74 is provisioned top-down and needs to be activated by the adapter.
75
76 :param device: A voltha.Device object, with possible device-type
Chip Bolingd2d7a4d2019-03-14 14:34:56 -050077 specific extensions. Such extensions shall be described as part of
78 the device type specification returned by device_types().
79
Chip Bolingf5af85d2019-02-12 15:36:17 -060080 :return: (Deferred) Shall be fired to acknowledge device ownership.
81 """
82 log.info('adopt-device', device=device)
83 kwargs = {
84 'adapter': self,
85 'device-id': device.id
86 }
Chip Bolingd2d7a4d2019-03-14 14:34:56 -050087 try:
88 self.devices_handlers[device.id] = self.device_handler_class(**kwargs)
89 d = defer.Deferred()
90 reactor.callLater(0, self.devices_handlers[device.id].activate, d, False)
91 return d
92
93 except Exception as _e:
94 raise
Chip Bolingf5af85d2019-02-12 15:36:17 -060095
96 def reconcile_device(self, device):
Chip Bolingd2d7a4d2019-03-14 14:34:56 -050097 """
98 Make sure the adapter looks after given device. Called when this
99 device has changed ownership from another Voltha instance to
100 this one (typically, this occurs when the previous voltha
101 instance went down).
102
103 :param device: A voltha.Device object, with possible device-type
104 specific extensions. Such extensions shall be described as part of
105 the device type specification returned by device_types().
106
107 :return: (Deferred) Shall be fired to acknowledge device ownership.
108 """
Chip Bolingf5af85d2019-02-12 15:36:17 -0600109 try:
Chip Bolingd2d7a4d2019-03-14 14:34:56 -0500110 kwargs = {
111 'adapter': self,
112 'device-id': device.id
113 }
114 self.devices_handlers[device.id] = self.device_handler_class(**kwargs)
Chip Bolingf5af85d2019-02-12 15:36:17 -0600115 # Work only required for devices that are in ENABLED state
116 if device.admin_state == AdminState.ENABLED:
Chip Bolingf5af85d2019-02-12 15:36:17 -0600117 d = defer.Deferred()
118 reactor.callLater(0, self.devices_handlers[device.id].activate, d, True)
119
120 else:
121 # Invoke the children reconciliation which would setup the
122 # basic children data structures
123 self.core_proxy.reconcile_child_devices(device.id)
124 return device
125
126 except Exception, e:
127 log.exception('Exception', e=e)
128
129 def self_test_device(self, device):
130 """
131 This is called to Self a device based on a NBI call.
132 :param device: A Voltha.Device object.
133 :return: Will return result of self test
134 """
135 log.info('self-test-device', device=device.id)
136 # TODO: Support self test?
137 from pyvoltha.protos.voltha_pb2 import SelfTestResponse
138 return SelfTestResponse(result=SelfTestResponse.NOT_SUPPORTED)
139
140 def delete_device(self, device):
141 """
142 This is called to delete a device from the PON based on a NBI call.
143 If the device is an OLT then the whole PON will be deleted.
144
145 :param device: A Voltha.Device object.
146 :return: (Deferred) Shall be fired to acknowledge the deletion.
147 """
148 log.info('delete-device', device=device)
149 handler = self.devices_handlers.get(device.id)
150 if handler is not None:
151 reactor.callLater(0, handler.delete)
152 del self.device_handlers[device.id]
153 del self.logical_device_id_to_root_device_id[device.parent_id]
154
155 return device
156
157 def download_image(self, device, request):
158 """
159 This is called to request downloading a specified image into the standby partition
160 of a device based on a NBI call.
161
162 :param device: A Voltha.Device object.
163 :param request: A Voltha.ImageDownload object.
164 :return: (Deferred) Shall be fired to acknowledge the download.
165 """
166 log.info('image_download', device=device, request=request)
167 handler = self.devices_handlers.get(device.id)
168 if handler is not None:
169 return handler.start_download(device, request, defer.Deferred())
170
171 def get_image_download_status(self, device, request):
172 """
173 This is called to inquire about a requested image download status based
174 on a NBI call. The adapter is expected to update the DownloadImage DB object
175 with the query result
176
177 :param device: A Voltha.Device object.
178 :param request: A Voltha.ImageDownload object.
179 :return: (Deferred) Shall be fired to acknowledge
180 """
181 log.info('get_image_download', device=device, request=request)
182 handler = self.devices_handlers.get(device.id)
183 if handler is not None:
184 return handler.download_status(device, request, defer.Deferred())
185
186 def cancel_image_download(self, device, request):
187 """
188 This is called to cancel a requested image download
189 based on a NBI call. The admin state of the device will not
190 change after the download.
191 :param device: A Voltha.Device object.
192 :param request: A Voltha.ImageDownload object.
193 :return: (Deferred) Shall be fired to acknowledge
194 """
195 log.info('cancel_image_download', device=device)
196 handler = self.devices_handlers.get(device.id)
197 if handler is not None:
198 return handler.cancel_download(device, request, defer.Deferred())
199
200 def activate_image_update(self, device, request):
201 """
202 This is called to activate a downloaded image from
203 a standby partition into active partition.
204 Depending on the device implementation, this call
205 may or may not cause device reboot.
206 If no reboot, then a reboot is required to make the
207 activated image running on device
208 This call is expected to be non-blocking.
209 :param device: A Voltha.Device object.
210 :param request: A Voltha.ImageDownload object.
211 :return: (Deferred) OperationResponse object.
212 """
213 log.info('activate_image_update', device=device, request=request)
214 handler = self.devices_handlers.get(device.id)
215 if handler is not None:
216 return handler.activate_image(device, request, defer.Deferred())
217
218 def revert_image_update(self, device, request):
219 """
220 This is called to deactivate the specified image at
221 active partition, and revert to previous image at
222 standby partition.
223 Depending on the device implementation, this call
224 may or may not cause device reboot.
225 If no reboot, then a reboot is required to make the
226 previous image running on device
227 This call is expected to be non-blocking.
228 :param device: A Voltha.Device object.
229 :param request: A Voltha.ImageDownload object.
230 :return: (Deferred) OperationResponse object.
231 """
232 log.info('revert_image_update', device=device, request=request)
233 handler = self.devices_handlers.get(device.id)
234 if handler is not None:
235 return handler.revert_image(device, request, defer.Deferred())