Code

Automatically prefix all log messages with the plugin name (if available).
[sysdb.git] / src / plugins / store / network.c
index 9f55d23c76f7e244eed37b057df6e388676160d7..fc416fe34b978de5c93515030797118af7579051 100644 (file)
@@ -35,6 +35,7 @@
 #include "utils/error.h"
 #include "utils/proto.h"
 #include "utils/os.h"
+#include "utils/ssl.h"
 
 #include "liboconfig/utils.h"
 
@@ -54,14 +55,14 @@ typedef struct {
        sdb_client_t *client;
        char *addr;
        char *username;
+       sdb_ssl_options_t ssl_opts;
 } user_data_t;
-#define UD(obj) ((user_data_t *)(obj))
-#define CLIENT(obj) UD(SDB_OBJ_WRAPPER(obj)->data)->client
+#define UD(obj) SDB_OBJ_WRAPPER(obj)->data
 
 static void
 user_data_destroy(void *obj)
 {
-       user_data_t *ud = UD(obj);
+       user_data_t *ud = obj;
 
        if (! ud)
                return;
@@ -76,6 +77,8 @@ user_data_destroy(void *obj)
                free(ud->username);
        ud->username = NULL;
 
+       sdb_ssl_free_options(&ud->ssl_opts);
+
        free(ud);
 } /* user_data_destroy */
 
@@ -84,18 +87,29 @@ user_data_destroy(void *obj)
  */
 
 static int
-store_rpc(sdb_client_t *client, const char *msg, size_t msg_len)
+store_rpc(user_data_t *ud, const char *msg, size_t msg_len)
 {
        sdb_strbuf_t *buf = sdb_strbuf_create(128);
        uint32_t rstatus = 0;
        ssize_t status;
 
-       status = sdb_client_rpc(client, SDB_CONNECTION_STORE,
+       if (sdb_client_eof(ud->client)) {
+               sdb_client_close(ud->client);
+               if (sdb_client_connect(ud->client, ud->username)) {
+                       sdb_log(SDB_LOG_ERR, "Failed to reconnect to SysDB "
+                                       "at %s as user %s", ud->addr, ud->username);
+                       return -1;
+               }
+               sdb_log(SDB_LOG_INFO, "Successfully reconnected to SysDB "
+                               "at %s as user %s", ud->addr, ud->username);
+       }
+
+       status = sdb_client_rpc(ud->client, SDB_CONNECTION_STORE,
                        (uint32_t)msg_len, msg, &rstatus, buf);
        if (status < 0)
-               sdb_log(SDB_LOG_ERR, "store::network: %s", sdb_strbuf_string(buf));
+               sdb_log(SDB_LOG_ERR, "%s", sdb_strbuf_string(buf));
        else if (rstatus != SDB_CONNECTION_OK) {
-               sdb_log(SDB_LOG_ERR, "store::network: Failed to send object: %s",
+               sdb_log(SDB_LOG_ERR, "Failed to send object: %s",
                                sdb_strbuf_string(buf));
                status = -1;
        }
@@ -107,91 +121,62 @@ store_rpc(sdb_client_t *client, const char *msg, size_t msg_len)
 } /* store_rpc */
 
 static int
-store_host(const char *name, sdb_time_t last_update, sdb_object_t *user_data)
+store_host(sdb_store_host_t *host, sdb_object_t *user_data)
 {
-       sdb_proto_host_t host = { last_update, name };
-       size_t len = sdb_proto_marshal_host(NULL, 0, &host);
+       sdb_proto_host_t h = { host->last_update, host->name };
+       size_t len = sdb_proto_marshal_host(NULL, 0, &h);
        char buf[len];
 
-       sdb_proto_marshal_host(buf, len, &host);
-       return store_rpc(CLIENT(user_data), buf, len);
+       sdb_proto_marshal_host(buf, len, &h);
+       return store_rpc(UD(user_data), buf, len);
 } /* store_host */
 
 static int
-store_service(const char *hostname, const char *name, sdb_time_t last_update,
-               sdb_object_t *user_data)
+store_service(sdb_store_service_t *service, sdb_object_t *user_data)
 {
-       sdb_proto_service_t svc = { last_update, hostname, name };
-       ssize_t len = sdb_proto_marshal_service(NULL, 0, &svc);
+       sdb_proto_service_t s = {
+               service->last_update, service->hostname, service->name,
+       };
+       ssize_t len = sdb_proto_marshal_service(NULL, 0, &s);
        char buf[len];
 
-       sdb_proto_marshal_service(buf, len, &svc);
-       return store_rpc(CLIENT(user_data), buf, len);
+       sdb_proto_marshal_service(buf, len, &s);
+       return store_rpc(UD(user_data), buf, len);
 } /* store_service */
 
 static int
-store_metric(const char *hostname, const char *name,
-               sdb_metric_store_t *store, sdb_time_t last_update,
-               sdb_object_t *user_data)
+store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data)
 {
-       sdb_proto_metric_t metric = {
-               last_update, hostname, name,
-               store ? store->type : NULL, store ? store->id : NULL,
+       sdb_proto_metric_t m = {
+               metric->last_update, metric->hostname, metric->name,
+               /* TODO: Add support for sending all data stores. */
+               metric->stores_num ? metric->stores[0].type : NULL,
+               metric->stores_num ? metric->stores[0].id : NULL,
+               metric->stores_num ? metric->stores[0].last_update : 0,
        };
-       size_t len = sdb_proto_marshal_metric(NULL, 0, &metric);
+       size_t len = sdb_proto_marshal_metric(NULL, 0, &m);
        char buf[len];
 
-       sdb_proto_marshal_metric(buf, len, &metric);
-       return store_rpc(CLIENT(user_data), buf, len);
+       sdb_proto_marshal_metric(buf, len, &m);
+       return store_rpc(UD(user_data), buf, len);
 } /* store_metric */
 
 static int
-store_attr(const char *hostname, const char *key, const sdb_data_t *value,
-               sdb_time_t last_update, sdb_object_t *user_data)
+store_attr(sdb_store_attribute_t *attr, sdb_object_t *user_data)
 {
-       sdb_proto_attribute_t attr = {
-               last_update, SDB_HOST, NULL, hostname, key, *value,
+       sdb_proto_attribute_t a = {
+               attr->last_update, attr->parent_type, attr->hostname, attr->parent,
+               attr->key, attr->value,
        };
-       size_t len = sdb_proto_marshal_attribute(NULL, 0, &attr);
+       size_t len = sdb_proto_marshal_attribute(NULL, 0, &a);
        char buf[len];
 
-       sdb_proto_marshal_attribute(buf, len, &attr);
-       return store_rpc(CLIENT(user_data), buf, len);
+       sdb_proto_marshal_attribute(buf, len, &a);
+       return store_rpc(UD(user_data), buf, len);
 } /* store_attr */
 
-static int
-store_service_attr(const char *hostname, const char *service,
-               const char *key, const sdb_data_t *value, sdb_time_t last_update,
-               sdb_object_t *user_data)
-{
-       sdb_proto_attribute_t attr = {
-               last_update, SDB_SERVICE, hostname, service, key, *value,
-       };
-       size_t len = sdb_proto_marshal_attribute(NULL, 0, &attr);
-       char buf[len];
-
-       sdb_proto_marshal_attribute(buf, len, &attr);
-       return store_rpc(CLIENT(user_data), buf, len);
-} /* store_service_attr */
-
-static int
-store_metric_attr(const char *hostname, const char *metric,
-               const char *key, const sdb_data_t *value, sdb_time_t last_update,
-               sdb_object_t *user_data)
-{
-       sdb_proto_attribute_t attr = {
-               last_update, SDB_METRIC, hostname, metric, key, *value,
-       };
-       size_t len = sdb_proto_marshal_attribute(NULL, 0, &attr);
-       char buf[len];
-
-       sdb_proto_marshal_attribute(buf, len, &attr);
-       return store_rpc(CLIENT(user_data), buf, len);
-} /* store_metric_attr */
-
 static sdb_store_writer_t store_impl = {
-       store_host, store_service, store_metric,
-       store_attr, store_service_attr, store_metric_attr,
+       store_host, store_service, store_metric, store_attr,
 };
 
 /*
@@ -208,13 +193,13 @@ store_init(sdb_object_t *user_data)
 
        ud = SDB_OBJ_WRAPPER(user_data)->data;
        if (sdb_client_connect(ud->client, ud->username)) {
-               sdb_log(SDB_LOG_ERR, "store::network: Failed to connect "
-                               "to SysDB at %s as user %s", ud->addr, ud->username);
+               sdb_log(SDB_LOG_ERR, "Failed to connect to SysDB "
+                               "at %s as user %s", ud->addr, ud->username);
                return -1;
        }
 
-       sdb_log(SDB_LOG_INFO, "store::network: Successfully connected "
-                       "to SysDB at %s as user %s", ud->addr, ud->username);
+       sdb_log(SDB_LOG_INFO, "Successfully connected to SysDB "
+                       "at %s as user %s", ud->addr, ud->username);
        return 0;
 } /* store_init */
 
@@ -223,28 +208,26 @@ store_config_server(oconfig_item_t *ci)
 {
        sdb_object_t *user_data;
        user_data_t *ud;
-
+       int ret = 0;
        int i;
 
        ud = calloc(1, sizeof(*ud));
        if (! ud) {
                char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "store::network: Failed to allocate "
-                               "a user-data object: %s",
+               sdb_log(SDB_LOG_ERR, "Failed to allocate a user-data object: %s",
                                sdb_strerror(errno, errbuf, sizeof(errbuf)));
                return -1;
        }
 
        if (oconfig_get_string(ci, &ud->addr)) {
-               sdb_log(SDB_LOG_ERR, "store::network: Server requires "
-                               "a single string argument\n\tUsage: <Server ADDRESS>");
+               sdb_log(SDB_LOG_ERR, "Server requires a single string argument\n"
+                               "\tUsage: <Server ADDRESS>");
                user_data_destroy(ud);
                return -1;
        }
        ud->addr = strdup(ud->addr);
        if (! ud->addr) {
-               sdb_log(SDB_LOG_ERR, "store::network: Failed to duplicate "
-                               "a string");
+               sdb_log(SDB_LOG_ERR, "Failed to duplicate a string");
                user_data_destroy(ud);
                return -1;
        }
@@ -252,35 +235,67 @@ store_config_server(oconfig_item_t *ci)
        ud->client = sdb_client_create(ud->addr);
        if (! ud->client) {
                char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "store::network: Failed to create client "
-                               "connecting to '%s': %s", ud->addr,
-                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               sdb_log(SDB_LOG_ERR, "Failed to create client connecting to '%s': %s",
+                               ud->addr, sdb_strerror(errno, errbuf, sizeof(errbuf)));
                user_data_destroy(ud);
                return -1;
        }
 
        for (i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *child = ci->children + i;
-
-               if (! strcasecmp(child->key, "Username"))
-                       oconfig_get_string(child, &ud->username);
+               char *tmp = NULL;
+
+               if (! strcasecmp(child->key, "Username")) {
+                       if (oconfig_get_string(child, &tmp)) {
+                               ret = -1;
+                               break;
+                       }
+                       ud->username = strdup(tmp);
+               }
+               else if (! strcasecmp(child->key, "SSLCertificate")) {
+                       if (oconfig_get_string(child, &tmp)) {
+                               ret = -1;
+                               break;
+                       }
+                       ud->ssl_opts.cert_file = strdup(tmp);
+               }
+               else if (! strcasecmp(child->key, "SSLCertificateKey")) {
+                       if (oconfig_get_string(child, &tmp)) {
+                               ret = -1;
+                               break;
+                       }
+                       ud->ssl_opts.key_file = strdup(tmp);
+               }
+               else if (! strcasecmp(child->key, "SSLCACertificates")) {
+                       if (oconfig_get_string(child, &tmp)) {
+                               ret = -1;
+                               break;
+                       }
+                       ud->ssl_opts.ca_file = strdup(tmp);
+               }
                else
-                       sdb_log(SDB_LOG_WARNING, "store::network: Ignoring "
-                                       "unknown config option '%s' inside <Server %s>.",
-                                       child->key, ud->addr);
+                       sdb_log(SDB_LOG_WARNING, "Ignoring unknown config option '%s' "
+                                       "inside <Server %s>.", child->key, ud->addr);
        }
 
-       if (ud->username)
-               ud->username = strdup(ud->username);
+       if (ret) {
+               user_data_destroy(ud);
+               return ret;
+       }
        if (! ud->username)
                ud->username = sdb_get_current_user();
 
+       if (sdb_client_set_ssl_options(ud->client, &ud->ssl_opts)) {
+               sdb_log(SDB_LOG_ERR, "Failed to apply SSL options");
+               user_data_destroy(ud);
+               return -1;
+       }
+
        user_data = sdb_object_create_wrapper("store-network-userdata", ud,
                        user_data_destroy);
        if (! user_data) {
                char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "store::network: Failed to allocate "
-                               "a user-data wrapper object: %s",
+               sdb_log(SDB_LOG_ERR, "Failed to allocate a user-data wrapper object: %s",
                                sdb_strerror(errno, errbuf, sizeof(errbuf)));
                user_data_destroy(ud);
                return -1;
@@ -306,8 +321,8 @@ store_config(oconfig_item_t *ci)
                if (! strcasecmp(child->key, "Server"))
                        store_config_server(child);
                else
-                       sdb_log(SDB_LOG_WARNING, "store::network: Ignoring "
-                                       "unknown config option '%s'.", child->key);
+                       sdb_log(SDB_LOG_WARNING, "Ignoring unknown config option '%s'.",
+                                       child->key);
        }
        return 0;
 } /* store_config */