VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxShell/shellcommon.py@ 20149

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

Python: ship and install bindings with binary install on Linux

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