2011-09-07 10:25:08 -04:00
|
|
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'cloudstack'))
|
|
|
|
require 'fog/compute'
|
2011-10-09 21:14:05 -04:00
|
|
|
require 'digest/md5'
|
2011-08-02 11:58:18 -04:00
|
|
|
|
|
|
|
module Fog
|
|
|
|
module Compute
|
|
|
|
class Cloudstack < Fog::Service
|
|
|
|
|
2011-10-09 21:14:05 -04:00
|
|
|
class BadRequest < Fog::Compute::Cloudstack::Error; end
|
|
|
|
class Unauthorized < Fog::Compute::Cloudstack::Error; end
|
2011-09-07 10:00:25 -04:00
|
|
|
|
2011-10-09 21:14:05 -04:00
|
|
|
requires :cloudstack_host
|
|
|
|
|
|
|
|
recognizes :cloudstack_api_key, :cloudstack_secret_access_key, :cloudstack_session_key, :cloudstack_session_id,
|
|
|
|
:cloudstack_port, :cloudstack_path, :cloudstack_scheme, :cloudstack_persistent
|
2011-09-07 10:00:25 -04:00
|
|
|
|
2011-09-07 10:25:08 -04:00
|
|
|
request_path 'fog/cloudstack/requests/compute'
|
2011-08-02 11:58:18 -04:00
|
|
|
|
2011-10-09 21:14:05 -04:00
|
|
|
request :acquire_ip_address
|
|
|
|
request :assign_to_load_balancer_rule
|
|
|
|
request :attach_volume
|
2011-09-07 10:00:25 -04:00
|
|
|
request :authorize_security_group_ingress
|
2011-10-29 19:53:10 -04:00
|
|
|
request :change_service_for_virtual_machine
|
2011-09-07 10:00:25 -04:00
|
|
|
request :create_account
|
2011-08-02 14:52:16 -04:00
|
|
|
request :create_domain
|
2011-10-09 21:14:05 -04:00
|
|
|
request :create_port_forwarding_rule
|
|
|
|
request :create_load_balancer_rule
|
2011-09-07 10:00:25 -04:00
|
|
|
request :create_security_group
|
|
|
|
request :create_snapshot
|
2011-08-02 14:46:21 -04:00
|
|
|
request :create_user
|
2011-10-09 21:14:05 -04:00
|
|
|
request :create_volume
|
2011-09-07 10:00:25 -04:00
|
|
|
request :delete_account
|
2011-08-02 14:52:16 -04:00
|
|
|
request :delete_domain
|
2011-10-09 21:14:05 -04:00
|
|
|
request :delete_load_balancer_rule
|
|
|
|
request :delete_port_forwarding_rule
|
2011-09-07 10:00:25 -04:00
|
|
|
request :delete_security_group
|
|
|
|
request :delete_snapshot
|
2011-08-02 14:46:21 -04:00
|
|
|
request :delete_user
|
2011-10-09 21:14:05 -04:00
|
|
|
request :delete_volume
|
|
|
|
request :detach_volume
|
2011-09-07 10:00:25 -04:00
|
|
|
request :deploy_virtual_machine
|
|
|
|
request :destroy_virtual_machine
|
2011-08-02 14:46:21 -04:00
|
|
|
request :disable_user
|
|
|
|
request :enable_user
|
2011-09-07 10:00:25 -04:00
|
|
|
request :generate_usage_records
|
|
|
|
request :get_vm_password
|
2011-08-02 11:58:18 -04:00
|
|
|
request :list_accounts
|
|
|
|
request :list_alerts
|
|
|
|
request :list_async_jobs
|
2011-09-07 10:00:25 -04:00
|
|
|
request :list_capacity
|
|
|
|
request :list_capabilities
|
|
|
|
request :list_clusters
|
|
|
|
request :list_configurations
|
2011-08-02 11:58:18 -04:00
|
|
|
request :list_disk_offerings
|
2011-09-07 10:00:25 -04:00
|
|
|
request :list_capacity
|
2011-08-02 11:58:18 -04:00
|
|
|
request :list_domains
|
2011-08-02 14:52:16 -04:00
|
|
|
request :list_domain_children
|
2011-08-02 11:58:18 -04:00
|
|
|
request :list_events
|
|
|
|
request :list_external_firewalls
|
|
|
|
request :list_external_load_balancers
|
|
|
|
request :list_hosts
|
|
|
|
request :list_hypervisors
|
|
|
|
request :list_instance_groups
|
|
|
|
request :list_isos
|
2011-10-09 21:14:05 -04:00
|
|
|
request :list_load_balancer_rules
|
|
|
|
request :list_load_balancer_rule_instances
|
2011-08-02 11:58:18 -04:00
|
|
|
request :list_network_offerings
|
|
|
|
request :list_networks
|
|
|
|
request :list_os_categories
|
|
|
|
request :list_os_types
|
|
|
|
request :list_pods
|
2011-10-09 21:14:05 -04:00
|
|
|
request :list_port_forwarding_rules
|
|
|
|
request :list_public_ip_addresses
|
2011-08-02 11:58:18 -04:00
|
|
|
request :list_resource_limits
|
|
|
|
request :list_security_groups
|
|
|
|
request :list_service_offerings
|
|
|
|
request :list_snapshots
|
|
|
|
request :list_ssh_key_pairs
|
|
|
|
request :list_storage_pools
|
|
|
|
request :list_templates
|
|
|
|
request :list_usage_records
|
|
|
|
request :list_users
|
|
|
|
request :list_virtual_machines
|
|
|
|
request :list_volumes
|
|
|
|
request :list_zones
|
2011-10-29 19:53:10 -04:00
|
|
|
request :migrate_virtual_machine
|
2011-09-07 10:00:25 -04:00
|
|
|
request :query_async_job_result
|
|
|
|
request :reboot_virtual_machine
|
2011-10-29 19:53:10 -04:00
|
|
|
request :recover_virtual_machine
|
2011-09-07 10:00:25 -04:00
|
|
|
request :register_user_keys
|
2011-10-09 21:14:05 -04:00
|
|
|
request :remove_from_load_balancer_rule
|
|
|
|
request :reset_password_for_virtual_machine
|
2011-09-07 10:00:25 -04:00
|
|
|
request :revoke_security_group_ingress
|
|
|
|
request :start_virtual_machine
|
|
|
|
request :stop_virtual_machine
|
|
|
|
request :update_account
|
|
|
|
request :update_domain
|
|
|
|
request :update_user
|
|
|
|
request :update_virtual_machine
|
|
|
|
|
2011-08-02 11:58:18 -04:00
|
|
|
class Mock
|
|
|
|
|
|
|
|
def self.data
|
|
|
|
@data ||= Hash.new do |hash, key|
|
|
|
|
hash[key] = {}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.reset
|
|
|
|
@data = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(options={})
|
|
|
|
@cloudstack_api_key = options[:cloudstack_api_key]
|
|
|
|
end
|
|
|
|
|
|
|
|
def data
|
|
|
|
self.class.data[@cloudstack_api_key]
|
|
|
|
end
|
|
|
|
|
|
|
|
def reset_data
|
|
|
|
self.class.data.delete(@cloudstack_api_key)
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
class Real
|
|
|
|
|
|
|
|
def initialize(options={})
|
2011-09-07 10:25:08 -04:00
|
|
|
require 'multi_json'
|
2011-08-02 11:58:18 -04:00
|
|
|
@cloudstack_api_key = options[:cloudstack_api_key]
|
|
|
|
@cloudstack_secret_access_key = options[:cloudstack_secret_access_key]
|
2011-10-09 21:14:05 -04:00
|
|
|
@cloudstack_session_id = options[:cloudstack_session_id]
|
|
|
|
@cloudstack_session_key = options[:cloudstack_session_key]
|
|
|
|
@host = options[:cloudstack_host]
|
|
|
|
@path = options[:cloudstack_path] || '/client/api'
|
|
|
|
@port = options[:cloudstack_port] || 443
|
|
|
|
@scheme = options[:cloudstack_scheme] || 'https'
|
|
|
|
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}#{@path}", options[:cloudstack_persistent])
|
2011-08-02 11:58:18 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def reload
|
|
|
|
@connection.reset
|
|
|
|
end
|
|
|
|
|
2011-10-09 21:14:05 -04:00
|
|
|
def login(username,password,domain)
|
|
|
|
response = issue_request({
|
|
|
|
'response' => 'json',
|
|
|
|
'command' => 'login',
|
|
|
|
'username' => username,
|
|
|
|
'password' => Digest::MD5.hexdigest(password),
|
|
|
|
'domain' => domain
|
2011-08-02 11:58:18 -04:00
|
|
|
})
|
2011-10-09 21:14:05 -04:00
|
|
|
|
|
|
|
# Parse response cookies to retrive JSESSIONID token
|
|
|
|
cookies = CGI::Cookie.parse(response.get_header('Set-Cookie'))
|
|
|
|
sessionid = cookies['JSESSIONID'].first
|
|
|
|
|
|
|
|
# Decode the login response
|
|
|
|
response = MultiJson.decode(response.body)
|
|
|
|
|
|
|
|
user = response['loginresponse']
|
|
|
|
user.merge!('sessionid' => sessionid)
|
|
|
|
|
|
|
|
@cloudstack_session_id = user['sessionid']
|
|
|
|
@cloudstack_session_key = user['sessionkey']
|
|
|
|
|
|
|
|
user
|
|
|
|
end
|
|
|
|
|
|
|
|
def request(params)
|
|
|
|
params.reject!{|k,v| v.nil?}
|
|
|
|
|
|
|
|
params.merge!('response' => 'json')
|
|
|
|
|
|
|
|
if has_session?
|
|
|
|
params, headers = authorize_session(params)
|
|
|
|
elsif has_keys?
|
|
|
|
params, headers = authorize_api_keys(params)
|
|
|
|
end
|
|
|
|
|
|
|
|
response = issue_request(params,headers)
|
|
|
|
response = MultiJson.decode(response.body) unless response.body.empty?
|
|
|
|
response
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def has_session?
|
|
|
|
@cloudstack_session_id && @cloudstack_session_key
|
|
|
|
end
|
|
|
|
|
|
|
|
def has_keys?
|
|
|
|
@cloudstack_api_key && @cloudstack_secret_access_key
|
|
|
|
end
|
|
|
|
|
|
|
|
def authorize_session(params)
|
|
|
|
# set the session id cookie for the request
|
|
|
|
headers = {'Cookie' => "JSESSIONID=#{@cloudstack_session_id};"}
|
|
|
|
# set the sesion key for the request, params are not signed using session auth
|
|
|
|
params.merge!('sessionkey' => @cloudstack_session_key)
|
2011-08-02 11:58:18 -04:00
|
|
|
|
2011-10-09 21:14:05 -04:00
|
|
|
return params, headers
|
|
|
|
end
|
|
|
|
|
|
|
|
def authorize_api_keys(params)
|
|
|
|
headers = {}
|
|
|
|
# merge the api key into the params
|
|
|
|
params.merge!('apiKey' => @cloudstack_api_key)
|
|
|
|
# sign the request parameters
|
|
|
|
signature = Fog::Cloudstack.signed_params(@cloudstack_secret_access_key,params)
|
|
|
|
# merge signature into request param
|
2011-08-02 11:58:18 -04:00
|
|
|
params.merge!({'signature' => signature})
|
|
|
|
|
2011-10-09 21:14:05 -04:00
|
|
|
return params, headers
|
|
|
|
end
|
|
|
|
|
|
|
|
def issue_request(params={},headers={},method='GET',expects=200)
|
2011-09-07 10:00:25 -04:00
|
|
|
begin
|
2011-10-09 21:14:05 -04:00
|
|
|
puts params.inspect
|
2011-09-07 10:00:25 -04:00
|
|
|
response = @connection.request({
|
|
|
|
:query => params,
|
2011-10-09 21:14:05 -04:00
|
|
|
:headers => headers,
|
|
|
|
:method => method,
|
|
|
|
:expects => expects
|
2011-09-07 10:00:25 -04:00
|
|
|
})
|
2011-10-09 21:14:05 -04:00
|
|
|
|
2011-09-07 10:00:25 -04:00
|
|
|
rescue Excon::Errors::HTTPStatusError => error
|
2011-09-07 10:25:08 -04:00
|
|
|
error_response = MultiJson.decode(error.response.body)
|
2011-09-07 10:00:25 -04:00
|
|
|
|
|
|
|
error_code = error_response.values.first['errorcode']
|
|
|
|
error_text = error_response.values.first['errortext']
|
|
|
|
|
2011-10-09 21:14:05 -04:00
|
|
|
puts error_response.inspect
|
|
|
|
|
|
|
|
puts error_code
|
|
|
|
puts error_text
|
|
|
|
|
2011-09-07 10:00:25 -04:00
|
|
|
case error_code
|
2011-10-09 21:14:05 -04:00
|
|
|
when 401
|
|
|
|
raise Fog::Compute::Cloudstack::Unauthorized, error_text
|
2011-09-07 10:00:25 -04:00
|
|
|
when 431
|
2011-10-09 21:14:05 -04:00
|
|
|
raise Fog::Compute::Cloudstack::BadRequest, error_text
|
2011-09-07 10:00:25 -04:00
|
|
|
else
|
2011-10-09 21:14:05 -04:00
|
|
|
raise Fog::Compute::Cloudstack::Error, error_text
|
2011-09-07 10:00:25 -04:00
|
|
|
end
|
|
|
|
end
|
2011-08-02 11:58:18 -04:00
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|