1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import os
22
23 from twisted.internet import defer
24 from zope.interface import implements
25
26 from flumotion.twisted.defer import defer_generator
27 from flumotion.admin.command import utils
28 from flumotion.common.planet import moods
29 from flumotion.common import errors, log, componentui, common
30 from flumotion.twisted import flavors
31
32 __all__ = ['commands']
33
34
40 return 'Command %r not found in the PATH.' % self.command
41
43 if os.sep in executable:
44 if os.access(os.path.abspath(executable), os.X_OK):
45 return os.path.abspath(executable)
46 elif os.getenv('PATH'):
47 for path in os.getenv('PATH').split(os.pathsep):
48 if os.access(os.path.join(path, executable), os.X_OK):
49 return os.path.join(path, executable)
50 raise CommandNotFoundException(executable)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
68 d = utils.get_component_uistate(model, avatarId)
69 yield d
70 uistate = d.value()
71 if uistate:
72 if uistate.hasKey(propname):
73 print uistate.get(propname)
74 else:
75 print ('Component %s in flow %s has no property called %s'
76 % (avatarId[1], avatarId[0], propname))
77 quit()
78 do_getprop = defer_generator(do_getprop)
79
81 d = utils.get_component_uistate(model, avatarId)
82 yield d
83 uistate = d.value()
84 if uistate:
85 for k in uistate.keys():
86 print k
87 quit()
88 do_listprops = defer_generator(do_listprops)
89
91 d = model.callRemote('getPlanetState')
92 yield d
93 planet = d.value()
94
95 for f in planet.get('flows'):
96 print 'flow: %s' % f.get('name')
97 for c in f.get('components'):
98 print ' %s' % c.get('name')
99
100 a = planet.get('atmosphere')
101 print 'atmosphere: %s' % a.get('name')
102 for c in a.get('components'):
103 print ' %s' % c.get('name')
104
105 quit()
106 do_showplanet = defer_generator(do_showplanet)
107
123 do_getmood = defer_generator(do_getmood)
124
126 def show_uistate(k, v, indent=0):
127 if isinstance(v, list):
128 show_uistate(k, '<list>', indent)
129 for x in v:
130 show_uistate(None, x, indent+4)
131 elif isinstance(v, dict):
132 show_uistate(k, '<dict>', indent)
133 keys = v.keys()
134 keys.sort()
135 for k in keys:
136 show_uistate(k, v[k], indent+4)
137 elif isinstance(v, componentui.AdminComponentUIState):
138 show_uistate(k, '<uistate>', indent)
139 keys = v.keys()
140 keys.sort()
141 for k in keys:
142 show_uistate(k, v.get(k), indent+4)
143 else:
144 print '%s%s%s' % (' '*indent, k and k+': ' or '', v)
145
146 d = model.callRemote('getPlanetState')
147 yield d
148 planet = d.value()
149 c = utils.find_component(planet, avatarId)
150 if c:
151 print 'Component state:'
152 keys = c.keys()
153 keys.sort()
154 for k in keys:
155 print ' %s: %r' % (k, c.get(k))
156 d = utils.get_component_uistate(model, avatarId, c, quiet=True)
157 yield d
158 try:
159 ui = d.value()
160 if ui:
161 print
162 show_uistate('UI state', ui)
163 except Exception, e:
164 print 'Error while retrieving UI state:', \
165 log.getExceptionMessage(e)
166 quit()
167 do_showcomponent = defer_generator(do_showcomponent)
168
171
173 def _readFile(filename):
174 try:
175 f = open(filename)
176 contents = f.read()
177 f.close()
178 return contents
179 except:
180 raise ParseException("Failed to read file %s" % (filename,))
181
182 def _do_parse_typed_args(spec, args):
183 accum = []
184 while spec:
185 argtype = spec.pop(0)
186 parsers = {'i': int, 's': str, 'b': common.strToBool,
187 'F': _readFile}
188 if argtype == ')':
189 return tuple(accum)
190 elif argtype == '(':
191 accum.append(_do_parse_typed_args(spec, args))
192 elif argtype == '}':
193 return dict(accum)
194 elif argtype == '{':
195 accum.append(_do_parse_typed_args(spec, args))
196 elif argtype not in parsers:
197 raise ParseException('Unknown argument type: %r'
198 % argtype)
199 else:
200 parser = parsers[argtype]
201 try:
202 arg = args.pop(0)
203 except IndexError:
204 raise ParseException('Missing argument of type %r'
205 % parser)
206 try:
207 accum.append(parser(arg))
208 except Exception, e:
209 raise ParseException('Failed to parse %s as %r: %s'
210 % (arg, parser, e))
211
212 spec = list(spec) + [')']
213 args = list(args)
214
215 try:
216 res = _do_parse_typed_args(spec, args)
217 except ParseException, e:
218 print e.args[0]
219 return None
220
221 if args:
222 print 'Left over arguments:', args
223 return None
224 else:
225 return res
226
227 -def do_invoke(model, quit, avatarId, methodName, *args):
259 do_invoke = defer_generator(do_invoke)
260
261 -def do_workerinvoke(model, quit, workerName, moduleName, methodName, *args):
262 if args:
263 args = _parse_typed_args(args[0], args[1:])
264 if args is None:
265 quit()
266 yield None
267
268 d = model.callRemote('workerCallRemote', workerName, 'runFunction',
269 moduleName, methodName, *args)
270 yield d
271
272 try:
273 v = d.value()
274 print "Invoke of %s on %s was successful." % (methodName, workerName)
275 print v
276 except errors.NoMethodError:
277 print "No method '%s' on component '%s'" % (methodName, workerName)
278 except Exception, e:
279 raise
280
281 quit()
282 do_workerinvoke = defer_generator(do_workerinvoke)
283
304 do_managerinvoke = defer_generator(do_managerinvoke)
305
307 print 'Loading configuration from file: %s' % confFile
308
309 f = open(confFile, 'r')
310 configurationXML = f.read()
311 f.close()
312
313 d = model.callRemote('loadConfiguration', configurationXML,
314 saveAs=saveAs)
315 yield d
316 d.value()
317 print 'Configuration loaded successfully.'
318 if saveAs:
319 print 'Additionally, the configuration XML was saved on the manager.'
320
321 quit()
322 do_loadconfiguration = defer_generator(do_loadconfiguration)
323
332 do_showworkers = defer_generator(do_showworkers)
333
339
340 - def stateSet(self, object, key, value):
343
344
345
347 """
348 @type action: a tuple of (actionName, remoteCall, moods, checkMoodFunc)
349 """
350 d = model.callRemote('getPlanetState')
351 yield d
352 planet = d.value()
353 components = []
354 if avatarPath[0] == 'flow':
355 flows = planet.get('flows')
356 flow_to_act = None
357 for f in flows:
358 if avatarPath[1] == f.get('name'):
359 flow_to_act = f
360 if flow_to_act == None:
361 print "The flow %s is not found." % avatarPath[1]
362 quit()
363 else:
364 components = flow_to_act.get('components')
365 elif avatarPath[0] == 'atmosphere':
366 components = planet.get('atmosphere').get('components')
367 elif avatarPath[0] == 'root':
368 flows = planet.get('flows')
369 for f in flows:
370 components = components + f.get('components')
371 components = components + planet.get('atmosphere').get('components')
372 else:
373 c = utils.find_component(planet, avatarPath[1:])
374 if c:
375 components.append(c)
376
377
378 if len(components) > 0:
379 def actionComponent(c):
380 if action[3](moods[c.get('mood')]):
381 return model.callRemote(action[1], c)
382 else:
383 print "Cannot %s component /%s/%s, it is in mood: %s." % (
384 action[0],
385 c.get("parent").get("name"), c.get("name"),
386 moods[c.get("mood")].name)
387 return None
388 dl = []
389 for comp in components:
390 actD = actionComponent(comp)
391
392 if actD:
393 dl.append(actD)
394 if action[2]:
395
396 dl.append(MoodListener(action[2], comp))
397 d = defer.DeferredList(dl)
398 yield d
399 d.value()
400 if avatarPath[0] == 'flow':
401 print "Components in flow now completed action %s." % action[0]
402 elif avatarPath[0] == 'atmosphere':
403 print "Components in atmosphere now completed action %s." % (
404 action[0],)
405 elif avatarPath[0] == 'root':
406 print "Components in / now completed action %s." % action[0]
407 else:
408 print "Component now completed action %s." % action[0]
409 quit()
410 do_avatar_action = defer_generator(do_avatar_action)
411
412 -def do_stop(model, quit, avatarPath):
413 return do_avatar_action(model, quit, avatarPath, ('stop', 'componentStop',
414 (moods.sleeping,), moods.can_stop))
415
417 return do_avatar_action(model, quit, avatarPath, ('start', 'componentStart',
418 (moods.happy, moods.sad), moods.can_start))
419
421 return do_avatar_action(model, quit, avatarPath, ('delete',
422 'deleteComponent', None, lambda m: not moods.can_stop(m)))
423
424 commands = (('getprop',
425 'gets a property on a component',
426 (('component-path', utils.avatarId),
427 ('property-name', str)),
428 do_getprop),
429 ('listprops',
430 'lists the properties a component has',
431 (('component-path', utils.avatarId),
432 ),
433 do_listprops),
434 ('showplanet',
435 'shows the flows, atmosphere, and components in the planet',
436 (),
437 do_showplanet),
438 ('getmood',
439 'gets the mood of a component',
440 (('component-path', utils.avatarId),
441 ),
442 do_getmood),
443 ('showcomponent',
444 'shows everything we know about a component',
445 (('component-path', utils.avatarId),
446 ),
447 do_showcomponent),
448 ('showworkers',
449 'shows all the workers that are logged into the manager',
450 (),
451 do_showworkers),
452 ('invoke',
453 'invoke a component method',
454 (('component-path', utils.avatarId),
455 ('method-name', str),
456 ('args', str, None, True)),
457 do_invoke),
458 ('workerinvoke',
459 'invoke a function on a worker',
460 (('worker-name', str),
461 ('module-name', str),
462 ('method-name', str),
463 ('args', str, None, True)),
464 do_workerinvoke),
465 ('managerinvoke',
466 'invoke a function on a manager',
467 (('method-name', str),
468 ('args', str, None, True)),
469 do_managerinvoke),
470 ('loadconfiguration',
471 'load configuration into the manager',
472 (('conf-file', str),
473 ('save-as', str, None),
474 ),
475 do_loadconfiguration),
476 ('stop',
477 'stops a component, flow or all flows',
478 (('path', utils.avatarPath),
479 ),
480 do_stop),
481 ('start',
482 'starts a componment, all components in a flow or all flows',
483 (('path', utils.avatarPath),
484 ),
485 do_start),
486 ('delete',
487 'deletes a component, all components in a flow or all flows',
488 (('path', utils.avatarPath),
489 ),
490 do_delete)
491 )
492