module Bosh::OpenStackCloud::Helpers
Constants
- DEFAULT_RETRY_TIMEOUT
- DEFAULT_STATE_TIMEOUT
- MAX_RETRIES
Public Instance Methods
cloud_error(message, exception = nil)
click to toggle source
Raises CloudError exception
@param [String] message Message about what went wrong @param [Exception] exception Exception to be logged (optional)
# File lib/cloud/openstack/helpers.rb, line 17 def cloud_error(message, exception = nil) @logger.error(message) if @logger @logger.error(exception) if @logger && exception raise Bosh::Clouds::CloudError, message end
parse_openstack_response(response, *keys)
click to toggle source
Parses and look ups for keys in an OpenStack response
@param [Excon::Response] response Response from OpenStack API @param [Array<String>] keys Keys to look up in response @return [Hash] Contents at the first key found, or nil if not found
# File lib/cloud/openstack/helpers.rb, line 79 def parse_openstack_response(response, *keys) unless response.body.empty? begin body = JSON.parse(response.body) key = keys.detect { |k| body.has_key?(k)} return body[key] if key rescue JSON::ParserError # do nothing end end nil end
wait_resource(resource, target_state, state_method = :status, allow_notfound = false)
click to toggle source
Waits for a resource to be on a target state
@param [Fog::Model] resource Resource to query @param [Array<Symbol>] target_state Resource's state desired @param [Symbol] state_method Resource's method to fetch state @param [Boolean] allow_notfound true if resource could be not found
# File lib/cloud/openstack/helpers.rb, line 99 def wait_resource(resource, target_state, state_method = :status, allow_notfound = false) started_at = Time.now desc = resource.class.name.split("::").last.to_s + " `" + resource.id.to_s + "'" target_state = Array(target_state) state_timeout = @state_timeout || DEFAULT_STATE_TIMEOUT loop do duration = Time.now - started_at if duration > state_timeout cloud_error("Timed out waiting for #{desc} to be #{target_state.join(", ")}") end if @logger @logger.debug("Waiting for #{desc} to be #{target_state.join(", ")} (#{duration}s)") end # If resource reload is nil, perhaps it's because resource went away # (ie: a destroy operation). Don't raise an exception if this is # expected (allow_notfound). if with_openstack { resource.reload.nil? } break if allow_notfound cloud_error("#{desc}: Resource not found") else state = with_openstack { resource.send(state_method).downcase.to_sym } end # This is not a very strong convention, but some resources # have 'error', 'failed' and 'killed' states, we probably don't want to keep # waiting if we're in these states. Alternatively we could introduce a # set of 'loop breaker' states but that doesn't seem very helpful # at the moment if state == :error || state == :failed || state == :killed cloud_error("#{desc} state is #{state}, expected #{target_state.join(", ")}") end break if target_state.include?(state) sleep(@wait_resource_poll_interval) end if @logger total = Time.now - started_at @logger.info("#{desc} is now #{target_state.join(", ")}, took #{total}s") end end
with_openstack() { || ... }
click to toggle source
# File lib/cloud/openstack/helpers.rb, line 23 def with_openstack retries = 0 begin yield rescue Excon::Errors::RequestEntityTooLarge => e message = "OpenStack API Request Entity Too Large error: \nCheck task debug log for details." overlimit = parse_openstack_response(e.response, "overLimit", "overLimitFault") if overlimit message.insert(46, overlimit["message"]) details = "#{overlimit["message"]} - #{overlimit["details"]}" if retries < MAX_RETRIES wait_time = overlimit["retryAfter"] || e.response.headers["Retry-After"] || DEFAULT_RETRY_TIMEOUT @logger.debug("OpenStack API Over Limit (#{details}), waiting #{wait_time} seconds before retrying") if @logger sleep(wait_time.to_i) retries += 1 retry end else message.insert(46, e.response.body) end cloud_error(message, e) rescue Excon::Errors::ServiceUnavailable => e unless retries >= MAX_RETRIES retries += 1 @logger.debug("OpenStack API Service Unavailable error, retrying (#{retries})") if @logger sleep(DEFAULT_RETRY_TIMEOUT) retry end cloud_error("OpenStack API Service Unavailable error. Check task debug log for details.", e) rescue Excon::Errors::BadRequest => e badrequest = parse_openstack_response(e.response, "badRequest") details = badrequest.nil? ? "" : " (#{badrequest["message"]})" cloud_error("OpenStack API Bad Request#{details}. Check task debug log for details.", e) rescue Excon::Errors::InternalServerError => e unless retries >= MAX_RETRIES retries += 1 @logger.debug("OpenStack API Internal Server error, retrying (#{retries})") if @logger sleep(DEFAULT_RETRY_TIMEOUT) retry end cloud_error("OpenStack API Internal Server error. Check task debug log for details.", e) end end