#!/usr/local/bin/perl
#
#  Purpose:
#  flowmonitor_grapher_recent runs through recently created FlowMonitors
#  creating new FlowMonitor graphs at all time-frames (i.e. Last 24 Hours,
#  Last 7 days, Last 4 Weeks, Last 12 Months, Last 3 Years). The "nonlazy"
#  option is used to force RRDtool to re-graph even if there have been no
#  changes in the underlying database. The recent period is established by
#  modifying the $include_period below.
#
#  Description:
#  The user simply invoke from the command line in the main directory. This
#  command will not alter any data stores and is completely limited to
#  re-drawing all graphs.
#
#  Controlling Parameters (specified in FlowViewer_Configuration.pm):
#  Name                 Description
#  -----------------------------------------------------------------------
#  rrd_area             Color of the area underneath the graph
#  rrd_line             Color of the line at the top of the graphed area
#  rrd_width            Width of the graph
#  rrd_height           Height of the graph
#  rrd_font             Color of the font used in the graphs
#  rrd_back             Image background color
#  rrd_canvas           Color of the background of the actual graph
#  rrd_grid             Color of the minor grid lines
#  rrd_mgrid            Color of the major grid lines
#  rrd_frame            Color of the graph frame
#  rrd_shadea           Color for the top and left border
#  rrd_shadeb           Color for the right and bottom border
#  rrd_thick            Thickness of the line at the top of the graph
#  rrd_lower_limit      Bottom of the y-axis
#  rrd_slope_mode       "--slope-mode" will round off tops of graph  
#  rrd_vrule_color      Color of the line that indicates when the filter was changed
#
#  Modification history:
#  Author       Date            Vers.   Description
#  -----------------------------------------------------------------------
#  J. Loiacono  05/08/2012      4.0     Original version
#  J. Loiacono  09/02/2012      4.2.1   Minor output format mods
#  J. Loiacono  07/04/2014      4.4     Multiple dashboards
#  J. Loiacono  11/02/2014      4.5     FlowTracker to FlowMonitor rename
#
#$Author$
#$Date$
#$Header$
#
###########################################################################
#
#               BEGIN EXECUTABLE STATEMENTS
#
 
use FlowViewer_Configuration;
use FlowViewer_Utilities;
use File::stat;
use lib $cgi_bin_directory;

$include_period = 12 * 3600;

if ($time_zone eq "") { 
        open(DATE,"date 2>&1|");   
        while (<DATE>) {  
                ($d_tz,$m_tz,$dt_tz,$t_tz,$time_zone,$y_tz) = split(/\s+/,$_);  
        }        
}  

$start_time = time;
$start_time_out = epoch_to_date($start_time,"LOCAL");
$current_time_rrd = $start_time_out . " $time_zone"; 
$current_time_rrd =~ s/:/\\:/g; 

if (!-e "$monitor_directory") {
        $mkdir_command = "mkdir $monitor_directory";
        system($mkdir_command);
        chmod $html_dir_perms, $monitor_directory;
}

# Load the colors 
     
$colors_file = "$cgi_bin_directory/FlowGrapher_Colors"; 
     
open (COLORS,"<$colors_file") || die "Can't open colors file; $colors_file\n"; 
while (<COLORS>) { 
        chop;    
        ($red,$green,$blue,$color_1,$color_2) = split(/\s+/); 
        $color_name = $color_1; 
        if ($color_2 ne "") { $color_name = $color_1 . " " . $color_2; } 
        $R = &dec2hex($red);   if (length($R) < 2) { $R = "0" . $R; }  
        $G = &dec2hex($green); if (length($G) < 2) { $G = "0" . $G; }  
        $B = &dec2hex($blue);  if (length($B) < 2) { $B = "0" . $B; }  
        $hex_colors{$color_name} =  $R . $G . $B; 
}    
$hex_colors{"standard"} = $rrd_area; 
sub dec2hex($) { return sprintf("%lx", $_[0]) } 

if ($debug_monitor eq "Y") { open(DEBUG,">$work_directory/DEBUG_MONITOR_G"); }

$end_rrd        = time;
$num_monitors   = 0;
$groups_exist   = 0;
$archives_exist = 0;
%monitors       = ();

# Work through each monitor

print "\nUpdating all graphs for all FlowMonitors, starting $start_time_out ...\n\n";

$files_cutoff = $end_rrd - $include_period;

while ($filter_file = <$filter_directory/*>) {

	$last_access = stat($filter_file)->mtime;
	if ($last_access < $files_cutoff) { next; }

	($directory,$monitor) = $filter_file =~ m/(.*\/)(.*)$/;
	($monitor,$extension) = split(/\./,$monitor);

	$num_monitors++;

        # Load information from filter file for graph and HTML page re-creation
      
	$monitor_type = "";
	@component_links = ();
	$vrule_1 = "";
	$vrule_2 = "";
	$vrule_3 = "";
	$hrule = "";
	$alert_threshold = 0;

        open (FILTER,"<$filter_file"); 
        while (<FILTER>) { 
                chop;    
                $key = substr($_,0,8); 
                if ($key eq " input: ") { 
                        ($input,$field,$field_value) = split(/: /); 

			if (($field eq "monitor_type") || ($field eq "tracking_type")) { 
				$monitor_type = $field_value; }
			if (($field eq "monitor_label") || ($field eq "tracking_label")) { 
				$monitors{$monitor} = $field_value;
				$monitor_label = $field_value; }
			if ($field eq "general_comment") { 
				$general_comment = $field_value; }
			if ($field eq "alert_threshold") { 
				$alert_threshold = $field_value; }

                        if ($field eq "revision") { 

                                ($notate_graphs,$revision_date,$revision_comment) = split(/\|/,$field_value);  
                                $revision_date_out = epoch_to_date($revision_date,"LOCAL"); 
                                $revision_date_out =~ s/:/\\:/g;

                                if ($notate_graphs eq "Y") {   
					if (($vrule_1 ne "") && ($vrule_2 ne "") && ($vrule_3 ne "")) {
						$vrule_1 = $vrule_2;
						$vrule_2 = $vrule_3;
                                                $vrule_3 = "VRULE:$revision_date#$rrd_vrule_color:\"$revision_date_out\\: $revision_comment\\n\""; 
					}
                                        if ($vrule_1 eq "") { 
                                                $vrule_1 = "VRULE:$revision_date#$rrd_vrule_color:\"$revision_date_out\\: $revision_comment\\n\""; 
                                                next;
                                        } elsif ($vrule_2 eq "") { 
                                                $vrule_2 = "VRULE:$revision_date#$rrd_vrule_color:\"$revision_date_out\\: $revision_comment\\n\""; 
                                                next;
                                        } elsif ($vrule_3 eq "") { 
                                                $vrule_3 = "VRULE:$revision_date#$rrd_vrule_color:\"$revision_date_out\\: $revision_comment\\n\""; 
                                                next;
					}  
                                } 
                        }       

			if ($alert_threshold > 0) {
				$hrule = "    HRULE:$alert_threshold#$rrd_hrule_color";
			}
		}
        }                
        close (FILTER);

	$monitors{$monitor} .= "^" . $general_comment;
	
	$type_out = "I";
	if ($monitor_type eq "Group") {
		$type_out = "G";
                open (FILTER,"<$filter_file"); 
                while (<FILTER>) { 
                        chop;    
                        $key = substr($_,0,8); 
                        if ($key eq " input: ") { 
				next;
			} else {
			        ($component_position,$component_label,$component_color) = split(/\^/);
				$component_file = $component_label; 
				$component_file =~ s/^\s+//; 
				$component_file =~ s/\s+$//; 
				$component_file =~ s/\&/-/g; 
				$component_file =~ s/\//-/g; 
				$component_file =~ s/\(/-/g; 
				$component_file =~ s/\)/-/g; 
				$component_file =~ s/\./-/g; 
				$component_file =~ s/\s+/_/g; 
				$component_file =~ tr/[A-Z]/[a-z]/;
				$component_html  = $monitor_short ."/". $component_file ."/index.html";
				push (@component_links,$component_html);
			}
		}
	}

	$html_directory = $monitor_directory ."/". $monitor;
	$html_file      = $html_directory ."/index.html";
	$monitor_file  = $monitor;

	# Look to skip Archives

	if ($extension eq "archive") { 
		$monitors{$monitor} .= "^Archive";
		$archives_exist = 1;
		$num_monitors--;
		next;
	} elsif ($monitor_type eq "Group") {
		$monitors{$monitor} .= "^Group";
		$groups_exist = 1;
	}

        # Set Vertical label

        if ($monitor_type =~ /fps/) {
                $vertical_label = "Flows per Second";
                $type_per_second = "fps";
        } elsif ($monitor_type =~ /pps/) {
                $vertical_label = "Packets per Second";
                $type_per_second = "pps";
        } else {
                $vertical_label = "Bits per Second";
                $type_per_second = "bps";
        }

	# Create each of the four graphs for this monitor
	
        $rrdtool_file = "$rrdtool_directory/$monitor" . ".rrd";  

	if (length($num_monitors) == 1) { $num_monitors_out = "00" . $num_monitors; }
	if (length($num_monitors) == 2) { $num_monitors_out = "0" .  $num_monitors; }
	if (length($num_monitors) == 3) { $num_monitors_out =        $num_monitors; }

	print "$type_out$num_monitors_out";

	foreach $graph_type ("Daily", "Weekly", "Monthly", "Yearly", "Three Years") {
	
		$x_grid  = "";

		if ($graph_type eq "Daily") {
			$start_rrd = $end_rrd - 86400;
                        $line_peak = "",
			$sample = "     Data collected over 5 minute periods          Graph Last Updated\\: $current_time_rrd";
			$rrd_title = "\"Last 24 Hours\"";
			if ($labels_in_titles) { $rrd_title = "\"$monitor_label\: Last 24 Hours\""; }
			$graph_file = "$monitor_directory/$monitor/daily.png";
		} elsif ($graph_type eq "Weekly") {
			$start_rrd = $end_rrd - (7*86400);
                        $line_peak = "LINE$rrd_thick:flowpeak#$rrd_peak:\"Peak 5 Minute Period\"",
			$sample = "     Data averaged over 30 minute periods          Graph Last Updated\\: $current_time_rrd";
			$rrd_title = "\"Last 7 Days\"";
			if ($labels_in_titles) { $rrd_title = "\"$monitor_label\: Last 7 Days\"";
			$graph_file = "$monitor_directory/$monitor/weekly.png"; }
		} elsif ($graph_type eq "Monthly") {
			$start_rrd = $end_rrd - (28*86400);
                        $line_peak = "LINE$rrd_thick:flowpeak#$rrd_peak:\"Peak 5 Minute Period\"",
			$sample = "     Data averaged over 2 hour periods             Graph Last Updated\\: $current_time_rrd";
			$rrd_title = "\"Last 4 Weeks\"";
			if ($labels_in_titles) { $rrd_title = "\"$monitor_label\: Last 4 Weeks\""; }
			$graph_file = "$monitor_directory/$monitor/monthly.png";
		} elsif ($graph_type eq "Yearly") {
			$start_rrd = $end_rrd - (365*86400);
                        $line_peak = "LINE$rrd_thick:flowpeak#$rrd_peak:\"Peak 5 Minute Period\"",
			$sample = "     Data averaged over 24 hour periods            Graph Last Updated\\: $current_time_rrd";
			$rrd_title = "\"Last 12 Months\"";
			if ($labels_in_titles) { $rrd_title = "\"$monitor_label\: Last 12 Months\""; }
			$graph_file = "$monitor_directory/$monitor/yearly.png";
		} elsif ($graph_type eq "Three Years") {
			$start_rrd = $end_rrd - (3*365*86400);
                        $line_peak = "LINE$rrd_thick:flowpeak#$rrd_peak:\"Peak 5 Minute Period\"",
			$sample = "     Data averaged over 24 hour periods            Graph Last Updated\\: $current_time_rrd";
			$rrd_title = "\"Last Three Years\"";
			if ($labels_in_titles) { $rrd_title = "\"$monitor_label\: Last Three Years\""; }
			$x_grid = "--x-grid MONTH:1:YEAR:1:MONTH:2:2800000:%b";
			$graph_file = "$monitor_directory/$monitor/threeyears.png";
		}

		if ($extension eq "grp") {

			$DEF_parameters  = "";
			$AREA_parameters = "";
			@components = ();

        		open (GROUP,"<$filter_file"); 
        		@group_lines = <GROUP>; 
        		close (GROUP); 
     
        		foreach $group_line (@group_lines) { 
                		if ($group_line =~ / input:/) { next; }
                		else { push (@components,$group_line); } 
        		}

			$num_components = 0;
			$first_below = 1;
        		foreach $component (@components) { 

			        $num_components++;
			        chop $component;
			        ($component_position,$component_label,$component_color) = split(/\^/,$component);
			 
				$component_file = $component_label; 
				$component_file =~ s/^\s+//; 
				$component_file =~ s/\s+$//; 
				$component_file =~ s/\&/-/g; 
				$component_file =~ s/\//-/g; 
				$component_file =~ s/\(/-/g; 
				$component_file =~ s/\)/-/g; 
				$component_file =~ s/\./-/g; 
				$component_file =~ s/\s+/_/g; 
				$component_file =~ tr/[A-Z]/[a-z]/;
				$component_rrd  = $rrdtool_directory ."/". $component_file .".rrd";

				$component_archive  = $rrdtool_directory ."/". $component_file .".archive";
				if (-e $component_archive) { $component_rrd = $component_archive; }
			 

                                # Set Vertical label for Group

                                if ($comp_monitor_type =~ /fps/) {
                                        $vertical_label = "Flows per Second";
                                } elsif ($comp_monitor_type =~ /pps/) {
                                        $vertical_label = "Packets per Second";
                                } else {
                                        $vertical_label = "Bits per Second";
                                }

			        $DEF_parameters  .= "DEF:flowbits$num_components=$component_rrd:flowbits:AVERAGE ";
			        $AREA_parameters .= "COMMENT:\"     \" ";
			 
			        if ($component_position < 200) {
			                $AREA_parameters .= "AREA:flowbits$num_components#$hex_colors{$component_color}:\"$component_label\\n\":STACK ";
			        } elsif (($component_position >= 200) && ($first_below)) {
			                $DEF_parameters .= "CDEF:flowbits_below$num_components=flowbits$num_components,-1,* ";
			                $AREA_parameters .= "AREA:flowbits_below$num_components#$hex_colors{$component_color}:\"$component_label\\n\" ";
			                $first_below = 0;
			        } else {
			                $DEF_parameters .= "CDEF:flowbits_below$num_components=flowbits$num_components,-1,* ";
			                $AREA_parameters .= "AREA:flowbits_below$num_components#$hex_colors{$component_color}:\"$component_label\\n\":STACK ";
			        }
			}
		
			@graph_parameters =  
		        ('--title',"$rrd_title",  
		        '--start',$start_rrd,  
		        '--end',$end_rrd,  
		        '--width',$rrd_width,  
		        '--height',$rrd_height,  
		        '--interlace',  
			'--vertical-label',"\"$vertical_label\"",
		        $x_grid,
		        $rrd_slope_mode,  
		        "--color=FONT#$rrd_font",  
		        "--color=BACK#$rrd_back",  
		        "--color=CANVAS#$rrd_canvas",  
		        "--color=GRID#$rrd_grid",  
		        "--color=MGRID#$rrd_mgrid",  
		        "--color=FRAME#$rrd_frame",  
		        "--color=SHADEA#$rrd_frame",  
		        "--color=SHADEB#$rrd_frame",  
		        '--lower-limit',$rrd_lower_limit,  
		        $DEF_parameters, 
                        "COMMENT:\"$sample   \"",
                        "COMMENT:\" \\n\"",
		        $AREA_parameters,
                        "COMMENT:\" \\n\"",
                        $vrule_1,
                        $vrule_2,
                        $vrule_3);

		} else {

                        @graph_parameters =
                        ('--title',"$rrd_title",
                        '--start',$start_rrd,
                        '--end',$end_rrd,
                        '--width',$rrd_width,
                        '--height',$rrd_height,
                        '--interlace',
			'--vertical-label',"\"$vertical_label\"",
		        $x_grid,
                        $rrd_slope_mode,
                        "--color=FONT#$rrd_font",
                        "--color=BACK#$rrd_back",
                        "--color=CANVAS#$rrd_canvas",
                        "--color=GRID#$rrd_grid",
                        "--color=MGRID#$rrd_mgrid",
                        "--color=FRAME#$rrd_frame",
                        "--color=SHADEA#$rrd_frame",
                        "--color=SHADEB#$rrd_frame",
                        '--lower-limit',$rrd_lower_limit,
                        "DEF:flowbits=$rrdtool_file:flowbits:AVERAGE",
                        "DEF:flowpeak=$rrdtool_file:flowbits:MAX",
                        'VDEF:flowbitsmax=flowbits,MAXIMUM',
                        'VDEF:flowbitsavg=flowbits,AVERAGE',
                        'VDEF:flowbitsmin=flowbits,MINIMUM',
                        'VDEF:flowbitspct=flowbits,95,PERCENT',
                        "AREA:flowbits#$rrd_area",
                        "LINE$rrd_thick:flowbits#$rrd_line:",
                        "COMMENT:\"$sample   \"",
                        "COMMENT:\" \\n\"",
                        "COMMENT:\"             Maximum    \"",
                        "GPRINT:flowbitsmax:\"%6.2lf %S$type_per_second\"",
                        "COMMENT:\"             \"",
			$line_peak,
                        "COMMENT:\" \\n\"",
                        "COMMENT:\"             95thPct    \"",
                        "GPRINT:flowbitspct:\"%6.2lf %S$type_per_second \"",
                        "COMMENT:\" \\n\"",
                        "COMMENT:\"             Average    \"",
                        "GPRINT:flowbitsavg:\"%6.2lf %S$type_per_second \"",
                        "COMMENT:\" \\n\"",
                        "COMMENT:\"             Minimum    \"",
                        "GPRINT:flowbitsmin:\"%6.2lf %S$type_per_second \"",
                        "COMMENT:\"                        [List Values]\\n\"",
                        "COMMENT:\" \\n\"",
                        $vrule_1,
                        $vrule_2,
                        $vrule_3,
			$hrule);
		}

                $rrdgraph_command = "$rrdtool_bin_directory/rrdtool graph " . "$graph_file " . "@graph_parameters " . ">/dev/null";
		if ($debug_monitor eq "Y") { print DEBUG "\n\n$rrdgraph_command\n\n"; }

                system($rrdgraph_command);

		chmod $graph_file_perms, $graph_file;

                print ".";
	}
	print "  $monitor_label\n";
}

# Update Dashboard Thumbnails

print "\nUpdating Dashboard(s)\n\n";

@all_dashboards = @other_dashboards;
unshift(@all_dashboards,$dashboard_directory);

$dashboard_entry = -1;

foreach $dashboard (@all_dashboards) {

	$dashboard_entry++;

        @dashboard_files = <$dashboard/*>;
        foreach $dashboard_file (@dashboard_files) {

		($directory,$thumbnail_file) = $dashboard_file =~ m/(.*\/)(.*)$/;

		($thumbnail_file,$thumbnail_suffix) = split(/\./,$thumbnail_file);

		$last_underscore = rindex($thumbnail_file,"_");
		$monitor_label = substr($thumbnail_file,0,$last_underscore);
		$position = substr($thumbnail_file,$last_underscore+1,1);

		$last_underscore = rindex($monitor_label,"_");
		$monitor_label = substr($monitor_label,0,$last_underscore);
		$graph_type = substr($thumbnail_file,$last_underscore+1,7);
		($graph_type,$last_underscore) = split(/_/,$graph_type);

		if (@dashboard_titles) {
			$update_dashboard = $dashboard_titles[$dashboard_entry];
			$update_dashboard =~ s/ /\~/;
		} else {
			$update_dashboard = "Main_Only";
		}
	
		$thumbnail_command = "$cgi_bin_directory/FlowMonitor_Thumbnail $update_dashboard $monitor_label $graph_type $position";
		system($thumbnail_command);
	}
	print "Updated $dashboard\n";
}


$finish_time = time;
$finish_time_out = epoch_to_date($finish_time,"LOCAL");
$run_seconds = $finish_time - $start_time;
print "\nDone at $finish_time_out. Loop took: $run_seconds seconds\n\n";
