Created
May 5, 2011 20:58
-
-
Save gosuri/957912 to your computer and use it in GitHub Desktop.
Backup script to take a snapshot of the database and upload to Rockspace Cloud Files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Backup script to take a snapshot of the database and upload to Rockspace Cloud Files | |
# also manages the no of backups to keep. | |
# | |
# Note: You will require a Rackspace Cloud account, more details @ http://www.rackspace.com/cloud/ | |
# | |
# ------------- | |
# Configuration | |
# ------------- | |
# The script uses the database.yml for configuration. Backup database details should be | |
# provided for the appropriate environment. | |
# | |
# --------------------- | |
# Sample Configuration | |
# --------------------- | |
# production: | |
# adapter: mysql | |
# host: db_host | |
# database: database_name | |
# username: db_user | |
# backup: | |
# adapter: mysql | |
# host: db_host | |
# database: db_name | |
# username: root | |
# cloud_user: rackspace_cloud_user_id | |
# cloud_key: api_key_provided_by_rackspace | |
# cloud_container: container_to_store | |
# keep_backups: no_of_backups_to_keep_in_the_container | |
# | |
# ----------------- | |
# Gem Dependencies | |
# ----------------- | |
# rails 2.3.8 | |
# cloudfiles | |
namespace :db do | |
desc "Creates a snapshot of the database under tmp/backups/db and uploads to Rackspace Cloud" | |
task :backup, :needs => :environment do | |
BACKUP_DIR_PATH = File.expand_path(File.join(RAILS_ROOT,"tmp","backups","db")) | |
# Create Directories if they don't exist | |
FileUtils.mkpath BACKUP_DIR_PATH unless File.directory?(BACKUP_DIR_PATH) | |
# Check for lock file to ensure just one backup is being taken at a time | |
lock_file = File.expand_path(File.join(BACKUP_DIR_PATH,".lock")) | |
raise "There is a backup process being run or did not finish properly, check #{BACKUP_DIR_PATH}" if File.exists? lock_file | |
# Create the lock file and write the process id, should delete this once the backup is done | |
File.open(lock_file, 'w') {|f| f.write(Process.pid) } | |
# Check if mysqldump exists in the path | |
mysqldump_path = nil | |
ENV['PATH'].split(':').each {|folder| mysqldump_path = folder + "/mysqldump" if File.exists?(folder+'/mysqldump')} | |
raise "mysqldump executable not found in path" if mysqldump_path.blank? | |
# Fetch Database details from database.yml | |
db_config = Rails::Configuration.new.database_configuration[RAILS_ENV]["backup"] | |
raise "backup DB is not defined in database config" if db_config.blank? | |
# Consutrcting the mysqldump command | |
command = "#{mysqldump_path} --opt " | |
command += "-h #{db_config['host']} " unless db_config['host'].blank? | |
command += "-P #{db_config['port']} " unless db_config['port'].blank? | |
command += "-u #{db_config['username']} " unless db_config['username'].blank? | |
command += "-p#{db_config['password']} " unless db_config['password'].blank? | |
command += "#{db_config['database']} " | |
file_name = Time.now.strftime("#{db_config['database']}-%d-%B-%YT%H%M.sql") | |
file_path = File.expand_path(File.join(BACKUP_DIR_PATH,file_name)) | |
command += "> #{file_path}" | |
puts "starting backup, writing to #{file_path}" | |
system command # Run the command | |
puts "backup complete, wrote to #{file_path}" | |
# Upload to the cloud | |
puts "starting upload" | |
cloud_files = CloudFiles::Connection.new(:username => db_config['cloud_user'], :api_key => db_config['cloud_key']) | |
container = cloud_files.container(db_config['cloud_container']) | |
obj = container.create_object(file_name) | |
obj.write File.open(file_path,'rb') | |
puts "upload complete" | |
# Cleanup | |
File.delete(file_path) | |
File.delete(lock_file) | |
# Number of files should not exceed the number specified @ keep_backups | |
if container.objects.count > db_config['keep_backups'] | |
objects = container.objects_detail # => Fetches all the object details | |
no_objs_to_delete = objects.size - db_config['keep_backups'] - 1 | |
sorted_objects = objects.sort_by {|obj| obj[1][:last_modified]} | |
sorted_objects[0..no_objs_to_delete].each {|obj| container.delete_object obj[0]} | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment