vboxshell.py revision 3e729152bacbdd8ae206df8fafe3187bb9fb7614
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# Copyright (C) 2009-2010 Oracle Corporation
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# This file is part of VirtualBox Open Source Edition (OSE), as
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# available from http://www.virtualbox.org. This file is free software;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# you can redistribute it and/or modify it under the terms of the GNU
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# General Public License (GPL) as published by the Free Software
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# Foundation, in version 2 as it comes in the "COPYING" file of the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#################################################################################
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# This program is a simple interactive shell for VirtualBox. You can query #
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# information and issue commands from a simple command line. #
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# It also provides you with examples on how to use VirtualBox's Python API. #
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# This shell is even somewhat documented, supports TAB-completion and #
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# history if you have Python readline installed. #
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# Finally, shell allows arbitrary custom extensions, just create #
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster# .VirtualBox/shexts/ and drop your extensions there. #
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster################################################################################
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return rlcompleter.Completer.__init__(self,dic)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return rlcompleter.Completer.complete(self,text,state)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster firstWord = (spaceIdx == -1 or begIdx < spaceIdx)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return not self.canBePath(phrase,word) and not self.canBeCommand(phrase, word)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Compute matches when text is a simple name.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Return a list of all names currently defined
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster in self.namespace that match.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # although it has autoconversion, we need to cast
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # explicitly for subscripts to work
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster word = re.sub("(?<!\\\\) ", "\\ ", str(m.name))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readline.set_completer_delims(re.sub("[\\./-]", "", delims)) # remove some of the delimiters
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readline.parse_and_bind("set editing-mode emacs")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # OSX need it
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # see http://www.certif.com/spec_help/readline.html
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readline.parse_and_bind ("bind ^I rl_complete")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster readline.parse_and_bind ("bind ^W ed-delete-prev-word")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # Doesn't work well
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # readline.parse_and_bind ("bind ^R em-inc-search-prev")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print "%s %%\r" %(colored(str(p.percent),'red')),
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print "Interrupted."
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print "Canceling task..."
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print colored("Error in %s: %s" %(ei.component, ei.text), 'red')
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster mach = vb.createMachine(name, kind, base, "", False)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # update cache
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print "removing machine ",mach.name,"with UUID",id
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster cmdClosedVm(ctx, mach, detachVmDevice, ["ALL"])
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # update cache
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster progress = mach.launchVMProcess(session, type, "")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if progressBar(ctx, progress, 100) and int(progress.resultCode) == 0:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # we ignore exceptions to allow starting VM even if
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # perf collector cannot be started
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # if session not opened, close doesn't make sense
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterdef getMachines(ctx, invalidate = False, simple=False):
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ctx['_machlist'] = ctx['global'].getArray(ctx['vb'], 'machines')
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ctx['_machlistsimple'] = cacheMachines(ctx,ctx['_machlist'])
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 'yes'
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for metric in ctx['perf'].query(["*"], [mach]):
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print metric['name'], metric['values_as_string']
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print "got event: %s %s" %(str(type), asEnumElem(ctx, 'VBoxEventType', type))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if type == ctx['global'].constants.VBoxEventType_OnMachineStateChanged:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster scev = ctx['global'].queryInterface(ev, 'IMachineStateChangedEvent')
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print "machine state event: mach=%s state=%s" %(scev.machineId, scev.state)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster elif type == ctx['global'].constants.VBoxEventType_OnGuestPropertyChanged:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster gpcev = ctx['global'].queryInterface(ev, 'IGuestPropertyChangedEvent')
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print "guest property change: name=%s value=%s" %(gpcev.name, gpcev.value)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster elif type == ctx['global'].constants.VBoxEventType_OnMousePointerShapeChanged:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster psev = ctx['global'].queryInterface(ev, 'IMousePointerShapeChangedEvent')
if psev:
if shape is None:
class EventListener:
if active:
if active:
if ev:
f = "/tmp/screenshot.png"
w = fbw
h = fbh
size = (w,h)
f = "/tmp/screenshot.png"
w = fbw
h = fbh
size = (w,h)
return v1
return v2
print " %s: %s (vendorId=%d productId=%d serial=%s) %s" %(ud.id, colored(ud.product,'blue'), ud.vendorId, ud.productId, ud.serialNumber,asEnumElem(ctx, 'USBDeviceState', ud.state))
print " %s: %s (vendorId=%d productId=%d serial=%s)" %(ud.id, colored(ud.product,'blue'), ud.vendorId, ud.productId, ud.serialNumber)
print " name=%s host=%s %s %s" %(sf.name, colPath(ctx,sf.hostPath), cond(sf.accessible, "accessible", "not accessible"), cond(sf.writable, "writable", "read-only"))
session = None
except Exception,e:
if g_verbose:
except Exception, e:
if g_verbose:
except Exception, e:
if g_verbose:
if save:
except Exception, e:
if g_verbose:
except Exception, e:
if g_verbose:
if save:
return mach
class XPathNode:
matches = []
for e in children:
return matches
return True
return False
return matches
children = []
return children
children = []
return children
return True
for p in pathnames:
seen = []
for s in seen:
for m in matches:
return nodes
for i in names:
if m.teleporterEnabled:
print "%sMachine '%s' [%s], machineState=%s, sessionState=%s" %(tele,colVm(ctx,m.name),m.id,asEnumElem(ctx, "MachineState", m.state), asEnumElem(ctx,"SessionState", m.sessionState))
except Exception, e:
if g_verbose:
if mach == None:
print " Firmware [firmwareType]: %s (%s)" %(asEnumElem(ctx,"FirmwareType", mach.firmwareType),mach.firmwareType)
print " Chipset [chipsetType]: %s (%s)" %(asEnumElem(ctx,"ChipsetType", mach.chipsetType), mach.chipsetType)
print " Clipboard mode [clipboardMode]: %s (%s)" %(asEnumElem(ctx,"ClipboardMode", mach.clipboardMode), mach.clipboardMode)
print " Machine status [n/a]: %s (%s)" % (asEnumElem(ctx,"SessionState", mach.sessionState), mach.sessionState)
print " Hardware virtualization [guest win machine.setHWVirtExProperty(ctx[\\'const\\'].HWVirtExPropertyType_Enabled,value)]: " + asState(hwVirtEnabled)
print " VPID support [guest win machine.setHWVirtExProperty(ctx[\\'const\\'].HWVirtExPropertyType_VPID,value)]: " + asState(hwVirtVPID)
print " Nested paging [guest win machine.setHWVirtExProperty(ctx[\\'const\\'].HWVirtExPropertyType_NestedPaging,value)]: " + asState(hwVirtNestedPaging)
print " Hardware 2d video acceleration [accelerate2DVideoEnabled]: " + asState(mach.accelerate2DVideoEnabled)
print " Audio [via audioAdapter]: chip %s; host driver %s" %(asEnumElem(ctx,"AudioControllerType", mach.audioAdapter.audioController), asEnumElem(ctx,"AudioDriverType", mach.audioAdapter.audioDriver))
print " Keyboard [keyboardHidType]: %s (%s)" %(asEnumElem(ctx,"KeyboardHidType", mach.keyboardHidType), mach.keyboardHidType)
print " Pointing device [pointingHidType]: %s (%s)" %(asEnumElem(ctx,"PointingHidType", mach.pointingHidType), mach.pointingHidType)
if controllers:
print " '%s': bus %s type %s" % (controller.name, asEnumElem(ctx,"StorageBus", controller.bus), asEnumElem(ctx,"StorageControllerType", controller.controllerType))
if attaches:
for a in attaches:
print " Controller: '%s' port/device: %d:%d type: %s (%s):" % (a.controller, a.port, a.device, asEnumElem(ctx,"DeviceType", a.type), a.type)
m = a.medium
if m.hostDrive:
if a.passthrough:
if m.hostDrive:
if mach == None:
except Exception, e:
if mach == None:
while True:
except KeyboardInterrupt:
if prompt:
if not line:
raise EOFError
return line
import getpass
if mach == None:
print "usage: gcat [vmname|uuid] local_file | guestProgram, such as gcat linux /home/nike/.bashrc | sh -c 'cat >'"
if mach == None:
env = []
if mach == None:
if mach == None:
if mach == None:
if mach == None:
if mach == None:
if mach == None:
if mach == None:
if mach == None:
if mach == None:
if mach == None:
if enabled:
if mach == None:
if mach == None:
if mach == None:
if plug:
if mach == None:
if mach == None:
exec expr
if mach == None:
value = None
if mach == None:
key = None
if obj == None:
if key == None:
for k in keys:
global g_verbose
global g_hascolors
print " processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i))
if mach == None:
cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: monitorSource(ctx, console.eventSource, active, dur)])
if mach == None:
if mach == None:
while True:
if mach == None:
while True:
for mt in m:
exec expr
except Exception, e:
if g_verbose:
except IOError,e:
except Exception,e:
if g_verbose:
except KeyboardInterrupt:
url = None
import sys
if mach is None:
scancodes = {
extScancodes = {
return [code]
return extCode
return codes
import time
pressed = []
for c in pressed:
pressed = []
if not group:
for c in pressed:
pressed = []
import sys
if mach is None:
if verbose:
if inBytes:
print " %s (%s)%s %s [logical %s]" %(colPath(ctx,hdd.location), hdd.format, optId(verbose,hdd.id),colSizeM(ctx,asSize(hdd.size, True)), colSizeM(ctx,asSize(hdd.logicalSize, True)))
print " %s (%s)%s %s" %(colPath(ctx,dvd.location), dvd.format,optId(verbose,dvd.id),colSizeM(ctx,asSize(dvd.size, True)))
print " %s (%s)%s %s" %(colPath(ctx,floppy.location), floppy.format,optId(verbose,floppy.id), colSizeM(ctx,asSize(floppy.size, True)))
for a in atts:
hdd = vb.openHardDisk(loc, ctx['global'].constants.AccessMode_ReadWrite, setImageId, imageId, setParentId, parentId)
if mach is None:
cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_HardDisk,hdd.id))
for a in atts:
if a.medium:
if mach is None:
for m in machs:
except Exception, e:
if mach is None:
cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_DVD,dvd.id))
if mach is None:
if mach is None:
if mach is None:
if type != None:
if type == None:
type = None
if mach is None:
if bus is None:
if mach is None:
if mach is None:
if mach is None:
except KeyboardInterrupt:
if mach is None:
if persistent:
cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: console.createSharedFolder(name, path, writable)])
if mach is None:
if not found:
cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: console.removeSharedFolder(name)])
if mach is None:
cmdAnyVm(ctx, mach, lambda ctx,mach,console,args: progressBar(ctx, console.takeSnapshot(name,desc)))
cmdAnyVm(ctx, mach, lambda ctx,mach,console,args: progressBar(ctx, console.deleteSnapshot(snap.id)))
alias = {
socksndbuf/sockrcvbuf - sets amount of kb for socket sending/receiving buffer
msg = 'mtu:{0} socket(snd:{1}, rcv:{2}) tcpwnd(snd:{3}, rcv:{4})'.format(mtu, socksndbuf, sockrcvbuf, tcpsndwnd, tcprcvwnd);
msg = 'passdomain:{0}, proxy:{1}, usehostresolver:{2}'.format(yesno[int(nat.dnsPassDomain)], yesno[int(nat.dnsProxy)], yesno[int(nat.dnsUseHostResolver)])
if server is None:
if server is None:
if prefix is None:
if bootfile is None:
msg = []
pfcmd = {
'func': lambda: nat.addRedirect(args[3], proto[args[2]], args[4], int(args[5]), args[6], int(args[7]))
natcommands = {
if mach == None:
if len(args) < 3 or not args[2].isdigit() or int(args[2]) not in range(0, ctx['vb'].systemProperties.networkAdapterCount):
print 'please specify adapter num {0} isn\'t in range [0-{1}]'.format(args[2], ctx['vb'].systemProperties.networkAdapterCount)
cmdargs = []
session = None
elif report is not None:
for r in report:
print msg
usage: nic <vm> <nicnum> attachment [Null|NAT|Bridged <interface>|Internal <name>|HostOnly <interface>]
import types
(r, p) = nicAttachmentType[t]
niccomand = {
if vm is None:
print 'please specify adapter num %d isn\'t in range [0-%d]'%(args[2], ctx['vb'].systemProperties.networkAdapterCount)
session = None
if report is not None:
for e in elems:
'eval':['Evaluate arbitrary Python construction: eval \'for m in getMachines(ctx): print m.name,"has",m.memorySize,"M"\'', evalCmd, 0],
'guest':['Execute command for guest: guest Win32 \'console.mouse.putMouseEvent(20, 20, 0, 0, 0)\'', guestCmd, 0],
'monitorGuest':['Monitor what happens with the guest for some time: monitorGuest Win32 10', monitorGuestCmd, 0],
'monitorVBox':['Monitor what happens with Virtual Box for some time: monitorVBox 10', monitorVBoxCmd, 0],
'portForward':['Setup permanent port forwarding for a VM, takes adapter number host port and guest port: portForward Win32 0 8080 80', portForwardCmd, 0],
'findLog':['Show entries matching pattern in log file of the VM, : findLog Win32 PDM|CPUM', findLogCmd, 0],
'screenshot':['Take VM screenshot to a file: screenshot Win /tmp/win.png 1024 768 0', screenshotCmd, 0],
'teleport':['Teleport VM to another box (see openportal): teleport Win anotherhost:8000 <passwd> <maxDowntime>', teleportCmd, 0],
'typeGuest':['Type arbitrary text in guest: typeGuest Linux "^lls\\n&UP;&BKSP;ess /etc/hosts\\nq^c" 0.7', typeGuestCmd, 0],
'openportal':['Open portal for teleportation of VM from another box (see teleport): openportal Win 8000 <passwd>', openportalCmd, 0],
'closeportal':['Close teleportation portal (see openportal,teleport): closeportal Win', closeportalCmd, 0],
'setextra':['Set extra data, empty value removes key: setextra <vm|global> <key> <value>', setExtraDataCmd, 0],
'gueststats':['Print available guest stats (only Windows guests with additions so far): gueststats Win32', gueststatsCmd, 0],
'unplugcpu':['Remove a CPU from a running VM (additions required, Windows cannot unplug): unplugcpu Linux 1', unplugcpuCmd, 0],
'registerHdd': ['Register HDD image with VirtualBox instance: registerHdd /disk.vdi', registerHddCmd, 0],
'unregisterHdd': ['Unregister HDD image with VirtualBox instance: unregisterHdd /disk.vdi', unregisterHddCmd, 0],
'attachHdd': ['Attach HDD to the VM: attachHdd win /disk.vdi "IDE Controller" 0:1', attachHddCmd, 0],
'registerIso': ['Register CD/DVD image with VirtualBox instance: registerIso /os.iso', registerIsoCmd, 0],
'unregisterIso': ['Unregister CD/DVD image with VirtualBox instance: unregisterIso /os.iso', unregisterIsoCmd, 0],
'attachIso': ['Attach CD/DVD to the VM: attachIso win /os.iso "IDE Controller" 0:1', attachIsoCmd, 0],
'mountIso': ['Mount CD/DVD to the running VM: mountIso win /os.iso "IDE Controller" 0:1', mountIsoCmd, 0],
'unmountIso': ['Unmount CD/DVD from running VM: unmountIso win "IDE Controller" 0:1', unmountIsoCmd, 0],
'attachUsb': ['Attach USB device to the VM (use listUsb to show available devices): attachUsb win uuid', attachUsbCmd, 0],
'shareFolder': ['Make host\'s folder visible to guest: shareFolder win /share share writable', shareFolderCmd, 0],
'foreach' : ['Generic "for each" construction, using XPath-like notation: foreach //vms/vm[@OSTypeId=\'MacOS\'] "print obj.name"', foreachCmd, 0],
c = aliases[c]
if ci == None:
# file ~/.VirtualBox/shellext.py with content like
# Also one can put shell extensions into ~/.VirtualBox/shexts and
if g_verbose:
for e in exts:
commands['connect'] = ["Connect to remote VBox instance: connect http://server:18083 user password", connectCmd, 0]
if vbox is not None:
global g_hascolors
cmds = []
if g_cmd is not None:
while True:
if g_batchmode:
elif g_cmd is not None:
if g_batchmode:
except KeyboardInterrupt:
except StopIteration:
except EOFError:
except Exception,e:
if g_verbose:
if g_hasreadline:
if mach == None:
style = None
params = None
script_file = None
parse.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help = "switch on verbose")
parse.add_option("-a", "--autopath", dest="autopath", action="store_true", default=False, help = "switch on autopath")
parse.add_option("-w", "--webservice", dest="style", action="store_const", const="WEBSERVICE", help = "connect to webservice")
params = {}
params[k] = v
params = None