From 0c802537ec02d6cfea4c41b3138535c09a319489 Mon Sep 17 00:00:00 2001 From: Andrew DeFaria Date: Sat, 22 Dec 2018 08:55:07 -0700 Subject: [PATCH] Big update of Clearadm --- bin/findsymlinks.sh | 23 + clearadm/alertlog.cgi | 4 +- clearadm/alerts.cgi | 4 +- clearadm/clearadmscrub.pl | 4 +- clearadm/clearagent.pl | 7 +- clearadm/clearexec.pl | 2 +- clearadm/cleartasks.pl | 55 +- clearadm/deletealertlog.cgi | 4 +- clearadm/discovery.pl | 37 +- clearadm/etc/conf.d/clearadm.conf | 3 +- clearadm/etc/init.d/clearagent | 157 +----- clearadm/etc/init.d/clearagent.linux | 156 ++++++ clearadm/etc/init.d/clearagent.solaris | 5 + clearadm/etc/init.d/cleartasks | 157 +----- clearadm/etc/init.d/cleartasks.linux | 156 ++++++ clearadm/etc/init.d/cleartasks.solaris | 5 + clearadm/filesystems.cgi | 4 +- clearadm/getFilesystems.cgi | 4 +- clearadm/getTimestamp.cgi | 4 +- clearadm/index.cgi | 10 +- clearadm/lib/Clearadm.pm | 683 +++++++++++++---------- clearadm/lib/ClearadmWeb.pm | 219 ++++---- clearadm/lib/User.pm | 2 +- clearadm/lib/clearadm.sql | 32 ++ clearadm/lib/load.sql | 48 +- clearadm/notifications.cgi | 4 +- clearadm/plot.cgi | 96 ++-- clearadm/plotfs.cgi | 2 +- clearadm/plotloadavg.cgi | 6 +- clearadm/plotstorage.cgi | 226 ++++++++ clearadm/processalert.cgi | 4 +- clearadm/processfilesystem.cgi | 4 +- clearadm/processnotification.cgi | 4 +- clearadm/processrunning.pl | 4 +- clearadm/processschedule.cgi | 4 +- clearadm/processsystem.cgi | 10 +- clearadm/processtask.cgi | 4 +- clearadm/readme.cgi | 4 +- clearadm/runlog.cgi | 13 +- clearadm/schedule.cgi | 4 +- clearadm/setup.pl | 106 ++-- clearadm/systemdetails.cgi | 4 +- clearadm/systems.cgi | 4 +- clearadm/tasks.cgi | 4 +- clearadm/test.pl | 4 +- clearadm/updateccfs.pl | 269 +++++++++ clearadm/updatefs.pl | 77 +-- clearadm/updatela.pl | 4 +- clearadm/updatesystem.pl | 47 +- clearadm/viewager.cgi | 143 +++-- clearadm/viewdetails.cgi | 83 ++- clearadm/viewservers.cgi | 4 +- clearadm/vobdetails.cgi | 411 ++++++++++++++ clearadm/vobservers.cgi | 236 +++++++- lib/Clearcase.pm | 1 + lib/Clearcase/Server.pm | 69 ++- lib/Clearcase/View.pm | 378 ++++++++++++- lib/Clearcase/Vob.pm | 732 ++++++++++++++++++++++++- lib/Clearcase/Vobs.pm | 26 +- lib/CmdLine.pm | 221 ++++---- lib/Utils.pm | 2 +- rc/bash_login | 3 +- rc/client_scripts/GD | 1 - rc/gitconfig | 11 +- test/testMDYHMS2SQLDatetime.pl | 107 ++++ 65 files changed, 3918 insertions(+), 1203 deletions(-) create mode 100755 bin/findsymlinks.sh mode change 100755 => 120000 clearadm/etc/init.d/clearagent create mode 100755 clearadm/etc/init.d/clearagent.linux create mode 100755 clearadm/etc/init.d/clearagent.solaris mode change 100755 => 120000 clearadm/etc/init.d/cleartasks create mode 100755 clearadm/etc/init.d/cleartasks.linux create mode 100755 clearadm/etc/init.d/cleartasks.solaris create mode 100755 clearadm/plotstorage.cgi create mode 100755 clearadm/updateccfs.pl create mode 100755 clearadm/vobdetails.cgi create mode 100755 test/testMDYHMS2SQLDatetime.pl diff --git a/bin/findsymlinks.sh b/bin/findsymlinks.sh new file mode 100755 index 0000000..f5d3a95 --- /dev/null +++ b/bin/findsymlinks.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +path=$1 + +if [ -z "$path" ]; then + echo "Usage $0 " + 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 diff --git a/clearadm/alertlog.cgi b/clearadm/alertlog.cgi index e2c1e45..8269699 100755 --- a/clearadm/alertlog.cgi +++ b/clearadm/alertlog.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -151,4 +151,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/alerts.cgi b/clearadm/alerts.cgi index 8bfa1fa..2fb1ede 100755 --- a/clearadm/alerts.cgi +++ b/clearadm/alerts.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -143,4 +143,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/clearadmscrub.pl b/clearadm/clearadmscrub.pl index 8417622..c88ddac 100755 --- a/clearadm/clearadmscrub.pl +++ b/clearadm/clearadmscrub.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl =pod @@ -178,4 +178,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/clearagent.pl b/clearadm/clearagent.pl index 5fae618..fae4519 100755 --- a/clearadm/clearagent.pl +++ b/clearadm/clearagent.pl @@ -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; diff --git a/clearadm/clearexec.pl b/clearadm/clearexec.pl index 53963a7..cd593e5 100755 --- a/clearadm/clearexec.pl +++ b/clearadm/clearexec.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl =pod diff --git a/clearadm/cleartasks.pl b/clearadm/cleartasks.pl index 66c964b..25a297b 100755 --- a/clearadm/cleartasks.pl +++ b/clearadm/cleartasks.pl @@ -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.

    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 .= "
  • Filesystem "; $message .= "$fsinfo{filesystem} is $fsinfo{usedPct}% full. Threshold is "; $message .= "$fsinfo{threshold}%
  • "; - } # foreach + } # for $message .= "
"; @@ -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 diff --git a/clearadm/deletealertlog.cgi b/clearadm/deletealertlog.cgi index e16d4a3..af79c21 100755 --- a/clearadm/deletealertlog.cgi +++ b/clearadm/deletealertlog.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -156,4 +156,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/discovery.pl b/clearadm/discovery.pl index af0b789..49b4b3f 100755 --- a/clearadm/discovery.pl +++ b/clearadm/discovery.pl @@ -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 : Broadcast IP (Default: Current subnet) -broadcastT|ime : 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 . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/etc/conf.d/clearadm.conf b/clearadm/etc/conf.d/clearadm.conf index 38ef606..b1031cf 100644 --- a/clearadm/etc/conf.d/clearadm.conf +++ b/clearadm/etc/conf.d/clearadm.conf @@ -12,6 +12,8 @@ # ############################################################################### Alias /clearadm /opt/clearscm/clearadm + +DirectoryIndex index.cgi index.html 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 AddHandler cgi-script .cgi diff --git a/clearadm/etc/init.d/clearagent b/clearadm/etc/init.d/clearagent deleted file mode 100755 index 99b5e55..0000000 --- a/clearadm/etc/init.d/clearagent +++ /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 -# -# 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 b/clearadm/etc/init.d/clearagent new file mode 120000 index 0000000..0f3fa68 --- /dev/null +++ b/clearadm/etc/init.d/clearagent @@ -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 index 0000000..99b5e55 --- /dev/null +++ b/clearadm/etc/init.d/clearagent.linux @@ -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 +# +# 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 index 0000000..b7c6883 --- /dev/null +++ b/clearadm/etc/init.d/clearagent.solaris @@ -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 diff --git a/clearadm/etc/init.d/cleartasks b/clearadm/etc/init.d/cleartasks deleted file mode 100755 index ddbb1c2..0000000 --- a/clearadm/etc/init.d/cleartasks +++ /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 -# -# 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 b/clearadm/etc/init.d/cleartasks new file mode 120000 index 0000000..904fa9f --- /dev/null +++ b/clearadm/etc/init.d/cleartasks @@ -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 index 0000000..ddbb1c2 --- /dev/null +++ b/clearadm/etc/init.d/cleartasks.linux @@ -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 +# +# 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 index 0000000..c9cd40d --- /dev/null +++ b/clearadm/etc/init.d/cleartasks.solaris @@ -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 diff --git a/clearadm/filesystems.cgi b/clearadm/filesystems.cgi index a278f3a..b2fa03b 100755 --- a/clearadm/filesystems.cgi +++ b/clearadm/filesystems.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -151,4 +151,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/getFilesystems.cgi b/clearadm/getFilesystems.cgi index 88d8084..4a84c87 100755 --- a/clearadm/getFilesystems.cgi +++ b/clearadm/getFilesystems.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -117,4 +117,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/getTimestamp.cgi b/clearadm/getTimestamp.cgi index 2c4212e..b4878d3 100755 --- a/clearadm/getTimestamp.cgi +++ b/clearadm/getTimestamp.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -165,4 +165,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/index.cgi b/clearadm/index.cgi index a5259ea..4fc9cec 100755 --- a/clearadm/index.cgi +++ b/clearadm/index.cgi @@ -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 .= '' if $system{active} eq 'false'; + $load{uptime} ||= 'Unknown'; + display td {class => 'dataCentered'}, "$data ", font {class => 'dim' }, "
Up: $load{uptime}"; } # foreach @@ -203,4 +205,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/lib/Clearadm.pm b/clearadm/lib/Clearadm.pm index 719b772..4205e44 100644 --- a/clearadm/lib/Clearadm.pm +++ b/clearadm/lib/Clearadm.pm @@ -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 => "

An unexpected, internal error occurred in Clearadm:

$msg

", @@ -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 (;$) { +sub SearchSystem(;$) { my ($self, $condition) = @_; $condition = "name like '%'" unless $condition; - return $self->_getRecords ('system', $condition); + return $self->_getRecords('system', $condition); } # 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 .= "Clearadm
"; $footing .= "Copyright © $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 .= "

You will receive this alert no more than $nomorethan.

"; - ($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 diff --git a/clearadm/lib/ClearadmWeb.pm b/clearadm/lib/ClearadmWeb.pm index 17ccb6e..54f164e 100644 --- a/clearadm/lib/ClearadmWeb.pm +++ b/clearadm/lib/ClearadmWeb.pm @@ -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} = ''; } #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 " $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 " $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 "VOB»$ieTableWrapStart"; - display start_ul; - display li a {href => "systemdetails.cgi?system=jupiter"}, ' Jupiter (defaria.com)'; - display end_ul; - display $ieTableWrapEnd; - display end_li; - - display start_li; - display start_a {href => 'views.cgi'}; - display "View»$ieTableWrapStart"; - display start_ul; - display li a {href => "systemdetails.cgi?system=earth"}, ' Earth'; - display li a {href => "systemdetails.cgi?system=mars"}, ' 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 => '#'}, ' /vobs/clearscm'; - display li a {href => '#'}, ' /vobs/clearadm'; - display li a {href => '#'}, ' /vobs/test'; - display li a {href => '#'}, ' /vobs/test2'; - display end_ul; + display a {href => 'vobservers.cgi'}, "   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'}, ' View Ager'; - display li a {href => '#'}, ' 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 '') { $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', ), ); diff --git a/clearadm/lib/User.pm b/clearadm/lib/User.pm index 2203c29..d787d92 100644 --- a/clearadm/lib/User.pm +++ b/clearadm/lib/User.pm @@ -51,7 +51,7 @@ use strict; use warnings; use Carp; -use Net::LDAP; +#use Net::LDAP; use GetConfig; diff --git a/clearadm/lib/clearadm.sql b/clearadm/lib/clearadm.sql index f365201..e722015 100644 --- a/clearadm/lib/clearadm.sql +++ b/clearadm/lib/clearadm.sql @@ -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, diff --git a/clearadm/lib/load.sql b/clearadm/lib/load.sql index 4c005f4..a6efa48 100644 --- a/clearadm/lib/load.sql +++ b/clearadm/lib/load.sql @@ -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' +); + + diff --git a/clearadm/notifications.cgi b/clearadm/notifications.cgi index 040a88f..d444582 100755 --- a/clearadm/notifications.cgi +++ b/clearadm/notifications.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -143,4 +143,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/plot.cgi b/clearadm/plot.cgi index 422f156..9fada55 100755 --- a/clearadm/plot.cgi +++ b/clearadm/plot.cgi @@ -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 '
'; 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 '
'; @@ -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 . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/plotfs.cgi b/clearadm/plotfs.cgi index 3bc8a03..8617e79 100755 --- a/clearadm/plotfs.cgi +++ b/clearadm/plotfs.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod diff --git a/clearadm/plotloadavg.cgi b/clearadm/plotloadavg.cgi index 853edd8..c8acbfa 100755 --- a/clearadm/plotloadavg.cgi +++ b/clearadm/plotloadavg.cgi @@ -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 . 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 index 0000000..22c20ba --- /dev/null +++ b/clearadm/plotstorage.cgi @@ -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 + +=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= type= storage= + [height=] [width=] [color=] + [scaling=] [points=] [tiny=<0|1>] + + Where: + : Tag of the Clearcase object (vob or view) + : Designates whether is a vob of a view + : Name of the Clearcase storage pool to plot information for + : Height of chart (Default: 480px - tiny: 40) + : Width of chart (Default: 800px - tiny: 150) + : A GD::Color color value (Default: lblue) + : Currently one of Minute, Hour, Day or Month. Specifies how + Clearadm::GetFS will scale the data returned (Default: Minute + - tiny: Day) + : 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 +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 + +L + +L + +L + +=head2 ClearSCM Perl Modules + +=begin man + + Clearadm + ClearadmWeb + Display + +=end man + +=begin html + +
+Clearadm
+ClearadmWeb
+Display
+
+ +=end html + +=head1 BUGS AND LIMITATIONS + +There are no known bugs in this script + +Please report problems to Andrew DeFaria . + +=head1 LICENSE AND COPYRIGHT + +Copyright (c) 2010, ClearSCM, Inc. All rights reserved. + +=cut diff --git a/clearadm/processalert.cgi b/clearadm/processalert.cgi index f3fca08..86373a9 100755 --- a/clearadm/processalert.cgi +++ b/clearadm/processalert.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -209,4 +209,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/processfilesystem.cgi b/clearadm/processfilesystem.cgi index 9ade442..9b2f3b2 100755 --- a/clearadm/processfilesystem.cgi +++ b/clearadm/processfilesystem.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -205,4 +205,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/processnotification.cgi b/clearadm/processnotification.cgi index 6889eb4..fa116c8 100755 --- a/clearadm/processnotification.cgi +++ b/clearadm/processnotification.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -223,4 +223,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/processrunning.pl b/clearadm/processrunning.pl index 3eabc4a..c5a2a4f 100755 --- a/clearadm/processrunning.pl +++ b/clearadm/processrunning.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl =pod @@ -186,4 +186,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/processschedule.cgi b/clearadm/processschedule.cgi index 30f4c32..88d0a29 100755 --- a/clearadm/processschedule.cgi +++ b/clearadm/processschedule.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -222,4 +222,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/processsystem.cgi b/clearadm/processsystem.cgi index 8bdd2e2..b68a9ae 100755 --- a/clearadm/processsystem.cgi +++ b/clearadm/processsystem.cgi @@ -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 . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/processtask.cgi b/clearadm/processtask.cgi index cca5801..369d008 100755 --- a/clearadm/processtask.cgi +++ b/clearadm/processtask.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -210,4 +210,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/readme.cgi b/clearadm/readme.cgi index de4a05d..9a259a3 100755 --- a/clearadm/readme.cgi +++ b/clearadm/readme.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -123,4 +123,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/runlog.cgi b/clearadm/runlog.cgi index d0410ed..e5e3f56 100755 --- a/clearadm/runlog.cgi +++ b/clearadm/runlog.cgi @@ -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 . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/schedule.cgi b/clearadm/schedule.cgi index ef3feef..9020c18 100755 --- a/clearadm/schedule.cgi +++ b/clearadm/schedule.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -139,4 +139,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/setup.pl b/clearadm/setup.pl index 7724992..98a0094 100755 --- a/clearadm/setup.pl +++ b/clearadm/setup.pl @@ -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 diff --git a/clearadm/systemdetails.cgi b/clearadm/systemdetails.cgi index 1014e03..6cb81cf 100755 --- a/clearadm/systemdetails.cgi +++ b/clearadm/systemdetails.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -279,4 +279,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/systems.cgi b/clearadm/systems.cgi index 4346c93..1f7aba7 100755 --- a/clearadm/systems.cgi +++ b/clearadm/systems.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -286,4 +286,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/tasks.cgi b/clearadm/tasks.cgi index 518103a..8400203 100755 --- a/clearadm/tasks.cgi +++ b/clearadm/tasks.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -142,4 +142,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/test.pl b/clearadm/test.pl index 8e89bbb..3447284 100755 --- a/clearadm/test.pl +++ b/clearadm/test.pl @@ -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 index 0000000..ff4dd25 --- /dev/null +++ b/clearadm/updateccfs.pl @@ -0,0 +1,269 @@ +#!/usr/local/bin/perl + +=pod + +=head1 NAME $RCSfile: updateccstorage.pl,v $ + +Update Filesystem + +=head1 VERSION + +=over + +=item Author + +Andrew DeFaria + +=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 [|all]| -vob [|all]] + + Where: + -u|sage: Displays usage + + -ve|rbose: Be verbose + -deb|ug: Output debug messages + + -view [|all] Update view storage (Default: all) + -vob [|all] Update vob storage (Default: all) + -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 + +L + +L + +=head2 ClearSCM Perl Modules + +=begin man + + Clearadm + Clearexec + DateUtils + Display + Utils + +=end man + +=begin html + +
+Clearadm
+Clearcase::Vobs
+Clearcase::Vob
+Clearcase::Views
+Clearcase::View
+DateUtils
+Display
+Utils
+
+ +=end html + +=head1 BUGS AND LIMITATIONS + +There are no known bugs in this script + +Please report problems to Andrew DeFaria . + +=head1 LICENSE AND COPYRIGHT + +Copyright (c) 2010, ClearSCM, Inc. All rights reserved. + +=cut diff --git a/clearadm/updatefs.pl b/clearadm/updatefs.pl index 7340dde..86df94c 100755 --- a/clearadm/updatefs.pl +++ b/clearadm/updatefs.pl @@ -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; diff --git a/clearadm/updatela.pl b/clearadm/updatela.pl index 5c8c078..e9b4b38 100755 --- a/clearadm/updatela.pl +++ b/clearadm/updatela.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl =pod @@ -245,4 +245,4 @@ Please report problems to Andrew DeFaria . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/updatesystem.pl b/clearadm/updatesystem.pl index 784303f..f5fbb06 100755 --- a/clearadm/updatesystem.pl +++ b/clearadm/updatesystem.pl @@ -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); diff --git a/clearadm/viewager.cgi b/clearadm/viewager.cgi index c283ebe..9ac1b1e 100755 --- a/clearadm/viewager.cgi +++ b/clearadm/viewager.cgi @@ -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 to use when looking for the view + -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, '
', + setField($Clearcase::CC->registry_host), '
', 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 ($@) {

Won't you take a moment to review this message and clean up any views you no longer need?

-

The following views are owned by you and have not been modified in $ageThreshold +

The following views are owned by you and have not been modified in $opts{ageThreshold} days:

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 . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/viewdetails.cgi b/clearadm/viewdetails.cgi index 51e4265..72b486b 100755 --- a/clearadm/viewdetails.cgi +++ b/clearadm/viewdetails.cgi @@ -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'}, '<no-gpath>' if $gpath eq ''; @@ -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 . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/clearadm/viewservers.cgi b/clearadm/viewservers.cgi index 1b91175..f214c04 100755 --- a/clearadm/viewservers.cgi +++ b/clearadm/viewservers.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl =pod @@ -221,4 +221,4 @@ Please report problems to Andrew DeFaria . 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 index 0000000..89a38d6 --- /dev/null +++ b/clearadm/vobdetails.cgi @@ -0,0 +1,411 @@ +#!/usr/local/bin/perl + +=pod + +=head1 NAME $RCSfile: vobdetails.cgi,v $ + +View Details + +=head1 VERSION + +=over + +=item Author + +Andrew DeFaria + +=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 ] -vo|b + [-ve|rbose] [-d|ebug] + + Where: + -u|sage: Displays usage + -r|egion : Region to use when looking for the vob + -vo|b : 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'}, '<no-gpath>' + if $gpath eq ''; + + 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 "
", $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{$_}
"; + } # 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{$_}
"; + } # 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 + +L + +L + +L + +=head2 ClearSCM Perl Modules + +=begin man + + ClearadmWeb + Clearcase + Clearcase::View + Clearcase::Views + Display + Utils + +=end man + +=begin html + +
+ClearadmWeb
+Clearcase
+Clearcase::View
+Clearcase::Views
+Display
+Utils
+
+ +=end html + +=head1 BUGS AND LIMITATIONS + +There are no known bugs in this script + +Please report problems to Andrew DeFaria . + +=head1 LICENSE AND COPYRIGHT + +Copyright (c) 2010, ClearSCM, Inc. All rights reserved. + +=cut diff --git a/clearadm/vobservers.cgi b/clearadm/vobservers.cgi index 453fd09..6748c9e 100755 --- a/clearadm/vobservers.cgi +++ b/clearadm/vobservers.cgi @@ -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', + }, ' '; + 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 . Copyright (c) 2010, ClearSCM, Inc. All rights reserved. -=cut \ No newline at end of file +=cut diff --git a/lib/Clearcase.pm b/lib/Clearcase.pm index a845184..e9b58ff 100644 --- a/lib/Clearcase.pm +++ b/lib/Clearcase.pm @@ -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; diff --git a/lib/Clearcase/Server.pm b/lib/Clearcase/Server.pm index 0021a5c..c47e321 100644 --- a/lib/Clearcase/Server.pm +++ b/lib/Clearcase/Server.pm @@ -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 diff --git a/lib/Clearcase/View.pm b/lib/Clearcase/View.pm index 7a59cd2..79dea02 100644 --- a/lib/Clearcase/View.pm +++ b/lib/Clearcase/View.pm @@ -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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view private storage + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view private storage + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view database size + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view database percent + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view admin size + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view admin percent + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view space + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item view space percent + +=back + +=for html
+ +=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 diff --git a/lib/Clearcase/Vob.pm b/lib/Clearcase/Vob.pm index ca4f765..596fafb 100644 --- a/lib/Clearcase/Vob.pm +++ b/lib/Clearcase/Vob.pm @@ -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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB master replica + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item Date the VOB was created + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB Owner Name + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB master replica + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB comment + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB replica name + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB feature level + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB schema version + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item Remote Privilege capability + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item Whether atomic check in enabled + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB group + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB groups + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB aclsEnabled + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB attributes + +=back + +=for html
+ +=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
+ +=over + +=item none + +=back + +=for html
+ +Returns: + +=for html
+ +=over + +=item VOB hyperlinks + +=back + +=for html
+ +=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 diff --git a/lib/Clearcase/Vobs.pm b/lib/Clearcase/Vobs.pm index 0f2d85f..ad175f4 100644 --- a/lib/Clearcase/Vobs.pm +++ b/lib/Clearcase/Vobs.pm @@ -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 diff --git a/lib/CmdLine.pm b/lib/CmdLine.pm index 6920f0b..e6d6ead 100644 --- a/lib/CmdLine.pm +++ b/lib/CmdLine.pm @@ -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') . "\n" . color('reset'); + print color ('yellow') . "\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; diff --git a/lib/Utils.pm b/lib/Utils.pm index eddef3a..8aabcaa 100644 --- a/lib/Utils.pm +++ b/lib/Utils.pm @@ -578,7 +578,7 @@ Returns: =cut - open my $pipe, '|-', $to + open my $pipe, '|', $to or error "Unable to open pipe - $!", 1; foreach (@output) { diff --git a/rc/bash_login b/rc/bash_login index 2d31fb8..fcfa0a4 100644 --- a/rc/bash_login +++ b/rc/bash_login @@ -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 diff --git a/rc/client_scripts/GD b/rc/client_scripts/GD index 0ef2f64..e9abf66 100755 --- a/rc/client_scripts/GD +++ b/rc/client_scripts/GD @@ -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 - diff --git a/rc/gitconfig b/rc/gitconfig index 6fdaf4b..719fcef 100644 --- a/rc/gitconfig +++ b/rc/gitconfig @@ -17,6 +17,15 @@ 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 index 0000000..aef0e3b --- /dev/null +++ b/test/testMDYHMS2SQLDatetime.pl @@ -0,0 +1,107 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use FindBin; +use lib "$FindBin::Bin/../lib"; + +use Display; +use CmdLine; + +sub _is_leap_year($) { + my ($year) = @_; + + return 0 if $year % 4; + return 1 if $year % 100; + return 0 if $year % 400; + + return 1; +} # _is_leap_year + +sub MDYHMS2SQLDatetime($) { + my ($datetime) = @_; + + $datetime =~ s/^\s+|\s+$//g; + + my ($year, $mon, $day, $hour, $min, $sec, $ampm); + + # For datetime format of MM/DD/YYYY HH:MM:SS [Am|Pm] + if ($datetime =~ /^(\d{1,2})\/(\d{1,2})\/(\d{4}) (\d{1,2}):(\d{1,2}):(\d{1,2}) (\w{2})$/) { + $mon = $1; + $day = $2; + $year = $3; + $hour = $4; + $min = $5; + $sec = $6; + $ampm = $7; + # For datetime format of MM/DD/YYYY HH:MM:SS + } elsif ($datetime =~ /^(\d{1,2})\/(\d{1,2})\/(\d{4}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/){ + $mon = $1; + $day = $2; + $year = $3; + $hour = $4; + $min = $5; + $sec = $6; + # For datetime format of MM/DD/YYYY + } elsif ($datetime =~ /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/) { + $mon = $1; + $day = $2; + $year = $3; + $hour = '00'; + $min = '00'; + $sec = '00'; + } else { + return + } # if + + # Range checks + return if $mon > 12 or $mon <= 0; + return if $day > 31 or $day <= 0; + return if $hour > 23 or $hour < 0; + return if $min > 59 or $min < 0; + + if ($day >= 31 and ($mon == 2 + or $mon == 4 + or $mon == 6 + or $mon == 9 + or $mon == 11)) { + return; + } # if + + return if $day > 29 and $mon == 2; + return if $day == 29 and $mon == 2 and not _is_leap_year($year); + + # Convert to 24 hour time if necessary + $hour += 12 if $ampm and $ampm =~ /pm/i; + + # Add any leading zeros + $mon = "0$mon" if length $mon == 1; + $day = "0$day" if length $day == 1; + $hour = "0$hour" if length $hour == 1; + $min = "0$min" if length $min == 1; + $sec = "0$sec" if length $sec == 1; + + return "$year-$mon-$day $hour:$min:$sec"; +} # MDYHMS2SQLDatetime + +local $| = 1; + +$CmdLine::cmdline->set_prompt('Enter datetime:'); + +while () { + my $datetime = $CmdLine::cmdline->get; + + last unless defined $datetime; + last if $datetime =~ /(exit|quit|e|q)/i; + + if ($datetime) { + my $newdatetime = MDYHMS2SQLDatetime $datetime; + + if ($newdatetime) { + display $newdatetime; + } else { + error "Date $datetime is invalid"; + } # if + } # if +} # while -- 2.17.1