Skip to content

Instantly share code, notes, and snippets.

@jayjanssen
Created December 24, 2015 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jayjanssen/c081e938a247f4e3b552 to your computer and use it in GitHub Desktop.
Save jayjanssen/c081e938a247f4e3b552 to your computer and use it in GitHub Desktop.
ZFS full/incrementals to AWS Glacier
#!/usr/bin/perl
use vars qw/ @ARGV /;
local $ENV{PATH} = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
die "Usage: $0 <filesystem>\n" unless $#ARGV == 0;
my $filesystem = shift @ARGV;
my $base_snap = '@glacier';
my $tmp_snap = '@glacier-tmp';
# ZFS Snapshots
sub check_snap {
my( $snap_name ) = @_;
return system( "zfs list -t snap $snap_name > /dev/null" ) == 0;
}
sub create_snap {
my( $snap_name ) = @_;
print "Creating snap: $snap_name\n";
system( "zfs snap $snap_name" );
}
sub delete_snap {
my( $snap_name ) = @_;
print "Destroying snap: $snap_name\n";
system( "zfs destroy $snap_name" );
}
sub rename_snap {
my( $old, $new ) = @_;
print "Renaming $old to $new\n";
system( "zfs rename $old $new" );
}
# Glacier Vaults
sub sanitize_name {
my( $vault_name ) = @_;
$vault_name =~ s|\/|_|g;
return $vault_name
}
sub check_vault {
my $vault_name = &sanitize_name( @_ );
return system( "glacier-cmd describevault $vault_name > /dev/null" ) == 0;
}
sub create_vault {
my $vault_name = &sanitize_name( @_ );
print "Creating Glacier vault $vault_name\n";
return system( "glacier-cmd mkvault $vault_name > /dev/null" ) == 0;
}
# Glacier upload
sub glacier_upload {
my( $filesystem, $snap, $base ) = @_;
my $vault_name = &sanitize_name( $filesystem );
my $incremental = "";
my $date = `date +"%F"`; chop $date;
my $description = "Full for $date";
if( defined( $base )) {
$description = "Incremental for $date";
$incremental = "-i $base ";
}
my $cmd = "zfs send -p $incremental$snap | glacier-cmd upload --description '$description' --stdin $vault_name";
print "$cmd\n";
return (system( $cmd ) == 0);
}
# Check for glacier vault and create if needed
&create_vault( $filesystem ) unless( &check_vault( $filesystem ));
# Check for base snapshot
my $base = "$filesystem$base_snap";
unless( &check_snap( $base ) ) {
print "Missing base snap\n";
&create_snap( $base );
# Upload base snap and exit
&glacier_upload( $filesystem, $base );
exit;
}
my $tmp = "$filesystem$tmp_snap";
if( &check_snap( $tmp ) ) {
print "Found tmp snap, dropping it\n";
&delete_snap( $tmp );
}
&create_snap( $tmp );
# Check for diffs
my $diffs = `zfs diff $base $tmp | wc -l`; chop $diffs;
if( $diffs == 0 ) {
print "No diffs!\n";
&delete_snap( $tmp );
exit;
}
# Upload incremental snap
if( &glacier_upload( $filesystem, $tmp, $base )) {
&delete_snap( $base );
&rename_snap( $tmp, $base );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment