aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xfiles/checkbackups.pl161
-rw-r--r--manifests/maildir.pp1
-rw-r--r--manifests/mysql.pp8
-rw-r--r--manifests/rdiff.pp31
-rw-r--r--manifests/server.pp71
-rw-r--r--templates/mysql.conf.erb4
-rw-r--r--templates/rdiff.conf.erb2
7 files changed, 250 insertions, 28 deletions
diff --git a/files/checkbackups.pl b/files/checkbackups.pl
new file mode 100755
index 0000000..80fc07f
--- /dev/null
+++ b/files/checkbackups.pl
@@ -0,0 +1,161 @@
+#!/usr/bin/perl -w
+
+# This script is designed to check a backup directory populated with
+# subdirectories named after hosts, within which there are backups of various
+# types.
+#
+# Example:
+# /home/backup:
+# foo.example.com
+#
+# foo.example.com:
+# rdiff-backup .ssh
+#
+# rdiff-backup:
+# root home rdiff-backup-data usr var
+#
+# There are heuristics to determine the backup type. Currently, the following
+# types are supported:
+#
+# rdiff-backup: assumes there is a rdiff-backup/rdiff-backup-data/backup.log file
+# duplicity: assumes there is a dup subdirectory, checks the latest file
+# dump files: assumes there is a dump subdirectory, checks the latest file
+#
+# This script returns output suitable for send_nsca to send the results to
+# nagios and should therefore be used like this:
+#
+# checkbackups.sh | send_nsca -H nagios.example.com
+
+use Getopt::Std;
+
+# XXX: taken from utils.sh from nagios-plugins-basic
+my $STATE_OK=0;
+my $STATE_WARNING=1;
+my $STATE_CRITICAL=2;
+my $STATE_UNKNOWN=3;
+my $STATE_DEPENDENT=4;
+
+# gross hack: we look into subdirs to find vservers
+my @vserver_dirs = qw{/var/lib/vservers /vservers};
+
+our $opt_d = "/backup";
+our $opt_c = 48 * 60 * 60;
+our $opt_w = 24 * 60 * 60;
+our $opt_v = 0;
+our $opt_o;
+
+if (!getopts('d:c:w:vo')) {
+ print <<EOF
+Usage: $0 [ -d <backupdir> ] [ -c <threshold> ] [ -w <threshold> ] [ -o ] [ -v ]
+EOF
+ ;
+ exit();
+}
+
+my $backupdir= $opt_d;
+my $crit = $opt_c;
+my $warn = $opt_w;
+
+my @hosts;
+if (defined($opt_o)) {
+ @hosts=qx{hostname -f};
+} else {
+ # XXX: this should be a complete backup registry instead
+ @hosts=qx{ls $backupdir};
+}
+
+chdir($backupdir);
+my ($state, $message, @vservers, $host);
+foreach $host (@hosts) {
+ chomp($host);
+ if ($opt_o) {
+ $dir = $backupdir;
+ } else {
+ $dir = $host;
+ }
+ my $flag="";
+ my $type="unknown";
+ my $extra_msg="";
+ @vservers = ();
+ $state = $STATE_UNKNOWN;
+ $message = "???";
+ if (-d $dir) {
+ # guess the backup type and find a proper stamp file to compare
+ # XXX: the backup type should be part of the machine registry
+ my $last_bak;
+ if (-d "$dir/rdiff-backup") {
+ $flag="$dir/rdiff-backup/rdiff-backup-data/backup.log";
+ $type="rdiff";
+ if (open(FLAG, $flag)) {
+ while (<FLAG>) {
+ if (/StartTime ([0-9]*).[0-9]* \((.*)\)/) {
+ $last_bak = $1;
+ $extra_msg = ' [backup.log]';
+ $opt_v && print STDERR "found timestamp $1 ($2) in backup.log\n";
+ }
+ }
+ if (!$last_bak) {
+ $message = "cannot parse backup.log for a valid timestamp";
+ next;
+ }
+ } else {
+ $opt_v && print STDERR "cannot open backup.log\n";
+ }
+ close(FLAG);
+ foreach my $vserver_dir (@vserver_dirs) {
+ $vsdir = "$dir/rdiff-backup$vserver_dir";
+ if (opendir(DIR, $vsdir)) {
+ @vservers = grep { /^[^\.]/ && -d "$vsdir/$_" } readdir(DIR);
+ $opt_v && print STDERR "found vservers $vsdir: @vservers\n";
+ closedir DIR;
+ } else {
+ $opt_v && print STDERR "no vserver in $vsdir\n";
+ }
+ }
+ } elsif (-d "$dir/dump") {
+ # XXX: this doesn't check backup consistency
+ $flag="$dir/dump/" . `ls -tr $dir/dump | tail -1`;
+ chomp($flag);
+ $type="dump";
+ } elsif (-d "$dir/dup") {
+ # XXX: this doesn't check backup consistency
+ $flag="$dir/dup/" . `ls -tr $dir/dup | tail -1`;
+ chomp($flag);
+ $type="dup";
+ } elsif (-r "$dir/rsync.log") {
+ # XXX: this doesn't check backup consistency
+ $flag="$dir/rsync.log";
+ $type="rsync";
+ } else {
+ $message = "unknown system";
+ next;
+ }
+ if (!defined($last_bak)) {
+ my @stats = stat($flag);
+ if (not @stats) {
+ $message = "cannot stat flag $flag";
+ next;
+ }
+ $last_bak = $stats[9];
+ }
+ my $t = time();
+ my $delta = $t - $last_bak;
+ if ($delta > $crit) {
+ $state = $STATE_CRITICAL;
+ } elsif ($delta > $warn) {
+ $state = $STATE_WARNING;
+ } elsif ($delta >= 0) {
+ $state = $STATE_OK;
+ }
+ $message = "$delta seconds old$extra_msg";
+ } else {
+ $message = "no directory";
+ }
+} continue {
+ printf "$host\tbackups\t$state\t$message\n";
+ my @dom_sufx = split(/\./, $host);
+ my $dom_sufx = join('.', @dom_sufx[1,-1]);
+ foreach my $vserver (@vservers) {
+ printf "$vserver.$dom_sufx\tbackups\t$state\t$message, same as parent: $host\n";
+ }
+}
diff --git a/manifests/maildir.pp b/manifests/maildir.pp
index d871654..1427af1 100644
--- a/manifests/maildir.pp
+++ b/manifests/maildir.pp
@@ -38,4 +38,5 @@ define backupninja::maildir(
mode => 0600,
require => File["${backupninja::client::defaults::configdir}"]
}
+ package { rsync: ensure => installed }
}
diff --git a/manifests/mysql.pp b/manifests/mysql.pp
index e6cfe90..83d8f8f 100644
--- a/manifests/mysql.pp
+++ b/manifests/mysql.pp
@@ -17,9 +17,15 @@
define backupninja::mysql(
$order = 10, $ensure = present, $user = false, $dbusername = false, $dbpassword = false,
$dbhost = 'localhost', $databases = 'all', $backupdir = false, $hotcopy = false,
- $sqldump = false, $compress = false, $configfile = '/etc/mysql/debian.cnf',
+ $sqldump = false, $compress = false, $configfile = true,
$vsname = false)
{
+
+ $real_configfile = $configfile ? {
+ true => "/etc/mysql/debian.cnf",
+ default => $configfile,
+ }
+
include backupninja::client::defaults
file { "${backupninja::client::defaults::configdir}/${order}_${name}.mysql":
ensure => $ensure,
diff --git a/manifests/rdiff.pp b/manifests/rdiff.pp
index b32a262..1d171b2 100644
--- a/manifests/rdiff.pp
+++ b/manifests/rdiff.pp
@@ -16,21 +16,25 @@
# directories.
#
define backupninja::rdiff(
- $order = 90, $ensure = present, $user = false, $directory = false, $host = false,
+ $order = 90, $ensure = present, $user = false, $home = false, $host = false,
$type = 'local',
$exclude = [ "/home/*/.gnupg", "/home/*/.local/share/Trash", "/home/*/.Trash",
"/home/*/.thumbnails", "/home/*/.beagle", "/home/*/.aMule",
"/home/*/gtk-gnutella-downloads" ],
$include = [ "/var/spool/cron/crontabs", "/var/backups", "/etc", "/root",
"/home", "/usr/local/*bin", "/var/lib/dpkg/status*" ],
- $vsinclude = false, $keep = 30, $sshoptions = false, $options = false, $ssh_dir_manage = true,
- $ssh_dir = false, $authorized_keys_file = false, $installuser = true, $installkey = true,
- $backuptag = false, $home = false, $backupkeytype = "rsa", $backupkeystore = false)
+ $vsinclude = false, $keep = 30, $sshoptions = false, $options = '--force', $ssh_dir_manage = true,
+ $ssh_dir = false, $authorized_keys_file = false, $installuser = true, $installkey = true, $key = false,
+ $backuptag = false, $home = false, $backupkeytype = "rsa", $backupkeystore = false, $extras = false)
{
+ $real_backuptag = $backuptag ? {
+ false => "backupninja-$host",
+ default => $backuptag
+ }
+
+ $directory = "$home/rdiff-backup/"
include backupninja::client::defaults
- case $directory { false: { err("need to define a directory for where the backups should go!") } }
-
case $type {
'remote': {
case $host { false: { err("need to define a host for remote backups!") } }
@@ -42,10 +46,10 @@ define backupninja::rdiff(
backupninja::server::sandbox
{
- "${user}-${name}": user => $user, host => $host, dir => $real_home,
- manage_ssh_dir => $ssh_dir_manage, ssh_dir => $ssh_dir,
+ "${user}-${name}": user => $user, host => $fqdn, dir => $home,
+ manage_ssh_dir => $ssh_dir_manage, ssh_dir => $ssh_dir, key => $key,
authorized_keys_file => $authorized_keys_file, installuser => $installuser,
- backuptag => $backuptag, keytype => $backupkeytype, backupkeys => $backupkeystore,
+ backuptag => $real_backuptag, keytype => $backupkeytype, backupkeys => $backupkeystore,
}
backupninja::client::key
@@ -65,5 +69,14 @@ define backupninja::rdiff(
mode => 0600,
require => File["${backupninja::client::defaults::configdir}"]
}
+ include backupninja::rdiff-installed
+}
+
+class backupninja::rdiff-installed {
+ case $lsbdistcodename {
+ "etch": { $version = "1.2.5-1~bpo40+1" }
+ default: { $version = "installed" }
+ }
+ package { "rdiff-backup": ensure => $version }
}
diff --git a/manifests/server.pp b/manifests/server.pp
index 790c931..52cb11c 100644
--- a/manifests/server.pp
+++ b/manifests/server.pp
@@ -23,18 +23,36 @@ class backupninja::server {
mode => 0710, owner => root, group => "backupninjas"
}
+ file { "/usr/local/bin/checkbackups":
+ ensure => "present",
+ source => "puppet://$servername/backupninja/checkbackups.pl",
+ mode => 0755, owner => root, group => root,
+ }
+
+ cron { checkbackups:
+ command => "/usr/local/bin/checkbackups -d $real_backupdir | /usr/sbin/send_nsca -H nagios.koumbit.net -c /etc/send_nsca.cfg | grep -v 'sent to host successfully'",
+ user => "root",
+ hour => "8-23",
+ minute => 59,
+ require => [ File["/usr/local/bin/checkbackups"], Package['nsca'] ]
+ }
+
User <<| tag == "backupninja-$real_backupserver_tag" |>>
File <<| tag == "backupninja-$real_backupserver_tag" |>>
+ Ssh_authorized_key <<| tag == "backupninja-$real_backupserver_tag" |>>
+
+ package { "rsync": ensure => installed }
+ include backupninja::rdiff-installed
# this define allows nodes to declare a remote backup sandbox, that have to
# get created on the server
define sandbox(
$user = false, $host = false, $installuser = true, $dir = false, $manage_ssh_dir = true,
- $ssh_dir = false, $authorized_keys_file = false, $backupkeys = false, $keytype = "rsa",
- $uid = false, $gid = "backupninjas", $backuptag = false)
+ $ssh_dir = false, $authorized_keys_file = false, $key = false, $keytype = 'dss', $backupkeys = false, $uid = false,
+ $gid = "backupninjas", $backuptag = false)
{
- $real_user = $name ? {
+ $real_user = $user ? {
false => $name,
default => $user,
'' => $name,
@@ -63,11 +81,14 @@ class backupninja::server {
false => "backupninja-$real_host",
default => $backuptag,
}
-
+
+ # configure a passive service check for backups
+ nagios2::passive_service { "backups-$real_host": nagios2_host_name => $real_host, nagios2_description => 'backups', servicegroups => "backups" }
+
if !defined(File["$real_dir"]) {
@@file { "$real_dir":
ensure => directory,
- mode => 0750, owner => $user, group => 0,
+ mode => 0750, owner => $real_user, group => 0,
tag => "$real_backuptag",
}
}
@@ -78,22 +99,36 @@ class backupninja::server {
if !defined(File["$real_ssh_dir"]) {
@@file { "${real_ssh_dir}":
ensure => directory,
- mode => 0700, owner => $user, group => 0,
- require => File["$real_dir"],
+ mode => 0700, owner => $real_user, group => 0,
+ require => [User[$real_user], File["$real_dir"]],
tag => "$real_backuptag",
}
}
}
}
- if !defined(File["${real_ssh_dir}/${real_authorized_keys_file}"]) {
- @@file { "${real_ssh_dir}/${real_authorized_keys_file}":
- ensure => present,
- mode => 0644, owner => 0, group => 0,
- source => "$real_backupkeys/${user}_id_${keytype}.pub",
- require => File["${real_ssh_dir}"],
- tag => "$real_backuptag",
+ case $key {
+ false: {
+ if !defined(File["${real_ssh_dir}/${real_authorized_keys_file}"]) {
+ @@file { "${real_ssh_dir}/${real_authorized_keys_file}":
+ ensure => present,
+ mode => 0644, owner => 0, group => 0,
+ source => "$real_backupkeys/${real_user}_id_${keytype}.pub",
+ require => File["${real_ssh_dir}"],
+ tag => "$real_backuptag",
+ }
+ }
+ }
+ default: {
+ @@ssh_authorized_key{ $real_user:
+ type => $key_type,
+ key => $key,
+ user => $real_user,
+ target => "${real_ssh_dir}/${real_authorized_keys_file}",
+ tag => "$real_backuptag",
+ require => User[$real_user],
+ }
}
- }
+ }
case $uid {
false: {
if !defined(User["$real_user"]) {
@@ -105,13 +140,13 @@ class backupninja::server {
managehome => true,
shell => "/bin/sh",
password => '*',
- require => Group['backupninjas'],
+ require => Group['backupninjas'],
tag => "$real_backuptag"
}
}
}
default: {
- if !defined(User["$real_user"]) {
+ if !defined(User["$real_user"]) {
@@user { "$real_user":
ensure => "present",
uid => "$uid",
@@ -121,7 +156,7 @@ class backupninja::server {
managehome => true,
shell => "/bin/sh",
password => '*',
- require => Group['backupninjas'],
+ require => Group['backupninjas'],
tag => "$real_backuptag"
}
}
diff --git a/templates/mysql.conf.erb b/templates/mysql.conf.erb
index 9d22ab0..14905fd 100644
--- a/templates/mysql.conf.erb
+++ b/templates/mysql.conf.erb
@@ -12,3 +12,7 @@ end -%>
hotcopy = <%= hotcopy ? 'yes' : 'no' %>
sqldump = <%= sqldump ? 'yes' : 'no' %>
compress = <%= compress ? 'yes' : 'no' %>
+
+<% if real_configfile %>
+configfile = <%= real_configfile %>
+<% end %>
diff --git a/templates/rdiff.conf.erb b/templates/rdiff.conf.erb
index a41e969..23c336f 100644
--- a/templates/rdiff.conf.erb
+++ b/templates/rdiff.conf.erb
@@ -5,6 +5,8 @@
<%= 'options = ' + options if options %>
+<%= extras if extras %>
+
[source]
type = local
<%= 'keep = ' + keep if keep %>