VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxShell/shellcommon.py@ 19852

最後變更 在這個檔案從19852是 19852,由 vboxsync 提交於 16 年 前

Python: generic glue library, hiding all ugly platform details

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.4 KB
 
1import traceback
2import sys
3import pdb
4
5class PerfCollector:
6 """ This class provides a wrapper over IPerformanceCollector in order to
7 get more 'pythonic' interface.
8
9 To begin collection of metrics use setup() method.
10
11 To get collected data use query() method.
12
13 It is possible to disable metric collection without changing collection
14 parameters with disable() method. The enable() method resumes metric
15 collection.
16 """
17
18 def __init__(self, vb):
19 """ Initializes the instance.
20
21 Pass an instance of IVirtualBox as parameter.
22 """
23 self.collector = vb.performanceCollector
24
25 def setup(self, names, objects, period, nsamples):
26 """ Discards all previously collected values for the specified
27 metrics, sets the period of collection and the number of retained
28 samples, enables collection.
29 """
30 self.collector.setupMetrics(names, objects, period, nsamples)
31
32 def enable(self, names, objects):
33 """ Resumes metric collection for the specified metrics.
34 """
35 self.collector.enableMetrics(names, objects)
36
37 def disable(self, names, objects):
38 """ Suspends metric collection for the specified metrics.
39 """
40 self.collector.disableMetrics(names, objects)
41
42 def query(self, names, objects):
43 """ Retrieves collected metric values as well as some auxiliary
44 information. Returns an array of dictionaries, one dictionary per
45 metric. Each dictionary contains the following entries:
46 'name': metric name
47 'object': managed object this metric associated with
48 'unit': unit of measurement
49 'scale': divide 'values' by this number to get float numbers
50 'values': collected data
51 'values_as_string': pre-processed values ready for 'print' statement
52 """
53 (values, names_out, objects_out, units, scales, sequence_numbers,
54 indices, lengths) = self.collector.queryMetricsData(names, objects)
55 out = []
56 for i in xrange(0, len(names_out)):
57 scale = int(scales[i])
58 if scale != 1:
59 fmt = '%.2f%s'
60 else:
61 fmt = '%d %s'
62 out.append({
63 'name':str(names_out[i]),
64 'object':str(objects_out[i]),
65 'unit':str(units[i]),
66 'scale':scale,
67 'values':[int(values[j]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))],
68 'values_as_string':'['+', '.join([fmt % (int(values[j])/scale, units[i]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))])+']'
69 })
70 return out
71
72g_hasreadline = 1
73try:
74 import readline
75 import rlcompleter
76except:
77 g_hasreadline = 0
78
79
80if g_hasreadline:
81 class CompleterNG(rlcompleter.Completer):
82 def __init__(self, dic, ctx):
83 self.ctx = ctx
84 return rlcompleter.Completer.__init__(self,dic)
85
86 def complete(self, text, state):
87 """
88 taken from:
89 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812
90 """
91 if text == "":
92 return ['\t',None][state]
93 else:
94 return rlcompleter.Completer.complete(self,text,state)
95
96 def global_matches(self, text):
97 """
98 Compute matches when text is a simple name.
99 Return a list of all names currently defined
100 in self.namespace that match.
101 """
102
103 matches = []
104 n = len(text)
105
106 for list in [ self.namespace ]:
107 for word in list:
108 if word[:n] == text:
109 matches.append(word)
110
111
112 try:
113 for m in getMachines(self.ctx):
114 # although it has autoconversion, we need to cast
115 # explicitly for subscripts to work
116 word = str(m.name)
117 if word[:n] == text:
118 matches.append(word)
119 word = str(m.id)
120 if word[0] == '{':
121 word = word[1:-1]
122 if word[:n] == text:
123 matches.append(word)
124 except Exception,e:
125 traceback.print_exc()
126 print e
127
128 return matches
129
130
131def autoCompletion(commands, ctx):
132 if not g_hasreadline:
133 return
134
135 comps = {}
136 for (k,v) in commands.items():
137 comps[k] = None
138 completer = CompleterNG(comps, ctx)
139 readline.set_completer(completer.complete)
140 readline.parse_and_bind("tab: complete")
141
142g_verbose = True
143
144def split_no_quotes(s):
145 return s.split()
146
147def createVm(ctx,name,kind,base):
148 mgr = ctx['mgr']
149 vb = ctx['vb']
150 session = mgr.getSessionObject(vb)
151 mach = vb.createMachine(name, kind, base,
152 "00000000-0000-0000-0000-000000000000")
153 mach.saveSettings()
154 print "created machine with UUID",mach.id
155 vb.registerMachine(mach)
156 session.close()
157
158def removeVm(ctx,mach):
159 mgr = ctx['mgr']
160 vb = ctx['vb']
161 id = mach.id
162 print "removing machine ",mach.name,"with UUID",id
163 session = mgr.getSessionObject(vb)
164 vb.openSession(session, id)
165 mach=session.machine
166 for d in mach.getHardDiskAttachments():
167 mach.detachHardDisk(d.controller, d.port, d.device)
168 session.close()
169 mach = vb.unregisterMachine(id)
170 if mach:
171 mach.deleteSettings()
172
173def startVm(ctx,mach,type):
174 mgr = ctx['mgr']
175 vb = ctx['vb']
176 perf = ctx['perf']
177 session = mgr.getSessionObject(vb)
178 uuid = mach.id
179 progress = vb.openRemoteSession(session, uuid, type, "")
180 progress.waitForCompletion(-1)
181 completed = progress.completed
182 rc = int(progress.resultCode)
183 print "Completed:", completed, "rc:",hex(rc&0xffffffff)
184 if rc == 0:
185 # we ignore exceptions to allow starting VM even if
186 # perf collector cannot be started
187 if perf:
188 try:
189 perf.setup(['*'], [mach], 10, 15)
190 except Exception,e:
191 print e
192 if g_verbose:
193 traceback.print_exc()
194 pass
195 # if session not opened, close doesn't make sense
196 session.close()
197 else:
198 # Not yet implemented error string query API for remote API
199 if not ctx['remote']:
200 print session.QueryErrorObject(rc)
201
202def getMachines(ctx):
203 return ctx['global'].getArray(ctx['vb'], 'machines')
204
205def asState(var):
206 if var:
207 return 'on'
208 else:
209 return 'off'
210
211def guestStats(ctx,mach):
212 if not ctx['perf']:
213 return
214 for metric in ctx['perf'].query(["*"], [mach]):
215 print metric['name'], metric['values_as_string']
216
217def guestExec(ctx, machine, console, cmds):
218 exec cmds
219
220def cmdExistingVm(ctx,mach,cmd,args):
221 mgr=ctx['mgr']
222 vb=ctx['vb']
223 session = mgr.getSessionObject(vb)
224 uuid = mach.id
225 try:
226 progress = vb.openExistingSession(session, uuid)
227 except Exception,e:
228 print "Session to '%s' not open: %s" %(mach.name,e)
229 if g_verbose:
230 traceback.print_exc()
231 return
232 if session.state != ctx['ifaces'].SessionState.Open:
233 print "Session to '%s' in wrong state: %s" %(mach.name, session.state)
234 return
235 # unfortunately IGuest is suppressed, thus WebServices knows not about it
236 # this is an example how to handle local only functionality
237 if ctx['remote'] and cmd == 'stats2':
238 print 'Trying to use local only functionality, ignored'
239 return
240 console=session.console
241 ops={'pause' : lambda: console.pause(),
242 'resume': lambda: console.resume(),
243 'powerdown': lambda: console.powerDown(),
244 'stats': lambda: guestStats(ctx, mach),
245 'guest': lambda: guestExec(ctx, mach, console, args)
246 }
247 try:
248 ops[cmd]()
249 except Exception, e:
250 print 'failed: ',e
251 if g_verbose:
252 traceback.print_exc()
253
254 session.close()
255
256# can cache known machines, if needed
257def machById(ctx,id):
258 mach = None
259 for m in getMachines(ctx):
260 if m.name == id:
261 mach = m
262 break
263 mid = str(m.id)
264 if mid[0] == '{':
265 mid = mid[1:-1]
266 if mid == id:
267 mach = m
268 break
269 return mach
270
271def argsToMach(ctx,args):
272 if len(args) < 2:
273 print "usage: %s [vmname|uuid]" %(args[0])
274 return None
275 id = args[1]
276 m = machById(ctx, id)
277 if m == None:
278 print "Machine '%s' is unknown, use list command to find available machines" %(id)
279 return m
280
281def helpCmd(ctx, args):
282 if len(args) == 1:
283 print "Help page:"
284 for i in commands:
285 print " ",i,":", commands[i][0]
286 else:
287 c = commands.get(args[1], None)
288 if c == None:
289 print "Command '%s' not known" %(args[1])
290 else:
291 print " ",args[1],":", c[0]
292 return 0
293
294def listCmd(ctx, args):
295 for m in getMachines(ctx):
296 print "Machine '%s' [%s], state=%s" %(m.name,m.id,m.sessionState)
297 return 0
298
299def infoCmd(ctx,args):
300 if (len(args) < 2):
301 print "usage: info [vmname|uuid]"
302 return 0
303 mach = argsToMach(ctx,args)
304 if mach == None:
305 return 0
306 os = ctx['vb'].getGuestOSType(mach.OSTypeId)
307 print " Name: ",mach.name
308 print " ID: ",mach.id
309 print " OS Type: ",os.description
310 print " RAM: %dM" %(mach.memorySize)
311 print " VRAM: %dM" %(mach.VRAMSize)
312 print " Clipboard mode: %d" %(mach.clipboardMode)
313 print " Machine status: " ,mach.sessionState
314 bios = mach.BIOSSettings
315 print " BIOS ACPI: ",bios.ACPIEnabled
316 print " PAE: ",mach.PAEEnabled
317 print " Hardware virtualization: ",asState(mach.HWVirtExEnabled)
318 print " Nested paging: ",asState(mach.HWVirtExNestedPagingEnabled)
319 print " Last changed: ",mach.lastStateChange
320
321 return 0
322
323def startCmd(ctx, args):
324 mach = argsToMach(ctx,args)
325 if mach == None:
326 return 0
327 if len(args) > 2:
328 type = args[2]
329 else:
330 type = "gui"
331 startVm(ctx, mach, type)
332 return 0
333
334def createCmd(ctx, args):
335 if (len(args) < 3 or len(args) > 4):
336 print "usage: create name ostype <basefolder>"
337 return 0
338 name = args[1]
339 oskind = args[2]
340 if len(args) == 4:
341 base = args[3]
342 else:
343 base = ''
344 try:
345 ctx['vb'].getGuestOSType(oskind)
346 except Exception, e:
347 print 'Unknown OS type:',oskind
348 return 0
349 createVm(ctx, name, oskind, base)
350 return 0
351
352def removeCmd(ctx, args):
353 mach = argsToMach(ctx,args)
354 if mach == None:
355 return 0
356 removeVm(ctx, mach)
357 return 0
358
359def pauseCmd(ctx, args):
360 mach = argsToMach(ctx,args)
361 if mach == None:
362 return 0
363 cmdExistingVm(ctx, mach, 'pause', '')
364 return 0
365
366def powerdownCmd(ctx, args):
367 mach = argsToMach(ctx,args)
368 if mach == None:
369 return 0
370 cmdExistingVm(ctx, mach, 'powerdown', '')
371 return 0
372
373def resumeCmd(ctx, args):
374 mach = argsToMach(ctx,args)
375 if mach == None:
376 return 0
377 cmdExistingVm(ctx, mach, 'resume', '')
378 return 0
379
380def statsCmd(ctx, args):
381 mach = argsToMach(ctx,args)
382 if mach == None:
383 return 0
384 cmdExistingVm(ctx, mach, 'stats', '')
385 return 0
386
387def guestCmd(ctx, args):
388 if (len(args) < 3):
389 print "usage: guest name commands"
390 return 0
391 mach = argsToMach(ctx,args)
392 if mach == None:
393 return 0
394 cmdExistingVm(ctx, mach, 'guest', ' '.join(args[2:]))
395 return 0
396
397def setvarCmd(ctx, args):
398 if (len(args) < 4):
399 print "usage: setvar [vmname|uuid] expr value"
400 return 0
401 mach = argsToMach(ctx,args)
402 if mach == None:
403 return 0
404 vbox = ctx['vb']
405 session = ctx['mgr'].getSessionObject(vbox)
406 vbox.openSession(session, mach.id)
407 mach = session.machine
408 expr = 'mach.'+args[2]+' = '+args[3]
409 print "Executing",expr
410 try:
411 exec expr
412 except Exception, e:
413 print 'failed: ',e
414 if g_verbose:
415 traceback.print_exc()
416 mach.saveSettings()
417 session.close()
418 return 0
419
420def quitCmd(ctx, args):
421 return 1
422
423def aliasesCmd(ctx, args):
424 for (k,v) in aliases.items():
425 print "'%s' is an alias for '%s'" %(k,v)
426 return 0
427
428def verboseCmd(ctx, args):
429 global g_verbose
430 g_verbose = not g_verbose
431 return 0
432
433def hostCmd(ctx, args):
434 host = ctx['vb'].host
435 cnt = host.processorCount
436 print "Processor count:",cnt
437 for i in range(0,cnt):
438 print "Processor #%d speed: %dMHz" %(i,host.getProcessorSpeed(i))
439
440 if ctx['perf']:
441 for metric in ctx['perf'].query(["*"], [host]):
442 print metric['name'], metric['values_as_string']
443
444 return 0
445
446
447def evalCmd(ctx, args):
448 expr = ' '.join(args[1:])
449 try:
450 exec expr
451 except Exception, e:
452 print 'failed: ',e
453 if g_verbose:
454 traceback.print_exc()
455 return 0
456
457aliases = {'s':'start',
458 'i':'info',
459 'l':'list',
460 'h':'help',
461 'a':'aliases',
462 'q':'quit', 'exit':'quit',
463 'v':'verbose'}
464
465commands = {'help':['Prints help information', helpCmd],
466 'start':['Start virtual machine by name or uuid', startCmd],
467 'create':['Create virtual machine', createCmd],
468 'remove':['Remove virtual machine', removeCmd],
469 'pause':['Pause virtual machine', pauseCmd],
470 'resume':['Resume virtual machine', resumeCmd],
471 'stats':['Stats for virtual machine', statsCmd],
472 'powerdown':['Power down virtual machine', powerdownCmd],
473 'list':['Shows known virtual machines', listCmd],
474 'info':['Shows info on machine', infoCmd],
475 'aliases':['Shows aliases', aliasesCmd],
476 'verbose':['Toggle verbosity', verboseCmd],
477 'setvar':['Set VMs variable: setvar Fedora BIOSSettings.ACPIEnabled True', setvarCmd],
478 'eval':['Evaluate arbitrary Python construction: eval for m in getMachines(ctx): print m.name,"has",m.memorySize,"M"', evalCmd],
479 'quit':['Exits', quitCmd],
480 'host':['Show host information', hostCmd],
481 'guest':['Execute command for guest: guest Win32 console.mouse.putMouseEvent(20, 20, 0, 0)', guestCmd],
482 }
483
484def runCommand(ctx, cmd):
485 if len(cmd) == 0: return 0
486 args = split_no_quotes(cmd)
487 if len(args) == 0: return 0
488 c = args[0]
489 if aliases.get(c, None) != None:
490 c = aliases[c]
491 ci = commands.get(c,None)
492 if ci == None:
493 print "Unknown command: '%s', type 'help' for list of known commands" %(c)
494 return 0
495 return ci[1](ctx, args)
496
497
498def interpret(ctx):
499 vbox = ctx['vb']
500 print "Running VirtualBox version %s" %(vbox.version)
501
502 # MSCOM doesn't work with collector yet
503 if ctx['type'] != 'MSCOM':
504 ctx['perf'] = PerfCollector(vbox)
505 else:
506 ctx['perf'] = None
507
508 autoCompletion(commands, ctx)
509
510 # to allow to print actual host information, we collect info for
511 # last 150 secs maximum, (sample every 10 secs and keep up to 15 samples)
512 if ctx['perf']:
513 try:
514 ctx['perf'].setup(['*'], [vbox.host], 10, 15)
515 except:
516 pass
517
518 while True:
519 try:
520 cmd = raw_input("vbox> ")
521 done = runCommand(ctx, cmd)
522 if done != 0: break
523 except KeyboardInterrupt:
524 print '====== You can type quit or q to leave'
525 break
526 except EOFError:
527 break;
528 except Exception,e:
529 print e
530 if g_verbose:
531 traceback.print_exc()
532
533 try:
534 # There is no need to disable metric collection. This is just an example.
535 if ct['perf']:
536 ctx['perf'].disable(['*'], [vbox.host])
537 except:
538 pass
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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