VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/python/sample/shellcommon.py@ 16909

Last change on this file since 16909 was 16903, checked in by vboxsync, 16 years ago

Python: imporved error reporting in XPCOM, shell updates, docs

  • Property svn:eol-style set to native
File size: 14.3 KB
Line 
1import traceback
2import sys
3import pdb
4
5class PerfCollector:
6 """ This class provides a wrapper over IPerformanceCollector in order to
7 get more 'pythonic' interface.
8
9 To begin collection of metrics use setup() method.
10
11 To get collected data use query() method.
12
13 It is possible to disable metric collection without changing collection
14 parameters with disable() method. The enable() method resumes metric
15 collection.
16 """
17
18 def __init__(self, vb):
19 """ Initializes the instance.
20
21 Pass an instance of IVirtualBox as parameter.
22 """
23 self.collector = vb.performanceCollector
24
25 def setup(self, names, objects, period, nsamples):
26 """ Discards all previously collected values for the specified
27 metrics, sets the period of collection and the number of retained
28 samples, enables collection.
29 """
30 self.collector.setupMetrics(names, objects, period, nsamples)
31
32 def enable(self, names, objects):
33 """ Resumes metric collection for the specified metrics.
34 """
35 self.collector.enableMetrics(names, objects)
36
37 def disable(self, names, objects):
38 """ Suspends metric collection for the specified metrics.
39 """
40 self.collector.disableMetrics(names, objects)
41
42 def query(self, names, objects):
43 """ Retrieves collected metric values as well as some auxiliary
44 information. Returns an array of dictionaries, one dictionary per
45 metric. Each dictionary contains the following entries:
46 'name': metric name
47 'object': managed object this metric associated with
48 'unit': unit of measurement
49 'scale': divide 'values' by this number to get float numbers
50 'values': collected data
51 'values_as_string': pre-processed values ready for 'print' statement
52 """
53 (values, names_out, objects_out, units, scales, sequence_numbers,
54 indices, lengths) = self.collector.queryMetricsData(names, objects)
55 out = []
56 for i in xrange(0, len(names_out)):
57 scale = int(scales[i])
58 if scale != 1:
59 fmt = '%.2f%s'
60 else:
61 fmt = '%d %s'
62 out.append({
63 'name':str(names_out[i]),
64 'object':str(objects_out[i]),
65 'unit':str(units[i]),
66 'scale':scale,
67 'values':[int(values[j]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))],
68 'values_as_string':'['+', '.join([fmt % (int(values[j])/scale, units[i]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))])+']'
69 })
70 return out
71
72g_hasreadline = 1
73try:
74 import readline
75 import rlcompleter
76except:
77 g_hasreadline = 0
78
79
80if g_hasreadline:
81 class CompleterNG(rlcompleter.Completer):
82 def __init__(self, dic, ctx):
83 self.ctx = ctx
84 return rlcompleter.Completer.__init__(self,dic)
85
86 def complete(self, text, state):
87 """
88 taken from:
89 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
90 """
91 if text == "":
92 return ['\t',None][state]
93 else:
94 return rlcompleter.Completer.complete(self,text,state)
95
96 def global_matches(self, text):
97 """
98 Compute matches when text is a simple name.
99 Return a list of all names currently defined
100 in self.namespace that match.
101 """
102
103 matches = []
104 n = len(text)
105
106 for list in [ self.namespace ]:
107 for word in list:
108 if word[:n] == text:
109 matches.append(word)
110
111
112 try:
113 for m in getMachines(self.ctx):
114 # although it has autoconversion, we need to cast
115 # explicitly for subscripts to work
116 word = str(m.name)
117 if word[:n] == text:
118 matches.append(word)
119 word = str(m.id)
120 if word[0] == '{':
121 word = word[1:-1]
122 if word[:n] == text:
123 matches.append(word)
124 except Exception,e:
125 traceback.print_exc()
126 print e
127
128 return matches
129
130
131def autoCompletion(commands, ctx):
132 if not g_hasreadline:
133 return
134
135 comps = {}
136 for (k,v) in commands.items():
137 comps[k] = None
138 completer = CompleterNG(comps, ctx)
139 readline.set_completer(completer.complete)
140 readline.parse_and_bind("tab: complete")
141
142g_verbose = True
143
144def split_no_quotes(s):
145 return s.split()
146
147def createVm(ctx,name,kind,base):
148 mgr = ctx['mgr']
149 vb = ctx['vb']
150 session = mgr.getSessionObject(vb)
151 mach = vb.createMachine(name, kind, base,
152 "00000000-0000-0000-0000-000000000000")
153 mach.saveSettings()
154 print "created machine with UUID",mach.id
155 vb.registerMachine(mach)
156
157def removeVm(ctx,mach):
158 mgr = ctx['mgr']
159 vb = ctx['vb']
160 print "removing machine ",mach.name,"with UUID",mach.id
161 mach = vb.unregisterMachine(mach.id)
162 if mach:
163 mach.deleteSettings()
164
165def startVm(ctx,mach,type):
166 mgr = ctx['mgr']
167 vb = ctx['vb']
168 perf = ctx['perf']
169 session = mgr.getSessionObject(vb)
170 uuid = mach.id
171 progress = vb.openRemoteSession(session, uuid, type, "")
172 progress.waitForCompletion(-1)
173 completed = progress.completed
174 rc = progress.resultCode
175 print "Completed:", completed, "rc:",hex(rc&0xffffffff)
176 if int(rc) == 0:
177 # we ignore exceptions to allow starting VM even if
178 # perf collector cannot be started
179 try:
180 perf.setup(['*'], [mach], 10, 15)
181 except:
182 print e
183 if g_verbose:
184 traceback.print_exc()
185 pass
186 # if session not opened, close doesn't make sense
187 session.close()
188 else:
189 # Not yet implemented error string query API for remote API
190 if not ctx['remote']:
191 print session.QueryErrorObject(rc)
192
193def getMachines(ctx):
194 return ctx['vb'].getMachines2()
195
196def asState(var):
197 if var:
198 return 'on'
199 else:
200 return 'off'
201
202def guestStats(ctx,mach):
203 for metric in ctx['perf'].query(["*"], [mach]):
204 print metric['name'], metric['values_as_string']
205
206def cmdExistingVm(ctx,mach,cmd):
207 mgr=ctx['mgr']
208 vb=ctx['vb']
209 session = mgr.getSessionObject(vb)
210 uuid = mach.id
211 try:
212 progress = vb.openExistingSession(session, uuid)
213 except Exception,e:
214 print "Session to '%s' not open: %s" %(mach.name,e)
215 if g_verbose:
216 traceback.print_exc()
217 return
218 if session.state != ctx['ifaces'].SessionState.Open:
219 print "Session to '%s' in wrong state: %s" %(mach.name, session.state)
220 return
221 # unfortunately IGuest is suppressed, thus WebServices knows not about it
222 # this is an example how to handle local only functionality
223 if ctx['remote'] and cmd == 'stats2':
224 print 'Trying to use local only functionality, ignored'
225 return
226 console=session.console
227 ops={'pause' : lambda: console.pause(),
228 'resume': lambda: console.resume(),
229 'powerdown': lambda: console.powerDown(),
230 'stats': lambda: guestStats(ctx, mach),
231 }
232 ops[cmd]()
233 session.close()
234
235# can cache known machines, if needed
236def machById(ctx,id):
237 mach = None
238 for m in getMachines(ctx):
239 if m.name == id:
240 mach = m
241 break
242 mid = str(m.id)
243 if mid[0] == '{':
244 mid = mid[1:-1]
245 if mid == id:
246 mach = m
247 break
248 return mach
249
250def argsToMach(ctx,args):
251 if len(args) < 2:
252 print "usage: %s [vmname|uuid]" %(args[0])
253 return None
254 id = args[1]
255 m = machById(ctx, id)
256 if m == None:
257 print "Machine '%s' is unknown, use list command to find available machines" %(id)
258 return m
259
260def helpCmd(ctx, args):
261 if len(args) == 1:
262 print "Help page:"
263 for i in commands:
264 print " ",i,":", commands[i][0]
265 else:
266 c = commands.get(args[1], None)
267 if c == None:
268 print "Command '%s' not known" %(args[1])
269 else:
270 print " ",args[1],":", c[0]
271 return 0
272
273def listCmd(ctx, args):
274 for m in getMachines(ctx):
275 print "Machine '%s' [%s], state=%s" %(m.name,m.id,m.sessionState)
276 return 0
277
278def infoCmd(ctx,args):
279 if (len(args) < 2):
280 print "usage: info [vmname|uuid]"
281 return 0
282 mach = argsToMach(ctx,args)
283 if mach == None:
284 return 0
285 os = ctx['vb'].getGuestOSType(mach.OSTypeId)
286 print " Name: ",mach.name
287 print " ID: ",mach.id
288 print " OS Type: ",os.description
289 print " RAM: %dM" %(mach.memorySize)
290 print " VRAM: %dM" %(mach.VRAMSize)
291 print " Clipboard mode: %d" %(mach.clipboardMode)
292 print " Machine status: " ,mach.sessionState
293 bios = mach.BIOSSettings
294 print " BIOS ACPI: ",bios.ACPIEnabled
295 print " PAE: ",mach.PAEEnabled
296 print " Hardware virtualization: ",asState(mach.HWVirtExEnabled)
297 print " Nested paging: ",asState(mach.HWVirtExNestedPagingEnabled)
298 print " Last changed: ",mach.lastStateChange
299
300 return 0
301
302def startCmd(ctx, args):
303 mach = argsToMach(ctx,args)
304 if mach == None:
305 return 0
306 if len(args) > 2:
307 type = args[2]
308 else:
309 type = "gui"
310 startVm(ctx, mach, type)
311 return 0
312
313def createCmd(ctx, args):
314 if (len(args) < 3 or len(args) > 4):
315 print "usage: create name ostype <basefolder>"
316 return 0
317 name = args[1]
318 oskind = args[2]
319 if len(args) == 4:
320 base = args[3]
321 else:
322 base = ''
323 try:
324 ctx['vb'].getGuestOSType(oskind)
325 except Exception, e:
326 print 'Unknown OS type:',oskind
327 return 0
328 createVm(ctx, name, oskind, base)
329 return 0
330
331def removeCmd(ctx, args):
332 mach = argsToMach(ctx,args)
333 if mach == None:
334 return 0
335 removeVm(ctx, mach)
336 return 0
337
338def pauseCmd(ctx, args):
339 mach = argsToMach(ctx,args)
340 if mach == None:
341 return 0
342 cmdExistingVm(ctx, mach, 'pause')
343 return 0
344
345def powerdownCmd(ctx, args):
346 mach = argsToMach(ctx,args)
347 if mach == None:
348 return 0
349 cmdExistingVm(ctx, mach, 'powerdown')
350 return 0
351
352def resumeCmd(ctx, args):
353 mach = argsToMach(ctx,args)
354 if mach == None:
355 return 0
356 cmdExistingVm(ctx, mach, 'resume')
357 return 0
358
359def statsCmd(ctx, args):
360 mach = argsToMach(ctx,args)
361 if mach == None:
362 return 0
363 cmdExistingVm(ctx, mach, 'stats')
364 return 0
365
366def setvarCmd(ctx, args):
367 if (len(args) < 4):
368 print "usage: setvar [vmname|uuid] expr value"
369 return 0
370 mach = argsToMach(ctx,args)
371 if mach == None:
372 return 0
373 vbox = ctx['vb']
374 session = ctx['mgr'].getSessionObject(vbox)
375 vbox.openSession(session, mach.id)
376 mach = session.machine
377 expr = 'mach.'+args[2]+' = '+args[3]
378 print "Executing",expr
379 try:
380 exec expr
381 except Exception, e:
382 print 'failed: ',e
383 if g_verbose:
384 traceback.print_exc()
385 mach.saveSettings()
386 session.close()
387 return 0
388
389def quitCmd(ctx, args):
390 return 1
391
392def aliasesCmd(ctx, args):
393 for (k,v) in aliases.items():
394 print "'%s' is an alias for '%s'" %(k,v)
395 return 0
396
397def verboseCmd(ctx, args):
398 global g_verbose
399 g_verbose = not g_verbose
400 return 0
401
402def hostCmd(ctx, args):
403 host = ctx['vb'].host
404 cnt = host.processorCount
405 print "Processor count:",cnt
406 for i in range(0,cnt):
407 print "Processor #%d speed: %dMHz" %(i,host.getProcessorSpeed(i))
408
409 for metric in ctx['perf'].query(["*"], [host]):
410 print metric['name'], metric['values_as_string']
411
412 return 0
413
414
415def evalCmd(ctx, args):
416 expr = ' '.join(args[1:])
417 try:
418 exec expr
419 except Exception, e:
420 print 'failed: ',e
421 if g_verbose:
422 traceback.print_exc()
423 return 0
424
425aliases = {'s':'start',
426 'i':'info',
427 'l':'list',
428 'h':'help',
429 'a':'aliases',
430 'q':'quit', 'exit':'quit',
431 'v':'verbose'}
432
433commands = {'help':['Prints help information', helpCmd],
434 'start':['Start virtual machine by name or uuid', startCmd],
435 'create':['Create virtual machine', createCmd],
436 'remove':['Remove virtual machine', removeCmd],
437 'pause':['Pause virtual machine', pauseCmd],
438 'resume':['Resume virtual machine', resumeCmd],
439 'stats':['Stats for virtual machine', statsCmd],
440 'powerdown':['Power down virtual machine', powerdownCmd],
441 'list':['Shows known virtual machines', listCmd],
442 'info':['Shows info on machine', infoCmd],
443 'aliases':['Shows aliases', aliasesCmd],
444 'verbose':['Toggle verbosity', verboseCmd],
445 'setvar':['Set VMs variable: setvar Fedora BIOSSettings.ACPIEnabled True', setvarCmd],
446 'eval':['Evaluate arbitrary Python construction: eval for m in getMachines(ctx): print m.name,"has",m.memorySize,"M"', evalCmd],
447 'quit':['Exits', quitCmd],
448 'host':['Show host information', hostCmd]}
449
450def runCommand(ctx, cmd):
451 if len(cmd) == 0: return 0
452 args = split_no_quotes(cmd)
453 if len(args) == 0: return 0
454 c = args[0]
455 if aliases.get(c, None) != None:
456 c = aliases[c]
457 ci = commands.get(c,None)
458 if ci == None:
459 print "Unknown command: '%s', type 'help' for list of known commands" %(c)
460 return 0
461 return ci[1](ctx, args)
462
463
464def interpret(ctx):
465 vbox = ctx['vb']
466 print "Running VirtualBox version %s" %(vbox.version)
467
468 ctx['perf'] = PerfCollector(vbox)
469
470 autoCompletion(commands, ctx)
471
472 # to allow to print actual host information, we collect info for
473 # last 150 secs maximum, (sample every 10 secs and keep up to 15 samples)
474 try:
475 ctx['perf'].setup(['*'], [vbox.host], 10, 15)
476 except:
477 pass
478
479 while True:
480 try:
481 cmd = raw_input("vbox> ")
482 done = runCommand(ctx, cmd)
483 if done != 0: break
484 except KeyboardInterrupt:
485 print '====== You can type quit or q to leave'
486 break
487 except EOFError:
488 break;
489 except Exception,e:
490 print e
491 if g_verbose:
492 traceback.print_exc()
493
494 try:
495 # There is no need to disable metric collection. This is just an example.
496 ctx['perf'].disable(['*'], [vbox.host])
497 except:
498 pass
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette