Changeset b553f9a4d73487ee85e5cfedf2cd67352b4d5e6b

Show
Ignore:
Timestamp:
01/08/11 17:51:19 (3 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1294509079 +0000
git-parent:

[4b55797971a3f98431112b9eb43d2a76c7ba3e2b]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1294509079 +0000
Message:

refs #340

This is a rather major change. Targets can now be hostnames in addition
to IP addresses so long as //checks/@resolve_targets is not false.

If a target is entered that does not look like an IP (inet_pton fails)
then the check is marked as needing resolution NP_RESOLVE.

A passive look-aside dns cache has been implemented in noit_check_resolver.c
that is used to power the whole system and some reasonably simply console
command have been provided:

show dns_cache [fqdn1 [fqdn2]] -- shows the state
dns_cache <fqdn> [fqdn2 [fqdn3]] -- submits for lookup
no dns_cache <fqdn> [fqdn2 [fqdn3]] -- purges from cache

The big change is that modules that relied on check->target to be an IP
address are going to explode when names are provided. Instead, modules
should now use target for the provided target (possibly a FQDN) and use
target_ip (check->target_ip or check.target_ip) for a resolved IP address
and also check for the case of empty string: (check->target_ip[0] == '\0')
for the case that resolution has failed. In lua, the target_ip will be
presented as nil in the case of failed name resolution.

I believe I've updated all necessary components of the system for this to
"just work" but people that have implemented their own check should update
them before they elect to use non-IP addresses as targets.

The dns subsystem supports both IPv4 and IPv6, but currently prefers IPv4
addresses if any are present.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/Makefile.in

    r4b55797 rb553f9a  
    3737MODDIR=modules 
    3838 
    39 HEADERS=noit_capabilities_listener.h noit_check.h noit_check_rest.h \ 
    40         noit_check_tools_shared.h \ 
     39HEADERS=noit_capabilities_listener.h noit_check.h noit_check_resolver.h \ 
     40        noit_check_rest.h \ 
     41        noit_check_tools_shared.h \ 
    4142        noit_check_tools.h noit_conf.h noit_conf_checks.h noit_conf_private.h \ 
    4243        noit_config.h noit_console.h noit_console_telnet.h noit_defines.h \ 
     
    6364NOIT_OBJS=noitd.o noit_listener.o \ 
    6465        noit_console.o noit_console_state.o noit_console_telnet.o \ 
    65         noit_console_complete.o
    66         noit_check_tools_shared.o \ 
     66        noit_console_complete.o noit_check_resolver.o
     67       noit_check_tools_shared.o \ 
    6768        noit_check.o noit_check_log.o noit_check_tools.o \ 
    6869        noit_module.o noit_conf.o noit_conf_checks.o noit_tokenizer.o \ 
  • src/java/com/omniti/jezebel/JezebelDispatch.java

    r92fd1d9 rb553f9a  
    143143      o.put("name", root.getAttribute("name")); 
    144144      o.put("target", root.getAttribute("target")); 
     145      String target_ip = root.getAttribute("target_ip"); 
     146      if(target_ip != null) o.put("target_ip", target_ip); 
    145147      o.put("timeout", root.getAttribute("timeout")); 
    146148      o.put("period", root.getAttribute("period")); 
  • src/java/com/omniti/jezebel/check/JDBC.java

    rfa18f5a rb553f9a  
    5757    if(port == null) port = defaultPort(); 
    5858    String sql = config.remove("sql"); 
    59     String url = jdbcConnectUrl(check.get("target"), port, database); 
     59    String url = jdbcConnectUrl(check.get("target_ip"), port, database); 
    6060    Properties props = new Properties(); 
    6161    props.setProperty("user", username == null ? "" : username); 
  • src/java/com/omniti/jezebel/check/jmx.java

    r92fd1d9 rb553f9a  
    6161                        ResmonResult rr)  
    6262    { 
    63         final String host = check.remove("target"); 
     63        final String host = check.remove("target_ip"); 
    6464        final String port = config.remove("port"); 
    6565        final String username = config.remove("username"); 
  • src/modules-lua/noit/module/haproxy.lua

    r7a6be88 rb553f9a  
    9494 
    9595function initiate(module, check) 
    96   local host = check.config.host or check.target 
     96  local host = check.config.host or check.target or check.target_ip 
    9797  local port = check.config.port or 80 
    9898  local uri  = check.config.uri or "/admin?stats;csv" 
     
    127127 
    128128  local client = HttpClient:new(callbacks) 
    129   local rv, err = client:connect(check.target, port, false) 
     129  local rv, err = client:connect(check.target_ip, port, false) 
    130130  
    131131  if rv ~= 0 then error(err or "unknown error") end 
  • src/modules-lua/noit/module/http.lua

    r73df43f rb553f9a  
    342342        -- this is handled later as we need our challenge. 
    343343        local client = HttpClient:new() 
    344         local rv, err = client:connect(check.target, port, use_ssl) 
     344        local rv, err = client:connect(check.target_ip, port, use_ssl) 
    345345        if rv ~= 0 then 
    346346            check.status(str or "unknown error") 
     
    381381    local client 
    382382    local dns = noit.dns() 
    383     local target = check.target 
     383    local target = check.target_ip 
    384384    local payload = check.config.payload 
    385385    -- artificially increase redirects as the initial request counts 
  • src/modules-lua/noit/module/jezebel.lua

    rb70de4f rb553f9a  
    101101  local root = doc:root() 
    102102  root:attr("target", check.target) 
     103  if(check.target_ip ~= nil) then 
     104    root:attr("target_ip", check.target_ip) 
     105  end 
    103106  root:attr("module", check.module) 
    104107  root:attr("name", check.name) 
  • src/modules-lua/noit/module/memcached.lua

    r5e4903b rb553f9a  
    8383  -- connect to the memcache instance 
    8484  local e = noit.socket() 
    85   local rv, err = e:connect(check.target, check.config.port or 11211) 
     85  local rv, err = e:connect(check.target_ip, check.config.port or 11211) 
    8686 
    8787  -- issue the stats command and read everything until the END keyword 
  • src/modules-lua/noit/module/munin.lua

    r3f95e0c rb553f9a  
    8686  local e = noit.socket() 
    8787  local plugins = check.config.plugins 
    88   local rv, err = e:connect(check.target, check.config.port or 4949) 
     88  local rv, err = e:connect(check.target_ip, check.config.port or 4949) 
    8989 
    9090  check.bad() 
  • src/modules-lua/noit/module/ntp.lua

    rd00b3d5 rb553f9a  
    162162    check.bad() 
    163163 
    164     s:connect(check.target, 123) 
     164    s:connect(check.target_ip, 123) 
    165165    status.responses = 0 
    166166    status.avg_offset = 0 
  • src/modules-lua/noit/module/resmon.lua

    rb0d6e99 rb553f9a  
    212212    callbacks.headers = function (t) hdrs_in = t end 
    213213    local client = HttpClient:new(callbacks) 
    214     local rv, err = client:connect(check.target, port, use_ssl) 
     214    local rv, err = client:connect(check.target_ip, port, use_ssl) 
    215215    
    216216    if rv ~= 0 then 
  • src/modules-lua/noit/module/smtp.lua

    ra957a50 rb553f9a  
    151151  local starttime = noit.timeval.now() 
    152152  local e = noit.socket() 
    153   local rv, err = e:connect(check.target, check.config.port or 25) 
     153  local rv, err = e:connect(check.target_ip, check.config.port or 25) 
    154154  check.unavailable() 
    155155 
  • src/modules-lua/noit/module/tcp.lua

    ra02eba1 rb553f9a  
    136136 
    137137  local e = noit.socket() 
    138   local rv, err = e:connect(check.target, check.config.port) 
     138  local rv, err = e:connect(check.target_ip, check.config.port) 
    139139 
    140140  if rv ~= 0 then 
  • src/modules-lua/noit/module/varnish.lua

    racf04f0 rb553f9a  
    8181function initiate(module, check) 
    8282  local e = noit.socket() 
    83   local rv, err = e:connect(check.target, check.config.port or 8081) 
     83  local rv, err = e:connect(check.target_ip, check.config.port or 8081) 
    8484 
    8585  e:write("stats\r\n") 
  • src/modules/dns.c

    r9761c2f rb553f9a  
    630630    nameserver = NULL; 
    631631    rtype = "PTR"; 
    632     query = "%[:inaddrarpa:target]"; 
     632    query = "%[:inaddrarpa:target_ip]"; 
    633633  } 
    634634  else { 
    635     nameserver = "%[target]"; 
     635    nameserver = "%[target_ip]"; 
    636636    rtype = "A"; 
    637637    query = "%[name]"; 
  • src/modules/dns.xml

    r9761c2f rb553f9a  
    1010    <parameter name="nameserver" 
    1111               required="optional" 
    12                default="%[target] or determined from underlying system" 
    13                allowed=".+">The domain name server to query. If the name of the check is in-addr.arpa, the system default nameserver is used.  Otherwise, the nameserver is the %[target] of the the check.  If set to the string "default" the underlying system default nameserver is used.</parameter> 
     12               default="%[target_ip] or determined from underlying system" 
     13               allowed=".+">The domain name server to query. If the name of the check is in-addr.arpa, the system default nameserver is used.  Otherwise, the nameserver is the %[target_ip] of the the check.  If set to the string "default" the underlying system default nameserver is used.</parameter> 
    1414    <parameter name="ctype" 
    1515               required="optional" 
     
    2222    <parameter name="query" 
    2323               required="required" 
    24                default="%[name]|%[:inaddrarpa:target]" 
     24               default="%[name]|%[:inaddrarpa:target_ip]" 
    2525               allowed=".+">The query to send.  If the name of the check is in-addr.arpa, the reverse IP octet notation of in-addr.arpa syntax is synthesized by default.  Otherwise the default query is the name of the check itself.</parameter> 
    2626    <parameter name="want_sort" 
  • src/modules/lua.c

    r3821135 rb553f9a  
    431431    case 't': 
    432432      if(!strcmp(k, "target")) lua_pushstring(L, check->target); 
     433      if(!strcmp(k, "target_ip")) { 
     434        if(check->target_ip[0] == '\0') lua_pushnil(L); 
     435        else lua_pushstring(L, check->target_ip); 
     436      } 
    433437      else if(!strcmp(k, "timeout")) lua_pushinteger(L, check->timeout); 
    434438      else break; 
  • src/modules/ping_icmp.c

    ref66c59 rb553f9a  
    108108    if(data->turnaround[i] < 0.0) { 
    109109      noitL(nldeb, "ping_icmp: %s %d is still outstanding.\n", 
    110             check->target, i); 
     110            check->target_ip, i); 
    111111      return 0; 
    112112    } 
     
    149149           "cnt=%d,avail=%0.0f,min=%0.4f,max=%0.4f,avg=%0.4f", 
    150150           (int)cnt, 100.0*avail, min, max, avg); 
    151   noitL(nldeb, "ping_icmp(%s) [%s]\n", check->target, human_buffer); 
     151  noitL(nldeb, "ping_icmp(%s) [%s]\n", check->target_ip, human_buffer); 
    152152 
    153153  gettimeofday(&current.whence, NULL); 
     
    392392  k.addr_of_check = payload->addr_of_check; 
    393393  uuid_copy(k.checkid, payload->checkid); 
     394 
     395  if(pcl->check->target_ip[0] == '\0') goto cleanup; 
     396 
    394397  if(!noit_hash_retrieve(data->in_flight, (const char *)&k, sizeof(k), 
    395398                         &vcheck)) { 
     
    398401  } 
    399402 
    400   noitLT(nldeb, now, "ping_icmp_real_send(%s)\n", pcl->check->target); 
     403  noitLT(nldeb, now, "ping_icmp_real_send(%s)\n", pcl->check->target_ip); 
    401404  gettimeofday(&payload->whence, NULL); /* now isn't accurate enough */ 
    402405  icp->icmp_cksum = in_cksum(pcl->payload, pcl->payload_len); 
     
    411414               (struct sockaddr *)&sin, sizeof(sin)); 
    412415  } 
    413   else
     416  else if(pcl->check->target_family == AF_INET6)
    414417    struct sockaddr_in6 sin; 
    415418    memset(&sin, 0, sizeof(sin)); 
     
    422425  } 
    423426  if(i != pcl->payload_len) { 
    424     noitLT(nlerr, now, "Error sending ICMP packet to %s: %s\n", 
    425              pcl->check->target, strerror(errno)); 
     427    noitLT(nlerr, now, "Error sending ICMP packet to %s(%s): %s\n", 
     428             pcl->check->target, pcl->check->target_ip, strerror(errno)); 
    426429  } 
    427430 cleanup: 
     
    474477  } 
    475478  noitL(nldeb, "ping_icmp_send(%p,%s,%d,%d)\n", 
    476         self, check->target, interval, count); 
     479        self, check->target_ip, interval, count); 
    477480 
    478481  /* remove a timeout if we still have one -- we should unless someone 
  • src/modules/snmp.c

    r000581a rb553f9a  
    894894    port = atoi(portstr); 
    895895  } 
    896   snprintf(target_port, sizeof(target_port), "%s:%d", check->target, port); 
     896  snprintf(target_port, sizeof(target_port), "%s:%d", check->target_ip, port); 
    897897  ts = _get_target_session(self, target_port); 
    898898  gettimeofday(&check->last_fire_time, NULL); 
  • src/modules/ssh2.c

    rfbc0571 rb553f9a  
    307307  memcpy(&check->last_fire_time, &__now, sizeof(__now)); 
    308308 
     309  if(check->target_ip[0] == '\0') { 
     310    ci->error = strdup("name resolution failure"); 
     311    goto fail; 
     312  } 
    309313  /* Open a socket */ 
    310314  fd = socket(check->target_family, SOCK_STREAM, 0); 
  • src/noit_check.c

    r8c720f9 rb553f9a  
    4949#include "noit_console.h" 
    5050#include "noit_check_tools.h" 
     51#include "noit_check_resolver.h" 
    5152#include "eventer/eventer.h" 
    5253 
     
    374375void 
    375376noit_poller_init() { 
     377  noit_check_resolver_init(); 
    376378  noit_check_tools_init(); 
    377379  noit_skiplist_init(&polls_by_name); 
     
    543545} 
    544546int 
     547noit_check_set_ip(noit_check_t *new_check, 
     548                  const char *ip_str) { 
     549  int8_t family; 
     550  int rv, failed = 0; 
     551  union { 
     552    struct in_addr addr4; 
     553    struct in6_addr addr6; 
     554  } a; 
     555 
     556 
     557  family = AF_INET; 
     558  rv = inet_pton(family, ip_str, &a); 
     559  if(rv != 1) { 
     560    family = AF_INET6; 
     561    rv = inet_pton(family, ip_str, &a); 
     562    if(rv != 1) { 
     563      family = AF_INET; 
     564      noitL(noit_error, "Cannot translate '%s' to IP\n", ip_str); 
     565      memset(&a, 0, sizeof(a)); 
     566      failed = -1; 
     567    } 
     568  } 
     569 
     570  new_check->target_family = family; 
     571  memcpy(&new_check->target_addr, &a, sizeof(a)); 
     572  new_check->target_ip[0] = '\0'; 
     573  if(failed == 0) 
     574    inet_ntop(new_check->target_family, 
     575              &new_check->target_addr, 
     576              new_check->target_ip, 
     577              sizeof(new_check->target_ip)); 
     578  return failed; 
     579} 
     580int 
     581noit_check_resolve(noit_check_t *check) { 
     582  uint8_t family_pref = AF_INET; 
     583  char ipaddr[INET6_ADDRSTRLEN]; 
     584  if(!NOIT_CHECK_SHOULD_RESOLVE(check)) return 1; /* success, not required */ 
     585  noit_check_resolver_remind(check->target); 
     586  if(noit_check_resolver_fetch(check->target, ipaddr, sizeof(ipaddr), 
     587                               family_pref) >= 0) { 
     588    check->flags |= NP_RESOLVED; 
     589    noit_check_set_ip(check, ipaddr); 
     590    return 0; 
     591  } 
     592  check->flags &= ~NP_RESOLVED; 
     593  return -1; 
     594} 
     595int 
    545596noit_check_update(noit_check_t *new_check, 
    546597                  const char *target, 
     
    552603                  const char *oncheck, 
    553604                  int flags) { 
    554   int8_t family; 
    555   int rv; 
    556605  int mask = NP_DISABLED | NP_UNCONFIG; 
    557   union { 
    558     struct in_addr addr4; 
    559     struct in6_addr addr6; 
    560   } a; 
    561  
    562  
    563   family = AF_INET; 
    564   rv = inet_pton(family, target, &a); 
    565   if(rv != 1) { 
    566     family = AF_INET6; 
    567     rv = inet_pton(family, target, &a); 
    568     if(rv != 1) { 
    569       noitL(noit_stderr, "Cannot translate '%s' to IP\n", target); 
    570       memset(&a, 0, sizeof(a)); 
    571       flags |= (NP_UNCONFIG | NP_DISABLED); 
    572     } 
    573   } 
    574606 
    575607  new_check->generation = __config_load_generation; 
    576   new_check->target_family = family; 
    577   memcpy(&new_check->target_addr, &a, sizeof(a)); 
    578608  if(new_check->target) free(new_check->target); 
    579609  new_check->target = strdup(target); 
     610 
     611  if(noit_check_set_ip(new_check, target)) { 
     612    noit_boolean should_resolve; 
     613    new_check->flags |= NP_RESOLVE; 
     614    new_check->flags &= ~NP_RESOLVED; 
     615    if(noit_conf_get_boolean(NULL, "//checks/@resolve_targets", 
     616                             &should_resolve) && should_resolve == noit_false) 
     617       
     618      flags |= NP_DISABLED | NP_UNCONFIG; 
     619    noit_check_resolve(new_check); 
     620  } 
     621 
    580622  if(new_check->name) free(new_check->name); 
    581623  new_check->name = name ? strdup(name): NULL; 
  • src/noit_check.h

    r8c720f9 rb553f9a  
    6767#define NP_UNCONFIG  0x00000008 
    6868#define NP_TRANSIENT 0x00000010 
     69#define NP_RESOLVE   0x00000020 
     70#define NP_RESOLVED  0x00000040 
    6971 
    7072#define NP_UNKNOWN '0'             /* stats_t.{available,state} */ 
     
    140142 
    141143  noit_skiplist *feeds; 
     144  char target_ip[INET6_ADDRSTRLEN]; 
    142145} noit_check_t; 
    143146 
     
    147150#define NOIT_CHECK_RUNNING(a) ((a)->flags & NP_RUNNING) 
    148151#define NOIT_CHECK_KILLED(a) ((a)->flags & NP_KILLED) 
     152#define NOIT_CHECK_SHOULD_RESOLVE(a) ((a)->flags & NP_RESOLVE) 
     153/* It is resolved if it is resolved or never needed to be resolved */ 
     154#define NOIT_CHECK_RESOLVED(a) (((a)->flags & NP_RESOLVED) || (((a)->flags & NP_RESOLVE) == 0)) 
    149155 
    150156API_EXPORT(void) noit_poller_init(); 
     
    175181 
    176182API_EXPORT(int) 
     183  noit_check_resolve(noit_check_t *check); 
     184 
     185API_EXPORT(int) 
    177186  noit_check_update(noit_check_t *new_check, 
    178187                    const char *target, 
  • src/noit_check_rest.c

    r1498116 rb553f9a  
    7272               NOIT_CHECK_CONFIGURED(check)?"true":"false"); 
    7373  NODE_CONTENT(state, "disabled", NOIT_CHECK_DISABLED(check)?"true":"false"); 
     74  NODE_CONTENT(state, "target_ip", check->target_ip); 
    7475  xmlAddChild(state, (tmp = xmlNewNode(NULL, (xmlChar *)"last_run"))); 
    7576  if(check->stats.current.whence.tv_sec) { 
     
    268269        else CHECK_N_SET(module) module = 1; /* This is validated by called */ 
    269270        else CHECK_N_SET(target) { 
     271          noit_boolean should_resolve; 
    270272          int valid; 
    271273          xmlChar *tmp; 
     
    273275          valid = noit_check_is_valid_target((char *)tmp); 
    274276          xmlFree(tmp); 
    275           if(!valid) { *error = "invalid target"; return 0; } 
     277          if(noit_conf_get_boolean(NULL, "//checks/@resolve_targets", 
     278                                   &should_resolve) && 
     279             should_resolve == noit_false && 
     280             !valid) { 
     281            *error = "invalid target"; 
     282            return 0; 
     283          } 
    276284          target = 1; 
    277285        } 
  • src/noit_check_tools.c

    r4b55797 rb553f9a  
    5151  noit_check_schedule_next(rcl->self, &e->whence, rcl->check, now, 
    5252                           rcl->dispatch); 
    53   rcl->dispatch(rcl->self, rcl->check); 
     53  noit_check_resolve(rcl->check); 
     54  if(NOIT_CHECK_RESOLVED(rcl->check)) 
     55    rcl->dispatch(rcl->self, rcl->check); 
     56  else 
     57    noitL(noit_debug, "skipping %s`%s`%s, unresolved\n", 
     58          rcl->check->target, rcl->check->module, rcl->check->name); 
    5459  free(rcl); 
    5560  return 0; 
     
    7580  else 
    7681    gettimeofday(&earliest, NULL); 
    77   period.tv_sec = check->period / 1000; 
    78   period.tv_usec = (check->period % 1000) * 1000; 
     82 
     83  /* If the check is unconfigured and needs resolving, we'll set the 
     84   * period down a bit lower so we can pick up the resolution quickly. 
     85   */ 
     86  if(!NOIT_CHECK_RESOLVED(check) && NOIT_CHECK_SHOULD_RESOLVE(check) && 
     87      check->period > 1000) { 
     88    period.tv_sec = 1; 
     89    period.tv_usec = 0; 
     90  } 
     91  else { 
     92    period.tv_sec = check->period / 1000; 
     93    period.tv_usec = (check->period % 1000) * 1000; 
     94  } 
    7995 
    8096  newe = eventer_alloc(); 
  • src/noit_check_tools_shared.c

    r4b55797 rb553f9a  
    181181#define CA_STORE(a,b) noit_hash_store(attrs, a, strlen(a), b) 
    182182  CA_STORE("target", check->target); 
     183  CA_STORE("target_ip", check->target_ip); 
    183184  CA_STORE("name", check->name); 
    184185  CA_STORE("module", check->module); 
  • src/noit_conf_checks.c

    r15d06bf rb553f9a  
    475475    else { 
    476476      int idx = 0; 
     477      nc_printf(ncct, " target_ip: %s\n", check->target_ip); 
    477478      nc_printf(ncct, " currently: "); 
    478479      if(NOIT_CHECK_RUNNING(check)) nc_printf(ncct, "%srunning", idx++?",":"");