VOL-1137: Support new shared KPI and Alarm libraries
Change-Id: Iaa51a1da59263a4079751f6b697a09c8effe3251
diff --git a/voltha/adapters/adtran_onu/adtran_onu.py b/voltha/adapters/adtran_onu/adtran_onu.py
index 1f7f366..1e05f02 100755
--- a/voltha/adapters/adtran_onu/adtran_onu.py
+++ b/voltha/adapters/adtran_onu/adtran_onu.py
@@ -39,10 +39,11 @@
config=config,
device_handler_class=AdtranOnuHandler,
name='adtran_onu',
- vendor='Adtran, Inc.',
- version='0.11',
+ vendor='Adtran Inc.',
+ version='0.12',
device_type='adtran_onu',
- vendor_id='ADTN')
+ vendor_id='ADTN',
+ accepts_add_remove_flow_updates=False), # TODO: Support flow-mods
# Customize OpenOMCI for Adtran ONUs
self.adtran_omci = deepcopy(OpenOmciAgentDefaults)
diff --git a/voltha/adapters/adtran_onu/adtran_onu_handler.py b/voltha/adapters/adtran_onu/adtran_onu_handler.py
index cdefaa0..ff69b22 100644
--- a/voltha/adapters/adtran_onu/adtran_onu_handler.py
+++ b/voltha/adapters/adtran_onu/adtran_onu_handler.py
@@ -15,7 +15,6 @@
#
import arrow
-import structlog
from voltha.adapters.adtran_olt.xpon.adtran_xpon import AdtranXPON
from pon_port import PonPort
@@ -23,8 +22,8 @@
from heartbeat import HeartBeat
from omci.omci import OMCI
-from voltha.adapters.adtran_olt.alarms.adapter_alarms import AdapterAlarms
-from onu_pm_metrics import OnuPmMetrics
+from voltha.extensions.alarms.adapter_alarms import AdapterAlarms
+from voltha.extensions.pki.onu.onu_pm_metrics import OnuPmMetrics
from uuid import uuid4
from twisted.internet import reactor
@@ -223,74 +222,85 @@
def activate(self, device):
self.log.info('activating')
- # first we verify that we got parent reference and proxy info
- assert device.parent_id, 'Invalid Parent ID'
- assert device.proxy_address.device_id, 'Invalid Device ID'
+ try:
+ # first we verify that we got parent reference and proxy info
+ assert device.parent_id, 'Invalid Parent ID'
+ assert device.proxy_address.device_id, 'Invalid Device ID'
- if device.vlan:
- # vlan non-zero if created via legacy method (not xPON). Also
- # Set a random serial number since not xPON based
- self._olt_created = True
+ if device.vlan:
+ # vlan non-zero if created via legacy method (not xPON).
+ self._olt_created = True
- # register for proxied messages right away
- self.proxy_address = device.proxy_address
- self.adapter_agent.register_for_proxied_messages(device.proxy_address)
+ # register for proxied messages right away
+ self.proxy_address = device.proxy_address
+ self.adapter_agent.register_for_proxied_messages(device.proxy_address)
- # initialize device info
- device.root = True
- device.vendor = 'Adtran Inc.'
- device.model = 'n/a'
- device.hardware_version = 'n/a'
- device.firmware_version = 'n/a'
- device.reason = ''
- device.connect_status = ConnectStatus.UNKNOWN
+ # initialize device info
+ device.root = True
+ device.vendor = 'Adtran Inc.'
+ device.model = 'n/a'
+ device.hardware_version = 'n/a'
+ device.firmware_version = 'n/a'
+ device.reason = ''
+ device.connect_status = ConnectStatus.UNKNOWN
- ############################################################################
- # Setup PM configuration for this device
+ # Register physical ports. Should have at least one of each
+ self._pon = PonPort.create(self, self._next_port_number)
+ self.adapter_agent.add_port(device.id, self._pon.get_port())
- self.pm_metrics = OnuPmMetrics(self, device, grouped=True, freq_override=False)
- pm_config = self.pm_metrics.make_proto()
- self.log.info("initial-pm-config", pm_config=pm_config)
- self.adapter_agent.update_device_pm_config(pm_config, init=True)
+ if self._olt_created:
+ # vlan non-zero if created via legacy method (not xPON). Also
+ # Set a random serial number since not xPON based
- ############################################################################
- # Setup Alarm handler
+ uni_port = UniPort.create(self, self._next_port_number, device.vlan,
+ 'deprecated', device.vlan, None)
+ self._unis[uni_port.port_number] = uni_port
+ self.adapter_agent.add_port(device.id, uni_port.get_port())
- self.alarms = AdapterAlarms(self.adapter, device.id)
+ device.serial_number = uuid4().hex
+ uni_port.add_logical_port(device.vlan, subscriber_vlan=device.vlan)
- # reference of uni_port is required when re-enabling the device if
- # it was disabled previously
- # Need to query ONU for number of supported uni ports
- # For now, temporarily set number of ports to 1 - port #2
+ # Start things up for this ONU Handler.
+ self.enabled = True
- parent_device = self.adapter_agent.get_device(device.parent_id)
- self.logical_device_id = parent_device.parent_id
- assert self.logical_device_id, 'Invalid logical device ID'
+ ############################################################################
+ # Setup PM configuration for this device
+ # Pass in ONU specific options
+ kwargs = {
+ 'heartbeat': self.heartbeat,
+ 'omci-cc': self.openomci.omci_cc
+ }
+ self.pm_metrics = OnuPmMetrics(self.adapter_agent, self.device_id,
+ grouped=True, freq_override=False,
+ **kwargs)
+ pm_config = self.pm_metrics.make_proto()
+ self.openomci.set_pm_config(self.pm_metrics.omci_pm.openomci_interval_pm)
+ self.log.info("initial-pm-config", pm_config=pm_config)
+ self.adapter_agent.update_device_pm_config(pm_config, init=True)
- # Register physical ports. Should have at least one of each
+ # reference of uni_port is required when re-enabling the device if
+ # it was disabled previously
+ # Need to query ONU for number of supported uni ports
+ # For now, temporarily set number of ports to 1 - port #2
+ parent_device = self.adapter_agent.get_device(device.parent_id)
+ self.logical_device_id = parent_device.parent_id
+ assert self.logical_device_id, 'Invalid logical device ID'
+ self.adapter_agent.update_device(device)
- self._pon = PonPort.create(self, self._next_port_number)
- self.adapter_agent.add_port(device.id, self._pon.get_port())
+ ############################################################################
+ # Setup Alarm handler
+ self.alarms = AdapterAlarms(self.adapter_agent, device.id, self.logical_device_id)
- if self._olt_created:
- # vlan non-zero if created via legacy method (not xPON). Also
- # Set a random serial number since not xPON based
+ ############################################################################
+ # Start collecting stats from the device after a brief pause
+ reactor.callLater(30, self.pm_metrics.start_collector)
- uni_port = UniPort.create(self, self._next_port_number, device.vlan,
- 'deprecated', device.vlan, None)
- self._unis[uni_port.port_number] = uni_port
- self.adapter_agent.add_port(device.id, uni_port.get_port())
-
- device.serial_number = uuid4().hex
- uni_port.add_logical_port(device.vlan, subscriber_vlan=device.vlan)
-
- # Start things up for this ONU Handler.
- self.enabled = True
-
- # Start collecting stats from the device after a brief pause
- reactor.callLater(30, self.start_kpi_collection, device.id)
-
- self.adapter_agent.update_device(device)
+ except Exception as e:
+ self.log.exception('activate-failure', e=e)
+ device.reason = 'Failed to activate: {}'.format(e.message)
+ device.connect_status = ConnectStatus.UNREACHABLE
+ device.oper_status = OperStatus.FAILED
+ self.adapter_agent.update_device(device)
def reconcile(self, device):
self.log.info('reconciling-ONU-device-starts')
@@ -329,34 +339,6 @@
self.log.info('update_pm_config', pm_config=pm_config)
self.pm_metrics.update(pm_config)
- def start_kpi_collection(self, device_id):
- # TODO: This has not been tested
- def _collect(device_id, prefix):
- from voltha.protos.events_pb2 import KpiEvent, KpiEventType, MetricValuePairs
-
- if self.enabled:
- try:
- # Step 1: gather metrics from device
- port_metrics = self.pm_metrics.collect_port_metrics()
-
- # Step 2: prepare the KpiEvent for submission
- # we can time-stamp them here or could use time derived from OLT
- ts = arrow.utcnow().timestamp
- kpi_event = KpiEvent(
- type=KpiEventType.slice,
- ts=ts,
- prefixes={
- prefix + '.{}'.format(k): MetricValuePairs(metrics=port_metrics[k])
- for k in port_metrics.keys()}
- )
- # Step 3: submit
- self.adapter_agent.submit_kpis(kpi_event)
-
- except Exception as e:
- self.log.exception('failed-to-submit-kpis', e=e)
-
- self.pm_metrics.start_collector(_collect)
-
@inlineCallbacks
def update_flow_table(self, device, flows):
#
diff --git a/voltha/adapters/adtran_onu/heartbeat.py b/voltha/adapters/adtran_onu/heartbeat.py
index 2d5796f..f0efe30 100644
--- a/voltha/adapters/adtran_onu/heartbeat.py
+++ b/voltha/adapters/adtran_onu/heartbeat.py
@@ -149,7 +149,7 @@
device = self._handler.adapter_agent.get_device(self._device_id)
try:
- from ..adtran_olt.alarms.heartbeat_alarm import HeartbeatAlarm
+ from voltha.extensions.alarms.heartbeat_alarm import HeartbeatAlarm
if self._heartbeat_miss >= self.heartbeat_failed_limit:
if device.connect_status == ConnectStatus.REACHABLE:
@@ -158,7 +158,7 @@
device.oper_status = OperStatus.FAILED
device.reason = self.heartbeat_last_reason
self._handler.adapter_agent.update_device(device)
- HeartbeatAlarm(self._handler, 'onu', self._heartbeat_miss).raise_alarm()
+ HeartbeatAlarm(self._handler.alarms, 'onu', self._heartbeat_miss).raise_alarm()
self._alarm_active = True
self.on_heartbeat_alarm(True)
else:
@@ -168,7 +168,7 @@
device.oper_status = OperStatus.ACTIVE
device.reason = ''
self._handler.adapter_agent.update_device(device)
- HeartbeatAlarm(self._handler, 'onu').clear_alarm()
+ HeartbeatAlarm(self._handler.alarms, 'onu').clear_alarm()
self._alarm_active = False
self._alarms_raised_count += 1
diff --git a/voltha/adapters/adtran_onu/omci/omci.py b/voltha/adapters/adtran_onu/omci/omci.py
index 0e4791f..2b008a5 100644
--- a/voltha/adapters/adtran_onu/omci/omci.py
+++ b/voltha/adapters/adtran_onu/omci/omci.py
@@ -57,7 +57,7 @@
self._onu_omci_device = omci_agent.add_device(handler.device_id,
handler.adapter_agent,
- onu_custom_me_entities(),
+ custom_me_map=onu_custom_me_entities(),
support_classes=handler.adapter.adtran_omci)
def __str__(self):
@@ -151,6 +151,15 @@
def onu_omci_device(self):
return self._onu_omci_device
+ def set_pm_config(self, pm_config):
+ """
+ Set PM interval configuration
+
+ :param pm_config: (OnuPmIntervalMetrics) PM Interval configuration
+ :return:
+ """
+ self.onu_omci_device.set_pm_config(pm_config)
+
def _mib_in_sync(self):
"""
This method is ran whenever the ONU MIB database is in-sync. This is often after
@@ -233,7 +242,7 @@
except Exception as e:
self.log.exception('device-info-load', e=e)
- self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT, self._mib_in_sync())
+ self._deferred = reactor.callLater(_STARTUP_RETRY_WAIT, self._mib_in_sync)
def gem_or_tcont_added(self):
if self._in_sync_reached:
diff --git a/voltha/adapters/adtran_onu/onu_pm_metrics.py b/voltha/adapters/adtran_onu/onu_pm_metrics.py
deleted file mode 100644
index 20a45b3..0000000
--- a/voltha/adapters/adtran_onu/onu_pm_metrics.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# Copyright 2017-present Adtran, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from voltha.protos.device_pb2 import PmConfig, PmConfigs, PmGroupConfig
-from ..adtran_olt.pki.adapter_pm_metrics import AdapterPmMetrics
-
-
-class OnuPmMetrics(AdapterPmMetrics):
- def __init__(self, handler, device, grouped=False, freq_override=False):
- super(OnuPmMetrics, self).__init__(handler, device,
- grouped=grouped, freq_override=freq_override)
-
- # PM Config Types are COUNTER, GUAGE, and STATE # Note: GAUGE is misspelled in device.proto
- self.omci_pm_names = {
- ('enabled', PmConfig.STATE),
- ('tx_frames', PmConfig.COUNTER),
- ('tx_errors', PmConfig.COUNTER),
- ('rx_frames', PmConfig.COUNTER),
- ('rx_unknown_tid', PmConfig.COUNTER),
- ('rx_onu_frames', PmConfig.COUNTER), # Rx ONU autonomous messages
- ('rx_alarm_overflow', PmConfig.COUNTER), # Autonomous ONU generated alarm message overflows
- ('rx_avc_overflow', PmConfig.COUNTER), # Autonomous ONU generated AVC message overflows
- ('rx_onu_discards', PmConfig.COUNTER), # Autonomous ONU message unknown type discards
- ('rx_unknown_me', PmConfig.COUNTER), # Managed Entities without a decode definition
- ('rx_timeouts', PmConfig.COUNTER),
- ('consecutive_errors', PmConfig.COUNTER),
- ('reply_min', PmConfig.GUAGE), # Milliseconds
- ('reply_max', PmConfig.GUAGE), # Milliseconds
- ('reply_average', PmConfig.GUAGE), # Milliseconds
- }
- self.health_pm_names = {
- ('enabled', PmConfig.STATE),
- ('alarm_active', PmConfig.STATE),
- ('heartbeat_count', PmConfig.COUNTER),
- ('heartbeat_miss', PmConfig.COUNTER),
- ('alarms_raised_count', PmConfig.COUNTER),
- ('heartbeat_failed_limit', PmConfig.COUNTER),
- ('heartbeat_interval', PmConfig.COUNTER),
- }
- # TODO Add PON Port PM
- # TODO Add UNI Port PM
-
- self.omci_metrics_config = {m: PmConfig(name=m, type=t, enabled=True)
- for (m, t) in self.omci_pm_names}
- self.health_metrics_config = {m: PmConfig(name=m, type=t, enabled=True)
- for (m, t) in self.health_pm_names}
-
- def update(self, pm_config):
- # TODO: Test both 'group' and 'non-group' functionality
- # TODO: Test frequency override capability for a particular group
- if self.default_freq != pm_config.default_freq:
- # Update the callback to the new frequency.
- self.default_freq = pm_config.default_freq
- self.lc.stop()
- self.lc.start(interval=self.default_freq / 10)
-
- if pm_config.grouped is True:
- for m in pm_config.groups:
- pass
- # self.pm_group_metrics[m.group_name].config.enabled = m.enabled
- # if m.enabled is True:,
- ('tx_errors', PmConfig.COUNTER),
- ('rx_frames', PmConfig.COUNTER),
- # self.enable_pm_collection(m.group_name, remote)
- # else:
- # self.disable_pm_collection(m.group_name, remote)
- else:
- for m in pm_config.metrics:
- self.omci_metrics_config[m.name].enabled = m.enabled
- self.health_metrics_config[m.name].enabled = m.enabled
-
- def make_proto(self):
- pm_config = PmConfigs(id=self.id, default_freq=self.default_freq,
- grouped=self.grouped,
- freq_override=self.freq_override)
- metrics = set()
-
- if self.grouped:
- pm_omci_stats = PmGroupConfig(group_name='OMCI',
- group_freq=self.default_freq,
- enabled=True)
-
- pm_health_stats = PmGroupConfig(group_name='Heartbeat',
- group_freq=self.default_freq,
- enabled=True)
- # TODO Add PON Port PM
- # TODO Add UNI Port PM
- else:
- pm_omci_stats = pm_config
- pm_health_stats = pm_config
- # TODO Add PON Port PM
- # TODO Add UNI Port PM
-
- for m in sorted(self.omci_metrics_config):
- pm = self.omci_metrics_config[m]
- if not self.grouped:
- if pm.name in metrics:
- continue
- metrics.add(pm.name)
-
- pm_omci_stats.metrics.extend([PmConfig(name=pm.name,
- type=pm.type,
- enabled=pm.enabled)])
-
- for m in sorted(self.health_metrics_config):
- pm = self.health_metrics_config[m]
- if not self.grouped:
- if pm.name in metrics:
- continue
- metrics.add(pm.name)
-
- pm_health_stats.metrics.extend([PmConfig(name=pm.name,
- type=pm.type,
- enabled=pm.enabled)])
-
- return pm_config
-
- def collect_port_metrics(self):
- metrics = dict()
- metrics['omci'] = self.collect_metrics(self.handler.openomci.omci_cc,
- self.omci_pm_names,
- self.omci_metrics_config)
-
- metrics['heartbeat'] = self.collect_metrics(self.handler.heartbeat,
- self.health_pm_names,
- self.health_metrics_config)
-
- # TODO Add PON Port PM
- # TODO Add UNI Port PM
-
- return metrics
-
-
-
-
-
diff --git a/voltha/adapters/adtran_onu/uni_port.py b/voltha/adapters/adtran_onu/uni_port.py
index 8663b38..32636a2 100644
--- a/voltha/adapters/adtran_onu/uni_port.py
+++ b/voltha/adapters/adtran_onu/uni_port.py
@@ -212,9 +212,9 @@
if self._logical_port_number is not None:
# delete old logical port if it exists
try:
- port = self.adapter_agent.get_logical_port(self._handler.logical_device_id,
- self.port_id_name())
- self.adapter_agent.delete_logical_port(self._handler.logical_device_id, port)
+ port = self._handler.adapter_agent.get_logical_port(self._handler.logical_device_id,
+ self.port_id_name())
+ self._handler.adapter_agent.delete_logical_port(self._handler.logical_device_id, port)
except Exception as e:
# assume this exception was because logical port does not already exist