Enh: (Grégory Starck) still code clean for pyro wrapper in satellitelinks.
[shinken.git] / shinken / downtime.py
blobcbf8172381333ad1e22faf33ac24cebda549c53c
1 #!/usr/bin/env python
2 #Copyright (C) 2009-2010 :
3 # Gabes Jean, naparuba@gmail.com
4 # Gerhard Lausser, Gerhard.Lausser@consol.de
6 #This file is part of Shinken.
8 #Shinken is free software: you can redistribute it and/or modify
9 #it under the terms of the GNU Affero General Public License as published by
10 #the Free Software Foundation, either version 3 of the License, or
11 #(at your option) any later version.
13 #Shinken is distributed in the hope that it will be useful,
14 #but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 #GNU Affero General Public License for more details.
18 #You should have received a copy of the GNU Affero General Public License
19 #along with Shinken. If not, see <http://www.gnu.org/licenses/>.
22 import time
23 from comment import Comment
25 class Downtime:
26 id = 1
28 #Just to list the properties we will send as pickle
29 #so to others daemons, so all but NOT REF
30 properties = {
31 'activate_me' : None,
32 'entry_time' : None,
33 'fixed' : None,
34 'start_time' : None,
35 'duration' : None,
36 'trigger_id' : None,
37 'end_time' : None,
38 'real_end_time' : None,
39 'author' : None,
40 'comment' : None,
41 'is_in_effect' : None,
42 'has_been_triggered' : None,
43 'can_be_deleted' : None,
47 #Schedules downtime for a specified service. If the "fixed" argument is set
48 #to one (1), downtime will start and end at the times specified by the
49 #"start" and "end" arguments.
50 #Otherwise, downtime will begin between the "start" and "end" times and last
51 #for "duration" seconds. The "start" and "end" arguments are specified
52 #in time_t format (seconds since the UNIX epoch). The specified service
53 #downtime can be triggered by another downtime entry if the "trigger_id"
54 #is set to the ID of another scheduled downtime entry.
55 #Set the "trigger_id" argument to zero (0) if the downtime for the
56 #specified service should not be triggered by another downtime entry.
57 def __init__(self, ref, start_time, end_time, fixed, trigger_id, duration, author, comment):
58 self.id = self.__class__.id
59 self.__class__.id += 1
60 self.ref = ref #pointer to srv or host we are apply
61 self.activate_me = [] #The other downtimes i need to activate
62 self.entry_time = int(time.time())
63 self.fixed = fixed
64 self.start_time = start_time
65 self.duration = duration
66 self.trigger_id = trigger_id
67 if self.trigger_id != 0: # triggered plus fixed makes no sense
68 self.fixed = False
69 self.end_time = end_time
70 if fixed:
71 self.duration = end_time - start_time
72 #This is important for flexible downtimes. Here start_time and
73 #end_time mean: in this time interval it is possible to trigger
74 #the beginning of the downtime which lasts for duration.
75 #Later, when a non-ok event happens, real_end_time will be
76 #recalculated from now+duration
77 #end_time will be displayed in the web interface, but real_end_time
78 #is used internally
79 self.real_end_time = end_time
80 self.author = author
81 self.comment = comment
82 self.is_in_effect = False # fixed: start_time has been reached, flexible: non-ok checkresult
83 self.has_been_triggered = False # another downtime has triggered me
84 self.can_be_deleted = False
85 self.add_automatic_comment()
88 def __str__(self):
89 if self.is_in_effect == True:
90 active = "active"
91 else:
92 active = "inactive"
93 if self.fixed == True:
94 type = "fixed"
95 else:
96 type = "flexible"
97 return "%s %s Downtime id=%d %s - %s" % (active, type, self.id, time.ctime(self.start_time), time.ctime(self.end_time))
100 def trigger_me(self, other_downtime):
101 self.activate_me.append(other_downtime)
104 def in_scheduled_downtime(self):
105 return self.is_in_effect
108 #The referenced host/service object enters now a (or another) scheduled
109 #downtime. Write a log message only if it was not already in a downtime
110 def enter(self):
111 res = []
112 self.is_in_effect = True
113 if self.fixed == False:
114 now = time.time()
115 self.real_end_time = now + self.duration
116 if self.ref.scheduled_downtime_depth == 0:
117 self.ref.raise_enter_downtime_log_entry()
118 self.ref.create_notifications('DOWNTIMESTART')
119 self.ref.scheduled_downtime_depth += 1
120 self.ref.in_scheduled_downtime = True
121 for dt in self.activate_me:
122 res.extend(dt.enter())
123 return res
126 #The end of the downtime was reached.
127 def exit(self):
128 res = []
129 if self.is_in_effect == True:
130 #This was a fixed or a flexible+triggered downtime
131 self.is_in_effect = False
132 self.ref.scheduled_downtime_depth -= 1
133 if self.ref.scheduled_downtime_depth == 0:
134 self.ref.raise_exit_downtime_log_entry()
135 self.ref.create_notifications('DOWNTIMEEND')
136 self.ref.in_scheduled_downtime = False
137 else:
138 #This was probably a flexible downtime which was not triggered
139 #In this case it silently disappears
140 pass
141 self.del_automatic_comment()
142 self.can_be_deleted = True
143 #when a downtime ends and the service was critical
144 #a notification is sent with the next critical check
145 #So we should set a flag here which signals consume_result
146 #to send a notification
147 self.ref.in_scheduled_downtime_during_last_check = True
148 return res
151 #A scheduled downtime was prematurely cancelled
152 def cancel(self):
153 res = []
154 self.is_in_effect = False
155 self.ref.scheduled_downtime_depth -= 1
156 if self.ref.scheduled_downtime_depth == 0:
157 self.ref.raise_cancel_downtime_log_entry()
158 self.ref.in_scheduled_downtime = False
159 self.del_automatic_comment()
160 self.can_be_deleted = True
161 self.ref.in_scheduled_downtime_during_last_check = True
162 #Nagios does not notify on cancelled downtimes
163 #res.extend(self.ref.create_notifications('DOWNTIMECANCELLED'))
164 #Also cancel other downtimes triggered by me
165 for dt in self.activate_me:
166 res.extend(dt.cancel())
167 return res
170 #Scheduling a downtime creates a comment automatically
171 def add_automatic_comment(self):
172 if self.fixed == True:
173 text = "This %s has been scheduled for fixed downtime from %s to %s. Notifications for the %s will not be sent out during that time period." % (self.ref.my_type, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.start_time)), time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.end_time)), self.ref.my_type)
174 else:
175 hours, remainder = divmod(self.duration, 3600)
176 minutes, seconds = divmod(remainder, 60)
177 text = "This %s has been scheduled for flexible downtime starting between %s and %s and lasting for a period of %d hours and %d minutes. Notifications for the %s will not be sent out during that time period." % (self.ref.my_type, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.start_time)), time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.end_time)), hours, minutes, self.ref.my_type)
178 if self.ref.my_type == 'host':
179 comment_type = 1
180 else:
181 comment_type = 2
182 c = Comment(self.ref, False, "(Nagios Process)", text, comment_type, 2, 0, False, 0)
183 self.comment_id = c.id
184 self.extra_comment = c
185 self.ref.add_comment(c)
188 def del_automatic_comment(self):
189 self.extra_comment.can_be_deleted = True
190 #self.ref.del_comment(self.comment_id)
193 #Call by picle for dataify the coment
194 #because we DO NOT WANT REF in this pickleisation!
195 def __getstate__(self):
196 # print "Asking a getstate for a downtime on", self.ref.get_dbg_name()
197 cls = self.__class__
198 #id is not in *_properties
199 res = [self.id]
200 for prop in cls.properties:
201 res.append(getattr(self, prop))
202 #We reverse because we want to recreate
203 #By check at properties in the same order
204 res.reverse()
205 return res
208 #Inversed funtion of getstate
209 def __setstate__(self, state):
210 cls = self.__class__
211 self.id = state.pop()
212 for prop in cls.properties:
213 val = state.pop()
214 setattr(self, prop, val)