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.
- data/bin/hostmon +4 -0
- data/examples/config.yml +14 -0
- data/examples/reports/bad_exit_status/cluster1/mach1/report_2012-06-28-16:49:32.yaml +11 -0
- data/examples/reports/bad_exit_status/cluster2/mach1/report_2012-06-14-15:06:12.yaml +11 -0
- data/examples/reports/bad_exit_status/cluster2/mach2/report_2012-06-14-15:06:12.yaml +11 -0
- data/examples/reports/foo/cluster1/mach1/report_2012-06-28-16:49:32.yaml +10 -0
- data/examples/reports/foo/cluster2/mach1/report_2012-06-14-15:06:12.yaml +10 -0
- data/examples/reports/foo/cluster2/mach2/report_2012-06-14-15:06:12.yaml +10 -0
- data/examples/reports/missing_prelude/cluster1/mach1/report_2012-06-28-16:49:32.yaml +12 -0
- data/examples/reports/missing_prelude/cluster2/mach1/report_2012-06-14-15:06:12.yaml +12 -0
- data/examples/reports/missing_prelude/cluster2/mach2/report_2012-06-14-15:06:12.yaml +12 -0
- data/examples/reports/network/config/bootproto_dhcp/cluster1/mach1/report_2012-06-28-16:49:32.yaml +10 -0
- data/examples/reports/network/config/bootproto_dhcp/cluster2/mach1/report_2012-06-14-15:06:12.yaml +10 -0
- data/examples/reports/network/config/bootproto_dhcp/cluster2/mach2/report_2012-06-14-15:06:12.yaml +10 -0
- data/examples/reports/network/ethernet_bonded/cluster1/mach1/report_2012-06-28-16:49:32.yaml +31 -0
- data/examples/reports/network/ethernet_bonded/cluster2/mach1/report_2012-06-14-15:06:12.yaml +22 -0
- data/examples/reports/network/ethernet_bonded/cluster2/mach2/report_2012-06-14-15:06:12.yaml +22 -0
- data/examples/reports/nonexec/cluster1/mach1/report_2012-06-28-16:49:32.yaml +10 -0
- data/examples/reports/nonexec/cluster2/mach1/report_2012-06-14-15:06:12.yaml +10 -0
- data/examples/reports/nonexec/cluster2/mach2/report_2012-06-14-15:06:12.yaml +10 -0
- data/examples/reports/yum/badcheck/cluster1/mach1/report_2012-06-28-16:49:32.yaml +13 -0
- data/examples/reports/yum/badcheck/cluster2/mach1/report_2012-06-14-15:06:12.yaml +13 -0
- data/examples/reports/yum/badcheck/cluster2/mach2/report_2012-06-14-15:06:12.yaml +13 -0
- data/lib/hostmon.rb +208 -0
- data/lib/hostmon/config.rb +47 -0
- data/lib/hostmon/helpers.rb +174 -0
- data/lib/hostmon/models.rb +4 -0
- data/lib/hostmon/models/base.rb +39 -0
- data/lib/hostmon/models/check.rb +45 -0
- data/lib/hostmon/models/host.rb +211 -0
- data/lib/hostmon/models/report.rb +108 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_flat_30_cccccc_40x100.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_glass_20_333333_1x400.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_glass_40_000000_1x400.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_glass_40_ffc73d_1x400.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_highlight-soft_15_000000_1x100.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-bg_inset-soft_30_ff4e0a_1x100.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_222222_256x240.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_4b8e0b_256x240.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_a83300_256x240.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_cccccc_256x240.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/images/ui-icons_ffffff_256x240.png +0 -0
- data/lib/hostmon/public/css/jquery_themes/hostmon/jquery-ui-1.8.16.custom.css +568 -0
- data/lib/hostmon/public/favicon.ico +0 -0
- data/lib/hostmon/public/js/cufon.js +7 -0
- data/lib/hostmon/public/js/gotham.font.js +40 -0
- data/lib/hostmon/public/js/hostmon.js +89 -0
- data/lib/hostmon/public/js/jquery-1.6.2.min.js +18 -0
- data/lib/hostmon/public/js/jquery-ui-1.8.16.custom.min.js +791 -0
- data/lib/hostmon/public/js/product-design.font.js +8 -0
- data/lib/hostmon/public/style.css +311 -0
- data/lib/hostmon/rubyfixes.rb +12 -0
- data/lib/hostmon/version.rb +3 -0
- data/lib/hostmon/views/check.erb +23 -0
- data/lib/hostmon/views/check_status.erb +16 -0
- data/lib/hostmon/views/cluster.erb +19 -0
- data/lib/hostmon/views/host.erb +15 -0
- data/lib/hostmon/views/host_status.erb +16 -0
- data/lib/hostmon/views/layout.erb +61 -0
- data/lib/hostmon/views/partials/check_status_selector.erb +6 -0
- data/lib/hostmon/views/partials/host_status_selector.erb +6 -0
- data/lib/hostmon/views/partials/hosts_selector.erb +9 -0
- data/lib/hostmon/views/partials/report.erb +7 -0
- data/lib/hostmon/views/partials/search.erb +18 -0
- data/lib/hostmon/views/partials/status_selector.erb +7 -0
- data/lib/hostmon/views/search_all.erb +25 -0
- data/lib/hostmon/views/search_checks.erb +12 -0
- data/lib/hostmon/views/search_host.erb +7 -0
- data/lib/hostmon/views/status.erb +15 -0
- data/lib/hostmon/views/view.erb +49 -0
- 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("&", "&")}"
|
|
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 += "&" + url_parts.join("&")
|
|
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 += "&" + url_parts.join("&")
|
|
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 += "&" + url_parts.join("&")
|
|
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,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
|