1
2
3
4
5
6
7
8
9
10
11
12
13
14 import os
15 import time
16 from datetime import datetime
17 import transaction
18 from twisted.internet import defer, reactor
19 from twisted.internet.protocol import ProcessProtocol
20 from zope.interface import implements
21 from Globals import InitializeClass
22 from Products.ZenModel.ZenModelRM import ZenModelRM
23 from Products.ZenRelations.RelSchema import *
24 from Products.ZenUtils.Utils import basicAuthUrl, zenPath
25 from Products.ZenWidgets import messaging
26
27 from interfaces import IJob
28 from status import SUCCESS, FAILURE
29 from logfile import LogFile
30
31 -class Job(ZenModelRM):
32
33 implements(IJob)
34
35 _relations = (
36 ("status", ToOne( ToOne, "Products.Jobber.status.JobStatus", "job")),
37 )
38
40 return self.id.split('_')[-1]
41
44
47
49 """
50 @return: The L{JobStatus} associated with this job.
51 @rtype: L{JobStatus}
52 """
53 return self.status()
54
56 """
57 Halt the job, for whatever reason.
58
59 This will almost certainly be implemented differently in various
60 subclasses.
61
62 @param why: The reason why the build is interrupted
63 @type why: str
64 """
65 pass
66
68 """
69 This starts off the job. Returns a Deferred that will fire when the
70 step finishes.
71 """
72 whendone = defer.Deferred()
73 self._v_deferred = whendone
74 status = self.getStatus()
75 if status is not None:
76 status.jobStarted()
77 d = defer.succeed(None)
78 d.addCallback(self.run)
79 return whendone
80
82 """
83 Should call self.finished(results) when done, where results is one of
84 SUCCESS, FAILURE.
85 """
86 raise NotImplementedError("Your subclass must implement this method.")
87
89 """
90 Called to signify the end of the job.
91 """
92 d = self._v_deferred
93
94 status = self.getStatus()
95 if status is not None:
96 status.jobFinished(results)
97
98 d.callback(results)
99
100
102 log = None
104 """
105 Initialization method. Accepts a reference to the relevant Job
106 instance and a defer.Deferred that will be called back.
107 """
108 self.job = job
109 self.whenComplete = whenComplete
110
120
128
129
130 errReceived = outReceived
131
133 """
134 We're done. End the job.
135 """
136 code = 1
137 try:
138 code = reason.value.exitCode
139 except AttributeError:
140 pass
141 if code==0:
142 result = SUCCESS
143 else:
144 result = FAILURE
145
146 if self.log is not None:
147 now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
148 self.log.msg('Job completed at %s. Result: %s.' % (now,
149 result==SUCCESS and 'success' or 'failure'))
150 self.log.finish()
151
152 self.whenComplete.callback(result)
153
154
156 _v_process = None
157 pid = 0
159 """
160 Initialization method.
161
162 @param cmd: The command that will be run by the job.
163 @type cmd: list or string
164 """
165 super(ShellCommandJob, self).__init__(jobid)
166 if isinstance(cmd, basestring):
167 cmd = cmd.split()
168 self.cmd = cmd
169
170
171 self.environ = os.environ.copy()
172
174 return " ".join(self.cmd)
175
185
187
188
189 if self._v_process is not None:
190 self._v_process.signalProcess('STOP')
191
192 elif self.pid:
193 try: os.kill(self.pid, 15)
194 except OSError: pass
195
196
198 """
199 Adapts IJobs to send messages. Differs from MessageSender insofar as it
200 forces a commit to the database after sending.
201 """
205
209
213