Class: Ec2Backup
- Inherits:
-
Object
- Object
- Ec2Backup
- Defined in:
- lib/ec2-backup/ec2-backup.rb
Instance Method Summary collapse
-
#create_snapshot(options) ⇒ Object
def create_snapshot.
-
#delete_snapshot(snapshot_id) ⇒ Object
def delete_snapshot.
-
#ec2 ⇒ Object
def ec2.
-
#find_instances(tags) ⇒ Object
def find_instances.
-
#initialize ⇒ Ec2Backup
constructor
A new instance of Ec2Backup.
-
#log(text) ⇒ Object
def log.
-
#start ⇒ Object
def start.
-
#too_soon?(history, snapshot_type) ⇒ Boolean
def too_soon?.
-
#volume_snapshots(volume_id) ⇒ Object
def volume_snapshots.
Constructor Details
#initialize ⇒ Ec2Backup
Returns a new instance of Ec2Backup.
5 6 7 8 9 10 11 12 13 14 15 |
# File 'lib/ec2-backup/ec2-backup.rb', line 5 def initialize @settings = YAML.load_file("#{ENV['HOME']}/.ec2-backup.yml") @hourly_snapshots = @settings['hourly_snapshots'] @daily_snapshots = @settings['daily_snapshots'] @weekly_snapshots = @settings['weekly_snapshots'] @monthly_snapshots = @settings['monthly_snapshots'] @tags = @settings['tags'] end |
Instance Method Details
#create_snapshot(options) ⇒ Object
def create_snapshot
Purpose: Creates an EBS snapshot Parameters:
options<~Hash>
volume_id<~String>: The volume id to snapshot
description<~String>: The description of the snapshot
snapshot_type<~String>: The type of snapshot being created (hourly, etc)
tags<~Hash>: Key-value pairs of tags to apply to the snapshot
Returns: nil
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/ec2-backup/ec2-backup.rb', line 88 def create_snapshot() snapshot = ec2.snapshots.new snapshot.volume_id = ['volume_id'] snapshot.description = ['description'] attempts = 0 begin snapshot.save snapshot.reload rescue Fog::Compute::AWS::Error sleep 5 attempts += 1 if attempts == 5 log "Error communicating with API; Unable to save volume `#{['volume_id']}` (Desc: #{['description']})" end return unless attempts == 5 end ['tags'].each do |k,v| begin ec2..create({resource_id: snapshot.id, key: k, value: v}) rescue Errno::EINPROGRESS , Errno::EISCONN log "API Connection Error" sleep 1 retry rescue Fog::Compute::AWS::Error log "Failed attaching tag `'#{k}' => #{v}` to #{['snapshot_type']} snapshot #{snapshot.id}" sleep 1 retry end end end |
#delete_snapshot(snapshot_id) ⇒ Object
def delete_snapshot
Purpose: Delete an EBS snapshot from Amazon EC2 Parameters:
snapshot_id<~String>: The id of the snapshot to be deleted
Returns: nil
131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/ec2-backup/ec2-backup.rb', line 131 def delete_snapshot(snapshot_id) log "\e[0;31m:: Deleting snapshot:\e[0m #{snapshot_id}" begin ec2.delete_snapshot(snapshot_id) sleep 0.2 rescue Fog::Compute::AWS::NotFound log "Failed to delete snapshot: #{snapshot_id}; setting { 'protected' => true }" ec2..create({resource_id: snapshot_id, key: 'protected', value: 'true'}) rescue Fog::Compute::AWS::Error log "API Error" end end |
#ec2 ⇒ Object
def ec2
Purpose: Connects to the Amazon API Parameters: None Returns: Fog::Compute::AWS
37 38 39 |
# File 'lib/ec2-backup/ec2-backup.rb', line 37 def ec2 Fog::Compute::AWS.new(aws_access_key_id: @aws_access_key_id, aws_secret_access_key: @aws_secret_access_key) end |
#find_instances(tags) ⇒ Object
def find_instances
Purpose: Returns all servers with matching key-value tags Parameters:
tags<~Hash>: key-value pairs of tags to match against EC2 instances
Returns: <~Array>
Fog::Compute::AWS::Server
64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/ec2-backup/ec2-backup.rb', line 64 def find_instances() attempts = 0 begin ec2.servers.select { |server| .reject { |k,v| server.[k] == [k] }.empty? } rescue Excon::Errors::ServiceUnavailable sleep 5 attempts += 1 return [] if attempts == 5 retry end end |
#log(text) ⇒ Object
def log
Purpose: Neatly logs events to the screen Parameters:
text<~String>: The text to log to the screen
Returns:
<~String> - Full line of text
26 27 28 |
# File 'lib/ec2-backup/ec2-backup.rb', line 26 def log(text) puts "[#{Time.now}] \e[0;30mCaller: #{caller[0][/`(.*)'/,1]} \e[0m| #{text}" end |
#start ⇒ Object
def start
Purpose: Start the backup process Parameters: none Returns: nil
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/ec2-backup/ec2-backup.rb', line 184 def start @settings['accounts'].each do |account,keys| puts "Account: #{account}" @aws_access_key_id = keys['access_key_id'] @aws_secret_access_key = keys['secret_access_key'] # Find all servers with tags matching the supplied Hash find_instances(@tags).each do |server| # Begin snapshotting each volume attached to the server # server.block_device_mapping.each do |block_device| log "\e[0;32m Searching for matching snapshots \e[0m(#{server.id}:#{block_device}).." snapshots = volume_snapshots(block_device['volumeId']) # Create each type of backup we'll be using # %w(hourly daily weekly monthly).each do |snapshot_type| # Build snapshot history for the working volume and return all snapshots # matching our particular snapshot type history = snapshots.select do |snapshot| snapshot.['snapshot_type'] == snapshot_type && snapshot.['volume_id'] == block_device['volumeId'] && snapshot.['protected'] == 'false' end history.sort_by! { |snapshot| snapshot.created_at } unless too_soon?(history,snapshot_type) || instance_variable_get("@#{snapshot_type}_snapshots") == 0 # Check against threshold limits for backup history and delete as needed # while history.size >= instance_variable_get("@#{snapshot_type}_snapshots") delete_snapshot(history.first.id) history.delete(history.first) end log "Creating #{snapshot_type} for #{block_device['volumeId']}.." create_snapshot({ 'volume_id' => block_device['volumeId'], 'snapshot_type' => snapshot_type, 'description' => "Snapshot::#{snapshot_type.capitalize}> Server: #{server.id}", 'tags' => { 'snapshot_time' => "#{Time.now}", 'snapshot_type' => snapshot_type, 'instance_id' => server.id, 'volume_id' => block_device['volumeId'], 'deviceName' => block_device['deviceName'], 'protected' => 'false' } }) end end end end end end |
#too_soon?(history, snapshot_type) ⇒ Boolean
def too_soon?
Purpose: Determines if enough time has passed between taking snapshots Parameters:
history<~Array>
Fog::Compute::AWS::Snapshot: Volume snapshot
snapshot_type<~String>: The type of snapshot (hourly, etc)
Returns: Boolean
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/ec2-backup/ec2-backup.rb', line 156 def too_soon?(history,snapshot_type) # If the backup history size is zero, # the server doesn't have any backups yet. return false if history.size == 0 elapsed = Time.now - history.last.created_at case snapshot_type when 'hourly' elapsed < 1.hour when 'daily' elapsed < 1.day when 'weekly' elapsed < 1.week when 'monthly' elapsed < 1.month end end |
#volume_snapshots(volume_id) ⇒ Object
def volume_snapshots
Purpose: Returns all snapshots associated with an EBS volume id Parameters:
volume_id<~String>: The volume id of the EBS volume
Returns: <~Array>
Fog::AWS::Snapshot
50 51 52 |
# File 'lib/ec2-backup/ec2-backup.rb', line 50 def volume_snapshots(volume_id) ec2.snapshots.select { |snapshot| snapshot.volume_id == volume_id } end |