VirtualBox

source: vbox/trunk/src/VBox/Main/glue/vboxapi.py@ 21878

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

SDK: make documentation match reality, minor refactoring

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.7 KB
Line 
1#
2# Copyright (C) 2009 Sun Microsystems, Inc.
3#
4# This file is part of VirtualBox Open Source Edition (OSE), as
5# available from http://www.virtualbox.org. This file is free software;
6# you can redistribute it and/or modify it under the terms of the GNU
7# General Public License (GPL) as published by the Free Software
8# Foundation, in version 2 as it comes in the "COPYING" file of the
9# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11#
12# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
13# Clara, CA 95054 USA or visit http://www.sun.com if you need
14# additional information or have any questions.
15#
16import sys,os
17import traceback
18
19VboxBinDir = os.environ.get("VBOX_PROGRAM_PATH", None)
20VboxSdkDir = os.environ.get("VBOX_SDK_PATH", None)
21
22if VboxBinDir is None:
23 # Will be set by the installer
24 VboxBinDir = "%VBOX_INSTALL_PATH%"
25
26if VboxSdkDir is None:
27 VboxSdkDir = os.path.join(VboxBinDir,"sdk")
28
29os.environ["VBOX_PROGRAM_PATH"] = VboxBinDir
30os.environ["VBOX_SDK_PATH"] = VboxSdkDir
31sys.path.append(VboxBinDir)
32
33from VirtualBox_constants import VirtualBoxReflectionInfo
34
35class PerfCollector:
36 """ This class provides a wrapper over IPerformanceCollector in order to
37 get more 'pythonic' interface.
38
39 To begin collection of metrics use setup() method.
40
41 To get collected data use query() method.
42
43 It is possible to disable metric collection without changing collection
44 parameters with disable() method. The enable() method resumes metric
45 collection.
46 """
47
48 def __init__(self, vb):
49 """ Initializes the instance.
50
51 Pass an instance of IVirtualBox as parameter.
52 """
53 self.collector = vb.performanceCollector
54
55 def setup(self, names, objects, period, nsamples):
56 """ Discards all previously collected values for the specified
57 metrics, sets the period of collection and the number of retained
58 samples, enables collection.
59 """
60 self.collector.setupMetrics(names, objects, period, nsamples)
61
62 def enable(self, names, objects):
63 """ Resumes metric collection for the specified metrics.
64 """
65 self.collector.enableMetrics(names, objects)
66
67 def disable(self, names, objects):
68 """ Suspends metric collection for the specified metrics.
69 """
70 self.collector.disableMetrics(names, objects)
71
72 def query(self, names, objects):
73 """ Retrieves collected metric values as well as some auxiliary
74 information. Returns an array of dictionaries, one dictionary per
75 metric. Each dictionary contains the following entries:
76 'name': metric name
77 'object': managed object this metric associated with
78 'unit': unit of measurement
79 'scale': divide 'values' by this number to get float numbers
80 'values': collected data
81 'values_as_string': pre-processed values ready for 'print' statement
82 """
83 # Get around the problem with input arrays returned in output parameters (see #3953).
84 if sys.platform == 'win32':
85 (values, names, objects, names_out, objects_out, units, scales, sequence_numbers,
86 indices, lengths) = self.collector.queryMetricsData(names, objects)
87 else:
88 (values, names_out, objects_out, units, scales, sequence_numbers,
89 indices, lengths) = self.collector.queryMetricsData(names, objects)
90 out = []
91 for i in xrange(0, len(names_out)):
92 scale = int(scales[i])
93 if scale != 1:
94 fmt = '%.2f%s'
95 else:
96 fmt = '%d %s'
97 out.append({
98 'name':str(names_out[i]),
99 'object':str(objects_out[i]),
100 'unit':str(units[i]),
101 'scale':scale,
102 'values':[int(values[j]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))],
103 'values_as_string':'['+', '.join([fmt % (int(values[j])/scale, units[i]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))])+']'
104 })
105 return out
106
107def ComifyName(name):
108 return name[0].capitalize()+name[1:]
109
110_COMForward = { 'getattr' : None,
111 'setattr' : None}
112
113def CustomGetAttr(self, attr):
114 # fastpath
115 if self.__class__.__dict__.get(attr) != None:
116 return self.__class__.__dict__.get(attr)
117
118 # try case-insensitivity workaround for class attributes (COM methods)
119 for k in self.__class__.__dict__.keys():
120 if k.lower() == attr.lower():
121 self.__class__.__dict__[attr] = self.__class__.__dict__[k]
122 return getattr(self, k)
123 try:
124 return _COMForward['getattr'](self,ComifyName(attr))
125 except AttributeError:
126 return _COMForward['getattr'](self,attr)
127
128def CustomSetAttr(self, attr, value):
129 try:
130 return _COMForward['setattr'](self, ComifyName(attr), value)
131 except AttributeError:
132 return _COMForward['setattr'](self, attr, value)
133
134class PlatformMSCOM:
135 # Class to fake access to constants in style of foo.bar.boo
136 class ConstantFake:
137 def __init__(self, parent, name):
138 self.__dict__['_parent'] = parent
139 self.__dict__['_name'] = name
140 self.__dict__['_consts'] = {}
141 try:
142 self.__dict__['_depth']=parent.__dict__['_depth']+1
143 except:
144 self.__dict__['_depth']=0
145 if self.__dict__['_depth'] > 4:
146 raise AttributeError
147
148 def __getattr__(self, attr):
149 import win32com
150 from win32com.client import constants
151
152 if attr.startswith("__"):
153 raise AttributeError
154
155 consts = self.__dict__['_consts']
156
157 fake = consts.get(attr, None)
158 if fake != None:
159 return fake
160 try:
161 name = self.__dict__['_name']
162 parent = self.__dict__['_parent']
163 while parent != None:
164 if parent._name is not None:
165 name = parent._name+'_'+name
166 parent = parent._parent
167
168 if name is not None:
169 name += "_" + attr
170 else:
171 name = attr
172 return win32com.client.constants.__getattr__(name)
173 except AttributeError,e:
174 fake = PlatformMSCOM.ConstantFake(self, attr)
175 consts[attr] = fake
176 return fake
177
178
179 class InterfacesWrapper:
180 def __init__(self):
181 self.__dict__['_rootFake'] = PlatformMSCOM.ConstantFake(None, None)
182
183 def __getattr__(self, a):
184 import win32com
185 from win32com.client import constants
186 if a.startswith("__"):
187 raise AttributeError
188 try:
189 return win32com.client.constants.__getattr__(a)
190 except AttributeError,e:
191 return self.__dict__['_rootFake'].__getattr__(a)
192
193 VBOX_TLB_GUID = '{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}'
194 VBOX_TLB_LCID = 0
195 VBOX_TLB_MAJOR = 1
196 VBOX_TLB_MINOR = 0
197
198 def __init__(self, params):
199 from win32com import universal
200 from win32com.client import gencache, DispatchBaseClass
201 from win32com.client import constants, getevents
202 import win32com
203 import pythoncom
204 import win32api
205 self.constants = PlatformMSCOM.InterfacesWrapper()
206 from win32con import DUPLICATE_SAME_ACCESS
207 from win32api import GetCurrentThread,GetCurrentThreadId,DuplicateHandle,GetCurrentProcess
208 pid = GetCurrentProcess()
209 self.tid = GetCurrentThreadId()
210 handle = DuplicateHandle(pid, GetCurrentThread(), pid, 0, 0, DUPLICATE_SAME_ACCESS)
211 self.handles = []
212 self.handles.append(handle)
213 _COMForward['getattr'] = DispatchBaseClass.__dict__['__getattr__']
214 DispatchBaseClass.__dict__['__getattr__'] = CustomGetAttr
215 _COMForward['setattr'] = DispatchBaseClass.__dict__['__setattr__']
216 DispatchBaseClass.__dict__['__setattr__'] = CustomSetAttr
217 win32com.client.gencache.EnsureDispatch('VirtualBox.Session')
218 win32com.client.gencache.EnsureDispatch('VirtualBox.VirtualBox')
219
220 def getSessionObject(self, vbox):
221 import win32com
222 from win32com.client import Dispatch
223 return win32com.client.Dispatch("VirtualBox.Session")
224
225 def getVirtualBox(self):
226 import win32com
227 from win32com.client import Dispatch
228 return win32com.client.Dispatch("VirtualBox.VirtualBox")
229
230 def getConstants(self):
231 return self.constants
232
233 def getType(self):
234 return 'MSCOM'
235
236 def getRemote(self):
237 return False
238
239 def getArray(self, obj, field):
240 return obj.__getattr__(field)
241
242 def initPerThread(self):
243 import pythoncom
244 pythoncom.CoInitializeEx(0)
245
246 def deinitPerThread(self):
247 import pythoncom
248 pythoncom.CoUninitialize()
249
250 def createCallback(self, iface, impl, arg):
251 d = {}
252 d['BaseClass'] = impl
253 d['arg'] = arg
254 d['tlb_guid'] = PlatformMSCOM.VBOX_TLB_GUID
255 str = ""
256 str += "import win32com.server.util\n"
257 #str += "import win32com.server.register\n"
258 #str += "from win32com import universal\n"
259 str += "import pythoncom\n"
260 #str += "universal.RegisterInterfaces(tlb_guid, 0, 1, 0, ['"+iface+"'])\n"
261
262 str += "class "+iface+"Impl(BaseClass):\n"
263 str += " _com_interfaces_ = ['"+iface+"']\n"
264 str += " _typelib_guid_ = tlb_guid\n"
265 str += " _typelib_version_ = 1, 0\n"
266 #str += " _reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER\n"
267 #str += " _reg_clsid_ = '{F21202A2-959A-4149-B1C3-68B9013F3335}'\n"
268 #str += " _reg_progid_ = 'VirtualBox."+iface+"Impl'\n"
269 #str += " _reg_desc_ = 'Generated callback implementation class'\n"
270 #str += " _reg_policy_spec_ = 'win32com.server.policy.EventHandlerPolicy'\n"
271
272 # generate capitalized version of callbacks - that's how Python COM
273 # looks them up on Windows
274 for m in dir(impl):
275 if m.startswith("on"):
276 str += " "+ComifyName(m)+"=BaseClass."+m+"\n"
277
278 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
279 #str += "win32com.server.register.UseCommandLine("+iface+"Impl)\n"
280
281 str += "result = win32com.server.util.wrap("+iface+"Impl())\n"
282 exec (str,d,d)
283 return d['result']
284
285 def waitForEvents(self, timeout):
286 from win32api import GetCurrentThreadId
287 from win32event import MsgWaitForMultipleObjects, \
288 QS_ALLINPUT, WAIT_TIMEOUT, WAIT_OBJECT_0
289 from pythoncom import PumpWaitingMessages
290
291 if (self.tid != GetCurrentThreadId()):
292 raise Exception("wait for events from the same thread you inited!")
293
294 rc = MsgWaitForMultipleObjects(self.handles, 0, timeout, QS_ALLINPUT)
295 if rc >= WAIT_OBJECT_0 and rc < WAIT_OBJECT_0+len(self.handles):
296 # is it possible?
297 pass
298 elif rc==WAIT_OBJECT_0 + len(self.handles):
299 # Waiting messages
300 PumpWaitingMessages()
301 else:
302 # Timeout
303 pass
304
305 def deinit(self):
306 import pythoncom
307 from win32file import CloseHandle
308
309 for h in self.handles:
310 if h is not None:
311 CloseHandle(h)
312 self.handles = None
313 pythoncom.CoUninitialize()
314 pass
315
316 def getPerfCollector(self, vbox):
317 return PerfCollector(vbox)
318
319
320class PlatformXPCOM:
321 def __init__(self, params):
322 sys.path.append(VboxSdkDir+'/bindings/xpcom/python/')
323 import xpcom.vboxxpcom
324 import xpcom
325 import xpcom.components
326
327 def getSessionObject(self, vbox):
328 import xpcom.components
329 return xpcom.components.classes["@virtualbox.org/Session;1"].createInstance()
330
331 def getVirtualBox(self):
332 import xpcom.components
333 return xpcom.components.classes["@virtualbox.org/VirtualBox;1"].createInstance()
334
335 def getConstants(self):
336 import xpcom.components
337 return xpcom.components.interfaces
338
339 def getType(self):
340 return 'XPCOM'
341
342 def getRemote(self):
343 return False
344
345 def getArray(self, obj, field):
346 return obj.__getattr__('get'+ComifyName(field))()
347
348 def initPerThread(self):
349 pass
350
351 def deinitPerThread(self):
352 pass
353
354 def createCallback(self, iface, impl, arg):
355 d = {}
356 d['BaseClass'] = impl
357 d['arg'] = arg
358 str = ""
359 str += "import xpcom.components\n"
360 str += "class "+iface+"Impl(BaseClass):\n"
361 str += " _com_interfaces_ = xpcom.components.interfaces."+iface+"\n"
362 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
363 str += "result = "+iface+"Impl()\n"
364 exec (str,d,d)
365 return d['result']
366
367 def waitForEvents(self, timeout):
368 import xpcom
369 xpcom._xpcom.WaitForEvents(timeout)
370
371 def deinit(self):
372 import xpcom
373 xpcom._xpcom.DeinitCOM()
374
375 def getPerfCollector(self, vbox):
376 return PerfCollector(vbox)
377
378class PlatformWEBSERVICE:
379 def __init__(self, params):
380 sys.path.append(os.path.join(VboxSdkDir,'bindings', 'webservice', 'python', 'lib'))
381 # not really needed, but just fail early if misconfigured
382 import VirtualBox_services
383 import VirtualBox_wrappers
384 from VirtualBox_wrappers import IWebsessionManager2
385
386 if params is not None:
387 self.user = params.get("user", "")
388 self.password = params.get("password", "")
389 self.url = params.get("url", "")
390 else:
391 self.user = ""
392 self.password = ""
393 self.url = None
394 self.vbox = None
395
396 def getSessionObject(self, vbox):
397 return self.wsmgr.getSessionObject(vbox)
398
399 def getVirtualBox(self):
400 return self.connect(self.url, self.user, self.password)
401
402 def connect(self, url, user, passwd):
403 if self.vbox is not None:
404 self.disconnect()
405 from VirtualBox_wrappers import IWebsessionManager2
406 if url is None:
407 url = ""
408 self.url = url
409 if user is None:
410 user = ""
411 self.user = user
412 if passwd is None:
413 passwd = ""
414 self.password = passwd
415 self.wsmgr = IWebsessionManager2(self.url)
416 self.vbox = self.wsmgr.logon(self.user, self.password)
417 if not self.vbox.handle:
418 raise Exception("cannot connect to '"+self.url+"' as '"+self.user+"'")
419 return self.vbox
420
421 def disconnect(self):
422 if self.vbox is not None and self.wsmgr is not None:
423 self.wsmgr.logoff(self.vbox)
424 self.vbox = None
425 self.wsmgr = None
426
427 def getConstants(self):
428 return None
429
430 def getType(self):
431 return 'WEBSERVICE'
432
433 def getRemote(self):
434 return True
435
436 def getArray(self, obj, field):
437 return obj.__getattr__(field)
438
439 def initPerThread(self):
440 pass
441
442 def deinitPerThread(self):
443 pass
444
445 def createCallback(self, iface, impl, arg):
446 raise Exception("no callbacks for webservices")
447
448 def waitForEvents(self, timeout):
449 # Webservices cannot do that yet
450 pass
451
452 def deinit(self):
453 try:
454 disconnect()
455 except:
456 pass
457
458 def getPerfCollector(self, vbox):
459 return PerfCollector(vbox)
460
461class SessionManager:
462 def __init__(self, mgr):
463 self.mgr = mgr
464
465 def getSessionObject(self, vbox):
466 return self.mgr.platform.getSessionObject(vbox)
467
468class VirtualBoxManager:
469 def __init__(self, style, platparams):
470 if style is None:
471 if sys.platform == 'win32':
472 style = "MSCOM"
473 else:
474 style = "XPCOM"
475
476 exec "self.platform = Platform"+style+"(platparams)"
477
478 self.constants = VirtualBoxReflectionInfo()
479 self.type = self.platform.getType()
480 self.remote = self.platform.getRemote()
481 self.style = style
482 self.mgr = SessionManager(self)
483
484 try:
485 self.vbox = self.platform.getVirtualBox()
486 except NameError,ne:
487 print "Installation problem: check that appropriate libs in place"
488 traceback.print_exc()
489 raise ne
490 except Exception,e:
491 print "init exception: ",e
492 traceback.print_exc()
493 if self.remote:
494 self.vbox = None
495 else:
496 raise e
497
498 def getArray(self, obj, field):
499 return self.platform.getArray(obj, field)
500
501 def getVirtualBox(self):
502 return self.platform.getVirtualBox()
503
504 def __del__(self):
505 self.deinit()
506
507 def deinit(self):
508 if hasattr(self, "vbox"):
509 del self.vbox
510 self.vbox = None
511 if hasattr(self, "platform"):
512 self.platform.deinit()
513 self.platform = None
514
515 def initPerThread(self):
516 self.platform.initPerThread()
517
518 def openMachineSession(self, machineId):
519 session = self.mgr.getSessionObject(self.vbox)
520 self.vbox.openSession(session, machineId)
521 return session
522
523 def closeMachineSession(self, session):
524 session.close()
525
526 def deinitPerThread(self):
527 self.platform.deinitPerThread()
528
529 def createCallback(self, iface, impl, arg):
530 return self.platform.createCallback(iface, impl, arg)
531
532 def waitForEvents(self, timeout):
533 return self.platform.waitForEvents(timeout)
534
535 def getPerfCollector(self, vbox):
536 return PerfCollector(vbox)
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