mockNagios.c

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002 
00003    Copyright (c) 2006-2010, Intellectual Reserve, Inc. All rights reserved.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License version 2 as
00007    published by the Free Software Foundation.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software
00016    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018   --------------------------------------------------------------------------*/
00019 
00033 #ifdef HAVE_CONFIG_H
00034 # include "config.h"
00035 #endif
00036 
00037 #ifndef NSCORE
00038 # define NSCORE
00039 #endif
00040 #include "nagios.h"
00041 #include "nebstructs.h"
00042 #include "nebcallbacks.h"
00043 #include "neberrors.h"
00044 #include "nebmodules.h"
00045 #include "broker.h"
00046 
00047 #include <stdio.h>
00048 #include <string.h>
00049 #include <signal.h>
00050 #include <dlfcn.h>
00051 
00052 #define USEC2MSEC 1000L
00053 
00054 typedef int nebmodule_init(int flags, char * args, void * handle);
00055 typedef int nebmodule_deinit(int flags, int reason);
00056 
00057 #if CURRENT_NEB_API_VERSION == 2
00058 
00059 int check_result_buffer_slots = 4096;
00060 circular_buffer service_result_buffer;
00061 
00062 int init_service_result_buffer(void)
00063 {
00064    int result;
00065 
00066    /* initialize circular buffer */
00067    service_result_buffer.head = 0;
00068    service_result_buffer.tail = 0;
00069    service_result_buffer.items = 0;
00070    service_result_buffer.high = 0;
00071    service_result_buffer.overflow = 0L;
00072    service_result_buffer.buffer = (void **)malloc(
00073       check_result_buffer_slots * sizeof(service_message **));
00074 
00075    if (service_result_buffer.buffer == 0)
00076       return ERROR;
00077 
00078    /* initialize mutex */
00079    pthread_mutex_init(&service_result_buffer.buffer_lock, 0);
00080 
00081    return OK;
00082 }
00083 
00084 # define OBJECT_FIELD_NAME object
00085 
00086 #elif CURRENT_NEB_API_VERSION == 3
00087 
00088 # define DIRECT_POST
00089 # ifdef DIRECT_POST
00090 
00091 check_result * check_result_list = 0;
00092 
00093 static volatile int results_processed = 0;
00094 
00095 void process_results_list(void)
00096 {
00097    check_result * tmp = check_result_list;
00098    while (tmp)
00099    {
00100       check_result_list = tmp->next;
00101       results_processed++;
00102       free(tmp->host_name);
00103       free(tmp->service_description);
00104       free(tmp->output);
00105       free(tmp);
00106       tmp = check_result_list;
00107    }
00108 }
00109 
00110 # else // !DIRECT_POST
00111 
00112 // used to indicate how many results have been processed 
00113 static volatile int files_moved = 0;
00114 
00115 int my_rename(char * source, char * destination)
00116 {
00117    files_moved++
00118    return rename(source, destination);
00119 }
00120 
00121 # endif // ?DIRECT_POST
00122 
00123 char * temp_path;
00124 char * check_result_path;
00125 
00126 check_result check_result_info;
00127 
00128 # define OBJECT_FIELD_NAME object_ptr
00129 
00130 #else
00131 # error Unsupported NEB API version.
00132 #endif
00133 
00134 service * service_list = 0;
00135 
00136 int (*pdata_callback)(int,void *);
00137 int (*schk_callback)(int,void *);
00138 int (*tevt_callback)(int,void *);
00139 
00140 int neb_register_callback(int callback_type, void *handle, 
00141       int priority, int (*callback_func)(int,void *))
00142 {
00143    int err = 0;
00144    if (callback_type == NEBCALLBACK_PROCESS_DATA)
00145       pdata_callback = callback_func;
00146    else if (callback_type == NEBCALLBACK_SERVICE_CHECK_DATA)
00147       schk_callback = callback_func;
00148    else if (callback_type == NEBCALLBACK_TIMED_EVENT_DATA)
00149       tevt_callback = callback_func;
00150    else
00151    {
00152       printf("Unhandled callback type in neb_register_callback.\n");
00153       err = -1;
00154    }
00155    return err;
00156 }
00157 
00158 int neb_deregister_callback(int callback_type, int (*callback_func)(int,void *))
00159 {
00160    int err = 0;
00161    if (callback_type == NEBCALLBACK_PROCESS_DATA)
00162       pdata_callback = 0;
00163    else if (callback_type == NEBCALLBACK_SERVICE_CHECK_DATA)
00164       schk_callback = 0;
00165    else if (callback_type == NEBCALLBACK_TIMED_EVENT_DATA)
00166       tevt_callback = 0;
00167    else 
00168    {
00169       printf("Unhandled callback type in neb_deregister_callback.\n");
00170       err = -1;
00171    }
00172    return err;
00173 }
00174 
00175 int neb_deregister_module_callbacks(nebmodule * mod)
00176 {
00177    return 0;
00178 }
00179 
00180 int neb_unload_module(void * handle, int (*deinitfunc)(int, int), int flags, int reason)
00181 {
00182    char temp_buffer[MAX_INPUT_BUFFER];
00183    int result;
00184 
00185    if (!handle) return -1;
00186 
00187    /* call the de-initialization function if available (and the module was initialized) */
00188    if (deinitfunc && reason != NEBMODULE_ERROR_BAD_INIT)
00189    {
00190       /* module can opt to not be unloaded */
00191       result = (*deinitfunc)(flags, reason);
00192 
00193       /* if module doesn't want to be unloaded, exit with error (unless its being forced) */
00194       if (result != OK && !(flags & NEBMODULE_FORCE_UNLOAD))
00195          return ERROR;
00196    }
00197 
00198    /* deregister all of the module's callbacks */
00199    // neb_deregister_module_callbacks(mod);
00200 
00201    /* unload the module */
00202    result = dlclose(handle);
00203 
00204    return OK;
00205 }
00206 
00207 int main(int argc, char ** argv)
00208 {
00209    int i, ret;
00210    void * handle; 
00211    nebmodule_init * initptr;
00212    nebmodule_deinit * deinitptr;
00213    int * module_version_ptr;
00214    nebstruct_process_data pdata;
00215    service svc;
00216    nebstruct_service_check_data svcdata;
00217    timed_event evt;
00218    nebstruct_timed_event_data evtdata;
00219    int dnxHandled = 0;
00220    int nagiosHandled = 0; 
00221 
00222    if (argc != 4)
00223    {
00224       printf("Usage: mockNagios <run-path> <dnx-plugin-path> <dnx-server-cfg-path>\n");
00225       exit(1);
00226    }
00227 
00228    // ignore broken pipe signals
00229    signal(SIGPIPE, SIG_IGN);
00230 
00231 #if CURRENT_NEB_API_VERSION == 2
00232 
00233    init_service_result_buffer();
00234    
00235 #elif CURRENT_NEB_API_VERSION == 3
00236    
00237    memset(&check_result_info, 0, sizeof check_result_info);
00238    temp_path = check_result_path = argv[1];
00239    
00240 #endif
00241 
00242    if ((handle = dlopen(argv[2], RTLD_NOW|RTLD_GLOBAL)) == 0)
00243    {
00244       printf("Error opening %s: %s.\n", argv[2], dlerror());
00245       return -1;
00246    }
00247 
00248    initptr = dlsym(handle, "nebmodule_init");
00249    deinitptr = dlsym(handle, "nebmodule_deinit");
00250    if (initptr == 0 || deinitptr == 0)
00251    {
00252       printf("Error importing symbols: %s.\n", dlerror());
00253       return -1;
00254    }
00255 
00256    module_version_ptr = (int *)dlsym(handle, "__neb_api_version");
00257    if (!module_version_ptr || *module_version_ptr != CURRENT_NEB_API_VERSION)
00258    {
00259       printf("Error: Module '%s' is using an old or unspecified version of "
00260             "the event broker API. Module will be unloaded.\n", argv[2]);
00261       
00262       neb_unload_module(handle, deinitptr, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_NO_INIT);
00263       return -1; 
00264    }
00265 
00266    if ((ret = initptr(0, argv[3], handle)) != 0)
00267    {
00268       printf("Error executing init: %d.\n", ret);
00269       return ret;
00270    }
00271 
00272    if (pdata_callback == 0)
00273    {
00274       printf("Oops! init function didn't register process data callback.\n");
00275       return -1;
00276    }
00277 
00278    pdata.type = NEBTYPE_PROCESS_EVENTLOOPSTART;
00279    if ((ret = pdata_callback(NEBCALLBACK_PROCESS_DATA, &pdata)) != 0)
00280    {
00281       printf("pdata_callback returned %d.\n", ret);
00282       return ret;
00283    }
00284 
00285    if (schk_callback == 0)
00286    {
00287       printf("Oops! pdata_callback didn't register svc check callback.\n");
00288       return -1;
00289    }
00290 
00291 #ifdef DIRECT_POST
00292    if (tevt_callback == 0)
00293    {
00294       printf("Oops! pdata_callback didn't register timed event callback.\n");
00295       return -1;
00296    }
00297 #endif
00298 
00299    // give the client time to wake up and notice the server is running
00300    sleep(2);
00301 
00302    // post 100 bogus service checks
00303    svc.host_name = "bogushost";
00304    svc.description = "description of a bogushost";
00305    svc.parallelize = 1;
00306    svcdata.type = NEBTYPE_SERVICECHECK_INITIATE;
00307    svcdata.command_line = "/bin/check.script --version";
00308    gettimeofday(&svcdata.start_time, 0);
00309    svcdata.OBJECT_FIELD_NAME = &svc;
00310    svcdata.timeout = 10;
00311    for (i = 0; i < 100; i++)
00312    {
00313       // imitate Nagios internal latency; sleep 10 ms between calls
00314       usleep(10L * USEC2MSEC);
00315       ret = schk_callback(NEBCALLBACK_SERVICE_CHECK_DATA, &svcdata);
00316       if (ret == NEBERROR_CALLBACKOVERRIDE)
00317          dnxHandled++;
00318       else if (ret == 0)
00319          nagiosHandled++;
00320       else
00321       {
00322          printf("schk_callback failed: %d.\n", ret);
00323          return -1;
00324       }
00325    }
00326    printf("TEST: DNX handled %d, Nagios handled %d of %d checks.\n", 
00327          dnxHandled, nagiosHandled, i);
00328 
00329    if (getenv("DNX_KEYSTROKE_TERMINATE") != 0)
00330    {
00331       printf("Press any key to terminate...");
00332       getchar();
00333       printf("Cleaning up, please wait...\n");
00334    }
00335    
00336    // wait for all results to be posted back to results buffer
00337 #if CURRENT_NEB_API_VERSION == 2
00338 
00339    while (service_result_buffer.items < dnxHandled)
00340       usleep(250L * USEC2MSEC);
00341 
00342 #elif CURRENT_NEB_API_VERSION == 3
00343 # ifdef DIRECT_POST
00344 
00345    evt.event_type = EVENT_CHECK_REAPER;
00346    evt.recurring = 1;
00347    evt.run_time = 0;
00348    evt.event_data = 0;
00349 
00350    evtdata.type = NEBTYPE_TIMEDEVENT_EXECUTE;
00351    evtdata.flags = 0;
00352    evtdata.attr = 0; 
00353    gettimeofday(&evtdata.timestamp, 0);
00354    evtdata.event_type = evt.event_type;
00355    evtdata.recurring = evt.recurring;
00356    evtdata.run_time = evt.run_time;
00357    evtdata.event_data = evt.event_data;
00358    evtdata.event_ptr = &evt;
00359 
00360    tevt_callback(NEBCALLBACK_TIMED_EVENT_DATA, &evtdata);
00361    process_results_list();
00362    while (results_processed < dnxHandled)
00363    {
00364       usleep(500L * USEC2MSEC);
00365       tevt_callback(NEBCALLBACK_TIMED_EVENT_DATA, &evtdata);
00366       process_results_list();
00367    }
00368 
00369 # else
00370 
00371    while (files_moved < dnxHandled)
00372       usleep(250L * USEC2MSEC);
00373 
00374 # endif
00375 #endif
00376 
00377    // going down...
00378    if ((ret = deinitptr(0, 0)) != 0)
00379    {
00380       printf("Error executing deinit: %d.\n", ret);
00381       return ret;
00382    }
00383 
00384 #ifdef DIRECT_POST
00385    if (tevt_callback != 0)
00386    {
00387       printf("Oops! deinit didn't deregister timed event callback.\n");
00388       return -1;
00389    }
00390 #endif
00391 
00392    if (schk_callback != 0)
00393    {
00394       printf("Oops! deinit didn't deregister svc check callback.\n");
00395       return -1;
00396    }
00397 
00398    if (pdata_callback != 0)
00399    {
00400       printf("Oops! deinit didn't deregister process data callback.\n");
00401       return -1;
00402    }
00403 
00404 
00405    dlclose(handle);
00406    return 0;
00407 }
00408 
00409 /*--------------------------------------------------------------------------*/
00410 

Generated on Tue Apr 13 15:48:07 2010 for DNX by  doxygen 1.5.6