VirtualBox

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

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

vboxshell: typo

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

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