class Cloudkeeper::Aws::Cloud

Class for AWS Cloud related operations

Constants

SUCCESSFUL_STATUS
UNSUCCESSFUL_STATUS

Attributes

bucket[R]
ec2[R]
s3[R]

Public Class Methods

new(s3service: nil, ec2service: nil) click to toggle source

Constructs Cloud object that can communicate with AWS cloud.

@note This method can be billed by AWS

# File lib/cloudkeeper/aws/cloud.rb, line 17
def initialize(s3service: nil, ec2service: nil)
  ::Aws.config.update(Cloudkeeper::Aws::Settings['aws'].deep_symbolize_keys)
  @s3 = s3service || ::Aws::S3::Resource.new
  @ec2 = ec2service || ::Aws::EC2::Client.new
  @bucket = s3.bucket(Cloudkeeper::Aws::Settings['bucket-name'])
  bucket.create unless bucket.exists?
end

Public Instance Methods

delete_data(file_name) click to toggle source
# File lib/cloudkeeper/aws/cloud.rb, line 57
def delete_data(file_name)
  logger.debug { "Deleting file: #{file_name} from bucket: #{Cloudkeeper::Aws::Settings['bucket-name']}" }
  obj = bucket.object(file_name)
  obj.exists? ? obj.delete : logger.info("File does not exist: #{file_name}")
end
deregister_image(image_id) click to toggle source

Deregisters specific image.

@note This method can be billed by AWS @param image_id [String] id of specific AMI

# File lib/cloudkeeper/aws/cloud.rb, line 139
def deregister_image(image_id)
  logger.debug { "Deregistering AMI #{image_id}" }
  ec2.deregister_image(image_id: image_id)
end
disk_container(appliance) click to toggle source

Method used for generating disk container for import image task

@param appliance [Appliance] data about image @return [Hash] disk container hash

# File lib/cloudkeeper/aws/cloud.rb, line 81
def disk_container(appliance)
  {
    description: appliance.description,
    format: appliance.image.format,
    user_bucket: {
      s3_bucket: @bucket.name,
      s3_key: appliance.identifier
    }
  }
end
find_appliance(identifier) click to toggle source
# File lib/cloudkeeper/aws/cloud.rb, line 160
def find_appliance(identifier)
  logger.debug { "Fetching appliance with identifier: #{identifier}" }
  images = ec2.describe_images(filters: FilterHelper.appliance(identifier)).images
  raise Cloudkeeper::Aws::Errors::Backend::ApplianceNotFoundError, 'Appliance not found' if images.empty?

  if images.size > 1
    raise Cloudkeeper::Aws::Errors::Backend::MultipleAppliancesFoundError,
          'Multiple appliances with same identifier exist in AWS'
  end
  images.first
end
poll_import_task(import_id) click to toggle source

Polls for import image task result. This method is blocking, so after image import task is completed, successfully or not, it will return true or false.

@note This method can be billed by AWS @param import_id [String] id of import image task @raise [Cloudkeeper::Aws::Errors::BackendError] if polling timed out

# File lib/cloudkeeper/aws/cloud.rb, line 99
def poll_import_task(import_id)
  logger.debug { "Polling for import task #{import_id}" }
  timeout do
    sleep_loop do
      import_task = ec2.describe_import_image_tasks(import_task_ids: [import_id]).import_image_tasks.first
      print_progress(import_task)
      if UNSUCCESSFUL_STATUS.include?(import_task.status)
        raise Cloudkeeper::Aws::Errors::Backend::ImageImportError,
              "Import failed with status #{import_task.status} and message: #{import_task.status_message}"
      end
      return import_task.image_id if SUCCESSFUL_STATUS.include?(import_task.status)
    end
  end
end
print_progress(import_task) click to toggle source
search_images(filters) click to toggle source
# File lib/cloudkeeper/aws/cloud.rb, line 155
def search_images(filters)
  logger.debug { "Searching for AMI with filters: #{filters}" }
  ec2.describe_images(filters: filters).images
end
set_tags(tags, image_id) click to toggle source

Sets tags to specific AMI.

@note This method can be billed by AWS @param tags [Array<Hash{Symbol => String}>] array of tags to set

to specific AMI. Tag consists of key and value symbols

@param image_id [String] id of specific AMI

# File lib/cloudkeeper/aws/cloud.rb, line 150
def set_tags(tags, image_id)
  logger.debug { "Setting tags for AMI #{image_id}: #{tags}" }
  ec2.create_tags(resources: [image_id], tags: tags)
end
sleep_loop() { || ... } click to toggle source

Simple method used for calling block in intervals

# File lib/cloudkeeper/aws/cloud.rb, line 120
def sleep_loop
  loop do
    sleep Cloudkeeper::Aws::Settings['polling-interval']
    yield
  end
end
start_import_image(appliance) click to toggle source

Creates import image task on AWS cloud. This task needs to be polled for. See {#poll_import_task}.

@note This method can be billed by AWS @param appliance [Appliance] data about image @return [Number] import task id

# File lib/cloudkeeper/aws/cloud.rb, line 69
def start_import_image(appliance)
  logger.debug { "Starting import image task for #{appliance.identifier}" }
  ec2.import_image(
    description: appliance.description,
    disk_containers: [disk_container(appliance)]
  ).import_task_id
end
timeout() { || ... } click to toggle source

Simple method used for handling timeout

# File lib/cloudkeeper/aws/cloud.rb, line 128
def timeout
  Timeout.timeout(Cloudkeeper::Aws::Settings['polling-timeout'],
                  Cloudkeeper::Aws::Errors::Backend::TimeoutError) do
    yield
  end
end
upload_data(file_name, &block) click to toggle source

Uploads data in block AWS file with given name

@note This method can be billed by AWS @param file_name [String] key of object in bucket @yield [write_stream] output stream @raise [Cloudkeeper::Aws::Errors::BackendError] if file already exists

# File lib/cloudkeeper/aws/cloud.rb, line 31
def upload_data(file_name, &block)
  logger.debug { "Block uploading to entry (#{file_name}) in bucket(#{Cloudkeeper::Aws::Settings['bucket-name']})" }
  obj = bucket.object(file_name)
  if obj.exists?
    raise Cloudkeeper::Aws::Errors::Backend::BackendError,
          "File #{file_name} in AWS bucket already exists"
  end
  obj.upload_stream(&block)
end
upload_file(file_name, file_path) click to toggle source

Uploads file to AWS bucket

@note This method can be billed by AWS @param file_name [String] name of file in AWS bucket @param file_path [String] name of file on local machine @raise [Cloudkeeper::Aws::Errors::BackendError] if file already exists

# File lib/cloudkeeper/aws/cloud.rb, line 47
def upload_file(file_name, file_path)
  logger.debug { "Local file uploading to entry (#{file_name}) in bucket(#{Cloudkeeper::Aws::Settings['bucket-name']})" }
  obj = bucket.object(file_name)
  if obj.exists?
    raise Cloudkeeper::Aws::Errors::Backend::BackendError,
          "File #{file_name} in AWS bucket already exists"
  end
  obj.upload_file(file_path)
end