VirtualBox

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

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

API: big medium handling change and lots of assorted other cleanups and fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.8 KB
Line 
1#!/usr/bin/python
2#
3# Copyright (C) 2009 Sun Microsystems, Inc.
4#
5# This file is part of VirtualBox Open Source Edition (OSE), as
6# available from http://www.virtualbox.org. This file is free software;
7# you can redistribute it and/or modify it under the terms of the GNU
8# General Public License (GPL) as published by the Free Software
9# Foundation, in version 2 as it comes in the "COPYING" file of the
10# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
11# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
12#
13# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
14# Clara, CA 95054 USA or visit http://www.sun.com if you need
15# additional information or have any questions.
16#
17#
18#################################################################################
19# This program is a simple interactive shell for VirtualBox. You can query #
20# information and issue commands from a simple command line. #
21# #
22# It also provides you with examples on how to use VirtualBox's Python API. #
23# This shell is even somewhat documented and supports TAB-completion and #
24# history if you have Python readline installed. #
25# #
26# Enjoy. #
27################################################################################
28
29import os,sys
30import traceback
31import shlex
32import time
33
34# Simple implementation of IConsoleCallback, one can use it as skeleton
35# for custom implementations
36class GuestMonitor:
37 def __init__(self, mach):
38 self.mach = mach
39
40 def onMousePointerShapeChange(self, visible, alpha, xHot, yHot, width, height, shape):
41 print "%s: onMousePointerShapeChange: visible=%d" %(self.mach.name, visible)
42 def onMouseCapabilityChange(self, supportsAbsolute, needsHostCursor):
43 print "%s: onMouseCapabilityChange: needsHostCursor=%d" %(self.mach.name, needsHostCursor)
44
45 def onKeyboardLedsChange(self, numLock, capsLock, scrollLock):
46 print "%s: onKeyboardLedsChange capsLock=%d" %(self.mach.name, capsLock)
47
48 def onStateChange(self, state):
49 print "%s: onStateChange state=%d" %(self.mach.name, state)
50
51 def onAdditionsStateChange(self):
52 print "%s: onAdditionsStateChange" %(self.mach.name)
53
54 def onNetworkAdapterChange(self, adapter):
55 print "%s: onNetworkAdapterChange" %(self.mach.name)
56
57 def onSerialPortChange(self, port):
58 print "%s: onSerialPortChange" %(self.mach.name)
59
60 def onParallelPortChange(self, port):
61 print "%s: onParallelPortChange" %(self.mach.name)
62
63 def onStorageControllerChange(self):
64 print "%s: onStorageControllerChange" %(self.mach.name)
65
66 def onMediumChange(self, attachment):
67 print "%s: onMediumChange" %(self.mach.name)
68
69 def onVRDPServerChange(self):
70 print "%s: onVRDPServerChange" %(self.mach.name)
71
72 def onUSBControllerChange(self):
73 print "%s: onUSBControllerChange" %(self.mach.name)
74
75 def onUSBDeviceStateChange(self, device, attached, error):
76 print "%s: onUSBDeviceStateChange" %(self.mach.name)
77
78 def onSharedFolderChange(self, scope):
79 print "%s: onSharedFolderChange" %(self.mach.name)
80
81 def onRuntimeError(self, fatal, id, message):
82 print "%s: onRuntimeError fatal=%d message=%s" %(self.mach.name, fatal, message)
83
84 def onCanShowWindow(self):
85 print "%s: onCanShowWindow" %(self.mach.name)
86 return True
87
88 def onShowWindow(self, winId):
89 print "%s: onShowWindow: %d" %(self.mach.name, winId)
90
91class VBoxMonitor:
92 def __init__(self, params):
93 self.vbox = params[0]
94 self.isMscom = params[1]
95 pass
96
97 def onMachineStateChange(self, id, state):
98 print "onMachineStateChange: %s %d" %(id, state)
99
100 def onMachineDataChange(self,id):
101 print "onMachineDataChange: %s" %(id)
102
103 def onExtraDataCanChange(self, id, key, value):
104 print "onExtraDataCanChange: %s %s=>%s" %(id, key, value)
105 # Witty COM bridge thinks if someone wishes to return tuple, hresult
106 # is one of values we want to return
107 if self.isMscom:
108 return "", 0, True
109 else:
110 return True, ""
111
112 def onExtraDataChange(self, id, key, value):
113 print "onExtraDataChange: %s %s=>%s" %(id, key, value)
114
115 def onMediaRegistered(self, id, type, registered):
116 print "onMediaRegistered: %s" %(id)
117
118 def onMachineRegistered(self, id, registred):
119 print "onMachineRegistered: %s" %(id)
120
121 def onSessionStateChange(self, id, state):
122 print "onSessionStateChange: %s %d" %(id, state)
123
124 def onSnapshotTaken(self, mach, id):
125 print "onSnapshotTaken: %s %s" %(mach, id)
126
127 def onSnapshotDiscarded(self, mach, id):
128 print "onSnapshotDiscarded: %s %s" %(mach, id)
129
130 def onSnapshotChange(self, mach, id):
131 print "onSnapshotChange: %s %s" %(mach, id)
132
133 def onGuestPropertyChange(self, id, name, newValue, flags):
134 print "onGuestPropertyChange: %s: %s=%s" %(id, name, newValue)
135
136g_hasreadline = 1
137try:
138 import readline
139 import rlcompleter
140except:
141 g_hasreadline = 0
142
143
144if g_hasreadline:
145 class CompleterNG(rlcompleter.Completer):
146 def __init__(self, dic, ctx):
147 self.ctx = ctx
148 return rlcompleter.Completer.__init__(self,dic)
149
150 def complete(self, text, state):
151 """
152 taken from:
153 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
154 """
155 if text == "":
156 return ['\t',None][state]
157 else:
158 return rlcompleter.Completer.complete(self,text,state)
159
160 def global_matches(self, text):
161 """
162 Compute matches when text is a simple name.
163 Return a list of all names currently defined
164 in self.namespace that match.
165 """
166
167 matches = []
168 n = len(text)
169
170 for list in [ self.namespace ]:
171 for word in list:
172 if word[:n] == text:
173 matches.append(word)
174
175
176 try:
177 for m in getMachines(self.ctx):
178 # although it has autoconversion, we need to cast
179 # explicitly for subscripts to work
180 word = str(m.name)
181 if word[:n] == text:
182 matches.append(word)
183 word = str(m.id)
184 if word[0] == '{':
185 word = word[1:-1]
186 if word[:n] == text:
187 matches.append(word)
188 except Exception,e:
189 traceback.print_exc()
190 print e
191
192 return matches
193
194
195def autoCompletion(commands, ctx):
196 if not g_hasreadline:
197 return
198
199 comps = {}
200 for (k,v) in commands.items():
201 comps[k] = None
202 completer = CompleterNG(comps, ctx)
203 readline.set_completer(completer.complete)
204 readline.parse_and_bind("tab: complete")
205
206g_verbose = True
207
208def split_no_quotes(s):
209 return shlex.split(s)
210
211def progressBar(ctx,p,wait=1000):
212 try:
213 while not p.completed:
214 print "%d %%\r" %(p.percent),
215 sys.stdout.flush()
216 p.waitForCompletion(wait)
217 ctx['global'].waitForEvents(0)
218 except KeyboardInterrupt:
219 print "Interrupted."
220
221
222def createVm(ctx,name,kind,base):
223 mgr = ctx['mgr']
224 vb = ctx['vb']
225 mach = vb.createMachine(name, kind, base, "")
226 mach.saveSettings()
227 print "created machine with UUID",mach.id
228 vb.registerMachine(mach)
229 # update cache
230 getMachines(ctx, True)
231
232def removeVm(ctx,mach):
233 mgr = ctx['mgr']
234 vb = ctx['vb']
235 id = mach.id
236 print "removing machine ",mach.name,"with UUID",id
237 session = ctx['global'].openMachineSession(id)
238 try:
239 mach = session.machine
240 for d in ctx['global'].getArray(mach, 'hardDiskAttachments'):
241 mach.detachHardDisk(d.controller, d.port, d.device)
242 except:
243 traceback.print_exc()
244 mach.saveSettings()
245 ctx['global'].closeMachineSession(session)
246 mach = vb.unregisterMachine(id)
247 if mach:
248 mach.deleteSettings()
249 # update cache
250 getMachines(ctx, True)
251
252def startVm(ctx,mach,type):
253 mgr = ctx['mgr']
254 vb = ctx['vb']
255 perf = ctx['perf']
256 session = mgr.getSessionObject(vb)
257 uuid = mach.id
258 progress = vb.openRemoteSession(session, uuid, type, "")
259 progressBar(ctx, progress, 100)
260 completed = progress.completed
261 rc = int(progress.resultCode)
262 print "Completed:", completed, "rc:",hex(rc&0xffffffff)
263 if rc == 0:
264 # we ignore exceptions to allow starting VM even if
265 # perf collector cannot be started
266 if perf:
267 try:
268 perf.setup(['*'], [mach], 10, 15)
269 except Exception,e:
270 print e
271 if g_verbose:
272 traceback.print_exc()
273 pass
274 # if session not opened, close doesn't make sense
275 session.close()
276 else:
277 # Not yet implemented error string query API for remote API
278 if not ctx['remote']:
279 print session.QueryErrorObject(rc)
280
281def getMachines(ctx, invalidate = False):
282 if ctx['vb'] is not None:
283 if ctx['_machlist'] is None or invalidate:
284 ctx['_machlist'] = ctx['global'].getArray(ctx['vb'], 'machines')
285 return ctx['_machlist']
286 else:
287 return []
288
289def asState(var):
290 if var:
291 return 'on'
292 else:
293 return 'off'
294
295def guestStats(ctx,mach):
296 if not ctx['perf']:
297 return
298 for metric in ctx['perf'].query(["*"], [mach]):
299 print metric['name'], metric['values_as_string']
300
301def guestExec(ctx, machine, console, cmds):
302 exec cmds
303
304def monitorGuest(ctx, machine, console, dur):
305 cb = ctx['global'].createCallback('IConsoleCallback', GuestMonitor, machine)
306 console.registerCallback(cb)
307 if dur == -1:
308 # not infinity, but close enough
309 dur = 100000
310 try:
311 end = time.time() + dur
312 while time.time() < end:
313 ctx['global'].waitForEvents(500)
314 # We need to catch all exceptions here, otherwise callback will never be unregistered
315 except:
316 pass
317 console.unregisterCallback(cb)
318
319
320def monitorVBox(ctx, dur):
321 vbox = ctx['vb']
322 isMscom = (ctx['global'].type == 'MSCOM')
323 cb = ctx['global'].createCallback('IVirtualBoxCallback', VBoxMonitor, [vbox, isMscom])
324 vbox.registerCallback(cb)
325 if dur == -1:
326 # not infinity, but close enough
327 dur = 100000
328 try:
329 end = time.time() + dur
330 while time.time() < end:
331 ctx['global'].waitForEvents(500)
332 # We need to catch all exceptions here, otherwise callback will never be unregistered
333 except:
334 pass
335 vbox.unregisterCallback(cb)
336
337def cmdExistingVm(ctx,mach,cmd,args):
338 mgr=ctx['mgr']
339 vb=ctx['vb']
340 session = mgr.getSessionObject(vb)
341 uuid = mach.id
342 try:
343 progress = vb.openExistingSession(session, uuid)
344 except Exception,e:
345 print "Session to '%s' not open: %s" %(mach.name,e)
346 if g_verbose:
347 traceback.print_exc()
348 return
349 if session.state != ctx['ifaces'].SessionState_Open:
350 print "Session to '%s' in wrong state: %s" %(mach.name, session.state)
351 return
352 # unfortunately IGuest is suppressed, thus WebServices knows not about it
353 # this is an example how to handle local only functionality
354 if ctx['remote'] and cmd == 'stats2':
355 print 'Trying to use local only functionality, ignored'
356 return
357 console=session.console
358 ops={'pause': lambda: console.pause(),
359 'resume': lambda: console.resume(),
360 'powerdown': lambda: console.powerDown(),
361 'powerbutton': lambda: console.powerButton(),
362 'stats': lambda: guestStats(ctx, mach),
363 'guest': lambda: guestExec(ctx, mach, console, args),
364 'monitorGuest': lambda: monitorGuest(ctx, mach, console, args),
365 'save': lambda: progressBar(ctx,console.saveState())
366 }
367 try:
368 ops[cmd]()
369 except Exception, e:
370 print 'failed: ',e
371 if g_verbose:
372 traceback.print_exc()
373
374 session.close()
375
376def machById(ctx,id):
377 mach = None
378 for m in getMachines(ctx):
379 if m.name == id:
380 mach = m
381 break
382 mid = str(m.id)
383 if mid[0] == '{':
384 mid = mid[1:-1]
385 if mid == id:
386 mach = m
387 break
388 return mach
389
390def argsToMach(ctx,args):
391 if len(args) < 2:
392 print "usage: %s [vmname|uuid]" %(args[0])
393 return None
394 id = args[1]
395 m = machById(ctx, id)
396 if m == None:
397 print "Machine '%s' is unknown, use list command to find available machines" %(id)
398 return m
399
400def helpSingleCmd(cmd,h,sp):
401 if sp != 0:
402 spec = " [ext from "+sp+"]"
403 else:
404 spec = ""
405 print " %s: %s%s" %(cmd,h,spec)
406
407def helpCmd(ctx, args):
408 if len(args) == 1:
409 print "Help page:"
410 names = commands.keys()
411 names.sort()
412 for i in names:
413 helpSingleCmd(i, commands[i][0], commands[i][2])
414 else:
415 cmd = args[1]
416 c = commands.get(cmd)
417 if c == None:
418 print "Command '%s' not known" %(cmd)
419 else:
420 helpSingleCmd(cmd, c[0], c[2])
421 return 0
422
423def listCmd(ctx, args):
424 for m in getMachines(ctx, True):
425 print "Machine '%s' [%s], state=%s" %(m.name,m.id,m.sessionState)
426 return 0
427
428def getControllerType(type):
429 if type == 0:
430 return "Null"
431 elif type == 1:
432 return "LsiLogic"
433 elif type == 2:
434 return "BusLogic"
435 elif type == 3:
436 return "IntelAhci"
437 elif type == 4:
438 return "PIIX3"
439 elif type == 5:
440 return "PIIX4"
441 elif type == 6:
442 return "ICH6"
443 else:
444 return "Unknown"
445
446def infoCmd(ctx,args):
447 if (len(args) < 2):
448 print "usage: info [vmname|uuid]"
449 return 0
450 mach = argsToMach(ctx,args)
451 if mach == None:
452 return 0
453 os = ctx['vb'].getGuestOSType(mach.OSTypeId)
454 print " One can use setvar <mach> <var> <value> to change variable, using name in []."
455 print " Name [name]: %s" %(mach.name)
456 print " ID [n/a]: %s" %(mach.id)
457 print " OS Type [n/a]: %s" %(os.description)
458 print
459 print " CPUs [CPUCount]: %d" %(mach.CPUCount)
460 print " RAM [memorySize]: %dM" %(mach.memorySize)
461 print " VRAM [VRAMSize]: %dM" %(mach.VRAMSize)
462 print " Monitors [monitorCount]: %d" %(mach.monitorCount)
463 print
464 print " Clipboard mode [clipboardMode]: %d" %(mach.clipboardMode)
465 print " Machine status [n/a]: %d" % (mach.sessionState)
466 print
467 bios = mach.BIOSSettings
468 print " ACPI [BIOSSettings.ACPIEnabled]: %s" %(asState(bios.ACPIEnabled))
469 print " APIC [BIOSSettings.IOAPICEnabled]: %s" %(asState(bios.IOAPICEnabled))
470 print " PAE [PAEEnabled]: %s" %(asState(int(mach.PAEEnabled)))
471 print " Hardware virtualization [HWVirtExEnabled]: " + asState(mach.HWVirtExEnabled)
472 print " VPID support [HWVirtExVPIDEnabled]: " + asState(mach.HWVirtExVPIDEnabled)
473 print " Hardware 3d acceleration[accelerate3DEnabled]: " + asState(mach.accelerate3DEnabled)
474 print " Nested paging [HWVirtExNestedPagingEnabled]: " + asState(mach.HWVirtExNestedPagingEnabled)
475 print " Last changed [n/a]: " + time.asctime(time.localtime(long(mach.lastStateChange)/1000))
476 print " VRDP server [VRDPServer.enabled]: %s" %(asState(mach.VRDPServer.enabled))
477
478 controllers = ctx['global'].getArray(mach, 'storageControllers')
479 if controllers:
480 print
481 print " Controllers:"
482 for controller in controllers:
483 print " %s %s bus: %d" % (controller.name, getControllerType(controller.controllerType), controller.bus)
484
485 disks = ctx['global'].getArray(mach, 'hardDiskAttachments')
486 if disks:
487 print
488 print " Hard disk(s):"
489 for disk in disks:
490 print " Controller: %s port: %d device: %d:" % (disk.controller, disk.port, disk.device)
491 hd = disk.hardDisk
492 print " id: %s" %(hd.id)
493 print " location: %s" %(hd.location)
494 print " name: %s" %(hd.name)
495 print " format: %s" %(hd.format)
496 print
497
498 dvd = mach.DVDDrive
499 if dvd.getHostDrive():
500 hdvd = dvd.getHostDrive()
501 print " DVD:"
502 print " Host disk: %s" %(hdvd.name)
503 print
504
505 if dvd.getImage():
506 vdvd = dvd.getImage()
507 print " DVD:"
508 print " Image at: %s" %(vdvd.location)
509 print " Size: %s" %(vdvd.size)
510 print " Id: %s" %(vdvd.id)
511 print
512
513 floppy = mach.floppyDrive
514 if floppy.getHostDrive():
515 hfloppy = floppy.getHostDrive()
516 print " Floppy:"
517 print " Host disk: %s" %(hfloppy.name)
518 print
519
520 if floppy.getImage():
521 vfloppy = floppy.getImage()
522 print " Floppy:"
523 print " Image at: %s" %(vfloppy.location)
524 print " Size: %s" %(vfloppy.size)
525 print
526
527 return 0
528
529def startCmd(ctx, args):
530 mach = argsToMach(ctx,args)
531 if mach == None:
532 return 0
533 if len(args) > 2:
534 type = args[2]
535 else:
536 type = "gui"
537 startVm(ctx, mach, type)
538 return 0
539
540def createCmd(ctx, args):
541 if (len(args) < 3 or len(args) > 4):
542 print "usage: create name ostype <basefolder>"
543 return 0
544 name = args[1]
545 oskind = args[2]
546 if len(args) == 4:
547 base = args[3]
548 else:
549 base = ''
550 try:
551 ctx['vb'].getGuestOSType(oskind)
552 except Exception, e:
553 print 'Unknown OS type:',oskind
554 return 0
555 createVm(ctx, name, oskind, base)
556 return 0
557
558def removeCmd(ctx, args):
559 mach = argsToMach(ctx,args)
560 if mach == None:
561 return 0
562 removeVm(ctx, mach)
563 return 0
564
565def pauseCmd(ctx, args):
566 mach = argsToMach(ctx,args)
567 if mach == None:
568 return 0
569 cmdExistingVm(ctx, mach, 'pause', '')
570 return 0
571
572def powerdownCmd(ctx, args):
573 mach = argsToMach(ctx,args)
574 if mach == None:
575 return 0
576 cmdExistingVm(ctx, mach, 'powerdown', '')
577 return 0
578
579def powerbuttonCmd(ctx, args):
580 mach = argsToMach(ctx,args)
581 if mach == None:
582 return 0
583 cmdExistingVm(ctx, mach, 'powerbutton', '')
584 return 0
585
586def resumeCmd(ctx, args):
587 mach = argsToMach(ctx,args)
588 if mach == None:
589 return 0
590 cmdExistingVm(ctx, mach, 'resume', '')
591 return 0
592
593def saveCmd(ctx, args):
594 mach = argsToMach(ctx,args)
595 if mach == None:
596 return 0
597 cmdExistingVm(ctx, mach, 'save', '')
598 return 0
599
600def statsCmd(ctx, args):
601 mach = argsToMach(ctx,args)
602 if mach == None:
603 return 0
604 cmdExistingVm(ctx, mach, 'stats', '')
605 return 0
606
607def guestCmd(ctx, args):
608 if (len(args) < 3):
609 print "usage: guest name commands"
610 return 0
611 mach = argsToMach(ctx,args)
612 if mach == None:
613 return 0
614 cmdExistingVm(ctx, mach, 'guest', ' '.join(args[2:]))
615 return 0
616
617def setvarCmd(ctx, args):
618 if (len(args) < 4):
619 print "usage: setvar [vmname|uuid] expr value"
620 return 0
621 mach = argsToMach(ctx,args)
622 if mach == None:
623 return 0
624 session = ctx['global'].openMachineSession(mach.id)
625 mach = session.machine
626 expr = 'mach.'+args[2]+' = '+args[3]
627 print "Executing",expr
628 try:
629 exec expr
630 except Exception, e:
631 print 'failed: ',e
632 if g_verbose:
633 traceback.print_exc()
634 mach.saveSettings()
635 session.close()
636 return 0
637
638def quitCmd(ctx, args):
639 return 1
640
641def aliasCmd(ctx, args):
642 if (len(args) == 3):
643 aliases[args[1]] = args[2]
644 return 0
645
646 for (k,v) in aliases.items():
647 print "'%s' is an alias for '%s'" %(k,v)
648 return 0
649
650def verboseCmd(ctx, args):
651 global g_verbose
652 g_verbose = not g_verbose
653 return 0
654
655def getUSBStateString(state):
656 if state == 0:
657 return "NotSupported"
658 elif state == 1:
659 return "Unavailable"
660 elif state == 2:
661 return "Busy"
662 elif state == 3:
663 return "Available"
664 elif state == 4:
665 return "Held"
666 elif state == 5:
667 return "Captured"
668 else:
669 return "Unknown"
670
671def hostCmd(ctx, args):
672 host = ctx['vb'].host
673 cnt = host.processorCount
674 print "Processor count:",cnt
675 for i in range(0,cnt):
676 print "Processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i))
677
678 print "RAM: %dM (free %dM)" %(host.memorySize, host.memoryAvailable)
679 print "OS: %s (%s)" %(host.operatingSystem, host.OSVersion)
680 if host.Acceleration3DAvailable:
681 print "3D acceleration available"
682 else:
683 print "3D acceleration NOT available"
684
685 print "Network interfaces:"
686 for ni in ctx['global'].getArray(host, 'networkInterfaces'):
687 print " %s (%s)" %(ni.name, ni.IPAddress)
688
689 print "DVD drives:"
690 for dd in ctx['global'].getArray(host, 'DVDDrives'):
691 print " %s - %s" %(dd.name, dd.description)
692
693 print "USB devices:"
694 for ud in ctx['global'].getArray(host, 'USBDevices'):
695 print " %s (vendorId=%d productId=%d serial=%s) %s" %(ud.product, ud.vendorId, ud.productId, ud.serialNumber, getUSBStateString(ud.state))
696
697 if ctx['perf']:
698 for metric in ctx['perf'].query(["*"], [host]):
699 print metric['name'], metric['values_as_string']
700
701 return 0
702
703def monitorGuestCmd(ctx, args):
704 if (len(args) < 2):
705 print "usage: monitorGuest name (duration)"
706 return 0
707 mach = argsToMach(ctx,args)
708 if mach == None:
709 return 0
710 dur = 5
711 if len(args) > 2:
712 dur = float(args[2])
713 cmdExistingVm(ctx, mach, 'monitorGuest', dur)
714 return 0
715
716def monitorVBoxCmd(ctx, args):
717 if (len(args) > 2):
718 print "usage: monitorVBox (duration)"
719 return 0
720 dur = 5
721 if len(args) > 1:
722 dur = float(args[1])
723 monitorVBox(ctx, dur)
724 return 0
725
726def getAdapterType(ctx, type):
727 if (type == ctx['global'].constants.NetworkAdapterType_Am79C970A or
728 type == ctx['global'].constants.NetworkAdapterType_Am79C973):
729 return "pcnet"
730 elif (type == ctx['global'].constants.NetworkAdapterType_I82540EM or
731 type == ctx['global'].constants.NetworkAdapterType_I82545EM or
732 type == ctx['global'].constants.NetworkAdapterType_I82543GC):
733 return "e1000"
734 elif (type == ctx['global'].constants.NetworkAdapterType_Null):
735 return None
736 else:
737 raise Exception("Unknown adapter type: "+type)
738
739
740def portForwardCmd(ctx, args):
741 if (len(args) != 5):
742 print "usage: portForward <vm> <adapter> <hostPort> <guestPort>"
743 return 0
744 mach = argsToMach(ctx,args)
745 if mach == None:
746 return 0
747 adapterNum = int(args[2])
748 hostPort = int(args[3])
749 guestPort = int(args[4])
750 proto = "TCP"
751 session = ctx['global'].openMachineSession(mach.id)
752 mach = session.machine
753
754 adapter = mach.getNetworkAdapter(adapterNum)
755 adapterType = getAdapterType(ctx, adapter.adapterType)
756
757 profile_name = proto+"_"+str(hostPort)+"_"+str(guestPort)
758 config = "VBoxInternal/Devices/" + adapterType + "/"
759 config = config + str(adapter.slot) +"/LUN#0/Config/" + profile_name
760
761 mach.setExtraData(config + "/Protocol", proto)
762 mach.setExtraData(config + "/HostPort", str(hostPort))
763 mach.setExtraData(config + "/GuestPort", str(guestPort))
764
765 mach.saveSettings()
766 session.close()
767
768 return 0
769
770
771def showLogCmd(ctx, args):
772 if (len(args) < 2):
773 print "usage: showLog <vm> <num>"
774 return 0
775 mach = argsToMach(ctx,args)
776 if mach == None:
777 return 0
778
779 log = "VBox.log"
780 if (len(args) > 2):
781 log += "."+args[2]
782 fileName = os.path.join(mach.logFolder, log)
783
784 try:
785 lf = open(fileName, 'r')
786 except IOError,e:
787 print "cannot open: ",e
788 return 0
789
790 for line in lf:
791 print line,
792 lf.close()
793
794 return 0
795
796def evalCmd(ctx, args):
797 expr = ' '.join(args[1:])
798 try:
799 exec expr
800 except Exception, e:
801 print 'failed: ',e
802 if g_verbose:
803 traceback.print_exc()
804 return 0
805
806def reloadExtCmd(ctx, args):
807 # maybe will want more args smartness
808 checkUserExtensions(ctx, commands, getHomeFolder(ctx))
809 autoCompletion(commands, ctx)
810 return 0
811
812
813def runScriptCmd(ctx, args):
814 if (len(args) != 2):
815 print "usage: runScript <script>"
816 return 0
817 try:
818 lf = open(args[1], 'r')
819 except IOError,e:
820 print "cannot open:",args[1], ":",e
821 return 0
822
823 try:
824 for line in lf:
825 done = runCommand(ctx, line)
826 if done != 0: break
827 except Exception,e:
828 print "error:",e
829 if g_verbose:
830 traceback.print_exc()
831 lf.close()
832 return 0
833
834def sleepCmd(ctx, args):
835 if (len(args) != 2):
836 print "usage: sleep <secs>"
837 return 0
838
839 try:
840 time.sleep(float(args[1]))
841 except:
842 # to allow sleep interrupt
843 pass
844 return 0
845
846
847def shellCmd(ctx, args):
848 if (len(args) < 2):
849 print "usage: shell <commands>"
850 return 0
851 cmd = ' '.join(args[1:])
852 try:
853 os.system(cmd)
854 except KeyboardInterrupt:
855 # to allow shell command interruption
856 pass
857 return 0
858
859
860def connectCmd(ctx, args):
861 if (len(args) > 4):
862 print "usage: connect [url] [username] [passwd]"
863 return 0
864
865 if ctx['vb'] is not None:
866 print "Already connected, disconnect first..."
867 return 0
868
869 if (len(args) > 1):
870 url = args[1]
871 else:
872 url = None
873
874 if (len(args) > 2):
875 user = args[2]
876 else:
877 user = ""
878
879 if (len(args) > 3):
880 passwd = args[3]
881 else:
882 passwd = ""
883
884 vbox = ctx['global'].platform.connect(url, user, passwd)
885 ctx['vb'] = vbox
886 print "Running VirtualBox version %s" %(vbox.version)
887 ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
888 return 0
889
890def disconnectCmd(ctx, args):
891 if (len(args) != 1):
892 print "usage: disconnect"
893 return 0
894
895 if ctx['vb'] is None:
896 print "Not connected yet."
897 return 0
898
899 try:
900 ctx['global'].platform.disconnect()
901 except:
902 ctx['vb'] = None
903 raise
904
905 ctx['vb'] = None
906 return 0
907
908def exportVMCmd(ctx, args):
909 import sys
910
911 if len(args) < 3:
912 print "usage: exportVm <machine> <path> <format> <license>"
913 return 0
914 mach = ctx['machById'](args[1])
915 if mach is None:
916 return 0
917 path = args[2]
918 if (len(args) > 3):
919 format = args[3]
920 else:
921 format = "ovf-1.0"
922 if (len(args) > 4):
923 license = args[4]
924 else:
925 license = "GPL"
926
927 app = ctx['vb'].createAppliance()
928 desc = mach.export(app)
929 desc.addDescription(ctx['global'].constants.VirtualSystemDescriptionType_License, license, "")
930 p = app.write(format, path)
931 progressBar(ctx, p)
932 print "Exported to %s in format %s" %(path, format)
933 return 0
934
935aliases = {'s':'start',
936 'i':'info',
937 'l':'list',
938 'h':'help',
939 'a':'alias',
940 'q':'quit', 'exit':'quit',
941 'v':'verbose'}
942
943commands = {'help':['Prints help information', helpCmd, 0],
944 'start':['Start virtual machine by name or uuid', startCmd, 0],
945 'create':['Create virtual machine', createCmd, 0],
946 'remove':['Remove virtual machine', removeCmd, 0],
947 'pause':['Pause virtual machine', pauseCmd, 0],
948 'resume':['Resume virtual machine', resumeCmd, 0],
949 'save':['Save execution state of virtual machine', saveCmd, 0],
950 'stats':['Stats for virtual machine', statsCmd, 0],
951 'powerdown':['Power down virtual machine', powerdownCmd, 0],
952 'powerbutton':['Effectively press power button', powerbuttonCmd, 0],
953 'list':['Shows known virtual machines', listCmd, 0],
954 'info':['Shows info on machine', infoCmd, 0],
955 'alias':['Control aliases', aliasCmd, 0],
956 'verbose':['Toggle verbosity', verboseCmd, 0],
957 'setvar':['Set VMs variable: setvar Fedora BIOSSettings.ACPIEnabled True', setvarCmd, 0],
958 'eval':['Evaluate arbitrary Python construction: eval \'for m in getMachines(ctx): print m.name,"has",m.memorySize,"M"\'', evalCmd, 0],
959 'quit':['Exits', quitCmd, 0],
960 'host':['Show host information', hostCmd, 0],
961 'guest':['Execute command for guest: guest Win32 \'console.mouse.putMouseEvent(20, 20, 0, 0)\'', guestCmd, 0],
962 'monitorGuest':['Monitor what happens with the guest for some time: monitorGuest Win32 10', monitorGuestCmd, 0],
963 'monitorVBox':['Monitor what happens with Virtual Box for some time: monitorVBox 10', monitorVBoxCmd, 0],
964 'portForward':['Setup permanent port forwarding for a VM, takes adapter number host port and guest port: portForward Win32 0 8080 80', portForwardCmd, 0],
965 'showLog':['Show log file of the VM, : showLog Win32', showLogCmd, 0],
966 'reloadExt':['Reload custom extensions: reloadExt', reloadExtCmd, 0],
967 'runScript':['Run VBox script: runScript script.vbox', runScriptCmd, 0],
968 'sleep':['Sleep for specified number of seconds: sleep 3.14159', sleepCmd, 0],
969 'shell':['Execute external shell command: shell "ls /etc/rc*"', shellCmd, 0],
970 'exportVm':['Export VM in OVF format: export Win /tmp/win.ovf', exportVMCmd, 0]
971 }
972
973def runCommandArgs(ctx, args):
974 c = args[0]
975 if aliases.get(c, None) != None:
976 c = aliases[c]
977 ci = commands.get(c,None)
978 if ci == None:
979 print "Unknown command: '%s', type 'help' for list of known commands" %(c)
980 return 0
981 return ci[1](ctx, args)
982
983
984def runCommand(ctx, cmd):
985 if len(cmd) == 0: return 0
986 args = split_no_quotes(cmd)
987 if len(args) == 0: return 0
988 return runCommandArgs(ctx, args)
989
990#
991# To write your own custom commands to vboxshell, create
992# file ~/.VirtualBox/shellext.py with content like
993#
994# def runTestCmd(ctx, args):
995# print "Testy test", ctx['vb']
996# return 0
997#
998# commands = {
999# 'test': ['Test help', runTestCmd]
1000# }
1001# and issue reloadExt shell command.
1002# This file also will be read automatically on startup or 'reloadExt'.
1003#
1004# Also one can put shell extensions into ~/.VirtualBox/shexts and
1005# they will also be picked up, so this way one can exchange
1006# shell extensions easily.
1007def addExtsFromFile(ctx, cmds, file):
1008 if not os.path.isfile(file):
1009 return
1010 d = {}
1011 try:
1012 execfile(file, d, d)
1013 for (k,v) in d['commands'].items():
1014 if g_verbose:
1015 print "customize: adding \"%s\" - %s" %(k, v[0])
1016 cmds[k] = [v[0], v[1], file]
1017 except:
1018 print "Error loading user extensions from %s" %(file)
1019 traceback.print_exc()
1020
1021
1022def checkUserExtensions(ctx, cmds, folder):
1023 folder = str(folder)
1024 name = os.path.join(folder, "shellext.py")
1025 addExtsFromFile(ctx, cmds, name)
1026 # also check 'exts' directory for all files
1027 shextdir = os.path.join(folder, "shexts")
1028 if not os.path.isdir(shextdir):
1029 return
1030 exts = os.listdir(shextdir)
1031 for e in exts:
1032 addExtsFromFile(ctx, cmds, os.path.join(shextdir,e))
1033
1034def getHomeFolder(ctx):
1035 if ctx['remote'] or ctx['vb'] is None:
1036 return os.path.join(os.path.expanduser("~"), ".VirtualBox")
1037 else:
1038 return ctx['vb'].homeFolder
1039
1040def interpret(ctx):
1041 if ctx['remote']:
1042 commands['connect'] = ["Connect to remote VBox instance", connectCmd, 0]
1043 commands['disconnect'] = ["Disconnect from remote VBox instance", disconnectCmd, 0]
1044
1045 vbox = ctx['vb']
1046
1047 if vbox is not None:
1048 print "Running VirtualBox version %s" %(vbox.version)
1049 ctx['perf'] = ctx['global'].getPerfCollector(vbox)
1050 else:
1051 ctx['perf'] = None
1052
1053 home = getHomeFolder(ctx)
1054 checkUserExtensions(ctx, commands, home)
1055
1056 autoCompletion(commands, ctx)
1057
1058 # to allow to print actual host information, we collect info for
1059 # last 150 secs maximum, (sample every 10 secs and keep up to 15 samples)
1060 if ctx['perf']:
1061 try:
1062 ctx['perf'].setup(['*'], [vbox.host], 10, 15)
1063 except:
1064 pass
1065
1066 while True:
1067 try:
1068 cmd = raw_input("vbox> ")
1069 done = runCommand(ctx, cmd)
1070 if done != 0: break
1071 except KeyboardInterrupt:
1072 print '====== You can type quit or q to leave'
1073 break
1074 except EOFError:
1075 break;
1076 except Exception,e:
1077 print e
1078 if g_verbose:
1079 traceback.print_exc()
1080 ctx['global'].waitForEvents(0)
1081 try:
1082 # There is no need to disable metric collection. This is just an example.
1083 if ct['perf']:
1084 ctx['perf'].disable(['*'], [vbox.host])
1085 except:
1086 pass
1087
1088def runCommandCb(ctx, cmd, args):
1089 args.insert(0, cmd)
1090 return runCommandArgs(ctx, args)
1091
1092def main(argv):
1093 style = None
1094 autopath = False
1095 argv.pop(0)
1096 while len(argv) > 0:
1097 if argv[0] == "-w":
1098 style = "WEBSERVICE"
1099 if argv[0] == "-a":
1100 autopath = True
1101 argv.pop(0)
1102
1103 if autopath:
1104 cwd = os.getcwd()
1105 vpp = os.environ.get("VBOX_PROGRAM_PATH")
1106 if vpp is None and (os.path.isfile(os.path.join(cwd, "VirtualBox")) or os.path.isfile(os.path.join(cwd, "VirtualBox.exe"))) :
1107 vpp = cwd
1108 print "Autodetected VBOX_PROGRAM_PATH as",vpp
1109 os.environ["VBOX_PROGRAM_PATH"] = cwd
1110 sys.path.append(os.path.join(vpp, "sdk", "installer"))
1111
1112 from vboxapi import VirtualBoxManager
1113 g_virtualBoxManager = VirtualBoxManager(style, None)
1114 ctx = {'global':g_virtualBoxManager,
1115 'mgr':g_virtualBoxManager.mgr,
1116 'vb':g_virtualBoxManager.vbox,
1117 'ifaces':g_virtualBoxManager.constants,
1118 'remote':g_virtualBoxManager.remote,
1119 'type':g_virtualBoxManager.type,
1120 'run': lambda cmd,args: runCommandCb(ctx, cmd, args),
1121 'machById': lambda id: machById(ctx,id),
1122 'progressBar': lambda p: progressBar(ctx,p),
1123 '_machlist':None
1124 }
1125 interpret(ctx)
1126 g_virtualBoxManager.deinit()
1127 del g_virtualBoxManager
1128
1129if __name__ == '__main__':
1130 main(sys.argv)
Note: See TracBrowser for help on using the repository browser.

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