#!/usr/bin/perl
#Author: Nathan Flynn & Mr Google
#Date 09/08/07
# A script to dump all the MySQL databases and archive them.
# Version 1.0
use strict;
use warnings;
use DBI;
use DBD::mysql;
use File::Copy;
use File::Path;
use Sys::Hostname;


my $hostname = hostname;
my $configfile = 'mysqlbackup-config';
my $configurl = 'http://82.71.204.220/~mirror/mysqlbackup-config';
my $maxbackups_default = 6; # If config !exist defaults to this value
my $maxbackups = &_parse_config_file();
my $tmpdumpdir='/home/mysqlbackups'; # tmp dumps best to use localdisk
#my $dumpdir='/home/backups/mysql'; # becomes .0 
my $dumpdir='/data01/backups/mysql';
#my $err_log='/home/backups/mysql.0/backup.log';
my $err_log='/data01/backups/mysql.0/backup.log';
my $dump='/usr/bin/mysqldump --defaults-file=/root/.my.cnf';
my $tar='/bin/tar';
my $tar_switches="--remove-files -C $tmpdumpdir -zcf";
# Email settings
my $sendmail='/usr/sbin/sendmail';
my $contact='netops@zeninternet.co.uk';
#my $contact='eper@eper.net';
my $from = "root\@$hostname";
my $subject = "MySQL backup script $hostname";

#Define my subroutines
sub mysql_dump_gzip($);
sub mysql_getdbs();
sub _rotate_archives();
sub _mysql_connect();
sub _email_errors($);
sub _read_logs();
sub _parse_config_file();

&_rotate_archives();

&mysql_dump_gzip(&mysql_getdbs);


if ( -z "$err_log" ) {
}
else{
	&_email_errors(&_read_logs);
}

sub mysql_dump_gzip($) {
	foreach (@_) {
		my $database = $_;
		my $errors = ""; 
		mkpath "$tmpdumpdir" unless( -d "$tmpdumpdir");
		mkpath "$dumpdir.0" unless( -d "$dumpdir.0");
		system("$dump --database $_ > $tmpdumpdir/$_.sql 2>> $err_log") == 0
			or &_error_logs("$_ dump failed","$?");
		system("$tar $tar_switches $dumpdir.0/$_.sql.tar.gz $_.sql 2>> $err_log") == 0
			or &_error_logs("$_ gzip failed","$?");
	}
}

sub mysql_getdbs() {
	my $dbh = &_mysql_connect;
	my @db_names = $dbh->func('_ListDBs');
	$dbh->disconnect();
	return @db_names;
}

sub _rotate_archives() {

        until (!-d "$dumpdir.$maxbackups") {
                rmtree "$dumpdir.$maxbackups" or die "Could not delete $dumpdir.$maxbackups: $!";
                $maxbackups++;
        }

        $maxbackups--;
        while ($maxbackups>=0) {
                if ( -d "$dumpdir.$maxbackups") {
                        my $maxbackups_plus_one = $maxbackups + 1;
                        move("$dumpdir.$maxbackups", "$dumpdir".'.'.$maxbackups_plus_one ) or die "copy failed $dumpdir.$maxbackups $dumpdir.$maxbackups_plus_one: $!";
                }
                $maxbackups--;
        }
}

sub _mysql_connect() {
	my $dsn = "DBI:mysql:;mysql_read_default_file=/root/.my.cnf";
	my ($user,$pass) = ("","");
	my ($dbh,$sth,$query);
	$dbh = DBI->connect($dsn,$user,$pass,{ RaiseError => 1 });
}

sub _error_logs($) {
	my $database = $_[0];
	my $errorcode = $_[1];
	open(ERRORLOG, ">> $err_log") || die("Could not open file $err_log!");
	print ERRORLOG "Warning ","Database: $database",':',"Error Code: $errorcode","\n","\n";
	close ERRORLOG;
}

sub _email_errors($) {
	my $body = shift;
	open(MAIL, "|$sendmail -oi -t");
	print MAIL "From: $from\n";
	print MAIL "To: $contact\n";
	print MAIL "Subject: $subject\n\n";
	print MAIL "$body\n";
	close(MAIL);
}

sub _read_logs() {
	my $line = "";
	my $tmp = "";
	open(LOGFILE, "$err_log") or die("Could not open log file.");
	while ($line = <LOGFILE>) {
		$tmp .= $line;
	}
	return $tmp;
	close(LOGFILE);
}

sub _parse_config_file() {
	`wget $configurl -t 1 -T 10 -O $configfile 2>&1`;
	if (-z $configfile) {
		unlink("$configfile") or die "Could not delete $configfile: $!";
		return $maxbackups_default;
	}
	{
		my $name="";
		my $value="";
		if(open(CONF, $configfile))
                {
                        while(<CONF>)
                        {
                                if(m/^\s*($hostname)=\s*([^(#*|\s*)]+)/)
                                {
                                        ($name, $value) = split (/=/, $_);
                                        chomp $value;
                                }
                        }
                }
		unlink("$configfile") or die "Could not delete $configfile: $!";
		if ($value) {
			return "$value";
		}
		else {
			return "$maxbackups_default";
		}
        }
}


