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);
         alarm_id = sql_get_alarm_id(host, chart, name, next_event_id, config_hash_id);
 
 
         if (!alarm_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)
   if cloud is disabled or openssl is not available (which will prevent cloud connectivity)
   skip hash calculations
   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))
 #define DIGEST_ALERT_CONFIG_VAL(v) ((v) ? EVP_DigestUpdate(evpctx, (string2str(v)), string_strlen((v))) : EVP_DigestUpdate(evpctx, "", 1))
 #endif
 #endif
 int alert_hash_and_store_config(
 int alert_hash_and_store_config(
@@ -1223,7 +1223,7 @@ int alert_hash_and_store_config(
     struct alert_config *cfg,
     struct alert_config *cfg,
     int store_hash)
     int store_hash)
 {
 {
-#if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
+#if defined ENABLE_HTTPS
     EVP_MD_CTX *evpctx;
     EVP_MD_CTX *evpctx;
     unsigned char hash_value[EVP_MAX_MD_SIZE];
     unsigned char hash_value[EVP_MAX_MD_SIZE];
     unsigned int hash_len;
     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;
      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 " \
 #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 " \
         "health_log_detail hld, health_log hl WHERE hld.transition_id = @transition_id " \
         "and hld.health_log_id = hl.health_log_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);
 void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *chart);
 int health_migrate_old_health_log_table(char *table);
 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(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(
 void sql_alert_transitions(
     DICTIONARY *nodes,
     DICTIONARY *nodes,
     time_t after,
     time_t after,