VirtualBox

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

Last change on this file since 21288 was 21288, checked in by vboxsync, 16 years ago

Python: case-insensitive attribute lookup for MS COM

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.3 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.215389.xyz. 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 = 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 (values, names_out, objects_out, units, scales, sequence_numbers,
84 indices, lengths) = self.collector.queryMetricsData(names, objects)
85 out = []
86 for i in xrange(0, len(names_out)):
87 scale = int(scales[i])
88 if scale != 1:
89 fmt = '%.2f%s'
90 else:
91 fmt = '%d %s'
92 out.append({
93 'name':str(names_out[i]),
94 'object':str(objects_out[i]),
95 'unit':str(units[i]),
96 'scale':scale,
97 'values':[int(values[j]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))],
98 'values_as_string':'['+', '.join([fmt % (int(values[j])/scale, units[i]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))])+']'
99 })
100 return out
101
102def ComifyName(name):
103 return name[0].capitalize()+name[1:]
104
105_COMForward = { 'getattr' : None,
106 'setattr' : None}
107
108def CustomGetAttr(self, attr):
109 # fastpath
110 if self.__class__.__dict__.get(attr) != None:
111 return self.__class__.__dict__.get(attr)
112
113 # try case-insensitivity workaround for class attributes (COM methods)
114 for k in self.__class__.__dict__.keys():
115 if k.lower() == attr.lower():
116 self.__class__.__dict__[attr] = self.__class__.__dict__[k]
117 return getattr(self, k)
118 try:
119 return _COMForward['getattr'](self,ComifyName(attr))
120 except AttributeError:
121 return _COMForward['getattr'](self,attr)
122
123def CustomSetAttr(self, attr, value):
124 try:
125 return _COMForward['setattr'](self, ComifyName(attr), value)
126 except AttributeError:
127 return _COMForward['setattr'](self, attr, value)
128
129class PlatformMSCOM:
130 # Class to fake access to constants in style of foo.bar.boo
131 class ConstantFake:
132 def __init__(self, parent, name):
133 self.__dict__['_parent'] = parent
134 self.__dict__['_name'] = name
135 self.__dict__['_consts'] = {}
136 try:
137 self.__dict__['_depth']=parent.__dict__['_depth']+1
138 except:
139 self.__dict__['_depth']=0
140 if self.__dict__['_depth'] > 4:
141 raise AttributeError
142
143 def __getattr__(self, attr):
144 import win32com
145 from win32com.client import constants
146
147 if attr.startswith("__"):
148 raise AttributeError
149
150 consts = self.__dict__['_consts']
151
152 fake = consts.get(attr, None)
153 if fake != None:
154 return fake
155 try:
156 name = self.__dict__['_name']
157 parent = self.__dict__['_parent']
158 while parent != None:
159 if parent._name is not None:
160 name = parent._name+'_'+name
161 parent = parent._parent
162
163 if name is not None:
164 name += "_" + attr
165 else:
166 name = attr
167 return win32com.client.constants.__getattr__(name)
168 except AttributeError,e:
169 fake = PlatformMSCOM.ConstantFake(self, attr)
170 consts[attr] = fake
171 return fake
172
173
174 class InterfacesWrapper:
175 def __init__(self):
176 self.__dict__['_rootFake'] = PlatformMSCOM.ConstantFake(None, None)
177
178 def __getattr__(self, a):
179 import win32com
180 from win32com.client import constants
181 if a.startswith("__"):
182 raise AttributeError
183 try:
184 return win32com.client.constants.__getattr__(a)
185 except AttributeError,e:
186 return self.__dict__['_rootFake'].__getattr__(a)
187
188 VBOX_TLB_GUID = '{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}'
189 VBOX_TLB_LCID = 0
190 VBOX_TLB_MAJOR = 1
191 VBOX_TLB_MINOR = 0
192
193 def __init__(self, params):
194 from win32com import universal
195 from win32com.client import gencache, DispatchBaseClass
196 from win32com.client import constants, getevents
197 import win32com
198 import pythoncom
199 import win32api
200 self.constants = PlatformMSCOM.InterfacesWrapper()
201 from win32con import DUPLICATE_SAME_ACCESS
202 from win32api import GetCurrentThread,GetCurrentThreadId,DuplicateHandle,GetCurrentProcess
203 pid = GetCurrentProcess()
204 self.tid = GetCurrentThreadId()
205 handle = DuplicateHandle(pid, GetCurrentThread(), pid, 0, 0, DUPLICATE_SAME_ACCESS)
206 self.handles = []
207 self.handles.append(handle)
208 _COMForward['getattr'] = DispatchBaseClass.__dict__['__getattr__']
209 DispatchBaseClass.__dict__['__getattr__'] = CustomGetAttr
210 _COMForward['setattr'] = DispatchBaseClass.__dict__['__setattr__']
211 DispatchBaseClass.__dict__['__setattr__'] = CustomSetAttr
212 win32com.client.gencache.EnsureDispatch('VirtualBox.Session')
213 win32com.client.gencache.EnsureDispatch('VirtualBox.VirtualBox')
214
215 def getSessionObject(self, vbox):
216 import win32com
217 from win32com.client import Dispatch
218 return win32com.client.Dispatch("VirtualBox.Session")
219
220 def getVirtualBox(self):
221 import win32com
222 from win32com.client import Dispatch
223 return win32com.client.Dispatch("VirtualBox.VirtualBox")
224
225 def getConstants(self):
226 return self.constants
227
228 def getType(self):
229 return 'MSCOM'
230
231 def getRemote(self):
232 return False
233
234 def getArray(self, obj, field):
235 return obj.__getattr__(field)
236
237 def initPerThread(self):
238 import pythoncom
239 pythoncom.CoInitializeEx(0)
240
241 def deinitPerThread(self):
242 import pythoncom
243 pythoncom.CoUninitialize()
244
245 def createCallback(self, iface, impl, arg):
246 d = {}
247 d['BaseClass'] = impl
248 d['arg'] = arg
249 d['tlb_guid'] = PlatformMSCOM.VBOX_TLB_GUID
250 str = ""
251 str += "import win32com.server.util\n"
252 #str += "import win32com.server.register\n"
253 #str += "from win32com import universal\n"
254 str += "import pythoncom\n"
255 #str += "universal.RegisterInterfaces(tlb_guid, 0, 1, 0, ['"+iface+"'])\n"
256
257 str += "class "+iface+"Impl(BaseClass):\n"
258 str += " _com_interfaces_ = ['"+iface+"']\n"
259 str += " _typelib_guid_ = tlb_guid\n"
260 str += " _typelib_version_ = 1, 0\n"
261 #str += " _reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER\n"
262 #str += " _reg_clsid_ = '{F21202A2-959A-4149-B1C3-68B9013F3335}'\n"
263 #str += " _reg_progid_ = 'VirtualBox."+iface+"Impl'\n"
264 #str += " _reg_desc_ = 'Generated callback implementation class'\n"
265 #str += " _reg_policy_spec_ = 'win32com.server.policy.EventHandlerPolicy'\n"
266
267 # generate capitalized version of callbacks - that's how Python COM
268 # looks them up on Windows
269 for m in dir(impl):
270 if m.startswith("on"):
271 str += " "+m[0].capitalize()+m[1:]+"=BaseClass."+m+"\n"
272
273 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
274 #str += "win32com.server.register.UseCommandLine("+iface+"Impl)\n"
275
276 str += "result = win32com.server.util.wrap("+iface+"Impl())\n"
277 exec (str,d,d)
278 return d['result']
279
280 def waitForEvents(self, timeout):
281 from win32api import GetCurrentThreadId
282 from win32event import MsgWaitForMultipleObjects, \
283 QS_ALLINPUT, WAIT_TIMEOUT, WAIT_OBJECT_0
284 from pythoncom import PumpWaitingMessages
285
286 if (self.tid != GetCurrentThreadId()):
287 raise Exception("wait for events from the same thread you inited!")
288
289 rc = MsgWaitForMultipleObjects(self.handles, 0, timeout, QS_ALLINPUT)
290 if rc >= WAIT_OBJECT_0 and rc < WAIT_OBJECT_0+len(self.handles):
291 # is it possible?
292 pass
293 elif rc==WAIT_OBJECT_0 + len(self.handles):
294 # Waiting messages
295 PumpWaitingMessages()
296 else:
297 # Timeout
298 pass
299
300 def deinit(self):
301 import pythoncom
302 from win32file import CloseHandle
303
304 for h in self.handles:
305 if h is not None:
306 CloseHandle(h)
307 self.handles = None
308 pythoncom.CoUninitialize()
309 pass
310
311 def getPerfCollector(self, vbox):
312 return PerfCollector(vbox)
313
314
315class PlatformXPCOM:
316 def __init__(self, params):
317 sys.path.append(VboxSdkDir+'/bindings/xpcom/python/')
318 import xpcom.vboxxpcom
319 import xpcom
320 import xpcom.components
321
322 def getSessionObject(self, vbox):
323 import xpcom.components
324 return xpcom.components.classes["@virtualbox.org/Session;1"].createInstance()
325
326 def getVirtualBox(self):
327 import xpcom.components
328 return xpcom.components.classes["@virtualbox.org/VirtualBox;1"].createInstance()
329
330 def getConstants(self):
331 import xpcom.components
332 return xpcom.components.interfaces
333
334 def getType(self):
335 return 'XPCOM'
336
337 def getRemote(self):
338 return False
339
340 def getArray(self, obj, field):
341 return obj.__getattr__('get'+field.capitalize())()
342
343 def initPerThread(self):
344 pass
345
346 def deinitPerThread(self):
347 pass
348
349 def createCallback(self, iface, impl, arg):
350 d = {}
351 d['BaseClass'] = impl
352 d['arg'] = arg
353 str = ""
354 str += "import xpcom.components\n"
355 str += "class "+iface+"Impl(BaseClass):\n"
356 str += " _com_interfaces_ = xpcom.components.interfaces."+iface+"\n"
357 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
358 str += "result = "+iface+"Impl()\n"
359 exec (str,d,d)
360 return d['result']
361
362 def waitForEvents(self, timeout):
363 import xpcom
364 xpcom._xpcom.WaitForEvents(timeout)
365
366 def deinit(self):
367 import xpcom
368 xpcom._xpcom.DeinitCOM()
369
370 def getPerfCollector(self, vbox):
371 return PerfCollector(vbox)
372
373class PlatformWEBSERVICE:
374 def __init__(self, params):
375 sys.path.append(VboxSdkDir+'/bindings/webservice/python/lib')
376 import VirtualBox_services
377 import VirtualBox_wrappers
378 from VirtualBox_wrappers import IWebsessionManager2
379 if params is not None:
380 self.user = params.get("user", "")
381 self.password = params.get("password", "")
382 self.url = params.get("url", "")
383 else:
384 self.user = ""
385 self.password = ""
386 self.url = None
387 self.wsmgr = IWebsessionManager2(self.url)
388
389 def getSessionObject(self, vbox):
390 return self.wsmgr.getSessionObject(vbox)
391
392 def getVirtualBox(self):
393 self.vbox = self.wsmgr.logon(self.user, self.password)
394
395 def getConstants(self):
396 return None
397
398 def getType(self):
399 return 'WEBSERVICE'
400
401 def getRemote(self):
402 return True
403
404 def getArray(self, obj, field):
405 return obj.__getattr__(field)
406
407 def initPerThread(self):
408 pass
409
410 def deinitPerThread(self):
411 pass
412
413 def createCallback(self, iface, impl, arg):
414 raise Exception("no callbacks for webservices")
415
416 def waitForEvents(self, timeout):
417 # Webservices cannot do that yet
418 pass
419
420 def deinit(self):
421 try:
422 if self.vbox is not None:
423 self.wsmg.logoff(self.vbox)
424 self.vbox = None
425 except:
426 pass
427
428 def getPerfCollector(self, vbox):
429 return PerfCollector(vbox)
430
431class SessionManager:
432 def __init__(self, mgr):
433 self.mgr = mgr
434
435 def getSessionObject(self, vbox):
436 return self.mgr.platform.getSessionObject(vbox)
437
438class VirtualBoxManager:
439 def __init__(self, style, platparams):
440 if style is None:
441 if sys.platform == 'win32':
442 style = "MSCOM"
443 else:
444 style = "XPCOM"
445 try:
446 exec "self.platform = Platform"+style+"(platparams)"
447 self.vbox = self.platform.getVirtualBox()
448 self.mgr = SessionManager(self)
449 self.constants = VirtualBoxReflectionInfo()
450 self.type = self.platform.getType()
451 self.remote = self.platform.getRemote()
452 self.style = style
453 except Exception,e:
454 print "init exception: ",e
455 traceback.print_exc()
456 raise e
457
458 def getArray(self, obj, field):
459 return self.platform.getArray(obj, field)
460
461 def getVirtualBox(self):
462 return self.platform.getVirtualBox()
463
464 def __del__(self):
465 self.deinit()
466
467 def deinit(self):
468 if hasattr(self, "vbox"):
469 del self.vbox
470 self.vbox = None
471 if hasattr(self, "platform"):
472 self.platform.deinit()
473 self.platform = None
474
475 def initPerThread(self):
476 self.platform.initPerThread()
477
478 def openMachineSession(self, machineId):
479 session = self.mgr.getSessionObject(self.vbox)
480 self.vbox.openSession(session, machineId)
481 return session
482
483 def closeMachineSession(self, session):
484 session.close()
485
486 def deinitPerThread(self):
487 self.platform.deinitPerThread()
488
489 def createCallback(self, iface, impl, arg):
490 return self.platform.createCallback(iface, impl, arg)
491
492 def waitForEvents(self, timeout):
493 return self.platform.waitForEvents(timeout)
494
495 def getPerfCollector(self, vbox):
496 return PerfCollector(vbox)
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