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/>.
23 from comment
import Comment
28 #Just to list the properties we will send as pickle
29 #so to others daemons, so all but NOT REF
38 'real_end_time' : 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())
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
69 self
.end_time
= end_time
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
79 self
.real_end_time
= end_time
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()
89 if self
.is_in_effect
== True:
93 if self
.fixed
== True:
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
112 self
.is_in_effect
= True
113 if self
.fixed
== False:
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())
126 #The end of the downtime was reached.
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
138 #This was probably a flexible downtime which was not triggered
139 #In this case it silently disappears
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
151 #A scheduled downtime was prematurely cancelled
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())
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
)
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':
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()
198 #id is not in *_properties
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
208 #Inversed funtion of getstate
209 def __setstate__(self
, state
):
211 self
.id = state
.pop()
212 for prop
in cls
.properties
:
214 setattr(self
, prop
, val
)