1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """
23 manager-side objects to handle worker clients
24 """
25
26 from twisted.internet import defer
27
28
29 from flumotion.manager import base
30 from flumotion.common import errors, interfaces, log, registry
31 from flumotion.common import config, worker, common
32 from flumotion.twisted.defer import defer_generator_method
33
35 """
36 I am an avatar created for a worker.
37 A reference to me is given when logging in and requesting a worker avatar.
38 I live in the manager.
39
40 @ivar feedServerPort: TCP port the feed server is listening on
41 @type feedServerPort: int
42 """
43 logCategory = 'worker-avatar'
44
45 _portSet = None
46 feedServerPort = None
47
50
73 attached = defer_generator_method(attached)
74
81
83 """
84 Reserve the given number of ports on the worker.
85
86 @param numPorts: how many ports to reserve
87 @type numPorts: int
88 """
89 return self._portSet.reservePorts(numPorts)
90
92 """
93 Release the given list of ports on the worker.
94
95 @param ports: list of ports to release
96 @type ports: list of int
97 """
98 self._portSet.releasePorts(ports)
99
101 """
102 Create a component of the given type with the given nice level.
103
104 @param avatarId: avatarId the component should use to log in
105 @type avatarId: str
106 @param type: type of the component to create
107 @type type: str
108 @param nice: the nice level to create the component at
109 @type nice: int
110
111 @returns: a deferred that will give the avatarId the component
112 will use to log in to the manager
113 """
114 self.debug('creating %s (%s) on worker %s with nice level %d' % (
115 avatarId, type, self.avatarId, nice))
116 defs = registry.getRegistry().getComponent(type)
117 try:
118 entry = defs.getEntryByType('component')
119
120 moduleName = defs.getSource()
121 methodName = entry.getFunction()
122 except KeyError:
123 self.warning('no "component" entry in registry of type %s, %s',
124 type, 'falling back to createComponent')
125 moduleName = defs.getSource()
126 methodName = "createComponent"
127
128 self.debug('call remote create')
129 return self.mindCallRemote('create', avatarId, type, moduleName,
130 methodName, nice)
131
133 """
134 Get a list of components that the worker is running.
135
136 @returns: a deferred that will give the avatarIds running on the
137 worker
138 """
139 self.debug('getting component list from worker %s' %
140 self.avatarId)
141 return self.mindCallRemote('getComponents')
142
143
145 """
146 Called by the worker to tell the manager to add a given message to
147 the given component.
148
149 Useful in cases where the component can't report messages itself,
150 for example because it crashed.
151
152 @param avatarId: avatarId of the component the message is about
153 @type message: L{flumotion.common.messages.Message}
154 """
155 self.debug('received message from component %s' % avatarId)
156 self.vishnu.componentAddMessage(avatarId, message)
157
159 """
160 I interface between the Manager and worker clients.
161 For each worker client I create an L{WorkerAvatar} to handle requests.
162 I live in the manager.
163 """
164
165 logCategory = "workerheaven"
166 avatarClass = WorkerAvatar
167
172
173
191
193 """
194 Notify the heaven that the given worker has logged out.
195
196 @type workerAvatar: L{WorkerAvatar}
197 """
198 workerName = workerAvatar.getName()
199 try:
200 self.state.remove('names', workerName)
201 for state in list(self.state.get('workers')):
202 if state.get('name') == workerName:
203 self.state.remove('workers', state)
204 except ValueError:
205 self.warning('worker %s was never registered in the heaven' %
206 workerName)
207