Changeset e781d1eba05c6dd4520aec7f96642bc77a0f9de1

Show
Ignore:
Timestamp:
02/15/08 17:14:47 (6 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1203095687 +0000
git-parent:

[129a0bae7c19dce74dfb70efd8e069b47209c6d8]

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

oh dear, check creation?!

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_check.c

    re01b3ad re781d1e  
    156156    options = noit_conf_get_hash(sec[i], "ancestor-or-self::node()/config/*"); 
    157157 
     158    INHERIT(boolean, disable, &disabled); 
    158159    flags = 0; 
    159160    if(busted) flags |= NP_UNCONFIG; 
     
    162163    if(noit_hash_retrieve(&polls, (char *)uuid, UUID_SIZE, 
    163164                          (void **)&existing_check)) { 
     165      /* Once set, we can never change it. */ 
     166      assert(!existing_check->module || !existing_check->module[0] || 
     167             !strcmp(existing_check->module, module)); 
     168      /* Only set it if it is not yet set */ 
     169      if(!existing_check->module || !existing_check->module[0]) { 
     170        if(existing_check->module) free(existing_check->module); 
     171        existing_check->module = strdup(module); 
     172      } 
    164173      noit_check_update(existing_check, target, name, options, 
    165174                           period, timeout, oncheck[0] ? oncheck : NULL, 
     
    203212 
    204213void 
     214noit_poller_flush_epoch(int oldest_allowed) { 
     215  noit_hash_iter iter = NOIT_HASH_ITER_ZERO; 
     216  uuid_t key_id; 
     217  int klen; 
     218  noit_check_t *check, *tofree = NULL; 
     219 
     220  /* Cleanup any previous causal map */ 
     221  while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, 
     222                       (void **)&check)) { 
     223    /* We don't free the one we're looking at... we free it on the next 
     224     * pass.  This leaves out iterator in good shape.  We just need to 
     225     * remember to free it one last time outside the while loop, down... 
     226     */ 
     227    if(tofree) { 
     228      noit_poller_deschedule(tofree->checkid); 
     229      tofree = NULL; 
     230    } 
     231    if(check->generation < oldest_allowed) { 
     232      tofree = check; 
     233    } 
     234  } 
     235  /* ... here */ 
     236  if(tofree) noit_poller_deschedule(tofree->checkid); 
     237} 
     238 
     239void 
    205240noit_poller_make_causal_map() { 
    206241  noit_hash_iter iter = NOIT_HASH_ITER_ZERO; 
     
    219254  } 
    220255 
     256  memset(&iter, 0, sizeof(iter)); 
    221257  /* Walk all checks and add check dependencies to their parents */ 
    222258  while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, 
     
    228264      char *target = NULL; 
    229265 
     266      noitL(noit_debug, "Searching for upstream trigger on %s\n", name); 
    230267      if((target = strchr(check->oncheck, '`')) != NULL) { 
    231268        strlcpy(fullcheck, check->oncheck, target - check->oncheck); 
     
    258295{ 
    259296  noit_poller_process_checks(xpath ? xpath : "/noit/checks//check"); 
     297  if(!xpath) { 
     298    /* Full reload, we need to wipe old checks */ 
     299    noit_poller_flush_epoch(__config_load_generation); 
     300  } 
    260301  noit_poller_make_causal_map(); 
    261302  noit_poller_initiate(); 
  • src/noit_conf.c

    r129a0ba re781d1e  
    6767    master_config = new_config; 
    6868    xpath_ctxt = xmlXPathNewContext(master_config); 
    69     realpath(path, master_config_file); 
     69    if(path != master_config_file) realpath(path, master_config_file); 
    7070    return 0; 
    7171  } 
     
    202202  return 1; 
    203203} 
     204int noit_conf_get_uuid(noit_conf_section_t section, 
     205                       const char *path, uuid_t out) { 
     206  char *str; 
     207  if(_noit_conf_get_string(section,NULL,path,&str)) { 
     208    if(uuid_parse(str, out) == 0) return 1; 
     209    return 0; 
     210  } 
     211  return 0; 
     212} 
    204213int noit_conf_get_string(noit_conf_section_t section, 
    205214                         const char *path, char **value) { 
     
    313322  char argcopy[1024], *target, *name; 
    314323 
    315   strlcpy(argcopy, arg, sizeof(argcopy)); 
     324  argcopy[0] = '\0'; 
     325  if(arg) strlcpy(argcopy, arg, sizeof(argcopy)); 
     326 
    316327  if(uuid_parse(argcopy, checkid) == 0) { 
    317328    /* If they kill by uuid, we'll seek and destroy -- find it anywhere */ 
     
    334345  else { 
    335346    char *path = (!info || !strcmp(info->path, "/")) ? "" : info->path; 
    336     snprintf(xpath, len, "/noit%s/%s[@uuid]", path, arg); 
     347    snprintf(xpath, len, "/noit%s%s%s[@uuid]", 
     348             path, arg ? "/" : "", arg ? arg : ""); 
    337349  } 
    338350  return 0; 
     
    358370  nc_write(ncct, "\n", 1); 
    359371} 
     372static void  
     373refresh_subchecks(noit_console_closure_t ncct, 
     374                  noit_conf_t_userdata_t *info) { 
     375  char *path; 
     376  char xpath[1024]; 
     377  
     378  path = info->path; 
     379  if(!strcmp(path, "/")) path = ""; 
     380 
     381  /* The first one is just a process_checks, the second is the reload. 
     382   * Reload does a lot of work and there is no need to do it twice. 
     383   */ 
     384  snprintf(xpath, sizeof(xpath), "/noit/%s[@uuid]", path); 
     385  noit_poller_process_checks(xpath); 
     386  snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); 
     387  noit_poller_reload(xpath); 
     388} 
     389static int 
     390noit_conf_mkcheck_under(const char *ppath, uuid_t out) { 
     391  int rv = -1; 
     392  const char *path; 
     393  char xpath[1024]; 
     394  xmlXPathObjectPtr pobj = NULL; 
     395  xmlNodePtr node = NULL, newnode; 
     396 
     397  path = strcmp(ppath, "/") ? ppath : ""; 
     398  snprintf(xpath, sizeof(xpath), "/noit%s", path); 
     399  pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
     400  if(!pobj || pobj->type != XPATH_NODESET || 
     401     xmlXPathNodeSetGetLength(pobj->nodesetval) != 1) { 
     402    goto out; 
     403  } 
     404  node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     405  if((newnode = xmlNewChild(node, NULL, (xmlChar *)"check", NULL)) != NULL) { 
     406    char outstr[37]; 
     407    uuid_generate(out); 
     408    uuid_unparse_lower(out, outstr); 
     409    xmlSetProp(newnode, (xmlChar *)"uuid", (xmlChar *)outstr); 
     410    rv = 0; 
     411  } 
     412 out: 
     413  if(pobj) xmlXPathFreeObject(pobj); 
     414  return rv; 
     415} 
    360416static int 
    361417noit_console_check(noit_console_closure_t ncct, 
    362418                   int argc, char **argv, 
    363419                   noit_console_state_t *state, void *closure) { 
    364   int i, cnt; 
     420  int cnt; 
    365421  noit_conf_t_userdata_t *info; 
    366   char xpath[1024]; 
     422  char xpath[1024], newuuid_str[37]; 
     423  char *uuid_conf, *wanted; 
     424  uuid_t checkid; 
    367425  xmlXPathObjectPtr pobj = NULL; 
     426  xmlNodePtr node = NULL; 
     427  noit_conf_boolean creating_new = noit_false; 
    368428 
    369429  if(argc > 1) { 
     
    373433 
    374434  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     435  wanted = argc ? argv[0] : NULL; 
     436  if(!wanted) { 
     437    /* We are creating a new node */ 
     438    uuid_t out; 
     439    creating_new = noit_true; 
     440    if(noit_conf_mkcheck_under(info->path, out)) { 
     441      nc_printf(ncct, "Error creating new check\n"); 
     442      return -1; 
     443    } 
     444    newuuid_str[0] = '\0'; 
     445    uuid_unparse_lower(out, newuuid_str); 
     446    wanted = newuuid_str; 
     447  } 
    375448  /* We many not be in conf-t mode -- that's fine */ 
    376   if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, 
    377                                 argc ? argv[0] : ".")) { 
    378     nc_printf(ncct, "could not find check '%s'\n", argv[0]); 
     449  if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, wanted)) { 
     450    nc_printf(ncct, "could not find check '%s'\n", wanted); 
    379451    return -1; 
    380452  } 
     
    391463    goto out; 
    392464  } 
     465  node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); 
     466  uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); 
     467  if(!uuid_conf || uuid_parse(uuid_conf, checkid)) { 
     468    nc_printf(ncct, "%s has invalid or missing UUID!\n", 
     469              (char *)xmlGetNodePath(node) + strlen("/noit")); 
     470    goto out; 
     471  } 
     472  if(info) { 
     473    if(info->path) free(info->path); 
     474    info->path = strdup((char *)xmlGetNodePath(node) + strlen("/noit")); 
     475    uuid_copy(info->current_check, checkid); 
     476    if(creating_new) refresh_subchecks(ncct, info); 
     477    noit_console_state_push_state(ncct, state); 
     478    noit_console_state_init(ncct); 
     479    goto out; 
     480  } 
     481 out: 
     482  if(pobj) xmlXPathFreeObject(pobj); 
     483  return 0; 
     484} 
     485static int 
     486noit_console_show_check(noit_console_closure_t ncct, 
     487                        int argc, char **argv, 
     488                        noit_console_state_t *state, void *closure) { 
     489  int i, cnt; 
     490  noit_conf_t_userdata_t *info; 
     491  char xpath[1024]; 
     492  xmlXPathObjectPtr pobj = NULL; 
     493 
     494  if(argc > 1) { 
     495    nc_printf(ncct, "requires zero or one arguments\n"); 
     496    return -1; 
     497  } 
     498 
     499  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     500  /* We many not be in conf-t mode -- that's fine */ 
     501  if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, 
     502                                argc ? argv[0] : NULL)) { 
     503    nc_printf(ncct, "could not find check '%s'\n", argv[0]); 
     504    return -1; 
     505  } 
     506 
     507  pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
     508  if(!pobj || pobj->type != XPATH_NODESET || 
     509     xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
     510    nc_printf(ncct, "no checks found\n"); 
     511    goto out; 
     512  } 
     513  cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); 
     514  if(info && cnt != 1) { 
     515    nc_printf(ncct, "Ambiguous check specified\n"); 
     516    goto out; 
     517  } 
    393518  for(i=0; i<cnt; i++) { 
    394519    uuid_t checkid; 
     520    noit_check_t *check; 
    395521    xmlNodePtr node, anode, mnode = NULL; 
    396522    char *uuid_conf; 
     
    398524 
    399525    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); 
    400     if(info) { 
    401       if(info->path) free(info->path); 
    402       info->path = strdup((char *)xmlGetNodePath(node) + strlen("/noit")); 
    403     } 
    404526    uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); 
    405527    if(!uuid_conf || uuid_parse(uuid_conf, checkid)) { 
     
    430552    SHOW_ATTR(timeout); 
    431553    SHOW_ATTR(oncheck); 
     554    SHOW_ATTR(disable); 
     555    check = noit_poller_lookup(checkid); 
     556    if(!check) { 
     557      nc_printf(ncct, " ERROR: not in running system\n"); 
     558    } 
     559    else { 
     560      int idx = 0; 
     561      nc_printf(ncct, " currently: "); 
     562      if(NOIT_CHECK_RUNNING(check)) nc_printf(ncct, "%srunning", idx++?",":""); 
     563      if(NOIT_CHECK_KILLED(check)) nc_printf(ncct, "%skilled", idx++?",":""); 
     564      if(!NOIT_CHECK_CONFIGURED(check)) nc_printf(ncct, "%sunconfig", idx++?",":""); 
     565      if(NOIT_CHECK_DISABLED(check)) nc_printf(ncct, "%sdisabled", idx++?",":""); 
     566      nc_write(ncct, "\n", 1); 
     567      if(check->stats.current.status) 
     568        nc_printf(ncct, " recently: %s\n", check->stats.current.status); 
     569    } 
    432570  } 
    433571 out: 
     
    582720  xmlXPathContextPtr current_ctxt; 
    583721  xmlNodePtr node = NULL; 
    584  
    585   if(argc != 1) { 
     722  char *dest; 
     723 
     724  if(argc != 1 && !closure) { 
    586725    nc_printf(ncct, "requires one argument\n"); 
    587726    return -1; 
    588727  } 
     728  dest = argc ? argv[0] : (char *)closure; 
    589729  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
    590   if(argv[0][0] == '/') 
    591     snprintf(xpath, sizeof(xpath), "/noit%s", argv[0]); 
     730  if(dest[0] == '/') 
     731    snprintf(xpath, sizeof(xpath), "/noit%s", dest); 
    592732  else { 
    593     snprintf(xpath, sizeof(xpath), "/noit%s/%s", info->path, argv[0]); 
     733    snprintf(xpath, sizeof(xpath), "/noit%s/%s", info->path, dest); 
    594734  } 
    595735  if(xpath[strlen(xpath)-1] == '/') xpath[strlen(xpath)-1] = '\0'; 
     
    623763    info->path = strdup((char *)xmlGetNodePath(node) + strlen("/noit")); 
    624764  if(pobj) xmlXPathFreeObject(pobj); 
     765  if(closure) noit_console_state_pop(ncct, argc, argv, NULL, NULL); 
    625766  return 0; 
    626767 bad: 
     
    703844  /* _shorten string_ turning last { / @ * } to { / * } */ 
    704845  strlcpy(xpath + strlen(xpath) - 2, "*", 2); 
    705 nc_printf(ncct, "Looking up path '%s'\n", xpath); 
    706846  pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); 
    707847  if(!pobj || pobj->type != XPATH_NODESET) { 
     
    761901 
    762902static char * 
     903conf_t_check_prompt(EditLine *el) { 
     904  noit_console_closure_t ncct; 
     905  noit_conf_t_userdata_t *info; 
     906  noit_check_t *check; 
     907  static char *tl = "noit(conf)# "; 
     908  static char *pfmt = "noit(conf:%s%s%s)# "; 
     909 
     910  el_get(el, EL_USERDATA, (void *)&ncct); 
     911  if(!ncct) return tl; 
     912  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); 
     913  if(!info) return tl; 
     914 
     915  check = noit_poller_lookup(info->current_check); 
     916  if(check && 
     917     check->target && check->target[0] && 
     918     check->name && check->name[0]) 
     919    snprintf(info->prompt, sizeof(info->prompt), 
     920             pfmt, check->target, "`", check->name); 
     921  else { 
     922    char uuid_str[37]; 
     923    uuid_unparse_lower(info->current_check, uuid_str); 
     924    snprintf(info->prompt, sizeof(info->prompt), pfmt, "[", uuid_str, "]"); 
     925  } 
     926  return info->prompt; 
     927} 
     928static char * 
    763929conf_t_prompt(EditLine *el) { 
    764930  noit_console_closure_t ncct; 
     
    8651031  { "/checks", "timeout", "@timeout", 0 }, 
    8661032  { "/checks", "oncheck", "@oncheck", 0 }, 
     1033  { "/checks", "disable", "@disable", 0 }, 
    8671034  { "/checks", "module", "@module", 1 }, 
    8681035}; 
     
    8961063             noit_conf_t_userdata_t *info, struct _valid_attr_t *attrinfo, 
    8971064             const char *value) { 
    898   int cnt, rv = -1
     1065  int i, cnt, rv = -1, active = 0
    8991066  xmlXPathObjectPtr pobj = NULL; 
    9001067  xmlNodePtr node; 
     
    9121079    snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); 
    9131080    pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); 
    914     if(pobj && pobj->type == XPATH_NODESET && 
    915        !xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { 
    916       nc_printf(ncct, "Cannot set '%s', it would effect live checks\n", 
    917                 attrinfo->name); 
    918       goto out; 
     1081    if(!pobj || pobj->type != XPATH_NODESET) goto out; 
     1082    cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); 
     1083    for(i=0; i<cnt; i++) { 
     1084      uuid_t checkid; 
     1085      node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); 
     1086      if(noit_conf_get_uuid(node, "@uuid", checkid)) { 
     1087        noit_check_t *check; 
     1088        check = noit_poller_lookup(checkid); 
     1089        if(NOIT_CHECK_LIVE(check)) active++; 
     1090      } 
    9191091    } 
    9201092    if(pobj) xmlXPathFreeObject(pobj); 
     
    9311103  if(attrinfo->checks_fixate && 
    9321104     !strcmp((const char *)node->name, "check")) { 
     1105    uuid_t checkid; 
    9331106    /* Detect if  we are actually a <check> node and attempting to 
    9341107     * change something we shouldn't. 
    9351108     * This is the counterpart noted above. 
    9361109     */ 
    937     nc_printf(ncct, "Cannot set '%s', it would effect live checks\n"); 
     1110    if(noit_conf_get_uuid(node, "@uuid", checkid)) { 
     1111      noit_check_t *check; 
     1112      check = noit_poller_lookup(checkid); 
     1113      if(NOIT_CHECK_LIVE(check)) active++; 
     1114    } 
     1115  } 
     1116  if(active) { 
     1117    nc_printf(ncct, "Cannot set '%s', it would effect %d live check(s)\n", 
     1118              attrinfo->name, active); 
    9381119    goto out; 
    9391120  } 
     
    9451126  if(pobj) xmlXPathFreeObject(pobj); 
    9461127  return rv; 
    947 } 
    948 static void  
    949 refresh_subchecks(noit_console_closure_t ncct, 
    950                   noit_conf_t_userdata_t *info) { 
    951   char *path; 
    952   char xpath[1024]; 
    953   
    954   path = info->path; 
    955   if(!strcmp(path, "/")) path = ""; 
    956  
    957   /* The first one is just a process_checks, the second is the reload. 
    958    * Reload does a lot of work and there is no need to do it twice. 
    959    */ 
    960   snprintf(xpath, sizeof(xpath), "/noit/%s[@uuid]", path); 
    961   noit_poller_process_checks(xpath); 
    962   snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); 
    963   noit_poller_reload(xpath); 
    9641128} 
    9651129int 
     
    10391203  cmd_info_t *showcmd; 
    10401204  noit_console_state_t *tl, *_conf_state, *_conf_t_state, 
     1205                       *_conf_t_check_state, 
    10411206                       *_write_state, *_attr_state, 
    10421207                       *_unset_state, *_uattr_state; 
     
    10631228  ADD_CMD(_unset_state, "check", noit_console_config_nocheck, NULL, NULL); 
    10641229  
     1230  NEW_STATE(_conf_t_check_state); 
     1231  _conf_t_check_state->console_prompt_function = conf_t_check_prompt; 
     1232  DELEGATE_CMD(_conf_t_check_state, "attribute", _attr_state); 
     1233  DELEGATE_CMD(_conf_t_check_state, "no", _unset_state); 
     1234  ADD_CMD(_conf_t_check_state, "status", noit_console_show_check, NULL, NULL); 
     1235  ADD_CMD(_conf_t_check_state, "exit", noit_console_config_cd, NULL, ".."); 
     1236 
    10651237  NEW_STATE(_conf_t_state);  
    10661238  _conf_t_state->console_prompt_function = conf_t_prompt; 
     
    10681240  ADD_CMD(_conf_t_state, "ls", noit_console_config_show, NULL, NULL); 
    10691241  ADD_CMD(_conf_t_state, "cd", noit_console_config_cd, NULL, NULL); 
    1070   ADD_CMD(_conf_t_state, "check", noit_console_check, NULL, NULL); 
    10711242  ADD_CMD(_conf_t_state, "section", noit_console_config_section, NULL, (void *)0); 
     1243  ADD_CMD(_conf_t_state, "check", noit_console_check, _conf_t_check_state, NULL); 
    10721244 
    10731245  showcmd = noit_console_state_get_cmd(tl, "show"); 
    1074   ADD_CMD(showcmd->dstate, "check", noit_console_check, NULL, NULL); 
     1246  ADD_CMD(showcmd->dstate, "check", noit_console_show_check, NULL, NULL); 
    10751247 
    10761248  DELEGATE_CMD(_conf_t_state, "write", _write_state); 
  • src/noit_conf.h

    r7a1324a re781d1e  
    1717typedef struct { 
    1818  char *path; 
    19   char prompt[40]; 
     19  uuid_t current_check; 
     20  char prompt[50]; 
    2021} noit_conf_t_userdata_t; 
    2122 
  • src/sample.conf

    re01b3ad re781d1e  
    3939  </listeners> 
    4040  <checks> 
    41     <check uuid="1b4e28ba-2fa1-11d2-883f-b9b761bde3fb" /> 
     41    <check uuid="1b4e28ba-2fa1-11d2-883f-b9b761bde3fb" module="ping_icmp" target="10.80.116.4" period="15000" timeout="14000"/> 
    4242    <dc1 timeout="30000" period="60000"> 
    4343      <icmp module="ping_icmp" timeout="12000">