1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 __doc__='''Schedule
16
17 Walk through the maintenance schedule.
18
19 $Id$
20 '''
21 import time
22 import logging
23 import transaction
24 from twisted.internet import reactor
25
26 from Products.ZenEvents.ZenEventClasses import Status_Update
27 import Event
28
30
32 "start executing the schedule"
33 self.dmd = dmd
34 self.maintenance = []
35 self.options = options
36 self.log = logging.getLogger("zen.Schedule")
37 self.workList = []
38 self.timer = None
39
40
42 "Set options in a borrowed parser"
43
44
48
49
54
55
57 "Synch with the database"
58 self.dmd._p_jar.sync()
59
61 result = []
62 catalog = getattr(self.dmd, 'maintenanceWindowSearch', None)
63 if catalog is not None:
64 for brain in catalog():
65 try:
66 ob = brain.getObject()
67 except KeyError:
68
69
70
71 pass
72 else:
73 result.append(ob)
74 else:
75 self.log.warn('Run zenmigrate to index your maintenance windows.')
76 for dev in self.dmd.Devices.getSubDevices():
77 result.extend(dev.maintenanceWindows())
78 for name in 'Systems', 'Locations', 'Groups', 'Devices':
79 organizer = getattr(self.dmd, name)
80 for c in organizer.getSubOrganizers():
81 result.extend(c.maintenanceWindows())
82 result.extend(organizer.maintenanceWindows())
83 for lst in [self.dmd.ZenUsers.getAllUserSettings(),
84 self.dmd.ZenUsers.getAllGroupSettings()]:
85 for us in lst:
86 for ar in us.objectValues(spec="ActionRule"):
87 result.extend([w for w in ar.windows() if w.enabled])
88 return result
89
95
97 work = [(mw.nextEvent(now), mw) for mw in workList]
98 work.sort()
99
100 while len(work):
101 t, mw = work[0]
102 if t: break
103 if mw.enabled:
104 self.log.debug("Never going to run Maintenance "
105 "Window %s for %s again",
106 mw.getId(), mw.target().getId())
107 if mw.started:
108 mw.end()
109 work.pop(0)
110 return work
111
114
116 "Execute all the maintanance windows at the proper time"
117
118 if self.timer and not self.timer.called:
119 self.timer.cancel()
120
121
122 now = self.now()
123 work = self.makeWorkList(now, self.workList)
124 self.workList = [mw for t, mw in work]
125
126
127 for next, mw in work:
128 if next <= now:
129 how = {True:'stopping', False:'starting'}[bool(mw.started)]
130 severity = {True:Event.Clear, False:Event.Info}[bool(mw.started)]
131
132
133
134 prodState = {True:-99, False:mw.startProductionState}[bool(mw.started)]
135 mwId = mw.getId()
136 devices = mw.target().getId()
137 msg = "Maintenance window %s %s for %s" % (how, mwId, devices)
138 self.log.debug(msg)
139 dedupid = '|'.join(["zenactions",self.monitor,mwId,devices])
140 self.sendEvent(Event.Event(
141 component="zenactions",
142 severity=severity,
143 dedupid=dedupid,
144 eventClass=Status_Update,
145 eventClassKey="mw_change",
146 summary=msg,
147 maintenance_window=mwId,
148 maintenance_devices=devices,
149 device=self.monitor,
150 prodState=prodState,
151 ))
152 self.executeMaintenanceWindow(mw, next)
153 else:
154 break
155
156 work = self.makeWorkList(now, self.workList)
157 if work:
158 wait = max(0, work[0][0] - now)
159 self.log.debug("Waiting %f seconds", wait)
160 self.timer = self.callLater(wait)
161 self.commit()
162
165
168
169 - def executeMaintenanceWindow(self, mw, timestamp):
171
172 if __name__ == "__main__":
190
191 import Globals
192 from Products.ZenUtils.ZCmdBase import ZCmdBase
193
194 cmd = ZCmdBase()
196 s = MySchedule(Options(), cmd.dmd)
197
198 end = s.currentTime + 60*60*24*30
199 while s.currentTime < end:
200 s.run()
201