blob: c822c428b8f9805d799c51cba4a47948c3f47050 [file] [log] [blame]
Zsolt Haraszti66862032016-11-28 14:28:39 -08001#
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08002# Copyright 2017 the original author or authors.
Zsolt Haraszti66862032016-11-28 14:28:39 -08003#
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"""
18Agent to play gateway between CORE and an individual adapter.
19"""
20from uuid import uuid4
Stephane Barbarie52198b92017-03-02 13:44:46 -050021import arrow
22import re
Zsolt Haraszti66862032016-11-28 14:28:39 -080023
24import structlog
Zsolt Harasztief05ad22017-01-07 22:08:06 -080025from google.protobuf.json_format import MessageToJson
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -080026from scapy.packet import Packet
Zsolt Haraszti66862032016-11-28 14:28:39 -080027from twisted.internet.defer import inlineCallbacks, returnValue
28from zope.interface import implementer
29
Zsolt Haraszti89a27302016-12-08 16:53:06 -080030from common.event_bus import EventBusClient
Zsolt Harasztief05ad22017-01-07 22:08:06 -080031from common.frameio.frameio import hexify
Zsolt Haraszti66862032016-11-28 14:28:39 -080032from voltha.adapters.interface import IAdapterAgent
33from voltha.protos import third_party
34from voltha.protos.device_pb2 import Device, Port
Stephane Barbariecc6b2e62017-03-02 14:35:55 -050035from voltha.protos.events_pb2 import KpiEvent, AlarmEvent, AlarmEventType, \
36 AlarmEventSeverity, AlarmEventState, AlarmEventCategory
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -050037from voltha.protos.device_pb2 import Device, Port, PmConfigs
38from voltha.protos.events_pb2 import KpiEvent
Zsolt Haraszti66862032016-11-28 14:28:39 -080039from voltha.protos.voltha_pb2 import DeviceGroup, LogicalDevice, \
Khen Nursimulud068d812017-03-06 11:44:18 -050040 LogicalPort, AdminState, OperStatus
Zsolt Haraszti66862032016-11-28 14:28:39 -080041from voltha.registry import registry
Zsolt Haraszti656ecc62016-12-28 15:08:23 -080042from voltha.core.flow_decomposer import OUTPUT
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -050043import sys
Zsolt Haraszti66862032016-11-28 14:28:39 -080044
45
Zsolt Haraszti66862032016-11-28 14:28:39 -080046@implementer(IAdapterAgent)
47class AdapterAgent(object):
48 """
49 Gate-keeper between CORE and device adapters.
50
51 On one side it interacts with Core's internal model and update/dispatch
52 mechanisms.
53
54 On the other side, it interacts with the adapters standard interface as
55 defined in
56 """
57
58 def __init__(self, adapter_name, adapter_cls):
59 self.adapter_name = adapter_name
60 self.adapter_cls = adapter_cls
61 self.core = registry('core')
62 self.adapter = None
63 self.adapter_node_proxy = None
64 self.root_proxy = self.core.get_proxy('/')
Zsolt Haraszti89a27302016-12-08 16:53:06 -080065 self._rx_event_subscriptions = {}
66 self._tx_event_subscriptions = {}
67 self.event_bus = EventBusClient()
Khen Nursimulud068d812017-03-06 11:44:18 -050068 self.packet_out_subscription = None
Zsolt Haraszti89a27302016-12-08 16:53:06 -080069 self.log = structlog.get_logger(adapter_name=adapter_name)
Zsolt Haraszti66862032016-11-28 14:28:39 -080070
71 @inlineCallbacks
72 def start(self):
Zsolt Haraszti89a27302016-12-08 16:53:06 -080073 self.log.debug('starting')
Zsolt Haraszti66862032016-11-28 14:28:39 -080074 config = self._get_adapter_config() # this may be None
Zsolt Haraszti89a27302016-12-08 16:53:06 -080075 try:
76 adapter = self.adapter_cls(self, config)
77 yield adapter.start()
Zsolt Haraszti656ecc62016-12-28 15:08:23 -080078 self.adapter = adapter
79 self.adapter_node_proxy = self._update_adapter_node()
80 self._update_device_types()
Zsolt Haraszti89a27302016-12-08 16:53:06 -080081 except Exception, e:
82 self.log.exception(e)
Zsolt Haraszti89a27302016-12-08 16:53:06 -080083 self.log.info('started')
Zsolt Haraszti66862032016-11-28 14:28:39 -080084 returnValue(self)
85
86 @inlineCallbacks
87 def stop(self):
Zsolt Haraszti89a27302016-12-08 16:53:06 -080088 self.log.debug('stopping')
Zsolt Haraszti66862032016-11-28 14:28:39 -080089 if self.adapter is not None:
90 yield self.adapter.stop()
91 self.adapter = None
Zsolt Haraszti89a27302016-12-08 16:53:06 -080092 self.log.info('stopped')
Zsolt Haraszti66862032016-11-28 14:28:39 -080093
94 def _get_adapter_config(self):
95 """
96 Opportunistically load persisted adapter configuration.
97 Return None if no configuration exists yet.
98 """
99 proxy = self.core.get_proxy('/')
100 try:
101 config = proxy.get('/adapters/' + self.adapter_name)
102 return config
103 except KeyError:
104 return None
105
106 def _update_adapter_node(self):
107 """
108 Creates or updates the adapter node object based on self
109 description from the adapter.
110 """
111
112 adapter_desc = self.adapter.adapter_descriptor()
113 assert adapter_desc.id == self.adapter_name
114 path = self._make_up_to_date(
115 '/adapters', self.adapter_name, adapter_desc)
116 return self.core.get_proxy(path)
117
118 def _update_device_types(self):
119 """
120 Make sure device types are registered in Core
121 """
122 device_types = self.adapter.device_types()
123 for device_type in device_types.items:
124 key = device_type.id
125 self._make_up_to_date('/device_types', key, device_type)
126
127 def _make_up_to_date(self, container_path, key, data):
128 full_path = container_path + '/' + str(key)
129 root_proxy = self.core.get_proxy('/')
130 try:
131 root_proxy.get(full_path)
132 root_proxy.update(full_path, data)
133 except KeyError:
134 root_proxy.add(container_path, data)
135 return full_path
136
Khen Nursimulud068d812017-03-06 11:44:18 -0500137 def _remove_node(self, container_path, key):
138 """
139 Remove a node from the data model
140 :param container_path: path to node
141 :param key: node
142 :return: None
143 """
144 full_path = container_path + '/' + str(key)
145 root_proxy = self.core.get_proxy('/')
146 try:
147 root_proxy.get(full_path)
148 root_proxy.remove(full_path)
149 except KeyError:
150 # Node does not exist
151 pass
152
Zsolt Haraszti66862032016-11-28 14:28:39 -0800153 # ~~~~~~~~~~~~~~~~~~~~~ Core-Facing Service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154
155 def adopt_device(self, device):
156 return self.adapter.adopt_device(device)
157
158 def abandon_device(self, device):
159 return self.adapter.abandon_device(device)
160
Khen Nursimulud068d812017-03-06 11:44:18 -0500161 def disable_device(self, device):
162 return self.adapter.disable_device(device)
163
164 def reenable_device(self, device):
165 return self.adapter.reenable_device(device)
166
167 def reboot_device(self, device):
168 return self.adapter.reboot_device(device)
169
170 def delete_device(self, device):
171 return self.adapter.delete_device(device)
172
173 def get_device_details(self, device):
174 return self.adapter.get_device_details(device)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800175
Zsolt Harasztic5c5d102016-12-07 21:12:27 -0800176 def update_flows_bulk(self, device, flows, groups):
177 return self.adapter.update_flows_bulk(device, flows, groups)
178
179 def update_flows_incrementally(self, device, flow_changes, group_changes):
180 return self.update_flows_incrementally(
181 device, flow_changes, group_changes)
182
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500183 #def update_pm_collection(self, device, pm_collection_config):
184 # return self.adapter.update_pm_collection(device, pm_collection_config)
185
186
Zsolt Haraszti66862032016-11-28 14:28:39 -0800187 # ~~~~~~~~~~~~~~~~~~~ Adapter-Facing Service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188
189 def get_device(self, device_id):
190 return self.root_proxy.get('/devices/{}'.format(device_id))
191
192 def add_device(self, device):
193 assert isinstance(device, Device)
194 self._make_up_to_date('/devices', device.id, device)
195
alshabibbe8ca2e2017-02-01 18:28:57 -0800196 # Ultimately, assign devices to device grpups.
197 # see https://jira.opencord.org/browse/CORD-838
Zsolt Haraszti66862032016-11-28 14:28:39 -0800198
199 dg = DeviceGroup(id='1')
200 self._make_up_to_date('/device_groups', dg.id, dg)
201
202 # add device to device group
alshabibbe8ca2e2017-02-01 18:28:57 -0800203 # see https://jira.opencord.org/browse/CORD-838
Zsolt Haraszti66862032016-11-28 14:28:39 -0800204
205 def update_device(self, device):
206 assert isinstance(device, Device)
207
208 # we run the update through the device_agent so that the change
209 # does not loop back to the adapter unnecessarily
210 device_agent = self.core.get_device_agent(device.id)
211 device_agent.update_device(device)
212
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500213 def update_device_pm_config(self, device_pm_config, init=False):
214 assert isinstance(device_pm_config, PmConfigs)
215
216 # we run the update through the device_agent so that the change
217 # does not loop back to the adapter unnecessarily
218 device_agent = self.core.get_device_agent(device_pm_config.id)
219 device_agent.update_device_pm_config(device_pm_config,init)
220
Sergio Slobodrian98eff412017-03-15 14:46:30 -0400221 def update_adapter_pm_config(self, device_id, device_pm_config):
222 device = self.get_device(device_id)
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500223 self.adapter.update_pm_config(device, device_pm_config)
224
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400225 def _add_peer_reference(self, device_id, port):
Zsolt Haraszti66862032016-11-28 14:28:39 -0800226 # for referential integrity, add/augment references
227 port.device_id = device_id
228 me_as_peer = Port.PeerPort(device_id=device_id, port_no=port.port_no)
229 for peer in port.peers:
230 peer_port_path = '/devices/{}/ports/{}'.format(
231 peer.device_id, peer.port_no)
232 peer_port = self.root_proxy.get(peer_port_path)
233 if me_as_peer not in peer_port.peers:
234 new = peer_port.peers.add()
235 new.CopyFrom(me_as_peer)
236 self.root_proxy.update(peer_port_path, peer_port)
237
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400238 def _del_peer_reference(self, device_id, port):
239 me_as_peer = Port.PeerPort(device_id=device_id, port_no=port.port_no)
240 for peer in port.peers:
241 peer_port_path = '/devices/{}/ports/{}'.format(
242 peer.device_id, peer.port_no)
243 peer_port = self.root_proxy.get(peer_port_path)
244 if me_as_peer in peer_port.peers:
245 peer_port.peers.remove(me_as_peer)
246 self.root_proxy.update(peer_port_path, peer_port)
247
248 def add_port(self, device_id, port):
249 assert isinstance(port, Port)
250
251 # for referential integrity, add/augment references
252 self._add_peer_reference(device_id, port)
253
254 # Add port
Zsolt Haraszti66862032016-11-28 14:28:39 -0800255 self._make_up_to_date('/devices/{}/ports'.format(device_id),
256 port.port_no, port)
257
Khen Nursimulud068d812017-03-06 11:44:18 -0500258 def disable_all_ports(self, device_id):
259 """
260 Disable all ports on that device, i.e. change the admin status to
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400261 disable and operational status to UNKNOWN.
Khen Nursimulud068d812017-03-06 11:44:18 -0500262 :param device_id: device id
263 :return: None
264 """
265
266 # get all device ports
267 ports = self.root_proxy.get('/devices/{}/ports'.format(device_id))
268 for port in ports:
269 port.admin_state = AdminState.DISABLED
270 port.oper_status = OperStatus.UNKNOWN
271 self._make_up_to_date('/devices/{}/ports'.format(device_id),
272 port.port_no, port)
273
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400274
275 def enable_all_ports(self, device_id):
Khen Nursimulud068d812017-03-06 11:44:18 -0500276 """
277 Re-enable all ports on that device, i.e. change the admin status to
278 enabled and operational status to ACTIVE
279 :param device_id: device id
280 :return: None
281 """
282
283 # get all device ports
284 ports = self.root_proxy.get('/devices/{}/ports'.format(device_id))
285 for port in ports:
286 port.admin_state = AdminState.ENABLED
287 port.oper_status = OperStatus.ACTIVE
288 self._make_up_to_date('/devices/{}/ports'.format(device_id),
289 port.port_no, port)
290
291 def delete_all_peer_references(self, device_id):
292 """
293 Remove all peer port references for that device
294 :param device_id: device_id of device
295 :return: None
296 """
297 ports = self.root_proxy.get('/devices/{}/ports'.format(device_id))
298 for port in ports:
299 port_path = '/devices/{}/ports/{}'.format(device_id, port.port_no)
300 for peer in port.peers:
301 port.peers.remove(peer)
302 self.root_proxy.update(port_path, port)
303
304 def delete_port_reference_from_parent(self, device_id, port):
305 """
306 Delete the port reference from the parent device
307 :param device_id: id of device containing the port
308 :param port: port to remove
309 :return: None
310 """
311 assert isinstance(port, Port)
312 self.log.info('delete-port-reference', device_id=device_id, port=port)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400313 self._del_peer_reference(device_id, port)
Khen Nursimulud068d812017-03-06 11:44:18 -0500314
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400315 def add_port_reference_to_parent(self, device_id, port):
316 """
317 Add the port reference to the parent device
318 :param device_id: id of device containing the port
319 :param port: port to add
320 :return: None
321 """
322 assert isinstance(port, Port)
323 self.log.info('add-port-reference', device_id=device_id, port=port)
324 self._add_peer_reference(device_id, port)
Khen Nursimulud068d812017-03-06 11:44:18 -0500325
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800326 def _find_first_available_id(self):
327 logical_devices = self.root_proxy.get('/logical_devices')
328 existing_ids = set(ld.id for ld in logical_devices)
329 existing_datapath_ids = set(ld.datapath_id for ld in logical_devices)
330 i = 1
331 while True:
332 if i not in existing_datapath_ids and str(i) not in existing_ids:
333 return i
334 i += 1
335
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800336 def get_logical_device(self, logical_device_id):
337 return self.root_proxy.get('/logical_devices/{}'.format(
338 logical_device_id))
339
Khen Nursimulud068d812017-03-06 11:44:18 -0500340 def get_logical_port(self, logical_device_id, port_id):
341 return self.root_proxy.get('/logical_devices/{}/ports/{}'.format(
342 logical_device_id, port_id))
343
Zsolt Haraszti66862032016-11-28 14:28:39 -0800344 def create_logical_device(self, logical_device):
345 assert isinstance(logical_device, LogicalDevice)
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800346
347 if not logical_device.id:
348 id = self._find_first_available_id()
349 logical_device.id = str(id)
350 logical_device.datapath_id = id
351
Zsolt Haraszti66862032016-11-28 14:28:39 -0800352 self._make_up_to_date('/logical_devices',
353 logical_device.id, logical_device)
354
Khen Nursimulud068d812017-03-06 11:44:18 -0500355 # Keep a reference to the packet out subscription as it will be
356 # referred during removal
357 self.packet_out_subscription = self.event_bus.subscribe(
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800358 topic='packet-out:{}'.format(logical_device.id),
359 callback=lambda _, p: self.receive_packet_out(logical_device.id, p)
360 )
361
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800362 return logical_device
363
Khen Nursimulud068d812017-03-06 11:44:18 -0500364
365 def delete_logical_device(self, logical_device):
366 """
367 This will remove the logical device as well as all logical ports
368 associated with it
369 :param logical_device: The logical device to remove
370 :return: None
371 """
372 assert isinstance(logical_device, LogicalDevice)
373
374 # Remove packet out subscription
375 self.event_bus.unsubscribe(self.packet_out_subscription)
376
377 # Remove node from the data model - this will trigger the logical
378 # device 'remove callbacks' as well as logical ports 'remove
379 # callbacks' if present
380 self._remove_node('/logical_devices', logical_device.id)
381
382
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800383 def receive_packet_out(self, logical_device_id, ofp_packet_out):
384
385 def get_port_out(opo):
386 for action in opo.actions:
387 if action.type == OUTPUT:
388 return action.output.port
389
390 out_port = get_port_out(ofp_packet_out)
391 frame = ofp_packet_out.data
392 self.adapter.receive_packet_out(logical_device_id, out_port, frame)
393
Zsolt Haraszti66862032016-11-28 14:28:39 -0800394 def add_logical_port(self, logical_device_id, port):
395 assert isinstance(port, LogicalPort)
396 self._make_up_to_date(
397 '/logical_devices/{}/ports'.format(logical_device_id),
398 port.id, port)
399
Khen Nursimulud068d812017-03-06 11:44:18 -0500400 def delete_logical_port(self, logical_device_id, port):
401 assert isinstance(port, LogicalPort)
402 self._remove_node('/logical_devices/{}/ports'.format(
403 logical_device_id), port.id)
404
405 def update_logical_port(self, logical_device_id, port):
406 assert isinstance(port, LogicalPort)
407 self.log.debug('update-logical-port',
408 logical_device_id=logical_device_id,
409 port=port)
410
411 self._make_up_to_date(
412 '/logical_devices/{}/ports'.format(logical_device_id),
413 port.id, port)
414
Zsolt Haraszti66862032016-11-28 14:28:39 -0800415 def child_device_detected(self,
416 parent_device_id,
417 parent_port_no,
418 child_device_type,
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800419 proxy_address,
420 **kw):
Zsolt Haraszti66862032016-11-28 14:28:39 -0800421 # we create new ONU device objects and insert them into the config
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800422 # TODO should we auto-enable the freshly created device? Probably.
Zsolt Haraszti66862032016-11-28 14:28:39 -0800423 device = Device(
424 id=uuid4().hex[:12],
425 type=child_device_type,
426 parent_id=parent_device_id,
427 parent_port_no=parent_port_no,
428 admin_state=AdminState.ENABLED,
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800429 proxy_address=proxy_address,
430 **kw
Zsolt Haraszti66862032016-11-28 14:28:39 -0800431 )
432 self._make_up_to_date(
433 '/devices', device.id, device)
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800434
435 topic = self._gen_tx_proxy_address_topic(proxy_address)
436 self._tx_event_subscriptions[topic] = self.event_bus.subscribe(
437 topic, lambda t, m: self._send_proxied_message(proxy_address, m))
438
Khen Nursimulud068d812017-03-06 11:44:18 -0500439 def remove_all_logical_ports(self, logical_device_id):
440 """ Remove all logical ports from a given logical device"""
441 ports = self.root_proxy.get('/logical_devices/{}/ports')
442 for port in ports:
443 self._remove_node('/logical_devices/{}/ports', port.id)
444
445 def delete_all_child_devices(self, parent_device_id):
446 """ Remove all ONUs from a given OLT """
447 devices = self.root_proxy.get('/devices')
448 children_ids = set(d.id for d in devices if d.parent_id == parent_device_id)
449 self.log.debug('devices-to-delete',
450 parent_id=parent_device_id,
451 children_ids=children_ids)
452 for child_id in children_ids:
453 self._remove_node('/devices', child_id)
454
455 def reenable_all_child_devices(self, parent_device_id):
456 """ Re-enable all ONUs from a given OLT """
457 devices = self.root_proxy.get('/devices')
458 children_ids = set(d.id for d in devices if d.parent_id == parent_device_id)
459 self.log.debug('devices-to-reenable',
460 parent_id=parent_device_id,
461 children_ids=children_ids)
462 for child_id in children_ids:
463 device = self.get_device(child_id)
464 device.admin_state = AdminState.ENABLED
465 self._make_up_to_date(
466 '/devices', device.id, device)
467
468 def disable_all_child_devices(self, parent_device_id):
469 """ Disable all ONUs from a given OLT """
470 devices = self.root_proxy.get('/devices')
471 children_ids = set(d.id for d in devices if d.parent_id == parent_device_id)
472 self.log.debug('devices-to-disable',
473 parent_id=parent_device_id,
474 children_ids=children_ids)
475 for child_id in children_ids:
476 # Change the admin state pf the device to DISABLE
477 device = self.get_device(child_id)
478 device.admin_state = AdminState.DISABLED
479 self._make_up_to_date(
480 '/devices', device.id, device)
481
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800482 def _gen_rx_proxy_address_topic(self, proxy_address):
483 """Generate unique topic name specific to this proxy address for rx"""
Zsolt Harasztief05ad22017-01-07 22:08:06 -0800484 topic = 'rx:' + MessageToJson(proxy_address)
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800485 return topic
486
487 def _gen_tx_proxy_address_topic(self, proxy_address):
488 """Generate unique topic name specific to this proxy address for tx"""
Zsolt Harasztief05ad22017-01-07 22:08:06 -0800489 topic = 'tx:' + MessageToJson(proxy_address)
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800490 return topic
491
492 def register_for_proxied_messages(self, proxy_address):
493 topic = self._gen_rx_proxy_address_topic(proxy_address)
494 self._rx_event_subscriptions[topic] = self.event_bus.subscribe(
Stephane Barbariecc6b2e62017-03-02 14:35:55 -0500495 topic,
496 lambda t, m: self._receive_proxied_message(proxy_address, m))
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800497
Khen Nursimulud068d812017-03-06 11:44:18 -0500498 def unregister_for_proxied_messages(self, proxy_address):
499 topic = self._gen_rx_proxy_address_topic(proxy_address)
500 self.event_bus.unsubscribe(self._rx_event_subscriptions[topic])
501 del self._rx_event_subscriptions[topic]
502
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800503 def _receive_proxied_message(self, proxy_address, msg):
504 self.adapter.receive_proxied_message(proxy_address, msg)
505
506 def send_proxied_message(self, proxy_address, msg):
507 topic = self._gen_tx_proxy_address_topic(proxy_address)
508 self.event_bus.publish(topic, msg)
509
510 def _send_proxied_message(self, proxy_address, msg):
511 self.adapter.send_proxied_message(proxy_address, msg)
512
513 def receive_proxied_message(self, proxy_address, msg):
514 topic = self._gen_rx_proxy_address_topic(proxy_address)
515 self.event_bus.publish(topic, msg)
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -0800516
517 # ~~~~~~~~~~~~~~~~~~ Handling packet-in and packet-out ~~~~~~~~~~~~~~~~~~~~
518
519 def send_packet_in(self, logical_device_id, logical_port_no, packet):
520 self.log.debug('send-packet-in', logical_device_id=logical_device_id,
Zsolt Harasztief05ad22017-01-07 22:08:06 -0800521 logical_port_no=logical_port_no, packet=hexify(packet))
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -0800522
523 if isinstance(packet, Packet):
524 packet = str(packet)
525
526 topic = 'packet-in:' + logical_device_id
527 self.event_bus.publish(topic, (logical_port_no, packet))
Zsolt Haraszti749b0952017-01-18 09:02:35 -0800528
529 # ~~~~~~~~~~~~~~~~~~~ Handling KPI metric submissions ~~~~~~~~~~~~~~~~~~~~~
Zsolt Harasztic5f740b2017-01-18 09:53:17 -0800530
Zsolt Haraszti749b0952017-01-18 09:02:35 -0800531 def submit_kpis(self, kpi_event_msg):
532 try:
533 assert isinstance(kpi_event_msg, KpiEvent)
534 self.event_bus.publish('kpis', kpi_event_msg)
535 except Exception as e:
536 self.log.exception('failed-kpi-submission',
537 type=type(kpi_event_msg))
Stephane Barbarie52198b92017-03-02 13:44:46 -0500538
539 # ~~~~~~~~~~~~~~~~~~~ Handle alarm submissions ~~~~~~~~~~~~~~~~~~~~~
540
Stephane Barbariecc6b2e62017-03-02 14:35:55 -0500541 def create_alarm(self, id=None, resource_id=None, description=None,
542 raised_ts=0, changed_ts=0,
543 type=AlarmEventType.EQUIPMENT,
Stephane Barbariebf3e10c2017-03-03 10:15:58 -0500544 category=AlarmEventCategory.PON,
Stephane Barbariecc6b2e62017-03-02 14:35:55 -0500545 severity=AlarmEventSeverity.MINOR,
546 state=AlarmEventState.RAISED,
Stephane Barbarie52198b92017-03-02 13:44:46 -0500547 context=None):
548
549 # Construct the ID if it is not provided
550 if id == None:
551 id = 'voltha.{}.{}'.format(self.adapter_name, resource_id)
552
553 return AlarmEvent(
554 id=id,
555 resource_id=resource_id,
556 type=type,
557 category=category,
558 severity=severity,
559 state=state,
560 description=description,
561 reported_ts=arrow.utcnow().timestamp,
562 raised_ts=raised_ts,
563 changed_ts=changed_ts,
564 context=context
565 )
566
567 def submit_alarm(self, alarm_event_msg):
568 try:
569 assert isinstance(alarm_event_msg, AlarmEvent)
570 self.event_bus.publish('alarms', alarm_event_msg)
571
572 except Exception as e:
573 self.log.exception('failed-alarm-submission',
574 type=type(alarm_event_msg))