Browse Source

Allow to create alert hashes with --disable-cloud (#15519)

* check for alarm ids with zero hashes

* use zeroblob(16)
Emmanuel Vasilakis 1 year ago
parent
commit
fd1edfb699
3 changed files with 139 additions and 5 deletions
  1. 7 3
      database/rrdcalc.c
  2. 131 2
      database/sqlite/sqlite_health.c
  3. 1 0
      database/sqlite/sqlite_health.h

+ 7 - 3
database/rrdcalc.c

@@ -82,10 +82,14 @@ uint32_t rrdcalc_get_unique_id(RRDHOST *host, STRING *chart, STRING *name, uint3
         alarm_id = sql_get_alarm_id(host, chart, name, next_event_id, config_hash_id);
 
         if (!alarm_id) {
-            if (unlikely(!host->health_log.next_alarm_id))
-                host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();
+            //check possible stored config hash as zeroes or null
+            alarm_id = sql_get_alarm_id_check_zero_hash(host, chart, name, next_event_id, config_hash_id);
+            if (!alarm_id) {
+                if (unlikely(!host->health_log.next_alarm_id))
+                    host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();
 
-            alarm_id = host->health_log.next_alarm_id++;
+                alarm_id = host->health_log.next_alarm_id++;
+            }
         }
     }
 

+ 131 - 2
database/sqlite/sqlite_health.c

@@ -1215,7 +1215,7 @@ bind_fail:
   if cloud is disabled or openssl is not available (which will prevent cloud connectivity)
   skip hash calculations
 */
-#if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
+#if defined ENABLE_HTTPS
 #define DIGEST_ALERT_CONFIG_VAL(v) ((v) ? EVP_DigestUpdate(evpctx, (string2str(v)), string_strlen((v))) : EVP_DigestUpdate(evpctx, "", 1))
 #endif
 int alert_hash_and_store_config(
@@ -1223,7 +1223,7 @@ int alert_hash_and_store_config(
     struct alert_config *cfg,
     int store_hash)
 {
-#if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
+#if defined ENABLE_HTTPS
     EVP_MD_CTX *evpctx;
     unsigned char hash_value[EVP_MAX_MD_SIZE];
     unsigned int hash_len;
@@ -1729,6 +1729,135 @@ uint32_t sql_get_alarm_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t *
      return alarm_id;
 }
 
+#define SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH "update health_log set config_hash_id = @config_hash_id where host_id = @host_id and alarm_id = @alarm_id and health_log_id = @health_log_id"
+void sql_update_alarm_with_config_hash(RRDHOST *host, uint32_t alarm_id, uint64_t health_log_id, uuid_t *config_hash_id)
+{
+    int rc = 0;
+    sqlite3_stmt *res = NULL;
+
+    rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH, -1, &res, 0);
+    if (rc != SQLITE_OK) {
+        error_report("Failed to prepare statement when trying to update an alarm id with a config hash.");
+        return;
+    }
+
+    rc = sqlite3_bind_blob(res, 1, config_hash_id, sizeof(*config_hash_id), SQLITE_STATIC);
+    if (unlikely(rc != SQLITE_OK)) {
+        error_report("Failed to bind config_hash_id parameter for SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH.");
+        sqlite3_finalize(res);
+        return;
+    }
+
+    rc = sqlite3_bind_blob(res, 2, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+    if (unlikely(rc != SQLITE_OK)) {
+        error_report("Failed to bind host_id parameter for SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH.");
+        sqlite3_finalize(res);
+        return;
+    }
+
+    rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) alarm_id);
+    if (unlikely(rc != SQLITE_OK)) {
+        error_report("Failed to bind alarm_id parameter for SQL_GET_ALARM_ID.");
+        sqlite3_finalize(res);
+        return;
+    }
+
+    rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) health_log_id);
+    if (unlikely(rc != SQLITE_OK)) {
+        error_report("Failed to bind alarm_id parameter for SQL_GET_ALARM_ID.");
+        sqlite3_finalize(res);
+        return;
+    }
+
+    rc = execute_insert(res);
+    if (unlikely(rc != SQLITE_DONE)) {
+        error_report("Failed to execute SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH, rc = %d", rc);
+        rc = sqlite3_finalize(res);
+        if (unlikely(rc != SQLITE_OK))
+            error_report("Failed to reset statement to update health log detail table with config hash ids, rc = %d", rc);
+        return;
+    }
+}
+
+#define SQL_GET_ALARM_ID_CHECK_ZERO_HASH "select alarm_id, health_log_id from health_log where host_id = @host_id and chart = @chart and name = @name and (config_hash_id is null or config_hash_id = zeroblob(16))"
+uint32_t sql_get_alarm_id_check_zero_hash(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id, uuid_t *config_hash_id)
+{
+    int rc = 0;
+    sqlite3_stmt *res = NULL;
+    uint32_t alarm_id = 0;
+    uint64_t health_log_id = 0;
+
+    rc = sqlite3_prepare_v2(db_meta, SQL_GET_ALARM_ID_CHECK_ZERO_HASH, -1, &res, 0);
+    if (rc != SQLITE_OK) {
+        error_report("Failed to prepare statement when trying to get an alarm id with zero hash");
+        return alarm_id;
+    }
+
+    rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+    if (unlikely(rc != SQLITE_OK)) {
+        error_report("Failed to bind host_id parameter for SQL_GET_ALARM_ID_CHECK_ZERO_HASH.");
+        sqlite3_finalize(res);
+        return alarm_id;
+    }
+
+    rc = sqlite3_bind_string_or_null(res, chart, 2);
+    if (unlikely(rc != SQLITE_OK)) {
+        error_report("Failed to bind char parameter for SQL_GET_ALARM_ID_CHECK_ZERO_HASH.");
+        sqlite3_finalize(res);
+        return alarm_id;
+    }
+
+    rc = sqlite3_bind_string_or_null(res, name, 3);
+    if (unlikely(rc != SQLITE_OK)) {
+        error_report("Failed to bind name parameter for SQL_GET_ALARM_ID_CHECK_ZERO_HASH.");
+        sqlite3_finalize(res);
+        return alarm_id;
+    }
+
+    while (sqlite3_step_monitored(res) == SQLITE_ROW) {
+        alarm_id = (uint32_t) sqlite3_column_int64(res, 0);
+        health_log_id = (uint64_t) sqlite3_column_int64(res, 1);
+    }
+
+     rc = sqlite3_finalize(res);
+     if (unlikely(rc != SQLITE_OK))
+         error_report("Failed to finalize the statement while getting an alarm id.");
+
+     if (alarm_id) {
+         sql_update_alarm_with_config_hash(host, alarm_id, health_log_id, config_hash_id);
+
+         rc = sqlite3_prepare_v2(db_meta, SQL_GET_EVENT_ID, -1, &res, 0);
+         if (rc != SQLITE_OK) {
+             error_report("Failed to prepare statement when trying to get an event id");
+             return alarm_id;
+         }
+
+         rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) health_log_id);
+         if (unlikely(rc != SQLITE_OK)) {
+             error_report("Failed to bind host_id parameter for SQL_GET_EVENT_ID.");
+             sqlite3_finalize(res);
+             return alarm_id;
+         }
+
+         rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
+         if (unlikely(rc != SQLITE_OK)) {
+             error_report("Failed to bind char parameter for SQL_GET_EVENT_ID.");
+             sqlite3_finalize(res);
+             return alarm_id;
+         }
+
+         while (sqlite3_step_monitored(res) == SQLITE_ROW) {
+             *next_event_id = (uint32_t) sqlite3_column_int64(res, 0);
+         }
+
+         rc = sqlite3_finalize(res);
+         if (unlikely(rc != SQLITE_OK))
+             error_report("Failed to finalize the statement while getting an alarm id.");
+     }
+
+     return alarm_id;
+}
+
 #define SQL_GET_ALARM_ID_FROM_TRANSITION_ID "SELECT hld.alarm_id, hl.host_id, hl.chart_context FROM " \
         "health_log_detail hld, health_log hl WHERE hld.transition_id = @transition_id " \
         "and hld.health_log_id = hl.health_log_id"

+ 1 - 0
database/sqlite/sqlite_health.h

@@ -19,6 +19,7 @@ int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_S
 void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *chart);
 int health_migrate_old_health_log_table(char *table);
 uint32_t sql_get_alarm_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id, uuid_t *config_hash_id);
+uint32_t sql_get_alarm_id_check_zero_hash(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id, uuid_t *config_hash_id);
 void sql_alert_transitions(
     DICTIONARY *nodes,
     time_t after,