class DoSnapshot::Command

Our commands live here :)

Constants

RESET_OPTIONS

Attributes

api[W]
clean[RW]
delay[RW]
droplets[RW]
exclude[RW]
keep[RW]
only[RW]
protocol[RW]
quiet[RW]
shutdown[RW]
stop[RW]
stop_by_power[RW]
threads[W]
timeout[RW]

Public Class Methods

new(*args) click to toggle source
# File lib/do_snapshot/command.rb, line 14
def initialize(*args)
  load_options(*args)
end

Public Instance Methods

api() click to toggle source

API launcher

# File lib/do_snapshot/command.rb, line 100
def api
  @api ||= DoSnapshot::Adapter.api(protocol, delay: delay, timeout: timeout, stop_by: stop_by)
end
create_snapshot(droplet) click to toggle source

Trying to create a snapshot.

# File lib/do_snapshot/command.rb, line 60
def create_snapshot(droplet) # rubocop:disable MethodLength,Metrics/AbcSize
  fail_if_shutdown(droplet)

  logger.info "Start creating snapshot for droplet id: #{droplet.id} name: #{droplet.name}."

  today         = DateTime.now
  name          = "#{droplet.name}_#{today.strftime('%Y_%m_%d')}"
  # noinspection RubyResolve
  snapshot_size = api.snapshots(droplet).size

  logger.debug 'Wait until snapshot will be created.'

  api.create_snapshot droplet.id, name

  snapshot_size += 1

  logger.info "Snapshot name: #{name} created successfully."
  logger.info "Droplet id: #{droplet.id} name: #{droplet.name} snapshots: #{snapshot_size}."

  # Cleanup snapshots.
  cleanup_snapshots droplet, snapshot_size if clean
rescue => e
  case e.class.to_s
  when 'DoSnapshot::SnapshotCleanupError'
    raise e.class, e.message, e.backtrace
  when 'DoSnapshot::DropletPowerError'
    return
  else
    raise SnapshotCreateError.new(droplet.id), e.message, e.backtrace
  end
end
fail_power_off(e) click to toggle source
# File lib/do_snapshot/command.rb, line 27
def fail_power_off(e)
  return unless shutdown
  return unless e && e.id
  api.start_droplet(e.id)
rescue
  raise DropletFindError, e.message, e.backtrace
end
load_options(options = {}, skip = %w()) click to toggle source
# File lib/do_snapshot/command.rb, line 35
def load_options(options = {}, skip = %w())
  reset_options
  options.each_pair do |key, option|
    send("#{key}=", option) unless skip.include?(key)
  end if options
end
power_on_failed_droplets() click to toggle source
# File lib/do_snapshot/command.rb, line 92
def power_on_failed_droplets
  processed_droplet_ids
    .select { |id| api.inactive?(id) }
    .each   { |id| api.power_on(id) }
end
processed_droplet_ids() click to toggle source

Processed droplets

# File lib/do_snapshot/command.rb, line 106
def processed_droplet_ids
  @droplet_ids ||= %w()
end
reset_options() click to toggle source
# File lib/do_snapshot/command.rb, line 42
def reset_options
  RESET_OPTIONS.each do |key|
    send("#{key}=", nil)
  end
end
snap() click to toggle source
# File lib/do_snapshot/command.rb, line 18
def snap
  logger.info 'Start performing operations'
  work_with_droplets
  power_on_failed_droplets
  logger.info 'All operations has been finished.'

  mailer.notify if mailer && notify && !quiet
end
stop_droplet(droplet) click to toggle source
# File lib/do_snapshot/command.rb, line 48
def stop_droplet(droplet)
  return true unless shutdown
  logger.debug 'Shutting down droplet.'
  api.stop_droplet(droplet.id) unless droplet.status.include? 'off'
  true
rescue => e
  logger.error e.message
  false
end

Protected Instance Methods

cleanup_snapshots(droplet, size) click to toggle source

Cleanup our snapshots.

# File lib/do_snapshot/command.rb, line 199
def cleanup_snapshots(droplet, size) # rubocop:disable Metrics/AbcSize
  return unless size > keep

  warning_size(droplet.id, droplet.name, size)

  logger.debug "Cleaning up snapshots for droplet id: #{droplet.id} name: #{droplet.name}."

  api.cleanup_snapshots(droplet, size - keep - 1)
rescue => e
  raise SnapshotCleanupError, e.message, e.backtrace
end
dispatch_droplets() click to toggle source

Dispatch received droplets, each by each.

# File lib/do_snapshot/command.rb, line 148
def dispatch_droplets
  droplets.each do |droplet|
    id = droplet.id.to_s
    next if exclude.include? id
    next unless only.empty? || only.include?(id)

    prepare_droplet id, droplet.name
  end
end
fail_if_shutdown(droplet) click to toggle source
# File lib/do_snapshot/command.rb, line 192
def fail_if_shutdown(droplet)
  return unless shutdown
  fail DropletPowerError.new(droplet.id), droplet.name unless api.inactive?(droplet.id)
end
load_droplets() click to toggle source

Getting droplets list from API. And store into object.

# File lib/do_snapshot/command.rb, line 141
def load_droplets
  logger.debug 'Loading list of DigitalOcean droplets'
  self.droplets = api.droplets
end
notify() click to toggle source
# File lib/do_snapshot/command.rb, line 117
def notify
  @notify ||= false
end
prepare_droplet(id, name) click to toggle source

Preparing droplet to take a snapshot. Droplet instance must be powered off first!

# File lib/do_snapshot/command.rb, line 175
def prepare_droplet(id, name)
  logger.debug "Droplet id: #{id} name: #{name}\n"
  droplet = api.droplet id

  return unless droplet
  logger.info "Preparing droplet id: #{droplet.id} name: #{droplet.name} to take snapshot."
  return if too_much_snapshots?(droplet)
  processed_droplet_ids << droplet.id
  thread_runner(droplet)
end
stop_by() click to toggle source
# File lib/do_snapshot/command.rb, line 125
def stop_by
  stop_by_power ? :power_status : :event_status
end
thread_chain() click to toggle source

Join threads

# File lib/do_snapshot/command.rb, line 160
def thread_chain
  threads.each(&:join)
end
thread_runner(droplet) click to toggle source

Run threads

# File lib/do_snapshot/command.rb, line 166
def thread_runner(droplet)
  threads << Thread.new do
    create_snapshot droplet if stop_droplet(droplet)
  end
end
threads() click to toggle source
# File lib/do_snapshot/command.rb, line 121
def threads
  @threads ||= []
end
too_much_snapshots?(instance) click to toggle source
# File lib/do_snapshot/command.rb, line 186
def too_much_snapshots?(instance)
  return false if api.snapshots(instance).size < keep
  warning_size(instance.id, instance.name, keep)
  stop ? true : false
end
warning_size(id, name, keep) click to toggle source

Helpers

# File lib/do_snapshot/command.rb, line 213
def warning_size(id, name, keep)
  message = "For droplet with id: #{id} and name: #{name} the maximum number #{keep} of snapshots is reached."
  logger.warn message
  @notify = true
end
work_with_droplets() click to toggle source

Working with list of droplets.

# File lib/do_snapshot/command.rb, line 131
def work_with_droplets
  load_droplets
  dispatch_droplets
  logger.debug 'Working with list of DigitalOcean droplets'
  thread_chain
end