X-Git-Url: https://defaria.com/gitweb/?a=blobdiff_plain;ds=inline;f=clearadm%2Flib%2FClearadm.pm;h=a9bcb364e9f1d67937cfe92d7ca2f597c8fa9919;hb=77469c863330f5d3d547cfc02562d179e6be9799;hp=fb63079c385888de4b13382a320543ee1c448e02;hpb=ffa5a122584a2218799bfd6dccbee689670fdf75;p=clearscm.git diff --git a/clearadm/lib/Clearadm.pm b/clearadm/lib/Clearadm.pm index fb63079..a9bcb36 100644 --- a/clearadm/lib/Clearadm.pm +++ b/clearadm/lib/Clearadm.pm @@ -36,9 +36,9 @@ specifics about the method you are envoking. # Create new Clearadm object my $clearadm = new Clearadm; - + # Add a new system - my %system = ( + my %system =( name => 'jupiter', alias => 'defaria.com', admin => 'Andrew DeFaria', @@ -46,31 +46,31 @@ specifics about the method you are envoking. type => 'Linux', description => 'Home server', ); - - my ($err, $msg) = $clearadm->AddSystem (%system); - + + my ($err, $msg) = $clearadm->AddSystem(%system); + # Find systems matching 'jup' - my @systems = $clearadm->FindSystem ('jup'); - + my @systems = $clearadm->FindSystem('jup'); + # Get a system by name - my %system = $clearadm->GetSystem ('jupiter'); - + my %system = $clearadm->GetSystem('jupiter'); + # Update system my %update = ( 'region' => 'East Coast', ); my ($err, $msg) = $clearadm->UpdateSystem ('jupiter', %update); - + # Delete system (Warning: will delete all related records regarding this # system). - my ($err, $msg) = $clearadm->DeleteSystem ('jupiter'); + my ($err, $msg) = $clearadm->DeleteSystem('jupiter'); =head1 DESCRIPTION This package provides and object oriented interface to the Clearadm database. -Methods are provided to manipulate records by adding, updating and deleting -them. In general you need to specify a hash which contains keys and values +Methods are provided to manipulate records by adding, updating and deleting +them. In general you need to specify a hash which contains keys and values corresponding to the database field names and values. =head1 ROUTINES @@ -88,6 +88,7 @@ use Carp; use DBI; use File::Basename; use Net::Domain qw(hostdomain); +use Sys::Hostname; use FindBin; @@ -97,27 +98,29 @@ use DateUtils; use Display; use GetConfig; use Mail; +use Clearcase::Vob; +use Clearcase::View; -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 $'; ($VERSION) = ($VERSION =~ /\$Revision: (.*) /); - -$CLEAROPTS{CLEARADM_USERNAME} = $ENV{CLEARADM_USERNAME} + +$CLEAROPTS{CLEARADM_USERNAME} = $ENV{CLEARADM_USERNAME} ? $ENV{CLEARADM_USERNAME} : $CLEAROPTS{CLEARADM_USERNAME} ? $CLEAROPTS{CLEARADM_USERNAME} : 'clearwriter'; -$CLEAROPTS{CLEARADM_PASSWORD} = $ENV{CLEARADM_PASSWORD} +$CLEAROPTS{CLEARADM_PASSWORD} = $ENV{CLEARADM_PASSWORD} ? $ENV{CLEARADM_PASSWORD} : $CLEAROPTS{CLEARADM_PASSWORD} ? $CLEAROPTS{CLEARADM_PASSWORD} : 'clearwriter'; -$CLEAROPTS{CLEARADM_SERVER} = $ENV{CLEARADM_SERVER} - ? $ENV{CLEARADM_SERVER} +$CLEAROPTS{CLEARADM_SERVER} = $ENV{CLEARADM_SERVER} + ? $ENV{CLEARADM_SERVER} : $CLEAROPTS{CLEARADM_SERVER} ? $CLEAROPTS{CLEARADM_SERVER} : 'localhost'; @@ -127,152 +130,149 @@ my $defaultFilesystemHist = '6 months'; my $defaultLoadavgHist = '6 months'; # Internal methods -sub _dberror ($$) { +sub _dberror($$) { my ($self, $msg, $statement) = @_; my $dberr = $self->{db}->err; my $dberrmsg = $self->{db}->errstr; - + $dberr ||= 0; $dberrmsg ||= 'Success'; my $message = ''; - + if ($dberr) { - my $function = (caller (1)) [3]; + my $function = (caller(1)) [3]; $message = "$function: $msg\nError #$dberr: $dberrmsg\n" . "SQL Statement: $statement"; } # if - return $dberr, $message; + return $dberr, $message; } # _dberror -sub _formatValues (@) { +sub _formatValues(@) { my ($self, @values) = @_; - + my @returnValues; - + # Quote data values - push @returnValues, $_ eq '' ? 'null' : $self->{db}->quote ($_) - foreach (@values); - + 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{$_}) - foreach (keys %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); - - return $self->_dberror ("Unable to add record to $table", $statement); + + $self->{db}->do($statement); + + return $self->_dberror("Unable to add record to $table", $statement); } # _addRecord -sub _deleteRecord ($;$) { +sub _deleteRecord($;$) { my ($self, $table, $condition) = @_; - + my $count; - + my $statement = "select count(*) from $table "; - $statement .= "where $condition" - if $condition; - - my $sth = $self->{db}->prepare ($statement) - or return $self->_dberror ('Unable to prepare statement', $statement); - + $statement .= "where $condition" if $condition; + + 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; - + $sth->finish; - + if ($row[0]) { $count = $row[0]; } else { $count = 0; } # if - - return ($count, 'Records deleted') - if $count == 0; - + + return ($count, 'Records deleted') if $count == 0; + $statement = "delete from $table "; - $statement .= "where $condition" - if $condition; - - $self->{db}->do ($statement); - + $statement .= "where $condition" if $condition; + + $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 .= " where $condition" - if $condition; - - $self->{db}->do ($statement); - - return $self->_dberror ("Unable to update record in $table", $statement); + $statement .= join ',', $self->_formatNameValues(%rec); + $statement .= " where $condition" if $condition; + + $self->{db}->do($statement); + + return $self->_dberror("Unable to update record in $table", $statement); } # _updateRecord -sub _checkRequiredFields ($$) { +sub _checkRequiredFields($$) { my ($fields, $rec) = @_; - - foreach my $fieldname (@$fields) { + + for my $fieldname (@$fields) { my $found = 0; - - foreach (keys %$rec) { + + for (keys %$rec) { if ($fieldname eq $_) { $found = 1; last; } # if - } # foreach - - return "$fieldname is required" - unless $found; - } # foreach - + } # for + + return "$fieldname is required" unless $found; + } # for + 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"; - - my $sth = $self->{db}->prepare ($statement); - + + $additional ||= ''; + + my $statement = "select * from $table"; + $statement .= " where $condition" if $condition; + $statement .= $additional; + + 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 @@ -280,224 +280,222 @@ sub _getRecords ($$) { my $maxAttempts = 3; my $sleepTime = 30; my $status; - + # We've been having the server going away. Supposedly it should reconnect so - # here we simply retry up to $maxAttempts times to re-execute the statement. + # here we simply retry up to $maxAttempts times to re-execute the statement. # (Are there other places where we need to do this?) $err = 2006; - + while ($err == 2006 and $attempts++ < $maxAttempts) { $status = $sth->execute; - + if ($status) { $err = 0; last; } else { - ($err, $msg) = $self->_dberror ('Unable to execute statement', + ($err, $msg) = $self->_dberror('Unable to execute statement', $statement); } # if - + last if $err == 0; - + croak $msg unless $err == 2006; 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; - + while (my $row = $sth->fetchrow_hashref) { push @records, $row; } # 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}; } else { - return; + return; } # 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 - + 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 - + my @records; my @row = $sth->fetchrow_array; - + return $row[0]; } # _getLastID -sub _connect (;$) { +sub _connect(;$) { my ($self, $dbserver) = @_; - + $dbserver ||= $CLEAROPTS{CLEARADM_SERVER}; - + my $dbname = 'clearadm'; my $dbdriver = 'mysql'; - $self->{db} = DBI->connect ( - "DBI:$dbdriver:$dbname:$dbserver", + $self->{db} = DBI->connect( + "DBI:$dbdriver:$dbname:$dbserver", $CLEAROPTS{CLEARADM_USERNAME}, $CLEAROPTS{CLEARADM_PASSWORD}, {PrintError => 0}, - ) or croak ( - "Couldn't connect to $dbname database " + ) or croak( + "Couldn't connect to $dbname database " . "as $CLEAROPTS{CLEARADM_USERNAME}\@$CLEAROPTS{CLEARADM_SERVER}" ); - + $self->{dbserver} = $dbserver; - + 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}; - + return; } # SetNotify -sub Error ($;$) { +sub Error($;$) { my ($self, $msg, $errno) = @_; # If $errno is specified we need to stop. However we need to notify somebody - # that cleartasks is no longer running. + # that cleartasks is no longer running. error $msg; - + 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
", mode => 'html', ); - + exit $errno if $errno > 0; } # if } # if - + return; } # Error -sub AddSystem (%) { +sub AddSystem(%) { my ($self, %system) = @_; - + my @requiredFields = ( 'name', ); my $result = _checkRequiredFields \@requiredFields, \%system; - - return -1, "AddSystem: $result" - if $result; - + + return -1, "AddSystem: $result" if $result; + $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 ( - 'system', + + return unless $system; + + my @records = $self->_getRecords( + 'system', "name='$system' or alias like '%$system%'" ); - + if ($records[0]) { return %{$records[0]}; } else { - return; + return; } # 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 = ( 'system', 'name', @@ -505,73 +503,67 @@ sub AddPackage (%) { ); my $result = _checkRequiredFields \@requiredFields, \%package; - - return -1, "AddPackage: $result" - if $result; - - return $self->_addRecord ('package', %package); + + return -1, "AddPackage: $result" if $result; + + return $self->_addRecord('package', %package); } # AddPackage -sub DeletePackage ($$) { +sub DeletePackage($$) { my ($self, $system, $name) = @_; - - return $self->_deleteRecord ( - 'package', + + 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); - - return - unless $system; - - return $self->_updateRecord ('package', "system='$system'", %update); + + $system = $self->_aliasSystem($system); + + return unless $system; + + return $self->_updateRecord('package', "system='$system'", %update); } # UpdatePackage sub GetPackage($$) { my ($self, $system, $name) = @_; - - $system = $self->_aliasSystem ($system); - - return - unless $system; - - return - unless $name; - - my @records = $self->_getRecords ( - 'package', + + $system = $self->_aliasSystem($system); + + return unless $system; + return unless $name; + + my @records = $self->_getRecords( + 'package', "system='$system' and name='$name'" ); - + if ($records[0]) { return %{$records[0]}; } else { - return; + return; } # if } # GetPackage -sub FindPackage ($;$) { +sub FindPackage($;$) { my ($self, $system, $name) = @_; $name ||= ''; - $system = $self->_aliasSystem ($system); - - return - unless $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 = ( 'system', 'filesystem', @@ -579,61 +571,55 @@ sub AddFilesystem (%) { ); my $result = _checkRequiredFields \@requiredFields, \%filesystem; - - return -1, "AddFilesystem: $result" - if $result; - + + return -1, "AddFilesystem: $result" if $result; + # 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); - - return - unless $system; - - return $self->_deleteRecord ( - 'filesystem', + + $system = $self->_aliasSystem($system); + + return unless $system; + + return $self->_deleteRecord( + 'filesystem', "system='$system' and filesystem='$filesystem'" ); } # DeleteFilesystem -sub UpdateFilesystem ($$%) { +sub UpdateFilesystem($$%) { my ($self, $system, $filesystem, %update) = @_; - - $system = $self->_aliasSystem ($system); - - return - unless $system; - - return $self->_updateRecord ( + + $system = $self->_aliasSystem($system); + + return unless $system; + + return $self->_updateRecord( 'filesystem', "system='$system' and filesystem='$filesystem'", %update ); } # UpdateFilesystem -sub GetFilesystem ($$) { +sub GetFilesystem($$) { my ($self, $system, $filesystem) = @_; - - $system = $self->_aliasSystem ($system); - - return - unless $system; - - return - unless $filesystem; - - my @records = $self->_getRecords ( - 'filesystem', + + $system = $self->_aliasSystem($system); + + return unless $system; + return unless $filesystem; + + my @records = $self->_getRecords( + 'filesystem', "system='$system' and filesystem='$filesystem'" ); - + if ($records[0]) { return %{$records[0]}; } else { @@ -641,156 +627,199 @@ sub GetFilesystem ($$) { } # if } # GetFilesystem -sub FindFilesystem ($;$) { +sub FindFilesystem($;$) { my ($self, $system, $filesystem) = @_; - + $filesystem ||= ''; - $system = $self->_aliasSystem ($system); - - return - unless $system; + $system = $self->_aliasSystem($system); + + return unless $system; - my $condition = "system='$system' and filesystem like '%$filesystem%'"; - - return $self->_getRecords ('filesystem', $condition); + my $condition = "system='$system' and filesystem like '%$filesystem%'"; + + return $self->_getRecords('filesystem', $condition); } # FindFilesystem -sub AddVob (%) { +sub AddVob(%) { my ($self, %vob) = @_; - + my @requiredFields = ( - 'system', 'tag', + 'region', ); my $result = _checkRequiredFields \@requiredFields, \%vob; - - return -1, "AddVob: $result" - if $result; - - return $self->_addRecord ('vob', %vob); + + return -1, "AddVob: $result" if $result; + + return $self->_addRecord('vob', %vob); } # AddVob -sub DeleteVob ($) { - my ($self, $tag) = @_; - - return $self->_deleteRecord ('vob', "tag='$tag'"); +sub DeleteVob($$) { + my ($self, $tag, $region) = @_; + + return $self->_deleteRecord('vob', "tag='$tag' and region='$region'"); } # DeleteVob -sub GetVob ($) { - my ($self, $tag) = @_; - - return - unless $tag; - - my @records = $self->_getRecords ('vob', "tag='$tag'"); - +sub GetVob($$) { + my ($self, $tag, $region) = @_; + + return unless $tag; + + # Windows vob tags begin with "\", which is problematic. The solution is to + # escape the "\" + $tag =~ s/^\\/\\\\/; + + my @records = $self->_getRecords('vob', "tag='$tag' and region='$region'"); + if ($records[0]) { return %{$records[0]}; } else { - return; + return; } # if } # GetVob -sub FindVob ($) { - my ($self, $tag) = @_; +<<<<<<< HEAD +sub FindVobStorage(;$$) { + my ($self, $tag, $region) = @_; + + $tag ||= ''; + $region ||= ''; + +======= +sub FindVob($;$) { + my ($self, $tag, $region) = @_; + + # Windows vob tags begin with "\", which is problematic. The solution is to + # escape the "\" + $tag =~ s/^\\/\\\\/; + + my $condition = "tag like '%$tag%'"; + + $condition .= " and region='$region'" if $region; + + return $self->_getRecords('vobstorage', $condition); +} # FindVobStorage + +sub FindVob(;$$) { + my ($self, $tag, $region) = @_; + + $tag ||= ''; + $region ||= ''; + + # Windows vob tags begin with "\", which is problematic. The solution is to + # escape the "\" + $tag =~ s/^\\/\\\\/; + + my $condition = "tag like '%$tag%'"; - return $self->_getRecords ('vob', "tag like '%$tag%'"); + $condition .= " and region='$region'" if $region; + + return $self->_getRecords('vob', $condition); } # FindVob -sub AddView (%) { +sub UpdateVob(%) { + my ($self, %vob) = @_; + + # Windows vob tags begin with "\", which is problematic. The solution is to + # escape the "\" + my $vobtag = $vob{tag}; + + $vobtag =~ s/^\\/\\\\/; + + return $self->_updateRecord('vob', "tag='$vobtag' and region='$vob{region}'", %vob); +} # UpdateVob + +sub AddView(%) { my ($self, %view) = @_; - + my @requiredFields = ( - 'system', 'tag', + 'region' ); my $result = _checkRequiredFields \@requiredFields, \%view; - - return -1, "AddView: $result" - if $result; - - return $self->_addRecord ('view', %view); + + return -1, "AddView: $result" if $result; + + return $self->_addRecord('view', %view); } # AddView -sub DeleteView ($) { - my ($self, $tag) = @_; - - return $self->_deleteRecord ('vob', "tag='$tag'"); +sub DeleteView($$) { + my ($self, $tag, $region) = @_; + + return $self->_deleteRecord('vob', "tag='$tag' and region='$region'"); } # DeleteView -sub GetView ($) { - my ($self, $tag) = @_; - - return - unless $tag; - - my @records = $self->_getRecords ('view', "tag='$tag'"); - +sub UpdateView(%) { + my ($self, %view) = @_; + + return $self->_updateRecord('view', "tag='$view{tag}' and region='$view{region}'", %view); +} # UpdateView + +sub GetView($$) { + my ($self, $tag, $region) = @_; + + return unless $tag; + + my @records = $self->_getRecords('view', "tag='$tag' and region='$region'"); + if ($records[0]) { return %{$records[0]}; } else { - return; + return; } # if } # GetView -sub FindView (;$$$$) { - my ($self, $system, $region, $tag, $ownerName) = @_; +sub FindView(;$$$$) { + my ($self, $tag, $region, $ownerName) = @_; - $system ||= ''; - $region ||= ''; - $tag ||= ''; - $ownerName ||= ''; - my $condition; - - $condition = "system like '%$system%'"; - $condition .= ' and '; - $condition = "region like '%$region%'"; - $condition .= ' and '; - $condition .= "tag like '%$tag'"; - $condition .= ' and '; - $condition .= "ownerName like '%$ownerName'"; - - return $self->_getRecords ('view', $condition); + my @conditions; + + push @conditions, "tag like '%$tag%'" if $tag; + push @conditions, "region = '$region'" if $region; + push @conditions, "ownerName like '$ownerName'" if $ownerName; + + $condition = join " and ", @conditions if @conditions; + + return $self->_getRecords('view', $condition); } # FindView -sub AddFS (%) { +sub AddFS(%) { my ($self, %fs) = @_; - + my @requiredFields = ( 'system', 'filesystem', ); my $result = _checkRequiredFields \@requiredFields, \%fs; - + return -1, "AddFS: $result" if $result; - + # 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); - - return - unless %filesystem; - - my %task = $self->GetTask ('scrub'); - - $self->Error ("Unable to find scrub task!", 1) unless %task; - + + my %filesystem = $self->GetFilesystem($system, $filesystem); + + return unless %filesystem; + + my %task = $self->GetTask('scrub'); + + $self->Error("Unable to find scrub task!", 1) unless %task; + my $days; my $today = Today2SQLDatetime; - + # TODO: SubtractDays uses just an approximation (i.e. subtracting 30 days when # in February is not right. if ($filesystem{filesystemHist} =~ /(\d+) month/i) { @@ -800,44 +829,42 @@ sub TrimFS ($$) { } # if my $oldage = SubtractDays $today, $days; - - my ($dberr, $dbmsg) = $self->_deleteRecord ( + + my ($dberr, $dbmsg) = $self->_deleteRecord( 'fs', "system='$system' and filesystem='$filesystem' and timestamp<='$oldage'" ); - + if ($dbmsg eq 'Records deleted') { - return (0, $dbmsg) - if $dberr == 0; - + return (0, $dbmsg) if $dberr == 0; + my %runlog; - + $runlog{task} = $task{name}; $runlog{started} = $today; $runlog{status} = 0; - $runlog{message} = + $runlog{message} = "Scrubbed $dberr fs records for filesystem $system:$filesystem"; - - my ($err, $msg) = $self->AddRunlog (%runlog); - - $self->Error ("Unable to add runlog - (Error: $err)\n$msg") if $err; + + my ($err, $msg) = $self->AddRunlog(%runlog); + + $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); - - return - unless %system; - - my %task = $self->GetTask ('loadavg'); - - $self->Error ("Unable to find loadavg task!", 1) unless %task; - + + my %system = $self->GetSystem($system); + + return unless %system; + + my %task = $self->GetTask('loadavg'); + + $self->Error("Unable to find loadavg task!", 1) unless %task; + my $days; my $today = Today2SQLDatetime; @@ -850,45 +877,139 @@ sub TrimLoadavg ($) { } # if my $oldage = SubtractDays $today, $days; - - my ($dberr, $dbmsg) = $self->_deleteRecord ( + + my ($dberr, $dbmsg) = $self->_deleteRecord( 'loadavg', "system='$system' and timestamp<='$oldage'" ); - + if ($dbmsg eq 'Records deleted') { - return (0, $dbmsg) - if $dberr == 0; - + return (0, $dbmsg) if $dberr == 0; + my %runlog; - + $runlog{task} = $task{name}; $runlog{started} = $today; $runlog{status} = 0; - $runlog{message} = + $runlog{message} = "Scrubbed $dberr loadavg records for system $system"; - my ($err, $msg) = $self->AddRunlog (%runlog); - - $self->Error ("Unable to add runload (Error: $err)\n$msg") if $err; + my ($err, $msg) = $self->AddRunlog(%runlog); + + $self->Error("Unable to add runload (Error: $err)\n$msg") if $err; } # if return ($dberr, $dbmsg); } # TrimLoadavg -sub GetFS ($$;$$$$) { +sub TrimStorage($$$) { + my ($self, $type, $tag, $region) = @_; + + my $today = Today2SQLDatetime; + + my $oldage = SubtractDays $today, $Clearadm::CLEAROPTS{CLEARADM_SCRUBDAYS}; + + my $table = $type =~ /vob/i + ? 'vobstorage' + : 'viewstorage'; + + my ($dberr, $dbmsg) = $self->_deleteRecord( + $table, + "tag='$tag' and region='$region' and timestamp<='$oldage'" + ); + + if ($dbmsg eq 'Records deleted') { + return (0, $dbmsg) if $dberr == 0; + + my %runlog; + + $runlog{task} = 'Scrub'; + $runlog{started} = $today; + $runlog{status} = 0; + $runlog{message} = + "Scrubbed $dberr ${type}storage records"; + + my ($err, $msg) = $self->AddRunlog(%runlog); + + $self->Error("Unable to add runload (Error: $err)\n$msg") if $err; + } # if + + return ($dberr, $dbmsg); +} # TrimStorage + +sub ValidateCCObjects() { + my ($self) = @_; + + my $vobRecordsDeleted = 0; + my $viewRecordsDeleted = 0; + + for my $region ($Clearcase::CC->regions) { + for my $type (qw(vob view)) { + my @ccobjs; + verbose "Processing ${type}s in $region"; + + if ($type eq 'vob') { + verbose "Finding all vobs in region $region"; + @ccobjs = $self->FindVob(undef, $region); + verbose 'Found ' . scalar @ccobjs . ' vobs to process'; + } elsif ($type eq 'view') { + verbose "Finding all views in region $region"; + @ccobjs = $self->FindView(undef, $region); + verbose 'Found ' . scalar @ccobjs . ' views to process'; + } # if + + for my $object (@ccobjs) { + my %ccobjrec = %$object; + + verbose "Processing $ccobjrec{tag}:$ccobjrec{region}"; + + my $ccobj; + + if ($type eq 'vob') { + $ccobj = Clearcase::Vob->new($ccobjrec{tag}, $ccobjrec{region}); + } else { + $ccobj = Clearcase::View->new($ccobjrec{tag}, $ccobjrec{region}); + } # if + + verbose_nolf 'Checking if ' . $ccobj->{tag} . ':' . $ccobj->{region} . ' exists anymore...'; + + if ($ccobj->exists) { + verbose ' it does! Skipping...'; + next; + } else { + verbose ' it doesn\'t!'; + } # if + + #next if $ccobj->exists; + + verbose "Deleting $type $ccobjrec{tag}:$ccobjrec{region}"; + + my ($recordsDeleted, $msg) = $self->_deleteRecord($type, + "tag='$ccobjrec{tag}' and region='$ccobjrec{region}'"); + + if ($msg ne 'Records deleted') { + return ($recordsDeleted, $msg); + } else { + $viewRecordsDeleted += $recordsDeleted if $type eq 'view'; + $vobRecordsDeleted += $recordsDeleted if $type eq 'vob'; + } # if + } # for + } # for + } # for + + return ($viewRecordsDeleted, $vobRecordsDeleted); +} # ValidateCCObjects + +sub GetFS($$;$$$$) { my ($self, $system, $filesystem, $start, $end, $count, $interval) = @_; - - $system = $self->_aliasSystem ($system); - - return - unless $system; - - return - unless $filesystem; - + + $system = $self->_aliasSystem($system); + + return unless $system; + return unless $filesystem; + $interval ||= 'Minute'; - + my $size = $interval =~ /month/i ? 7 : $interval =~ /day/i @@ -896,32 +1017,32 @@ sub GetFS ($$;$$$$) { : $interval =~ /hour/i ? 13 : 16; - + undef $start if $start and $start =~ /earliest/i; undef $end if $end and $end =~ /latest/i; - + my $condition = "system='$system' and filesystem='$filesystem'"; $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 ('fs', $condition); + my $nbrRecs = $self->Count('fs', $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 system, @@ -938,84 +1059,79 @@ from 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 - + 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 - + my @records; - + while (my $row = $sth->fetchrow_hashref) { push @records, $row; } # while - + return @records; } # GetFS -sub GetLatestFS ($$) { +sub GetLatestFS($$) { my ($self, $system, $filesystem) = @_; - - $system = $self->_aliasSystem ($system); - - return - unless $system; - - return - unless $filesystem; - - my @records = $self->_getRecords ( + + $system = $self->_aliasSystem($system); + + return unless $system; + return unless $filesystem; + + my @records = $self->_getRecords( 'fs', "system='$system' and filesystem='$filesystem'" . " order by timestamp desc limit 0, 1", ); - + if ($records[0]) { - return %{$records[0]}; + return %{$records[0]}; } else { - return; + return; } # if } # GetLatestFS -sub AddLoadavg () { +sub AddLoadavg() { my ($self, %loadavg) = @_; - + my @requiredFields = ( 'system', ); my $result = _checkRequiredFields \@requiredFields, \%loadavg; - - return -1, "AddLoadavg: $result" - if $result; - + + return -1, "AddLoadavg: $result" if $result; + # 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); - - return - unless $system; - + + $system = $self->_aliasSystem($system); + + return unless $system; + $interval ||= 'Minute'; - + my $size = $interval =~ /month/i ? 7 : $interval =~ /day/i @@ -1023,16 +1139,16 @@ sub GetLoadavg ($;$$$$) { : $interval =~ /hour/i ? 13 : 16; - + my $condition; - + undef $start if $start and $start =~ /earliest/i; undef $end if $end and $end =~ /latest/i; - + $condition .= " system='$system'" if $system; $condition .= " and timestamp>='$start'" if $start; $condition .= " and timestamp<='$end'" if $end; - + $condition .= " group by left(timestamp,$size)"; if ($count) { @@ -1041,16 +1157,15 @@ 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. - $offset = 0 - if $offset < 0; + $offset = 0 if $offset < 0; $condition .= " limit $offset, $count"; } # if - + my $statement = <<"END"; select system, @@ -1064,46 +1179,45 @@ from 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 - + 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 - + my @records; - + while (my $row = $sth->fetchrow_hashref) { push @records, $row; } # while - + return @records; } # GetLoadvg -sub GetLatestLoadavg ($) { +sub GetLatestLoadavg($) { my ($self, $system) = @_; - - $system = $self->_aliasSystem ($system); - - return - unless $system; - - my @records = $self->_getRecords ( + + $system = $self->_aliasSystem($system); + + return unless $system; + + my @records = $self->_getRecords( 'loadavg', "system='$system'" . " order by timestamp desc limit 0, 1", ); - + if ($records[0]) { return %{$records[0]}; } else { @@ -1111,226 +1225,310 @@ sub GetLatestLoadavg ($) { } # if } # GetLatestLoadavg -sub AddTask (%) { +sub GetStoragePool($$$;$$$$$) { + 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; + + # Windows vob tags begin with "\", which is problematic. The solution is to + # escape the "\" + $tag =~ s/^\\/\\\\/; + + 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; +} # GetStoragePool + +sub AddTask(%) { my ($self, %task) = @_; - + my @requiredFields = ( 'name', 'command' ); - + my $result = _checkRequiredFields \@requiredFields, \%task; - - return -1, "AddTask: $result" - if $result; - - return $self->_addRecord ('task', %task); + + return -1, "AddTask: $result" if $result; + + 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'"); + + return unless $name; + + my @records = $self->_getRecords('task', "name='$name'"); if ($records[0]) { return %{$records[0]}; } else { return; - } # if + } # 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 = ( 'task', ); - + my $result = _checkRequiredFields \@requiredFields, \%schedule; - - return -1, "AddSchedule: $result" - if $result; - - return $self->_addRecord ('schedule', %schedule); + + return -1, "AddSchedule: $result" if $result; + + 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 ||= ''; - $task||= ''; - + $task ||= ''; + my $condition = "name like '%$name%'"; $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]}; } else { return; - } # if + } # 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 = ( 'task', ); - + my $result = _checkRequiredFields \@requiredFields, \%runlog; - - return -1, "AddRunlog: $result" - if $result; - + + return -1, "AddRunlog: $result" if $result; + $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 ($system) { - $condition .= " and system like '%$system%'" - unless $system eq 'All'; - } else { - $condition .= ' and system is null'; - } # unless - - if (defined $status) { + if ($task !~ /all/i) { + $conditions++; + $condition = "task like '%$task%'"; + } # if + + if ($system !~ /all/i) { + $condition .= ' and ' if $conditions; + $condition .= "system like '%$system%'"; + $conditions++; + } # if + + if ($status) { + $condition .= ' and ' if $conditions; + 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 ($) { - my ($self, $id) = @_; - - return - unless $id; - - my @records = $self->_getRecords ('runlog', "id=$id"); - +sub GetRunlog($) { + my ($self, $id) = @_; + + return unless $id; + + my @records = $self->_getRecords('runlog', "id=$id"); + if ($records[0]) { return %{$records[0]}; } else { return; - } # if + } # 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 : ''; - + my ($err, $msg); - + 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 - + 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 - + # Hack! Statements such as the following: # # select count(*) from fs where system='jupiter' and filesystem='/dev/sdb5' - # > group by left(timestamp,10); + # > group by left(timestamp,10); # +----------+ # | count(*) | # +----------+ @@ -1343,7 +1541,7 @@ sub Count ($;$) { # | 190 | # +----------+ # 7 rows in set (0.00 sec) - # + # # Here we want 7 but what we see in $records[0] is 49. So the hack is that if # statement contains "group by" then we assume we have the above and return # scalar @records, otherwise we return $records[0]; @@ -1363,11 +1561,11 @@ 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); - + my $statement = <<"END"; select schedule.name as schedulename, @@ -1385,43 +1583,43 @@ where and schedule.active='true' 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 - + 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 - - my $sleep; + + my $sleep; my @records; - + 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'; } # if - + # If started is not defined then this task was never run so run it now. unless ($$row{lastrun}) { push @records, $row; next; } # unless - + # TODO: Handle frequencies better. my $seconds; - + if ($$row{frequency} =~ /(\d+) seconds/i) { $seconds = $1; } elsif ($$row{frequency} =~ /(\d+) minute/i) { @@ -1434,23 +1632,23 @@ END warning "Don't know how to handle frequencies like $$row{frequency}"; next; } # 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 push @records, $row; } # if - + $sleep ||= $waitTime; - + if ($sleep > $waitTime) { $sleep = $waitTime; } # if } # while - + # Even if there is nothing to do the caller should sleep a bit and come back # to us. So if it ends up there's nothing past due, and nothing upcoming, then # sleep for a minute and return here. Somebody may have added a new task next @@ -1458,94 +1656,93 @@ END if (@records == 0 and not $sleep) { $sleep = 60; } # if - - return ($sleep, @records); + + 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 - + 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 my @values; - + while (my @row = $sth->fetchrow_array) { if ($row[0]) { push @values, $row[0]; } else { push @values, '';
$footing .= '';
my $year = (localtime)[5] + 1900;
- $footing .= "Clearadm You will receive this alert no more than $nomorethan.
";
+ $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",
mode => 'html',
- data => $message,
- footing => $footing,
+ data => $message,
+ 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
@@ -1589,40 +1786,40 @@ sub SendAlert ($$$$$$$) {
notification => $notification,
runlog => $runlogID,
timestamp => Today2SQLDatetime,
- message => $subject,
- );
-
- return $self->AddAlertlog (%alertlog);
+ message => $subject,
+ );
+
+ return $self->AddAlertlog(%alertlog);
} # SendAlert
-sub GetLastAlert ($$) {
+sub GetLastAlert($$) {
my ($self, $notification, $system) = @_;
-
+
my $statement = <<"END";
select
runlog,
timestamp
-from
+from
alertlog
where
notification='$notification'
and system='$system'
order by
timestamp desc
-limit
+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;
-
+
$sth->finish;
-
+
if ($alertlog) {
return %$alertlog;
} else {
@@ -1630,40 +1827,40 @@ END
} # if
} # GetLastAlert
-sub GetLastTaskFailure ($$) {
+sub GetLastTaskFailure($$) {
my ($self, $task, $system) = @_;
-
+
my $statement = <<"END";
select
id,
ended
-from
+from
runlog
where
- status <> 0
+ status <> 0
and task='$task'
and system='$system'
and alerted='true'
order by
ended desc
-limit
+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;
-
+
$sth->finish;
-
+
if ($$runlog{ended}) {
return %$runlog;
} # if
-
+
# If we didn't get any ended in the last call then there's nothing that
# qualified. Still let's return a record (%runlog) that has a valid id so
# that the caller can update that runlog with alerted = 'true'.
@@ -1676,30 +1873,30 @@ where
status <> 0
and task='$task'
and system='$system'
-order by
+order by
ended desc
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;
-
+
$sth->finish;
-
+
if ($runlog) {
return %$runlog;
} else {
return
} # if
-} # GetLastTaskFailure
+} # GetLastTaskFailure
-sub Notify ($$$$$$) {
+sub Notify($$$$$$) {
my (
$self,
$notification,
@@ -1713,65 +1910,64 @@ sub Notify ($$$$$$) {
$runlogID = $self->_getLastID
unless $runlogID;
-
+
my ($err, $msg);
-
+
# 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 %lastnotified = $self->GetLastAlert ($notification, $system);
-
+
+ my %notification = $self->GetNotification($notification);
+
+ 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);
-
- return
- if $diff <= 0;
- } # if
+ my $diff = Compare($today, $lastnotified);
+
+ return if $diff <= 0;
+ } # if
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 {
# If we don't know what system this error occurred on we'll have to notify
@@ -1780,14 +1976,14 @@ sub Notify ($$$$$$) {
$to = $self->{NOTIFY};
} # if
} # unless
-
+
unless ($to) {
Error "To undefined";
} # unless
-
+
$message .= "