Logo Search packages:      
Sourcecode: nagios2 version File versions  Download package

statuswrl.c

/*****************************************************************************
 *
 * STATUSWRL.C - Nagios 3-D (VRML) Network Status View
 *
 * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org)
 * Last Modified: 10-21-2007
 *
 * Description:
 *
 * This CGI will dynamically create a 3-D VRML model of all hosts that are
 * being monitored on your network.
 *
 * License:
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *****************************************************************************/

#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"

#include "../include/cgiutils.h"
#include "../include/getcgi.h"
#include "../include/cgiauth.h"

extern char main_config_file[MAX_FILENAME_LENGTH];
extern char url_html_path[MAX_FILENAME_LENGTH];
extern char url_images_path[MAX_FILENAME_LENGTH];
extern char url_logo_images_path[MAX_FILENAME_LENGTH];

extern char *statuswrl_include;

extern host *host_list;
extern service *service_list;
extern hostextinfo *hostextinfo_list;

extern int default_statuswrl_layout_method;


#define NAGIOS_VRML_IMAGE               "nagiosvrml.png"

#define DEFAULT_NODE_WIDTH          0.5
#define DEFAULT_HORIZONTAL_SPACING  1.0
#define DEFAULT_VERTICAL_SPACING    1.0

/* needed for auto-layout modes */
#define DEFAULT_NODE_HEIGHT             0.5
#define DEFAULT_NODE_HSPACING           1.0
#define DEFAULT_NODE_VSPACING           1.0
#define CIRCULAR_DRAWING_RADIUS         5.0

#define LAYOUT_USER_SUPPLIED            0
#define LAYOUT_COLLAPSED_TREE           2
#define LAYOUT_BALANCED_TREE            3
#define LAYOUT_CIRCULAR                 4


void calculate_host_coords(void);
void calculate_world_bounds(void);
void display_world(void);
void write_global_vrml_data(void);
void draw_process_icon(void);
void draw_host(hostextinfo *);
void draw_host_links(void);
void draw_host_link(host *,double,double,double,double,double,double);
void document_header(void);
int process_cgivars(void);

int number_of_host_layer_members(host *,int);
int max_child_host_layer_members(host *);
int host_child_depth_separation(host *, host *);
int max_child_host_drawing_width(host *);

void calculate_balanced_tree_coords(host *,int,int);
void calculate_circular_coords(void);
void calculate_circular_layer_coords(host *,double,double,int,int);


authdata current_authdata;

float link_radius=0.016;

float floor_width=0.0;
float floor_depth=0.0;

double min_z_coord=0.0;
double min_x_coord=0.0;
double min_y_coord=0.0;
double max_z_coord=0.0;
double max_x_coord=0.0;
double max_y_coord=0.0;

double max_world_size=0.0;

double nagios_icon_x=0.0;
double nagios_icon_y=0.0;
int draw_nagios_icon=FALSE;

double custom_viewpoint_x=0.0;
double custom_viewpoint_y=0.0;
double custom_viewpoint_z=0.0;
int custom_viewpoint=FALSE;

float vertical_spacing=DEFAULT_VERTICAL_SPACING;
float horizontal_spacing=DEFAULT_HORIZONTAL_SPACING;
float node_width=DEFAULT_NODE_WIDTH;
float node_height=DEFAULT_NODE_WIDTH;     /* should be the same as the node width */

char *host_name="all";
int show_all_hosts=TRUE;

int use_textures=TRUE;
int use_text=TRUE;
int use_links=TRUE;

int layout_method=LAYOUT_USER_SUPPLIED;

int coordinates_were_specified=FALSE;   /* were drawing coordinates specified with extended host info entries? */





int main(int argc, char **argv){
      int result;

      /* reset internal variables */
      reset_cgi_vars();

      /* read the CGI configuration file */
      result=read_cgi_config_file(get_cgi_config_location());
      if(result==ERROR){
            document_header();
            return ERROR;
              }

      /* defaults from CGI config file */
      layout_method=default_statuswrl_layout_method;

      /* get the arguments passed in the URL */
      process_cgivars();

      document_header();

      /* read the main configuration file */
      result=read_main_config_file(main_config_file);
      if(result==ERROR)
            return ERROR;

      /* read all object configuration data */
      result=read_all_object_configuration_data(main_config_file,READ_ALL_OBJECT_DATA);
      if(result==ERROR)
            return ERROR;

      /* read all status data */
      result=read_all_status_data(get_cgi_config_location(),READ_ALL_STATUS_DATA);
      if(result==ERROR){
            free_memory();
            return ERROR;
                }

      /* get authentication information */
      get_authentication_information(&current_authdata);

      /* display the 3-D VRML world... */
      display_world();

      /* free all allocated memory */
      free_memory();

      return OK;
        }



void document_header(void){
      char date_time[MAX_DATETIME_LENGTH];
      time_t current_time;
      time_t expire_time;


      printf("Cache-Control: no-store\r\n");
      printf("Pragma: no-cache\r\n");

      time(&current_time);
      get_time_string(&current_time,date_time,sizeof(date_time),HTTP_DATE_TIME);
      printf("Last-Modified: %s\r\n",date_time);

      expire_time=0L;
      get_time_string(&expire_time,date_time,sizeof(date_time),HTTP_DATE_TIME);
      printf("Expires: %s\r\n",date_time);

      printf("Content-Type: x-world/x-vrml\r\n\r\n");

      return;
        }



int process_cgivars(void){
      char **variables;
      int error=FALSE;
      int x;

      variables=getcgivars();

      for(x=0;variables[x]!=NULL;x++){

            /* do some basic length checking on the variable identifier to prevent buffer overflows */
            if(strlen(variables[x])>=MAX_INPUT_BUFFER-1){
                  x++;
                  continue;
                    }


            /* we found the host argument */
            else if(!strcmp(variables[x],"host")){
                  x++;
                  if(variables[x]==NULL){
                        error=TRUE;
                        break;
                          }

                  host_name=(char *)malloc(strlen(variables[x])+1);
                  if(host_name==NULL)
                        host_name="all";
                  else
                        strcpy(host_name,variables[x]);
                  strip_html_brackets(host_name);

                  if(!strcmp(host_name,"all"))
                        show_all_hosts=TRUE;
                  else
                        show_all_hosts=FALSE;
                    }

            /* we found the no textures argument*/
            else if(!strcmp(variables[x],"notextures"))
                  use_textures=FALSE;

            /* we found the no text argument*/
            else if(!strcmp(variables[x],"notext"))
                  use_text=FALSE;

            /* we found the no links argument*/
            else if(!strcmp(variables[x],"nolinks"))
                  use_links=FALSE;

            /* we found the layout method option */
            else if(!strcmp(variables[x],"layout")){
                  x++;
                  if(variables[x]==NULL){
                        error=TRUE;
                        break;
                          }
                  layout_method=atoi(variables[x]);
                    }

            /* we found custom viewpoint coord */
            else if(!strcmp(variables[x],"viewx")){
                  x++;
                  if(variables[x]==NULL){
                        error=TRUE;
                        break;
                          }
                  custom_viewpoint_x=strtod(variables[x],NULL);
                  custom_viewpoint=TRUE;
                    }
            else if(!strcmp(variables[x],"viewy")){
                  x++;
                  if(variables[x]==NULL){
                        error=TRUE;
                        break;
                          }
                  custom_viewpoint_y=strtod(variables[x],NULL);
                  custom_viewpoint=TRUE;
                    }
            else if(!strcmp(variables[x],"viewz")){
                  x++;
                  if(variables[x]==NULL){
                        error=TRUE;
                        break;
                          }
                  custom_viewpoint_z=strtod(variables[x],NULL);
                  custom_viewpoint=TRUE;
                    }

              }

      /* free memory allocated to the CGI variables */
      free_cgivars(variables);

      return error;
        }



/* top-level VRML world generation... */
void display_world(void){
      hostextinfo *temp_hostextinfo;

      /* get the url we will use to grab the logo images... */
      snprintf(url_logo_images_path,sizeof(url_logo_images_path),"%slogos/",url_images_path);
      url_logo_images_path[sizeof(url_logo_images_path)-1]='\x0';

      /* calculate host drawing coordinates */
      calculate_host_coords();

      /* calculate world bounds */
      calculate_world_bounds();

      /* get the floor dimensions */
      if(max_x_coord>0)
            floor_width=(float)(max_x_coord-min_x_coord)+(node_width*2);
      else
            floor_width=(float)(max_x_coord+min_x_coord)+(node_width*2);
      if(max_z_coord>0)
            floor_depth=(float)(max_z_coord-min_z_coord)+(node_height*2);
      else
            floor_depth=(float)(max_z_coord+min_z_coord)+(node_height*2);

      /* write global VRML data */
      write_global_vrml_data();

      /* no coordinates were specified, so display warning message */
      if(coordinates_were_specified==FALSE){

            printf("\n");
            printf("Transform{\n");
            printf("translation 0.0 0.0 0.0\n");
            printf("children[\n");

            printf("Billboard{\n");
            printf("children[\n");
            printf("Shape{\n");
            printf("appearance Appearance {\n");
            printf("material Material {\n");
            printf("diffuseColor 1 0 0\n");
            printf("}\n");
            printf("}\n");
            printf("geometry Text {\n");
            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");
            printf("fontStyle FontStyle {\n");
            printf("family \"TYPEWRITER\"\n");
            printf("size 0.3\n");
            printf("justify \"MIDDLE\"\n");
            printf("}\n");
            printf("}\n");
            printf("}\n");
            printf("]\n");
            printf("}\n");

            printf("]\n");
            printf("}\n");
              }

      /* coordinates were specified... */
      else{

            /* draw Nagios icon */
            if(layout_method!=LAYOUT_USER_SUPPLIED)
                  draw_process_icon();

            /* draw all hosts */
            for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next)
                  draw_host(temp_hostextinfo);

            /* draw host links */
            draw_host_links();
              }

      return;
        }




/******************************************************************/
/************************ UTILITY FUNCTIONS ***********************/
/******************************************************************/

/* calculates how many "layers" separate parent and child - used by collapsed tree layout method */
int host_child_depth_separation(host *parent, host *child){
      int this_depth=0;
      int min_depth=0;
      int have_min_depth=FALSE;
      host *temp_host;

      if(child==NULL)
            return -1;

      if(parent==child)
            return 0;

      if(is_host_immediate_child_of_host(parent,child)==TRUE)
            return 1;

      for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){

            if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){

                  this_depth=host_child_depth_separation(temp_host,child);

                  if(this_depth>=0 && (have_min_depth==FALSE || (have_min_depth==TRUE && (this_depth<min_depth)))){
                        have_min_depth=TRUE;
                        min_depth=this_depth;
                          }
                    }
              }

      if(have_min_depth==FALSE)
            return -1;
      else
            return min_depth+1;
        }



/* calculates how many hosts reside on a specific "layer" - used by collapsed tree layout method */
int number_of_host_layer_members(host *parent, int layer){
      int current_layer;
      int layer_members=0;
      host *temp_host;

      for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){

            current_layer=host_child_depth_separation(parent,temp_host);

            if(current_layer==layer)
                  layer_members++;
              }

      return layer_members;
        }



/* calculate max number of members on all "layers" beneath and including parent host - used by collapsed tree layout method */
int max_child_host_layer_members(host *parent){
      int current_layer;
      int max_members=1;
      int current_members=0;

      for(current_layer=1;;current_layer++){

            current_members=number_of_host_layer_members(parent,current_layer);

            if(current_members<=0)
                  break;

            if(current_members>max_members)
                  max_members=current_members;
              }

      return max_members;
        }



/* calculate max drawing width for host and children - used by balanced tree layout method */
int max_child_host_drawing_width(host *parent){
      host *temp_host;
      int child_width=0;

      for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
            if(is_host_immediate_child_of_host(parent,temp_host)==TRUE)
                  child_width+=max_child_host_drawing_width(temp_host);
              }

      /* no children, so set width to 1 for this host */
      if(child_width==0)
            return 1;

      else
            return child_width;
        }
      



/******************************************************************/
/********************* CALCULATION FUNCTIONS **********************/
/******************************************************************/

/* calculates host drawing coordinates */
void calculate_host_coords(void){
      hostextinfo *temp_hostextinfo;
      host *this_host;
      host *temp_host;
      int parent_hosts=0;
      int max_layer_width=1;
      int current_parent_host=0;
      int center_x=0;
      int offset_x=DEFAULT_NODE_WIDTH/2;
      int offset_y=DEFAULT_NODE_WIDTH/2;
      int current_layer=0;
      int layer_members=0;
      int current_layer_member=0;
      int max_drawing_width=0;
  

      /******************************/
      /***** MANUAL LAYOUT MODE *****/
      /******************************/

      /* user-supplied coords */
      if(layout_method==LAYOUT_USER_SUPPLIED){

            /* see which hosts we should draw (only those with 3-D coords) */
            for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){

                  if(temp_hostextinfo->have_3d_coords==TRUE)
                        temp_hostextinfo->should_be_drawn=TRUE;
                  else
                        temp_hostextinfo->should_be_drawn=FALSE;
                    }

            return;
            }

      /*****************************/
      /***** AUTO-LAYOUT MODES *****/
      /*****************************/

      /* add empty extended host info entries for all hosts that don't have any */
      for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){

            /* find the corresponding hostextinfo definition */
            temp_hostextinfo=find_hostextinfo(temp_host->name);

            /* none was found, so add a blank one */
            if(temp_hostextinfo==NULL)
                  add_hostextinfo(temp_host->name,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0.0,0.0,0.0,0,0);

            /* default z coord should 0 for auto-layout modes unless overridden later */
            else
                  temp_hostextinfo->z_3d=0.0;
              }


      /***** COLLAPSED TREE MODE *****/
      if(layout_method==LAYOUT_COLLAPSED_TREE){

            /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */
            this_host=NULL;

            /* find total number of immediate parents for this host */
            parent_hosts=number_of_immediate_parent_hosts(this_host);

            /* find the max layer width we have... */
            max_layer_width=max_child_host_layer_members(this_host);
            if(parent_hosts>max_layer_width)
                  max_layer_width=parent_hosts;

            /* calculate center x coord */
            center_x=(((DEFAULT_NODE_WIDTH*max_layer_width)+(DEFAULT_NODE_HSPACING*(max_layer_width-1)))/2)+offset_x;

            /* coords for Nagios icon if necessary */
            if(this_host==NULL || this_host->parent_hosts==NULL){
                  nagios_icon_x=center_x;
                  nagios_icon_y=offset_y;
                  draw_nagios_icon=TRUE;
                    }

            /* do we need to draw a link to parent(s)? */
            if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE)
                  offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING;

            /* see which hosts we should draw and calculate drawing coords */
            for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){

                  /* find the host that matches this entry */
                  temp_host=find_host(temp_hostextinfo->host_name);

                  if(temp_host==NULL)
                        continue;
                  
                  /* this is an immediate parent of the "main" host we're drawing */
                  else if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){
                        temp_hostextinfo->should_be_drawn=TRUE;
                        temp_hostextinfo->have_3d_coords=TRUE;
                        temp_hostextinfo->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);
                        temp_hostextinfo->y_3d=offset_y;
                        current_parent_host++;
                          }
                  
                  /* this is the "main" host we're drawing */
                  else if(this_host==temp_host){
                        temp_hostextinfo->should_be_drawn=TRUE;
                        temp_hostextinfo->have_3d_coords=TRUE;
                        temp_hostextinfo->x_3d=center_x;
                        temp_hostextinfo->y_3d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y;
                          }

                  /* else do not draw this host (we might if its a child - see below, but assume no for now) */
                  else{
                        temp_hostextinfo->should_be_drawn=FALSE;
                        temp_hostextinfo->have_3d_coords=FALSE;
                          }
                    }


            /* TODO: REORDER CHILD LAYER MEMBERS SO THAT WE MINIMIZE LINK CROSSOVERS FROM PARENT HOSTS */

            /* draw hosts in child "layers" */
            for(current_layer=1;;current_layer++){
                  
                  /* how many members in this layer? */
                  layer_members=number_of_host_layer_members(this_host,current_layer);

                  if(layer_members==0)
                        break;

                  current_layer_member=0;

                  /* see which hosts are members of this layer and calculate drawing coords */
                  for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){

                        /* find the host that matches this entry */
                        temp_host=find_host(temp_hostextinfo->host_name);

                        if(temp_host==NULL)
                              continue;

                        /* is this host a member of the current child layer? */
                        if(host_child_depth_separation(this_host,temp_host)==current_layer){
                              temp_hostextinfo->should_be_drawn=TRUE;
                              temp_hostextinfo->have_3d_coords=TRUE;
                              temp_hostextinfo->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);
                              if(this_host==NULL)
                                    temp_hostextinfo->y_3d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*current_layer)+offset_y;
                              else
                                    temp_hostextinfo->y_3d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*(current_layer+1))+offset_y;
                              current_layer_member++;
                                }
                          }
                    }

              }


      /***** "BALANCED" TREE MODE *****/
      else if(layout_method==LAYOUT_BALANCED_TREE){

            /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */
            this_host=NULL;

            /* find total number of immediate parents for this host */
            parent_hosts=number_of_immediate_parent_hosts(this_host);

            /* find the max drawing width we have... */
            max_drawing_width=max_child_host_drawing_width(this_host);
            if(parent_hosts>max_drawing_width)
                  max_drawing_width=parent_hosts;

            /* calculate center x coord */
            center_x=(((DEFAULT_NODE_WIDTH*max_drawing_width)+(DEFAULT_NODE_HSPACING*(max_drawing_width-1)))/2)+offset_x;

            /* coords for Nagios icon if necessary */
            if(this_host==NULL || this_host->parent_hosts==NULL){
                  nagios_icon_x=center_x;
                  nagios_icon_y=offset_y;
                  draw_nagios_icon=TRUE;
                    }

            /* do we need to draw a link to parent(s)? */
            if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE)
                  offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING;

            /* see which hosts we should draw and calculate drawing coords */
            for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){

                  /* find the host that matches this entry */
                  temp_host=find_host(temp_hostextinfo->host_name);

                  if(temp_host==NULL)
                        continue;
                  
                  /* this is an immediate parent of the "main" host we're drawing */
                  else if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){
                        temp_hostextinfo->should_be_drawn=TRUE;
                        temp_hostextinfo->have_3d_coords=TRUE;
                        temp_hostextinfo->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);
                        temp_hostextinfo->y_3d=offset_y;
                        current_parent_host++;
                          }
                  
                  /* this is the "main" host we're drawing */
                  else if(this_host==temp_host){
                        temp_hostextinfo->should_be_drawn=TRUE;
                        temp_hostextinfo->have_3d_coords=TRUE;
                        temp_hostextinfo->x_3d=center_x;
                        temp_hostextinfo->y_3d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y;
                          }

                  /* else do not draw this host (we might if its a child - see below, but assume no for now) */
                  else{
                        temp_hostextinfo->should_be_drawn=FALSE;
                        temp_hostextinfo->have_3d_coords=FALSE;
                          }
                    }

            /* draw all children hosts */
            calculate_balanced_tree_coords(this_host,center_x,DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y);

              }


      /***** CIRCULAR LAYOUT MODE *****/
      else if(layout_method==LAYOUT_CIRCULAR){

            /* draw process icon */
            nagios_icon_x=0;
            nagios_icon_y=0;
            draw_nagios_icon=TRUE;

            /* calculate coordinates for all hosts */
            calculate_circular_coords();
              }

      return;
        }



/* calculate world dimensions */
void calculate_world_bounds(void){
      hostextinfo *temp_hostextinfo;

      min_x_coord=0.0;
      min_y_coord=0.0;
      min_z_coord=0.0;
      max_x_coord=0.0;
      max_y_coord=0.0;
      max_z_coord=0.0;

      /* check all extended host entries */
      for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){

            if(temp_hostextinfo->have_3d_coords==FALSE){
                  temp_hostextinfo->should_be_drawn=FALSE;
                  continue;
                    }

            if(temp_hostextinfo->should_be_drawn==FALSE)
                  continue;

            if(temp_hostextinfo->x_3d < min_x_coord)
                  min_x_coord=temp_hostextinfo->x_3d;
            else if(temp_hostextinfo->x_3d > max_x_coord)
                  max_x_coord=temp_hostextinfo->x_3d;
            if(temp_hostextinfo->y_3d < min_y_coord)
                  min_y_coord=temp_hostextinfo->y_3d;
            else if(temp_hostextinfo->y_3d > max_y_coord)
                  max_y_coord=temp_hostextinfo->y_3d;
            if(temp_hostextinfo->z_3d < min_z_coord)
                  min_z_coord=temp_hostextinfo->z_3d;
            else if(temp_hostextinfo->z_3d > max_z_coord)
                  max_z_coord=temp_hostextinfo->z_3d;

            coordinates_were_specified=TRUE;
              }

      /* no drawing coordinates were specified */
      if(coordinates_were_specified==FALSE){
            min_x_coord=0.0;
            max_x_coord=0.0;
            min_y_coord=0.0;
            max_y_coord=0.0;
            min_z_coord=0.0;
            max_z_coord=6.0;
              }

      max_world_size=max_x_coord-min_x_coord;
      if(max_world_size<(max_y_coord-min_y_coord))
            max_world_size=max_y_coord-min_y_coord;
      if(max_world_size<(max_z_coord-min_z_coord))
            max_world_size=max_z_coord-min_z_coord;

      return;
        }


/******************************************************************/
/*********************** DRAWING FUNCTIONS ************************/
/******************************************************************/


/* write global VRML data */
void write_global_vrml_data(void){
      hostextinfo *temp_hostextinfo;
      float visibility_range=0.0;
      float viewpoint_z=0.0;

      /* write VRML code header */
      printf("#VRML V2.0 utf8\n");

      /* write world information */
      printf("\n");
      printf("WorldInfo{\n");
      printf("title \"Nagios 3-D Network Status View\"\n");
      printf("info [\"Copyright (c) 1999-2002 Ethan Galstad\"\n");
        printf("\"nagios@nagios.org\"]\n");
      printf("}\n");

      /* background color */
      printf("\n");
      printf("Background{\n");
      printf("skyColor 0.1 0.1 0.15\n");
      printf("}\n");

      /* calculate visibility range - don't let it get too low */
      visibility_range=(max_world_size*2.0);
      if(visibility_range<25.0)
            visibility_range=25.0;

      /* write fog information */
      printf("\n");
      printf("Fog{\n");
      printf("color 0.1 0.1 0.15\n");
      printf("fogType \"EXPONENTIAL\"\n");
      printf("visibilityRange %2.2f\n",visibility_range);
      printf("}\n");

      /* custom viewpoint */
      if(custom_viewpoint==TRUE){
            printf("\n");
            printf("Viewpoint{\n");
            printf("position %2.2f %2.2f %2.2f\n",custom_viewpoint_x,custom_viewpoint_y,custom_viewpoint_z);
            printf("fieldOfView 0.78\n");
            printf("description \"Entry Viewpoint\"\n");
            printf("}\n");
              }

      /* host close-up viewpoint */
      if(show_all_hosts==FALSE){

            temp_hostextinfo=find_hostextinfo(host_name);
            if(temp_hostextinfo!=NULL && temp_hostextinfo->have_3d_coords==TRUE){
                  printf("\n");
                  printf("Viewpoint{\n");
                  printf("position %2.3f %2.3f %2.3f\n",temp_hostextinfo->x_3d,temp_hostextinfo->y_3d,temp_hostextinfo->z_3d+5.0);
                  printf("fieldOfView 0.78\n");
                  printf("description \"Host Close-Up Viewpoint\"\n");
                  printf("}\n");
                      }
              }

      /* calculate z coord for default viewpoint - don't get too close */
      viewpoint_z=max_world_size;
      if(viewpoint_z<10.0)
            viewpoint_z=10.0;

      /* default viewpoint */
      printf("\n");
      printf("Viewpoint{\n");
      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);
      printf("fieldOfView 0.78\n");
      printf("description \"Default Viewpoint\"\n");
      printf("}\n");

      /* problem timer */
      printf("DEF ProblemTimer TimeSensor{\n");
      printf("loop TRUE\n");
      printf("cycleInterval 5\n");
      printf("}\n");

      /* host text prototype */
      printf("PROTO HostText[\n");
      printf("field MFString the_text [\"\"]\n");
      printf("field SFColor font_color 0.6 0.6 0.6");
      printf("]\n");
      printf("{\n");
      printf("Billboard{\n");
      printf("children[\n");
      printf("Shape{\n");
      printf("appearance Appearance {\n");
      printf("material Material {\n");
      printf("diffuseColor IS font_color\n");
      printf("}\n");
      printf("}\n");
      printf("geometry Text {\n");
      printf("string IS the_text\n");
      printf("fontStyle FontStyle {\n");
      printf("family \"TYPEWRITER\"\n");
      printf("size 0.1\n");
      printf("justify \"MIDDLE\"\n");
      printf("}\n");
      printf("}\n");
      printf("}\n");
      printf("]\n");
      printf("}\n");
      printf("}\n");

      /* include user-defined world */
      if(statuswrl_include!=NULL && coordinates_were_specified==TRUE && layout_method==LAYOUT_USER_SUPPLIED){
            printf("\n");
            printf("Inline{\n");
            printf("url \"%s%s\"\n",url_html_path,statuswrl_include);
            printf("}\n");
              }

      return;
      }



/* draws a host */
void draw_host(hostextinfo *temp_hostextinfo){
      host *temp_host;
      hoststatus *temp_hoststatus=NULL;
      char state_string[16]="";
      double x, y, z;
      char *vrml_safe_hostname=NULL;
      int a, ch;

      if(temp_hostextinfo==NULL)
            return;

      /* make sure we have the coordinates */
      if(temp_hostextinfo->have_3d_coords==FALSE)
            return;
      else{
            x=temp_hostextinfo->x_3d;
            y=temp_hostextinfo->y_3d;
            z=temp_hostextinfo->z_3d;
              }

      /* find the config entry for this host */
      temp_host=find_host(temp_hostextinfo->host_name);
      if(temp_host==NULL)
            return;

      /* make the host name safe for embedding in VRML */
      vrml_safe_hostname=(char *)strdup(temp_host->name);
      if(vrml_safe_hostname==NULL)
            return;
      for(a=0;vrml_safe_hostname[a]!='\x0';a++){
            ch=vrml_safe_hostname[a];
            if((ch<'a' || ch>'z') && (ch<'A' || ch>'Z') && (ch<'0' || ch>'9'))
                  vrml_safe_hostname[a]='_';
              }

      /* see if user is authorized to view this host  */
      if(is_authorized_for_host(temp_host,&current_authdata)==FALSE)
            return;

      /* get the status of the host */
      temp_hoststatus=find_hoststatus(temp_host->name);

      printf("\n");


      /* host object */
      printf("Anchor{\n");
      printf("children[\n");

      printf("Transform {\n");
      printf("translation %2.2f %2.2f %2.2f\n",x,y,z);
      printf("children [\n");

      printf("DEF Host%s Shape{\n",vrml_safe_hostname);
      printf("appearance Appearance{\n");
      printf("material DEF HostMat%s Material{\n",vrml_safe_hostname);
      if(temp_hoststatus==NULL)
            printf("emissiveColor 0.2 0.2 0.2\ndiffuseColor 0.2 0.2 0.2\n");
      else if(temp_hoststatus->status==HOST_UP)
            printf("emissiveColor 0.2 1.0 0.2\ndiffuseColor 0.2 1.0 0.2\n");
      else
            printf("emissiveColor 1.0 0.2 0.2\ndiffuseColor 1.0 0.2 0.2\n");
      printf("transparency 0.4\n");
      printf("}\n");
      if(use_textures==TRUE && temp_hostextinfo->vrml_image!=NULL){
            printf("texture ImageTexture{\n");
            printf("url \"%s%s\"\n",url_logo_images_path,temp_hostextinfo->vrml_image);
            printf("}\n");
            }
      printf("}\n");
      printf("geometry Box{\n");
      printf("size %2.2f %2.2f %2.2f\n",node_width,node_width,node_width);
      printf("}\n");
      printf("}\n");

      printf("]\n");
      printf("}\n");

      printf("]\n");
      printf("description \"View status details for host '%s' (%s)\"\n",temp_host->name,temp_host->alias);
      printf("url \"%s?host=%s\"\n",STATUS_CGI,temp_host->name);
      printf("}\n");


      /* draw status text */
      if(use_text==TRUE){

            printf("\n");
            printf("Transform{\n");
            printf("translation %2.3f %2.3f %2.3f\n",x,y+DEFAULT_NODE_WIDTH,z);
            printf("children[\n");
            printf("HostText{\n");

            if(temp_hoststatus!=NULL){
                  if(temp_hoststatus->status==HOST_UP)
                        printf("font_color 0 1 0\n");
                  else if(temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE)
                        printf("font_color 1 0 0\n");
                      }
            printf("the_text [\"%s\", \"%s\", ",temp_host->name,temp_host->alias);
            if(temp_hoststatus==NULL)
                  strcpy(state_string,"UNKNOWN");
            else{
                  if(temp_hoststatus->status==HOST_DOWN)
                        strcpy(state_string,"DOWN");
                  else if(temp_hoststatus->status==HOST_UNREACHABLE)
                        strcpy(state_string,"UNREACHABLE");
                  else if(temp_hoststatus->status==HOST_PENDING)
                        strcpy(state_string,"PENDING");
                  else
                        strcpy(state_string,"UP");
                      }
            printf("\"%s\"]\n",state_string);

            printf("}\n");
            printf("]\n");
            printf("}\n");
              }

      /* host is down or unreachable, so make it fade in and out */
      if(temp_hoststatus!=NULL && (temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE))
            printf("ROUTE ProblemTimer.fraction_changed TO HostMat%s.set_transparency\n",vrml_safe_hostname);

      free(vrml_safe_hostname);

      return;
      }



/* draw links between hosts */
void draw_host_links(void){
      hostextinfo *child_hostextinfo;
      hostextinfo *parent_hostextinfo;
      host *parent_host;
      host *child_host;

      if(use_links==FALSE)
            return;

      for(child_hostextinfo=hostextinfo_list;child_hostextinfo!=NULL;child_hostextinfo=child_hostextinfo->next){

            if(child_hostextinfo->have_3d_coords==FALSE)
                  continue;

            child_host=find_host(child_hostextinfo->host_name);
            if(child_host==NULL)
                  continue;

            /* check authorization */
            if(is_authorized_for_host(child_host,&current_authdata)==FALSE)
                  continue;

            /* draw a link from this host to all of its parent hosts */
            for(parent_host=host_list;parent_host!=NULL;parent_host=parent_host->next){

                  if(is_host_immediate_child_of_host(child_host,parent_host)==TRUE){

                        parent_hostextinfo=find_hostextinfo(parent_host->name);

                        if(parent_hostextinfo==NULL)
                              continue;

                        if(parent_hostextinfo->have_3d_coords==FALSE)
                              continue;
                        
                        /* check authorization */
                        if(is_authorized_for_host(parent_host,&current_authdata)==FALSE)
                              continue;

                        /* draw the link between the child and parent hosts */
                        draw_host_link(parent_host,parent_hostextinfo->x_3d,parent_hostextinfo->y_3d,parent_hostextinfo->z_3d,child_hostextinfo->x_3d,child_hostextinfo->y_3d,child_hostextinfo->z_3d);
                          }
                    }
              }

      
      return;
        }




/* draws a link from a parent host to a child host */
void draw_host_link(host *hst,double x0, double y0, double z0, double x1, double y1, double z1){

      printf("\n");

      if(hst!=NULL)
            printf("# Host '%s' LINK\n",hst->name);

      printf("Shape{\n");

      printf("appearance DEF MATslategrey_0_ Appearance {\n");
      printf("material Material {\n");
      printf("diffuseColor 0.6 0.6 0.6\n");
      printf("ambientIntensity 0.5\n");
      printf("emissiveColor 0.6 0.6 0.6\n");
        printf("}\n");
      printf("}\n");

      printf("geometry IndexedLineSet{\n");
      printf("coord Coordinate{\n");
      printf("point [ %2.3f %2.3f %2.3f, %2.3f %2.3f %2.3f ]\n",x0,y0,z0,x1,y1,z1);
      printf("}\n");
      printf("coordIndex [ 0,1,-1 ]\n");
      printf("}\n");

      printf("}\n");

      return;
      }



/* draw process icon */
void draw_process_icon(void){
      hostextinfo *child_hostextinfo;
      host *child_host;

      if(draw_nagios_icon==FALSE)
            return;

      /* draw process icon */
      printf("\n");


      printf("Anchor{\n");
      printf("children[\n");

      printf("Transform {\n");
      printf("translation %2.2f %2.2f %2.2f\n",nagios_icon_x,nagios_icon_y,0.0);
      printf("children [\n");

      printf("DEF ProcessNode Shape{\n");
      printf("appearance Appearance{\n");
      printf("material Material{\n");
      printf("emissiveColor 0.5 0.5 0.5\n");
      printf("diffuseColor 0.5 0.5 0.5\n");
      printf("transparency 0.2\n");
      printf("}\n");
      if(use_textures==TRUE){
            printf("texture ImageTexture{\n");
            printf("url \"%s%s\"\n",url_logo_images_path,NAGIOS_VRML_IMAGE);
            printf("}\n");
            }
      printf("}\n");
      printf("geometry Box{\n");
      printf("size %2.2f %2.2f %2.2f\n",node_width*3.0,node_width*3.0,node_width*3.0);
      printf("}\n");
      printf("}\n");

      printf("]\n");
      printf("}\n");

      printf("]\n");
      printf("description \"View Nagios Process Information\"\n");
      printf("url \"%s?type=%d\"\n",EXTINFO_CGI,DISPLAY_PROCESS_INFO);
      printf("}\n");


      if(use_links==FALSE)
            return;

      /* draw links to immediate child hosts */
      for(child_hostextinfo=hostextinfo_list;child_hostextinfo!=NULL;child_hostextinfo=child_hostextinfo->next){

            if(child_hostextinfo->have_3d_coords==FALSE)
                  continue;

            child_host=find_host(child_hostextinfo->host_name);
            if(child_host==NULL)
                  continue;

            /* check authorization */
            if(is_authorized_for_host(child_host,&current_authdata)==FALSE)
                  continue;

            /* draw a link to the host */
            if(is_host_immediate_child_of_host(NULL,child_host)==TRUE)
                  draw_host_link(NULL,nagios_icon_x,nagios_icon_y,0.0,child_hostextinfo->x_3d,child_hostextinfo->y_3d,child_hostextinfo->z_3d);
              }

      return;
        }




/******************************************************************/
/***************** COORDINATE CALCULATION FUNCTIONS ***************/
/******************************************************************/

/* calculates coords of a host's children - used by balanced tree layout method */
void calculate_balanced_tree_coords(host *parent, int x, int y){
      int parent_drawing_width;
      int start_drawing_x;
      int current_drawing_x;
      int this_drawing_width;
      host *temp_host;
      hostextinfo *temp_hostextinfo;

      /* calculate total drawing width of parent host */
      parent_drawing_width=max_child_host_drawing_width(parent);

      /* calculate starting x coord */
      start_drawing_x=x-(((DEFAULT_NODE_WIDTH*parent_drawing_width)+(DEFAULT_NODE_HSPACING*(parent_drawing_width-1)))/2);
      current_drawing_x=start_drawing_x;


      /* calculate coords for children */
      for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){

            temp_hostextinfo=find_hostextinfo(temp_host->name);
            if(temp_hostextinfo==NULL)
                  continue;

            if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){

                  /* get drawing width of child host */
                  this_drawing_width=max_child_host_drawing_width(temp_host);

                  temp_hostextinfo->x_3d=current_drawing_x+(((DEFAULT_NODE_WIDTH*this_drawing_width)+(DEFAULT_NODE_HSPACING*(this_drawing_width-1)))/2);
                  temp_hostextinfo->y_3d=y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING;
                  temp_hostextinfo->have_3d_coords=TRUE;
                  temp_hostextinfo->should_be_drawn=TRUE;
                  
                  current_drawing_x+=(this_drawing_width*DEFAULT_NODE_WIDTH)+((this_drawing_width-1)*DEFAULT_NODE_HSPACING)+DEFAULT_NODE_HSPACING;

                  /* recurse into child host ... */
                  calculate_balanced_tree_coords(temp_host,temp_hostextinfo->x_3d,temp_hostextinfo->y_3d);
                    }

              }

      return;
        }


/* calculate coords of all hosts in circular layout method */
void calculate_circular_coords(void){

      /* calculate all host coords, starting with first layer */
      calculate_circular_layer_coords(NULL,0.0,360.0,1,CIRCULAR_DRAWING_RADIUS);

      return;
        }
      

/* calculates coords of all hosts in a particular "layer" in circular layout method */
void calculate_circular_layer_coords(host *parent, double start_angle, double useable_angle, int layer, int radius){
      int parent_drawing_width=0;
      int this_drawing_width=0;
      int immediate_children=0;
      double current_drawing_angle=0.0;
      double this_drawing_angle=0.0;
      double available_angle=0.0;
      double clipped_available_angle=0.0;
      double average_child_angle=0.0;
      double x_coord=0.0;
      double y_coord=0.0;
      host *temp_host;
      hostextinfo *temp_hostextinfo;


      /* get the total number of immediate children to this host */
      immediate_children=number_of_immediate_child_hosts(parent);

      /* bail out if we're done */
      if(immediate_children==0)
            return;

      /* calculate total drawing "width" of parent host */
      parent_drawing_width=max_child_host_drawing_width(parent);

      /* calculate average angle given to each child host */
      average_child_angle=(double)(useable_angle/(double)immediate_children);

      /* calculate initial drawing angle */
      current_drawing_angle=start_angle;


      /* calculate coords for children */
      for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){

            temp_hostextinfo=find_hostextinfo(temp_host->name);
            if(temp_hostextinfo==NULL)
                  continue;

            if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){

                  /* get drawing width of child host */
                  this_drawing_width=max_child_host_drawing_width(temp_host);

                  /* calculate angle this host gets for drawing */
                  available_angle=useable_angle*((double)this_drawing_width/(double)parent_drawing_width);

                  /* clip available angle if necessary */
                  /* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */
                  clipped_available_angle=360.0/layer;
                  if(available_angle<clipped_available_angle)
                        clipped_available_angle=available_angle;

                  /* calculate the exact angle at which we should draw this child */
                  this_drawing_angle=current_drawing_angle+(available_angle/2.0);

                  /* compensate for angle overflow */
                  while(this_drawing_angle>=360.0)
                        this_drawing_angle-=360.0;
                  while(this_drawing_angle<0.0)
                        this_drawing_angle+=360.0;

                  /* calculate drawing coords of this host using good ol' geometry... */
                  x_coord=-(sin(-this_drawing_angle*(M_PI/180.0))*radius);
                  y_coord=-(sin((90+this_drawing_angle)*(M_PI/180.0))*radius);

                  temp_hostextinfo->x_3d=(int)x_coord;
                  temp_hostextinfo->y_3d=(int)y_coord;
                  temp_hostextinfo->have_3d_coords=TRUE;
                  temp_hostextinfo->should_be_drawn=TRUE;

                  /* recurse into child host ... */
                  calculate_circular_layer_coords(temp_host,current_drawing_angle+((available_angle-clipped_available_angle)/2),clipped_available_angle,layer+1,radius+CIRCULAR_DRAWING_RADIUS);

                  /* increment current drawing angle */
                  current_drawing_angle+=available_angle;
                    }
              }

      return;
        }



Generated by  Doxygen 1.6.0   Back to index