SEBA-237 Add simulate_alarm CLI command and plumb through
Change-Id: I3e146bf2d2d4a4b2ee7e491fb62cb762e884e233
diff --git a/cli/device.py b/cli/device.py
index 3a6345c..3f02dcd 100644
--- a/cli/device.py
+++ b/cli/device.py
@@ -510,6 +510,116 @@
self.poutput('response: {}'.format(name))
self.poutput('{}'.format(response))
+ def help_simulate_alarm(self):
+ self.poutput(
+'''
+simulate_alarm <alarm_name> [-b <bit rate>] [-c] [-d <drift>] [-e <eqd>]
+ [-i <interface id>] [-o <onu device id>] [-p <port type name>]
+
+<name> is the name of the alarm to raise. Other rguments are alarm specific
+and only have meaning in the context of a particular alarm. Below is a list
+of the alarms that may be raised:
+
+simulate_alarm los -i <interface_id> -p <port_type_name>
+simulate_alarm dying_gasp -i <interface_id> -o <onu_device_id>
+simulate_alarm onu_los -i <interface_id> -o <onu_device_id>
+simulate_alarm onu_lopc_miss -i <interface_id> -o <onu_device_id>
+simulate_alarm onu_lopc_mic -i <interface_id> -o <onu_device_id>
+simulate_alarm onu_lob -i <interface_id> -o <onu_device_id>
+simulate_alarm onu_signal_degrade -i <interface_id> -o <onu_device_id>
+ -b <bit_rate>
+simulate_alarm onu_drift_of_window -i <interface_id>
+ -o <onu_device_id> -d <drift> -e <eqd>
+simulate_alarm onu_signal_fail -i <interface_id> -o <onu_device_id>
+ -b <bit_rate>
+simulate_alarm onu_activation -i <interface_id> -o <onu_device_id>
+simulate_alarm onu_startup -i <interface_id> -o <onu_device_id>
+simulate_alarm onu_discovery -i <interface_id> -s <onu_serial_number>
+
+If the -c option is specified then the alarm will be cleared. By default,
+it will be raised. Note that only some alarms can be cleared.
+'''
+ )
+
+ @options([
+ make_option('-c', '--clear', action='store_true', default=False,
+ help="Clear alarm instead of raising"),
+ make_option('-b', '--inverse_bit_error_rate', action='store', dest='inverse_bit_error_rate',
+ help="Inverse bit error rate", default=0, type="int"),
+ make_option('-d', '--drift', action='store', dest='drift',
+ help="Drift", default=0, type="int"),
+ make_option('-e', '--new_eqd', action='store', dest='new_eqd',
+ help="New EQD", default=0, type="int"),
+ make_option('-i', '--intf_id', action='store', dest='intf_id',
+ help="Interface ID", default=""),
+ make_option('-o', '--onu_device_id', action='store', dest='onu_device_id',
+ help="ONU device ID", default=""),
+ make_option('-p', '--port_type_name', action='store', dest='port_type_name',
+ help="Port type name", default=""),
+ make_option('-s', '--onu_serial_number', action='store', dest='onu_serial_number',
+ help="ONU Serial Number", default=""),
+ ])
+ def do_simulate_alarm(self, line, opts):
+ indicator = line
+ device = self.get_device(depth=-1)
+ device_id = device.id
+
+ alarm_args = {"los": ["intf_id", "port_type_name"],
+ "dying_gasp": ["intf_id", "onu_device_id"],
+ "onu_los": ["intf_id", "onu_device_id"],
+ "onu_lopc_miss": ["intf_id", "onu_device_id"],
+ "onu_lopc_mic": ["intf_id", "onu_device_id"],
+ "onu_lob": ["intf_id", "onu_device_id"],
+ "onu_signal_degrade": ["intf_id", "onu_device_id", "inverse_bit_error_rate"],
+ "onu_drift_of_window": ["intf_id", "onu_device_id", "drift", "new_eqd"],
+ "onu_signal_fail": ["intf_id", "onu_device_id", "inverse_bit_error_rate"],
+ "onu_activation": ["intf_id", "onu_device_id"],
+ "onu_startup": ["intf_id", "onu_device_id"],
+ "onu_discovery": ["intf_id", "onu_serial_number"]
+ }
+ try:
+ if indicator not in alarm_args:
+ self.poutput("Unknown alarm indicator %s. Valid choices are %s." % (indicator,
+ ", ".join(alarm_args.keys())))
+ raise Exception("Unknown alarm indicator %s" % indicator)
+
+ for arg_name in alarm_args[indicator]:
+ if not getattr(opts, arg_name):
+ self.poutput("Option %s is required for alarm %s. See help." % (arg_name, indicator))
+ raise Exception("Option %s is required for alarm %s" % (arg_name, indicator))
+
+ # TODO: check for required arguments
+ kw = dict(id=device_id)
+
+ kw["indicator"] = indicator
+ kw["intf_id"] = opts.intf_id
+ kw["onu_device_id"] = opts.onu_device_id
+ kw["port_type_name"] = opts.port_type_name
+ kw["inverse_bit_error_rate"] = opts.inverse_bit_error_rate
+ kw["drift"] = opts.drift
+ kw["new_eqd"] = opts.new_eqd
+ kw["onu_serial_number"] = opts.onu_serial_number
+
+ if opts.clear:
+ kw["operation"] = voltha_pb2.SimulateAlarmRequest.CLEAR
+ else:
+ kw["operation"] = voltha_pb2.SimulateAlarmRequest.RAISE
+ except Exception as e:
+ self.poutput('Error simulate alarm {}. Error:{}'.format(device_id, e))
+ return
+ response = None
+ try:
+ simulate_alarm = voltha_pb2.SimulateAlarmRequest(**kw)
+ stub = self.get_stub()
+ response = stub.SimulateAlarm(simulate_alarm)
+ except Exception as e:
+ self.poutput('Error simulate alarm {}. Error:{}'.format(kw['id'], e))
+ return
+ name = enum2name(common_pb2.OperationResp,
+ 'OperationReturnCode', response.code)
+ self.poutput('response: {}'.format(name))
+ self.poutput('{}'.format(response))
+
@options([
make_option('-n', '--name', action='store', dest='name',
help="Image name"),
diff --git a/voltha/adapters/openolt/openolt.py b/voltha/adapters/openolt/openolt.py
index 6dde34a..1179dd5 100644
--- a/voltha/adapters/openolt/openolt.py
+++ b/voltha/adapters/openolt/openolt.py
@@ -26,6 +26,7 @@
from voltha.protos.adapter_pb2 import Adapter
from voltha.protos.adapter_pb2 import AdapterConfig
from voltha.protos.common_pb2 import LogLevel
+from voltha.protos.common_pb2 import OperationResp
from voltha.protos.device_pb2 import DeviceType, DeviceTypes
from voltha.registry import registry
@@ -363,3 +364,17 @@
log.error('Could not find matching handler',
looking_for_device_id=device_id,
available_handlers=self.devices.keys())
+
+ def simulate_alarm(self, device, request):
+ log.info('simulate_alarm', device=device, request=request)
+
+ if device.id not in self.devices:
+ log.error("Device does not exist", device_id=device.id)
+ return OperationResp(code=OperationResp.OPERATION_FAILURE,
+ additional_info="Device %s does not exist" % device.id)
+
+ handler = self.devices[device.id]
+
+ handler.simulate_alarm(request)
+
+ return OperationResp(code=OperationResp.OPERATION_SUCCESS)
diff --git a/voltha/adapters/openolt/openolt_alarms.py b/voltha/adapters/openolt/openolt_alarms.py
index 5ebf20b..6eb0702 100644
--- a/voltha/adapters/openolt/openolt_alarms.py
+++ b/voltha/adapters/openolt/openolt_alarms.py
@@ -31,6 +31,8 @@
from voltha.extensions.alarms.onu.onu_window_drift_alarm import OnuWindowDriftAlarm
from voltha.extensions.alarms.onu.onu_activation_fail_alarm import OnuActivationFailAlarm
+from voltha.extensions.alarms.onu.onu_discovery_alarm import OnuDiscoveryAlarm
+
import protos.openolt_pb2 as openolt_pb2
import voltha.protos.device_pb2 as device_pb2
@@ -101,6 +103,50 @@
self.log.error('sorting of alarm went wrong', error=e,
alarm=alarm_ind)
+ def simulate_alarm(self, alarm):
+ if alarm.indicator == "los":
+ alarm_obj = OltLosAlarm(self.alarms, intf_id=alarm.intf_id, port_type_name=alarm.port_type_name)
+ elif alarm.indicator == "dying_gasp":
+ alarm_obj = OnuDyingGaspAlarm(self.alarms, alarm.intf_id, alarm.onu_device_id)
+ elif alarm.indicator == "onu_los":
+ alarm_obj = OnuLosAlarm(self.alarms, onu_id=alarm.onu_device_id, intf_id=alarm.intf_id)
+ elif alarm.indicator == "onu_lopc_miss":
+ alarm_obj = OnuLopcMissAlarm(self.alarms, onu_id=alarm.onu_device_id, intf_id=alarm.intf_id)
+ elif alarm.indicator == "onu_lopc_mic":
+ alarm_obj = OnuLopcMicErrorAlarm(self.alarms, onu_id=alarm.onu_device_id, intf_id=alarm.intf_id)
+ elif alarm.indicator == "onu_lob":
+ alarm_obj = OnuLobAlarm(self.alarms, onu_id=alarm.onu_device_id, intf_id=alarm.intf_id)
+ elif alarm.indicator == "onu_startup":
+ alarm_obj = OnuStartupAlarm(self.alarms, intf_id=alarm.intf_id, onu_id=alarm.onu_device_id)
+ elif alarm.indicator == "onu_signal_degrade":
+ alarm_obj = OnuSignalDegradeAlarm(self.alarms, intf_id=alarm.intf_id, onu_id=alarm.onu_device_id,
+ inverse_bit_error_rate=alarm.inverse_bit_error_rate)
+ elif alarm.indicator == "onu_drift_of_window":
+ alarm_obj = OnuWindowDriftAlarm(self.alarms, intf_id=alarm.intf_id,
+ onu_id=alarm.onu_device_id,
+ drift=alarm.drift,
+ new_eqd=alarm.new_eqd)
+ elif alarm.indicator == "onu_signal_fail":
+ alarm_obj = OnuSignalFailAlarm(self.alarms, intf_id=alarm.intf_id,
+ onu_id=alarm.onu_device_id,
+ inverse_bit_error_rate=alarm.inverse_bit_error_rate)
+ elif alarm.indicator == "onu_activation":
+ alarm_obj = OnuActivationFailAlarm(self.alarms, intf_id=alarm.intf_id,
+ onu_id=alarm.onu_device_id)
+ elif alarm.indicator == "onu_discovery":
+ alarm_obj = OnuDiscoveryAlarm(self.alarms, pon_id=alarm.intf_id,
+ serial_number=alarm.onu_serial_number)
+ else:
+ raise Exception("Unknown alarm indicator %s" % alarm.indicator)
+
+ if alarm.operation == alarm.RAISE:
+ alarm_obj.raise_alarm()
+ elif alarm.operation == alarm.CLEAR:
+ alarm_obj.clear_alarm()
+ else:
+ # This shouldn't happen
+ raise Exception("Unknown alarm operation")
+
def los_indication(self, los_ind):
try:
diff --git a/voltha/adapters/openolt/openolt_device.py b/voltha/adapters/openolt/openolt_device.py
index db68bca..087179c 100644
--- a/voltha/adapters/openolt/openolt_device.py
+++ b/voltha/adapters/openolt/openolt_device.py
@@ -1078,3 +1078,6 @@
error=e)
else:
self.log.info('statistics requested')
+
+ def simulate_alarm(self, alarm):
+ self.alarm_mgr.simulate_alarm(alarm)
diff --git a/voltha/core/adapter_agent.py b/voltha/core/adapter_agent.py
index a063533..bf048d0 100644
--- a/voltha/core/adapter_agent.py
+++ b/voltha/core/adapter_agent.py
@@ -271,6 +271,9 @@
def remove_multicast_distribution_set(self, device, data):
return self.adapter.remove_multicast_distribution_set(device, data)
+ def simulate_alarm(self, device, request):
+ return self.adapter.simulate_alarm(device, request)
+
# ~~~~~~~~~~~~~~~~~~~ Adapter-Facing Service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def get_device(self, device_id):
diff --git a/voltha/core/device_agent.py b/voltha/core/device_agent.py
index 5d7a8a2..33f7008 100644
--- a/voltha/core/device_agent.py
+++ b/voltha/core/device_agent.py
@@ -379,6 +379,14 @@
if not dry_run:
yield self.adapter_agent.delete_device(device)
+ def simulate_alarm(self, device, alarm):
+ try:
+ self.log.debug('simulate_alarm', alarm=alarm)
+ return self.adapter_agent.simulate_alarm(device, alarm)
+ except Exception as e:
+ self.log.exception(e.message)
+ return OperationResp(code=OperationResp.OPERATION_FAILURE)
+
admin_state_fsm = {
# Missing entries yield no-op
diff --git a/voltha/core/global_handler.py b/voltha/core/global_handler.py
index 54c2d28..098e145 100644
--- a/voltha/core/global_handler.py
+++ b/voltha/core/global_handler.py
@@ -1778,4 +1778,26 @@
returnValue(AlarmDeviceData())
else:
log.debug('grpc-success-response', response=response)
+ returnValue(response)
+
+ @twisted_async
+ @inlineCallbacks
+ def SimulateAlarm(self, request, context):
+ try:
+ log.debug('grpc-request', request=request)
+ response = yield self.dispatcher.dispatch('SimulateAlarm',
+ request,
+ context,
+ id=request.id)
+ log.debug('grpc-response', response=response)
+ except Exception as e:
+ log.exception('grpc-exception', e=e)
+
+ if isinstance(response, DispatchError):
+ log.warn('grpc-error-response', error=response.error_code)
+ context.set_details('Device \'{}\' error'.format(request.id))
+ context.set_code(response.error_code)
+ returnValue(OperationResp(code=OperationResp.OPERATION_FAILURE))
+ else:
+ log.debug('grpc-success-response', response=response)
returnValue(response)
\ No newline at end of file
diff --git a/voltha/core/local_handler.py b/voltha/core/local_handler.py
index 8520a42..2a2df05 100644
--- a/voltha/core/local_handler.py
+++ b/voltha/core/local_handler.py
@@ -1372,4 +1372,33 @@
context.set_details(
'OMCI ALARM for Device \'{}\' not found'.format(request.id))
context.set_code(StatusCode.NOT_FOUND)
- return AlarmDeviceData()
\ No newline at end of file
+ return AlarmDeviceData()
+
+ @twisted_async
+ def SimulateAlarm(self, request, context):
+ log.debug('grpc-request', request=request)
+
+ if '/' in request.id:
+ context.set_details(
+ 'Malformed device id \'{}\''.format(request.id))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ response = OperationResp(code=OperationResp.OPERATION_FAILURE)
+ return response
+
+ try:
+ path = '/devices/{}'.format(request.id)
+ device = self.root.get(path)
+ agent = self.core.get_device_agent(device.id)
+ response = agent.simulate_alarm(device, request)
+ return response
+
+ except KeyError:
+ context.set_details(
+ 'Device \'{}\' not found'.format(request.id))
+ context.set_code(StatusCode.NOT_FOUND)
+ response = OperationResp(code=OperationResp.OPERATION_FAILURE)
+ return response
+ except Exception as e:
+ log.exception(e.message)
+ response = OperationResp(code=OperationResp.OPERATION_FAILURE)
+ return response
\ No newline at end of file
diff --git a/voltha/protos/device.proto b/voltha/protos/device.proto
index 58594ed..46ed270 100644
--- a/voltha/protos/device.proto
+++ b/voltha/protos/device.proto
@@ -306,3 +306,21 @@
message Devices {
repeated Device items = 1;
}
+
+message SimulateAlarmRequest {
+ enum OperationType {
+ RAISE = 0;
+ CLEAR = 1;
+ }
+ // Device Identifier
+ string id = 1;
+ string indicator = 2;
+ string intf_id = 3;
+ string port_type_name = 4;
+ string onu_device_id = 5;
+ int32 inverse_bit_error_rate = 6;
+ int32 drift = 7;
+ int32 new_eqd = 8;
+ string onu_serial_number = 9;
+ OperationType operation = 10;
+}
\ No newline at end of file
diff --git a/voltha/protos/voltha.proto b/voltha/protos/voltha.proto
index 3d62878..4736973 100644
--- a/voltha/protos/voltha.proto
+++ b/voltha/protos/voltha.proto
@@ -972,6 +972,14 @@
get: "/api/v1/openomci/{id}/alarm"
};
}
+
+ // Simulate an Alarm
+ rpc SimulateAlarm(SimulateAlarmRequest) returns(OperationResp) {
+ option (google.api.http) = {
+ post: "/api/v1/devices/{id}/simulate_larm"
+ body: "*"
+ };
+ }
}
/*
@@ -1714,4 +1722,12 @@
get: "/api/v1/openomci/{id}/alarm"
};
}
+
+ // Simulate an Alarm
+ rpc SimulateAlarm(SimulateAlarmRequest) returns(OperationResp) {
+ option (google.api.http) = {
+ post: "/api/v1/devices/{id}/simulate_alarm"
+ body: "*"
+ };
+ }
}