Thursday, October 02, 2008

Python ZFS Backup Script

This is my incremental backup script for ZFS on Solaris 10
REQUIREMENTS:
mysql
python
pymysql
install these by doing this
/opt/csw/bin/pkg-get -i mysql5
/opt/csw/bin/pkg-get -i python
/opt/csw/bin/pkg-get -i pymysql


Requires a mySQL database with a table called logs in a database called backups, please feel free to amend this but remember to update the script below.
NOTES:
You will have to tab indent this script manually as I haven't figured out how to do it in here
SCRIPT:
#!/usr/bin/python
#backup_script_v0.1.py - Backup ZFS pool for sportsware
import sys
import MySQLdb
import os
import commands
import smtplib
import time
#set fixed parameters here
smtpserver = "IP.ADDRESS"
adminEmail = "address mail comes from"
backupsEmail = "address mail goes to"
targetZFSHost = "IP/hostname of ZFS target"
sourceZFSPool = "the zfs volume to be backed up"
targetZFSPool = "the zfs volume to back up to"
thisServer = "name of this server"
thisClient = "name of client"

#database connection attempts go here
try:
DBlog = MySQLdb.connect (host = "database IP",
user = "backups_user",
passwd = "backups_pass",
db = "backups")
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
sys.exit (1)

startTime = time.time()
timestamp = time.strftime("%Y%m%d%H%M")
buildSnapshotCommand = "zfs snapshot "+sourceZFSPool+"@"+timestamp
lastSnapshotCommand = "zfs list -r -t snapshot -o name "+sourceZFSPool
lastSnapshotInput = commands.getoutput(lastSnapshotCommand)
lastSnapshot = lastSnapshotInput[-12:]
zfsSendRecvCommand = "zfs send -i "+sourceZFSPool+"@"+lastSnapshot+" "+sourceZFSPool+"@"+timestamp+" ssh -C "+targetZFSHost+" zfs recv "+targetZFSPool
print "Creating Snapshot"
#CREATING THE SNAPSHOT
status = commands.getoutput(buildSnapshotCommand)
if status == "":
logStatus="No snapshot error occurred"
else:
logStatus=status
print logStatus
#build mail connection
mailSession = smtplib.SMTP(smtpserver)
emailMessage="To: "+adminEmail+"\nFrom: "+backupsEmail+"\nSubject:ZFS Snapshot Error occurred:\nThe following error occured at "+time.strftime("%H:%M - %d/%m/%Y")+"\n"+logStatus
mailSession.sendmail(backupsEmail,adminEmail,emailMessage)
mailSession.quit()

Logging = DBlog.cursor()
LoggingInsert = "INSERT INTO logs (site_name,server_name,log_output) VALUES ('"+thisClient+"\','"+thisServer+"\',\'"+logStatus+"\');"
Logging.execute(LoggingInsert)
endTime = time.time()
timeSpent=endTime - startTime
print "Sending Snapshot"
#ZFS SEND/RECV
status = commands.getoutput(zfsSendRecvCommand)
if status == "":
sendlogStatus="No ZFS transmission error occurred"
else:
logStatus=status
print logStatus
#build mail connection
mailSession = smtplib.SMTP(smtpserver)
emailMessage="To: "+adminEmail+"\nFrom: "+backupsEmail+"\nSubject:ZFS Send/Recv Error occurred:\nThe following error occured at "+time.strftime("%H:%M - %d/%m/%Y")+"\n"+logStatus
mailSession.sendmail(backupsEmail,adminEmail,emailMessage)
mailSession.quit()

Logging = DBlog.cursor()
LoggingInsert = "INSERT INTO logs (site_name,server_name,log_output) VALUES ('"+thisClient+"\','"+thisServer+"\',\'"+logStatus+"\');"
Logging.execute(LoggingInsert)
endTime = time.time()
timeSpent=endTime - startTime


emailCompletionMessage="To: "+adminEmail+"\nFrom: "+backupsEmail+"\nSubject:Backups Completed at "+time.strftime("%H:%M - %d/%m/%Y")+"\nThe ZFS Backups Completed @"+time.strftime("%H:%M - %d/%m/%Y")+"\n\n They completed in "+str(timeSpent)+" seconds"
zipMailSession = smtplib.SMTP(smtpserver)
zipMailSession.sendmail(backupsEmail,adminEmail,emailCompletionMessage)
zipMailSession.quit()
print endTime
DBconn.close()
sys.exit(0)