Skip to content

Backup

This snapshot backup enable you to have retention.
this manage my infrastructure backup on ec2.

Requirement :

  • perl
  • Net::Amazon::EC2
  • DBI:SQLite
  • bash

Files :

  • config # store your amazon key here
  • db.pl # manage local DB for your snapshot / dates / volume
  • backup.sh # Cron this script
  • create_snap.pl # Create Snapshot
  • config_bash # Manage config of your retention / backup
  • snap_status.pl # Check status of your snapshot
  • delete_snap.pl # Delete Snapshot which is out of retention.

C0D3s

config

File: config

#!/usr/bin/perl

$awsId = '<your AWS_ID>'; 
$awsKey = '<your AWS_KEY>';
$awsinstance = '<AWS_INSTANCES>'; ## right now it is not used anywhere

bash config

File: config_bash

# this file contain what need to be backup.  
# Follow the format of value
# instance<serial number must be unique> = <Volume ID> <Retention Freq.> <total Retention>

instance1="vol-2222pqrs 7 2"
instance2="vol-1111abcd 1 1"

db.pl

File: db.pl

#!/usr/bin/perl

# developed by k2patel
# [email protected]

# this Script Manage all Backup Record.

use Switch;
use DBI;

$filename = 'machine.db';
unless (-e $filename) {
    print "Creating Database...";
    $dbh = DBI->connect( "dbi:SQLite:machine.db" ) || die "Cannot connect: $DBI::errstr";
    $dbh->do( "CREATE TABLE DESK ( v_ID, s_ID, Dte )" );
    $dbh->disconnect;
} 

my($num_args) = $#ARGV + 1;
if ($num_args < 3) {
  print "\nUsage: db.pl <Operation> <Volume_ID> <Date> [<Snapshot ID>]\n";
  print "Operation : Allowed \"add / get / del\" \n";
  print "All three Value require\n";
  print "Snapshot ID must provided when the Operation is Add / Del\n";
  exit 1;
}

$dbh = DBI->connect( "dbi:SQLite:machine.db" ) || die "Cannot connect: $DBI::errstr";

switch( $ARGV[0] ){
    case "add"  {
        if ($ARGV[3] eq ''){
            print "You can not use ADD without Snapshot";
            exit 1;
        }else{
        $dbh->do( "INSERT INTO DESK VALUES ( '$ARGV[1]', '$ARGV[2]', '$ARGV[3]' )" );
        }
    }
    case "del"  {
        if ($ARGV[3] eq ''){
            print "You can not use DEL without Snapshot";
            exit 1;
        }else{
        $dbh->do( "DELETE FROM DESK WHERE s_ID = '$ARGV[2]' AND Dte = '$ARGV[3]'" );
        }
    }
    case "get"  {
        $res = $dbh->selectall_arrayref( "SELECT s_ID, Dte FROM DESK WHERE v_ID = '$ARGV[1]' AND Dte = '$ARGV[2]'" );
        foreach( @$res ) {
            #print "$_->[0] $_->[1] $_->[2]\n";
            print "$_->[0] $_->[1] $_->[2]\n"
            }
    }
    else
        {
        $res = $dbh->selectall_arrayref( "SELECT * FROM DESK" );
        foreach( @$res ) {
            print "$_->[0] $_->[1] $_->[2]\n";
            }
        }
}
$dbh->disconnect;

backup.sh

File: backup.sh

#!/bin/bash

# developed by k2patel
# [email protected]

############# Read ME ###############
# this Script will do the Backup and remove old copy.
# This script work based on existing DB Entry.
# When you initialize it only create one copy rest of the dummy entry need to be entered by you.
#####################################


BASE="$( cd "$( dirname "$0" )" && pwd )"
cd $BASE

source config_bash

DATE=$(date +%Y%m%d)
perl=$(which perl)


for inst in instance{1..10}
do
    eval var1=\$$inst
    arry=($var1)
if [[ $1 == "init" ]]; then
    if [ "$var1" != "" ]
        then
            vol=${arry[0]}
            echo "Running backup for $vol stored in "
            newsnp=`$perl create_snap.pl $vol $DATE`
            $perl db.pl add $vol $newsnp $DATE
            echo "waiting."
            $perl snap_status.pl $newsnp
            echo "done"
    fi
else
    if [ "$var1" != "" ]
        then
        freq=${arry[1]}
        vol=${arry[0]}
        iter=${arry[2]}
        lookup=$(echo "$iter * $freq" | bc)
        isit=`date -d "now -$lookup days" +%Y%m%d`
        isit_nxt=`date -d "now -$freq days" +%Y%m%d`
        lstnc=(`$perl $BASE/db.pl get "$vol" "$isit"`)
        if [ "$isit" == "${lstnc[1]}" ];then
                echo "Running backup for $vol stored in "
                newsnp=`$perl create_snap.pl $vol $DATE`
                $perl db.pl add $vol $newsnp $DATE
                echo "waiting."
                $perl snap_status.pl $newsnp
                echo "done"
                lstnx=(`$perl $BASE/db.pl get "$vol" "$isit_nxt"`)
            if [ "${lstnx[0]}" == '' ]; then
                echo "Notify Admin"
            else
                if [ "${lstnc[0]}" != '' ]; then
                    $perl delete_snap.pl ${lstnc[0]}
                fi
            fi
        else
            echo "backup is not needed"
        fi
    fi
fi
done

create snapshot

File: create_snap.pl

#!/usr/bin/perl -w
# Created / written by [email protected]
# this script create snapshot for given volume.

use Data::Dumper;
use strict;
#use Date::Calc qw( :all );

use lib "/usr/share/perl5/vendor_perl";
use Net::Amazon::EC2;

# Configuration.
require "config";

# our $ec2;
our $awsId;
our $awsKey;
our $awsinstance;

my($num_args) = $#ARGV + 1;
if ($num_args < 2) {
  print "\nUsage: create_snap.pl <Volume_ID> <Today>\n";
  print "This will create Snapshot for given Volume\n";
  print "Format for today's Date must be \"YYYYMMDD\"\n";
  exit 1;
}

## Define Access Keys for Amazon.
my $ec2 = Net::Amazon::EC2->new(
        AWSAccessKeyId => $awsId, 
        SecretAccessKey => $awsKey
);

my @result = $ec2->create_snapshot(
VolumeId => $ARGV[0],
Description => $ARGV[1]
);

print $result[0]->{snapshot_id};
#print Dumper \@result;

delete shnapshot

File: delete_snap.pl

# This script delete snapshot of requested volume
# Author : k2patel <[email protected]>
# Please send me message for suggestion or update.

# this script delete snapshot

use Data::Dumper;
use strict;
#use Date::Calc qw( :all );

use lib "/usr/share/perl5/vendor_perl";
use Net::Amazon::EC2;

# Configuration.
require "config";

# our $ec2;
our $awsId;
our $awsKey;
our $awsinstance;

my($num_args) = $#ARGV + 1;
if ($num_args < 1) {
  print "\nUsage: delete_snap.pl <Snapshot_ID>\n";
  print "This will Delete Snapshot\n";
  exit 1;
}

## Define Access Keys for Amazon.
my $ec2 = Net::Amazon::EC2->new(
        AWSAccessKeyId => $awsId, 
        SecretAccessKey => $awsKey
);

my @result = $ec2->delete_snapshot(
SnapshotId => $ARGV[0]
);


if ( $result[0] eq 1 ){
    #print "Good to go \n";
    exit 0;
}else{
    my $err = Dumper \@result;
    open F,">./rnd895896";
    print F $err;
    close F;
    if(system ("/bin/mail -s \"ERROR : Dump Of Error\" k2patel\@hotmail.com < ./rnd895896") == 0){
        unlink "./rnd895896";
    }
    exit 1;
    }

Check Snapshot status

File: snap_status.pl

# This script check status of given snapshot and wait for it get completed.
# Author : k2patel <[email protected]>
# Please send me message for suggestion or update.


use Data::Dumper;
use strict;
#use Date::Calc qw( :all );

use lib "/usr/share/perl5/vendor_perl";
use Net::Amazon::EC2;

# Configuration.
require "config";

# our $ec2;
our $awsId;
our $awsKey;
our $awsinstance;

my($num_args) = $#ARGV + 1;
if ($num_args < 1) {
  print "\nUsage: snap_status.pl <Snapshot_ID>\n";
  print "This will check Snapshot Status\n";
  exit 1;
}

## Define Access Keys for Amazon.
my $ec2 = Net::Amazon::EC2->new(
        AWSAccessKeyId => $awsId, 
        SecretAccessKey => $awsKey
);

my @result = $ec2->describe_snapshots(
SnapshotId => $ARGV[0]
);

while ( $result[0][0]->{status} ne 'completed' ){
    sleep 10;
}

if ( $result[0][0]->{status} eq 'completed' ){
    my $tst = "Good to go \n";
    exit 0;
}else{
    my $err = Dumper \@result;
    open F,">./rnd892346";
    print F $err;
    close F;
    if(system ("/bin/mail -s \"ERROR : Dump Of Error\" k2patel\@hotmail.com < ./rnd892346") == 0){
        unlink "./rnd892346";
    }
    exit 1;
    }

Machine DB

sqlite3 machine.db

File: machine.db

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE DESK ( v_ID, s_ID, Dte );