From b2749e80c6a5ccb860b73b91c772b34ba251949d Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Mon, 21 Apr 2025 22:42:50 +0100 Subject: [PATCH 01/26] Local make customizations. --- sonic-slave-bookworm/Dockerfile.j2 | 6 ++++++ sonic-slave-bullseye/Dockerfile.j2 | 7 +++++++ sonic-slave-buster/Dockerfile.j2 | 11 +++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sonic-slave-bookworm/Dockerfile.j2 b/sonic-slave-bookworm/Dockerfile.j2 index 97f2959e3da..e3c2cc7ed42 100644 --- a/sonic-slave-bookworm/Dockerfile.j2 +++ b/sonic-slave-bookworm/Dockerfile.j2 @@ -516,6 +516,12 @@ RUN apt-get remove -y libnl-3-200 RUN eatmydata apt-get install -y libpcre3:$arch {%- endif %} + +# Add Dell CA +RUN wget --no-check-certificate -O /usr/local/share/ca-certificates/dellca2018-bundle.crt \ + https://nsdn.artifactory.cec.lab.emc.com/artifactory/sonic-dell-cert/dellca2018-bundle.crt \ + && update-ca-certificates + RUN eatmydata apt-get -y build-dep openssh # Build fix for ARM64 and ARMHF /etc/debian_version diff --git a/sonic-slave-bullseye/Dockerfile.j2 b/sonic-slave-bullseye/Dockerfile.j2 index acef2aa01ff..4279501a4d0 100644 --- a/sonic-slave-bullseye/Dockerfile.j2 +++ b/sonic-slave-bullseye/Dockerfile.j2 @@ -646,6 +646,13 @@ EXPOSE 22 RUN pip3 install parameterized==0.8.1 RUN pip3 install pyfakefs + +# Add Dell CA +RUN wget --no-check-certificate -O /usr/local/share/ca-certificates/dellca2018-bundle.crt \ + https://nsdn.artifactory.cec.lab.emc.com/artifactory/sonic-dell-cert/dellca2018-bundle.crt \ + && update-ca-certificates + + # Install docker engine 24 inside docker and enable experimental feature RUN apt-get update RUN eatmydata apt-get install -y \ diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 index 3acd9be01ab..c7ced00afb4 100644 --- a/sonic-slave-buster/Dockerfile.j2 +++ b/sonic-slave-buster/Dockerfile.j2 @@ -606,10 +606,6 @@ RUN cd /usr/src/gtest && cmake . && make -C /usr/src/gtest RUN mkdir /var/run/sshd EXPOSE 22 -# Install depot-tools (for git-retry) -RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools -ENV PATH /usr/share/depot_tools:$PATH - # Install dependencies for dhcp relay test RUN pip3 install parameterized==0.8.1 RUN pip3 install pyfakefs @@ -625,6 +621,13 @@ RUN eatmydata apt-get install -y \ {%- if CONFIGURED_ARCH == "armhf" %} RUN update-ca-certificates --fresh {%- endif %} + +RUN wget --no-check-certificate -O /usr/local/share/ca-certificates/dellca2018-bundle.crt https://nsdn.artifactory.cec.lab.emc.com/artifactory/sonic-dell-cert/dellca2018-bundle.crt && update-ca-certificates + +# Install depot-tools (for git-retry) +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools +ENV PATH /usr/share/depot_tools:$PATH + RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - RUN add-apt-repository \ {%- if CROSS_BUILD_ENVIRON == "y" %} From da9452a3753f26c67f1c4f700e2bc5c3cbda2ae0 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 24 Jan 2024 13:46:38 -0800 Subject: [PATCH 02/26] Support for event persistence in redis-db. --- .../docker-database/database_config.json.j2 | 6 + dockers/docker-eventd/supervisord.conf | 10 + files/build_templates/docker_image_ctl.j2 | 10 +- src/sonic-eventd/Makefile | 10 +- src/sonic-eventd/debian/sonic-eventd.install | 3 + src/sonic-eventd/etc/eventd.json | 5 + src/sonic-eventd/src/eventconsume.cpp | 684 ++++++++++++++++++ src/sonic-eventd/src/eventconsume.h | 50 ++ src/sonic-eventd/src/eventdb.cpp | 30 + src/sonic-eventd/src/eventutils.cpp | 80 ++ src/sonic-eventd/src/eventutils.h | 52 ++ src/sonic-eventd/src/loghandler.cpp | 37 + src/sonic-eventd/src/loghandler.h | 5 + src/sonic-eventd/var/evprofile/default.json | 12 + .../yang-models/sonic-events-common.yang | 41 ++ 15 files changed, 1033 insertions(+), 2 deletions(-) create mode 100644 src/sonic-eventd/etc/eventd.json create mode 100644 src/sonic-eventd/src/eventconsume.cpp create mode 100644 src/sonic-eventd/src/eventconsume.h create mode 100644 src/sonic-eventd/src/eventdb.cpp create mode 100644 src/sonic-eventd/src/eventutils.cpp create mode 100644 src/sonic-eventd/src/eventutils.h create mode 100755 src/sonic-eventd/src/loghandler.cpp create mode 100644 src/sonic-eventd/src/loghandler.h create mode 100644 src/sonic-eventd/var/evprofile/default.json diff --git a/dockers/docker-database/database_config.json.j2 b/dockers/docker-database/database_config.json.j2 index 0e8c6bc93b4..aa747ad812a 100644 --- a/dockers/docker-database/database_config.json.j2 +++ b/dockers/docker-database/database_config.json.j2 @@ -149,6 +149,12 @@ "instance" : "redis_bmp" } {% endif %} + , + "EVENT_DB" : { + "id" : 18, + "separator": "|", + "instance" : "redis" + } }, "VERSION" : "1.0" } diff --git a/dockers/docker-eventd/supervisord.conf b/dockers/docker-eventd/supervisord.conf index 7fbcced6d77..def9cdefaa8 100644 --- a/dockers/docker-eventd/supervisord.conf +++ b/dockers/docker-eventd/supervisord.conf @@ -56,3 +56,13 @@ stderr_syslog=true dependent_startup=true dependent_startup_wait_for=start:exited +[program:eventdb] +command=/usr/bin/eventdb +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index 84c643d5987..5bd2af95fcb 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -110,10 +110,18 @@ function preStartAction() else # Create an emtpy file and overwrite any RDB if already there echo -n > /tmp/dump.rdb - docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/ if [[ "$DATABASE_TYPE" != "bmcdb" ]]; then docker cp /tmp/dump.rdb database$DEV:/var/lib/redis_bmp/ fi + COLD_DIR=/host/coldboot + #In case of cold reboot, load redis content from /host/coldboot/dump.rdb + if [[ -f $COLD_DIR/dump.rdb ]]; then + #Load redis content from /host/coldboot/dump.rdb + docker cp $COLD_DIR/dump.rdb database$DEV:/var/lib/redis/dump.rdb + else + # Create an emtpy file and overwrite any RDB if already there + docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/ + fi fi fi {%- elif docker_container_name == "pde" %} diff --git a/src/sonic-eventd/Makefile b/src/sonic-eventd/Makefile index f907a3a14d1..b1797ec140d 100644 --- a/src/sonic-eventd/Makefile +++ b/src/sonic-eventd/Makefile @@ -1,5 +1,6 @@ RM := rm -rf EVENTD_TARGET := eventd +EVENTD_DB_TARGET := eventdb EVENTD_TEST := tests/tests EVENTD_TOOL := tools/events_tool EVENTD_PUBLISH_TOOL := tools/events_publish_tool.py @@ -7,6 +8,8 @@ RSYSLOG-PLUGIN_TARGET := rsyslog_plugin/rsyslog_plugin RSYSLOG-PLUGIN_TEST := rsyslog_plugin_tests/tests EVENTD_MONIT := tools/events_monit_test.py EVENTD_MONIT_CONF := tools/monit_events +EVENTD_DEFAULT_PROFILE := var/evprofile/default.json +EVENT_DB_PROF := etc/eventd.json CP := cp MKDIR := mkdir @@ -33,10 +36,11 @@ all: sonic-eventd eventd-tool rsyslog-plugin test: eventd-tests rsyslog-plugin-tests -sonic-eventd: $(OBJS) +sonic-eventd: $(OBJS) $(EVENTDB_OBJS) @echo 'Building target: $@' @echo 'Invoking: G++ Linker' $(CC) $(LDFLAGS) -o $(EVENTD_TARGET) $(OBJS) $(LIBS) + $(CC) $(LDFLAGS) -o $(EVENTD_DB_TARGET) $(EVENTDB_OBJS) $(LIBS) @echo 'Finished building target: $@' @echo ' ' @@ -75,12 +79,16 @@ rsyslog-plugin-tests: $(RSYSLOG-PLUGIN-TEST_OBJS) install: $(MKDIR) -p $(DESTDIR)/usr/bin $(MKDIR) -p $(DESTDIR)/etc/monit/conf.d + $(MKDIR) -p $(DESTDIR)/etc/evprofile $(CP) $(EVENTD_TARGET) $(DESTDIR)/usr/bin + $(CP) $(EVENTD_DB_TARGET) $(DESTDIR)/usr/bin $(CP) $(EVENTD_TOOL) $(DESTDIR)/usr/bin $(CP) $(EVENTD_PUBLISH_TOOL) $(DESTDIR)/usr/bin $(CP) $(RSYSLOG-PLUGIN_TARGET) $(DESTDIR)/usr/bin $(CP) $(EVENTD_MONIT) $(DESTDIR)/usr/bin $(CP) $(EVENTD_MONIT_CONF) $(DESTDIR)/etc/monit/conf.d + $(CP) $(EVENT_DB_PROF) $(DESTDIR)/etc/eventd.json + $(CP) $(EVENTD_DEFAULT_PROFILE) $(DESTDIR)/etc/evprofile/default.json deinstall: $(RM) -rf $(DESTDIR)/usr diff --git a/src/sonic-eventd/debian/sonic-eventd.install b/src/sonic-eventd/debian/sonic-eventd.install index bdba566c77b..273b07adf18 100644 --- a/src/sonic-eventd/debian/sonic-eventd.install +++ b/src/sonic-eventd/debian/sonic-eventd.install @@ -1,3 +1,6 @@ usr/bin/eventd +usr/bin/eventdb usr/bin/events_tool usr/bin/events_publish_tool.py +etc/evprofile/default.json +etc/eventd.json diff --git a/src/sonic-eventd/etc/eventd.json b/src/sonic-eventd/etc/eventd.json new file mode 100644 index 00000000000..ee441eb329f --- /dev/null +++ b/src/sonic-eventd/etc/eventd.json @@ -0,0 +1,5 @@ +{ + "__README__": "Specify size of event history table. Whichever limit is hit first, eventd wraps event history table around and deletes older records.", + "max-records": 40000, + "max-days": 30 +} diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp new file mode 100644 index 00000000000..4820512cc22 --- /dev/null +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -0,0 +1,684 @@ + +#include +#include +#include +#include +#include +#include "eventconsume.h" +#include "loghandler.h" +#include "eventutils.h" +#include "events_common.h" + + +using namespace std::chrono; + +// map to store sequence-id for alarms +unordered_map cal_lookup_map; + +// temporary map to hold merge of default map of events and any event profile +EventMap static_event_table; + +volatile bool g_run = true; +uint64_t seq_id = 0; +uint64_t PURGE_SECONDS = 86400; + +typedef pair pi; +priority_queue, greater > event_history_list; + +map SYSLOG_SEVERITY = { + {EVENT_SEVERITY_CRITICAL_STR, LOG_ALERT}, + {EVENT_SEVERITY_MAJOR_STR, LOG_CRIT}, + {EVENT_SEVERITY_MINOR_STR, LOG_ERR}, + {EVENT_SEVERITY_WARNING_STR, LOG_WARNING}, + {EVENT_SEVERITY_INFORMATIONAL_STR, LOG_NOTICE} +}; + +map SYSLOG_SEVERITY_STR = { + {LOG_ALERT , EVENT_SEVERITY_CRITICAL_STR}, + {LOG_CRIT , EVENT_SEVERITY_MAJOR_STR}, + {LOG_ERR , EVENT_SEVERITY_MINOR_STR}, + {LOG_WARNING , EVENT_SEVERITY_WARNING_STR}, + {LOG_NOTICE , EVENT_SEVERITY_INFORMATIONAL_STR} +}; + +static string flood_ev_id; +static string flood_ev_action; +static string flood_ev_resource; +static string flood_ev_msg; + +EventConsume::EventConsume(DBConnector *dbConn): + m_eventTable(dbConn, EVENT_HISTORY_TABLE_NAME), + m_alarmTable(dbConn, EVENT_CURRENT_ALARM_TABLE_NAME), + m_eventStatsTable(dbConn, EVENT_STATS_TABLE_NAME), + m_alarmStatsTable(dbConn, EVENT_ALARM_STATS_TABLE_NAME) { + + // open syslog connection + openSyslog(); + + // init stats + initStats(); + + // populate local queue of event histor table + read_events(); + + // read and apply eventd configuration files + // read eventd.json and apply it on history table. + // read default and custom profiles, build static_event_table + read_eventd_config(); + + SWSS_LOG_NOTICE("DONE WITH EventConsume constructor"); +} + +EventConsume::~EventConsume() { +} + +void EventConsume::run() +{ + SWSS_LOG_ENTER(); + int total_missed =0; + event_handle_t hsub; + hsub = events_init_subscriber(); + + while (true) { + event_receive_op_t evt; + map_str_str_t evtOp; + + int rc = event_receive(hsub, evt); + if (rc != 0) { + SWSS_LOG_ERROR("Failed to receive rc=%d", rc); + continue; + } + + total_missed += evt.missed_cnt; + //evtOp[evt.key] = t_map_to_str(evt.params); + handle_notification(evt); + } + + events_deinit_subscriber(hsub); + +} + +void EventConsume::read_eventd_config(bool read_all) { + // read manifest file for config options + if (read_all) { + read_config_and_purge(); + } + + // read from default map + static_event_table.clear(); + if (!parse(EVENTD_DEFAULT_MAP_FILE, static_event_table)) { + SWSS_LOG_ERROR("Can not initialize event map"); + closeSyslog(); + exit(0); + } + + SWSS_LOG_NOTICE("Event map is built as follows:"); + for (auto& x: static_event_table) { + SWSS_LOG_NOTICE(" %s (%s %s %s)", x.first.c_str(), x.second.severity.c_str(), x.second.enable.c_str(), x.second.static_event_msg.c_str()); + } +} + + +void EventConsume::handle_notification(const event_receive_op_t& evt) +{ + SWSS_LOG_ENTER(); + + string ev_id, ev_msg, ev_src, ev_act, ev_timestamp, ev_type("EVENT"), + ev_static_msg(""), ev_reckey; + string ev_sev = string(EVENT_SEVERITY_INFORMATIONAL_STR); + bool is_raise = false; + bool is_clear = false; + bool is_ack = false; + vector vec; + + fetchFieldValues(evt, vec, ev_id, ev_msg, ev_src, ev_act, ev_timestamp); + + // flood protection. If a rogue application sends same event repeatedly, throttle repeated instances of that event + if (isFloodedEvent(ev_src, ev_act, ev_id, ev_msg)) { + return; + } + + // get static info + if (!staticInfoExists(ev_id, ev_act, ev_sev, ev_static_msg, vec)) { + return; + } + + // increment save seq-id for the newly received event + uint64_t new_seq_id = seq_id + 1; + FieldValueTuple seqfv("id", to_string(new_seq_id)); + vec.push_back(seqfv); + + if (ev_act.length() > 0) + { + SWSS_LOG_DEBUG("ev_act %s", ev_act.c_str()); + ev_type = "ALARM"; + string almkey = ev_id; + if (!ev_src.empty()) + { + almkey += "|" + ev_src; + } + + if (ev_act.compare(EVENT_ACTION_RAISE_STR) == 0) + { + is_raise = true; + // add entry to the lookup map + cal_lookup_map.insert(make_pair(almkey, new_seq_id)); + + // add acknowledged field intializing it to false + FieldValueTuple seqfv1("acknowledged", "false"); + vec.push_back(seqfv1); + m_alarmTable.set(to_string(new_seq_id), vec); + + // update alarm counters + updateAlarmStatistics(ev_sev, ev_act); + } + else if (ev_act.compare(EVENT_ACTION_CLEAR_STR) == 0) + { + is_clear = true; + SWSS_LOG_DEBUG(" Received clear alarm for %s", almkey.c_str()); + + bool ack_flag = false; + // remove entry from local cache, alarm table + if (!udpateLocalCacheAndAlarmTable(almkey, ack_flag)) + { + SWSS_LOG_ERROR("Received clear for non-existent alarm %s", almkey.c_str()); + return; + } + + // update alarm counters ONLY if it has not been ack'd before. + // This is because when alarm is ack'd, alarms/severity counter is reduced already. + if (!ack_flag) + { + updateAlarmStatistics(ev_sev, ev_act); + } + else + { + // if it has been ack'd before, ack counter would have been incremented for this alrm. + // Now is the time reduce it. + clearAckAlarmStatistic(); + } + } + else + { + // ack/unack events comes with seq-id of raised alarm as resource field. + // fetch details of "raised" alarm record + string raise_act; + string raise_ack_flag; + string raise_ts; + + // fetch information from raised event record + if (!fetchRaiseInfo(vec, ev_src, ev_id, ev_sev, raise_act, raise_ack_flag, raise_ts)) + { + SWSS_LOG_ERROR("Action %s on a non-existent Alarm id %s", ev_act.c_str(), ev_src.c_str()); + return; + } + + if (ev_act.compare(EVENT_ACTION_ACK_STR) == 0) + { + if (raise_ack_flag.compare("true") == 0) + { + SWSS_LOG_INFO("%s/%s is already acknowledged", ev_id.c_str(), ev_src.c_str()); + return; + } + if (raise_act.compare(EVENT_ACTION_RAISE_STR) == 0) + { + is_ack = true; + SWSS_LOG_DEBUG("Received acknowledge event - %s/%s", ev_id.c_str(), ev_src.c_str()); + + // update the record with ack flag and ack-time and stats + updateAckInfo(is_ack, ev_timestamp, ev_sev, ev_act, ev_src); + } + else + { + SWSS_LOG_ERROR("Alarm %s/%s not in RAISE state", ev_id.c_str(), ev_src.c_str()); + return; + } + } + else if (ev_act.compare(EVENT_ACTION_UNACK_STR) == 0) + { + if (raise_ack_flag.compare("true") == 0) + { + SWSS_LOG_DEBUG(" received un-ACKnowledge event - %s/%s", ev_id.c_str(), ev_src.c_str()); + + // update the record with ack flag and ack-time and stats + updateAckInfo(is_ack, ev_timestamp, ev_sev, ev_act, ev_src); + } + else + { + SWSS_LOG_INFO(" %s/%s is already un-acknowledged", ev_id.c_str(), ev_src.c_str()); + return; + } + } + } + } + // verify the size of history table; delete older entry; add new entry + seq_id = new_seq_id; + update_events(to_string(seq_id), ev_timestamp, vec); + + updateEventStatistics(true, is_raise, is_ack, is_clear); + + // raise a syslog message + writeToSyslog(ev_id, (int)(SYSLOG_SEVERITY.find(ev_sev)->second), ev_type, ev_act, ev_msg, ev_static_msg); + + return; +} + +void EventConsume::read_events() { + vector tuples; + m_eventTable.getContent(tuples); + + SWSS_LOG_ENTER(); + // find out last sequence-id; build local history list + for (auto tuple: tuples) { + for (auto fv: kfvFieldsValues(tuple)) { + if (fvField(fv) == "time-created") { + char* end; + uint64_t seq = strtoull(kfvKey(tuple).c_str(), &end,10); + if (seq > seq_id) { + seq_id = seq; + } + uint64_t val = strtoull(fvValue(fv).c_str(), &end,10); + event_history_list.push(make_pair( seq, val )); + } + } + } + SWSS_LOG_NOTICE("eventd sequence-id intialized to %lu", seq_id); +} + +void EventConsume::updateAlarmStatistics(string ev_sev, string ev_act) { + vector vec; + vector temp; + + // severity counter names are of lower case + transform(ev_sev.begin(), ev_sev.end(), ev_sev.begin(), ::tolower); + + if (m_alarmStatsTable.get("state", vec)) { + for (auto fv: vec) { + if (!fv.first.compare("alarms")) { + if ((ev_act.compare(EVENT_ACTION_RAISE_STR) == 0) || (ev_act.compare(EVENT_ACTION_UNACK_STR) == 0)) { + fv.second = to_string(stoi(fv.second.c_str())+1); + } else { + fv.second = to_string(stoi(fv.second.c_str())-1); + } + temp.push_back(fv); + } else if (!fv.first.compare(ev_sev)) { + if ((ev_act.compare(EVENT_ACTION_RAISE_STR) == 0) || (ev_act.compare(EVENT_ACTION_UNACK_STR) == 0)) { + fv.second = to_string(stoi(fv.second.c_str())+1); + } else { + fv.second = to_string(stoi(fv.second.c_str())-1); + } + temp.push_back(fv); + } else if (!fv.first.compare("acknowledged")) { + if (ev_act.compare(EVENT_ACTION_ACK_STR) == 0) { + fv.second = to_string(stoi(fv.second.c_str())+1); + } else if (ev_act.compare(EVENT_ACTION_UNACK_STR) == 0) { + fv.second = to_string(stoi(fv.second.c_str())-1); + } + temp.push_back(fv); + } + } + m_alarmStatsTable.set("state", temp); + } else { + SWSS_LOG_ERROR("Can not update alarm statistics (table does not exist)"); + } +} + +void EventConsume::updateEventStatistics(bool is_add, bool is_raise, bool is_ack, bool is_clear) { + vector vec; + vector temp; + + if (m_eventStatsTable.get("state", vec)) { + for (auto fv: vec) { + if (!fv.first.compare("events")) { + if (is_add) { + fv.second = to_string(stoi(fv.second.c_str())+1); + } else { + fv.second = to_string(stoi(fv.second.c_str())-1); + } + temp.push_back(fv); + } else if (!fv.first.compare("raised")) { + if (is_raise) { + if (is_add) { + fv.second = to_string(stoi(fv.second.c_str())+1); + } else { + fv.second = to_string(stoi(fv.second.c_str())-1); + } + temp.push_back(fv); + } + } else if (!fv.first.compare("cleared")) { + if (is_clear) { + if (is_add) { + fv.second = to_string(stoi(fv.second.c_str())+1); + } else { + fv.second = to_string(stoi(fv.second.c_str())-1); + } + temp.push_back(fv); + } + } else if (!fv.first.compare("acked")) { + if (is_ack) { + if (is_add) { + fv.second = to_string(stoi(fv.second.c_str())+1); + } else { + fv.second = to_string(stoi(fv.second.c_str())-1); + } + temp.push_back(fv); + } + } + } + + m_eventStatsTable.set("state", temp); + } else { + SWSS_LOG_ERROR("Can not update event statistics (table does not exist)"); + } +} + +void EventConsume::modifyEventStats(string seq_id) { + vector rec; + m_eventTable.get(seq_id, rec); + bool is_raise = false; + bool is_clear = false; + bool is_ack = false; + for (auto fvr: rec) { + if (!fvr.first.compare("action")) { + if (!fvr.second.compare(EVENT_ACTION_RAISE_STR)) { + is_raise = true; + } else if (!fvr.second.compare(EVENT_ACTION_CLEAR_STR)) { + is_clear = true; + } + } + if (!fvr.first.compare("acknowledged")) { + if (!fvr.second.compare("true")) { + is_ack = true; + } + } + } + updateEventStatistics(false, is_raise, is_ack, is_clear); +} + +void EventConsume::purge_events() { + SWSS_LOG_ENTER(); + uint32_t size = event_history_list.size(); + + while (size >= count) { + pair oldest_entry = event_history_list.top(); + SWSS_LOG_NOTICE("Rollover based on count(%d/%d). Deleting %lu", size, count, oldest_entry.first); + m_eventTable.del(to_string(oldest_entry.first)); + modifyEventStats(to_string(oldest_entry.first)); + event_history_list.pop(); + --size; + } + + const auto p1 = system_clock::now(); + unsigned tnow_seconds = duration_cast(p1.time_since_epoch()).count(); + + while (!event_history_list.empty()) { + pair oldest_entry = event_history_list.top(); + unsigned old_seconds = oldest_entry.second / 1000000000ULL; + + if ((tnow_seconds - old_seconds) > PURGE_SECONDS) { + SWSS_LOG_NOTICE("Rollover based on time (%lu days). Deleting %lu.. now %u old %u", (PURGE_SECONDS/days), oldest_entry.second, tnow_seconds, old_seconds); + m_eventTable.del(to_string(oldest_entry.first)); + modifyEventStats(to_string(oldest_entry.first)); + event_history_list.pop(); + } else { + return; + } + } + return; +} + +void EventConsume::read_config_and_purge() { + days = 0; + count = 0; + // read from the manifest file + parse_config(EVENTD_CONF_FILE, days, count); + SWSS_LOG_NOTICE("max-days %d max-records %d", days, count); + + // update the nanosecond limit + PURGE_SECONDS *= days; + + // purge events based on # of days + purge_events(); +} + +void EventConsume::update_events(string seq_id, string ts, vector vec) { + // purge events based on # of days + purge_events(); + + // now add the event to the event table + m_eventTable.set(seq_id, vec); + + // store it into the event history list + char* end; + uint64_t seq = strtoull(seq_id.c_str(), &end, 10); + uint64_t val = strtoull(ts.c_str(), &end, 10); + event_history_list.push(make_pair( seq, val )); +} + +void EventConsume::resetAlarmStats(int alarms, int critical, int major, int minor, int warning, int acknowledged) { + vector temp; + FieldValueTuple fv; + map::iterator it; + for (it = SYSLOG_SEVERITY_STR.begin(); it != SYSLOG_SEVERITY_STR.end(); it++) { + // there wont be any informational alarms + if (it->second.compare(EVENT_SEVERITY_CRITICAL_STR) == 0) { + fv = FieldValueTuple("critical", to_string(critical)); + temp.push_back(fv); + } else if (it->second.compare(EVENT_SEVERITY_MAJOR_STR) == 0) { + fv = FieldValueTuple("major", to_string(major)); + temp.push_back(fv); + } else if (it->second.compare(EVENT_SEVERITY_MINOR_STR) == 0) { + fv = FieldValueTuple("minor", to_string(minor)); + temp.push_back(fv); + } else if (it->second.compare(EVENT_SEVERITY_WARNING_STR) == 0) { + fv = FieldValueTuple("warning", to_string(warning)); + temp.push_back(fv); + } + } + fv = FieldValueTuple("alarms", to_string(alarms)); + temp.push_back(fv); + fv = FieldValueTuple("acknowledged", to_string(acknowledged)); + temp.push_back(fv); + m_alarmStatsTable.set("state", temp); +} + +void EventConsume::clearAckAlarmStatistic() { + vector vec; + vector temp; + + if (m_alarmStatsTable.get("state", vec)) { + for (auto fv: vec) { + if (!fv.first.compare("acknowledged")) { + fv.second = to_string(stoi(fv.second.c_str())-1); + temp.push_back(fv); + m_alarmStatsTable.set("state", temp); + return; + } + } + } +} + + +void EventConsume::fetchFieldValues(const event_receive_op_t& evt, + vector& vec, + string& ev_id, + string& ev_msg, + string& ev_src, + string& ev_act, + string &ev_timestamp) { + + ev_timestamp = to_string(evt.publish_epoch_ms); + vec.push_back(FieldValueTuple("time-created", ev_timestamp)); + for (const auto& idx : evt.params) { + if (idx.first == "type-id") { + ev_id = idx.second; + vec.push_back(FieldValueTuple("type-id", ev_id)); + SWSS_LOG_DEBUG("type-id: <%s> ", ev_id.c_str()); + } else if (idx.first == "text") { + ev_msg = idx.second; + vec.push_back(FieldValueTuple("text", ev_msg)); + SWSS_LOG_DEBUG("text: <%s> ", ev_msg.c_str()); + } else if (idx.first == "resource") { + ev_src = idx.second; + vec.push_back(idx); + SWSS_LOG_DEBUG("resource: <%s> ", ev_src.c_str()); + } else if (idx.first == "action") { + ev_act = idx.second; + // for events, action is empty + if (!ev_act.empty()) { + vec.push_back(FieldValueTuple("action", ev_act)); + } + } + } +} + +bool EventConsume::isFloodedEvent(string ev_src, string ev_act, string ev_id, string ev_msg) { + // flood protection. If a rogue application sends same event repeatedly, throttle repeated instances of that event + if (!flood_ev_resource.compare(ev_src) && + !flood_ev_action.compare(ev_act) && + !flood_ev_id.compare(ev_id) && + !(flood_ev_msg.compare(ev_msg))) { + SWSS_LOG_INFO("Ignoring the event %s from %s action %s msg %s as it is repeated", ev_id.c_str(), ev_src.c_str(), ev_act.c_str(), ev_msg.c_str()); + return true; + } + + flood_ev_resource = ev_src; + flood_ev_action = ev_act; + flood_ev_id = ev_id; + flood_ev_msg = ev_msg; + return false; +} + +bool EventConsume::staticInfoExists(string &ev_id, string &ev_act, string &ev_sev, string &ev_static_msg, vector &vec) { + auto it = static_event_table.find(ev_id); + if (it != static_event_table.end()) { + EventInfo tmp = (EventInfo) (it->second); + // discard the event as event_static_map shows enable is false for this event + if (tmp.enable == EVENT_ENABLE_FALSE_STR) { + SWSS_LOG_NOTICE("Discarding event <%s> as it is set to disabled", ev_id.c_str()); + return false;; + } + + // get severity in the map and store it in the db + ev_sev = tmp.severity; + ev_static_msg = tmp.static_event_msg; + SWSS_LOG_DEBUG("static info: <%s> <%s> ", tmp.severity.c_str(), tmp.static_event_msg.c_str()); + + FieldValueTuple seqfv1("severity", tmp.severity); + vec.push_back(seqfv1); + return true; + } else { + // dont process the incoming alarms if action is neither raise nor clear + // for ack/unack, no need for this check + if ((ev_act.compare(EVENT_ACTION_ACK_STR) && ev_act.compare(EVENT_ACTION_UNACK_STR))) { + // TODO currently, applications may raise events but default evprofile doesnt contain + // ID info. This is planned for later. + // Change it back to SWSS_LOG_ERROR once event profile contains event-ids + SWSS_LOG_DEBUG("static info NOT FOUND for <%s> ", ev_id.c_str()); + return false; + } + } + return true; +} + +bool EventConsume::udpateLocalCacheAndAlarmTable(string almkey, bool &ack_flag) { + // find and remove the raised alarm + uint64_t lookup_seq_id = 0; + auto it = cal_lookup_map.find(almkey); + if (it != cal_lookup_map.end()) { + lookup_seq_id = (uint64_t) (it->second); + cal_lookup_map.erase(almkey); + + // get status of is_aknowledged flag so that we dont decrement counters twice + vector alm_rec; + m_alarmTable.get(to_string(lookup_seq_id), alm_rec); + for (auto fvr: alm_rec) { + if (!fvr.first.compare("acknowledged")) { + ack_flag = (fvr.second.compare("true") == 0) ? true : false; + break; + } + } + + // delete the record from alarm table + m_alarmTable.del(to_string(lookup_seq_id)); + } else { + // possible - when event profile removes alarms for which enable is false and application cleared them later. + // ignore by logging a debug message.. + SWSS_LOG_INFO("Received alarm-clear for non-existing alarm %s", almkey.c_str()); + return false; + } + return true; +} + +void EventConsume::initStats() { + vector vec; + // possible after a cold-boot or very first time + if (! m_eventStatsTable.get("state", vec)) { + FieldValueTuple fv; + vector temp; + + SWSS_LOG_DEBUG("resetting Event Statistics table"); + fv = FieldValueTuple("events", to_string(0)); + temp.push_back(fv); + fv = FieldValueTuple("raised", to_string(0)); + temp.push_back(fv); + fv = FieldValueTuple("cleared", to_string(0)); + temp.push_back(fv); + fv = FieldValueTuple("acked", to_string(0)); + temp.push_back(fv); + m_eventStatsTable.set("state", temp); + } + if (! m_alarmStatsTable.get("state", vec)) { + SWSS_LOG_DEBUG("resetting Alarm Statistics table"); + resetAlarmStats(0, 0, 0, 0, 0, 0); + } +} + +void EventConsume::updateAckInfo(bool is_ack, string ev_timestamp, string ev_sev, string ev_act, string ev_src) { + vector ack_vec; + + FieldValueTuple seqfv1("acknowledged", (is_ack ? "true" : "false")); + ack_vec.push_back(seqfv1); + + FieldValueTuple seqfv2("acknowledge-time", ev_timestamp); + ack_vec.push_back(seqfv2); + + // update alarm stats + updateAlarmStatistics(ev_sev, ev_act); + + // update alarm/event tables for the "raise" record with ack flag and ack timestamp + // for ack/unack, ev_src contains the "seq-id" + m_alarmTable.set(ev_src, ack_vec); + m_eventTable.set(ev_src, ack_vec); +} + + +bool EventConsume::fetchRaiseInfo(vector &vec, string ev_src, string &ev_id, string &ev_sev, string &raise_act, + string &raise_ack_flag, string &raise_ts) { + vector raise_vec; + if (!m_alarmTable.get(ev_src, raise_vec)) { + return false; + } + for (auto fv: raise_vec) { + if (!fv.first.compare("type-id")) { + ev_id = fv.second; + vec.push_back(fv); + } + if (!fv.first.compare("severity")) { + ev_sev = fv.second; + vec.push_back(fv); + } + if (!fv.first.compare("action")) { + raise_act = fv.second; + } + if (!fv.first.compare("acknowledged")) { + raise_ack_flag = fv.second; + } + if (!fv.first.compare("time-created")) { + raise_ts = fv.second; + } + } + return true; +} + + diff --git a/src/sonic-eventd/src/eventconsume.h b/src/sonic-eventd/src/eventconsume.h new file mode 100644 index 00000000000..bdac8c68186 --- /dev/null +++ b/src/sonic-eventd/src/eventconsume.h @@ -0,0 +1,50 @@ +#ifndef __EVENTCONSUME_H__ +#define __EVENTCONSUME_H__ + +#include +#include +#include +#include "events.h" +#include "dbconnector.h" +#include "subscriberstatetable.h" + +using namespace swss; +using namespace std; + +class EventConsume +{ +public: + EventConsume(DBConnector *dbConn); + ~EventConsume(); + void read_eventd_config(bool read_all=true); + void run(); + +private: + Table m_eventTable; + Table m_alarmTable; + Table m_eventStatsTable; + Table m_alarmStatsTable; + u_int32_t days, count; + + void handle_notification(const event_receive_op_t& evt); + void read_events(); + void updateAlarmStatistics(string ev_sev, string ev_act); + void updateEventStatistics(bool is_add, bool is_alarm, bool is_ack, bool is_clear); + void read_config_and_purge(); + void update_events(string seq_id, string ts, vector vec); + void purge_events(); + void modifyEventStats(string seq_id); + void clearAckAlarmStatistic(); + void resetAlarmStats(int, int, int, int, int, int); + void fetchFieldValues(const event_receive_op_t& evt , vector &, string &, string &, string &, string &, string &); + bool isFloodedEvent(string, string, string, string); + bool staticInfoExists(string &, string &, string &, string &, vector &); + bool udpateLocalCacheAndAlarmTable(string, bool &); + void initStats(); + void updateAckInfo(bool, string, string, string, string); + bool fetchRaiseInfo(vector &, string, string &, string &, string &, string &, string &); +}; + + +#endif /* __EVENTCONSUME_H__ */ + diff --git a/src/sonic-eventd/src/eventdb.cpp b/src/sonic-eventd/src/eventdb.cpp new file mode 100644 index 00000000000..9b162416bf3 --- /dev/null +++ b/src/sonic-eventd/src/eventdb.cpp @@ -0,0 +1,30 @@ +#include "eventconsume.h" +#include + +static EventConsume *evtd_instance = NULL; + +void signalHandler(const int signal) { + SWSS_LOG_NOTICE("in signalHandler"); + + if (signal == SIGINT) { + evtd_instance->read_eventd_config(); + } +} + +int main() +{ + swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); + + swss::DBConnector eventDb("EVENT_DB", 0); + + // register signal SIGINT and signal handler + signal(SIGINT, signalHandler); + + EventConsume evtd(&eventDb); + evtd_instance = &evtd; + + evtd.run(); + + return 0; +} + diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp new file mode 100644 index 00000000000..5e8f097f597 --- /dev/null +++ b/src/sonic-eventd/src/eventutils.cpp @@ -0,0 +1,80 @@ +#include "eventutils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "json.h" +#include + + +using namespace swss; +using json = nlohmann::json; + +bool isValidSeverity(string severityStr) { + transform(severityStr.begin(), severityStr.end(), severityStr.begin(), ::toupper); + if (severityStr == EVENT_SEVERITY_MAJOR_STR) return true; + if (severityStr == EVENT_SEVERITY_CRITICAL_STR) return true; + if (severityStr == EVENT_SEVERITY_MINOR_STR) return true; + if (severityStr == EVENT_SEVERITY_WARNING_STR) return true; + if (severityStr == EVENT_SEVERITY_INFORMATIONAL_STR) return true; + return false; +} + +bool isValidEnable(string enableStr) { + if (enableStr == EVENT_ENABLE_TRUE_STR) return true; + if (enableStr == EVENT_ENABLE_FALSE_STR) return true; + return false; +} + +bool parse_config(const char *filename, unsigned int& days, unsigned int& count) { + days = EHT_MAX_DAYS; + count = EHT_MAX_ELEMS; + std::ifstream ifs(filename); + json j = json::parse(ifs); + for (json::iterator it = j.begin(); it != j.end(); ++it) { + if(it.key() == "max-days") { + days = it.value(); + } + if(it.key() == "max-records") { + count = it.value(); + } + } + return true; +} + +bool parse(const char *filename, EventMap& tmp_event_table) { + ifstream fs(filename); + if (!fs.is_open()) { + return false; + } + + fstream file(filename, fstream::in); + json j; + file >> j; + + if (j["events"].size() == 0) { + SWSS_LOG_ERROR("No entries in 'events' field in %s", filename); + return false; + } + + for (size_t i = 0; i < j["events"].size(); i++) { + auto elem = j["events"][i]; + struct EventInfo_t ev_info; + string ev_name = elem["name"]; + ev_info.severity = elem["severity"]; + ev_info.enable = elem["enable"]; + ev_info.static_event_msg = elem["message"]; + tmp_event_table.emplace(ev_name, ev_info); + } + + return true; +} + diff --git a/src/sonic-eventd/src/eventutils.h b/src/sonic-eventd/src/eventutils.h new file mode 100644 index 00000000000..7f0a98bb77c --- /dev/null +++ b/src/sonic-eventd/src/eventutils.h @@ -0,0 +1,52 @@ +#ifndef __EVENTUTILS_H__ +#define __EVENTUTILS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +const string EVENT_SEVERITY_CRITICAL_STR = "CRITICAL"; +const string EVENT_SEVERITY_MAJOR_STR = "MAJOR"; +const string EVENT_SEVERITY_MINOR_STR = "MINOR"; +const string EVENT_SEVERITY_WARNING_STR = "WARNING"; +const string EVENT_SEVERITY_INFORMATIONAL_STR = "INFORMATIONAL"; + +const string EVENT_ENABLE_TRUE_STR = "true"; +const string EVENT_ENABLE_FALSE_STR = "false"; + +const string EVENT_ACTION_RAISE_STR = "RAISE"; +const string EVENT_ACTION_CLEAR_STR = "CLEAR"; +const string EVENT_ACTION_ACK_STR = "ACKNOWLEDGE"; +const string EVENT_ACTION_UNACK_STR = "UNACKNOWLEDGE"; + +constexpr char EVENTD_DEFAULT_MAP_FILE[] = "/etc/evprofile/default.json"; + +constexpr size_t EHT_MAX_ELEMS = 40000; +constexpr size_t EHT_MAX_DAYS = 30; +constexpr char EVENTD_CONF_FILE[] = "/etc/eventd.json"; + +typedef struct EventInfo_t { + string severity; + string enable; + string static_event_msg; +} EventInfo; + +//unordered_map static_event_table; +typedef unordered_map EventMap; + +bool isValidSeverity(string severityStr); +bool isValidEnable(string enableStr); +bool parse_config(const char *filename, unsigned int& days, unsigned int& count); +bool parse(const char *filename, EventMap& tmp_event_table); + +#endif diff --git a/src/sonic-eventd/src/loghandler.cpp b/src/sonic-eventd/src/loghandler.cpp new file mode 100755 index 00000000000..d560ccc2e0e --- /dev/null +++ b/src/sonic-eventd/src/loghandler.cpp @@ -0,0 +1,37 @@ +#include +#include + +extern "C" void openSyslog() { + openlog (NULL, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL4); +} + +extern "C" void writeToSyslog(std::string ev_id, int ev_sev, std::string ev_type, std::string ev_act, std::string ev_msg, std::string ev_static_msg) { + int SYSLOG_FACILITY = LOG_LOCAL4; + if (ev_act.empty()) { + const char LOG_FORMAT[] = "[%s], %%%s: %s %s"; + // event Type + // Event Name + // Static Desc + // Dynamic Desc + + // raise a syslog message + syslog(LOG_MAKEPRI(ev_sev, SYSLOG_FACILITY), LOG_FORMAT, + ev_type.c_str(), + ev_id.c_str(), ev_static_msg.c_str(), ev_msg.c_str()); + } else { + const char LOG_FORMAT[] = "[%s] (%s), %%%s: %s %s"; + // event Type + // event action + // Event Name + // Static Desc + // Dynamic Desc + // raise a syslog message + syslog(LOG_MAKEPRI(ev_sev, SYSLOG_FACILITY), LOG_FORMAT, + ev_type.c_str(), ev_act.c_str(), + ev_id.c_str(), ev_static_msg.c_str(), ev_msg.c_str()); + } +} + +extern "C" void closeSyslog() { + closelog (); +} diff --git a/src/sonic-eventd/src/loghandler.h b/src/sonic-eventd/src/loghandler.h new file mode 100644 index 00000000000..1e98a940152 --- /dev/null +++ b/src/sonic-eventd/src/loghandler.h @@ -0,0 +1,5 @@ +#include +extern "C" void openSyslog(); +extern "C" void writeToSyslog(std::string ev_id, int ev_sev, std::string ev_type, std::string ev_act, std::string ev_msg, std::string ev_static_msg); +extern "C" void closeSyslog(); + diff --git a/src/sonic-eventd/var/evprofile/default.json b/src/sonic-eventd/var/evprofile/default.json new file mode 100644 index 00000000000..7b937b7de3f --- /dev/null +++ b/src/sonic-eventd/var/evprofile/default.json @@ -0,0 +1,12 @@ +{ + "__README__" : "This is default map of events that eventd uses. Developer can modify this file and send SIGINT to eventd to make it read and use the updated file. Alternatively developer can test the new event by adding it to a custom event profile and use 'event profile ' command to apply that profile without having to send SIGINT to eventd. Developer need to commit default.json file with the new event after testing it out. Supported severities are: CRITICAL, MAJOR, MINOR, WARNING and INFORMATIONAL. Supported enable flag values are: true and false.", + "events":[ + { + "name" : "LICENSE_STATE", + "severity" : "WARNING", + "enable" : "true", + "message" : "License State changed -" + } + ] +} + \ No newline at end of file diff --git a/src/sonic-yang-models/yang-models/sonic-events-common.yang b/src/sonic-yang-models/yang-models/sonic-events-common.yang index ed6c81a7b90..a9ebb1b3cea 100644 --- a/src/sonic-yang-models/yang-models/sonic-events-common.yang +++ b/src/sonic-yang-models/yang-models/sonic-events-common.yang @@ -21,11 +21,52 @@ module sonic-events-common { "Common reusable definitions"; } + typedef action-type { + type enumeration { + enum RAISE { + description "Event with raise alarm action."; + } + enum CLEAR { + description "Event with clear alarm action."; + } + enum ACKNOWLEDGE { + description "Event with ack alarm action."; + } + enum UNACKNOWLEDGE { + description "Event with unacknowledge alarm action."; + } + } + description + "This type defines the actions associated with an event notification."; + } + grouping sonic-events-cmn { leaf timestamp { type yang:date-and-time; description "time of the event"; } + leaf type-id { + type string; + description + "The abbreviated name of the event, for example FAN_SPEED_STATUS, + SYSTEM_STATUS, or PSU_FAULTY.; + } + + leaf text { + type string; + description + "The string used to inform operators about the event. This + MUST contain enough information for an operator to be able + to understand the problem. If this string contains structure, + this format should be clearly documented for programs to be + able to parse that information"; + } + + leaf action { + type action-type; + description + "This denotes the action associated with the event."; + } } grouping sonic-events-usage { From 9b8ba37b1d3939b5ec9567efd19e4d4217b304d2 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:58:59 -0800 Subject: [PATCH 03/26] Updates --- src/sonic-eventd/src/eventutils.cpp | 8 -------- src/sonic-eventd/src/eventutils.h | 9 --------- 2 files changed, 17 deletions(-) diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp index 5e8f097f597..eb634350a3f 100644 --- a/src/sonic-eventd/src/eventutils.cpp +++ b/src/sonic-eventd/src/eventutils.cpp @@ -1,17 +1,9 @@ #include "eventutils.h" #include #include -#include #include -#include #include -#include -#include #include -#include -#include -#include -//#include "json.h" #include diff --git a/src/sonic-eventd/src/eventutils.h b/src/sonic-eventd/src/eventutils.h index 7f0a98bb77c..8ec6d39558b 100644 --- a/src/sonic-eventd/src/eventutils.h +++ b/src/sonic-eventd/src/eventutils.h @@ -2,16 +2,7 @@ #define __EVENTUTILS_H__ #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include using namespace std; From fc8904264323d89bc683d1434016d24423a990f9 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:21:29 -0800 Subject: [PATCH 04/26] Updates including fix to eventdb in test enviroment. --- src/sonic-eventd/Makefile | 16 ++++++------ src/sonic-eventd/src/eventconsume.cpp | 26 +++++++++++-------- src/sonic-eventd/src/eventconsume.h | 10 ++++--- src/sonic-eventd/src/eventutils.cpp | 4 +++ src/sonic-eventd/src/subdir.mk | 3 ++- src/sonic-eventd/var/evprofile/default.json | 7 +---- .../yang-models/sonic-events-common.yang | 8 +++++- 7 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/sonic-eventd/Makefile b/src/sonic-eventd/Makefile index b1797ec140d..acb226ed0f3 100644 --- a/src/sonic-eventd/Makefile +++ b/src/sonic-eventd/Makefile @@ -1,6 +1,5 @@ RM := rm -rf EVENTD_TARGET := eventd -EVENTD_DB_TARGET := eventdb EVENTD_TEST := tests/tests EVENTD_TOOL := tools/events_tool EVENTD_PUBLISH_TOOL := tools/events_publish_tool.py @@ -8,8 +7,9 @@ RSYSLOG-PLUGIN_TARGET := rsyslog_plugin/rsyslog_plugin RSYSLOG-PLUGIN_TEST := rsyslog_plugin_tests/tests EVENTD_MONIT := tools/events_monit_test.py EVENTD_MONIT_CONF := tools/monit_events -EVENTD_DEFAULT_PROFILE := var/evprofile/default.json -EVENT_DB_PROF := etc/eventd.json +EVENTDB_TARGET := eventdb +EVENTDB_DEFAULT_PROFILE := var/evprofile/default.json +EVENTDB_PROF := etc/eventd.json CP := cp MKDIR := mkdir @@ -22,7 +22,7 @@ PWD := $(shell pwd) ifneq ($(MAKECMDGOALS),clean) ifneq ($(strip $(C_DEPS)),) --include $(C_DEPS) $(OBJS) +-include $(C_DEPS) $(OBJS) $(EVENTDB_OBJS) endif endif @@ -40,7 +40,7 @@ sonic-eventd: $(OBJS) $(EVENTDB_OBJS) @echo 'Building target: $@' @echo 'Invoking: G++ Linker' $(CC) $(LDFLAGS) -o $(EVENTD_TARGET) $(OBJS) $(LIBS) - $(CC) $(LDFLAGS) -o $(EVENTD_DB_TARGET) $(EVENTDB_OBJS) $(LIBS) + $(CC) $(LDFLAGS) -o $(EVENTDB_TARGET) $(EVENTDB_OBJS) $(LIBS) @echo 'Finished building target: $@' @echo ' ' @@ -81,14 +81,14 @@ install: $(MKDIR) -p $(DESTDIR)/etc/monit/conf.d $(MKDIR) -p $(DESTDIR)/etc/evprofile $(CP) $(EVENTD_TARGET) $(DESTDIR)/usr/bin - $(CP) $(EVENTD_DB_TARGET) $(DESTDIR)/usr/bin $(CP) $(EVENTD_TOOL) $(DESTDIR)/usr/bin $(CP) $(EVENTD_PUBLISH_TOOL) $(DESTDIR)/usr/bin $(CP) $(RSYSLOG-PLUGIN_TARGET) $(DESTDIR)/usr/bin $(CP) $(EVENTD_MONIT) $(DESTDIR)/usr/bin $(CP) $(EVENTD_MONIT_CONF) $(DESTDIR)/etc/monit/conf.d - $(CP) $(EVENT_DB_PROF) $(DESTDIR)/etc/eventd.json - $(CP) $(EVENTD_DEFAULT_PROFILE) $(DESTDIR)/etc/evprofile/default.json + $(CP) $(EVENTDB_TARGET) $(DESTDIR)/usr/bin + $(CP) $(EVENTDB_PROF) $(DESTDIR)/etc/eventd.json + $(CP) $(EVENTDB_DEFAULT_PROFILE) $(DESTDIR)/etc/evprofile/default.json deinstall: $(RM) -rf $(DESTDIR)/usr diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index 4820512cc22..89af3d02914 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -46,11 +46,15 @@ static string flood_ev_action; static string flood_ev_resource; static string flood_ev_msg; -EventConsume::EventConsume(DBConnector *dbConn): +EventConsume::EventConsume(DBConnector* dbConn, + string evProfile, + string dbProfile): m_eventTable(dbConn, EVENT_HISTORY_TABLE_NAME), m_alarmTable(dbConn, EVENT_CURRENT_ALARM_TABLE_NAME), m_eventStatsTable(dbConn, EVENT_STATS_TABLE_NAME), - m_alarmStatsTable(dbConn, EVENT_ALARM_STATS_TABLE_NAME) { + m_alarmStatsTable(dbConn, EVENT_ALARM_STATS_TABLE_NAME), + m_evProfile(evProfile), + m_dbProfile(dbProfile) { // open syslog connection openSyslog(); @@ -106,7 +110,7 @@ void EventConsume::read_eventd_config(bool read_all) { // read from default map static_event_table.clear(); - if (!parse(EVENTD_DEFAULT_MAP_FILE, static_event_table)) { + if (!parse(m_evProfile.c_str(), static_event_table)) { SWSS_LOG_ERROR("Can not initialize event map"); closeSyslog(); exit(0); @@ -399,9 +403,9 @@ void EventConsume::purge_events() { SWSS_LOG_ENTER(); uint32_t size = event_history_list.size(); - while (size >= count) { + while (size >= m_count) { pair oldest_entry = event_history_list.top(); - SWSS_LOG_NOTICE("Rollover based on count(%d/%d). Deleting %lu", size, count, oldest_entry.first); + SWSS_LOG_NOTICE("Rollover based on count(%d/%d). Deleting %lu", size, m_count, oldest_entry.first); m_eventTable.del(to_string(oldest_entry.first)); modifyEventStats(to_string(oldest_entry.first)); event_history_list.pop(); @@ -416,7 +420,7 @@ void EventConsume::purge_events() { unsigned old_seconds = oldest_entry.second / 1000000000ULL; if ((tnow_seconds - old_seconds) > PURGE_SECONDS) { - SWSS_LOG_NOTICE("Rollover based on time (%lu days). Deleting %lu.. now %u old %u", (PURGE_SECONDS/days), oldest_entry.second, tnow_seconds, old_seconds); + SWSS_LOG_NOTICE("Rollover based on time (%lu days). Deleting %lu.. now %u old %u", (PURGE_SECONDS/m_days), oldest_entry.second, tnow_seconds, old_seconds); m_eventTable.del(to_string(oldest_entry.first)); modifyEventStats(to_string(oldest_entry.first)); event_history_list.pop(); @@ -428,14 +432,14 @@ void EventConsume::purge_events() { } void EventConsume::read_config_and_purge() { - days = 0; - count = 0; + m_days = 0; + m_count = 0; // read from the manifest file - parse_config(EVENTD_CONF_FILE, days, count); - SWSS_LOG_NOTICE("max-days %d max-records %d", days, count); + parse_config(m_dbProfile.c_str(), m_days, m_count); + SWSS_LOG_NOTICE("max-days %d max-records %d", m_days, m_count); // update the nanosecond limit - PURGE_SECONDS *= days; + PURGE_SECONDS *= m_days; // purge events based on # of days purge_events(); diff --git a/src/sonic-eventd/src/eventconsume.h b/src/sonic-eventd/src/eventconsume.h index bdac8c68186..36e75f7dac9 100644 --- a/src/sonic-eventd/src/eventconsume.h +++ b/src/sonic-eventd/src/eventconsume.h @@ -2,9 +2,9 @@ #define __EVENTCONSUME_H__ #include -#include #include #include "events.h" +#include "eventutils.h" #include "dbconnector.h" #include "subscriberstatetable.h" @@ -14,7 +14,9 @@ using namespace std; class EventConsume { public: - EventConsume(DBConnector *dbConn); + EventConsume(DBConnector *dbConn, + string evProfile =EVENTD_DEFAULT_MAP_FILE, + string dbProfile =EVENTD_CONF_FILE); ~EventConsume(); void read_eventd_config(bool read_all=true); void run(); @@ -24,7 +26,9 @@ class EventConsume Table m_alarmTable; Table m_eventStatsTable; Table m_alarmStatsTable; - u_int32_t days, count; + u_int32_t m_days, m_count; + string m_evProfile; + string m_dbProfile; void handle_notification(const event_receive_op_t& evt); void read_events(); diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp index eb634350a3f..0a977b4475a 100644 --- a/src/sonic-eventd/src/eventutils.cpp +++ b/src/sonic-eventd/src/eventutils.cpp @@ -1,8 +1,12 @@ #include "eventutils.h" #include #include +#include #include +#include #include +#include +#include #include #include diff --git a/src/sonic-eventd/src/subdir.mk b/src/sonic-eventd/src/subdir.mk index eb067fd6e86..f9a8e65062a 100644 --- a/src/sonic-eventd/src/subdir.mk +++ b/src/sonic-eventd/src/subdir.mk @@ -2,8 +2,9 @@ CC := g++ TEST_OBJS += ./src/eventd.o OBJS += ./src/eventd.o ./src/main.o +EVENTDB_OBJS += ./src/eventdb.o ./src/eventconsume.o ./src/loghandler.o ./src/eventutils.o -C_DEPS += ./src/eventd.d ./src/main.d +C_DEPS += ./src/eventd.d ./src/main.d ./src/eventdb.d ./src/eventconsume.d ./src/loghandler.d ./src/eventutils.d src/%.o: src/%.cpp @echo 'Building file: $<' diff --git a/src/sonic-eventd/var/evprofile/default.json b/src/sonic-eventd/var/evprofile/default.json index 7b937b7de3f..af4166fc082 100644 --- a/src/sonic-eventd/var/evprofile/default.json +++ b/src/sonic-eventd/var/evprofile/default.json @@ -1,12 +1,7 @@ { "__README__" : "This is default map of events that eventd uses. Developer can modify this file and send SIGINT to eventd to make it read and use the updated file. Alternatively developer can test the new event by adding it to a custom event profile and use 'event profile ' command to apply that profile without having to send SIGINT to eventd. Developer need to commit default.json file with the new event after testing it out. Supported severities are: CRITICAL, MAJOR, MINOR, WARNING and INFORMATIONAL. Supported enable flag values are: true and false.", "events":[ - { - "name" : "LICENSE_STATE", - "severity" : "WARNING", - "enable" : "true", - "message" : "License State changed -" - } + ] } \ No newline at end of file diff --git a/src/sonic-yang-models/yang-models/sonic-events-common.yang b/src/sonic-yang-models/yang-models/sonic-events-common.yang index a9ebb1b3cea..c4f666c1033 100644 --- a/src/sonic-yang-models/yang-models/sonic-events-common.yang +++ b/src/sonic-yang-models/yang-models/sonic-events-common.yang @@ -49,7 +49,13 @@ module sonic-events-common { type string; description "The abbreviated name of the event, for example FAN_SPEED_STATUS, - SYSTEM_STATUS, or PSU_FAULTY.; + SYSTEM_STATUS, or PSU_FAULTY."; + } + + leaf resource { + type string; + description + "The item generating the event. for example eth1, cpu_sensor"; } leaf text { From 8d5afbdc7444e609e278f21ddebf1cdaf527e853 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:00:50 -0800 Subject: [PATCH 05/26] Add sonic yang to model event and alarm table. remove ack, noack from sonic-common-event yang. --- .../docker-database/database_config.json.j2 | 2 +- .../yang-models/sonic-alarm.yang | 142 ++++++++++++++++++ .../yang-models/sonic-event.yang | 134 +++++++++++++++++ .../yang-models/sonic-events-common.yang | 6 - 4 files changed, 277 insertions(+), 7 deletions(-) create mode 100644 src/sonic-yang-models/yang-models/sonic-alarm.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-event.yang diff --git a/dockers/docker-database/database_config.json.j2 b/dockers/docker-database/database_config.json.j2 index aa747ad812a..9972816ccba 100644 --- a/dockers/docker-database/database_config.json.j2 +++ b/dockers/docker-database/database_config.json.j2 @@ -151,7 +151,7 @@ {% endif %} , "EVENT_DB" : { - "id" : 18, + "id" : 19, "separator": "|", "instance" : "redis" } diff --git a/src/sonic-yang-models/yang-models/sonic-alarm.yang b/src/sonic-yang-models/yang-models/sonic-alarm.yang new file mode 100644 index 00000000000..e54ad69858d --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-alarm.yang @@ -0,0 +1,142 @@ + module sonic-alarm { + + namespace "http://github.com/sonic-net/sonic-alarm"; + prefix salarm; + yang-version 1.1; + + import sonic-event { + prefix event; + } + + // meta + organization + "SONiC"; + + contact + "SONiC"; + + description + "This module defines operational state data for SONiC alarms."; + + revision "2024-01-30" { + description + "Initial revision."; + } + + + grouping alarm-state { + + leaf id { + type string; + description "Sequence identifier for an alarm."; + } + + leaf resource { + type string; + description "The item that is under alarm within the device."; + } + + leaf text { + type string; + description "Dynamic message raised with the alarm."; + } + + leaf time-created { + type uint64; + description + "The time at which the alarm was raised by the system. + Expressed in nanoseconds since Unix epoch."; + } + + leaf type-id { + type string; + description "Type of the alarm raised"; + } + + leaf severity { + type event:severity-type; + description + "Severity of a raised condition."; + } + + leaf acknowledged { + type boolean; + description + "This denotes whether an alarm is acknowledged by the operator. + An acknowledged alarm is not considered in determining the + health of the system."; + } + + leaf acknowledge-time { + type uint64; + description + "The time at which alarm is acknowledged by the system. + This value is expressed as nanoseconds since the Unix Epoch."; + } + + } + + container sonic-alarm { + + container ALARM { + + list ALARM_LIST { + key "id"; + uses alarm-state; + } + } + + container ALARM_STATS { + + + list ALARM_STATS_LIST { + + key "id"; + leaf id { + type enumeration { + enum state; + } + description + "Table identifier value defined as state."; + } + + leaf alarms { + type uint64; + description + "Total alarms in the system."; + } + + leaf critical { + type uint64; + description + "Total critical alarms in the system."; + } + + leaf major { + type uint64; + description + "Total major alarms in the system."; + } + + leaf minor { + type uint64; + description + "Total minor alarms in the system."; + } + + leaf warning { + type uint64; + description + "Total warnings in the system."; + } + + leaf acknowledged { + type uint64; + description + "Total acknowledged alarms in the system."; + } + + } + } + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-event.yang b/src/sonic-yang-models/yang-models/sonic-event.yang new file mode 100644 index 00000000000..e9ec738190a --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-event.yang @@ -0,0 +1,134 @@ + module sonic-event { + namespace "http://github.com/Azure/sonic-event"; + prefix sevents; + yang-version 1.1; + + organization + "SONiC"; + + contact + "SONiC"; + + description + "This module defines operational state data for SONiC events."; + + revision "2024-01-30" { + description + "Initial revision."; + } + + typedef severity-type { + type enumeration { + enum CRITICAL; + enum MAJOR; + enum MINOR; + enum WARNING; + enum INFORMATIONAL; + } + description + "Severity of a raised condition."; + } + + typedef action-type { + type enumeration { + enum RAISE; + enum CLEAR; + enum ACKNOWLEDGE; + enum UNACKNOWLEDGE; + } + description + "Action on a raised condition."; + } + + grouping event-state { + + leaf id { + type string; + description "Sequence identifier for events."; + } + + leaf resource { + type string; + description "The item in the device that raised the event."; + } + + leaf text { + type string; + description "Dynamic message raised with the event."; + } + + leaf time-created { + type uint64; + description + "The time at which the event was raised by the system. + Expressed in epoch time."; + } + + leaf type-id { + type string; + description "Type of event raised by the device."; + } + + leaf severity { + type severity-type; + description + "Severity of the event."; + } + + leaf action { + type action-type; + description "Action on the event."; + } + } + + container sonic-event { + + container EVENT { + + list EVENT_LIST { + key "id"; + uses event-state; + } + } + + container EVENT_STATS { + + + list EVENT_STATS_LIST { + + key "id"; + leaf id { + type enumeration { + enum state; + } + description + "Table identifier value defined as state."; + } + + leaf events { + type uint64; + description + "Total number of events in the system store."; + } + + leaf raised { + type uint64; + description + "Total number of events for raise operation in system store."; + } + + leaf acked { + type uint64; + description + "Total number of events for ack operation in system store."; + } + + leaf cleared { + type uint64; + description + "Total number of events for clear operation in system store."; + } + } + } + } + } diff --git a/src/sonic-yang-models/yang-models/sonic-events-common.yang b/src/sonic-yang-models/yang-models/sonic-events-common.yang index c4f666c1033..cac93a69c81 100644 --- a/src/sonic-yang-models/yang-models/sonic-events-common.yang +++ b/src/sonic-yang-models/yang-models/sonic-events-common.yang @@ -29,12 +29,6 @@ module sonic-events-common { enum CLEAR { description "Event with clear alarm action."; } - enum ACKNOWLEDGE { - description "Event with ack alarm action."; - } - enum UNACKNOWLEDGE { - description "Event with unacknowledge alarm action."; - } } description "This type defines the actions associated with an event notification."; From a4316e5cbabcb1073e7475c86d9f0cf7c0ba05e0 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:34:28 -0800 Subject: [PATCH 06/26] Add event/alarm persistence related testscases --- src/eventdb_ut.cpp | 107 ++++++ src/sonic-eventd/src/eventconsume.cpp | 66 +--- src/sonic-eventd/src/subdir.mk | 2 +- src/sonic-eventd/tests/default.json | 24 ++ src/sonic-eventd/tests/eventd.json | 5 + src/sonic-eventd/tests/eventdb_ut.cpp | 348 ++++++++++++++++++ .../database_config.json | 4 +- .../database_config0.json | 2 +- .../database_config1.json | 2 +- src/sonic-eventd/tests/subdir.mk | 4 +- .../yang-models/sonic-event.yang | 2 +- 11 files changed, 512 insertions(+), 54 deletions(-) create mode 100644 src/eventdb_ut.cpp create mode 100755 src/sonic-eventd/tests/default.json create mode 100755 src/sonic-eventd/tests/eventd.json create mode 100644 src/sonic-eventd/tests/eventdb_ut.cpp diff --git a/src/eventdb_ut.cpp b/src/eventdb_ut.cpp new file mode 100644 index 00000000000..7886d247c2c --- /dev/null +++ b/src/eventdb_ut.cpp @@ -0,0 +1,107 @@ +#include +#include "gtest/gtest.h" +#include "events_common.h" +#include "events.h" +#include "../src/eventd.h" +#include "../src/eventconsume.h" + +using namespace std; +using namespace swss; + +typedef struct { + int key; + string type-id; + string resource; + string action; + string text; +} event_data_t; + +static const event_data_t events[] = { + {1, "SYSTEM_STATE", "System", "", "System Ready"}, + {2, "USER_LOGIN", "ssh", "", "user testuser logged in"}, +}; + +static const event_data_t alarms[] = { + {1, "TEMP_THRESHOLD_HIGH", "CPU_SENSOR", "RAISE", "Temperature cross threshold 50C"}, + {2, "INTERFACE_OPER_STATE", "eth1", "RAISE", "Operational Down"}, + {3, "INTERFACE_OPER_STATE", "eth1", "CLEAR", "Operational Down"}, + {4, "TEMP_THRESHOLD_HIGH", "CPU_SENSOR", "CLEAR", "Temperature cross threshold 50C"}, + +}; + +const string event_profile = "default_event.json"; +const string event_db_profile = "event_db.json"; + +//typedef unordered_map params; + +//params events_lst[] = [("id":" 1", "type-id": SYSTEM_STATE, "resource": "System", "text": "System Ready", "severity" : "INFORMATIONAL"}, +// {"id":"2", "type-id": USER_LOGIN, "resource": "SSH", "text": "User login", "severity": "WARNING"}]; +/* + 1) "time-created" + 2) "1706507049241598976" + 3) "type-id" + 4) "SYSTEM_STATUS" + 5) "text" + 6) "System is ready" + 7) "resource" + 8) "system_status" + 9) "severity" +10) "INFORMATIONAL" +11) "id" +12) "4" +*/ + +class EventDbFixture : public ::testing::Environment { + protected: + void SetUp() override { + zctx = zmq_ctx_new(); + EXPECT_TRUE(NULL != zctx); + + /* Run proxy to enable receive as capture test needs to receive */ + eventd_proxy *pxy = new eventd_proxy(zctx); + EXPECT_TRUE(NULL != pxy); + + /* Starting proxy */ + EXPECT_EQ(0, pxy->init()); + + /* Start Eventdb in a separate thread*/ + swss::DBConnector eventDb("EVENT_DB", 0); + + EventConsume evtd(&eventDb, event_profile, event_db_profile); + thread thr(&EventConsume::run, &evtd); + } + + void TearDown() override { + + } + void *zctx; +} + +void *init_publish(void *zctx) +{ + void *mock_pub = zmq_socket (zctx, ZMQ_PUB); + EXPECT_TRUE(NULL != mock_pub); + EXPECT_EQ(0, zmq_connect(mock_pub, get_config(XSUB_END_KEY).c_str())); + + /* Provide time for async connect to complete */ + this_thread::sleep_for(chrono::milliseconds(200)); + + return mock_pub; +} + + +TEST_F(EventDbFixture, validate_events) +{ + DBConnector db("EVENT_DB", 0, true); + void* pub_handle = init_publish(zctx); +// pub_handle = events_init_publisher("test_db"); + for(int i = 0; i < ARRAY_SIZE(events); i++) { + string tag = string("test_db_tag_") + to_string(i); + const event_params_t params = {{"type-id", events[i].type-id}, + { "resource", events[i].resource}, + { "action", events[i].action}, + { "text", events[i].text}}; + + event_publish(pub_handle, tag, ¶ms); + } +} diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index 89af3d02914..5ef249e2761 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -18,7 +18,7 @@ unordered_map cal_lookup_map; // temporary map to hold merge of default map of events and any event profile EventMap static_event_table; -volatile bool g_run = true; +bool g_run = true; uint64_t seq_id = 0; uint64_t PURGE_SECONDS = 86400; @@ -78,28 +78,22 @@ EventConsume::~EventConsume() { void EventConsume::run() { + SWSS_LOG_ENTER(); - int total_missed =0; event_handle_t hsub; hsub = events_init_subscriber(); - while (true) { + while (g_run) { event_receive_op_t evt; map_str_str_t evtOp; - int rc = event_receive(hsub, evt); if (rc != 0) { SWSS_LOG_ERROR("Failed to receive rc=%d", rc); continue; } - - total_missed += evt.missed_cnt; - //evtOp[evt.key] = t_map_to_str(evt.params); handle_notification(evt); } - events_deinit_subscriber(hsub); - } void EventConsume::read_eventd_config(bool read_all) { @@ -149,21 +143,19 @@ void EventConsume::handle_notification(const event_receive_op_t& evt) // increment save seq-id for the newly received event uint64_t new_seq_id = seq_id + 1; + FieldValueTuple seqfv("id", to_string(new_seq_id)); vec.push_back(seqfv); - if (ev_act.length() > 0) - { + if (ev_act.length() > 0) { SWSS_LOG_DEBUG("ev_act %s", ev_act.c_str()); ev_type = "ALARM"; string almkey = ev_id; - if (!ev_src.empty()) - { + if (!ev_src.empty()) { almkey += "|" + ev_src; } - if (ev_act.compare(EVENT_ACTION_RAISE_STR) == 0) - { + if (ev_act.compare(EVENT_ACTION_RAISE_STR) == 0) { is_raise = true; // add entry to the lookup map cal_lookup_map.insert(make_pair(almkey, new_seq_id)); @@ -175,35 +167,27 @@ void EventConsume::handle_notification(const event_receive_op_t& evt) // update alarm counters updateAlarmStatistics(ev_sev, ev_act); - } - else if (ev_act.compare(EVENT_ACTION_CLEAR_STR) == 0) - { + } else if (ev_act.compare(EVENT_ACTION_CLEAR_STR) == 0) { is_clear = true; SWSS_LOG_DEBUG(" Received clear alarm for %s", almkey.c_str()); bool ack_flag = false; // remove entry from local cache, alarm table - if (!udpateLocalCacheAndAlarmTable(almkey, ack_flag)) - { + if (!udpateLocalCacheAndAlarmTable(almkey, ack_flag)) { SWSS_LOG_ERROR("Received clear for non-existent alarm %s", almkey.c_str()); return; } // update alarm counters ONLY if it has not been ack'd before. // This is because when alarm is ack'd, alarms/severity counter is reduced already. - if (!ack_flag) - { + if (!ack_flag) { updateAlarmStatistics(ev_sev, ev_act); - } - else - { + } else { // if it has been ack'd before, ack counter would have been incremented for this alrm. // Now is the time reduce it. clearAckAlarmStatistic(); } - } - else - { + } else { // ack/unack events comes with seq-id of raised alarm as resource field. // fetch details of "raised" alarm record string raise_act; @@ -217,38 +201,28 @@ void EventConsume::handle_notification(const event_receive_op_t& evt) return; } - if (ev_act.compare(EVENT_ACTION_ACK_STR) == 0) - { - if (raise_ack_flag.compare("true") == 0) - { + if (ev_act.compare(EVENT_ACTION_ACK_STR) == 0) { + if (raise_ack_flag.compare("true") == 0) { SWSS_LOG_INFO("%s/%s is already acknowledged", ev_id.c_str(), ev_src.c_str()); return; } - if (raise_act.compare(EVENT_ACTION_RAISE_STR) == 0) - { + if (raise_act.compare(EVENT_ACTION_RAISE_STR) == 0) { is_ack = true; SWSS_LOG_DEBUG("Received acknowledge event - %s/%s", ev_id.c_str(), ev_src.c_str()); // update the record with ack flag and ack-time and stats updateAckInfo(is_ack, ev_timestamp, ev_sev, ev_act, ev_src); - } - else - { + } else { SWSS_LOG_ERROR("Alarm %s/%s not in RAISE state", ev_id.c_str(), ev_src.c_str()); return; } - } - else if (ev_act.compare(EVENT_ACTION_UNACK_STR) == 0) - { - if (raise_ack_flag.compare("true") == 0) - { + } else if (ev_act.compare(EVENT_ACTION_UNACK_STR) == 0) { + if (raise_ack_flag.compare("true") == 0) { SWSS_LOG_DEBUG(" received un-ACKnowledge event - %s/%s", ev_id.c_str(), ev_src.c_str()); // update the record with ack flag and ack-time and stats updateAckInfo(is_ack, ev_timestamp, ev_sev, ev_act, ev_src); - } - else - { + } else { SWSS_LOG_INFO(" %s/%s is already un-acknowledged", ev_id.c_str(), ev_src.c_str()); return; } @@ -417,7 +391,7 @@ void EventConsume::purge_events() { while (!event_history_list.empty()) { pair oldest_entry = event_history_list.top(); - unsigned old_seconds = oldest_entry.second / 1000000000ULL; + unsigned old_seconds = oldest_entry.second / 1000000000ULL; if ((tnow_seconds - old_seconds) > PURGE_SECONDS) { SWSS_LOG_NOTICE("Rollover based on time (%lu days). Deleting %lu.. now %u old %u", (PURGE_SECONDS/m_days), oldest_entry.second, tnow_seconds, old_seconds); diff --git a/src/sonic-eventd/src/subdir.mk b/src/sonic-eventd/src/subdir.mk index f9a8e65062a..b5e2551cef3 100644 --- a/src/sonic-eventd/src/subdir.mk +++ b/src/sonic-eventd/src/subdir.mk @@ -1,6 +1,6 @@ CC := g++ -TEST_OBJS += ./src/eventd.o +TEST_OBJS += ./src/eventd.o ./src/eventconsume.o ./src/eventutils.o ./src/loghandler.o OBJS += ./src/eventd.o ./src/main.o EVENTDB_OBJS += ./src/eventdb.o ./src/eventconsume.o ./src/loghandler.o ./src/eventutils.o diff --git a/src/sonic-eventd/tests/default.json b/src/sonic-eventd/tests/default.json new file mode 100755 index 00000000000..9a151118851 --- /dev/null +++ b/src/sonic-eventd/tests/default.json @@ -0,0 +1,24 @@ +{ + "__README__" : "This is default map of events that eventd uses. Developer can modify this file and send SIGINT to eventd to make it read and use the updated file. Alternatively developer can test the new event by adding it to a custom event profile and use 'event profile ' command to apply that profile without having to send SIGINT to eventd. Developer need to commit default.json file with the new event after testing it out. Supported severities are: CRITICAL, MAJOR, MINOR, WARNING and INFORMATIONAL. Supported enable flag values are: true and false.", + "events":[ + { + "name": "SYSTEM_STATE", + "severity": "INFORMATIONAL", + "enable": "true", + "message" : "" + }, + { + "name": "SENSOR_TEMP_HIGH", + "severity": "WARNING", + "enable": "true", + "message" : "" + }, + { + "name": "USER_LOGIN", + "severity": "INFORMATIONAL", + "enable": "true", + "message" : "" + } + ] +} + diff --git a/src/sonic-eventd/tests/eventd.json b/src/sonic-eventd/tests/eventd.json new file mode 100755 index 00000000000..2236e0c6a9e --- /dev/null +++ b/src/sonic-eventd/tests/eventd.json @@ -0,0 +1,5 @@ +{ + "__README__": "Specify size of event history table. Whichever limit is hit first, eventd wraps event history table around and deletes older records.", + "max-records": 200, + "max-days": 30 +} diff --git a/src/sonic-eventd/tests/eventdb_ut.cpp b/src/sonic-eventd/tests/eventdb_ut.cpp new file mode 100644 index 00000000000..8c5fad5329b --- /dev/null +++ b/src/sonic-eventd/tests/eventdb_ut.cpp @@ -0,0 +1,348 @@ +#include +#include "gtest/gtest.h" +#include "events_common.h" +#include "events.h" + +#include +#include "../src/eventd.h" +#include "../src/eventconsume.h" + +using namespace std; +using namespace swss; + +extern volatile bool g_run; +extern uint64_t seq_id; +extern uint64_t PURGE_SECONDS; +extern unordered_map cal_lookup_map; +typedef pair pi; +extern priority_queue, greater > event_history_list; +extern EventMap static_event_table; + +extern void run_pub(void *mock_pub, const string wr_source, internal_events_lst_t &lst); + +typedef struct { + map ev_data; + string severity; +} ev_data_struct; +map, ev_data_struct> event_data_t = { + {{"SYSTEM_STATE","NOTIFY"}, + {{{"type-id","SYSTEM_STATE"}, {"resource", "system-state"}, {"text", "System Ready"}}, + "INFORMATIONAL"}}, + {{"INTERFACE_OPER_STATE", "NOTIFY"}, + {{{"type-id", "INTERFACE_OPER_STATE"}, {"resource", "Ethernet1"}, {"text", "Operational Down"}, {"state", "up"}}, + "INFORMATIONAL"}}, + {{"SENSOR_TEMP_HIGH", "RAISE"}, + {{{"type-id", "SENSOR_TEMP_HIGH"}, {"resource", "cpu_sensor"}, {"action", "RAISE"}, {"text", "sensor temp 55C, threshold temp 52C"}}, + "WARNING"}}, + {{"SENSOR_TEMP_HIGH", "CLEAR"}, + {{{"type-id", "SENSOR_TEMP_HIGH"}, {"resource", "cpu_sensor"}, {"action", "CLEAR"}, {"text", "sensor temp 50C, threshold temp 52C"}}, + "WARNING"}} +}; + + +typedef struct { + int id; + string source; + string tag; + string rid; + string seq; +} test_data_t; + +const string event_profile = "tests/default.json"; +const string event_db_profile = "tests/eventd.json"; + +void delete_evdb(DBConnector& dbConn) +{ + auto keys = dbConn.keys("*"); + for (const auto& key : keys) + { + dbConn.del(key); + } +} + +void clear_eventdb_data() +{ + g_run = true; + seq_id =0; + cal_lookup_map.clear(); + PURGE_SECONDS = 86400; + event_history_list = priority_queue, greater >(); + static_event_table.clear(); +} + + +class EventDbFixture : public ::testing::Test { + protected: + void SetUp() override { + zctx = zmq_ctx_new(); + EXPECT_TRUE(NULL != zctx); + + /* Run proxy to enable receive as capture test needs to receive */ + pxy = new eventd_proxy(zctx); + EXPECT_TRUE(NULL != pxy); + + /* Starting proxy */ + EXPECT_EQ(0, pxy->init()); + DBConnector eventDb("EVENT_DB", 0, true); + //delete any entries in the EVENT_DB + delete_evdb(eventDb); + try + { + /* Start Eventdb in a separate thread*/ + evtConsume= new EventConsume(&eventDb, event_profile, event_db_profile); + thread thr(&EventConsume::run, evtConsume); + thr.detach(); + } + catch (exception &e) + { + printf("EventDbFixture::SetUP: Unable to get DB Connector, e=(%s)\n", e.what()); + } + } + + void TearDown() override { + delete evtConsume; + evtConsume = NULL; + delete pxy; + pxy= NULL; + zmq_ctx_term(zctx); + zctx = NULL; + clear_eventdb_data(); + } + EventConsume *evtConsume; + void *zctx; + eventd_proxy *pxy; +}; + + +void *init_publish(void *zctx) +{ + void *mock_pub = zmq_socket (zctx, ZMQ_PUB); + EXPECT_TRUE(NULL != mock_pub); + EXPECT_EQ(0, zmq_connect(mock_pub, get_config(XSUB_END_KEY).c_str())); + + /* Provide time for async connect to complete */ + this_thread::sleep_for(chrono::milliseconds(200)); + + return mock_pub; +} + +internal_event_t create_ev(const int id, const int ev_id, const string& event, + const string& action, + map> &verify_data) +{ + internal_event_t event_data; + stringstream ss; + //new data + test_data_t data = {id, "source" +id, "tag" + id, "guid-" + id, to_string(id)}; + + event_data[EVENT_STR_DATA] = convert_to_json( + data.source + ":" + data.tag, map(event_data_t[make_pair(event, action)].ev_data)); + event_data[EVENT_RUNTIME_ID] = data.rid; + event_data[EVENT_SEQUENCE] = data.seq; + auto timepoint = system_clock::now(); + ss << duration_cast(timepoint.time_since_epoch()).count(); + + event_data[EVENT_EPOCH] = ss.str(); + unordered_map ev_val(event_data_t[make_pair(event, action)].ev_data.begin(), + event_data_t[make_pair(event, action)].ev_data.end()); + ev_val.insert({"id", to_string(ev_id)}); + ev_val.insert({"time-created", ss.str()}); + ev_val.insert({"severity", event_data_t[make_pair(event, action)].severity}); + + if (action == "RAISE") { + ev_val.insert({"acknowledged", "false"}); + ev_val.insert({"action", action}); + } + verify_data.insert({to_string(ev_id), ev_val}); + + return event_data; +} + +#if 0 +void run_pub(void *mock_pub, const string wr_source, internal_events_lst_t &lst) +{ + for(internal_events_lst_t::const_iterator itc = lst.begin(); itc != lst.end(); ++itc) { + EXPECT_EQ(0, zmq_message_send(mock_pub, wr_source, *itc)); + } +} +#endif + +void verify_events(map> verifyData) +{ + DBConnector eventDb("EVENT_DB", 0, true); + auto dbKeys = eventDb.keys("EVENT:*"); + EXPECT_EQ(verifyData.size(), dbKeys.size()); + for (const auto& vKey : verifyData) + { + string evtKey = "EVENT:" + vKey.first; + EXPECT_TRUE(count(dbKeys.begin(), dbKeys.end(), evtKey) == 1); + auto ev = eventDb.hgetall(evtKey); + EXPECT_TRUE(ev == verifyData[vKey.first]); + } +} + + +void verify_alarms_clear(map> verifyData) +{ + DBConnector eventDb("EVENT_DB", 0, true); + auto dbKeys = eventDb.keys("ALARM:*"); + EXPECT_EQ(0, dbKeys.size()); +} + +void verify_alarms_raise(map> verifyData) +{ + DBConnector eventDb("EVENT_DB", 0, true); + auto dbKeys = eventDb.keys("ALARM:*"); + EXPECT_EQ(verifyData.size(), dbKeys.size()); + + for (const auto& vKey : verifyData) + { + string almKey = "ALARM:" + vKey.first; + EXPECT_TRUE(count(dbKeys.begin(), dbKeys.end(), almKey) == 1); + auto ev = eventDb.hgetall(almKey); + EXPECT_TRUE(ev == verifyData[vKey.first]); + } +} + +TEST_F(EventDbFixture, validate_events) +{ + internal_events_lst_t wr_evts; + string wr_source("eventd-test"); + + void *mock_pub = init_publish(zctx); + + map> verify_data; + + wr_evts.push_back(create_ev(1, 1, "SENSOR_TEMP_HIGH", "RAISE", verify_data)); + wr_evts.push_back(create_ev(2, 2, "SYSTEM_STATE", "NOTIFY", verify_data)); + + run_pub(mock_pub, wr_source, wr_evts); + + this_thread::sleep_for(chrono::milliseconds(2000)); + + // verify events logged in DB. + verify_events(verify_data); + + //send events to close eventdb task + g_run = false; + wr_evts.clear(); + wr_evts.push_back(create_ev(301, 3, "SYSTEM_STATE", "NOTIFY", verify_data)); + run_pub(mock_pub, wr_source, wr_evts); + this_thread::sleep_for(chrono::milliseconds(2000)); + zmq_close(mock_pub); + +} + + +TEST_F(EventDbFixture, validate_alarms) +{ + internal_events_lst_t wr_evts; + string wr_source("eventd-test"); + void *mock_pub = init_publish(zctx); + + map> verify_data; + wr_evts.push_back(create_ev(3, 1, "SENSOR_TEMP_HIGH", "RAISE", verify_data)); + + run_pub(mock_pub, wr_source, wr_evts); + + this_thread::sleep_for(chrono::milliseconds(2000)); + + // verify events logged in DB. + verify_events(verify_data); + verify_alarms_raise(verify_data); + + wr_evts.clear(); + wr_evts.push_back(create_ev(4, 2, "SENSOR_TEMP_HIGH", "CLEAR", verify_data)); + + run_pub(mock_pub, wr_source, wr_evts); + this_thread::sleep_for(chrono::milliseconds(2000)); + verify_events(verify_data); + verify_alarms_clear(verify_data); + g_run = false; + wr_evts.clear(); + wr_evts.push_back(create_ev(302, 3, "SYSTEM_STATE", "NOTIFY", verify_data)); + run_pub(mock_pub, wr_source, wr_evts); + this_thread::sleep_for(chrono::milliseconds(2000)); + zmq_close(mock_pub); +} + + +TEST_F(EventDbFixture, expiry_purge) +{ + internal_events_lst_t wr_evts; + string wr_source("eventd-test"); + void *mock_pub = init_publish(zctx); + map> verify_data; + //set epoch time back to 31 days + auto timepoint = system_clock::now(); + auto epochTimeNs = duration_cast(timepoint.time_since_epoch()).count(); + epochTimeNs = epochTimeNs - (32UL * 24 * 60 * 60 * 1000 * 1000 * 1000); + auto ev_data = create_ev(5, 1, "SENSOR_TEMP_HIGH", "RAISE", verify_data); + + ev_data[EVENT_EPOCH] = to_string(epochTimeNs); + verify_data["1"]["time-created"] = ev_data[EVENT_EPOCH]; + wr_evts.push_back(ev_data); + + run_pub(mock_pub, wr_source, wr_evts); + this_thread::sleep_for(chrono::milliseconds(2000)); + + // verify events logged in DB. + verify_events(verify_data); + verify_alarms_raise(verify_data); + + wr_evts.clear(); + verify_data.clear(); + wr_evts.push_back(create_ev(6, 2, "SENSOR_TEMP_HIGH", "CLEAR", verify_data)); + run_pub(mock_pub, wr_source, wr_evts); + this_thread::sleep_for(chrono::milliseconds(2000)); + + verify_events(verify_data); + verify_alarms_clear(verify_data); + wr_evts.clear(); + g_run = false; + wr_evts.push_back(create_ev(303, 3, "SYSTEM_STATE", "NOTIFY", verify_data)); + run_pub(mock_pub, wr_source, wr_evts); + this_thread::sleep_for(chrono::milliseconds(2000)); + zmq_close(mock_pub); +} + + + +TEST_F(EventDbFixture, overflow_purge) +{ + internal_events_lst_t wr_evts; + string wr_source("eventd-test"); + void *mock_pub = init_publish(zctx); + map> verify_data; + int i=0,j=6; + + for (; i <= 198; i+=2, j+=2) + { + wr_evts.push_back(create_ev(j+1, i+1, "SENSOR_TEMP_HIGH", "RAISE", verify_data)); + wr_evts.push_back(create_ev(j+2, i+2, "SENSOR_TEMP_HIGH", "CLEAR", verify_data)); + } + + run_pub(mock_pub, wr_source, wr_evts); + + this_thread::sleep_for(chrono::milliseconds(5000)); + + // verify events logged in DB. + verify_events(verify_data); + // This will make it out of limit + wr_evts.push_back(create_ev(j+1, i+1, "SENSOR_TEMP_HIGH", "RAISE", verify_data)); + run_pub(mock_pub, wr_source, wr_evts); + + this_thread::sleep_for(chrono::milliseconds(2000)); + + DBConnector eventDb("EVENT_DB", 0, true); + auto dbKeys = eventDb.keys("EVENT:*"); + EXPECT_EQ(200, dbKeys.size()); + EXPECT_TRUE(count(dbKeys.begin(), dbKeys.end(), "EVENT:1") == 0); + EXPECT_TRUE(count(dbKeys.begin(), dbKeys.end(), "EVENT:2") == 1); + EXPECT_TRUE(count(dbKeys.begin(), dbKeys.end(), "EVENT:" + to_string(i+1)) == 1); + g_run = false; + wr_evts.push_back(create_ev(303, 3, "SYSTEM_STATE", "NOTIFY", verify_data)); + run_pub(mock_pub, wr_source, wr_evts); + this_thread::sleep_for(chrono::milliseconds(2000)); + zmq_close(mock_pub); +} diff --git a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json index 602a97cb511..3fb6d6339af 100644 --- a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json +++ b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json @@ -97,11 +97,11 @@ "separator": ":", "instance" : "redis" }, - "TEST_DB" : { + "EVENT_DB" : { "id" : 15, "separator": ":", "instance" : "redis" - } + } }, "VERSION" : "1.0" } diff --git a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config0.json b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config0.json index 01b7486e504..edbdebea35f 100644 --- a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config0.json +++ b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config0.json @@ -77,7 +77,7 @@ "separator": ":", "instance" : "redis" }, - "TEST_DB" : { + "EVENT_DB" : { "id" : 15, "separator": ":", "instance" : "redis" diff --git a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config1.json b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config1.json index bbe0930dcec..5eb661ae627 100644 --- a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config1.json +++ b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config1.json @@ -77,7 +77,7 @@ "separator": ":", "instance" : "redis" }, - "TEST_DB" : { + "EVENT_DB" : { "id" : 15, "separator": ":", "instance" : "redis" diff --git a/src/sonic-eventd/tests/subdir.mk b/src/sonic-eventd/tests/subdir.mk index a251b4bea82..c2f142f2474 100644 --- a/src/sonic-eventd/tests/subdir.mk +++ b/src/sonic-eventd/tests/subdir.mk @@ -1,8 +1,8 @@ CC := g++ -TEST_OBJS += ./tests/eventd_ut.o ./tests/main.o +TEST_OBJS += ./tests/eventd_ut.o ./tests/eventdb_ut.o ./tests/main.o -C_DEPS += ./tests/eventd_ut.d ./tests/main.d +C_DEPS += ./tests/eventd_ut.d ./tests/eventdb_ut.d ./tests/main.d tests/%.o: tests/%.cpp @echo 'Building file: $<' diff --git a/src/sonic-yang-models/yang-models/sonic-event.yang b/src/sonic-yang-models/yang-models/sonic-event.yang index e9ec738190a..f5bb27782ec 100644 --- a/src/sonic-yang-models/yang-models/sonic-event.yang +++ b/src/sonic-yang-models/yang-models/sonic-event.yang @@ -1,5 +1,5 @@ module sonic-event { - namespace "http://github.com/Azure/sonic-event"; + namespace "http://github.com/sonic-net/sonic-event"; prefix sevents; yang-version 1.1; From c3a70dc02cb340fb0aff8b1603ee0315b35e76f6 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Thu, 16 May 2024 10:10:17 -0700 Subject: [PATCH 07/26] Remove file eventdb_ut.cpp. --- src/eventdb_ut.cpp | 107 --------------------------------------------- 1 file changed, 107 deletions(-) delete mode 100644 src/eventdb_ut.cpp diff --git a/src/eventdb_ut.cpp b/src/eventdb_ut.cpp deleted file mode 100644 index 7886d247c2c..00000000000 --- a/src/eventdb_ut.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include "gtest/gtest.h" -#include "events_common.h" -#include "events.h" -#include "../src/eventd.h" -#include "../src/eventconsume.h" - -using namespace std; -using namespace swss; - -typedef struct { - int key; - string type-id; - string resource; - string action; - string text; -} event_data_t; - -static const event_data_t events[] = { - {1, "SYSTEM_STATE", "System", "", "System Ready"}, - {2, "USER_LOGIN", "ssh", "", "user testuser logged in"}, -}; - -static const event_data_t alarms[] = { - {1, "TEMP_THRESHOLD_HIGH", "CPU_SENSOR", "RAISE", "Temperature cross threshold 50C"}, - {2, "INTERFACE_OPER_STATE", "eth1", "RAISE", "Operational Down"}, - {3, "INTERFACE_OPER_STATE", "eth1", "CLEAR", "Operational Down"}, - {4, "TEMP_THRESHOLD_HIGH", "CPU_SENSOR", "CLEAR", "Temperature cross threshold 50C"}, - -}; - -const string event_profile = "default_event.json"; -const string event_db_profile = "event_db.json"; - -//typedef unordered_map params; - -//params events_lst[] = [("id":" 1", "type-id": SYSTEM_STATE, "resource": "System", "text": "System Ready", "severity" : "INFORMATIONAL"}, -// {"id":"2", "type-id": USER_LOGIN, "resource": "SSH", "text": "User login", "severity": "WARNING"}]; -/* - 1) "time-created" - 2) "1706507049241598976" - 3) "type-id" - 4) "SYSTEM_STATUS" - 5) "text" - 6) "System is ready" - 7) "resource" - 8) "system_status" - 9) "severity" -10) "INFORMATIONAL" -11) "id" -12) "4" -*/ - -class EventDbFixture : public ::testing::Environment { - protected: - void SetUp() override { - zctx = zmq_ctx_new(); - EXPECT_TRUE(NULL != zctx); - - /* Run proxy to enable receive as capture test needs to receive */ - eventd_proxy *pxy = new eventd_proxy(zctx); - EXPECT_TRUE(NULL != pxy); - - /* Starting proxy */ - EXPECT_EQ(0, pxy->init()); - - /* Start Eventdb in a separate thread*/ - swss::DBConnector eventDb("EVENT_DB", 0); - - EventConsume evtd(&eventDb, event_profile, event_db_profile); - thread thr(&EventConsume::run, &evtd); - } - - void TearDown() override { - - } - void *zctx; -} - -void *init_publish(void *zctx) -{ - void *mock_pub = zmq_socket (zctx, ZMQ_PUB); - EXPECT_TRUE(NULL != mock_pub); - EXPECT_EQ(0, zmq_connect(mock_pub, get_config(XSUB_END_KEY).c_str())); - - /* Provide time for async connect to complete */ - this_thread::sleep_for(chrono::milliseconds(200)); - - return mock_pub; -} - - -TEST_F(EventDbFixture, validate_events) -{ - DBConnector db("EVENT_DB", 0, true); - void* pub_handle = init_publish(zctx); -// pub_handle = events_init_publisher("test_db"); - for(int i = 0; i < ARRAY_SIZE(events); i++) { - string tag = string("test_db_tag_") + to_string(i); - const event_params_t params = {{"type-id", events[i].type-id}, - { "resource", events[i].resource}, - { "action", events[i].action}, - { "text", events[i].text}}; - - event_publish(pub_handle, tag, ¶ms); - } -} From 127531c53cc3f288510c0c38e590a21dedffdffa Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Thu, 16 May 2024 18:32:47 -0700 Subject: [PATCH 08/26] Updates to eventdb testsuite. --- src/sonic-eventd/tests/eventdb_ut.cpp | 50 ++++++++++++++++----------- src/sonic-eventd/tests/main.cpp | 7 +++- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/sonic-eventd/tests/eventdb_ut.cpp b/src/sonic-eventd/tests/eventdb_ut.cpp index 8c5fad5329b..76159dd2722 100644 --- a/src/sonic-eventd/tests/eventdb_ut.cpp +++ b/src/sonic-eventd/tests/eventdb_ut.cpp @@ -2,6 +2,7 @@ #include "gtest/gtest.h" #include "events_common.h" #include "events.h" +#include #include #include "../src/eventd.h" @@ -132,8 +133,13 @@ internal_event_t create_ev(const int id, const int ev_id, const string& event, { internal_event_t event_data; stringstream ss; - //new data - test_data_t data = {id, "source" +id, "tag" + id, "guid-" + id, to_string(id)}; + + test_data_t data; + data.id = id; + data.source = "source" + to_string(id); + data.tag = "tag" + to_string(id); + data.rid = "guid-" + to_string(id); + data.seq = to_string(id); event_data[EVENT_STR_DATA] = convert_to_json( data.source + ":" + data.tag, map(event_data_t[make_pair(event, action)].ev_data)); @@ -145,33 +151,26 @@ internal_event_t create_ev(const int id, const int ev_id, const string& event, event_data[EVENT_EPOCH] = ss.str(); unordered_map ev_val(event_data_t[make_pair(event, action)].ev_data.begin(), event_data_t[make_pair(event, action)].ev_data.end()); - ev_val.insert({"id", to_string(ev_id)}); - ev_val.insert({"time-created", ss.str()}); - ev_val.insert({"severity", event_data_t[make_pair(event, action)].severity}); - + ev_val.insert({{"id", to_string(ev_id)}}); + ev_val.insert({{"time-created", ss.str()}}); + ev_val.insert({{"severity", event_data_t[make_pair(event, action)].severity}}); + if (action == "RAISE") { - ev_val.insert({"acknowledged", "false"}); - ev_val.insert({"action", action}); - } + ev_val.insert({{"acknowledged", "false"}}); + ev_val.insert({{"action", action}}); + } verify_data.insert({to_string(ev_id), ev_val}); return event_data; } -#if 0 -void run_pub(void *mock_pub, const string wr_source, internal_events_lst_t &lst) -{ - for(internal_events_lst_t::const_iterator itc = lst.begin(); itc != lst.end(); ++itc) { - EXPECT_EQ(0, zmq_message_send(mock_pub, wr_source, *itc)); - } -} -#endif void verify_events(map> verifyData) { DBConnector eventDb("EVENT_DB", 0, true); auto dbKeys = eventDb.keys("EVENT:*"); EXPECT_EQ(verifyData.size(), dbKeys.size()); + for (const auto& vKey : verifyData) { string evtKey = "EVENT:" + vKey.first; @@ -206,6 +205,8 @@ void verify_alarms_raise(map> verifyData) TEST_F(EventDbFixture, validate_events) { + printf("Validate events TEST started\n"); + internal_events_lst_t wr_evts; string wr_source("eventd-test"); @@ -229,13 +230,16 @@ TEST_F(EventDbFixture, validate_events) wr_evts.push_back(create_ev(301, 3, "SYSTEM_STATE", "NOTIFY", verify_data)); run_pub(mock_pub, wr_source, wr_evts); this_thread::sleep_for(chrono::milliseconds(2000)); - zmq_close(mock_pub); + zmq_close(mock_pub); + + printf("Validate events TEST completed\n"); } TEST_F(EventDbFixture, validate_alarms) { + printf("Validate alarms TEST started\n"); internal_events_lst_t wr_evts; string wr_source("eventd-test"); void *mock_pub = init_publish(zctx); @@ -263,12 +267,14 @@ TEST_F(EventDbFixture, validate_alarms) wr_evts.push_back(create_ev(302, 3, "SYSTEM_STATE", "NOTIFY", verify_data)); run_pub(mock_pub, wr_source, wr_evts); this_thread::sleep_for(chrono::milliseconds(2000)); - zmq_close(mock_pub); + zmq_close(mock_pub); + printf("Validate alarms TEST completed\n"); } TEST_F(EventDbFixture, expiry_purge) { + printf("Expiry purge TEST started\n"); internal_events_lst_t wr_evts; string wr_source("eventd-test"); void *mock_pub = init_publish(zctx); @@ -304,12 +310,13 @@ TEST_F(EventDbFixture, expiry_purge) run_pub(mock_pub, wr_source, wr_evts); this_thread::sleep_for(chrono::milliseconds(2000)); zmq_close(mock_pub); + printf("Expiry purge TEST completed\n"); } - -TEST_F(EventDbFixture, overflow_purge) +TEST_F(EventDbFixture, rollover_purge) { + printf("Rollover purge TEST started\n"); internal_events_lst_t wr_evts; string wr_source("eventd-test"); void *mock_pub = init_publish(zctx); @@ -345,4 +352,5 @@ TEST_F(EventDbFixture, overflow_purge) run_pub(mock_pub, wr_source, wr_evts); this_thread::sleep_for(chrono::milliseconds(2000)); zmq_close(mock_pub); + printf("Rollover purge TEST completed\n"); } diff --git a/src/sonic-eventd/tests/main.cpp b/src/sonic-eventd/tests/main.cpp index 22ee2326c0d..f0896b4be46 100644 --- a/src/sonic-eventd/tests/main.cpp +++ b/src/sonic-eventd/tests/main.cpp @@ -17,6 +17,11 @@ string global_existing_file = "./tests/redis_multi_db_ut_config/database_global. #define TEST_NAMESPACE "asic0" #define INVALID_NAMESPACE "invalid" +//std::string TEST_DB= "APPL_DB"; +//std::string TEST_NAMESPACE= "asic0"; +//std::string INVALID_NAMESPACE= "invalid"; + + bool g_is_redis_available = false; class SwsscommonEnvironment : public ::testing::Environment { @@ -74,7 +79,7 @@ class SwsscommonEnvironment : public ::testing::Environment { // Get this info handy try { - DBConnector db("TEST_DB", 0, true); + DBConnector db("EVENT_DB", 0, true); g_is_redis_available = true; } catch (exception &e) From a9536670b7281113861420e11784e6e8215063d9 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Mon, 20 May 2024 10:39:21 -0700 Subject: [PATCH 09/26] Revert changes to existing eventd UT. Set eventdb testcases as separate test binary. Skip testcase execution if DB connection failure. --- src/sonic-eventd/Makefile | 5 +- src/sonic-eventd/src/subdir.mk | 1 + src/sonic-eventd/tests/eventdb_ut.cpp | 80 ++++++++++++++++++- src/sonic-eventd/tests/main.cpp | 7 +- .../database_config.json | 2 +- .../database_config0.json | 2 +- .../database_config1.json | 2 +- src/sonic-eventd/tests/subdir.mk | 7 +- 8 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/sonic-eventd/Makefile b/src/sonic-eventd/Makefile index acb226ed0f3..2ee969b094b 100644 --- a/src/sonic-eventd/Makefile +++ b/src/sonic-eventd/Makefile @@ -1,6 +1,7 @@ RM := rm -rf EVENTD_TARGET := eventd EVENTD_TEST := tests/tests +EVENTDB_TEST := tests/eventdb EVENTD_TOOL := tools/events_tool EVENTD_PUBLISH_TOOL := tools/events_publish_tool.py RSYSLOG-PLUGIN_TARGET := rsyslog_plugin/rsyslog_plugin @@ -58,12 +59,14 @@ rsyslog-plugin: $(RSYSLOG-PLUGIN_OBJS) @echo 'Finished building target: $@' @echo ' ' -eventd-tests: $(TEST_OBJS) +eventd-tests: $(TEST_OBJS) $(EVENTDB_TEST_OBJS) @echo 'Building target: $@' @echo 'Invoking: G++ Linker' $(CC) $(LDFLAGS) -o $(EVENTD_TEST) $(TEST_OBJS) $(LIBS) $(TEST_LIBS) + $(CC) $(LDFLAGS) -o $(EVENTDB_TEST) $(EVENTDB_TEST_OBJS) $(LIBS) $(TEST_LIBS) @echo 'Finished building target: $@' $(EVENTD_TEST) + $(EVENTDB_TEST) @echo 'Finished running tests' @echo ' ' diff --git a/src/sonic-eventd/src/subdir.mk b/src/sonic-eventd/src/subdir.mk index b5e2551cef3..1b03f3d4b04 100644 --- a/src/sonic-eventd/src/subdir.mk +++ b/src/sonic-eventd/src/subdir.mk @@ -1,6 +1,7 @@ CC := g++ TEST_OBJS += ./src/eventd.o ./src/eventconsume.o ./src/eventutils.o ./src/loghandler.o +EVENTDB_TEST_OBJS += ./src/eventd.o ./src/eventconsume.o ./src/eventutils.o ./src/loghandler.o OBJS += ./src/eventd.o ./src/main.o EVENTDB_OBJS += ./src/eventdb.o ./src/eventconsume.o ./src/loghandler.o ./src/eventutils.o diff --git a/src/sonic-eventd/tests/eventdb_ut.cpp b/src/sonic-eventd/tests/eventdb_ut.cpp index 76159dd2722..a3e9e4aba8f 100644 --- a/src/sonic-eventd/tests/eventdb_ut.cpp +++ b/src/sonic-eventd/tests/eventdb_ut.cpp @@ -3,6 +3,8 @@ #include "events_common.h" #include "events.h" #include +#include "dbconnector.h" +#include #include #include "../src/eventd.h" @@ -19,7 +21,18 @@ typedef pair pi; extern priority_queue, greater > event_history_list; extern EventMap static_event_table; -extern void run_pub(void *mock_pub, const string wr_source, internal_events_lst_t &lst); + +#define TEST_DB "APPL_DB" +#define TEST_NAMESPACE "asic0" +#define INVALID_NAMESPACE "invalid" + +//extern void run_pub(void *mock_pub, const string wr_source, internal_events_lst_t &lst); + +string existing_file = "./tests//eventdb_database_config.json"; +string nonexisting_file = "./tests//database_config_nonexisting.json"; +string global_existing_file = "./tests//eventdb_database_global.json"; + + typedef struct { map ev_data; @@ -71,6 +84,12 @@ void clear_eventdb_data() static_event_table.clear(); } +void run_pub(void *mock_pub, const string wr_source, internal_events_lst_t &lst) +{ + for(internal_events_lst_t::const_iterator itc = lst.begin(); itc != lst.end(); ++itc) { + EXPECT_EQ(0, zmq_message_send(mock_pub, wr_source, *itc)); + } +} class EventDbFixture : public ::testing::Test { protected: @@ -87,6 +106,7 @@ class EventDbFixture : public ::testing::Test { DBConnector eventDb("EVENT_DB", 0, true); //delete any entries in the EVENT_DB delete_evdb(eventDb); + try { /* Start Eventdb in a separate thread*/ @@ -354,3 +374,61 @@ TEST_F(EventDbFixture, rollover_purge) zmq_close(mock_pub); printf("Rollover purge TEST completed\n"); } + +class SwsscommonEnvironment : public ::testing::Environment { +public: + // Override this to define how to set up the environment + void SetUp() override { + // by default , init should be false + cout << "Default : isInit = " << SonicDBConfig::isInit() << endl; + EXPECT_FALSE(SonicDBConfig::isInit()); + EXPECT_THROW(SonicDBConfig::initialize(nonexisting_file), runtime_error); + + EXPECT_FALSE(SonicDBConfig::isInit()); + + // load local config file, init should be true + SonicDBConfig::initialize(existing_file); + cout << "INIT: load local db config file, isInit = " << SonicDBConfig::isInit() << endl; + EXPECT_TRUE(SonicDBConfig::isInit()); + + // Test the database_global.json file + // by default , global_init should be false + cout << "Default : isGlobalInit = " << SonicDBConfig::isGlobalInit() << endl; + EXPECT_FALSE(SonicDBConfig::isGlobalInit()); + + // Call an API which actually needs the data populated by SonicDBConfig::initializeGlobalConfig +// EXPECT_THROW(SonicDBConfig::getDbId(EVENT_DB, TEST_NAMESPACE), runtime_error); + + // load local global file, init should be true + SonicDBConfig::initializeGlobalConfig(global_existing_file); + cout<<"INIT: load global db config file, isInit = "< Date: Mon, 20 May 2024 11:30:46 -0700 Subject: [PATCH 10/26] Commit test related config files. --- .../tests/eventdb_database_config.json | 107 ++++++++++++++++++ .../tests/eventdb_database_config_global.json | 8 ++ .../database_config.json | 2 +- 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 src/sonic-eventd/tests/eventdb_database_config.json create mode 100644 src/sonic-eventd/tests/eventdb_database_config_global.json diff --git a/src/sonic-eventd/tests/eventdb_database_config.json b/src/sonic-eventd/tests/eventdb_database_config.json new file mode 100644 index 00000000000..3fb6d6339af --- /dev/null +++ b/src/sonic-eventd/tests/eventdb_database_config.json @@ -0,0 +1,107 @@ +{ + "INSTANCES": { + "redis":{ + "hostname" : "127.0.0.1", + "port": 6379, + "unix_socket_path": "/var/run/redis/redis.sock" + }, + "redis1":{ + "hostname" : "127.0.0.1", + "port": 6380, + "unix_socket_path": "/var/run/redis/redis1.sock" + }, + "redis2":{ + "hostname" : "127.0.0.1", + "port": 6381, + "unix_socket_path": "/var/run/redis/redis2.sock" + }, + "redis3":{ + "hostname" : "127.0.0.1", + "port": 6382, + "unix_socket_path": "/var/run/redis/redis3.sock" + }, + "redis4":{ + "hostname" : "127.0.0.1", + "port": 6383, + "unix_socket_path": "/var/run/redis/redis4.sock" + } + }, + "DATABASES" : { + "APPL_DB" : { + "id" : 0, + "separator": ":", + "instance" : "redis" + }, + "ASIC_DB" : { + "id" : 1, + "separator": ":", + "instance" : "redis" + }, + "COUNTERS_DB" : { + "id" : 2, + "separator": ":", + "instance" : "redis" + }, + "CONFIG_DB" : { + "id" : 4, + "separator": "|", + "instance" : "redis" + }, + "PFC_WD_DB" : { + "id" : 5, + "separator": ":", + "instance" : "redis" + }, + "FLEX_COUNTER_DB" : { + "id" : 5, + "separator": ":", + "instance" : "redis" + }, + "STATE_DB" : { + "id" : 6, + "separator": "|", + "instance" : "redis" + }, + "SNMP_OVERLAY_DB" : { + "id" : 7, + "separator": "|", + "instance" : "redis" + }, + "RESTAPI_DB": { + "id": 8, + "separator": "|", + "instance": "redis" + }, + "GB_ASIC_DB": { + "id": 9, + "separator": ":", + "instance": "redis" + }, + "GB_COUNTERS_DB": { + "id": 10, + "separator": ":", + "instance": "redis" + }, + "GB_FLEX_COUNTER_DB": { + "id": 11, + "separator": ":", + "instance": "redis" + }, + "STATE_DB2" : { + "id" : 13, + "separator": "|", + "instance" : "redis" + }, + "APPL_STATE_DB" : { + "id" : 14, + "separator": ":", + "instance" : "redis" + }, + "EVENT_DB" : { + "id" : 15, + "separator": ":", + "instance" : "redis" + } + }, + "VERSION" : "1.0" +} diff --git a/src/sonic-eventd/tests/eventdb_database_config_global.json b/src/sonic-eventd/tests/eventdb_database_config_global.json new file mode 100644 index 00000000000..e55e1ab1b18 --- /dev/null +++ b/src/sonic-eventd/tests/eventdb_database_config_global.json @@ -0,0 +1,8 @@ +{ + "INCLUDES" : [ + { + "include" : "eventdb_database_config.json" + } + ], + "VERSION" : "1.0" +} diff --git a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json index 7b2ea2c2bd3..602a97cb511 100644 --- a/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json +++ b/src/sonic-eventd/tests/redis_multi_db_ut_config/database_config.json @@ -101,7 +101,7 @@ "id" : 15, "separator": ":", "instance" : "redis" - } + } }, "VERSION" : "1.0" } From ccb162ce41a376a61e1fc9e11e7cb7f3ea118e04 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Mon, 21 Apr 2025 22:49:24 +0100 Subject: [PATCH 11/26] wRevert "Local make customizations." This reverts commit e9425a0aad5d9413efaaf1b4eccd6236aef50aba. --- sonic-slave-bookworm/Dockerfile.j2 | 6 ------ sonic-slave-bullseye/Dockerfile.j2 | 7 ------- sonic-slave-buster/Dockerfile.j2 | 11 ++++------- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/sonic-slave-bookworm/Dockerfile.j2 b/sonic-slave-bookworm/Dockerfile.j2 index e3c2cc7ed42..97f2959e3da 100644 --- a/sonic-slave-bookworm/Dockerfile.j2 +++ b/sonic-slave-bookworm/Dockerfile.j2 @@ -516,12 +516,6 @@ RUN apt-get remove -y libnl-3-200 RUN eatmydata apt-get install -y libpcre3:$arch {%- endif %} - -# Add Dell CA -RUN wget --no-check-certificate -O /usr/local/share/ca-certificates/dellca2018-bundle.crt \ - https://nsdn.artifactory.cec.lab.emc.com/artifactory/sonic-dell-cert/dellca2018-bundle.crt \ - && update-ca-certificates - RUN eatmydata apt-get -y build-dep openssh # Build fix for ARM64 and ARMHF /etc/debian_version diff --git a/sonic-slave-bullseye/Dockerfile.j2 b/sonic-slave-bullseye/Dockerfile.j2 index 4279501a4d0..acef2aa01ff 100644 --- a/sonic-slave-bullseye/Dockerfile.j2 +++ b/sonic-slave-bullseye/Dockerfile.j2 @@ -646,13 +646,6 @@ EXPOSE 22 RUN pip3 install parameterized==0.8.1 RUN pip3 install pyfakefs - -# Add Dell CA -RUN wget --no-check-certificate -O /usr/local/share/ca-certificates/dellca2018-bundle.crt \ - https://nsdn.artifactory.cec.lab.emc.com/artifactory/sonic-dell-cert/dellca2018-bundle.crt \ - && update-ca-certificates - - # Install docker engine 24 inside docker and enable experimental feature RUN apt-get update RUN eatmydata apt-get install -y \ diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 index c7ced00afb4..3acd9be01ab 100644 --- a/sonic-slave-buster/Dockerfile.j2 +++ b/sonic-slave-buster/Dockerfile.j2 @@ -606,6 +606,10 @@ RUN cd /usr/src/gtest && cmake . && make -C /usr/src/gtest RUN mkdir /var/run/sshd EXPOSE 22 +# Install depot-tools (for git-retry) +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools +ENV PATH /usr/share/depot_tools:$PATH + # Install dependencies for dhcp relay test RUN pip3 install parameterized==0.8.1 RUN pip3 install pyfakefs @@ -621,13 +625,6 @@ RUN eatmydata apt-get install -y \ {%- if CONFIGURED_ARCH == "armhf" %} RUN update-ca-certificates --fresh {%- endif %} - -RUN wget --no-check-certificate -O /usr/local/share/ca-certificates/dellca2018-bundle.crt https://nsdn.artifactory.cec.lab.emc.com/artifactory/sonic-dell-cert/dellca2018-bundle.crt && update-ca-certificates - -# Install depot-tools (for git-retry) -RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools -ENV PATH /usr/share/depot_tools:$PATH - RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - RUN add-apt-repository \ {%- if CROSS_BUILD_ENVIRON == "y" %} From a1788ae245b36886f9ccc2c6401a3eefb88fac2f Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 14 May 2025 22:50:13 +0100 Subject: [PATCH 12/26] Separate eventd and eventdb targets in the makefile. Set eventdb process startretries= 0 and expected exit code=0. This is since if no event types are defined in the event_profile, the process can exit. --- dockers/docker-eventd/supervisord.conf | 3 +++ src/sonic-eventd/Makefile | 23 ++++++++++++++++++----- src/sonic-eventd/src/eventconsume.cpp | 2 +- src/sonic-eventd/src/eventutils.cpp | 7 +++---- src/sonic-eventd/src/subdir.mk | 2 +- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/dockers/docker-eventd/supervisord.conf b/dockers/docker-eventd/supervisord.conf index def9cdefaa8..44734eefcd6 100644 --- a/dockers/docker-eventd/supervisord.conf +++ b/dockers/docker-eventd/supervisord.conf @@ -61,6 +61,9 @@ command=/usr/bin/eventdb priority=3 autostart=false autorestart=false +startsecs=0 +startretries=0 +exitcodes=0 stdout_logfile=syslog stderr_logfile=syslog dependent_startup=true diff --git a/src/sonic-eventd/Makefile b/src/sonic-eventd/Makefile index 2ee969b094b..31f35bb7460 100644 --- a/src/sonic-eventd/Makefile +++ b/src/sonic-eventd/Makefile @@ -33,14 +33,20 @@ endif -include rsyslog_plugin/subdir.mk -include rsyslog_plugin_tests/subdir.mk -all: sonic-eventd eventd-tool rsyslog-plugin +all: sonic-eventd eventd-tool rsyslog-plugin sonic-eventdb -test: eventd-tests rsyslog-plugin-tests +test: eventd-tests rsyslog-plugin-tests eventdb-tests -sonic-eventd: $(OBJS) $(EVENTDB_OBJS) +sonic-eventd: $(OBJS) @echo 'Building target: $@' @echo 'Invoking: G++ Linker' $(CC) $(LDFLAGS) -o $(EVENTD_TARGET) $(OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +sonic-eventdb: $(EVENTDB_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: G++ Linker' $(CC) $(LDFLAGS) -o $(EVENTDB_TARGET) $(EVENTDB_OBJS) $(LIBS) @echo 'Finished building target: $@' @echo ' ' @@ -59,13 +65,20 @@ rsyslog-plugin: $(RSYSLOG-PLUGIN_OBJS) @echo 'Finished building target: $@' @echo ' ' -eventd-tests: $(TEST_OBJS) $(EVENTDB_TEST_OBJS) +eventd-tests: $(TEST_OBJS) @echo 'Building target: $@' @echo 'Invoking: G++ Linker' $(CC) $(LDFLAGS) -o $(EVENTD_TEST) $(TEST_OBJS) $(LIBS) $(TEST_LIBS) - $(CC) $(LDFLAGS) -o $(EVENTDB_TEST) $(EVENTDB_TEST_OBJS) $(LIBS) $(TEST_LIBS) @echo 'Finished building target: $@' $(EVENTD_TEST) + @echo 'Finished running tests' + @echo ' ' + +eventdb-tests: $(EVENTDB_TEST_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: G++ Linker' + $(CC) $(LDFLAGS) -o $(EVENTDB_TEST) $(EVENTDB_TEST_OBJS) $(LIBS) $(TEST_LIBS) + @echo 'Finished building target: $@' $(EVENTDB_TEST) @echo 'Finished running tests' @echo ' ' diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index 5ef249e2761..a10cc639f70 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -105,7 +105,7 @@ void EventConsume::read_eventd_config(bool read_all) { // read from default map static_event_table.clear(); if (!parse(m_evProfile.c_str(), static_event_table)) { - SWSS_LOG_ERROR("Can not initialize event map"); + SWSS_LOG_NOTICE("Can not initialize event map"); closeSyslog(); exit(0); } diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp index 0a977b4475a..74d09191411 100644 --- a/src/sonic-eventd/src/eventutils.cpp +++ b/src/sonic-eventd/src/eventutils.cpp @@ -1,6 +1,4 @@ #include "eventutils.h" -#include -#include #include #include #include @@ -9,7 +7,8 @@ #include #include #include - +#include "logger.h" +#include "table.h" using namespace swss; using json = nlohmann::json; @@ -57,7 +56,7 @@ bool parse(const char *filename, EventMap& tmp_event_table) { file >> j; if (j["events"].size() == 0) { - SWSS_LOG_ERROR("No entries in 'events' field in %s", filename); + SWSS_LOG_NOTICE("No entries in 'events' field in %s", filename); return false; } diff --git a/src/sonic-eventd/src/subdir.mk b/src/sonic-eventd/src/subdir.mk index 1b03f3d4b04..c56e4b17e63 100644 --- a/src/sonic-eventd/src/subdir.mk +++ b/src/sonic-eventd/src/subdir.mk @@ -1,6 +1,6 @@ CC := g++ -TEST_OBJS += ./src/eventd.o ./src/eventconsume.o ./src/eventutils.o ./src/loghandler.o +TEST_OBJS += ./src/eventd.o EVENTDB_TEST_OBJS += ./src/eventd.o ./src/eventconsume.o ./src/eventutils.o ./src/loghandler.o OBJS += ./src/eventd.o ./src/main.o EVENTDB_OBJS += ./src/eventdb.o ./src/eventconsume.o ./src/loghandler.o ./src/eventutils.o From 51c2d261d5219f419f148306a928d0cae5c56f13 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Thu, 4 Sep 2025 23:59:21 +0100 Subject: [PATCH 13/26] Address review comments. Avoid using namespace std; in a header file to prevent namespace pollution; qualify standard types explicitly. Avoid non-async-signal-safe function inside signal handler. --- src/sonic-eventd/src/eventconsume.cpp | 12 ++++++--- src/sonic-eventd/src/eventconsume.h | 2 ++ src/sonic-eventd/src/eventdb.cpp | 3 +-- src/sonic-eventd/src/eventutils.cpp | 8 ++++++ src/sonic-eventd/src/eventutils.h | 36 +++++++++++++-------------- src/sonic-eventd/src/loghandler.h | 2 +- src/sonic-eventd/tests/eventdb_ut.cpp | 7 +++--- 7 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index a10cc639f70..a444cdc3119 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -18,6 +18,8 @@ unordered_map cal_lookup_map; // temporary map to hold merge of default map of events and any event profile EventMap static_event_table; +std::atomic reload_config_flag(false); // Definition and initialization + bool g_run = true; uint64_t seq_id = 0; uint64_t PURGE_SECONDS = 86400; @@ -81,11 +83,15 @@ void EventConsume::run() SWSS_LOG_ENTER(); event_handle_t hsub; - hsub = events_init_subscriber(); + hsub = events_init_subscriber(false, 3000); while (g_run) { event_receive_op_t evt; map_str_str_t evtOp; + if (reload_config_flag.load()) { + read_eventd_config(); + } + int rc = event_receive(hsub, evt); if (rc != 0) { SWSS_LOG_ERROR("Failed to receive rc=%d", rc); @@ -105,7 +111,7 @@ void EventConsume::read_eventd_config(bool read_all) { // read from default map static_event_table.clear(); if (!parse(m_evProfile.c_str(), static_event_table)) { - SWSS_LOG_NOTICE("Can not initialize event map"); + SWSS_LOG_INFO("Can not initialize event map"); closeSyslog(); exit(0); } @@ -236,7 +242,7 @@ void EventConsume::handle_notification(const event_receive_op_t& evt) updateEventStatistics(true, is_raise, is_ack, is_clear); // raise a syslog message - writeToSyslog(ev_id, (int)(SYSLOG_SEVERITY.find(ev_sev)->second), ev_type, ev_act, ev_msg, ev_static_msg); + writeToSyslog(ev_id.c_str(), (int)(SYSLOG_SEVERITY.find(ev_sev)->second), ev_type.c_str(), ev_act.c_str(), ev_msg.c_str(), ev_static_msg.c_str()); return; } diff --git a/src/sonic-eventd/src/eventconsume.h b/src/sonic-eventd/src/eventconsume.h index 36e75f7dac9..ec5d8510679 100644 --- a/src/sonic-eventd/src/eventconsume.h +++ b/src/sonic-eventd/src/eventconsume.h @@ -11,6 +11,8 @@ using namespace swss; using namespace std; +extern std::atomic reload_config_flag; + class EventConsume { public: diff --git a/src/sonic-eventd/src/eventdb.cpp b/src/sonic-eventd/src/eventdb.cpp index 9b162416bf3..246bbe4fb5a 100644 --- a/src/sonic-eventd/src/eventdb.cpp +++ b/src/sonic-eventd/src/eventdb.cpp @@ -4,10 +4,9 @@ static EventConsume *evtd_instance = NULL; void signalHandler(const int signal) { - SWSS_LOG_NOTICE("in signalHandler"); if (signal == SIGINT) { - evtd_instance->read_eventd_config(); + reload_config_flag.store(true); } } diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp index 74d09191411..bcc988b7c74 100644 --- a/src/sonic-eventd/src/eventutils.cpp +++ b/src/sonic-eventd/src/eventutils.cpp @@ -11,6 +11,8 @@ #include "table.h" using namespace swss; +using namespace std; + using json = nlohmann::json; bool isValidSeverity(string severityStr) { @@ -33,6 +35,12 @@ bool parse_config(const char *filename, unsigned int& days, unsigned int& count) days = EHT_MAX_DAYS; count = EHT_MAX_ELEMS; std::ifstream ifs(filename); + + if (!ifs.is_open()) { + std::cerr << "Error: File does not exist or cannot be opened." << std::endl; + return false; + } + json j = json::parse(ifs); for (json::iterator it = j.begin(); it != j.end(); ++it) { if(it.key() == "max-days") { diff --git a/src/sonic-eventd/src/eventutils.h b/src/sonic-eventd/src/eventutils.h index 8ec6d39558b..40633893f4f 100644 --- a/src/sonic-eventd/src/eventutils.h +++ b/src/sonic-eventd/src/eventutils.h @@ -4,21 +4,19 @@ #include #include -using namespace std; +const std::string EVENT_SEVERITY_CRITICAL_STR = "CRITICAL"; +const std::string EVENT_SEVERITY_MAJOR_STR = "MAJOR"; +const std::string EVENT_SEVERITY_MINOR_STR = "MINOR"; +const std::string EVENT_SEVERITY_WARNING_STR = "WARNING"; +const std::string EVENT_SEVERITY_INFORMATIONAL_STR = "INFORMATIONAL"; -const string EVENT_SEVERITY_CRITICAL_STR = "CRITICAL"; -const string EVENT_SEVERITY_MAJOR_STR = "MAJOR"; -const string EVENT_SEVERITY_MINOR_STR = "MINOR"; -const string EVENT_SEVERITY_WARNING_STR = "WARNING"; -const string EVENT_SEVERITY_INFORMATIONAL_STR = "INFORMATIONAL"; +const std::string EVENT_ENABLE_TRUE_STR = "true"; +const std::string EVENT_ENABLE_FALSE_STR = "false"; -const string EVENT_ENABLE_TRUE_STR = "true"; -const string EVENT_ENABLE_FALSE_STR = "false"; - -const string EVENT_ACTION_RAISE_STR = "RAISE"; -const string EVENT_ACTION_CLEAR_STR = "CLEAR"; -const string EVENT_ACTION_ACK_STR = "ACKNOWLEDGE"; -const string EVENT_ACTION_UNACK_STR = "UNACKNOWLEDGE"; +const std::string EVENT_ACTION_RAISE_STR = "RAISE"; +const std::string EVENT_ACTION_CLEAR_STR = "CLEAR"; +const std::string EVENT_ACTION_ACK_STR = "ACKNOWLEDGE"; +const std::string EVENT_ACTION_UNACK_STR = "UNACKNOWLEDGE"; constexpr char EVENTD_DEFAULT_MAP_FILE[] = "/etc/evprofile/default.json"; @@ -27,16 +25,16 @@ constexpr size_t EHT_MAX_DAYS = 30; constexpr char EVENTD_CONF_FILE[] = "/etc/eventd.json"; typedef struct EventInfo_t { - string severity; - string enable; - string static_event_msg; + std::string severity; + std::string enable; + std::string static_event_msg; } EventInfo; //unordered_map static_event_table; -typedef unordered_map EventMap; +typedef std::unordered_map EventMap; -bool isValidSeverity(string severityStr); -bool isValidEnable(string enableStr); +bool isValidSeverity(std::string severityStr); +bool isValidEnable(std::string enableStr); bool parse_config(const char *filename, unsigned int& days, unsigned int& count); bool parse(const char *filename, EventMap& tmp_event_table); diff --git a/src/sonic-eventd/src/loghandler.h b/src/sonic-eventd/src/loghandler.h index 1e98a940152..2be0f65267a 100644 --- a/src/sonic-eventd/src/loghandler.h +++ b/src/sonic-eventd/src/loghandler.h @@ -1,5 +1,5 @@ #include extern "C" void openSyslog(); -extern "C" void writeToSyslog(std::string ev_id, int ev_sev, std::string ev_type, std::string ev_act, std::string ev_msg, std::string ev_static_msg); +extern "C" void writeToSyslog(const char* ev_id, int ev_sev, const char* ev_type, const char* ev_act, const char* ev_msg, const char* ev_static_msg); extern "C" void closeSyslog(); diff --git a/src/sonic-eventd/tests/eventdb_ut.cpp b/src/sonic-eventd/tests/eventdb_ut.cpp index a3e9e4aba8f..a088ba5df35 100644 --- a/src/sonic-eventd/tests/eventdb_ut.cpp +++ b/src/sonic-eventd/tests/eventdb_ut.cpp @@ -30,7 +30,7 @@ extern EventMap static_event_table; string existing_file = "./tests//eventdb_database_config.json"; string nonexisting_file = "./tests//database_config_nonexisting.json"; -string global_existing_file = "./tests//eventdb_database_global.json"; +string global_existing_file = "./tests//eventdb_database_config_global.json"; @@ -397,7 +397,7 @@ class SwsscommonEnvironment : public ::testing::Environment { EXPECT_FALSE(SonicDBConfig::isGlobalInit()); // Call an API which actually needs the data populated by SonicDBConfig::initializeGlobalConfig -// EXPECT_THROW(SonicDBConfig::getDbId(EVENT_DB, TEST_NAMESPACE), runtime_error); + // EXPECT_THROW(SonicDBConfig::getDbId(EVENT_DB, TEST_NAMESPACE), runtime_error); // load local global file, init should be true SonicDBConfig::initializeGlobalConfig(global_existing_file); @@ -405,8 +405,7 @@ class SwsscommonEnvironment : public ::testing::Environment { EXPECT_TRUE(SonicDBConfig::isGlobalInit()); // Call an API with wrong namespace passed - cout << "INIT: Invoking SonicDBConfig::getDbId(APPL_DB, invalid)" << endl; -// EXPECT_THROW(SonicDBConfig::getDbId(EVENT_DB, INVALID_NAMESPACE), out_of_range); + // EXPECT_THROW(SonicDBConfig::getDbId(EVENT_DB, INVALID_NAMESPACE), out_of_range); // Get this info handy try From 446efe71fcd183cb2400609e2cefd9322a070160 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Tue, 16 Sep 2025 00:28:27 +0100 Subject: [PATCH 14/26] Updates. --- src/sonic-eventd/src/eventconsume.cpp | 12 ++++++---- src/sonic-eventd/src/loghandler.cpp | 20 ++++++++++++----- src/sonic-eventd/tests/eventdb_ut.cpp | 32 +++++++++++++-------------- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index a444cdc3119..3dd4ff19bf5 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -82,20 +82,24 @@ void EventConsume::run() { SWSS_LOG_ENTER(); - event_handle_t hsub; - hsub = events_init_subscriber(false, 3000); + event_handle_t hsub = events_init_subscriber(false, 3000); + + if (hsub == nullptr) { + SWSS_LOG_ERROR("Failed to initialize event subscriber"); + return; + } while (g_run) { event_receive_op_t evt; map_str_str_t evtOp; if (reload_config_flag.load()) { read_eventd_config(); + reload_config_flag.store(false); } int rc = event_receive(hsub, evt); if (rc != 0) { - SWSS_LOG_ERROR("Failed to receive rc=%d", rc); - continue; + continue; } handle_notification(evt); } diff --git a/src/sonic-eventd/src/loghandler.cpp b/src/sonic-eventd/src/loghandler.cpp index d560ccc2e0e..e010ac540aa 100755 --- a/src/sonic-eventd/src/loghandler.cpp +++ b/src/sonic-eventd/src/loghandler.cpp @@ -1,13 +1,23 @@ #include #include +#include + + + +// Safe fallback for null or empty C-style strings +const char* safe(const char* s) { + return (s && std::strlen(s) > 0) ? s : ""; +} + extern "C" void openSyslog() { openlog (NULL, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL4); } -extern "C" void writeToSyslog(std::string ev_id, int ev_sev, std::string ev_type, std::string ev_act, std::string ev_msg, std::string ev_static_msg) { +extern "C" void writeToSyslog(char* ev_id, int ev_sev, char* ev_type, char* ev_act, char* ev_msg, char* ev_static_msg) { int SYSLOG_FACILITY = LOG_LOCAL4; - if (ev_act.empty()) { + + if (!ev_act || std::strlen(ev_act) == 0) { const char LOG_FORMAT[] = "[%s], %%%s: %s %s"; // event Type // Event Name @@ -16,8 +26,7 @@ extern "C" void writeToSyslog(std::string ev_id, int ev_sev, std::string ev_type // raise a syslog message syslog(LOG_MAKEPRI(ev_sev, SYSLOG_FACILITY), LOG_FORMAT, - ev_type.c_str(), - ev_id.c_str(), ev_static_msg.c_str(), ev_msg.c_str()); + safe(ev_type), safe(ev_id), safe(ev_static_msg), safe(ev_msg)); } else { const char LOG_FORMAT[] = "[%s] (%s), %%%s: %s %s"; // event Type @@ -27,8 +36,7 @@ extern "C" void writeToSyslog(std::string ev_id, int ev_sev, std::string ev_type // Dynamic Desc // raise a syslog message syslog(LOG_MAKEPRI(ev_sev, SYSLOG_FACILITY), LOG_FORMAT, - ev_type.c_str(), ev_act.c_str(), - ev_id.c_str(), ev_static_msg.c_str(), ev_msg.c_str()); + safe(ev_type), safe(ev_act), safe(ev_id), safe(ev_static_msg), safe(ev_msg)); } } diff --git a/src/sonic-eventd/tests/eventdb_ut.cpp b/src/sonic-eventd/tests/eventdb_ut.cpp index a088ba5df35..8e943639edb 100644 --- a/src/sonic-eventd/tests/eventdb_ut.cpp +++ b/src/sonic-eventd/tests/eventdb_ut.cpp @@ -106,32 +106,32 @@ class EventDbFixture : public ::testing::Test { DBConnector eventDb("EVENT_DB", 0, true); //delete any entries in the EVENT_DB delete_evdb(eventDb); - - try - { - /* Start Eventdb in a separate thread*/ - evtConsume= new EventConsume(&eventDb, event_profile, event_db_profile); - thread thr(&EventConsume::run, evtConsume); - thr.detach(); - } - catch (exception &e) - { - printf("EventDbFixture::SetUP: Unable to get DB Connector, e=(%s)\n", e.what()); - } + evtConsume= new EventConsume(&eventDb, event_profile, event_db_profile); + consumerThread = std::thread(&EventConsume::run, evtConsume); } void TearDown() override { + g_run = false; + + if (consumerThread.joinable()) { + consumerThread.join(); // Wait for clean exit + } + delete evtConsume; - evtConsume = NULL; + evtConsume = nullptr; + delete pxy; - pxy= NULL; + pxy= nullptr; + zmq_ctx_term(zctx); - zctx = NULL; + zctx = nullptr; + clear_eventdb_data(); } EventConsume *evtConsume; void *zctx; eventd_proxy *pxy; + std::thread consumerThread; }; @@ -370,7 +370,7 @@ TEST_F(EventDbFixture, rollover_purge) g_run = false; wr_evts.push_back(create_ev(303, 3, "SYSTEM_STATE", "NOTIFY", verify_data)); run_pub(mock_pub, wr_source, wr_evts); - this_thread::sleep_for(chrono::milliseconds(2000)); + this_thread::sleep_for(chrono::milliseconds(2000)); zmq_close(mock_pub); printf("Rollover purge TEST completed\n"); } From 0272ac6c15e62313c86f8783328adf2a6135469e Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Tue, 16 Sep 2025 09:17:49 +0100 Subject: [PATCH 15/26] Remove debug statements. --- src/sonic-eventd/src/eventconsume.cpp | 13 +++++-------- src/sonic-eventd/src/loghandler.cpp | 13 ++++++++----- src/sonic-eventd/src/loghandler.h | 4 +++- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index 3dd4ff19bf5..9ef12c32725 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -82,7 +82,7 @@ void EventConsume::run() { SWSS_LOG_ENTER(); - event_handle_t hsub = events_init_subscriber(false, 3000); + event_handle_t hsub = events_init_subscriber(); if (hsub == nullptr) { SWSS_LOG_ERROR("Failed to initialize event subscriber"); @@ -99,6 +99,7 @@ void EventConsume::run() int rc = event_receive(hsub, evt); if (rc != 0) { + SWSS_LOG_ERROR("Failed to receive rc=%d", rc); continue; } handle_notification(evt); @@ -129,8 +130,6 @@ void EventConsume::read_eventd_config(bool read_all) { void EventConsume::handle_notification(const event_receive_op_t& evt) { - SWSS_LOG_ENTER(); - string ev_id, ev_msg, ev_src, ev_act, ev_timestamp, ev_type("EVENT"), ev_static_msg(""), ev_reckey; string ev_sev = string(EVENT_SEVERITY_INFORMATIONAL_STR); @@ -246,7 +245,8 @@ void EventConsume::handle_notification(const event_receive_op_t& evt) updateEventStatistics(true, is_raise, is_ack, is_clear); // raise a syslog message - writeToSyslog(ev_id.c_str(), (int)(SYSLOG_SEVERITY.find(ev_sev)->second), ev_type.c_str(), ev_act.c_str(), ev_msg.c_str(), ev_static_msg.c_str()); + writeToSyslog(ev_id.c_str(), (int)(SYSLOG_SEVERITY.find(ev_sev)->second), ev_type.c_str(), ev_act.c_str(), + ev_src.c_str(), ev_msg.c_str(), ev_static_msg.c_str()); return; } @@ -384,7 +384,7 @@ void EventConsume::modifyEventStats(string seq_id) { } void EventConsume::purge_events() { - SWSS_LOG_ENTER(); + uint32_t size = event_history_list.size(); while (size >= m_count) { @@ -501,15 +501,12 @@ void EventConsume::fetchFieldValues(const event_receive_op_t& evt, if (idx.first == "type-id") { ev_id = idx.second; vec.push_back(FieldValueTuple("type-id", ev_id)); - SWSS_LOG_DEBUG("type-id: <%s> ", ev_id.c_str()); } else if (idx.first == "text") { ev_msg = idx.second; vec.push_back(FieldValueTuple("text", ev_msg)); - SWSS_LOG_DEBUG("text: <%s> ", ev_msg.c_str()); } else if (idx.first == "resource") { ev_src = idx.second; vec.push_back(idx); - SWSS_LOG_DEBUG("resource: <%s> ", ev_src.c_str()); } else if (idx.first == "action") { ev_act = idx.second; // for events, action is empty diff --git a/src/sonic-eventd/src/loghandler.cpp b/src/sonic-eventd/src/loghandler.cpp index e010ac540aa..84b7fec7a46 100755 --- a/src/sonic-eventd/src/loghandler.cpp +++ b/src/sonic-eventd/src/loghandler.cpp @@ -14,29 +14,32 @@ extern "C" void openSyslog() { openlog (NULL, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL4); } -extern "C" void writeToSyslog(char* ev_id, int ev_sev, char* ev_type, char* ev_act, char* ev_msg, char* ev_static_msg) { +extern "C" void writeToSyslog(char* ev_id, int ev_sev, char* ev_type, char* ev_act, + char* ev_src, char* ev_msg, char* ev_static_msg) { int SYSLOG_FACILITY = LOG_LOCAL4; if (!ev_act || std::strlen(ev_act) == 0) { - const char LOG_FORMAT[] = "[%s], %%%s: %s %s"; + const char LOG_FORMAT[] = "[%s], %%%s: %%%%%s: %s %s"; // event Type // Event Name + // Event Source // Static Desc // Dynamic Desc // raise a syslog message syslog(LOG_MAKEPRI(ev_sev, SYSLOG_FACILITY), LOG_FORMAT, - safe(ev_type), safe(ev_id), safe(ev_static_msg), safe(ev_msg)); + safe(ev_type), safe(ev_id), safe(ev_src), safe(ev_static_msg), safe(ev_msg)); } else { - const char LOG_FORMAT[] = "[%s] (%s), %%%s: %s %s"; + const char LOG_FORMAT[] = "[%s] (%s), %%%s: %%%%%s: %s %s"; // event Type // event action // Event Name + // Event Source // Static Desc // Dynamic Desc // raise a syslog message syslog(LOG_MAKEPRI(ev_sev, SYSLOG_FACILITY), LOG_FORMAT, - safe(ev_type), safe(ev_act), safe(ev_id), safe(ev_static_msg), safe(ev_msg)); + safe(ev_type), safe(ev_act), safe(ev_id), safe(ev_src), safe(ev_static_msg), safe(ev_msg)); } } diff --git a/src/sonic-eventd/src/loghandler.h b/src/sonic-eventd/src/loghandler.h index 2be0f65267a..bb55d1bb6d7 100644 --- a/src/sonic-eventd/src/loghandler.h +++ b/src/sonic-eventd/src/loghandler.h @@ -1,5 +1,7 @@ #include extern "C" void openSyslog(); -extern "C" void writeToSyslog(const char* ev_id, int ev_sev, const char* ev_type, const char* ev_act, const char* ev_msg, const char* ev_static_msg); +extern "C" void writeToSyslog(const char* ev_id, int ev_sev, const char* ev_type, + const char* ev_act, const char* ev_src, const char* ev_msg, + const char* ev_static_msg); extern "C" void closeSyslog(); From f4b5e87cd5a4bd0129c07437277009fbca201bdd Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 17 Sep 2025 00:46:49 +0100 Subject: [PATCH 16/26] Add script to start eventdb. Script starts eventdb only if atleast one event is defined in the profile. Add validation around json operations. --- dockers/docker-eventd/Dockerfile.j2 | 1 + dockers/docker-eventd/eventdb_wrapper.sh | 18 +++++++++++ dockers/docker-eventd/supervisord.conf | 2 +- src/sonic-eventd/src/eventutils.cpp | 40 ++++++++++++++++++------ 4 files changed, 50 insertions(+), 11 deletions(-) create mode 100755 dockers/docker-eventd/eventdb_wrapper.sh diff --git a/dockers/docker-eventd/Dockerfile.j2 b/dockers/docker-eventd/Dockerfile.j2 index 59d915ecfcc..a7d811f751d 100644 --- a/dockers/docker-eventd/Dockerfile.j2 +++ b/dockers/docker-eventd/Dockerfile.j2 @@ -27,6 +27,7 @@ COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] COPY ["critical_processes", "/etc/supervisor"] COPY ["*.json", "/etc/rsyslog.d/rsyslog_plugin_conf/"] COPY ["files/rsyslog_plugin.conf.j2", "/etc/rsyslog.d/rsyslog_plugin_conf/"] +COPY ["eventdb_wrapper.sh", "/usr/bin"] RUN j2 -f json /etc/rsyslog.d/rsyslog_plugin_conf/rsyslog_plugin.conf.j2 /etc/rsyslog.d/rsyslog_plugin_conf/host_events_info.json > /etc/rsyslog.d/rsyslog_plugin_conf/host_events.conf RUN j2 -f json /etc/rsyslog.d/rsyslog_plugin_conf/rsyslog_plugin.conf.j2 /etc/rsyslog.d/rsyslog_plugin_conf/bgp_events_info.json > /etc/rsyslog.d/rsyslog_plugin_conf/bgp_events.conf diff --git a/dockers/docker-eventd/eventdb_wrapper.sh b/dockers/docker-eventd/eventdb_wrapper.sh new file mode 100755 index 00000000000..836c69f0dde --- /dev/null +++ b/dockers/docker-eventd/eventdb_wrapper.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +JSON_FILE="/etc/evprofile/default.json" + +# Check if file exists and is not empty +if [ -s "$JSON_FILE" ]; then + # Check if "events" is defined and has at least one entry + if jq -e '.events and (.events | length > 0)' "$JSON_FILE" > /dev/null; then + echo "Valid events found. Starting eventdb." + exec /usr/bin/eventdb + else + echo "'events' list is missing or empty. Skipping eventdb start." + exit 0 + fi +else + echo "JSON file missing or empty. Skipping eventdb start." + exit 0 +fi diff --git a/dockers/docker-eventd/supervisord.conf b/dockers/docker-eventd/supervisord.conf index 44734eefcd6..65fa1b90b92 100644 --- a/dockers/docker-eventd/supervisord.conf +++ b/dockers/docker-eventd/supervisord.conf @@ -57,7 +57,7 @@ dependent_startup=true dependent_startup_wait_for=start:exited [program:eventdb] -command=/usr/bin/eventdb +command=/usr/bin/eventdb_wrapper.sh priority=3 autostart=false autorestart=false diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp index bcc988b7c74..94a80bd4ba2 100644 --- a/src/sonic-eventd/src/eventutils.cpp +++ b/src/sonic-eventd/src/eventutils.cpp @@ -37,11 +37,18 @@ bool parse_config(const char *filename, unsigned int& days, unsigned int& count) std::ifstream ifs(filename); if (!ifs.is_open()) { - std::cerr << "Error: File does not exist or cannot be opened." << std::endl; + std::cerr << "Failed to open file: " << filename << std::endl; return false; } - json j = json::parse(ifs); + json j; + try { + j = json::parse(ifs); + } + catch (const std::exception &e) { + SWSS_LOG_ERROR("Error parsing config file %s:%s ", filename, e.what()); + return false; + } for (json::iterator it = j.begin(); it != j.end(); ++it) { if(it.key() == "max-days") { days = it.value(); @@ -54,27 +61,40 @@ bool parse_config(const char *filename, unsigned int& days, unsigned int& count) } bool parse(const char *filename, EventMap& tmp_event_table) { - ifstream fs(filename); - if (!fs.is_open()) { + ifstream file(filename); + if (!file.is_open()) { + SWSS_LOG_ERROR("Failed to open file: %s", filename); return false; } - fstream file(filename, fstream::in); json j; - file >> j; + try { + file >> j; + } + catch (const std::exception &e) { + SWSS_LOG_ERROR("Error parsing profile file %s:%s ", filename, e.what()); + return false; + } - if (j["events"].size() == 0) { + if (!j.contains("events") || j["events"].empty()) { SWSS_LOG_NOTICE("No entries in 'events' field in %s", filename); return false; } - for (size_t i = 0; i < j["events"].size(); i++) { - auto elem = j["events"][i]; + + for (const auto& elem : j["events"]) { + if (!elem.contains("name") || !elem.contains("severity") || + !elem.contains("enable")) { + SWSS_LOG_ERROR("Missing required fields in event entry in %s", filename); + continue; + } struct EventInfo_t ev_info; string ev_name = elem["name"]; ev_info.severity = elem["severity"]; ev_info.enable = elem["enable"]; - ev_info.static_event_msg = elem["message"]; + if (elem.contains("message")) { + ev_info.static_event_msg = elem["message"]; + } tmp_event_table.emplace(ev_name, ev_info); } From 19ee70f3db477544aef215f88a5edb6044551be9 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Mon, 10 Nov 2025 22:34:30 +0000 Subject: [PATCH 17/26] Handle specific exception while parsing json file. Fix indentation. --- src/sonic-eventd/src/eventutils.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp index 94a80bd4ba2..123b203b3fb 100644 --- a/src/sonic-eventd/src/eventutils.cpp +++ b/src/sonic-eventd/src/eventutils.cpp @@ -34,21 +34,26 @@ bool isValidEnable(string enableStr) { bool parse_config(const char *filename, unsigned int& days, unsigned int& count) { days = EHT_MAX_DAYS; count = EHT_MAX_ELEMS; - std::ifstream ifs(filename); + ifstream ifs(filename); if (!ifs.is_open()) { - std::cerr << "Failed to open file: " << filename << std::endl; + SWSS_LOG_ERROR("Failed to open file: %s", filename); return false; } json j; try { - j = json::parse(ifs); + j = json::parse(ifs); } - catch (const std::exception &e) { + catch (const json::parse_error &e) { SWSS_LOG_ERROR("Error parsing config file %s:%s ", filename, e.what()); return false; } + catch (const std::exception &e) { + SWSS_LOG_ERROR("Unexpected error parsing config file %s: %s", filename, e.what()); + return false; + } + for (json::iterator it = j.begin(); it != j.end(); ++it) { if(it.key() == "max-days") { days = it.value(); @@ -69,12 +74,16 @@ bool parse(const char *filename, EventMap& tmp_event_table) { json j; try { - file >> j; + j = json::parse(file); } - catch (const std::exception &e) { + catch (const json::parse_error &e) { SWSS_LOG_ERROR("Error parsing profile file %s:%s ", filename, e.what()); return false; } + catch (const std::exception &e) { + SWSS_LOG_ERROR("Unexpected error parsing config file %s: %s", filename, e.what()); + return false; + } if (!j.contains("events") || j["events"].empty()) { SWSS_LOG_NOTICE("No entries in 'events' field in %s", filename); From bfb3048e58da7e475d8145c192778f0e2582fc76 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 12 Nov 2025 00:18:04 +0000 Subject: [PATCH 18/26] Add the new yangs to setup.py --- src/sonic-yang-models/setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sonic-yang-models/setup.py b/src/sonic-yang-models/setup.py index 3f1ea6f0608..156008307a6 100644 --- a/src/sonic-yang-models/setup.py +++ b/src/sonic-yang-models/setup.py @@ -217,6 +217,8 @@ def print_yang_files_validation_report(yang_files_list): 'sonic-xcvrd-log.yang', 'sonic-ztp.yang', 'sonic-fast-linkup.yang', + 'sonic-alarm.yang', + 'sonic-event.yang', ] class my_build_py(build_py): From 88a99190f9255e4a1334a36e209fb3c6d3ac60c2 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 12 Nov 2025 20:52:54 +0000 Subject: [PATCH 19/26] Add the sonic-alarm.yang and sonic-event.yang as NON_CONF_YANG_FILES --- .../tests/libyang-python-tests/test_sonic_yang.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py index bdabcfc13ee..f7543ea836d 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py @@ -519,12 +519,12 @@ def test_validate_yang_models(self, sonic_yang_data): test_file = sonic_yang_data['test_file'] syc = sonic_yang_data['syc'] # Currently only 3 YANG files are not directly related to config, along with event YANG models - # which are: sonic-extension.yang, sonic-types.yang and sonic-bgp-common.yang. Hard coding - # it right now. + # which are: sonic-extension.yang, sonic-types.yang, sonic-bgp-common.yang, sonic-event.yang + # and sonic-alarm.yang. Hard coding it right now. # event YANG models do not map directly to config_db and are included to NON_CONFIG_YANG_FILES at run time # If any more such helper yang files are added, we need to update here. EVENT_YANG_FILES = sum(1 for yang_model in syc.yangFiles if 'sonic-events' in yang_model) - NON_CONFIG_YANG_FILES = 3 + EVENT_YANG_FILES + NON_CONFIG_YANG_FILES = 5 + EVENT_YANG_FILES # read config jIn = self.readIjsonInput(test_file, 'SAMPLE_CONFIG_DB_JSON') jIn = json.loads(jIn) From 9d053ee3d70c451f7991b72eb91b8d196d202835 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:11:28 +0000 Subject: [PATCH 20/26] Address review comments. Fix event purge time computation. Fix stats update on purge. --- src/sonic-eventd/src/eventconsume.cpp | 10 +++++----- src/sonic-eventd/src/loghandler.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index 9ef12c32725..cdcba5ede29 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -91,7 +91,7 @@ void EventConsume::run() while (g_run) { event_receive_op_t evt; - map_str_str_t evtOp; + if (reload_config_flag.load()) { read_eventd_config(); reload_config_flag.store(false); @@ -390,8 +390,8 @@ void EventConsume::purge_events() { while (size >= m_count) { pair oldest_entry = event_history_list.top(); SWSS_LOG_NOTICE("Rollover based on count(%d/%d). Deleting %lu", size, m_count, oldest_entry.first); - m_eventTable.del(to_string(oldest_entry.first)); modifyEventStats(to_string(oldest_entry.first)); + m_eventTable.del(to_string(oldest_entry.first)); event_history_list.pop(); --size; } @@ -405,8 +405,8 @@ void EventConsume::purge_events() { if ((tnow_seconds - old_seconds) > PURGE_SECONDS) { SWSS_LOG_NOTICE("Rollover based on time (%lu days). Deleting %lu.. now %u old %u", (PURGE_SECONDS/m_days), oldest_entry.second, tnow_seconds, old_seconds); - m_eventTable.del(to_string(oldest_entry.first)); modifyEventStats(to_string(oldest_entry.first)); + m_eventTable.del(to_string(oldest_entry.first)); event_history_list.pop(); } else { return; @@ -422,8 +422,8 @@ void EventConsume::read_config_and_purge() { parse_config(m_dbProfile.c_str(), m_days, m_count); SWSS_LOG_NOTICE("max-days %d max-records %d", m_days, m_count); - // update the nanosecond limit - PURGE_SECONDS *= m_days; + // calculate purge interval in seconds, 84600 seconds per day + PURGE_SECONDS = static_cast(m_days) * 86400; // purge events based on # of days purge_events(); diff --git a/src/sonic-eventd/src/loghandler.cpp b/src/sonic-eventd/src/loghandler.cpp index 84b7fec7a46..4587241e322 100755 --- a/src/sonic-eventd/src/loghandler.cpp +++ b/src/sonic-eventd/src/loghandler.cpp @@ -14,8 +14,8 @@ extern "C" void openSyslog() { openlog (NULL, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL4); } -extern "C" void writeToSyslog(char* ev_id, int ev_sev, char* ev_type, char* ev_act, - char* ev_src, char* ev_msg, char* ev_static_msg) { +extern "C" void writeToSyslog(const char* ev_id, int ev_sev, const char* ev_type, const char* ev_act, + const char* ev_src, const char* ev_msg, const char* ev_static_msg) { int SYSLOG_FACILITY = LOG_LOCAL4; if (!ev_act || std::strlen(ev_act) == 0) { From 57afe9a9dda72dd9eb4e1abd426355799e274bfc Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Wed, 15 Apr 2026 23:58:52 -0700 Subject: [PATCH 21/26] Resolve build errors. --- src/sonic-eventd/Makefile | 6 +++--- src/sonic-eventd/debian/control | 2 +- src/sonic-eventd/src/eventconsume.cpp | 2 +- src/sonic-eventd/src/eventconsume.h | 6 +++--- src/sonic-eventd/src/eventutils.cpp | 4 ++-- src/sonic-eventd/tests/eventdb_ut.cpp | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/sonic-eventd/Makefile b/src/sonic-eventd/Makefile index 31f35bb7460..5920a8f8723 100644 --- a/src/sonic-eventd/Makefile +++ b/src/sonic-eventd/Makefile @@ -16,9 +16,9 @@ CP := cp MKDIR := mkdir CC := g++ LIBS := -lhiredis -lswsscommon -lzmq -lboost_serialization -llua5.1 -TEST_LIBS := -L/usr/src/gtest -lgtest -lgtest_main -lgmock -lgmock_main +TEST_LIBS := -lgtest -lgtest_main -lgmock -lgmock_main -CFLAGS += -Wall -std=c++17 -fPIE +CFLAGS += -Wall -std=c++17 -fPIE -I/usr/include/swss PWD := $(shell pwd) ifneq ($(MAKECMDGOALS),clean) @@ -111,7 +111,7 @@ deinstall: $(RM) -rf $(DESTDIR)/etc clean: - -$(RM) $(EVENTD_TARGET) $(OBJS) $(EVENTD_TOOL) $(TOOL_OBJS) $(RSYSLOG-PLUGIN_TARGET) $(RSYSLOG-PLUGIN_OBJS) $(EVENTD_TEST) $(TEST_OBJS) $(RSYSLOG-PLUGIN_TEST) $(RSYSLOG-PLUGIN-TEST_OBJS) $(C_DEPS) + -$(RM) $(EVENTD_TARGET) $(OBJS) $(EVENTD_TOOL) $(TOOL_OBJS) $(RSYSLOG-PLUGIN_TARGET) $(RSYSLOG-PLUGIN_OBJS) $(EVENTD_TEST) $(TEST_OBJS) $(EVENTDB_TEST) $(EVENTDB_TEST_OBJS) $(RSYSLOG-PLUGIN_TEST) $(RSYSLOG-PLUGIN-TEST_OBJS) $(C_DEPS) -@echo ' ' .PHONY: all clean dependents diff --git a/src/sonic-eventd/debian/control b/src/sonic-eventd/debian/control index ebf61a9f69b..e6b207d9e09 100644 --- a/src/sonic-eventd/debian/control +++ b/src/sonic-eventd/debian/control @@ -2,7 +2,7 @@ Source: sonic-eventd Section: devel Priority: optional Maintainer: Renuka Manavalan -Build-Depends: debhelper (>= 12.0.0), libswsscommon-dev, liblua5.1-0, libzmq3-dev, libboost-serialization1.83-dev +Build-Depends: debhelper (>= 12.0.0), libswsscommon-dev, liblua5.1-0, libzmq3-dev, libboost-serialization1.83-dev, libgtest-dev, libgmock-dev Standards-Version: 3.9.3 Homepage: https://github.com/Azure/sonic-buildimage XS-Go-Import-Path: github.com/Azure/sonic-buildimage diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index cdcba5ede29..7b67f2b58b9 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -7,7 +7,7 @@ #include "eventconsume.h" #include "loghandler.h" #include "eventutils.h" -#include "events_common.h" +#include using namespace std::chrono; diff --git a/src/sonic-eventd/src/eventconsume.h b/src/sonic-eventd/src/eventconsume.h index ec5d8510679..35e93855f1a 100644 --- a/src/sonic-eventd/src/eventconsume.h +++ b/src/sonic-eventd/src/eventconsume.h @@ -3,10 +3,10 @@ #include #include -#include "events.h" +#include #include "eventutils.h" -#include "dbconnector.h" -#include "subscriberstatetable.h" +#include +#include using namespace swss; using namespace std; diff --git a/src/sonic-eventd/src/eventutils.cpp b/src/sonic-eventd/src/eventutils.cpp index 123b203b3fb..ad674379896 100644 --- a/src/sonic-eventd/src/eventutils.cpp +++ b/src/sonic-eventd/src/eventutils.cpp @@ -7,8 +7,8 @@ #include #include #include -#include "logger.h" -#include "table.h" +#include +#include using namespace swss; using namespace std; diff --git a/src/sonic-eventd/tests/eventdb_ut.cpp b/src/sonic-eventd/tests/eventdb_ut.cpp index 8e943639edb..03185a894f7 100644 --- a/src/sonic-eventd/tests/eventdb_ut.cpp +++ b/src/sonic-eventd/tests/eventdb_ut.cpp @@ -1,9 +1,9 @@ #include #include "gtest/gtest.h" -#include "events_common.h" -#include "events.h" +#include +#include #include -#include "dbconnector.h" +#include #include #include From 56fa563c36476a9176223ff540250c25db622dea Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:39:46 -0700 Subject: [PATCH 22/26] fix: Fix review comments - Remove namespace pollution from eventconsume.h and fix build issues - Add explicit swss:: and std:: prefixes to maintain type safety - Optimize clearAckAlarmStatistic with early exit flag --- src/sonic-eventd/Makefile | 2 +- src/sonic-eventd/src/eventconsume.cpp | 33 +++++++++++---------- src/sonic-eventd/src/eventconsume.h | 42 +++++++++++++-------------- src/sonic-eventd/src/eventdb.cpp | 11 +++---- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/sonic-eventd/Makefile b/src/sonic-eventd/Makefile index 5920a8f8723..f12c7947c17 100644 --- a/src/sonic-eventd/Makefile +++ b/src/sonic-eventd/Makefile @@ -18,7 +18,7 @@ CC := g++ LIBS := -lhiredis -lswsscommon -lzmq -lboost_serialization -llua5.1 TEST_LIBS := -lgtest -lgtest_main -lgmock -lgmock_main -CFLAGS += -Wall -std=c++17 -fPIE -I/usr/include/swss +CFLAGS += -Wall -std=c++17 -fPIE PWD := $(shell pwd) ifneq ($(MAKECMDGOALS),clean) diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index 7b67f2b58b9..63c3b9aef6c 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -4,12 +4,15 @@ #include #include #include +#include #include "eventconsume.h" #include "loghandler.h" #include "eventutils.h" -#include + +using namespace swss; +using namespace std; using namespace std::chrono; // map to store sequence-id for alarms @@ -20,7 +23,7 @@ EventMap static_event_table; std::atomic reload_config_flag(false); // Definition and initialization -bool g_run = true; +volatile bool g_run = true; uint64_t seq_id = 0; uint64_t PURGE_SECONDS = 86400; @@ -97,7 +100,7 @@ void EventConsume::run() reload_config_flag.store(false); } - int rc = event_receive(hsub, evt); + int rc = event_receive(hsub, evt); if (rc != 0) { SWSS_LOG_ERROR("Failed to receive rc=%d", rc); continue; @@ -323,7 +326,6 @@ void EventConsume::updateEventStatistics(bool is_add, bool is_raise, bool is_ack } else { fv.second = to_string(stoi(fv.second.c_str())-1); } - temp.push_back(fv); } else if (!fv.first.compare("raised")) { if (is_raise) { if (is_add) { @@ -331,7 +333,6 @@ void EventConsume::updateEventStatistics(bool is_add, bool is_raise, bool is_ack } else { fv.second = to_string(stoi(fv.second.c_str())-1); } - temp.push_back(fv); } } else if (!fv.first.compare("cleared")) { if (is_clear) { @@ -340,7 +341,6 @@ void EventConsume::updateEventStatistics(bool is_add, bool is_raise, bool is_ack } else { fv.second = to_string(stoi(fv.second.c_str())-1); } - temp.push_back(fv); } } else if (!fv.first.compare("acked")) { if (is_ack) { @@ -349,9 +349,9 @@ void EventConsume::updateEventStatistics(bool is_add, bool is_raise, bool is_ack } else { fv.second = to_string(stoi(fv.second.c_str())-1); } - temp.push_back(fv); } } + temp.push_back(fv); } m_eventStatsTable.set("state", temp); @@ -397,14 +397,14 @@ void EventConsume::purge_events() { } const auto p1 = system_clock::now(); - unsigned tnow_seconds = duration_cast(p1.time_since_epoch()).count(); + uint64_t tnow_seconds = duration_cast(p1.time_since_epoch()).count(); while (!event_history_list.empty()) { pair oldest_entry = event_history_list.top(); - unsigned old_seconds = oldest_entry.second / 1000000000ULL; + uint64_t old_seconds = oldest_entry.second / 1000000000ULL; if ((tnow_seconds - old_seconds) > PURGE_SECONDS) { - SWSS_LOG_NOTICE("Rollover based on time (%lu days). Deleting %lu.. now %u old %u", (PURGE_SECONDS/m_days), oldest_entry.second, tnow_seconds, old_seconds); + SWSS_LOG_NOTICE("Rollover based on time (%u days). Deleting %lu.. now %lu old %lu", m_days, oldest_entry.second, tnow_seconds, old_seconds); modifyEventStats(to_string(oldest_entry.first)); m_eventTable.del(to_string(oldest_entry.first)); event_history_list.pop(); @@ -475,15 +475,16 @@ void EventConsume::clearAckAlarmStatistic() { vector temp; if (m_alarmStatsTable.get("state", vec)) { + bool ack_found = false; for (auto fv: vec) { - if (!fv.first.compare("acknowledged")) { + if (!ack_found && !fv.first.compare("acknowledged")) { fv.second = to_string(stoi(fv.second.c_str())-1); - temp.push_back(fv); - m_alarmStatsTable.set("state", temp); - return; + ack_found = true; } + temp.push_back(fv); } - } + m_alarmStatsTable.set("state", temp); + } } @@ -541,7 +542,7 @@ bool EventConsume::staticInfoExists(string &ev_id, string &ev_act, string &ev_se // discard the event as event_static_map shows enable is false for this event if (tmp.enable == EVENT_ENABLE_FALSE_STR) { SWSS_LOG_NOTICE("Discarding event <%s> as it is set to disabled", ev_id.c_str()); - return false;; + return false; } // get severity in the map and store it in the db diff --git a/src/sonic-eventd/src/eventconsume.h b/src/sonic-eventd/src/eventconsume.h index 35e93855f1a..bd71a6f0b27 100644 --- a/src/sonic-eventd/src/eventconsume.h +++ b/src/sonic-eventd/src/eventconsume.h @@ -4,51 +4,49 @@ #include #include #include -#include "eventutils.h" #include #include - -using namespace swss; -using namespace std; +#include "eventutils.h" extern std::atomic reload_config_flag; +extern volatile bool g_run; class EventConsume { public: - EventConsume(DBConnector *dbConn, - string evProfile =EVENTD_DEFAULT_MAP_FILE, - string dbProfile =EVENTD_CONF_FILE); + EventConsume(swss::DBConnector *dbConn, + std::string evProfile =EVENTD_DEFAULT_MAP_FILE, + std::string dbProfile =EVENTD_CONF_FILE); ~EventConsume(); void read_eventd_config(bool read_all=true); void run(); private: - Table m_eventTable; - Table m_alarmTable; - Table m_eventStatsTable; - Table m_alarmStatsTable; + swss::Table m_eventTable; + swss::Table m_alarmTable; + swss::Table m_eventStatsTable; + swss::Table m_alarmStatsTable; u_int32_t m_days, m_count; - string m_evProfile; - string m_dbProfile; + std::string m_evProfile; + std::string m_dbProfile; void handle_notification(const event_receive_op_t& evt); void read_events(); - void updateAlarmStatistics(string ev_sev, string ev_act); + void updateAlarmStatistics(std::string ev_sev, std::string ev_act); void updateEventStatistics(bool is_add, bool is_alarm, bool is_ack, bool is_clear); void read_config_and_purge(); - void update_events(string seq_id, string ts, vector vec); + void update_events(std::string seq_id, std::string ts, std::vector vec); void purge_events(); - void modifyEventStats(string seq_id); + void modifyEventStats(std::string seq_id); void clearAckAlarmStatistic(); void resetAlarmStats(int, int, int, int, int, int); - void fetchFieldValues(const event_receive_op_t& evt , vector &, string &, string &, string &, string &, string &); - bool isFloodedEvent(string, string, string, string); - bool staticInfoExists(string &, string &, string &, string &, vector &); - bool udpateLocalCacheAndAlarmTable(string, bool &); + void fetchFieldValues(const event_receive_op_t& evt , std::vector &, std::string &, std::string &, std::string &, std::string &, std::string &); + bool isFloodedEvent(std::string, std::string, std::string, std::string); + bool staticInfoExists(std::string &, std::string &, std::string &, std::string &, std::vector &); + bool udpateLocalCacheAndAlarmTable(std::string, bool &); void initStats(); - void updateAckInfo(bool, string, string, string, string); - bool fetchRaiseInfo(vector &, string, string &, string &, string &, string &, string &); + void updateAckInfo(bool, std::string, std::string, std::string, std::string); + bool fetchRaiseInfo(std::vector &, std::string, std::string &, std::string &, std::string &, std::string &, std::string &); }; diff --git a/src/sonic-eventd/src/eventdb.cpp b/src/sonic-eventd/src/eventdb.cpp index 246bbe4fb5a..5f41fc8d195 100644 --- a/src/sonic-eventd/src/eventdb.cpp +++ b/src/sonic-eventd/src/eventdb.cpp @@ -1,9 +1,7 @@ #include "eventconsume.h" #include -static EventConsume *evtd_instance = NULL; - -void signalHandler(const int signal) { +void signalHandler(const int signal) { if (signal == SIGINT) { reload_config_flag.store(true); @@ -12,15 +10,14 @@ void signalHandler(const int signal) { int main() { - swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); + swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE); swss::DBConnector eventDb("EVENT_DB", 0); - - // register signal SIGINT and signal handler + + // register signal handlers signal(SIGINT, signalHandler); EventConsume evtd(&eventDb); - evtd_instance = &evtd; evtd.run(); From 14a0b4829e746ad3e5820c85b4bfcde2d9495910 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Thu, 23 Apr 2026 16:58:39 -0700 Subject: [PATCH 23/26] Add timeout to event receive blocking call. Updates to the eventdb testsuite. --- src/sonic-eventd/src/eventconsume.cpp | 6 +++++- src/sonic-eventd/tests/eventdb_ut.cpp | 17 +++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/sonic-eventd/src/eventconsume.cpp b/src/sonic-eventd/src/eventconsume.cpp index 63c3b9aef6c..9c5b9357445 100644 --- a/src/sonic-eventd/src/eventconsume.cpp +++ b/src/sonic-eventd/src/eventconsume.cpp @@ -85,7 +85,7 @@ void EventConsume::run() { SWSS_LOG_ENTER(); - event_handle_t hsub = events_init_subscriber(); + event_handle_t hsub = events_init_subscriber(false, 1000); if (hsub == nullptr) { SWSS_LOG_ERROR("Failed to initialize event subscriber"); @@ -102,6 +102,10 @@ void EventConsume::run() int rc = event_receive(hsub, evt); if (rc != 0) { + if (rc == 11) { + // Timeout - loop will check g_run + continue; + } SWSS_LOG_ERROR("Failed to receive rc=%d", rc); continue; } diff --git a/src/sonic-eventd/tests/eventdb_ut.cpp b/src/sonic-eventd/tests/eventdb_ut.cpp index 03185a894f7..1826c6abf16 100644 --- a/src/sonic-eventd/tests/eventdb_ut.cpp +++ b/src/sonic-eventd/tests/eventdb_ut.cpp @@ -94,6 +94,7 @@ void run_pub(void *mock_pub, const string wr_source, internal_events_lst_t &lst) class EventDbFixture : public ::testing::Test { protected: void SetUp() override { + g_run = true; zctx = zmq_ctx_new(); EXPECT_TRUE(NULL != zctx); @@ -103,10 +104,10 @@ class EventDbFixture : public ::testing::Test { /* Starting proxy */ EXPECT_EQ(0, pxy->init()); - DBConnector eventDb("EVENT_DB", 0, true); - //delete any entries in the EVENT_DB - delete_evdb(eventDb); - evtConsume= new EventConsume(&eventDb, event_profile, event_db_profile); + eventDb = new DBConnector("EVENT_DB", 0, true); + //delete any entries in the EVENT_DB + delete_evdb(*eventDb); + evtConsume= new EventConsume(eventDb, event_profile, event_db_profile); consumerThread = std::thread(&EventConsume::run, evtConsume); } @@ -120,15 +121,19 @@ class EventDbFixture : public ::testing::Test { delete evtConsume; evtConsume = nullptr; - delete pxy; - pxy= nullptr; + delete eventDb; + eventDb = nullptr; zmq_ctx_term(zctx); zctx = nullptr; + delete pxy; + pxy= nullptr; + clear_eventdb_data(); } EventConsume *evtConsume; + DBConnector *eventDb; void *zctx; eventd_proxy *pxy; std::thread consumerThread; From 3737b10b81f5da0b4645d265576a04e11e620a87 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:29:09 -0700 Subject: [PATCH 24/26] Remove loading of eventdb on database start. --- files/build_templates/docker_image_ctl.j2 | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index 5bd2af95fcb..84c643d5987 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -110,18 +110,10 @@ function preStartAction() else # Create an emtpy file and overwrite any RDB if already there echo -n > /tmp/dump.rdb + docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/ if [[ "$DATABASE_TYPE" != "bmcdb" ]]; then docker cp /tmp/dump.rdb database$DEV:/var/lib/redis_bmp/ fi - COLD_DIR=/host/coldboot - #In case of cold reboot, load redis content from /host/coldboot/dump.rdb - if [[ -f $COLD_DIR/dump.rdb ]]; then - #Load redis content from /host/coldboot/dump.rdb - docker cp $COLD_DIR/dump.rdb database$DEV:/var/lib/redis/dump.rdb - else - # Create an emtpy file and overwrite any RDB if already there - docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/ - fi fi fi {%- elif docker_container_name == "pde" %} From c3618742c7c97119e21e350a2cb6b93ae1034a5a Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:39:17 -0700 Subject: [PATCH 25/26] Guard creation of EVENTDB with flag include_system_eventdb. --- dockers/docker-database/database_config.json.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dockers/docker-database/database_config.json.j2 b/dockers/docker-database/database_config.json.j2 index 9972816ccba..5f7be0455f4 100644 --- a/dockers/docker-database/database_config.json.j2 +++ b/dockers/docker-database/database_config.json.j2 @@ -149,12 +149,14 @@ "instance" : "redis_bmp" } {% endif %} +{% if include_system_eventd == "y" %} , "EVENT_DB" : { "id" : 19, "separator": "|", "instance" : "redis" } +{% endif %} }, "VERSION" : "1.0" } From 0f2eb128c73d1ce130057eb729fc3f5a930a28c6 Mon Sep 17 00:00:00 2001 From: bhaveshdell <55215495+bhaveshdell@users.noreply.github.com> Date: Mon, 11 May 2026 16:31:53 -0700 Subject: [PATCH 26/26] Pass include_system_eventd to runtime jinjanate rendering - database_config.json.j2: Add 'is defined' guard for include_system_eventd - Dockerfile.j2: Add ENV INCLUDE_SYSTEM_EVENTD to bake build-time flag into container - docker-database-init.sh: Pass include_system_eventd to jinjanate calls --- dockers/docker-database/Dockerfile.j2 | 1 + dockers/docker-database/database_config.json.j2 | 2 +- dockers/docker-database/docker-database-init.sh | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dockers/docker-database/Dockerfile.j2 b/dockers/docker-database/Dockerfile.j2 index 32b56f4462a..1aa56e4ab5f 100644 --- a/dockers/docker-database/Dockerfile.j2 +++ b/dockers/docker-database/Dockerfile.j2 @@ -52,4 +52,5 @@ FROM $BASE {{ rsync_from_builder_stage() }} ENV DEBIAN_FRONTEND=noninteractive +ENV INCLUDE_SYSTEM_EVENTD={{ include_system_eventd | default("n") }} ENTRYPOINT ["/usr/local/bin/docker-database-init.sh"] diff --git a/dockers/docker-database/database_config.json.j2 b/dockers/docker-database/database_config.json.j2 index 5f7be0455f4..1079a2eb256 100644 --- a/dockers/docker-database/database_config.json.j2 +++ b/dockers/docker-database/database_config.json.j2 @@ -149,7 +149,7 @@ "instance" : "redis_bmp" } {% endif %} -{% if include_system_eventd == "y" %} +{% if include_system_eventd is defined and include_system_eventd == "y" %} , "EVENT_DB" : { "id" : 19, diff --git a/dockers/docker-database/docker-database-init.sh b/dockers/docker-database/docker-database-init.sh index dc6247bd767..1520e353049 100755 --- a/dockers/docker-database/docker-database-init.sh +++ b/dockers/docker-database/docker-database-init.sh @@ -56,9 +56,9 @@ if [ -f /etc/sonic/database_config$NAMESPACE_ID.json ]; then cp /etc/sonic/database_config$NAMESPACE_ID.json $REDIS_DIR/sonic-db/database_config.json else if [ -f /etc/sonic/enable_multidb ]; then - HOST_IP=$host_ip REDIS_PORT=$redis_port DATABASE_TYPE=$DATABASE_TYPE BMP_DB_PORT=$BMP_DB_PORT jinjanate /usr/share/sonic/templates/multi_database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json + HOST_IP=$host_ip REDIS_PORT=$redis_port DATABASE_TYPE=$DATABASE_TYPE BMP_DB_PORT=$BMP_DB_PORT include_system_eventd=$INCLUDE_SYSTEM_EVENTD jinjanate /usr/share/sonic/templates/multi_database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json else - HOST_IP=$host_ip REDIS_PORT=$redis_port DATABASE_TYPE=$DATABASE_TYPE BMP_DB_PORT=$BMP_DB_PORT jinjanate /usr/share/sonic/templates/database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json + HOST_IP=$host_ip REDIS_PORT=$redis_port DATABASE_TYPE=$DATABASE_TYPE BMP_DB_PORT=$BMP_DB_PORT include_system_eventd=$INCLUDE_SYSTEM_EVENTD jinjanate /usr/share/sonic/templates/database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json fi fi