VirtualBox

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

Last change on this file since 29544 was 29544, checked in by vboxsync, 15 years ago

vboxshell: executeProcess() signature changed

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 84.1 KB
Line 
1#!/usr/bin/python
2#
3# Copyright (C) 2009-2010 Oracle Corporation
4#
5# This file is part of VirtualBox Open Source Edition (OSE), as
6# available from http://www.virtualbox.org. This file is free software;
7# you can redistribute it and/or modify it under the terms of the GNU
8# General Public License (GPL) as published by the Free Software
9# Foundation, in version 2 as it comes in the "COPYING" file of the
10# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
11# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
12#
13#################################################################################
14# This program is a simple interactive shell for VirtualBox. You can query #
15# information and issue commands from a simple command line. #
16# #
17# It also provides you with examples on how to use VirtualBox's Python API. #
18# This shell is even somewhat documented, supports TAB-completion and #
19# history if you have Python readline installed. #
20# #
21# Finally, shell allows arbitrary custom extensions, just create #
22# .VirtualBox/shexts/ and drop your extensions there. #
23# Enjoy. #
24################################################################################
25
26import os,sys
27import traceback
28import shlex
29import time
30import re
31import platform
32
33# Simple implementation of IConsoleCallback, one can use it as skeleton
34# for custom implementations
35class GuestMonitor:
36 def __init__(self, mach):
37 self.mach = mach
38
39 def onMousePointerShapeChange(self, visible, alpha, xHot, yHot, width, height, shape):
40 print "%s: onMousePointerShapeChange: visible=%d shape=%d bytes" %(self.mach.name, visible,len(shape))
41
42 def onMouseCapabilityChange(self, supportsAbsolute, supportsRelative, needsHostCursor):
43 print "%s: onMouseCapabilityChange: supportsAbsolute = %d, supportsRelative = %d, needsHostCursor = %d" %(self.mach.name, supportsAbsolute, supportsRelative, needsHostCursor)
44
45 def onKeyboardLedsChange(self, numLock, capsLock, scrollLock):
46 print "%s: onKeyboardLedsChange capsLock=%d" %(self.mach.name, capsLock)
47
48 def onStateChange(self, state):
49 print "%s: onStateChange state=%d" %(self.mach.name, state)
50
51 def onAdditionsStateChange(self):
52 print "%s: onAdditionsStateChange" %(self.mach.name)
53
54 def onNetworkAdapterChange(self, adapter):
55 print "%s: onNetworkAdapterChange" %(self.mach.name)
56
57 def onSerialPortChange(self, port):
58 print "%s: onSerialPortChange" %(self.mach.name)
59
60 def onParallelPortChange(self, port):
61 print "%s: onParallelPortChange" %(self.mach.name)
62
63 def onStorageControllerChange(self):
64 print "%s: onStorageControllerChange" %(self.mach.name)
65
66 def onMediumChange(self, attachment):
67 print "%s: onMediumChange" %(self.mach.name)
68
69 def onVRDPServerChange(self):
70 print "%s: onVRDPServerChange" %(self.mach.name)
71
72 def onUSBControllerChange(self):
73 print "%s: onUSBControllerChange" %(self.mach.name)
74
75 def onUSBDeviceStateChange(self, device, attached, error):
76 print "%s: onUSBDeviceStateChange" %(self.mach.name)
77
78 def onSharedFolderChange(self, scope):
79 print "%s: onSharedFolderChange" %(self.mach.name)
80
81 def onRuntimeError(self, fatal, id, message):
82 print "%s: onRuntimeError fatal=%d message=%s" %(self.mach.name, fatal, message)
83
84 def onCanShowWindow(self):
85 print "%s: onCanShowWindow" %(self.mach.name)
86 return True
87
88 def onShowWindow(self, winId):
89 print "%s: onShowWindow: %d" %(self.mach.name, winId)
90
91class VBoxMonitor:
92 def __init__(self, params):
93 self.vbox = params[0]
94 self.isMscom = params[1]
95 pass
96
97 def onMachineStateChange(self, id, state):
98 print "onMachineStateChange: %s %d" %(id, state)
99
100 def onMachineDataChange(self,id):
101 print "onMachineDataChange: %s" %(id)
102
103 def onExtraDataCanChange(self, id, key, value):
104 print "onExtraDataCanChange: %s %s=>%s" %(id, key, value)
105 # Witty COM bridge thinks if someone wishes to return tuple, hresult
106 # is one of values we want to return
107 if self.isMscom:
108 return "", 0, True
109 else:
110 return True, ""
111
112 def onExtraDataChange(self, id, key, value):
113 print "onExtraDataChange: %s %s=>%s" %(id, key, value)
114
115 def onMediaRegistered(self, id, type, registered):
116 print "onMediaRegistered: %s" %(id)
117
118 def onMachineRegistered(self, id, registred):
119 print "onMachineRegistered: %s" %(id)
120
121 def onSessionStateChange(self, id, state):
122 print "onSessionStateChange: %s %d" %(id, state)
123
124 def onSnapshotTaken(self, mach, id):
125 print "onSnapshotTaken: %s %s" %(mach, id)
126
127 def onSnapshotDeleted(self, mach, id):
128 print "onSnapshotDeleted: %s %s" %(mach, id)
129
130 def onSnapshotChange(self, mach, id):
131 print "onSnapshotChange: %s %s" %(mach, id)
132
133 def onGuestPropertyChange(self, id, name, newValue, flags):
134 print "onGuestPropertyChange: %s: %s=%s" %(id, name, newValue)
135
136g_hasreadline = True
137try:
138 import readline
139 import rlcompleter
140except:
141 g_hasreadline = False
142
143
144g_hascolors = True
145term_colors = {
146 'red':'\033[31m',
147 'blue':'\033[94m',
148 'green':'\033[92m',
149 'yellow':'\033[93m',
150 'magenta':'\033[35m'
151 }
152def colored(string,color):
153 if not g_hascolors:
154 return string
155 global term_colors
156 col = term_colors.get(color,None)
157 if col:
158 return col+str(string)+'\033[0m'
159 else:
160 return string
161
162if g_hasreadline:
163 import string
164 class CompleterNG(rlcompleter.Completer):
165 def __init__(self, dic, ctx):
166 self.ctx = ctx
167 return rlcompleter.Completer.__init__(self,dic)
168
169 def complete(self, text, state):
170 """
171 taken from:
172 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
173 """
174 if False and text == "":
175 return ['\t',None][state]
176 else:
177 return rlcompleter.Completer.complete(self,text,state)
178
179 def canBeCommand(self, phrase, word):
180 spaceIdx = phrase.find(" ")
181 begIdx = readline.get_begidx()
182 firstWord = (spaceIdx == -1 or begIdx < spaceIdx)
183 if firstWord:
184 return True
185 if phrase.startswith('help'):
186 return True
187 return False
188
189 def canBeMachine(self,phrase,word):
190 return not self.canBeCommand(phrase, word)
191
192 def global_matches(self, text):
193 """
194 Compute matches when text is a simple name.
195 Return a list of all names currently defined
196 in self.namespace that match.
197 """
198
199 matches = []
200 n = len(text)
201 phrase = readline.get_line_buffer()
202
203 if self.canBeCommand(phrase,text):
204 for list in [ self.namespace ]:
205 for word in list:
206 if word[:n] == text:
207 matches.append(word)
208 try:
209 if self.canBeMachine(phrase,text):
210 for m in getMachines(self.ctx, False, True):
211 # although it has autoconversion, we need to cast
212 # explicitly for subscripts to work
213 word = re.sub("(?<!\\\\) ", "\\ ", str(m.name))
214 if word[:n] == text:
215 matches.append(word)
216 word = str(m.id)
217 if word[0] == '{':
218 word = word[1:-1]
219 if word[:n] == text:
220 matches.append(word)
221 except Exception,e:
222 printErr(e)
223 if g_verbose:
224 traceback.print_exc()
225
226 return matches
227
228def autoCompletion(commands, ctx):
229 if not g_hasreadline:
230 return
231
232 comps = {}
233 for (k,v) in commands.items():
234 comps[k] = None
235 completer = CompleterNG(comps, ctx)
236 readline.set_completer(completer.complete)
237 delims = readline.get_completer_delims()
238 readline.set_completer_delims(re.sub("[\\.]", "", delims)) # remove some of the delimiters
239 readline.parse_and_bind("set editing-mode emacs")
240 # OSX need it
241 if platform.system() == 'Darwin':
242 # see http://www.certif.com/spec_help/readline.html
243 readline.parse_and_bind ("bind ^I rl_complete")
244 readline.parse_and_bind ("bind ^W ed-delete-prev-word")
245 # Doesn't work well
246 # readline.parse_and_bind ("bind ^R em-inc-search-prev")
247 readline.parse_and_bind("tab: complete")
248
249
250g_verbose = False
251
252def split_no_quotes(s):
253 return shlex.split(s)
254
255def progressBar(ctx,p,wait=1000):
256 try:
257 while not p.completed:
258 print "%s %%\r" %(colored(str(p.percent),'red')),
259 sys.stdout.flush()
260 p.waitForCompletion(wait)
261 ctx['global'].waitForEvents(0)
262 return 1
263 except KeyboardInterrupt:
264 print "Interrupted."
265 if p.cancelable:
266 print "Canceling task..."
267 p.cancel()
268 return 0
269
270def printErr(ctx,e):
271 print colored(str(e), 'red')
272
273def reportError(ctx,progress):
274 ei = progress.errorInfo
275 if ei:
276 print colored("Error in %s: %s" %(ei.component, ei.text), 'red')
277
278def colCat(ctx,str):
279 return colored(str, 'magenta')
280
281def colVm(ctx,vm):
282 return colored(vm, 'blue')
283
284def colPath(ctx,vm):
285 return colored(vm, 'green')
286
287
288def createVm(ctx,name,kind,base):
289 mgr = ctx['mgr']
290 vb = ctx['vb']
291 mach = vb.createMachine(name, kind, base, "", False)
292 mach.saveSettings()
293 print "created machine with UUID",mach.id
294 vb.registerMachine(mach)
295 # update cache
296 getMachines(ctx, True)
297
298def removeVm(ctx,mach):
299 mgr = ctx['mgr']
300 vb = ctx['vb']
301 id = mach.id
302 print "removing machine ",mach.name,"with UUID",id
303 cmdClosedVm(ctx, mach, detachVmDevice, ["ALL"])
304 mach = vb.unregisterMachine(id)
305 if mach:
306 mach.deleteSettings()
307 # update cache
308 getMachines(ctx, True)
309
310def startVm(ctx,mach,type):
311 mgr = ctx['mgr']
312 vb = ctx['vb']
313 perf = ctx['perf']
314 session = mgr.getSessionObject(vb)
315 uuid = mach.id
316 progress = vb.openRemoteSession(session, uuid, type, "")
317 if progressBar(ctx, progress, 100) and int(progress.resultCode) == 0:
318 # we ignore exceptions to allow starting VM even if
319 # perf collector cannot be started
320 if perf:
321 try:
322 perf.setup(['*'], [mach], 10, 15)
323 except Exception,e:
324 printErr(ctx, e)
325 if g_verbose:
326 traceback.print_exc()
327 # if session not opened, close doesn't make sense
328 session.close()
329 else:
330 reportError(ctx,progress)
331
332class CachedMach:
333 def __init__(self, mach):
334 self.name = mach.name
335 self.id = mach.id
336
337def cacheMachines(ctx,list):
338 result = []
339 for m in list:
340 elem = CachedMach(m)
341 result.append(elem)
342 return result
343
344def getMachines(ctx, invalidate = False, simple=False):
345 if ctx['vb'] is not None:
346 if ctx['_machlist'] is None or invalidate:
347 ctx['_machlist'] = ctx['global'].getArray(ctx['vb'], 'machines')
348 ctx['_machlistsimple'] = cacheMachines(ctx,ctx['_machlist'])
349 if simple:
350 return ctx['_machlistsimple']
351 else:
352 return ctx['_machlist']
353 else:
354 return []
355
356def asState(var):
357 if var:
358 return colored('on', 'green')
359 else:
360 return colored('off', 'green')
361
362def asFlag(var):
363 if var:
364 return 'yes'
365 else:
366 return 'no'
367
368def perfStats(ctx,mach):
369 if not ctx['perf']:
370 return
371 for metric in ctx['perf'].query(["*"], [mach]):
372 print metric['name'], metric['values_as_string']
373
374def guestExec(ctx, machine, console, cmds):
375 exec cmds
376
377def monitorGuest(ctx, machine, console, dur):
378 cb = ctx['global'].createCallback('IConsoleCallback', GuestMonitor, machine)
379 console.registerCallback(cb)
380 if dur == -1:
381 # not infinity, but close enough
382 dur = 100000
383 try:
384 end = time.time() + dur
385 while time.time() < end:
386 ctx['global'].waitForEvents(500)
387 # We need to catch all exceptions here, otherwise callback will never be unregistered
388 except:
389 pass
390 console.unregisterCallback(cb)
391
392
393def monitorVBox(ctx, dur):
394 vbox = ctx['vb']
395 isMscom = (ctx['global'].type == 'MSCOM')
396 cb = ctx['global'].createCallback('IVirtualBoxCallback', VBoxMonitor, [vbox, isMscom])
397 vbox.registerCallback(cb)
398 if dur == -1:
399 # not infinity, but close enough
400 dur = 100000
401 try:
402 end = time.time() + dur
403 while time.time() < end:
404 ctx['global'].waitForEvents(500)
405 # We need to catch all exceptions here, otherwise callback will never be unregistered
406 except:
407 pass
408 vbox.unregisterCallback(cb)
409
410
411def takeScreenshot(ctx,console,args):
412 from PIL import Image
413 display = console.display
414 if len(args) > 0:
415 f = args[0]
416 else:
417 f = "/tmp/screenshot.png"
418 if len(args) > 3:
419 screen = int(args[3])
420 else:
421 screen = 0
422 (fbw, fbh, fbbpp) = display.getScreenResolution(screen)
423 if len(args) > 1:
424 w = int(args[1])
425 else:
426 w = fbw
427 if len(args) > 2:
428 h = int(args[2])
429 else:
430 h = fbh
431
432 print "Saving screenshot (%d x %d) screen %d in %s..." %(w,h,screen,f)
433 data = display.takeScreenShotToArray(screen, w,h)
434 size = (w,h)
435 mode = "RGBA"
436 im = Image.frombuffer(mode, size, str(data), "raw", mode, 0, 1)
437 im.save(f, "PNG")
438
439
440def teleport(ctx,session,console,args):
441 if args[0].find(":") == -1:
442 print "Use host:port format for teleport target"
443 return
444 (host,port) = args[0].split(":")
445 if len(args) > 1:
446 passwd = args[1]
447 else:
448 passwd = ""
449
450 if len(args) > 2:
451 maxDowntime = int(args[2])
452 else:
453 maxDowntime = 250
454
455 port = int(port)
456 print "Teleporting to %s:%d..." %(host,port)
457 progress = console.teleport(host, port, passwd, maxDowntime)
458 if progressBar(ctx, progress, 100) and int(progress.resultCode) == 0:
459 print "Success!"
460 else:
461 reportError(ctx,progress)
462
463
464def guestStats(ctx,console,args):
465 guest = console.guest
466 # we need to set up guest statistics
467 if len(args) > 0 :
468 update = args[0]
469 else:
470 update = 1
471 if guest.statisticsUpdateInterval != update:
472 guest.statisticsUpdateInterval = update
473 try:
474 time.sleep(float(update)+0.1)
475 except:
476 # to allow sleep interruption
477 pass
478 all_stats = ctx['ifaces'].all_values('GuestStatisticType')
479 cpu = 0
480 for s in all_stats.keys():
481 try:
482 val = guest.getStatistic( cpu, all_stats[s])
483 print "%s: %d" %(s, val)
484 except:
485 # likely not implemented
486 pass
487
488def plugCpu(ctx,machine,session,args):
489 cpu = int(args[0])
490 print "Adding CPU %d..." %(cpu)
491 machine.hotPlugCPU(cpu)
492
493def unplugCpu(ctx,machine,session,args):
494 cpu = int(args[0])
495 print "Removing CPU %d..." %(cpu)
496 machine.hotUnplugCPU(cpu)
497
498def mountIso(ctx,machine,session,args):
499 machine.mountMedium(args[0], args[1], args[2], args[3], args[4])
500 machine.saveSettings()
501
502def cond(c,v1,v2):
503 if c:
504 return v1
505 else:
506 return v2
507
508def printHostUsbDev(ctx,ud):
509 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))
510
511def printUsbDev(ctx,ud):
512 print " %s: %s (vendorId=%d productId=%d serial=%s)" %(ud.id, colored(ud.product,'blue'), ud.vendorId, ud.productId, ud.serialNumber)
513
514def printSf(ctx,sf):
515 print " name=%s host=%s %s %s" %(sf.name, sf.hostPath, cond(sf.accessible, "accessible", "not accessible"), cond(sf.writable, "writable", "read-only"))
516
517def ginfo(ctx,console, args):
518 guest = console.guest
519 if guest.additionsActive:
520 vers = int(str(guest.additionsVersion))
521 print "Additions active, version %d.%d" %(vers >> 16, vers & 0xffff)
522 print "Support seamless: %s" %(asFlag(guest.supportsSeamless))
523 print "Support graphics: %s" %(asFlag(guest.supportsGraphics))
524 print "Baloon size: %d" %(guest.memoryBalloonSize)
525 print "Statistic update interval: %d" %(guest.statisticsUpdateInterval)
526 else:
527 print "No additions"
528 usbs = ctx['global'].getArray(console, 'USBDevices')
529 print "Attached USB:"
530 for ud in usbs:
531 printUsbDev(ctx,ud)
532 rusbs = ctx['global'].getArray(console, 'remoteUSBDevices')
533 print "Remote USB:"
534 for ud in rusbs:
535 printHostUsbDev(ctx,ud)
536 print "Transient shared folders:"
537 sfs = rusbs = ctx['global'].getArray(console, 'sharedFolders')
538 for sf in sfs:
539 printSf(ctx,sf)
540
541def cmdExistingVm(ctx,mach,cmd,args):
542 session = None
543 try:
544 vb = ctx['vb']
545 session = ctx['mgr'].getSessionObject(vb)
546 vb.openExistingSession(session, mach.id)
547 except Exception,e:
548 printErr(ctx, "Session to '%s' not open: %s" %(mach.name,str(e)))
549 if g_verbose:
550 traceback.print_exc()
551 return
552 if session.state != ctx['ifaces'].SessionState_Open:
553 print "Session to '%s' in wrong state: %s" %(mach.name, session.state)
554 session.close()
555 return
556 # this could be an example how to handle local only (i.e. unavailable
557 # in Webservices) functionality
558 if ctx['remote'] and cmd == 'some_local_only_command':
559 print 'Trying to use local only functionality, ignored'
560 session.close()
561 return
562 console=session.console
563 ops={'pause': lambda: console.pause(),
564 'resume': lambda: console.resume(),
565 'powerdown': lambda: console.powerDown(),
566 'powerbutton': lambda: console.powerButton(),
567 'stats': lambda: perfStats(ctx, mach),
568 'guest': lambda: guestExec(ctx, mach, console, args),
569 'ginfo': lambda: ginfo(ctx, console, args),
570 'guestlambda': lambda: args[0](ctx, mach, console, args[1:]),
571 'monitorGuest': lambda: monitorGuest(ctx, mach, console, args),
572 'save': lambda: progressBar(ctx,console.saveState()),
573 'screenshot': lambda: takeScreenshot(ctx,console,args),
574 'teleport': lambda: teleport(ctx,session,console,args),
575 'gueststats': lambda: guestStats(ctx, console, args),
576 'plugcpu': lambda: plugCpu(ctx, session.machine, session, args),
577 'unplugcpu': lambda: unplugCpu(ctx, session.machine, session, args),
578 'mountiso': lambda: mountIso(ctx, session.machine, session, args),
579 }
580 try:
581 ops[cmd]()
582 except Exception, e:
583 printErr(ctx,e)
584 if g_verbose:
585 traceback.print_exc()
586
587 session.close()
588
589
590def cmdClosedVm(ctx,mach,cmd,args=[],save=True):
591 session = ctx['global'].openMachineSession(mach.id)
592 mach = session.machine
593 try:
594 cmd(ctx, mach, args)
595 except Exception, e:
596 save = False
597 printErr(ctx,e)
598 if g_verbose:
599 traceback.print_exc()
600 if save:
601 mach.saveSettings()
602 ctx['global'].closeMachineSession(session)
603
604
605def cmdAnyVm(ctx,mach,cmd, args=[],save=False):
606 session = ctx['global'].openMachineSession(mach.id)
607 mach = session.machine
608 try:
609 cmd(ctx, mach, session.console, args)
610 except Exception, e:
611 save = False;
612 printErr(ctx,e)
613 if g_verbose:
614 traceback.print_exc()
615 if save:
616 mach.saveSettings()
617 ctx['global'].closeMachineSession(session)
618
619def machById(ctx,id):
620 mach = None
621 for m in getMachines(ctx):
622 if m.name == id:
623 mach = m
624 break
625 mid = str(m.id)
626 if mid[0] == '{':
627 mid = mid[1:-1]
628 if mid == id:
629 mach = m
630 break
631 return mach
632
633def argsToMach(ctx,args):
634 if len(args) < 2:
635 print "usage: %s [vmname|uuid]" %(args[0])
636 return None
637 id = args[1]
638 m = machById(ctx, id)
639 if m == None:
640 print "Machine '%s' is unknown, use list command to find available machines" %(id)
641 return m
642
643def helpSingleCmd(cmd,h,sp):
644 if sp != 0:
645 spec = " [ext from "+sp+"]"
646 else:
647 spec = ""
648 print " %s: %s%s" %(colored(cmd,'blue'),h,spec)
649
650def helpCmd(ctx, args):
651 if len(args) == 1:
652 print "Help page:"
653 names = commands.keys()
654 names.sort()
655 for i in names:
656 helpSingleCmd(i, commands[i][0], commands[i][2])
657 else:
658 cmd = args[1]
659 c = commands.get(cmd)
660 if c == None:
661 print "Command '%s' not known" %(cmd)
662 else:
663 helpSingleCmd(cmd, c[0], c[2])
664 return 0
665
666def asEnumElem(ctx,enum,elem):
667 all = ctx['ifaces'].all_values(enum)
668 for e in all.keys():
669 if str(elem) == str(all[e]):
670 return colored(e, 'green')
671 return colored("<unknown>", 'green')
672
673def enumFromString(ctx,enum,str):
674 all = ctx['ifaces'].all_values(enum)
675 return all.get(str, None)
676
677def listCmd(ctx, args):
678 for m in getMachines(ctx, True):
679 if m.teleporterEnabled:
680 tele = "[T] "
681 else:
682 tele = " "
683 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))
684 return 0
685
686def infoCmd(ctx,args):
687 if (len(args) < 2):
688 print "usage: info [vmname|uuid]"
689 return 0
690 mach = argsToMach(ctx,args)
691 if mach == None:
692 return 0
693 os = ctx['vb'].getGuestOSType(mach.OSTypeId)
694 print " One can use setvar <mach> <var> <value> to change variable, using name in []."
695 print " Name [name]: %s" %(colVm(ctx,mach.name))
696 print " Description [description]: %s" %(mach.description)
697 print " ID [n/a]: %s" %(mach.id)
698 print " OS Type [via OSTypeId]: %s" %(os.description)
699 print " Firmware [firmwareType]: %s (%s)" %(asEnumElem(ctx,"FirmwareType", mach.firmwareType),mach.firmwareType)
700 print
701 print " CPUs [CPUCount]: %d" %(mach.CPUCount)
702 print " RAM [memorySize]: %dM" %(mach.memorySize)
703 print " VRAM [VRAMSize]: %dM" %(mach.VRAMSize)
704 print " Monitors [monitorCount]: %d" %(mach.monitorCount)
705 print
706 print " Clipboard mode [clipboardMode]: %s (%s)" %(asEnumElem(ctx,"ClipboardMode", mach.clipboardMode), mach.clipboardMode)
707 print " Machine status [n/a]: %s (%s)" % (asEnumElem(ctx,"SessionState", mach.sessionState), mach.sessionState)
708 print
709 if mach.teleporterEnabled:
710 print " Teleport target on port %d (%s)" %(mach.teleporterPort, mach.teleporterPassword)
711 print
712 bios = mach.BIOSSettings
713 print " ACPI [BIOSSettings.ACPIEnabled]: %s" %(asState(bios.ACPIEnabled))
714 print " APIC [BIOSSettings.IOAPICEnabled]: %s" %(asState(bios.IOAPICEnabled))
715 hwVirtEnabled = mach.getHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_Enabled)
716 print " Hardware virtualization [mach.setHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_Enabled,value)]: " + asState(hwVirtEnabled)
717 hwVirtVPID = mach.getHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_VPID)
718 print " VPID support [mach.setHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_VPID,value)]: " + asState(hwVirtVPID)
719 hwVirtNestedPaging = mach.getHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_NestedPaging)
720 print " Nested paging [mach.setHWVirtExProperty(ctx['global'].constants.HWVirtExPropertyType_NestedPaging,value)]: " + asState(hwVirtNestedPaging)
721
722 print " Hardware 3d acceleration [accelerate3DEnabled]: " + asState(mach.accelerate3DEnabled)
723 print " Hardware 2d video acceleration [accelerate2DVideoEnabled]: " + asState(mach.accelerate2DVideoEnabled)
724
725 print " Use universal time [RTCUseUTC]: %s" %(asState(mach.RTCUseUTC))
726 print " HPET [hpetEnabled]: %s" %(asState(mach.hpetEnabled))
727 if mach.audioAdapter.enabled:
728 print " Audio [via audioAdapter]: chip %s; host driver %s" %(asEnumElem(ctx,"AudioControllerType", mach.audioAdapter.audioController), asEnumElem(ctx,"AudioDriverType", mach.audioAdapter.audioDriver))
729 if mach.USBController.enabled:
730 print " USB [via USBController]: high speed %s" %(asState(mach.USBController.enabledEhci))
731 print " CPU hotplugging [CPUHotPlugEnabled]: %s" %(asState(mach.CPUHotPlugEnabled))
732
733 print " Keyboard [keyboardHidType]: %s (%s)" %(asEnumElem(ctx,"KeyboardHidType", mach.keyboardHidType), mach.keyboardHidType)
734 print " Pointing device [pointingHidType]: %s (%s)" %(asEnumElem(ctx,"PointingHidType", mach.pointingHidType), mach.pointingHidType)
735 print " Last changed [n/a]: " + time.asctime(time.localtime(long(mach.lastStateChange)/1000))
736 print " VRDP server [VRDPServer.enabled]: %s" %(asState(mach.VRDPServer.enabled))
737
738 print
739 print colCat(ctx," I/O subsystem info:")
740 print " Cache enabled [ioCacheEnabled]: %s" %(asState(mach.ioCacheEnabled))
741 print " Cache size [ioCacheSize]: %dM" %(mach.ioCacheSize)
742 print " Bandwidth limit [ioBandwidthMax]: %dM/s" %(mach.ioBandwidthMax)
743
744 controllers = ctx['global'].getArray(mach, 'storageControllers')
745 if controllers:
746 print
747 print colCat(ctx," Controllers:")
748 for controller in controllers:
749 print " '%s': bus %s type %s" % (controller.name, asEnumElem(ctx,"StorageBus", controller.bus), asEnumElem(ctx,"StorageControllerType", controller.controllerType))
750
751 attaches = ctx['global'].getArray(mach, 'mediumAttachments')
752 if attaches:
753 print
754 print colCat(ctx," Media:")
755 for a in attaches:
756 print " Controller: '%s' port/device: %d:%d type: %s (%s):" % (a.controller, a.port, a.device, asEnumElem(ctx,"DeviceType", a.type), a.type)
757 m = a.medium
758 if a.type == ctx['global'].constants.DeviceType_HardDisk:
759 print " HDD:"
760 print " Id: %s" %(m.id)
761 print " Location: %s" %(m.location)
762 print " Name: %s" %(m.name)
763 print " Format: %s" %(m.format)
764
765 if a.type == ctx['global'].constants.DeviceType_DVD:
766 print " DVD:"
767 if m:
768 print " Id: %s" %(m.id)
769 print " Name: %s" %(m.name)
770 if m.hostDrive:
771 print " Host DVD %s" %(m.location)
772 if a.passthrough:
773 print " [passthrough mode]"
774 else:
775 print " Virtual image at %s" %(m.location)
776 print " Size: %s" %(m.size)
777
778 if a.type == ctx['global'].constants.DeviceType_Floppy:
779 print " Floppy:"
780 if m:
781 print " Id: %s" %(m.id)
782 print " Name: %s" %(m.name)
783 if m.hostDrive:
784 print " Host floppy %s" %(m.location)
785 else:
786 print " Virtual image at %s" %(m.location)
787 print " Size: %s" %(m.size)
788
789 print
790 print colCat(ctx," Shared folders:")
791 for sf in ctx['global'].getArray(mach, 'sharedFolders'):
792 printSf(ctx,sf)
793
794 return 0
795
796def startCmd(ctx, args):
797 mach = argsToMach(ctx,args)
798 if mach == None:
799 return 0
800 if len(args) > 2:
801 type = args[2]
802 else:
803 type = "gui"
804 startVm(ctx, mach, type)
805 return 0
806
807def createVmCmd(ctx, args):
808 if (len(args) < 3 or len(args) > 4):
809 print "usage: createvm name ostype <basefolder>"
810 return 0
811 name = args[1]
812 oskind = args[2]
813 if len(args) == 4:
814 base = args[3]
815 else:
816 base = ''
817 try:
818 ctx['vb'].getGuestOSType(oskind)
819 except Exception, e:
820 print 'Unknown OS type:',oskind
821 return 0
822 createVm(ctx, name, oskind, base)
823 return 0
824
825def ginfoCmd(ctx,args):
826 if (len(args) < 2):
827 print "usage: ginfo [vmname|uuid]"
828 return 0
829 mach = argsToMach(ctx,args)
830 if mach == None:
831 return 0
832 cmdExistingVm(ctx, mach, 'ginfo', '')
833 return 0
834
835def execInGuest(ctx,console,args,env):
836 if len(args) < 1:
837 print "exec in guest needs at least program name"
838 return
839 user = ""
840 passwd = ""
841 tmo = 0
842 guest = console.guest
843 # shall contain program name as argv[0]
844 gargs = args
845 print "executing %s with args %s" %(args[0], gargs)
846 (progress, pid) = guest.executeProcess(args[0], 0, gargs, env, user, passwd, tmo)
847 print "executed with pid %d" %(pid)
848 if pid != 0:
849 try:
850 while True:
851 data = guest.getProcessOutput(pid, 0, 1000, 4096)
852 if data and len(data) > 0:
853 sys.stdout.write(data)
854 continue
855 progress.waitForCompletion(100)
856 ctx['global'].waitForEvents(0)
857 if progress.completed:
858 break
859
860 except KeyboardInterrupt:
861 print "Interrupted."
862 if progress.cancelable:
863 progress.cancel()
864 return 0
865 else:
866 reportError(ctx, progress)
867
868def gexecCmd(ctx,args):
869 if (len(args) < 2):
870 print "usage: gexec [vmname|uuid] command args"
871 return 0
872 mach = argsToMach(ctx,args)
873 if mach == None:
874 return 0
875 gargs = args[2:]
876 env = [] # ["DISPLAY=:0"]
877 gargs.insert(0, lambda ctx,mach,console,args: execInGuest(ctx,console,args,env))
878 cmdExistingVm(ctx, mach, 'guestlambda', gargs)
879 return 0
880
881def gcatCmd(ctx,args):
882 if (len(args) < 2):
883 print "usage: gcat [vmname|uuid] local_file | guestProgram, such as gcat linux /home/nike/.bashrc | sh -c 'cat >'"
884 return 0
885 mach = argsToMach(ctx,args)
886 if mach == None:
887 return 0
888 gargs = args[2:]
889 env = []
890 gargs.insert(0, lambda ctx,mach,console,args: execInGuest(ctx,console,args,env))
891 cmdExistingVm(ctx, mach, 'guestlambda', gargs)
892 return 0
893
894
895def removeVmCmd(ctx, args):
896 mach = argsToMach(ctx,args)
897 if mach == None:
898 return 0
899 removeVm(ctx, mach)
900 return 0
901
902def pauseCmd(ctx, args):
903 mach = argsToMach(ctx,args)
904 if mach == None:
905 return 0
906 cmdExistingVm(ctx, mach, 'pause', '')
907 return 0
908
909def powerdownCmd(ctx, args):
910 mach = argsToMach(ctx,args)
911 if mach == None:
912 return 0
913 cmdExistingVm(ctx, mach, 'powerdown', '')
914 return 0
915
916def powerbuttonCmd(ctx, args):
917 mach = argsToMach(ctx,args)
918 if mach == None:
919 return 0
920 cmdExistingVm(ctx, mach, 'powerbutton', '')
921 return 0
922
923def resumeCmd(ctx, args):
924 mach = argsToMach(ctx,args)
925 if mach == None:
926 return 0
927 cmdExistingVm(ctx, mach, 'resume', '')
928 return 0
929
930def saveCmd(ctx, args):
931 mach = argsToMach(ctx,args)
932 if mach == None:
933 return 0
934 cmdExistingVm(ctx, mach, 'save', '')
935 return 0
936
937def statsCmd(ctx, args):
938 mach = argsToMach(ctx,args)
939 if mach == None:
940 return 0
941 cmdExistingVm(ctx, mach, 'stats', '')
942 return 0
943
944def guestCmd(ctx, args):
945 if (len(args) < 3):
946 print "usage: guest name commands"
947 return 0
948 mach = argsToMach(ctx,args)
949 if mach == None:
950 return 0
951 cmdExistingVm(ctx, mach, 'guest', ' '.join(args[2:]))
952 return 0
953
954def screenshotCmd(ctx, args):
955 if (len(args) < 2):
956 print "usage: screenshot vm <file> <width> <height> <monitor>"
957 return 0
958 mach = argsToMach(ctx,args)
959 if mach == None:
960 return 0
961 cmdExistingVm(ctx, mach, 'screenshot', args[2:])
962 return 0
963
964def teleportCmd(ctx, args):
965 if (len(args) < 3):
966 print "usage: teleport name host:port <password>"
967 return 0
968 mach = argsToMach(ctx,args)
969 if mach == None:
970 return 0
971 cmdExistingVm(ctx, mach, 'teleport', args[2:])
972 return 0
973
974def portalsettings(ctx,mach,args):
975 enabled = args[0]
976 mach.teleporterEnabled = enabled
977 if enabled:
978 port = args[1]
979 passwd = args[2]
980 mach.teleporterPort = port
981 mach.teleporterPassword = passwd
982
983def openportalCmd(ctx, args):
984 if (len(args) < 3):
985 print "usage: openportal name port <password>"
986 return 0
987 mach = argsToMach(ctx,args)
988 if mach == None:
989 return 0
990 port = int(args[2])
991 if (len(args) > 3):
992 passwd = args[3]
993 else:
994 passwd = ""
995 if not mach.teleporterEnabled or mach.teleporterPort != port or passwd:
996 cmdClosedVm(ctx, mach, portalsettings, [True, port, passwd])
997 startVm(ctx, mach, "gui")
998 return 0
999
1000def closeportalCmd(ctx, args):
1001 if (len(args) < 2):
1002 print "usage: closeportal name"
1003 return 0
1004 mach = argsToMach(ctx,args)
1005 if mach == None:
1006 return 0
1007 if mach.teleporterEnabled:
1008 cmdClosedVm(ctx, mach, portalsettings, [False])
1009 return 0
1010
1011def gueststatsCmd(ctx, args):
1012 if (len(args) < 2):
1013 print "usage: gueststats name <check interval>"
1014 return 0
1015 mach = argsToMach(ctx,args)
1016 if mach == None:
1017 return 0
1018 cmdExistingVm(ctx, mach, 'gueststats', args[2:])
1019 return 0
1020
1021def plugcpu(ctx,mach,args):
1022 plug = args[0]
1023 cpu = args[1]
1024 if plug:
1025 print "Adding CPU %d..." %(cpu)
1026 mach.hotPlugCPU(cpu)
1027 else:
1028 print "Removing CPU %d..." %(cpu)
1029 mach.hotUnplugCPU(cpu)
1030
1031def plugcpuCmd(ctx, args):
1032 if (len(args) < 2):
1033 print "usage: plugcpu name cpuid"
1034 return 0
1035 mach = argsToMach(ctx,args)
1036 if mach == None:
1037 return 0
1038 if str(mach.sessionState) != str(ctx['ifaces'].SessionState_Open):
1039 if mach.CPUHotPlugEnabled:
1040 cmdClosedVm(ctx, mach, plugcpu, [True, int(args[2])])
1041 else:
1042 cmdExistingVm(ctx, mach, 'plugcpu', args[2])
1043 return 0
1044
1045def unplugcpuCmd(ctx, args):
1046 if (len(args) < 2):
1047 print "usage: unplugcpu name cpuid"
1048 return 0
1049 mach = argsToMach(ctx,args)
1050 if mach == None:
1051 return 0
1052 if str(mach.sessionState) != str(ctx['ifaces'].SessionState_Open):
1053 if mach.CPUHotPlugEnabled:
1054 cmdClosedVm(ctx, mach, plugcpu, [False, int(args[2])])
1055 else:
1056 cmdExistingVm(ctx, mach, 'unplugcpu', args[2])
1057 return 0
1058
1059def setvar(ctx,mach,args):
1060 expr = 'mach.'+args[0]+' = '+args[1]
1061 print "Executing",expr
1062 exec expr
1063
1064def setvarCmd(ctx, args):
1065 if (len(args) < 4):
1066 print "usage: setvar [vmname|uuid] expr value"
1067 return 0
1068 mach = argsToMach(ctx,args)
1069 if mach == None:
1070 return 0
1071 cmdClosedVm(ctx, mach, setvar, args[2:])
1072 return 0
1073
1074def setvmextra(ctx,mach,args):
1075 key = args[0]
1076 value = args[1]
1077 print "%s: setting %s to %s" %(mach.name, key, value)
1078 mach.setExtraData(key, value)
1079
1080def setExtraDataCmd(ctx, args):
1081 if (len(args) < 3):
1082 print "usage: setextra [vmname|uuid|global] key <value>"
1083 return 0
1084 key = args[2]
1085 if len(args) == 4:
1086 value = args[3]
1087 else:
1088 value = None
1089 if args[1] == 'global':
1090 ctx['vb'].setExtraData(key, value)
1091 return 0
1092
1093 mach = argsToMach(ctx,args)
1094 if mach == None:
1095 return 0
1096 cmdClosedVm(ctx, mach, setvmextra, [key, value])
1097 return 0
1098
1099def printExtraKey(obj, key, value):
1100 print "%s: '%s' = '%s'" %(obj, key, value)
1101
1102def getExtraDataCmd(ctx, args):
1103 if (len(args) < 2):
1104 print "usage: getextra [vmname|uuid|global] <key>"
1105 return 0
1106 if len(args) == 3:
1107 key = args[2]
1108 else:
1109 key = None
1110
1111 if args[1] == 'global':
1112 obj = ctx['vb']
1113 else:
1114 obj = argsToMach(ctx,args)
1115 if obj == None:
1116 return 0
1117
1118 if key == None:
1119 keys = obj.getExtraDataKeys()
1120 else:
1121 keys = [ key ]
1122 for k in keys:
1123 printExtraKey(args[1], k, obj.getExtraData(k))
1124
1125 return 0
1126
1127def quitCmd(ctx, args):
1128 return 1
1129
1130def aliasCmd(ctx, args):
1131 if (len(args) == 3):
1132 aliases[args[1]] = args[2]
1133 return 0
1134
1135 for (k,v) in aliases.items():
1136 print "'%s' is an alias for '%s'" %(k,v)
1137 return 0
1138
1139def verboseCmd(ctx, args):
1140 global g_verbose
1141 g_verbose = not g_verbose
1142 return 0
1143
1144def colorsCmd(ctx, args):
1145 global g_hascolors
1146 g_hascolors = not g_hascolors
1147 return 0
1148
1149def hostCmd(ctx, args):
1150 vb = ctx['vb']
1151 print "VirtualBox version %s" %(colored(vb.version, 'blue'))
1152 props = vb.systemProperties
1153 print "Machines: %s" %(colPath(ctx,props.defaultMachineFolder))
1154 print "HDDs: %s" %(colPath(ctx,props.defaultHardDiskFolder))
1155
1156 #print "Global shared folders:"
1157 #for ud in ctx['global'].getArray(vb, 'sharedFolders'):
1158 # printSf(ctx,sf)
1159 host = vb.host
1160 cnt = host.processorCount
1161 print colCat(ctx,"Processors:")
1162 print " available/online: %d/%d " %(cnt,host.processorOnlineCount)
1163 for i in range(0,cnt):
1164 print " processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i))
1165
1166 print colCat(ctx, "RAM:")
1167 print " %dM (free %dM)" %(host.memorySize, host.memoryAvailable)
1168 print colCat(ctx,"OS:");
1169 print " %s (%s)" %(host.operatingSystem, host.OSVersion)
1170 if host.Acceleration3DAvailable:
1171 print colCat(ctx,"3D acceleration available")
1172 else:
1173 print colCat(ctx,"3D acceleration NOT available")
1174
1175 print colCat(ctx,"Network interfaces:")
1176 for ni in ctx['global'].getArray(host, 'networkInterfaces'):
1177 print " %s (%s)" %(ni.name, ni.IPAddress)
1178
1179 print colCat(ctx,"DVD drives:")
1180 for dd in ctx['global'].getArray(host, 'DVDDrives'):
1181 print " %s - %s" %(dd.name, dd.description)
1182
1183 print colCat(ctx,"Floppy drives:")
1184 for dd in ctx['global'].getArray(host, 'floppyDrives'):
1185 print " %s - %s" %(dd.name, dd.description)
1186
1187 print colCat(ctx,"USB devices:")
1188 for ud in ctx['global'].getArray(host, 'USBDevices'):
1189 printHostUsbDev(ctx,ud)
1190
1191 if ctx['perf']:
1192 for metric in ctx['perf'].query(["*"], [host]):
1193 print metric['name'], metric['values_as_string']
1194
1195 return 0
1196
1197def monitorGuestCmd(ctx, args):
1198 if (len(args) < 2):
1199 print "usage: monitorGuest name (duration)"
1200 return 0
1201 mach = argsToMach(ctx,args)
1202 if mach == None:
1203 return 0
1204 dur = 5
1205 if len(args) > 2:
1206 dur = float(args[2])
1207 cmdExistingVm(ctx, mach, 'monitorGuest', dur)
1208 return 0
1209
1210def monitorVBoxCmd(ctx, args):
1211 if (len(args) > 2):
1212 print "usage: monitorVBox (duration)"
1213 return 0
1214 dur = 5
1215 if len(args) > 1:
1216 dur = float(args[1])
1217 monitorVBox(ctx, dur)
1218 return 0
1219
1220def getAdapterType(ctx, type):
1221 if (type == ctx['global'].constants.NetworkAdapterType_Am79C970A or
1222 type == ctx['global'].constants.NetworkAdapterType_Am79C973):
1223 return "pcnet"
1224 elif (type == ctx['global'].constants.NetworkAdapterType_I82540EM or
1225 type == ctx['global'].constants.NetworkAdapterType_I82545EM or
1226 type == ctx['global'].constants.NetworkAdapterType_I82543GC):
1227 return "e1000"
1228 elif (type == ctx['global'].constants.NetworkAdapterType_Virtio):
1229 return "virtio"
1230 elif (type == ctx['global'].constants.NetworkAdapterType_Null):
1231 return None
1232 else:
1233 raise Exception("Unknown adapter type: "+type)
1234
1235
1236def portForwardCmd(ctx, args):
1237 if (len(args) != 5):
1238 print "usage: portForward <vm> <adapter> <hostPort> <guestPort>"
1239 return 0
1240 mach = argsToMach(ctx,args)
1241 if mach == None:
1242 return 0
1243 adapterNum = int(args[2])
1244 hostPort = int(args[3])
1245 guestPort = int(args[4])
1246 proto = "TCP"
1247 session = ctx['global'].openMachineSession(mach.id)
1248 mach = session.machine
1249
1250 adapter = mach.getNetworkAdapter(adapterNum)
1251 adapterType = getAdapterType(ctx, adapter.adapterType)
1252
1253 profile_name = proto+"_"+str(hostPort)+"_"+str(guestPort)
1254 config = "VBoxInternal/Devices/" + adapterType + "/"
1255 config = config + str(adapter.slot) +"/LUN#0/Config/" + profile_name
1256
1257 mach.setExtraData(config + "/Protocol", proto)
1258 mach.setExtraData(config + "/HostPort", str(hostPort))
1259 mach.setExtraData(config + "/GuestPort", str(guestPort))
1260
1261 mach.saveSettings()
1262 session.close()
1263
1264 return 0
1265
1266
1267def showLogCmd(ctx, args):
1268 if (len(args) < 2):
1269 print "usage: showLog vm <num>"
1270 return 0
1271 mach = argsToMach(ctx,args)
1272 if mach == None:
1273 return 0
1274
1275 log = 0
1276 if (len(args) > 2):
1277 log = args[2]
1278
1279 uOffset = 0
1280 while True:
1281 data = mach.readLog(log, uOffset, 4096)
1282 if (len(data) == 0):
1283 break
1284 # print adds either NL or space to chunks not ending with a NL
1285 sys.stdout.write(str(data))
1286 uOffset += len(data)
1287
1288 return 0
1289
1290def findLogCmd(ctx, args):
1291 if (len(args) < 3):
1292 print "usage: findLog vm pattern <num>"
1293 return 0
1294 mach = argsToMach(ctx,args)
1295 if mach == None:
1296 return 0
1297
1298 log = 0
1299 if (len(args) > 3):
1300 log = args[3]
1301
1302 pattern = args[2]
1303 uOffset = 0
1304 while True:
1305 # to reduce line splits on buffer boundary
1306 data = mach.readLog(log, uOffset, 512*1024)
1307 if (len(data) == 0):
1308 break
1309 d = str(data).split("\n")
1310 for s in d:
1311 m = re.findall(pattern, s)
1312 if len(m) > 0:
1313 for mt in m:
1314 s = s.replace(mt, colored(mt,'red'))
1315 print s
1316 uOffset += len(data)
1317
1318 return 0
1319
1320def evalCmd(ctx, args):
1321 expr = ' '.join(args[1:])
1322 try:
1323 exec expr
1324 except Exception, e:
1325 printErr(ctx,e)
1326 if g_verbose:
1327 traceback.print_exc()
1328 return 0
1329
1330def reloadExtCmd(ctx, args):
1331 # maybe will want more args smartness
1332 checkUserExtensions(ctx, commands, getHomeFolder(ctx))
1333 autoCompletion(commands, ctx)
1334 return 0
1335
1336
1337def runScriptCmd(ctx, args):
1338 if (len(args) != 2):
1339 print "usage: runScript <script>"
1340 return 0
1341 try:
1342 lf = open(args[1], 'r')
1343 except IOError,e:
1344 print "cannot open:",args[1], ":",e
1345 return 0
1346
1347 try:
1348 for line in lf:
1349 done = runCommand(ctx, line)
1350 if done != 0: break
1351 except Exception,e:
1352 printErr(ctx,e)
1353 if g_verbose:
1354 traceback.print_exc()
1355 lf.close()
1356 return 0
1357
1358def sleepCmd(ctx, args):
1359 if (len(args) != 2):
1360 print "usage: sleep <secs>"
1361 return 0
1362
1363 try:
1364 time.sleep(float(args[1]))
1365 except:
1366 # to allow sleep interrupt
1367 pass
1368 return 0
1369
1370
1371def shellCmd(ctx, args):
1372 if (len(args) < 2):
1373 print "usage: shell <commands>"
1374 return 0
1375 cmd = ' '.join(args[1:])
1376
1377 try:
1378 os.system(cmd)
1379 except KeyboardInterrupt:
1380 # to allow shell command interruption
1381 pass
1382 return 0
1383
1384
1385def connectCmd(ctx, args):
1386 if (len(args) > 4):
1387 print "usage: connect url <username> <passwd>"
1388 return 0
1389
1390 if ctx['vb'] is not None:
1391 print "Already connected, disconnect first..."
1392 return 0
1393
1394 if (len(args) > 1):
1395 url = args[1]
1396 else:
1397 url = None
1398
1399 if (len(args) > 2):
1400 user = args[2]
1401 else:
1402 user = ""
1403
1404 if (len(args) > 3):
1405 passwd = args[3]
1406 else:
1407 passwd = ""
1408
1409 ctx['wsinfo'] = [url, user, passwd]
1410 vbox = ctx['global'].platform.connect(url, user, passwd)
1411 ctx['vb'] = vbox
1412 print "Running VirtualBox version %s" %(vbox.version)
1413 ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
1414 return 0
1415
1416def disconnectCmd(ctx, args):
1417 if (len(args) != 1):
1418 print "usage: disconnect"
1419 return 0
1420
1421 if ctx['vb'] is None:
1422 print "Not connected yet."
1423 return 0
1424
1425 try:
1426 ctx['global'].platform.disconnect()
1427 except:
1428 ctx['vb'] = None
1429 raise
1430
1431 ctx['vb'] = None
1432 return 0
1433
1434def reconnectCmd(ctx, args):
1435 if ctx['wsinfo'] is None:
1436 print "Never connected..."
1437 return 0
1438
1439 try:
1440 ctx['global'].platform.disconnect()
1441 except:
1442 pass
1443
1444 [url,user,passwd] = ctx['wsinfo']
1445 ctx['vb'] = ctx['global'].platform.connect(url, user, passwd)
1446 print "Running VirtualBox version %s" %(ctx['vb'].version)
1447 return 0
1448
1449def exportVMCmd(ctx, args):
1450 import sys
1451
1452 if len(args) < 3:
1453 print "usage: exportVm <machine> <path> <format> <license>"
1454 return 0
1455 mach = argsToMach(ctx,args)
1456 if mach is None:
1457 return 0
1458 path = args[2]
1459 if (len(args) > 3):
1460 format = args[3]
1461 else:
1462 format = "ovf-1.0"
1463 if (len(args) > 4):
1464 license = args[4]
1465 else:
1466 license = "GPL"
1467
1468 app = ctx['vb'].createAppliance()
1469 desc = mach.export(app)
1470 desc.addDescription(ctx['global'].constants.VirtualSystemDescriptionType_License, license, "")
1471 p = app.write(format, path)
1472 if (progressBar(ctx, p) and int(p.resultCode) == 0):
1473 print "Exported to %s in format %s" %(path, format)
1474 else:
1475 reportError(ctx,p)
1476 return 0
1477
1478# PC XT scancodes
1479scancodes = {
1480 'a': 0x1e,
1481 'b': 0x30,
1482 'c': 0x2e,
1483 'd': 0x20,
1484 'e': 0x12,
1485 'f': 0x21,
1486 'g': 0x22,
1487 'h': 0x23,
1488 'i': 0x17,
1489 'j': 0x24,
1490 'k': 0x25,
1491 'l': 0x26,
1492 'm': 0x32,
1493 'n': 0x31,
1494 'o': 0x18,
1495 'p': 0x19,
1496 'q': 0x10,
1497 'r': 0x13,
1498 's': 0x1f,
1499 't': 0x14,
1500 'u': 0x16,
1501 'v': 0x2f,
1502 'w': 0x11,
1503 'x': 0x2d,
1504 'y': 0x15,
1505 'z': 0x2c,
1506 '0': 0x0b,
1507 '1': 0x02,
1508 '2': 0x03,
1509 '3': 0x04,
1510 '4': 0x05,
1511 '5': 0x06,
1512 '6': 0x07,
1513 '7': 0x08,
1514 '8': 0x09,
1515 '9': 0x0a,
1516 ' ': 0x39,
1517 '-': 0xc,
1518 '=': 0xd,
1519 '[': 0x1a,
1520 ']': 0x1b,
1521 ';': 0x27,
1522 '\'': 0x28,
1523 ',': 0x33,
1524 '.': 0x34,
1525 '/': 0x35,
1526 '\t': 0xf,
1527 '\n': 0x1c,
1528 '`': 0x29
1529};
1530
1531extScancodes = {
1532 'ESC' : [0x01],
1533 'BKSP': [0xe],
1534 'SPACE': [0x39],
1535 'TAB': [0x0f],
1536 'CAPS': [0x3a],
1537 'ENTER': [0x1c],
1538 'LSHIFT': [0x2a],
1539 'RSHIFT': [0x36],
1540 'INS': [0xe0, 0x52],
1541 'DEL': [0xe0, 0x53],
1542 'END': [0xe0, 0x4f],
1543 'HOME': [0xe0, 0x47],
1544 'PGUP': [0xe0, 0x49],
1545 'PGDOWN': [0xe0, 0x51],
1546 'LGUI': [0xe0, 0x5b], # GUI, aka Win, aka Apple key
1547 'RGUI': [0xe0, 0x5c],
1548 'LCTR': [0x1d],
1549 'RCTR': [0xe0, 0x1d],
1550 'LALT': [0x38],
1551 'RALT': [0xe0, 0x38],
1552 'APPS': [0xe0, 0x5d],
1553 'F1': [0x3b],
1554 'F2': [0x3c],
1555 'F3': [0x3d],
1556 'F4': [0x3e],
1557 'F5': [0x3f],
1558 'F6': [0x40],
1559 'F7': [0x41],
1560 'F8': [0x42],
1561 'F9': [0x43],
1562 'F10': [0x44 ],
1563 'F11': [0x57],
1564 'F12': [0x58],
1565 'UP': [0xe0, 0x48],
1566 'LEFT': [0xe0, 0x4b],
1567 'DOWN': [0xe0, 0x50],
1568 'RIGHT': [0xe0, 0x4d],
1569};
1570
1571def keyDown(ch):
1572 code = scancodes.get(ch, 0x0)
1573 if code != 0:
1574 return [code]
1575 extCode = extScancodes.get(ch, [])
1576 if len(extCode) == 0:
1577 print "bad ext",ch
1578 return extCode
1579
1580def keyUp(ch):
1581 codes = keyDown(ch)[:] # make a copy
1582 if len(codes) > 0:
1583 codes[len(codes)-1] += 0x80
1584 return codes
1585
1586def typeInGuest(console, text, delay):
1587 import time
1588 pressed = []
1589 group = False
1590 modGroupEnd = True
1591 i = 0
1592 while i < len(text):
1593 ch = text[i]
1594 i = i+1
1595 if ch == '{':
1596 # start group, all keys to be pressed at the same time
1597 group = True
1598 continue
1599 if ch == '}':
1600 # end group, release all keys
1601 for c in pressed:
1602 console.keyboard.putScancodes(keyUp(c))
1603 pressed = []
1604 group = False
1605 continue
1606 if ch == 'W':
1607 # just wait a bit
1608 time.sleep(0.3)
1609 continue
1610 if ch == '^' or ch == '|' or ch == '$' or ch == '_':
1611 if ch == '^':
1612 ch = 'LCTR'
1613 if ch == '|':
1614 ch = 'LSHIFT'
1615 if ch == '_':
1616 ch = 'LALT'
1617 if ch == '$':
1618 ch = 'LGUI'
1619 if not group:
1620 modGroupEnd = False
1621 else:
1622 if ch == '\\':
1623 if i < len(text):
1624 ch = text[i]
1625 i = i+1
1626 if ch == 'n':
1627 ch = '\n'
1628 elif ch == '&':
1629 combo = ""
1630 while i < len(text):
1631 ch = text[i]
1632 i = i+1
1633 if ch == ';':
1634 break
1635 combo += ch
1636 ch = combo
1637 modGroupEnd = True
1638 console.keyboard.putScancodes(keyDown(ch))
1639 pressed.insert(0, ch)
1640 if not group and modGroupEnd:
1641 for c in pressed:
1642 console.keyboard.putScancodes(keyUp(c))
1643 pressed = []
1644 modGroupEnd = True
1645 time.sleep(delay)
1646
1647def typeGuestCmd(ctx, args):
1648 import sys
1649
1650 if len(args) < 3:
1651 print "usage: typeGuest <machine> <text> <charDelay>"
1652 return 0
1653 mach = argsToMach(ctx,args)
1654 if mach is None:
1655 return 0
1656
1657 text = args[2]
1658
1659 if len(args) > 3:
1660 delay = float(args[3])
1661 else:
1662 delay = 0.1
1663
1664 gargs = [lambda ctx,mach,console,args: typeInGuest(console, text, delay)]
1665 cmdExistingVm(ctx, mach, 'guestlambda', gargs)
1666
1667 return 0
1668
1669def optId(verbose,id):
1670 if verbose:
1671 return ": "+id
1672 else:
1673 return ""
1674
1675def asSize(val,inBytes):
1676 if inBytes:
1677 return int(val)/(1024*1024)
1678 else:
1679 return int(val)
1680
1681def listMediaCmd(ctx,args):
1682 if len(args) > 1:
1683 verbose = int(args[1])
1684 else:
1685 verbose = False
1686 hdds = ctx['global'].getArray(ctx['vb'], 'hardDisks')
1687 print "Hard disks:"
1688 for hdd in hdds:
1689 if hdd.state != ctx['global'].constants.MediumState_Created:
1690 hdd.refreshState()
1691 print " %s (%s)%s %dM [logical %dM]" %(hdd.location, hdd.format, optId(verbose,hdd.id),asSize(hdd.size, True), asSize(hdd.logicalSize, False))
1692
1693 dvds = ctx['global'].getArray(ctx['vb'], 'DVDImages')
1694 print "CD/DVD disks:"
1695 for dvd in dvds:
1696 if dvd.state != ctx['global'].constants.MediumState_Created:
1697 dvd.refreshState()
1698 print " %s (%s)%s %dM" %(dvd.location, dvd.format,optId(verbose,hdd.id),asSize(hdd.size, True))
1699
1700 floppys = ctx['global'].getArray(ctx['vb'], 'floppyImages')
1701 print "Floopy disks:"
1702 for floppy in floppys:
1703 if floppy.state != ctx['global'].constants.MediumState_Created:
1704 floppy.refreshState()
1705 print " %s (%s)%s %dM" %(floppy.location, floppy.format,optId(verbose,hdd.id), asSize(hdd.size, True))
1706
1707 return 0
1708
1709def listUsbCmd(ctx,args):
1710 if (len(args) > 1):
1711 print "usage: listUsb"
1712 return 0
1713
1714 host = ctx['vb'].host
1715 for ud in ctx['global'].getArray(host, 'USBDevices'):
1716 printHostUsbDev(ctx,ud)
1717
1718 return 0
1719
1720def findDevOfType(ctx,mach,type):
1721 atts = ctx['global'].getArray(mach, 'mediumAttachments')
1722 for a in atts:
1723 if a.type == type:
1724 return [a.controller, a.port, a.device]
1725 return [None, 0, 0]
1726
1727def createHddCmd(ctx,args):
1728 if (len(args) < 3):
1729 print "usage: createHdd sizeM location type"
1730 return 0
1731
1732 size = int(args[1])
1733 loc = args[2]
1734 if len(args) > 3:
1735 format = args[3]
1736 else:
1737 format = "vdi"
1738
1739 hdd = ctx['vb'].createHardDisk(format, loc)
1740 progress = hdd.createBaseStorage(size, ctx['global'].constants.MediumVariant_Standard)
1741 if progressBar(ctx,progress) and hdd.id:
1742 print "created HDD at %s as %s" %(hdd.location, hdd.id)
1743 else:
1744 print "cannot create disk (file %s exist?)" %(loc)
1745 reportError(ctx,progress)
1746 return 0
1747
1748 return 0
1749
1750def registerHddCmd(ctx,args):
1751 if (len(args) < 2):
1752 print "usage: registerHdd location"
1753 return 0
1754
1755 vb = ctx['vb']
1756 loc = args[1]
1757 setImageId = False
1758 imageId = ""
1759 setParentId = False
1760 parentId = ""
1761 hdd = vb.openHardDisk(loc, ctx['global'].constants.AccessMode_ReadWrite, setImageId, imageId, setParentId, parentId)
1762 print "registered HDD as %s" %(hdd.id)
1763 return 0
1764
1765def controldevice(ctx,mach,args):
1766 [ctr,port,slot,type,id] = args
1767 mach.attachDevice(ctr, port, slot,type,id)
1768
1769def attachHddCmd(ctx,args):
1770 if (len(args) < 3):
1771 print "usage: attachHdd vm hdd controller port:slot"
1772 return 0
1773
1774 mach = argsToMach(ctx,args)
1775 if mach is None:
1776 return 0
1777 vb = ctx['vb']
1778 loc = args[2]
1779 try:
1780 hdd = vb.findHardDisk(loc)
1781 except:
1782 print "no HDD with path %s registered" %(loc)
1783 return 0
1784 if len(args) > 3:
1785 ctr = args[3]
1786 (port,slot) = args[4].split(":")
1787 else:
1788 [ctr, port, slot] = findDevOfType(ctx, mach, ctx['global'].constants.DeviceType_HardDisk)
1789
1790 cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_HardDisk,hdd.id))
1791 return 0
1792
1793def detachVmDevice(ctx,mach,args):
1794 atts = ctx['global'].getArray(mach, 'mediumAttachments')
1795 hid = args[0]
1796 for a in atts:
1797 if a.medium:
1798 if hid == "ALL" or a.medium.id == hid:
1799 mach.detachDevice(a.controller, a.port, a.device)
1800
1801def detachMedium(ctx,mid,medium):
1802 cmdClosedVm(ctx, mach, detachVmDevice, [medium.id])
1803
1804def detachHddCmd(ctx,args):
1805 if (len(args) < 3):
1806 print "usage: detachHdd vm hdd"
1807 return 0
1808
1809 mach = argsToMach(ctx,args)
1810 if mach is None:
1811 return 0
1812 vb = ctx['vb']
1813 loc = args[2]
1814 try:
1815 hdd = vb.findHardDisk(loc)
1816 except:
1817 print "no HDD with path %s registered" %(loc)
1818 return 0
1819
1820 detachMedium(ctx,mach.id,hdd)
1821 return 0
1822
1823def unregisterHddCmd(ctx,args):
1824 if (len(args) < 2):
1825 print "usage: unregisterHdd path <vmunreg>"
1826 return 0
1827
1828 vb = ctx['vb']
1829 loc = args[1]
1830 if (len(args) > 2):
1831 vmunreg = int(args[2])
1832 else:
1833 vmunreg = 0
1834 try:
1835 hdd = vb.findHardDisk(loc)
1836 except:
1837 print "no HDD with path %s registered" %(loc)
1838 return 0
1839
1840 if vmunreg != 0:
1841 machs = ctx['global'].getArray(hdd, 'machineIds')
1842 try:
1843 for m in machs:
1844 print "Trying to detach from %s" %(m)
1845 detachMedium(ctx,m,hdd)
1846 except Exception, e:
1847 print 'failed: ',e
1848 return 0
1849 hdd.close()
1850 return 0
1851
1852def removeHddCmd(ctx,args):
1853 if (len(args) != 2):
1854 print "usage: removeHdd path"
1855 return 0
1856
1857 vb = ctx['vb']
1858 loc = args[1]
1859 try:
1860 hdd = vb.findHardDisk(loc)
1861 except:
1862 print "no HDD with path %s registered" %(loc)
1863 return 0
1864
1865 progress = hdd.deleteStorage()
1866 progressBar(ctx,progress)
1867
1868 return 0
1869
1870def registerIsoCmd(ctx,args):
1871 if (len(args) < 2):
1872 print "usage: registerIso location"
1873 return 0
1874 vb = ctx['vb']
1875 loc = args[1]
1876 id = ""
1877 iso = vb.openDVDImage(loc, id)
1878 print "registered ISO as %s" %(iso.id)
1879 return 0
1880
1881def unregisterIsoCmd(ctx,args):
1882 if (len(args) != 2):
1883 print "usage: unregisterIso path"
1884 return 0
1885
1886 vb = ctx['vb']
1887 loc = args[1]
1888 try:
1889 dvd = vb.findDVDImage(loc)
1890 except:
1891 print "no DVD with path %s registered" %(loc)
1892 return 0
1893
1894 progress = dvd.close()
1895 print "Unregistered ISO at %s" %(dvd.location)
1896
1897 return 0
1898
1899def removeIsoCmd(ctx,args):
1900 if (len(args) != 2):
1901 print "usage: removeIso path"
1902 return 0
1903
1904 vb = ctx['vb']
1905 loc = args[1]
1906 try:
1907 dvd = vb.findDVDImage(loc)
1908 except:
1909 print "no DVD with path %s registered" %(loc)
1910 return 0
1911
1912 progress = dvd.deleteStorage()
1913 if progressBar(ctx,progress):
1914 print "Removed ISO at %s" %(dvd.location)
1915 else:
1916 reportError(ctx,progress)
1917 return 0
1918
1919def attachIsoCmd(ctx,args):
1920 if (len(args) < 3):
1921 print "usage: attachIso vm iso controller port:slot"
1922 return 0
1923
1924 mach = argsToMach(ctx,args)
1925 if mach is None:
1926 return 0
1927 vb = ctx['vb']
1928 loc = args[2]
1929 try:
1930 dvd = vb.findDVDImage(loc)
1931 except:
1932 print "no DVD with path %s registered" %(loc)
1933 return 0
1934 if len(args) > 3:
1935 ctr = args[3]
1936 (port,slot) = args[4].split(":")
1937 else:
1938 [ctr, port, slot] = findDevOfType(ctx, mach, ctx['global'].constants.DeviceType_DVD)
1939 cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_DVD,dvd.id))
1940 return 0
1941
1942def detachIsoCmd(ctx,args):
1943 if (len(args) < 3):
1944 print "usage: detachIso vm iso"
1945 return 0
1946
1947 mach = argsToMach(ctx,args)
1948 if mach is None:
1949 return 0
1950 vb = ctx['vb']
1951 loc = args[2]
1952 try:
1953 dvd = vb.findDVDImage(loc)
1954 except:
1955 print "no DVD with path %s registered" %(loc)
1956 return 0
1957
1958 detachMedium(ctx,mach.id,dvd)
1959 return 0
1960
1961def mountIsoCmd(ctx,args):
1962 if (len(args) < 3):
1963 print "usage: mountIso vm iso controller port:slot"
1964 return 0
1965
1966 mach = argsToMach(ctx,args)
1967 if mach is None:
1968 return 0
1969 vb = ctx['vb']
1970 loc = args[2]
1971 try:
1972 dvd = vb.findDVDImage(loc)
1973 except:
1974 print "no DVD with path %s registered" %(loc)
1975 return 0
1976
1977 if len(args) > 3:
1978 ctr = args[3]
1979 (port,slot) = args[4].split(":")
1980 else:
1981 # autodetect controller and location, just find first controller with media == DVD
1982 [ctr, port, slot] = findDevOfType(ctx, mach, ctx['global'].constants.DeviceType_DVD)
1983
1984 cmdExistingVm(ctx, mach, 'mountiso', [ctr, port, slot, dvd.id, True])
1985
1986 return 0
1987
1988def unmountIsoCmd(ctx,args):
1989 if (len(args) < 2):
1990 print "usage: unmountIso vm controller port:slot"
1991 return 0
1992
1993 mach = argsToMach(ctx,args)
1994 if mach is None:
1995 return 0
1996 vb = ctx['vb']
1997
1998 if len(args) > 2:
1999 ctr = args[2]
2000 (port,slot) = args[3].split(":")
2001 else:
2002 # autodetect controller and location, just find first controller with media == DVD
2003 [ctr, port, slot] = findDevOfType(ctx, mach, ctx['global'].constants.DeviceType_DVD)
2004
2005 cmdExistingVm(ctx, mach, 'mountiso', [ctr, port, slot, "", True])
2006
2007 return 0
2008
2009def attachCtr(ctx,mach,args):
2010 [name, bus, type] = args
2011 ctr = mach.addStorageController(name, bus)
2012 if type != None:
2013 ctr.controllerType = type
2014
2015def attachCtrCmd(ctx,args):
2016 if (len(args) < 4):
2017 print "usage: attachCtr vm cname bus <type>"
2018 return 0
2019
2020 if len(args) > 4:
2021 type = enumFromString(ctx,'StorageControllerType', args[4])
2022 if type == None:
2023 print "Controller type %s unknown" %(args[4])
2024 return 0
2025 else:
2026 type = None
2027
2028 mach = argsToMach(ctx,args)
2029 if mach is None:
2030 return 0
2031 bus = enumFromString(ctx,'StorageBus', args[3])
2032 if bus is None:
2033 print "Bus type %s unknown" %(args[3])
2034 return 0
2035 name = args[2]
2036 cmdClosedVm(ctx, mach, attachCtr, [name, bus, type])
2037 return 0
2038
2039def detachCtrCmd(ctx,args):
2040 if (len(args) < 3):
2041 print "usage: detachCtr vm name"
2042 return 0
2043
2044 mach = argsToMach(ctx,args)
2045 if mach is None:
2046 return 0
2047 ctr = args[2]
2048 cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.removeStorageController(ctr))
2049 return 0
2050
2051def usbctr(ctx,mach,console,args):
2052 if (args[0]):
2053 console.attachUSBDevice(args[1])
2054 else:
2055 console.detachUSBDevice(args[1])
2056
2057def attachUsbCmd(ctx,args):
2058 if (len(args) < 3):
2059 print "usage: attachUsb vm deviceuid"
2060 return 0
2061
2062 mach = argsToMach(ctx,args)
2063 if mach is None:
2064 return 0
2065 dev = args[2]
2066 cmdExistingVm(ctx, mach, 'guestlambda', [usbctr,True,dev])
2067 return 0
2068
2069def detachUsbCmd(ctx,args):
2070 if (len(args) < 3):
2071 print "usage: detachUsb vm deviceuid"
2072 return 0
2073
2074 mach = argsToMach(ctx,args)
2075 if mach is None:
2076 return 0
2077 dev = args[2]
2078 cmdExistingVm(ctx, mach, 'guestlambda', [usbctr,False,dev])
2079 return 0
2080
2081
2082def guiCmd(ctx,args):
2083 if (len(args) > 1):
2084 print "usage: gui"
2085 return 0
2086
2087 binDir = ctx['global'].getBinDir()
2088
2089 vbox = os.path.join(binDir, 'VirtualBox')
2090 try:
2091 os.system(vbox)
2092 except KeyboardInterrupt:
2093 # to allow interruption
2094 pass
2095 return 0
2096
2097def shareFolderCmd(ctx,args):
2098 if (len(args) < 4):
2099 print "usage: shareFolder vm path name <writable> <persistent>"
2100 return 0
2101
2102 mach = argsToMach(ctx,args)
2103 if mach is None:
2104 return 0
2105 path = args[2]
2106 name = args[3]
2107 writable = False
2108 persistent = False
2109 if len(args) > 4:
2110 for a in args[4:]:
2111 if a == 'writable':
2112 writable = True
2113 if a == 'persistent':
2114 persistent = True
2115 if persistent:
2116 cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.createSharedFolder(name, path, writable), [])
2117 else:
2118 cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: console.createSharedFolder(name, path, writable)])
2119 return 0
2120
2121def unshareFolderCmd(ctx,args):
2122 if (len(args) < 3):
2123 print "usage: unshareFolder vm name"
2124 return 0
2125
2126 mach = argsToMach(ctx,args)
2127 if mach is None:
2128 return 0
2129 name = args[2]
2130 found = False
2131 for sf in ctx['global'].getArray(mach, 'sharedFolders'):
2132 if sf.name == name:
2133 cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.removeSharedFolder(name), [])
2134 found = True
2135 break
2136 if not found:
2137 cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: console.removeSharedFolder(name)])
2138 return 0
2139
2140
2141def snapshotCmd(ctx,args):
2142 if (len(args) < 2 or args[1] == 'help'):
2143 print "Take snapshot: snapshot vm take name <description>"
2144 print "Restore snapshot: snapshot vm restore name"
2145 print "Merge snapshot: snapshot vm merge name"
2146 return 0
2147
2148 mach = argsToMach(ctx,args)
2149 if mach is None:
2150 return 0
2151 cmd = args[2]
2152 if cmd == 'take':
2153 if (len(args) < 4):
2154 print "usage: snapshot vm take name <description>"
2155 return 0
2156 name = args[3]
2157 if (len(args) > 4):
2158 desc = args[4]
2159 else:
2160 desc = ""
2161 cmdAnyVm(ctx, mach, lambda ctx,mach,console,args: progressBar(ctx, console.takeSnapshot(name,desc)))
2162
2163 if cmd == 'restore':
2164 if (len(args) < 4):
2165 print "usage: snapshot vm restore name"
2166 return 0
2167 name = args[3]
2168 snap = mach.findSnapshot(name)
2169 cmdAnyVm(ctx, mach, lambda ctx,mach,console,args: progressBar(ctx, console.restoreSnapshot(snap)))
2170 return 0
2171
2172 if cmd == 'restorecurrent':
2173 if (len(args) < 4):
2174 print "usage: snapshot vm restorecurrent"
2175 return 0
2176 snap = mach.currentSnapshot()
2177 cmdAnyVm(ctx, mach, lambda ctx,mach,console,args: progressBar(ctx, console.restoreSnapshot(snap)))
2178 return 0
2179
2180 if cmd == 'delete':
2181 if (len(args) < 4):
2182 print "usage: snapshot vm delete name"
2183 return 0
2184 name = args[3]
2185 snap = mach.findSnapshot(name)
2186 cmdAnyVm(ctx, mach, lambda ctx,mach,console,args: progressBar(ctx, console.deleteSnapshot(snap.id)))
2187 return 0
2188
2189 print "Command '%s' is unknown" %(cmd)
2190
2191 return 0
2192
2193def natAlias(ctx, mach, nicnum, nat, args=[]):
2194 """This command shows/alters NAT's alias settings.
2195 usage: nat <vm> <nicnum> alias [default|[log] [proxyonly] [sameports]]
2196 default - set settings to default values
2197 log - switch on alias loging
2198 proxyonly - switch proxyonly mode on
2199 sameports - enforces NAT using the same ports
2200 """
2201 alias = {
2202 'log': 0x1,
2203 'proxyonly': 0x2,
2204 'sameports': 0x4
2205 }
2206 if len(args) == 1:
2207 first = 0
2208 msg = ''
2209 for aliasmode, aliaskey in alias.iteritems():
2210 if first == 0:
2211 first = 1
2212 else:
2213 msg += ', '
2214 if int(nat.aliasMode) & aliaskey:
2215 msg += '{0}: {1}'.format(aliasmode, 'on')
2216 else:
2217 msg += '{0}: {1}'.format(aliasmode, 'off')
2218 msg += ')'
2219 return (0, [msg])
2220 else:
2221 nat.aliasMode = 0
2222 if 'default' not in args:
2223 for a in range(1, len(args)):
2224 if not alias.has_key(args[a]):
2225 print 'Invalid alias mode: ' + args[a]
2226 print natAlias.__doc__
2227 return (1, None)
2228 nat.aliasMode = int(nat.aliasMode) | alias[args[a]];
2229 return (0, None)
2230
2231def natSettings(ctx, mach, nicnum, nat, args):
2232 """This command shows/alters NAT settings.
2233 usage: nat <vm> <nicnum> settings [<mtu> [[<socsndbuf> <sockrcvbuf> [<tcpsndwnd> <tcprcvwnd>]]]]
2234 mtu - set mtu <= 16000
2235 socksndbuf/sockrcvbuf - sets amount of kb for socket sending/receiving buffer
2236 tcpsndwnd/tcprcvwnd - sets size of initial tcp sending/receiving window
2237 """
2238 if len(args) == 1:
2239 (mtu, socksndbuf, sockrcvbuf, tcpsndwnd, tcprcvwnd) = nat.getNetworkSettings();
2240 if mtu == 0: mtu = 1500
2241 if socksndbuf == 0: socksndbuf = 64
2242 if sockrcvbuf == 0: sockrcvbuf = 64
2243 if tcpsndwnd == 0: tcpsndwnd = 64
2244 if tcprcvwnd == 0: tcprcvwnd = 64
2245 msg = 'mtu:{0} socket(snd:{1}, rcv:{2}) tcpwnd(snd:{3}, rcv:{4})'.format(mtu, socksndbuf, sockrcvbuf, tcpsndwnd, tcprcvwnd);
2246 return (0, [msg])
2247 else:
2248 if args[1] < 16000:
2249 print 'invalid mtu value ({0} no in range [65 - 16000])'.format(args[1])
2250 return (1, None)
2251 for i in range(2, len(args)):
2252 if not args[i].isdigit() or int(args[i]) < 8 or int(args[i]) > 1024:
2253 print 'invalid {0} parameter ({1} not in range [8-1024])'.format(i, args[i])
2254 return (1, None)
2255 a = [args[1]]
2256 if len(args) < 6:
2257 for i in range(2, len(args)): a.append(args[i])
2258 for i in range(len(args), 6): a.append(0)
2259 else:
2260 for i in range(2, len(args)): a.append(args[i])
2261 #print a
2262 nat.setNetworkSettings(int(a[0]), int(a[1]), int(a[2]), int(a[3]), int(a[4]))
2263 return (0, None)
2264
2265def natDns(ctx, mach, nicnum, nat, args):
2266 """This command shows/alters DNS's NAT settings
2267 usage: nat <vm> <nicnum> dns [passdomain] [proxy] [usehostresolver]
2268 passdomain - enforces builtin DHCP server to pass domain
2269 proxy - switch on builtin NAT DNS proxying mechanism
2270 usehostresolver - proxies all DNS requests to Host Resolver interface
2271 """
2272 yesno = {0: 'off', 1: 'on'}
2273 if len(args) == 1:
2274 msg = 'passdomain:{0}, proxy:{1}, usehostresolver:{2}'.format(yesno[int(nat.dnsPassDomain)], yesno[int(nat.dnsProxy)], yesno[int(nat.dnsUseHostResolver)])
2275 return (0, [msg])
2276 else:
2277 nat.dnsPassDomain = 'passdomain' in args
2278 nat.dnsProxy = 'proxy' in args
2279 nat.dnsUseHostResolver = 'usehostresolver' in args
2280 return (0, None)
2281
2282def natTftp(ctx, mach, nicnum, nat, args):
2283 """This command shows/alters TFTP settings
2284 usage nat <vm> <nicnum> tftp [prefix <prefix>| bootfile <bootfile>| server <server>]
2285 prefix - alters prefix TFTP settings
2286 bootfile - alters bootfile TFTP settings
2287 server - sets booting server
2288 """
2289 if len(args) == 1:
2290 server = nat.tftpNextServer
2291 if server is None:
2292 server = nat.network
2293 if server is None:
2294 server = '10.0.{0}/24'.format(int(nicnum) + 2)
2295 (server,mask) = server.split('/')
2296 while server.count('.') != 3:
2297 server += '.0'
2298 (a,b,c,d) = server.split('.')
2299 server = '{0}.{1}.{2}.4'.format(a,b,c)
2300 prefix = nat.tftpPrefix
2301 if prefix is None:
2302 prefix = '{0}/TFTP/'.format(ctx['vb'].homeFolder)
2303 bootfile = nat.tftpBootFile
2304 if bootfile is None:
2305 bootfile = '{0}.pxe'.format(mach.name)
2306 msg = 'server:{0}, prefix:{1}, bootfile:{2}'.format(server, prefix, bootfile)
2307 return (0, [msg])
2308 else:
2309
2310 cmd = args[1]
2311 if len(args) != 3:
2312 print 'invalid args:', args
2313 print natTftp.__doc__
2314 return (1, None)
2315 if cmd == 'prefix': nat.tftpPrefix = args[2]
2316 elif cmd == 'bootfile': nat.tftpBootFile = args[2]
2317 elif cmd == 'server': nat.tftpNextServer = args[2]
2318 else:
2319 print "invalid cmd:", cmd
2320 return (1, None)
2321 return (0, None)
2322
2323def natPortForwarding(ctx, mach, nicnum, nat, args):
2324 """This command shows/manages port-forwarding settings
2325 usage:
2326 nat <vm> <nicnum> <pf> [ simple tcp|udp <hostport> <guestport>]
2327 |[no_name tcp|udp <hostip> <hostport> <guestip> <guestport>]
2328 |[ex tcp|udp <pf-name> <hostip> <hostport> <guestip> <guestport>]
2329 |[delete <pf-name>]
2330 """
2331 if len(args) == 1:
2332 # note: keys/values are swapped in defining part of the function
2333 proto = {0: 'udp', 1: 'tcp'}
2334 msg = []
2335 pfs = ctx['global'].getArray(nat, 'redirects')
2336 for pf in pfs:
2337 (pfnme, pfp, pfhip, pfhp, pfgip, pfgp) = str(pf).split(',')
2338 msg.append('{0}: {1} {2}:{3} => {4}:{5}'.format(pfnme, proto[int(pfp)], pfhip, pfhp, pfgip, pfgp))
2339 return (0, msg) # msg is array
2340 else:
2341 proto = {'udp': 0, 'tcp': 1}
2342 pfcmd = {
2343 'simple': {
2344 'validate': lambda: args[1] in pfcmd.keys() and args[2] in proto.keys() and len(args) == 5,
2345 'func':lambda: nat.addRedirect('', proto[args[2]], '', int(args[3]), '', int(args[4]))
2346 },
2347 'no_name': {
2348 'validate': lambda: args[1] in pfcmd.keys() and args[2] in proto.keys() and len(args) == 7,
2349 'func': lambda: nat.addRedirect('', proto[args[2]], args[3], int(args[4]), args[5], int(args[6]))
2350 },
2351 'ex': {
2352 'validate': lambda: args[1] in pfcmd.keys() and args[2] in proto.keys() and len(args) == 8,
2353 'func': lambda: nat.addRedirect(args[3], proto[args[2]], args[4], int(args[5]), args[6], int(args[7]))
2354 },
2355 'delete': {
2356 'validate': lambda: len(args) == 3,
2357 'func': lambda: nat.removeRedirect(args[2])
2358 }
2359 }
2360
2361 if not pfcmd[args[1]]['validate']():
2362 print 'invalid port-forwarding or args of sub command ', args[1]
2363 print natPortForwarding.__doc__
2364 return (1, None)
2365
2366 a = pfcmd[args[1]]['func']()
2367 return (0, None)
2368
2369def natNetwork(ctx, mach, nicnum, nat, args):
2370 """This command shows/alters NAT network settings
2371 usage: nat <vm> <nicnum> network [<network>]
2372 """
2373 if len(args) == 1:
2374 if nat.network is not None and len(str(nat.network)) != 0:
2375 msg = '\'%s\'' % (nat.network)
2376 else:
2377 msg = '10.0.{0}.0/24'.format(int(nicnum) + 2)
2378 return (0, [msg])
2379 else:
2380 (addr, mask) = args[1].split('/')
2381 if addr.count('.') > 3 or int(mask) < 0 or int(mask) > 32:
2382 print 'Invalid arguments'
2383 return (1, None)
2384 nat.network = args[1]
2385 return (0, None)
2386def natCmd(ctx, args):
2387 """This command is entry point to NAT settins management
2388 usage: nat <vm> <nicnum> <cmd> <cmd-args>
2389 cmd - [alias|settings|tftp|dns|pf|network]
2390 for more information about commands:
2391 nat help <cmd>
2392 """
2393
2394 natcommands = {
2395 'alias' : natAlias,
2396 'settings' : natSettings,
2397 'tftp': natTftp,
2398 'dns': natDns,
2399 'pf': natPortForwarding,
2400 'network': natNetwork
2401 }
2402
2403 if args[1] == 'help':
2404 if len(args) > 2:
2405 print natcommands[args[2]].__doc__
2406 else:
2407 print natCmd.__doc__
2408 return 0
2409 if len(args) == 1 or len(args) < 4 or args[3] not in natcommands:
2410 print natCmd.__doc__
2411 return 0
2412 mach = ctx['argsToMach'](args)
2413 if mach == None:
2414 print "please specify vm"
2415 return 0
2416 if len(args) < 3 or not args[2].isdigit() or int(args[2]) not in range(0, ctx['vb'].systemProperties.networkAdapterCount):
2417 print 'please specify adapter num {0} isn\'t in range [0-{1}]'.format(args[2], ctx['vb'].systemProperties.networkAdapterCount)
2418 return 0
2419 nicnum = int(args[2])
2420 cmdargs = []
2421 for i in range(3, len(args)):
2422 cmdargs.append(args[i])
2423
2424 # @todo vvl if nicnum is missed but command is entered
2425 # use NAT func for every adapter on machine.
2426 func = args[3]
2427 rosession = 1
2428 session = None
2429 if len(cmdargs) > 1:
2430 rosession = 0
2431 session = ctx['global'].openMachineSession(mach.id);
2432 mach = session.machine;
2433
2434 adapter = mach.getNetworkAdapter(nicnum)
2435 natEngine = adapter.natDriver
2436 (rc, report) = natcommands[func](ctx, mach, nicnum, natEngine, cmdargs)
2437 if rosession == 0:
2438 if rc == 0:
2439 mach.saveSettings()
2440 session.close()
2441 elif report is not None:
2442 for r in report:
2443 msg ='{0} nic{1} {2}: {3}'.format(mach.name, nicnum, func, r)
2444 print msg
2445 return 0
2446
2447
2448aliases = {'s':'start',
2449 'i':'info',
2450 'l':'list',
2451 'h':'help',
2452 'a':'alias',
2453 'q':'quit', 'exit':'quit',
2454 'tg': 'typeGuest',
2455 'v':'verbose'}
2456
2457commands = {'help':['Prints help information', helpCmd, 0],
2458 'start':['Start virtual machine by name or uuid: start Linux', startCmd, 0],
2459 'createVm':['Create virtual machine: createVm macvm MacOS', createVmCmd, 0],
2460 'removeVm':['Remove virtual machine', removeVmCmd, 0],
2461 'pause':['Pause virtual machine', pauseCmd, 0],
2462 'resume':['Resume virtual machine', resumeCmd, 0],
2463 'save':['Save execution state of virtual machine', saveCmd, 0],
2464 'stats':['Stats for virtual machine', statsCmd, 0],
2465 'powerdown':['Power down virtual machine', powerdownCmd, 0],
2466 'powerbutton':['Effectively press power button', powerbuttonCmd, 0],
2467 'list':['Shows known virtual machines', listCmd, 0],
2468 'info':['Shows info on machine', infoCmd, 0],
2469 'ginfo':['Shows info on guest', ginfoCmd, 0],
2470 'gexec':['Executes program in the guest', gexecCmd, 0],
2471 'alias':['Control aliases', aliasCmd, 0],
2472 'verbose':['Toggle verbosity', verboseCmd, 0],
2473 'setvar':['Set VMs variable: setvar Fedora BIOSSettings.ACPIEnabled True', setvarCmd, 0],
2474 'eval':['Evaluate arbitrary Python construction: eval \'for m in getMachines(ctx): print m.name,"has",m.memorySize,"M"\'', evalCmd, 0],
2475 'quit':['Exits', quitCmd, 0],
2476 'host':['Show host information', hostCmd, 0],
2477 'guest':['Execute command for guest: guest Win32 \'console.mouse.putMouseEvent(20, 20, 0, 0, 0)\'', guestCmd, 0],
2478 'monitorGuest':['Monitor what happens with the guest for some time: monitorGuest Win32 10', monitorGuestCmd, 0],
2479 'monitorVBox':['Monitor what happens with Virtual Box for some time: monitorVBox 10', monitorVBoxCmd, 0],
2480 'portForward':['Setup permanent port forwarding for a VM, takes adapter number host port and guest port: portForward Win32 0 8080 80', portForwardCmd, 0],
2481 'showLog':['Show log file of the VM, : showLog Win32', showLogCmd, 0],
2482 'findLog':['Show entries matching pattern in log file of the VM, : findLog Win32 PDM|CPUM', findLogCmd, 0],
2483 'reloadExt':['Reload custom extensions: reloadExt', reloadExtCmd, 0],
2484 'runScript':['Run VBox script: runScript script.vbox', runScriptCmd, 0],
2485 'sleep':['Sleep for specified number of seconds: sleep 3.14159', sleepCmd, 0],
2486 'shell':['Execute external shell command: shell "ls /etc/rc*"', shellCmd, 0],
2487 'exportVm':['Export VM in OVF format: exportVm Win /tmp/win.ovf', exportVMCmd, 0],
2488 'screenshot':['Take VM screenshot to a file: screenshot Win /tmp/win.png 1024 768', screenshotCmd, 0],
2489 'teleport':['Teleport VM to another box (see openportal): teleport Win anotherhost:8000 <passwd> <maxDowntime>', teleportCmd, 0],
2490 'typeGuest':['Type arbitrary text in guest: typeGuest Linux "^lls\\n&UP;&BKSP;ess /etc/hosts\\nq^c" 0.7', typeGuestCmd, 0],
2491 'openportal':['Open portal for teleportation of VM from another box (see teleport): openportal Win 8000 <passwd>', openportalCmd, 0],
2492 'closeportal':['Close teleportation portal (see openportal,teleport): closeportal Win', closeportalCmd, 0],
2493 'getextra':['Get extra data, empty key lists all: getextra <vm|global> <key>', getExtraDataCmd, 0],
2494 'setextra':['Set extra data, empty value removes key: setextra <vm|global> <key> <value>', setExtraDataCmd, 0],
2495 'gueststats':['Print available guest stats (only Windows guests with additions so far): gueststats Win32', gueststatsCmd, 0],
2496 'plugcpu':['Add a CPU to a running VM: plugcpu Win 1', plugcpuCmd, 0],
2497 'unplugcpu':['Remove a CPU from a running VM (additions required, Windows cannot unplug): unplugcpu Linux 1', unplugcpuCmd, 0],
2498 'createHdd': ['Create virtual HDD: createHdd 1000 /disk.vdi ', createHddCmd, 0],
2499 'removeHdd': ['Permanently remove virtual HDD: removeHdd /disk.vdi', removeHddCmd, 0],
2500 'registerHdd': ['Register HDD image with VirtualBox instance: registerHdd /disk.vdi', registerHddCmd, 0],
2501 'unregisterHdd': ['Unregister HDD image with VirtualBox instance: unregisterHdd /disk.vdi', unregisterHddCmd, 0],
2502 'attachHdd': ['Attach HDD to the VM: attachHdd win /disk.vdi "IDE Controller" 0:1', attachHddCmd, 0],
2503 'detachHdd': ['Detach HDD from the VM: detachHdd win /disk.vdi', detachHddCmd, 0],
2504 'registerIso': ['Register CD/DVD image with VirtualBox instance: registerIso /os.iso', registerIsoCmd, 0],
2505 'unregisterIso': ['Unregister CD/DVD image with VirtualBox instance: unregisterIso /os.iso', unregisterIsoCmd, 0],
2506 'removeIso': ['Permanently remove CD/DVD image: removeIso /os.iso', removeIsoCmd, 0],
2507 'attachIso': ['Attach CD/DVD to the VM: attachIso win /os.iso "IDE Controller" 0:1', attachIsoCmd, 0],
2508 'detachIso': ['Detach CD/DVD from the VM: detachIso win /os.iso', detachIsoCmd, 0],
2509 'mountIso': ['Mount CD/DVD to the running VM: mountIso win /os.iso "IDE Controller" 0:1', mountIsoCmd, 0],
2510 'unmountIso': ['Unmount CD/DVD from running VM: unmountIso win "IDE Controller" 0:1', unmountIsoCmd, 0],
2511 'attachCtr': ['Attach storage controller to the VM: attachCtr win Ctr0 IDE ICH6', attachCtrCmd, 0],
2512 'detachCtr': ['Detach HDD from the VM: detachCtr win Ctr0', detachCtrCmd, 0],
2513 'attachUsb': ['Attach USB device to the VM (use listUsb to show available devices): attachUsb win uuid', attachUsbCmd, 0],
2514 'detachUsb': ['Detach USB device from the VM: detachUsb win uuid', detachUsbCmd, 0],
2515 'listMedia': ['List media known to this VBox instance', listMediaCmd, 0],
2516 'listUsb': ['List known USB devices', listUsbCmd, 0],
2517 'shareFolder': ['Make host\'s folder visible to guest: shareFolder win /share share writable', shareFolderCmd, 0],
2518 'unshareFolder': ['Remove folder sharing', unshareFolderCmd, 0],
2519 'gui': ['Start GUI frontend', guiCmd, 0],
2520 'colors':['Toggle colors', colorsCmd, 0],
2521 'snapshot':['VM snapshot manipulation, snapshot help for more info', snapshotCmd, 0],
2522 'nat':['NAT manipulation, nat help for more info', natCmd, 0],
2523 }
2524
2525def runCommandArgs(ctx, args):
2526 c = args[0]
2527 if aliases.get(c, None) != None:
2528 c = aliases[c]
2529 ci = commands.get(c,None)
2530 if ci == None:
2531 print "Unknown command: '%s', type 'help' for list of known commands" %(c)
2532 return 0
2533 if ctx['remote'] and ctx['vb'] is None:
2534 if c not in ['connect', 'reconnect', 'help', 'quit']:
2535 print "First connect to remote server with %s command." %(colored('connect', 'blue'))
2536 return 0
2537 return ci[1](ctx, args)
2538
2539
2540def runCommand(ctx, cmd):
2541 if len(cmd) == 0: return 0
2542 args = split_no_quotes(cmd)
2543 if len(args) == 0: return 0
2544 return runCommandArgs(ctx, args)
2545
2546#
2547# To write your own custom commands to vboxshell, create
2548# file ~/.VirtualBox/shellext.py with content like
2549#
2550# def runTestCmd(ctx, args):
2551# print "Testy test", ctx['vb']
2552# return 0
2553#
2554# commands = {
2555# 'test': ['Test help', runTestCmd]
2556# }
2557# and issue reloadExt shell command.
2558# This file also will be read automatically on startup or 'reloadExt'.
2559#
2560# Also one can put shell extensions into ~/.VirtualBox/shexts and
2561# they will also be picked up, so this way one can exchange
2562# shell extensions easily.
2563def addExtsFromFile(ctx, cmds, file):
2564 if not os.path.isfile(file):
2565 return
2566 d = {}
2567 try:
2568 execfile(file, d, d)
2569 for (k,v) in d['commands'].items():
2570 if g_verbose:
2571 print "customize: adding \"%s\" - %s" %(k, v[0])
2572 cmds[k] = [v[0], v[1], file]
2573 except:
2574 print "Error loading user extensions from %s" %(file)
2575 traceback.print_exc()
2576
2577
2578def checkUserExtensions(ctx, cmds, folder):
2579 folder = str(folder)
2580 name = os.path.join(folder, "shellext.py")
2581 addExtsFromFile(ctx, cmds, name)
2582 # also check 'exts' directory for all files
2583 shextdir = os.path.join(folder, "shexts")
2584 if not os.path.isdir(shextdir):
2585 return
2586 exts = os.listdir(shextdir)
2587 for e in exts:
2588 addExtsFromFile(ctx, cmds, os.path.join(shextdir,e))
2589
2590def getHomeFolder(ctx):
2591 if ctx['remote'] or ctx['vb'] is None:
2592 return os.path.join(os.path.expanduser("~"), ".VirtualBox")
2593 else:
2594 return ctx['vb'].homeFolder
2595
2596def interpret(ctx):
2597 if ctx['remote']:
2598 commands['connect'] = ["Connect to remote VBox instance: connect http://server:18083 user password", connectCmd, 0]
2599 commands['disconnect'] = ["Disconnect from remote VBox instance", disconnectCmd, 0]
2600 commands['reconnect'] = ["Reconnect to remote VBox instance", reconnectCmd, 0]
2601 ctx['wsinfo'] = ["http://localhost:18083", "", ""]
2602
2603 vbox = ctx['vb']
2604
2605 if vbox is not None:
2606 print "Running VirtualBox version %s" %(vbox.version)
2607 ctx['perf'] = None # ctx['global'].getPerfCollector(vbox)
2608 else:
2609 ctx['perf'] = None
2610
2611 home = getHomeFolder(ctx)
2612 checkUserExtensions(ctx, commands, home)
2613 if platform.system() == 'Windows':
2614 global g_hascolors
2615 g_hascolors = False
2616 hist_file=os.path.join(home, ".vboxshellhistory")
2617 autoCompletion(commands, ctx)
2618
2619 if g_hasreadline and os.path.exists(hist_file):
2620 readline.read_history_file(hist_file)
2621
2622 # to allow to print actual host information, we collect info for
2623 # last 150 secs maximum, (sample every 10 secs and keep up to 15 samples)
2624 if ctx['perf']:
2625 try:
2626 ctx['perf'].setup(['*'], [vbox.host], 10, 15)
2627 except:
2628 pass
2629
2630 while True:
2631 try:
2632 cmd = raw_input("vbox> ")
2633 done = runCommand(ctx, cmd)
2634 if done != 0: break
2635 except KeyboardInterrupt:
2636 print '====== You can type quit or q to leave'
2637 except EOFError:
2638 break
2639 except Exception,e:
2640 printErr(ctx,e)
2641 if g_verbose:
2642 traceback.print_exc()
2643 ctx['global'].waitForEvents(0)
2644 try:
2645 # There is no need to disable metric collection. This is just an example.
2646 if ct['perf']:
2647 ctx['perf'].disable(['*'], [vbox.host])
2648 except:
2649 pass
2650 if g_hasreadline:
2651 readline.write_history_file(hist_file)
2652
2653def runCommandCb(ctx, cmd, args):
2654 args.insert(0, cmd)
2655 return runCommandArgs(ctx, args)
2656
2657def runGuestCommandCb(ctx, id, guestLambda, args):
2658 mach = machById(ctx,id)
2659 if mach == None:
2660 return 0
2661 args.insert(0, guestLambda)
2662 cmdExistingVm(ctx, mach, 'guestlambda', args)
2663 return 0
2664
2665def main(argv):
2666 style = None
2667 autopath = False
2668 argv.pop(0)
2669 while len(argv) > 0:
2670 if argv[0] == "-w":
2671 style = "WEBSERVICE"
2672 if argv[0] == "-a":
2673 autopath = True
2674 argv.pop(0)
2675
2676 if autopath:
2677 cwd = os.getcwd()
2678 vpp = os.environ.get("VBOX_PROGRAM_PATH")
2679 if vpp is None and (os.path.isfile(os.path.join(cwd, "VirtualBox")) or os.path.isfile(os.path.join(cwd, "VirtualBox.exe"))) :
2680 vpp = cwd
2681 print "Autodetected VBOX_PROGRAM_PATH as",vpp
2682 os.environ["VBOX_PROGRAM_PATH"] = cwd
2683 sys.path.append(os.path.join(vpp, "sdk", "installer"))
2684
2685 from vboxapi import VirtualBoxManager
2686 g_virtualBoxManager = VirtualBoxManager(style, None)
2687 ctx = {'global':g_virtualBoxManager,
2688 'mgr':g_virtualBoxManager.mgr,
2689 'vb':g_virtualBoxManager.vbox,
2690 'ifaces':g_virtualBoxManager.constants,
2691 'remote':g_virtualBoxManager.remote,
2692 'type':g_virtualBoxManager.type,
2693 'run': lambda cmd,args: runCommandCb(ctx, cmd, args),
2694 'guestlambda': lambda id,guestLambda,args: runGuestCommandCb(ctx, id, guestLambda, args),
2695 'machById': lambda id: machById(ctx,id),
2696 'argsToMach': lambda args: argsToMach(ctx,args),
2697 'progressBar': lambda p: progressBar(ctx,p),
2698 'typeInGuest': typeInGuest,
2699 '_machlist':None
2700 }
2701 interpret(ctx)
2702 g_virtualBoxManager.deinit()
2703 del g_virtualBoxManager
2704
2705if __name__ == '__main__':
2706 main(sys.argv)
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette