Project

General

Profile

Download (4.32 KB) Statistics
| Branch: | Tag: | Revision:
module Foreman::Model
class EC2 < ComputeResource
include KeyPairComputeResource
delegate :flavors, :subnets, :to => :client
delegate :security_groups, :flavors, :zones, :to => :self, :prefix => 'available'
validates :user, :password, :presence => true

alias_attribute :access_key, :user
alias_attribute :region, :url

def to_label
"#{name} (#{region}-#{provider_friendly_name})"
end

def provided_attributes
super.merge({ :ip => :vm_ip_address })
end

def self.available?
Fog::Compute.providers.include?(:aws)
end

def self.model_name
ComputeResource.model_name
end

def capabilities
[:image]
end

def find_vm_by_uuid(uuid)
super
rescue Fog::Compute::AWS::Error
raise(ActiveRecord::RecordNotFound)
end

def create_vm(args = { })
args = vm_instance_defaults.merge(args.to_h.symbolize_keys).deep_symbolize_keys
if (name = args[:name])
args[:tags] = {:Name => name}
end
if (image_id = args[:image_id])
image = images.find_by_uuid(image_id.to_s)
iam_hash = image.iam_role.present? ? {:iam_instance_profile_name => image.iam_role} : {}
args.merge!(iam_hash)
end
args[:groups].reject!(&:empty?) if args.has_key?(:groups)
args[:security_group_ids].reject!(&:empty?) if args.has_key?(:security_group_ids)
args[:associate_public_ip] = subnet_implies_is_vpc?(args) && args[:managed_ip] == 'public'
args[:private_ip_address] = args[:interfaces_attributes][:"0"][:ip]
super(args)
rescue Fog::Errors::Error => e
Foreman::Logging.exception("Unhandled EC2 error", e)
raise e
end

def security_groups(vpc = nil)
groups = client.security_groups
groups.reject! { |sg| sg.vpc_id != vpc } if vpc
groups
end

def regions
return [] if user.blank? || password.blank?
@regions ||= client.describe_regions.body["regionInfo"].map { |r| r["regionName"] }
end

def zones
@zones ||= client.describe_availability_zones.body["availabilityZoneInfo"].map { |r| r["zoneName"] if r["regionName"] == region }.compact
end

def test_connection(options = {})
super
errors[:user].empty? && errors[:password].empty? && regions
rescue Fog::Compute::AWS::Error => e
errors[:base] << e.message
rescue Excon::Error::Socket => e
errors[:base] << e.message
end

def console(uuid)
vm = find_vm_by_uuid(uuid)
vm.console_output.body.merge(:type => 'log', :name => vm.name)
end

def destroy_vm(uuid)
vm = find_vm_by_uuid(uuid)
vm&.destroy
true
end

# not supporting update at the moment
def update_required?(old_attrs, new_attrs)
false
end

def associated_host(vm)
associate_by("ip", [vm.public_ip_address, vm.private_ip_address])
end

def user_data_supported?
true
end

def image_exists?(image)
client.images.get(image).present?
end

def normalize_vm_attrs(vm_attrs)
normalized = slice_vm_attributes(vm_attrs, ['flavor_id', 'availability_zone', 'subnet_id', 'image_id', 'managed_ip'])

normalized['flavor_name'] = self.flavors.detect { |f| f.id == normalized['flavor_id'] }.try(:name)
normalized['subnet_name'] = self.subnets.detect { |f| f.subnet_id == normalized['subnet_id'] }.try(:cidr_block)
normalized['image_name'] = self.images.find_by(:uuid => vm_attrs['image_id']).try(:name)

group_ids = vm_attrs['security_group_ids'] || []
group_ids = group_ids.select { |gid| gid != '' }
normalized['security_groups'] = group_ids.map.with_index do |gid, idx|
[idx.to_s, {
'id' => gid,
'name' => self.security_groups.detect { |g| g.group_id == gid }.try(:name)
}]
end.to_h

normalized
rescue Fog::Compute::AWS::Error => e
Foreman::Logging.exception("Unhandled EC2 error", e)
{}
end

private

def subnet_implies_is_vpc?(args)
args[:subnet_id].present?
end

def client
@client ||= ::Fog::Compute.new(:provider => "AWS", :aws_access_key_id => user, :aws_secret_access_key => password, :region => region, :connection_options => connection_options)
end

def vm_instance_defaults
super.merge(
:flavor_id => "m1.small",
:key_pair => key_pair
)
end
end
end
(1-1/7)