class CloudstackClient::Connection
Constants
- DEF_ASYNC_TIMEOUT
- DEF_POLL_INTERVAL
- DEF_REQ_TIMEOUT
Attributes
api_key[RW]
api_url[RW]
async_poll_interval[RW]
async_timeout[RW]
debug[RW]
host[RW]
read_timeout[RW]
secret_key[RW]
symbolize_keys[RW]
verbose[RW]
Public Class Methods
new(api_url, api_key, secret_key, options = {})
click to toggle source
# File lib/cloudstack_client/connection.rb 19 def initialize(api_url, api_key, secret_key, options = {}) 20 @api_url = api_url 21 @api_key = api_key 22 @secret_key = secret_key 23 @verbose = options[:quiet] ? false : true 24 @debug = options[:debug] ? true : false 25 @symbolize_keys = options[:symbolize_keys] ? true : false 26 @host = options[:host] 27 @read_timeout = options[:read_timeout] || DEF_REQ_TIMEOUT 28 @async_poll_interval = options[:async_poll_interval] || DEF_POLL_INTERVAL 29 @async_timeout = options[:async_timeout] || DEF_ASYNC_TIMEOUT 30 @options = options 31 validate_input! 32 end
Public Instance Methods
send_async_request(params)
click to toggle source
Sends an asynchronous request and waits for the response.
The contents of the ‘jobresult’ element are returned upon completion of the command.
# File lib/cloudstack_client/connection.rb 90 def send_async_request(params) 91 data = send_request(params) 92 93 params = { 94 'command' => 'queryAsyncJobResult', 95 'jobid' => data[k('jobid')] 96 } 97 98 max_tries.times do 99 data = send_request(params) 100 print "." if @verbose 101 102 case data[k('jobstatus')] 103 when 1 104 return data[k('jobresult')] 105 when 2 106 raise JobError, "Request failed (#{data[k('jobresultcode')]}): #{data[k('jobresult')][k('errortext')]}." 107 end 108 109 STDOUT.flush if @verbose 110 sleep @async_poll_interval 111 end 112 113 raise TimeoutError, "Asynchronous request timed out." 114 end
send_request(params)
click to toggle source
Sends a synchronous request to the CloudStack API and returns the response as a Hash.
# File lib/cloudstack_client/connection.rb 38 def send_request(params) 39 params['response'] = 'json' 40 params['apiKey'] = @api_key 41 print_debug_output JSON.pretty_generate(params) if @debug 42 43 data = params_to_data(params) 44 uri = URI.parse "#{@api_url}?#{data}&signature=#{create_signature(data)}" 45 46 http = Net::HTTP.new(uri.host, uri.port) 47 if uri.scheme == 'https' 48 http.use_ssl = true 49 http.verify_mode = OpenSSL::SSL::VERIFY_NONE 50 end 51 http.read_timeout = @read_timeout 52 53 begin 54 req = Net::HTTP::Get.new(uri.request_uri) 55 req['Host'] = host if host.present? 56 response = http.request(req) 57 rescue 58 raise ConnectionError, "API URL \'#{@api_url}\' is not reachable." 59 end 60 61 begin 62 body = JSON.parse(response.body, symbolize_names: @symbolize_keys).values.first 63 rescue JSON::ParserError 64 raise ParseError, 65 "Response from server is not readable. Check if the API endpoint (#{@api_url}) is valid and accessible." 66 end 67 68 if response.is_a?(Net::HTTPOK) 69 return body unless body.respond_to?(:keys) 70 if body.size == 2 && body.key?(k('count')) 71 return body.reject { |key, _| key == k('count') }.values.first 72 elsif body.size == 1 && body.values.first.respond_to?(:keys) 73 item = body.values.first 74 return (item.is_a?(Array) || item.is_a?(Hash)) ? item : [] 75 else 76 body.reject! { |key, _| key == k('count') } if body.key?(k('count')) 77 body.size == 0 ? [] : body 78 end 79 else 80 message = body[k('errortext')] rescue body 81 raise ApiError, "Status #{response.code}: #{message}." 82 end 83 end
Private Instance Methods
create_signature(data)
click to toggle source
# File lib/cloudstack_client/connection.rb 147 def create_signature(data) 148 signature = OpenSSL::HMAC.digest('sha1', @secret_key, data.downcase) 149 signature = Base64.encode64(signature).chomp 150 CGI.escape(signature) 151 end
escape(input)
click to toggle source
# File lib/cloudstack_client/connection.rb 157 def escape(input) 158 CGI.escape(input.to_s).gsub('+', '%20').gsub(' ', '%20') 159 end
max_tries()
click to toggle source
# File lib/cloudstack_client/connection.rb 153 def max_tries 154 (@async_timeout / @async_poll_interval).round 155 end
params_to_data(params)
click to toggle source
# File lib/cloudstack_client/connection.rb 126 def params_to_data(params) 127 params_arr = params.sort.map do |key, value| 128 case value 129 when Array # support for maps (Arrays of Hashes) 130 map = [] 131 value.each_with_index do |items, i| 132 items.each {|k, v| map << "#{key}[#{i}].#{k}=#{escape(v)}"} 133 end 134 map.sort.join("&") 135 when Hash # support for maps values of values (Hash values of Hashes) 136 value.each_with_index.map do |(k, v), i| 137 "#{key}[#{i}].key=#{escape(k)}&" + 138 "#{key}[#{i}].value=#{escape(v)}" 139 end.join("&") 140 else 141 "#{key}=#{escape(value)}" 142 end 143 end 144 params_arr.sort.join('&') 145 end
symbolized_key(name)
click to toggle source
# File lib/cloudstack_client/connection.rb 161 def symbolized_key(name) 162 @symbolize_keys ? name.to_sym : name 163 end
Also aliased as: k
validate_input!()
click to toggle source
# File lib/cloudstack_client/connection.rb 118 def validate_input! 119 raise InputError, "API URL not set." if @api_url == nil 120 raise InputError, "API KEY not set." if @api_key == nil 121 raise InputError, "API SECRET KEY not set." if @secret_key == nil 122 raise InputError, "ASYNC POLL INTERVAL must be at least 1." if @async_poll_interval < 1.0 123 raise InputError, "ASYNC TIMEOUT must be at least 60." if @async_timeout < 60 124 end