Add new methods/options to FM API
This commit does the following:
- Add a new option "keep_existing_alarm" when creating an alarm so,
if said alarm already exists, it won't be updated.
- Add a new method to clear alarms from a list. The input is a list
with each element being a tuple consisted of alarm_id and
entity_instance_id.
- Modified the existing method that created alarms from a list.
Previously, the client would loop through the list of alarms and send
requests to FM API. Now, alarms from the list are converted into
a vector of structs and passed to FM API in a single request.
Test plan (using FaultAPIsV2):
- PASS: Build package and install.
- PASS: Create a new alarm with keep_existing_alarm=True and verify
a new alarm was created.
- PASS: Create an existing alarm with keep_existing_alarm=True and
verify the original alarm was kept and the returned UUID
is correct.
- PASS: Create an existing alarm without keep_existing_alarm and
verify the original alarm was updated and the returned UUID
is correct.
- PASS: Create a list of alarms and verify they were correctly
created and it was faster than previous method.
- PASS: Clear a list of alarms that exist and verify they were
successfully cleared.
- PASS: Clear a list of alarms that don't exist and verify the API
didn't raise any errors.
- PASS: Stop pmond process and verify mtce raises the correct
200.006 alarm only once. Restart pmond and verify the alarm
is cleared.
Story: 2011311
Task: 52166
Change-Id: I2f901c4726c24f3522a8c5bae1d7d9b03ef24ce0
Signed-off-by: Victor Romano <victor.gluzromano@windriver.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2025 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -44,6 +44,10 @@ class APIException(Exception):
|
||||
# suppression: true/false (allowed/not-allowed), default to false
|
||||
# uuid: unique identifier of an active alarm instance, filled by FM system
|
||||
# Timestamp: when the alarm has been raised/updated, filled by FM system
|
||||
# inhibit_alarms: hierarchical suppression of alarms if it is set to true
|
||||
# true/false, default to false
|
||||
# keep_existing_alarm: keep original alarm when creating an alarm that already exist
|
||||
# true/false, default to false
|
||||
# See CGCS FM Guide for the alarm model specification
|
||||
class Fault(object):
|
||||
|
||||
@@ -51,7 +55,8 @@ class Fault(object):
|
||||
entity_instance_id, severity, reason_text,
|
||||
alarm_type, probable_cause, proposed_repair_action,
|
||||
service_affecting=False, suppression=False,
|
||||
uuid=None, timestamp=None):
|
||||
uuid=None, timestamp=None, inhibit_alarms=False,
|
||||
keep_existing_alarm=False):
|
||||
self.alarm_id = alarm_id
|
||||
self.alarm_state = alarm_state
|
||||
self.entity_type_id = self._unicode(entity_type_id)
|
||||
@@ -65,6 +70,8 @@ class Fault(object):
|
||||
self.suppression = suppression
|
||||
self.uuid = uuid
|
||||
self.timestamp = timestamp
|
||||
self.inhibit_alarms = inhibit_alarms
|
||||
self.keep_existing_alarm = keep_existing_alarm
|
||||
|
||||
def as_dict(self):
|
||||
return copy.copy(self.__dict__)
|
||||
@@ -95,7 +102,10 @@ class FaultAPIsBase(object):
|
||||
sep + data.alarm_type + sep + data.probable_cause + sep +
|
||||
self._check_val(data.proposed_repair_action) + sep +
|
||||
str(data.service_affecting) + sep +
|
||||
str(data.suppression) + sep)
|
||||
str(data.suppression) + sep +
|
||||
str(data.inhibit_alarms) + sep +
|
||||
str(data.keep_existing_alarm) + sep
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _str_to_alarm(alarm_str):
|
||||
@@ -386,3 +396,37 @@ class FaultAPIsV2(FaultAPIsBase):
|
||||
return data
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_faults(self, data: list[Fault]) -> bool:
|
||||
"""Set a list of provided faults
|
||||
|
||||
:param data: list of Fault objects
|
||||
"""
|
||||
buff_list = []
|
||||
for alarm_data in data:
|
||||
self._check_required_attributes(alarm_data)
|
||||
self._validate_attributes(alarm_data)
|
||||
buff = self._alarm_to_str(alarm_data)
|
||||
buff_list.append(buff)
|
||||
|
||||
with fm_api_lock:
|
||||
resp = fm_core.set_fault_list(buff_list)
|
||||
if resp is False:
|
||||
raise APIException("Failed to execute set_faults.")
|
||||
return resp
|
||||
|
||||
def clear_faults_list(self, faults_list: list[tuple[str, str]]) -> bool:
|
||||
"""Clear a list of provided faults
|
||||
|
||||
:param faults_list: list of tuples (alarm_id, entity_instance_id)
|
||||
"""
|
||||
buff_list = []
|
||||
sep = constants.FM_CLIENT_STR_SEP
|
||||
for alarm_id, entity_instance_id in faults_list:
|
||||
buff_list.append(sep + self._check_val(alarm_id) + sep +
|
||||
self._check_val(entity_instance_id) + sep)
|
||||
with fm_api_lock:
|
||||
resp = fm_core.clear_list(buff_list)
|
||||
if resp is False:
|
||||
raise APIException("Failed to execute clear_faults_list.")
|
||||
return resp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017,2024 Wind River Systems, Inc.
|
||||
// Copyright (c) 2017, 2024-2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -287,6 +287,37 @@ EFmErrorT fm_set_fault(const SFmAlarmDataT *alarm,
|
||||
return FM_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
EFmErrorT fm_set_fault_list(const std::vector<SFmAlarmDataT> *alarm) {
|
||||
CFmMutexGuard m(getAPIMutex());
|
||||
if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT;
|
||||
|
||||
fm_buff_t buff;
|
||||
buff.clear();
|
||||
|
||||
// Calculate the total size of all alarm data
|
||||
size_t total_size = alarm->size() * sizeof(SFmAlarmDataT);
|
||||
const void* data_ptr = alarm->data();
|
||||
EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff, EFmCreateFaultList,
|
||||
data_ptr, total_size);
|
||||
if (erc != FM_ERR_OK) return erc;
|
||||
|
||||
if (m_client.write_packet(buff)) {
|
||||
if (!m_client.read_packet(buff)) {
|
||||
m_connected = false;
|
||||
return FM_ERR_NOCONNECT;
|
||||
}
|
||||
|
||||
HANDLE_SERVER_RC(ptr_to_hdr(buff));
|
||||
} else {
|
||||
m_connected = false;
|
||||
return FM_ERR_NOCONNECT;
|
||||
}
|
||||
|
||||
return FM_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears fault entries based on the specified filter.
|
||||
*
|
||||
@@ -357,6 +388,36 @@ EFmErrorT fm_clear_all(fm_ent_inst_t *inst_id) {
|
||||
}
|
||||
|
||||
|
||||
EFmErrorT fm_clear_fault_list(std::vector<AlarmFilter> *filter) {
|
||||
|
||||
CFmMutexGuard m(getAPIMutex());
|
||||
if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT;
|
||||
|
||||
fm_buff_t buff;
|
||||
buff.clear();
|
||||
|
||||
// Calculate the total size of all alarm data
|
||||
size_t total_size = filter->size() * sizeof(AlarmFilter);
|
||||
const void* data_ptr = filter->data();
|
||||
|
||||
EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff, EFmDeleteFaultList,
|
||||
data_ptr, total_size);
|
||||
if (erc!=FM_ERR_OK) return erc;
|
||||
|
||||
if (m_client.write_packet(buff)) {
|
||||
if (!m_client.read_packet(buff)) {
|
||||
m_connected = false;
|
||||
return FM_ERR_NOCONNECT;
|
||||
}
|
||||
HANDLE_SERVER_RC(ptr_to_hdr(buff));
|
||||
} else {
|
||||
m_connected = false;
|
||||
return FM_ERR_NOCONNECT;
|
||||
}
|
||||
return FM_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
EFmErrorT fm_get_fault(AlarmFilter *filter, SFmAlarmDataT *alarm ) {
|
||||
|
||||
CFmMutexGuard m(getAPIMutex());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2024 Wind River Systems, Inc.
|
||||
// Copyright (c) 2017, 2024-2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -160,6 +161,7 @@ typedef struct{
|
||||
FMBoolTypeT service_affecting;
|
||||
FMBoolTypeT suppression; //'allowed' or 'not-allowed'
|
||||
FMBoolTypeT inhibit_alarms; //hierarchical suppression of alarms if it is set to true
|
||||
FMBoolTypeT keep_existing_alarm; //keep original alarm when creating an alarm that already exist
|
||||
}SFmAlarmDataT;
|
||||
|
||||
typedef enum{
|
||||
@@ -194,10 +196,14 @@ typedef struct {
|
||||
*/
|
||||
EFmErrorT fm_set_fault(const SFmAlarmDataT *alarm, fm_uuid_t *uuid);
|
||||
|
||||
EFmErrorT fm_set_fault_list(const std::vector<SFmAlarmDataT> *alarm);
|
||||
|
||||
EFmErrorT fm_clear_fault(AlarmFilter *filter);
|
||||
|
||||
EFmErrorT fm_clear_all(fm_ent_inst_t *inst_id);
|
||||
|
||||
EFmErrorT fm_clear_fault_list(std::vector<AlarmFilter> *filter);
|
||||
|
||||
EFmErrorT fm_get_fault(AlarmFilter *filter, SFmAlarmDataT *alarm);
|
||||
|
||||
EFmErrorT fm_get_faults(fm_ent_inst_t *inst_id, SFmAlarmDataT *alarm,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2014 Wind River Systems, Inc.
|
||||
// Copyright (c) 2014, 2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -359,6 +359,15 @@ static void fm_inhibit_alarm(SFmAlarmDataT *a, std::string &s,
|
||||
}
|
||||
|
||||
|
||||
static void fm_keep_existing_alarm(SFmAlarmDataT *a, std::string &s,
|
||||
bool is_get) {
|
||||
if (is_get)
|
||||
s = tostr(a->keep_existing_alarm, bool_to_str);
|
||||
else
|
||||
a->keep_existing_alarm = (((s == "t") || (s == "True"))? 1 :0);
|
||||
}
|
||||
|
||||
|
||||
typedef void (*set_get_field_type)(SFmAlarmDataT *a, std::string &s, bool is_get);
|
||||
|
||||
|
||||
@@ -379,7 +388,8 @@ struct alarm_struct_update_t {
|
||||
{ FM_ALM_IX_REPAIR_ACTION, fm_repair },
|
||||
{ FM_ALM_IX_SERVICE_AFFECT, fm_service_affect },
|
||||
{ FM_ALM_IX_SUPPRESSION, fm_suppression },
|
||||
{ FM_ALM_IX_INHIBIT_ALARM, fm_inhibit_alarm }
|
||||
{ FM_ALM_IX_INHIBIT_ALARM, fm_inhibit_alarm },
|
||||
{ FM_ALM_IX_KEEP_EXISTING_ALARM, fm_keep_existing_alarm }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2014 Wind River Systems, Inc.
|
||||
// Copyright (c) 2014, 2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -29,6 +29,7 @@ enum EFmAlarmIndexMap {
|
||||
FM_ALM_IX_SERVICE_AFFECT,
|
||||
FM_ALM_IX_SUPPRESSION,
|
||||
FM_ALM_IX_INHIBIT_ALARM,
|
||||
FM_ALM_IX_KEEP_EXISTING_ALARM,
|
||||
FM_ALM_IX_MAX
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2014-2018 Wind River Systems, Inc.
|
||||
// Copyright (c) 2014-2018, 2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -48,6 +48,9 @@
|
||||
#define FM_ALARM_COLUMN_INHIBIT_ALARMS "inhibit_alarms"
|
||||
#define FM_ALARM_COLUMN_MASKED "masked"
|
||||
|
||||
// Not a table column, but can be sent as an alarm parameter
|
||||
#define FM_ALARM_KEEP_EXISTING_ALARM "keep_existing_alarm"
|
||||
|
||||
/* Event Log Table Columns */
|
||||
#define FM_EVENT_LOG_COLUMN_CREATED_AT "created_at"
|
||||
#define FM_EVENT_LOG_COLUMN_UPDATED_AT "updated_at"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2014-2024 Wind River Systems, Inc.
|
||||
// Copyright (c) 2014-2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -41,7 +41,8 @@ static const char * field_map[] = {
|
||||
FM_ALARM_COLUMN_SERVICE_AFFECTING,
|
||||
FM_ALARM_COLUMN_SUPPRESSION,
|
||||
FM_ALARM_COLUMN_INHIBIT_ALARMS,
|
||||
FM_ALARM_COLUMN_MASKED //18
|
||||
FM_ALARM_KEEP_EXISTING_ALARM,
|
||||
FM_ALARM_COLUMN_MASKED //19
|
||||
};
|
||||
|
||||
void add_both_tables(const char *str, int id, itos_t &t1,stoi_t &t2 ) {
|
||||
@@ -81,6 +82,8 @@ static void init_tables() {
|
||||
add_both_tables(FM_ALARM_COLUMN_SERVICE_AFFECTING,FM_ALM_IX_SERVICE_AFFECT,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix);
|
||||
add_both_tables(FM_ALARM_COLUMN_SUPPRESSION,FM_ALM_IX_SUPPRESSION,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix);
|
||||
add_both_tables(FM_ALARM_COLUMN_INHIBIT_ALARMS,FM_ALM_IX_INHIBIT_ALARM,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix);
|
||||
|
||||
add_both_tables(FM_ALARM_KEEP_EXISTING_ALARM,FM_ALM_IX_KEEP_EXISTING_ALARM,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix);
|
||||
has_inited = true;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
@@ -175,6 +178,12 @@ bool CFmDbAlarmOperation::create_alarm(CFmDBSession &sess,CFmDbAlarm &a) {
|
||||
data.erase(it);
|
||||
}
|
||||
|
||||
// Remove keep_existing_alarm field as it's a control field, not a DB column
|
||||
it = data.find(FM_ALARM_KEEP_EXISTING_ALARM);
|
||||
if (it != data.end()){
|
||||
data.erase(it);
|
||||
}
|
||||
|
||||
std::string query;
|
||||
FM_DB_UT_NAME_VAL(query,FM_ALARM_COLUMN_ALARM_ID,
|
||||
data[FM_ALARM_COLUMN_ALARM_ID]);
|
||||
@@ -200,6 +209,12 @@ bool CFmDbAlarmOperation::create_alarm(CFmDBSession &sess,CFmDbAlarm &a) {
|
||||
if (result.size() == 0){
|
||||
fm_db_util_build_sql_insert((const char*)FM_ALARM_TABLE_NAME, data, sql_params);
|
||||
}else{
|
||||
if (a.find_field(FM_ALARM_KEEP_EXISTING_ALARM) == "True") {
|
||||
FM_DEBUG_LOG("Alarm exists and keep_existing_alarm was provided, not updating...\n");
|
||||
// Since alarm was kept, we need to set the uuid to the one from db
|
||||
a.set_field(FM_ALARM_COLUMN_UUID, result[0][FM_ALARM_COLUMN_UUID]);
|
||||
return true;
|
||||
}
|
||||
fm_db_single_result_t alm = result[0];
|
||||
fm_db_util_build_sql_update((const char*)FM_ALARM_TABLE_NAME,
|
||||
alm[FM_ALARM_COLUMN_ID],data, sql_params);
|
||||
@@ -555,6 +570,12 @@ bool CFmDbAlarmOperation::add_alarm_history(CFmDBSession &sess,
|
||||
data.erase(it);
|
||||
}
|
||||
|
||||
// Remove keep_existing_alarm field as it's a control field, not a DB column
|
||||
it = data.find(FM_ALARM_KEEP_EXISTING_ALARM);
|
||||
if (it != data.end()){
|
||||
data.erase(it);
|
||||
}
|
||||
|
||||
int id =0;
|
||||
std::string sql;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2024 Wind River Systems, Inc.
|
||||
// Copyright (c) 2014, 2024-2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -37,6 +37,8 @@ typedef enum {
|
||||
EFmReturnUUID,
|
||||
EFmGetFaultsById,
|
||||
EFmGetFaultsByIdnEid,
|
||||
EFmCreateFaultList,
|
||||
EFmDeleteFaultList,
|
||||
EFmActMax
|
||||
}EFmMsgActionsT;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||
// Copyright (c) 2017-2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -467,7 +467,7 @@ void FmSocketServerProcessor::send_response(int fd, SFmMsgHdrT *hdr, void *data,
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_create_fault(int fd,
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata, CFmDBSession &sess) {
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata, CFmDBSession &sess, bool send_response_flag) {
|
||||
|
||||
is_request_valid(hdr->msg_size,SFmAlarmDataT);
|
||||
void * data = &(rdata[sizeof(SFmMsgHdrT)]);
|
||||
@@ -504,26 +504,80 @@ void FmSocketServerProcessor::handle_create_fault(int fd,
|
||||
}
|
||||
FM_INFO_LOG("Send response for create log, uuid:(%s) (%u)\n",
|
||||
alarm->uuid, hdr->msg_rc);
|
||||
send_response(fd,hdr,alarm->uuid,sizeof(alarm->uuid));
|
||||
if (send_response_flag)
|
||||
send_response(fd,hdr,alarm->uuid,sizeof(alarm->uuid));
|
||||
} else {
|
||||
a.create_data(alarm);
|
||||
//a.print();
|
||||
if (op.create_alarm(sess,a)){
|
||||
FM_INFO_LOG("Alarm created/updated: (%s) (%s) (%d) (%s)\n",
|
||||
alarm->alarm_id, alarm->entity_instance_id, alarm->severity, alarm->uuid);
|
||||
if (op.create_alarm(sess, a)) {
|
||||
std::string uuid_str = a.find_field(FM_ALARM_COLUMN_UUID);
|
||||
strncpy(alarm->uuid, uuid_str.c_str(), sizeof(alarm->uuid));
|
||||
FM_INFO_LOG("Alarm created/updated/kept: (%s) (%s) (%d) (%s)\n",
|
||||
alarm->alarm_id, alarm->entity_instance_id, alarm->severity, alarm->uuid);
|
||||
req.type = alarm->severity;
|
||||
enqueue_job(req);
|
||||
}else{
|
||||
FM_ERROR_LOG("Fail to created/updated alarm: (%s) (%s)\n",
|
||||
alarm->alarm_id, alarm->entity_instance_id);
|
||||
} else {
|
||||
FM_ERROR_LOG("Fail to create/update alarm: (%s) (%s)\n",
|
||||
alarm->alarm_id, alarm->entity_instance_id);
|
||||
hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE;
|
||||
}
|
||||
FM_INFO_LOG("Send response for create fault, uuid:(%s) (%u)\n",
|
||||
alarm->uuid, hdr->msg_rc);
|
||||
send_response(fd,hdr,alarm->uuid,sizeof(alarm->uuid));
|
||||
|
||||
if (send_response_flag) {
|
||||
FM_INFO_LOG("Send response for create fault, uuid:(%s) (%u)\n",
|
||||
alarm->uuid, hdr->msg_rc);
|
||||
send_response(fd, hdr, alarm->uuid, sizeof(alarm->uuid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_create_fault_list(int fd,
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata, CFmDBSession &sess) {
|
||||
|
||||
// Validate the basic message size first
|
||||
// We cannot use is_request_valid because the size is variable based
|
||||
// on the number of alarms, so we just verify if the sent size is a
|
||||
// multiple of sizeof(SFmAlarmDataT)
|
||||
if (hdr->msg_size % sizeof(SFmAlarmDataT) != 0) {
|
||||
FM_ERROR_LOG("Invalid message size: %u, expected multiple of %zu",
|
||||
hdr->msg_size, sizeof(SFmAlarmDataT));
|
||||
hdr->msg_rc = FM_ERR_INVALID_REQ;
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t num_alarms = hdr->msg_size / sizeof(SFmAlarmDataT);
|
||||
|
||||
FM_INFO_LOG("Processing create fault list with %u entries", num_alarms);
|
||||
|
||||
size_t offset = sizeof(SFmMsgHdrT);
|
||||
for (uint32_t i = 0; i < num_alarms; ++i) {
|
||||
// Create a new message header and data to isolate each alarm information when
|
||||
// passing to the handle_create_fault function
|
||||
SFmMsgHdrT alarm_hdr = *hdr;
|
||||
alarm_hdr.msg_size = sizeof(SFmAlarmDataT);
|
||||
std::vector<char> alarm_data(sizeof(SFmMsgHdrT) + sizeof(SFmAlarmDataT));
|
||||
memcpy(alarm_data.data(), &alarm_hdr, sizeof(SFmMsgHdrT));
|
||||
memcpy(alarm_data.data() + sizeof(SFmMsgHdrT), &rdata[offset], sizeof(SFmAlarmDataT));
|
||||
|
||||
// We don't want for handle_create_fault to send any response back to the client or else it
|
||||
// will receive the response for the first call only, so we set send_response_flag to false
|
||||
handle_create_fault(fd, &alarm_hdr, alarm_data, sess, false);
|
||||
|
||||
if (alarm_hdr.msg_rc != FM_ERR_OK) {
|
||||
FM_ERROR_LOG("Failed to create fault entry %u, stopping processing", i);
|
||||
hdr->msg_rc = alarm_hdr.msg_rc;
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the offset to the next alarm
|
||||
offset += sizeof(SFmAlarmDataT);
|
||||
}
|
||||
|
||||
FM_INFO_LOG("Successfully processed all %u fault entries", num_alarms);
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_delete_faults(int fd,
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata, CFmDBSession &sess) {
|
||||
|
||||
@@ -585,7 +639,8 @@ void FmSocketServerProcessor::handle_delete_fault(
|
||||
int fd,
|
||||
SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata,
|
||||
CFmDBSession &sess) {
|
||||
CFmDBSession &sess,
|
||||
bool send_response_flag) {
|
||||
|
||||
CFmDbAlarmOperation op;
|
||||
sFmJobReq req;
|
||||
@@ -640,6 +695,60 @@ void FmSocketServerProcessor::handle_delete_fault(
|
||||
}
|
||||
}
|
||||
FM_INFO_LOG("Response to delete fault: %u\n", hdr->msg_rc);
|
||||
if (send_response_flag)
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_delete_fault_list(int fd,
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata, CFmDBSession &sess) {
|
||||
|
||||
// Validate the basic message size first
|
||||
// We cannot use is_request_valid because the size is variable based
|
||||
// on the number of entities, so we just verify if the sent size is a
|
||||
// multiple of sizeof(AlarmFilter)
|
||||
if (hdr->msg_size % sizeof(AlarmFilter) != 0) {
|
||||
FM_ERROR_LOG("Invalid message size: %u, expected multiple of %zu",
|
||||
hdr->msg_size, sizeof(AlarmFilter));
|
||||
hdr->msg_rc = FM_ERR_INVALID_REQ;
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t num_alarms = hdr->msg_size / sizeof(AlarmFilter);
|
||||
|
||||
FM_INFO_LOG("Processing delete fault list with %u entries", num_alarms);
|
||||
|
||||
size_t offset = sizeof(SFmMsgHdrT);
|
||||
|
||||
// Process each alarm entry
|
||||
for (uint32_t i = 0; i < num_alarms; ++i) {
|
||||
// Create a new message header and data to isolate each alarm information when
|
||||
// passing to the handle_delete_fault function
|
||||
SFmMsgHdrT alarm_hdr = *hdr;
|
||||
alarm_hdr.msg_size = sizeof(AlarmFilter);
|
||||
std::vector<char> alarm_data(sizeof(SFmMsgHdrT) + sizeof(AlarmFilter));
|
||||
memcpy(alarm_data.data(), &alarm_hdr, sizeof(SFmMsgHdrT));
|
||||
memcpy(alarm_data.data() + sizeof(SFmMsgHdrT), &rdata[offset], sizeof(AlarmFilter));
|
||||
|
||||
// We don't want for handle_delete_fault to send any response, so we set
|
||||
// send_response_flag to false
|
||||
handle_delete_fault(fd, &alarm_hdr, alarm_data, sess, false);
|
||||
|
||||
// Ignore FM_ERR_ENTITY_NOT_FOUND since an absent alarm doesn't raise API errors
|
||||
if (alarm_hdr.msg_rc != FM_ERR_OK &&
|
||||
alarm_hdr.msg_rc != FM_ERR_ENTITY_NOT_FOUND) {
|
||||
FM_ERROR_LOG("Failed to delete fault entry %u with rc %u, stopping processing",
|
||||
i, alarm_hdr.msg_rc);
|
||||
hdr->msg_rc = alarm_hdr.msg_rc;
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the offset to the next alarm
|
||||
offset += sizeof(AlarmFilter);
|
||||
}
|
||||
|
||||
FM_INFO_LOG("Successfully deleted all %u fault entries", num_alarms);
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -697,6 +806,8 @@ void FmSocketServerProcessor::handle_socket_data(int fd,
|
||||
case EFmGetFaults:handle_get_faults(fd,hdr,rdata); break;
|
||||
case EFmGetFaultsById:handle_get_faults_by_id(fd,hdr,rdata); break;
|
||||
case EFmGetFaultsByIdnEid:handle_get_faults_by_id_n_eid(fd,hdr,rdata); break;
|
||||
case EFmCreateFaultList:handle_create_fault_list(fd,hdr,rdata, sess); break;
|
||||
case EFmDeleteFaultList:handle_delete_fault_list(fd,hdr,rdata,sess); break;
|
||||
default:
|
||||
FM_ERROR_LOG("Unexpected client request, action:%u\n",hdr->action);
|
||||
break;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2014 Wind River Systems, Inc.
|
||||
// Copyright (c) 2014, 2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -19,9 +19,9 @@ protected:
|
||||
CFmDBSession &sess);
|
||||
|
||||
virtual void handle_create_fault(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata, CFmDBSession &sess);
|
||||
std::vector<char> &rdata, CFmDBSession &sess, bool send_response_flag = true);
|
||||
virtual void handle_delete_fault(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata, CFmDBSession &sess);
|
||||
std::vector<char> &rdata, CFmDBSession &sess, bool send_response_flag = true);
|
||||
virtual void handle_delete_faults(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata,CFmDBSession &sess);
|
||||
|
||||
@@ -33,6 +33,10 @@ protected:
|
||||
std::vector<char> &rdata);
|
||||
virtual void handle_get_faults_by_id_n_eid(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata);
|
||||
virtual void handle_create_fault_list(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata, CFmDBSession &sess);
|
||||
virtual void handle_delete_fault_list(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata,CFmDBSession &sess);
|
||||
public:
|
||||
void send_response(int fd, SFmMsgHdrT *hdr, void *data, size_t len);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2024 Wind River Systems, Inc.
|
||||
// Copyright (c) 2018, 2024-2025 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@@ -106,27 +106,27 @@ static PyObject * _fm_set_list(PyObject * self, PyObject *args) {
|
||||
structures, which are filled and sent to the C++ core. */
|
||||
|
||||
std::string alarm;
|
||||
fm_uuid_t tmp_uuid;
|
||||
PyObject *uuidList = PyList_New(0);
|
||||
EFmErrorT rc = FM_ERR_INVALID_REQ;
|
||||
|
||||
PyObject *listObj = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "O", &listObj)) {
|
||||
ERROR_LOG("Failed to parse args.");
|
||||
Py_RETURN_NONE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (!PyList_Check(listObj)) {
|
||||
ERROR_LOG("Expected a list.");
|
||||
Py_RETURN_NONE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
Py_ssize_t num_items = PyList_Size(listObj);
|
||||
std::vector<SFmAlarmDataT> alarms_vector;
|
||||
|
||||
for (Py_ssize_t i = 0; i < num_items; i++) {
|
||||
PyObject *item = PyList_GetItem(listObj, i);
|
||||
if (!PyUnicode_Check(item)) {
|
||||
ERROR_LOG("List items must be strings.");
|
||||
Py_RETURN_NONE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
const char *alm_str = PyUnicode_AsUTF8(item);
|
||||
@@ -137,25 +137,24 @@ static PyObject * _fm_set_list(PyObject * self, PyObject *args) {
|
||||
ERROR_LOG("Failed to convert string to alarm.");
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = fm_set_fault(&alm_data, &tmp_uuid);
|
||||
if (rc == FM_ERR_OK) {
|
||||
PyObject *uuidStr = PyUnicode_FromString(tmp_uuid);
|
||||
PyList_Append(uuidList, uuidStr);
|
||||
Py_DECREF(uuidStr);
|
||||
} else if (rc == FM_ERR_NOCONNECT) {
|
||||
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);
|
||||
}
|
||||
alarms_vector.push_back(alm_data);
|
||||
}
|
||||
|
||||
if (alarms_vector.empty()) {
|
||||
WARNING_LOG("No valid alarms to process.");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
rc = fm_set_fault_list(&alarms_vector);
|
||||
if (rc == FM_ERR_OK) {
|
||||
return uuidList;
|
||||
Py_RETURN_TRUE;
|
||||
} else if (rc == FM_ERR_NOCONNECT) {
|
||||
WARNING_LOG("Failed to connect to FM manager");
|
||||
} else {
|
||||
ERROR_LOG("Failed to set fault list, error code: %d", rc);
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyObject * _fm_get(PyObject * self, PyObject *args) {
|
||||
@@ -425,12 +424,60 @@ static PyObject * _fm_clear_all(PyObject * self, PyObject *args) {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyObject * _fm_clear_list(PyObject * self, PyObject *args) {
|
||||
|
||||
std::string alm_str, filter_str;
|
||||
EFmErrorT rc;
|
||||
|
||||
PyObject *listObj = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "O", &listObj)) {
|
||||
ERROR_LOG("Failed to parse args.");
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
Py_ssize_t num_items = PyList_Size(listObj);
|
||||
std::vector<AlarmFilter> alarms_vector;
|
||||
|
||||
for (Py_ssize_t i = 0; i < num_items; i++) {
|
||||
PyObject *item = PyList_GetItem(listObj, i);
|
||||
if (!PyUnicode_Check(item)) {
|
||||
ERROR_LOG("List items must be strings.");
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
const char *alm_str = PyUnicode_AsUTF8(item);
|
||||
|
||||
AlarmFilter af;
|
||||
if (!fm_alarm_filter_from_string(alm_str, &af)) {
|
||||
ERROR_LOG("Invalid alarm filter: (%s)", filter_str.c_str());
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
alarms_vector.push_back(af);
|
||||
}
|
||||
|
||||
rc = fm_clear_fault_list(&alarms_vector);
|
||||
if (rc == FM_ERR_OK) {
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
|
||||
if (rc == FM_ERR_ENTITY_NOT_FOUND) {
|
||||
DEBUG_LOG("No alarms found to clear from list");
|
||||
Py_RETURN_NONE;
|
||||
} else if (rc == FM_ERR_NOCONNECT) {
|
||||
WARNING_LOG("Failed to connect to FM manager");
|
||||
} else {
|
||||
ERROR_LOG("Failed to clear alarm list, error code: (%d)", 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"},
|
||||
{ "clear_list", _fm_clear_list, METH_VARARGS,
|
||||
"Clear alarms list 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,
|
||||
|
||||
Reference in New Issue
Block a user