#!/usr/bin/python # # Copyright (C) 2009-2011 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 from optparse import OptionParser g_batchmode = False g_scripfile = None g_cmd = None g_hasreadline = True try: if g_hasreadline: import readline import rlcompleter except: g_hasreadline = False g_prompt = "vbox> " g_hascolors = True term_colors = { 'red':'\033[31m', 'blue':'\033[94m', 'green':'\033[92m', 'yellow':'\033[93m', 'magenta':'\033[35m', 'cyan':'\033[36m' } 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: import string 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 False and text == "": return ['\t',None][state] else: return rlcompleter.Completer.complete(self,text,state) def canBePath(self, phrase,word): return word.startswith('/') def canBeCommand(self, phrase, word): spaceIdx = phrase.find(" ") begIdx = readline.get_begidx() firstWord = (spaceIdx == -1 or begIdx < spaceIdx) if firstWord: return True if phrase.startswith('help'): return True return False def canBeMachine(self,phrase,word): return not self.canBePath(phrase,word) and not self.canBeCommand(phrase, word) 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 = [] phrase = readline.get_line_buffer() try: if self.canBePath(phrase,text): (dir,rest) = os.path.split(text) n = len(rest) for word in os.listdir(dir): if n == 0 or word[:n] == rest: matches.append(os.path.join(dir,word)) if self.canBeCommand(phrase,text): n = len(text) for list in [ self.namespace ]: for word in list: if word[:n] == text: matches.append(word) if self.canBeMachine(phrase,text): n = len(text) for m in getMachines(self.ctx, False, True): # although it has autoconversion, we need to cast # explicitly for subscripts to work word = re.sub("(?\d+): (?P[km]) (?P

.*)') mre = re.compile(r'(?P\d+) (?P-*\d+) (?P-*\d+) (?P-*\d+) (?P-*\d+) (?P-*\d+)') kre = re.compile(r'\d+') kbd = console.keyboard mouse = console.mouse try: end = time.time() + dur for line in demo: if time.time() > end: break m = basere.search(line) if m is None: continue dict = m.groupdict() stamp = dict['s'] params = dict['p'] type = dict['t'] time.sleep(float(stamp)/1000) if type == 'k': codes=kre.findall(params) #print "KBD:",codes kbd.putScancodes(codes) elif type == 'm': mm = mre.search(params) if mm is not None: mdict = mm.groupdict() if mdict['a'] == '1': # absolute #print "MA: ",mdict['x'],mdict['y'],mdict['z'],mdict['b'] mouse.putMouseEventAbsolute(int(mdict['x']), int(mdict['y']), int(mdict['z']), int(mdict['w']), int(mdict['b'])) else: #print "MR: ",mdict['x'],mdict['y'],mdict['b'] mouse.putMouseEvent(int(mdict['x']), int(mdict['y']), int(mdict['z']), int(mdict['w']), int(mdict['b'])) # We need to catch all exceptions here, to close file except KeyboardInterrupt: ctx['interrupt'] = True except: traceback.print_exc() pass demo.close() def takeScreenshotOld(ctx,console,args): from PIL import Image display = console.display if len(args) > 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 takeScreenshot(ctx,console,args): display = console.display if len(args) > 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.takeScreenShotPNGToArray(screen, w,h) size = (w,h) file = open(f, 'wb') file.write(data) file.close() 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['const'].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, colPath(ctx,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): session = None try: vb = ctx['vb'] session = ctx['mgr'].getSessionObject(vb) mach.lockMachine(session, ctx['global'].constants.LockType_Shared) 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['const'].SessionState_Locked: print "Session to '%s' in wrong state: %s" %(mach.name, session.state) session.unlockMachine() 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.unlockMachine() 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:]), '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 KeyboardInterrupt: ctx['interrupt'] = True except Exception, e: printErr(ctx,e) if g_verbose: traceback.print_exc() session.unlockMachine() def cmdClosedVm(ctx,mach,cmd,args=[],save=True): session = ctx['global'].openMachineSession(mach, True) mach = session.machine try: cmd(ctx, mach, args) except Exception, e: save = False printErr(ctx,e) if g_verbose: traceback.print_exc() if save: try: mach.saveSettings() except Exception, e: printErr(ctx,e) if g_verbose: traceback.print_exc() ctx['global'].closeMachineSession(session) def cmdAnyVm(ctx,mach,cmd, args=[],save=False): session = ctx['global'].openMachineSession(mach) 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): try: mach = ctx['vb'].getMachine(id) except: mach = ctx['vb'].findMachine(id) return mach class XPathNode: def __init__(self, parent, obj, type): self.parent = parent self.obj = obj self.type = type def lookup(self, subpath): children = self.enum() matches = [] for e in children: if e.matches(subpath): matches.append(e) return matches def enum(self): return [] def matches(self,subexp): if subexp == self.type: return True if not subexp.startswith(self.type): return False m = re.search(r"@(?P\w+)=(?P[^\'\[\]]+)", subexp) matches = False try: if m is not None: dict = m.groupdict() attr = dict['a'] val = dict['v'] matches = (str(getattr(self.obj, attr)) == val) except: pass return matches def apply(self, cmd): exec(cmd, {'obj':self.obj,'node':self,'ctx':self.getCtx()}, {}) def getCtx(self): if hasattr(self,'ctx'): return self.ctx return self.parent.getCtx() class XPathNodeHolder(XPathNode): def __init__(self, parent, obj, attr, heldClass, xpathname): XPathNode.__init__(self, parent, obj, 'hld '+xpathname) self.attr = attr self.heldClass = heldClass self.xpathname = xpathname def enum(self): children = [] for n in self.getCtx()['global'].getArray(self.obj, self.attr): node = self.heldClass(self, n) children.append(node) return children def matches(self,subexp): return subexp == self.xpathname class XPathNodeValue(XPathNode): def __init__(self, parent, obj, xpathname): XPathNode.__init__(self, parent, obj, 'val '+xpathname) self.xpathname = xpathname def matches(self,subexp): return subexp == self.xpathname class XPathNodeHolderVM(XPathNodeHolder): def __init__(self, parent, vbox): XPathNodeHolder.__init__(self, parent, vbox, 'machines', XPathNodeVM, 'vms') class XPathNodeVM(XPathNode): def __init__(self, parent, obj): XPathNode.__init__(self, parent, obj, 'vm') #def matches(self,subexp): # return subexp=='vm' def enum(self): return [XPathNodeHolderNIC(self, self.obj), XPathNodeValue(self, self.obj.BIOSSettings, 'bios'), XPathNodeValue(self, self.obj.USBController, 'usb')] class XPathNodeHolderNIC(XPathNodeHolder): def __init__(self, parent, mach): XPathNodeHolder.__init__(self, parent, mach, 'nics', XPathNodeVM, 'nics') self.maxNic = self.getCtx()['vb'].systemProperties.getMaxNetworkAdapters(self.obj.chipsetType) def enum(self): children = [] for i in range(0, self.maxNic): node = XPathNodeNIC(self, self.obj.getNetworkAdapter(i)) children.append(node) return children class XPathNodeNIC(XPathNode): def __init__(self, parent, obj): XPathNode.__init__(self, parent, obj, 'nic') def matches(self,subexp): return subexp=='nic' class XPathNodeRoot(XPathNode): def __init__(self, ctx): XPathNode.__init__(self, None, None, 'root') self.ctx = ctx def enum(self): return [XPathNodeHolderVM(self, self.ctx['vb'])] def matches(self,subexp): return True def eval_xpath(ctx,scope): pathnames = scope.split("/")[2:] nodes = [XPathNodeRoot(ctx)] for p in pathnames: seen = [] while len(nodes) > 0: n = nodes.pop() seen.append(n) for s in seen: matches = s.lookup(p) for m in matches: nodes.append(m) if len(nodes) == 0: break return nodes 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['const'].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['const'].all_values(enum) return all.get(str, None) def listCmd(ctx, args): for m in getMachines(ctx, True): try: 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)) except Exception, e: printErr(ctx,e) if g_verbose: traceback.print_exc() 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 " Chipset [chipsetType]: %s (%s)" %(asEnumElem(ctx,"ChipsetType", mach.chipsetType), mach.chipsetType) 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 [guest win machine.setHWVirtExProperty(ctx[\\'const\\'].HWVirtExPropertyType_Enabled,value)]: " + asState(hwVirtEnabled) hwVirtVPID = mach.getHWVirtExProperty(ctx['const'].HWVirtExPropertyType_VPID) print " VPID support [guest win machine.setHWVirtExProperty(ctx[\\'const\\'].HWVirtExPropertyType_VPID,value)]: " + asState(hwVirtVPID) hwVirtNestedPaging = mach.getHWVirtExProperty(ctx['const'].HWVirtExPropertyType_NestedPaging) print " Nested paging [guest win machine.setHWVirtExProperty(ctx[\\'const\\'].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)) # OSE has no VRDE try: print " VRDE server [VRDEServer.enabled]: %s" %(asState(mach.VRDEServer.enabled)) except: pass print print colCat(ctx," I/O subsystem info:") print " Cache enabled [ioCacheEnabled]: %s" %(asState(mach.ioCacheEnabled)) print " Cache size [ioCacheSize]: %dM" %(mach.ioCacheSize) 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" %(colPath(ctx,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" %(colPath(ctx,m.location)) if a.passthrough: print " [passthrough mode]" else: print " Virtual image at %s" %(colPath(ctx,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" %(colPath(ctx,m.location)) else: print " Virtual image at %s" %(colPath(ctx,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): if len(args) < 2: print "usage: start name " return 0 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): print "usage: createvm name ostype" return 0 name = args[1] oskind = args[2] try: ctx['vb'].getGuestOSType(oskind) except Exception, e: print 'Unknown OS type:',oskind return 0 createVm(ctx, name, oskind) 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,user,passwd,tmo,inputPipe=None,outputPipe=None): if len(args) < 1: print "exec in guest needs at least program name" return guest = console.guest # shall contain program name as argv[0] gargs = args print "executing %s with args %s as %s" %(args[0], gargs, user) flags = 0 if inputPipe is not None: flags = 1 # set WaitForProcessStartOnly print args[0] (progress, pid) = guest.executeProcess(args[0], flags, gargs, env, user, passwd, tmo) print "executed with pid %d" %(pid) if pid != 0: try: while True: if inputPipe is not None: indata = inputPipe(ctx) if indata is not None: write = len(indata) off = 0 while write > 0: w = guest.setProcessInput(pid, 0, 10*1000, indata[off:]) off = off + w write = write - w else: # EOF try: guest.setProcessInput(pid, 1, 10*1000, " ") except: pass data = guest.getProcessOutput(pid, 0, 10000, 4096) if data and len(data) > 0: sys.stdout.write(data) continue progress.waitForCompletion(100) ctx['global'].waitForEvents(0) data = guest.getProcessOutput(pid, 0, 0, 4096) if data and len(data) > 0: if outputPipe is not None: outputPipe(ctx,data) else: sys.stdout.write(data) continue if progress.completed: break except KeyboardInterrupt: print "Interrupted." ctx['interrupt'] = True if progress.cancelable: progress.cancel() (reason, code, flags) = guest.getProcessStatus(pid) print "Exit code: %d" %(code) return 0 else: reportError(ctx, progress) def copyToGuest(ctx,console,args,user,passwd): src = args[0] dst = args[1] flags = 0 print "Copying host %s to guest %s" %(src,dst) progress = console.guest.copyToGuest(src, dst, user, passwd, flags) progressBar(ctx, progress) def nh_raw_input(prompt=""): stream = sys.stdout prompt = str(prompt) if prompt: stream.write(prompt) line = sys.stdin.readline() if not line: raise EOFError if line[-1] == '\n': line = line[:-1] return line def getCred(ctx): import getpass user = getpass.getuser() user_inp = nh_raw_input("User (%s): " %(user)) if len (user_inp) > 0: user = user_inp passwd = getpass.getpass() return (user,passwd) 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"] (user,passwd) = getCred(ctx) gargs.insert(0, lambda ctx,mach,console,args: execInGuest(ctx,console,args,env,user,passwd,10000)) cmdExistingVm(ctx, mach, 'guestlambda', gargs) return 0 def gcopyCmd(ctx,args): if (len(args) < 2): print "usage: gcopy [vmname|uuid] host_path guest_path" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 gargs = args[2:] (user,passwd) = getCred(ctx) gargs.insert(0, lambda ctx,mach,console,args: copyToGuest(ctx,console,args,user,passwd)) cmdExistingVm(ctx, mach, 'guestlambda', gargs) return 0 def readCmdPipe(ctx,hcmd): try: return ctx['process'].communicate()[0] except: return None def gpipeCmd(ctx,args): if (len(args) < 4): print "usage: gpipe [vmname|uuid] hostProgram guestProgram, such as gpipe linux '/bin/uname -a' '/bin/sh -c \"/usr/bin/tee; /bin/uname -a\"'" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 hcmd = args[2] gcmd = args[3] (user,passwd) = getCred(ctx) import subprocess ctx['process'] = subprocess.Popen(split_no_quotes(hcmd), stdout=subprocess.PIPE) gargs = split_no_quotes(gcmd) env = [] gargs.insert(0, lambda ctx,mach,console,args: execInGuest(ctx,console,args,env,user,passwd, 10000,lambda ctx:readCmdPipe(ctx, hcmd))) cmdExistingVm(ctx, mach, 'guestlambda', gargs) try: ctx['process'].terminate() except: pass ctx['process'] = None 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 if mach.state != ctx['const'].MachineState_Running: cmdClosedVm(ctx, mach, lambda ctx, mach, a: guestExec (ctx, mach, None, ' '.join(args[2:]))) else: 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['const'].SessionState_Locked): 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['const'].SessionState_Locked): 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 if (len(args) > 1): g_verbose = (args[1]=='on') else: g_verbose = not g_verbose return 0 def colorsCmd(ctx, args): global g_hascolors if (len(args) > 1): g_hascolors = (args[1]=='on') else: 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 "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]) active = False cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: monitorSource(ctx, console.eventSource, active, dur)]) return 0 def monitorGuestKbdCmd(ctx, args): if (len(args) < 2): print "usage: monitorGuestKbd name (duration)" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 dur = 5 if len(args) > 2: dur = float(args[2]) active = False cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: monitorSource(ctx, console.keyboard.eventSource, active, dur)]) return 0 def monitorGuestMouseCmd(ctx, args): if (len(args) < 2): print "usage: monitorGuestMouse name (duration)" return 0 mach = argsToMach(ctx,args) if mach == None: return 0 dur = 5 if len(args) > 2: dur = float(args[2]) active = False cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: monitorSource(ctx, console.mouse.eventSource, active, 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]) vbox = ctx['vb'] active = False monitorSource(ctx, vbox.eventSource, active, 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) 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.unlockMachine() 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 findAssertCmd(ctx, args): if (len(args) < 2): print "usage: findAssert vm " return 0 mach = argsToMach(ctx,args) if mach == None: return 0 log = 0 if (len(args) > 2): log = args[2] uOffset = 0 ere = re.compile(r'(Expression:|\!\!\!\!\!\!)') active = False context = 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: if active: print s if context == 0: active = False else: context = context - 1 continue m = ere.findall(s) if len(m) > 0: active = True context = 50 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