hostmon 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/bin/hostmon +4 -0
  2. data/examples/config.yml +14 -0
  3. data/examples/reports/bad_exit_status/cluster1/mach1/report_2012-06-28-16:49:32.yaml +11 -0
  4. data/examples/reports/bad_exit_status/cluster2/mach1/report_2012-06-14-15:06:12.yaml +11 -0
  5. data/examples/reports/bad_exit_status/cluster2/mach2/report_2012-06-14-15:06:12.yaml +11 -0
  6. data/examples/reports/foo/cluster1/mach1/report_2012-06-28-16:49:32.yaml +10 -0
  7. data/examples/reports/foo/cluster2/mach1/report_2012-06-14-15:06:12.yaml +10 -0
  8. data/examples/reports/foo/cluster2/mach2/report_2012-06-14-15:06:12.yaml +10 -0
  9. data/examples/reports/missing_prelude/cluster1/mach1/report_2012-06-28-16:49:32.yaml +12 -0
  10. data/examples/reports/missing_prelude/cluster2/mach1/report_2012-06-14-15:06:12.yaml +12 -0
  11. data/examples/reports/missing_prelude/cluster2/mach2/report_2012-06-14-15:06:12.yaml +12 -0
  12. data/examples/reports/network/config/bootproto_dhcp/cluster1/mach1/report_2012-06-28-16:49:32.yaml +10 -0
  13. data/examples/reports/network/config/bootproto_dhcp/cluster2/mach1/report_2012-06-14-15:06:12.yaml +10 -0
  14. data/examples/reports/network/config/bootproto_dhcp/cluster2/mach2/report_2012-06-14-15:06:12.yaml +10 -0
  15. data/examples/reports/network/ethernet_bonded/cluster1/mach1/report_2012-06-28-16:49:32.yaml +31 -0
  16. data/examples/reports/network/ethernet_bonded/cluster2/mach1/report_2012-06-14-15:06:12.yaml +22 -0
  17. data/examples/reports/network/ethernet_bonded/cluster2/mach2/report_2012-06-14-15:06:12.yaml +22 -0
  18. data/examples/reports/nonexec/cluster1/mach1/report_2012-06-28-16:49:32.yaml +10 -0
  19. data/examples/reports/nonexec/cluster2/mach1/report_2012-06-14-15:06:12.yaml +10 -0
  20. data/examples/reports/nonexec/cluster2/mach2/report_2012-06-14-15:06:12.yaml +10 -0
  21. data/examples/reports/yum/badcheck/cluster1/mach1/report_2012-06-28-16:49:32.yaml +13 -0
  22. data/examples/reports/yum/badcheck/cluster2/mach1/report_2012-06-14-15:06:12.yaml +13 -0
  23. data/examples/reports/yum/badcheck/cluster2/mach2/report_2012-06-14-15:06:12.yaml +13 -0
  24. data/lib/hostmon.rb +208 -0
  25. data/lib/hostmon/config.rb +47 -0
  26. data/lib/hostmon/helpers.rb +174 -0
  27. data/lib/hostmon/models.rb +4 -0
  28. data/lib/hostmon/models/base.rb +39 -0
  29. data/lib/hostmon/models/check.rb +45 -0
  30. data/lib/hostmon/models/host.rb +211 -0
  31. data/lib/hostmon/models/report.rb +108 -0
  32. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_flat_30_cccccc_40x100.png +0 -0
  33. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  34. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_glass_20_333333_1x400.png +0 -0
  35. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_glass_40_000000_1x400.png +0 -0
  36. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  37. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  38. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_highlight-soft_15_000000_1x100.png +0 -0
  39. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  40. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_inset-soft_30_ff4e0a_1x100.png +0 -0
  41. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_222222_256x240.png +0 -0
  42. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_4b8e0b_256x240.png +0 -0
  43. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_a83300_256x240.png +0 -0
  44. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_cccccc_256x240.png +0 -0
  45. data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_ffffff_256x240.png +0 -0
  46. data/lib/hostmon/public/css/jquery_themes/hostmon/jquery-ui-1.8.16.custom.css +568 -0
  47. data/lib/hostmon/public/favicon.ico +0 -0
  48. data/lib/hostmon/public/js/cufon.js +7 -0
  49. data/lib/hostmon/public/js/gotham.font.js +40 -0
  50. data/lib/hostmon/public/js/hostmon.js +89 -0
  51. data/lib/hostmon/public/js/jquery-1.6.2.min.js +18 -0
  52. data/lib/hostmon/public/js/jquery-ui-1.8.16.custom.min.js +791 -0
  53. data/lib/hostmon/public/js/product-design.font.js +8 -0
  54. data/lib/hostmon/public/style.css +311 -0
  55. data/lib/hostmon/rubyfixes.rb +12 -0
  56. data/lib/hostmon/version.rb +3 -0
  57. data/lib/hostmon/views/check.erb +23 -0
  58. data/lib/hostmon/views/check_status.erb +16 -0
  59. data/lib/hostmon/views/cluster.erb +19 -0
  60. data/lib/hostmon/views/host.erb +15 -0
  61. data/lib/hostmon/views/host_status.erb +16 -0
  62. data/lib/hostmon/views/layout.erb +61 -0
  63. data/lib/hostmon/views/partials/check_status_selector.erb +6 -0
  64. data/lib/hostmon/views/partials/host_status_selector.erb +6 -0
  65. data/lib/hostmon/views/partials/hosts_selector.erb +9 -0
  66. data/lib/hostmon/views/partials/report.erb +7 -0
  67. data/lib/hostmon/views/partials/search.erb +18 -0
  68. data/lib/hostmon/views/partials/status_selector.erb +7 -0
  69. data/lib/hostmon/views/search_all.erb +25 -0
  70. data/lib/hostmon/views/search_checks.erb +12 -0
  71. data/lib/hostmon/views/search_host.erb +7 -0
  72. data/lib/hostmon/views/status.erb +15 -0
  73. data/lib/hostmon/views/view.erb +49 -0
  74. metadata +152 -0
@@ -0,0 +1,47 @@
1
+ require "optparse"
2
+ require "hostmon/models"
3
+
4
+ module Hostmon
5
+ class Config
6
+ include Hostmon::Models
7
+ attr_reader :global_config, :report_dir, :conf_file, :amqp_config
8
+ attr_reader :bugzilla_config
9
+
10
+ def initialize
11
+ port = 9292
12
+ @conf_file = "./config.yml"
13
+
14
+ optparse = OptionParser.new do |o|
15
+ o.on("-f", "--config-file FILE",
16
+ "location of the config directory (default .)") do |arg|
17
+ @conf_file = arg
18
+ end
19
+ o.on("-p", "--port PORT", "port to bind to (default 9292)") do |arg|
20
+ port = arg.to_i
21
+ end
22
+ end
23
+
24
+ optparse.parse!
25
+ reload!
26
+ @global_config[:port] = port
27
+ end
28
+
29
+ def reload!
30
+ raw = File.read(@conf_file)
31
+ raise "failed to load #{@conf_file}" unless yaml = YAML.load(raw)
32
+
33
+ @global_config = yaml[:main]
34
+ @bugzilla_config = yaml[:bugzilla] || false
35
+ @amqp_config = yaml[:amqp] || {}
36
+ # do some sanity checking of other configuration parameters
37
+ [:report_dir].each do |c|
38
+ if not @global_config[c]
39
+ raise "Missing config name '#{c.to_s}'"
40
+ end
41
+ end
42
+
43
+ @global_config[:saved_reports] ||= 1
44
+ @report_dir = @global_config[:report_dir]
45
+ end
46
+ end # Hostmon::Config
47
+ end # Hostmon
@@ -0,0 +1,174 @@
1
+ module Hostmon::Helpers
2
+ include Hostmon::Models
3
+
4
+ #fixme failing vs failed
5
+ def cluster_link(cluster)
6
+ "/cluster/#{cluster}"
7
+ end
8
+
9
+ def append_query_string(str)
10
+ v = str.dup
11
+ # CGI::escapeHTML()?
12
+ unless request.query_string.empty?
13
+ v << "?#{request.query_string.gsub("&", "&amp;")}"
14
+ end
15
+ return v
16
+ end
17
+
18
+ def color(status)
19
+ map = {:CHECK_OK => "green",
20
+ :CHECK_FAILED => "red"}
21
+ "[" + status.map do |s|
22
+ "<span style=\"color:#{map[s]||'orange'}\">#{s}</span>"
23
+ end.join(', ') + "]"
24
+ end
25
+
26
+ def rstatus(report)
27
+ j = report.ok? ? "ok" : "error"
28
+ "<#{j}>#{color(report.status)}</#{j}> #{bugzilla_link(report) if j=="error" } #{bugzilla_search_link(report) if j=="error" }"
29
+ end
30
+
31
+ def css_url
32
+ style = File.join(settings.root, "public/style.css")
33
+ mtime = File.mtime(style).to_i.to_s
34
+ return \
35
+ %Q[<link href="/style.css?#{mtime}" rel="stylesheet" type="text/css">]
36
+ end
37
+
38
+ def aggregate_bugzilla(check)
39
+ return "" unless settings.config.bugzilla_config
40
+ url = settings.config.bugzilla_config[:bugzilla_url]
41
+ h_url = settings.config.bugzilla_config[:hostlint_url]
42
+ failing = check.hosts_failing.map(&:first).size
43
+ failing += check.hosts_check_failing.map(&:first).size
44
+ succeeding = check.hosts_ok.map(&:first).size
45
+ fields = { :short_desc => "[hostlint] hosts failing #{check}",
46
+ :comment => "#{failing.size}/#{failing + succeeding} hosts failing at report time (#{Time.now}).
47
+ See #{h_url}/check/#{check}",
48
+ :keyword => ""
49
+ }
50
+ url_parts = []
51
+ fields.each do |k, v|
52
+ [v].flatten.each do |v2|
53
+ url_parts << "#{URI.escape(k.to_s)}=#{URI.escape(v2.to_s)}"
54
+ end
55
+ end
56
+ url += "&amp;" + url_parts.join("&amp;")
57
+ "<a href=\"#{url}\" target=\"_blank\" style=\"font-size:small;\">[file an aggregate bug]</a>"
58
+ end
59
+
60
+ def bugzilla_link(report)
61
+ return "" unless settings.config.bugzilla_config
62
+
63
+ # info should have host, cluster, report_time
64
+ url = settings.config.bugzilla_config[:bugzilla_url]
65
+ h_url = settings.config.bugzilla_config[:hostlint_url]
66
+ desc = "[hostlint ##{report.hostlint_id}] " +
67
+ "#{report.host}.#{report.cluster}: #{report.name}"
68
+ fields = { :short_desc => desc,
69
+ :comment => "hostlint link: #{h_url}/report/#{report.name}##{report.hostlint_id}
70
+ #{report.body}",
71
+ :keyword => ""
72
+ }
73
+ url_parts = []
74
+ fields.each do |k, v|
75
+ [v].flatten.each do |v2|
76
+ url_parts << "#{URI.escape(k.to_s)}=#{URI.escape(v2.to_s)}"
77
+ end
78
+ end
79
+ url += "&amp;" + url_parts.join("&amp;")
80
+ "<a href=\"#{url}\" target=\"_blank\" style=\"font-size:small;\">file a bug</a>"
81
+ end
82
+
83
+ def bugzilla_search_link(check)
84
+ return "" unless settings.config.bugzilla_config
85
+
86
+ url = settings.config.bugzilla_config[:bugzilla_search_url]
87
+ desc = "[hostlint ##{check.hostlint_id}] " +
88
+ "#{check.host}.#{check.cluster}: #{check.name}"
89
+ fields = { :short_desc => desc }
90
+ url_parts = []
91
+ fields.each do |k, v|
92
+ [v].flatten.each do |v2|
93
+ url_parts << "#{URI.escape(k.to_s)}=#{URI.escape(v2.to_s)}"
94
+ end
95
+ end
96
+ url += "&amp;" + url_parts.join("&amp;")
97
+ "<a href=\"#{url}\" target=\"_blank\" style=\"font-size:small;\">search</a>"
98
+ end
99
+
100
+ # when single cluster view, don't display cluster in hostname
101
+ def hostlink(host, single=false)
102
+ str = "<a href=\"/host/#{host.cluster}/#{host}\">#{host}"
103
+ str << ".#{host.cluster}" unless single
104
+ str << "</a>"
105
+ end
106
+
107
+ def checklink(check)
108
+ "<a href=\"/check/#{check}\">#{check}</a>"
109
+ end
110
+
111
+ def hosts_selector(hosts)
112
+ @hosts = hosts
113
+ erb :'partials/hosts_selector', :layout => false
114
+ end
115
+
116
+ def status_selector()
117
+ erb :'partials/status_selector', :layout => false
118
+ end
119
+
120
+ def stats_helper(check)
121
+ total = ok = failed = check_failed = 0
122
+ Check.find(check).host_map.each do |h, r|
123
+ r = r.last
124
+ total += 1
125
+ if r.ok?
126
+ ok += 1
127
+ elsif r.failed?
128
+ failed += 1
129
+ else
130
+ check_failed += 1
131
+ end
132
+ end
133
+
134
+ ol = append_query_string("/check/#{check}/#{Host::OK}")
135
+ fl = append_query_string("/check/#{check}/#{Host::FAIL}")
136
+ cfl = append_query_string("/check/#{check}/#{Host::EXEC_FAIL}")
137
+
138
+ "<span><a style=\"color:green\" href=\"#{ol}\">#{ok}</a></span>" +
139
+ "/<span><a style=\"color:red\" href=\"#{fl}\">#{failed}</a></span>" +
140
+ "/<span><a style=\"color:orange\" href=\"#{cfl}\">#{check_failed}</a></span>" +
141
+ " <span>(#{total})</span>"
142
+ end
143
+
144
+ # fixme de-duplication
145
+ def host_helper(host)
146
+ ok = host.succeeding.size
147
+ failed = host.failing.size
148
+ check_failed = host.checks_failing.size
149
+ total = ok + failed + check_failed
150
+ if failed + check_failed != 0
151
+
152
+ ol = append_query_string("/host/#{host.cluster}/#{host}/#{Host::OK}")
153
+ fl = append_query_string("/host/#{host.cluster}/#{host}/#{Host::FAIL}")
154
+ cfl = append_query_string("/host/#{host.cluster}/#{host}/#{Host::EXEC_FAIL}")
155
+
156
+ "<span><a style=\"color:green\" href=\"#{ol}\">#{ok}</a></span>" +
157
+ "/<span><a style=\"color:red\" href=\"#{fl}\">#{failed}</a></span>" +
158
+ "/<span><a style=\"color:orange\" href=\"#{cfl}\">#{check_failed}</a></span>" +
159
+ " <span>(#{total})</span>"
160
+ end
161
+ end
162
+
163
+ def check_status_to_hosts_map
164
+ bucket = {}
165
+ @hosts.each do |h|
166
+ type = @status == Host::OK ? :checks_succeeding : :checks_failing
167
+ h.send(type).each do |c|
168
+ bucket[c.name] ||= []
169
+ bucket[c.name] << h
170
+ end
171
+ end
172
+ bucket
173
+ end
174
+ end
@@ -0,0 +1,4 @@
1
+ require "hostmon/models/base"
2
+ require "hostmon/models/host"
3
+ require "hostmon/models/check"
4
+ require "hostmon/models/report"
@@ -0,0 +1,39 @@
1
+ module Hostmon::Models
2
+ # fixme define [] for find
3
+ class Base
4
+ @@objects = Hash.new { |h, k| h[k] = Hash.new }
5
+ attr_reader :name
6
+
7
+ def initialize(name, params={})
8
+ @name = name
9
+ @params = params
10
+ @@objects[self.class.to_s][name] = self
11
+ end
12
+
13
+ def self.find(name)
14
+ return @@objects[self.name][name] rescue []
15
+ end
16
+
17
+ def self.each(&block)
18
+ h = @@objects[self.name] rescue {}
19
+ h.sort.each { |k, v| yield(k, v) }
20
+ end
21
+
22
+ def self.all
23
+ return @@objects[self.name].values.sort
24
+ end
25
+
26
+ def [](key)
27
+ return @params[key] rescue []
28
+ end
29
+
30
+ def to_s
31
+ return @name
32
+ end
33
+
34
+ def <=>(other)
35
+ return to_s <=> other.to_s
36
+ end
37
+
38
+ end # Hostmon::Models::Base
39
+ end # Hostmon::Models
@@ -0,0 +1,45 @@
1
+ module Hostmon::Models
2
+ class Check < Base
3
+ attr_reader :name
4
+ attr_accessor :host_map
5
+
6
+ def self.absorb (name, host)
7
+ unless c = find(name)
8
+ c = new(name)
9
+ end
10
+ c.host_map[host] = host.check_reports(name)
11
+ c
12
+ end
13
+
14
+ def initialize(name)
15
+ super(name)
16
+ @host_map = {} #Host => reports
17
+ end
18
+
19
+ def host_status
20
+ ok = []
21
+ failed = []
22
+ check_failed = []
23
+ @host_map.each do |h, r|
24
+ if r.last.ok?
25
+ ok << [h, r.last]
26
+ elsif r.last.failed?
27
+ failed << [h, r.last]
28
+ else
29
+ check_failed << [h, r.last]
30
+ end
31
+ end
32
+ return ok, failed, check_failed
33
+ end
34
+
35
+ def hosts_ok
36
+ host_status[0] # .map(&:first)
37
+ end
38
+ def hosts_failing
39
+ host_status[1] # .map(&:first)
40
+ end
41
+ def hosts_check_failing
42
+ host_status[2] # .map(&:first)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,211 @@
1
+ require "hostmon/models/base"
2
+
3
+ module Hostmon::Models
4
+ class Host < Base
5
+ OK = "OK"
6
+ FAIL = "FAIL"
7
+ EXEC_FAIL = "EXEC_FAIL"
8
+ def self.statuses
9
+ [OK, FAIL, EXEC_FAIL]
10
+ end
11
+
12
+ @@clusters = Set.new
13
+
14
+ @@saved_reports = 1
15
+ def self.saved_reports
16
+ @@saved_reports
17
+ end
18
+ def self.saved_reports= (i)
19
+ @@saved_reports = i
20
+ end
21
+
22
+ @@checks = Set.new
23
+ @@check_map = {}
24
+
25
+ class << self
26
+ def clusters # attr_*
27
+ @@clusters
28
+ end
29
+ def hosts_failing(check)
30
+ @@check_map[check][FAIL]||Set.new
31
+ end
32
+
33
+ def hosts_succeeding(check)
34
+ @@check_map[check][OK]||Set.new
35
+ end
36
+
37
+ def check_map
38
+ @@check_map
39
+ end
40
+
41
+ def find_by_name_and_cluster(name, cluster)
42
+ Host.each do |host_name, host|
43
+ next unless host.name == name
44
+ return host if host.cluster == cluster
45
+ end
46
+ return nil
47
+ end
48
+
49
+ def find_by_cluster(cluster)
50
+ ret = []
51
+ Host.each do |name, host|
52
+ ret << host if host.cluster == cluster
53
+ end
54
+ return ret
55
+ end
56
+ end
57
+
58
+ attr_reader :hostname, :checks, :cluster, :status_map, :report
59
+ attr_accessor :reports, :report_time
60
+
61
+ def checks
62
+ @reports.map(&:first)
63
+ end
64
+
65
+
66
+ # return reports for checks that the host passes
67
+ def succeeding
68
+ ok_reports = Set.new
69
+ @reports.each do |n, r|
70
+ if r.last.ok?
71
+ ok_reports << r.last
72
+ end
73
+ end
74
+ ok_reports.sort
75
+ end
76
+
77
+ # return reports for checks that the host fails
78
+ def failing
79
+ failing_reports = Set.new
80
+ @reports.each do |n, r|
81
+ if r.last.failed?
82
+ failing_reports << r.last
83
+ end
84
+ end
85
+ failing_reports.sort
86
+ end
87
+
88
+ # return reports for checks that failed to execute properly
89
+ def checks_failing
90
+ failing = Set.new
91
+ @reports.each do |n, r|
92
+ if r.last.check_failed?
93
+ failing << r.last
94
+ end
95
+ end
96
+ failing.sort
97
+ end
98
+
99
+ # hacks
100
+ def to_s
101
+ @hostname
102
+ end
103
+
104
+ def name
105
+ @hostname
106
+ end
107
+
108
+ def initialize(h, c)
109
+ # needed to disambiguate
110
+ super(h+'.'+c)
111
+ @hostname = h
112
+ @cluster = c
113
+ @report_time = nil
114
+ end
115
+
116
+ def key
117
+ "#{@cluster}#{@name}"
118
+ end
119
+
120
+ def eql?(other)
121
+ key == other.key
122
+ end
123
+
124
+ def ==(other)
125
+ key == other.key
126
+ end
127
+
128
+ # fixme this is just silly
129
+ def sname
130
+ @hostname + "." + @cluster
131
+ end
132
+
133
+ # fixme @params is always empty right now
134
+ def <=>(other)
135
+ if @params[:host_sort] == "builtin"
136
+ return key <=> other.key
137
+ elsif @params[:host_sort] == "numeric"
138
+ regexp = /\d+/
139
+ match = @name.match(regexp)
140
+ match2 = other.name.match(regexp)
141
+ if match.pre_match != match2.pre_match
142
+ return match.pre_match <=> match2.pre_match
143
+ else
144
+ return match[0].to_i <=> match2[0].to_i
145
+ end
146
+ else
147
+ # http://www.bofh.org.uk/2007/12/16/comprehensible-sorting-in-ruby
148
+ sensible = lambda do |k|
149
+ k.sname.split(
150
+ /((?:(?:^|\s)[-+])?(?:\.\d+|\d+(?:\.\d+?(?:[eE]\d+)?(?:$|(?![eE\.])))?))/ms
151
+ ).map { |v| Float(v) rescue v.downcase }
152
+ end
153
+ return sensible.call(self) <=> sensible.call(other)
154
+ end
155
+ end
156
+
157
+ def hash
158
+ key.hash
159
+ end
160
+
161
+ # process and update (or create) a host and return it
162
+ # fixme saved_reports unbounded
163
+ # fixme special case for 0 (only store in memory)
164
+ def self.absorb(report)
165
+ h = report.host
166
+ c = report.cluster
167
+ unless host = find_by_name_and_cluster(h, c)
168
+ host = new(h, c)
169
+ puts "new host #{h}"
170
+ end
171
+ host.reports ||= Hash.new {|hsh,k| hsh[k] = Array.new}
172
+
173
+ # fixme slightly offensive
174
+ if host.reports[report.name].size < @@saved_reports
175
+ host.reports[report.name] << report
176
+ host.reports[report.name].sort! {|a,b| a.timestamp <=> b.timestamp }
177
+ report.write
178
+ elsif report.timestamp < host.reports[report.name].first.timestamp
179
+ return host
180
+ else
181
+ pp host.reports[report.name].size
182
+ pp @@saved_reports
183
+ host.reports[report.name] << report
184
+ host.reports[report.name].sort! {|a,b| a.timestamp <=> b.timestamp }
185
+ while host.reports[report.name].size > @@saved_reports
186
+ shift = host.reports[report.name].shift
187
+ shift.delete
188
+ end
189
+ report.write
190
+ end
191
+ ####################
192
+
193
+ time = report.timestamp
194
+ if (!host.report_time) || (host.report_time < time)
195
+ host.report_time = time
196
+ end
197
+ @@clusters << host.cluster
198
+ host
199
+ end
200
+
201
+ def check_reports(check_name)
202
+ reports[check_name]
203
+ end
204
+
205
+ # temporary
206
+ def inspect
207
+ @hostname
208
+ end
209
+
210
+ end # Hostmon::Models::Host
211
+ end # Hostmon::Models