1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """objects related to the state of workers.
23 """
24
25 import os
26 import signal
27
28 from twisted.spread import pb
29 from twisted.internet import protocol
30
31 from flumotion.common import log, errors, messages
32 from flumotion.common.i18n import N_, gettexter
33 from flumotion.twisted import flavors
34
35 __version__ = "$Rev$"
36 T_ = gettexter()
37
38
40
41 - def __init__(self, loggable, avatarId, processType, where):
42 self.loggable = loggable
43 self.avatarId = avatarId
44 self.processType = processType
45 self.where = where
46
47 self.setPid(None)
48
51
53 raise NotImplementedError
54
56
57
58
59
60 message = None
61 obj = self.loggable
62 pid = None
63
64
65 if self.pid:
66 pid = str(self.pid)
67 else:
68 pid = "unknown"
69 if status.value.exitCode is not None:
70 obj.info("Reaped child with pid %s, exit value %d.",
71 pid, status.value.exitCode)
72 signum = status.value.signal
73
74
75
76
77 if signum is not None:
78 if signum == signal.SIGKILL:
79 obj.warning("Child with pid %s killed.", pid)
80 message = messages.Error(T_(N_("The %s was killed.\n"),
81 self.processType))
82 else:
83 message = messages.Error(T_(N_("The %s crashed.\n"),
84 self.processType),
85 debug='Terminated with signal number %d' % signum)
86
87
88 if signum == signal.SIGSEGV:
89 obj.warning("Child with pid %s segfaulted.", pid)
90 elif signum == signal.SIGTRAP:
91
92 obj.warning("Child with pid %s received a SIGTRAP.",
93 pid)
94 else:
95
96 obj.info("Reaped child with pid %s signaled by "
97 "signal %d.", pid, signum)
98
99 if not os.WCOREDUMP(status.value.status):
100 obj.warning("No core dump generated. "
101 "Were core dumps enabled at the start ?")
102 message.add(T_(N_(
103 "However, no core dump was generated. "
104 "You may need to configure the environment "
105 "if you want to further debug this problem.")))
106
107
108 else:
109 obj.info("Core dumped.")
110 corepath = os.path.join(os.getcwd(), 'core.%s' % pid)
111 if os.path.exists(corepath):
112 obj.info("Core file is probably '%s'." % corepath)
113 message.add(T_(N_(
114 "The core dump is '%s' on the host running '%s'."),
115 corepath, self.where))
116
117
118
119 message.description = T_(N_(
120 "Learn how to analyze core dumps."))
121 message.section = 'chapter-debug'
122 message.anchor = 'section-os-analyze-core-dumps'
123
124 if message:
125 obj.debug('sending message to manager/admin')
126 self.sendMessage(message)
127
128 self.setPid(None)
129
130
132 """
133 A list of ports that keeps track of which are available for use on a
134 given machine.
135 """
136
137
138 - def __init__(self, logName, ports, randomPorts=False):
139 self.logName = logName
140 self.ports = ports
141 self.used = [0] * len(ports)
142 self.random = randomPorts
143
145 ret = []
146 while numPorts > 0:
147 if self.random:
148 ret.append(0)
149 numPorts -= 1
150 continue
151 if not 0 in self.used:
152 raise errors.ComponentStartError(
153 'could not allocate port on worker %s' % self.logName)
154 i = self.used.index(0)
155 ret.append(self.ports[i])
156 self.used[i] = 1
157 numPorts -= 1
158 return ret
159
161 for port in ports:
162 try:
163 i = self.ports.index(port)
164 except ValueError:
165 self.warning('portset does not include port %d', port)
166 else:
167 if self.used[i]:
168 self.warning('port %d already in use!', port)
169 else:
170 self.used[i] = 1
171
173 """
174 @param ports: list of ports to release
175 @type ports: list of int
176 """
177 for p in ports:
178 try:
179 i = self.ports.index(p)
180 if self.used[i]:
181 self.used[i] = 0
182 else:
183 self.warning('releasing unallocated port: %d' % p)
184 except ValueError:
185 self.warning('releasing unknown port: %d' % p)
186
188 return len(self.ports) - self.numUsed()
189
191 return len(filter(None, self.used))
192
193
194
195
197 """
198 I represent the state of the worker heaven on the manager.
199
200 I have the following keys:
201
202 - names (list): list of worker names that we have state for
203 - workers (list): list of L{ManagerWorkerState}
204 """
205
210
212 return "%r" % self._dict
213
214
216 """
217 I represent the state of the worker heaven in the admin.
218 See L{ManagerWorkerHeavenState}
219 """
220 pass
221
222 pb.setUnjellyableForClass(ManagerWorkerHeavenState, AdminWorkerHeavenState)
223
224
226 """
227 I represent the state of a worker in the manager.
228
229 - name: name of the worker
230 - host: the IP address of the worker as seen by the manager
231 """
232
239
241 return ("<ManagerWorkerState for %s on %s>"
242 % (self.get('name'), self.get('host')))
243
244
246 """
247 I represent the state of a worker in the admin.
248
249 See L{ManagerWorkerState}
250 """
251 pass
252
253 pb.setUnjellyableForClass(ManagerWorkerState, AdminWorkerState)
254