Changeset 629726b79fb2f0024767c64498f20e1743d963b2

Show
Ignore:
Timestamp:
12/05/10 18:29:06 (3 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1291573746 +0000
git-parent:

[c7cb2706c8c9efa28ec98e664f1ba670d7d6e5bb]

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

Running NTP checks against each noit is reasonable, but it would be good to be able to do all of this directly over port 43191.

Let's add a display of the time on the noit in the capabilities command. This can be used by an API client as a poor-man's time check. It will not be nearly as accurate as an NTP check, but we're looking for wild skew here anyway and this should do the trick.

closes #330

Files:

Legend:

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

    r4790fc8 r629726b  
    6363} 
    6464 
    65 int 
    66 noit_capabilities_handler(eventer_t e, int mask, void *closure, 
    67                           struct timeval *now) { 
    68   int newmask = EVENTER_WRITE | EVENTER_EXCEPTION; 
    69   acceptor_closure_t *ac = closure; 
    70   noit_capsvc_closure_t *cl = ac->service_ctx; 
    71  
    72   if(mask & EVENTER_EXCEPTION) { 
    73 socket_error: 
    74     /* Exceptions cause us to simply snip the connection */ 
    75 cleanup_shutdown: 
    76     eventer_remove_fd(e->fd); 
    77     e->opset->close(e->fd, &newmask, e); 
    78     if(cl) { 
    79       if(cl->buff) free(cl->buff); 
    80       free(cl); 
    81     } 
    82     if(ac) acceptor_closure_free(ac); 
    83     return 0; 
    84   } 
    85  
    86   if(!ac->service_ctx) { 
     65static void 
     66noit_capabilities_tobuff(noit_capsvc_closure_t *cl, eventer_func_t curr) { 
    8767    char vbuff[128]; 
    8868    noit_hash_table *lc; 
     
    9171    int klen; 
    9272    void *data; 
     73    struct timeval now; 
    9374 
    9475    xmlDocPtr xmldoc; 
    9576    xmlNodePtr root, cmds; 
    9677 
    97     cl = ac->service_ctx = calloc(1, sizeof(*cl)); 
    9878    /* fill out capabilities */ 
    99     noit_build_version(vbuff, sizeof(vbuff)); 
    10079 
    10180    /* Create an XML Document */ 
     
    10584 
    10685    /* Fill in the document */ 
     86    noit_build_version(vbuff, sizeof(vbuff)); 
    10787    xmlNewTextChild(root, NULL, (xmlChar *)"version", (xmlChar *)vbuff); 
     88 
     89    /* time (poor man's time check) */ 
     90    gettimeofday(&now, NULL); 
     91    snprintf(vbuff, sizeof(vbuff), "%llu.%03d", (unsigned long long)now.tv_sec, 
     92             now.tv_usec / 1000); 
     93    xmlNewTextChild(root, NULL, (xmlChar *)"current_time", (xmlChar *)vbuff); 
    10894 
    10995    cmds = xmlNewNode(NULL, (xmlChar *)"services"); 
     
    124110      cnode = xmlNewNode(NULL, (xmlChar *)"service"); 
    125111      xmlSetProp(cnode, (xmlChar *)"name", name ? (xmlChar *)name : NULL); 
    126       if(*f == ac->dispatch
     112      if(*f == curr
    127113        xmlSetProp(cnode, (xmlChar *)"connected", (xmlChar *)"true"); 
    128114      xmlAddChild(cmds, cnode); 
     
    154140    /* Clean up after ourselves */ 
    155141    xmlFreeDoc(xmldoc); 
     142} 
     143 
     144int 
     145noit_capabilities_handler(eventer_t e, int mask, void *closure, 
     146                          struct timeval *now) { 
     147  int newmask = EVENTER_WRITE | EVENTER_EXCEPTION; 
     148  acceptor_closure_t *ac = closure; 
     149  noit_capsvc_closure_t *cl = ac->service_ctx; 
     150 
     151  if(mask & EVENTER_EXCEPTION) { 
     152socket_error: 
     153    /* Exceptions cause us to simply snip the connection */ 
     154cleanup_shutdown: 
     155    eventer_remove_fd(e->fd); 
     156    e->opset->close(e->fd, &newmask, e); 
     157    if(cl) { 
     158      if(cl->buff) free(cl->buff); 
     159      free(cl); 
     160    } 
     161    if(ac) acceptor_closure_free(ac); 
     162    return 0; 
     163  } 
     164 
     165  if(!ac->service_ctx) { 
     166    cl = ac->service_ctx = calloc(1, sizeof(*cl)); 
     167    noit_capabilities_tobuff(cl, ac->dispatch); 
    156168  } 
    157169 
     
    169181  goto cleanup_shutdown; 
    170182} 
     183 
     184 
  • test/t/103_simple_noit.t

    r49b8645 r629726b  
    1 use Test::More tests => 6
     1use Test::More tests => 9
    22use XML::LibXML; 
    33use XML::LibXML::XPathContext; 
    44use testconfig; 
     5use Time::HiRes qw/gettimeofday tv_interval/; 
    56use apiclient; 
    67 
     
    89my $xp = XML::LibXML->new(); 
    910my $xpc = XML::LibXML::XPathContext->new(); 
     11my @r; 
     12my $doc; 
     13my $codes = {}; 
    1014 
    1115ok(start_noit("103", { logs_debug => { '' => 'false' } }), 'starting noit'); 
    1216sleep(1); 
    1317my $c = apiclient->new('localhost', $NOIT_API_PORT); 
    14 my @r = $c->get("/checks/show/f7cea020-f19d-11dd-85a6-cb6d3a2207dc"); 
     18my $req_time = [gettimeofday]; 
     19@r = $c->capabilities(); 
     20my $answer_time = [gettimeofday]; 
     21is($r[0], 0, 'capa'); 
     22$doc = $xp->parse_string($r[1]); 
     23foreach ($xpc->findnodes('/noit_capabilities/services/service[@name="control_dispatch"]/command', $doc)) { 
     24  $codes->{$_->getAttribute("code")} = $_->getAttribute("name"); 
     25
     26is_deeply($codes, 
     27          { '0xfa57feed' => 'livestream_transit' 
     28          , '0x43415041' => 'capabilities_transit' 
     29          , '0x44454c45' => 'noit_wire_rest_api' 
     30          , '0x47455420' => 'noit_wire_rest_api' 
     31          , '0x48454144' => 'noit_wire_rest_api' 
     32          , '0x4d455247' => 'noit_wire_rest_api' 
     33          , '0x504f5354' => 'noit_wire_rest_api' 
     34          , '0x50555420' => 'noit_wire_rest_api' 
     35          , '0x7e66feed' => 'log_transit' 
     36          , '0xda7afeed' => 'log_transit' 
     37          }, 
     38          'commands available'); 
     39 
     40# Time check 
     41my $remote_time = $xpc->findvalue('/noit_capabilities/current_time', $doc); 
     42my $request_duration = tv_interval($req_time, $answer_time); 
     43$remote_time += $request_duration/2.0; 
     44my $answer_time_sec = $answer_time->[0] + $answer_time->[1]/1000000.0; 
     45my $time_error = abs($remote_time - $answer_time_sec); 
     46cmp_ok($time_error, '<', $request_duration, 'time skew check'); 
     47 
     48@r = $c->get("/checks/show/f7cea020-f19d-11dd-85a6-cb6d3a2207dc"); 
    1549is($r[0], 404, 'get checks'); 
    1650 
     
    2054 
    2155is($r[0], 200, 'add selfcheck'); 
    22 my $doc = $xp->parse_string($r[1]); 
     56$doc = $xp->parse_string($r[1]); 
    2357is($xpc->findvalue('/check/attributes/uuid', $doc), 'f7cea020-f19d-11dd-85a6-cb6d3a2207dc', 'saved'); 
    2458 
  • test/t/apiclient.pm

    rc35ae3a r629726b  
    2727    my $self = shift; 
    2828    my $method = shift; 
    29     my $uri = shift
     29    my $uri = shift || '/'
    3030    if (@_) { 
    3131        my $payload = shift; 
     
    5252    die $self->{curl}->strerror($retcode); 
    5353} 
     54sub capabilities { shift->do('CAPA', @_); } 
    5455sub get { shift->do('GET', @_); } 
    5556sub post { shift->do('POST', @_); }