class VpsAdmin::CLI::Commands::SnapshotDownload

Public Instance Methods

do_exec(opts) click to toggle source
# File lib/vpsadmin/cli/commands/snapshot_download.rb, line 72
def do_exec(opts)
  @opts = opts
  f = action = nil
  pos = 0

  if @opts[:file] == '-'
    f = STDOUT

  elsif @opts[:file]
    f, action, pos = open_file(@opts[:file])
  end

  dl, created = find_or_create_dl(@opts, action != :resume)
  f, action, pos = open_file(dl.file_name) unless @opts[:file]

  if created
    if action == :resume
      warn "Unable to resume the download: the file has been deleted from the server"
      exit(false)
    end

    msg "The download is being prepared..."
    sleep(5)

  else
    warn "Reusing existing SnapshotDownload (id=#{dl.id})"
  end

  msg "Downloading to #{f.path}"

  begin
    VpsAdmin::CLI::StreamDownloader.download(
        @api,
        dl,
        f,
        progress: !@opts[:quiet] && (f == STDOUT ? STDERR : STDOUT),
        position: pos,
        max_rate: @opts[:max_rate],
        checksum: @opts[:checksum],
    )

  rescue VpsAdmin::CLI::DownloadError => e
    warn e.message
    exit(false)
    
  ensure
    f.close
  end

  @api.snapshot_download.delete(dl.id) if @opts[:delete_after]
end
exec(args) click to toggle source
# File lib/vpsadmin/cli/commands/snapshot_download.rb, line 57
def exec(args)
  if args.size == 0 && STDIN.tty?
    @opts[:snapshot] = snapshot_chooser

  elsif args.size != 1
    warn "Provide exactly one SNAPSHOT_ID as an argument"
    exit(false)

  else
    @opts[:snapshot] = args.first.to_i
  end
  
  do_exec(@opts)
end
options(opts) click to toggle source
# File lib/vpsadmin/cli/commands/snapshot_download.rb, line 7
def options(opts)
  @opts = {
      delete_after: true,
      send_mail: false,
      checksum: true,
      format: 'archive',
  }

  opts.on('-f', '--format FORMAT', 'archive, stream or incremental_stream') do |f|
    @opts[:format] = f
  end
  
  opts.on('-I', '--from-snapshot SNAPSHOT_ID', Integer, 'Download snapshot incrementally from SNAPSHOT_ID') do |s|
    @opts[:from_snapshot] = s
  end

  opts.on('-d', '--[no-]delete-after', 'Delete the file from the server after successful download') do |d|
    @opts[:delete_after] = d
  end

  opts.on('-F', '--force', 'Overwrite existing files if necessary') do |f|
    @opts[:force] = f
  end

  opts.on('-o', '--output FILE', 'Save the download to FILE') do |f|
    @opts[:file] = f
  end

  opts.on('-q', '--quiet', 'Print only errors') do |q|
    @opts[:quiet] = q
  end

  opts.on('-r', '--resume', 'Resume cancelled download') do |r|
    @opts[:resume] = r
  end

  opts.on('-s', '--[no-]send-mail', 'Send mail after the file for download is completed') do |s|
    @opts[:send_mail] = s
  end

  opts.on('-x', '--max-rate N', Integer, 'Maximum download speed in kB/s') do |r|
    exit_msg('--max-rate must be greater than zero') if r <= 0
    @opts[:max_rate] = r
  end

  opts.on('--[no-]checksum', 'Verify checksum of the downloaded data (enabled)') do |c|
    @opts[:checksum] = c
  end
end

Protected Instance Methods

open_file(path) click to toggle source
# File lib/vpsadmin/cli/commands/snapshot_download.rb, line 125
def open_file(path)
  f = action = nil
  pos = 0

  if File.exists?(path) && File.size(path) > 0
    if @opts[:resume]
      action = :resume

    elsif @opts[:force]
      action = :overwrite

    elsif STDIN.tty?
      while action.nil?
        STDERR.write("'#{path}' already exists. [A]bort, [r]esume or [o]verwrite? [a]: ")
        STDERR.flush

        action = {
            'r' => :resume,
            'o' => :overwrite,
            '' => false,
        }[STDIN.readline.strip.downcase]
      end

    else
      warn "File '#{path}' already exists"
      exit(false)
    end
    
    case action
    when :resume
      mode = 'a+'
      pos = File.size(path)

    when :overwrite
      mode = 'w'

    else
      exit
    end

    f = File.open(path, mode)
  else
    f = File.open(path, 'w')
  end

  [f, action, pos]
end
snapshot_chooser() click to toggle source
# File lib/vpsadmin/cli/commands/snapshot_download.rb, line 173
def snapshot_chooser
  user = @api.user.current
  vpses = @api.vps.list(user: user.id)

  ds_map = {}
  vpses.each do |vps|
    ds_map[vps.dataset_id] = vps
  end

  i = 1
  snap_map = {}

  @api.dataset.index(user: user.id).each do |ds|
    snapshots = ds.snapshot.index
    next if snapshots.empty?

    if vps = ds_map[ds.id]
      puts "VPS ##{vps.id}"

    else
      puts "Dataset #{ds.name}"
    end

    snapshots.each do |s|
      snap_map[i] = s
      puts "  (#{i}) @#{s.created_at}"
      i += 1
    end
  end

  if snap_map.empty?
    warn "There are no snapshots to choose from, create one first."
    exit(false)
  end

  loop do
    STDOUT.write('Pick a snapshot for download: ')
    STDOUT.flush

    i = STDIN.readline.strip.to_i
    next if i <= 0 || snap_map[i].nil?

    return snap_map[i].id
  end
end