1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """
23 Serializable objects from worker through manager to admin for
24 planet, flow, job and component.
25 """
26
27 from twisted.spread import pb
28 from twisted.internet import defer
29 from zope.interface import implements
30
31 from flumotion.twisted import flavors
32 from flumotion.common import enum, log
33
35 """
36 I represent the state of a planet in the manager.
37
38 I have the following keys:
39
40 - name
41 - manager
42 - atmosphere: L{ManagerAtmosphereState}
43 - flows (list): list of L{ManagerFlowState}
44 """
45
58
60 """
61 Return a list of all component states in this planet
62 (from atmosphere and all flows).
63
64 @rtype: list of L{ManagerComponentState}
65 """
66 list = []
67
68 a = self.get('atmosphere')
69 if a:
70 list.extend(a.get('components'))
71
72 flows = self.get('flows')
73 if flows:
74 for flow in flows:
75 list.extend(flow.get('components'))
76
77 return list
78
79
81 """
82 I represent the state of a planet in an admin client.
83 See L{ManagerPlanetState}.
84 """
92
93 pb.setUnjellyableForClass(ManagerPlanetState, AdminPlanetState)
94
96 """
97 I represent the state of an atmosphere in the manager.
98 The atmosphere contains components that do not participate in a flow,
99 but provide services to flow components.
100
101 I have the following keys:
102
103 - name: string, "atmosphere"
104 - parent: L{ManagerPlanetState}
105 - components (list): list of L{ManagerComponentState}
106 """
107
114
116 """
117 Clear out all component entries.
118
119 @returns: a DeferredList that will fire when all notifications are done.
120 """
121 list = [self.remove('components', c) for c in self.get('components')]
122 return defer.DeferredList(list)
123
125 """
126 I represent the state of an atmosphere in an admin client.
127 See L{ManagerAtmosphereState}.
128 """
134
135 pb.setUnjellyableForClass(ManagerAtmosphereState, AdminAtmosphereState)
136
138 """
139 I represent the state of a flow in the manager.
140
141 I have the following keys:
142
143 - name: string, name of the flow
144 - parent: L{ManagerPlanetState}
145 - components (list): list of L{ManagerComponentState}
146 """
148 """
149 ManagerFlowState constructor. Any keyword arguments are
150 intepreted as initial key-value pairs to set on the new
151 ManagerFlowState.
152 """
153 flavors.StateCacheable.__init__(self)
154 self.addKey('name')
155 self.addKey('parent')
156 self.addListKey('components')
157 for k, v in kwargs.items():
158 self.set(k, v)
159
161 """
162 Clear out all component entries
163 """
164
165 components = self.get('components')[:]
166
167 list = [self.remove('components', c) for c in components]
168 return defer.DeferredList(list)
169
171 """
172 I represent the state of a flow in an admin client.
173 See L{ManagerFlowState}.
174 """
180
181 pb.setUnjellyableForClass(ManagerFlowState, AdminFlowState)
182
183
184
185 """
186 @cvar moods: an enum representing the mood a component can be in.
187 """
188 moods = enum.EnumClass(
189 'Moods',
190 ('happy', 'hungry', 'waking', 'sleeping', 'lost', 'sad')
191 )
192 moods.can_stop = staticmethod(lambda m: m != moods.sleeping)
193 moods.can_start = staticmethod(lambda m: m == moods.sleeping)
194
195 _jobStateKeys = ['mood', 'manager-ip', 'pid', 'workerName']
196 _jobStateListKeys = ['messages', ]
197
198
200 """
201 I represent the state of a component in the manager.
202 I have my own state, and also proxy state from the L{ManagerJobState}
203 when the component is actually created in a worker.
204
205 I have the following keys of my own:
206
207 - name: str, name of the component, unique in the parent
208 - parent: L{ManagerFlowState} or L{ManagerAtmosphereState}
209 - type: str, type of the component
210 - moodPending: int, the mood value the component is being set to
211 - workerRequested: str, name of the worker this component is
212 requested to be started on.
213 - config: dict, the configuration dict for this component
214
215 It also has a special key, 'mood'. This acts as a proxy for the mood
216 in the L{WorkerJobState}, when there is a job attached (the job's copy
217 is authoritative when it connects), and is controlled independently at
218 other times.
219
220 I proxy the following keys from the serialized L{WorkerJobState}:
221 - mood, manager-ip, pid, workerName
222 - messages (list)
223 """
224
241
243 return "<ManagerComponentState %s>" % self._dict['name']
244
274 return event
275
276 jobState.addListener(self, proxy('set'), proxy('append'),
277 proxy('remove'))
278
279 - def set(self, key, value):
288
290 if self._jobState and moodValue != moods.sad.value:
291 log.warning('componentstate', 'cannot set component mood to '
292 'something other than sad when we have a '
293 'jobState -- fix your code!')
294 elif moodValue == self.get('mood'):
295 log.log('componentstate', '%s already in mood %d',
296 self.get('name'), moodValue)
297 else:
298 log.debug('componentstate', 'manager sets mood of %s from %s to %d',
299 self.get('name'), self.get('mood'), moodValue)
300 self.set('mood', moodValue)
301
303 """
304 Remove the job state.
305 """
306
307 for m in self._jobState.get('messages'):
308 self.remove('messages', m)
309
310 self._jobState.removeListener(self)
311 self._jobState = None
312
313
314
315
316
317
318 if self.get('mood') != moods.sad.value:
319 if shutdownRequested:
320 log.debug('componentstate', "Shutdown was requested, %s"
321 " now sleeping", self.get('name'))
322 self.setMood(moods.sleeping.value)
323 else:
324 log.debug('componentstate', "Shutdown was NOT requested,"
325 " %s now lost", self.get('name'))
326 self.setMood(moods.lost.value)
327
329 """
330 I represent the state of a component in the admin client.
331 See L{ManagerComponentState}.
332 """
334 return "<AdminComponentState %s>" % self._dict['name']
335
336 pb.setUnjellyableForClass(ManagerComponentState, AdminComponentState)
337
338
339
341 """
342 I represent the state of a job in the worker, running a component.
343
344 I have the following keys:
345
346 - mood: int, value of the mood this component is in
347 - ip: string, IP address of the worker
348 - pid: int, PID of the job process
349 - workerName: string, name of the worker I'm running on
350 - messages: list of L{flumotion.common.messages.Message}
351
352 In addition, if I am the state of a FeedComponent, then I also
353 have the following keys:
354
355 - eaterNames: list of feedId being eaten by the eaters
356 - feederNames: list of feedId being fed by the feeders
357
358 @todo: change eaterNames and feederNames to eaterFeedIds and ...
359 """
366
368 """
369 I represent the state of a job in the manager.
370 See L{WorkerJobState}.
371 """
372 pass
373
374 pb.setUnjellyableForClass(WorkerJobState, ManagerJobState)
375