vboxshell.py revision 607b00ae1e4b8c91f833af3c2b4a7d20b327d261
#
# Copyright (C) 2009-2010 Sun Microsystems, Inc.
#
# This file is part of VirtualBox Open Source Edition (OSE), as
# available from http://www.virtualbox.org. This file is free software;
# General Public License (GPL) as published by the Free Software
# Foundation, in version 2 as it comes in the "COPYING" file of the
# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
# Clara, CA 95054 USA or visit http://www.sun.com if you need
# additional information or have any questions.
#
#################################################################################
# This program is a simple interactive shell for VirtualBox. You can query #
# information and issue commands from a simple command line. #
# #
# It also provides you with examples on how to use VirtualBox's Python API. #
# This shell is even somewhat documented, supports TAB-completion and #
# history if you have Python readline installed. #
# #
# Finally, shell allows arbitrary custom extensions, just create #
# .VirtualBox/shexts/ and drop your extensions there. #
# Enjoy. #
################################################################################
import traceback
import shlex
import time
# Simple implementation of IConsoleCallback, one can use it as skeleton
# for custom implementations
class GuestMonitor:
print "%s: onMouseCapabilityChange: supportsAbsolute = %d, supportsRelative = %d, needsHostCursor = %d" %(self.mach.name, supportsAbsolute, supportsRelative, needsHostCursor)
def onAdditionsStateChange(self):
def onVRDPServerChange(self):
def onUSBControllerChange(self):
def onCanShowWindow(self):
return True
class VBoxMonitor:
pass
print "onMachineDataChange: %s" %(id)
# Witty COM bridge thinks if someone wishes to return tuple, hresult
# is one of values we want to return
else:
return True, ""
print "onMediaRegistered: %s" %(id)
print "onMachineRegistered: %s" %(id)
g_hasreadline = 1
try:
import readline
import rlcompleter
except:
g_hasreadline = 0
if g_hasreadline:
"""
taken from:
"""
if text == "":
return ['\t',None][state]
else:
"""
Compute matches when text is a simple name.
Return a list of all names currently defined
in self.namespace that match.
"""
matches = []
try:
# although it has autoconversion, we need to cast
# explicitly for subscripts to work
except Exception,e:
print e
return matches
if not g_hasreadline:
return
comps = {}
comps[k] = None
# OSX need it
def split_no_quotes(s):
try:
while not p.completed:
print "%d %%\r" %(p.percent),
except KeyboardInterrupt:
print "Interrupted."
if not ctx['remote']:
# update cache
try:
except:
if mach:
# update cache
if rc == 0:
# we ignore exceptions to allow starting VM even if
# perf collector cannot be started
if perf:
try:
except Exception,e:
print e
if g_verbose:
pass
# if session not opened, close doesn't make sense
else:
if ctx['vb'] is not None:
return ctx['_machlist']
else:
return []
if var:
return 'on'
else:
return 'off'
if not ctx['perf']:
return
exec cmds
if dur == -1:
# not infinity, but close enough
dur = 100000
try:
# We need to catch all exceptions here, otherwise callback will never be unregistered
except:
pass
if dur == -1:
# not infinity, but close enough
dur = 100000
try:
# We need to catch all exceptions here, otherwise callback will never be unregistered
except:
pass
f = args[0]
else:
f = "/tmp/screenshot.png"
w = args[1]
else:
h = args[2]
else:
print "Saving screenshot (%d x %d) in %s..." %(w,h,f)
size = (w,h)
mode = "RGBA"
print "Use host:port format for teleport target"
return
else:
passwd = ""
else:
maxDowntime = 250
if rc == 0:
print "Success!"
else:
# we need to set up guest statistics
else:
update = 1
try:
except:
# to allow sleep interruption
pass
cpu = 0
try:
print "%s: %d" %(s, val)
except:
# likely not implemented
pass
print "Adding CPU %d..." %(cpu)
print "Removing CPU %d..." %(cpu)
try:
except Exception,e:
if g_verbose:
return
return
# this could be an example how to handle local only (i.e. unavailable
# in Webservices) functionality
print 'Trying to use local only functionality, ignored'
return
}
try:
except Exception, e:
print 'failed: ',e
if g_verbose:
mach = None
for m in getMachines(ctx):
mach = m
break
mach = m
break
return mach
return None
if m == None:
print "Machine '%s' is unknown, use list command to find available machines" %(id)
return m
if sp != 0:
else:
spec = ""
print "Help page:"
for i in names:
else:
if c == None:
print "Command '%s' not known" %(cmd)
else:
return 0
if m.teleporterEnabled:
tele = "[T] "
else:
tele = " "
return 0
return e
return "<unknown>"
print "usage: info [vmname|uuid]"
return 0
if mach == None:
return 0
print " One can use setvar <mach> <var> <value> to change variable, using name in []."
print " Firmware [firmwareType]: %s (%s)" %(asEnumElem(ctx,"FirmwareType", mach.firmwareType),mach.firmwareType)
print
print
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
print
print " Hardware virtualization [mach.setHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_Enabled,value)]: " + asState(hwVirtEnabled)
print " VPID support [mach.setHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_VPID,value)]: " + asState(hwVirtVPID)
hwVirtNestedPaging = mach.getHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_NestedPaging)
print " Nested paging [mach.setHWVirtExProperty(ctx['global'].constants.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
print " Controllers:"
for controller in controllers:
print " %s %s bus: %d" % (controller.name, asEnumElem(ctx,"StorageControllerType", controller.controllerType), controller.bus)
if attaches:
print
print " Mediums:"
for a in attaches:
print " Controller: %s port: %d device: %d type: %s (%s):" % (a.controller, a.port, a.device, asEnumElem(ctx,"DeviceType", a.type), a.type)
m = a.medium
print " HDD:"
print " Id: %s" %(m.id)
print " Location: %s" %(m.location)
print " Name: %s" %(m.name)
print " Format: %s" %(m.format)
print " DVD:"
if m:
print " Id: %s" %(m.id)
print " Name: %s" %(m.name)
if m.hostDrive:
print " Host DVD %s" %(m.location)
if a.passthrough:
print " [passthrough mode]"
else:
print " Virtual image at %s" %(m.location)
print " Size: %s" %(m.size)
print " Floppy:"
if m:
print " Id: %s" %(m.id)
print " Name: %s" %(m.name)
if m.hostDrive:
print " Host floppy %s" %(m.location)
else:
print " Virtual image at %s" %(m.location)
print " Size: %s" %(m.size)
return 0
if mach == None:
return 0
else:
type = "gui"
return 0
print "usage: create name ostype <basefolder>"
return 0
else:
base = ''
try:
except Exception, e:
print 'Unknown OS type:',oskind
return 0
return 0
if mach == None:
return 0
return 0
if mach == None:
return 0
return 0
if mach == None:
return 0
return 0
if mach == None:
return 0
return 0
if mach == None:
return 0
return 0
if mach == None:
return 0
return 0
if mach == None:
return 0
return 0
print "usage: guest name commands"
return 0
if mach == None:
return 0
return 0
print "usage: screenshot name file <width> <height>"
return 0
if mach == None:
return 0
return 0
print "usage: teleport name host:port <password>"
return 0
if mach == None:
return 0
return 0
print "usage: openportal name port <password>"
return 0
if mach == None:
return 0
else:
passwd = ""
return 0
print "usage: closeportal name"
return 0
if mach == None:
return 0
return 0
print "usage: gueststats name <check interval>"
return 0
if mach == None:
return 0
return 0
print "usage: plugcpu name cpuid"
return 0
if mach == None:
return 0
try:
print "Adding CPU %d..." %(cpu)
except:
raise
else:
return 0
print "usage: unplugcpu name cpuid"
return 0
if mach == None:
return 0
try:
print "Removing CPU %d..." %(cpu)
except:
raise
else:
return 0
print "usage: setvar [vmname|uuid] expr value"
return 0
if mach == None:
return 0
print "Executing",expr
try:
exec expr
except Exception, e:
print 'failed: ',e
if g_verbose:
return 0
print "usage: setextra [vmname|uuid|global] key <value>"
return 0
else:
value = None
return 0
if mach == None:
return 0
return 0
print "usage: getextra [vmname|uuid|global] <key>"
return 0
else:
key = None
else:
if obj == None:
return 0
if key == None:
else:
for k in keys:
return 0
return 1
return 0
print "'%s' is an alias for '%s'" %(k,v)
return 0
global g_verbose
return 0
def getUSBStateString(state):
if state == 0:
return "NotSupported"
elif state == 1:
return "Unavailable"
elif state == 2:
return "Busy"
elif state == 3:
return "Available"
elif state == 4:
return "Held"
elif state == 5:
return "Captured"
else:
return "Unknown"
print "Processor count:",cnt
print "Processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i))
print "3D acceleration available"
else:
print "3D acceleration NOT available"
print "Network interfaces:"
print "DVD drives:"
print "USB devices:"
print " %s (vendorId=%d productId=%d serial=%s) %s" %(ud.product, ud.vendorId, ud.productId, ud.serialNumber, getUSBStateString(ud.state))
if ctx['perf']:
return 0
print "usage: monitorGuest name (duration)"
return 0
if mach == None:
return 0
dur = 5
return 0
print "usage: monitorVBox (duration)"
return 0
dur = 5
return 0
return "pcnet"
return "e1000"
return "virtio"
return None
else:
print "usage: portForward <vm> <adapter> <hostPort> <guestPort>"
return 0
if mach == None:
return 0
proto = "TCP"
return 0
print "usage: showLog <vm> <num>"
return 0
if mach == None:
return 0
log = "VBox.log"
try:
except IOError,e:
print "cannot open: ",e
return 0
print line,
return 0
try:
exec expr
except Exception, e:
print 'failed: ',e
if g_verbose:
return 0
# maybe will want more args smartness
return 0
print "usage: runScript <script>"
return 0
try:
except IOError,e:
return 0
try:
if done != 0: break
except Exception,e:
print "error:",e
if g_verbose:
return 0
print "usage: sleep <secs>"
return 0
try:
except:
# to allow sleep interrupt
pass
return 0
print "usage: shell <commands>"
return 0
try:
except KeyboardInterrupt:
# to allow shell command interruption
pass
return 0
print "usage: connect [url] [username] [passwd]"
return 0
if ctx['vb'] is not None:
print "Already connected, disconnect first..."
return 0
else:
url = None
else:
user = ""
else:
passwd = ""
return 0
print "usage: disconnect"
return 0
if ctx['vb'] is None:
print "Not connected yet."
return 0
try:
except:
ctx['vb'] = None
raise
ctx['vb'] = None
return 0
import sys
print "usage: exportVm <machine> <path> <format> <license>"
return 0
if mach is None:
return 0
else:
format = "ovf-1.0"
else:
license = "GPL"
progressBar(ctx, p)
return 0
# PC XT scancodes
scancodes = {
'a': 0x1e,
'b': 0x30,
'c': 0x2e,
'd': 0x20,
'e': 0x12,
'f': 0x21,
'g': 0x22,
'h': 0x23,
'i': 0x17,
'j': 0x24,
'k': 0x25,
'l': 0x26,
'm': 0x32,
'n': 0x31,
'o': 0x18,
'p': 0x19,
'q': 0x10,
'r': 0x13,
's': 0x1f,
't': 0x14,
'u': 0x16,
'v': 0x2f,
'w': 0x11,
'x': 0x2d,
'y': 0x15,
'z': 0x2c,
'0': 0x0b,
'1': 0x02,
'2': 0x03,
'3': 0x04,
'4': 0x05,
'5': 0x06,
'6': 0x07,
'7': 0x08,
'8': 0x09,
'9': 0x0a,
' ': 0x39,
'-': 0xc,
'=': 0xd,
'[': 0x1a,
']': 0x1b,
';': 0x27,
'\'': 0x28,
',': 0x33,
'.': 0x34,
'/': 0x35,
'\t': 0xf,
'\n': 0x1c,
'`': 0x29
};
extScancodes = {
'ESC' : [0x01],
'BKSP': [0xe],
'SPACE': [0x39],
'TAB': [0x0f],
'CAPS': [0x3a],
'ENTER': [0x1c],
'LSHIFT': [0x2a],
'RSHIFT': [0x36],
'INS': [0xe0, 0x52],
'DEL': [0xe0, 0x53],
'END': [0xe0, 0x4f],
'HOME': [0xe0, 0x47],
'PGUP': [0xe0, 0x49],
'PGDOWN': [0xe0, 0x51],
'LGUI': [0xe0, 0x5b], # GUI, aka Win, aka Apple key
'RGUI': [0xe0, 0x5c],
'LCTR': [0x1d],
'RCTR': [0xe0, 0x1d],
'LALT': [0x38],
'RALT': [0xe0, 0x38],
'APPS': [0xe0, 0x5d],
'F1': [0x3b],
'F2': [0x3c],
'F3': [0x3d],
'F4': [0x3e],
'F5': [0x3f],
'F6': [0x40],
'F7': [0x41],
'F8': [0x42],
'F9': [0x43],
'F10': [0x44 ],
'F11': [0x57],
'F12': [0x58],
'UP': [0xe0, 0x48],
'LEFT': [0xe0, 0x4b],
'DOWN': [0xe0, 0x50],
'RIGHT': [0xe0, 0x4d],
};
if code != 0:
return [code]
print "bad ext",ch
return extCode
return codes
import time
pressed = []
i = 0
i = i+1
if ch == '{':
# start group, all keys to be pressed at the same time
continue
if ch == '}':
# end group, release all keys
for c in pressed:
pressed = []
continue
if ch == 'W':
# just wait a bit
continue
if ch == '^':
ch = 'LCTR'
if ch == '|':
ch = 'LSHIFT'
if ch == '_':
ch = 'LALT'
if ch == '$':
ch = 'LGUI'
if not group:
else:
if ch == '\\':
i = i+1
if ch == 'n':
ch = '\n'
elif ch == '&':
combo = ""
i = i+1
if ch == ';':
break
if not group and modGroupEnd:
for c in pressed:
pressed = []
import sys
print "usage: typeGuest <machine> <text> <charDelay>"
return 0
if mach is None:
return 0
else:
delay = 0.1
return 0
'i':'info',
'l':'list',
'h':'help',
'a':'alias',
'q':'quit', 'exit':'quit',
'tg': 'typeGuest',
'v':'verbose'}
'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],
'screenshot':['Take VM screenshot to a file: screenshot Win /tmp/win.png 1024 768', 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],
}
c = args[0]
c = aliases[c]
if ci == None:
print "Unknown command: '%s', type 'help' for list of known commands" %(c)
return 0
#
# To write your own custom commands to vboxshell, create
# file ~/.VirtualBox/shellext.py with content like
#
# def runTestCmd(ctx, args):
# print "Testy test", ctx['vb']
# return 0
#
# commands = {
# 'test': ['Test help', runTestCmd]
# }
# and issue reloadExt shell command.
# This file also will be read automatically on startup or 'reloadExt'.
#
# Also one can put shell extensions into ~/.VirtualBox/shexts and
# they will also be picked up, so this way one can exchange
# shell extensions easily.
return
d = {}
try:
for (k,v) in d['commands'].items():
if g_verbose:
print "customize: adding \"%s\" - %s" %(k, v[0])
except:
print "Error loading user extensions from %s" %(file)
# also check 'exts' directory for all files
return
for e in exts:
def getHomeFolder(ctx):
else:
if ctx['remote']:
if vbox is not None:
else:
ctx['perf'] = None
# to allow to print actual host information, we collect info for
# last 150 secs maximum, (sample every 10 secs and keep up to 15 samples)
if ctx['perf']:
try:
except:
pass
while True:
try:
if done != 0: break
except KeyboardInterrupt:
print '====== You can type quit or q to leave'
break
except EOFError:
break;
except Exception,e:
print e
if g_verbose:
try:
# There is no need to disable metric collection. This is just an example.
if ct['perf']:
except:
pass
if mach == None:
return 0
return 0
style = None
style = "WEBSERVICE"
if autopath:
if vpp is None and (os.path.isfile(os.path.join(cwd, "VirtualBox")) or os.path.isfile(os.path.join(cwd, "VirtualBox.exe"))) :
print "Autodetected VBOX_PROGRAM_PATH as",vpp
from vboxapi import VirtualBoxManager
'typeInGuest': typeInGuest,
'_machlist':None
}
if __name__ == '__main__':