![]() |
Icinga-core 1.4.0
next gen monitoring
|
00001 /***************************************************************************** 00002 * 00003 * STATUSWRL.C - Icinga 3-D (VRML) Network Status View 00004 * 00005 * Copyright (c) 1999-2007 Ethan Galstad (egalstad@nagios.org) 00006 * Copyright (c) 2009-2011 Icinga Development Team (http://www.icinga.org) 00007 * 00008 * Description: 00009 * 00010 * This CGI will dynamically create a 3-D VRML model of all hosts that are 00011 * being monitored on your network. 00012 * 00013 * License: 00014 * 00015 * This program is free software; you can redistribute it and/or modify 00016 * it under the terms of the GNU General Public License version 2 as 00017 * published by the Free Software Foundation. 00018 * 00019 * This program is distributed in the hope that it will be useful, 00020 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 * GNU General Public License for more details. 00023 * 00024 * You should have received a copy of the GNU General Public License 00025 * along with this program; if not, write to the Free Software 00026 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00027 * 00028 *****************************************************************************/ 00029 00030 #include "../include/config.h" 00031 #include "../include/common.h" 00032 #include "../include/objects.h" 00033 #include "../include/statusdata.h" 00034 00035 #include "../include/cgiutils.h" 00036 #include "../include/getcgi.h" 00037 #include "../include/cgiauth.h" 00038 00039 extern char main_config_file[MAX_FILENAME_LENGTH]; 00040 extern char url_html_path[MAX_FILENAME_LENGTH]; 00041 extern char url_images_path[MAX_FILENAME_LENGTH]; 00042 extern char url_logo_images_path[MAX_FILENAME_LENGTH]; 00043 extern char url_js_path[MAX_FILENAME_LENGTH]; 00044 00045 extern char *statuswrl_include; 00046 00047 extern host *host_list; 00048 extern service *service_list; 00049 00050 extern int default_statuswrl_layout_method; 00051 00052 00053 #define ICINGA_VRML_IMAGE "icingavrml.png" 00054 00055 #define DEFAULT_NODE_WIDTH 0.5 00056 #define DEFAULT_HORIZONTAL_SPACING 1.0 00057 #define DEFAULT_VERTICAL_SPACING 1.0 00058 00059 /* needed for auto-layout modes */ 00060 #define DEFAULT_NODE_HEIGHT 0.5 00061 #define DEFAULT_NODE_HSPACING 1.0 00062 #define DEFAULT_NODE_VSPACING 1.0 00063 #define CIRCULAR_DRAWING_RADIUS 5.0 00064 00065 #define LAYOUT_USER_SUPPLIED 0 00066 #define LAYOUT_COLLAPSED_TREE 2 00067 #define LAYOUT_BALANCED_TREE 3 00068 #define LAYOUT_CIRCULAR 4 00069 00070 00071 void calculate_host_coords(void); 00072 void calculate_world_bounds(void); 00073 void display_world(void); 00074 void write_global_vrml_data(void); 00075 void draw_process_icon(void); 00076 void draw_host(host *); 00077 void draw_host_links(void); 00078 void draw_host_link(host *,double,double,double,double,double,double); 00079 int process_cgivars(void); 00080 00081 int number_of_host_layer_members(host *,int); 00082 int max_child_host_layer_members(host *); 00083 int host_child_depth_separation(host *, host *); 00084 int max_child_host_drawing_width(host *); 00085 00086 void calculate_balanced_tree_coords(host *,int,int); 00087 void calculate_circular_coords(void); 00088 void calculate_circular_layer_coords(host *,double,double,int,int); 00089 00090 00091 authdata current_authdata; 00092 00093 float link_radius=0.016; 00094 00095 float floor_width=0.0; 00096 float floor_depth=0.0; 00097 00098 double min_z_coord=0.0; 00099 double min_x_coord=0.0; 00100 double min_y_coord=0.0; 00101 double max_z_coord=0.0; 00102 double max_x_coord=0.0; 00103 double max_y_coord=0.0; 00104 00105 double max_world_size=0.0; 00106 00107 double nagios_icon_x=0.0; 00108 double nagios_icon_y=0.0; 00109 int draw_nagios_icon=FALSE; 00110 00111 double custom_viewpoint_x=0.0; 00112 double custom_viewpoint_y=0.0; 00113 double custom_viewpoint_z=0.0; 00114 int custom_viewpoint=FALSE; 00115 00116 float vertical_spacing=DEFAULT_VERTICAL_SPACING; 00117 float horizontal_spacing=DEFAULT_HORIZONTAL_SPACING; 00118 float node_width=DEFAULT_NODE_WIDTH; 00119 float node_height=DEFAULT_NODE_WIDTH; /* should be the same as the node width */ 00120 00121 int use_textures=TRUE; 00122 int use_text=TRUE; 00123 int use_links=TRUE; 00124 00125 int layout_method=LAYOUT_USER_SUPPLIED; 00126 00127 int coordinates_were_specified=FALSE; /* were drawing coordinates specified with extended host info entries? */ 00128 00129 extern int daemon_check; 00130 00131 int display_type=DISPLAY_HOSTS; 00132 int show_all_hosts=TRUE; 00133 int show_all_hostgroups=TRUE; 00134 int show_all_servicegroups=TRUE; 00135 00136 char *host_name="all"; 00137 char *host_filter=NULL; 00138 char *hostgroup_name=NULL; 00139 char *servicegroup_name=NULL; 00140 char *service_desc=NULL; 00141 char *service_filter=NULL; 00142 00143 int CGI_ID=STATUSWRL_CGI_ID; 00144 00145 int main(int argc, char **argv){ 00146 int result; 00147 00148 /* reset internal variables */ 00149 reset_cgi_vars(); 00150 00151 /* read the CGI configuration file */ 00152 result=read_cgi_config_file(get_cgi_config_location()); 00153 if(result==ERROR){ 00154 document_header(CGI_ID,TRUE); 00155 return ERROR; 00156 } 00157 00158 /* defaults from CGI config file */ 00159 layout_method=default_statuswrl_layout_method; 00160 00161 /* get the arguments passed in the URL */ 00162 process_cgivars(); 00163 00164 document_header(CGI_ID,TRUE); 00165 00166 /* read the main configuration file */ 00167 result=read_main_config_file(main_config_file); 00168 if(result==ERROR) 00169 return ERROR; 00170 00171 /* read all object configuration data */ 00172 result=read_all_object_configuration_data(main_config_file,READ_ALL_OBJECT_DATA); 00173 if(result==ERROR) 00174 return ERROR; 00175 00176 /* read all status data */ 00177 result=read_all_status_data(get_cgi_config_location(),READ_ALL_STATUS_DATA); 00178 if(result==ERROR && daemon_check==TRUE){ 00179 free_memory(); 00180 return ERROR; 00181 } 00182 00183 /* get authentication information */ 00184 get_authentication_information(¤t_authdata); 00185 00186 /* display the 3-D VRML world... */ 00187 display_world(); 00188 00189 /* free all allocated memory */ 00190 free_memory(); 00191 00192 return OK; 00193 } 00194 00195 int process_cgivars(void){ 00196 char **variables; 00197 int error=FALSE; 00198 int x; 00199 00200 variables=getcgivars(); 00201 00202 for(x=0;variables[x]!=NULL;x++){ 00203 00204 /* do some basic length checking on the variable identifier to prevent buffer overflows */ 00205 if(strlen(variables[x])>=MAX_INPUT_BUFFER-1){ 00206 x++; 00207 continue; 00208 } 00209 00210 00211 /* we found the host argument */ 00212 else if(!strcmp(variables[x],"host")){ 00213 x++; 00214 if(variables[x]==NULL){ 00215 error=TRUE; 00216 break; 00217 } 00218 00219 if((host_name=(char *)strdup(variables[x]))==NULL) 00220 host_name="all"; 00221 else 00222 strip_html_brackets(host_name); 00223 00224 if(!strcmp(host_name,"all")) 00225 show_all_hosts=TRUE; 00226 else 00227 show_all_hosts=FALSE; 00228 } 00229 00230 /* we found the no textures argument*/ 00231 else if(!strcmp(variables[x],"notextures")) 00232 use_textures=FALSE; 00233 00234 /* we found the no text argument*/ 00235 else if(!strcmp(variables[x],"notext")) 00236 use_text=FALSE; 00237 00238 /* we found the no links argument*/ 00239 else if(!strcmp(variables[x],"nolinks")) 00240 use_links=FALSE; 00241 00242 /* we found the layout method option */ 00243 else if(!strcmp(variables[x],"layout")){ 00244 x++; 00245 if(variables[x]==NULL){ 00246 error=TRUE; 00247 break; 00248 } 00249 layout_method=atoi(variables[x]); 00250 } 00251 00252 /* we found custom viewpoint coord */ 00253 else if(!strcmp(variables[x],"viewx")){ 00254 x++; 00255 if(variables[x]==NULL){ 00256 error=TRUE; 00257 break; 00258 } 00259 custom_viewpoint_x=strtod(variables[x],NULL); 00260 custom_viewpoint=TRUE; 00261 } 00262 else if(!strcmp(variables[x],"viewy")){ 00263 x++; 00264 if(variables[x]==NULL){ 00265 error=TRUE; 00266 break; 00267 } 00268 custom_viewpoint_y=strtod(variables[x],NULL); 00269 custom_viewpoint=TRUE; 00270 } 00271 else if(!strcmp(variables[x],"viewz")){ 00272 x++; 00273 if(variables[x]==NULL){ 00274 error=TRUE; 00275 break; 00276 } 00277 custom_viewpoint_z=strtod(variables[x],NULL); 00278 custom_viewpoint=TRUE; 00279 } 00280 00281 /* we found the nodaemoncheck option */ 00282 else if(!strcmp(variables[x],"nodaemoncheck")) 00283 daemon_check=FALSE; 00284 00285 } 00286 00287 /* free memory allocated to the CGI variables */ 00288 free_cgivars(variables); 00289 00290 return error; 00291 } 00292 00293 00294 00295 /* top-level VRML world generation... */ 00296 void display_world(void){ 00297 host *temp_host=NULL; 00298 00299 /* get the url we will use to grab the logo images... */ 00300 snprintf(url_logo_images_path,sizeof(url_logo_images_path),"%slogos/",url_images_path); 00301 url_logo_images_path[sizeof(url_logo_images_path)-1]='\x0'; 00302 00303 /* calculate host drawing coordinates */ 00304 calculate_host_coords(); 00305 00306 /* calculate world bounds */ 00307 calculate_world_bounds(); 00308 00309 /* get the floor dimensions */ 00310 if(max_x_coord>0) 00311 floor_width=(float)(max_x_coord-min_x_coord)+(node_width*2); 00312 else 00313 floor_width=(float)(max_x_coord+min_x_coord)+(node_width*2); 00314 if(max_z_coord>0) 00315 floor_depth=(float)(max_z_coord-min_z_coord)+(node_height*2); 00316 else 00317 floor_depth=(float)(max_z_coord+min_z_coord)+(node_height*2); 00318 00319 /* write global VRML data */ 00320 write_global_vrml_data(); 00321 00322 /* no coordinates were specified, so display warning message */ 00323 if(coordinates_were_specified==FALSE){ 00324 00325 printf("\n"); 00326 printf("Transform{\n"); 00327 printf("translation 0.0 0.0 0.0\n"); 00328 printf("children[\n"); 00329 00330 printf("Billboard{\n"); 00331 printf("children[\n"); 00332 printf("Shape{\n"); 00333 printf("appearance Appearance {\n"); 00334 printf("material Material {\n"); 00335 printf("diffuseColor 1 0 0\n"); 00336 printf("}\n"); 00337 printf("}\n"); 00338 printf("geometry Text {\n"); 00339 printf("string [ \"Error: You have not supplied any 3-D drawing coordinates.\", \"Read the documentation for more information on supplying\", \"3-D drawing coordinates by defining\", \"extended host information entries in your config files.\" ]\n"); 00340 printf("fontStyle FontStyle {\n"); 00341 printf("family \"TYPEWRITER\"\n"); 00342 printf("size 0.3\n"); 00343 printf("justify \"MIDDLE\"\n"); 00344 printf("}\n"); 00345 printf("}\n"); 00346 printf("}\n"); 00347 printf("]\n"); 00348 printf("}\n"); 00349 00350 printf("]\n"); 00351 printf("}\n"); 00352 } 00353 00354 /* coordinates were specified... */ 00355 else{ 00356 00357 /* draw Icinga icon */ 00358 if(layout_method!=LAYOUT_USER_SUPPLIED) 00359 draw_process_icon(); 00360 00361 /* draw all hosts */ 00362 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next) 00363 draw_host(temp_host); 00364 00365 /* draw host links */ 00366 draw_host_links(); 00367 } 00368 00369 return; 00370 } 00371 00372 00373 00374 00375 /******************************************************************/ 00376 /************************ UTILITY FUNCTIONS ***********************/ 00377 /******************************************************************/ 00378 00379 /* calculates how many "layers" separate parent and child - used by collapsed tree layout method */ 00380 int host_child_depth_separation(host *parent, host *child){ 00381 int this_depth=0; 00382 int min_depth=0; 00383 int have_min_depth=FALSE; 00384 host *temp_host; 00385 00386 if(child==NULL) 00387 return -1; 00388 00389 if(parent==child) 00390 return 0; 00391 00392 if(is_host_immediate_child_of_host(parent,child)==TRUE) 00393 return 1; 00394 00395 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00396 00397 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ 00398 00399 this_depth=host_child_depth_separation(temp_host,child); 00400 00401 if(this_depth>=0 && (have_min_depth==FALSE || (have_min_depth==TRUE && (this_depth<min_depth)))){ 00402 have_min_depth=TRUE; 00403 min_depth=this_depth; 00404 } 00405 } 00406 } 00407 00408 if(have_min_depth==FALSE) 00409 return -1; 00410 else 00411 return min_depth+1; 00412 } 00413 00414 00415 00416 /* calculates how many hosts reside on a specific "layer" - used by collapsed tree layout method */ 00417 int number_of_host_layer_members(host *parent, int layer){ 00418 int current_layer; 00419 int layer_members=0; 00420 host *temp_host; 00421 00422 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00423 00424 current_layer=host_child_depth_separation(parent,temp_host); 00425 00426 if(current_layer==layer) 00427 layer_members++; 00428 } 00429 00430 return layer_members; 00431 } 00432 00433 00434 00435 /* calculate max number of members on all "layers" beneath and including parent host - used by collapsed tree layout method */ 00436 int max_child_host_layer_members(host *parent){ 00437 int current_layer; 00438 int max_members=1; 00439 int current_members=0; 00440 00441 for(current_layer=1;;current_layer++){ 00442 00443 current_members=number_of_host_layer_members(parent,current_layer); 00444 00445 if(current_members<=0) 00446 break; 00447 00448 if(current_members>max_members) 00449 max_members=current_members; 00450 } 00451 00452 return max_members; 00453 } 00454 00455 00456 00457 /* calculate max drawing width for host and children - used by balanced tree layout method */ 00458 int max_child_host_drawing_width(host *parent){ 00459 host *temp_host; 00460 int child_width=0; 00461 00462 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00463 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE) 00464 child_width+=max_child_host_drawing_width(temp_host); 00465 } 00466 00467 /* no children, so set width to 1 for this host */ 00468 if(child_width==0) 00469 return 1; 00470 00471 else 00472 return child_width; 00473 } 00474 00475 00476 00477 00478 /******************************************************************/ 00479 /********************* CALCULATION FUNCTIONS **********************/ 00480 /******************************************************************/ 00481 00482 /* calculates host drawing coordinates */ 00483 void calculate_host_coords(void){ 00484 host *this_host; 00485 host *temp_host; 00486 int parent_hosts=0; 00487 int max_layer_width=1; 00488 int current_parent_host=0; 00489 int center_x=0; 00490 int offset_x=DEFAULT_NODE_WIDTH/2; 00491 int offset_y=DEFAULT_NODE_WIDTH/2; 00492 int current_layer=0; 00493 int layer_members=0; 00494 int current_layer_member=0; 00495 int max_drawing_width=0; 00496 00497 00498 /******************************/ 00499 /***** MANUAL LAYOUT MODE *****/ 00500 /******************************/ 00501 00502 /* user-supplied coords */ 00503 if(layout_method==LAYOUT_USER_SUPPLIED){ 00504 00505 /* see which hosts we should draw (only those with 3-D coords) */ 00506 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00507 00508 if(temp_host->have_3d_coords==TRUE) 00509 temp_host->should_be_drawn=TRUE; 00510 else 00511 temp_host->should_be_drawn=FALSE; 00512 } 00513 00514 return; 00515 } 00516 00517 /*****************************/ 00518 /***** AUTO-LAYOUT MODES *****/ 00519 /*****************************/ 00520 00521 /* add empty extended host info entries for all hosts that don't have any */ 00522 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00523 00524 /* none was found, so add a blank one */ 00525 /* 00526 if(temp_hostextinfo==NULL) 00527 add_hostextinfo(temp_host->name,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0.0,0.0,0.0,0,0); 00528 */ 00529 00530 /* default z coord should 0 for auto-layout modes unless overridden later */ 00531 /* 00532 else 00533 */ 00534 temp_host->z_3d=0.0; 00535 } 00536 00537 00538 /***** COLLAPSED TREE MODE *****/ 00539 if(layout_method==LAYOUT_COLLAPSED_TREE){ 00540 00541 /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */ 00542 this_host=NULL; 00543 00544 /* find total number of immediate parents for this host */ 00545 parent_hosts=number_of_immediate_parent_hosts(this_host); 00546 00547 /* find the max layer width we have... */ 00548 max_layer_width=max_child_host_layer_members(this_host); 00549 if(parent_hosts>max_layer_width) 00550 max_layer_width=parent_hosts; 00551 00552 /* calculate center x coord */ 00553 center_x=(((DEFAULT_NODE_WIDTH*max_layer_width)+(DEFAULT_NODE_HSPACING*(max_layer_width-1)))/2)+offset_x; 00554 00555 /* coords for Icinga icon if necessary */ 00556 if(this_host==NULL || this_host->parent_hosts==NULL){ 00557 nagios_icon_x=center_x; 00558 nagios_icon_y=offset_y; 00559 draw_nagios_icon=TRUE; 00560 } 00561 00562 /* do we need to draw a link to parent(s)? */ 00563 if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE) 00564 offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 00565 00566 /* see which hosts we should draw and calculate drawing coords */ 00567 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00568 00569 /* this is an immediate parent of the "main" host we're drawing */ 00570 if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ 00571 temp_host->should_be_drawn=TRUE; 00572 temp_host->have_3d_coords=TRUE; 00573 temp_host->x_3d=center_x-(((parent_hosts*DEFAULT_NODE_WIDTH)+((parent_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_parent_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); 00574 temp_host->y_3d=offset_y; 00575 current_parent_host++; 00576 } 00577 00578 /* this is the "main" host we're drawing */ 00579 else if(this_host==temp_host){ 00580 temp_host->should_be_drawn=TRUE; 00581 temp_host->have_3d_coords=TRUE; 00582 temp_host->x_3d=center_x; 00583 temp_host->y_3d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; 00584 } 00585 00586 /* else do not draw this host (we might if its a child - see below, but assume no for now) */ 00587 else{ 00588 temp_host->should_be_drawn=FALSE; 00589 temp_host->have_3d_coords=FALSE; 00590 } 00591 } 00592 00593 00594 /* TODO: REORDER CHILD LAYER MEMBERS SO THAT WE MINIMIZE LINK CROSSOVERS FROM PARENT HOSTS */ 00595 00596 /* draw hosts in child "layers" */ 00597 for(current_layer=1;;current_layer++){ 00598 00599 /* how many members in this layer? */ 00600 layer_members=number_of_host_layer_members(this_host,current_layer); 00601 00602 if(layer_members==0) 00603 break; 00604 00605 current_layer_member=0; 00606 00607 /* see which hosts are members of this layer and calculate drawing coords */ 00608 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00609 00610 /* is this host a member of the current child layer? */ 00611 if(host_child_depth_separation(this_host,temp_host)==current_layer){ 00612 temp_host->should_be_drawn=TRUE; 00613 temp_host->have_3d_coords=TRUE; 00614 temp_host->x_3d=center_x-(((layer_members*DEFAULT_NODE_WIDTH)+((layer_members-1)*DEFAULT_NODE_HSPACING))/2)+(current_layer_member*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); 00615 if(this_host==NULL) 00616 temp_host->y_3d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*current_layer)+offset_y; 00617 else 00618 temp_host->y_3d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*(current_layer+1))+offset_y; 00619 current_layer_member++; 00620 } 00621 } 00622 } 00623 00624 } 00625 00626 00627 /***** "BALANCED" TREE MODE *****/ 00628 else if(layout_method==LAYOUT_BALANCED_TREE){ 00629 00630 /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */ 00631 this_host=NULL; 00632 00633 /* find total number of immediate parents for this host */ 00634 parent_hosts=number_of_immediate_parent_hosts(this_host); 00635 00636 /* find the max drawing width we have... */ 00637 max_drawing_width=max_child_host_drawing_width(this_host); 00638 if(parent_hosts>max_drawing_width) 00639 max_drawing_width=parent_hosts; 00640 00641 /* calculate center x coord */ 00642 center_x=(((DEFAULT_NODE_WIDTH*max_drawing_width)+(DEFAULT_NODE_HSPACING*(max_drawing_width-1)))/2)+offset_x; 00643 00644 /* coords for Icinga icon if necessary */ 00645 if(this_host==NULL || this_host->parent_hosts==NULL){ 00646 nagios_icon_x=center_x; 00647 nagios_icon_y=offset_y; 00648 draw_nagios_icon=TRUE; 00649 } 00650 00651 /* do we need to draw a link to parent(s)? */ 00652 if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE) 00653 offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 00654 00655 /* see which hosts we should draw and calculate drawing coords */ 00656 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00657 00658 /* this is an immediate parent of the "main" host we're drawing */ 00659 if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ 00660 temp_host->should_be_drawn=TRUE; 00661 temp_host->have_3d_coords=TRUE; 00662 temp_host->x_3d=center_x-(((parent_hosts*DEFAULT_NODE_WIDTH)+((parent_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_parent_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); 00663 temp_host->y_3d=offset_y; 00664 current_parent_host++; 00665 } 00666 00667 /* this is the "main" host we're drawing */ 00668 else if(this_host==temp_host){ 00669 temp_host->should_be_drawn=TRUE; 00670 temp_host->have_3d_coords=TRUE; 00671 temp_host->x_3d=center_x; 00672 temp_host->y_3d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; 00673 } 00674 00675 /* else do not draw this host (we might if its a child - see below, but assume no for now) */ 00676 else{ 00677 temp_host->should_be_drawn=FALSE; 00678 temp_host->have_3d_coords=FALSE; 00679 } 00680 } 00681 00682 /* draw all children hosts */ 00683 calculate_balanced_tree_coords(this_host,center_x,DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y); 00684 00685 } 00686 00687 00688 /***** CIRCULAR LAYOUT MODE *****/ 00689 else if(layout_method==LAYOUT_CIRCULAR){ 00690 00691 /* draw process icon */ 00692 nagios_icon_x=0; 00693 nagios_icon_y=0; 00694 draw_nagios_icon=TRUE; 00695 00696 /* calculate coordinates for all hosts */ 00697 calculate_circular_coords(); 00698 } 00699 00700 return; 00701 } 00702 00703 00704 00705 /* calculate world dimensions */ 00706 void calculate_world_bounds(void){ 00707 host *temp_host; 00708 00709 min_x_coord=0.0; 00710 min_y_coord=0.0; 00711 min_z_coord=0.0; 00712 max_x_coord=0.0; 00713 max_y_coord=0.0; 00714 max_z_coord=0.0; 00715 00716 /* check all extended host entries */ 00717 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00718 00719 if(temp_host->have_3d_coords==FALSE){ 00720 temp_host->should_be_drawn=FALSE; 00721 continue; 00722 } 00723 00724 if(temp_host->should_be_drawn==FALSE) 00725 continue; 00726 00727 if(temp_host->x_3d < min_x_coord) 00728 min_x_coord=temp_host->x_3d; 00729 else if(temp_host->x_3d > max_x_coord) 00730 max_x_coord=temp_host->x_3d; 00731 if(temp_host->y_3d < min_y_coord) 00732 min_y_coord=temp_host->y_3d; 00733 else if(temp_host->y_3d > max_y_coord) 00734 max_y_coord=temp_host->y_3d; 00735 if(temp_host->z_3d < min_z_coord) 00736 min_z_coord=temp_host->z_3d; 00737 else if(temp_host->z_3d > max_z_coord) 00738 max_z_coord=temp_host->z_3d; 00739 00740 coordinates_were_specified=TRUE; 00741 } 00742 00743 /* no drawing coordinates were specified */ 00744 if(coordinates_were_specified==FALSE){ 00745 min_x_coord=0.0; 00746 max_x_coord=0.0; 00747 min_y_coord=0.0; 00748 max_y_coord=0.0; 00749 min_z_coord=0.0; 00750 max_z_coord=6.0; 00751 } 00752 00753 max_world_size=max_x_coord-min_x_coord; 00754 if(max_world_size<(max_y_coord-min_y_coord)) 00755 max_world_size=max_y_coord-min_y_coord; 00756 if(max_world_size<(max_z_coord-min_z_coord)) 00757 max_world_size=max_z_coord-min_z_coord; 00758 00759 return; 00760 } 00761 00762 00763 /******************************************************************/ 00764 /*********************** DRAWING FUNCTIONS ************************/ 00765 /******************************************************************/ 00766 00767 00768 /* write global VRML data */ 00769 void write_global_vrml_data(void){ 00770 host *temp_host; 00771 float visibility_range=0.0; 00772 float viewpoint_z=0.0; 00773 00774 /* write VRML code header */ 00775 printf("#VRML V2.0 utf8\n"); 00776 00777 /* write world information */ 00778 printf("\n"); 00779 printf("WorldInfo{\n"); 00780 printf("title \"%s 3-D Network Status View\"\n", PROGRAM_NAME); 00781 printf("info [\"Copyright (c) 1999-2002 Ethan Galstad\"\n"); 00782 printf("\"egalstad@nagios.org\"]\n"); 00783 printf("}\n"); 00784 00785 /* background color */ 00786 printf("\n"); 00787 printf("Background{\n"); 00788 printf("skyColor 0.1 0.1 0.15\n"); 00789 printf("}\n"); 00790 00791 /* calculate visibility range - don't let it get too low */ 00792 visibility_range=(max_world_size*2.0); 00793 if(visibility_range<25.0) 00794 visibility_range=25.0; 00795 00796 /* write fog information */ 00797 printf("\n"); 00798 printf("Fog{\n"); 00799 printf("color 0.1 0.1 0.15\n"); 00800 printf("fogType \"EXPONENTIAL\"\n"); 00801 printf("visibilityRange %2.2f\n",visibility_range); 00802 printf("}\n"); 00803 00804 /* custom viewpoint */ 00805 if(custom_viewpoint==TRUE){ 00806 printf("\n"); 00807 printf("Viewpoint{\n"); 00808 printf("position %2.2f %2.2f %2.2f\n",custom_viewpoint_x,custom_viewpoint_y,custom_viewpoint_z); 00809 printf("fieldOfView 0.78\n"); 00810 printf("description \"Entry Viewpoint\"\n"); 00811 printf("}\n"); 00812 } 00813 00814 /* host close-up viewpoint */ 00815 if(show_all_hosts==FALSE){ 00816 00817 temp_host=find_host(host_name); 00818 if(temp_host!=NULL && temp_host->have_3d_coords==TRUE){ 00819 printf("\n"); 00820 printf("Viewpoint{\n"); 00821 printf("position %2.3f %2.3f %2.3f\n",temp_host->x_3d,temp_host->y_3d,temp_host->z_3d+5.0); 00822 printf("fieldOfView 0.78\n"); 00823 printf("description \"Host Close-Up Viewpoint\"\n"); 00824 printf("}\n"); 00825 } 00826 } 00827 00828 /* calculate z coord for default viewpoint - don't get too close */ 00829 viewpoint_z=max_world_size; 00830 if(viewpoint_z<10.0) 00831 viewpoint_z=10.0; 00832 00833 /* default viewpoint */ 00834 printf("\n"); 00835 printf("Viewpoint{\n"); 00836 printf("position %2.2f %2.2f %2.2f\n",min_x_coord+((max_x_coord-min_x_coord)/2.0),min_y_coord+((max_y_coord-min_y_coord)/2.0),viewpoint_z); 00837 printf("fieldOfView 0.78\n"); 00838 printf("description \"Default Viewpoint\"\n"); 00839 printf("}\n"); 00840 00841 /* problem timer */ 00842 printf("DEF ProblemTimer TimeSensor{\n"); 00843 printf("loop TRUE\n"); 00844 printf("cycleInterval 5\n"); 00845 printf("}\n"); 00846 00847 /* host text prototype */ 00848 printf("PROTO HostText[\n"); 00849 printf("field MFString the_text [\"\"]\n"); 00850 printf("field SFColor font_color 0.6 0.6 0.6"); 00851 printf("]\n"); 00852 printf("{\n"); 00853 printf("Billboard{\n"); 00854 printf("children[\n"); 00855 printf("Shape{\n"); 00856 printf("appearance Appearance {\n"); 00857 printf("material Material {\n"); 00858 printf("diffuseColor IS font_color\n"); 00859 printf("}\n"); 00860 printf("}\n"); 00861 printf("geometry Text {\n"); 00862 printf("string IS the_text\n"); 00863 printf("fontStyle FontStyle {\n"); 00864 printf("family \"TYPEWRITER\"\n"); 00865 printf("size 0.1\n"); 00866 printf("justify \"MIDDLE\"\n"); 00867 printf("}\n"); 00868 printf("}\n"); 00869 printf("}\n"); 00870 printf("]\n"); 00871 printf("}\n"); 00872 printf("}\n"); 00873 00874 /* include user-defined world */ 00875 if(statuswrl_include!=NULL && coordinates_were_specified==TRUE && layout_method==LAYOUT_USER_SUPPLIED){ 00876 printf("\n"); 00877 printf("Inline{\n"); 00878 printf("url \"%s%s\"\n",url_html_path,statuswrl_include); 00879 printf("}\n"); 00880 } 00881 00882 return; 00883 } 00884 00885 00886 00887 /* draws a host */ 00888 void draw_host(host *temp_host){ 00889 hoststatus *temp_hoststatus=NULL; 00890 char state_string[16]=""; 00891 double x, y, z; 00892 char *vrml_safe_hostname=NULL; 00893 int a, ch; 00894 00895 if(temp_host==NULL) 00896 return; 00897 00898 /* make sure we have the coordinates */ 00899 if(temp_host->have_3d_coords==FALSE) 00900 return; 00901 else{ 00902 x=temp_host->x_3d; 00903 y=temp_host->y_3d; 00904 z=temp_host->z_3d; 00905 } 00906 00907 /* make the host name safe for embedding in VRML */ 00908 vrml_safe_hostname=(char *)strdup(temp_host->name); 00909 if(vrml_safe_hostname==NULL) 00910 return; 00911 for(a=0;vrml_safe_hostname[a]!='\x0';a++){ 00912 ch=vrml_safe_hostname[a]; 00913 if((ch<'a' || ch>'z') && (ch<'A' || ch>'Z') && (ch<'0' || ch>'9')) 00914 vrml_safe_hostname[a]='_'; 00915 } 00916 00917 /* see if user is authorized to view this host */ 00918 if(is_authorized_for_host(temp_host,¤t_authdata)==FALSE) 00919 return; 00920 00921 /* get the status of the host */ 00922 temp_hoststatus=find_hoststatus(temp_host->name); 00923 00924 printf("\n"); 00925 00926 00927 /* host object */ 00928 printf("Anchor{\n"); 00929 printf("children[\n"); 00930 00931 printf("Transform {\n"); 00932 printf("translation %2.2f %2.2f %2.2f\n",x,y,z); 00933 printf("children [\n"); 00934 00935 printf("DEF Host%s Shape{\n",vrml_safe_hostname); 00936 printf("appearance Appearance{\n"); 00937 printf("material DEF HostMat%s Material{\n",vrml_safe_hostname); 00938 if(temp_hoststatus==NULL) 00939 printf("emissiveColor 0.2 0.2 0.2\ndiffuseColor 0.2 0.2 0.2\n"); 00940 else if(temp_hoststatus->status==HOST_UP) 00941 printf("emissiveColor 0.2 1.0 0.2\ndiffuseColor 0.2 1.0 0.2\n"); 00942 else 00943 printf("emissiveColor 1.0 0.2 0.2\ndiffuseColor 1.0 0.2 0.2\n"); 00944 printf("transparency 0.4\n"); 00945 printf("}\n"); 00946 if(use_textures==TRUE && temp_host->vrml_image!=NULL){ 00947 printf("texture ImageTexture{\n"); 00948 printf("url \"%s%s\"\n",url_logo_images_path,temp_host->vrml_image); 00949 printf("}\n"); 00950 } 00951 printf("}\n"); 00952 printf("geometry Box{\n"); 00953 printf("size %2.2f %2.2f %2.2f\n",node_width,node_width,node_width); 00954 printf("}\n"); 00955 printf("}\n"); 00956 00957 printf("]\n"); 00958 printf("}\n"); 00959 00960 printf("]\n"); 00961 printf("description \"View status details for host '%s' (%s)\"\n",(temp_host->display_name!=NULL)?temp_host->display_name:temp_host->name,temp_host->alias); 00962 printf("url \"%s?host=%s\"\n",STATUS_CGI,temp_host->name); 00963 printf("}\n"); 00964 00965 00966 /* draw status text */ 00967 if(use_text==TRUE){ 00968 00969 printf("\n"); 00970 printf("Transform{\n"); 00971 printf("translation %2.3f %2.3f %2.3f\n",x,y+DEFAULT_NODE_WIDTH,z); 00972 printf("children[\n"); 00973 printf("HostText{\n"); 00974 00975 if(temp_hoststatus!=NULL){ 00976 if(temp_hoststatus->status==HOST_UP) 00977 printf("font_color 0 1 0\n"); 00978 else if(temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE) 00979 printf("font_color 1 0 0\n"); 00980 } 00981 printf("the_text [\"%s\", \"%s\", ",(temp_host->display_name!=NULL)?temp_host->display_name:temp_host->name,temp_host->alias); 00982 if(temp_hoststatus==NULL) 00983 strcpy(state_string,"UNKNOWN"); 00984 else{ 00985 if(temp_hoststatus->status==HOST_DOWN) 00986 strcpy(state_string,"DOWN"); 00987 else if(temp_hoststatus->status==HOST_UNREACHABLE) 00988 strcpy(state_string,"UNREACHABLE"); 00989 else if(temp_hoststatus->status==HOST_PENDING) 00990 strcpy(state_string,"PENDING"); 00991 else 00992 strcpy(state_string,"UP"); 00993 } 00994 printf("\"%s\"]\n",state_string); 00995 00996 printf("}\n"); 00997 printf("]\n"); 00998 printf("}\n"); 00999 } 01000 01001 /* host is down or unreachable, so make it fade in and out */ 01002 if(temp_hoststatus!=NULL && (temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE)) 01003 printf("ROUTE ProblemTimer.fraction_changed TO HostMat%s.set_transparency\n",vrml_safe_hostname); 01004 01005 free(vrml_safe_hostname); 01006 01007 return; 01008 } 01009 01010 01011 01012 /* draw links between hosts */ 01013 void draw_host_links(void){ 01014 host *parent_host; 01015 host *child_host; 01016 01017 if(use_links==FALSE) 01018 return; 01019 01020 for(child_host=host_list;child_host!=NULL;child_host=child_host->next){ 01021 01022 if(child_host->have_3d_coords==FALSE) 01023 continue; 01024 01025 /* check authorization */ 01026 if(is_authorized_for_host(child_host,¤t_authdata)==FALSE) 01027 continue; 01028 01029 /* draw a link from this host to all of its parent hosts */ 01030 for(parent_host=host_list;parent_host!=NULL;parent_host=parent_host->next){ 01031 01032 if(is_host_immediate_child_of_host(child_host,parent_host)==TRUE){ 01033 01034 if(parent_host->have_3d_coords==FALSE) 01035 continue; 01036 01037 /* check authorization */ 01038 if(is_authorized_for_host(parent_host,¤t_authdata)==FALSE) 01039 continue; 01040 01041 /* draw the link between the child and parent hosts */ 01042 draw_host_link(parent_host,parent_host->x_3d,parent_host->y_3d,parent_host->z_3d,child_host->x_3d,child_host->y_3d,child_host->z_3d); 01043 } 01044 } 01045 } 01046 01047 01048 return; 01049 } 01050 01051 01052 01053 01054 /* draws a link from a parent host to a child host */ 01055 void draw_host_link(host *hst,double x0, double y0, double z0, double x1, double y1, double z1){ 01056 01057 printf("\n"); 01058 01059 if(hst!=NULL) 01060 printf("# Host '%s' LINK\n",hst->name); 01061 01062 printf("Shape{\n"); 01063 01064 printf("appearance DEF MATslategrey_0_ Appearance {\n"); 01065 printf("material Material {\n"); 01066 printf("diffuseColor 0.6 0.6 0.6\n"); 01067 printf("ambientIntensity 0.5\n"); 01068 printf("emissiveColor 0.6 0.6 0.6\n"); 01069 printf("}\n"); 01070 printf("}\n"); 01071 01072 printf("geometry IndexedLineSet{\n"); 01073 printf("coord Coordinate{\n"); 01074 printf("point [ %2.3f %2.3f %2.3f, %2.3f %2.3f %2.3f ]\n",x0,y0,z0,x1,y1,z1); 01075 printf("}\n"); 01076 printf("coordIndex [ 0,1,-1 ]\n"); 01077 printf("}\n"); 01078 01079 printf("}\n"); 01080 01081 return; 01082 } 01083 01084 01085 01086 /* draw process icon */ 01087 void draw_process_icon(void){ 01088 host *child_host; 01089 01090 if(draw_nagios_icon==FALSE) 01091 return; 01092 01093 /* draw process icon */ 01094 printf("\n"); 01095 01096 01097 printf("Anchor{\n"); 01098 printf("children[\n"); 01099 01100 printf("Transform {\n"); 01101 printf("translation %2.2f %2.2f %2.2f\n",nagios_icon_x,nagios_icon_y,0.0); 01102 printf("children [\n"); 01103 01104 printf("DEF ProcessNode Shape{\n"); 01105 printf("appearance Appearance{\n"); 01106 printf("material Material{\n"); 01107 printf("emissiveColor 0.5 0.5 0.5\n"); 01108 printf("diffuseColor 0.5 0.5 0.5\n"); 01109 printf("transparency 0.2\n"); 01110 printf("}\n"); 01111 if(use_textures==TRUE){ 01112 printf("texture ImageTexture{\n"); 01113 printf("url \"%s%s\"\n",url_logo_images_path,ICINGA_VRML_IMAGE); 01114 printf("}\n"); 01115 } 01116 printf("}\n"); 01117 printf("geometry Box{\n"); 01118 printf("size %2.2f %2.2f %2.2f\n",node_width*3.0,node_width*3.0,node_width*3.0); 01119 printf("}\n"); 01120 printf("}\n"); 01121 01122 printf("]\n"); 01123 printf("}\n"); 01124 01125 printf("]\n"); 01126 printf("description \"View %s Process Information\"\n", PROGRAM_NAME); 01127 printf("url \"%s?type=%d\"\n",EXTINFO_CGI,DISPLAY_PROCESS_INFO); 01128 printf("}\n"); 01129 01130 01131 if(use_links==FALSE) 01132 return; 01133 01134 /* draw links to immediate child hosts */ 01135 for(child_host=host_list;child_host!=NULL;child_host=child_host->next){ 01136 01137 if(child_host->have_3d_coords==FALSE) 01138 continue; 01139 01140 /* check authorization */ 01141 if(is_authorized_for_host(child_host,¤t_authdata)==FALSE) 01142 continue; 01143 01144 /* draw a link to the host */ 01145 if(is_host_immediate_child_of_host(NULL,child_host)==TRUE) 01146 draw_host_link(NULL,nagios_icon_x,nagios_icon_y,0.0,child_host->x_3d,child_host->y_3d,child_host->z_3d); 01147 } 01148 01149 return; 01150 } 01151 01152 01153 01154 01155 /******************************************************************/ 01156 /***************** COORDINATE CALCULATION FUNCTIONS ***************/ 01157 /******************************************************************/ 01158 01159 /* calculates coords of a host's children - used by balanced tree layout method */ 01160 void calculate_balanced_tree_coords(host *parent, int x, int y){ 01161 int parent_drawing_width; 01162 int start_drawing_x; 01163 int current_drawing_x; 01164 int this_drawing_width; 01165 host *temp_host; 01166 01167 /* calculate total drawing width of parent host */ 01168 parent_drawing_width=max_child_host_drawing_width(parent); 01169 01170 /* calculate starting x coord */ 01171 start_drawing_x=x-(((DEFAULT_NODE_WIDTH*parent_drawing_width)+(DEFAULT_NODE_HSPACING*(parent_drawing_width-1)))/2); 01172 current_drawing_x=start_drawing_x; 01173 01174 01175 /* calculate coords for children */ 01176 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 01177 01178 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ 01179 01180 /* get drawing width of child host */ 01181 this_drawing_width=max_child_host_drawing_width(temp_host); 01182 01183 temp_host->x_3d=current_drawing_x+(((DEFAULT_NODE_WIDTH*this_drawing_width)+(DEFAULT_NODE_HSPACING*(this_drawing_width-1)))/2); 01184 temp_host->y_3d=y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 01185 temp_host->have_3d_coords=TRUE; 01186 temp_host->should_be_drawn=TRUE; 01187 01188 current_drawing_x+=(this_drawing_width*DEFAULT_NODE_WIDTH)+((this_drawing_width-1)*DEFAULT_NODE_HSPACING)+DEFAULT_NODE_HSPACING; 01189 01190 /* recurse into child host ... */ 01191 calculate_balanced_tree_coords(temp_host,temp_host->x_3d,temp_host->y_3d); 01192 } 01193 01194 } 01195 01196 return; 01197 } 01198 01199 01200 /* calculate coords of all hosts in circular layout method */ 01201 void calculate_circular_coords(void){ 01202 01203 /* calculate all host coords, starting with first layer */ 01204 calculate_circular_layer_coords(NULL,0.0,360.0,1,CIRCULAR_DRAWING_RADIUS); 01205 01206 return; 01207 } 01208 01209 01210 /* calculates coords of all hosts in a particular "layer" in circular layout method */ 01211 void calculate_circular_layer_coords(host *parent, double start_angle, double useable_angle, int layer, int radius){ 01212 int parent_drawing_width=0; 01213 int this_drawing_width=0; 01214 int immediate_children=0; 01215 double current_drawing_angle=0.0; 01216 double this_drawing_angle=0.0; 01217 double available_angle=0.0; 01218 double clipped_available_angle=0.0; 01219 double average_child_angle=0.0; 01220 double x_coord=0.0; 01221 double y_coord=0.0; 01222 host *temp_host; 01223 01224 01225 /* get the total number of immediate children to this host */ 01226 immediate_children=number_of_immediate_child_hosts(parent); 01227 01228 /* bail out if we're done */ 01229 if(immediate_children==0) 01230 return; 01231 01232 /* calculate total drawing "width" of parent host */ 01233 parent_drawing_width=max_child_host_drawing_width(parent); 01234 01235 /* calculate average angle given to each child host */ 01236 average_child_angle=(double)(useable_angle/(double)immediate_children); 01237 01238 /* calculate initial drawing angle */ 01239 current_drawing_angle=start_angle; 01240 01241 01242 /* calculate coords for children */ 01243 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 01244 01245 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ 01246 01247 /* get drawing width of child host */ 01248 this_drawing_width=max_child_host_drawing_width(temp_host); 01249 01250 /* calculate angle this host gets for drawing */ 01251 available_angle=useable_angle*((double)this_drawing_width/(double)parent_drawing_width); 01252 01253 /* clip available angle if necessary */ 01254 /* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */ 01255 clipped_available_angle=360.0/layer; 01256 if(available_angle<clipped_available_angle) 01257 clipped_available_angle=available_angle; 01258 01259 /* calculate the exact angle at which we should draw this child */ 01260 this_drawing_angle=current_drawing_angle+(available_angle/2.0); 01261 01262 /* compensate for angle overflow */ 01263 while(this_drawing_angle>=360.0) 01264 this_drawing_angle-=360.0; 01265 while(this_drawing_angle<0.0) 01266 this_drawing_angle+=360.0; 01267 01268 /* calculate drawing coords of this host using good ol' geometry... */ 01269 x_coord=-(sin(-this_drawing_angle*(M_PI/180.0))*radius); 01270 y_coord=-(sin((90+this_drawing_angle)*(M_PI/180.0))*radius); 01271 01272 temp_host->x_3d=(int)x_coord; 01273 temp_host->y_3d=(int)y_coord; 01274 temp_host->have_3d_coords=TRUE; 01275 temp_host->should_be_drawn=TRUE; 01276 01277 /* recurse into child host ... */ 01278 calculate_circular_layer_coords(temp_host,current_drawing_angle+((available_angle-clipped_available_angle)/2),clipped_available_angle,layer+1,radius+CIRCULAR_DRAWING_RADIUS); 01279 01280 /* increment current drawing angle */ 01281 current_drawing_angle+=available_angle; 01282 } 01283 } 01284 01285 return; 01286 } 01287 01288