2011-08-31 16:52:53 -04:00
|
|
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'vcloud'))
|
|
|
|
require 'fog/compute'
|
2011-05-23 21:17:16 -04:00
|
|
|
|
|
|
|
module Fog
|
|
|
|
module Vcloud
|
|
|
|
class Collection < Fog::Collection
|
|
|
|
|
|
|
|
def load(objects)
|
|
|
|
objects = [ objects ] if objects.is_a?(Hash)
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
|
|
|
def check_href!(opts = {})
|
2011-05-30 01:16:31 -04:00
|
|
|
self.href = connection.default_vdc_href unless href
|
2011-05-23 21:17:16 -04:00
|
|
|
unless href
|
|
|
|
if opts.is_a?(String)
|
|
|
|
t = Hash.new
|
|
|
|
t[:parent] = opts
|
|
|
|
opts = t
|
|
|
|
end
|
|
|
|
msg = ":href missing, call with a :href pointing to #{if opts[:message]
|
|
|
|
opts[:message]
|
|
|
|
elsif opts[:parent]
|
|
|
|
"the #{opts[:parent]} whos #{self.class.to_s.split('::').last.downcase} you want to enumerate"
|
|
|
|
else
|
|
|
|
"the resource"
|
|
|
|
end}"
|
|
|
|
raise Fog::Errors::Error.new(msg)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Fog
|
|
|
|
module Vcloud
|
|
|
|
class Model < Fog::Model
|
|
|
|
|
|
|
|
attr_accessor :loaded
|
|
|
|
alias_method :loaded?, :loaded
|
|
|
|
|
|
|
|
def reload
|
|
|
|
instance = super
|
|
|
|
@loaded = true
|
|
|
|
instance
|
|
|
|
end
|
|
|
|
|
|
|
|
def load_unless_loaded!
|
|
|
|
unless @loaded
|
|
|
|
reload
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Fog
|
|
|
|
module Vcloud
|
|
|
|
class Compute < Fog::Service
|
|
|
|
|
|
|
|
PATH = '/api/v1.0'
|
|
|
|
PORT = 443
|
|
|
|
SCHEME = 'https'
|
|
|
|
|
|
|
|
requires :vcloud_username, :vcloud_password, :vcloud_host
|
2011-05-25 20:23:49 -04:00
|
|
|
recognizes :vcloud_port, :vcloud_scheme, :vcloud_path, :vcloud_default_vdc
|
2011-05-23 21:17:16 -04:00
|
|
|
recognizes :provider # remove post deprecation
|
|
|
|
|
2011-08-24 21:11:42 -04:00
|
|
|
model_path 'fog/vcloud/models/compute'
|
2011-05-23 21:17:16 -04:00
|
|
|
model :catalog
|
2011-05-24 02:25:28 -04:00
|
|
|
collection :catalogs
|
|
|
|
model :catalog_item
|
|
|
|
model :catalog_items
|
2011-05-23 21:17:16 -04:00
|
|
|
model :ip
|
|
|
|
collection :ips
|
|
|
|
model :network
|
|
|
|
collection :networks
|
|
|
|
model :server
|
|
|
|
collection :servers
|
|
|
|
model :task
|
|
|
|
collection :tasks
|
|
|
|
model :vdc
|
|
|
|
collection :vdcs
|
|
|
|
|
2011-08-24 21:11:42 -04:00
|
|
|
request_path 'fog/vcloud/requests/compute'
|
2011-05-23 21:17:16 -04:00
|
|
|
request :clone_vapp
|
|
|
|
request :configure_network
|
|
|
|
request :configure_network_ip
|
|
|
|
request :configure_vapp
|
2011-05-30 01:20:13 -04:00
|
|
|
request :configure_vm_memory
|
2011-06-15 02:37:56 -04:00
|
|
|
request :configure_vm_name_description
|
2011-05-31 02:06:46 -04:00
|
|
|
request :configure_vm_disks
|
2011-05-23 21:17:16 -04:00
|
|
|
request :delete_vapp
|
|
|
|
request :get_catalog
|
|
|
|
request :get_catalog_item
|
|
|
|
request :get_customization_options
|
|
|
|
request :get_network
|
|
|
|
request :get_network_ip
|
|
|
|
request :get_network_ips
|
|
|
|
request :get_network_extensions
|
|
|
|
request :get_organization
|
|
|
|
request :get_task
|
|
|
|
request :get_task_list
|
|
|
|
request :get_vapp
|
|
|
|
request :get_vapp_template
|
2011-05-31 02:06:46 -04:00
|
|
|
request :get_vm_disks
|
2011-05-30 01:20:13 -04:00
|
|
|
request :get_vm_memory
|
2011-05-23 21:17:16 -04:00
|
|
|
request :get_vdc
|
|
|
|
request :instantiate_vapp_template
|
|
|
|
request :login
|
|
|
|
request :power_off
|
|
|
|
request :power_on
|
|
|
|
request :power_reset
|
|
|
|
request :power_shutdown
|
2011-05-30 01:19:49 -04:00
|
|
|
request :undeploy
|
2011-05-23 21:17:16 -04:00
|
|
|
|
|
|
|
class Mock
|
2011-07-20 13:11:10 -04:00
|
|
|
|
|
|
|
def initialize(options={})
|
|
|
|
Fog::Mock.not_implemented
|
2011-05-23 21:17:16 -04:00
|
|
|
end
|
2011-07-20 13:11:10 -04:00
|
|
|
|
2011-05-23 21:17:16 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
class Real
|
|
|
|
|
|
|
|
class << self
|
|
|
|
|
|
|
|
def basic_request(*args)
|
|
|
|
self.class_eval <<-EOS, __FILE__,__LINE__
|
|
|
|
def #{args[0]}(uri)
|
|
|
|
request({
|
|
|
|
:expects => #{args[1] || 200},
|
|
|
|
:method => '#{args[2] || 'GET'}',
|
|
|
|
:headers => #{args[3] ? args[3].inspect : '{}'},
|
|
|
|
:body => '#{args[4] ? args[4] : ''}',
|
|
|
|
:parse => true,
|
|
|
|
:uri => uri })
|
|
|
|
end
|
|
|
|
EOS
|
|
|
|
end
|
|
|
|
|
|
|
|
def unauthenticated_basic_request(*args)
|
|
|
|
self.class_eval <<-EOS, __FILE__,__LINE__
|
|
|
|
def #{args[0]}(uri)
|
|
|
|
unauthenticated_request({
|
|
|
|
:expects => #{args[1] || 200},
|
|
|
|
:method => '#{args[2] || 'GET'}',
|
|
|
|
:headers => #{args[3] ? args[3].inspect : '{}'},
|
|
|
|
:parse => true,
|
|
|
|
:uri => uri })
|
|
|
|
end
|
|
|
|
EOS
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(options = {})
|
|
|
|
require 'builder'
|
|
|
|
require 'fog/core/parser'
|
|
|
|
|
|
|
|
@connections = {}
|
|
|
|
@persistent = options[:persistent]
|
|
|
|
|
2011-05-24 02:26:20 -04:00
|
|
|
@username = options[:vcloud_username]
|
|
|
|
@password = options[:vcloud_password]
|
|
|
|
@host = options[:vcloud_host]
|
2011-05-25 20:23:49 -04:00
|
|
|
@vdc_href = options[:vcloud_default_vdc]
|
2011-05-24 02:26:20 -04:00
|
|
|
@path = options[:vcloud_path] || Fog::Vcloud::Compute::PATH
|
|
|
|
@port = options[:vcloud_port] || Fog::Vcloud::Compute::PORT
|
|
|
|
@scheme = options[:vcloud_scheme] || Fog::Vcloud::Compute::SCHEME
|
2011-05-23 21:17:16 -04:00
|
|
|
end
|
|
|
|
|
2011-05-29 21:25:48 -04:00
|
|
|
def reload
|
|
|
|
@connections.each_value { |k,v| v.reset if v }
|
|
|
|
end
|
|
|
|
|
2011-05-23 21:17:16 -04:00
|
|
|
def default_organization_uri
|
|
|
|
@default_organization_uri ||= begin
|
|
|
|
unless @login_results
|
|
|
|
do_login
|
|
|
|
end
|
|
|
|
case @login_results.body[:Org]
|
|
|
|
when Array
|
|
|
|
@login_results.body[:Org].first[:href]
|
|
|
|
when Hash
|
|
|
|
@login_results.body[:Org][:href]
|
|
|
|
else
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-05-29 21:25:48 -04:00
|
|
|
def default_vdc_href
|
|
|
|
@vdc_href
|
|
|
|
end
|
|
|
|
|
|
|
|
# login handles the auth, but we just need the Set-Cookie
|
|
|
|
# header from that call.
|
|
|
|
def do_login
|
|
|
|
@login_results = login
|
|
|
|
@cookie = @login_results.headers['Set-Cookie']
|
|
|
|
end
|
|
|
|
|
|
|
|
def ensure_unparsed(uri)
|
|
|
|
if uri.is_a?(String)
|
|
|
|
uri
|
|
|
|
else
|
|
|
|
uri.to_s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def xmlns
|
|
|
|
{ "xmlns" => "http://www.vmware.com/vcloud/v1",
|
|
|
|
"xmlns:ovf" => "http://schemas.dmtf.org/ovf/envelope/1",
|
|
|
|
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
|
|
|
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema" }
|
2011-05-23 21:17:16 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
# If the cookie isn't set, do a get_organizations call to set it
|
|
|
|
# and try the request.
|
|
|
|
# If we get an Unauthorized error, we assume the token expired, re-auth and try again
|
|
|
|
def request(params)
|
|
|
|
unless @cookie
|
|
|
|
do_login
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
do_request(params)
|
|
|
|
rescue Excon::Errors::Unauthorized => e
|
|
|
|
do_login
|
|
|
|
do_request(params)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def ensure_parsed(uri)
|
|
|
|
if uri.is_a?(String)
|
|
|
|
URI.parse(uri)
|
|
|
|
else
|
|
|
|
uri
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Don't need to set the cookie for these or retry them if the cookie timed out
|
|
|
|
def unauthenticated_request(params)
|
|
|
|
do_request(params)
|
|
|
|
end
|
|
|
|
|
2011-05-24 02:26:20 -04:00
|
|
|
def base_url
|
|
|
|
"#{@scheme}://#{@host}:#{@port}#{@path}"
|
|
|
|
end
|
|
|
|
|
2011-05-23 21:17:16 -04:00
|
|
|
# Use this to set the Authorization header for login
|
|
|
|
def authorization_header
|
|
|
|
"Basic #{Base64.encode64("#{@username}:#{@password}").chomp!}"
|
|
|
|
end
|
|
|
|
|
|
|
|
# Actually do the request
|
|
|
|
def do_request(params)
|
|
|
|
# Convert the uri to a URI if it's a string.
|
|
|
|
if params[:uri].is_a?(String)
|
|
|
|
params[:uri] = URI.parse(params[:uri])
|
|
|
|
end
|
|
|
|
host_url = "#{params[:uri].scheme}://#{params[:uri].host}#{params[:uri].port ? ":#{params[:uri].port}" : ''}"
|
|
|
|
|
|
|
|
# Hash connections on the host_url ... There's nothing to say we won't get URI's that go to
|
|
|
|
# different hosts.
|
|
|
|
@connections[host_url] ||= Fog::Connection.new(host_url, @persistent)
|
|
|
|
|
|
|
|
# Set headers to an empty hash if none are set.
|
|
|
|
headers = params[:headers] || {}
|
|
|
|
|
|
|
|
# Add our auth cookie to the headers
|
|
|
|
if @cookie
|
|
|
|
headers.merge!('Cookie' => @cookie)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Make the request
|
|
|
|
response = @connections[host_url].request({
|
|
|
|
:body => params[:body] || '',
|
|
|
|
:expects => params[:expects] || 200,
|
|
|
|
:headers => headers,
|
|
|
|
:method => params[:method] || 'GET',
|
|
|
|
:path => params[:uri].path
|
|
|
|
})
|
|
|
|
|
|
|
|
# Parse the response body into a hash
|
|
|
|
#puts response.body
|
|
|
|
unless response.body.empty?
|
|
|
|
if params[:parse]
|
|
|
|
document = Fog::ToHashDocument.new
|
|
|
|
parser = Nokogiri::XML::SAX::PushParser.new(document)
|
|
|
|
parser << response.body
|
|
|
|
parser.finish
|
|
|
|
|
|
|
|
response.body = document.body
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
response
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|