Class: RightScale::ReposeDownloader
- Includes:
- RightSupport::Log::Mixin
- Defined in:
- lib/instance/cook/repose_downloader.rb
Overview
Abstract download capabilities
Defined Under Namespace
Classes: ConnectionException, DownloadException
Constant Summary collapse
- PROXY_ENVIRONMENT_VARIABLES =
Environment variables to examine for proxy settings, in order.
['HTTPS_PROXY', 'HTTP_PROXY', 'http_proxy', 'ALL_PROXY']
- CONNECTION_EXCEPTIONS =
Class names of exceptions to be re-raised as a ConnectionException
['Errno::ECONNREFUSED', 'Errno::ETIMEDOUT', 'SocketError', 'RestClient::InternalServerError', 'RestClient::RequestTimeout']
- RETRY_BACKOFF_MAX =
max timeout 8 (2**3) minutes for each retry
3- RETRY_MAX_ATTEMPTS =
retry 5 times maximum
5
Instance Attribute Summary collapse
-
#ips ⇒ Object
readonly
Hash of IP Address => Hostname.
-
#sanitized_resource ⇒ Object
readonly
(String) Last resource downloaded.
-
#size ⇒ Object
readonly
(Integer) Size in bytes of last successful download (nil if none).
-
#speed ⇒ Object
readonly
(Integer) Speed in bytes/seconds of last successful download (nil if none).
Instance Method Summary collapse
-
#details ⇒ String
Message summarizing last successful download details.
-
#download(resource) { ... } ⇒ Object
Downloads an attachment from Repose.
-
#initialize(hostnames) ⇒ Downloader
constructor
Initializes a Downloader with a list of hostnames.
Constructor Details
#initialize(hostnames) ⇒ Downloader
Initializes a Downloader with a list of hostnames
The purpose of this method is to instantiate a Downloader. It will perform DNS resolution on the hostnames provided and will configure a proxy if necessary
Parameters
Return
73 74 75 76 77 78 79 80 81 |
# File 'lib/instance/cook/repose_downloader.rb', line 73 def initialize(hostnames) raise ArgumentError, "At least one hostname must be provided" if hostnames.empty? hostnames = [hostnames] unless hostnames.respond_to?(:each) @ips = resolve(hostnames) @hostnames = hostnames proxy_var = PROXY_ENVIRONMENT_VARIABLES.detect { |v| ENV.has_key?(v) } @proxy = ENV[proxy_var].match(/^[[:alpha:]]+:\/\//) ? URI.parse(ENV[proxy_var]) : URI.parse("http://" + ENV[proxy_var]) if proxy_var end |
Instance Attribute Details
#ips ⇒ Object (readonly)
Hash of IP Address => Hostname
59 60 61 |
# File 'lib/instance/cook/repose_downloader.rb', line 59 def ips @ips end |
#sanitized_resource ⇒ Object (readonly)
(String) Last resource downloaded
56 57 58 |
# File 'lib/instance/cook/repose_downloader.rb', line 56 def sanitized_resource @sanitized_resource end |
#size ⇒ Object (readonly)
(Integer) Size in bytes of last successful download (nil if none)
50 51 52 |
# File 'lib/instance/cook/repose_downloader.rb', line 50 def size @size end |
#speed ⇒ Object (readonly)
(Integer) Speed in bytes/seconds of last successful download (nil if none)
53 54 55 |
# File 'lib/instance/cook/repose_downloader.rb', line 53 def speed @speed end |
Instance Method Details
#details ⇒ String
Message summarizing last successful download details
Return
140 141 142 |
# File 'lib/instance/cook/repose_downloader.rb', line 140 def details "Downloaded '#{@sanitized_resource}' (#{ scale(size.to_i).join(' ') }) at #{ scale(speed.to_i).join(' ') }/s" end |
#download(resource) { ... } ⇒ Object
Downloads an attachment from Repose
The purpose of this method is to download the specified attachment from Repose If a failure is encountered it will provide proper feedback regarding the nature of the failure
Parameters
Block
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/instance/cook/repose_downloader.rb', line 96 def download(resource) client = get_http_client @size = 0 @speed = 0 @sanitized_resource = sanitize_resource(resource) resource = parse_resource(resource) attempts = 0 begin balancer.request do |endpoint| RightSupport::Net::SSL.with_expected_hostname(ips[endpoint]) do logger.info("Requesting '#{sanitized_resource}' from '#{endpoint}'") attempts += 1 t0 = Time.now # Previously we accessed RestClient directly and used it's wrapper method to instantiate # a RestClient::Request object. This wrapper was not passing all options down the stack # so now we invoke the RestClient::Request object directly, passing it our desired options client.execute(:method => :get, :url => "https://#{endpoint}:443#{resource}", :timeout => calculate_timeout(attempts), :verify_ssl => OpenSSL::SSL::VERIFY_PEER, :ssl_ca_file => get_ca_file, :headers => {:user_agent => "RightLink v#{AgentConfig.protocol_version}", 'X-RightLink-Version' => RightLink.version }) do |response, request, result| if result.kind_of?(Net::HTTPSuccess) @size = result.content_length || response.size || 0 @speed = @size / (Time.now - t0) yield response else response.return!(request, result) end end end end rescue Exception => e list = (e) = list.join(", ") logger.error("Request '#{sanitized_resource}' failed - #{message}") raise ConnectionException, unless (list & CONNECTION_EXCEPTIONS).empty? raise DownloadException, end end |