Code

Add ReconnectInterval option to Network plugin
authorJohn Ferlito <johnf@inodes.org>
Sat, 13 Sep 2014 01:24:14 +0000 (11:24 +1000)
committerJohn Ferlito <johnf@inodes.org>
Sun, 14 Sep 2014 06:45:16 +0000 (16:45 +1000)
The Network plugin only performs DNS resolution at initialization. This
can be problematic when trying to performs migrations of collectd
infrastructure or when trying to create HA solutions which are dependant
on DNS.

The ReconnectInterval options forces a reconnect of all the sockets at
the defined number of seconds. By default no re-connections are attempted
if this option is not set.

src/collectd.conf.in
src/collectd.conf.pod
src/network.c

index 38b2ba46749d5869a31c6f2641676a14bb50380c..91c040a3ca67a144ba573c4faaf2d5ef5f926c23 100644 (file)
 #              Username "user"
 #              Password "secret"
 #              Interface "eth0"
+#              ResolveInterval 14400
 @LOAD_PLUGIN_NETWORK@  </Server>
 #      TimeToLive "128"
 #
index ba99b60d5dd787b61ca9daa08e41071d363a24b9..8ecc92d647ff7a38c5ea9310560d29b05ef9bfb4 100644 (file)
@@ -3890,6 +3890,12 @@ behavior is to let the kernel choose the appropriate interface. Be warned
 that the manual selection of an interface for unicast traffic is only
 necessary in rare cases.
 
+=item B<ResolveInterval> I<Seconds>
+
+Sets the interval at which to re-resolve the DNS for the I<Host>. This is
+useful to force a regular DNS lookup to support a high availability setup. If
+not specified, re-resolves are never attempted.
+
 =back
 
 =item B<E<lt>Listen> I<Host> [I<Port>]B<E<gt>>
index 9ad4dead906d8619e3d6df8766dd0e4231e95e3d..bf0b2bc647e63f7de410e561dd2d9b16817fbd7c 100644 (file)
@@ -117,6 +117,8 @@ struct sockent_client
        gcry_cipher_hd_t cypher;
        unsigned char password_hash[32];
 #endif
+       cdtime_t next_resolve_reconnect;
+       cdtime_t resolve_interval;
 };
 
 struct sockent_server
@@ -2031,6 +2033,8 @@ static sockent_t *sockent_create (int type) /* {{{ */
        {
                se->data.client.fd = -1;
                se->data.client.addr = NULL;
+               se->data.client.resolve_interval = 0;
+               se->data.client.next_resolve_reconnect = 0;
 #if HAVE_LIBGCRYPT
                se->data.client.security_level = SECURITY_LEVEL_NONE;
                se->data.client.username = NULL;
@@ -2125,12 +2129,22 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
        struct addrinfo  ai_hints;
        struct addrinfo *ai_list = NULL, *ai_ptr;
        int status;
+       _Bool reconnect = 0;
+       cdtime_t now;
 
        if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT))
                return (EINVAL);
 
        client = &se->data.client;
-       if (client->fd >= 0) /* already connected */
+
+       now = cdtime ();
+       if (client->resolve_interval != 0 && client->next_resolve_reconnect < now) {
+               DEBUG("network plugin: Reconnecting socket, resolve_interval = %lf, next_resolve_reconnect = %lf",
+                       CDTIME_T_TO_DOUBLE(client->resolve_interval), CDTIME_T_TO_DOUBLE(client->next_resolve_reconnect));
+               reconnect = 1;
+       }
+
+       if (client->fd >= 0 && !reconnect) /* already connected and not stale*/
                return (0);
 
        memset (&ai_hints, 0, sizeof (ai_hints));
@@ -2162,6 +2176,9 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
 
        for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
+               if (client->fd >= 0) /* when we reconnect */
+                       sockent_client_disconnect(se);
+
                client->fd = socket (ai_ptr->ai_family,
                                ai_ptr->ai_socktype,
                                ai_ptr->ai_protocol);
@@ -2199,6 +2216,9 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
        freeaddrinfo (ai_list);
        if (client->fd < 0)
                return (-1);
+
+       if (client->resolve_interval > 0)
+               client->next_resolve_reconnect = now + client->resolve_interval;
        return (0);
 } /* }}} int sockent_client_connect */
 
@@ -3209,6 +3229,8 @@ static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */
     if (strcasecmp ("Interface", child->key) == 0)
       network_config_set_interface (child,
           &se->interface);
+               else if (strcasecmp ("ResolveInterval", child->key) == 0)
+                       cf_util_get_cdtime(child, &se->data.client.resolve_interval);
     else
     {
       WARNING ("network plugin: Option `%s' is not allowed here.",