VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxShell/vboxshell.py@ 21331

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

Python shell: adding shell command, repeat count for runScript

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.9 KB
Line 
1#!/usr/bin/python
2#
3# Copyright (C) 2009 Sun Microsystems, Inc.
4#
5# This file is part of VirtualBox Open Source Edition (OSE), as
6# available from http://www.virtualbox.org. This file is free software;
7# you can redistribute it and/or modify it under the terms of the GNU
8# General Public License (GPL) as published by the Free Software
9# Foundation, in version 2 as it comes in the "COPYING" file of the
10# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
11# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
12#
13# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
14# Clara, CA 95054 USA or visit http://www.sun.com if you need
15# additional information or have any questions.
16#
17#
18#################################################################################
19# This program is a simple interactive shell for VirtualBox. You can query #
20# information and issue commands from a simple command line. #
21# #
22# It also provides you with examples on how to use VirtualBox's Python API. #
23# This shell is even somewhat documented and supports TAB-completion and #
24# history if you have Python readline installed. #
25# #
26# Enjoy. #
27################################################################################
28
29import os,sys
30import traceback
31import shlex
32
33# Simple implementation of IConsoleCallback, one can use it as skeleton
34# for custom implementations
35class GuestMonitor:
36 def __init__(self, mach):
37 self.mach = mach
38
39 def onMousePointerShapeChange(self, visible, alpha, xHot, yHot, width, height, shape):
40 print "%s: onMousePointerShapeChange: visible=%d" %(self.mach.name, visible)
41 def onMouseCapabilityChange(self, supportsAbsolute, needsHostCursor):
42 print "%s: onMouseCapabilityChange: needsHostCursor=%d" %(self.mach.name, needsHostCursor)
43
44 def onKeyboardLedsChange(self, numLock, capsLock, scrollLock):
45 print "%s: onKeyboardLedsChange capsLock=%d" %(self.mach.name, capsLock)
46
47 def onStateChange(self, state):
48 print "%s: onStateChange state=%d" %(self.mach.name, state)
49
50 def onAdditionsStateChange(self):
51 print "%s: onAdditionsStateChange" %(self.mach.name)
52
53 def onDVDDriveChange(self):
54 print "%s: onDVDDriveChange" %(self.mach.name)
55
56 def onFloppyDriveChange(self):
57 print "%s: onFloppyDriveChange" %(self.mach.name)
58
59 def onNetworkAdapterChange(self, adapter):
60 print "%s: onNetworkAdapterChange" %(self.mach.name)
61
62 def onSerialPortChange(self, port):
63 print "%s: onSerialPortChange" %(self.mach.name)
64
65 def onParallelPortChange(self, port):
66 print "%s: onParallelPortChange" %(self.mach.name)
67
68 def onStorageControllerChange(self):
69 print "%s: onStorageControllerChange" %(self.mach.name)
70
71 def onVRDPServerChange(self):
72 print "%s: onVRDPServerChange" %(self.mach.name)
73
74 def onUSBControllerChange(self):
75 print "%s: onUSBControllerChange" %(self.mach.name)
76
77 def onUSBDeviceStateChange(self, device, attached, error):
78 print "%s: onUSBDeviceStateChange" %(self.mach.name)
79
80 def onSharedFolderChange(self, scope):
81 print "%s: onSharedFolderChange" %(self.mach.name)
82
83 def onRuntimeError(self, fatal, id, message):
84 print "%s: onRuntimeError fatal=%d message=%s" %(self.mach.name, fatal, message)
85
86 def onCanShowWindow(self):
87 print "%s: onCanShowWindow" %(self.mach.name)
88 return True
89
90 def onShowWindow(self, winId):
91 print "%s: onShowWindow: %d" %(self.mach.name, winId)
92
93class VBoxMonitor:
94 def __init__(self, vbox):
95 self.vbox = vbox
96 pass
97
98 def onMachineStateChange(self, id, state):
99 print "onMachineStateChange: %s %d" %(id, state)
100
101 def onMachineDataChange(self,id):
102 print "onMachineDataChange: %s" %(id)
103
104 def onExtraDataCanChange(self, id, key, value):
105 print "onExtraDataCanChange: %s %s=>%s" %(id, key, value)
106 return True, ""
107
108 def onExtraDataChange(self, id, key, value):
109 print "onExtraDataChange: %s %s=>%s" %(id, key, value)
110
111 def onMediaRegistred(self, id, type, registred):
112 print "onMediaRegistred: %s" %(id)
113
114 def onMachineRegistred(self, id, registred):
115 print "onMachineRegistred: %s" %(id)
116
117 def onSessionStateChange(self, id, state):
118 print "onSessionStateChange: %s %d" %(id, state)
119
120 def onSnapshotTaken(self, mach, id):
121 print "onSnapshotTaken: %s %s" %(mach, id)
122
123 def onSnapshotDiscarded(self, mach, id):
124 print "onSnapshotDiscarded: %s %s" %(mach, id)
125
126 def onSnapshotChange(self, mach, id):
127 print "onSnapshotChange: %s %s" %(mach, id)
128
129 def onGuestPropertyChange(self, id, name, newValue, flags):
130 print "onGuestPropertyChange: %s: %s=%s" %(id, name, newValue)
131
132g_hasreadline = 1
133try:
134 import readline
135 import rlcompleter
136except:
137 g_hasreadline = 0
138
139
140if g_hasreadline:
141 class CompleterNG(rlcompleter.Completer):
142 def __init__(self, dic, ctx):
143 self.ctx = ctx
144 return rlcompleter.Completer.__init__(self,dic)
145
146 def complete(self, text, state):
147 """
148 taken from:
149 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
150 """
151 if text == "":
152 return ['\t',None][state]
153 else:
154 return rlcompleter.Completer.complete(self,text,state)
155
156 def global_matches(self, text):
157 """
158 Compute matches when text is a simple name.
159 Return a list of all names currently defined
160 in self.namespace that match.
161 """
162
163 matches = []
164 n = len(text)
165
166 for list in [ self.namespace ]:
167 for word in list:
168 if word[:n] == text:
169 matches.append(word)
170
171
172 try:
173 for m in getMachines(self.ctx):
174 # although it has autoconversion, we need to cast
175 # explicitly for subscripts to work
176 word = str(m.name)
177 if word[:n] == text:
178 matches.append(word)
179 word = str(m.id)
180 if word[0] == '{':
181 word = word[1:-1]
182 if word[:n] == text:
183 matches.append(word)
184 except Exception,e:
185 traceback.print_exc()
186 print e
187
188 return matches
189
190
191def autoCompletion(commands, ctx):
192 if not g_hasreadline:
193 return
194
195 comps = {}
196 for (k,v) in commands.items():
197 comps[k] = None
198 completer = CompleterNG(comps, ctx)
199 readline.set_completer(completer.complete)
200 readline.parse_and_bind("tab: complete")
201
202g_verbose = True
203
204def split_no_quotes(s):
205 return shlex.split(s)
206
207def createVm(ctx,name,kind,base):
208 mgr = ctx['mgr']
209 vb = ctx['vb']
210 mach = vb.createMachine(name, kind, base,
211 "00000000-0000-0000-0000-000000000000")
212 mach.saveSettings()
213 print "created machine with UUID",mach.id
214 vb.registerMachine(mach)
215
216def removeVm(ctx,mach):
217 mgr = ctx['mgr']
218 vb = ctx['vb']
219 id = mach.id
220 print "removing machine ",mach.name,"with UUID",id
221 session = ctx['global'].openMachineSession(id)
222 mach=session.machine
223 for d in mach.getHardDiskAttachments():
224 mach.detachHardDisk(d.controller, d.port, d.device)
225 ctx['global'].closeMachineSession(session)
226 mach = vb.unregisterMachine(id)
227 if mach:
228 mach.deleteSettings()
229
230def startVm(ctx,mach,type):
231 mgr = ctx['mgr']
232 vb = ctx['vb']
233 perf = ctx['perf']
234 session = mgr.getSessionObject(vb)
235 uuid = mach.id
236 progress = vb.openRemoteSession(session, uuid, type, "")
237 progress.waitForCompletion(-1)
238 rc = long(progress.resultCode)
239 #print "Completed:", progress.completed, "rc:",hex(rc&0xffffffff)
240 if rc == 0:
241 # we ignore exceptions to allow starting VM even if
242 # perf collector cannot be started
243 if perf:
244 try:
245 perf.setup(['*'], [mach], 10, 15)
246 except Exception,e:
247 print e
248 if g_verbose:
249 traceback.print_exc()
250 pass
251 # if session not opened, close doesn't make sense
252 session.close()
253 else:
254 # Not yet implemented error string query API for remote API
255 if not ctx['remote']:
256 print session.QueryErrorObject(rc)
257
258def getMachines(ctx):
259 return ctx['global'].getArray(ctx['vb'], 'machines')
260
261def asState(var):
262 if var:
263 return 'on'
264 else:
265 return 'off'
266
267def guestStats(ctx,mach):
268 if not ctx['perf']:
269 return
270 for metric in ctx['perf'].query(["*"], [mach]):
271 print metric['name'], metric['values_as_string']
272
273def guestExec(ctx, machine, console, cmds):
274 exec cmds
275
276def monitorGuest(ctx, machine, console, dur):
277 import time
278 cb = ctx['global'].createCallback('IConsoleCallback', GuestMonitor, machine)
279 console.registerCallback(cb)
280 if dur == -1:
281 # not infinity, but close enough
282 dur = 100000
283 try:
284 end = time.time() + dur
285 while time.time() < end:
286 ctx['global'].waitForEvents(500)
287 # We need to catch all exceptions here, otherwise callback will never be unregistered
288 except:
289 pass
290 console.unregisterCallback(cb)
291
292
293def monitorVbox(ctx, dur):
294 import time
295 vbox = ctx['vb']
296 cb = ctx['global'].createCallback('IVirtualBoxCallback', VBoxMonitor, vbox)
297 vbox.registerCallback(cb)
298 if dur == -1:
299 # not infinity, but close enough
300 dur = 100000
301 try:
302 end = time.time() + dur
303 while time.time() < end:
304 ctx['global'].waitForEvents(500)
305 # We need to catch all exceptions here, otherwise callback will never be unregistered
306 except:
307 if g_verbose:
308 traceback.print_exc()
309 vbox.unregisterCallback(cb)
310
311def cmdExistingVm(ctx,mach,cmd,args):
312 mgr=ctx['mgr']
313 vb=ctx['vb']
314 session = mgr.getSessionObject(vb)
315 uuid = mach.id
316 try:
317 progress = vb.openExistingSession(session, uuid)
318 except Exception,e:
319 print "Session to '%s' not open: %s" %(mach.name,e)
320 if g_verbose:
321 traceback.print_exc()
322 return
323 if session.state != ctx['ifaces'].SessionState_Open:
324 print "Session to '%s' in wrong state: %s" %(mach.name, session.state)
325 return
326 # unfortunately IGuest is suppressed, thus WebServices knows not about it
327 # this is an example how to handle local only functionality
328 if ctx['remote'] and cmd == 'stats2':
329 print 'Trying to use local only functionality, ignored'
330 return
331 console=session.console
332 ops={'pause' : lambda: console.pause(),
333 'resume': lambda: console.resume(),
334 'powerdown': lambda: console.powerDown().waitForCompletion(-1),
335 'powerbutton': lambda: console.powerButton(),
336 'stats': lambda: guestStats(ctx, mach),
337 'guest': lambda: guestExec(ctx, mach, console, args),
338 'monitorGuest': lambda: monitorGuest(ctx, mach, console, args),
339 'save' : lambda: console.saveState().waitForCompletion(-1)
340 }
341 try:
342 ops[cmd]()
343 except Exception, e:
344 print 'failed: ',e
345 if g_verbose:
346 traceback.print_exc()
347
348 session.close()
349
350# can cache known machines, if needed
351def machById(ctx,id):
352 mach = None
353 for m in getMachines(ctx):
354 if m.name == id:
355 mach = m
356 break
357 mid = str(m.id)
358 if mid[0] == '{':
359 mid = mid[1:-1]
360 if mid == id:
361 mach = m
362 break
363 return mach
364
365def argsToMach(ctx,args):
366 if len(args) < 2:
367 print "usage: %s [vmname|uuid]" %(args[0])
368 return None
369 id = args[1]
370 m = machById(ctx, id)
371 if m == None:
372 print "Machine '%s' is unknown, use list command to find available machines" %(id)
373 return m
374
375def helpCmd(ctx, args):
376 if len(args) == 1:
377 print "Help page:"
378 names = commands.keys()
379 names.sort()
380 for i in names:
381 print " ",i,":", commands[i][0]
382 else:
383 c = commands.get(args[1], None)
384 if c == None:
385 print "Command '%s' not known" %(args[1])
386 else:
387 print " ",args[1],":", c[0]
388 return 0
389
390def listCmd(ctx, args):
391 for m in getMachines(ctx):
392 print "Machine '%s' [%s], state=%s" %(m.name,m.id,m.sessionState)
393 return 0
394
395def infoCmd(ctx,args):
396 import time
397 if (len(args) < 2):
398 print "usage: info [vmname|uuid]"
399 return 0
400 mach = argsToMach(ctx,args)
401 if mach == None:
402 return 0
403 os = ctx['vb'].getGuestOSType(mach.OSTypeId)
404 print " One can use setvar <mach> <var> <value> to change variable, using name in []."
405 print " Name [name]: ",mach.name
406 print " ID [n/a]: ",mach.id
407 print " OS Type [n/a]: ",os.description
408 print " CPUs [CPUCount]: %d" %(mach.CPUCount)
409 print " RAM [memorySize]: %dM" %(mach.memorySize)
410 print " VRAM [VRAMSize]: %dM" %(mach.VRAMSize)
411 print " Monitors [monitorCount]: %d" %(mach.monitorCount)
412 print " Clipboard mode [clipboardMode]: %d" %(mach.clipboardMode)
413 print " Machine status [n/a]: " ,mach.sessionState
414 bios = mach.BIOSSettings
415 print " ACPI [BIOSSettings.ACPIEnabled]: %s" %(asState(bios.ACPIEnabled))
416 print " APIC [BIOSSettings.IOAPICEnabled]: %s" %(asState(bios.IOAPICEnabled))
417 print " PAE [PAEEnabled]: %s" %(asState(mach.PAEEnabled))
418 print " Hardware virtualization [HWVirtExEnabled]: ",asState(mach.HWVirtExEnabled)
419 print " VPID support [HWVirtExVPIDEnabled]: ",asState(mach.HWVirtExVPIDEnabled)
420 print " Hardware 3d acceleration[accelerate3DEnabled]: ",asState(mach.accelerate3DEnabled)
421 print " Nested paging [HWVirtExNestedPagingEnabled]: ",asState(mach.HWVirtExNestedPagingEnabled)
422 print " Last changed [n/a]: ",time.asctime(time.localtime(mach.lastStateChange/1000))
423
424 return 0
425
426def startCmd(ctx, args):
427 mach = argsToMach(ctx,args)
428 if mach == None:
429 return 0
430 if len(args) > 2:
431 type = args[2]
432 else:
433 type = "gui"
434 startVm(ctx, mach, type)
435 return 0
436
437def createCmd(ctx, args):
438 if (len(args) < 3 or len(args) > 4):
439 print "usage: create name ostype <basefolder>"
440 return 0
441 name = args[1]
442 oskind = args[2]
443 if len(args) == 4:
444 base = args[3]
445 else:
446 base = ''
447 try:
448 ctx['vb'].getGuestOSType(oskind)
449 except Exception, e:
450 print 'Unknown OS type:',oskind
451 return 0
452 createVm(ctx, name, oskind, base)
453 return 0
454
455def removeCmd(ctx, args):
456 mach = argsToMach(ctx,args)
457 if mach == None:
458 return 0
459 removeVm(ctx, mach)
460 return 0
461
462def pauseCmd(ctx, args):
463 mach = argsToMach(ctx,args)
464 if mach == None:
465 return 0
466 cmdExistingVm(ctx, mach, 'pause', '')
467 return 0
468
469def powerdownCmd(ctx, args):
470 mach = argsToMach(ctx,args)
471 if mach == None:
472 return 0
473 cmdExistingVm(ctx, mach, 'powerdown', '')
474 return 0
475
476def powerbuttonCmd(ctx, args):
477 mach = argsToMach(ctx,args)
478 if mach == None:
479 return 0
480 cmdExistingVm(ctx, mach, 'powerbutton', '')
481 return 0
482
483def resumeCmd(ctx, args):
484 mach = argsToMach(ctx,args)
485 if mach == None:
486 return 0
487 cmdExistingVm(ctx, mach, 'resume', '')
488 return 0
489
490def saveCmd(ctx, args):
491 mach = argsToMach(ctx,args)
492 if mach == None:
493 return 0
494 cmdExistingVm(ctx, mach, 'save', '')
495 return 0
496
497def statsCmd(ctx, args):
498 mach = argsToMach(ctx,args)
499 if mach == None:
500 return 0
501 cmdExistingVm(ctx, mach, 'stats', '')
502 return 0
503
504def guestCmd(ctx, args):
505 if (len(args) < 3):
506 print "usage: guest name commands"
507 return 0
508 mach = argsToMach(ctx,args)
509 if mach == None:
510 return 0
511 cmdExistingVm(ctx, mach, 'guest', ' '.join(args[2:]))
512 return 0
513
514def setvarCmd(ctx, args):
515 if (len(args) < 4):
516 print "usage: setvar [vmname|uuid] expr value"
517 return 0
518 mach = argsToMach(ctx,args)
519 if mach == None:
520 return 0
521 session = ctx['global'].openMachineSession(mach.id)
522 mach = session.machine
523 expr = 'mach.'+args[2]+' = '+args[3]
524 print "Executing",expr
525 try:
526 exec expr
527 except Exception, e:
528 print 'failed: ',e
529 if g_verbose:
530 traceback.print_exc()
531 mach.saveSettings()
532 session.close()
533 return 0
534
535def quitCmd(ctx, args):
536 return 1
537
538def aliasCmd(ctx, args):
539 if (len(args) == 3):
540 aliases[args[1]] = args[2]
541 return 0
542
543 for (k,v) in aliases.items():
544 print "'%s' is an alias for '%s'" %(k,v)
545 return 0
546
547def verboseCmd(ctx, args):
548 global g_verbose
549 g_verbose = not g_verbose
550 return 0
551
552def hostCmd(ctx, args):
553 host = ctx['vb'].host
554 cnt = host.processorCount
555 print "Processor count:",cnt
556 for i in range(0,cnt):
557 print "Processor #%d speed: %dMHz" %(i,host.getProcessorSpeed(i))
558
559 if ctx['perf']:
560 for metric in ctx['perf'].query(["*"], [host]):
561 print metric['name'], metric['values_as_string']
562
563 return 0
564
565def monitorGuestCmd(ctx, args):
566 if (len(args) < 2):
567 print "usage: monitorGuest name (duration)"
568 return 0
569 mach = argsToMach(ctx,args)
570 if mach == None:
571 return 0
572 dur = 5
573 if len(args) > 2:
574 dur = float(args[2])
575 cmdExistingVm(ctx, mach, 'monitorGuest', dur)
576 return 0
577
578def monitorVboxCmd(ctx, args):
579 if (len(args) > 2):
580 print "usage: monitorVbox (duration)"
581 return 0
582 dur = 5
583 if len(args) > 1:
584 dur = float(args[1])
585 monitorVbox(ctx, dur)
586 return 0
587
588def getAdapterType(ctx, type):
589 if (type == ctx['global'].constants.NetworkAdapterType_Am79C970A or
590 type == ctx['global'].constants.NetworkAdapterType_Am79C973):
591 return "pcnet"
592 elif (type == ctx['global'].constants.NetworkAdapterType_I82540EM or
593 type == ctx['global'].constants.NetworkAdapterType_I82545EM or
594 type == ctx['global'].constants.NetworkAdapterType_I82543GC):
595 return "e1000"
596 elif (type == ctx['global'].constants.NetworkAdapterType_Null):
597 return None
598 else:
599 raise Exception("Unknown adapter type: "+type)
600
601
602def portForwardCmd(ctx, args):
603 if (len(args) != 5):
604 print "usage: portForward <vm> <adapter> <hostPort> <guestPort>"
605 return 0
606 mach = argsToMach(ctx,args)
607 if mach == None:
608 return 0
609 adapterNum = int(args[2])
610 hostPort = int(args[3])
611 guestPort = int(args[4])
612 proto = "TCP"
613 session = ctx['global'].openMachineSession(mach.id)
614 mach = session.machine
615
616 adapter = mach.getNetworkAdapter(adapterNum)
617 adapterType = getAdapterType(ctx, adapter.adapterType)
618
619 profile_name = proto+"_"+str(hostPort)+"_"+str(guestPort)
620 config = "VBoxInternal/Devices/" + adapterType + "/"
621 config = config + str(adapter.slot) +"/LUN#0/Config/" + profile_name
622
623 mach.setExtraData(config + "/Protocol", proto)
624 mach.setExtraData(config + "/HostPort", str(hostPort))
625 mach.setExtraData(config + "/GuestPort", str(guestPort))
626
627 mach.saveSettings()
628 session.close()
629
630 return 0
631
632
633def showLogCmd(ctx, args):
634 if (len(args) < 2):
635 print "usage: showLog <vm> <num>"
636 return 0
637 mach = argsToMach(ctx,args)
638 if mach == None:
639 return 0
640
641 log = "VBox.log"
642 if (len(args) > 2):
643 log += "."+args[2]
644 fileName = os.path.join(mach.logFolder, log)
645
646 try:
647 lf = open(fileName, 'r')
648 except IOError,e:
649 print "cannot open: ",e
650 return 0
651
652 for line in lf:
653 print line,
654 lf.close()
655
656 return 0
657
658def evalCmd(ctx, args):
659 expr = ' '.join(args[1:])
660 try:
661 exec expr
662 except Exception, e:
663 print 'failed: ',e
664 if g_verbose:
665 traceback.print_exc()
666 return 0
667
668def reloadExtCmd(ctx, args):
669 # maybe will want more args smartness
670 checkUserExtensions(ctx, commands, ctx['vb'].homeFolder)
671 autoCompletion(commands, ctx)
672 return 0
673
674
675def runScriptCmd(ctx, args):
676 import time
677 if (len(args) < 2 or len (args) > 4):
678 print "usage: runScript <script> <times> <pause>"
679 return 0
680
681 if len (args) >= 3:
682 times = int(args[2])
683 if g_verbose:
684 print "repeating %d times" %(times)
685 else:
686 times = 1
687
688 if len (args) >= 4:
689 pause = int(args[3])
690 else:
691 pause = 0
692
693 try:
694 lf = open(args[1], 'r')
695 except IOError,e:
696 print "cannot open:",args[1], ":",e
697 return 0
698
699 script = []
700 try:
701 for line in lf:
702 script.append(line)
703
704 for i in range(times):
705 for line in script:
706 done = runCommand(ctx, line)
707 if done != 0: break
708 if g_verbose:
709 print "%d done" %(i)
710 if i != times - 1 and pause != 0:
711 time.sleep(pause)
712 except Exception,e:
713 print "error:",e
714 if g_verbose:
715 traceback.print_exc()
716 lf.close()
717 return 0
718
719
720def runShellCmd(ctx, args):
721 if len (args) < 2:
722 print "usage: shell <command>"
723 expr = ' '.join(args[1:])
724 try:
725 os.system(expr)
726 except Exception,e:
727 print "error:",e
728 if g_verbose:
729 traceback.print_exc()
730 return 0
731
732aliases = {'s':'start',
733 'i':'info',
734 'l':'list',
735 'h':'help',
736 'a':'alias',
737 'q':'quit', 'exit':'quit',
738 'v':'verbose'}
739
740commands = {'help':['Prints help information', helpCmd, 0],
741 'start':['Start virtual machine by name or uuid', startCmd, 0],
742 'create':['Create virtual machine', createCmd, 0],
743 'remove':['Remove virtual machine', removeCmd, 0],
744 'pause':['Pause virtual machine', pauseCmd, 0],
745 'resume':['Resume virtual machine', resumeCmd, 0],
746 'save':['Save execution state of virtual machine', saveCmd, 0],
747 'stats':['Stats for virtual machine', statsCmd, 0],
748 'powerdown':['Power down virtual machine', powerdownCmd, 0],
749 'powerbutton':['Effectively press power button', powerbuttonCmd, 0],
750 'list':['Shows known virtual machines', listCmd, 0],
751 'info':['Shows info on machine', infoCmd, 0],
752 'alias':['Control aliases', aliasCmd, 0],
753 'verbose':['Toggle verbosity', verboseCmd, 0],
754 'setvar':['Set VMs variable: setvar Fedora BIOSSettings.ACPIEnabled True', setvarCmd, 0],
755 'eval':['Evaluate arbitrary Python construction: eval \'for m in getMachines(ctx): print m.name,"has",m.memorySize,"M"\'', evalCmd, 0],
756 'quit':['Exits', quitCmd, 0],
757 'host':['Show host information', hostCmd, 0],
758 'guest':['Execute command for guest: guest Win32 \'console.mouse.putMouseEvent(20, 20, 0, 0)\'', guestCmd, 0],
759 'monitorGuest':['Monitor what happens with the guest for some time: monitorGuest Win32 10', monitorGuestCmd, 0],
760 'monitorVbox':['Monitor what happens with Virtual Box for some time: monitorVbox 10', monitorVboxCmd, 0],
761 'portForward':['Setup permanent port forwarding for a VM, takes adapter number host port and guest port: portForward Win32 0 8080 80', portForwardCmd, 0],
762 'showLog':['Show log file of the VM, : showLog Win32', showLogCmd, 0],
763 'reloadExt':['Reload custom extensions: reloadExt', reloadExtCmd, 0],
764 'runScript':['Run VBox script: runScript script.vbox <times>', runScriptCmd, 0],
765 'shell':['Execute system shell command: shell ls -l', runShellCmd, 0],
766 }
767
768def runCommand(ctx, cmd):
769 if len(cmd) == 0: return 0
770 args = split_no_quotes(cmd)
771 if len(args) == 0: return 0
772 c = args[0]
773 if aliases.get(c, None) != None:
774 c = aliases[c]
775 ci = commands.get(c,None)
776 if ci == None:
777 print "Unknown command: '%s', type 'help' for list of known commands" %(c)
778 return 0
779 return ci[1](ctx, args)
780
781#
782# To write your own custom commands to vboxshell, create
783# file ~/.VirtualBox/shellext.py with content like
784#
785# def runTestCmd(ctx, args):
786# print "Testy test", ctx['vb']
787# return 0
788#
789# commands = {
790# 'test': ['Test help', runTestCmd]
791# }
792# and issue reloadExt shell command.
793# This file also will be read automatically on startup.
794#
795def checkUserExtensions(ctx, cmds, folder):
796 name = os.path.join(folder, "shellext.py")
797 if not os.path.isfile(name):
798 return
799 d = {}
800 try:
801 execfile(name, d, d)
802 for (k,v) in d['commands'].items():
803 if g_verbose:
804 print "customize: adding \"%s\" - %s" %(k, v[0])
805 cmds[k] = [v[0], v[1], 1]
806 except:
807 print "Error loading user extensions:"
808 traceback.print_exc()
809
810def interpret(ctx):
811 vbox = ctx['vb']
812 print "Running VirtualBox version %s" %(vbox.version)
813 ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
814
815 checkUserExtensions(ctx, commands, vbox.homeFolder)
816
817 autoCompletion(commands, ctx)
818
819 # to allow to print actual host information, we collect info for
820 # last 150 secs maximum, (sample every 10 secs and keep up to 15 samples)
821 if ctx['perf']:
822 try:
823 ctx['perf'].setup(['*'], [vbox.host], 10, 15)
824 except:
825 pass
826
827 while True:
828 try:
829 cmd = raw_input("vbox> ")
830 done = runCommand(ctx, cmd)
831 if done != 0: break
832 except KeyboardInterrupt:
833 print '====== You can type quit or q to leave'
834 break
835 except EOFError:
836 break;
837 except Exception,e:
838 print e
839 if g_verbose:
840 traceback.print_exc()
841
842 try:
843 # There is no need to disable metric collection. This is just an example.
844 if ct['perf']:
845 ctx['perf'].disable(['*'], [vbox.host])
846 except:
847 pass
848
849def main(argv):
850 style = None
851 autopath = False
852 argv.pop(0)
853 while len(argv) > 0:
854 if argv[0] == "-w":
855 style = "WEBSERVICE"
856 if argv[0] == "-a":
857 autopath = True
858 argv.pop(0)
859
860 if autopath:
861 cwd = os.getcwd()
862 vpp = os.environ.get("VBOX_PROGRAM_PATH")
863 if vpp is None and (os.path.isfile(os.path.join(cwd, "VirtualBox")) or os.path.isfile(os.path.join(cwd, "VirtualBox.exe"))) :
864 vpp = cwd
865 print "Autodetected VBOX_PROGRAM_PATH as",vpp
866 os.environ["VBOX_PROGRAM_PATH"] = cwd
867 sys.path.append(os.path.join(vpp, "sdk", "installer"))
868
869 from vboxapi import VirtualBoxManager
870 g_virtualBoxManager = VirtualBoxManager(style, None)
871 ctx = {'global':g_virtualBoxManager,
872 'mgr':g_virtualBoxManager.mgr,
873 'vb':g_virtualBoxManager.vbox,
874 'ifaces':g_virtualBoxManager.constants,
875 'remote':g_virtualBoxManager.remote,
876 'type':g_virtualBoxManager.type
877 }
878 interpret(ctx)
879 g_virtualBoxManager.deinit()
880 del g_virtualBoxManager
881
882if __name__ == '__main__':
883 main(sys.argv)
Note: See TracBrowser for help on using the repository browser.

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