2 # Copyright (C) 2009-2010 :
3 # Gabes Jean, naparuba@gmail.com
4 # Gerhard Lausser, Gerhard.Lausser@consol.de
5 # Gregory Starck, g.starck@gmail.com
7 # This file is part of Shinken.
9 # Shinken is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU Affero General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # Shinken is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU Affero General Public License for more details.
19 # You should have received a copy of the GNU Affero General Public License
20 # along with Shinken. If not, see <http://www.gnu.org/licenses/>.
24 Here is a node class for dependency_node(s) and a factory to create them
29 #pat = "(h1;db | h2;db | h3;db) & (h4;Apache & h5;Apache & h6;Apache) & (h7;lvs | h8;lvs)"
30 #pat2 = "h1;db | h2;db"
31 #pat3 = "(h1;db | h2;db | h3;db) & (h4;Apache & h5;Apache)"
32 #pat4 = "2 of: h1;db | h2;db | h3;db"
34 class DependencyNode(object):
39 self
.configuration_errors
= []
42 return "Op:'%s' Val:'%s' Sons:'[%s]'" % (self
.operand
, self
.of_values
, ','.join([str(s
) for s
in self
.sons
]))
45 # We will get the state of this node, by looking at the state of
46 # our sons, and apply our operand
48 #print "Ask state of me", self
50 # If we are a host or a service, wee just got the host/service
52 if self
.operand
in ['host', 'service']:
53 state
= self
.sons
[0].last_hard_state_id
54 #print "Get the hard state (%s) for the object %s" % (state, self.sons[0].get_name())
55 # Make DOWN look as CRITICAL (2 instead of 1)
56 if self
.operand
== 'host' and state
== 1:
60 # First we get teh state of all our sons
66 # We will surely need the worse state
67 worse_state
= max(states
)
69 # We look for the better state but not OK/UP
70 no_ok
= [s
for s
in states
if s
!= 0]
72 better_no_good
= min(no_ok
)
74 # Now look at the rule. For a or
75 if self
.operand
== '|':
77 #print "We find a OK/UP match in an OR", states
79 # no ok/UP-> return worse state
81 #print "I send the better no good state...in an OR", better_no_good, states
84 # With an AND, we just send the worse state
85 if self
.operand
== '&':
86 #print "We raise worse state for a AND", worse_state,states
89 # Ok we've got a 'of:' rule
90 nb_search
= self
.of_values
91 # Look if we've got enouth 0
92 if len([s
for s
in states
if s
== 0]) >= nb_search
:
93 #print "Good, we find at least %d 0 in states for a of:" % nb_search, states
96 # Now maybe at least enouth WARNING, still beter than CRITICAL...
97 if len([s
for s
in states
if s
== 1]) >= nb_search
:
98 #print "Beter than nothing, we find at least %d 1 in states for a of:" % nb_search, states
101 # Sic... not good, return 2
102 #print "ARG, not enough 1 or 0, return 2..."
106 #return a list of all host/service in our node and below
107 def list_all_elements(self
):
110 #We are a host/service
111 if self
.operand
in ['host', 'service']:
112 return [self
.sons
[0]]
115 r
.extend(s
.list_all_elements())
122 """Check for empty (= not found) leaf nodes"""
128 if isinstance(s
, DependencyNode
) and not s
.is_valid():
129 self
.configuration_errors
.extend(s
.configuration_errors
)
136 class DependencyNodeFactory(object):
140 # the () will be eval in a recursiv way, only one level of ()
141 def eval_cor_patern(self
, patern
, hosts
, services
):
142 patern
= patern
.strip()
143 #print "*****Loop", patern
146 # Look if it's a complex patern (with rule) or
147 # if it's a leef ofit, like a host/service
154 node
= DependencyNode()
155 p
= "^(\d+) *of: *(.+)"
159 #print "Match the of: thing N=", m.groups()
161 node
.of_values
= int(m
.groups()[0])
162 patern
= m
.groups()[1]
164 #print "Is so complex?", patern, complex_node
166 # if it's a single host/service
168 #print "Try to find?", patern
169 node
.operand
= 'object'
170 obj
, error
= self
.find_object(patern
, hosts
, services
)
172 # Set host or service
173 node
.operand
= obj
.__class
__.my_type
174 node
.sons
.append(obj
)
176 node
.configuration_errors
.append(error
)
188 o
= self
.eval_cor_patern(tmp
, hosts
, services
)
189 #print "1( I've %s got new sons" % patern , o
196 #print "Evaling sub pat", tmp
197 o
= self
.eval_cor_patern(tmp
, hosts
, services
)
198 #print "2) I've %s got new sons" % patern , o
201 #print "Fuck a node son!"
207 current_rule
= node
.operand
208 #print "Current rule", current_rule
209 if current_rule
!= None and current_rule
!= 'of:' and c
!= current_rule
:
210 #print "Fuck, you mix all dumbass!"
212 if current_rule
!= 'of:':
216 o
= self
.eval_cor_patern(tmp
, hosts
, services
)
217 #print "3&| I've %s got new sons" % patern , o
228 o
= self
.eval_cor_patern(tmp
, hosts
, services
)
229 #print "4end I've %s got new sons" % patern , o
232 #print "End, tmp", tmp
233 #print "R %s :" % patern, node
237 # We've got an object, like h1,db1 that mean the
238 # db1 service of the host db1, or just h1, that mean
240 def find_object(self
, patern
, hosts
, services
):
241 #print "Finding object", patern
245 # h_name, service_desc are , separated
246 elts
= patern
.split(',')
248 # Look if we have a service
251 service_description
= elts
[1]
253 obj
= services
.find_srv_by_name_and_hostname(host_name
, service_description
)
255 error
= "Business rule uses unknown service %s/%s" % (host_name
, service_description
)
257 obj
= hosts
.find_by_name(host_name
)
259 error
= "Business rule uses unknown host %s" % (host_name
,)