Changed cvs_man.php -> scm_man.php.
[clearscm.git] / clearadm / lib / ClearadmWeb.pm
1 =pod
2
3 =head1 NAME $RCSfile: ClearadmWeb.pm,v $
4
5 Common routines for the web portion of Clearadm
6
7 =head1 VERSION
8
9 =over
10
11 =item Author
12
13 Andrew DeFaria <Andrew@ClearSCM.com>
14
15 =item Revision
16
17 $Revision: 1.46 $
18
19 =item Created
20
21 Sat Dec 18 08:43:27 EST 2010
22
23 =item Modified
24
25 $Date: 2011/12/26 19:00:58 $
26
27 =back
28
29 =head1 SYNOPSIS
30
31 This module holds common web routines for the web portion of Clearadm.
32
33 =head1 DESCRIPTION
34
35 To be filled out.
36
37 =head1 ROUTINES
38
39 The following routines are exported:
40
41 =cut
42
43 package ClearadmWeb;
44
45 use warnings;
46 use strict;
47
48 use base 'Exporter';
49
50 use CGI qw (
51   :standard 
52    start_a
53    end_a
54    start_div
55    end_div
56    start_li
57    end_li
58    start_table
59    end_table
60    start_td
61    end_td
62    start_Tr
63    end_Tr
64    start_ul
65    end_ul
66 );
67
68 use Carp;
69 use File::Basename;
70
71 use FindBin;
72
73 use lib "$FindBin::Bin/../../lib";
74
75 use Clearadm;
76 use DateUtils;
77 use Display;
78 use Utils;
79
80 my $clearadm = Clearadm->new;
81
82 our $APPNAME= 'Clearadm';
83 our $VERSION  = '$Revision: 1.46 $';
84    ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
85   
86 our @EXPORT = qw (
87   autoScale
88   displayError
89   displayAlert
90   displayAlertlog
91   displayFilesystem
92   displayNotification
93   displayRunlog
94   displaySchedule
95   displaySystem
96   displayTask
97   dbug
98   dumpVars
99   editAlert
100   editFilesystem
101   editNotification
102   editSchedule
103   editSystem
104   editTask
105   footing
106   graphError
107   heading
108   makeAlertDropdown
109   makeFilesystemDropdown
110   makeIntervalDropdown
111   makeNotificationDropdown
112   makeSystemDropdown
113   makeTimeDropdown
114   makeTaskDropdown
115   setField
116   setFields
117 );
118
119 our @PREDEFINED_ALERTS = (
120   'Email admin',
121 );
122
123 our @PREDEFINED_NOTIFICATIONS = (
124   'Loadavg',
125   'Filesystem',
126   'Scrub',
127   'Heartbeat',
128   'System checkin',
129   'Update systems',
130 );
131
132 our @PREDEFINED_TASKS = (
133   'Loadavg',
134   'Filesystem',
135   'Scrub',
136   'System checkin',
137   'Update systems',
138 );
139
140 our @PREDEFINED_SCHEDULES = (
141   'Loadavg',
142   'Filesystem',
143   'Scrub',
144   'Update systems',
145 );
146
147 our @PREDEFINED_NOTMORETHAN = (
148   'Once an hour',
149   'Once a day',
150   'Once a week',
151   'Once a month',
152 );
153
154 our @PREDEFINED_MULTIPLIERS = (
155   'Seconds',
156   'Minutes',
157   'Hours',
158   'Days',
159 );
160
161 sub dbug ($) {
162   my ($msg) = @_;
163   
164   display font ({-class => 'error'}, '<br>DEBUG: '). $msg;
165   
166   return;
167 } # dbug
168
169 sub displayError ($) {
170   my ($msg) = @_;
171   
172   display font ({-class => 'error'}, 'Error: ') . $msg;
173   
174   return
175 } # displayError;
176
177 sub setField ($;$) {
178   my ($field, $label) = @_;
179   
180   $label ||= 'Unknown';
181
182   my $undef = font {-class => 'unknown'}, $label;
183   
184   return defined $field ? $field : $undef;
185 } # setField
186
187 sub setFields ($%) {
188   my ($label, %rec) = @_;
189   
190   $rec{$_} = setField ($rec{$_}, $label)
191     foreach keys %rec;
192     
193   return %rec;
194 } # setFields;
195
196 sub dumpVars (%) {
197   my (%vars) = @_;
198   
199   foreach (keys %vars) {
200     dbug "$_: $vars{$_}";
201   } # foreach
202   
203   return;
204 } # dumpVars
205
206 sub graphError ($) {
207   my ($msg) = @_;
208   
209   use GD;
210   
211   # Make the image fit the message. It seems that characters are ~ 7px wide.
212   my $imageLength = length ($msg) * 7;
213   
214   my $errorImage = GD::Image->new ($imageLength, 20);
215
216   # Allocate some colors
217   my $white = $errorImage->colorAllocate (255, 255, 255);
218   my $red   = $errorImage->colorAllocate (255, 0, 0);
219   
220   # Allow the text to shine through
221   $errorImage->transparent($white);
222   $errorImage->interlaced('true');
223
224   # Now put out the message  
225   $errorImage->string (gdMediumBoldFont, 0, 0, $msg, $red);
226
227   # And return it
228   print "Content-type: image/png\n\n";
229   print $errorImage->png;
230   
231   # Since we've "returned" the error in the form of an image, there's nothing
232   # left for us to do so we can exit
233   exit;
234 } # graphError
235
236 sub autoScale ($) {
237   my ($amount) = @_;
238   
239   my $kbyte = 1024;
240   my $meg   = (1024 * $kbyte);
241   my $gig   = (1024 * $meg);
242   
243   my $size = $amount > $gig
244            ? sprintf ('%.2f Gig',   $amount / $gig)
245            : $amount > $meg
246            ? sprintf ('%.2f Meg',   $amount / $meg)
247            : sprintf ('%.2f Kbyte', $amount / $kbyte);
248            
249   return $size;         
250 } # autoScale
251
252 sub _makeAlertlogSelection ($$) {
253   my ($name, $default) = @_;
254   
255   $default ||= 'All';
256
257   my %values;
258
259   $values{All} = 'All';
260   
261   $values{$$_{$name}} = $$_{$name}
262     foreach ($clearadm->FindAlertlog);
263
264   my $dropdown = popup_menu {
265     name    => $name,
266     class   => 'dropdown',
267     values  => [sort keys %values],
268     default => $default,
269   };  
270   
271   return $dropdown;
272 } # _makeAlertlogSelection
273
274 sub _makeRunlogSelection ($$) {
275   my ($name, $default) = @_;
276   
277   $default ||= 'All';
278
279   my @values = sort $clearadm->GetUniqueList ('runlog', $name);
280   
281   unshift @values, 'All';
282   
283   my %values;
284   
285   foreach (@values) {
286      unless ($_ eq '') {
287        $values{$_} = $_;
288      } else {
289        $values{NULL} = '<NULL>';
290      } #if 
291   } # foreach
292   
293   my $dropdown = popup_menu {
294     name    => $name,
295     class   => 'dropdown',
296     values  => \@values,
297     default => $default,
298     labels  => \%values,
299   };  
300   
301   return $dropdown;
302 } # _makeRunlogSelection
303
304 sub _makeRunlogSelectionNumeric ($$) {
305   my ($name, $default) = @_;
306   
307   $default ||= 'All';
308
309   my @values = sort {$a <=> $b} $clearadm->GetUniqueList ('runlog', $name);
310   
311   unshift @values, 'All';
312   
313   my $dropdown = popup_menu {
314     name    => $name,
315     class   => 'dropdown',
316     values  => [@values],
317     default => $default,
318   };  
319   
320   return $dropdown;
321 } # _makeRunlogSelection
322
323 sub makeAlertDropdown (;$$) {
324   my ($label, $default) = @_;
325   
326   $label ||= '';
327
328   my @values;
329
330   push @values, $$_{name}
331     foreach ($clearadm->FindAlert);
332   
333   my $dropdown  = "$label ";
334      $dropdown .= popup_menu {
335     name    => 'alert',
336     class   => 'dropdown',
337     values  => [sort @values],
338     default => $default,
339   };  
340   
341   return $dropdown;
342 } # makeAlertDropdown
343
344 sub makeMultiplierDropdown (;$$) {
345   my ($label, $default) = @_;
346   
347   $label ||= '';
348   
349   my $dropdown  = "$label ";
350      $dropdown .= popup_menu {
351     name    => 'multiplier',
352     class   => 'dropdown',
353     values  => [sort @PREDEFINED_MULTIPLIERS],
354     default => $default,
355   };     
356
357   return $dropdown;
358 } # makeMultiplierDropdown
359
360 sub makeNoMoreThanDropdown (;$$) {
361   my ($label, $default) = @_;
362   
363   $label ||= '';
364   
365   my $dropdown  = "$label ";
366      $dropdown .= popup_menu {
367     name    => 'nomorethan',
368     class   => 'dropdown',
369     values  => [sort @PREDEFINED_NOTMORETHAN],
370     default => $default,
371   };     
372
373   return $dropdown;
374 } # makeNoMorThanDropdown
375  
376 sub makeFilesystemDropdown ($;$$$) {
377   my ($system, $label, $default, $onchange) = @_;
378
379   $label ||= '';
380   
381   my %filesystems;
382   
383   foreach ($clearadm->FindFilesystem ($system)) {
384     my %filesystem = %{$_};
385     
386     my $value = "$filesystem{filesystem} ($filesystem{mount})";
387
388     $filesystems{$filesystem{filesystem}} = $value;
389   } # foreach
390   
391   my $dropdown .= "$label ";
392      $dropdown .= popup_menu {
393     name     => 'filesystem',
394     class    => 'dropdown',
395     values   => [sort keys %filesystems],
396     labels   => \%filesystems,
397     onChange => ($onchange) ? $onchange : '',
398     default  => $default,
399   };
400     
401   return span {id => 'filesystems'}, $dropdown;  
402 } # makeFilesystemDropdown
403
404 sub makeIntervalDropdown (;$$$) {
405   my ($label, $default, $onchange) = @_;
406   
407   $label ||= '';
408   
409   my @intervals = (
410     'Minute',
411     'Hour',
412     'Day',
413     'Month',
414   );
415
416   $default = ucfirst lc $default
417     if $default;
418   
419   my $dropdown  = "$label ";
420      $dropdown .= popup_menu {
421     name     => 'scaling',
422     id       => 'scalingFactor',
423     class    => 'dropdown',
424     values   => [@intervals],
425     default  => $default,
426     onchange => $onchange,
427   };
428    
429    return span {id => 'scaling'}, $dropdown; 
430 } # makeIntervalDropdown;
431
432 sub makeNotificationDropdown (;$$) {
433   my ($label, $default) = @_;
434   
435   $label ||= '';
436
437   my @values;
438   
439   push @values, $$_{name} 
440     foreach ($clearadm->FindNotification);
441   
442   my $dropdown  = "$label ";
443      $dropdown .= popup_menu {
444     name    => 'notification',
445     class   => 'dropdown',
446     values  => [sort @values],
447     default => $default,
448   };  
449   
450   return $dropdown;
451 } # makeNotificationDropdown
452
453 sub makeRestartableDropdown (;$$) {
454   my ($label, $default) = @_;
455   
456   $label ||= '';
457
458   my @values = (
459     'true',
460     'false',
461   );
462   
463   my $dropdown  = "$label ";
464      $dropdown .= popup_menu {
465     name    => 'restartable',
466     class   => 'dropdown',
467     values  => [@values],
468     default => $default,
469   };  
470   
471   return $dropdown;
472 } # makeRestartableDropdown
473
474 sub makeSystemDropdown (;$$$%) {
475   my ($label, $default, $onchange, %systems) = @_;
476
477   $label ||= '';
478   
479   foreach ($clearadm->FindSystem) {
480     my %system = %{$_};
481     
482     my $value  = $system{name};
483        $value .= $system{alias} ? " ($system{alias})" : '';
484
485     $systems{$system{name}} = $value;
486   } # foreach
487   
488   my $systemDropdown .= "$label ";
489      $systemDropdown .= popup_menu {
490        name     => 'system',
491        class    => 'dropdown',
492        values   => [sort keys %systems],
493        labels   => \%systems,
494        onchange => ($onchange) ? $onchange : '',
495        default  => $default,
496     };
497     
498   return span {id => 'systems'}, $systemDropdown;
499 } # makeSystemDropdown
500
501 sub makeTaskDropdown (;$$) {
502   my ($label, $default) = @_;
503   
504   $label ||= '';
505
506   my @values;
507
508   push @values, $$_{name}
509     foreach ($clearadm->FindTask);
510   
511   my $taskDropdown  = "$label ";
512      $taskDropdown .= popup_menu {
513     name    => 'task',
514     class   => 'dropdown',
515     values  => [sort @values],
516     default => $default,
517   };  
518   
519   return $taskDropdown;
520 } # makeTaskDropdown
521
522 sub makeTimeDropdown ($$$;$$$$$) {
523   my (
524     $table,
525     $elementID,
526     $system,
527     $filesystem,
528     $label,
529     $default,
530     $interval,
531     $name,
532   ) = @_;
533
534   $label ||= '';
535     
536   my @times;
537   
538   $name ||= lc $label;
539   
540   push @times, 'Earliest';
541
542   if ($table =~ /loadavg/i) {
543     push @times, $$_{timestamp}
544       foreach ($clearadm->GetLoadavg ($system, undef, undef, undef, $interval));
545   } elsif ($table =~ /filesystem/i) {
546     push @times, $$_{timestamp}
547       foreach ($clearadm->GetFS ($system, $filesystem, undef, undef, undef, $interval));
548   } # if  
549
550   push @times, 'Latest';
551   
552   unless ($default) {
553     $default = $name eq 'start' ? 'Earliest' : 'Latest';
554   } # unless
555   
556   my $timeDropdown = "$label ";
557      $timeDropdown .= span {id => $elementID}, popup_menu {
558     name    => $name,
559     class   => 'dropdown',
560     values  => [@times],
561     default => $default,
562   };
563   
564   return $timeDropdown;   
565 } # makeTimeDropdown
566
567 sub heading (;$$) {
568   my ($title, $type) = @_;
569
570   if ($title) {
571     $title = "$APPNAME: $title";
572   } else {
573     $title = $APPNAME;
574   } # if
575   
576   display header;
577   display start_html {
578         -title  => $title,
579         -author => 'Andrew DeFaria <Andrew@ClearSCM.com>',
580         -meta   => {
581           keywords  => 'ClearSCM Clearadm',
582       copyright => 'Copyright (c) ClearSCM, Inc. 2010, All rights reserved',
583         },
584         -script => [{
585           -language => 'JavaScript',
586           -src      => 'clearadm.js',
587         }],
588         -style   => ['clearadm.css', 'clearmenu.css'],
589   }, $title;
590
591   return if $type;
592   
593   my $ieTableWrapStart = '<!--[if gt IE 6]><!--></a><!--<![endif]--><!--'
594                        . '[if lt IE 7]><table border="0" cellpadding="0" '
595                        . 'cellspacing="0"><tr><td><![endif]-->';
596   my $ieTableWrapEnd   = '<!--[if lte IE 6]></td></tr></table></a><![endif]-->';
597             
598   # Menubar
599   display div {id=>'mastheadlogo'}, h1 {class => 'title'}, $APPNAME;
600   display start_div {class => 'menu'};
601   
602   # Home
603   display ul li a {href => '/clearadm'}, 'Home';
604   
605   my @allSystems = $clearadm->FindSystem;
606   
607   # Systems
608   display start_ul;
609     display start_li;
610       display a {href => 'systems.cgi'}, "Systems$ieTableWrapStart";
611         display start_ul;
612           foreach (@allSystems) {
613             my %system = %{$_};
614             my $sysName  = ucfirst $system{name};
615                $sysName .= " ($system{alias})"
616                  if $system{alias};
617                  
618             display li a {
619               href => "systemdetails.cgi?system=$system{name}"
620             }, ucfirst "&nbsp;$sysName";
621           } # foreach
622         display end_ul;
623         display $ieTableWrapEnd;
624         display end_li;
625     display end_li;
626   display end_ul;
627   
628   # Filesystems
629   display start_ul;
630     display start_li;
631       display a {href => 'filesystems.cgi'}, "Filesystems$ieTableWrapStart";
632         display start_ul;
633           foreach (@allSystems) {
634             my %system = %{$_};
635             my $sysName  = ucfirst $system{name};
636                $sysName .= " ($system{alias})"
637                  if $system{alias};
638                              
639             display li a {
640               href => "filesystems.cgi?system=$system{name}"
641             }, ucfirst "&nbsp;$sysName";
642           } # foreach
643         display end_ul;
644         display $ieTableWrapEnd;
645     display end_li;
646   display end_ul;
647   
648   # Servers
649   display start_ul;
650     display start_li;
651       display a {href => '#'}, "Servers$ieTableWrapStart";
652       display start_ul {class => 'skinny'};
653         display start_li;
654           display start_a {href => 'vobs.cgi'};
655           display "<span class='drop'><span>VOB</span>&raquo;</span>$ieTableWrapStart";
656         display start_ul;
657           display li a {href => "systemdetails.cgi?system=jupiter"}, '&nbsp;Jupiter (defaria.com)';
658         display end_ul;
659         display $ieTableWrapEnd;
660         display end_li;
661         
662         display start_li;
663         display start_a {href => 'views.cgi'};
664         display "<span class='drop'><span>View</span>&raquo;</span>$ieTableWrapStart";
665         display start_ul;
666           display li a {href => "systemdetails.cgi?system=earth"}, '&nbsp;Earth';
667           display li a {href => "systemdetails.cgi?system=mars"}, '&nbsp;Mars';
668         display end_ul;
669         display $ieTableWrapEnd;
670       display end_ul;
671       display $ieTableWrapEnd;
672     display end_li;
673   display end_ul;
674  
675   # Vobs
676   display start_ul;
677     display start_li;
678       display a {href => 'vobs.cgi'}, "VOBs$ieTableWrapStart";
679       display start_ul;
680         display li a {href => '#'}, '&nbsp;/vobs/clearscm';
681         display li a {href => '#'}, '&nbsp;/vobs/clearadm';
682         display li a {href => '#'}, '&nbsp;/vobs/test';
683         display li a {href => '#'}, '&nbsp;/vobs/test2';
684       display end_ul;
685       display $ieTableWrapEnd;
686     display end_li;
687   display end_ul;  
688   
689   # Views
690   display start_ul;
691     display start_li;
692       display a {href => 'views.cgi'}, "Views$ieTableWrapStart";
693       display start_ul;
694         display li a {href => 'viewager.cgi'}, '&nbsp;View Ager';
695         display li a {href => '#'}, '&nbsp;Releast View';
696       display end_ul;
697       display $ieTableWrapEnd;
698     display end_li;
699   display end_ul;  
700
701   # Configure
702   display start_ul;
703     display start_li;
704       display a {href => '#'}, "Configure$ieTableWrapStart";
705       display start_ul;
706         display li a {href => 'alerts.cgi'},        '&nbsp;Alerts';
707         display li a {href => 'notifications.cgi'}, '&nbsp;Notifications';
708         display li a {href => 'schedule.cgi'},      '&nbsp;Schedule';
709         display li a {href => 'tasks.cgi'},         '&nbsp;Tasks';
710       display end_ul;
711       display $ieTableWrapEnd;
712     display end_li;
713   display end_ul;  
714   
715   # Logs
716   display start_ul;
717     display start_li;
718       display a {href => '#'}, "Logs$ieTableWrapStart";
719       display start_ul;
720         display li a {href => 'alertlog.cgi'}, '&nbsp;Alert';
721         display li a {href => 'runlog.cgi'},   '&nbsp;Run';
722       display end_ul;
723       display $ieTableWrapEnd;
724     display end_li;
725   display end_ul;  
726         
727   # Help
728   display start_ul;
729     display start_li;
730       display a {href => '#'}, "Help$ieTableWrapStart";
731       display start_ul {class => 'rightmenu'};
732         display li a {href => 'readme.cgi'}, "&nbsp;About: $APPNAME $VERSION";
733       display end_ul;
734       display $ieTableWrapEnd;
735     display end_li;
736   display end_ul;
737   display end_div;
738   
739   display start_div {class => 'page'};
740   
741   return;
742 } # heading
743
744 sub displayAlert (;$) {
745   my ($alert) = @_;
746   
747   display start_table {cellspacing => 1};
748
749   display start_Tr;
750     display th {class => 'labelCentered'}, 'Actions';
751     display th {class => 'labelCentered'}, 'Name';
752     display th {class => 'labelCentered'}, 'Type';
753     display th {class => 'labelCentered'}, 'Who';
754     display th {class => 'labelCentered'}, 'Category';
755   display end_Tr;
756   
757   foreach ($clearadm->FindAlert ($alert)) {
758     my %alert = %{$_};
759    
760     $alert{who} = setField $alert{who}, 'System Administrator';
761     
762     display start_Tr;
763       my $areYouSure = "Are you sure you want to delete the $alert{name} alert?";
764                    
765       my $actions = start_form {
766         method => 'post',
767         action => 'processalert.cgi',
768       };
769
770       $actions .= input {
771         name   => 'name',
772         type   => 'hidden',
773         value  => $alert{name},
774       };
775
776       if (InArray $alert{name}, @PREDEFINED_ALERTS) {
777         $actions .= input {
778           name     => 'delete',
779           disabled => 'true',
780           type     => 'image',
781           src      => 'delete.png',
782           alt      => 'Delete',
783           value    => 'Delete',
784           title    => 'Cannot delete predefined alert',
785         };     
786         $actions .= input {
787           name     => 'edit',
788           disabled => 'true',
789           type     => 'image',
790           src      => 'edit.png',
791           alt      => 'Edit',
792           value    => 'Edit',
793           title    => 'Cannot edit predefined alert',
794         };
795       } else {
796         $actions .= input {
797           name    => 'delete',
798           type    => 'image',
799           src     => 'delete.png',
800           alt     => 'Delete',
801           value   => 'Delete',
802           title   => 'Delete',
803           onclick => "return AreYouSure ('$areYouSure');",
804         };
805         $actions .= input {
806           name    => 'edit',
807           type    => 'image',
808           src     => 'edit.png',
809           alt     => 'Edit',
810           value   => 'Edit',
811           title   => 'Edit',
812         };
813       } # if
814
815       display end_form;     
816
817       my $who = $alert{who};
818       
819       if ($who =~ /^([a-zA-Z0-9._-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})$/) {
820         $who = a {href => "mailto:$1\@$2"}, $who;
821       } # if
822
823       display td {class => 'dataCentered'}, $actions;
824       display td {class => 'data'},         $alert{name};
825       display td {class => 'data'},         $alert{type};
826       display td {class => 'data'},         $who;
827       display td {class => 'data'},
828         (InArray $alert{name}, @PREDEFINED_ALERTS) ? 'Predefined' : 'User Defined';
829     display end_Tr;
830   } # foreach
831
832   display end_table; 
833   
834   display p {class => 'center'}, a {
835     href => 'processalert.cgi?action=Add',
836   }, 'New alert ', img {
837     src    => 'add.png',
838     border => 0,
839   };
840
841   return;
842 } # DisplayAlerts
843
844 sub displayAlertlog (%) {
845   my (%opts) = @_;
846   
847   my $optsChanged;
848   
849   unless (($opts{oldalert}        and $opts{alert}         and
850            $opts{oldalert}        eq  $opts{alert})        and
851           ($opts{oldsystem}       and $opts{system}        and
852            $opts{oldsystem}       eq  $opts{system})       and
853           ($opts{oldnotification} and $opts{notification}  and
854            $opts{oldnotification} eq  $opts{notification})) {
855     $optsChanged = 1;           
856   } # unless
857   
858   my $condition;
859
860   unless ($opts{id}) {
861     $condition  = "alert like '%";
862     $condition .= $opts{alert} ? $opts{alert} : '';
863     $condition .= "%'";
864     $condition .= ' and ';
865     $condition .= "system like '%";
866     $condition .= $opts{system} ? $opts{system} : '';
867     $condition .= "%'";
868     $condition .= ' and ';
869     $condition .= "notification like '%";
870     $condition .= $opts{notification} ? $opts{notification} : '';
871     $condition .= "%'";
872   } # unless
873
874   my $total = $clearadm->Count ('alertlog', $condition);
875
876   if ($opts{'nextArrow.x'}) {
877     $opts{start} = $opts{next};
878   } elsif ($opts{'prevArrow.x'}) {
879     $opts{start} = $opts{prev};
880   } else {
881     $opts{start} = 0;
882   } # if
883
884   my $next = $opts{start} + $opts{page} < $total 
885            ? $opts{start} + $opts{page}
886            : $opts{start};
887   my $prev = $opts{start} - $opts{page} >= 0
888            ? $opts{start} - $opts{page}
889            : $opts{start};
890
891   my $opts  = $opts{start} + 1;
892      $opts .= '-';
893      $opts .= $opts{start} + $opts{page} < $total
894             ? $opts{start} + $opts{page}
895             : $total;
896      $opts .= " of $total";
897
898   display start_form {
899     method => 'post', 
900     action => 'alertlog.cgi'
901   };
902
903   # Hidden fields to pass along
904   display input {name  => 'prev', type  => 'hidden', value => $prev};
905   display input {name  => 'next', type  => 'hidden', value => $next};
906   
907   display input {
908     name  => 'oldalert',
909     type  => 'hidden',
910     value => $opts{alert},
911   };
912   display input {
913     name  => 'oldsystem',
914     type  => 'hidden',
915     value => $opts{system},
916   };
917   display input {
918     name  => 'oldnotification',
919     type  => 'hidden',
920     value => $opts{notification},
921   };
922
923   my $caption = start_table {
924     class       => 'caption',
925     cellspacing => 1,
926     width       => '100%',
927   };
928
929   $caption .= start_Tr;
930
931     unless ($opts{id}) {
932       $caption .= td {align => 'left'}, input {
933         name     => 'prevArrow',
934         type     => 'image',
935         src      => 'left.png',
936         alt      => 'Previous',
937         value    => 'prev',
938       };
939     } else {
940       $caption .= td {align => 'left'}, img {
941         src      => 'left.png',
942         disabled => 'disabled',
943       };
944     } # unless
945   
946     $caption .= td {align => 'center'}, $opts;
947
948     unless ($opts{id}) {
949       $caption .= td {align => 'right'}, input {
950         name     => 'nextArrow',
951         type     => 'image',
952         src      => 'right.png',
953         alt      => 'Next',
954         value    => 'next',
955       };
956     } else {
957       $caption .= td {align => 'right'}, img {
958         src      => 'right.png',
959         disabled => 'disabled',
960       };
961     } # unless
962
963   $caption .= end_Tr;
964
965   $caption .= end_table;
966
967   display start_table {cellspacing => 1, width => '98%'};
968
969   display caption $caption;
970
971   display start_Tr;
972     display th {class => 'labelCentered'}, '#';
973     display th {class => 'labelCentered'}, 'Delete';
974     display th {class => 'labelCentered'}, 'Name';
975     display th {class => 'labelCentered'}, 'System';
976     display th {class => 'labelCentered'}, 'Notification';
977     display th {class => 'labelCentered'}, 'Date/Time';
978     display th {class => 'labelCentered'}, 'Runlog';
979     display th {class => 'labelCentered'}, 'Message';
980   display end_Tr;
981
982   display start_Tr;
983     display td {
984       class   => 'filter',
985       align   => 'right',
986       colspan => 2,
987     }, b 'Filter:';
988     display td {
989       class => 'filter'
990     }, _makeAlertlogSelection ('alert', $opts{alert});
991     display td {
992       class => 'filter'
993     }, _makeAlertlogSelection ('system', $opts{system});
994     display td {
995       class => 'filter'
996     }, _makeAlertlogSelection ('notification', $opts{notification});
997     display td {
998       class => 'filter',
999     }, input {
1000       type  => 'submit',
1001       value => 'Update',
1002     };
1003     display end_form;
1004     display td {
1005       class   => 'filter',
1006       align   => 'center',
1007       colspan => 2,
1008     # TODO: Would like to have Clear All Alerts be Clear Alerts and for it to
1009     # clear only the alerts that have been filtered.
1010     }, a {
1011         href => 'deletealertlog.cgi?alertlogid=all'
1012     }, input {
1013       type    => 'button',
1014       value   => 'Clear All Events',
1015       onclick => "return AreYouSure('Are you sure you want to delete all alerts?');",
1016     }; 
1017   display end_Tr;
1018   
1019   my $i = $opts{start};
1020
1021   foreach ($clearadm->FindAlertlog (
1022     $opts{alert},
1023     $opts{system},
1024     $opts{notification},
1025     $opts{start},
1026     $opts{page},
1027     )) {
1028     my %alertlog = setFields 'N/A', %{$_};
1029      
1030     display start_Tr;
1031       my %system = $clearadm->GetSystem ($alertlog{system});
1032     
1033       display td {class => 'dataCentered'}, ++$i;
1034       display td {class => 'dataCentered'}, a {
1035         href => "deletealertlog.cgi?alertlogid=$alertlog{id}"
1036       }, img {
1037         src => 'delete.png',
1038         alt     => 'Delete',
1039         title   => 'Delete',
1040         border  => 0,
1041         onclick => "return AreYouSure ('Are you sure you wish to delete this alertlog entry?');",
1042       };
1043       display td {class => 'data'}, a {
1044         href => "alerts.cgi?alert=$alertlog{alert}"
1045       }, $alertlog{alert};
1046       display td {class => 'data'}, a {
1047         href => "systemdetails.cgi?system=$alertlog{system}"
1048       }, $alertlog{system};
1049       display td {class => 'data'}, a {
1050         href => "notifications.cgi?notification=$alertlog{notification}"
1051       }, $alertlog{notification};
1052       display td {class => 'data'},         $alertlog{timestamp};
1053       display td {class => 'dataCentered'}, a {
1054         href => "runlog.cgi?id=$alertlog{runlog}"
1055       }, $alertlog{runlog};
1056       display td {class => 'data'},         $alertlog{message};
1057     display end_Tr;
1058   } # foreach
1059
1060   display end_form;
1061
1062   display end_table; 
1063   
1064   return;
1065 } # displayAlertlog
1066
1067 sub displayFilesystem ($) {
1068   my ($systemName) = @_;
1069
1070   display start_table {cellspacing => 1, width => '98%'};
1071   
1072   display start_Tr;
1073     display th {class => 'labelCentered'}, 'Action';
1074     display th {class => 'labelCentered'}, 'Name';
1075     display th {class => 'labelCentered'}, 'Alias';
1076     display th {class => 'labelCentered'}, 'Admin';
1077     display th {class => 'labelCentered'}, 'Filesystem';
1078     display th {class => 'labelCentered'}, 'Mount';
1079     display th {class => 'labelCentered'}, 'Type';
1080     display th {class => 'labelCentered'}, 'History';
1081     display th {class => 'labelCentered'}, 'Used';
1082     display th {class => 'labelCentered'}, 'Threshold';
1083     display th {class => 'labelCentered'}, 'Usage';
1084   display end_Tr;
1085   
1086   foreach ($clearadm->FindSystem ($systemName)) {
1087     my %system = %{$_};
1088   
1089     %system = setFields ('N/A', %system);
1090
1091     my $admin = ($system{email} !~ 'N/A')
1092               ? a {-href => "mailto:$system{email}"}, $system{admin}
1093               : $system{admin};
1094               
1095     foreach ($clearadm->FindFilesystem ($system{name})) {
1096       my %filesystem = %{$_};
1097
1098       my %fs = $clearadm->GetLatestFS ($system{name}, $filesystem{filesystem});
1099
1100       my $size = autoScale $fs{size};
1101       my $used = autoScale $fs{used};
1102       my $free = autoScale $fs{free};
1103
1104       # TODO: Note that this percentages does not agree with df output. I'm not 
1105       # sure why.
1106       my $usedPct = $fs{size} == 0 ? 0 
1107                   : sprintf ('%.0f',
1108                      (($fs{reserve} + $fs{used}) / $fs{size} * 100));
1109
1110       my $alias = ($system{alias} !~ 'N/A')
1111                 ? a {
1112                     href => "systemdetails.cgi?system=$system{name}"
1113                   }, $system{alias}
1114                 : $system{alias};
1115                   
1116       my $class         = $usedPct < $filesystem{threshold} 
1117                         ? 'data'
1118                         : 'dataAlert';
1119       my $classRight    = $usedPct < $filesystem{threshold} 
1120                         ? 'dataRight'
1121                         : 'dataRightAlert';
1122       my $classCentered = $usedPct < $filesystem{threshold} 
1123                         ? 'dataCentered'
1124                         : 'dataCenteredAlert';
1125       my $classRightTop = $usedPct < $filesystem{threshold}
1126                         ? 'dataRightTop'
1127                         : 'dataRightAlertTop'; 
1128
1129       display start_Tr;
1130         display start_td {class => 'dataCentered'};
1131
1132         my $areYouSure = 'Are you sure you want to delete '
1133                        . "$system{name}:$filesystem{filesystem}?" . '\n'
1134                        . 'Doing so will remove all records related to this\n'
1135                        . 'filesystem and its history.';
1136
1137         display start_form {
1138           method => 'post',
1139           action => "processfilesystem.cgi",
1140         };
1141         
1142         display input {
1143           type  => 'hidden',
1144           name  => 'system',
1145           value => $system{name},
1146         };
1147         display input {
1148           type  => 'hidden',
1149           name  => 'filesystem',
1150           value => $filesystem{filesystem},
1151         };
1152         
1153         display input {
1154           name    => 'delete',
1155           type    => 'image',
1156           src     => 'delete.png',
1157           alt     => 'Delete',
1158           value   => 'Delete',
1159           title   => 'Delete',
1160           onclick => "return AreYouSure ('$areYouSure');"
1161         };
1162         display input {
1163           name    => 'edit',
1164           type    => 'image',
1165           src     => 'edit.png',
1166           alt     => 'Edit',
1167           value   => 'Edit',
1168           title   => 'Edit',
1169         };
1170         
1171         if ($filesystem{notification}) {
1172           display a {
1173             href => "alertlog.cgi?system=$filesystem{system}"}, img {
1174             src    => 'alert.png',
1175             border => 0,
1176             alt    => 'Alert!',
1177             title  => 'This filesystem has alerts', 
1178           };
1179         } # if        
1180                 
1181         display end_form;
1182         
1183         display end_td;      
1184         display td {class => $class},
1185           a {-href => "systemdetails.cgi?system=$system{name}"}, $system{name};
1186         display td {class => $class}, $alias;
1187         display td {class => $class}, $admin;
1188         display td {class => $class}, $filesystem{filesystem};
1189         display td {class => $class}, $filesystem{mount};
1190         display td {class => $class}, $filesystem{fstype};
1191         display td {class => $classCentered}, $filesystem{filesystemHist};
1192         display td {class => $classRightTop}, "$used ($usedPct%)<br>", 
1193           font {class => 'unknown'}, "$fs{timestamp}";
1194         display td {class => $classRightTop}, "$filesystem{threshold}%";
1195         display td {class => $class},
1196           a {href => 
1197             "plot.cgi?type=filesystem&system=$system{name}"
1198           . "&filesystem=$filesystem{filesystem}&scaling=Day&points=7"
1199           }, img {
1200             src    => "plotfs.cgi?system=$system{name}"
1201                     . "&filesystem=$filesystem{filesystem}&tiny=1",
1202             border => 0,
1203           };
1204       display end_Tr;
1205     } # foreach
1206   } # foreach
1207
1208   display end_table;
1209   
1210   return;
1211 } # displayFilesystem
1212
1213 sub displayNotification (;$) {
1214   my ($notification) = @_;
1215   
1216   display start_table {cellspacing => 1};
1217
1218   display start_Tr;
1219     display th {class => 'labelCentered'}, 'Actions';
1220     display th {class => 'labelCentered'}, 'Name';
1221     display th {class => 'labelCentered'}, 'Alert';
1222     display th {class => 'labelCentered'}, 'Condition';
1223     display th {class => 'labelCentered'}, 'Not More Than';
1224     display th {class => 'labelCentered'}, 'Category';
1225   display end_Tr;
1226   
1227   foreach ($clearadm->FindNotification ($notification)) {
1228     my %notification= setFields 'N/A', %{$_};
1229   
1230     display start_Tr;
1231     my $areYouSure = "Are you sure you want to delete the $notification{name} "
1232                    . 'notification?';
1233                    
1234     my $actions = start_form {
1235       method => 'post',
1236       action => 'processnotification.cgi',
1237     };
1238
1239     $actions .= input {
1240       name   => 'name',
1241       type   => 'hidden',
1242       value  => $notification{name},
1243     };
1244   
1245     if (InArray $notification{name}, @PREDEFINED_NOTIFICATIONS) {
1246       $actions .= input {
1247         name     => 'delete',
1248         disabled => 'true',
1249         type     => 'image',
1250         src      => 'delete.png',
1251         alt      => 'Delete',
1252         value    => 'Delete',
1253         title    => 'Cannot delete predefined notification',
1254       };     
1255       $actions .= input {
1256         name     => 'edit',
1257         disabled => 'true',
1258         type     => 'image',
1259         src      => 'edit.png',
1260         alt      => 'Edit',
1261         value    => 'Edit',
1262         title    => 'Cannot edit predefined notification',
1263       };
1264     } else {
1265       $actions .= input {
1266         name    => 'delete',
1267         type    => 'image',
1268         src     => 'delete.png',
1269         alt     => 'Delete',
1270         value   => 'Delete',
1271         title   => 'Delete',
1272         onclick => "return AreYouSure ('$areYouSure');",
1273       };
1274       $actions .= input {
1275         name    => 'edit',
1276         type    => 'image',
1277         src     => 'edit.png',
1278         alt     => 'Edit',
1279         value   => 'Edit',
1280         title   => 'Edit',
1281       };
1282     } # if
1283                 
1284     display end_form;     
1285
1286     display td {class => 'dataCentered'}, $actions;
1287     display td {class => 'data'},         $notification{name};
1288     display td {class => 'data'},         a {
1289       href => "alerts.cgi?alert=$notification{alert}"
1290     }, $notification{alert};
1291     display td {class => 'data'},         $notification{cond};
1292     display td {class => 'data'},         $notification{nomorethan};
1293     display td {class => 'data'},
1294       (InArray $notification{name}, @PREDEFINED_NOTIFICATIONS) 
1295       ? 'Predefined'
1296       : 'User Defined';
1297       
1298     display end_Tr;
1299   } # foreach
1300
1301   display end_table;
1302   
1303   display p {class => 'center'}, a {
1304     href => 'processnotification.cgi?action=Add',
1305   }, 'New notification', img {
1306     src    => 'add.png',
1307     border => 0,
1308   };
1309
1310   return;
1311 } # displayNotification
1312
1313 sub displayRunlog (%) {
1314   my (%opts) = @_;
1315   
1316   my $optsChanged;
1317   
1318   unless (($opts{oldtask}   and $opts{task}    or
1319            $opts{oldtask}   eq  $opts{task})   and
1320           ($opts{oldsystem} and $opts{system}  or
1321            $opts{oldsystem} eq  $opts{system}) and
1322           ($opts{oldnot}    and $opts{not}     or
1323            $opts{oldnot}    eq  $opts{not})    and
1324           ($opts{oldstatus} and $opts{status}  or
1325            $opts{oldstatus} eq  $opts{status})) {
1326     $optsChanged = 1;           
1327   } # unless
1328             
1329   my $condition;  
1330
1331   unless ($opts{id}) {
1332     $condition  = "task like '%";
1333     $condition .= $opts{task} ? $opts{task} : '';
1334     $condition .= "%'";
1335     
1336     if ($opts{system}) {
1337       if ($opts{system} eq '<NULL>') {
1338         $condition .= ' and system is null';
1339         undef $opts{system}
1340       } elsif ($opts{system} ne 'All') {
1341         $condition .= " and system like '%$opts{system}%'";;        
1342       } # if
1343     } # if
1344
1345     if (defined $opts{status}) {
1346       $condition .= ' and ';
1347       unless ($opts{not}) {
1348         $condition .= "status=$opts{status}";    
1349       } else {
1350         $condition .= "status<>$opts{status}";
1351       } # unless
1352     } # if
1353   } # unless
1354
1355   my $total = $clearadm->Count ('runlog', $condition);
1356   
1357   $opts{start} = $opts{'nextArrow.x'} ? $opts{next} : $opts{prev};
1358   $opts{start} ||= 0;
1359   $opts{start} = 0
1360     if $optsChanged;
1361     
1362   my $next = $opts{start} + $opts{page} < $total 
1363            ? $opts{start} + $opts{page}
1364            : $opts{start};
1365   my $prev = $opts{start} - $opts{page} >= 0
1366            ? $opts{start} - $opts{page}
1367            : $opts{start};
1368
1369   my $opts  = $opts{'nextArrow.x'} ? $opts{next} + 1 : $opts{prev} + 1;
1370      $opts .= '-';
1371      $opts .= $opts{start} + $opts{page} < $total
1372             ? $opts{start} + $opts{page}
1373             : $total;
1374      $opts .= " of $total";
1375
1376   display start_form {
1377     method => 'post', 
1378     action => 'runlog.cgi'
1379   };
1380
1381   # Hidden fields to pass along
1382   display input {name => 'prev',      type => 'hidden', value => $prev};
1383   display input {name => 'next',      type => 'hidden', value => $next};
1384   display input {name => 'oldtask',   type => 'hidden', value => $opts{task}};
1385   display input {name => 'oldsystem', type => 'hidden', value => $opts{system}};
1386   display input {name => 'oldnot',    type => 'hidden', value => $opts{not}};
1387   display input {name => 'oldstatus', type => 'hidden', value => $opts{status}};
1388
1389   my $caption = start_table {
1390     class       => 'caption',
1391     cellspacing => 1,
1392     width       => '100%',
1393   };
1394
1395   $caption .= start_Tr;
1396
1397   unless ($opts{id}) {
1398     $caption .= td {align => 'left'}, input {
1399       name     => 'prevArrow',
1400       type     => 'image',
1401       src      => 'left.png',
1402       alt      => 'Previous',
1403       value    => 'prev',
1404     };
1405   } else {
1406     $caption .= td {align => 'left'}, img {
1407       src      => 'left.png',
1408       disabled => 'disabled',
1409     };
1410   } # unless
1411   
1412   $caption .= td {align => 'center'}, $opts;
1413
1414   unless ($opts{id}) {
1415     $caption .= td {align => 'right'}, input {
1416       name     => 'nextArrow',
1417       type     => 'image',
1418       src      => 'right.png',
1419       alt      => 'Next',
1420       value    => 'next',
1421     };
1422   } else {
1423     $caption .= td {align => 'right'}, img {
1424       src      => 'right.png',
1425       disabled => 'disabled',
1426     };
1427   } # unless
1428
1429   $caption .= end_Tr;
1430
1431   $caption .= end_table;
1432
1433   display start_table {cellspacing => 1, width => '98%'};
1434
1435   display caption $caption;
1436
1437   display start_Tr;
1438     display th {class => 'labelCentered'}, '#';
1439     display th {class => 'labelCentered'}, 'ID';
1440     display th {class => 'labelCentered'}, 'Task';
1441     display th {class => 'labelCentered'}, 'System';
1442     display th {class => 'labelCentered'}, 'Started';
1443     display th {class => 'labelCentered'}, 'Ended';
1444     display th {class => 'labelCentered'}, 'Status';
1445     display th {class => 'labelCentered'}, 'Message';
1446   display end_Tr;
1447   
1448   display start_Tr;
1449     $opts{not} ||= 'false';
1450
1451     display start_form {
1452       method => 'post', 
1453       action => 'runlog.cgi'
1454     };
1455     display td {
1456       class   => 'filter',
1457       align   => 'right',
1458       colspan => 2,
1459     }, b 'Filter:';
1460     display td {
1461       class => 'filter'
1462     }, _makeRunlogSelection ('task', $opts{task});
1463     display td {
1464       class => 'filter'
1465     }, _makeRunlogSelection ('system', $opts{system});
1466     display td {class => 'filter'}, '&nbsp;';
1467     display td {
1468       class => 'filter',
1469       align => 'right',
1470     }, "Not: ", checkbox {
1471       name    => 'not',
1472       value   => 'true',
1473       checked => $opts{not} eq 'true' ? 1 : 0,
1474       label   => '',
1475     };
1476     display td {
1477       class => 'filter'
1478     }, _makeRunlogSelectionNumeric ('status', $opts{status});
1479     display td {
1480       class => 'filter',
1481     }, input {
1482       type  => 'submit',
1483       value => 'Update',
1484     };
1485     
1486     display end_form;
1487   display end_Tr;
1488
1489   my $i = $opts{start};
1490
1491   my $status;
1492   
1493   if (defined $opts{status}) {
1494     if ($opts{status} !~ /all/i) {
1495       $status = $opts{not} ne 'true' ? $opts{status} : "!$opts{status}";
1496     } # if
1497   } # if
1498   
1499   foreach ($clearadm->FindRunlog (
1500     $opts{task},
1501     $opts{system},
1502     $status,
1503     $opts{id},
1504     $opts{start},
1505     $opts{page},
1506     )) {
1507     my %runlog = setFields 'N/A', %{$_};
1508  
1509     my $class         = $runlog{status} == 0 
1510                       ? 'data'
1511                       : 'dataAlert';
1512     my $classCentered = $runlog{status} == 0
1513                       ? 'dataCentered'
1514                       : 'dataAlertCentered';
1515     my $classRight    = $runlog{status} == 0
1516                       ? 'dataRight'
1517                       : 'dataAlertRight';
1518    
1519     display start_Tr;
1520       display td {class => 'dataCentered'}, ++$i;
1521       display td {class => 'dataCentered'}, $runlog{id};
1522       display td {class => 'data'},         a {
1523         href => "tasks.cgi?task=$runlog{task}"
1524       }, $runlog{task};
1525       display td {class => 'data'}, $runlog{system} eq 'Localhost'
1526         ? $runlog{system}
1527         : a {
1528         href => "systemdetails.cgi?system=$runlog{system}"
1529       }, $runlog{system};
1530       display td {class => 'dataCentered'}, $runlog{started};
1531       display td {class => 'dataCentered'}, $runlog{ended};
1532       display td {class => $classRight},    $runlog{status};
1533      
1534       my $message = $runlog{message};
1535          $message =~ s/\r\n/<br>/g;
1536      
1537       display td {class => $class, width => '50%'},         $message;
1538     display end_Tr;
1539   } # foreach
1540
1541   display end_table;
1542   
1543   return;
1544 } # displayRunlog
1545
1546 sub displaySchedule () {
1547   display start_table {cellspacing => 1};
1548
1549   display start_Tr;
1550     display th {class => 'labelCentered'}, 'Actions';
1551     display th {class => 'labelCentered'}, 'Active';
1552     display th {class => 'labelCentered'}, 'Name';
1553     display th {class => 'labelCentered'}, 'Task';
1554     display th {class => 'labelCentered'}, 'Notification';
1555     display th {class => 'labelCentered'}, 'Frequency';
1556     display th {class => 'labelCentered'}, 'Category';
1557   display end_Tr;
1558   
1559   foreach ($clearadm->FindSchedule) {
1560     my %schedule = setFields 'N/A', %{$_};
1561   
1562     display start_Tr;
1563     my $areYouSure = "Are you sure you want to delete the $schedule{name} "
1564                    . "schedule?";
1565                    
1566     my $actions = start_form {
1567       method => 'post',
1568       action => 'processschedule.cgi',
1569     };
1570
1571     $actions .= input {
1572       name   => 'name',
1573       type   => 'hidden',
1574       value  => $schedule{name},
1575     };
1576   
1577     if (InArray $schedule{name}, @PREDEFINED_SCHEDULES) {
1578       $actions .= input {
1579         name     => 'delete',
1580         disabled => 'true',
1581         type     => 'image',
1582         src      => 'delete.png',
1583         alt      => 'Delete',
1584         value    => 'Delete',
1585         title    => 'Cannot delete predefined schedule',
1586       };     
1587       $actions .= input {
1588         name     => 'edit',
1589         disabled => 'true',
1590         type     => 'image',
1591         src      => 'edit.png',
1592         alt      => 'Edit',
1593         value    => 'Edit',
1594         title    => 'Cannot edit predefined schedule',
1595       };
1596     } else {
1597       $actions .= input {
1598         name    => 'delete',
1599         type    => 'image',
1600         src     => 'delete.png',
1601         alt     => 'Delete',
1602         value   => 'Delete',
1603         title   => 'Delete',
1604         onclick => "return AreYouSure ('$areYouSure');",
1605       };
1606       $actions .= input {
1607         name    => 'edit',
1608         type    => 'image',
1609         src     => 'edit.png',
1610         alt     => 'Edit',
1611         value   => 'Edit',
1612         title   => 'Edit',
1613       };
1614     } # if
1615                 
1616     display end_form; 
1617     
1618     display td {class => 'dataCentered'}, $actions;
1619     display td {class => 'dataCentered'}, checkbox {
1620       disabled => 'disabled',
1621       checked  => $schedule{active} eq 'true' ? 1 : 0,
1622     };
1623     display td {class => 'data'},         $schedule{name};
1624     display td {class => 'data'},         a {
1625       href => "tasks.cgi?task=$schedule{task}"
1626     }, $schedule{task};
1627     display td {class => 'data'},         a {
1628       href => "notifications.cgi?notification=$schedule{notification}"
1629     }, $schedule{notification};
1630     display td {class => 'data'},         $schedule{frequency};
1631     display td {class => 'data'},
1632       (InArray $schedule{name}, @PREDEFINED_SCHEDULES) 
1633         ? 'Predefined' 
1634         : 'User Defined';    
1635       
1636     display end_Tr;
1637   } # foreach
1638
1639   display end_table;
1640   
1641   display p {class => 'center'}, a {
1642     href => 'processschedule.cgi?action=Add',
1643   }, 'New schedule', img {
1644     src    => 'add.png',
1645     border => 0,
1646   };
1647
1648   return;
1649 } # displaySchedule
1650
1651 sub displaySystem ($) {
1652   my ($systemName) = @_;
1653     
1654   my %system = $clearadm->GetSystem ($systemName);
1655   
1656   unless (%system) {
1657     displayError "Nothing known about system $systemName";
1658     return;
1659   } # unless
1660   
1661   my $lastheardfromClass = 'dataCentered';
1662   my $lastheardfromData  = $system{lastheardfrom};
1663   
1664   my %load = $clearadm->GetLatestLoadavg ($systemName);
1665
1666   unless ($clearadm->SystemAlive (%system)) {
1667     $lastheardfromClass = 'dataCenteredAlert';
1668     $lastheardfromData  = a {
1669       href  => "alertlog.cgi?system=$system{name}",
1670       class => 'alert',
1671       title => "Have not heard from $system{name} for a while"
1672     }, $system{lastheardfrom};
1673     $system{notification} = 'Heartbeat';
1674   } # unless
1675
1676   my $admin = ($system{email})
1677             ? a {-href => "mailto:$system{email}"}, $system{admin}
1678             : $system{admin};
1679                     
1680   $system{alias}  = setField $system{alias},  'N/A';
1681   $system{region} = setField $system{region}, 'N/A';
1682
1683   display start_table {cellspacing => 1};
1684   
1685   display start_Tr;
1686     my $areYouSure = 'Are you sure you want to delete this system?\n'
1687                    . "Doing so will remove all records related to $system{name}"
1688                    . '\nincluding filesystem records and history as well as '
1689                    . 'loadavg history.';
1690                    
1691     my $actions = start_form {
1692       method => 'post',
1693       action => 'processsystem.cgi',
1694     };
1695
1696     $actions .= input {
1697       name   => 'name',
1698       type   => 'hidden',
1699       value  => $system{name},
1700     };
1701   
1702     $actions .= input {
1703       name    => 'delete',
1704       type    => 'image',
1705       src     => 'delete.png',
1706       alt     => 'Delete',
1707       value   => 'Delete',
1708       title   => 'Delete',
1709       onclick => "return AreYouSure ('$areYouSure');",
1710     };
1711     $actions .= input {
1712       name    => 'edit',
1713       type    => 'image',
1714       src     => 'edit.png',
1715       alt     => 'Edit',
1716       value   => 'Edit',
1717       title   => 'Edit',
1718     };
1719     $actions .= checkbox {
1720       disabled => 'disabled',
1721       checked  => $system{active} eq 'true' ? 1 : 0,
1722     };    
1723     
1724     if ($system{notification}) {
1725       $actions .= a {
1726         href => "alertlog.cgi?system=$system{name}"}, img {
1727         src    => 'alert.png',
1728         border => 0,
1729         alt    => 'Alert!',
1730         title  => 'This system has alerts', 
1731       };
1732     } # if
1733                 
1734     display th {class => 'label'},                      "$actions Name:";
1735     display end_form;
1736     display td {class => 'dataCentered', colspan => 2}, $system{name};
1737     display th {class => 'label'},                      'Alias:';
1738     display td {class => 'dataCentered'},               $system{alias};
1739     display th {class => 'label'},                      'Admin:';
1740     display td {class => 'dataCentered', colspan => 2}, $admin;
1741     display th {class => 'label', colspan => 2},        'Type:';
1742     display td {class => 'dataCentered'},               $system{type};
1743   display end_Tr;
1744   
1745   display start_Tr;
1746     display th {class => 'label'},               'OS Version:';
1747     display td {class => 'data', colspan => 10}, $system{os}; 
1748   display end_Tr;
1749   
1750   display start_Tr;
1751     display th {class => 'label'}, 'Last Contacted:';
1752     display td {
1753       class => $lastheardfromClass,
1754       colspan => 2
1755     }, "$lastheardfromData ",
1756       font {class => 'dim' }, "<br>Up: $load{uptime}";
1757     display th {class => 'label'},        'Port:';
1758     display td {class => 'dataCentered'}, $system{port};
1759     display th {class => 'label'},        'Threshold:';
1760     display td {class => 'dataCentered'}, $system{loadavgThreshold};
1761     display th {class => 'label'},        'History:';
1762     display td {class => 'dataCentered'}, $system{loadavgHist};
1763     display th {class => 'label'},        'Load Avg:';
1764     display td {class => 'data'},
1765       a {href => 
1766         "plot.cgi?type=loadavg&system=$system{name}&scaling=Hour&points=24"
1767         }, img {
1768           src    => "plotloadavg.cgi?system=$system{name}&tiny=1",
1769           border => 0,
1770       };
1771     
1772   my $description = $system{description};
1773   $description =~ s/\r\n/<br>/g;
1774    
1775   display start_Tr;
1776     display th {class => 'label'},               'Description:';
1777     display td {class => 'data', colSpan => 10}, $description; 
1778   display end_Tr;
1779   
1780   display end_table;
1781   
1782   display p {class => 'center'}, a {
1783     href => 'processsystem.cgi?action=Add',
1784   }, 'New system', img {
1785     src    => 'add.png',
1786     border => 0,
1787   };
1788
1789   display h1 {class => 'center'}, 
1790     'Filesystem Details: ' . ucfirst $system{name};
1791   
1792   display start_table {cellspacing => 1};
1793   
1794   display start_Tr;
1795     display th {class => 'labelCentered'}, 'Action';
1796     display th {class => 'labelCentered'}, 'Filesystem';
1797     display th {class => 'labelCentered'}, 'Type';
1798     display th {class => 'labelCentered'}, 'Mount';
1799     display th {class => 'labelCentered'}, 'Size';
1800     display th {class => 'labelCentered'}, 'Used';
1801     display th {class => 'labelCentered'}, 'Free';
1802     display th {class => 'labelCentered'}, 'Used %';
1803     display th {class => 'labelCentered'}, 'Threshold';
1804     display th {class => 'labelCentered'}, 'History';
1805     display th {class => 'labelCentered'}, 'Usage';
1806   display end_Tr;  
1807   
1808   foreach ($clearadm->FindFilesystem ($system{name})) {
1809     my %filesystem = %{$_};
1810     
1811     my %fs = $clearadm->GetLatestFS (
1812       $filesystem{system}, 
1813       $filesystem{filesystem}
1814     );
1815     
1816     my $size = autoScale $fs{size};
1817     my $used = autoScale $fs{used};
1818     my $free = autoScale $fs{free};  
1819
1820     # TODO: Note that this percentages does not agree with df output. I'm not 
1821     # sure why.
1822     my $usedPct = $fs{size} == 0 ? 0 
1823                 : sprintf ('%.0f',
1824                    (($fs{reserve} + $fs{used}) / $fs{size} * 100));
1825     
1826     my $class         = $usedPct < $filesystem{threshold} 
1827                       ? 'data'
1828                       : 'dataAlert';
1829     my $classCentered = $class . 'Centered';
1830     my $classRight    = $class . 'Right';
1831     
1832     display start_Tr;
1833         display start_td {class => 'data'};
1834
1835         my $areYouSure = 'Are you sure you want to delete '
1836                        . "$system{name}:$filesystem{filesystem}?" . '\n'
1837                        . 'Doing so will remove all records related to this\n'
1838                        . 'filesystem and its history.';
1839
1840         display start_form {
1841           method => 'post',
1842           action => 'processfilesystem.cgi',
1843         };
1844         
1845         display input {
1846           type  => 'hidden',
1847           name  => 'system',
1848           value => $system{name},
1849         };
1850         display input {
1851           type  => 'hidden',
1852           name  => 'filesystem',
1853           value => $filesystem{filesystem},
1854         };
1855         
1856         display input {
1857           name    => 'delete',
1858           type    => 'image',
1859           src     => 'delete.png',
1860           alt     => 'Delete',
1861           value   => 'Delete',
1862           title   => 'Delete',
1863           onclick => "return AreYouSure ('$areYouSure');"
1864         };
1865         display input {
1866           name    => 'edit',
1867           type    => 'image',
1868           src     => 'edit.png',
1869           alt     => 'Edit',
1870           value   => 'Edit',
1871           title   => 'Edit',
1872         };
1873         
1874         if ($filesystem{notification}) {
1875           display a {
1876             href => "alertlog.cgi?system=$filesystem{system}"}, img {
1877             src    => 'alert.png',
1878             border => 0,
1879             alt    => 'Alert!',
1880             title  => 'This filesystem has alerts', 
1881           };
1882         } # if        
1883
1884         display end_form;    
1885       display td {class => $class},         $filesystem{filesystem};
1886       display td {class => $classCentered}, $filesystem{fstype};
1887       display td {class => $class},         $filesystem{mount};
1888       display td {class => $classRight},    $size;
1889       display td {class => $classRight},    $used;
1890       display td {class => $classRight},    $free;
1891       display td {class => $classRight},    "$usedPct%";
1892       display td {class => $classRight},    "$filesystem{threshold}%";
1893       display td {class => $classCentered}, $filesystem{filesystemHist};
1894       display td {class => $classCentered},        
1895         a {href => 
1896           "plot.cgi?type=filesystem&system=$system{name}"
1897         . "&filesystem=$filesystem{filesystem}"
1898         . "&scaling=Day&points=7"
1899         }, img {
1900            src    => "plotfs.cgi?system=$system{name}&"
1901                    . "filesystem=$filesystem{filesystem}"
1902                    . '&tiny=1',
1903            border => 0,
1904         };
1905     display end_Tr;
1906   } # foreach
1907
1908   display end_table;
1909   
1910   return;
1911 } # displaySystem
1912
1913 sub displayTask (;$) {
1914   my ($task) = @_;
1915   
1916   display start_table {cellspacing => 1, width => '98%'};
1917
1918   display start_Tr;
1919     display th {class => 'labelCentered'}, 'Actions';
1920     display th {class => 'labelCentered'}, 'Name';
1921     display th {class => 'labelCentered'}, 'System';
1922     display th {class => 'labelCentered'}, 'Description';
1923     display th {class => 'labelCentered'}, 'Command';
1924     display th {class => 'labelCentered'}, 'Restartable';
1925     display th {class => 'labelCentered'}, 'Category';
1926   display end_Tr;
1927   
1928   foreach ($clearadm->FindTask ($task)) {
1929     my %task = %{$_};
1930     
1931     $task{system} = 'All Systems'
1932       unless $task{system};
1933    
1934     display start_Tr;
1935       my $areYouSure = "Are you sure you want to delete the $task{name} task?";
1936                    
1937       my $actions = start_form {
1938         method => 'post',
1939         action => 'processtask.cgi',
1940       };
1941
1942       $actions .= input {
1943         name   => 'name',
1944         type   => 'hidden',
1945         value  => $task{name},
1946       };
1947
1948       if (InArray $task{name}, @PREDEFINED_TASKS) {
1949         $actions .= input {
1950           name     => 'delete',
1951           disabled => 'true',
1952           type     => 'image',
1953           src      => 'delete.png',
1954           alt      => 'Delete',
1955           value    => 'Delete',
1956           title    => 'Cannot delete predefined task',
1957         };     
1958         $actions .= input {
1959           name     => 'edit',
1960           disabled => 'true',
1961           type     => 'image',
1962           src      => 'edit.png',
1963           alt      => 'Edit',
1964           value    => 'Edit',
1965           title    => 'Cannot edit predefined task',
1966         };
1967       } else {
1968         $actions .= input {
1969           name    => 'delete',
1970           type    => 'image',
1971           src     => 'delete.png',
1972           alt     => 'Delete',
1973           value   => 'Delete',
1974           title   => 'Delete',
1975           onclick => "return AreYouSure ('$areYouSure');",
1976         };
1977         $actions .= input {
1978           name    => 'edit',
1979           type    => 'image',
1980           src     => 'edit.png',
1981           alt     => 'Edit',
1982           value   => 'Edit',
1983           title   => 'Edit',
1984         };
1985       } # if
1986
1987       display end_form;     
1988
1989       display td {class => 'dataCentered'}, $actions;
1990       display td {class => 'data'},         $task{name};
1991       display td {class => 'data'},         $task{system};      
1992       display td {class => 'data'},         $task{description};
1993       display td {class => 'data'},         $task{command};
1994       display td {class => 'dataCentered'}, $task{restartable};
1995       display td {class => 'data'},         
1996         (InArray $task{name}, @PREDEFINED_TASKS) ? 'Predefined' : 'User Defined';
1997     display end_Tr;
1998   } # foreach
1999
2000   display end_table; 
2001   
2002   display p {class => 'center'}, a {
2003     href => 'processtask.cgi?action=Add',
2004   }, 'New task', img {
2005     src    => 'add.png',
2006     border => 0,
2007   };
2008   
2009   return;
2010 } # DisplayAlerts
2011
2012 sub editAlert (;$) {
2013   my ($alert) = @_;
2014   
2015   display start_form (
2016     -method   => 'post',
2017     -action   => 'processalert.cgi',
2018     -onsubmit => 'return validateAlert (this);',
2019   );
2020
2021   my %alert;
2022
2023   if ($alert) {
2024     %alert = $clearadm->GetAlert ($alert);
2025   
2026     return
2027       unless %alert;      
2028       
2029     display input {
2030       name  => 'oldname',
2031       type  => 'hidden',
2032       value => $alert,
2033     };
2034   } else {
2035     $alert= '';
2036   } # if
2037   
2038   display input {
2039     name  => 'action',
2040     type  => 'hidden',
2041     value => 'Post',
2042   };
2043   
2044   display start_table {cellspacing => 1};
2045   
2046   display start_Tr;
2047     display th {class => 'labelCentered'}, 'Name';
2048     display th {class => 'labelCentered'}, 'Type';
2049     display th {class => 'labelCentered'}, 'Who';
2050   display end_Tr;
2051   
2052   display start_Tr;
2053     display td {
2054       class => 'data',
2055     }, input {
2056       class     => 'inputfield',
2057       maxlength => 255,
2058       name      => 'name',
2059       size      => 20,
2060       type      => 'text',
2061       value     => $alert ? $alert{name} : '',
2062     };
2063     display td {
2064       class => 'dataCentered',
2065     }, popup_menu {
2066       name    => 'type',
2067       class   => 'dropdown',
2068       values  => [ 'email', 'page', 'im' ],
2069       default => $alert ? $alert{type} : 'email',
2070     };
2071     display td {
2072       class => 'data',
2073     }, input {
2074       class     => 'inputfield',
2075       maxlength => 255,
2076       name      => 'who',
2077       size      => 20,
2078       type      => 'text',
2079       value     => $alert ? $alert{who} : '',
2080     };
2081   display end_Tr;
2082   display end_table;
2083   
2084   display '<center>';
2085   display p submit ({value => $alert ? 'Update' : 'Add'}),  reset;
2086   display '</center>';
2087   
2088   display end_form;
2089   
2090   return;
2091 } # editAlert
2092
2093 sub editFilesystem ($$) {
2094   my ($system, $filesystem) = @_;
2095   
2096   display start_form (
2097     -method => 'post',
2098     -action => 'processfilesystem.cgi',
2099   );
2100
2101   display start_table {width => '800px', cellspacing => 1};
2102   
2103   display start_Tr;
2104     display th {class => 'labelCentered'}, 'Filesystem';
2105     display th {class => 'labelCentered'}, 'Type';
2106     display th {class => 'labelCentered'}, 'Mount';
2107     display th {class => 'labelCentered'}, 'Size';
2108     display th {class => 'labelCentered'}, 'Used';
2109     display th {class => 'labelCentered'}, 'Free';
2110     display th {class => 'labelCentered'}, 'Used %';
2111     display th {class => 'labelCentered'}, 'History';
2112     display th {class => 'labelCentered'}, 'Threshold';
2113   display end_Tr;  
2114   
2115   my %filesystem = $clearadm->GetFilesystem ($system, $filesystem);
2116   my %fs         = $clearadm->GetLatestFS   ($system, $filesystem);
2117   
2118   display input {
2119     name  => 'action',
2120     type  => 'hidden',
2121     value => 'Post',
2122   };
2123   display input {
2124     name  => 'system',
2125     type  => 'hidden',
2126     value => $filesystem{system},
2127   };  
2128   display input {
2129     name  => 'filesystem',
2130     type  => 'hidden',
2131     value => $filesystem{filesystem},
2132   } ; 
2133   
2134   my $size = autoScale $fs{size};
2135   my $used = autoScale $fs{used};
2136   my $free = autoScale $fs{free};
2137
2138   display start_Tr;
2139     display td {class => 'data'},         $filesystem{filesystem};
2140     display td {class => 'dataCentered'}, $filesystem{fstype};
2141     display td {class => 'data'},         $filesystem{mount};
2142     display td {class => 'dataRight'},    $size;
2143     display td {class => 'dataRight'},    $used;
2144     display td {class => 'dataRight'},    $free;
2145     # TODO: Note that this percentages does not agree with df output. I'm not 
2146     # sure why.
2147     display td {class => 'dataCentered'},
2148       sprintf ('%.0f%%', (($fs{reserve} + $fs{used}) / $fs{size} * 100));
2149       
2150     my $historyDropdown = popup_menu {
2151       name    => 'filesystemHist',
2152       class   => 'dropdown',
2153       values  => [
2154         '1 month',
2155         '2 months',
2156         '3 months',
2157         '4 months',
2158         '5 months',
2159         '6 months',
2160         '7 months',
2161         '8 months',
2162         '9 months',
2163         '10 months',
2164         '11 months',
2165         '1 year',
2166       ],
2167       default => $system ? $filesystem{filesystemHist} : '6 months',
2168     };
2169         
2170     display td {
2171       class => 'dataRight',
2172     }, $historyDropdown; 
2173   
2174     my $thresholdDropdown = popup_menu {
2175       name    => 'threshold',
2176       class   => 'dropdown',
2177       values  => [1 .. 100],
2178       default => $filesystem{threshold},
2179     };        
2180     display td {class => 'dataCentered'}, $thresholdDropdown . '%';
2181   display end_Tr;
2182   
2183   display end_table; 
2184   
2185   display '<center>';
2186   display p submit ({value => 'Update'}),  reset;
2187   display '</center>';
2188   
2189   display end_form;
2190   
2191   return;
2192 } # editFilesytem
2193
2194 sub editNotification (;$) {
2195   my ($notification) = @_;
2196   
2197   display start_form (
2198     -method   => 'post',
2199     -action   => 'processnotification.cgi',
2200     -onsubmit => 'return validateNotification (this);',
2201   );
2202
2203   my %notification;
2204
2205   if ($notification) {
2206     %notification = $clearadm->GetNotification ($notification);
2207   
2208     return
2209       unless %notification;      
2210       
2211     display input {
2212       name  => 'oldname',
2213       type  => 'hidden',
2214       value => $notification,
2215     };
2216   } else {
2217     $notification = '';
2218   } # if
2219   
2220   display input {
2221     name  => 'action',
2222     type  => 'hidden',
2223     value => 'Post',
2224   };
2225   
2226   display start_table {cellspacing => 1};
2227   
2228   display start_Tr;
2229     display th {class => 'labelCentered'}, 'Name';
2230     display th {class => 'labelCentered'}, 'Alert';
2231     display th {class => 'labelCentered'}, 'Condition';
2232     display th {class => 'labelCentered'}, 'Not More Than';
2233   display end_Tr;
2234   
2235   display start_Tr;
2236     display td {
2237       class => 'data',
2238     }, input {
2239       class     => 'inputfield',
2240       maxlength => 255,
2241       name      => 'name',
2242       size      => 20,
2243       type      => 'text',
2244       value     => $notification ? $notification{name} : '',
2245     };
2246     
2247     display td {
2248       class => 'dataCentered',
2249     }, makeAlertDropdown undef, $notification{alert} 
2250        ? $notification{alert}
2251        : 'Email admin';
2252     
2253     display td {
2254       class => 'data',
2255     }, input {
2256       class     => 'inputfield',
2257       maxlength => 255,
2258       name      => 'cond',
2259       size      => 20,
2260       type      => 'text',
2261       value     => $notification ? $notification{cond} : '',
2262     };
2263     display td {
2264       class => 'dataCentered',
2265     }, makeNoMoreThanDropdown undef, $notification{nomorethan};
2266     
2267   display end_Tr;
2268   display end_table;
2269   
2270   display '<center>';
2271   display p submit ({value => $notification ? 'Update' : 'Add'}),  reset;
2272   display '</center>';
2273   
2274   display end_form;
2275   
2276   return;
2277 } # editNotification
2278
2279 sub editSchedule (;$) {
2280   my ($schedule) = @_;
2281   
2282   display start_form (
2283     -method   => 'post',
2284     -action   => 'processschedule.cgi',
2285     -onsubmit => 'return validateSchedule (this);',
2286   );
2287
2288   my %schedule;
2289
2290   if ($schedule) {
2291     %schedule = $clearadm->GetSchedule ($schedule);
2292   
2293     return
2294       unless %schedule;      
2295       
2296     display input {
2297       name  => 'oldname',
2298       type  => 'hidden',
2299       value => $schedule,
2300     };
2301   } else {
2302     $schedule = '';
2303   } # if
2304   
2305   display input {
2306     name  => 'action',
2307     type  => 'hidden',
2308     value => 'Post',
2309   };
2310   
2311   display start_table {cellspacing => 1};
2312   
2313   display start_Tr;
2314     display th {class => 'labelCentered'}, 'Active';
2315     display th {class => 'labelCentered'}, 'Name';
2316     display th {class => 'labelCentered'}, 'Task';
2317     display th {class => 'labelCentered'}, 'Notification';
2318     display th {class => 'labelCentered'}, 'Frequency';
2319   display end_Tr;
2320   
2321   display start_Tr;
2322     display td {
2323       class => 'dataCentered',
2324     }, checkbox {
2325       name    => 'active',
2326       value   => 'true',
2327       checked => $schedule{active} eq 'false' ? 0 : 1,
2328       label   => '',
2329     };
2330     display td {
2331       class => 'data',
2332     }, input {
2333       class     => 'inputfield',
2334       maxlength => 255,
2335       name      => 'name',
2336       size      => 20,
2337       type      => 'text',
2338       value     => $schedule ? $schedule{name} : '',
2339     };
2340     display td {
2341       class => 'dataCentered',
2342     }, makeTaskDropdown undef, $schedule{task}; 
2343     display td {
2344       class => 'dataCentered',
2345     }, makeNotificationDropdown undef, $schedule{notification}; 
2346     
2347     my $nbr        = 5;
2348     my $multiplier = 'minutes';
2349     
2350     if ($schedule{frequency} =~ /(\d+)\s(\S+)/ ) {
2351       $nbr        = $1;
2352       $multiplier = $2;
2353       
2354       $multiplier .= 's' if $nbr == 1;
2355     } # if
2356         
2357     display td {
2358       class => 'data',
2359     }, input {
2360       class     => 'inputfieldRight',
2361       maxlength => 3,
2362       name      => 'nbr',
2363       size      => 1,
2364       type      => 'text',
2365       value     => $nbr,
2366     }, 
2367       ' ',
2368       makeMultiplierDropdown undef, $multiplier;
2369     
2370   display end_Tr;
2371   display end_table;
2372   
2373   display '<center>';
2374   display p submit ({value => $schedule ? 'Update' : 'Add'}),  reset;
2375   display '</center>';
2376   
2377   display end_form;
2378   
2379   return;
2380 } # editSchedule
2381
2382 sub editSystem (;$) {
2383   my ($system) = @_;
2384   
2385   display start_form (
2386     -method   => 'post',
2387     -action   => 'processsystem.cgi',
2388     -onsubmit => 'return validateSystem (this);',
2389   );
2390
2391   my %system;
2392   
2393   if ($system) {
2394     %system = $clearadm->GetSystem ($system);
2395   
2396     return
2397       unless %system;
2398       
2399     display input {
2400       name  => 'name',
2401       type  => 'hidden',
2402       value => $system,
2403     };
2404   } else {
2405     $system = '';
2406   } # if
2407   
2408   display input {
2409     name  => 'action',
2410     type  => 'hidden',
2411     value => 'Post',
2412   };
2413   
2414   display start_table {cellspacing => 1};
2415   
2416   display start_Tr;
2417     display th {class => 'label'}, checkbox ({
2418       name    => 'active',
2419       value   => 'true',
2420       checked => $system{active} eq 'false' ? 0 : 1,
2421       label   => '',
2422     }) . ' Name: ';
2423     
2424     if ($system) {
2425       display td {class => 'data'},  $system{name};
2426     } else {
2427       display td {
2428         class => 'data',
2429       }, input {
2430         class     => 'inputfield',
2431         maxlength => 255,
2432         name      => 'name',
2433         size      => 20,
2434         type      => 'text',
2435       };
2436     } # if
2437     
2438     display th {class => 'label'}, 'Alias:';
2439     display td {
2440       class => 'data',
2441     }, input {
2442       class     => 'inputfield',
2443       maxlength => 255,
2444       name      => 'alias',
2445       size      => 20,
2446       type      => 'text',
2447       value     => $system ? $system{alias} : '',
2448     };
2449
2450     display th {class => 'label'}, 'Port:';
2451     display td {
2452       class => 'dataRight',
2453     }, input {
2454       class     => 'inputfieldRight',
2455       maxlength => 6,
2456       name      => 'port',
2457       size      => 4,
2458       type      => 'text',
2459       value     => $system 
2460                  ? $system{port}
2461                  : $Clearadm::CLEAROPTS{CLEARADM_PORT},
2462     };
2463     
2464     my $systemTypeDropdown = popup_menu {
2465       name    => 'type',
2466       class   => 'dropdown',
2467       values  => ['Unix', 'Linux', 'Windows'],
2468       default => $system ? $system{type} : 'Linux',
2469     };
2470     
2471     display th {class => 'label'}, 'Type:';
2472     display td {
2473       class   => 'dataRight',
2474     },  $systemTypeDropdown;
2475   display end_Tr;
2476   
2477   display start_Tr;
2478     display th {class => 'label'}, 'Admin:';
2479     display td {
2480       class => 'data',
2481     }, input {
2482       class     => 'inputfield',
2483       maxlength => 255,
2484       name      => 'admin',
2485       size      => 20,
2486       type      => 'text',
2487       value     => $system ? $system{admin} : '',
2488     };
2489     display th {class => 'label'}, 'Admin Email:';
2490     display td {
2491       class => 'data',
2492     }, input {
2493       class     => 'inputfield',
2494       maxlength => 255,
2495       name      => 'email',
2496       size      => 20,
2497       type      => 'text',
2498       value     => $system ? $system{email} : '',
2499     };
2500
2501     display th {class => 'label'}, 'Threshold:';
2502     display td {
2503       class => 'dataRight',
2504     }, input {
2505       class     => 'inputfieldRight',
2506       maxlength => 5,
2507       name      => 'loadavgThreshold',
2508       size      => 3,
2509       type      => 'text',
2510       value     => $system 
2511                  ? $system{loadavgThreshold}
2512                  : $Clearadm::CLEAROPTS{CLEARADM_LOADAVG_THRESHOLD},
2513     };
2514         
2515     my $historyDropdown = popup_menu {
2516       name    => 'loadavgHist',
2517       class   => 'dropdown',
2518       values  => [
2519         '1 month',
2520         '2 months',
2521         '3 months',
2522         '4 months',
2523         '5 months',
2524         '6 months',
2525         '7 months',
2526         '8 months',
2527         '9 months',
2528         '10 months',
2529         '11 months',
2530         '1 year',
2531       ],
2532       default => $system ? $system{loadavgHist} : '6 months',
2533     };
2534         
2535     display th {class => 'label'}, 'History:';
2536     display td {
2537       class => 'dataRight',
2538     }, $historyDropdown; 
2539     
2540   my $description = $system ? $system{description} : '';
2541      $description =~ s/\r\n/<br>/g;
2542      
2543   display start_Tr;
2544     display th {class => 'label'}, 'Description:';
2545     display td {
2546       class   => 'data',
2547       colspan => 7,
2548     }, textarea {
2549       class   => 'inputfield',
2550       cols    => 103,
2551       name    => 'description',
2552       rows    => 3,
2553       value   => $description,
2554     };
2555   display end_Tr;
2556   display end_table;
2557   
2558   display '<center>';
2559   display p submit ({value => $system ? 'Update' : 'Add'}),  reset;
2560   display '</center>';
2561   
2562   display end_form;
2563   
2564   return;
2565 } # editSystem
2566
2567 sub editTask (;$) {
2568   my ($task) = @_;
2569   
2570   display start_form (
2571     -method   => 'post',
2572     -action   => 'processtask.cgi',
2573     -onsubmit => 'return validateTask (this);',
2574   );
2575
2576   my %task;
2577
2578   if ($task) {
2579     %task = $clearadm->GetTask ($task);
2580   
2581     return
2582       unless %task;
2583       
2584     display input {
2585       name  => 'oldname',
2586       type  => 'hidden',
2587       value => $task,
2588     };
2589   } else {
2590     $task = '';
2591   } # if
2592   
2593   display input {
2594     name  => 'action',
2595     type  => 'hidden',
2596     value => 'Post',
2597   };
2598   
2599   display start_table {cellspacing => 1};
2600   
2601   display start_Tr;
2602     display th {class => 'labelCentered'}, 'Name';
2603     display th {class => 'labelCentered'}, 'System';
2604     display th {class => 'labelCentered'}, 'Description';
2605     display th {class => 'labelCentered'}, 'Command';
2606     display th {class => 'labelCentered'}, 'Restartable';
2607   display end_Tr;
2608   
2609   display start_Tr;
2610     display td {
2611       class => 'data',
2612     }, input {
2613       class     => 'inputfield',
2614       maxlength => 255,
2615       name      => 'name',
2616       size      => 15,
2617       type      => 'text',
2618       value     => $task ? $task{name} : '',
2619     };
2620     my $systemDropdown = makeSystemDropdown (
2621       undef,
2622       $task{system} ? $task{system} : 'All Systems',
2623       undef, (
2624         'All systems' => undef,
2625         'Localhost'   => 'Localhost',
2626       ),
2627     );
2628         
2629     display td {class => 'data'}, $systemDropdown;      
2630
2631     display td {
2632       class => 'data',
2633     }, input {
2634       class     => 'inputfield',
2635       maxlength => 255,
2636       name      => 'description',
2637       size      => 30,
2638       type      => 'text',
2639       value     => $task ? $task{description} : '',
2640     };
2641     
2642     display td {
2643       class => 'data',
2644     }, input {
2645       class     => 'inputfield',
2646       maxlength => 255,
2647       name      => 'command',
2648       size      => 40,
2649       type      => 'text',
2650       value     => $task ? $task{command} : '',
2651     };
2652
2653     display td {
2654       class => 'dataCentered',
2655     }, makeRestartableDropdown undef, $task{restartable};
2656     
2657   display end_Tr;
2658   display end_table;
2659   
2660   display '<center>';
2661   display p submit ({value => $task ? 'Update' : 'Add'}),  reset;
2662   display '</center>';
2663   
2664   display end_form;
2665   
2666   return;
2667 } # editTask
2668
2669 sub footing () {
2670   my $clearscm = a {-href => 'http://clearscm.com'}, 'ClearSCM, Inc.';
2671   
2672   # Figure out which script by using CLEARADM_BASE.
2673   my $script = basename (url {-absolute => 1}); 
2674      $script = 'index.cgi'
2675        if $script eq 'clearadm';
2676
2677   my $scriptFullPath = "$Clearadm::CLEAROPTS{CLEARADM_BASE}/$script";
2678   
2679   my ($year, $mon, $mday, $hour, $min, $sec) = 
2680     ymdhms ((stat ($scriptFullPath))[9]);
2681
2682   my $dateModified = "$mon/$mday/$year @ $hour:$min";
2683   
2684   $script = a {
2685     -href => "http://clearscm.com/php/scm_man.php?file=clearadm/$script"
2686   }, $script;
2687   
2688   display end_div;
2689   
2690   display start_div {-class => 'copyright'};
2691     display "$script: Last modified: $dateModified";
2692     display br "Copyright &copy; $year, $clearscm - All rights reserved";
2693   display end_div;
2694   
2695   print end_html;
2696   
2697   return;
2698 } # footing
2699     
2700 1;
2701
2702 =pod
2703
2704 =head1 CONFIGURATION AND ENVIRONMENT
2705
2706 DEBUG: If set then $debug is set to this level.
2707
2708 VERBOSE: If set then $verbose is set to this level.
2709
2710 TRACE: If set then $trace is set to this level.
2711
2712 =head1 DEPENDENCIES
2713
2714 =head2 Perl Modules
2715
2716 L<Carp>
2717
2718 L<CGI>
2719
2720 L<File::Basename|File::Basename>
2721
2722 L<FindBin>
2723
2724 L<GD>
2725
2726 =head2 ClearSCM Perl Modules
2727
2728 =begin man 
2729
2730  Clearadm
2731  DateUtils
2732  Display
2733  Utils
2734  
2735 =end man
2736
2737 =begin html
2738
2739 <blockquote>
2740 <a href="http://clearscm.com/php/scm_man.php?file=lib/Clearadm.pm">Clearadm</a><br>
2741 <a href="http://clearscm.com/php/scm_man.php?file=lib/DateUtils.pm">DateUtils</a><br>
2742 <a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
2743 <a href="http://clearscm.com/php/scm_man.php?file=lib/Utils.pm">Utils</a><br>
2744 </blockquote>
2745
2746 =end html
2747
2748 =head1 BUGS AND LIMITATIONS
2749
2750 There are no known bugs in this module.
2751
2752 Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
2753
2754 =head1 LICENSE AND COPYRIGHT
2755
2756 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
2757
2758 =cut