require 'timeout' require 'open-uri' # Provide a set of utility static methods that help with resolving the EC2 # fact. module Facter::Util::EC2 class << self # Test if we can connect to the EC2 api. Return true if able to connect. # On failure this function fails silently and returns false. # # The +wait_sec+ parameter provides you with an adjustable timeout. # def can_connect?(wait_sec=2) url = "http://169.254.169.254:80/" Timeout::timeout(wait_sec) {open(url)} return true rescue Timeout::Error return false rescue return false end # Test if this host has a mac address used by Eucalyptus clouds, which # normally is +d0:0d+. def has_euca_mac? !!(Facter.value(:macaddress) =~ %r{^[dD]0:0[dD]:}) end # Test if this host has a mac address used by OpenStack, which # normally starts with FA:16:3E (older versions of OpenStack # may generate mac addresses starting with 02:16:3E) def has_openstack_mac? !!(Facter.value(:macaddress) =~ %r{^(02|[fF][aA]):16:3[eE]}) end # Test if the host has an arp entry in its cache that matches the EC2 arp, # which is normally +fe:ff:ff:ff:ff:ff+. def has_ec2_arp? kernel = Facter.value(:kernel) mac_address_re = case kernel when /Windows/i /fe-ff-ff-ff-ff-ff/i else /fe:ff:ff:ff:ff:ff/i end arp_command = case kernel when /Windows/i, /SunOS/i "arp -a" else "arp -an" end if arp_table = Facter::Util::Resolution.exec(arp_command) return true if arp_table.match(mac_address_re) end return false end end ## # userdata returns a single string containing the body of the response of the # GET request for the URI http://169.254.169.254/latest/user-data/ If the # metadata server responds with a 404 Not Found error code then this method # retuns `nil`. # # @param version [String] containing the API version for the request. # Defaults to "latest" and other examples are documented at # http://aws.amazon.com/archives/Amazon%20EC2 # # @api public # # @return [String] containing the response body or `nil` def self.userdata(version="latest") uri = "http://169.254.169.254/#{version}/user-data/" begin read_uri(uri) rescue OpenURI::HTTPError => detail case detail.message when /404 Not Found/i Facter.debug "No user-data present at #{uri}: server responded with #{detail.message}" return nil else raise detail end end end ## # read_uri provides a seam method to easily test the HTTP client # functionality of a HTTP based metadata server. # # @api private # # @return [String] containing the body of the response def self.read_uri(uri) open(uri).read end private_class_method :read_uri end