|
| 1 | +require 'rubygems' |
| 2 | +require 'mysql' |
| 3 | +require 'open4' |
| 4 | +require 'fog' |
| 5 | +require 'active_support' |
| 6 | + |
| 7 | +# Amazon AWS Configuration |
| 8 | +AWS_ACCESS_KEY_ID = '' |
| 9 | +AWS_SECRET_ACCESS_KEY = '' |
| 10 | +AWS_VOLUME = '' # EBS volume to make snapshots of |
| 11 | + |
| 12 | +# MySQL Configuration |
| 13 | +MYSQL_HOST = '' |
| 14 | +MYSQL_USERNAME = '' |
| 15 | +MYSQL_PASSWORD = '' |
| 16 | + |
| 17 | +class Time |
| 18 | + %w(to_date to_datetime).each do |method| |
| 19 | + public method if private_instance_methods.include?(method) |
| 20 | + end |
| 21 | +end |
| 22 | + |
| 23 | +now = Time.now |
| 24 | +today = now.to_date |
| 25 | +hr24 = (now - 86400) |
| 26 | + |
| 27 | +# Connect to MySQL |
| 28 | +puts 'Connecting to MySQL...' |
| 29 | +my = Mysql::new(MYSQL_HOST, MYSQL_USERNAME, MYSQL_PASSWORD) |
| 30 | + |
| 31 | +# Connect to AWS |
| 32 | +puts 'Connecting to AWS...' |
| 33 | +compute = Fog::Compute.new(:provider => 'AWS', |
| 34 | + :aws_access_key_id => AWS_ACCESS_KEY_ID, |
| 35 | + :aws_secret_access_key => AWS_SECRET_ACCESS_KEY) |
| 36 | + |
| 37 | +# Stop replication |
| 38 | +puts 'Stopping MySQL Replication...' |
| 39 | +my.query('STOP SLAVE') |
| 40 | + |
| 41 | +# Lock the table(s) |
| 42 | +puts 'Locking MySQL Tables...' |
| 43 | +my.query('FLUSH TABLES WITH READ LOCK') |
| 44 | + |
| 45 | +# Sync the filesystem |
| 46 | +puts 'Syncing the filesystem...' |
| 47 | +status = Open4::popen4('sync') do |pid, stdin, stdout, stderr| |
| 48 | + # Wait for the command to finish executing; handle any errors |
| 49 | + # TODO: Add e-mail / ticket support if an error occurs |
| 50 | +end |
| 51 | + |
| 52 | +# XFS Freeze |
| 53 | +puts 'Freezing XFS...' |
| 54 | +status = Open4::popen4('xfs_freeze -f') do |pid, stdin, stdout, stderr| |
| 55 | + # Wait for the command to finish executing; handle any errors |
| 56 | + # TODO: Add e-mail / ticket support if an error occurs |
| 57 | +end |
| 58 | + |
| 59 | +# Create new EBS Snapshot |
| 60 | +puts 'Creating a new EBS Snapshot...' |
| 61 | +snap = compute.snapshots.new :volume_id => AWS_VOLUME, :description => 'MySQL Backup' |
| 62 | +puts 'Saving the new EBS Snapshot...' |
| 63 | +snap.save |
| 64 | + |
| 65 | +# XFS Unfreeze |
| 66 | +puts 'Unfreezing XFS...' |
| 67 | +status = Open4::popen4('xfs_freeze -u') do |pid, stdin, stdout, stderr| |
| 68 | + # Wait for the command to finish executing; handle any errors |
| 69 | + # TODO: Add e-mail / ticket support if an error occurs |
| 70 | +end |
| 71 | + |
| 72 | +# Unlock the table(s) |
| 73 | +puts 'Unlocking MySQL Tables...' |
| 74 | +my.query('UNLOCK TABLES') |
| 75 | + |
| 76 | +# Start replication |
| 77 | +puts 'Starting MySQL Replication...' |
| 78 | +my.query('START SLAVE') |
| 79 | + |
| 80 | +# Delete old EBS Snapshot(s) |
| 81 | +puts 'Deleting old EBS Snapshots...' |
| 82 | +snaps = compute.snapshots.all.collect do |s| |
| 83 | + if s.volume_id == AWS_VOLUME |
| 84 | + if s.progress == '100%' |
| 85 | + [s.id, Time.parse(s.created_at.to_s)] |
| 86 | + end |
| 87 | + end |
| 88 | +end |
| 89 | + |
| 90 | +# Remove nil entries |
| 91 | +snaps.delete_if do |s| |
| 92 | + s == nil |
| 93 | +end |
| 94 | + |
| 95 | +# Remove entries from the past 24 hours |
| 96 | +snaps.delete_if do |s| |
| 97 | + s.last >= hr24 |
| 98 | +end |
| 99 | + |
| 100 | +# Keep only one from each day |
| 101 | +dated = snaps.group_by do |s| |
| 102 | + s.last.to_date |
| 103 | +end |
| 104 | + |
| 105 | +today.downto(today - 7) do |date| |
| 106 | + dated[date].delete dated[date].sort_by(&:last).last if dated[date] |
| 107 | +end |
| 108 | + |
| 109 | +deleting = dated.inject([]) { |a,(k,v)| a << v.map(&:first) }.flatten |
| 110 | + |
| 111 | +deleting.each do |snap| |
| 112 | + compute.snapshots.get(snap).destroy |
| 113 | +end |
0 commit comments