Skip to content

Instantly share code, notes, and snippets.

@steevee
Forked from simonmorley/gist:19f9c9b1142d43b2e278
Last active April 18, 2016 13:59
Show Gist options
  • Save steevee/8e2fe9f7c7107b5d84647f94e1a5ecf0 to your computer and use it in GitHub Desktop.
Save steevee/8e2fe9f7c7107b5d84647f94e1a5ecf0 to your computer and use it in GitHub Desktop.
Google Compute Engine Snapshot Create and Rotate in Ruby
#!/usr/bin/ruby
require 'json'
require 'time'
require 'optparse'
require 'ostruct'
class Snapshot
def initialize(args)
@options = OpenStruct.new
# Default options
@options.rotate_days = 7
@options.rotate_keep_days_of_month = 1 # Keep snapshots on first of every month
@options.primary_disk_only = false
@options.silent = false
opt_parser = OptionParser.new do |opts|
opts.banner = "Usage: snapshotAndRotate.rb [options]"
opts.on('--rotate_days NUMBEROFDAYSTOKEEP', OptionParser::DecimalInteger, "Keep last X days of snapshots") { |o| @options.rotate_days = o }
opts.on('--rotate_keep_days_of_month DAYOFMONTHTOKEEP', OptionParser::DecimalInteger, "Keep snapshots created on this day of the month") { |o| @options.rotate_keep_days_of_month = o }
opts.on('--primary_disk_only', "Only backup primary disk. Only deletes snapshots if from primary disk too.") { |o| @options.primary_disk_only = true }
opts.on('--silent', "Supress output") { |o| @options.silent = true }
end
opt_parser.parse!(args)
# Non-configurable settings
@zone = get_zone
@hostname = hostname
@time = Time.now.to_i
@snapshot_name_regex = "^#{@hostname}--.*" # n.b. see create_snapshot_name - must match
@rotate_period = @options.rotate_days * 60 * 60 *24
end
def get_zone
output = `curl --silent "http://metadata.google.internal/computeMetadata/v1/instance/zone" -H "Metadata-Flavor: Google"`
output.split("/").last
end
def hostname
hostname = `curl --silent "http://metadata.google.internal/computeMetadata/v1/instance/hostname" -H "Metadata-Flavor: Google"`
hostname.split(".").first
end
def get_disks
instance = `gcloud compute instances describe #{@hostname} --format json --zone #{@zone}`
instance = JSON.parse instance
disks = []
if @options.primary_disk_only
disks.push( instance["disks"][0]["deviceName"] )
else
instance["disks"].each do |d|
disks.push( d["deviceName"] )
end
end
disks
end
def run_backup
disks_backed_up = create_snapshot
delete_old_snapshots(disks_backed_up)
end
def create_snapshot_name(disk_name)
"#{@hostname}--#{disk_name}--#{@time}"
end
def create_snapshot
disks = get_disks
disks.each do |disk_name|
snapshot_name = create_snapshot_name(disk_name)
puts "Creating snapshot #{snapshot_name}" if !@options.silent
`gcloud compute disks snapshot #{disk_name} --snapshot-name #{snapshot_name} --zone #{@zone}`
end
disks
end
def delete_old_snapshots(disks)
snapshots = get_snapshots(disks)
if snapshots.length > 0
snapshots.each do |name|
puts "Deleting snapshot #{name}" if !@options.silent
`gcloud compute snapshots delete #{name} --quiet`
end
else
puts "No snapshots to delete" if !@options.silent
end
end
def get_snapshots(disks)
puts "Finding snapshots older than #{Time.now - @rotate_period} for all attached disks (unless primary_disk_only), excluding those created on day #{@options.rotate_keep_days_of_month} of any month." if !@options.silent
instances = `gcloud compute snapshots list --format json --regex #{@snapshot_name_regex}`
instances = JSON.parse instances
instances.select { |instance| Time.parse(instance["creationTimestamp"]) <= Time.now - (@rotate_period) && Time.parse(instance["creationTimestamp"]).day != @options.rotate_keep_days_of_month && disks.include?(instance["sourceDisk"].split("/").last) }.map { |instance| instance["name"] }
end
end
snapshot = Snapshot.new(ARGV)
snapshot.run_backup
@steevee
Copy link
Author

steevee commented Apr 18, 2016

Usage: snapshotAndRotate.rb [options]
        --rotate_days NUMBEROFDAYSTOKEEP
                                     Keep last X days of snapshots
        --rotate_keep_days_of_month DAYOFMONTHTOKEEP
                                     Keep snapshots created on this day of the month
        --primary_disk_only          Only backup primary disk. Only deletes snapshots if from primary disk too.
        --silent                     Supress output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment