// // Copyright (c) 2018 Wind River Systems, Inc. // // SPDX-License-Identifier: Apache-2.0 // #include #include #include "fmAPI.h" #include "fmAlarmUtils.h" static const size_t DEF_MAX_ALARMS (1000); static const size_t MAXSTRINGSIZE (500); static PyObject *logging = NULL; enum { error, warning, info, debug, max_level }; #define LOG_MSG(level,data,...) \ log_msg(level, "fm_python_extension: "\ data, ## __VA_ARGS__ ) #define ERROR_LOG(data,...) \ LOG_MSG(error, data, ## __VA_ARGS__) #define WARNING_LOG(data,...) \ LOG_MSG(warning, data, ## __VA_ARGS__) #define INFO_LOG(data,...) \ LOG_MSG(info, data, ## __VA_ARGS__) #define DEBUG_LOG(data,...) \ LOG_MSG(debug, data, ## __VA_ARGS__) static void log_msg(int type, const char *data,...) { static PyObject *str = NULL; const char* methods[] = {"error", "warning", "info", "debug"}; if (logging == NULL) { logging = PyImport_ImportModuleNoBlock("logging"); if (logging == NULL) { PyErr_SetString(PyExc_ImportError, "Could not import python module 'logging'"); } } va_list ap; char buff[MAXSTRINGSIZE]; va_start(ap, data ); vsnprintf(buff, sizeof(buff), data, ap); va_end(ap); str = Py_BuildValue((char *)"s", buff); if (type < max_level) { PyObject_CallMethod(logging, (char *)methods[type], (char *)"O", str); } Py_DECREF(str); } static PyObject * _fm_set(PyObject * self, PyObject *args) { SFmAlarmDataT alm_data; std::string alarm; fm_uuid_t tmp_uuid; const char *alm_str; EFmErrorT rc; if (!PyArg_ParseTuple(args, "s", &alm_str)) { ERROR_LOG("Failed to parse args."); Py_RETURN_NONE; } alarm.assign(alm_str); if (!fm_alarm_from_string(alarm, &alm_data)) { ERROR_LOG("Failed to convert string to alarm."); Py_RETURN_NONE; } rc = fm_set_fault(&alm_data, &tmp_uuid); if (rc == FM_ERR_OK) { return PyString_FromString(&(tmp_uuid[0])); } if (rc == FM_ERR_NOCONNECT){ // when the fm-manager process has not been started by SM WARNING_LOG("Failed to connect to FM manager"); } else { ERROR_LOG("Failed to generate an alarm: (%s) (%s)", alm_data.alarm_id, alm_data.entity_instance_id); } Py_RETURN_NONE; } static PyObject * _fm_get(PyObject * self, PyObject *args) { const char *filter; std::string alm_str, filter_str; AlarmFilter af; SFmAlarmDataT ad; EFmErrorT rc; if (!PyArg_ParseTuple(args, "s", &filter)) { ERROR_LOG("Failed to parse args"); Py_RETURN_FALSE; } filter_str.assign(filter); if (!fm_alarm_filter_from_string(filter_str, &af)) { ERROR_LOG("Invalid alarm filter: (%s)", filter_str.c_str()); Py_RETURN_FALSE; } rc = fm_get_fault(&af,&ad); if (rc == FM_ERR_OK) { fm_alarm_to_string(&ad,alm_str); return PyString_FromString(alm_str.c_str()); } if (rc == FM_ERR_ENTITY_NOT_FOUND) { DEBUG_LOG("Alarm id (%s), Entity id:(%s) not found", af.alarm_id, af.entity_instance_id); Py_RETURN_NONE; } else if (rc == FM_ERR_NOCONNECT) { WARNING_LOG("Failed to connect to FM manager"); } else { ERROR_LOG("Failed to get alarm by filter: (%s) (%s), error code: (%d)", af.alarm_id, af.entity_instance_id, rc); } Py_RETURN_FALSE; } static PyObject * _fm_get_by_aid(PyObject * self, PyObject *args, PyObject* kwargs) { const char *aid; fm_alarm_id alm_id; unsigned int max = DEF_MAX_ALARMS; char* keywords[] = {"alarm_id", "max", (char*)NULL}; memset(alm_id, 0 , sizeof(alm_id)); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i", keywords, &aid, &max)) { ERROR_LOG("Failed to parse args"); Py_RETURN_FALSE; } strncpy(alm_id, aid, sizeof(alm_id)-1); std::vector< SFmAlarmDataT > lst; try { lst.resize(max); } catch(...) { ERROR_LOG("Failed to allocate memory"); Py_RETURN_FALSE; } unsigned int max_alarms_to_get = max; EFmErrorT rc = fm_get_faults_by_id(&alm_id, &(lst[0]), &max_alarms_to_get); if (rc == FM_ERR_OK) { PyObject *__lst = PyList_New(0); for ( size_t ix = 0 ; ix < max_alarms_to_get ; ++ix ) { std::string s; fm_alarm_to_string(&lst[ix],s); if (s.size() > 0) { if (PyList_Append(__lst, PyString_FromString(s.c_str())) != 0) { ERROR_LOG("Failed to append alarm to the list"); } } } /* python will garbage collect if the reference count is correct (it should be 1 at this point) */ return __lst; } if (rc == FM_ERR_ENTITY_NOT_FOUND) { DEBUG_LOG("No alarm found for alarm id (%s)", alm_id); Py_RETURN_NONE; } else if (rc == FM_ERR_NOCONNECT) { WARNING_LOG("Failed to connect to FM manager"); } else { ERROR_LOG("Failed to get alarm list for alarm id (%s), error code: (%d)", alm_id, rc); } Py_RETURN_FALSE; } static PyObject * _fm_get_by_eid(PyObject * self, PyObject *args, PyObject* kwargs) { const char *eid; fm_ent_inst_t inst_id; std::vector< SFmAlarmDataT > lst; unsigned int max= DEF_MAX_ALARMS; char* keywords[] = {"entity_instance_id", "max", (char*)NULL}; memset(inst_id, 0 , sizeof(inst_id)); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i", keywords, &eid, &max)) { ERROR_LOG("Failed to parse args"); Py_RETURN_FALSE; } strncpy(inst_id, eid ,sizeof(inst_id)-1); try { lst.resize(max); } catch(...) { ERROR_LOG("Failed to allocate memory"); Py_RETURN_FALSE; } unsigned int max_alarms_to_get = max; EFmErrorT rc = fm_get_faults(&inst_id, &(lst[0]), &max_alarms_to_get); if (rc == FM_ERR_OK) { PyObject *__lst = PyList_New(0); for ( size_t ix = 0; ix < max_alarms_to_get; ++ix ) { std::string s; fm_alarm_to_string(&lst[ix], s); if (s.size() > 0) { if (PyList_Append(__lst,PyString_FromString(s.c_str())) != 0) { ERROR_LOG("Failed to append alarm to the list"); } } } /* python will garbage collect if the reference count is correct (it should be 1 at this point) */ return __lst; } if (rc == FM_ERR_ENTITY_NOT_FOUND) { DEBUG_LOG("No alarm found for entity id (%s)", inst_id); Py_RETURN_NONE; } else if (rc == FM_ERR_NOCONNECT) { WARNING_LOG("Failed to connect to FM manager"); } else { ERROR_LOG("Failed to get alarm list for entity id (%s), error code: (%d)", inst_id, rc); } Py_RETURN_FALSE; } static PyObject * _fm_clear(PyObject * self, PyObject *args) { const char *filter; std::string alm_str, filter_str; AlarmFilter af; EFmErrorT rc; if (!PyArg_ParseTuple(args, "s", &filter)) { ERROR_LOG("Failed to parse args"); Py_RETURN_FALSE; } filter_str.assign(filter); if (!fm_alarm_filter_from_string(filter_str, &af)) { ERROR_LOG("Invalid alarm filter: (%s)", filter_str.c_str()); Py_RETURN_FALSE; } rc = fm_clear_fault(&af); if (rc == FM_ERR_OK) { Py_RETURN_TRUE; } if (rc == FM_ERR_ENTITY_NOT_FOUND) { DEBUG_LOG("No alarm found to clear: (%s) (%s)", af.alarm_id, af.entity_instance_id); } else if (rc == FM_ERR_NOCONNECT) { WARNING_LOG("Failed to connect to FM manager"); } else { ERROR_LOG("Failed to clear alarm by filter: (%s) (%s), error code: (%d)", af.alarm_id, af.entity_instance_id, rc); } Py_RETURN_FALSE; } static PyObject * _fm_clear_all(PyObject * self, PyObject *args) { fm_ent_inst_t inst_id; const char *eid; EFmErrorT rc; memset(inst_id, 0 , sizeof(inst_id)); if (!PyArg_ParseTuple(args,"s", &eid)) { ERROR_LOG("Failed to parse args"); Py_RETURN_FALSE; } strncpy(inst_id, eid ,sizeof(inst_id)-1); rc = fm_clear_all(&inst_id); if (rc == FM_ERR_OK) { Py_RETURN_TRUE; } else { ERROR_LOG("Failed to clear alarms with entity id (%s), error code: (%d)", inst_id, rc); Py_RETURN_FALSE; } } static PyMethodDef _methods [] = { { "set", _fm_set, METH_VARARGS, "Set or update an alarm" }, { "get", _fm_get, METH_VARARGS, "Get alarms by filter" }, { "clear", _fm_clear, METH_VARARGS, "Clear an alarm by filter" }, { "clear_all", _fm_clear_all, METH_VARARGS, "Clear alarms that match the entity instance id"}, { "get_by_aid", (PyCFunction)_fm_get_by_aid, METH_VARARGS | METH_KEYWORDS, "Get alarms by alarm id" }, { "get_by_eid", (PyCFunction)_fm_get_by_eid, METH_VARARGS | METH_KEYWORDS, "Get alarms by entity instance id" }, { NULL, NULL, 0, NULL } }; PyMODINIT_FUNC initfm_core() { PyObject *m = Py_InitModule("fm_core", _methods); if (m == NULL){ PySys_WriteStderr("Failed to initialize fm_core"); return; } }