// SPDX-License-Identifier: GPL-3.0-or-later
#include "sqlite_functions.h"
#include "sqlite_aclk_alert.h"
#ifdef ENABLE_NEW_CLOUD_PROTOCOL
#include "../../aclk/aclk_alarm_api.h"
#include "../../aclk/aclk.h"
#endif
// will replace call to aclk_update_alarm in health/health_log.c
// and handle both cases
int sql_queue_alarm_to_aclk(RRDHOST *host, ALARM_ENTRY *ae)
{
//check aclk architecture and handle old json alarm update to cloud
//include also the valid statuses for this case
#ifdef ENABLE_ACLK
#ifdef ENABLE_NEW_CLOUD_PROTOCOL
if (!aclk_use_new_cloud_arch && aclk_connected) {
#endif
if ((ae->new_status == RRDCALC_STATUS_WARNING || ae->new_status == RRDCALC_STATUS_CRITICAL) ||
((ae->old_status == RRDCALC_STATUS_WARNING || ae->old_status == RRDCALC_STATUS_CRITICAL))) {
aclk_update_alarm(host, ae);
}
#endif
#ifdef ENABLE_NEW_CLOUD_PROTOCOL
}
if (!claimed())
return 0;
if (ae->flags & HEALTH_ENTRY_FLAG_ACLK_QUEUED)
return 0;
if (ae->new_status == RRDCALC_STATUS_REMOVED || ae->new_status == RRDCALC_STATUS_UNINITIALIZED)
return 0;
if (unlikely(!host->dbsync_worker))
return 1;
if (unlikely(uuid_is_null(ae->config_hash_id)))
return 0;
int rc = 0;
CHECK_SQLITE_CONNECTION(db_meta);
sqlite3_stmt *res_alert = NULL;
char uuid_str[GUID_LEN + 1];
uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
BUFFER *sql = buffer_create(1024);
buffer_sprintf(
sql,
"INSERT INTO aclk_alert_%s (alert_unique_id, date_created) "
"VALUES (@alert_unique_id, strftime('%%s')) on conflict (alert_unique_id) do nothing; ",
uuid_str);
rc = sqlite3_prepare_v2(db_meta, buffer_tostring(sql), -1, &res_alert, 0);
if (unlikely(rc != SQLITE_OK)) {
error_report("Failed to prepare statement to store alert event");
buffer_free(sql);
return 1;
}
rc = sqlite3_bind_int(res_alert, 1, ae->unique_id);
if (unlikely(rc != SQLITE_OK))
goto bind_fail;
rc = execute_insert(res_alert);
if (unlikely(rc != SQLITE_DONE)) {
error_report("Failed to store alert event %u, rc = %d", ae->unique_id, rc);
goto bind_fail;
}
ae->flags |= HEALTH_ENTRY_FLAG_ACLK_QUEUED;
bind_fail:
if (unlikely(sqlite3_finalize(res_alert) != SQLITE_OK))
error_report("Failed to reset statement in store alert event, rc = %d", rc);
buffer_free(sql);
return 0;
#else
UNUSED(host);
UNUSED(ae);
#endif
return 0;
}
int rrdcalc_status_to_proto_enum(RRDCALC_STATUS status)
{
#ifdef ENABLE_NEW_CLOUD_PROTOCOL
switch(status) {
case RRDCALC_STATUS_REMOVED:
return ALARM_STATUS_REMOVED;
case RRDCALC_STATUS_UNDEFINED:
return ALARM_STATUS_NOT_A_NUMBER;
case RRDCALC_STATUS_CLEAR:
return ALARM_STATUS_CLEAR;
case RRDCALC_STATUS_WARNING:
return ALARM_STATUS_WARNING;
case RRDCALC_STATUS_CRITICAL:
return ALARM_STATUS_CRITICAL;
default:
return ALARM_STATUS_UNKNOWN;
}
#else
UNUSED(status);
return 1;
#endif
}
void aclk_push_alert_event(struct aclk_database_worker_config *wc, struct aclk_database_cmd cmd)
{
#ifndef ENABLE_NEW_CLOUD_PROTOCOL
UNUSED(wc);
UNUSED(cmd);
#else
int rc;
if (unlikely(!wc->alert_updates)) {
log_access("AC [%s (%s)]: Ignoring alert push event, updates have been turned off for this node.", wc->node_id, wc->host ? wc->host->hostname : "N/A");
return;
}
char *claim_id = is_agent_claimed();
if (unlikely(!claim_id))
return;
BUFFER *sql = buffer_create(1024);
if (wc->alerts_start_seq_id != 0) {
buffer_sprintf(
sql,
"UPDATE aclk_alert_%s SET date_submitted = NULL, date_cloud_ack = NULL WHERE sequence_id >= %"PRIu64
"; UPDATE aclk_alert_%s SET date_cloud_ack = strftime('%%s','now') WHERE sequence_id < %"PRIu64
" and date_cloud_ack is null "
"; UPDATE aclk_alert_%s SET date_submitted = strftime('%%s','now') WHERE sequence_id < %"PRIu64
" and date_submitted is null",
wc->uuid_str,
wc->alerts_start_seq_id,
wc->uuid_str,
wc->alerts_start_seq_id,
wc->uuid_str,
wc->alerts_start_seq_id);
db_execute(buffer_tostring(sql));
buffer_reset(sql);
wc->alerts_start_seq_id = 0;
}
int limit = cmd.count > 0 ? cmd.count : 1;
sqlite3_stmt