#!/usr/bin/perl
use strict;
#
# Copyright (c) 2009--2012 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public License,
# version 2 (GPLv2). There is NO WARRANTY for this software, express or
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
# along with this software; if not, see
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
#
# Red Hat trademarks are not licensed under GPLv2. No permission is
# granted to use or replicate Red Hat trademarks that are incorporated
# in this software or its documentation.
#

use lib '/etc/rc.d/np.d';
use NOCpulse::NOCpulseini;
use PhysCluster;

use Date::Manip;
use Getopt::Long;
use Pod::Usage;

#set the defaults
my $delete_unmatched = 1;
my $delta = "";
my $dry_run = 0;
my $help = 0;
my $interval= "";

my ($sql, $err, $sth);

GetOptions(
        "delete-unmatched!" => \$delete_unmatched,
        "dry-run" => \$dry_run,
	"interval:s" => \$interval,
        "keep-monitoring-data:s" => \$delta,
        "help" => \$help,
        );
pod2usage(0) if $help;

if ($dry_run) {
        print "Warning: Dry run active - no changes will be made.\n";
}
 
my $cluster = PhysCluster->newInitialized('/etc/rhn/cluster.ini');
my $localConfig = $cluster->get_LocalConfig;
my $ini = NOCpulse::NOCpulseini->new;

if (%$localConfig) {
        $ini->connect();
        $ini->fetch_nocpulseini('INTERNAL');
} else {
        print "Error: This script can be run only on monitoring backend.\n";
        exit 1;
}

if ($delete_unmatched) {
        print "Deleting data from already deleted probes...\n";
        $sql = qq|
                delete from time_series_data
                 where probe_id in (
                       select id
                         from time_series_purge
                        where deleted = 1
                 )|;
        $sth = $ini->dbh->prepare($sql);
        $sth->execute();
        print "\t", $sth->rows, " records deleted from time_series_data.\n";
        $dry_run ? $ini->dbh->rollback : $ini->dbh->commit;
}

if ($interval && $delta) {
        #Lookup oldest monitoring data
        $sql = qq|select min(entry_time) as earliest from time_series_data|;

	$sth = $ini->dbh->prepare($sql);
	$sth->execute;
	my $earliest_entry = $sth->fetchrow() or die("Unable to retrieve earliest entry");
	my $earliest_date = &ParseDateString("epoch $earliest_entry");
	my $date=DateCalc("today", "- $delta",\$err);

	print UnixDate($earliest_date,"Deleting data from %T %b %e, %Y to ").UnixDate($date,"%T %b %e, %Y")." with interval of $interval\n";

	#Calculate list of intervals, last one being $date
	my (@date_list,$interval_date);
	while(1) {
	        $interval_date=DateCalc(UnixDate($earliest_date,"epoch %s"),"+ $interval",\$err);
	        if ($err > 0) {
	                print STDERR "Error: $interval is not valid date delta.\n";
		        exit 1;
	        }
	        if (Date_Cmp($interval_date,$date) >= 0) {
		        last;
	        }
	        push(@date_list,$interval_date);
	        $earliest_date=$interval_date;
	}

	push(@date_list,$date);

	$sql = qq|delete from time_series_data where entry_time < ?|;
	$sth = $ini->dbh->prepare($sql);

	foreach my $delete_date (@date_list) {
                print UnixDate($delete_date,"Deleting probes data older than %T %b %e, %Y...\n");
	        $sth->execute(UnixDate($delete_date,"%s"));
	        print "\t", $sth->rows, " record deleted.\n";
	        $dry_run ? $ini->dbh->rollback : $ini->dbh->commit;
	}

} elsif ($delta) {
        # delete probes older then $delta
        my $date=DateCalc("today", "- $delta", \$err);
        if ($err > 0) {
                print STDERR "Error: $delta is not valid date delta.\n";
                exit 1;
        }
        print UnixDate($date,"Deleting probes data older than %T %b %e, %Y...\n");
        $sql = qq|delete from time_series_data where entry_time < ?|;
        $sth = $ini->dbh->prepare($sql);
        $sth->execute(UnixDate($date,"%s"));
        print "\t", $sth->rows, " record deleted.\n";
        $dry_run ? $ini->dbh->rollback : $ini->dbh->commit;
} else {
        print "No date delta specified. I do not know what to delete.\n";
}

=pod

=head1 NAME

monitoring-data-cleanup - Delete unused and old data from monitoring probes.

=head1 SYNOPSIS

monitoring-data-cleanup [OPTIONS]

=head1 DESCRIPTION

This script deletes data from monitoring probes older than given time frame.
It can be useful to run from cron to periodically delete data which is not 
interesting for you.

Additionally - in Spacewalk 0.5 and older we did not deletes data when probe
has been deleted. And if you did not push scout configs you will be getting
data for deleted probes too. This script will delete them too.

=head1 OPTIONS

--dry-run
        No changes will be committed. All data will remain intact.

--delete-unmatched
        Delete data from probes, which have been already deleted. This is default.

--no-delete-unmatched
        Do not delete data from probes, which have been already deleted. Default is to delete them.

--keep-monitoring-data DELTA
        Delete data older than DELTA. Recognized deltas are of the form:
             +Yy +Mm +Ww +Dd +Hh +MNmn +Ss
        Examples:
                "1year 2 months 3hours"
                "2 business days"
        For more information about format see ParseDateDelta section of Date::Manip(3)

--interval INTERVAL_DELTA
       If set, delete data older than DELTA in increments of
       INTERVAL_DELTA, starting with the oldest record.
       Example:
             monitoring-data-cleanup --keep-monitoring-data "1 month" --interval "1 month"
       This is used to delete large amounts of monitoring data without encountering error
       ORA-30036 or requiring an enormous undo tablespace.

--help
        Display this help.

=head1 SEE ALSO

Date::Manip(3)

=head1 AUTHOR

Miroslav Suchý <msuchy@redhat.com>

=head1 COPYRIGHT AND LICENSE

Copyright (c) 2009--2012 Red Hat, Inc.
Released under GNU General Public License, version 2 (GPLv2).

=cut

