-
Notifications
You must be signed in to change notification settings - Fork 0
/
bluster.rb
117 lines (106 loc) · 3.17 KB
/
bluster.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
class Bluster
attr_accessor :objects_path, :redis_host, :redis_port, :last_update_timestamp, :redis
# Instantiate a new Bluster object.
#
# objects_path - path to the Nagios objects.cache file
#
# Returns a configured Bluster instance.
def initialize(objects_path, server)
self.objects_path = objects_path
self.redis_host = server.split(':').first
self.redis_port = server.split(':').last.to_i
self.last_update_timestamp = 0
ensure_object_cache_exists
ensure_redis_connection
end
# The list of contact object names.
#
# Returns an Array of String contact names.
def contacts
ensure_cache_up_to_date
contacts = self.redis.keys("bluster:objects:contact:*")
contacts.map! { |r| r.split(":")[3] }
contacts.uniq
end
# The configuration details of a contact.
#
# Returns a Hash of Strings.
def get_contact(contact)
ensure_cache_up_to_date
namespace = "bluster:objects:contact:#{contact}"
keys = self.redis.keys("#{namespace}:*")
data = {}
keys.each { |key|
short_key = key.split(":")[4]
data[short_key] = self.redis.get("#{namespace}:#{short_key}")
}
data
end
private
# Checks that the provided object cache path exists.
#
# Returns nothing.
def ensure_object_cache_exists
if not File.exist? self.objects_path
raise ObjectCacheNotFound.new(self.objects_path)
end
end
# Ensure that the cache in Redis is up to date
#
# Returns nothing.
def ensure_cache_up_to_date
self.last_update_timestamp = self.redis.get("bluster:last_update_timestamp").to_i
if self.last_update_timestamp.nil?
update_object_cache
elsif self.last_update_timestamp != File.new(self.objects_path).mtime.to_i
update_object_cache
end
end
# Ensure that a working connection to Redis has been established and that
# the object cache is up to date.
#
# Returns nothing.
def ensure_redis_connection
self.redis = Redis.new(:host => self.redis_host, :port => self.redis_port)
ensure_cache_up_to_date
rescue Errno::ECONNREFUSED
raise RedisConnectionError.new("Unable to connect to redis")
end
# Read the object cache file and store the contents in redis.
#
# Returns nothing.
def update_object_cache
in_object = false
objects = {}
data = {}
type = ""
File.open(self.objects_path, "r").readlines.each { |line|
line = line.strip
if line =~ %r{^define (\w+) .*}
type = $1
in_object = true
data = {}
if objects[type].nil?
objects[type] = []
end
else
if in_object == true
if line == "}"
in_object = false
objects[type] << data
else
chunks = line.squeeze(' ').split(' ')
data[chunks.first] = chunks.last
end
end
end
}
objects["contact"].each { |contact|
namespace = "bluster:objects:contact:#{contact['contact_name']}"
contact.keys.each { |key|
self.redis.set("#{namespace}:#{key}", contact[key]) if key != "contact_name"
}
}
self.redis.set("bluster:last_update_timestamp", File.new(self.objects_path).mtime.to_i)
end
end