Module: CloudStackClient::API

Defined in:
lib/cloud_stack_client/api.rb

Overview

Collection of functions to work with the API

Class Method Summary collapse

Class Method Details

Generate a single sign on link for the management console

Parameters:

  • web_uri (String)

    The base URL of Webinterface

  • username (String)

    CloudStack login user

  • hashed_password (String)

    CloudStack login password (use Helpers::hash_password)

  • domain (String) (defaults to: "")

    CloudStack login domain

  • login_parameter (String) (defaults to: nil)

    The name of the CloudStack URL parameter that has been specified in scripts/cloud.core.callbacks.js to contain the login credentials

  • timestamp_offset (Fixnum) (defaults to: nil)

    Custom scripts/cloud.core.callbacks.js parameter to invalidate the login link after the specified number of seconds

Returns:

  • (String)

    A complete URL

See Also:

  • Helpers::hash_password


215
216
217
218
219
220
221
222
# File 'lib/cloud_stack_client/api.rb', line 215

def self.generate_management_console_link(web_uri, username, hashed_password, domain = "",  = nil, timestamp_offset = nil)
   ||= API_DEFAULTS[:login_parameter]
  timestamp_offset ||= API_DEFAULTS[:timestamp_offset]
  uri = "#{web_uri}?#{login_parameter}="
  uri += escape(generate_query({:command => "login", :response => "json", :username => username, :password => hashed_password, :domain => parse_domain(domain)}))
  uri += "&timestamp=#{Time.new.to_i + timestamp_offset}" if timestamp_offset
  return uri
end

.get_credentials(api_uri, username, hashed_password, domain = "", http_method = nil, ssl_check = nil) ⇒ Hash

Login with username, password hash and domain to get session credentials

Parameters:

  • api_uri (String)

    HTTP URL of the CloudStack API

  • username (String)

    CloudStack login user

  • hashed_password (String)

    CloudStack login password (use Helpers::hash_password)

  • domain (String) (defaults to: "")

    CloudStack login domain

  • http_method (Symbol) (defaults to: nil)

    The HTTP method to submit the query (:post or :get)

  • ssl_check (Boolean) (defaults to: nil)

    Check Server SSL certificate?

Returns:

  • (Hash)

    Credentials for subsequent queries

See Also:

  • Helpers::hash_password


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/cloud_stack_client/api.rb', line 36

def self.get_credentials(api_uri, username, hashed_password, domain = "", http_method = nil , ssl_check = nil)
  http_method ||= API_DEFAULTS[:http_method]
  ssl_check = API_DEFAULTS[:ssl_check] if ssl_check.nil?
  parameters = {:command => "login", :response => "json", :username => username, :password => hashed_password, :domain => parse_domain(domain)}
  headers, body = execute_query(api_uri, generate_query(parameters), [], http_method, ssl_check)
  credentials = {}
  if headers.has_key? "set-cookie" # Expect lowercase names from Net::HTTPHeader 
    credentials[:session_cookies] = headers["set-cookie"].map {|raw| raw.split(";").first}
  end
  json = JSON.parse body
  return nil unless CloudStackClient::API::response_is_success? json
  credentials[:session_key] = json["loginresponse"]["sessionkey"]
  credentials[:user_id] = json["loginresponse"]["userid"]
  credentials
end

.query(api_uri, parameters, credentials, http_method = nil, ssl_check = nil) ⇒ REXML::Document, Hash

Execute a query

Parameters:

  • api_uri (String)

    HTTP URL of the CloudStack API

  • parameters (Hash)

    A Hash containing all query parameters. The keys can be specified as Symbol or String

  • credentials (Hash)

    Contains either :api_key and :secret_key or :session_key and :session_cookies as obtained from get_credentials

  • http_method (Symbol) (defaults to: nil)

    The HTTP method to submit the query (:post or :get)

  • ssl_check (Boolean) (defaults to: nil)

    Check Server SSL certificate?

Returns:

  • (REXML::Document, Hash)

    An XML Document or the parsed JSON (commonly a Hash)



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/cloud_stack_client/api.rb', line 74

def self.query(api_uri, parameters, credentials, http_method = nil, ssl_check = nil)
  http_method ||= API_DEFAULTS[:http_method]
  ssl_check = API_DEFAULTS[:ssl_check] if ssl_check.nil?
  if credentials.is_a?(Hash) && credentials.has_key?(:api_key) && credentials.has_key?(:secret_key)
    parameters[:apiKey] = credentials[:api_key]
    parameters[:secret] = credentials[:secret_key]
    parameters[:timestamp] = Time.new.to_i
    headers, body = self.execute_query(api_uri, generate_query(parameters), [], http_method, ssl_check)
  elsif credentials.is_a? Hash
    parameters[:sessionkey] = credentials[:session_key] if credentials.has_key? :session_key
    headers, body = self.execute_query(api_uri, generate_query(parameters), credentials[:session_cookies], http_method, ssl_check)
  end
  
  format = nil
  if headers["content-type"]
    format = headers["content-type"][0].split(";").first
  end
  
  case format
  when "text/javascript"
    JSON.parse body
  when "text/xml"
    REXML::Document.new body
  else
    body
  end
end

.query_with_auto_paging(api_uri, parameters, credentials, page_size = nil, http_method = nil, ssl_check = nil) ⇒ REXML::Document, Hash

Executes the query like query() but merges all result pages into one

Parameters:

  • api_uri (String)

    HTTP URL of the CloudStack API

  • parameters (Hash)

    A Hash containing all query parameters. The keys can be specified as Symbol or String

  • credentials (Hash)

    Contains either :api_key and :secret_key or :session_key and :session_cookies as obtained from get_credentials

  • http_method (Symbol) (defaults to: nil)

    The HTTP method to submit the query (:post or :get)

  • ssl_check (Boolean) (defaults to: nil)

    Check Server SSL certificate?

Returns:

  • (REXML::Document, Hash)

    An XML Document or the parsed JSON (commonly a Hash)



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/cloud_stack_client/api.rb', line 110

def self.query_with_auto_paging(api_uri, parameters, credentials, page_size = nil, http_method = nil, ssl_check = nil)
  page_size ||= API_DEFAULTS[:page_size]
  http_method ||= API_DEFAULTS[:http_method]
  ssl_check = API_DEFAULTS[:ssl_check] if ssl_check.nil?
  output = nil
  parameters[:page] = 0
  parameters[:pageSize] = page_size
  has_count = false
  
  begin
    parameters[:page] += 1
    data = self.query api_uri, parameters, credentials, http_method, ssl_check
    return nil unless data
    format = :json
    format = :xml if data.is_a? REXML::Document
    
    # Remove count attribute from result data
    if format == :xml
      count_data = REXML::QuickPath.first(data.root, "//count")
      if count_data
        count = count_data.text.to_i
        count_data.remove
        has_count = true
      else
        count = 0
      end
    elsif format == :json
      if data.first[1].has_key? "count"
        count = data.first[1]["count"]
        data.first[1].delete "count"
        has_count = true
      else
        count = 0
      end
    end
    
    # Copy first page in total
    if !output
      output = data
      loop_done = count < parameters[:pageSize]
      next
    end
    
    if count <= 0
      # No elements
      loop_done = true
    elsif count >= parameters[:pageSize]
      # Copy all elements if page is full
      if format == :xml
        data.root.elements.each {|record| output.root << record}
      elsif format == :json
        data.first[1].first[1].each {|record| output.first[1].first[1] << record}
      end
    else
      # Handle last page
      loop_done = true
      # Detect and ignore duplicates that have already been extracted.
      # E.g. guest-utilities during listIsos command 
      if format == :xml
        pos_output = output.root.elements.size - count + 1
        end_output = output.root.elements.size + 1
        while pos_output < end_output
          if output.root.elements[pos_output].to_s != data.root.elements[1].to_s
            output.root << data.root.elements[1] # Move node to output tree
          end
          pos_output += 1
        end
      elsif format == :json
        pos_data = 0
        pos_output = output.first[1].first[1].size - count
        end_output = output.first[1].first[1].size
        while pos_output < end_output
          if output.first[1].first[1][pos_output] != data.first[1].first[1][pos_data]
            output.first[1].first[1] << data.first[1].first[1][pos_data]
          end
          pos_data += 1
          pos_output += 1
        end
      end
    end
  end until loop_done
  
  # Recalculate count attribute
  if has_count && CloudStackClient::API::response_is_success?(output)
    if format == :xml && output.root && output.root.has_elements?
      new_count = REXML::Element.new "count"
      new_count.add_text output.root.elements.count.to_s
      output.root << new_count
    elsif format == :json && output.first && output.first[1].any?
      output.first[1]["count"] = output.first[1].first[1].count
    end
  end
  output
end

.verify_keys(api_uri, api_key, secret_key, http_method = nil, ssl_check = nil) ⇒ Boolean

Test connection with supplied Secret key and API key

Parameters:

  • api_uri (String)

    HTTP URL of the CloudStack API

  • api_key (String)

    CloudStack API Key

  • secret_key (String)

    Cloudstack Secret Key

  • http_method (Symbol) (defaults to: nil)

    The HTTP method to submit the query (:post or :get)

  • ssl_check (Boolean) (defaults to: nil)

    Check Server SSL certificate?

Returns:

  • (Boolean)


60
61
62
63
64
# File 'lib/cloud_stack_client/api.rb', line 60

def self.verify_keys(api_uri, api_key, secret_key, http_method = nil, ssl_check = nil)
  http_method ||= API_DEFAULTS[:http_method]
  ssl_check ||= API_DEFAULTS[:ssl_check]
  CloudStackClient::API::response_is_success? query(api_uri, {:command => "listCapabilities"}, {:api_key => api_key, :secret_key => secret_key}, http_method, ssl_check)
end