Class: Aebus::Core
Constant Summary collapse
- AWS_NAME_TAG =
"Name"- AEBUS_TAG =
"Aebus"
Class Method Summary collapse
-
.name_and_desc(volume_id, tags, utc_time) ⇒ Array
calculates the name and the description to be set to a snapshot.
Instance Method Summary collapse
- #backup(args, options) ⇒ Object
-
#backup_volume(volume_id, tags) ⇒ boolean
backs up a given volume using the given time as part of the name and setting the given tags to the snapshot.
- #check_status(target_volumes) ⇒ Object
- #get_snapshots_map ⇒ Object
- #init_logger(options) ⇒ Object
- #purge_snapshot(snapshot_id) ⇒ Object
- #send_report(message) ⇒ Object
- #status(args, options) ⇒ Object
- #target_volumes(args) ⇒ Object
- #validate_target_volumes(target_volumes) ⇒ Object
Methods included from Logging
Class Method Details
.name_and_desc(volume_id, tags, utc_time) ⇒ Array
calculates the name and the description to be set to a snapshot
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/aebus.rb', line 227 def self.name_and_desc(volume_id, , utc_time) name = "backup_#{utc_time.strftime("%Y%m%d")}_#{volume_id}" volume_name = volume_id .each do |tag| if tag["key"].eql?(AWS_NAME_TAG) volume_name = tag["value"] break end end description = "Backup for volume #{volume_name} taken at #{utc_time.strftime("%Y-%m-%d %H:%M:%S")}" return [name, description] end |
Instance Method Details
#backup(args, options) ⇒ Object
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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/aebus.rb', line 89 def backup(args, ) backed_up = 0 max_delay = 0 purged = 0 to_purge = 0 to_backup = 0 @current_time_utc = Time.now.utc @config = Config::Config.new(File.join(File.dirname("."), .config), @current_time_utc) init_logger logger.info("backup started at #{@current_time_utc}") @ec2 = AWS::EC2::Base.new(:access_key_id => @config.defaults["access_key_id"], :secret_access_key => @config.defaults["secret_access_key"], :server => EC2::zone_to_url(@config.defaults["zone"])) target_volumes = target_volumes(args) abort("Configuration contains invalid volumes") unless validate_target_volumes(target_volumes) if (.manual) then target_volumes.each do |volume| to_backup += 1 break unless backup_volume(volume, [EC2::AEBUS_MANUAL_TAG]) backed_up += 1 end else snap_map = get_snapshots_map target_volumes.each do |target| volume = @config.volumes[target] to_be_run = volume.backups_to_be_run(snap_map[target], @current_time_utc) max_delay = [max_delay, to_be_run[0]].max = to_be_run[1] if .count > 0 << EC2::AEBUS_AUTO_TAG logger.info("Creating backup for volume #{target} with tags #{.join(',')}, max delay #{max_delay}") to_backup +=1 break unless backup_volume(target, ) backed_up += 1 else logger.info("Volume #{target} does not need to be backed up") end end snap_map = get_snapshots_map # we reload the map since we may have created more snapshots if .purge then target_volumes.each do |target| volume = @config.volumes[target] purgeable_snapshot_ids = volume.purgeable_snapshot_ids(snap_map[target]) purgeable_snapshot_ids.each do |snapshot_id| to_purge += 1 purged += 1 if purge_snapshot(snapshot_id) end end else logger.info("Skipping purging phase") end end = "Backup Completed at #{Time.now}. Checked #{target_volumes.count} volume(s), #{to_backup} to be backed up, #{backed_up} actually backed up, max delay detected #{max_delay}s, #{to_purge} purgeable snapshot(s), #{purged} purged" logger.info() puts() if to_backup > 0 or to_purge > 0 then send_report end end |
#backup_volume(volume_id, tags) ⇒ boolean
backs up a given volume using the given time as part of the name and setting the given tags to the snapshot
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 |
# File 'lib/aebus.rb', line 186 def backup_volume(volume_id, ) begin volume_info = @ec2.describe_volumes(:volume_id => volume_id) rescue AWS::Error => e logger.error("Volume Id #{volume_id} not found. Underlying message #{e.}") return false end begin tag_set = volume_info.volumeSet.item[0].tagSet = (tag_set and tag_set.item) ? tag_set.item : [] name_and_desc = Core.name_and_desc(volume_id, , @current_time_utc) create_response = @ec2.create_snapshot(:volume_id => volume_id, :description => name_and_desc[1]) rescue AWS::Error => e logger.error("Volume Id #{volume_id} could not be backed up. Underlying message #{e.}") return false end begin @ec2.(:resource_id => create_response.snapshotId, :tag => [{AWS_NAME_TAG => name_and_desc[0]}, {AEBUS_TAG => .join(',')}]) rescue AWS::Error => e logger.error("[WARNING] Could not set tags to snapshot #{create_response.snapshotId}. Underlying message #{e.}") return false end logger.info("Created snapshot #{create_response.snapshotId} for volume #{volume_id}") true end |
#check_status(target_volumes) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/aebus.rb', line 48 def check_status(target_volumes) result = {} result[:timestamp] = @current_time_utc snap_map = get_snapshots_map result[:volumes] = Array.new to_backup = 0 to_purge = 0 target_volumes.each do |target| vs = VolumeStatus.new(target) volume = @config.volumes[target] vs.last_backup = volume.last_backup vs.next_backup = volume.next_backup to_be_run = volume.backups_to_be_run(snap_map[target], @current_time_utc) vs.delay = to_be_run[0] vs. = to_be_run[1] if vs.needs_backup? logger.info("Volume #{target} needs to be backed up. Tags: #{vs..join(',')}, max delay #{vs.delay}") to_backup += 1 else logger.info("Volume #{target} does not need to be backed up") end vs.purgeable_snapshot_ids = volume.purgeable_snapshot_ids(snap_map[target]) to_purge += vs.purgeable_snapshot_ids.count if vs.purgeable_snapshot_ids logger.info("Volume #{target} has #{vs.purgeable_snapshot_ids.count} purgeable snapshot(s): #{vs.purgeable_snapshot_ids.join(',')}") result[:volumes] << vs end result[:to_backup] = to_backup result[:to_purge] = to_purge result[:delay] = result[:volumes].inject([0]) {|acc, vs| acc << vs.delay}.max result[:total] = result[:volumes].count result end |
#get_snapshots_map ⇒ Object
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/aebus.rb', line 244 def get_snapshots_map response = @ec2.describe_snapshots(:owner => 'self') snap_array = response.snapshotSet.item result = Hash.new snap_array.each do |snap| snapshot = EC2::Snapshot.new(snap) if result.include?(snapshot.volume_id) vol_array = result[snapshot.volume_id] index = vol_array.index{ |s| snapshot.start_time > s.start_time} index ||= vol_array.count vol_array.insert(index, snapshot) else vol_array = Array.new vol_array << snapshot result.store(snapshot.volume_id, vol_array) end end result end |
#init_logger(options) ⇒ Object
178 179 180 |
# File 'lib/aebus.rb', line 178 def init_logger() Logging.log_to_file(.logfile) unless .logfile.nil? end |
#purge_snapshot(snapshot_id) ⇒ Object
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/aebus.rb', line 266 def purge_snapshot(snapshot_id) begin response = @ec2.delete_snapshot(:snapshot_id => snapshot_id) if response['return'] logger.info("Purged snapshot #{snapshot_id}") true else false end rescue AWS::Error => e logger.warn("Could not purge snapshot #{snapshot_id}; underlying message #{e.}") false end end |
#send_report(message) ⇒ Object
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/aebus.rb', line 294 def send_report() if .nil? logger.warn('Tried to send a message, but no message was specified') return end to_address = @config.defaults["to_address"] from_address = @config.defaults["from_address"] if to_address.nil? or from_address.nil? logger.warn('Tried to send a message but either to or from address where missing from configuration') return end ses = AWS::SES::Base.new( :access_key_id => @config.defaults["access_key_id"], :secret_access_key => @config.defaults["secret_access_key"] ) logger.info("Sending report to #{to_address} from account #{from_address}") ses.send_email :to => to_address, :source => from_address, :subject => "Aebus Report", :text_body => end |
#status(args, options) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/aebus.rb', line 22 def status(args, ) @current_time_utc = Time.now.utc init_logger logger.info("status check started at #{@current_time_utc}") @config = Config::Config.new(File.join(File.dirname("."), .config), @current_time_utc) @ec2 = AWS::EC2::Base.new(:access_key_id => @config.defaults["access_key_id"], :secret_access_key => @config.defaults["secret_access_key"], :server => EC2::zone_to_url(@config.defaults["zone"])) target_volumes = target_volumes(args) abort("Configuration contains invalid volumes") unless validate_target_volumes(target_volumes) status = check_status(target_volumes) = "status check completed - #{status[:total]} volume(s) checked, #{status[:to_backup]} to be backed up, max delay detected #{status[:delay]}s, #{status[:to_purge]} snapshots to be purged" logger.info puts end |
#target_volumes(args) ⇒ Object
167 168 169 170 171 172 173 174 175 176 |
# File 'lib/aebus.rb', line 167 def target_volumes(args) result = @config.volume_ids if args && (args.count > 0) then result &= args end result end |
#validate_target_volumes(target_volumes) ⇒ Object
282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/aebus.rb', line 282 def validate_target_volumes(target_volumes) begin @ec2.describe_volumes(:volume_id => target_volumes) logger.info("Target volumes validated") true rescue AWS::Error => e logger.error("Target validation failed with message '#{e.}' Check your configuration") false end end |