Big update of Clearadm
authorAndrew DeFaria <Andrew@DeFaria.com>
Sat, 22 Dec 2018 15:55:07 +0000 (08:55 -0700)
committerAndrew DeFaria <Andrew@DeFaria.com>
Sat, 22 Dec 2018 15:55:07 +0000 (08:55 -0700)
65 files changed:
bin/findsymlinks.sh [new file with mode: 0755]
clearadm/alertlog.cgi
clearadm/alerts.cgi
clearadm/clearadmscrub.pl
clearadm/clearagent.pl
clearadm/clearexec.pl
clearadm/cleartasks.pl
clearadm/deletealertlog.cgi
clearadm/discovery.pl
clearadm/etc/conf.d/clearadm.conf
clearadm/etc/init.d/clearagent [changed from file to symlink]
clearadm/etc/init.d/clearagent.linux [new file with mode: 0755]
clearadm/etc/init.d/clearagent.solaris [new file with mode: 0755]
clearadm/etc/init.d/cleartasks [changed from file to symlink]
clearadm/etc/init.d/cleartasks.linux [new file with mode: 0755]
clearadm/etc/init.d/cleartasks.solaris [new file with mode: 0755]
clearadm/filesystems.cgi
clearadm/getFilesystems.cgi
clearadm/getTimestamp.cgi
clearadm/index.cgi
clearadm/lib/Clearadm.pm
clearadm/lib/ClearadmWeb.pm
clearadm/lib/User.pm
clearadm/lib/clearadm.sql
clearadm/lib/load.sql
clearadm/notifications.cgi
clearadm/plot.cgi
clearadm/plotfs.cgi
clearadm/plotloadavg.cgi
clearadm/plotstorage.cgi [new file with mode: 0755]
clearadm/processalert.cgi
clearadm/processfilesystem.cgi
clearadm/processnotification.cgi
clearadm/processrunning.pl
clearadm/processschedule.cgi
clearadm/processsystem.cgi
clearadm/processtask.cgi
clearadm/readme.cgi
clearadm/runlog.cgi
clearadm/schedule.cgi
clearadm/setup.pl
clearadm/systemdetails.cgi
clearadm/systems.cgi
clearadm/tasks.cgi
clearadm/test.pl
clearadm/updateccfs.pl [new file with mode: 0755]
clearadm/updatefs.pl
clearadm/updatela.pl
clearadm/updatesystem.pl
clearadm/viewager.cgi
clearadm/viewdetails.cgi
clearadm/viewservers.cgi
clearadm/vobdetails.cgi [new file with mode: 0755]
clearadm/vobservers.cgi
lib/Clearcase.pm
lib/Clearcase/Server.pm
lib/Clearcase/View.pm
lib/Clearcase/Vob.pm
lib/Clearcase/Vobs.pm
lib/CmdLine.pm
lib/Utils.pm
rc/bash_login
rc/client_scripts/GD
rc/gitconfig
test/testMDYHMS2SQLDatetime.pl [new file with mode: 0755]

diff --git a/bin/findsymlinks.sh b/bin/findsymlinks.sh
new file mode 100755 (executable)
index 0000000..f5d3a95
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+path=$1
+
+if [ -z "$path" ]; then
+  echo "Usage $0 <path>"
+  exit 1
+fi
+
+IFS='/' read -ra components <<< "$path"
+
+testpath=''
+
+for component in "${components[@]}"; do
+  [ -z "$component" ] && continue
+
+  testpath="${testpath}/$component"
+
+  if [ -h "$testpath" ]; then
+    echo "$testpath: symbolic link to $(ls -l $testpath | awk '{print $NF}')"
+    testpath=$(readlink -n $testpath)
+  fi
+done
index e2c1e45..8269699 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -151,4 +151,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 8bfa1fa..2fb1ede 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -143,4 +143,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 8417622..c88ddac 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -178,4 +178,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 5fae618..fae4519 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -57,6 +57,7 @@ use warnings;
 
 use Getopt::Long;
 use FindBin;
+use Sys::Hostname;
 
 use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
 
@@ -95,7 +96,9 @@ $clearexec = Clearexec->new;
 
 $clearexec->setMultithreaded ($multithreaded);
 
-my $logfile = "$Clearexec::CLEAROPTS{CLEAREXEC_LOGDIR}/$FindBin::Script.log";
+my $logfile  = "$Clearexec::CLEAROPTS{CLEAREXEC_LOGDIR}/$FindBin::Script";
+   $logfile =~ s/\.pl$//;
+   $logfile .= '.' . hostname() . '.log';
 
 EnterDaemonMode $logfile, $logfile, $pidfile
   if $daemon;
index 53963a7..cd593e5 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
index 66c964b..25a297b 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -47,6 +47,9 @@ $Date: 2013/06/02 18:47:26 $
 
 Examine the Clearadm schedule and perform the tasks required.
 
+Note that sending the Cleartasks.pl process a sigusr1 will cause it to toggle
+verbose mode.
+
 =cut
 
 use strict;
@@ -54,6 +57,7 @@ use warnings;
 
 use FindBin;
 use Getopt::Long;
+use Sys::Hostname;
 
 use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
 
@@ -67,7 +71,10 @@ use Utils;
 my $VERSION  = '$Revision: 1.25 $';
   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
 
-my $logfile = "$Clearadm::CLEAROPTS{CLEARADM_LOGDIR}/$FindBin::Script.log";           
+my $logfile =  "$Clearadm::CLEAROPTS{CLEARADM_LOGDIR}/$FindBin::Script";
+   $logfile =~ s/\.pl$//;
+   $logfile .= '.' . hostname() . '.log';
+
 my $pidfile = "$Clearadm::CLEAROPTS{CLEARADM_RUNDIR}/$FindBin::Script.pid";
 my $daemon  = 1;
 
@@ -76,6 +83,18 @@ $ENV{PATH} .= ":$Clearadm::CLEAROPTS{CLEARADM_BASE}";
 
 my ($clearadm, $clearexec);
 
+sub ToggleVerbose() {
+  if (get_verbose) {
+    display 'Turning verbose off';
+    set_verbose 0;
+  } else {
+    display 'Turning verbose on';
+    set_verbose 1;
+  } # if
+} # ToggleVerbose
+
+$SIG{USR1} = \&ToggleVerbose;
+
 sub HandleSystemNotCheckingIn (%) {
   my (%system) = @_;
    
@@ -131,7 +150,7 @@ END
 } # HandleSystemNotCheckingIn
 
 sub SystemsCheckin () {
-  foreach ($clearadm->FindSystem) {
+  for ($clearadm->FindSystem) {
     my %system = %$_;
     
     next if $system{active} eq 'false';
@@ -163,7 +182,7 @@ sub SystemsCheckin () {
   
     $clearadm->ClearNotifications ($system{name})
       if $system{notification} and $system{notification} eq 'Heartbeat';
-  } # foreach
+  } # for
   
   return;
 } # SystemsCheckin
@@ -225,7 +244,7 @@ sub ProcessLoadavgErrors ($$$$@) {
   
   my $when = Today2SQLDatetime;
   
-  foreach (@output) {
+  for (@output) {
     # We need to log this output. Write it to STDOUT
     display $_;
 
@@ -285,7 +304,7 @@ END
       undef,
       $lastid,
     );
-  } # foreach
+  } # for
   
   return;
 } # ProcessLoadAvgErrors
@@ -300,7 +319,7 @@ sub ProcessFilesystemErrors ($$$$@) {
 
   my %system;
   
-  foreach (@output) {
+  for (@output) {
     # We need to log this output. Write it to STDOUT
     display $_;
     
@@ -317,9 +336,9 @@ sub ProcessFilesystemErrors ($$$$@) {
         $system{$1} = \%fsinfo;
       } # if
     } # if
-  } # foreach
+  } # for
    
-  foreach my $systemName (keys %system) {
+  for my $systemName (keys %system) {
     my @fsinfo;
     
     if (ref $system{$systemName} eq 'HASH') {
@@ -340,7 +359,7 @@ were over their threshold.</p>
 
 <ul>
 END
-    foreach (@fsinfo) {
+    for (@fsinfo) {
       my %fsinfo = %{$_};
       my $filesystemLink  = $Clearadm::CLEAROPTS{CLEARADM_WEBBASE};
          $filesystemLink .= "/plot.cgi?type=filesystem&system=$systemName";
@@ -349,7 +368,7 @@ END
       $message .= "<li>Filesystem <a href=\"$filesystemLink\">";
       $message .= "$fsinfo{filesystem}</a> is $fsinfo{usedPct}% full. Threshold is ";
       $message .= "$fsinfo{threshold}%</li>";
-    } # foreach
+    } # for
       
     $message .= "</ul>";
     
@@ -362,7 +381,7 @@ END
       undef,
       $lastid,
     );
-  } # foreach
+  } # for
   
   return;
 } # ProcessFilesystemErrors
@@ -518,26 +537,28 @@ while () {
   
   my ($sleep, @workItems) = $clearadm->GetWork;
   
-  foreach (@workItems) {
+  for (@workItems) {
     my %scheduledTask = %{$_};
     
     $scheduledTask{system} ||= 'All systems';
     
     if ($scheduledTask{system} =~ /all systems/i) {
-      foreach my $system ($clearadm->FindSystem) {
+      for my $system ($clearadm->FindSystem) {
+        next if $$system{active} eq 'false';
+
         $scheduledTask{system} = $$system{name};
         $sleep = ExecuteTask $sleep, %scheduledTask;
-      } # foreach
+      } # for
     } else {
       $sleep = ExecuteTask $sleep, %scheduledTask;
     } # if
-  } # foreach  
+  } # for  
   
   if ($sleep > 0) {
     verbose "Sleeping for $sleep seconds";
     sleep $sleep;
   } # if  
-} # foreach
+} # for
 
 =pod
 
index e16d4a3..af79c21 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -156,4 +156,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index af0b789..49b4b3f 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -41,7 +41,7 @@ $Date: 2011/01/07 20:48:22 $
    
    -broadcastA|ddr <ip>:      Broadcast IP (Default: Current subnet)
    -broadcastT|ime <seconds>: Number of sends to wait for responses to broadcast
-                              (Default: 30 seconds)
+                              (Default: 10 seconds)
 
 =head1 DESCRIPTION
 
@@ -62,6 +62,7 @@ use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
 
 use Clearadm;
 use Display;
+use OSDep;
 use Utils;
 
 my $VERSION  = '$Revision: 1.1 $';
@@ -81,14 +82,18 @@ sub discover ($) {
   verbose "Performing discovery (for $broadcastTime seconds)...";
 
   while (<$broadcast>) {
-    if (/from (.*):/) {
-      my $ip       = $1;
-      my $hostname = gethostbyaddr (inet_aton ($ip), AF_INET);
-     
-       unless ($hosts{$ip}) {
-         verbose "Received response from ($ip): $hostname";
-         $hosts{$ip} = $hostname;
-       } # unless
+    display "Received line: $_";
+    if (/from (\S+) \((.+)\)/) {
+      my $hostname = $1;
+      my $ip       = $2;
+
+      # Remove domain
+      $hostname =~ s/(\w+)\..*/$1/;
+
+      unless ($hosts{$ip}) {
+        verbose "Received response from ($ip): $hostname";
+        $hosts{$ip} = $hostname;
+      } # unless
     } # if
   
     last
@@ -117,8 +122,16 @@ Usage 'Extraneous options: ' . join ' ', @ARGV
 # Announce ourselves
 verbose "$FindBin::Script V$VERSION";
 
-my $broadcastCmd = "ping -b $broadcastAddress 2>&1";
+my $broadcastCmd = 'ping ';
 
+if ($ARCHITECTURE eq 'solaris') {
+  $broadcastCmd .= '-s ';
+} else {
+  $broadcastCmd .= '-b ';
+} # if
+
+$broadcastCmd .= "$broadcastAddress 2>&1";
+  
 my $pid = open my $broadcast, '-|', $broadcastCmd
   or error "Unable to do $broadcastCmd", 1;
 
@@ -196,4 +209,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 38ef606..b1031cf 100644 (file)
@@ -12,6 +12,8 @@
 #
 ###############################################################################
 Alias /clearadm /opt/clearscm/clearadm
+
+DirectoryIndex index.cgi index.html
  
 <Directory "/opt/clearscm/clearadm">
   Options Indexes FollowSymLinks ExecCGI
@@ -19,7 +21,6 @@ Alias /clearadm /opt/clearscm/clearadm
   Order allow,deny
   Allow from all
   Require all granted
-  DirectoryIndex index.cgi index.html
 </Directory>
 
 AddHandler cgi-script .cgi
deleted file mode 100755 (executable)
index 99b5e55fb704b4bb0c20f404d8f97456c17b7af2..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/bin/sh
-### BEGIN INIT INFO
-# Provides:          clearagent
-# Required-Start:    $network
-# Required-Stop:     none
-# Default-Start:     2 3 4 5
-# Default-Stop:      0 1 6
-# Short-Description: Starts the clearagent daemon
-# Description:       Clearagent is part of the Clearadm package by ClearSCM, 
-#                    Inc. It is a daemon that runs in the background and
-#                    responds to requests to run commands on the local system
-#                    and return the results.                    
-### END INIT INFO
-
-# Author: Andrew DeFaria <Andrew@ClearSCM.com>
-#
-# Do NOT "set -e"
-
-# PATH should only include /usr/* if it runs after the mountnfs.sh script
-PATH=/sbin:/usr/sbin:/bin:/usr/bin
-DESC="Clearagent Daemon"
-NAME=clearagent.pl
-DAEMON=/opt/clearscm/clearadm/$NAME
-PIDFILE=/opt/clearscm/clearadm/var/run/$NAME.pid
-DAEMON_ARGS=""
-SCRIPTNAME=/etc/init.d/$NAME
-RUNASUSER="clearagent"
-
-# Exit if the package is not installed
-[ -x "$DAEMON" ] || exit 0
-
-# Read configuration variable file if it is present
-[ -r /etc/default/$NAME ] && . /etc/default/$NAME
-
-# Load the VERBOSE setting and other rcs variables
-. /lib/init/vars.sh
-
-# Define LSB log_* functions.
-# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
-. /lib/lsb/init-functions
-
-#
-# Function that starts the daemon/service
-#
-do_start()
-{
-       # Return
-       #   0 if daemon has been started
-       #   1 if daemon was already running
-       #   2 if daemon could not be started
-       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
-               || return 1
-       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
-               --chuid $RUNASUSER \
-               -- $DAEMON_ARGS \
-               || return 2
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
-       # Return
-       #   0 if daemon has been stopped
-       #   1 if daemon was already stopped
-       #   2 if daemon could not be stopped
-       #   other if a failure occurred
-       start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
-       RETVAL="$?"
-       [ "$RETVAL" = 2 ] && return 2
-       # Wait for children to finish too if this is a daemon that forks
-       # and if the daemon is only ever run from this initscript.
-       # If the above conditions are not satisfied then add some other code
-       # that waits for the process to drop all resources that could be
-       # needed by services started subsequently.  A last resort is to
-       # sleep for some time.
-       start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
-       [ "$?" = 2 ] && return 2
-       # Many daemons don't delete their pidfiles when they exit.
-       rm -f $PIDFILE
-       return "$RETVAL"
-}
-
-#
-# Function that sends a SIGHUP to the daemon/service
-#
-do_reload() {
-       #
-       # If the daemon can reload its configuration without
-       # restarting (for example, when it is sent a SIGHUP),
-       # then implement that here.
-       #
-       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
-       return 0
-}
-
-case "$1" in
-  start)
-       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
-       do_start
-       case "$?" in
-               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
-               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
-       esac
-       ;;
-  stop)
-       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
-       do_stop
-       case "$?" in
-               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
-               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
-       esac
-       ;;
-  status)
-       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
-       ;;
-  #reload|force-reload)
-       #
-       # If do_reload() is not implemented then leave this commented out
-       # and leave 'force-reload' as an alias for 'restart'.
-       #
-       #log_daemon_msg "Reloading $DESC" "$NAME"
-       #do_reload
-       #log_end_msg $?
-       #;;
-  restart|force-reload)
-       #
-       # If the "reload" option is implemented then remove the
-       # 'force-reload' alias
-       #
-       log_daemon_msg "Restarting $DESC" "$NAME"
-       do_stop
-       case "$?" in
-         0|1)
-               do_start
-               case "$?" in
-                       0) log_end_msg 0 ;;
-                       1) log_end_msg 1 ;; # Old process is still running
-                       *) log_end_msg 1 ;; # Failed to start
-               esac
-               ;;
-         *)
-               # Failed to stop
-               log_end_msg 1
-               ;;
-       esac
-       ;;
-  *)
-       #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
-       echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
-       exit 3
-       ;;
-esac
-
-:
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..0f3fa6879091e80fb9e952c1121b4c570884231d
--- /dev/null
@@ -0,0 +1 @@
+clearagent.solaris
\ No newline at end of file
diff --git a/clearadm/etc/init.d/clearagent.linux b/clearadm/etc/init.d/clearagent.linux
new file mode 100755 (executable)
index 0000000..99b5e55
--- /dev/null
@@ -0,0 +1,156 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          clearagent
+# Required-Start:    $network
+# Required-Stop:     none
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Starts the clearagent daemon
+# Description:       Clearagent is part of the Clearadm package by ClearSCM, 
+#                    Inc. It is a daemon that runs in the background and
+#                    responds to requests to run commands on the local system
+#                    and return the results.                    
+### END INIT INFO
+
+# Author: Andrew DeFaria <Andrew@ClearSCM.com>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="Clearagent Daemon"
+NAME=clearagent.pl
+DAEMON=/opt/clearscm/clearadm/$NAME
+PIDFILE=/opt/clearscm/clearadm/var/run/$NAME.pid
+DAEMON_ARGS=""
+SCRIPTNAME=/etc/init.d/$NAME
+RUNASUSER="clearagent"
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcs variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+       # Return
+       #   0 if daemon has been started
+       #   1 if daemon was already running
+       #   2 if daemon could not be started
+       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+               || return 1
+       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
+               --chuid $RUNASUSER \
+               -- $DAEMON_ARGS \
+               || return 2
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+       # Return
+       #   0 if daemon has been stopped
+       #   1 if daemon was already stopped
+       #   2 if daemon could not be stopped
+       #   other if a failure occurred
+       start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+       RETVAL="$?"
+       [ "$RETVAL" = 2 ] && return 2
+       # Wait for children to finish too if this is a daemon that forks
+       # and if the daemon is only ever run from this initscript.
+       # If the above conditions are not satisfied then add some other code
+       # that waits for the process to drop all resources that could be
+       # needed by services started subsequently.  A last resort is to
+       # sleep for some time.
+       start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+       [ "$?" = 2 ] && return 2
+       # Many daemons don't delete their pidfiles when they exit.
+       rm -f $PIDFILE
+       return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+       #
+       # If the daemon can reload its configuration without
+       # restarting (for example, when it is sent a SIGHUP),
+       # then implement that here.
+       #
+       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+       return 0
+}
+
+case "$1" in
+  start)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+       do_start
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  stop)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+       do_stop
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  status)
+       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+       ;;
+  #reload|force-reload)
+       #
+       # If do_reload() is not implemented then leave this commented out
+       # and leave 'force-reload' as an alias for 'restart'.
+       #
+       #log_daemon_msg "Reloading $DESC" "$NAME"
+       #do_reload
+       #log_end_msg $?
+       #;;
+  restart|force-reload)
+       #
+       # If the "reload" option is implemented then remove the
+       # 'force-reload' alias
+       #
+       log_daemon_msg "Restarting $DESC" "$NAME"
+       do_stop
+       case "$?" in
+         0|1)
+               do_start
+               case "$?" in
+                       0) log_end_msg 0 ;;
+                       1) log_end_msg 1 ;; # Old process is still running
+                       *) log_end_msg 1 ;; # Failed to start
+               esac
+               ;;
+         *)
+               # Failed to stop
+               log_end_msg 1
+               ;;
+       esac
+       ;;
+  *)
+       #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+       echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+       exit 3
+       ;;
+esac
+
+:
diff --git a/clearadm/etc/init.d/clearagent.solaris b/clearadm/etc/init.d/clearagent.solaris
new file mode 100755 (executable)
index 0000000..b7c6883
--- /dev/null
@@ -0,0 +1,5 @@
+#/bin/bash
+#
+# Solaris doesn't support init.d scripts and I'm not writting a bona fide
+# SMF service for this
+exec /opt/clearscm/clearadm/clearagent.pl
deleted file mode 100755 (executable)
index ddbb1c23cb8505d2583c9739f6898d25bcc16643..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/bin/sh
-### BEGIN INIT INFO
-# Provides:          cleartasks
-# Required-Start:    $network $mysql
-# Required-Stop:     none
-# Default-Start:     2 3 4 5
-# Default-Stop:      0 1 6
-# Short-Description: Starts the cleartasks daemon
-# Description:       Cleartasks are part of the Clearadm package by ClearSCM, 
-#                    Inc. It is a daemon that runs in the background and 
-#                    performs the various predefined and user defined tasks
-#                    from the Clearadm database
-### END INIT INFO
-
-# Author: Andrew DeFaria <Andrew@ClearSCM.com>
-#
-# Do NOT "set -e"
-
-# PATH should only include /usr/* if it runs after the mountnfs.sh script
-PATH=/sbin:/usr/sbin:/bin:/usr/bin
-DESC="Cleartasks Daemon"
-NAME=cleartasks.pl
-DAEMON=/opt/clearscm/clearadm/$NAME
-PIDFILE=/opt/clearscm/clearadm/var/run/$NAME.pid
-DAEMON_ARGS=""
-SCRIPTNAME=/etc/init.d/$NAME
-RUNASUSER="clearagent"
-
-# Exit if the package is not installed
-[ -x "$DAEMON" ] || exit 0
-
-# Read configuration variable file if it is present
-[ -r /etc/default/$NAME ] && . /etc/default/$NAME
-
-# Load the VERBOSE setting and other rcs variables
-. /lib/init/vars.sh
-
-# Define LSB log_* functions.
-# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
-. /lib/lsb/init-functions
-
-#
-# Function that starts the daemon/service
-#
-do_start()
-{
-       # Return
-       #   0 if daemon has been started
-       #   1 if daemon was already running
-       #   2 if daemon could not be started
-       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
-               || return 1
-       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
-               --chuid $RUNASUSER \
-               -- $DAEMON_ARGS \
-               || return 2
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
-       # Return
-       #   0 if daemon has been stopped
-       #   1 if daemon was already stopped
-       #   2 if daemon could not be stopped
-       #   other if a failure occurred
-       start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
-       RETVAL="$?"
-       [ "$RETVAL" = 2 ] && return 2
-       # Wait for children to finish too if this is a daemon that forks
-       # and if the daemon is only ever run from this initscript.
-       # If the above conditions are not satisfied then add some other code
-       # that waits for the process to drop all resources that could be
-       # needed by services started subsequently.  A last resort is to
-       # sleep for some time.
-       start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
-       [ "$?" = 2 ] && return 2
-       # Many daemons don't delete their pidfiles when they exit.
-       rm -f $PIDFILE
-       return "$RETVAL"
-}
-
-#
-# Function that sends a SIGHUP to the daemon/service
-#
-do_reload() {
-       #
-       # If the daemon can reload its configuration without
-       # restarting (for example, when it is sent a SIGHUP),
-       # then implement that here.
-       #
-       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
-       return 0
-}
-
-case "$1" in
-  start)
-       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
-       do_start
-       case "$?" in
-               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
-               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
-       esac
-       ;;
-  stop)
-       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
-       do_stop
-       case "$?" in
-               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
-               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
-       esac
-       ;;
-  status)
-       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
-       ;;
-  #reload|force-reload)
-       #
-       # If do_reload() is not implemented then leave this commented out
-       # and leave 'force-reload' as an alias for 'restart'.
-       #
-       #log_daemon_msg "Reloading $DESC" "$NAME"
-       #do_reload
-       #log_end_msg $?
-       #;;
-  restart|force-reload)
-       #
-       # If the "reload" option is implemented then remove the
-       # 'force-reload' alias
-       #
-       log_daemon_msg "Restarting $DESC" "$NAME"
-       do_stop
-       case "$?" in
-         0|1)
-               do_start
-               case "$?" in
-                       0) log_end_msg 0 ;;
-                       1) log_end_msg 1 ;; # Old process is still running
-                       *) log_end_msg 1 ;; # Failed to start
-               esac
-               ;;
-         *)
-               # Failed to stop
-               log_end_msg 1
-               ;;
-       esac
-       ;;
-  *)
-       #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
-       echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
-       exit 3
-       ;;
-esac
-
-:
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..904fa9f2d020c699dd7a35f3c135a162be52b1f6
--- /dev/null
@@ -0,0 +1 @@
+cleartasks.solaris
\ No newline at end of file
diff --git a/clearadm/etc/init.d/cleartasks.linux b/clearadm/etc/init.d/cleartasks.linux
new file mode 100755 (executable)
index 0000000..ddbb1c2
--- /dev/null
@@ -0,0 +1,156 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          cleartasks
+# Required-Start:    $network $mysql
+# Required-Stop:     none
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Starts the cleartasks daemon
+# Description:       Cleartasks are part of the Clearadm package by ClearSCM, 
+#                    Inc. It is a daemon that runs in the background and 
+#                    performs the various predefined and user defined tasks
+#                    from the Clearadm database
+### END INIT INFO
+
+# Author: Andrew DeFaria <Andrew@ClearSCM.com>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="Cleartasks Daemon"
+NAME=cleartasks.pl
+DAEMON=/opt/clearscm/clearadm/$NAME
+PIDFILE=/opt/clearscm/clearadm/var/run/$NAME.pid
+DAEMON_ARGS=""
+SCRIPTNAME=/etc/init.d/$NAME
+RUNASUSER="clearagent"
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcs variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+       # Return
+       #   0 if daemon has been started
+       #   1 if daemon was already running
+       #   2 if daemon could not be started
+       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+               || return 1
+       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
+               --chuid $RUNASUSER \
+               -- $DAEMON_ARGS \
+               || return 2
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+       # Return
+       #   0 if daemon has been stopped
+       #   1 if daemon was already stopped
+       #   2 if daemon could not be stopped
+       #   other if a failure occurred
+       start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+       RETVAL="$?"
+       [ "$RETVAL" = 2 ] && return 2
+       # Wait for children to finish too if this is a daemon that forks
+       # and if the daemon is only ever run from this initscript.
+       # If the above conditions are not satisfied then add some other code
+       # that waits for the process to drop all resources that could be
+       # needed by services started subsequently.  A last resort is to
+       # sleep for some time.
+       start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+       [ "$?" = 2 ] && return 2
+       # Many daemons don't delete their pidfiles when they exit.
+       rm -f $PIDFILE
+       return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+       #
+       # If the daemon can reload its configuration without
+       # restarting (for example, when it is sent a SIGHUP),
+       # then implement that here.
+       #
+       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+       return 0
+}
+
+case "$1" in
+  start)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+       do_start
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  stop)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+       do_stop
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  status)
+       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+       ;;
+  #reload|force-reload)
+       #
+       # If do_reload() is not implemented then leave this commented out
+       # and leave 'force-reload' as an alias for 'restart'.
+       #
+       #log_daemon_msg "Reloading $DESC" "$NAME"
+       #do_reload
+       #log_end_msg $?
+       #;;
+  restart|force-reload)
+       #
+       # If the "reload" option is implemented then remove the
+       # 'force-reload' alias
+       #
+       log_daemon_msg "Restarting $DESC" "$NAME"
+       do_stop
+       case "$?" in
+         0|1)
+               do_start
+               case "$?" in
+                       0) log_end_msg 0 ;;
+                       1) log_end_msg 1 ;; # Old process is still running
+                       *) log_end_msg 1 ;; # Failed to start
+               esac
+               ;;
+         *)
+               # Failed to stop
+               log_end_msg 1
+               ;;
+       esac
+       ;;
+  *)
+       #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+       echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+       exit 3
+       ;;
+esac
+
+:
diff --git a/clearadm/etc/init.d/cleartasks.solaris b/clearadm/etc/init.d/cleartasks.solaris
new file mode 100755 (executable)
index 0000000..c9cd40d
--- /dev/null
@@ -0,0 +1,5 @@
+#/bin/bash
+#
+# Solaris doesn't support init.d scripts and I'm not writting a bona fide
+# SMF service for this
+exec /opt/clearscm/clearadm/cleartasks.pl
index a278f3a..b2fa03b 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -151,4 +151,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 88d8084..4a84c87 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -117,4 +117,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 2c4212e..b4878d3 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -165,4 +165,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index a5259ea..4fc9cec 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -49,8 +49,8 @@ use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
 
 use ClearadmWeb;
 use Clearadm;
-#use Clearcase;
-#use Clearcase::Views;
+use Clearcase;
+use Clearcase::Views;
 use Display;
 use Utils;
 
@@ -134,6 +134,8 @@ foreach (@systems) {
   $data .= '</strike>'
     if $system{active} eq 'false';
     
+  $load{uptime} ||= 'Unknown';
+
   display td {class => 'dataCentered'}, "$data ",
     font {class => 'dim' }, "<br>Up: $load{uptime}";
 } # foreach
@@ -203,4 +205,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 719b772..4205e44 100644 (file)
@@ -88,6 +88,7 @@ use Carp;
 use DBI;
 use File::Basename;
 use Net::Domain qw(hostdomain);
+use Sys::Hostname;
 
 use FindBin;
 
@@ -98,9 +99,9 @@ use Display;
 use GetConfig;
 use Mail;
 
-my $conf = dirname (__FILE__) . '/../etc/clearadm.conf';
+my $conf = dirname(__FILE__) . '/../etc/clearadm.conf';
 
-our %CLEAROPTS = GetConfig ($conf);
+our %CLEAROPTS = GetConfig($conf);
 
 # Globals
 our $VERSION  = '$Revision: 1.54 $';
@@ -127,7 +128,7 @@ my $defaultFilesystemHist      = '6 months';
 my $defaultLoadavgHist         = '6 months';
 
 # Internal methods
-sub _dberror ($$) {
+sub _dberror($$) {
   my ($self, $msg, $statement) = @_;
 
   my $dberr    = $self->{db}->err;
@@ -139,7 +140,7 @@ sub _dberror ($$) {
   my $message = '';
 
   if ($dberr) {
-    my $function = (caller (1)) [3];
+    my $function = (caller(1)) [3];
 
     $message = "$function: $msg\nError #$dberr: $dberrmsg\n"
              . "SQL Statement: $statement";
@@ -148,46 +149,46 @@ sub _dberror ($$) {
   return $dberr, $message;
 } # _dberror
 
-sub _formatValues (@) {
+sub _formatValues(@) {
   my ($self, @values) = @_;
 
   my @returnValues;
 
   # Quote data values
-  push @returnValues, $_ eq '' ? 'null' : $self->{db}->quote ($_)
+  push @returnValues, $_ eq '' ? 'null' : $self->{db}->quote($_)
     for (@values);
 
   return @returnValues;
 } # _formatValues
 
-sub _formatNameValues (%) {
+sub _formatNameValues(%) {
   my ($self, %rec) = @_;
 
   my @nameValueStrs;
 
-  push @nameValueStrs, "$_=" . $self->{db}->quote ($rec{$_})
+  push @nameValueStrs, "$_=" . $self->{db}->quote($rec{$_})
     for (keys %rec);
 
   return @nameValueStrs;
 } # _formatNameValues
 
-sub _addRecord ($%) {
+sub _addRecord($%) {
   my ($self, $table, %rec) = @_;
 
   my $statement  = "insert into $table (";
      $statement .= join ',', keys %rec;
      $statement .= ') values (';
-     $statement .= join ',', $self->_formatValues (values %rec);
+     $statement .= join ',', $self->_formatValues(values %rec);
      $statement .= ')';
 
   my ($err, $msg);
 
-  $self->{db}->do ($statement);
+  $self->{db}->do($statement);
 
-  return $self->_dberror ("Unable to add record to $table", $statement);
+  return $self->_dberror("Unable to add record to $table", $statement);
 } # _addRecord
 
-sub _deleteRecord ($;$) {
+sub _deleteRecord($;$) {
   my ($self, $table, $condition) = @_;
 
   my $count;
@@ -196,11 +197,11 @@ sub _deleteRecord ($;$) {
      $statement .= "where $condition"
       if $condition;
 
-  my $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
+  my $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
 
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
+    or return $self->_dberror('Unable to execute statement', $statement);
 
   my @row = $sth->fetchrow_array;
 
@@ -219,29 +220,29 @@ sub _deleteRecord ($;$) {
   $statement .= "where $condition"
     if $condition;
 
-  $self->{db}->do ($statement);
+  $self->{db}->do($statement);
 
   if ($self->{db}->err) {
-    return $self->_dberror ("Unable to delete record from $table", $statement);
+    return $self->_dberror("Unable to delete record from $table", $statement);
   } else {
     return $count, 'Records deleted';
   } # if
 } # _deleteRecord
 
-sub _updateRecord ($$%) {
+sub _updateRecord($$%) {
   my ($self, $table, $condition, %rec) = @_;
 
   my $statement  = "update $table set ";
-     $statement .= join ',', $self->_formatNameValues (%rec);
+     $statement .= join ',', $self->_formatNameValues(%rec);
      $statement .= " where $condition"
        if $condition;
 
-  $self->{db}->do ($statement);
+  $self->{db}->do($statement);
 
-  return $self->_dberror ("Unable to update record in $table", $statement);
+  return $self->_dberror("Unable to update record in $table", $statement);
 } # _updateRecord
 
-sub _checkRequiredFields ($$) {
+sub _checkRequiredFields($$) {
   my ($fields, $rec) = @_;
 
   for my $fieldname (@$fields) {
@@ -261,17 +262,21 @@ sub _checkRequiredFields ($$) {
   return;
 } # _checkRequiredFields
 
-sub _getRecords ($$) {
-  my ($self, $table, $condition) = @_;
+sub _getRecords($$;$) {
+  my ($self, $table, $condition, $additional) = @_;
 
   my ($err, $msg);
 
-  my $statement = "select * from $table where $condition";
+  $additional ||= '';
+
+  my $statement  = "select * from $table";
+     $statement .= " where $condition" if $condition;
+     $statement .= $additional;
 
-  my $sth = $self->{db}->prepare ($statement);
+  my $sth = $self->{db}->prepare($statement);
 
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
 
     croak $msg;
   } # if
@@ -293,7 +298,7 @@ sub _getRecords ($$) {
       $err = 0;
       last;
     } else {
-      ($err, $msg) = $self->_dberror ('Unable to execute statement',
+      ($err, $msg) = $self->_dberror('Unable to execute statement',
                                       $statement);
     } # if
 
@@ -303,16 +308,16 @@ sub _getRecords ($$) {
 
     my $timestamp = YMDHMS;
 
-    $self->Error ("$timestamp: Unable to talk to DB server.\n\n$msg\n\n"
+    $self->Error("$timestamp: Unable to talk to DB server.\n\n$msg\n\n"
                 . "Will try again in $sleepTime seconds", -1);
 
     # Try to reconnect
-    $self->_connect ($self->{dbserver});
+    $self->_connect($self->{dbserver});
 
     sleep $sleepTime;
   } # while
 
-  $self->Error ("After $maxAttempts attempts I could not connect to the database", $err)
+  $self->Error("After $maxAttempts attempts I could not connect to the database", $err)
     if ($err == 2006 and $attempts > $maxAttempts);
 
   my @records;
@@ -322,12 +327,12 @@ sub _getRecords ($$) {
   } # while
 
   return @records;
-} # _getRecord
+} # _getRecords
 
-sub _aliasSystem ($) {
+sub _aliasSystem($) {
   my ($self, $system) = @_;
 
-  my %system = $self->GetSystem ($system);
+  my %system = $self->GetSystem($system);
 
   if ($system{name}) {
     return $system{name};
@@ -336,17 +341,17 @@ sub _aliasSystem ($) {
   } # if
 } # _aliasSystem
 
-sub _getLastID () {
+sub _getLastID() {
   my ($self) = @_;
 
   my $statement = 'select last_insert_id()';
 
-  my $sth = $self->{db}->prepare ($statement);
+  my $sth = $self->{db}->prepare($statement);
 
   my ($err, $msg);
 
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
 
     croak $msg;
   } # if
@@ -354,7 +359,7 @@ sub _getLastID () {
   my $status = $sth->execute;
 
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
 
     croak $msg;
   } # if
@@ -366,7 +371,7 @@ sub _getLastID () {
   return $row[0];
 } # _getLastID
 
-sub _connect (;$) {
+sub _connect(;$) {
   my ($self, $dbserver) = @_;
 
   $dbserver ||= $CLEAROPTS{CLEARADM_SERVER};
@@ -374,12 +379,12 @@ sub _connect (;$) {
   my $dbname   = 'clearadm';
   my $dbdriver = 'mysql';
 
-  $self->{db} = DBI->connect (
+  $self->{db} = DBI->connect(
     "DBI:$dbdriver:$dbname:$dbserver",
     $CLEAROPTS{CLEARADM_USERNAME},
     $CLEAROPTS{CLEARADM_PASSWORD},
     {PrintError => 0},
-  ) or croak (
+  ) or croak(
     "Couldn't connect to $dbname database "
   . "as $CLEAROPTS{CLEARADM_USERNAME}\@$CLEAROPTS{CLEARADM_SERVER}"
   );
@@ -389,17 +394,17 @@ sub _connect (;$) {
   return;
 } # _connect
 
-sub new (;$) {
+sub new(;$) {
   my ($class, $dbserver) = @_;
 
   my $self = bless {}, $class;
 
-  $self->_connect ($dbserver);
+  $self->_connect($dbserver);
 
   return $self;
 } # new
 
-sub SetNotify () {
+sub SetNotify() {
   my ($self) = @_;
 
   $self->{NOTIFY} = $CLEAROPTS{CLEARADM_NOTIFY};
@@ -407,7 +412,7 @@ sub SetNotify () {
   return;
 } # SetNotify
 
-sub Error ($;$) {
+sub Error($;$) {
   my ($self, $msg, $errno) = @_;
 
   # If $errno is specified we need to stop. However we need to notify somebody
@@ -416,7 +421,7 @@ sub Error ($;$) {
 
   if ($errno) {
     if ($self->{NOTIFY}) {
-      mail (
+      mail(
         to      => $self->{NOTIFY},
         subject => 'Internal error occurred in Clearadm',
         data    => "<p>An unexpected, internal error occurred in Clearadm:</p><p>$msg</p>",
@@ -430,7 +435,7 @@ sub Error ($;$) {
   return;
 } # Error
 
-sub AddSystem (%) {
+sub AddSystem(%) {
   my ($self, %system) = @_;
 
   my @requiredFields = (
@@ -444,28 +449,28 @@ sub AddSystem (%) {
 
   $system{loadavgHist} ||= $defaultLoadavgHist;
 
-  return $self->_addRecord ('system', %system);
+  return $self->_addRecord('system', %system);
 } # AddSystem
 
-sub DeleteSystem ($) {
+sub DeleteSystem($) {
   my ($self, $name) = @_;
 
-  return $self->_deleteRecord ('system', "name='$name'");
+  return $self->_deleteRecord('system', "name='$name'");
 } # DeleteSystem
 
 sub UpdateSystem ($%) {
   my ($self, $name, %update) = @_;
 
-  return $self->_updateRecord ('system', "name='$name'", %update);
+  return $self->_updateRecord('system', "name='$name'", %update);
 } # UpdateSystem
 
-sub GetSystem ($) {
+sub GetSystem($) {
   my ($self, $system) = @_;
 
   return
     unless $system;
 
-  my @records = $self->_getRecords (
+  my @records = $self->_getRecords(
     'system',
     "name='$system' or alias like '%$system%'"
   );
@@ -477,25 +482,25 @@ sub GetSystem ($) {
   } # if
 } # GetSystem
 
-sub FindSystem (;$) {
+sub FindSystem(;$) {
   my ($self, $system) = @_;
 
   $system ||= '';
 
   my $condition = "name like '%$system%' or alias like '%$system%'";
 
-  return $self->_getRecords ('system', $condition);
+  return $self->_getRecords('system', $condition);
 } # FindSystem
 
-sub SearchSystem (;$) {\r
+sub SearchSystem(;$) {\r
   my ($self, $condition) = @_;
 
   $condition = "name like '%'" unless $condition;
 
-  return $self->_getRecords ('system', $condition);\r
+  return $self->_getRecords('system', $condition);\r
 } # SearchSystem
 
-sub AddPackage (%) {
+sub AddPackage(%) {
   my ($self, %package) = @_;
 
   my @requiredFields = (
@@ -509,32 +514,32 @@ sub AddPackage (%) {
   return -1, "AddPackage: $result"
     if $result;
 
-  return $self->_addRecord ('package', %package);
+  return $self->_addRecord('package', %package);
 } # AddPackage
 
-sub DeletePackage ($$) {
+sub DeletePackage($$) {
   my ($self, $system, $name) = @_;
 
-  return $self->_deleteRecord (
+  return $self->_deleteRecord(
     'package',
     "(system='$system' or alias='$system') and name='$name'");
 } # DeletePackage
 
-sub UpdatePackage ($$%) {
+sub UpdatePackage($$%) {
   my ($self, $system, $name, %update) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
 
-  return $self->_updateRecord ('package', "system='$system'", %update);
+  return $self->_updateRecord('package', "system='$system'", %update);
 } # UpdatePackage
 
 sub GetPackage($$) {
   my ($self, $system, $name) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
@@ -542,7 +547,7 @@ sub GetPackage($$) {
   return
     unless $name;
 
-  my @records = $self->_getRecords (
+  my @records = $self->_getRecords(
     'package',
     "system='$system' and name='$name'"
   );
@@ -554,22 +559,22 @@ sub GetPackage($$) {
   } # if
 } # GetPackage
 
-sub FindPackage ($;$) {
+sub FindPackage($;$) {
   my ($self, $system, $name) = @_;
 
   $name ||= '';
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
 
   my $condition = "system='$system' and name like '%$name%'";
 
-  return $self->_getRecords ('package', $condition);
+  return $self->_getRecords('package', $condition);
 } # FindPackage
 
-sub AddFilesystem (%) {
+sub AddFilesystem(%) {
   my ($self, %filesystem) = @_;
 
   my @requiredFields = (
@@ -586,42 +591,42 @@ sub AddFilesystem (%) {
   # Default filesystem threshold
   $filesystem{threshold} ||= $defaultFilesystemThreshold;
 
-  return $self->_addRecord ('filesystem', %filesystem);
+  return $self->_addRecord('filesystem', %filesystem);
 } # AddFilesystem
 
-sub DeleteFilesystem ($$) {
+sub DeleteFilesystem($$) {
   my ($self, $system, $filesystem) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
 
-  return $self->_deleteRecord (
+  return $self->_deleteRecord(
     'filesystem',
     "system='$system' and filesystem='$filesystem'"
   );
 } # DeleteFilesystem
 
-sub UpdateFilesystem ($$%) {
+sub UpdateFilesystem($$%) {
   my ($self, $system, $filesystem, %update) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
 
-  return $self->_updateRecord (
+  return $self->_updateRecord(
     'filesystem',
     "system='$system' and filesystem='$filesystem'",
     %update
   );
 } # UpdateFilesystem
 
-sub GetFilesystem ($$) {
+sub GetFilesystem($$) {
   my ($self, $system, $filesystem) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
@@ -629,7 +634,7 @@ sub GetFilesystem ($$) {
   return
     unless $filesystem;
 
-  my @records = $self->_getRecords (
+  my @records = $self->_getRecords(
     'filesystem',
     "system='$system' and filesystem='$filesystem'"
   );
@@ -641,22 +646,22 @@ sub GetFilesystem ($$) {
   } # if
 } # GetFilesystem
 
-sub FindFilesystem ($;$) {
+sub FindFilesystem($;$) {
   my ($self, $system, $filesystem) = @_;
 
   $filesystem ||= '';
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
 
   my $condition = "system='$system' and filesystem like '%$filesystem%'";
 
-  return $self->_getRecords ('filesystem', $condition);
+  return $self->_getRecords('filesystem', $condition);
 } # FindFilesystem
 
-sub AddVob (%) {
+sub AddVob(%) {
   my ($self, %vob) = @_;
 
   my @requiredFields = (
@@ -669,22 +674,22 @@ sub AddVob (%) {
   return -1, "AddVob: $result"
     if $result;
 
-  return $self->_addRecord ('vob', %vob);
+  return $self->_addRecord('vob', %vob);
 } # AddVob
 
-sub DeleteVob ($) {
+sub DeleteVob($) {
   my ($self, $tag) = @_;
 
-  return $self->_deleteRecord ('vob', "tag='$tag'");
+  return $self->_deleteRecord('vob', "tag='$tag'");
 } # DeleteVob
 
-sub GetVob ($) {
+sub GetVob($) {
   my ($self, $tag) = @_;
 
   return
     unless $tag;
 
-  my @records = $self->_getRecords ('vob', "tag='$tag'");
+  my @records = $self->_getRecords('vob', "tag='$tag'");
 
   if ($records[0]) {
     return %{$records[0]};
@@ -693,13 +698,13 @@ sub GetVob ($) {
   } # if
 } # GetVob
 
-sub FindVob ($) {
+sub FindVob($) {
   my ($self, $tag) = @_;
 
-  return $self->_getRecords ('vob', "tag like '%$tag%'");
+  return $self->_getRecords('vob', "tag like '%$tag%'");
 } # FindVob
 
-sub AddView (%) {
+sub AddView(%) {
   my ($self, %view) = @_;
 
   my @requiredFields = (
@@ -712,31 +717,36 @@ sub AddView (%) {
   return -1, "AddView: $result"
     if $result;
 
-  return $self->_addRecord ('view', %view);
+  return $self->_addRecord('view', %view);
 } # AddView
 
-sub DeleteView ($) {
+sub DeleteView($) {
   my ($self, $tag) = @_;
 
-  return $self->_deleteRecord ('vob', "tag='$tag'");
+  return $self->_deleteRecord('vob', "tag='$tag'");
 } # DeleteView
 
-sub GetView ($) {
-  my ($self, $tag) = @_;
+sub UpdateView($$) {
+  my ($self, $tag, $region, %viewRec) = @_;
 
-  return
-    unless $tag;
+  return $self->_updateRecord('view', "tag='$tag' and region='$region'", %viewRec);
+} # UpdateView
+
+sub GetView($$) {
+  my ($self, $tag, $region) = @_;
+
+  return unless $tag;
 
-  my @records = $self->_getRecords ('view', "tag='$tag'");
+  my @records = $self->_getRecords('view', "tag='$tag' and region='$region'");
 
   if ($records[0]) {
     return %{$records[0]};
   } else {
-       return;
+    return;
   } # if
 } # GetView
 
-sub FindView (;$$$$) {
+sub FindView(;$$$$) {
   my ($self, $system, $region, $tag, $ownerName) = @_;
 
   $system    ||= '';
@@ -754,10 +764,10 @@ sub FindView (;$$$$) {
   $condition .= ' and ';
   $condition .= "ownerName like '%$ownerName'";
 
-  return $self->_getRecords ('view', $condition);
+  return $self->_getRecords('view', $condition);
 } # FindView
 
-sub AddFS (%) {
+sub AddFS(%) {
   my ($self, %fs) = @_;
 
   my @requiredFields = (
@@ -773,20 +783,20 @@ sub AddFS (%) {
   # Timestamp record
   $fs{timestamp} = Today2SQLDatetime;
 
-  return $self->_addRecord ('fs', %fs);
+  return $self->_addRecord('fs', %fs);
 } # AddFS
 
-sub TrimFS ($$) {
+sub TrimFS($$) {
   my ($self, $system, $filesystem) = @_;
 
-  my %filesystem = $self->GetFilesystem ($system, $filesystem);
+  my %filesystem = $self->GetFilesystem($system, $filesystem);
 
   return
     unless %filesystem;
 
-  my %task = $self->GetTask ('scrub');
+  my %task = $self->GetTask('scrub');
 
-  $self->Error ("Unable to find scrub task!", 1) unless %task;
+  $self->Error("Unable to find scrub task!", 1) unless %task;
 
   my $days;
   my $today = Today2SQLDatetime;
@@ -801,7 +811,7 @@ sub TrimFS ($$) {
 
   my $oldage = SubtractDays $today, $days;
 
-  my ($dberr, $dbmsg) = $self->_deleteRecord (
+  my ($dberr, $dbmsg) = $self->_deleteRecord(
     'fs',
     "system='$system' and filesystem='$filesystem' and timestamp<='$oldage'"
   );
@@ -818,25 +828,25 @@ sub TrimFS ($$) {
     $runlog{message} =
       "Scrubbed $dberr fs records for filesystem $system:$filesystem";
 
-    my ($err, $msg) = $self->AddRunlog (%runlog);
+    my ($err, $msg) = $self->AddRunlog(%runlog);
 
-    $self->Error ("Unable to add runlog - (Error: $err)\n$msg") if $err;
+    $self->Error("Unable to add runlog - (Error: $err)\n$msg") if $err;
   } # if
 
   return ($dberr, $dbmsg);
 } # TrimFS
 
-sub TrimLoadavg ($) {
+sub TrimLoadavg($) {
   my ($self, $system) = @_;
 
-  my %system = $self->GetSystem ($system);
+  my %system = $self->GetSystem($system);
 
   return
     unless %system;
 
-  my %task = $self->GetTask ('loadavg');
+  my %task = $self->GetTask('loadavg');
 
-  $self->Error ("Unable to find loadavg task!", 1) unless %task;
+  $self->Error("Unable to find loadavg task!", 1) unless %task;
 
   my $days;
   my $today = Today2SQLDatetime;
@@ -851,7 +861,7 @@ sub TrimLoadavg ($) {
 
   my $oldage = SubtractDays $today, $days;
 
-  my ($dberr, $dbmsg) = $self->_deleteRecord (
+  my ($dberr, $dbmsg) = $self->_deleteRecord(
     'loadavg',
     "system='$system' and timestamp<='$oldage'"
   );
@@ -868,18 +878,18 @@ sub TrimLoadavg ($) {
     $runlog{message} =
       "Scrubbed $dberr loadavg records for system $system";
 
-    my ($err, $msg) = $self->AddRunlog (%runlog);
+    my ($err, $msg) = $self->AddRunlog(%runlog);
 
-    $self->Error ("Unable to add runload (Error: $err)\n$msg") if $err;
+    $self->Error("Unable to add runload (Error: $err)\n$msg") if $err;
   } # if
 
   return ($dberr, $dbmsg);
 } # TrimLoadavg
 
-sub GetFS ($$;$$$$) {
+sub GetFS($$;$$$$) {
   my ($self, $system, $filesystem, $start, $end, $count, $interval) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
@@ -912,7 +922,7 @@ sub GetFS ($$;$$$$) {
     # returns 40 rows we'll see only rows 1-10, not rows 31-40). We need limit
     # $offset, $count where $offset = the number of qualifying records minus
     # $count
-    my $nbrRecs = $self->Count ('fs', $condition);
+    my $nbrRecs = $self->Count('fs', $condition);
     my $offset  = $nbrRecs - $count;
 
     # Offsets of < 0 are not allowed.
@@ -939,10 +949,10 @@ END
 
   my ($err, $msg);
 
-  my $sth = $self->{db}->prepare ($statement);
+  my $sth = $self->{db}->prepare($statement);
 
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
 
     croak $msg;
   } # if
@@ -950,7 +960,7 @@ END
   my $status = $sth->execute;
 
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
 
     croak $msg;
   } # if
@@ -964,10 +974,10 @@ END
   return @records;
 } # GetFS
 
-sub GetLatestFS ($$) {
+sub GetLatestFS($$) {
   my ($self, $system, $filesystem) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
@@ -975,7 +985,7 @@ sub GetLatestFS ($$) {
   return
     unless $filesystem;
 
-  my @records = $self->_getRecords (
+  my @records = $self->_getRecords(
     'fs',
     "system='$system' and filesystem='$filesystem'"
   . " order by timestamp desc limit 0, 1",
@@ -988,7 +998,7 @@ sub GetLatestFS ($$) {
   } # if
 } # GetLatestFS
 
-sub AddLoadavg () {
+sub AddLoadavg() {
   my ($self, %loadavg) = @_;
 
   my @requiredFields = (
@@ -1003,13 +1013,13 @@ sub AddLoadavg () {
   # Timestamp record
   $loadavg{timestamp} = Today2SQLDatetime;
 
-  return $self->_addRecord ('loadavg', %loadavg);
+  return $self->_addRecord('loadavg', %loadavg);
 } # AddLoadavg
 
-sub GetLoadavg ($;$$$$) {
+sub GetLoadavg($;$$$$) {
   my ($self, $system, $start, $end, $count, $interval) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
@@ -1041,7 +1051,7 @@ sub GetLoadavg ($;$$$$) {
     # returns 40 rows we'll see only rows 1-10, not rows 31-40). We need limit
     # $offset, $count where $offset = the number of qualifying records minus
     # $count
-    my $nbrRecs = $self->Count ('loadavg', $condition);
+    my $nbrRecs = $self->Count('loadavg', $condition);
     my $offset  = $nbrRecs - $count;
 
     # Offsets of < 0 are not allowed.
@@ -1065,10 +1075,10 @@ END
 
   my ($err, $msg);
 
-  my $sth = $self->{db}->prepare ($statement);
+  my $sth = $self->{db}->prepare($statement);
 
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
 
     croak $msg;
   } # if
@@ -1076,7 +1086,7 @@ END
   my $status = $sth->execute;
 
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
 
     croak $msg;
   } # if
@@ -1090,15 +1100,15 @@ END
   return @records;
 } # GetLoadvg
 
-sub GetLatestLoadavg ($) {
+sub GetLatestLoadavg($) {
   my ($self, $system) = @_;
 
-  $system = $self->_aliasSystem ($system);
+  $system = $self->_aliasSystem($system);
 
   return
     unless $system;
 
-  my @records = $self->_getRecords (
+  my @records = $self->_getRecords(
     'loadavg',
     "system='$system'"
   . " order by timestamp desc limit 0, 1",
@@ -1111,7 +1121,88 @@ sub GetLatestLoadavg ($) {
   } # if
 } # GetLatestLoadavg
 
-sub AddTask (%) {
+sub GetStorage($$$;$$$$$) {
+  my ($self, $type, $tag, $storage, $region, $start, $end, $count, $interval) = @_;
+
+  $interval ||= 'Day';
+  $region   ||= $Clearcase::CC->region;
+
+  return unless $type =~ /vob/i or $type =~ /view/;
+
+  my $size = $interval =~ /month/i
+           ? 7
+           : $interval =~ /day/i
+           ? 10
+           : $interval =~ /hour/i
+           ? 13
+           : 16;
+
+  undef $start if $start and $start =~ /earliest/i;
+  undef $end   if $end   and $end   =~ /latest/i;
+
+  my $condition;
+  my $table = $type eq 'vob' ? 'vobstorage' : 'viewstorage';
+
+  $condition  = "tag='$tag' and region='$region'";
+  $condition .= " and timestamp>='$start'" if $start;
+  $condition .= " and timestamp<='$end'"   if $end;
+
+  $condition .= " group by left(timestamp,$size)";
+
+  if ($count) {
+    # We can't simply do a "limit 0, $count" as that just gets the front end of
+    # the records return (i.e. if $count = say 10 and the timestamp range
+    # returns 40 rows we'll see only rows 1-10, not rows 31-40). We need limit
+    # $offset, $count where $offset = the number of qualifying records minus
+    # $count
+    my $nbrRecs = $self->Count($table, $condition);
+    my $offset  = $nbrRecs - $count;
+
+    # Offsets of < 0 are not allowed.
+    $offset = 0 if $offset < 0;
+
+    $condition .= " limit $offset, $count";
+  } # if
+
+  my $statement = <<"END";
+select
+  tag,
+  region,
+  left(timestamp,$size) as timestamp,
+  avg($storage) as size
+from
+  $table
+  where $condition
+END
+
+  my ($err, $msg);
+
+  my $sth = $self->{db}->prepare($statement);
+
+  unless ($sth) {
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
+
+    croak $msg;
+  } # if
+
+  my $status = $sth->execute;
+
+  unless ($status) {
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
+
+    croak $msg;
+  } # if
+
+  my @records;
+
+  while (my $row = $sth->fetchrow_hashref) {
+    push @records, $row;
+  } # while
+
+  return @records;
+} # GetStorage
+
+sub AddTask(%) {
   my ($self, %task) = @_;
 
   my @requiredFields = (
@@ -1124,32 +1215,32 @@ sub AddTask (%) {
   return -1, "AddTask: $result"
     if $result;
 
-  return $self->_addRecord ('task', %task);
+  return $self->_addRecord('task', %task);
 } # AddTask
 
-sub DeleteTask ($) {
+sub DeleteTask($) {
   my ($self, $name) = @_;
 
-  return $self->_deleteRecord ('task', "name='$name'");
+  return $self->_deleteRecord('task', "name='$name'");
 } # DeleteTask
 
-sub FindTask ($) {
+sub FindTask($) {
   my ($self, $name) = @_;
 
   $name ||= '';
 
   my $condition = "name like '%$name%'";
 
-  return $self->_getRecords ('task', $condition);
+  return $self->_getRecords('task', $condition);
 } # FindTask
 
-sub GetTask ($) {
+sub GetTask($) {
   my ($self, $name) = @_;
 
   return
     unless $name;
 
-  my @records = $self->_getRecords ('task', "name='$name'");
+  my @records = $self->_getRecords('task', "name='$name'");
 
   if ($records[0]) {
     return %{$records[0]};
@@ -1158,13 +1249,13 @@ sub GetTask ($) {
   } # if
 } # GetTask
 
-sub UpdateTask ($%) {
+sub UpdateTask($%) {
   my ($self, $name, %update) = @_;
 
-  return $self->_updateRecord ('task', "name='$name'", %update);
+  return $self->_updateRecord('task', "name='$name'", %update);
 } # Update
 
-sub AddSchedule (%) {
+sub AddSchedule(%) {
   my ($self, %schedule) = @_;
 
   my @requiredFields = (
@@ -1176,16 +1267,16 @@ sub AddSchedule (%) {
   return -1, "AddSchedule: $result"
     if $result;
 
-  return $self->_addRecord ('schedule', %schedule);
+  return $self->_addRecord('schedule', %schedule);
 } # AddSchedule
 
-sub DeleteSchedule ($) {
+sub DeleteSchedule($) {
   my ($self, $name) = @_;
 
-  return $self->_deleteRecord ('schedule', "name='$name'");
+  return $self->_deleteRecord('schedule', "name='$name'");
 } # DeleteSchedule
 
-sub FindSchedule (;$$) {
+sub FindSchedule(;$$) {
   my ($self, $name, $task) = @_;
 
   $name ||= '';
@@ -1195,13 +1286,13 @@ sub FindSchedule (;$$) {
      $condition .= ' and ';
      $condition .= "task like '%$task%'";
 
-  return $self->_getRecords ('schedule', $condition);
+  return $self->_getRecords('schedule', $condition);
 } # FindSchedule
 
-sub GetSchedule ($) {
+sub GetSchedule($) {
   my ($self, $name) = @_;
 
-  my @records = $self->_getRecords ('schedule', "name='$name'");
+  my @records = $self->_getRecords('schedule', "name='$name'");
 
   if ($records[0]) {
     return %{$records[0]};
@@ -1210,13 +1301,13 @@ sub GetSchedule ($) {
   } # if
 } # GetSchedule
 
-sub UpdateSchedule ($%) {
+sub UpdateSchedule($%) {
   my ($self, $name, %update) = @_;
 
-  return $self->_updateRecord ('schedule', "name='$name'", %update);
+  return $self->_updateRecord('schedule', "name='$name'", %update);
 } # UpdateSchedule
 
-sub AddRunlog (%) {
+sub AddRunlog(%) {
   my ($self, %runlog) = @_;
 
   my @requiredFields = (
@@ -1230,64 +1321,68 @@ sub AddRunlog (%) {
 
   $runlog{ended} = Today2SQLDatetime;
 
-  my ($err, $msg) = $self->_addRecord ('runlog', %runlog);
+  $runlog{system} = hostname if $runlog{system} =~ /localhost/i;
+
+  my ($err, $msg) = $self->_addRecord('runlog', %runlog);
 
   return ($err, $msg, $self->_getLastID);
 } # AddRunlog
 
-sub DeleteRunlog ($) {
+sub DeleteRunlog($) {
   my ($self, $condition) = @_;
 
-  return $self->_deleteRecord ('runlog', $condition);
+  return $self->_deleteRecord('runlog', $condition);
 } # DeleteRunlog
 
-sub FindRunlog (;$$$$$$) {
+sub FindRunlog(;$$$$$$) {
   my ($self, $task, $system, $status, $id, $start, $page) = @_;
 
-  $task ||= '';
-
   # If ID is specified then that's all that really matters as it uniquely
   # identifies a runlog entry;
-  my $condition;
+  my ($condition, $conditions);
+  my $limit = '';
 
   unless ($id) {
-    $condition  = "task like '%$task%'";
+    if ($task !~ /all/i) {
+      $conditions++;
+      $condition = "task like '%$task%'";
+    } # if
 
-    if ($system) {
-      $condition .= " and system like '%$system%'"
-        unless $system eq 'All';
-    } else {
-      $condition .= ' and system is null';
-    } # unless
+    if ($system !~ /all/i) {
+      $condition .= ' and ' if $conditions;
+      $condition .= "system like '%$system%'";
+      $conditions++;
+    } # if
+
+    if ($status) {
+      $condition .= ' and ' if $conditions;
 
-    if (defined $status) {
       if ($status =~ /!(-*\d+)/) {
-        $condition .= " and status<>$1";
+        $condition .= "status<>$1";
       } else {
-        $condition .= " and status=$status"
+        $condition .= "status=$status"
       } # if
     } # if
 
-    $condition .= " order by started desc";
-
+    # Need defined here as $start may be 0!
     if (defined $start) {
       $page ||= 10;
-      $condition .= " limit $start, $page";
+      $limit = "limit $start, $page";
     } # unless
   } else {
     $condition = "id=$id";
   } # unless
 
-  return $self->_getRecords ('runlog', $condition);
+  return $self->_getRecords('runlog', $condition, " order by started desc $limit");
 } # FindRunlog
 
-sub GetRunlog ($) {
+sub GetRunlog($) {
   my ($self, $id) = @_;
 
   return
     unless $id;
 
-  my @records = $self->_getRecords ('runlog', "id=$id");
+  my @records = $self->_getRecords('runlog', "id=$id");
 
   if ($records[0]) {
     return %{$records[0]};
@@ -1296,13 +1391,13 @@ sub GetRunlog ($) {
   } # if
 } # GetRunlog
 
-sub UpdateRunlog ($%) {
+sub UpdateRunlog($%) {
   my ($self, $id, %update) = @_;
 
-  return $self->_updateRecord ('runlog', "id=$id", %update);
+  return $self->_updateRecord('runlog', "id=$id", %update);
 } # UpdateRunlog
 
-sub Count ($;$) {
+sub Count($;$) {
   my ($self, $table, $condition) = @_;
 
   $condition = $condition ? 'where ' . $condition : '';
@@ -1311,10 +1406,10 @@ sub Count ($;$) {
 
   my $statement = "select count(*) from $table $condition";
 
-  my $sth = $self->{db}->prepare ($statement);
+  my $sth = $self->{db}->prepare($statement);
 
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
 
     croak $msg;
   } # if
@@ -1322,7 +1417,7 @@ sub Count ($;$) {
   my $status = $sth->execute;
 
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
 
     croak $msg;
   } # if
@@ -1363,7 +1458,7 @@ sub Count ($;$) {
 # execute the work to be done, timing it, and subtracting it from the $sleep
 # time returned. If the caller exhausts the $sleep time then they should call
 # us again.
-sub GetWork () {
+sub GetWork() {
   my ($self) = @_;
 
   my ($err, $msg);
@@ -1386,10 +1481,10 @@ where
 order by lastrun
 END
 
-  my $sth = $self->{db}->prepare ($statement);
+  my $sth = $self->{db}->prepare($statement);
 
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
 
     croak $msg;
   } # if
@@ -1397,7 +1492,7 @@ END
   my $status = $sth->execute;
 
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
 
     croak $msg;
   } # if
@@ -1407,7 +1502,7 @@ END
 
   while (my $row = $sth->fetchrow_hashref) {
    if ($$row{system} !~ /localhost/i) {
-     my %system = $self->GetSystem ($$row{system});
+     my %system = $self->GetSystem($$row{system});
 
      # Skip inactive systems
      next if $system{active} eq 'false';
@@ -1436,8 +1531,8 @@ END
     } # if
 
     my $today    = Today2SQLDatetime;
-    my $lastrun  = Add ($$row{lastrun}, (seconds => $seconds));
-    my $waitTime = DateToEpoch ($lastrun) - DateToEpoch ($today);
+    my $lastrun  = Add($$row{lastrun}, (seconds => $seconds));
+    my $waitTime = DateToEpoch($lastrun) - DateToEpoch($today);
 
     if ($waitTime < 0) {
       # We're late - push this onto records and move on
@@ -1462,17 +1557,17 @@ END
   return ($sleep, @records);
 } # GetWork
 
-sub GetUniqueList ($$) {
+sub GetUniqueList($$) {
   my ($self, $table, $field) = @_;
 
   my ($err, $msg);
 
   my $statement = "select $field from $table group by $field";
 
-  my $sth = $self->{db}->prepare ($statement);
+  my $sth = $self->{db}->prepare($statement);
 
   unless ($sth) {
-    ($err, $msg) = $self->_dberror ('Unable to prepare statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to prepare statement', $statement);
 
     croak $msg;
   } # if
@@ -1480,7 +1575,7 @@ sub GetUniqueList ($$) {
   my $status = $sth->execute;
 
   unless ($status) {
-    ($err, $msg) = $self->_dberror ('Unable to execute statement', $statement);
+    ($err, $msg) = $self->_dberror('Unable to execute statement', $statement);
 
     croak $msg;
   } # if
@@ -1511,32 +1606,32 @@ sub AddAlert(%) {
   return -1, "AddAlert: $result"
     if $result;
 
-  return $self->_addRecord ('alert', %alert);
+  return $self->_addRecord('alert', %alert);
 } # AddAlert
 
-sub DeleteAlert ($) {
+sub DeleteAlert($) {
   my ($self, $name) = @_;
 
-  return $self->_deleteRecord ('alert', "name='$name'");
+  return $self->_deleteRecord('alert', "name='$name'");
 } # DeleteAlert
 
-sub FindAlert (;$) {
+sub FindAlert(;$) {
   my ($self, $alert) = @_;
 
   $alert ||= '';
 
   my $condition = "name like '%$alert%'";
 
-  return $self->_getRecords ('alert', $condition);
+  return $self->_getRecords('alert', $condition);
 } # FindAlert
 
-sub GetAlert ($) {
+sub GetAlert($) {
   my ($self, $name) = @_;
 
   return
     unless $name;
 
-  my @records = $self->_getRecords ('alert', "name='$name'");
+  my @records = $self->_getRecords('alert', "name='$name'");
 
   if ($records[0]) {
     return %{$records[0]};
@@ -1545,7 +1640,7 @@ sub GetAlert ($) {
   } # if
 } # GetAlert
 
-sub SendAlert ($$$$$$$) {
+sub SendAlert($$$$$$$) {
   my (
     $self,
     $alert,
@@ -1563,12 +1658,12 @@ sub SendAlert ($$$$$$$) {
      $footing .= "<a href='$CLEAROPTS{CLEARADM_WEBBASE}'>Clearadm</a><br>";
      $footing .= "Copyright &copy; $year, ClearSCM, Inc. - All rights reserved";
 
-  my %alert = $self->GetAlert ($alert);
+  my %alert = $self->GetAlert($alert);
 
   if ($alert{type} eq 'email') {
     my $from = 'Clearadm@' . hostdomain;
 
-    mail (
+    mail(
       from    => $from,
       to      => $to,
       subject => "Clearadm Alert: $system: $subject",
@@ -1577,7 +1672,7 @@ sub SendAlert ($$$$$$$) {
       footing => $footing,
     );
   } else {
-    $self->Error ("Don't know how to send $alert{type} alerts\n"
+    $self->Error("Don't know how to send $alert{type} alerts\n"
                 . "Subject: $subject\n"
                 . "Message: $message", 1);
   } # if
@@ -1592,10 +1687,10 @@ sub SendAlert ($$$$$$$) {
     message      => $subject,
   );
 
-  return $self->AddAlertlog (%alertlog);
+  return $self->AddAlertlog(%alertlog);
 } # SendAlert
 
-sub GetLastAlert ($$) {
+sub GetLastAlert($$) {
   my ($self, $notification, $system) = @_;
 
   my $statement = <<"END";
@@ -1613,11 +1708,11 @@ limit
   0, 1
 END
 
-  my $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
+  my $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
 
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
+    or return $self->_dberror('Unable to execute statement', $statement);
 
   my $alertlog= $sth->fetchrow_hashref;
 
@@ -1630,7 +1725,7 @@ END
   } # if
 } # GetLastAlert
 
-sub GetLastTaskFailure ($$) {
+sub GetLastTaskFailure($$) {
   my ($self, $task, $system) = @_;
 
   my $statement = <<"END";
@@ -1650,11 +1745,11 @@ limit
   0, 1
 END
 
-  my $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
+  my $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
 
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
+    or return $self->_dberror('Unable to execute statement', $statement);
 
   my $runlog= $sth->fetchrow_hashref;
 
@@ -1682,11 +1777,11 @@ limit
   0, 1
 END
 
-  $sth = $self->{db}->prepare ($statement)
-    or return $self->_dberror ('Unable to prepare statement', $statement);
+  $sth = $self->{db}->prepare($statement)
+    or return $self->_dberror('Unable to prepare statement', $statement);
 
   $sth->execute
-    or return $self->_dberror ('Unable to execute statement', $statement);
+    or return $self->_dberror('Unable to execute statement', $statement);
 
   $runlog = $sth->fetchrow_hashref;
 
@@ -1699,7 +1794,7 @@ END
   } # if
 } # GetLastTaskFailure
 
-sub Notify ($$$$$$) {
+sub Notify($$$$$$) {
   my (
     $self,
     $notification,
@@ -1718,44 +1813,44 @@ sub Notify ($$$$$$) {
 
   # Update filesystem, if $filesystem was specified
   if ($filesystem) {
-    ($err, $msg) = $self->UpdateFilesystem (
+    ($err, $msg) = $self->UpdateFilesystem(
       $system,
       $filesystem, (
         notification => $notification,
       ),
     );
 
-    $self->Error ("Unable to set notification for filesystem $system:$filesystem "
+    $self->Error("Unable to set notification for filesystem $system:$filesystem "
                . "(Status: $err)\n$msg", $err) if $err;
   } # if
 
   # Update system
-  ($err, $msg) = $self->UpdateSystem (
+  ($err, $msg) = $self->UpdateSystem(
     $system, (
       notification => $notification,
     ),
   );
 
-  my %notification = $self->GetNotification ($notification);
+  my %notification = $self->GetNotification($notification);
 
-  my %lastnotified = $self->GetLastAlert ($notification, $system);
+  my %lastnotified = $self->GetLastAlert($notification, $system);
 
   if (%lastnotified and $lastnotified{timestamp}) {
     my $today        = Today2SQLDatetime;
     my $lastnotified = $lastnotified{timestamp};
 
     if ($notification{nomorethan} =~ /hour/i) {
-      $lastnotified = Add ($lastnotified, (hours => 1));
+      $lastnotified = Add($lastnotified, (hours => 1));
     } elsif ($notification{nomorethan} =~ /day/i) {
-      $lastnotified = Add ($lastnotified, (days => 1));
+      $lastnotified = Add($lastnotified, (days => 1));
     } elsif ($notification{nomorethan} =~ /week/i) {
-      $lastnotified = Add ($lastnotified, (days => 7));
+      $lastnotified = Add($lastnotified, (days => 7));
     } elsif ($notification{nomorethan} =~ /month/i) {
-      $lastnotified = Add ($lastnotified, (month => 1));
+      $lastnotified = Add($lastnotified, (month => 1));
     } # if
 
     # If you want to fake an alert in the debugger just change $diff accordingly
-    my $diff = Compare ($today, $lastnotified);
+    my $diff = Compare($today, $lastnotified);
 
     return
       if $diff <= 0;
@@ -1763,14 +1858,14 @@ sub Notify ($$$$$$) {
 
   my $when       = Today2SQLDatetime;
   my $nomorethan = lc $notification{nomorethan};
-  my %alert      = $self->GetAlert ($notification{alert});
+  my %alert      = $self->GetAlert($notification{alert});
   my $to         = $alert{who};
 
   # If $to is null then this means to send the alert to the admin for the
   # machine.
   unless ($to) {
     if ($system) {
-      my %system = $self->GetSystem ($system);
+      my %system = $self->GetSystem($system);
 
       $to = $system{email};
     } else {
@@ -1787,7 +1882,7 @@ sub Notify ($$$$$$) {
 
   $message .= "<p>You will receive this alert no more than $nomorethan.</p>";
 
-  ($err, $msg) = $self->SendAlert (
+  ($err, $msg) = $self->SendAlert(
     $notification{alert},
     $system,
     $notification{name},
@@ -1797,29 +1892,29 @@ sub Notify ($$$$$$) {
     $runlogID,
   );
 
-  $self->Error ("Unable to send alert (Status: $err)\n$msg", $err) if $err;
+  $self->Error("Unable to send alert (Status: $err)\n$msg", $err) if $err;
 
   verbose "Sent alert to $to";
 
   # Update runlog to indicate we notified the user for this execution
-  ($err, $msg) = $self->UpdateRunlog (
+  ($err, $msg) = $self->UpdateRunlog(
     $runlogID, (
       alerted => 'true',
     ),
   );
 
-  $self->Error ("Unable to update runlog (Status: $err)\n$msg", $err) if $err;
+  $self->Error("Unable to update runlog (Status: $err)\n$msg", $err) if $err;
 
   return;
 } # Notify
 
-sub ClearNotifications ($$;$) {
+sub ClearNotifications($$;$) {
   my ($self, $system, $filesystem) = @_;
 
   my ($err, $msg);
 
   if ($filesystem) {
-    ($err, $msg) = $self->UpdateFilesystem (
+    ($err, $msg) = $self->UpdateFilesystem(
       $system,
       $filesystem, (notification => undef),
     );
@@ -1834,12 +1929,12 @@ sub ClearNotifications ($$;$) {
     # 'Filesystem' then we can toggle off the notification on the system too
     my $filesystemsAlerted = 0;
 
-    for ($self->FindFilesystem ($system)) {
+    for ($self->FindFilesystem($system)) {
       $filesystemsAlerted++
         if $$_{notification};
     } # for
 
-    my %system = $self->GetSystem ($system);
+    my %system = $self->GetSystem($system);
 
     return
       unless $system;
@@ -1847,22 +1942,22 @@ sub ClearNotifications ($$;$) {
     if ($system{notification}                 and
         $system{notification} eq 'Filesystem' and
         $filesystemsAlerted == 0) {
-      ($err, $msg) = $self->UpdateSystem ($system, (notification => undef));
+      ($err, $msg) = $self->UpdateSystem($system, (notification => undef));
 
-      $self->Error ("Unable to clear notification for system $system "
+      $self->Error("Unable to clear notification for system $system "
                   . "(Status: $err)\n$msg", $err) if $err;
     } # if
   } else {
-    ($err, $msg) = $self->UpdateSystem ($system, (notification => undef));
+    ($err, $msg) = $self->UpdateSystem($system, (notification => undef));
 
-    $self->Error ("Unable to clear notification for system $system "
+    $self->Error("Unable to clear notification for system $system "
                 . "(Status: $err)\n$msg", $err) if $err;
   } # if
 
   return;
 } # ClearNotifications
 
-sub SystemAlive (%) {
+sub SystemAlive(%) {
   my ($self, %system) = @_;
 
   # If we've never heard from this system then we will assume that the system
@@ -1881,10 +1976,10 @@ sub SystemAlive (%) {
 
   my $tenMinutes = 10 * 60;
 
-  $lastheardfrom = Add ($lastheardfrom, (seconds => $tenMinutes));
+  $lastheardfrom = Add($lastheardfrom, (seconds => $tenMinutes));
 
-  if (DateToEpoch ($lastheardfrom) < DateToEpoch ($today)) {
-    $self->UpdateSystem (
+  if (DateToEpoch($lastheardfrom) < DateToEpoch($today)) {
+    $self->UpdateSystem(
       $system{name}, (
         notification => 'Heartbeat'
       ),
@@ -1893,7 +1988,7 @@ sub SystemAlive (%) {
     return;
   } else {
     if ($system{notification}) {
-      $self->UpdateSystem (
+      $self->UpdateSystem(
         $system{name}, (
           notification => undef
         ),
@@ -1903,17 +1998,17 @@ sub SystemAlive (%) {
   } # if
 } # SystemAlive
 
-sub UpdateAlert ($%) {
+sub UpdateAlert($%) {
   my ($self, $name, %update) = @_;
 
-  return $self->_updateRecord (
+  return $self->_updateRecord(
     'alert',
     "name='$name'",
     %update
   );
 } # UpdateAlert
 
-sub AddAlertlog (%) {
+sub AddAlertlog(%) {
   my ($self, %alertlog) = @_;
 
   my @requiredFields = (
@@ -1929,23 +2024,23 @@ sub AddAlertlog (%) {
   # Timestamp record
   $alertlog{timestamp} = Today2SQLDatetime;
 
-  return $self->_addRecord ('alertlog', %alertlog);
+  return $self->_addRecord('alertlog', %alertlog);
 } # AddAlertlog
 
-sub DeleteAlertlog ($) {
+sub DeleteAlertlog($) {
   my ($self, $condition) = @_;
 
   return
     unless $condition;
 
   if ($condition =~ /all/i) {
-    return $self->_deleteRecord ('alertlog');
+    return $self->_deleteRecord('alertlog');
   } else {
-    return $self->_deleteRecord ('alertlog', $condition);
+    return $self->_deleteRecord('alertlog', $condition);
   } # if
 } # DeleteAlertlog
 
-sub FindAlertlog (;$$$$$) {
+sub FindAlertlog(;$$$$$) {
   my ($self, $alert, $system, $notification, $start, $page) = @_;
 
   $alert        ||= '';
@@ -1964,16 +2059,16 @@ sub FindAlertlog (;$$$$$) {
        $condition .= " limit $start, $page";
      } # unless
 
-  return $self->_getRecords ('alertlog', $condition);
+  return $self->_getRecords('alertlog', $condition);
 } # FindAlertLog
 
-sub GetAlertlog ($) {
+sub GetAlertlog($) {
   my ($self, $alert) = @_;
 
   return
     unless $alert;
 
-  my @records = $self->_getRecords ('alertlog', "alert='$alert'");
+  my @records = $self->_getRecords('alertlog', "alert='$alert'");
 
   if ($records[0]) {
     return %{$records[0]};
@@ -1982,17 +2077,17 @@ sub GetAlertlog ($) {
   } # if
 } # GetAlertlog
 
-sub UpdateAlertlog ($%) {
+sub UpdateAlertlog($%) {
   my ($self, $alert, %update) = @_;
 
-  return $self->_updateRecord (
+  return $self->_updateRecord(
     'alertlog',
     "alert='$alert'",
     %update
   );
 } # UpdateAlertlog
 
-sub AddNotification (%) {
+sub AddNotification(%) {
   my ($self, %notification) = @_;
 
   my @requiredFields = (
@@ -2006,16 +2101,16 @@ sub AddNotification (%) {
   return -1, "AddNotification: $result"
     if $result;
 
-  return $self->_addRecord ('notification', %notification);
+  return $self->_addRecord('notification', %notification);
 } # AddNotification
 
-sub DeleteNotification ($) {
+sub DeleteNotification($) {
   my ($self, $name) = @_;
 
-  return $self->_deleteRecord ('notification', "name='$name'");
+  return $self->_deleteRecord('notification', "name='$name'");
 } # DeletePackage
 
-sub FindNotification (;$$) {
+sub FindNotification(;$$) {
   my ($self, $name, $cond, $ordering) = @_;
 
   $name ||= '';
@@ -2024,16 +2119,16 @@ sub FindNotification (;$$) {
      $condition .= " and $cond"
        if $cond;
 
-  return $self->_getRecords ('notification', $condition);
+  return $self->_getRecords('notification', $condition);
 } # FindNotification
 
-sub GetNotification ($) {
+sub GetNotification($) {
   my ($self, $name) = @_;
 
   return
     unless $name;
 
-  my @records = $self->_getRecords ('notification', "name='$name'");
+  my @records = $self->_getRecords('notification', "name='$name'");
 
   if ($records[0]) {
     return %{$records[0]};
@@ -2042,16 +2137,50 @@ sub GetNotification ($) {
   } # if
 } # GetNotification
 
-sub UpdateNotification ($%) {
+sub UpdateNotification($%) {
   my ($self, $name, %update) = @_;
 
-  return $self->_updateRecord (
+  return $self->_updateRecord(
     'notification',
     "name='$name'",
     %update
   );
 } # UpdateNotification
 
+sub AddVobStorage(%) {
+  my ($self, %vobstorage) = @_;
+
+  my @requiredFields = (
+    'tag',
+  );
+
+  my $result = _checkRequiredFields \@requiredFields, \%vobstorage;
+
+  return -1, "AddVobStorage: $result" if $result;
+
+  # Timestamp record
+  $vobstorage{timestamp} = Today2SQLDatetime;
+
+  return $self->_addRecord('vobstorage', %vobstorage);
+} # AddVobStorage
+
+sub AddViewStorage(%) {
+  my ($self, %viewstorage) = @_;
+
+  my @requiredFields = (
+    'tag',
+  );
+
+  my $result = _checkRequiredFields \@requiredFields, \%viewstorage;
+
+  return -1, "AddViewStorage: $result" if $result;
+
+  # Timestamp record
+  $viewstorage{timestamp} = Today2SQLDatetime;
+
+  return $self->_addRecord('viewstorage', %viewstorage);
+} # AddViewStorage
+
 1;
 
 =pod
index 17ccb6e..54f164e 100644 (file)
@@ -73,6 +73,8 @@ use FindBin;
 use lib "$FindBin::Bin/../../lib";
 
 use Clearadm;
+use Clearcase::Vobs;
+use Clearcase::Views;
 use DateUtils;
 use Display;
 use Utils;
@@ -109,7 +111,9 @@ our @EXPORT = qw (
   makeFilesystemDropdown
   makeIntervalDropdown
   makeNotificationDropdown
+  makeStoragePoolDropdown
   makeSystemDropdown
+  makeTagsDropdown
   makeTimeDropdown
   makeTaskDropdown
   setField
@@ -121,25 +125,28 @@ our @PREDEFINED_ALERTS = (
 );
 
 our @PREDEFINED_NOTIFICATIONS = (
+  'Clearcase Storage',
+  'Heartbeat',
   'Loadavg',
   'Filesystem',
   'Scrub',
-  'Heartbeat',
   'System checkin',
   'Update systems',
 );
 
 our @PREDEFINED_TASKS = (
-  'Loadavg',
+  'Clearcase Storage',
   'Filesystem',
+  'Loadavg',
   'Scrub',
   'System checkin',
   'Update systems',
 );
 
 our @PREDEFINED_SCHEDULES = (
-  'Loadavg',
+  'Clearcase Storage',
   'Filesystem',
+  'Loadavg',
   'Scrub',
   'Update systems',
 );
@@ -188,7 +195,7 @@ sub setFields ($%) {
   my ($label, %rec) = @_;
 
   $rec{$_} = setField ($rec{$_}, $label)
-    foreach keys %rec;
+    for keys %rec;
 
   return %rec;
 } # setFields;
@@ -196,9 +203,9 @@ sub setFields ($%) {
 sub dumpVars (%) {
   my (%vars) = @_;
 
-  foreach (keys %vars) {
+  for (keys %vars) {
     dbug "$_: $vars{$_}";
-  } # foreach
+  } # for
 
   return;
 } # dumpVars
@@ -259,7 +266,7 @@ sub _makeAlertlogSelection ($$) {
   $values{All} = 'All';
 
   $values{$$_{$name}} = $$_{$name}
-    foreach ($clearadm->FindAlertlog);
+    for ($clearadm->FindAlertlog);
 
   my $dropdown = popup_menu {
     name    => $name,
@@ -282,13 +289,13 @@ sub _makeRunlogSelection ($$) {
 
   my %values;
 
-  foreach (@values) {
+  for (@values) {
      unless ($_ eq '') {
        $values{$_} = $_;
      } else {
        $values{NULL} = '<NULL>';
      } #if
-  } # foreach
+  } # for
 
   my $dropdown = popup_menu {
     name    => $name,
@@ -328,7 +335,7 @@ sub makeAlertDropdown (;$$) {
   my @values;
 
   push @values, $$_{name}
-    foreach ($clearadm->FindAlert);
+    for ($clearadm->FindAlert);
 
   my $dropdown  = "$label ";
      $dropdown .= popup_menu {
@@ -373,6 +380,57 @@ sub makeNoMoreThanDropdown (;$$) {
   return $dropdown;
 } # makeNoMorThanDropdown
 
+sub makeTagsDropdown($$) {
+  my ($type, $tag) = @_;
+
+  my $dropdown = ucfirst $type . ' ';
+
+  if ($type eq 'vob') {
+    my $vobs = Clearcase::Vobs->new;
+
+    $dropdown .= popup_menu {
+      name    => 'tag',
+      class   => 'dropdown',
+      values  => [sort $vobs->vobs],
+      default => $tag,
+    }; 
+  } else {
+    my $views = Clearcase::Views->new;
+
+    $dropdown .= popup_menu {
+      name    => 'tag',
+      class   => 'dropdown',
+      values  => [sort $views->views],
+      default => $tag,
+    };
+  } # if
+      
+  return span {id => $type}, $dropdown;
+} # makeTagsDropdown
+
+sub makeStoragePoolDropdown($$) {
+  my ($type, $tag) = @_;
+
+  my @values;
+
+  my $dropdown = 'Storage pool ';
+    
+  if ($type eq 'vob') {
+    push @values, qw(admin db cleartext derivedobj source total);
+  } else {
+    push @values, qw(admin db private total);
+  } # if
+
+  $dropdown .= popup_menu {
+    name    => 'storage',
+    class   => 'dropdown',
+    values  => \@values,
+    default => $tag,
+  };
+
+  return span {id => $type}, $dropdown;
+} # makeStoragePoolsDropdown
+    
 sub makeFilesystemDropdown ($;$$$) {
   my ($system, $label, $default, $onchange) = @_;
 
@@ -380,13 +438,13 @@ sub makeFilesystemDropdown ($;$$$) {
 
   my %filesystems;
 
-  foreach ($clearadm->FindFilesystem ($system)) {
+  for ($clearadm->FindFilesystem ($system)) {
     my %filesystem = %{$_};
 
     my $value = "$filesystem{filesystem} ($filesystem{mount})";
 
     $filesystems{$filesystem{filesystem}} = $value;
-  } # foreach
+  } # for
 
   my $dropdown .= "$label ";
      $dropdown .= popup_menu {
@@ -437,7 +495,7 @@ sub makeNotificationDropdown (;$$) {
   my @values;
 
   push @values, $$_{name}
-    foreach ($clearadm->FindNotification);
+    for ($clearadm->FindNotification);
 
   my $dropdown  = "$label ";
      $dropdown .= popup_menu {
@@ -476,14 +534,14 @@ sub makeSystemDropdown (;$$$%) {
 
   $label ||= '';
 
-  foreach ($clearadm->FindSystem) {
+  for ($clearadm->FindSystem) {
     my %system = %{$_};
 
     my $value  = $system{name};
        $value .= $system{alias} ? " ($system{alias})" : '';
 
     $systems{$system{name}} = $value;
-  } # foreach
+  } # for
 
   my $systemDropdown .= "$label ";
      $systemDropdown .= popup_menu {
@@ -506,7 +564,7 @@ sub makeTaskDropdown (;$$) {
   my @values;
 
   push @values, $$_{name}
-    foreach ($clearadm->FindTask);
+    for ($clearadm->FindTask);
 
   my $taskDropdown  = "$label ";
      $taskDropdown .= popup_menu {
@@ -541,10 +599,10 @@ sub makeTimeDropdown ($$$;$$$$$) {
 
   if ($table =~ /loadavg/i) {
     push @times, $$_{timestamp}
-      foreach ($clearadm->GetLoadavg ($system, undef, undef, undef, $interval));
+      for ($clearadm->GetLoadavg ($system, undef, undef, undef, $interval));
   } elsif ($table =~ /filesystem/i) {
     push @times, $$_{timestamp}
-      foreach ($clearadm->GetFS ($system, $filesystem, undef, undef, undef, $interval));
+      for ($clearadm->GetFS ($system, $filesystem, undef, undef, undef, $interval));
   } # if
 
   push @times, 'Latest';
@@ -609,7 +667,7 @@ sub heading (;$$) {
     display start_li;
       display a {href => 'systems.cgi'}, "Systems$ieTableWrapStart";
         display start_ul;
-          foreach (@allSystems) {
+          for (sort @allSystems) {
             my %system = %{$_};
             my $sysName  = ucfirst $system{name};
                $sysName .= " ($system{alias})"
@@ -618,7 +676,7 @@ sub heading (;$$) {
             display li a {
               href => "systemdetails.cgi?system=$system{name}"
             }, ucfirst "&nbsp;$sysName";
-          } # foreach
+          } # for
         display end_ul;
         display $ieTableWrapEnd;
         display end_li;
@@ -630,7 +688,7 @@ sub heading (;$$) {
     display start_li;
       display a {href => 'filesystems.cgi'}, "Filesystems$ieTableWrapStart";
         display start_ul;
-          foreach (@allSystems) {
+          for (@allSystems) {
             my %system = %{$_};
             my $sysName  = ucfirst $system{name};
                $sysName .= " ($system{alias})"
@@ -639,49 +697,16 @@ sub heading (;$$) {
             display li a {
               href => "filesystems.cgi?system=$system{name}"
             }, ucfirst "&nbsp;$sysName";
-          } # foreach
+          } # for
         display end_ul;
         display $ieTableWrapEnd;
     display end_li;
   display end_ul;
 
-  # Servers
-  display start_ul;
-    display start_li;
-      display a {href => '#'}, "Servers$ieTableWrapStart";
-      display start_ul {class => 'skinny'};
-        display start_li;
-          display start_a {href => 'vobs.cgi'};
-          display "<span class='drop'><span>VOB</span>&raquo;</span>$ieTableWrapStart";
-        display start_ul;
-          display li a {href => "systemdetails.cgi?system=jupiter"}, '&nbsp;Jupiter (defaria.com)';
-        display end_ul;
-        display $ieTableWrapEnd;
-        display end_li;
-
-        display start_li;
-        display start_a {href => 'views.cgi'};
-        display "<span class='drop'><span>View</span>&raquo;</span>$ieTableWrapStart";
-        display start_ul;
-          display li a {href => "systemdetails.cgi?system=earth"}, '&nbsp;Earth';
-          display li a {href => "systemdetails.cgi?system=mars"}, '&nbsp;Mars';
-        display end_ul;
-        display $ieTableWrapEnd;
-      display end_ul;
-      display $ieTableWrapEnd;
-    display end_li;
-  display end_ul;
-
   # Vobs
   display start_ul;
     display start_li;
-      display a {href => 'vobs.cgi'}, "VOBs$ieTableWrapStart";
-      display start_ul;
-        display li a {href => '#'}, '&nbsp;/vobs/clearscm';
-        display li a {href => '#'}, '&nbsp;/vobs/clearadm';
-        display li a {href => '#'}, '&nbsp;/vobs/test';
-        display li a {href => '#'}, '&nbsp;/vobs/test2';
-      display end_ul;
+      display a {href => 'vobservers.cgi'}, "&nbsp;&nbsp;&nbsp;VOBs$ieTableWrapStart";
       display $ieTableWrapEnd;
     display end_li;
   display end_ul;
@@ -689,11 +714,7 @@ sub heading (;$$) {
   # Views
   display start_ul;
     display start_li;
-      display a {href => 'views.cgi'}, "Views$ieTableWrapStart";
-      display start_ul;
-        display li a {href => 'viewager.cgi'}, '&nbsp;View Ager';
-        display li a {href => '#'}, '&nbsp;Releast View';
-      display end_ul;
+      display a {href => 'viewager.cgi'}, "Views$ieTableWrapStart";
       display $ieTableWrapEnd;
     display end_li;
   display end_ul;
@@ -754,7 +775,7 @@ sub displayAlert (;$) {
     display th {class => 'labelCentered'}, 'Category';
   display end_Tr;
 
-  foreach ($clearadm->FindAlert ($alert)) {
+  for ($clearadm->FindAlert ($alert)) {
     my %alert = %{$_};
 
     $alert{who} = setField $alert{who}, 'System Administrator';
@@ -827,7 +848,7 @@ sub displayAlert (;$) {
       display td {class => 'data'},
         (InArray $alert{name}, @PREDEFINED_ALERTS) ? 'Predefined' : 'User Defined';
     display end_Tr;
-  } # foreach
+  } # for
 
   display end_table;
 
@@ -1018,7 +1039,7 @@ sub displayAlertlog (%) {
 
   my $i = $opts{start};
 
-  foreach ($clearadm->FindAlertlog (
+  for ($clearadm->FindAlertlog (
     $opts{alert},
     $opts{system},
     $opts{notification},
@@ -1055,7 +1076,7 @@ sub displayAlertlog (%) {
       }, $alertlog{runlog};
       display td {class => 'data'},         $alertlog{message};
     display end_Tr;
-  } # foreach
+  } # for
 
   display end_form;
 
@@ -1083,7 +1104,7 @@ sub displayFilesystem ($) {
     display th {class => 'labelCentered'}, 'Usage';
   display end_Tr;
 
-  foreach ($clearadm->FindSystem ($systemName)) {
+  for (sort { $a->{mount} cmp $b->{mount} } $clearadm->FindSystem ($systemName)) {
     my %system = %{$_};
 
     %system = setFields ('N/A', %system);
@@ -1092,7 +1113,7 @@ sub displayFilesystem ($) {
               ? a {-href => "mailto:$system{email}"}, $system{admin}
               : $system{admin};
 
-    foreach ($clearadm->FindFilesystem ($system{name})) {
+    for ($clearadm->FindFilesystem ($system{name})) {
       my %filesystem = %{$_};
 
       my %fs = $clearadm->GetLatestFS ($system{name}, $filesystem{filesystem});
@@ -1202,8 +1223,8 @@ sub displayFilesystem ($) {
             border => 0,
           };
       display end_Tr;
-    } # foreach
-  } # foreach
+    } # for
+  } # for
 
   display end_table;
 
@@ -1224,7 +1245,7 @@ sub displayNotification (;$) {
     display th {class => 'labelCentered'}, 'Category';
   display end_Tr;
 
-  foreach ($clearadm->FindNotification ($notification)) {
+  for ($clearadm->FindNotification ($notification)) {
     my %notification= setFields 'N/A', %{$_};
 
     display start_Tr;
@@ -1296,7 +1317,7 @@ sub displayNotification (;$) {
       : 'User Defined';
 
     display end_Tr;
-  } # foreach
+  } # for
 
   display end_table;
 
@@ -1315,25 +1336,24 @@ sub displayRunlog (%) {
 
   my $optsChanged;
 
-  unless (($opts{oldtask}   and $opts{task}    or
-           $opts{oldtask}   eq  $opts{task})   and
-          ($opts{oldsystem} and $opts{system}  or
-           $opts{oldsystem} eq  $opts{system}) and
-          ($opts{oldnot}    and $opts{not}     or
-           $opts{oldnot}    eq  $opts{not})    and
-          ($opts{oldstatus} and $opts{status}  or
-           $opts{oldstatus} eq  $opts{status})) {
-    $optsChanged = 1;
-  } # unless
+  for (qw(task system not status)) {
+    my $old = "old$_";
+    if (($opts{$old} and $opts{$_}) and ($opts{$old} ne $opts{$_})) {
+      $optsChanged = 1;
+      last;
+    } # if
+  } # for
 
-  my $condition;
+  my $condition = '';
 
   unless ($opts{id}) {
-    $condition  = "task like '%";
-    $condition .= $opts{task} ? $opts{task} : '';
-    $condition .= "%'";
+    if ($opts{task} !~ /all/i) {
+      $condition  = "task like '%";
+      $condition .= $opts{task} ? $opts{task} : '';
+      $condition .= "%'";
+    } # if
 
-    if ($opts{system}) {
+    if ($opts{system} !~ /all/i) {
       if ($opts{system} eq '<NULL>') {
         $condition .= ' and system is null';
         undef $opts{system}
@@ -1342,7 +1362,7 @@ sub displayRunlog (%) {
       } # if
     } # if
 
-    if (defined $opts{status}) {
+    if ($opts{status} !~ /all/i) {
       $condition .= ' and ';
       unless ($opts{not}) {
         $condition .= "status=$opts{status}";
@@ -1490,13 +1510,13 @@ sub displayRunlog (%) {
 
   my $status;
 
-  if (defined $opts{status}) {
+  if ($opts{status}) {
     if ($opts{status} !~ /all/i) {
       $status = $opts{not} ne 'true' ? $opts{status} : "!$opts{status}";
     } # if
   } # if
 
-  foreach ($clearadm->FindRunlog (
+  for ($clearadm->FindRunlog (
     $opts{task},
     $opts{system},
     $status,
@@ -1522,7 +1542,7 @@ sub displayRunlog (%) {
       display td {class => 'data'},         a {
         href => "tasks.cgi?task=$runlog{task}"
       }, $runlog{task};
-      display td {class => 'data'}, $runlog{system} eq 'Localhost'
+      display td {class => 'data'}, $runlog{system} eq 'localhost'
         ? $runlog{system}
         : a {
         href => "systemdetails.cgi?system=$runlog{system}"
@@ -1536,7 +1556,7 @@ sub displayRunlog (%) {
 
       display td {class => $class, width => '50%'},         $message;
     display end_Tr;
-  } # foreach
+  } # for
 
   display end_table;
 
@@ -1556,7 +1576,7 @@ sub displaySchedule () {
     display th {class => 'labelCentered'}, 'Category';
   display end_Tr;
 
-  foreach ($clearadm->FindSchedule) {
+  for ($clearadm->FindSchedule) {
     my %schedule = setFields 'N/A', %{$_};
 
     display start_Tr;
@@ -1634,7 +1654,7 @@ sub displaySchedule () {
         : 'User Defined';
 
     display end_Tr;
-  } # foreach
+  } # for
 
   display end_table;
 
@@ -1805,7 +1825,7 @@ sub displaySystem ($) {
     display th {class => 'labelCentered'}, 'Usage';
   display end_Tr;
 
-  foreach ($clearadm->FindFilesystem ($system{name})) {
+  for ($clearadm->FindFilesystem ($system{name})) {
     my %filesystem = %{$_};
 
     my %fs = $clearadm->GetLatestFS (
@@ -1903,7 +1923,7 @@ sub displaySystem ($) {
            border => 0,
         };
     display end_Tr;
-  } # foreach
+  } # for
 
   display end_table;
 
@@ -1925,7 +1945,7 @@ sub displayTask (;$) {
     display th {class => 'labelCentered'}, 'Category';
   display end_Tr;
 
-  foreach ($clearadm->FindTask ($task)) {
+  for ($clearadm->FindTask ($task)) {
     my %task = %{$_};
 
     $task{system} = 'All Systems'
@@ -1995,7 +2015,7 @@ sub displayTask (;$) {
       display td {class => 'data'},
         (InArray $task{name}, @PREDEFINED_TASKS) ? 'Predefined' : 'User Defined';
     display end_Tr;
-  } # foreach
+  } # for
 
   display end_table;
 
@@ -2619,10 +2639,9 @@ sub editTask (;$) {
     };
     my $systemDropdown = makeSystemDropdown (
       undef,
-      $task{system} ? $task{system} : 'All Systems',
+      $task{system} ? $task{system} : 'localhost',
       undef, (
-        'All systems' => undef,
-        'Localhost'   => 'Localhost',
+        'localhost' => 'localhost',
       ),
     );
 
index 2203c29..d787d92 100644 (file)
@@ -51,7 +51,7 @@ use strict;
 use warnings;
 
 use Carp;
-use Net::LDAP;
+#use Net::LDAP;
 
 use GetConfig;
 
index f365201..e722015 100644 (file)
@@ -157,6 +157,38 @@ create table fs (
       on update cascade
 ) engine=innodb; -- fs
 
+-- vobstorage: Contains a snapshot of a vob's storage pools at a given date
+-- and time
+create table vobstorage (
+  tag          varchar(255) not null,
+  region        varchar(255) not null,
+  timestamp    datetime     not null,
+  admin                decimal(10,1),
+  db           decimal(10,1),
+  cleartext    decimal(10,1),
+  derivedobj   decimal(10,1),
+  source       decimal(10,1),
+  total                decimal(10,1),
+
+  key vobtagIndex (tag),
+  primary key  (tag, region, timestamp)
+) engine=innodb; -- vobstorage
+
+-- viewstorage: Contains a snapshot of a view's storage pools at a given date
+-- and time
+create table viewstorage (
+  tag          varchar(255) not null,
+  region        varchar(255) not null,
+  timestamp    datetime     not null,
+  private      decimal(10,1),
+  db           decimal(10,1),
+  admin                decimal(10,1),
+  total         decimal(10,1),
+
+  key viewtagIndex (tag),
+  primary key (tag, region, timestamp)
+) engine=innodb; -- viewstorage
+
 -- loadavg: Contains a snapshot reading of a system's load average
 create table loadavg (
   system        varchar(255)    not null,
index 4c005f4..a6efa48 100644 (file)
@@ -69,6 +69,18 @@ insert into notification (
   'Once a day'
 );
 
+insert into notification (
+  name,
+  alert,
+  cond,
+  nomorethan
+) values (
+  'Clearcase Storage',
+  'Email admin',
+  'Clearcase Failure',
+  'Once a day'
+);
+
 insert into notification (
   name,
   alert,
@@ -101,7 +113,7 @@ insert into task (
   command
 ) values (
   'Loadavg',
-  'Localhost',
+  'localhost',
   'Obtain a loadavg snapshot on all systems',
   'updatela.pl'
 );
@@ -113,7 +125,7 @@ insert into task (
   command
 ) values (
   'Filesystem',
-  'Localhost',
+  'localhost',
   'Obtain a filesystem snapshot on all systems/filesystems',
   'updatefs.pl'
 );
@@ -125,7 +137,7 @@ insert into task (
   command
 ) values (
   'Scrub',
-  'Localhost',
+  'localhost',
   'Scrub Clearadm database',
   'clearadmscrub.pl'
 );
@@ -137,7 +149,7 @@ insert into task (
   command
 ) values (
   'System checkin',
-  'Localhost',
+  'localhost',
   'Checkin from all systems',
   'default'
 );
@@ -149,11 +161,23 @@ insert into task (
   command
 ) values (
   'Update systems',
-  'Localhost',
+  'localhost',
   'Update all systems',
   'updatesystem.pl -host all'
 );
 
+insert into task (
+  name,
+  system,
+  description,
+  command
+) values (
+  'Clearcase Storage',
+  'localhost',
+  'Update Clearcase VOB/View storage',
+  'updateccfs.pl'
+);
+
 -- Predefined schedule
 insert into schedule (
   name,
@@ -190,3 +214,17 @@ insert into schedule (
   'Scrub',
   '1 day'
 );
+
+insert into schedule (
+  name,
+  task,
+  notification,
+  frequency
+) values (
+  'Clearcase Storage',
+  'Clearcase Storage',
+  'Clearcase Storage',
+  '1 day'
+);
+
+
index 040a88f..d444582 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -143,4 +143,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 422f156..9fada55 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -58,26 +58,31 @@ my $clearadm;
 sub displayGraph () {
   my $parms;
 
-  foreach (keys %opts) {
-    $parms .= '&'
-      if $parms;
+  for (keys %opts) {
+    $parms .= '&' if $parms;
     $parms .= "$_=$opts{$_}"
-  } # foreach
+  } # for
 
   display '<center>';
   
   if ($opts{type} eq 'loadavg') {
-       unless ($opts{tiny}) {
+    unless ($opts{tiny}) {
       display img {src => "plotloadavg.cgi?$parms", class => 'chart'};
-       } else {
+    } else {
       display img {src => "plotloadavg.cgi?$parms", border => 0};
-       } # unless
+    } # unless
   } elsif ($opts{type} eq 'filesystem') {
-       unless ($opts{tiny}) {
+    unless ($opts{tiny}) {
       display img {src => "plotfs.cgi?$parms", class => 'chart'};
-       } else {
+    } else {
       display img {src => "plotfs.cgi?$parms", border => 0};
-       } # unless
+    } # unless
+  } elsif ($opts{type} eq 'vob' or $opts{type} eq 'view') {
+    unless ($opts{tiny}) {
+      display img {src => "plotstorage.cgi?$parms", class => 'chart'};
+    } else {
+      display img {src => "plotstorage.cgi?$parms", border => 0};
+    } # unless
   } # if
 
   display '</center>';
@@ -140,7 +145,7 @@ sub displayFSInfo () {
   return;  
 } # displayInfo
 
-sub displayControls () {
+sub displayControls() {
   my $class = $opts{type} =~ /loadavg/i 
             ? 'controls'
             : 'filesystemControls';
@@ -152,15 +157,22 @@ sub displayControls () {
     width       => '800px',
   };
   
-  my $systemLink = span {id => 'systemLink'}, a {
-    href => "systemdetails.cgi?system=$opts{system}",
-  }, 'System';
+  my $tagsButtons;
+  my ($systemLink, $systemButtons);
 
-  my $systemButtons = makeSystemDropdown (
-    $systemLink, 
-    $opts{system}, 
-    'updateFilesystems(this.value);updateSystemLink(this.value)'
-  );
+  if ($opts{type} =~ /(vob|view)/i) {
+    $tagsButtons = makeTagsDropdown ($opts{type}, $opts{tag});
+  } else {
+    $systemLink = span {id => 'systemLink'}, a {
+      href => "systemdetails.cgi?system=$opts{system}",
+    }, 'System';
+
+    $systemButtons = makeSystemDropdown (
+      $systemLink, 
+      $opts{system}, 
+      'updateFilesystems(this.value);updateSystemLink(this.value)'
+    );
+  } # if
 
   my $startButtons = makeTimeDropdown (
     $opts{type},
@@ -182,9 +194,15 @@ sub displayControls () {
     $opts{scaling},
   );
 
-  my $update = $opts{type} eq 'loadavg' 
-             ? "updateSystem('$opts{system}')"
-             : "updateFilesystem('$opts{system}','$opts{filesystem}')";
+  my $update;
+
+  if ($opts{type} eq 'loadavg') {
+    $update = "updateSystem('$opts{system}')";
+  } elsif ($opts{type} eq 'filsystem') {
+    $update = "updateFilesystem('$opts{system}','$opts{filesystem}')";
+  } else {
+    $update = ''; # TODO do I need something here?
+  } # if
              
   my $intervalButtons = makeIntervalDropdown (
     'Interval',
@@ -195,7 +213,7 @@ sub displayControls () {
   display start_Tr;
     display td $startButtons;
     display td $intervalButtons;
-    display td $systemButtons;
+    display td $opts{type} =~ /(vob|view)/i ? $tagsButtons : $systemButtons;
   display end_Tr;
 
   display start_Tr;
@@ -216,14 +234,20 @@ sub displayControls () {
       value => 'Draw Graph',
     };
   } else {
-    my $filesystemButtons = makeFilesystemDropdown (
-      $opts{system}, 
-      'Filesystem',
-      undef,
-      "updateFilesystem('$opts{system}',this.value)",
-    );
+    if ($opts{type} eq 'filesystem') {
+      my $filesystemButtons = makeFilesystemDropdown (
+        $opts{system}, 
+        'Filesystem',
+        undef,
+        "updateFilesystem('$opts{system}',this.value)",
+      );
        
-    display td $filesystemButtons;
+      display td $filesystemButtons;
+    } else {
+      my $storagePoolButtons = makeStoragePoolDropdown ($opts{type}, $opts{tag});
+
+      display td $storagePoolButtons;
+    } # if
     
     display end_Tr;
     display start_Tr;
@@ -240,10 +264,12 @@ sub displayControls () {
 
 $clearadm = Clearadm->new;
 
-my $title  = ucfirst ($opts{type}) . ': ' . ucfirst $opts{system};
+my $title  = ucfirst ($opts{type}) . ': ';
 
-$title .= ":$opts{filesystem}"
-  if $opts{filesystem};
+$title .= ucfirst $opts{system}           if $opts{system};
+$title .= ":$opts{filesystem}"            if $opts{filesystem};
+$title .= $opts{tag}                      if $opts{tag};
+$title .= " Storage pool: $opts{storage}" if $opts{storage};
 
 heading $title;
 
@@ -317,4 +343,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 3bc8a03..8617e79 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
index 853edd8..c8acbfa 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -103,7 +103,7 @@ my @loads = $clearadm->GetLoadavg (
   $opts{scaling}
 );
 
-graphError "No loadavg data found for system $opts{system}"
+graphError "No loadavg data"
   unless @loads;
 
 my (@x, @y);
@@ -207,4 +207,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
diff --git a/clearadm/plotstorage.cgi b/clearadm/plotstorage.cgi
new file mode 100755 (executable)
index 0000000..22c20ba
--- /dev/null
@@ -0,0 +1,226 @@
+#!/usr/local/bin/perl
+
+=pod
+
+=head1 NAME $RCSfile: plotstorage.cgi,v $
+
+Plot Clearcse Storage usage
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.13 $
+
+=item Created:
+
+Mon Dec 13 09:13:27 EST 2010
+
+=item Modified:
+
+$Date: 2011/01/14 16:37:04 $
+
+=back
+
+=head1 SYNOPSIS
+
+ Usage plotstorage.cgi: tag=<tag> type=<vob|view> storage=<storage>
+                        [height=<height>] [width=<width>] [color=<color>]
+                        [scaling=<scaling>] [points=<points>] [tiny=<0|1>] 
+
+ Where:
+   <tag>:     Tag of the Clearcase object (vob or view)
+   <type>:    Designates whether <tag> is a vob of a view
+   <storage>: Name of the Clearcase storage pool to plot information for
+   <height>:  Height of chart (Default: 480px - tiny: 40)
+   <width>:   Width of chart (Default: 800px - tiny: 150)
+   <color>:   A GD::Color color value (Default: lblue)
+   <scaling>: Currently one of Minute, Hour, Day or Month. Specifies how
+              Clearadm::GetFS will scale the data returned (Default: Minute 
+              - tiny: Day)
+   <points>:  Number of points to plot (Default: all points - tiny: 7)
+   
+=head1 DESCRIPTION
+
+Draws a chart of the storage usage for the Clearcase object (vob|view).
+Parameters such as height, width, color, scaling and points can be set 
+individually though more often the user will just use the web controls to set 
+them. Defaults produce a nice chart. Tiny mode is used by
+<vob|view>details.cgi to draw tiny charts in the table. Setting tiny sets
+a number of the other chart options to produce a standard, tiny chart.
+
+=cut
+
+use strict;
+use warnings;
+
+use FindBin;
+
+use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
+
+use Clearadm;
+use ClearadmWeb;
+use Clearcase;
+use Display;
+
+use CGI qw (:standard :cgi-lib);
+use GD::Graph::area;
+
+my %opts = Vars;
+
+my $VERSION  = '$Revision: 1.13 $';
+  ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
+
+$opts{color}  ||= 'lblue';
+$opts{height} ||= 350;
+$opts{width}  ||= 800;
+
+if ($opts{tiny}) {
+  $opts{height}  = 40;
+  $opts{width}   = 150;
+  $opts{points}  = 7;
+  $opts{scaling} = 'Day';
+} # if
+
+my $clearadm = Clearadm->new;
+
+my $graph = GD::Graph::area->new ($opts{width}, $opts{height});
+
+graphError "Tag is required"     unless $opts{tag};
+graphError "Type is required"    unless $opts{type};
+graphError "Storage is required" unless $opts{storage};
+
+graphError "Points not numeric (points: $opts{points})"
+  if $opts{points} and $opts{points} !~ /^\d+$/;
+  
+my @storage = $clearadm->GetStorage (
+  $opts{type},
+  $opts{tag},
+  $opts{storage},
+  $opts{region},
+  $opts{start},
+  $opts{end},
+  $opts{points},
+  $opts{scaling}
+);
+
+graphError "No data found for $opts{type} $opts{tag} for storage pool $opts{storage}"
+  unless @storage;
+
+my (@x, @y);
+
+my $i = 0;
+
+for (@storage) {
+  $i++;
+  my %storage = %{$_};
+  
+  if ($opts{tiny}) {
+    push @x, '';
+  } else {
+    push @x, $storage{timestamp};
+  } # if
+
+  push @y, $opts{meg} ? $storage{size} / (1024 * 1024) :
+                        $storage{size} / (1024 * 1024 * 12024);
+} # for
+
+my @data = ([@x], [@y]);
+
+my $x_label_skip = @x > 1000 ? 200
+                 : @x > 100  ?  20
+                 : @x > 50   ?   2
+                 : @x > 10   ?   1
+                 : 0;
+                 
+my $storageLabel = ucfirst $opts{storage};
+my $x_label = $opts{tiny} ? '' : "$storageLabel Storage";
+my $y_label = $opts{tiny} ? '' : 
+              $opts{msg}  ? 'Used (Meg)' : 'Used (Gig)';
+my $title   = $opts{tiny} ? '' : "Storage usage for "
+                               . "$opts{type}:$opts{tag} $storageLabel";
+my $labelY  = $opts{tiny} ? '' : '%.2f';
+
+$graph->set (
+  x_label           => $x_label,
+  x_labels_vertical => 1,
+  x_label_skip      => $x_label_skip,
+  x_label_position  => .5,
+  y_label           => $y_label,
+  y_number_format   => $labelY,
+  title             => $title,
+  dclrs             => [$opts{color}],
+  bgclr             => 'white',
+  transparent       => 0,
+  long_ticks        => 1,
+  t_margin          => 5,
+  b_margin          => 5,
+  l_margin          => 5,
+  r_margin          => 5,  
+) or graphError $graph->error;
+
+my $image = $graph->plot(\@data)
+  or croak $graph->error;
+
+print "Content-type: image/png\n\n";
+print $image->png;
+
+=pod
+
+=head1 CONFIGURATION AND ENVIRONMENT
+
+DEBUG: If set then $debug is set to this level.
+
+VERBOSE: If set then $verbose is set to this level.
+
+TRACE: If set then $trace is set to this level.
+
+=head1 DEPENDENCIES
+
+=head2 Perl Modules
+
+L<CGI>
+
+L<FindBin>
+
+L<Getopt::Long|Getopt::Long>
+
+L<GD::Graph::area|GD::Graph::area>
+
+=head2 ClearSCM Perl Modules
+
+=begin man 
+
+ Clearadm
+ ClearadmWeb
+ Display
+
+=end man
+
+=begin html
+
+<blockquote>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearadm.pm">Clearadm</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/ClearadmWeb.pm">ClearadmWeb</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
+</blockquote>
+
+=end html
+
+=head1 BUGS AND LIMITATIONS
+
+There are no known bugs in this script
+
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
+
+=cut
index f3fca08..86373a9 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -209,4 +209,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 9ade442..9b2f3b2 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -205,4 +205,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 6889eb4..fa116c8 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -223,4 +223,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 3eabc4a..c5a2a4f 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -186,4 +186,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 30f4c32..88d0a29 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -222,4 +222,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 8bdd2e2..b68a9ae 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -86,7 +86,11 @@ my $title = 'Process System';
 
 heading $title;
 
-unless ($opts{'delete.x'} or $opts{'edit.x'} or $opts{action} eq 'Post') {
+unless ($opts{'delete.x'}
+     or $opts{'edit.x'}
+     or $opts{action} eq 'Post'
+     or $opts{action} eq 'Add'
+  ) {
   displayError 'Action not defined!';
   exit 1;
 } # unless
@@ -199,4 +203,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index cca5801..369d008 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -210,4 +210,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index de4a05d..9a259a3 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -123,4 +123,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index d0410ed..e5e3f56 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod 
 
@@ -84,14 +84,11 @@ my $title = 'Run Log';
 
 heading $title;
 
-undef $opts{task}
-  if $opts{task} and $opts{task} eq 'All';
-  
+$opts{task}   ||= 'All';
 $opts{system} ||= 'All';
+$opts{not}    ||= 0;
+$opts{status} ||= 'All';
 
-undef $opts{status}
-  if $opts{status} and $opts{status} eq 'All';
-  
 display h1 {class => 'center'}, $title;
 
 displayRunlog (%opts);
@@ -152,4 +149,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index ef3feef..9020c18 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -139,4 +139,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 7724992..98a0094 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -78,7 +78,7 @@ sub SetupAgent () {
   
   my ($status, @output, $cmd);
   
-  if ($ARCH eq 'cygwin') {
+  if ($ARCHITECTURE eq 'cygwin') {
      verbose '[Cygwin] Creating up Clearagent Service';
      
      $cmd  = 'cygrunsrv -I clearagent -p C:/Cygwin/bin/perl ';
@@ -86,7 +86,7 @@ sub SetupAgent () {
      
     ($status, @output) = Execute "$cmd 2>&1";
   
-    error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+    error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
       if $status;
       
     verbose '[Cygwin] Starting Clearagent Service';
@@ -94,34 +94,44 @@ sub SetupAgent () {
     $cmd .= 'net start clearagent';
     ($status, @output) = Execute "$cmd 2>&1";
   
-    error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+    error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
       if $status;
   } else {
-    my $Arch = ucfirst $ARCH;
+    my $Arch = ucfirst $ARCHITECTURE;
   
     verbose 'Creating clearagent user';
     
     $cmd = 'useradd -Mr clearagent';
+    $cmd = 'useradd clearagent' if $ARCHITECTURE eq 'solaris';
     
     ($status, @output) = Execute "$cmd 2>&1";
   
     if ($status == 9) {
        warning "The user clearagent already exists";
+    } elsif ($status == 2304) {
+      # Stupid Solaris...
     } elsif ($status != 0) {
-      error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1;
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status;
     } # if
 
     verbose 'Setting permissions on log and var directories';
-    
-    $cmd  = "chmod 777 $Clearadm::CLEAROPTS{CLEARADM_BASE}/var;";
-    $cmd .= "chmod 777 $Clearadm::CLEAROPTS{CLEARADM_BASE}/var/run;";
-    $cmd .= "chmod 777 $Clearadm::CLEAROPTS{CLEARADM_BASE}/log";
-  
-    ($status, @output) = Execute "$cmd 2>&1";
-  
-    error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
-      if $status;
 
+    for (qw(var var/run log)) {
+      $cmd = "mkdir -p $Clearadm::CLEAROPTS{CLEARADM_BASE}/$_";
+
+      ($status, @output) = Execute "$cmd 2>&1";
+
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
+        if $status;
+
+      $cmd = "chmod 777 $Clearadm::CLEAROPTS{CLEARADM_BASE}/$_";
+
+      ($status, @output) = Execute "$cmd 2>&1";
+
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
+        if $status;
+    } # for
+  
     verbose "[$Arch] Setting up clearagent daemon";
        
     # Symlink $CLEARADM/etc/conf.d/clearadm -> /etc/init.d
@@ -130,29 +140,47 @@ sub SetupAgent () {
     error "Cannot find conf.d directory ($confdir)", 1
       unless -d $confdir;
 
-    unless (-e "$confdir/clearadm") {
-      $cmd = "ln -s $FindBin::Bin/etc/init.d/clearadm $confdir";
+    unless (-e "$confdir/clearagent") {
+      $cmd = "ln -s $FindBin::Bin/etc/init.d/clearagent $confdir";
   
       ($status, @output) = Execute "$cmd 2>&1";
   
-      error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
         if $status;
     } # unless
 
     # Setup runlevel links
-    $cmd = 'update-rc.d clearagent defaults';
+    if ($ARCHITECTURE eq 'solaris') {
+      $cmd = "ln -s /etc/init.d/clearagent /etc/rc2.d/S90clearagent";
+
+      ($status, @output) = Execute "$cmd 2>&1";
+
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
+        if $status;
+
+      verbose 'Starting clearagent';
     
-    ($status, @output) = Execute "$cmd 2>&1";
+      $cmd = '/etc/init.d/clearagent';
+
+      ($status, @output) = Execute "$cmd 2>&1";
   
-    error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
-      if $status;
-      
-    verbose 'Starting clearagent';
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
+        if $status;
+    } else {
+      $cmd = 'update-rc.d clearagent defaults';
     
-    $cmd = 'service clearagent start';
+      ($status, @output) = Execute "$cmd 2>&1";
   
-    error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
-      if $status;
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
+        if $status;
+
+      verbose 'Starting clearagent';
+    
+      $cmd = 'service clearagent start';
+  
+      error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
+        if $status;
+    } # if
   } # if
 
   verbose "Done";
@@ -176,7 +204,7 @@ sub SetupTasks () {
   
     ($status, @output) = Execute "$cmd 2>&1";
  
-    error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+    error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
       if $status;
   } # unless
 
@@ -185,7 +213,7 @@ sub SetupTasks () {
     
   ($status, @output) = Execute "$cmd 2>&1";
   
-  error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+  error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
     if $status;
  
   verbose 'Starting cleartasks';
@@ -194,7 +222,7 @@ sub SetupTasks () {
   
   ($status, @output) = Execute "$cmd 2>&1";
   
-  error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+  error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
     if $status;
 
   verbose 'Done';
@@ -218,11 +246,11 @@ sub SetupWeb () {
   
     ($status, @output) = Execute "$cmd 2>&1";
   
-    error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+    error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
       if $status;
   } # unless
     
-  if ($ARCH eq 'cygwin') {
+  if ($ARCHITECTURE eq 'cygwin') {
     $cmd = 'net stop apache2; net start apache2';
   } else {
     $cmd = '/etc/init.d/apache2 restart';
@@ -230,7 +258,7 @@ sub SetupWeb () {
   
   ($status, @output) = Execute "$cmd 2>&1";
   
-  error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+  error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
     if $status;
 
   verbose 'Done';
@@ -249,7 +277,7 @@ sub SetupDatabase () {
   
   ($status, @output) = Execute "$cmd 2>&1";
   
-  error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+  error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
     if $status;
 
   verbose 'Setting up database users';
@@ -258,7 +286,7 @@ sub SetupDatabase () {
   
   ($status, @output) = Execute "$cmd 2>&1";
   
-  error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+  error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
     if $status;
 
   verbose 'Setting up predefined tasks';
@@ -267,7 +295,7 @@ sub SetupDatabase () {
   
   ($status, @output) = Execute "$cmd 2>&1";
   
-  error "Unable to execute $cmd (Status: $status)\n" . join ("\n", @output), 1
+  error "Unable to execute $cmd (Status: $status)\n" . join("\n", @output), $status
     if $status;
 
   verbose 'Done';
@@ -277,10 +305,10 @@ sub SetupDatabase () {
 
 # Main
 error "Cannot setup Clearadm when using Windows - hint try using Cgywin", 1 
-  if $ARCH eq 'windows';
+  if $ARCHITECTURE eq 'windows';
 
 Usage 'You must be root'
-  unless $> == 0 or $ARCH eq 'cygwin'; 
+  unless $> == 0 or $ARCHITECTURE eq 'cygwin'; 
   
 my $package = 'all';
 
@@ -326,4 +354,4 @@ if ($lcpackage eq 'all') {
   SetupWeb;
 } # if
  
-=pod
\ No newline at end of file
+=pod
index 1014e03..6cb81cf 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -279,4 +279,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 4346c93..1f7aba7 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -286,4 +286,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 518103a..8400203 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -142,4 +142,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 8e89bbb..3447284 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 use strict;
 use warnings;
 
@@ -237,4 +237,4 @@ my ($err, $msg) = $clearadm->DeleteSystem ($system{name});
 
 error $msg, $err
   if $err;
-   
\ No newline at end of file
+   
diff --git a/clearadm/updateccfs.pl b/clearadm/updateccfs.pl
new file mode 100755 (executable)
index 0000000..ff4dd25
--- /dev/null
@@ -0,0 +1,269 @@
+#!/usr/local/bin/perl
+
+=pod
+
+=head1 NAME $RCSfile: updateccstorage.pl,v $
+
+Update Filesystem
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.29 $
+
+=item Created:
+
+Mon Dec 13 09:13:27 EST 2010
+
+=item Modified:
+
+$Date: 2011/06/16 15:12:50 $
+
+=back
+
+=head1 SYNOPSIS
+
+ Usage updateccstorage.pl: [-u|sage] [-ve|rbose] [-deb|ug]
+                           [-view [<tag>|all]| -vob [<tag>|all]]
+
+ Where:
+   -u|sage:     Displays usage
+   -ve|rbose:   Be verbose
+   -deb|ug:     Output debug messages
+   
+   -view [<tag>|all]      Update view storage (Default: all)
+   -vob         [<tag>|all]      Update vob storage (Default: all)
+   -region [<region>|all] Update region (Default: all)
+
+=head1 DESCRIPTION
+
+This script will record the state of Clearcase storage
+
+=cut
+
+use strict;
+use warnings;
+
+use FindBin;
+use Getopt::Long;
+
+use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
+
+use Clearadm;
+use Clearexec;
+use Clearcase::Views;
+use Clearcase::View;
+use Clearcase::Vobs;
+use Clearcase::Vob;
+use DateUtils;
+use Display;
+use Utils;
+
+my $VERSION  = '$Revision: 1.29 $';
+  ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
+
+my $clearadm = Clearadm->new;
+
+# Given a view tag, snapshot the storage sizes
+sub snapshotViewStorage($$) {
+  my ($tag, $region) = @_;
+
+  my %viewstorage = (
+    tag    => $tag,
+    region => $region,
+  );
+
+  my $view = Clearcase::View->new($tag, $region);
+  
+  $viewstorage{private} = $view->viewPrivateStorage;
+  $viewstorage{db}      = $view->viewDatabase;
+  $viewstorage{admin}   = $view->viewAdmin;
+  $viewstorage{total}   = $view->viewSpace;
+
+  my ($err, $msg) = $clearadm->AddViewStorage(%viewstorage);
+
+  error $msg, $err if $err;
+} # snapshotVobStorage
+
+# Given a vob tag, snapshot the storage sizes
+sub snapshotVobStorage($$) {
+  my ($tag, $region) = @_;
+
+  my %vobstorage = (
+    tag    => $tag,
+    region => $region,
+  );
+
+  my $vob = Clearcase::Vob->new($tag, $region);
+
+  $vobstorage{admin}     = $vob->admsize;
+  $vobstorage{db}        = $vob->dbsize;
+  $vobstorage{cleartext}  = $vob->ctsize;
+  $vobstorage{derivedobj} = $vob->dosize;
+  $vobstorage{source}    = $vob->srcsize;
+  $vobstorage{total}     = $vob->size;
+
+  my ($err, $msg) = $clearadm->AddVobStorage(%vobstorage);
+
+  error $msg, $err, if $err;
+} # snapshotVobStorage
+
+my %opts;
+
+# Main
+GetOptions (
+  \%opts,
+  'usage'   => sub { Usage },
+  'verbose' => sub { set_verbose },
+  'debug'   => sub { set_debug },
+  'view=s',
+  'vob=s',
+  'region=s',
+) or Usage "Invalid parameter";
+
+Usage 'Extraneous options: ' . join ' ', @ARGV if @ARGV;
+
+unless ($opts{view} or $opts{vob}) {
+  $opts{view} = 'all';
+  $opts{vob}  = 'all';
+} # unless
+
+$opts{region} ||= 'all';
+
+# Announce ourselves
+verbose "$FindBin::Script V$VERSION";
+
+if ($opts{view} and $opts{view} =~ /all/i) {
+  if ($opts{region} =~ /all/i) {
+    for my $region ($Clearcase::CC->regions) {
+      my $views = Clearcase::Views->new($region);
+
+      for my $view ($views->views) {
+        verbose "Snapshotting view $view in region $region";
+
+        snapshotViewStorage $view, $region;
+      } # for
+    } # for
+  } else {
+    my $views = Clearcase::Views->new($opts{region});
+
+    for my $view ($views->views) {
+      verbose "Snapshotting view $view in region $opts{region}";
+
+      snapshotViewStorage $view, $opts{region};
+    } # for
+  } # if
+} elsif ($opts{view}) {
+  if ($opts{region} =~ /all/i) {
+    for my $region ($Clearcase::CC->regions) {
+      verbose "Snapshotting view $opts{view} in region $region";
+
+      snapshotViewStorage $opts{view}, $region;
+    } # for
+  } else {
+    verbose "Snapshotting view $opts{view} in region $opts{region}";
+
+    snapshotViewStorage $opts{view}, $opts{region};
+  } # if
+} # if
+
+if ($opts{vob} and $opts{vob} =~ /all/i) {
+  if ($opts{region} =~ /all/i) {
+    for my $region ($Clearcase::CC->regions) {
+      my $vobs = Clearcase::Vobs->new(undef, $region);
+
+      for my $vob ($vobs->vobs) {
+        verbose "Snapshotting vob $vob in region $region";
+
+        snapshotVobStorage $vob, $region;
+      } # for
+    } # for
+  } else {
+    my $vobs = Clearcase::Vobs->new(undef, $opts{region});
+
+    for my $vob ($vobs->vobs) {
+      verbose "Snapshotting vob $vob in region $opts{region}";
+      
+      snapshotVobStorage $vob, $opts{region};
+    } # for
+  } # if
+} elsif ($opts{vob}) {
+  if ($opts{region} =~ /all/i) {
+    for my $region ($Clearcase::CC->regions) {
+      verbose "Snapshotting view $opts{vob} in region $region";
+
+      snapshotVobStorage $opts{vob}, $region;
+    } # for
+  } else {
+    verbose "Snapshotting vob $opts{vob} in region $opts{region}";
+
+    snapshotVobStorage $opts{vob}, $opts{region};
+  } # if
+} # if
+
+=pod
+
+=head1 CONFIGURATION AND ENVIRONMENT
+
+DEBUG: If set then $debug is set to this level.
+
+VERBOSE: If set then $verbose is set to this level.
+
+TRACE: If set then $trace is set to this level.
+
+=head1 DEPENDENCIES
+
+=head2 Perl Modules
+
+L<FindBin>
+
+L<Getopt::Long|Getopt::Long>
+
+L<Net::Domain|Net::Domain>
+
+=head2 ClearSCM Perl Modules
+
+=begin man 
+
+ Clearadm
+ Clearexec
+ DateUtils
+ Display
+ Utils
+
+=end man
+
+=begin html
+
+<blockquote>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearadm.pm">Clearadm</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearcase/Vobs.pm">Clearcase::Vobs</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearcase/Vobs.pm">Clearcase::Vob</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearcase/Views.pm">Clearcase::Views</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearcase/View.pm">Clearcase::View</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/DateUtils.pm">DateUtils</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Utils.pm">Utils</a><br>
+</blockquote>
+
+=end html
+
+=head1 BUGS AND LIMITATIONS
+
+There are no known bugs in this script
+
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
+
+=cut
index 7340dde..86df94c 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -94,47 +94,30 @@ sub snapshotFS ($$) {
   # Sun is so braindead!
   # TODO: Verify this works under Solaris
   if ($system{type} eq 'Unix') {
-    foreach ('ufs', 'vxfs') {
-      my $cmd = "/usr/bin/df -k -F $filesystem{mount}";
+    my $cmd = "df -v $filesystem{mount}";
 
-      my ($status, @unixfs) = $clearexec->execute ($cmd);
+    my ($status, @unixfs) = $clearexec->execute ($cmd);
 
-      if ($status != 0) {
-        error ('Unable to determine fsinfo for '
-             . "$system{name}:$filesystem{mount} ($cmd)\n" .
-               join "\n", @unixfs
-        );
-    
-        return;
-      } # if
+    if ($status != 0) {
+      error ('Unable to determine fsinfo for '
+           . "$system{name}:$filesystem{mount} ($cmd)\n" .
+             join "\n", @unixfs);
+   
+      return;
+    } # if
 
-      # Skip heading
-      shift @unixfs;
+    # Skip heading
+    shift @unixfs;
 
-      for (my $i = 0; $i < scalar @unixfs; $i++) {
-        my $firstField;
-    
-        # Trim leading and trailing spaces
-        $unixfs[$i] =~ s/^\s+//;
-        $unixfs[$i] =~ s/\s+$//;
-
-        my @fields = split /\s+/, $unixfs[$i];
-
-        if (@fields == 1) {
-          $firstField   = 0;
-          $i++;
-
-          @fields   = split /\s+/, $unixfs[$i];;
-        } else {
-          $firstField   = 1;
-        } #if
-
-        $fs{size}    = $fields[$firstField]     * 1024;
-        $fs{used}    = $fields[$firstField + 1] * 1024;
-        $fs{free}    = $fields[$firstField + 2] * 1024;
-        $fs{reserve} = $fs{size} - $fs{used} - $fs{free};
-      } # for
-    } # foreach
+    for (my $i = 0; $i < scalar @unixfs; $i++) {
+      my @fields = split ' ', $unixfs[$i];
+
+      $fs{mount}   = $fields[0];
+      $fs{size}    = $fields[2] * 1024;
+      $fs{used}    = $fields[3] * 1024;
+      $fs{free}    = $fields[4] * 1024;
+      $fs{reserve} = $fs{size} - $fs{used} - $fs{free};
+    } # for
   } elsif ($system{type} eq 'Linux' or $system{type} eq 'Windows') {
     my $cmd = "/bin/df --block-size=1 -P $filesystem{mount}";
 
@@ -181,7 +164,7 @@ verbose "$FindBin::Script V$VERSION";
 
 my $exit = 0;
 
-foreach my $system ($clearadm->FindSystem ($host)) {
+for my $system ($clearadm->FindSystem ($host)) {
   next if $$system{active} eq 'false';
   
   my $status = $clearexec->connectToServer (
@@ -194,7 +177,7 @@ foreach my $system ($clearadm->FindSystem ($host)) {
     next;
   } # unless
 
-  foreach my $filesystem ($clearadm->FindFilesystem ($$system{name}, $fs)) {
+  for my $filesystem ($clearadm->FindFilesystem ($$system{name}, $fs)) {
     verbose "Snapshotting $$system{name}:$$filesystem{filesystem}";
   
     my %fs = snapshotFS ($system, $$filesystem{filesystem});
@@ -211,23 +194,23 @@ foreach my $system ($clearadm->FindSystem ($host)) {
     next
       unless %notification;
   
-    my $usedPct = sprintf (
-      '%.2f',
-      (($fs{used} + $fs{reserve}) / $fs{size}) * 100
-    );
+    my $usedPct = '0%';
+
+    $usedPct = sprintf ('%.2f', (($fs{used} + $fs{reserve}) / $fs{size}) * 100) if $fs{size} != 0;
     
     if ($usedPct >= $$filesystem{threshold}) {
       $exit = 2;
-      display YMDHMS . " System: $$filesystem{system} "
+      display YMDHMS
+            . " System: $$filesystem{system} "
             . "Filesystem: $$filesystem{filesystem} Used: $usedPct% " 
             . "Threshold: $$filesystem{threshold}";    
     } else {
       $clearadm->ClearNotifications ($$system{name}, $$filesystem{filesystem});    
     } # if
-  } # foreach
+  } # for
   
   $clearexec->disconnectFromServer;
-} # foreach
+} # for
 
 exit $exit;
 
index 5c8c078..e9b4b38 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -245,4 +245,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 784303f..f5fbb06 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 =pod
 
@@ -73,36 +73,43 @@ my $clearexec = Clearexec->new;
 
 my ($delete, $host, $port);
 
-sub GetFilesystems (%) {
+sub GetFilesystems(%) {
   my (%system) = @_;
   
   # TODO: Unix/Linux systems often vary as to what parameters df supports. The
   # -P is to intended to make this POSIX standard. Need to make sure this works
   # on other systems (i.e. Solaris, HP-UX, Redhat, etc.).
-  my $cmd = $system{type} eq 'Windows' ? 'df -TP' : 'df -l -TP';
+  my $cmd = $system{type} eq 'Windows'
+          ? 'df -TP'
+         : $system{type} eq 'Unix' # I think I need to add a Solaris type
+         ? '/usr/xpg4/bin/df -l -P'
+         : 'df -l -TP';
    
   my ($status, @output) = $clearexec->execute ($cmd);
   
-  error "Unable to execute uname -a - $!", $status . join ("\n". @output)
+  error "Unable to execute $cmd - $! (Status: $status)\n" . join ("\n". @output), $status
     if $status;
   
   # Real file systems start with "/"
-  @output = grep { /^\// } @output;
+  my @fs = grep { /^\// } @output;
+
+  # Also add lines that start with rpool (This is for Solaris zones
+  push @fs, grep { /^rpool/ } @output;
   
   my @filesystems;
     
-  foreach (@output) {
-       if (/^(\S+)\s+(\S+).+?(\S+)$/) {
+  for (@fs) {
+    if (/^(\S+)\s+(\S+).+?(\S+)$/) {
       my %filesystem;
       
       $filesystem{system}     = $system{name};
-         $filesystem{filesystem} = $1;
-         $filesystem{fstype}     = $2;
-         $filesystem{mount}      = $3;
+      $filesystem{filesystem} = $1;
+      $filesystem{fstype}     = $2;
+      $filesystem{mount}      = $3;
 
       push @filesystems, \%filesystem;    
-       } # if
-  } # foreach
+    } # if
+  } # for
   
   return @filesystems;
 } # GetFilesystems
@@ -146,7 +153,13 @@ sub GatherSysInfo (;%) {
     if $status;
   
   # TODO: Need to handle this better
-  $system{type} = $output[0] =~ /cygwin/i ? 'Windows' : $output[0];
+  if ($output[0] =~ /sunos/i) {
+    $system{type} = 'Unix';
+  } elsif ($output[0] =~ /cygwin/i) {
+    $system{type} = 'Windows';
+  } else {
+    $system{type} = 'Linux';
+  } # if
   
   return %system;  
 } # GatherSysInfo
@@ -156,7 +169,7 @@ sub AddFilesystems (%) {
 
   my ($err, $msg);
     
-  foreach (GetFilesystems %system) {
+  for (GetFilesystems %system) {
     my %filesystem = %{$_};
     
     my %oldfilesystem = $clearadm->GetFilesystem (
@@ -186,7 +199,7 @@ sub AddFilesystems (%) {
           . "$filesystem{system}:$filesystem{filesystem}"
         if $err;
     } # if      
-  } # foreach
+  } # for
   
   return ($err, $msg);  
 } # AddFilesystems
@@ -284,14 +297,14 @@ if ($delete) {
   } # if
 } else {
   if ($host eq 'all') {
-    foreach ($clearadm->FindSystem) {
+    for ($clearadm->FindSystem) {
       my %system = %$_;
       
       ($err, $msg) = UpdateSystem (%system);
   
       error "Unable to update host $system{name}\n$msg", $err
         if $err;
-    } # foreach
+    } # for
   } else {
     my %system = $clearadm->GetSystem ($host);
     
index c283ebe..9ac1b1e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -59,7 +59,8 @@ including old ones.
 
  Where:
    -u|sage:            Displays usage
-   -region <region>:   Region to use when looking for the view
+   -region <region>:   Region to use when looking for views (Default
+                       for generate action: all)
    -e|mail:            Send email to owners of old views
    -ag|eThreshold:     Number of days before a view is considered old
                        (Default: 180)
@@ -140,11 +141,11 @@ use User;
 my $VERSION  = '$Revision: 1.11 $';
   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
 
-my %opts = Vars;
+my %opts;
 my $clearadm;
 
-$opts{sortby} ||= 'age';
-$opts{region} ||= $Clearcase::CC->region;
+$opts{sortby}       ||= 'age';
+$opts{ageThreshold}   = 180; # Default number of days a view must be older than
 
 my $subtitle = 'View Aging Report';
 my $email;
@@ -158,14 +159,13 @@ my $script     = 'http://'
                . $port
                . $scriptName;
 
-my (%total, $action);
-my $ageThreshold = 180; # Default number of days a view must be older than
+my %total;
 my $nbrThreshold;       # Number of views threshold - think top 10
 
 sub GenerateRegion ($) {
   my ($region) = @_;
 
-  verbose "Processing $region";
+  verbose "Processing region $region";
   $total{Regions}++;
 
   my $views = Clearcase::Views->new ($region);
@@ -176,7 +176,7 @@ sub GenerateRegion ($) {
 
   my $i = 0;
 
-  foreach my $name (@Views) {
+  for my $name (@Views) {
     $total{Views}++;
 
     if (++$i % 100 == 0) {
@@ -214,13 +214,17 @@ sub GenerateRegion ($) {
 
     my $ownerid = $view->owner;
 
-    if ($ownerid) {
-      $user = User->new ($ownerid);
+    if ($ownerid =~ /^\w+(\\|\/)(\w+)/) {
+      # TODO: Handle user identification better
+      #$user = User->new ($ownerid);
 
-      $user->{name} ||= 'Unknown';
+      $ownerid       = $2;
+      $user->{name}  = $2;
+      $user->{email} = "$2\@gddsi.com";
     } else {
       $ownerid       = 'Unknown';
       $user->{name}  = 'Unknown';
+      $user->{email} = 'unknown@gddsi.com';
     } # if
 
     my $age       = 0;
@@ -235,29 +239,42 @@ sub GenerateRegion ($) {
       # Compute age
       $age       = Age ($modified_date);
       $ageSuffix = $age != 1 ? 'days' : 'day';
-    } else {
-      $modified_date = 'Unknown';
+    #} else {
+    #  $modified_date = 'Unknown';
     } # if
 
-    my ($err, $msg) = $clearadm->AddView (
-      system        => $view->shost,
-      region        => $view->region,
-      tag           => $view->tag,
-      owner         => $ownerid,
-      ownerName     => $user->{name},
-      email         => $user->{email},
-      type          => $type,
-      gpath         => $gpath,
-      modified_date => $modified_date,
-      age           => $age,
-      ageSuffix     => $ageSuffix,
+    my %oldView = $clearadm->GetView($view->tag, $view->region);
+
+    my ($err, $msg);
+
+    my %viewRec = (
+      system    => $view->shost,
+      region    => $view->region,
+      tag       => $view->tag,
+      owner     => $ownerid,
+      ownerName => $user->{name},
+      email     => $user->{email},
+      type      => $type,
+      gpath     => $gpath,
+      age       => $age,
+      ageSuffix => $ageSuffix,
     );
 
-    error "Unable to add view $name to Clearadm\n$msg", $err
-      if $err;
-  } # foreach
+    # Some views have not yet been modified
+    $viewRec{modified} = $modified_date if $modified_date;
+
+    if (%oldView) {
+      ($err, $msg) = $clearadm->UpdateView($view->tag, $view->region, %viewRec);
 
-  verbose "\nProcessed $region";
+      error "Unable to update view $name in Clearadm\n$msg", $err if $err;
+    } else {
+      ($err, $msg) = $clearadm->AddView (%viewRec);
+
+      error "Unable to add view $name to Clearadm\n$msg", $err if $err;
+    } # if
+  } # for
+
+  verbose "\nProcessed region $region";
   
   return;
 } # GenerateRegion
@@ -266,9 +283,9 @@ sub Generate ($) {
   my ($region) = @_;
 
   if ($region =~ /all/i) {
-     foreach ($Clearcase::CC->regions) {
-        GenerateRegion $_;
-     } # foreach
+    for ($Clearcase::CC->regions) {
+      GenerateRegion $_;
+    } # for
   } else {
     GenerateRegion $region;
   } # if
@@ -283,21 +300,21 @@ sub Report (@) {
 
   my @sortedViews;
 
-  if ($opts{sort} eq 'age') {
+  if ($opts{sortby} eq 'age') {
     # Sort by age numerically decending
     @sortedViews = sort { $$b{$opts{sortby}} <=> $$a{$opts{sortby}} } @views;
   } else {
-    @sortedViews = sort { $$a{$opts{sort}} cmp $$b{$opts{sort}} } @views;
+    @sortedViews = sort { $$a{$opts{sortby}} cmp $$b{$opts{sortby}} } @views;
   } # if
 
   $total{Reported} = 0;
 
-  foreach (@sortedViews) {
+  for (@sortedViews) {
     my %view = %{$_};
 
     last
       if ($nbrThreshold and $total{Reported} + 1 > $nbrThreshold) or
-         ($view{age} < $ageThreshold);
+         ($view{age} < $opts{ageThreshold});
 
     $total{Reported}++;
 
@@ -321,11 +338,11 @@ format STDOUT_TOP =
 .
 format STDOUT =
 @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<<<<<<< @>>>> @<<<<
-$view{tag},$view{owner},$view{type},$view{modified_date},$view{age},$view{ageSuffix}
+$view{tag},$view{owner},$view{type},$view{modified},$view{age},$view{ageSuffix}
 .
 
     write;
-  } # foreach
+  } # for
   
   return;
 } # Report
@@ -369,17 +386,12 @@ sub FormatTable ($@) {
     width        => '100%',
   };
 
-  my $registryHost = $Clearcase::CC->registry_host;
-  
-  $registryHost = font {class => 'unknown'}, 'Unknown'
-    unless $registryHost;
-
   $caption   .= start_Tr;
     $caption .= td {
        -align => 'left',
        -width => '30%',
     }, font ({-class => 'label'}, 'Registry: '),
-       $registryHost, '<br>',
+       setField($Clearcase::CC->registry_host), '<br>',
        font ({-class => 'label'}, 'Views: '),
        $nbrViews;
     $caption .= td {
@@ -454,18 +466,20 @@ sub FormatTable ($@) {
     # Sort by age numerically decending
     @views = $opts{reverse} == 1
            ? sort { $$a{$opts{sortby}} <=> $$b{$opts{sortby}} } @views
-           : sort { $$b{$opts{sortby}} <=> $$a{$opts{sortby}} } @views
+           : sort { $$b{$opts{sortby}} <=> $$a{$opts{sortby}} } @views;
   } else {
     @views = $opts{reverse} == 1
            ? sort { $$b{$opts{sortby}} cmp $$a{$opts{sortby}} } @views
-           : sort { $$a{$opts{sortby}} cmp $$b{$opts{sortby}} } @views
+           : sort { $$a{$opts{sortby}} cmp $$b{$opts{sortby}} } @views;
   } # if
 
   my $i;
 
-  foreach (@views) {
+  for (@views) {
     my %view = %{$_};
 
+    next if $view{region} ne $opts{region};
+
     my $owner = $view{owner};
 
     if ($view{owner} =~ /\S+(\\|\/)(\S+)/) {
@@ -474,7 +488,9 @@ sub FormatTable ($@) {
 
     $owner = $view{ownerName} ? $view{ownerName} : 'Unknown';
 
-    my $rowClass= $view{age} > $ageThreshold ? 'oldview' : 'view';
+    next if $opts{user} and $owner ne $opts{user};
+
+    my $rowClass= $view{age} > $opts{ageThreshold} ? 'oldview' : 'view';
 
     $table   .= start_Tr {
       class => $rowClass
@@ -503,7 +519,7 @@ sub FormatTable ($@) {
         class => $view{type}
       }, $view{age}, ' ', $view{ageSuffix});
     $table .= end_Tr;
-  } # foreach
+  } # for
 
   $table .= end_table;
 
@@ -524,7 +540,7 @@ sub EmailUser ($@) {
 <p>Won't you take a moment to review this message and clean up any views you no
 longer need?</p>
 
-<p>The following views are owned by you and have not been modified in $ageThreshold
+<p>The following views are owned by you and have not been modified in $opts{ageThreshold}
 days:</p>
 END
 
@@ -587,7 +603,7 @@ sub EmailUsers (@) {
   my @userViews;
   my $currUser = $views [0]->{ownerName};
 
-  foreach (@views) {
+  for (@views) {
     my %view = %{$_};
 
     next
@@ -601,12 +617,12 @@ sub EmailUsers (@) {
 
       @userViews =();
     } else {
-      if ($view{age} > $ageThreshold) {
+      if ($view{age} > $opts{ageThreshold}) {
         push @userViews, \%view
           if !-f "$view{gpath}/ageless";
       } # if
     } # if
-  } # foreach
+  } # for
 
   display"Done";
   
@@ -627,18 +643,23 @@ GetOptions (
   'nbrThreshold=i',
 ) or Usage "Invalid parameter";
 
-local $| = 1;
+# Get options from CGI
+my %CGIOpts = Vars;
+
+$opts{$_} = $CGIOpts{$_} for keys %CGIOpts;
 
-$opts{region} ||= '';
+local $| = 1;
 
 # Announce ourselves
 verbose "$FindBin::Script v$VERSION";
 
 $clearadm = Clearadm->new;
 
-if ($action and $action eq 'generate') {
+if ($opts{action} and $opts{action} eq 'generate') {
+  $opts{region} ||= 'all';
+
   Generate $opts{region};
-  Stats \%total;
+  Stats \%total if $opts{verbose};
 } else {
   if ($opts{region} and ($opts{region} eq 'Clearcase not installed')) {
     heading;
@@ -647,6 +668,8 @@ if ($action and $action eq 'generate') {
     exit 1; 
   } # if
   
+  $opts{region} ||= $Clearcase::CC->region;
+
   my @views = $clearadm->FindView (
     'all',
     $opts{region},
@@ -654,7 +677,7 @@ if ($action and $action eq 'generate') {
     $opts{user}
   );
   
-  if ($action and $action eq 'report') {
+  if ($opts{action} and $opts{action} eq 'report') {
     Report @views;
     Stats \%total;
   } elsif ($email) {
@@ -743,4 +766,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 51e4265..72b486b 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -80,24 +80,11 @@ my $VERSION  = '$Revision: 1.11 $';
 sub DisplayTable ($) {
   my ($view) = @_;
 
-  # Data fields
-  my $tag             = setField $view->tag;
-  my $server          = setField $view->shost;
-  my $region          = setField $view->region;
-  my $properties      = setField $view->properties;
-  my $text_mode       = setField $view->text_mode;
   my $permissions     = setField $view->owner_mode
                       . setField $view->group_mode
                       . setField $view->other_mode;
-  my $owner           = setField $view->owner;
   my $active          = ($view->active) ? 'YES' : 'NO';
-  my $created_by      = setField $view->created_by;
-  my $created_date    = setField $view->created_date;
-  my $cs_updated_by   = setField $view->cs_updated_by;
-  my $cs_updated_date = setField $view->cs_updated_date;
-  my $gpath           = setField $view->gpath;
-  my $access_path     = setField $view->access_path;
-  my $uuid            = setField $view->uuid;
+  my $gpath           = $view->gpath;
 
   $gpath = font {-class => 'unknown'}, '&lt;no-gpath&gt;'
     if $gpath eq '<no-gpath>';
@@ -109,43 +96,43 @@ sub DisplayTable ($) {
 
   display start_Tr;
     display th {class => 'label'},              'Tag:';
-    display td {class => 'data', colspan => 3}, $tag;
+    display td {class => 'data', colspan => 3}, setField $view->tag;
     display th {class => 'label'},              'Server:';
     display td {class => 'data'}, a {
-      href => "serverdetails.cgi?server=$server"
-    }, $server;
+      href => 'systemdetails.cgi?system=' . $view->shost
+    }, $view->shost;
     display th {class => 'label'},               'Region:';
-    display td {class => 'data'},                 $region;
+    display td {class => 'data'},                 $view->region;
   display end_Tr;
 
   display start_Tr;
     display th {class => 'label'},              'Properties:';
-    display td {class => 'data', colspan => 3}, $properties;
+    display td {class => 'data', colspan => 3}, $view->properties;
     display th {class => 'label'},              'Text Mode:';
-    display td {class => 'data'},               $text_mode;
+    display td {class => 'data'},               $view->text_mode;
     display th {class => 'label'},              'Permission:';
     display td {class => 'data'},               $permissions;
   display end_Tr;
 
   display start_Tr;
     display th {class => 'label'},              'Owner:';
-    display td {class => 'data', colspan => 3}, $owner;
+    display td {class => 'data', colspan => 3}, $view->owner;
     display th {class => 'label'},              'Active:';
     display td {class => 'data', colspan => 3}, $active;
   display end_Tr;
 
   display start_Tr;
     display th {class => 'label'},              'Created by:';
-    display td {class => 'data', colspan => 3}, $created_by;
+    display td {class => 'data', colspan => 3}, $view->created_by;
     display th {class => 'label'},              'on:';
-    display td {class => 'data', colspan => 3}, $created_date;
+    display td {class => 'data', colspan => 3}, $view->created_date;
   display end_Tr;
 
   display start_Tr;
     display th {class => 'label'},              'CS Updated by:';
-    display td {class => 'data', colspan => 3}, $cs_updated_by;
+    display td {class => 'data', colspan => 3}, $view->cs_updated_by;
     display th {class => 'label'},              'on:';
-    display td {class => 'data', colspan => 3}, $cs_updated_date;
+    display td {class => 'data', colspan => 3}, $view->cs_updated_date;
   display end_Tr;
 
   display start_Tr;
@@ -155,12 +142,50 @@ sub DisplayTable ($) {
 
   display start_Tr;
     display th {class => 'label'},              'Access Path:';
-    display td {class => 'data', colspan => 7}, $access_path;
+    display td {class => 'data', colspan => 7}, $view->access_path;
   display end_Tr;
 
   display start_Tr;
     display th {class => 'label'},              'UUID:';
-    display td {class => 'data', colspan => 7}, $uuid;
+    display td {class => 'data', colspan => 7}, $view->uuid;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'labelCentered', colspan => 10}, 'View Storage Pools';
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},                                'Database:';
+    display td {class => 'data', colspan => 3, align => 'center'}, a {href =>
+       "plot.cgi?type=view&storage=private&tag=" . $view->tag
+    }, img {
+      src    => "plotstorage.cgi?type=view&storage=private&tiny=1&tag=" . $view->tag,
+      border => 0,
+    };
+    display th {class => 'label'},                                'Private:';
+    display td {class => 'data', colspan => 5, align => 'center'}, a {href =>
+       "plot.cgi?type=view&storage=db&tag=" . $view->tag
+    }, img {
+      src    => "plotstorage.cgi?type=view&storage=db&tiny=1&tag=" . $view->tag,
+      border => 0,
+    };
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},                                'Admin:';
+    display td {class => 'data', colspan => 3, align => 'center'}, a {href =>
+       "plot.cgi?type=view&storage=admin&tag=" . $view->tag
+    }, img {
+      src    => "plotstorage.cgi?type=view&storage=admin&tiny=1&tag=" . $view->tag,
+      border => 0,
+    };
+    display th {class => 'label'},                                'Total Space:';
+    display td {class => 'data', colspan => 5, align => 'center'}, a {href =>
+       "plot.cgi?type=view&storage=total&tag=" . $view->tag
+    }, img {
+      src    => "plotstorage.cgi?type=view&storage=total&tiny=1&tag=" . $view->tag,
+      border => 0,
+    };
   display end_Tr;
 
   display end_table;
@@ -322,4 +347,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index 1b91175..f214c04 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -221,4 +221,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
diff --git a/clearadm/vobdetails.cgi b/clearadm/vobdetails.cgi
new file mode 100755 (executable)
index 0000000..89a38d6
--- /dev/null
@@ -0,0 +1,411 @@
+#!/usr/local/bin/perl
+
+=pod
+
+=head1 NAME $RCSfile: vobdetails.cgi,v $
+
+View Details
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.11 $
+
+=item Created:
+
+Mon Oct 25 11:10:47 PDT 2008
+
+=item Modified:
+
+$Date: 2011/01/14 16:51:58 $
+
+=back
+
+=head1 SYNOPSIS
+
+ Usage vobdetails.cgi: [-u|sage] [-r|egion <region>] -vo|b <vobtag>
+                       [-ve|rbose] [-d|ebug]
+
+ Where:
+   -u|sage:           Displays usage
+   -r|egion <region>: Region to use when looking for the vob
+   -vo|b <vobtag>:    Tag of vob to display details for
+
+   -ve|rbose:         Be verbose
+   -d|ebug:           Output debug messages
+
+=head2 DESCRIPTION
+
+This script display the details for the given vob
+
+=cut
+
+use strict;
+use warnings;
+
+use FindBin;
+use Getopt::Long;
+use CGI qw (:standard :cgi-lib *table start_Tr end_Tr);
+use CGI::Carp 'fatalsToBrowser';
+
+use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
+
+use ClearadmWeb;
+use Clearcase;
+use Clearcase::Vob;
+use Clearcase::Vobs;
+use Display;
+use Utils;
+
+my %opts = Vars;
+
+my $subtitle = 'VOB Details';
+
+if ($Clearcase::CC->region) {
+  $opts{region} ||= $Clearcase::CC->region;
+} else {
+  $opts{region} ||= 'Clearcase not installed';
+} # if
+
+my $VERSION  = '$Revision: 1.11 $';
+  ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
+
+sub DisplayTable ($) {
+  my ($vob) = @_;
+
+  my $active = ($vob->active) ? 'YES' : 'NO';
+  my $gpath  = $vob->gpath;
+
+  $gpath = font {-class => 'unknown'}, '&lt;no-gpath&gt;'
+    if $gpath eq '<no-gpath>';
+
+  display start_table {
+    -cellspacing    => 1,
+    -class          => 'main',
+  };
+
+  display start_Tr;
+    display th {class => 'label'},              'Tag:';
+    display td {class => 'data', colspan => 3}, setField $vob->tag;
+    display th {class => 'label'},              'Server:';
+    display td {class => 'data'}, a {
+      href => 'systemdetails.cgi?system=' . $vob->shost
+    }, $vob->shost;
+    display th {class => 'label'},               'Region:';
+    display td {class => 'data', colspan => 3},  $vob->region;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},              'Type:';
+    display td {class => 'data', colspan => 3}, $vob->access;
+    display th {class => 'label'},              'Attributes:';
+    display td {class => 'data'},               $vob->vob_registry_attributes;
+    display th {class => 'label'},              'Mount Opts:';
+    display td {class => 'data', colspan => 3}, $vob->mopts;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},              'Owner:';
+    display td {class => 'data', colspan => 3}, $vob->owner;
+    display th {class => 'label'},              'Active:';
+    display td {class => 'data'},               $active;
+    display th {class => 'label'},              'ACLs Enabled:';
+    display td {class => 'data', colspan => 3}, $vob->aclsEnabled;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},              'Created by:';
+    display td {class => 'data', colspan => 3}, $vob->ownername;
+    display th {class => 'label'},              'on:';
+    display td {class => 'data'},               $vob->created;
+    display th {class => 'label'},              'Atomic Checkin:';
+    display td {class => 'data', colspan => 3}, $vob->atomicCheckin;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},              'Comment:';
+    display td {class => 'data', colspan => 5}, $vob->comment;
+    display th {class => 'label'},              'Schema Version:';
+    display td {class => 'data', colspan => 3}, $vob->schemaVersion;
+  display end_Tr;
+  
+  display start_Tr;
+    display th {class => 'label'},              'Global Path:';
+    display td {class => 'data', colspan => 5}, $gpath;
+    display th {class => 'label'},              'Registry Attributes:';
+    display td {class => 'data', colspan => 3}, $vob->vob_registry_attributes;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},              'Access Path:';
+    display td {class => 'data', colspan => 5}, $vob->access_path;
+    display th {class => 'label'},              'Group:';
+    display td {class => 'data', colspan => 3}, $vob->group;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},              'Family UUID:';
+    display td {class => 'data', colspan => 5}, $vob->family_uuid;
+    display th {class => 'label'},              'Remote Privilage:';
+    display td {class => 'data', colspan => 3}, $vob->remotePrivilege;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},              'Replica UUID:';
+    display td {class => 'data', colspan => 5}, $vob->replica_uuid;
+    display th {class => 'label'},              'Master Replica:';
+    display td {class => 'data', colspan => 3}, $vob->masterReplica;
+  display end_Tr;
+
+  my $groups = join "<br>", $vob->groups;
+
+  display start_Tr;
+    display th {class => 'label'},               'Groups:';
+    display td {class => 'data', colspan => 10}, $groups;
+  display end_Tr;
+
+  my %attributes = $vob->attributes;
+  my $attributes = '';
+
+  for (keys %attributes) {
+    $attributes .= "$_ = $attributes{$_}<br>";
+  } # for
+  
+  display start_Tr;
+    display th {class => 'label'},               'Attributes:';
+    display td {class => 'data', colspan => 10}, $attributes;
+  display end_Tr;
+
+  my %hyperlinks = $vob->hyperlinks;
+  my $hyperlinks = '';
+
+  for (keys %hyperlinks) {
+    $hyperlinks .= "$_ = $hyperlinks{$_}<br>";
+  } # for
+  
+  display start_Tr;
+    display th {class => 'label'},               'Hyperlinks:';
+    display td {class => 'data', colspan => 10}, $hyperlinks;
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'labelCentered', colspan => 10}, 'VOB Storage Pools';
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},                                'Admin:';
+    display td {class => 'data', colspan => 4, align => 'center'}, a {href =>
+      "plot.cgi?type=vob&storage=admin&scaling=Hour&points=24&tag=" . $vob->tag
+    }, img {
+      src    => "plotstorage.cgi?type=vob&storage=admin&tiny=1&tag=" . $vob->tag,
+      border => 0,
+    };
+    display th {class => 'label'},                                'Source Size:';
+    display td {class => 'data', colspan => 4, align => 'center'}, a {href =>
+      "plot.cgi?type=vob&storage=source&scaling=Hour&points=24&tag=" . $vob->tag
+    }, img {
+      src    => "plotstorage.cgi?type=vob&storage=source&tiny=1&tag=" . $vob->tag,
+      border => 0,
+    };
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},                                'Database:';
+    display td {class => 'data', colspan => 4, align => 'center'}, a {href =>
+      "plot.cgi?type=vob&storage=db&scaling=Hour&points=24&tag=" . $vob->tag
+    }, img {
+      src    => "plotstorage.cgi?type=vob&storage=db&tiny=1&tag=" . $vob->tag,
+      border => 0,
+    };
+    display th {class => 'label'},                                'Derived Obj:';
+    display td {class => 'data', colspan => 4, align => 'center'}, a {href =>
+      "plot.cgi?type=vob&storage=derivedobj&scaling=Hour&points=24&tag=" . $vob->tag
+    }, img {
+      src    => "plotstorage.cgi?type=vob&storage=derivedobj&tiny=1&tag=" . $vob->tag,
+      border => 0,
+    };
+  display end_Tr;
+
+  display start_Tr;
+    display th {class => 'label'},                                'Cleartext:';
+    display td {class => 'data', colspan => 4, align => 'center'}, a {href =>
+      "plot.cgi?type=vob&storage=cleartext&scaling=Hour&points=24&tag=" . $vob->tag
+    }, img {
+      src    => "plotstorage.cgi?type=vob&storage=cleartext&tiny=1&tag=" . $vob->tag,
+      border => 0,
+    };
+    display th {class => 'label'},                                'Total Size:';
+    display td {class => 'data', colspan => 4, align => 'center'}, a {href =>
+      "plot.cgi?type=vob&storage=total&scaling=Hour&points=24&tag=" . $vob->tag
+    }, img {
+      src    => "plotstorage.cgi?type=vob&storage=total&tiny=1&tag=" . $vob->tag,
+      border => 0,
+    };
+  display end_Tr;
+
+  display end_table;
+
+  return;
+} # DisplayTable
+
+sub DisplayRegion {
+  display start_form (action => 'vobdetails.cgi');
+
+  display 'Region ';
+
+  my ($defaultRegion, @regions) = ('', ('Clearcase not installed'));
+
+  display popup_menu (
+    -name     => 'region',
+    -values   => [@regions],
+    -default  => $defaultRegion,
+    -onchange => 'submit();',
+  );
+
+  display submit (
+    -value => 'Go',
+  );
+
+  display end_form;
+  
+  return
+} # DisplayRegion
+
+sub DisplayVobs($) {
+  my ($region) = @_;
+
+  my @vobs = Clearcase::Vobs->new ($region);
+
+  unless (@vobs) {
+    push @vobs, 'No VOBs';
+  } # unless
+
+  display start_form (action => 'vobdetails.cgi');
+
+  display 'Region ';
+
+  display popup_menu (
+    -name     => 'region',
+    -values   => [$Clearcase::CC->regions],
+    -default  => $region,
+    -onchange => 'submit();',
+  );
+
+  display b ' VOB: ';
+
+  display popup_menu (
+     -name     => 'vob',
+     -values   => \@vobs,
+     -onchange => 'submit();',
+  );
+
+  display submit (
+    -value     => 'Go',
+  );
+
+  display end_form;
+  
+  return;
+} # DisplayVobs
+
+# Main
+GetOptions (
+  \%opts,
+  'usage'        => sub { Usage },
+  'verbose'      => sub { set_verbose },
+  'debug'        => sub { set_debug },
+  'vob=s',
+  'region=s',
+) or Usage "Invalid parameter";
+
+# Announce ourselves
+verbose "$FindBin::Script v$VERSION";
+
+heading $subtitle;
+
+display h1 {
+  -class => 'center',
+}, $subtitle;
+
+unless ($opts{tag}) {
+  unless ($opts{region}) {
+    DisplayRegion;
+  } else {
+    DisplayVobs $opts{region};
+  } # unless
+
+  exit;
+} # unless
+
+my $vob = Clearcase::Vob->new ($opts{tag}, $opts{region});
+
+DisplayTable $vob;
+
+footing;
+
+=pod
+
+=head1 CONFIGURATION AND ENVIRONMENT
+
+DEBUG: If set then $debug is set to this level.
+
+VERBOSE: If set then $verbose is set to this level.
+
+TRACE: If set then $trace is set to this level.
+
+=head1 DEPENDENCIES
+
+=head2 Perl Modules
+
+L<CGI>
+
+L<CGI::Carp|CGI::Carp>
+
+L<FindBin>
+
+L<Getopt::Long|Getopt::Long>
+
+=head2 ClearSCM Perl Modules
+
+=begin man 
+
+ ClearadmWeb
+ Clearcase
+ Clearcase::View
+ Clearcase::Views
+ Display
+ Utils
+
+=end man
+
+=begin html
+
+<blockquote>
+<a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/ClearadmWeb.pm">ClearadmWeb</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/View.pm">Clearcase::View</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Views.pm">Clearcase::Views</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Utils.pm">Utils</a><br>
+</blockquote>
+
+=end html
+
+=head1 BUGS AND LIMITATIONS
+
+There are no known bugs in this script
+
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
+
+=cut
index 453fd09..6748c9e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/local/bin/perl
 
 =pod
 
@@ -51,7 +51,7 @@ use warnings;
 
 use FindBin;
 use Getopt::Long;
-use CGI qw (:standard :cgi-lib *table start_Tr end_Tr);
+use CGI qw (:standard :cgi-lib *table start_Tr end_Tr start_ol end_ol);
 use CGI::Carp 'fatalsToBrowser';
 
 use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
@@ -59,6 +59,8 @@ use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
 use ClearadmWeb;
 use Clearcase;
 use Clearcase::Server;
+use Clearcase::Vobs;
+use Clearcase::Vob;
 use Display;
 use Utils;
 
@@ -71,6 +73,68 @@ my $subtitle = 'Vob Servers';
 my $VERSION  = '$Revision: 1.9 $';
   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
 
+sub DisplayVobs($) {
+  my ($server) = @_;
+
+  display h3 {
+    -class => 'center',
+  }, "Vobs on " . $server->name;
+
+  display start_table;
+
+  display start_Tr;
+    display th {
+      -class => 'labelCentered',
+      }, '#';
+    display th {
+    -class => 'labelCentered',
+      }, 'Tag';
+    display th {
+      -class => 'labelCentered',
+      }, 'Type';
+    display th {
+      -class => 'labelCentered',
+      }, 'Active';
+    display th {
+      -class => 'labelCentered',
+      }, 'Access Path';
+    display th {
+      -class => 'labelCentered',
+      }, 'Attributes';
+  display end_Tr;
+
+  my $i = 0;
+
+  my $vobs = Clearcase::Vobs->new($server->name);
+
+  for (sort $vobs->vobs) {
+    my $vob = Clearcase::Vob->new($_);
+
+    display start_Tr;
+      display td {
+        -class => 'dataCentered',
+      }, ++$i;
+      display td {
+        -class => 'data',
+      }, a {-href => "vobdetails.cgi?tag=" . $vob->tag}, $vob->tag;
+      display td {
+        -class => 'dataCentered',
+      }, $vob->access;
+      display td {
+        -class => 'dataCentered',
+      }, $vob->active;
+      display td {
+        -class => 'data',
+      }, $vob->access_path;
+      display td {
+        -class => 'data',
+      }, $vob->vob_registry_attributes;
+    display end_Tr;
+  } # for
+
+  display end_table;
+} # DisplayVob
+
 sub DisplayTable (@) {
   my (@vobServers) = @_;
 
@@ -94,39 +158,167 @@ sub DisplayTable (@) {
     display th {
       -class => 'labelCentered',
       }, 'OS Version';
+    display th {
+      -class => 'labelCentered',
+      }, 'Hardware';
+    display th {
+      -class => 'labelCentered',
+      }, 'Registry Host';
+    display th {
+      -class => 'labelCentered',
+      }, 'Region';
+    display th {
+      -class => 'labelCentered',
+      }, 'License Host';
   display end_Tr;
 
   my $i = 0;
 
-  foreach (@vobServers) {
-    my $server = Clearcase::Server->new ($_, $opts{region});
-
-    # Data fields
-    my $name  = $server->name;
-    my $ccVer = $server->ccVer;
-    my $osVer = $server->osVer;
+  my $server;
 
-    $ccVer ||= $unknown;
-    $osVer ||= $unknown;
+  for (@vobServers) {
+    $server = Clearcase::Server->new ($_, $opts{region});
 
     display start_Tr;
       display td {
         -class => 'dataCentered',
       }, ++$i;
       display td {
-        -class   => 'data',
-      }, a {-href => "serverdetails.cgi?server=$name"}, $name;
+        -class   => 'dataCentered',
+      }, a {-href => "systemdetails.cgi?system=" . $server->name}, $server->name;
       display td {
-        -class => 'data',
-      }, $ccVer;
+        -class => 'dataCentered',
+      }, $server->ccVer;
       display td {
-        -class => 'data',
-      }, $osVer;
+        -class => 'dataCentered',
+      }, $server->osVer;
+      display td {
+        -class => 'dataCentered',
+      }, $server->hardware;
+      display td {
+        -class => 'dataCentered',
+      }, a {-href => "systemdetails.cgi?system=" . $server->registryHost}, $server->registryHost;
+      display td {
+        -class => 'dataCentered',
+      }, $server->registryRegion;
+      display td {
+        -class => 'dataCentered',
+      }, $server->licenseHost;
     display end_Tr;
-  } # foreach
 
-  display end_table;
+    display start_Tr;
+      display th {
+        -class => 'labelCentered',
+        }, 'MVFS';
+      display th {
+        -class => 'labelCentered',
+        }, 'Scaling';
+      display th {
+        -class => 'labelCentered',
+        }, 'Free Mnodes';
+      display th {
+        -class => 'labelCentered',
+        }, 'Free Mnodes Cleartext';
+      display th {
+        -class => 'labelCentered',
+        }, 'File names';
+      display th {
+        -class => 'labelCentered',
+        }, 'Directory names';
+      display th {
+        -class => 'labelCentered',
+        }, 'Blocks Per Directory';
+      display th {
+        -class => 'labelCentered',
+        }, 'Names not found';
+    display end_Tr;
+
+    display start_Tr;
+      display td {
+        -class => 'dataCentered',
+      }, '&nbsp;';
+      display td {
+        -class   => 'dataCentered',
+      }, $server->scalingFactor;
+      display td {
+        -class   => 'dataRight',
+      }, $server->mvfsFreeMnodes;
+      display td {
+        -class => 'dataRight',
+      }, $server->mvfsFreeMnodesCleartext;
+      display td {
+        -class => 'dataRight',
+      }, $server->mvfsFileNames;
+      display td {
+        -class => 'dataRight',
+      }, $server->mvfsDirectoryNames;
+      display td {
+        -class => 'dataRight',
+      }, $server->mvfsBlocksPerDirectory;
+      display td {
+        -class => 'dataRight',
+      }, $server->mvfsNamesNotFound;
+    display end_Tr;
+
+    display start_Tr;
+      display th {
+        -class => 'labelCentered',
+        }, 'RPC Handles';
+      display th {
+        -class => 'labelCentered',
+        }, 'Cleartext Idle Lifetime';
+      display th {
+        -class => 'labelCentered',
+        }, 'VOB HTS';
+      display th {
+        -class => 'labelCentered',
+        }, 'Cleartext HTS';
+      display th {
+        -class => 'labelCentered',
+        }, 'Thread HTS';
+      display th {
+        -class => 'labelCentered',
+        }, 'DNC HTS';
+      display th {
+        -class => 'labelCentered',
+        }, 'Process HTS';
+      display th {
+        -class => 'labelCentered',
+        }, 'Initial Mnode Table Size';
+    display end_Tr;
+
+    display start_Tr;
+      display td {
+        -class => 'dataRight',
+      }, $server->mvfsRPCHandles;
+      display td {
+        -class => 'dataRight',
+      }, $server->cleartextIdleLifetime;
+      display td {
+        -class   => 'dataRight',
+      }, $server->vobHashTableSize;
+      display td {
+        -class   => 'dataRight',
+      }, $server->cleartextHashTableSize;
+      display td {
+        -class => 'dataRight',
+      }, $server->threadHashTableSize;
+      display td {
+        -class => 'dataRight',
+      }, $server->dncHashTableSize;
+      display td {
+        -class => 'dataRight',
+      }, $server->processHashTableSize;
+      display td {
+        -class => 'dataRight',
+      }, $server->mvfsInitialMnodeTableSize;
+    display end_Tr;
+    display end_table;
+  } # for
   
+  display p;
+  DisplayVobs $server;
+
   return;
 } # DisplayTable
 
@@ -158,11 +350,11 @@ error "Unable to list all vobs in the region $opts{region}"
 
 my %vobServers;
 
-foreach (@output) {
+for (@output) {
   if (/Server host: (.*)/) {
     $vobServers{$1} = undef;
   } # if
-} # foreach
+} # for
 
 DisplayTable sort (keys (%vobServers));
 
@@ -224,4 +416,4 @@ Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-=cut
\ No newline at end of file
+=cut
index a845184..e9b58ff 100644 (file)
@@ -593,6 +593,7 @@ Array of output lines from the cleartool command execution.
   if (!$clearpid) {
     # Simple check to see if we can execute cleartool
     @output = `$cleartool -ver 2>&1`;
+    @output = ();
         
     return (-1, 'Clearcase not installed')
       unless $? == 0;
index 0021a5c..c47e321 100644 (file)
@@ -29,6 +29,7 @@ $Date: 2011/01/02 04:59:36 $
 =head2 SYNOPSIS
 
 Provides access to information about a Clearcase Server.
+
 =head2 DESCRIPTION
 
 This module implements an object oriented interface to a Clearcase
@@ -92,6 +93,8 @@ sub new ($;$) {
 
   my $self = bless { name => $name }, $class;
 
+  $self->updateServerInfo($name);
+
   return $self;
 } # new
   
@@ -143,11 +146,11 @@ sub mvfsBlocksPerDirectory () {
   return $self->{mvfsBlocksPerDirectory};
 } # mvfsBlocksPerDirectory
 
-sub mvfsCleartextMnodes () {
+sub mvfsFreeMnodesCleartext() {
   my ($self) = @_;
  
-  return $self->{mvfsCleartextMnodes};
-} # mvfsCleartextMnodes
+  return $self->{mvfsFreeMnodesCleartext};
+} # mvfsFreeMnodesCleartext
 
 sub mvfsDirectoryNames () {
   my ($self) = @_;
@@ -245,6 +248,66 @@ sub processHashTableSize () {
   return $self->{processHashTableSize};
 } # processHashTableSize
 
+sub updateServerInfo($) {
+  my ($self, $host) = @_;
+
+  my ($status, @output) = $Clearcase::CC->execute(
+    "hostinfo -long -properties -full $host"
+  );
+
+  for (@output) {
+    if (/Product: ClearCase (.*)/) {
+      $self->{ccVer} = $1;
+    } elsif (/Operating system: (.*)/) {
+      $self->{osVer} = $1;
+    } elsif (/Hardware type: (.*)/) {
+      $self->{hardware} = $1;
+    } elsif (/License host: (.*)/) {
+      $self->{licenseHost} = $1;
+    } elsif (/Registry host: (.*)/) {
+      $self->{registryHost} = $1;
+    } elsif (/Registry region: (.*)/) {
+      $self->{registryRegion} = $1;
+    } elsif (/Blocks per directory: (.*)/) {
+      $self->{mvfsBlocksPerDirectory} = $1;
+    } elsif (/Free mnodes for cleartext: (.*)/) {
+      $self->{mvfsFreeMnodesCleartext} = $1;
+    } elsif (/Directory names: (.*)/) {
+      $self->{mvfsDirectoryNames} = $1;
+    } elsif (/File names: (.*)/) {
+      $self->{mvfsFileNames} = $1;
+    } elsif (/Free mnodes: (.*)/) {
+      $self->{mvfsFreeMnodes} = $1;
+    } elsif (/Initial mnode table size: (.*)/) {
+      $self->{mvfsInitialMnodeTableSize} = $1;
+    } elsif (/Minimum free mnodes for cleartext: (.*)/) {
+      $self->{mvfsMinCleartextMnodes} = $1;
+    } elsif (/Mimimum free mnodes: (.*)/) {
+      $self->{mvfsMinFreeMnodes} = $1;
+    } elsif (/Names not found: (.*)/) {
+      $self->{mvfsNamesNotFound} = $1;
+    } elsif (/RPC handles: (.*)/) {
+      $self->{mvfsRPCHandles} = $1;
+    } elsif (/Scaling factor to initialize MVFS cache sizes: (.*)/) {
+      $self->{scalingFactor} = $1;
+    } elsif (/Cleartext idle lifetime: (.*)/) {
+      $self->{cleartextIdleLifetime} = $1;
+    } elsif (/VOB hash table size: (.*)/) {
+      $self->{vobHashTableSize} = $1;
+    } elsif (/Cleartext hash table size: (.*)/) {
+      $self->{cleartextHashTableSize} = $1;
+    } elsif (/Thread hash table size: (.*)/) {
+      $self->{threadHashTableSize} = $1;
+    } elsif (/DNC hash table size: (.*)/) {
+      $self->{dncHashTableSize} = $1;
+    } elsif (/Process hash table size: (.*)/) {
+      $self->{processHashTableSize} = $1;
+    } # if
+  } # for
+
+  return;
+} # updateServerInfo
+
 1;
 
 =pod
index 7a59cd2..79dea02 100644 (file)
@@ -46,9 +46,9 @@ fields they are expanded.
 
  display_nolf MAGENTA   . "Additional groups:\t";
 
- foreach ($view->additional_groups) {
+ for ($view->additional_groups) {
    display_nolf "$_ ";
- } # foreach
+ } # for
 
  display '';
 
@@ -1168,7 +1168,7 @@ Returns:
 =cut
 
   return $self->{tag};
- } # tag
+} # tag
 
 sub text_mode () {
   my ($self) = @_;
@@ -1764,7 +1764,7 @@ sub updateViewInfo ($$) {
   $self->{ucm}                = 0;
   $self->{additional_groups}  = '';
 
-  foreach (@output) {
+  for (@output) {
     if (/Global path: (.*)/) {
       $self->{gpath} = $1;
     } elsif (/Server host: (.*)/) {
@@ -1805,19 +1805,26 @@ sub updateViewInfo ($$) {
       $self->{text_mode} = $1;
     } elsif (/Properties: (.*)/) {
       $self->{properties} = $1;
-    } elsif (/Owner: (\S+)\s+: (\S+) /) {
+    } elsif (/View owner: (\S+)$/) {
+      # It is possible that there may be problems enumerating
+      # -properties and -full when listing views due to servers
+      # no longer being available. Still the "View owner" line
+      # denotes the view's owner.
+      $self->{owner}      = $1;
+      $self->{owner_mode} = '';
+    } elsif (/Owner: (\S+)\s+: (\S+)/) {
       $self->{owner}          = $1;
       $self->{owner_mode}     = $2;
     } elsif (/Group: (.+)\s+:\s+(\S+)\s+/) {
       $self->{group}          = $1;
-       $self->{group_mode}     = $2;
-    } elsif (/Other:\s+: (\S+) /) {
+      $self->{group_mode}     = $2;
+    } elsif (/Other:\s+: (\S+)/) {
       $self->{other_mode}     = $1;
     } elsif (/Additional groups: (.*)/) {
       my @additional_groups = split /\s+/, $1;
       $self->{additional_groups} = \@additional_groups;
     } # if
-  } # foreach
+  } # for
 
   # Change modes to numeric
   $self->{mode} = 0;
@@ -1837,6 +1844,361 @@ sub updateViewInfo ($$) {
   return;
 } # updateViewInfo
 
+sub viewPrivateStorage() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewPrivateStorage
+
+Returns the view private storage size for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view private storage
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewPrivateStorage});
+
+  return $self->{viewPrivateStorage};
+} # viewPrivateStorage
+
+sub viewPrivateStoragePct() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewPrivateStoragePct
+
+Returns the view private storage percent for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view private storage
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewPrivateStoragePct});
+
+  return $self->{viewPrivateStoragePct};
+} # viewPrivateStoragePct
+
+sub viewDatabase() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewDatabase
+
+Returns the view database size for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view database size
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewDatabase});
+
+  return $self->{viewDatabase};
+} # viewDatabase
+
+sub viewDatabasePct() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewDatabasePct
+
+Returns the view database percent for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view database percent
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewDatabasePct});
+
+  return $self->{viewDatabasePct};
+} # viewDatabasePct
+
+sub viewAdmin() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewAdmin
+
+Returns the view admin size for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view admin size
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewAdmin});
+
+  return $self->{viewAdmin};
+} # viewAdmin
+
+sub viewAdminPct() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewAdminPct
+
+Returns the view admin percent for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view admin percent
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewAdminPct});
+
+  return $self->{viewAdminPct};
+} # viewAdminPct
+
+sub viewSpace() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewSpace
+
+Returns the view total size for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view space
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewSpace});
+
+  return $self->{viewSpace};
+} # viewSpace
+
+sub viewSpacePct() {
+  my ($self) = @_;
+  
+=pod
+
+=head1 viewSpacePct
+
+Returns the view database percent for this view.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item view space percent
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->updateViewSpace unless ($self->{viewSpacePct});
+
+  return $self->{viewSpacePct};
+} # viewSpacePct
+
+sub updateViewSpace() {
+  my ($self) = @_;
+
+  my ($status, @output) = $Clearcase::CC->execute (
+    "space -region $self->{region} -view $self->{tag}"
+  );
+
+  $self->{viewPrivateStorage}    = 0.0;
+  $self->{viewPrivateStoragePct} = '0%';
+  $self->{viewAdmin}             = 0.0;
+  $self->{viewAdminPct}          = '0%';
+  $self->{viewDatabase}          = 0.0;
+  $self->{viewDatabasePct}       = '0%';
+  $self->{viewSpace}             = 0.0;
+  $self->{viewSpacePct}          = '0%';
+
+  for (@output) {
+    if (/\s*(\S+)\s*(\S+)\s*View private storage/) {
+      $self->{viewPrivateStorage}    = $1;
+      $self->{viewPrivateStoragePct} = $2;
+    } elsif (/\s*(\S+)\s*(\S+)\s*View database/) {
+      $self->{viewDatabase}    = $1;
+      $self->{viewDatabasePct} = $2;
+    } elsif (/\s*(\S+)\s*(\S+)\s*View administration/) {
+      $self->{viewAdmin}    = $1;
+      $self->{viewAdminPct} = $2;
+    } elsif (/\s*(\S+)\s*(\S+)\s*Subtotal/) {
+      $self->{viewSpace}    = $1;
+      $self->{viewSpacePct} = $2;
+    } # if
+  } # for
+
+  return;
+} # updateViewSpace
+
 1;
 
 =pod
index ca4f765..596fafb 100644 (file)
@@ -56,7 +56,7 @@ expanded if and when accessed. This helps the VOB object to be more efficient.
  display "DB Size:\t"          . $vob->dbsize;
  display "Adm Size:\t"         . $vob->admsize;
  display "CT Size:\t"          . $vob->ctsize;
- display "DO Size:\t"          . $vob->dbsize;
+ display "DO Size:\t"          . $vob->dosize;
  display "Src Size:\t"         . $vob->srcsize;
  display "Size:\t\t"           . $vob->size;
 
@@ -157,7 +157,7 @@ sub tag () {
 
 =head2 tag
 
-Returns the VOB's tag
+Returns the VOB tag
 
 Parameters:
 
@@ -195,7 +195,7 @@ sub gpath () {
 
 =head2 gpath
 
-Returns the VOB's global path
+Returns the VOB global path
 
 Parameters:
 
@@ -233,7 +233,7 @@ sub shost () {
 
 =head2 shost
 
-Returns the VOB's server host
+Returns the VOB server host
 
 Parameters:
 
@@ -430,7 +430,7 @@ sub replica_uuid () {
 
 =head2 replica_uuid
 
-Returns the VOBS replica_uuid
+Returns the VOB replica_uuid
 
 Parameters:
 
@@ -468,7 +468,7 @@ sub host () {
 
 =head2 host
 
-Returns the VOB's host
+Returns the VOB host
 
 Parameters:
 
@@ -506,7 +506,7 @@ sub access_path () {
 
 =head2 access_path
 
-Returns the VOB's access path
+Returns the VOB access path
 
 Parameters:
 
@@ -628,7 +628,7 @@ sub expand_space () {
   $self->{srcsize} = 0;
   $self->{size}    = 0;
 
-  foreach (@output) {
+  for (@output) {
     if (/(\d*\.\d).*VOB database(.*)/) {
       $self->{dbsize} = $1;
     } elsif (/(\d*\.\d).*administration data(.*)/) {
@@ -642,11 +642,717 @@ sub expand_space () {
     } elsif (/(\d*\.\d).*Subtotal(.*)/) {
       $self->{size} = $1;
     } # if
-  } # foreach
+  } # for
+  
+  return;
+} # expand_space
+
+sub expand_description () {
+  my ($self) = @_;
+
+  my ($status, @output) = $Clearcase::CC->execute ("describe -long vob:$self->{tag}");
+
+  for (my $i = 0; $i < @output; $i++) {
+    if ($output[$i] =~ /created (\S+) by (.+) \((\S+)\)/) {
+      $self->{created}   = $1;
+      $self->{ownername} = $2;
+      $self->{owner}     = $3;
+    } elsif ($output[$i] =~ /^\s+\"(.+)\"/) {
+      $self->{comment} = $1;
+    } elsif ($output[$i] =~ /master replica: (.+)/) {
+      $self->{masterReplica} = $1;
+    } elsif ($output[$i] =~ /replica name: (.+)/) {
+      $self->{replicaName} = $1;
+    } elsif ($output[$i] =~ /VOB family featch level: (\d+)/) {
+      $self->{featureLevel} = $1;
+    } elsif ($output[$i] =~ /database schema version: (\d+)/) {
+      $self->{schemaVersion} = $1;
+    } elsif ($output[$i] =~ /modification by remote privileged user: (.+)/) {
+      $self->{remotePrivilege} = $1;
+    } elsif ($output[$i] =~ /atomic checkin: (.+)/) {
+      $self->{atomicCheckin} = $1;
+    } elsif ($output[$i] =~ /VOB ownership:/) {
+      while ($output[$i] !~ /Additional groups:/) {
+        $i++;
+
+        if ($output[$i++] =~ /owner (.+)/) {
+         $self->{owner} = $1;
+       } # if
+
+       if ($output[$i++] =~ /group (.+)/) {
+         $self->{group} = $1;
+       } # if
+      } # while
+
+      my @groups;
+
+      while ($output[$i] !~ /ACLs enabled/) {
+        if ($output[$i++] =~ /group (.+)/) {
+         push @groups, $1;
+       } # if
+      } # while
+
+      $self->{groups} = \@groups;
+
+      if ($output[$i++] =~ /ACLs enabled: (.+)/) {
+        $self->{aclsEnabled} = $1;
+      } # if
+
+      my %attributes;
+
+      while ($i < @output and $output[$i] !~ /Hyperlinks:/) {
+        if ($output[$i] !~ /Attributes:/) {
+         my ($key, $value) = split / = /, $output[$i];
+
+          # Trim leading spaces
+         $key =~ s/^\s*(\S+)/$1/;
+
+         # Remove unnecessary '"'s
+         $value =~ s/\"(.*)\"/$1/;
+
+         $attributes{$key} = $value;
+       } # if
+
+       $i++;
+      } # while
+      
+      $self->{attributes} = \%attributes;
+
+      $i++;
+
+      my %hyperlinks;
+
+      while ($i < @output and $output[$i]) {
+        my ($key, $value) = split " -> ", $output[$i++];
+
+        # Trim leading spaces
+        $key =~ s/^\s*(\S+)/$1/;
+       
+       $hyperlinks{$key} = $value;
+      } # while
+
+      $self->{hyperlinks} = \%hyperlinks;
+    } # if
+  } # for
   
   return;
 } # expand_space
 
+sub masterReplica() {
+
+=pod
+
+=head2 masterReplica
+
+Returns the VOB master replica
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB master replica
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{masterReplica};
+
+  return $self->{masterReplica}
+} # masterReplica
+
+sub created() {
+
+=pod
+
+=head2 created
+
+Returns the date the VOB was created
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Date the VOB was created
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{created};
+
+  return $self->{created}
+} # created
+
+sub ownername() {
+
+=pod
+
+=head2 ownername
+
+Returns the VOB ownername
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB Owner Name
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{ownername};
+
+  return $self->{ownername}
+} # ownername
+
+sub owner() {
+
+=pod
+
+=head2 owner
+
+Returns the VOB owner
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB master replica
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{owner};
+
+  return $self->{owner}
+} # owner
+
+sub comment() {
+
+=pod
+
+=head2 comment
+
+Returns the VOB comment
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB comment
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{comment};
+
+  return $self->{comment}
+} # comment
+
+sub replicaName() {
+
+=pod
+
+=head2 replicaName
+
+Returns the VOB replicaName
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB replica name
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{replicaName};
+
+  return $self->{replicaName}
+} # replicaName
+
+sub featureLevel() {
+
+=pod
+
+=head2 featureLevel
+
+Returns the VOB featureLevel
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB feature level
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{featureLevel};
+
+  return $self->{featureLevel}
+} # featureLevel
+
+sub schemaVersion() {
+
+=pod
+
+=head2 schemaVersion
+
+Returns the VOB schemaVersion
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB schema version
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{schemaVersion};
+
+  return $self->{schemaVersion}
+} # schemaVersion
+
+sub remotePrivilege() {
+
+=pod
+
+=head2 remotePrivilege
+
+Returns the VOB remotePrivilege
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Remote Privilege capability
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{remotePrivilege};
+
+  return $self->{remotePrivilege}
+} # remotePrivilege
+
+sub atomicCheckin() {
+
+=pod
+
+=head2 atomicCheckin
+
+Returns the VOB atomicCheckin
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Whether atomic check in enabled
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{atomicCheckin};
+
+  return $self->{atomicCheckin}
+} # atomicCheckin
+
+sub group() {
+
+=pod
+
+=head2 group
+
+Returns the VOB group
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB group
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{group};
+
+  return $self->{group}
+} # group
+
+sub groups() {
+
+=pod
+
+=head2 groups
+
+Returns the VOB groups
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB groups
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{groups};
+
+  return @{$self->{groups}}
+} # groups
+
+sub aclsEnabled() {
+
+=pod
+
+=head2 aclsEnabled
+
+Returns the VOB aclsEnabled
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB aclsEnabled
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{aclsEnabled};
+
+  return $self->{aclsEnabled}
+} # aclsEnabled
+
+sub attributes() {
+
+=pod
+
+=head2 attributes
+
+Returns the VOB attributes
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB attributes
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{attributes};
+
+  return %{$self->{attributes}};
+} # attributes
+
+sub hyperlinks() {
+
+=pod
+
+=head2 hyperlinks
+
+Returns the VOB hyperlinks
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item VOB hyperlinks
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($self) = @_;
+
+  $self->expand_description unless $self->{hyperlinks};
+
+  return %{$self->{hyperlinks}};
+} # hyperlinks
+
 sub countdb () {
   my ($self) = @_;
 
@@ -672,7 +1378,7 @@ sub countdb () {
   chomp @output;
 
   # Parse output
-  foreach (@output) {
+  for (@output) {
     if (/^ELEMENT\s*:\s*(\d*)/) {
       $self->{elements} = $1;
     } elsif (/^BRANCH\s*:\s*(\d*)/) {
@@ -680,7 +1386,7 @@ sub countdb () {
     } elsif (/^VERSION\s*:\s*(\d*)/) {
       $self->{versions} = $1;
     } # if
-  } # foreach
+  } # for
 
   chdir $cwd;
   
@@ -1318,7 +2024,7 @@ sub updateVobInfo ($$) {
   # use the create method on, return our blessings...
   return if $status != 0;
 
-  foreach (@output) {
+  for (@output) {
     if (/Global path: (.*)/) {
       $self->{gpath} = $1;
     } elsif (/Server host: (.*)/) {
@@ -1342,7 +2048,7 @@ sub updateVobInfo ($$) {
     } elsif (/Vob registry attributes: (.*)/) {
       $self->{vob_registry_attributes} = $1;
     } # if
- } # foreach
+ } # for
  
  return;
 } # getVobInfo
index 0f2d85f..ad175f4 100644 (file)
@@ -72,12 +72,12 @@ use Clearcase;
 use Display;
 use OSDep;
 
-sub new () {
-  my ($class) = @_;
+sub new (;$) {
+  my ($class, $host, $region) = @_;
 
 =pod
 
-=head2 new (tag)
+=head2 new (host)
 
 Construct a new Clearcase Vobs object.
 
@@ -87,7 +87,10 @@ Parameters:
 
 =over
 
-=item none
+=item host
+
+If host is specified then limit the vob list to only those vobs on that host. If
+host is not specified then all vobs are considered
 
 =back
 
@@ -107,18 +110,13 @@ Returns:
 
 =cut
 
-  my ($status, @output) = $Clearcase::CC->execute ("lsvob -short");
+  my $cmd  = 'lsvob -short';
+     $cmd .= " -host $host"     if $host;
+     $cmd .= " -region $region" if $region;
 
-  return if $status;
+  my ($status, @output) = $Clearcase::CC->execute ($cmd);
 
-  # Strip $VOBTAG_PREFIX
-  foreach (@output) {
-    if ($ARCHITECTURE eq 'windows' or $ARCHITECTURE eq 'cygwin') {
-      s/\\//;
-    } else {
-      s/$Clearcase::VOBTAG_PREFIX//;
-    } # if
-  } # foreach
+  return if $status;
 
   return bless {
     vobs => \@output
index 6920f0b..e6d6ead 100644 (file)
@@ -93,19 +93,13 @@ use Display;
 use Utils;
 
 use Term::ReadLine;
-use Term::ANSIColor qw(color);
+use Term::ANSIColor qw (color);
 
 # Package globals
 my $_pos = 0;
 my $_haveGnu;
 
-my $promptColor = color('bold yellow');
-my $inputColor  = color('underline');
-my $resetColor  = color('reset');
-
-my (%_cmds, $_attribs);
-
-our $_cmdline;
+my (%_cmds, $_cmdline, $_attribs);
 
 BEGIN {
   # See if we can load Term::ReadLine::Gnu
@@ -120,9 +114,7 @@ BEGIN {
 } # BEGIN
 
 # Share %opts
-our %opts = (
-  color => 1,
-);
+our %opts;
 
 my %builtin_cmds = (
   history       => {
@@ -175,7 +167,7 @@ the specified file.',
   },
 );
 
-sub _cmdCompletion($$) {
+sub _cmdCompletion ($$) {
   my ($text, $state) = @_;
 
   return unless %_cmds;
@@ -192,13 +184,13 @@ sub _cmdCompletion($$) {
   return;
 } # _cmdCompletion
 
-sub _complete($$$$) {
+sub _complete ($$$$) {
   my ($text, $line, $start, $end) = @_;
 
   return $_cmdline->completion_matches ($text, \&CmdLine::_cmdCompletion);
 } # _complete
 
-sub _gethelp() {
+sub _gethelp () {
   my ($self) = @_;
 
   return unless %_cmds;
@@ -213,10 +205,10 @@ sub _gethelp() {
 
   # Sometimes we are called by ReadLine's callback and can't pass $self
   if (ref $self eq 'CmdLine') {
-    $self->help($line);
+    $self->help ($line);
   } else {
-    $CmdLine::cmdline->help($line);
-  } # if
+    $CmdLine::cmdline->help ($line);
+  } # if  
 
   $_cmdline->on_new_line;
 } # _gethelp
@@ -225,20 +217,21 @@ sub _interpolate ($) {
   my ($self, $str) = @_;
 
   # Skip interpolation for the perl command (Note this is raid specific)
-  return $str if $str =~ /^\s*perl\s*/i;
+  return $str
+    if $str =~ /^\s*perl\s*/i;
 
   while ($str =~ /\$/) {
     if ($str =~ /\$(\w+)/) {
       my $varname = $1;
 
-      if ($self->{vars}{$varname}) {
-        if ($self->{vars}{$varname} =~ / /) {
-          $str =~ s/\$$varname/\'$self->{vars}{$varname}\'/;
-        } else {
+      if (defined $self->{vars}{$varname}) {
+       if ($self->{vars}{$varname} =~ / /) {
+         $str =~ s/\$$varname/\'$self->{vars}{$varname}\'/;
+       } else {
           $str =~ s/\$$varname/$self->{vars}{$varname}/;
-        } # if
+       } # if
       } else {
-        $str =~ s/\$$varname//;
+       $str =~ s/\$$varname//;
       } # if
     } # if
   } # while
@@ -246,7 +239,7 @@ sub _interpolate ($) {
   return $str;
 } # _interpolate
 
-sub _builtinCmds($) {
+sub _builtinCmds ($) {
   my ($self, $line) = @_;
 
   unless (defined $line) {
@@ -266,7 +259,7 @@ sub _builtinCmds($) {
       system $1;
     } # if
 
-    #$_cmdline->remove_history($_cmdline->where_history);
+    #$_cmdline->remove_history ($_cmdline->where_history);
 
     return;
   } # if
@@ -275,14 +268,15 @@ sub _builtinCmds($) {
     $cmd = $1;
   } # if
 
-  return unless $cmd;
+  return
+    unless $cmd;
 
   my @parms;
 
   # Search for matches of partial commands
   my $foundCmd;
 
-  for (keys %builtin_cmds) {
+  for (keys %builtin_cmds) {    
     if ($_ eq $cmd) {
       # Exact match - honor it
       $foundCmd = $cmd;
@@ -309,7 +303,7 @@ sub _builtinCmds($) {
   if ($builtin_cmds{$cmd}) {
     if ($line =~ /^\s*help\s*(.*)/i) {
       if ($1 =~ /(.+)$/) {
-        $self->help($1);
+        $self->help ($1);
       } else {
         $self->help;
       } # if
@@ -317,22 +311,22 @@ sub _builtinCmds($) {
       if ($1 =~ /(\d+)\s+(\d+)\s*$/) {
         $self->history ('list', $1, $2);
       } elsif ($1 =~ /^\s*$/) {
-        $self->history('list');
+        $self->history ('list');
       } else {
         error "Invalid usage";
-        $self->help('history');
+        $self->help ('history');
       } # if
     } elsif ($line =~ /^\s*savehist\s*(.*)/i) {
       if ($1 =~ /(\S+)\s+(\d+)\s+(\d+)\s*$/) {
-        $self->history('save', $1, $2, $3);
+        $self->history ('save', $1, $2, $3);
       } else {
         error 'Invalid usage';
-        $self->help('savehist');
+        $self->help ('savehist');
       } # if
     } elsif ($line =~ /^\s*get\s*(.*)/i) {
       if ($1 =~ (/^\$*(\S+)\s*$/)) {
-        my $value = $self->_get($1);
-
+        my $value = $self->_get ($1);
+        
         if ($value) {
           display "$1 = $value";
         } else {
@@ -340,14 +334,14 @@ sub _builtinCmds($) {
         } # if
       } else {
         error 'Invalid usage';
-        $self->help('get');
+        $self->help ('get');
       } # if
     } elsif ($line =~ /^\s*set\s*(.*)/i) {
       if ($1 =~ /^\$*(\S+)\s*=\s*(.*)/) {
-        $self->_set($1, $2)
+        $self->_set ($1, $2)
       } else {
         error 'Invalid usage';
-        $self->help('set');
+        $self->help ('set');
       } # if
     } elsif ($line =~ /^\s*source\s+(\S+)/i) {
       $result = $self->source ($1);
@@ -356,12 +350,11 @@ sub _builtinCmds($) {
     } elsif ($line =~ /^\s*color\s*(.*)/i) {
       if ($1 =~ /(1|on)/i) {
         $opts{color} = 1;
-        delete $ENV{ANSI_COLORS_DISABLED} if $ENV{ANSI_COLORS_DISABLED};
-        $self->set_prompt;
+        delete $ENV{ANSI_COLORS_DISABLED}
+          if $ENV{ANSI_COLORS_DISABLED};
       } elsif ($1 =~ /(0|off)/i) {
-        $opts{color} = 0;
+        $opts{trace} = 0;
         $ENV{ANSI_COLORS_DISABLED} = 1;
-        $self->set_prompt;
       } elsif ($1 =~ /\s*$/) {
         if ($ENV{ANSI_COLORS_DISABLED}) {
           display 'Color is currently off';
@@ -370,7 +363,7 @@ sub _builtinCmds($) {
         } # if
       } else {
         error 'Invalid usage';
-        $self->help('color');
+        $self->help ('color');
       } # if
     } elsif ($line =~ /^\s*trace\s*(.*)/i) {
       if ($1 =~ /(1|on)/i) {
@@ -385,7 +378,7 @@ sub _builtinCmds($) {
         } # if
       } else {
         error 'Invalid usage';
-        $self->help('trace');
+        $self->help ('trace');
       } # if
     } # if
   } # if
@@ -395,7 +388,7 @@ sub _builtinCmds($) {
 
 sub _interrupt () {
   # Announce that we have hit an interrupt
-  print color('yellow') . "<Control-C>\n" . color('reset');
+  print color ('yellow') . "<Control-C>\n" . color ('reset');
 
   # Free up all of the line state info
   $_cmdline->free_line_state;
@@ -411,14 +404,14 @@ sub _interrupt () {
   return;
 } # _interrupt
 
-sub _displayMatches($$$) {
+sub _displayMatches ($$$) {
   my ($matches, $numMatches, $maxLength) = @_;
-
+  
   # Work on a copy... (Otherwise we were getting "Attempt to free unreferenced
   # scalar" internal errors from perl)
   my @Matches;
 
-  push @Matches, $_ for (@$matches);
+  push @Matches, $_ for (@$matches);  
 
   my $match = shift @Matches;
 
@@ -443,14 +436,14 @@ sub _displayMatches($$$) {
 
   unshift @newMatches, $match;
 
-  $_cmdline->display_match_list(\@newMatches);
+  $_cmdline->display_match_list (\@newMatches);
   $_cmdline->on_new_line;
   $_cmdline->redisplay;
 
   return;
 } # _displayMatches
-
-sub new(;$$%) {
+  
+sub new (;$$%) {
   my ($class, $histfile, $eval, %cmds) = @_;
 
 =pod
@@ -527,7 +520,7 @@ Returns:
   } # unless
 
   # Instantiate a commandline
-  $_cmdline = Term::ReadLine->new($me);
+  $_cmdline = Term::ReadLine->new ($me);
 
   # Store the function pointer of what to call when sourcing a file or
   # evaluating an expression.
@@ -539,21 +532,17 @@ Returns:
     } # if
   } # if
 
-  $self->{promptColor} = $promptColor;
-  $self->{inputColor}  = $inputColor;
-  $self->{resetColor}  = $resetColor;
-
   # Default prompt is "$me:"
-  $self->set_prompt("$me:");
+  $self->{prompt} = "$me:";
 
   # Set commands
-  $self->set_cmds(%cmds);
+  $self->set_cmds (%cmds);
 
   # Set some ornamentation
-  $_cmdline->ornaments('e,,u') unless $Config{cppflags} =~ /win32/i;
+  $_cmdline->ornaments ('s,e,u,') unless $Config{cppflags} =~ /win32/i;
 
   # Read in history
-  $self->set_histfile($histfile);
+  $self->set_histfile ($histfile);
 
   # Generator function for completion matches
   $_attribs = $_cmdline->Attribs;
@@ -566,7 +555,7 @@ Returns:
   # The following functionality requires Term::ReadLine::Gnu
   if ($_haveGnu) {
     # Bind a key to display completion
-    $_cmdline->add_defun('help-on-command', \&CmdLine::_gethelp, ord ("\cl"));
+    $_cmdline->add_defun ('help-on-command', \&CmdLine::_gethelp, ord ("\cl"));
 
     # Save a handy copy of RL_PROMPT_[START|END]_IGNORE
     $self->{ignstart} = $_cmdline->RL_PROMPT_START_IGNORE;
@@ -581,7 +570,7 @@ Returns:
   return $self;
 } # new
 
-sub get() {
+sub get () {
   my ($self) = @_;
 
 =pod
@@ -624,9 +613,6 @@ Returns:
 
     $prompt =~ s/\\\#/$self->{cmdnbr}/g;
 
-    # Now color it if color is on
-    $prompt = "$self->{resetColor}$self->{promptColor}$prompt$self->{resetColor}$self->{inputColor}" if $self->{promptColor};
-
     use POSIX;
 
     # Term::ReadLine::Gnu restarts whatever system call it is using, such that
@@ -647,32 +633,29 @@ Returns:
       $oldaction = POSIX::SigAction->new;
 
       # Set up our unsafe signal handler
-      POSIX::sigaction(&POSIX::SIGINT, $sigaction, $oldaction);
+      POSIX::sigaction (&POSIX::SIGINT, $sigaction, $oldaction);
     } # if
 
-    $line = $_cmdline->readline($prompt);
-
-    display_nolf $resetColor;
+    $line = $_cmdline->readline ($prompt);
 
     # Restore the old signal handler
     if ($Config{cppflags} !~ /win32/i) {
-      POSIX::sigaction(&POSIX::SIGINT, $oldaction);
+      POSIX::sigaction (&POSIX::SIGINT, $oldaction);
     } # if
 
-    $line = $self->_interpolate($line) if $line;
+    $line = $self->_interpolate ($line)
+      if $line;
 
-    $self->{cmdnbr}++ unless $self->{sourcing};
+    $self->{cmdnbr}++
+      unless $self->{sourcing};
 
-    ($cmd, $line, $result) = $self->_builtinCmds($line);
+    ($cmd, $line, $result) = $self->_builtinCmds ($line);
 
-    $line = '' unless $cmd;
+    $line = ''
+      unless $cmd;
   } while ($cmd and $builtin_cmds{$cmd});
 
-  if (wantarray) {
-    return ($line, $result);
-  } else {
-    return $result || $line;
-  } # if
+  return ($line, $result);
 } # get
 
 sub set_cmds (%) {
@@ -760,22 +743,14 @@ Returns:
 
 =cut
 
-  my $oldPrompt = $self->{prompt};
-
-  $self->{prompt} = $prompt if $prompt;
+  my $return = $self->{prompt};
 
-  if ($opts{color}) {
-    $self->{promptColor} = $promptColor;
-    $self->{resetColor}  = $resetColor;
-  } else {
-    undef $self->{promptColor};
-    undef $self->{resetColor};
-  } # if
+  $self->{prompt} = $prompt;
 
-  return $oldPrompt;
+  return $return;
 } # set_prompt
 
-sub set_histfile($) {
+sub set_histfile ($) {
   my ($self, $histfile) = @_;
 
 =pod
@@ -820,7 +795,7 @@ Returns:
       $_cmdline->clear_history;
 
       # Now read histfile
-      $_cmdline->ReadHistory($histfile);
+      $_cmdline->ReadHistory ($histfile);
     } # if
 
     # Determine the number of lines in the history file
@@ -836,7 +811,7 @@ Returns:
   return;
 } # set_histfile
 
-sub set_eval(;\&) {
+sub set_eval (;\&) {
   my ($self, $eval) = @_;
 
 =pod
@@ -881,7 +856,7 @@ Returns:
   return $returnEval;
 } # set_eval
 
-sub help(;$) {
+sub help (;$) {
   my ($self, $cmd) = @_;
 
 =pod
@@ -938,9 +913,9 @@ Returns:
       if (/$searchStr/i) {
         $helpFound = 1;
 
-        my $cmdcolor = $builtin_cmds{$_} ? color('cyan') : color ('magenta');
-        my $boldOn   = $builtin_cmds{$_} ? color('white on_cyan') : color ('white on_magenta');
-        my $boldOff  = color('reset') . $cmdcolor;
+        my $cmdcolor = $builtin_cmds{$_} ? color ('cyan') : color ('magenta');
+        my $boldOn   = $builtin_cmds{$_} ? color ('white on_cyan') : color ('white on_magenta');
+        my $boldOff  = color ('reset') . $cmdcolor;
 
            $cmd  = "$cmdcolor$_";
            $cmd =~ s/($searchStr)/$boldOn$1$boldOff/g;
@@ -980,12 +955,12 @@ Returns:
     } # for
   } # if
 
-  $self->handleOutput($cmd, @help);
+  $self->handleOutput ($cmd, @help);
 
   return;
 } # help
 
-sub history(;$) {
+sub history (;$) {
   my ($self, $action) = @_;
 
 =pod
@@ -1048,15 +1023,15 @@ Returns:
     $start = $_[3];
     $end   = $_[4];
   } elsif ($action eq 'redo') {
-    $_cmdline->remove_history($_cmdline->where_history);
+    $_cmdline->remove_history ($_cmdline->where_history);
 
     my $nbr  = $_[2];
-    my $line = $_cmdline->history_get($nbr);
+    my $line = $_cmdline->history_get ($nbr);
 
-    $_cmdline->add_history($line);
+    $_cmdline->add_history ($line);
     display $line;
 
-    my ($cmd, $result) = $self->_builtinCmds($line);
+    my ($cmd, $result) = $self->_builtinCmds ($line);
 
     if ($builtin_cmds{$cmd}) {
       return;
@@ -1131,12 +1106,12 @@ Returns:
   return;
 } # history
 
-sub _get($$) {
+sub _get ($$) {
   my ($self, $name) = @_;
 
 =pod
 
-=head2 _get($name)
+=head2 _get ($name)
 
 This method gets a variable to a value stored in the CmdLine
 object.
@@ -1172,7 +1147,7 @@ Returns:
   return $self->{vars}{$name}
 } # _get
 
-sub _set($$) {
+sub _set ($$) {
   my ($self, $name, $value) = @_;
 
 =pod
@@ -1216,14 +1191,14 @@ Returns:
 
   my $returnValue = $self->{vars}{$name};
 
-  if ($value) {
-    $value = $self->_interpolate($value);
+  if (defined $value) {
+    $value = $self->_interpolate ($value);
 
     # Do not call eval if we are setting result - otherwise we recurse
     # infinitely.
     unless ($name eq 'result') {
       no strict;
-      $value = $self->{eval}($value)
+      $value = $self->{eval} ($value)
         if $self->{eval};
       use strict;
     } # unless
@@ -1236,12 +1211,12 @@ Returns:
   return $returnValue;
 } # _set
 
-sub vars($) {
+sub vars ($) {
   my ($self, $cmd) = @_;
 
 =pod
 
-=head2 vars($name)
+=head2 vars ($name)
 
 This method will print out all known variables
 
@@ -1276,10 +1251,10 @@ Returns:
   push @output, "$_ = $self->{vars}{$_}"
     for (keys %{$self->{vars}});
 
-  $self->handleOutput($cmd, @output);
+  $self->handleOutput ($cmd, @output);
 } # vars
 
-sub handleOutput($@) {
+sub handleOutput ($@) {
   my ($self, $line, @output) = @_;
 
 =pod
@@ -1346,14 +1321,17 @@ Returns:
 
     local $SIG{PIPE} = 'IGNORE';
 
-    open $pipe, '|', $pipeToCmd or undef $pipe;
+    open $pipe, '|', $pipeToCmd
+      or undef $pipe;
 
     # TODO: Not handling the output here. Need open2 and then recursively call
     # handleOutput.
     if ($pipe) {
-      print $pipe "$_\n" for (@output);
+      print $pipe "$_\n"
+        for (@output);
 
-      close $pipe or error "Unable to close pipe for $pipeToCmd - $!";
+      close $pipe
+        or error "Unable to close pipe for $pipeToCmd - $!";
     } else {
       error "Unable to open pipe for $pipeToCmd - $!";
     } # if
@@ -1364,7 +1342,8 @@ Returns:
       open my $output, '>', $outToFile;
 
       if ($output) {
-        print $output "$_\n" for (@output);
+        print $output "$_\n"
+          for (@output);
 
         close $output;
 
@@ -1378,7 +1357,7 @@ Returns:
   return;
 } # handleOutput
 
-sub source($) {
+sub source ($) {
   my ($self, $file) = @_;
 
 =pod
@@ -1453,12 +1432,12 @@ Returns:
     $_ = $self->_interpolate ($_);
 
     # Check to see if it's a builtin
-    my ($cmd, $line, $result) = $self->_builtinCmds($_);
+    my ($cmd, $line, $result) = $self->_builtinCmds ($_);
 
     next if $builtin_cmds{$cmd};
 
     no strict;
-    $result = $self->{eval}($line);
+    $result = $self->{eval} ($line);
     use strict;
 
     if (defined $result) {
@@ -1480,7 +1459,7 @@ Returns:
 sub DESTROY {
   my ($self) = @_;
 
-  $_cmdline->WriteHistory($self->{histfile})
+  $_cmdline->WriteHistory ($self->{histfile})
     if $_cmdline and $_haveGnu;
 
   return;
index eddef3a..8aabcaa 100644 (file)
@@ -578,7 +578,7 @@ Returns:
 
 =cut
 
-  open my $pipe, '|-', $to
+  open my $pipe, '|', $to 
     or error "Unable to open pipe - $!", 1;
 
   foreach (@output) {
index 2d31fb8..fcfa0a4 100644 (file)
@@ -121,9 +121,10 @@ if [ -r /etc/bash_completion -a $ARCHITECTURE != "cygwin" ]; then
   source /etc/bash_completion
 fi
 
-# Alias ping
+# Windows aliases
 if [ $ARCHITECTURE = "cygwin" ]; then
   alias ping=$(echo $SYSTEMROOT | tr '\\' '\/')/system32/ping
+  alias rdp=mstsc
 fi
 
 # We specify /home/$USER here so that when we sudo to another user 
index 0ef2f64..e9abf66 100755 (executable)
@@ -63,4 +63,3 @@ append_to_path "/cygdrive/c/Program Files (x86)/ibm/gsk8/lib"
 # Common CDPATHS
 export CT=/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts
 CDPATH=$CDPATH:/vobs/ranccadm:$CT
-
index 6fdaf4b..719fcef 100644 (file)
   diff=auto
   branch=auto
 
+[diff]
+  tool = meld
+
+[difftool]
+  prompt = false
+
+[difftool "meld"]
+  cmd = meld "$LOCAL" "$REMOTE"
+
 # Currently these are restating the default
 [color "branch"]
   current=green
@@ -24,7 +33,7 @@
   remote=red
 
 [color "diff"]
-  external = /usr/local/bin/git-meld
+  external = /bin/meld
 
 [color "status"]
   added=yellow
diff --git a/test/testMDYHMS2SQLDatetime.pl b/test/testMDYHMS2SQLDatetime.pl
new file mode 100755 (executable)
index 0000000..aef0e3b
--- /dev/null
@@ -0,0 +1,107 @@
+#!/usr/bin/env perl\r
+\r
+use strict;\r
+use warnings;\r
+\r
+use FindBin;\r
+use lib "$FindBin::Bin/../lib";\r
+\r
+use Display;\r
+use CmdLine;\r
+\r
+sub _is_leap_year($) {\r
+  my ($year) = @_;\r
+\r
+  return 0 if $year % 4;\r
+  return 1 if $year % 100;\r
+  return 0 if $year % 400;\r
+\r
+  return 1; \r
+} # _is_leap_year\r
+\r
+sub MDYHMS2SQLDatetime($) {\r
+  my ($datetime) = @_;\r
+\r
+  $datetime =~ s/^\s+|\s+$//g;\r
+\r
+  my ($year, $mon, $day, $hour, $min, $sec, $ampm);\r
+\r
+  # For datetime format of MM/DD/YYYY HH:MM:SS [Am|Pm]\r
+  if ($datetime =~ /^(\d{1,2})\/(\d{1,2})\/(\d{4}) (\d{1,2}):(\d{1,2}):(\d{1,2}) (\w{2})$/) {\r
+    $mon   = $1;\r
+    $day   = $2;\r
+    $year  = $3;\r
+    $hour  = $4;\r
+    $min   = $5;\r
+    $sec   = $6;\r
+    $ampm  = $7;\r
+  # For datetime format of MM/DD/YYYY HH:MM:SS\r
+  } elsif ($datetime =~ /^(\d{1,2})\/(\d{1,2})\/(\d{4}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/){\r
+    $mon   = $1;\r
+    $day   = $2;\r
+    $year  = $3;\r
+    $hour  = $4;\r
+    $min   = $5;\r
+    $sec   = $6;\r
+  # For datetime format of MM/DD/YYYY\r
+  } elsif ($datetime =~ /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/) {\r
+    $mon   = $1;\r
+    $day   = $2;\r
+    $year  = $3;\r
+    $hour  = '00';\r
+    $min   = '00';\r
+    $sec   = '00';\r
+  } else {\r
+    return\r
+  } # if\r
+\r
+  # Range checks\r
+  return if $mon  > 12 or $mon  <= 0;\r
+  return if $day  > 31 or $day  <= 0;\r
+  return if $hour > 23 or $hour <  0;\r
+  return if $min  > 59 or $min  <  0;\r
+\r
+  if ($day >= 31 and ($mon == 2\r
+                   or $mon == 4\r
+                   or $mon == 6\r
+                   or $mon == 9\r
+                   or $mon == 11)) {\r
+    return;\r
+  } # if\r
+\r
+  return if $day >  29 and  $mon == 2;\r
+  return if $day == 29 and  $mon == 2 and not _is_leap_year($year);\r
+\r
+  # Convert to 24 hour time if necessary\r
+  $hour += 12 if $ampm and $ampm =~ /pm/i;\r
+\r
+  # Add any leading zeros\r
+  $mon  = "0$mon"  if length $mon  == 1;\r
+  $day  = "0$day"  if length $day  == 1;\r
+  $hour = "0$hour" if length $hour == 1;\r
+  $min  = "0$min"  if length $min  == 1;\r
+  $sec  = "0$sec"  if length $sec  == 1;\r
+\r
+  return "$year-$mon-$day $hour:$min:$sec";\r
+} # MDYHMS2SQLDatetime\r
+\r
+local $| = 1;\r
+\r
+$CmdLine::cmdline->set_prompt('Enter datetime:');\r
+\r
+while () {\r
+  my $datetime = $CmdLine::cmdline->get;\r
+\r
+  last unless defined $datetime;\r
+  last if $datetime =~ /(exit|quit|e|q)/i;\r
+\r
+  if ($datetime) {\r
+    my $newdatetime = MDYHMS2SQLDatetime $datetime;\r
+\r
+    if ($newdatetime) {\r
+      display $newdatetime;\r
+    } else {\r
+      error "Date $datetime is invalid";\r
+    } # if\r
+  } # if\r
+} # while\r