Revision d1fa5fa3
Added by Romain Vrignaud over 10 years ago
app/helpers/compute_resources_vms_helper.rb | ||
---|---|---|
actions << vm_power_action(vm)
|
||
end
|
||
|
||
actions << display_delete_if_authorized(hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.id))
|
||
actions << display_delete_if_authorized(hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.identity))
|
||
end
|
||
|
||
def default_available_actions(vm)
|
||
[vm_power_action(vm),
|
||
display_delete_if_authorized(hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.id))]
|
||
display_delete_if_authorized(hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.identity))]
|
||
end
|
||
|
||
def vpc_security_group_hash(security_groups)
|
app/models/compute_resource.rb | ||
---|---|---|
include Taxonomix
|
||
include Encryptable
|
||
encrypts :password
|
||
PROVIDERS = %w[ Libvirt Ovirt EC2 Vmware Openstack Rackspace].delete_if{|p| p == "Libvirt" && !SETTINGS[:libvirt]}
|
||
PROVIDERS = %w[ Libvirt Ovirt EC2 Vmware Openstack Rackspace GCE].delete_if{|p| p == "Libvirt" && !SETTINGS[:libvirt]}
|
||
audited :except => [:password, :attrs], :allow_mass_assignment => true
|
||
serialize :attrs, Hash
|
||
has_many :trends, :as => :trendable, :class_name => "ForemanTrend"
|
||
... | ... | |
|
||
def provider_friendly_name
|
||
list = SETTINGS[:libvirt] ? ["Libvirt"] : []
|
||
list += %w[ oVirt EC2 VMWare OpenStack Rackspace ]
|
||
list += %w[ oVirt EC2 VMWare OpenStack Rackspace Google]
|
||
list[PROVIDERS.index(provider)] rescue ""
|
||
end
|
||
|
||
... | ... | |
end
|
||
|
||
def create_vm args = {}
|
||
client.servers.create vm_instance_defaults.merge(args.to_hash.symbolize_keys)
|
||
options = vm_instance_defaults.merge(args.to_hash.symbolize_keys)
|
||
logger.debug("creating VM with the following options: #{options.inspect}")
|
||
client.servers.create options
|
||
rescue Fog::Errors::Error => e
|
||
logger.debug "Fog error: #{e.message}\n " + e.backtrace.join("\n ")
|
||
errors.add(:base, e.message.to_s)
|
app/models/compute_resources/foreman/model/gce.rb | ||
---|---|---|
module Foreman::Model
|
||
class GCE < ComputeResource
|
||
has_one :key_pair, :foreign_key => :compute_resource_id, :dependent => :destroy
|
||
before_create :setup_key_pair
|
||
validate :check_google_key_path
|
||
validates_presence_of :key_path, :project, :email
|
||
|
||
delegate :flavors, :to => :client
|
||
|
||
def to_label
|
||
"#{name} (#{zone}-#{provider_friendly_name})"
|
||
end
|
||
|
||
def capabilities
|
||
[:image]
|
||
end
|
||
|
||
def project
|
||
attrs[:project]
|
||
end
|
||
|
||
def project=(name)
|
||
attrs[:project] = name
|
||
end
|
||
|
||
def key_path
|
||
attrs[:key_path]
|
||
end
|
||
|
||
def key_path=(name)
|
||
attrs[:key_path] = name
|
||
end
|
||
|
||
def email
|
||
attrs[:email]
|
||
end
|
||
|
||
def email=(email)
|
||
attrs[:email] = email
|
||
end
|
||
|
||
#TODO: allow to select public / private ip address that foreman tries to find
|
||
def provided_attributes
|
||
super.merge({ :ip => :public_ip_address })
|
||
end
|
||
|
||
def vms
|
||
client.servers
|
||
end
|
||
|
||
def zones
|
||
client.list_zones.body['items'].map { |zone| zone['name'] }
|
||
end
|
||
|
||
def networks
|
||
client.list_networks.body['items'].map { |n| n['name'] }
|
||
end
|
||
|
||
def zone
|
||
url
|
||
end
|
||
|
||
def zone=(zone)
|
||
self.url = zone
|
||
end
|
||
|
||
def create_vm args = {}
|
||
#Dot are not allowed in names
|
||
args[:name] = args[:name].parameterize if args[:name].present?
|
||
args[:external_ip] = args[:external_ip] != '0'
|
||
args[:image_name] = args[:image_id]
|
||
|
||
username = images.where(:uuid => args[:image_name]).first.try(:username)
|
||
ssh = { :user => username, :public_key => key_pair.public }
|
||
super(args.merge(ssh))
|
||
rescue Exception => e
|
||
logger.debug "Unhandled GCE error: #{e.class}:#{e.message}\n " + e.backtrace.join("\n ")
|
||
errors.add(:base, e.message.to_s)
|
||
false
|
||
end
|
||
|
||
def available_images
|
||
client.images
|
||
end
|
||
|
||
def self.model_name
|
||
ComputeResource.model_name
|
||
end
|
||
|
||
def setup_key_pair
|
||
require 'sshkey'
|
||
name = "foreman-#{id}#{Foreman.uuid}"
|
||
key = ::SSHKey.generate
|
||
build_key_pair :name => name, :secret => key.private_key, :public => key.ssh_public_key
|
||
end
|
||
|
||
def test_connection(options = {})
|
||
super
|
||
errors[:user].empty? and errors[:password].empty? and zones
|
||
rescue => e
|
||
errors[:base] << e.message
|
||
end
|
||
|
||
private
|
||
def client
|
||
@client ||= ::Fog::Compute.new(:provider => 'google', :google_project => project, :google_client_email => email, :google_key_location => key_path)
|
||
end
|
||
|
||
def check_google_key_path
|
||
return if key_path.blank?
|
||
unless File.exists?(key_path)
|
||
errors.add(:key_path, _('Unable to access key'))
|
||
end
|
||
rescue => e
|
||
logger.warn("failed to access gce key path: #{e}")
|
||
logger.debug(e.backtrace)
|
||
errors.add(:key_path, e.message.to_s)
|
||
end
|
||
|
||
def vm_instance_defaults
|
||
super.merge(
|
||
:zone_name => zone,
|
||
:name => "foreman-#{Time.now.to_i}"
|
||
)
|
||
end
|
||
end
|
||
end
|
app/models/concerns/fog_extensions.rb | ||
---|---|---|
require 'fog/aws/models/compute/server'
|
||
Fog::Compute::AWS::Server.send(:include, FogExtensions::AWS::Server)
|
||
|
||
require 'fog/google'
|
||
require 'fog/google/models/compute/image'
|
||
Fog::Compute::Google::Image.send(:include, FogExtensions::Google::Image)
|
||
require 'fog/google/models/compute/server'
|
||
Fog::Compute::Google::Server.send(:include, FogExtensions::Google::Server)
|
||
require 'fog/google/models/compute/flavor'
|
||
Fog::Compute::Google::Flavor.send(:include, FogExtensions::Google::Flavor)
|
||
|
||
require 'fog/libvirt'
|
||
require 'fog/libvirt/models/compute/server'
|
||
Fog::Compute::Libvirt::Server.send(:include, FogExtensions::Libvirt::Server)
|
app/models/concerns/fog_extensions/google/flavor.rb | ||
---|---|---|
module FogExtensions
|
||
module Google
|
||
module Flavor
|
||
extend ActiveSupport::Concern
|
||
|
||
def id
|
||
name
|
||
end
|
||
end
|
||
end
|
||
end
|
app/models/concerns/fog_extensions/google/image.rb | ||
---|---|---|
module FogExtensions
|
||
module Google
|
||
module Image
|
||
extend ActiveSupport::Concern
|
||
|
||
def id
|
||
name
|
||
end
|
||
end
|
||
end
|
||
end
|
app/models/concerns/fog_extensions/google/server.rb | ||
---|---|---|
module FogExtensions
|
||
module Google
|
||
module Server
|
||
extend ActiveSupport::Concern
|
||
|
||
def pretty_machine_type
|
||
machine_type.split('/')[-1]
|
||
end
|
||
|
||
def flavors
|
||
service.flavors
|
||
end
|
||
|
||
end
|
||
end
|
||
end
|
app/views/compute_resources/form/_gce.html.erb | ||
---|---|---|
<%= text_f f, :project, :label => _("Google Project ID") %>
|
||
<%= text_f f, :email, :label => _("Client Email"), :class => 'span8' %>
|
||
<%= text_f f, :key_path, :label => _("Certificate path"), :help_inline => _('The file path where your p12 file is located'), :class => 'span8' %>
|
||
|
||
<% zones = f.object.zones rescue [] %>
|
||
<%= selectable_f(f, :zone, zones, {}, {:label => _('Zone'), :disabled => zones.empty?,
|
||
:help_inline => link_to_function(zones.empty? ? _("Load zones") : _("Test Connection"), "testConnection(this)",
|
||
:class => "btn + #{zones.empty? ? "" : "btn-success"}",
|
||
:'data-url' => test_connection_compute_resources_path) + image_tag('spinner.gif', :id => 'test_connection_indicator', :class => 'hide').html_safe }) %>
|
app/views/compute_resources_vms/form/_gce.html.erb | ||
---|---|---|
<%= select_f f, :machine_type, compute_resource.flavors, :id, :name %>
|
||
<%
|
||
arch ||= nil ; os ||= nil
|
||
images = possible_images(compute_resource, arch, os)
|
||
-%>
|
||
<div id='image_selection'>
|
||
<%= select_f f, :image_id, images, :uuid, :name,
|
||
{ :include_blank => (images.empty? || images.size == 1) ? false : _('Please select an image') },
|
||
{ :disabled => images.empty? } %>
|
||
</div>
|
||
<%= selectable_f f, :network, compute_resource.networks, {} %>
|
||
<%= checkbox_f f, :external_ip, :label => _('External IP') %>
|
app/views/compute_resources_vms/index/_gce.html.erb | ||
---|---|---|
<table class="table table-bordered" data-table="inline">
|
||
<thead>
|
||
<tr>
|
||
<th><%= _('Name') -%></th>
|
||
<th><%= _('Type') -%></th>
|
||
<th><%= _('State') -%></th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<% @vms.each do |vm| -%>
|
||
<tr>
|
||
<td><%= link_to_if_authorized vm.name, hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.identity) %></td>
|
||
<td><%= vm.pretty_machine_type %></td>
|
||
<td><%= vm.state.downcase %></td>
|
||
<td>
|
||
<%= action_buttons(vm_power_action(vm), display_delete_if_authorized(hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.identity))) %>
|
||
</td>
|
||
</tr>
|
||
<% end -%>
|
||
</table>
|
app/views/compute_resources_vms/show.html.erb | ||
---|---|---|
<% title_actions *available_actions(@vm),
|
||
show_console_action(@vm.ready?,
|
||
link_to_if_authorized(_("Console"), hash_for_console_compute_resource_vm_path, {:disabled => @vm.nil? || !@vm.ready?, :class => "btn btn-info"})),
|
||
display_link_if_authorized(_("Associate VM"), hash_for_associate_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => @vm.id), :title=> _("Associate VM to a Foreman host"), :method => :put, :class=>"btn"),
|
||
display_link_if_authorized(_("Associate VM"), hash_for_associate_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => @vm.identity), :title=> _("Associate VM to a Foreman host"), :method => :put, :class=>"btn"),
|
||
link_to(_("Back"), compute_resource_path(@compute_resource), :class=>'btn')
|
||
%>
|
app/views/compute_resources_vms/show/_gce.html.erb | ||
---|---|---|
<% title @vm.name %>
|
||
<div class='span12'>
|
||
<table class="table table-bordered table-striped">
|
||
<tr>
|
||
<th colspan="2">Properties</th>
|
||
</tr>
|
||
<tr>
|
||
<td>State</td>
|
||
<td><%= @vm.state.downcase %></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Machine Type</td>
|
||
<td><%= @vm.pretty_machine_type %></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Zone</td>
|
||
<td><%= @vm.zone %></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Private IP</td>
|
||
<td><%= @vm.private_ip_address %></td>
|
||
</tr>
|
||
<% if @vm.public_ip_address.present? -%>
|
||
<tr>
|
||
<td>Public IP</td>
|
||
<td><%= @vm.public_ip_address %></td>
|
||
</tr>
|
||
<% end -%>
|
||
</table>
|
||
</div>
|
bundler.d/gce.rb | ||
---|---|---|
group :gce do
|
||
gem "google-api-client"
|
||
gem 'sshkey'
|
||
end
|
db/migrate/20130804131949_add_public_to_key_pairs.rb | ||
---|---|---|
class AddPublicToKeyPairs < ActiveRecord::Migration
|
||
def change
|
||
add_column :key_pairs, :public, :text
|
||
end
|
||
end
|
Also available in: Unified diff
fixes #1719 - Add support for GCE