module Cloud66 module Utils class VitalSigns IP_BLOCK_REGEX = /\d{,2}|1\d{2}|2[0-4]\d|25[0-5]/ IP_REGEX = /\A#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\z/ def self.system_info # system info return parse_data(`facter`) end def self.vitals_alerts vitals_alerts = {} space_alerts = calculate_space_alerts(2, 5) vitals_alerts[:disk] = space_alerts if space_alerts && !space_alerts.empty? return vitals_alerts end def self.address_info result = {} # AWS special case if $config.is_aws reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4` result[:ext_ipv4] = reported_ip if reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/local-ipv4` result[:int_ipv4] = reported_ip if reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ # GC special case elsif $config.is_gc external_ip = `/usr/bin/curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip` result[:ext_ipv4] = external_ip if external_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ internal_ip = `/usr/bin/curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/ip` result[:int_ipv4] = internal_ip if internal_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ else interfaces_raw = `facter interfaces`.strip interfaces = interfaces_raw.split(',').select {|interface| interface !~ /^lo/} # don't have any ip address info unless interfaces.empty? # return all interface information facter_command = "facter #{interfaces.map {|interface| "ipaddress_#{interface} ipaddress6_#{interface}"}.join(' ')}" raw_data = `#{facter_command}`.strip result = parse_data(raw_data) rescue {} end end normalised_hash = {} result.each do |key, value| if value =~ IP_REGEX && value != '127.0.0.1' && value != '127.0.1.1' normalised_hash[key] = value end end return normalised_hash end def self.is_aws? # 6 seconds to find out if this is a AWS image or not! instance = `/usr/bin/curl --connect-timeout 6 -s http://169.254.169.254/latest/meta-data/instance-id` rescue nil return false if instance.nil? || instance.empty? # now check the external ip to make sure we're not just being routed reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4` rescue nil return false if reported_ip.nil? || reported_ip.empty? return false unless reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ # it is aws return true rescue => exc return false end def self.is_gc? # 6 seconds to find out if this is a AWS image or not! external_ip = `/usr/bin/curl --connect-timeout 6 -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip` rescue nil return false if external_ip.nil? || external_ip.empty? return false unless external_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ # it is google cloud return true rescue => exc return false end def self.calculate_space_alerts(warning_threshold, critical_threshold) space_alerts = [] return space_alerts if warning_threshold == 0 || critical_threshold == 0 # get the df output (linux only) df_output = `sudo df -h | grep -v /var/lib/docker | grep -v /var/lib/kubelet | grep -v Use% | awk '{print $1"|"$6"|"$5}'` df_output.lines.each do |df_line| parts = df_line.split('|') next unless parts.size == 3 filesystem = parts[0].strip mounted = parts[1].strip percentage = parts[2].strip.gsub(/%/, '').to_i if percentage >= critical_threshold space_alerts << {level: :critical, filesystem: filesystem, mounted: mounted, percentage: percentage} elsif percentage > warning_threshold space_alerts << {level: :warning, filesystem: filesystem, mounted: mounted, percentage: percentage} end end return space_alerts end # parse the data, not using YAML due to YAML parsing issues and JSON output not always working def self.parse_data(data) hash = {} data.lines.each do |line| split = line.split('=>') if split.size == 2 key = split[0].strip rescue '' value = split[1].strip rescue '' if !value.nil? && value != 'nil' # exclude empty or long results (like ssh keys) if !value.empty? && value.size < 100 hash[key] = value end end end end return hash end end end end