1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """
23 flumotion.launch.parse: A parsing library for flumotion-launch syntax.
24 """
25
26 import copy
27 import sys
28
29 from flumotion.common import log, common, dag, registry
30 from flumotion.manager import config
31
32 __all__ = ['parse_args']
33 __version__ = "$Rev: 7162 $"
34
35
37 sys.stderr.write(x + '\n')
38 raise SystemExit(1)
39
40
42 __slots__ = ('type', 'name', 'properties', 'plugs', 'source',
43 'clock_priority', 'config_entry', '_reg')
44
63
65 self.config_entry = config.ConfigEntryComponent(
66 self.name,
67 None,
68 self.type,
69 None,
70 self.properties,
71 self.plugs,
72 None,
73 [(None, feedId) for feedId in self.source],
74 None,
75 None,
76 None)
77
80
81
83
85 self._names = {}
86 self._last_component = None
87 self.components = {}
88 assert not self
89
91 i = self._names.get(type, 0)
92 self._names[type] = i + 1
93 return '%s%d' % (type, i)
94
95 - def add(self, type):
98
101
104
106 assert self._last_component
107 return self._last_component
108
110 return self.components.keys()
111
129
134
136 return self.components[key]
137
139 self.components[key] = val
140
142 return key in self.components
143
145 return len(self.components)
146
149
150
152
153 - def __init__(self, get_last_component):
154
155
156 self.links = []
157 self._tmp = None
158 self.get_last_component = get_last_component
159
161 return bool(self._tmp)
162
163 - def link(self, feedercompname=None, feeder=None, eatercompname=None,
164 eater=None):
165 if feedercompname:
166 assert not self._tmp
167 self._tmp = [feedercompname, feeder, eatercompname, eater]
168 elif feeder:
169 err('how did i get here?')
170 elif eatercompname:
171 if not self._tmp:
172 err('Invalid grammar: trying to link, but no feeder component')
173 self._tmp[2] = eatercompname
174 if eater:
175 self._tmp[3] = eater
176 elif eater:
177 if not self._tmp:
178 err('Invalid grammar: trying to link, but no feeder component')
179 self._tmp[3] = eater
180 else:
181
182 if not self._tmp:
183 self._tmp = [self.get_last_component(), None, None, None]
184 else:
185 if not self._tmp[0]:
186 self._tmp[0] = self.get_last_component()
187
188 if self._tmp and self._tmp[0] and self._tmp[2]:
189 self.links.append(self._tmp)
190 self._tmp = None
191
193 if self._tmp:
194 err('Invalid grammar: uncompleted link from %s.%s' % self._tmp[:2])
195 else:
196 return self.links
197
199 for link in self.get_links():
200 assert link[0] and link[2]
201 if not link[0] in component_types:
202 err('Invalid grammar: no feeder component %s to link from' % (
203 link[0], ))
204 if not link[2] in component_types:
205 err('Invalid grammar: no eater component %s to link to' % (
206 link[2], ))
207
208 reg = registry.getRegistry()
209 for link in self.get_links():
210 compname = link[0]
211 comptype = component_types[compname]
212 compreg = reg.getComponent(comptype)
213 if link[1]:
214 if not link[1] in compreg.getFeeders():
215 err('Component %s has no feeder named %s' % (
216 compname, link[1]))
217
218 else:
219 if not compreg.getFeeders():
220 err('Component %s has no feeders' % compname)
221 link[1] = compreg.getFeeders()[0]
222
223 for link in self.get_links():
224 compname = link[2]
225 comptype = component_types[compname]
226 compreg = reg.getComponent(comptype)
227 eaters = compreg.getEaters()
228 if link[3]:
229 if not link[3] in [x.getName() for x in eaters]:
230 err('Component %s has no eater named %s' % (
231 compname, link[3]))
232
233 else:
234 if not eaters:
235 err('Component %s has no eaters' % compname)
236 link[3] = eaters[0].getName()
237
238 feeders = dict([(name, []) for name in component_types])
239 for link in self.get_links():
240 feeders[link[2]].append('%s:%s' % (link[0], link[1]))
241 return feeders
242
245
247 for link in self.links:
248 print '%s:%s => %s:%s' % tuple(link)
249
250
252 plugargs = arg.split(',')
253 plug = plugargs.pop(0)[1:]
254 return plug, [parse_prop(arg) for arg in plugargs]
255
256
258 prop = arg[:arg.index('=')]
259 val = arg[arg.index('=')+1:]
260 if not prop or not val:
261 err('Invalid property setting: %s' % arg)
262 return prop, val
263
264
266
267 def assert_in_component(msg):
268 if linker.pending() or not components:
269 err('Invalid grammar: %s' % msg)
270
271 if arg == '!':
272 if not components:
273 err('Invalid grammar: `!\' without feeder component')
274 linker.link()
275
276 elif arg[0] == '/':
277 assert_in_component('Plug %s does not follow a component' % arg)
278 plug, props = parse_plug(arg)
279 components.add_plug_to_current(plug, props)
280
281 elif arg.find('=') != -1:
282 assert_in_component('Property %s does not follow a component' % arg)
283 prop, val = parse_prop(arg)
284 components.add_prop_to_current(prop, val)
285
286 elif arg.find('.') != -1:
287 t = arg.split('.')
288 if len(t) != 2:
289 err('Invalid grammar: bad eater/feeder specification: %s' % arg)
290 t = [z or None for z in t]
291 if linker.pending():
292 linker.link(eatercompname=t[0], eater=t[1])
293 elif components:
294 linker.link(feedercompname=t[0] or components.last(), feeder=t[1])
295 else:
296 err('Invalid grammar: trying to link from feeder %s but '
297 'no feeder component' % arg)
298
299 else:
300 components.add(arg)
301 if linker.pending():
302 linker.link(eatercompname=components.last())
303
304
306 """Parse flumotion-launch arguments.
307
308 Parse flumotion-launch arguments, returning a list of component
309 configs.
310
311 A component config is what we will pass to a component when we
312 create it. It is a dict:
313
314 - 'name': component name
315 - 'type': component type
316 - 'properties': dict of property name => property value
317 - 'feed': list of [feeder name,...]
318 - 'source': list of [feeder name,...], (optional)
319 - 'clock-master': clock master or None
320 - 'plugs': dict of socket name => plug config
321 """
322
323 if not args:
324 err('Usage: flumotion-launch COMPONENT [! COMPONENT]...')
325
326 components = ComponentStore()
327
328 linker = Linker(components.last)
329
330 args.reverse()
331 while args:
332 parse_arg(args.pop().strip(), components, linker)
333
334 feeders = linker.resolve_links(dict([(name, components[name].type)
335 for name in components]))
336
337 for compname in feeders:
338 components[compname].source = feeders[compname]
339 components.complete_and_verify_configs()
340
341 return components.sorted_configs(linker.get_sort_order())
342