Project

General

Profile

Download (4.43 KB) Statistics
| Branch: | Tag: | Revision:
class Report < ActiveRecord::Base
belongs_to :host
serialize :log, Puppet::Transaction::Report
validates_presence_of :log, :host_id, :reported_at, :status
validates_uniqueness_of :reported_at, :scope => :host_id

def to_label
"#{host.name} / #{reported_at.to_s}"
end

def failed
validate_meteric("resources",:failed)
end

def failed_restarts
validate_meteric("resources", :failed_restarts)
end

def skipped
validate_meteric("resources", :skipped)
end

def error?
status > 0
end

def changes?
t = validate_meteric("changes", :total)
t > 0 if t
end

def config_retrival
t = validate_meteric("time", :config_retrieval)
t.round_with_precision(2) if t
end

def runtime
t = validate_meteric("time", :total)
t.round_with_precision(2) if t
end

#imports a yaml report into database
def self.import(yaml)
report = YAML.load(yaml)
raise "Invalid report" unless report.is_a?(Puppet::Transaction::Report)
logger.info "processing report for #{report.host}"
begin
host = Host.find_or_create_by_name report.host
report_status = host.puppet_status = report_status(report)
host.last_report = report.time.utc if host.last_report.nil? or host.last_report.utc < report.time.utc

# we save the host without validation for two reasons:
# 1. it might be auto imported, therefore might not be valid (e.g. missing partition table etc)
# 2. we want this to be fast and light on the db.
# at this point, the report is important, not as much of the host
host.save_with_validation(perform_validation = false)

self.create! :host => host, :reported_at => report.time.utc, :log => report, :status => report_status
rescue Exception => e
logger.warn "failed to process report for #{report.host} due to:#{e}"
end
end

def self.summarise(message, type, hosts)
hosts.each do |host|
failed = (host.puppet_status & 0x00000fff)
skipped = (host.puppet_status & 0x00fff000) >> 12
failed_restarts = (host.puppet_status & 0x3f000000) >> 24
no_report = (host.puppet_status & 0x40000000) >> 30
message << "%-30s %9d %9d %9d %9d" % [host.name, failed, failed_restarts, skipped, no_report]
type[:failed] +=1 if failed > 0
type[:failed_restarts] +=1 if failed_restarts > 0
type[:skipped] +=1 if skipped > 0
type[:no_report] +=1 if no_report
end
end

# add sort by report time
def <=>(other)
self.created_at <=> other.created_at
end

# Expire reports based on time and status
# Defaults to expire reports older than a week regardless of the status
def self.expire(conditions = {})
timerange = conditions[:timerange] || 1.week
status = conditions[:status]
cond = "reported_at < \'#{(Time.now.utc - timerange).to_formatted_s(:db)}\'"
cond += " and status = #{status}" unless status.nil?
# delete the reports
count = Report.delete_all(cond)
logger.info Time.now.to_s + ": Expired #{count} Reports"
return count
end

def self.count_puppet_runs(interval = 5)
counter = []
now=Time.now.utc
(1..6).each do |i|
ago = now - interval.minutes
counter << Report.count(:all, :conditions => ["reported_at > ? and reported_at <= ?", ago, now])
now = ago
end
counter
end




protected

# process the metrics
# 0 is a good report, anything else requires attention
def self.report_status report
status = 0
raise "Invalid report: can't find metrics information for #{report.host} at #{report.id}" if report.metrics.nil?
resources = report.metrics["resources"]
# check if the report actually contain anything interesting
if resources[:failed] + resources[:skipped] + resources[:failed_restarts] + report.metrics["changes"][:total] > 0
status = resources[:failed] if resources[:failed] > 0
# We only capture skipped errors when there are associated log entries.
# Sometimes there are skipped entries but no errors in the messages file,
# This can happen when having notice, alias messages etc
status |= resources[:skipped] if resources[:skipped] > 0 and report.logs.size >0

status |= resources[:failed_restarts] << 24 if resources[:failed_restarts] > 0
end

return status
end

protected

def validate_meteric (type, name)
begin
log.metrics[type][name]
rescue
nil
end
end

end
(20-20/22)