Class: Skytap::Commands::Upload

Inherits:
Base
  • Object
show all
Defined in:
lib/skytap/plugins/vm_upload.rb

Constant Summary collapse

MAX_CONCURRENCY =
5
CHECK_PERIOD =
15
AT_CAPACITY_RETRY_PERIOD =
15.minutes.to_i

Instance Attribute Summary collapse

Attributes inherited from Base

#args, #command_options, #error, #global_options, #invoker, #logger

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#api_token, #ask, #ask_param, #command_line_params, command_name, #composed_params, #expected_options, #file_params, #find_id, #initialize, #interactive_params, #invoke, make_from, #noninteractive_params, #programmatic?, #solicit_user_input?, #username

Methods included from Help

#description, #help!, #help?, included, #synopsis, #version?

Constructor Details

This class inherits a constructor from Skytap::Commands::Base

Instance Attribute Details

#uploadersObject (readonly)

Returns the value of attribute uploaders.



10
11
12
# File 'lib/skytap/plugins/vm_upload.rb', line 10

def uploaders
  @uploaders
end

#vmsObject (readonly)

What was passed in, either a reference to a VM directory or a VM archive file.



9
10
11
# File 'lib/skytap/plugins/vm_upload.rb', line 9

def vms
  @vms
end

Class Method Details

.descriptionObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/skytap/plugins/vm_upload.rb', line 16

def self.description
    <<-"EOF"
Upload one or more VM directories or VM archive files to Skytap

The file must be one of the following archive types:
  .tgz .tar.gz .tbz .tbz2 .tar.bz2 .tar .ova .ovf .7z .7z.001 .zip

The contents of the archive file must contain a VMware image in either
VMX/VMDK or OVF/VMDK format.

See the following page for more information:
https://cloud.skytap.com/docs/index.php/Importing_and_Exporting_Virtual_Machines#How_to_Import_VMs_in_to_Skytap
    EOF
end

Instance Method Details

#active_uploadersObject



163
164
165
# File 'lib/skytap/plugins/vm_upload.rb', line 163

def active_uploaders
  uploaders.reject(&:finished?)
end

#concurrency_at_overageObject



68
69
70
# File 'lib/skytap/plugins/vm_upload.rb', line 68

def concurrency_at_overage
  @concurrency_at_overage
end

#estimated_available_slotsObject



138
139
140
141
142
143
144
# File 'lib/skytap/plugins/vm_upload.rb', line 138

def estimated_available_slots
  if full?
    0
  else
    MAX_CONCURRENCY - concurrency
  end
end

#expected_argsObject



31
32
33
34
35
# File 'lib/skytap/plugins/vm_upload.rb', line 31

def expected_args
  ActiveSupport::OrderedHash[
    'file*', 'One or more directories or VM archive files to upload'
  ]
end

#finished?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/skytap/plugins/vm_upload.rb', line 121

def finished?
  vms.empty? && concurrency == 0
end

#full?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/skytap/plugins/vm_upload.rb', line 155

def full?
  @full_at
end

#kick_off_import(vm, params) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/skytap/plugins/vm_upload.rb', line 72

def kick_off_import(vm, params)
  begin
    # Create import job on server in main thread.
    job = VmImportJob.new(logger, username, api_token, vm, params)

    # If successful, start FTP upload and subsequent steps in new thread.
    up = Uploader.new(job)
    uploaders << up
    log_line(up.status_line)
  rescue NoSlotsAvailable => ex
    vms << vm
    signal_full
    log_line(("#{vm}: " << no_capacity_message).color(:yellow))
  rescue Exception => ex
    up = DeadUploader.new(vm, ex)
    uploaders << up
    log_line(up.status_line)
  end
end

#log_line(msg, include_separator = true) ⇒ Object



103
104
105
106
107
# File 'lib/skytap/plugins/vm_upload.rb', line 103

def log_line(msg, include_separator=true)
  line = msg
  line += "\n---" if include_separator
  logger.info line
end

#no_capacity_messageObject



92
93
94
95
96
97
98
99
100
101
# File 'lib/skytap/plugins/vm_upload.rb', line 92

def no_capacity_message
  m = AT_CAPACITY_RETRY_PERIOD / 60
  "No import capacity is currently available on Skytap. Will retry in #{m} minutes".tap do |msg|
    if active_uploaders.present?
      msg << ' or when another import completes.'
    else
      msg << '.'
    end
  end
end

#parametersObject



37
38
39
40
41
42
43
44
# File 'lib/skytap/plugins/vm_upload.rb', line 37

def parameters
  # Only display import parameters if a single VM will be uploaded.
  if args.length == 1
    Import.subcommands.detect{|s| s.command_name == 'create'}.spec['params']
  else
    {}
  end
end


109
110
111
112
113
# File 'lib/skytap/plugins/vm_upload.rb', line 109

def print_status
  if (stat = status_lines).present?
    log_line(stat)
  end
end


115
116
117
118
119
# File 'lib/skytap/plugins/vm_upload.rb', line 115

def print_summary
  unless response.error?
    logger.info "#{'Summary'.bright}\n#{response.payload}"
  end
end

#run!Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/skytap/plugins/vm_upload.rb', line 46

def run!
  @vms = args
  @uploaders = []
  params = composed_params

  until finished?
    if vms.present? && slots_available?
      kick_off_import(vms.shift, params.dup)
    else
      sleep CHECK_PERIOD
      print_status
      invoker.try(:call, self)

      signal_available if signal_stale? || (concurrency_at_overage && concurrency < concurrency_at_overage)
    end
  end

  signal_available
  print_summary
  return response
end

#seconds_until_retryObject



133
134
135
136
# File 'lib/skytap/plugins/vm_upload.rb', line 133

def seconds_until_retry
  return unless full?
  [0, AT_CAPACITY_RETRY_PERIOD - (Time.now - @full_at)].max
end

#signal_availableObject



151
152
153
# File 'lib/skytap/plugins/vm_upload.rb', line 151

def signal_available
  @concurrency_at_overage = @full_at = nil
end

#signal_fullObject



146
147
148
149
# File 'lib/skytap/plugins/vm_upload.rb', line 146

def signal_full
  @concurrency_at_overage = concurrency
  @full_at = Time.now
end

#signal_stale?Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/skytap/plugins/vm_upload.rb', line 129

def signal_stale?
  full? && Time.now - @full_at > AT_CAPACITY_RETRY_PERIOD
end

#slots_available?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/skytap/plugins/vm_upload.rb', line 125

def slots_available?
  estimated_available_slots > 0
end

#status_linesObject



159
160
161
# File 'lib/skytap/plugins/vm_upload.rb', line 159

def status_lines
  active_uploaders.collect(&:status_line).join("\n")
end