class BoxGrinder::ElasticHostsPlugin

Public Instance Methods

api_url(path) click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 96
def api_url(path)
  "#{@plugin_config['ssl'] ? 'https' : 'http'}://#{CGI.escape(@plugin_config['username'])}:#{@plugin_config['password']}@#{@plugin_config['endpoint']}#{path}"
end
compress(data) click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 132
def compress(data)
  @log.trace "Compressing #{data.size / 1024} kB chunk of data..."

  io = StringIO.new

  writer = Zlib::GzipWriter.new(io, Zlib::DEFAULT_COMPRESSION, Zlib::FINISH)
  writer.write(data)
  writer.close

  @log.trace "Data compressed to #{io.size / 1024} kB."

  io.string
end
create_remote_disk() click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 72
def create_remote_disk
  size = disk_size

  @log.info "Creating new #{size} GB disk..."


  body = hash_to_request(
      'size' => size * 1024 *1024 * 1024,
      'name' => @plugin_config['drive_name']
  )

  begin
    ret = response_to_hash(RestClient.post(api_url('/drives/create'), body))


    @log.info "Disk created with UUID: #{ret['drive']}."
  rescue => e
    @log.error e.info
    raise PluginError, "An error occured while creating the drive, #{e.message}. See logs for more info."
  end

  ret['drive']
end
create_server() click to toggle source

Creates the server for previously uploaded disk

# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 182
def create_server
  @log.info "Creating new server..."

  memory = ((is_cloudsigma? and @appliance_config.hardware.memory < 512) ? 512 : @appliance_config.hardware.memory)

  body = hash_to_request(
      'name' => "#{@appliance_config.name}-#{@appliance_config.version}.#{@appliance_config.release}",
      'cpu' => @appliance_config.hardware.cpus * 1000, # MHz
      'smp' => 'auto',
      'mem' => memory,
      'persistent' => 'true', # hack
      'ide:0:0' => @plugin_config['drive_uuid'],
      'boot' => 'ide:0:0',
      'nic:0:model' => 'e1000',
      'nic:0:dhcp' => 'auto',
      'vnc:ip' => 'auto',
      'vnc:password' => (0...8).map { (('a'..'z').to_a + ('A'..'Z').to_a)[rand(52)] }.join # 8 character VNC password
  )

  begin
    path = is_cloudsigma? ? '/servers/create' : '/servers/create/stopped'
    ret = response_to_hash(RestClient.post(api_url(path), body))

    @log.info "Server was registered with '#{ret['name']}' name as '#{ret['server']}' UUID. Use web UI or API tools to start your server."
  rescue => e
    @log.error e.info
    raise PluginError, "An error occurred while creating the server, #{e.message}. See logs for more info."
  end
end
disk_size() click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 46
def disk_size
  size = 0
  @appliance_config.hardware.partitions.each_value { |partition| size += partition['size'] }
  size
end
execute() click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 41
def execute
  upload
  create_server
end
hash_to_request(h) click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 52
def hash_to_request(h)
  body = ""

  h.sort.each do |k, v|
    body << "#{k} #{v.to_s}\n"
  end

  body
end
is_cloudsigma?() click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 177
def is_cloudsigma?
  !@plugin_config['endpoint'].match(/cloudsigma\.com$/).nil?
end
response_to_hash(r) click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 62
def response_to_hash(r)
  h = {}

  r.each_line do |l|
    h[$1] = $2 if l =~ /(\w+) (.*)/
  end

  h
end
upload() click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 100
def upload
  @log.info "Uploading appliance..."

  # Create the disk with specific size or use already existing
  @plugin_config['drive_uuid'] = create_remote_disk unless @plugin_config['drive_uuid']

  upload_chunks

  @log.info "Appliance uploaded."
end
upload_chunk(data, part) click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 146
def upload_chunk(data, part)
  try = 1

  url = api_url("/drives/#{@plugin_config['drive_uuid']}/write/#{@step * part}")

  begin
    @log.info "Uploading part #{part+1}..."

    headers = {:content_type => "application/octet-stream"}
    headers['Content-Encoding'] = 'gzip' unless is_cloudsigma?

    RestClient.post url,
                    data,
                    headers

    @log.info "Part #{part+1} uploaded."
  rescue => e
    @log.warn "An error occured while uploading #{part} chunk, #{e.message}"
    try += 1

    unless try > @plugin_config['retry']
      # Let's sleep for specified amount of time
      sleep @plugin_config['wait']
      retry
    else
      @log.error e.info
      raise PluginError, "Couldn't upload appliance, #{e.message}."
    end
  end
end
upload_chunks() click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 111
def upload_chunks
  @step = @plugin_config['chunk'] * 1024 * 1024 # in bytes
  part = @plugin_config['start_part']

  @log.info "Uploading disk in #{disk_size * 1024 / @plugin_config['chunk']} parts."

  File.open(@previous_deliverables.disk, 'rb') do |f|
    while !f.eof?
      f.seek(part * @step, File::SEEK_SET)

      data = f.read(@step)
      data = compress(data) unless is_cloudsigma?
      upload_chunk(data, part)

      part += 1
    end
  end

  @log.info "Appliance #{@appliance_config.name} uploaded to drive with UUID #{@plugin_config['drive_uuid']}."
end
validate() click to toggle source
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 29
def validate
  set_default_config_value('chunk', 64) # chunk size in MB
  set_default_config_value('start_part', 0) # part number to start uploading
  set_default_config_value('wait', 5) # wait time before retrying upload
  set_default_config_value('retry', 3) # number of retries
  set_default_config_value('ssl', false) # use SSL?
  set_default_config_value('drive_name', @appliance_config.name)

  validate_plugin_config(['endpoint', 'username', 'password'], 'http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#ElasticHosts_Delivery_Plugin')
  raise PluginValidationError, "You can use ElasticHosts plugin with base appliances (appliances created with operating system plugins) only, see http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#ElasticHosts_Delivery_Plugin." unless @previous_plugin_info[:type] == :os
end