#!/usr/bin/python # # Copyright (C) 2009-2010 Oracle Corporation # # This file is part of VirtualBox Open Source Edition (OSE), as # available from http://www.virtualbox.org. This file is free software; # you can redistribute it and/or modify it under the terms of the GNU # 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. # ################################################################################# # 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 os,sys import traceback import shlex import time import re import platform # Simple implementation of IConsoleCallback, one can use it as skeleton # for custom implementations class GuestMonitor: def __init__(self, mach): self.mach = mach def onMousePointerShapeChange(self, visible, alpha, xHot, yHot, width, height, shape): print "%s: onMousePointerShapeChange: visible=%d shape=%d bytes" %(self.mach.name, visible,len(shape)) def onMouseCapabilityChange(self, supportsAbsolute, supportsRelative, needsHostCursor): print "%s: onMouseCapabilityChange: supportsAbsolute = %d, supportsRelative = %d, needsHostCursor = %d" %(self.mach.name, supportsAbsolute, supportsRelative, needsHostCursor) def onKeyboardLedsChange(self, numLock, capsLock, scrollLock): print "%s: onKeyboardLedsChange capsLock=%d" %(self.mach.name, capsLock) def onStateChange(self, state): print "%s: onStateChange state=%d" %(self.mach.name, state) def onAdditionsStateChange(self): print "%s: onAdditionsStateChange" %(self.mach.name) def onNetworkAdapterChange(self, adapter): print "%s: onNetworkAdapterChange" %(self.mach.name) def onSerialPortChange(self, port): print "%s: onSerialPortChange" %(self.mach.name) def onParallelPortChange(self, port): print "%s: onParallelPortChange" %(self.mach.name) def onStorageControllerChange(self): print "%s: onStorageControllerChange" %(self.mach.name) def onMediumChange(self, attachment): print "%s: onMediumChange" %(self.mach.name) def onVRDPServerChange(self): print "%s: onVRDPServerChange" %(self.mach.name) def onUSBControllerChange(self): print "%s: onUSBControllerChange" %(self.mach.name) def onUSBDeviceStateChange(self, device, attached, error): print "%s: onUSBDeviceStateChange" %(self.mach.name) def onSharedFolderChange(self, scope): print "%s: onSharedFolderChange" %(self.mach.name) def onRuntimeError(self, fatal, id, message): print "%s: onRuntimeError fatal=%d message=%s" %(self.mach.name, fatal, message) def onCanShowWindow(self): print "%s: onCanShowWindow" %(self.mach.name) return True def onShowWindow(self, winId): print "%s: onShowWindow: %d" %(self.mach.name, winId) class VBoxMonitor: def __init__(self, params): self.vbox = params[0] self.isMscom = params[1] pass def onMachineStateChange(self, id, state): print "onMachineStateChange: %s %d" %(id, state) def onMachineDataChange(self,id): print "onMachineDataChange: %s" %(id) def onExtraDataCanChange(self, id, key, value): print "onExtraDataCanChange: %s %s=>%s" %(id, key, value) # Witty COM bridge thinks if someone wishes to return tuple, hresult # is one of values we want to return if self.isMscom: return "", 0, True else: return True, "" def onExtraDataChange(self, id, key, value): print "onExtraDataChange: %s %s=>%s" %(id, key, value) def onMediaRegistered(self, id, type, registered): print "onMediaRegistered: %s" %(id) def onMachineRegistered(self, id, registred): print "onMachineRegistered: %s" %(id) def onSessionStateChange(self, id, state): print "onSessionStateChange: %s %d" %(id, state) def onSnapshotTaken(self, mach, id): print "onSnapshotTaken: %s %s" %(mach, id) def onSnapshotDeleted(self, mach, id): print "onSnapshotDeleted: %s %s" %(mach, id) def onSnapshotChange(self, mach, id): print "onSnapshotChange: %s %s" %(mach, id) def onGuestPropertyChange(self, id, name, newValue, flags): print "onGuestPropertyChange: %s: %s=%s" %(id, name, newValue) g_hasreadline = True try: import readline import rlcompleter except: g_hasreadline = False g_hascolors = True term_colors = { 'red':'\033[31m', 'blue':'\033[94m', 'green':'\033[92m', 'yellow':'\033[93m', 'magenta':'\033[35m' } def colored(string,color): if not g_hascolors: return string global term_colors col = term_colors.get(color,None) if col: return col+str(string)+'\033[0m' else: return string if g_hasreadline: class CompleterNG(rlcompleter.Completer): def __init__(self, dic, ctx): self.ctx = ctx return rlcompleter.Completer.__init__(self,dic) def complete(self, text, state): """ taken from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812 """ if text == "": return ['\t',None][state] else: return rlcompleter.Completer.complete(self,text,state) def global_matches(self, text): """ Compute matches when text is a simple name. Return a list of all names currently defined in self.namespace that match. """ matches = [] n = len(text) for list in [ self.namespace ]: for word in list: if word[:n] == text: matches.append(word) try: for m in getMachines(self.ctx, False, True): # although it has autoconversion, we need to cast # explicitly for subscripts to work word = re.sub("(? 0: f = args[0] else: f = "/tmp/screenshot.png" if len(args) > 3: screen = int(args[3]) else: screen = 0 (fbw, fbh, fbbpp) = display.getScreenResolution(screen) if len(args) > 1: w = int(args[1]) else: w = fbw if len(args) > 2: h = int(args[2]) else: h = fbh print "Saving screenshot (%d x %d) screen %d in %s..." %(w,h,screen,f) data = display.takeScreenShotToArray(screen, w,h) size = (w,h) mode = "RGBA" im = Image.frombuffer(mode, size, str(data), "raw", mode, 0, 1) im.save(f, "PNG") def teleport(ctx,session,console,args): if args[0].find(":") == -1: print "Use host:port format for teleport target" return (host,port) = args[0].split(":") if len(args) > 1: passwd = args[1] else: passwd = "" if len(args) > 2: maxDowntime = int(args[2]) else: maxDowntime = 250 port = int(port) print "Teleporting to %s:%d..." %(host,port) progress = console.teleport(host, port, passwd, maxDowntime) if progressBar(ctx, progress, 100) and int(progress.resultCode) == 0: print "Success!" else: reportError(ctx,progress) def guestStats(ctx,console,args): guest = console.guest # we need to set up guest statistics if len(args) > 0 : update = args[0] else: update = 1 if guest.statisticsUpdateInterval != update: guest.statisticsUpdateInterval = update try: time.sleep(float(update)+0.1) except: # to allow sleep interruption pass all_stats = ctx['ifaces'].all_values('GuestStatisticType') cpu = 0 for s in all_stats.keys(): try: val = guest.getStatistic( cpu, all_stats[s]) print "%s: %d" %(s, val) except: # likely not implemented pass def plugCpu(ctx,machine,session,args): cpu = int(args[0]) print "Adding CPU %d..." %(cpu) machine.hotPlugCPU(cpu) def unplugCpu(ctx,machine,session,args): cpu = int(args[0]) print "Removing CPU %d..." %(cpu) machine.hotUnplugCPU(cpu) def mountIso(ctx,machine,session,args): machine.mountMedium(args[0], args[1], args[2], args[3], args[4]) machine.saveSettings() def cond(c,v1,v2): if c: return v1 else: return v2 def printHostUsbDev(ctx,ud): 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)) def printUsbDev(ctx,ud): print " %s: %s (vendorId=%d productId=%d serial=%s)" %(ud.id, colored(ud.product,'blue'), ud.vendorId, ud.productId, ud.serialNumber) def printSf(ctx,sf): print " name=%s host=%s %s %s" %(sf.name, sf.hostPath, cond(sf.accessible, "accessible", "not accessible"), cond(sf.writable, "writable", "read-only")) def ginfo(ctx,console, args): guest = console.guest if guest.additionsActive: vers = int(str(guest.additionsVersion)) print "Additions active, version %d.%d" %(vers >> 16, vers & 0xffff) print "Support seamless: %s" %(asFlag(guest.supportsSeamless)) print "Support graphics: %s" %(asFlag(guest.supportsGraphics)) print "Baloon size: %d" %(guest.memoryBalloonSize) print "Statistic update interval: %d" %(guest.statisticsUpdateInterval) else: print "No additions" usbs = ctx['global'].getArray(console, 'USBDevices') print "Attached USB:" for ud in usbs: printUsbDev(ctx,ud) rusbs = ctx['global'].getArray(console, 'remoteUSBDevices') print "Remote USB:" for ud in rusbs: printHostUsbDev(ctx,ud) print "Transient shared folders:" sfs = rusbs = ctx['global'].getArray(console, 'sharedFolders') for sf in sfs: printSf(ctx,sf) def cmdExistingVm(ctx,mach,cmd,args): try: session = ctx['global'].openMachineSession(mach.id) except Exception,e: printErr(ctx, "Session to '%s' not open: %s" %(mach.name,str(e))) if g_verbose: traceback.print_exc() return if session.state != ctx['ifaces'].SessionState_Open: print "Session to '%s' in wrong state: %s" %(mach.name, session.state) session.close() return # this could be an example how to handle local only (i.e. unavailable # in Webservices) functionality if ctx['remote'] and cmd == 'some_local_only_command': print 'Trying to use local only functionality, ignored' session.close() return console=session.console ops={'pause': lambda: console.pause(), 'resume': lambda: console.resume(), 'powerdown': lambda: console.powerDown(), 'powerbutton': lambda: console.powerButton(), 'stats': lambda: perfStats(ctx, mach), 'guest': lambda: guestExec(ctx, mach, console, args), 'ginfo': lambda: ginfo(ctx, console, args), 'guestlambda': lambda: args[0](ctx, mach, console, args[1:]), 'monitorGuest': lambda: monitorGuest(ctx, mach, console, args), 'save': lambda: progressBar(ctx,console.saveState()), 'screenshot': lambda: takeScreenshot(ctx,console,args), 'teleport': lambda: teleport(ctx,session,console,args), 'gueststats': lambda: guestStats(ctx, console, args), 'plugcpu': lambda: plugCpu(ctx, session.machine, session, args), 'unplugcpu': lambda: unplugCpu(ctx, session.machine, session, args), 'mountiso': lambda: mountIso(ctx, session.machine, session, args), } try: ops[cmd]() except Exception, e: printErr(ctx,e) if g_verbose: traceback.print_exc() session.close() def cmdClosedVm(ctx,mach,cmd,args=[],save=True): session = ctx['global'].openMachineSession(mach.id) mach = session.machine try: cmd(ctx, mach, args) except Exception, e: save = False printErr(ctx,e) if g_verbose: traceback.print_exc() if save: mach.saveSettings() ctx['global'].closeMachineSession(session) def cmdAnyVm(ctx,mach,cmd, args=[],save=False): session = ctx['global'].openMachineSession(mach.id) mach = session.machine try: cmd(ctx, mach, session.console, args) except Exception, e: save = False; printErr(ctx,e) if g_verbose: traceback.print_exc() if save: mach.saveSettings() ctx['global'].closeMachineSession(session) def machById(ctx,id): mach = None for m in getMachines(ctx): if m.name == id: mach = m break mid = str(m.id) if mid[0] == '{': mid = mid[1:-1] if mid == id: mach = m break return mach def argsToMach(ctx,args): if len(args) < 2: print "usage: %s [vmname|uuid]" %(args[0]) return None id = args[1] m = machById(ctx, id) if m == None: print "Machine '%s' is unknown, use list command to find available machines" %(id) return m def helpSingleCmd(cmd,h,sp): if sp != 0: spec = " [ext from "+sp+"]" else: spec = "" print " %s: %s%s" %(colored(cmd,'blue'),h,spec) def helpCmd(ctx, args): if len(args) == 1: print "Help page:" names = commands.keys() names.sort() for i in names: helpSingleCmd(i, commands[i][0], commands[i][2]) else: cmd = args[1] c = commands.get(cmd) if c == None: print "Command '%s' not known" %(cmd) else: helpSingleCmd(cmd, c[0], c[2]) return 0 def asEnumElem(ctx,enum,elem): all = ctx['ifaces'].all_values(enum) for e in all.keys(): if str(elem) == str(all[e]): return colored(e, 'green') return colored("", 'green') def enumFromString(ctx,enum,str): all = ctx['ifaces'].all_values(enum) return all.get(str, None) def listCmd(ctx, args): for m in getMachines(ctx, True): if m.teleporterEnabled: tele = "[T] " else: tele = " " 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)) return 0 def infoCmd(ctx,args): if (len(args) < 2): print "usage: info [vmname|uuid]" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 os = ctx['vb'].getGuestOSType(mach.OSTypeId) print " One can use setvar to change variable, using name in []." print " Name [name]: %s" %(colVm(ctx,mach.name)) print " Description [description]: %s" %(mach.description) print " ID [n/a]: %s" %(mach.id) print " OS Type [via OSTypeId]: %s" %(os.description) print " Firmware [firmwareType]: %s (%s)" %(asEnumElem(ctx,"FirmwareType", mach.firmwareType),mach.firmwareType) print print " CPUs [CPUCount]: %d" %(mach.CPUCount) print " RAM [memorySize]: %dM" %(mach.memorySize) print " VRAM [VRAMSize]: %dM" %(mach.VRAMSize) print " Monitors [monitorCount]: %d" %(mach.monitorCount) 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 if mach.teleporterEnabled: print " Teleport target on port %d (%s)" %(mach.teleporterPort, mach.teleporterPassword) print bios = mach.BIOSSettings print " ACPI [BIOSSettings.ACPIEnabled]: %s" %(asState(bios.ACPIEnabled)) print " APIC [BIOSSettings.IOAPICEnabled]: %s" %(asState(bios.IOAPICEnabled)) hwVirtEnabled = mach.getHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_Enabled) print " Hardware virtualization [mach.setHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_Enabled,value)]: " + asState(hwVirtEnabled) hwVirtVPID = mach.getHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_VPID) 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 3d acceleration [accelerate3DEnabled]: " + asState(mach.accelerate3DEnabled) print " Hardware 2d video acceleration [accelerate2DVideoEnabled]: " + asState(mach.accelerate2DVideoEnabled) print " Use universal time [RTCUseUTC]: %s" %(asState(mach.RTCUseUTC)) print " HPET [hpetEnabled]: %s" %(asState(mach.hpetEnabled)) if mach.audioAdapter.enabled: print " Audio [via audioAdapter]: chip %s; host driver %s" %(asEnumElem(ctx,"AudioControllerType", mach.audioAdapter.audioController), asEnumElem(ctx,"AudioDriverType", mach.audioAdapter.audioDriver)) if mach.USBController.enabled: print " USB [via USBController]: high speed %s" %(asState(mach.USBController.enabledEhci)) print " CPU hotplugging [CPUHotPlugEnabled]: %s" %(asState(mach.CPUHotPlugEnabled)) 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) print " Last changed [n/a]: " + time.asctime(time.localtime(long(mach.lastStateChange)/1000)) print " VRDP server [VRDPServer.enabled]: %s" %(asState(mach.VRDPServer.enabled)) print print colCat(ctx," I/O subsystem info:") print " Cache enabled [ioCacheEnabled]: %s" %(asState(mach.ioCacheEnabled)) print " Cache size [ioCacheSize]: %dM" %(mach.ioCacheSize) print " Bandwidth limit [ioBandwidthMax]: %dM/s" %(mach.ioBandwidthMax) controllers = ctx['global'].getArray(mach, 'storageControllers') if controllers: print print colCat(ctx," Controllers:") for controller in controllers: print " '%s': bus %s type %s" % (controller.name, asEnumElem(ctx,"StorageBus", controller.bus), asEnumElem(ctx,"StorageControllerType", controller.controllerType)) attaches = ctx['global'].getArray(mach, 'mediumAttachments') if attaches: print print colCat(ctx," Media:") 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 a.type == ctx['global'].constants.DeviceType_HardDisk: print " HDD:" print " Id: %s" %(m.id) print " Location: %s" %(m.location) print " Name: %s" %(m.name) print " Format: %s" %(m.format) if a.type == ctx['global'].constants.DeviceType_DVD: 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) if a.type == ctx['global'].constants.DeviceType_Floppy: 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) print print colCat(ctx," Shared folders:") for sf in ctx['global'].getArray(mach, 'sharedFolders'): printSf(ctx,sf) return 0 def startCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 if len(args) > 2: type = args[2] else: type = "gui" startVm(ctx, mach, type) return 0 def createVmCmd(ctx, args): if (len(args) < 3 or len(args) > 4): print "usage: createvm name ostype " return 0 name = args[1] oskind = args[2] if len(args) == 4: base = args[3] else: base = '' try: ctx['vb'].getGuestOSType(oskind) except Exception, e: print 'Unknown OS type:',oskind return 0 createVm(ctx, name, oskind, base) return 0 def ginfoCmd(ctx,args): if (len(args) < 2): print "usage: ginfo [vmname|uuid]" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'ginfo', '') return 0 def execInGuest(ctx,console,args,env): if len(args) < 1: print "exec in guest needs at least program name" return user = "" passwd = "" tmo = 0 guest = console.guest # shall contain program name as argv[0] gargs = args print "executing %s with args %s" %(args[0], gargs) (progress, pid) = guest.executeProcess(args[0], 0, gargs, env, "", "", "", user, passwd, tmo) print "executed with pid %d" %(pid) if pid != 0: try: while True: data = guest.getProcessOutput(pid, 0, 1000, 4096) if data and len(data) > 0: sys.stdout.write(data) continue progress.waitForCompletion(100) ctx['global'].waitForEvents(0) if progress.completed: break except KeyboardInterrupt: print "Interrupted." if progress.cancelable: progress.cancel() return 0 else: reportError(ctx, progress) def gexecCmd(ctx,args): if (len(args) < 2): print "usage: gexec [vmname|uuid] command args" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 gargs = args[2:] env = [] # ["DISPLAY=:0"] gargs.insert(0, lambda ctx,mach,console,args: execInGuest(ctx,console,args,env)) cmdExistingVm(ctx, mach, 'guestlambda', gargs) return 0 def gcatCmd(ctx,args): if (len(args) < 2): print "usage: gcat [vmname|uuid] local_file | guestProgram, such as gcat linux /home/nike/.bashrc | sh -c 'cat >'" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 gargs = args[2:] env = [] gargs.insert(0, lambda ctx,mach,console,args: execInGuest(ctx,console,args,env)) cmdExistingVm(ctx, mach, 'guestlambda', gargs) return 0 def removeVmCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 removeVm(ctx, mach) return 0 def pauseCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'pause', '') return 0 def powerdownCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'powerdown', '') return 0 def powerbuttonCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'powerbutton', '') return 0 def resumeCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'resume', '') return 0 def saveCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'save', '') return 0 def statsCmd(ctx, args): mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'stats', '') return 0 def guestCmd(ctx, args): if (len(args) < 3): print "usage: guest name commands" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'guest', ' '.join(args[2:])) return 0 def screenshotCmd(ctx, args): if (len(args) < 2): print "usage: screenshot vm " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'screenshot', args[2:]) return 0 def teleportCmd(ctx, args): if (len(args) < 3): print "usage: teleport name host:port " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'teleport', args[2:]) return 0 def portalsettings(ctx,mach,args): enabled = args[0] mach.teleporterEnabled = enabled if enabled: port = args[1] passwd = args[2] mach.teleporterPort = port mach.teleporterPassword = passwd def openportalCmd(ctx, args): if (len(args) < 3): print "usage: openportal name port " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 port = int(args[2]) if (len(args) > 3): passwd = args[3] else: passwd = "" if not mach.teleporterEnabled or mach.teleporterPort != port or passwd: cmdClosedVm(ctx, mach, portalsettings, [True, port, passwd]) startVm(ctx, mach, "gui") return 0 def closeportalCmd(ctx, args): if (len(args) < 2): print "usage: closeportal name" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 if mach.teleporterEnabled: cmdClosedVm(ctx, mach, portalsettings, [False]) return 0 def gueststatsCmd(ctx, args): if (len(args) < 2): print "usage: gueststats name " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 cmdExistingVm(ctx, mach, 'gueststats', args[2:]) return 0 def plugcpu(ctx,mach,args): plug = args[0] cpu = args[1] if plug: print "Adding CPU %d..." %(cpu) mach.hotPlugCPU(cpu) else: print "Removing CPU %d..." %(cpu) mach.hotUnplugCPU(cpu) def plugcpuCmd(ctx, args): if (len(args) < 2): print "usage: plugcpu name cpuid" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 if str(mach.sessionState) != str(ctx['ifaces'].SessionState_Open): if mach.CPUHotPlugEnabled: cmdClosedVm(ctx, mach, plugcpu, [True, int(args[2])]) else: cmdExistingVm(ctx, mach, 'plugcpu', args[2]) return 0 def unplugcpuCmd(ctx, args): if (len(args) < 2): print "usage: unplugcpu name cpuid" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 if str(mach.sessionState) != str(ctx['ifaces'].SessionState_Open): if mach.CPUHotPlugEnabled: cmdClosedVm(ctx, mach, plugcpu, [False, int(args[2])]) else: cmdExistingVm(ctx, mach, 'unplugcpu', args[2]) return 0 def setvar(ctx,mach,args): expr = 'mach.'+args[0]+' = '+args[1] print "Executing",expr exec expr def setvarCmd(ctx, args): if (len(args) < 4): print "usage: setvar [vmname|uuid] expr value" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 cmdClosedVm(ctx, mach, setvar, args[2:]) return 0 def setvmextra(ctx,mach,args): key = args[0] value = args[1] print "%s: setting %s to %s" %(mach.name, key, value) mach.setExtraData(key, value) def setExtraDataCmd(ctx, args): if (len(args) < 3): print "usage: setextra [vmname|uuid|global] key " return 0 key = args[2] if len(args) == 4: value = args[3] else: value = None if args[1] == 'global': ctx['vb'].setExtraData(key, value) return 0 mach = argsToMach(ctx,args) if mach == None: return 0 cmdClosedVm(ctx, mach, setvmextra, [key, value]) return 0 def printExtraKey(obj, key, value): print "%s: '%s' = '%s'" %(obj, key, value) def getExtraDataCmd(ctx, args): if (len(args) < 2): print "usage: getextra [vmname|uuid|global] " return 0 if len(args) == 3: key = args[2] else: key = None if args[1] == 'global': obj = ctx['vb'] else: obj = argsToMach(ctx,args) if obj == None: return 0 if key == None: keys = obj.getExtraDataKeys() else: keys = [ key ] for k in keys: printExtraKey(args[1], k, obj.getExtraData(k)) return 0 def quitCmd(ctx, args): return 1 def aliasCmd(ctx, args): if (len(args) == 3): aliases[args[1]] = args[2] return 0 for (k,v) in aliases.items(): print "'%s' is an alias for '%s'" %(k,v) return 0 def verboseCmd(ctx, args): global g_verbose g_verbose = not g_verbose return 0 def colorsCmd(ctx, args): global g_hascolors g_hascolors = not g_hascolors return 0 def hostCmd(ctx, args): vb = ctx['vb'] print "VirtualBox version %s" %(colored(vb.version, 'blue')) props = vb.systemProperties print "Machines: %s" %(colPath(ctx,props.defaultMachineFolder)) print "HDDs: %s" %(colPath(ctx,props.defaultHardDiskFolder)) #print "Global shared folders:" #for ud in ctx['global'].getArray(vb, 'sharedFolders'): # printSf(ctx,sf) host = vb.host cnt = host.processorCount print colCat(ctx,"Processors:") print " available/online: %d/%d " %(cnt,host.processorOnlineCount) for i in range(0,cnt): print " processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i)) print colCat(ctx, "RAM:") print " %dM (free %dM)" %(host.memorySize, host.memoryAvailable) print colCat(ctx,"OS:"); print " %s (%s)" %(host.operatingSystem, host.OSVersion) if host.Acceleration3DAvailable: print colCat(ctx,"3D acceleration available") else: print colCat(ctx,"3D acceleration NOT available") print colCat(ctx,"Network interfaces:") for ni in ctx['global'].getArray(host, 'networkInterfaces'): print " %s (%s)" %(ni.name, ni.IPAddress) print colCat(ctx,"DVD drives:") for dd in ctx['global'].getArray(host, 'DVDDrives'): print " %s - %s" %(dd.name, dd.description) print colCat(ctx,"Floppy drives:") for dd in ctx['global'].getArray(host, 'floppyDrives'): print " %s - %s" %(dd.name, dd.description) print colCat(ctx,"USB devices:") for ud in ctx['global'].getArray(host, 'USBDevices'): printHostUsbDev(ctx,ud) if ctx['perf']: for metric in ctx['perf'].query(["*"], [host]): print metric['name'], metric['values_as_string'] return 0 def monitorGuestCmd(ctx, args): if (len(args) < 2): print "usage: monitorGuest name (duration)" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 dur = 5 if len(args) > 2: dur = float(args[2]) cmdExistingVm(ctx, mach, 'monitorGuest', dur) return 0 def monitorVBoxCmd(ctx, args): if (len(args) > 2): print "usage: monitorVBox (duration)" return 0 dur = 5 if len(args) > 1: dur = float(args[1]) monitorVBox(ctx, dur) return 0 def getAdapterType(ctx, type): if (type == ctx['global'].constants.NetworkAdapterType_Am79C970A or type == ctx['global'].constants.NetworkAdapterType_Am79C973): return "pcnet" elif (type == ctx['global'].constants.NetworkAdapterType_I82540EM or type == ctx['global'].constants.NetworkAdapterType_I82545EM or type == ctx['global'].constants.NetworkAdapterType_I82543GC): return "e1000" elif (type == ctx['global'].constants.NetworkAdapterType_Virtio): return "virtio" elif (type == ctx['global'].constants.NetworkAdapterType_Null): return None else: raise Exception("Unknown adapter type: "+type) def portForwardCmd(ctx, args): if (len(args) != 5): print "usage: portForward " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 adapterNum = int(args[2]) hostPort = int(args[3]) guestPort = int(args[4]) proto = "TCP" session = ctx['global'].openMachineSession(mach.id) mach = session.machine adapter = mach.getNetworkAdapter(adapterNum) adapterType = getAdapterType(ctx, adapter.adapterType) profile_name = proto+"_"+str(hostPort)+"_"+str(guestPort) config = "VBoxInternal/Devices/" + adapterType + "/" config = config + str(adapter.slot) +"/LUN#0/Config/" + profile_name mach.setExtraData(config + "/Protocol", proto) mach.setExtraData(config + "/HostPort", str(hostPort)) mach.setExtraData(config + "/GuestPort", str(guestPort)) mach.saveSettings() session.close() return 0 def showLogCmd(ctx, args): if (len(args) < 2): print "usage: showLog vm " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 log = 0 if (len(args) > 2): log = args[2] uOffset = 0 while True: data = mach.readLog(log, uOffset, 4096) if (len(data) == 0): break # print adds either NL or space to chunks not ending with a NL sys.stdout.write(str(data)) uOffset += len(data) return 0 def findLogCmd(ctx, args): if (len(args) < 3): print "usage: findLog vm pattern " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 log = 0 if (len(args) > 3): log = args[3] pattern = args[2] uOffset = 0 while True: # to reduce line splits on buffer boundary data = mach.readLog(log, uOffset, 512*1024) if (len(data) == 0): break d = str(data).split("\n") for s in d: m = re.findall(pattern, s) if len(m) > 0: for mt in m: s = s.replace(mt, colored(mt,'red')) print s uOffset += len(data) return 0 def evalCmd(ctx, args): expr = ' '.join(args[1:]) try: exec expr except Exception, e: printErr(ctx,e) if g_verbose: traceback.print_exc() return 0 def reloadExtCmd(ctx, args): # maybe will want more args smartness checkUserExtensions(ctx, commands, getHomeFolder(ctx)) autoCompletion(commands, ctx) return 0 def runScriptCmd(ctx, args): if (len(args) != 2): print "usage: runScript