lib/backup/model.rb in backup-3.0.27 vs lib/backup/model.rb in backup-3.1.0

- old
+ new

@@ -1,39 +1,28 @@ # encoding: utf-8 module Backup class Model - include Backup::CLI::Helpers - class << self ## # The Backup::Model.all class method keeps track of all the models # that have been instantiated. It returns the @all class variable, # which contains an array of all the models def all @all ||= [] end ## - # Return the first model matching +trigger+. - # Raises Errors::MissingTriggerError if no matches are found. - def find(trigger) - trigger = trigger.to_s - all.each do |model| - return model if model.trigger == trigger + # Return an Array of Models matching the given +trigger+. + def find_by_trigger(trigger) + if trigger.include?('*') + regex = /^#{ trigger.to_s.gsub('*', '(.*)') }$/ + all.select {|model| regex =~ model.trigger } + else + all.select {|model| trigger == model.trigger } end - raise Errors::Model::MissingTriggerError, - "Could not find trigger '#{trigger}'." end - - ## - # Find and return an Array of all models matching +trigger+ - # Used to match triggers using a wildcard (*) - def find_matching(trigger) - regex = /^#{ trigger.to_s.gsub('*', '(.*)') }$/ - all.select {|model| regex =~ model.trigger } - end end ## # The trigger (stored as a String) is used as an identifier # for initializing the backup process @@ -182,22 +171,10 @@ EOS end end ## - # Ensure DATA_PATH and DATA_PATH/TRIGGER are created - # if they do not yet exist - # - # Clean any temporary files and/or package files left over - # from the last time this model/trigger was performed. - # Logs warnings if files exist and are cleaned. - def prepare! - FileUtils.mkdir_p(File.join(Config.data_path, trigger)) - Cleaner.prepare(self) - end - - ## # Performs the backup process ## # [Databases] # Runs all (if any) database objects to dump the databases ## @@ -246,10 +223,12 @@ def perform! @started_at = Time.now @time = @started_at.strftime("%Y.%m.%d.%H.%M.%S") log!(:started) + prepare! + if databases.any? or archives.any? procedures.each do |procedure| (procedure.call; next) if procedure.is_a?(Proc) procedure.each(&:perform!) end @@ -258,46 +237,30 @@ syncers.each(&:perform!) notifiers.each(&:perform!) log!(:finished) rescue Exception => err - fatal = !err.is_a?(StandardError) - - err = Errors::ModelError.wrap(err, <<-EOS) - Backup for #{label} (#{trigger}) Failed! - An Error occured which has caused this Backup to abort before completion. - EOS - Logger.error err - Logger.error "\nBacktrace:\n\s\s" + err.backtrace.join("\n\s\s") + "\n\n" - - Cleaner.warnings(self) - - if fatal - Logger.error Errors::ModelError.new(<<-EOS) - This Error was Fatal and Backup will now exit. - If you have other Backup jobs (triggers) configured to run, - they will not be processed. - EOS - else - Logger.message Errors::ModelError.new(<<-EOS) - If you have other Backup jobs (triggers) configured to run, - Backup will now attempt to continue... - EOS - end - - notifiers.each do |n| - begin - n.perform!(true) - rescue Exception; end - end - - exit(1) if fatal + log!(:failure, err) + send_failure_notifications + exit(1) unless err.is_a?(StandardError) end private ## + # Ensure DATA_PATH and DATA_PATH/TRIGGER are created + # if they do not yet exist + # + # Clean any temporary files and/or package files left over + # from the last time this model/trigger was performed. + # Logs warnings if files exist and are cleaned. + def prepare! + FileUtils.mkdir_p(File.join(Config.data_path, trigger)) + Cleaner.prepare(self) + end + + ## # After all the databases and archives have been dumped and sorted, # these files will be bundled in to a .tar archive (uncompressed), # which may be optionally Encrypted and/or Split into multiple "chunks". # All information about this final archive is stored in the @package. # Once complete, the temporary folder used during packaging is removed. @@ -350,25 +313,48 @@ end klass end ## - # Logs messages when the backup starts and finishes - def log!(action) + # Logs messages when the backup starts, finishes or fails + def log!(action, exception = nil) case action when :started - Logger.message "Performing Backup for '#{label} (#{trigger})'!\n" + + Logger.info "Performing Backup for '#{label} (#{trigger})'!\n" + "[ backup #{ Version.current } : #{ RUBY_DESCRIPTION } ]" when :finished msg = "Backup for '#{ label } (#{ trigger })' " + "Completed %s in #{ elapsed_time }" if Logger.has_warnings? Logger.warn msg % 'Successfully (with Warnings)' else - Logger.message msg % 'Successfully' + Logger.info msg % 'Successfully' end + + when :failure + err = Errors::ModelError.wrap(exception, <<-EOS) + Backup for #{label} (#{trigger}) Failed! + An Error occured which has caused this Backup to abort before completion. + EOS + Logger.error err + Logger.error "\nBacktrace:\n\s\s" + err.backtrace.join("\n\s\s") + "\n\n" + + Cleaner.warnings(self) + + if exception.is_a?(StandardError) + Logger.info Errors::ModelError.new(<<-EOS) + If you have other Backup jobs (triggers) configured to run, + Backup will now attempt to continue... + EOS + else + Logger.error Errors::ModelError.new(<<-EOS) + This Error was Fatal and Backup will now exit. + If you have other Backup jobs (triggers) configured to run, + they will not be processed. + EOS + end end end ## # Returns a string representing the elapsed time since the backup started. @@ -377,9 +363,25 @@ hours = duration / 3600 remainder = duration - (hours * 3600) minutes = remainder / 60 seconds = remainder - (minutes * 60) '%02d:%02d:%02d' % [hours, minutes, seconds] + end + + ## + # Sends notifications when a backup fails. + # Errors are logged and rescued, since the error that caused the + # backup to fail could have been an error with a notifier. + def send_failure_notifications + notifiers.each do |n| + begin + n.perform!(true) + rescue Exception => err + Logger.error Errors::ModelError.wrap(err, <<-EOS) + #{ n.class } Failed to send notification of backup failure. + EOS + end + end end end end