VirtualBox

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

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

Python shell: fixes, shell extension dirs support

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.4 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
32import time
33
34# Simple implementation of IConsoleCallback, one can use it as skeleton
35# for custom implementations
36class GuestMonitor:
37 def __init__(self, mach):
38 self.mach = mach
39
40 def onMousePointerShapeChange(self, visible, alpha, xHot, yHot, width, height, shape):
41 print "%s: onMousePointerShapeChange: visible=%d" %(self.mach.name, visible)
42 def onMouseCapabilityChange(self, supportsAbsolute, needsHostCursor):
43 print "%s: onMouseCapabilityChange: needsHostCursor=%d" %(self.mach.name, needsHostCursor)
44
45 def onKeyboardLedsChange(self, numLock, capsLock, scrollLock):
46 print "%s: onKeyboardLedsChange capsLock=%d" %(self.mach.name, capsLock)
47
48 def onStateChange(self, state):
49 print "%s: onStateChange state=%d" %(self.mach.name, state)
50
51 def onAdditionsStateChange(self):
52 print "%s: onAdditionsStateChange" %(self.mach.name)
53
54 def onDVDDriveChange(self):
55 print "%s: onDVDDriveChange" %(self.mach.name)
56
57 def onFloppyDriveChange(self):
58 print "%s: onFloppyDriveChange" %(self.mach.name)
59
60 def onNetworkAdapterChange(self, adapter):
61 print "%s: onNetworkAdapterChange" %(self.mach.name)
62
63 def onSerialPortChange(self, port):
64 print "%s: onSerialPortChange" %(self.mach.name)
65
66 def onParallelPortChange(self, port):
67 print "%s: onParallelPortChange" %(self.mach.name)
68
69 def onStorageControllerChange(self):
70 print "%s: onStorageControllerChange" %(self.mach.name)
71
72 def onVRDPServerChange(self):
73 print "%s: onVRDPServerChange" %(self.mach.name)
74
75 def onUSBControllerChange(self):
76 print "%s: onUSBControllerChange" %(self.mach.name)
77
78 def onUSBDeviceStateChange(self, device, attached, error):
79 print "%s: onUSBDeviceStateChange" %(self.mach.name)
80
81 def onSharedFolderChange(self, scope):
82 print "%s: onSharedFolderChange" %(self.mach.name)
83
84 def onRuntimeError(self, fatal, id, message):
85 print "%s: onRuntimeError fatal=%d message=%s" %(self.mach.name, fatal, message)
86
87 def onCanShowWindow(self):
88 print "%s: onCanShowWindow" %(self.mach.name)
89 return True
90
91 def onShowWindow(self, winId):
92 print "%s: onShowWindow: %d" %(self.mach.name, winId)
93
94class VBoxMonitor:
95 def __init__(self, vbox):
96 self.vbox = vbox
97 pass
98
99 def onMachineStateChange(self, id, state):
100 print "onMachineStateChange: %s %d" %(id, state)
101
102 def onMachineDataChange(self,id):
103 print "onMachineDataChange: %s" %(id)
104
105 def onExtraDataCanChange(self, id, key, value):
106 print "onExtraDataCanChange: %s %s=>%s" %(id, key, value)
107 return True, ""
108
109 def onExtraDataChange(self, id, key, value):
110 print "onExtraDataChange: %s %s=>%s" %(id, key, value)
111
112 def onMediaRegistred(self, id, type, registred):
113 print "onMediaRegistred: %s" %(id)
114
115 def onMachineRegistred(self, id, registred):
116 print "onMachineRegistred: %s" %(id)
117
118 def onSessionStateChange(self, id, state):
119 print "onSessionStateChange: %s %d" %(id, state)
120
121 def onSnapshotTaken(self, mach, id):
122 print "onSnapshotTaken: %s %s" %(mach, id)
123
124 def onSnapshotDiscarded(self, mach, id):
125 print "onSnapshotDiscarded: %s %s" %(mach, id)
126
127 def onSnapshotChange(self, mach, id):
128 print "onSnapshotChange: %s %s" %(mach, id)
129
130 def onGuestPropertyChange(self, id, name, newValue, flags):
131 print "onGuestPropertyChange: %s: %s=%s" %(id, name, newValue)
132
133g_hasreadline = 1
134try:
135 import readline
136 import rlcompleter
137except:
138 g_hasreadline = 0
139
140
141if g_hasreadline:
142 class CompleterNG(rlcompleter.Completer):
143 def __init__(self, dic, ctx):
144 self.ctx = ctx
145 return rlcompleter.Completer.__init__(self,dic)
146
147 def complete(self, text, state):
148 """
149 taken from:
150 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
151 """
152 if text == "":
153 return ['\t',None][state]
154 else:
155 return rlcompleter.Completer.complete(self,text,state)
156
157 def global_matches(self, text):
158 """
159 Compute matches when text is a simple name.
160 Return a list of all names currently defined
161 in self.namespace that match.
162 """
163
164 matches = []
165 n = len(text)
166
167 for list in [ self.namespace ]:
168 for word in list:
169 if word[:n] == text:
170 matches.append(word)
171
172
173 try:
174 for m in getMachines(self.ctx):
175 # although it has autoconversion, we need to cast
176 # explicitly for subscripts to work
177 word = str(m.name)
178 if word[:n] == text:
179 matches.append(word)
180 word = str(m.id)
181 if word[0] == '{':
182 word = word[1:-1]
183 if word[:n] == text:
184 matches.append(word)
185 except Exception,e:
186 traceback.print_exc()
187 print e
188
189 return matches
190
191
192def autoCompletion(commands, ctx):
193 if not g_hasreadline:
194 return
195
196 comps = {}
197 for (k,v) in commands.items():
198 comps[k] = None
199 completer = CompleterNG(comps, ctx)
200 readline.set_completer(completer.complete)
201 readline.parse_and_bind("tab: complete")
202
203g_verbose = True
204
205def split_no_quotes(s):
206 return shlex.split(s)
207
208def progressBar(ctx,p,wait=1000):
209 try:
210 while not p.completed:
211 print "%d %%\r" %(p.percent),
212 sys.stdout.flush()
213 p.waitForCompletion(wait)
214 except KeyboardInterrupt:
215 print "Interrupted."
216
217def createVm(ctx,name,kind,base):
218 mgr = ctx['mgr']
219 vb = ctx['vb']
220 mach = vb.createMachine(name, kind, base, "")
221 mach.saveSettings()
222 print "created machine with UUID",mach.id
223 vb.registerMachine(mach)
224 # update cache
225 getMachines(ctx, True)
226
227def removeVm(ctx,mach):
228 mgr = ctx['mgr']
229 vb = ctx['vb']
230 id = mach.id
231 print "removing machine ",mach.name,"with UUID",id
232 session = ctx['global'].openMachineSession(id)
233 try:
234 mach = session.machine
235 for d in ctx['global'].getArray(mach, 'hardDiskAttachments'):
236 mach.detachHardDisk(d.controller, d.port, d.device)
237 except:
238 traceback.print_exc()
239 mach.saveSettings()
240 ctx['global'].closeMachineSession(session)
241 mach = vb.unregisterMachine(id)
242 if mach:
243 mach.deleteSettings()
244 # update cache
245 getMachines(ctx, True)
246
247def startVm(ctx,mach,type):
248 mgr = ctx['mgr']
249 vb = ctx['vb']
250 perf = ctx['perf']
251 session = mgr.getSessionObject(vb)
252 uuid = mach.id
253 progress = vb.openRemoteSession(session, uuid, type, "")
254 progressBar(ctx, progress, 100)
255 completed = progress.completed
256 rc = int(progress.resultCode)
257 print "Completed:", completed, "rc:",hex(rc&0xffffffff)
258 if rc == 0:
259 # we ignore exceptions to allow starting VM even if
260 # perf collector cannot be started
261 if perf:
262 try:
263 perf.setup(['*'], [mach], 10, 15)
264 except Exception,e:
265 print e
266 if g_verbose:
267 traceback.print_exc()
268 pass
269 # if session not opened, close doesn't make sense
270 session.close()
271 else:
272 # Not yet implemented error string query API for remote API
273 if not ctx['remote']:
274 print session.QueryErrorObject(rc)
275
276def getMachines(ctx, invalidate = False):
277 if ctx['vb'] is not None:
278 if ctx['_machlist'] is None or invalidate:
279 ctx['_machlist'] = ctx['global'].getArray(ctx['vb'], 'machines')
280 return ctx['_machlist']
281 else:
282 return []
283
284def asState(var):
285 if var:
286 return 'on'
287 else:
288 return 'off'
289
290def guestStats(ctx,mach):
291 if not ctx['perf']:
292 return
293 for metric in ctx['perf'].query(["*"], [mach]):
294 print metric['name'], metric['values_as_string']
295
296def guestExec(ctx, machine, console, cmds):
297 exec cmds
298
299def monitorGuest(ctx, machine, console, dur):
300 cb = ctx['global'].createCallback('IConsoleCallback', GuestMonitor, machine)
301 console.registerCallback(cb)
302 if dur == -1:
303 # not infinity, but close enough
304 dur = 100000
305 try:
306 end = time.time() + dur
307 while time.time() < end:
308 ctx['global'].waitForEvents(500)
309 # We need to catch all exceptions here, otherwise callback will never be unregistered
310 except:
311 pass
312 console.unregisterCallback(cb)
313
314
315def monitorVbox(ctx, dur):
316 vbox = ctx['vb']
317 cb = ctx['global'].createCallback('IVirtualBoxCallback', VBoxMonitor, vbox)
318 vbox.registerCallback(cb)
319 if dur == -1:
320 # not infinity, but close enough
321 dur = 100000
322 try:
323 end = time.time() + dur
324 while time.time() < end:
325 ctx['global'].waitForEvents(500)
326 # We need to catch all exceptions here, otherwise callback will never be unregistered
327 except:
328 if g_verbose:
329 traceback.print_exc()
330 vbox.unregisterCallback(cb)
331
332def cmdExistingVm(ctx,mach,cmd,args):
333 mgr=ctx['mgr']
334 vb=ctx['vb']
335 session = mgr.getSessionObject(vb)
336 uuid = mach.id
337 try:
338 progress = vb.openExistingSession(session, uuid)
339 except Exception,e:
340 print "Session to '%s' not open: %s" %(mach.name,e)
341 if g_verbose:
342 traceback.print_exc()
343 return
344 if session.state != ctx['ifaces'].SessionState_Open:
345 print "Session to '%s' in wrong state: %s" %(mach.name, session.state)
346 return
347 # unfortunately IGuest is suppressed, thus WebServices knows not about it
348 # this is an example how to handle local only functionality
349 if ctx['remote'] and cmd == 'stats2':
350 print 'Trying to use local only functionality, ignored'
351 return
352 console=session.console
353 ops={'pause': lambda: console.pause(),
354 'resume': lambda: console.resume(),
355 'powerdown': lambda: console.powerDown(),
356 'powerbutton': lambda: console.powerButton(),
357 'stats': lambda: guestStats(ctx, mach),
358 'guest': lambda: guestExec(ctx, mach, console, args),
359 'monitorGuest': lambda: monitorGuest(ctx, mach, console, args),
360 'save': lambda: progressBar(ctx,console.saveState())
361 }
362 try:
363 ops[cmd]()
364 except Exception, e:
365 print 'failed: ',e
366 if g_verbose:
367 traceback.print_exc()
368
369 session.close()
370
371def machById(ctx,id):
372 mach = None
373 for m in getMachines(ctx):
374 if m.name == id:
375 mach = m
376 break
377 mid = str(m.id)
378 if mid[0] == '{':
379 mid = mid[1:-1]
380 if mid == id:
381 mach = m
382 break
383 return mach
384
385def argsToMach(ctx,args):
386 if len(args) < 2:
387 print "usage: %s [vmname|uuid]" %(args[0])
388 return None
389 id = args[1]
390 m = machById(ctx, id)
391 if m == None:
392 print "Machine '%s' is unknown, use list command to find available machines" %(id)
393 return m
394
395def helpSingleCmd(cmd,h,sp):
396 if sp != 0:
397 spec = " [ext from "+sp+"]"
398 else:
399 spec = ""
400 print " %s: %s%s" %(cmd,h,spec)
401
402def helpCmd(ctx, args):
403 if len(args) == 1:
404 print "Help page:"
405 names = commands.keys()
406 names.sort()
407 for i in names:
408 helpSingleCmd(i, commands[i][0], commands[i][2])
409 else:
410 cmd = args[1]
411 c = commands.get(cmd)
412 if c == None:
413 print "Command '%s' not known" %(cmd)
414 else:
415 helpSingleCmd(cmd, c[0], c[2])
416 return 0
417
418def listCmd(ctx, args):
419 for m in getMachines(ctx, True):
420 print "Machine '%s' [%s], state=%s" %(m.name,m.id,m.sessionState)
421 return 0
422
423def getControllerType(type):
424 if type == 0:
425 return "Null"
426 elif type == 1:
427 return "LsiLogic"
428 elif type == 2:
429 return "BusLogic"
430 elif type == 3:
431 return "IntelAhci"
432 elif type == 4:
433 return "PIIX3"
434 elif type == 5:
435 return "PIIX4"
436 elif type == 6:
437 return "ICH6"
438 else:
439 return "Unknown"
440
441def infoCmd(ctx,args):
442 if (len(args) < 2):
443 print "usage: info [vmname|uuid]"
444 return 0
445 mach = argsToMach(ctx,args)
446 if mach == None:
447 return 0
448 os = ctx['vb'].getGuestOSType(mach.OSTypeId)
449 print " One can use setvar <mach> <var> <value> to change variable, using name in []."
450 print " Name [name]: %s" %(mach.name)
451 print " ID [n/a]: %s" %(mach.id)
452 print " OS Type [n/a]: %s" %(os.description)
453 print
454 print " CPUs [CPUCount]: %d" %(mach.CPUCount)
455 print " RAM [memorySize]: %dM" %(mach.memorySize)
456 print " VRAM [VRAMSize]: %dM" %(mach.VRAMSize)
457 print " Monitors [monitorCount]: %d" %(mach.monitorCount)
458 print
459 print " Clipboard mode [clipboardMode]: %d" %(mach.clipboardMode)
460 print " Machine status [n/a]: %d" % (mach.sessionState)
461 print
462 bios = mach.BIOSSettings
463 print " ACPI [BIOSSettings.ACPIEnabled]: %s" %(asState(bios.ACPIEnabled))
464 print " APIC [BIOSSettings.IOAPICEnabled]: %s" %(asState(bios.IOAPICEnabled))
465 print " PAE [PAEEnabled]: %s" %(asState(int(mach.PAEEnabled)))
466 print " Hardware virtualization [HWVirtExEnabled]: " + asState(mach.HWVirtExEnabled)
467 print " VPID support [HWVirtExVPIDEnabled]: " + asState(mach.HWVirtExVPIDEnabled)
468 print " Hardware 3d acceleration[accelerate3DEnabled]: " + asState(mach.accelerate3DEnabled)
469 print " Nested paging [HWVirtExNestedPagingEnabled]: " + asState(mach.HWVirtExNestedPagingEnabled)
470 print " Last changed [n/a]: " + time.asctime(time.localtime(long(mach.lastStateChange)/1000))
471 print " VRDP server [VRDPServer.enabled]: %s" %(asState(mach.VRDPServer.enabled))
472
473 controllers = ctx['global'].getArray(mach, 'storageControllers')
474 if controllers:
475 print
476 print " Controllers:"
477 for controller in controllers:
478 print " %s %s bus: %d" % (controller.name, getControllerType(controller.controllerType), controller.bus)
479
480 disks = ctx['global'].getArray(mach, 'hardDiskAttachments')
481 if disks:
482 print
483 print " Hard disk(s):"
484 for disk in disks:
485 print " Controller: %s port: %d device: %d:" % (disk.controller, disk.port, disk.device)
486 hd = disk.hardDisk
487 print " id: %s" %(hd.id)
488 print " location: %s" %(hd.location)
489 print " name: %s" %(hd.name)
490 print " format: %s" %(hd.format)
491 print
492
493 dvd = mach.DVDDrive
494 if dvd.getHostDrive():
495 hdvd = dvd.getHostDrive()
496 print " DVD:"
497 print " Host disk: %s" %(hdvd.name)
498 print
499
500 if dvd.getImage():
501 vdvd = dvd.getImage()
502 print " DVD:"
503 print " Image at: %s" %(vdvd.location)
504 print " Size: %s" %(vdvd.size)
505 print
506
507 floppy = mach.floppyDrive
508 if floppy.getHostDrive():
509 hfloppy = floppy.getHostDrive()
510 print " Floppy:"
511 print " Host disk: %s" %(hfloppy.name)
512 print
513
514 if floppy.getImage():
515 vfloppy = floppy.getImage()
516 print " Floppy:"
517 print " Image at: %s" %(vfloppy.location)
518 print " Size: %s" %(vfloppy.size)
519 print
520
521 return 0
522
523def startCmd(ctx, args):
524 mach = argsToMach(ctx,args)
525 if mach == None:
526 return 0
527 if len(args) > 2:
528 type = args[2]
529 else:
530 type = "gui"
531 startVm(ctx, mach, type)
532 return 0
533
534def createCmd(ctx, args):
535 if (len(args) < 3 or len(args) > 4):
536 print "usage: create name ostype <basefolder>"
537 return 0
538 name = args[1]
539 oskind = args[2]
540 if len(args) == 4:
541 base = args[3]
542 else:
543 base = ''
544 try:
545 ctx['vb'].getGuestOSType(oskind)
546 except Exception, e:
547 print 'Unknown OS type:',oskind
548 return 0
549 createVm(ctx, name, oskind, base)
550 return 0
551
552def removeCmd(ctx, args):
553 mach = argsToMach(ctx,args)
554 if mach == None:
555 return 0
556 removeVm(ctx, mach)
557 return 0
558
559def pauseCmd(ctx, args):
560 mach = argsToMach(ctx,args)
561 if mach == None:
562 return 0
563 cmdExistingVm(ctx, mach, 'pause', '')
564 return 0
565
566def powerdownCmd(ctx, args):
567 mach = argsToMach(ctx,args)
568 if mach == None:
569 return 0
570 cmdExistingVm(ctx, mach, 'powerdown', '')
571 return 0
572
573def powerbuttonCmd(ctx, args):
574 mach = argsToMach(ctx,args)
575 if mach == None:
576 return 0
577 cmdExistingVm(ctx, mach, 'powerbutton', '')
578 return 0
579
580def resumeCmd(ctx, args):
581 mach = argsToMach(ctx,args)
582 if mach == None:
583 return 0
584 cmdExistingVm(ctx, mach, 'resume', '')
585 return 0
586
587def saveCmd(ctx, args):
588 mach = argsToMach(ctx,args)
589 if mach == None:
590 return 0
591 cmdExistingVm(ctx, mach, 'save', '')
592 return 0
593
594def statsCmd(ctx, args):
595 mach = argsToMach(ctx,args)
596 if mach == None:
597 return 0
598 cmdExistingVm(ctx, mach, 'stats', '')
599 return 0
600
601def guestCmd(ctx, args):
602 if (len(args) < 3):
603 print "usage: guest name commands"
604 return 0
605 mach = argsToMach(ctx,args)
606 if mach == None:
607 return 0
608 cmdExistingVm(ctx, mach, 'guest', ' '.join(args[2:]))
609 return 0
610
611def setvarCmd(ctx, args):
612 if (len(args) < 4):
613 print "usage: setvar [vmname|uuid] expr value"
614 return 0
615 mach = argsToMach(ctx,args)
616 if mach == None:
617 return 0
618 session = ctx['global'].openMachineSession(mach.id)
619 mach = session.machine
620 expr = 'mach.'+args[2]+' = '+args[3]
621 print "Executing",expr
622 try:
623 exec expr
624 except Exception, e:
625 print 'failed: ',e
626 if g_verbose:
627 traceback.print_exc()
628 mach.saveSettings()
629 session.close()
630 return 0
631
632def quitCmd(ctx, args):
633 return 1
634
635def aliasCmd(ctx, args):
636 if (len(args) == 3):
637 aliases[args[1]] = args[2]
638 return 0
639
640 for (k,v) in aliases.items():
641 print "'%s' is an alias for '%s'" %(k,v)
642 return 0
643
644def verboseCmd(ctx, args):
645 global g_verbose
646 g_verbose = not g_verbose
647 return 0
648
649def getUSBStateString(state):
650 if state == 0:
651 return "NotSupported"
652 elif state == 1:
653 return "Unavailable"
654 elif state == 2:
655 return "Busy"
656 elif state == 3:
657 return "Available"
658 elif state == 4:
659 return "Held"
660 elif state == 5:
661 return "Captured"
662 else:
663 return "Unknown"
664
665def hostCmd(ctx, args):
666 host = ctx['vb'].host
667 cnt = host.processorCount
668 print "Processor count:",cnt
669 for i in range(0,cnt):
670 print "Processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i))
671
672 print "RAM: %dM (free %dM)" %(host.memorySize, host.memoryAvailable)
673 print "OS: %s (%s)" %(host.operatingSystem, host.OSVersion)
674 if host.Acceleration3DAvailable:
675 print "3D acceleration available"
676 else:
677 print "3D acceleration NOT available"
678
679 print "Network interfaces:"
680 for ni in ctx['global'].getArray(host, 'networkInterfaces'):
681 print " %s (%s)" %(ni.name, ni.IPAddress)
682
683 print "DVD drives:"
684 for dd in ctx['global'].getArray(host, 'DVDDrives'):
685 print " %s - %s" %(dd.name, dd.description)
686
687 print "USB devices:"
688 for ud in ctx['global'].getArray(host, 'USBDevices'):
689 print " %s (vendorId=%d productId=%d serial=%s) %s" %(ud.product, ud.vendorId, ud.productId, ud.serialNumber, getUSBStateString(ud.state))
690
691 if ctx['perf']:
692 for metric in ctx['perf'].query(["*"], [host]):
693 print metric['name'], metric['values_as_string']
694
695 return 0
696
697def monitorGuestCmd(ctx, args):
698 if (len(args) < 2):
699 print "usage: monitorGuest name (duration)"
700 return 0
701 mach = argsToMach(ctx,args)
702 if mach == None:
703 return 0
704 dur = 5
705 if len(args) > 2:
706 dur = float(args[2])
707 cmdExistingVm(ctx, mach, 'monitorGuest', dur)
708 return 0
709
710def monitorVboxCmd(ctx, args):
711 if (len(args) > 2):
712 print "usage: monitorVbox (duration)"
713 return 0
714 dur = 5
715 if len(args) > 1:
716 dur = float(args[1])
717 monitorVbox(ctx, dur)
718 return 0
719
720def getAdapterType(ctx, type):
721 if (type == ctx['global'].constants.NetworkAdapterType_Am79C970A or
722 type == ctx['global'].constants.NetworkAdapterType_Am79C973):
723 return "pcnet"
724 elif (type == ctx['global'].constants.NetworkAdapterType_I82540EM or
725 type == ctx['global'].constants.NetworkAdapterType_I82545EM or
726 type == ctx['global'].constants.NetworkAdapterType_I82543GC):
727 return "e1000"
728 elif (type == ctx['global'].constants.NetworkAdapterType_Null):
729 return None
730 else:
731 raise Exception("Unknown adapter type: "+type)
732
733
734def portForwardCmd(ctx, args):
735 if (len(args) != 5):
736 print "usage: portForward <vm> <adapter> <hostPort> <guestPort>"
737 return 0
738 mach = argsToMach(ctx,args)
739 if mach == None:
740 return 0
741 adapterNum = int(args[2])
742 hostPort = int(args[3])
743 guestPort = int(args[4])
744 proto = "TCP"
745 session = ctx['global'].openMachineSession(mach.id)
746 mach = session.machine
747
748 adapter = mach.getNetworkAdapter(adapterNum)
749 adapterType = getAdapterType(ctx, adapter.adapterType)
750
751 profile_name = proto+"_"+str(hostPort)+"_"+str(guestPort)
752 config = "VBoxInternal/Devices/" + adapterType + "/"
753 config = config + str(adapter.slot) +"/LUN#0/Config/" + profile_name
754
755 mach.setExtraData(config + "/Protocol", proto)
756 mach.setExtraData(config + "/HostPort", str(hostPort))
757 mach.setExtraData(config + "/GuestPort", str(guestPort))
758
759 mach.saveSettings()
760 session.close()
761
762 return 0
763
764
765def showLogCmd(ctx, args):
766 if (len(args) < 2):
767 print "usage: showLog <vm> <num>"
768 return 0
769 mach = argsToMach(ctx,args)
770 if mach == None:
771 return 0
772
773 log = "VBox.log"
774 if (len(args) > 2):
775 log += "."+args[2]
776 fileName = os.path.join(mach.logFolder, log)
777
778 try:
779 lf = open(fileName, 'r')
780 except IOError,e:
781 print "cannot open: ",e
782 return 0
783
784 for line in lf:
785 print line,
786 lf.close()
787
788 return 0
789
790def evalCmd(ctx, args):
791 expr = ' '.join(args[1:])
792 try:
793 exec expr
794 except Exception, e:
795 print 'failed: ',e
796 if g_verbose:
797 traceback.print_exc()
798 return 0
799
800def reloadExtCmd(ctx, args):
801 # maybe will want more args smartness
802 checkUserExtensions(ctx, commands, ctx['vb'].homeFolder)
803 autoCompletion(commands, ctx)
804 return 0
805
806
807def runScriptCmd(ctx, args):
808 if (len(args) != 2):
809 print "usage: runScript <script>"
810 return 0
811 try:
812 lf = open(args[1], 'r')
813 except IOError,e:
814 print "cannot open:",args[1], ":",e
815 return 0
816
817 try:
818 for line in lf:
819 done = runCommand(ctx, line)
820 if done != 0: break
821 except Exception,e:
822 print "error:",e
823 if g_verbose:
824 traceback.print_exc()
825 lf.close()
826 return 0
827
828def sleepCmd(ctx, args):
829 if (len(args) != 2):
830 print "usage: sleep <secs>"
831 return 0
832
833 try:
834 time.sleep(float(args[1]))
835 except:
836 # to allow sleep interrupt
837 pass
838 return 0
839
840
841def shellCmd(ctx, args):
842 if (len(args) < 2):
843 print "usage: shell <commands>"
844 return 0
845 cmd = ' '.join(args[1:])
846 try:
847 os.system(cmd)
848 except KeyboardInterrupt:
849 # to allow shell command interruption
850 pass
851 return 0
852
853
854def connectCmd(ctx, args):
855 if (len(args) > 4):
856 print "usage: connect [url] [username] [passwd]"
857 return 0
858
859 if ctx['vb'] is not None:
860 print "Already connected, disconnect first..."
861 return 0
862
863 if (len(args) > 1):
864 url = args[1]
865 else:
866 url = None
867
868 if (len(args) > 2):
869 user = args[2]
870 else:
871 user = ""
872
873 if (len(args) > 3):
874 passwd = args[3]
875 else:
876 passwd = ""
877
878 vbox = ctx['global'].platform.connect(url, user, passwd)
879 ctx['vb'] = vbox
880 print "Running VirtualBox version %s" %(vbox.version)
881 ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
882 return 0
883
884def disconnectCmd(ctx, args):
885 if (len(args) != 1):
886 print "usage: disconnect"
887 return 0
888
889 if ctx['vb'] is None:
890 print "Not connected yet."
891 return 0
892
893 try:
894 ctx['global'].platform.disconnect()
895 except:
896 ctx['vb'] = None
897 raise
898
899 ctx['vb'] = None
900 return 0
901
902def exportVMCmd(ctx, args):
903 import sys
904
905 if len(args) < 3:
906 print "usage: exportVm <machine> <path> <format> <license>"
907 return 0
908 mach = ctx['machById'](args[1])
909 if mach is None:
910 return 0
911 path = args[2]
912 if (len(args) > 3):
913 format = args[3]
914 else:
915 format = "ovf-1.0"
916 if (len(args) > 4):
917 license = args[4]
918 else:
919 license = "GPL"
920
921 app = ctx['vb'].createAppliance()
922 desc = mach.export(app)
923 desc.addDescription(ctx['global'].constants.VirtualSystemDescriptionType_License, license, "")
924 p = app.write(format, path)
925 progressBar(ctx, p)
926 print "Exported to %s in format %s" %(path, format)
927 return 0
928
929aliases = {'s':'start',
930 'i':'info',
931 'l':'list',
932 'h':'help',
933 'a':'alias',
934 'q':'quit', 'exit':'quit',
935 'v':'verbose'}
936
937commands = {'help':['Prints help information', helpCmd, 0],
938 'start':['Start virtual machine by name or uuid', startCmd, 0],
939 'create':['Create virtual machine', createCmd, 0],
940 'remove':['Remove virtual machine', removeCmd, 0],
941 'pause':['Pause virtual machine', pauseCmd, 0],
942 'resume':['Resume virtual machine', resumeCmd, 0],
943 'save':['Save execution state of virtual machine', saveCmd, 0],
944 'stats':['Stats for virtual machine', statsCmd, 0],
945 'powerdown':['Power down virtual machine', powerdownCmd, 0],
946 'powerbutton':['Effectively press power button', powerbuttonCmd, 0],
947 'list':['Shows known virtual machines', listCmd, 0],
948 'info':['Shows info on machine', infoCmd, 0],
949 'alias':['Control aliases', aliasCmd, 0],
950 'verbose':['Toggle verbosity', verboseCmd, 0],
951 'setvar':['Set VMs variable: setvar Fedora BIOSSettings.ACPIEnabled True', setvarCmd, 0],
952 'eval':['Evaluate arbitrary Python construction: eval \'for m in getMachines(ctx): print m.name,"has",m.memorySize,"M"\'', evalCmd, 0],
953 'quit':['Exits', quitCmd, 0],
954 'host':['Show host information', hostCmd, 0],
955 'guest':['Execute command for guest: guest Win32 \'console.mouse.putMouseEvent(20, 20, 0, 0)\'', guestCmd, 0],
956 'monitorGuest':['Monitor what happens with the guest for some time: monitorGuest Win32 10', monitorGuestCmd, 0],
957 'monitorVbox':['Monitor what happens with Virtual Box for some time: monitorVbox 10', monitorVboxCmd, 0],
958 'portForward':['Setup permanent port forwarding for a VM, takes adapter number host port and guest port: portForward Win32 0 8080 80', portForwardCmd, 0],
959 'showLog':['Show log file of the VM, : showLog Win32', showLogCmd, 0],
960 'reloadExt':['Reload custom extensions: reloadExt', reloadExtCmd, 0],
961 'runScript':['Run VBox script: runScript script.vbox', runScriptCmd, 0],
962 'sleep':['Sleep for specified number of seconds: sleep 3.14159', sleepCmd, 0],
963 'shell':['Execute external shell command: shell "ls /etc/rc*"', shellCmd, 0],
964 'exportVm':['Export VM in OVF format: export Win /tmp/win.ovf', exportVMCmd, 0]
965 }
966
967def runCommandArgs(ctx, args):
968 c = args[0]
969 if aliases.get(c, None) != None:
970 c = aliases[c]
971 ci = commands.get(c,None)
972 if ci == None:
973 print "Unknown command: '%s', type 'help' for list of known commands" %(c)
974 return 0
975 return ci[1](ctx, args)
976
977
978def runCommand(ctx, cmd):
979 if len(cmd) == 0: return 0
980 args = split_no_quotes(cmd)
981 if len(args) == 0: return 0
982 return runCommandArgs(ctx, args)
983
984#
985# To write your own custom commands to vboxshell, create
986# file ~/.VirtualBox/shellext.py with content like
987#
988# def runTestCmd(ctx, args):
989# print "Testy test", ctx['vb']
990# return 0
991#
992# commands = {
993# 'test': ['Test help', runTestCmd]
994# }
995# and issue reloadExt shell command.
996# This file also will be read automatically on startup or 'reloadExt'.
997#
998# Also one can put shell extensions into ~/.VirtualBox/shexts and
999# they will also be picked up, so this way one can exchange
1000# shell extensions easily.
1001def addExtsFromFile(ctx, cmds, file):
1002 if not os.path.isfile(file):
1003 return
1004 d = {}
1005 try:
1006 execfile(file, d, d)
1007 for (k,v) in d['commands'].items():
1008 if g_verbose:
1009 print "customize: adding \"%s\" - %s" %(k, v[0])
1010 cmds[k] = [v[0], v[1], file]
1011 except:
1012 print "Error loading user extensions from %s" %(file)
1013 traceback.print_exc()
1014
1015
1016def checkUserExtensions(ctx, cmds, folder):
1017 name = os.path.join(folder, "shellext.py")
1018 addExtsFromFile(ctx, cmds, name)
1019 # also check 'exts' directory for all files
1020 shextdir = os.path.join(folder, "shexts")
1021 if not os.path.isdir(shextdir):
1022 return
1023 exts = os.listdir(shextdir)
1024 for e in exts:
1025 addExtsFromFile(ctx, cmds, os.path.join(shextdir,e))
1026
1027def interpret(ctx):
1028 if ctx['remote']:
1029 commands['connect'] = ["Connect to remote VBox instance", connectCmd, 0]
1030 commands['disconnect'] = ["Disconnect from remote VBox instance", disconnectCmd, 0]
1031
1032 vbox = ctx['vb']
1033
1034 if vbox is not None:
1035 print "Running VirtualBox version %s" %(vbox.version)
1036 ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
1037 home = vbox.homeFolder
1038 else:
1039 ctx['perf'] = None
1040 home = os.path.join(os.path.expanduser("~"), ".VirtualBox")
1041
1042 checkUserExtensions(ctx, commands, home)
1043
1044 autoCompletion(commands, ctx)
1045
1046 # to allow to print actual host information, we collect info for
1047 # last 150 secs maximum, (sample every 10 secs and keep up to 15 samples)
1048 if ctx['perf']:
1049 try:
1050 ctx['perf'].setup(['*'], [vbox.host], 10, 15)
1051 except:
1052 pass
1053
1054 while True:
1055 try:
1056 cmd = raw_input("vbox> ")
1057 done = runCommand(ctx, cmd)
1058 if done != 0: break
1059 except KeyboardInterrupt:
1060 print '====== You can type quit or q to leave'
1061 break
1062 except EOFError:
1063 break;
1064 except Exception,e:
1065 print e
1066 if g_verbose:
1067 traceback.print_exc()
1068
1069 try:
1070 # There is no need to disable metric collection. This is just an example.
1071 if ct['perf']:
1072 ctx['perf'].disable(['*'], [vbox.host])
1073 except:
1074 pass
1075
1076def runCommandCb(ctx, cmd, args):
1077 args.insert(0, cmd)
1078 return runCommandArgs(ctx, args)
1079
1080def main(argv):
1081 style = None
1082 autopath = False
1083 argv.pop(0)
1084 while len(argv) > 0:
1085 if argv[0] == "-w":
1086 style = "WEBSERVICE"
1087 if argv[0] == "-a":
1088 autopath = True
1089 argv.pop(0)
1090
1091 if autopath:
1092 cwd = os.getcwd()
1093 vpp = os.environ.get("VBOX_PROGRAM_PATH")
1094 if vpp is None and (os.path.isfile(os.path.join(cwd, "VirtualBox")) or os.path.isfile(os.path.join(cwd, "VirtualBox.exe"))) :
1095 vpp = cwd
1096 print "Autodetected VBOX_PROGRAM_PATH as",vpp
1097 os.environ["VBOX_PROGRAM_PATH"] = cwd
1098 sys.path.append(os.path.join(vpp, "sdk", "installer"))
1099
1100 from vboxapi import VirtualBoxManager
1101 g_virtualBoxManager = VirtualBoxManager(style, None)
1102 ctx = {'global':g_virtualBoxManager,
1103 'mgr':g_virtualBoxManager.mgr,
1104 'vb':g_virtualBoxManager.vbox,
1105 'ifaces':g_virtualBoxManager.constants,
1106 'remote':g_virtualBoxManager.remote,
1107 'type':g_virtualBoxManager.type,
1108 'run': lambda cmd,args: runCommandCb(ctx, cmd, args),
1109 'machById': lambda id: machById(ctx,id),
1110 'progressBar': lambda p: progressBar(ctx,p),
1111 '_machlist':None
1112 }
1113 interpret(ctx)
1114 g_virtualBoxManager.deinit()
1115 del g_virtualBoxManager
1116
1117if __name__ == '__main__':
1118 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