VirtualBox

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

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

Main: generic events (disabled)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.4 KB
Line 
1#
2# Copyright (C) 2009 Oracle Corporation
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#
12import sys,os
13import traceback
14
15# To set Python bitness on OSX use 'export VERSIONER_PYTHON_PREFER_32_BIT=yes'
16
17VboxBinDir = os.environ.get("VBOX_PROGRAM_PATH", None)
18VboxSdkDir = os.environ.get("VBOX_SDK_PATH", None)
19
20if VboxBinDir is None:
21 # Will be set by the installer
22 VboxBinDir = "%VBOX_INSTALL_PATH%"
23
24if VboxSdkDir is None:
25 # Will be set by the installer
26 VboxSdkDir = "%VBOX_SDK_PATH%"
27
28os.environ["VBOX_PROGRAM_PATH"] = VboxBinDir
29os.environ["VBOX_SDK_PATH"] = VboxSdkDir
30sys.path.append(VboxBinDir)
31
32from VirtualBox_constants import VirtualBoxReflectionInfo
33
34class PerfCollector:
35 """ This class provides a wrapper over IPerformanceCollector in order to
36 get more 'pythonic' interface.
37
38 To begin collection of metrics use setup() method.
39
40 To get collected data use query() method.
41
42 It is possible to disable metric collection without changing collection
43 parameters with disable() method. The enable() method resumes metric
44 collection.
45 """
46
47 def __init__(self, mgr, vbox):
48 """ Initializes the instance.
49
50 """
51 self.mgr = mgr
52 self.isMscom = (mgr.type == 'MSCOM')
53 self.collector = vbox.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
84 # parameters (see #3953) for MSCOM.
85 if self.isMscom:
86 (values, names, objects, names_out, objects_out, units, scales, sequence_numbers,
87 indices, lengths) = self.collector.queryMetricsData(names, objects)
88 else:
89 (values, names_out, objects_out, units, scales, sequence_numbers,
90 indices, lengths) = self.collector.queryMetricsData(names, objects)
91 out = []
92 for i in xrange(0, len(names_out)):
93 scale = int(scales[i])
94 if scale != 1:
95 fmt = '%.2f%s'
96 else:
97 fmt = '%d %s'
98 out.append({
99 'name':str(names_out[i]),
100 'object':str(objects_out[i]),
101 'unit':str(units[i]),
102 'scale':scale,
103 'values':[int(values[j]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))],
104 'values_as_string':'['+', '.join([fmt % (int(values[j])/scale, units[i]) for j in xrange(int(indices[i]), int(indices[i])+int(lengths[i]))])+']'
105 })
106 return out
107
108def ComifyName(name):
109 return name[0].capitalize()+name[1:]
110
111_COMForward = { 'getattr' : None,
112 'setattr' : None}
113
114def CustomGetAttr(self, attr):
115 # fastpath
116 if self.__class__.__dict__.get(attr) != None:
117 return self.__class__.__dict__.get(attr)
118
119 # try case-insensitivity workaround for class attributes (COM methods)
120 for k in self.__class__.__dict__.keys():
121 if k.lower() == attr.lower():
122 self.__class__.__dict__[attr] = self.__class__.__dict__[k]
123 return getattr(self, k)
124 try:
125 return _COMForward['getattr'](self,ComifyName(attr))
126 except AttributeError:
127 return _COMForward['getattr'](self,attr)
128
129def CustomSetAttr(self, attr, value):
130 try:
131 return _COMForward['setattr'](self, ComifyName(attr), value)
132 except AttributeError:
133 return _COMForward['setattr'](self, attr, value)
134
135class PlatformMSCOM:
136 # Class to fake access to constants in style of foo.bar.boo
137 class ConstantFake:
138 def __init__(self, parent, name):
139 self.__dict__['_parent'] = parent
140 self.__dict__['_name'] = name
141 self.__dict__['_consts'] = {}
142 try:
143 self.__dict__['_depth']=parent.__dict__['_depth']+1
144 except:
145 self.__dict__['_depth']=0
146 if self.__dict__['_depth'] > 4:
147 raise AttributeError
148
149 def __getattr__(self, attr):
150 import win32com
151 from win32com.client import constants
152
153 if attr.startswith("__"):
154 raise AttributeError
155
156 consts = self.__dict__['_consts']
157
158 fake = consts.get(attr, None)
159 if fake != None:
160 return fake
161 try:
162 name = self.__dict__['_name']
163 parent = self.__dict__['_parent']
164 while parent != None:
165 if parent._name is not None:
166 name = parent._name+'_'+name
167 parent = parent._parent
168
169 if name is not None:
170 name += "_" + attr
171 else:
172 name = attr
173 return win32com.client.constants.__getattr__(name)
174 except AttributeError,e:
175 fake = PlatformMSCOM.ConstantFake(self, attr)
176 consts[attr] = fake
177 return fake
178
179
180 class InterfacesWrapper:
181 def __init__(self):
182 self.__dict__['_rootFake'] = PlatformMSCOM.ConstantFake(None, None)
183
184 def __getattr__(self, a):
185 import win32com
186 from win32com.client import constants
187 if a.startswith("__"):
188 raise AttributeError
189 try:
190 return win32com.client.constants.__getattr__(a)
191 except AttributeError,e:
192 return self.__dict__['_rootFake'].__getattr__(a)
193
194 VBOX_TLB_GUID = '{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}'
195 VBOX_TLB_LCID = 0
196 VBOX_TLB_MAJOR = 1
197 VBOX_TLB_MINOR = 0
198
199 def __init__(self, params):
200 from win32com import universal
201 from win32com.client import gencache, DispatchBaseClass
202 from win32com.client import constants, getevents
203 import win32com
204 import pythoncom
205 import win32api
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 win32com.client.gencache.EnsureDispatch('VirtualBox.CallbackWrapper')
220
221 def getSessionObject(self, vbox):
222 import win32com
223 from win32com.client import Dispatch
224 return win32com.client.Dispatch("VirtualBox.Session")
225
226 def getVirtualBox(self):
227 import win32com
228 from win32com.client import Dispatch
229 return win32com.client.Dispatch("VirtualBox.VirtualBox")
230
231 def getType(self):
232 return 'MSCOM'
233
234 def getRemote(self):
235 return False
236
237 def getArray(self, obj, field):
238 return obj.__getattr__(field)
239
240 def initPerThread(self):
241 import pythoncom
242 pythoncom.CoInitializeEx(0)
243
244 def deinitPerThread(self):
245 import pythoncom
246 pythoncom.CoUninitialize()
247
248 def createCallback(self, iface, impl, arg):
249 d = {}
250 d['BaseClass'] = impl
251 d['arg'] = arg
252 d['tlb_guid'] = PlatformMSCOM.VBOX_TLB_GUID
253 str = ""
254 str += "import win32com.server.util\n"
255 str += "import pythoncom\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_INPROC_SERVER\n"
262 # Maybe we'd better implement Dynamic invoke policy, to be more flexible here
263 str += " _reg_policy_spec_ = 'win32com.server.policy.EventHandlerPolicy'\n"
264
265 # generate capitalized version of callback methods -
266 # that's how Python COM looks them up
267 for m in dir(impl):
268 if m.startswith("on"):
269 str += " "+ComifyName(m)+"=BaseClass."+m+"\n"
270
271 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
272 str += "result = win32com.client.Dispatch('VirtualBox.CallbackWrapper')\n"
273 str += "result.SetLocalObject(win32com.server.util.wrap("+iface+"Impl()))\n"
274 exec (str,d,d)
275 return d['result']
276
277 def waitForEvents(self, timeout):
278 from win32api import GetCurrentThreadId
279 from win32event import MsgWaitForMultipleObjects, \
280 QS_ALLINPUT, WAIT_TIMEOUT, WAIT_OBJECT_0
281 from pythoncom import PumpWaitingMessages
282
283 if (self.tid != GetCurrentThreadId()):
284 raise Exception("wait for events from the same thread you inited!")
285
286 rc = MsgWaitForMultipleObjects(self.handles, 0, timeout, QS_ALLINPUT)
287 if rc >= WAIT_OBJECT_0 and rc < WAIT_OBJECT_0+len(self.handles):
288 # is it possible?
289 pass
290 elif rc==WAIT_OBJECT_0 + len(self.handles):
291 # Waiting messages
292 PumpWaitingMessages()
293 else:
294 # Timeout
295 pass
296
297 def interruptWaitEvents(self):
298 from win32api import PostThreadMessage
299 from win32con import WM_USER
300 PostThreadMessage(self.tid, WM_USER, None, None)
301
302 def deinit(self):
303 import pythoncom
304 from win32file import CloseHandle
305
306 for h in self.handles:
307 if h is not None:
308 CloseHandle(h)
309 self.handles = None
310 pythoncom.CoUninitialize()
311 pass
312
313 def queryInterface(self, obj, klazzName):
314 from win32com.client import CastTo
315 return CastTo(obj, klazzName)
316
317class PlatformXPCOM:
318 def __init__(self, params):
319 sys.path.append(VboxSdkDir+'/bindings/xpcom/python/')
320 import xpcom.vboxxpcom
321 import xpcom
322 import xpcom.components
323
324 def getSessionObject(self, vbox):
325 import xpcom.components
326 return xpcom.components.classes["@virtualbox.org/Session;1"].createInstance()
327
328 def getVirtualBox(self):
329 import xpcom.components
330 return xpcom.components.classes["@virtualbox.org/VirtualBox;1"].createInstance()
331
332 def getType(self):
333 return 'XPCOM'
334
335 def getRemote(self):
336 return False
337
338 def getArray(self, obj, field):
339 return obj.__getattr__('get'+ComifyName(field))()
340
341 def initPerThread(self):
342 import xpcom
343 xpcom._xpcom.AttachThread()
344
345 def deinitPerThread(self):
346 import xpcom
347 xpcom._xpcom.DetachThread()
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 = xpcom.components.classes['@virtualbox.org/CallbackWrapper;1'].createInstance()\n"
359 str += "result.setLocalObject("+iface+"Impl())\n"
360 exec (str,d,d)
361 return d['result']
362
363 def waitForEvents(self, timeout):
364 import xpcom
365 xpcom._xpcom.WaitForEvents(timeout)
366
367 def interruptWaitEvents(self):
368 import xpcom
369 xpcom._xpcom.InterruptWait()
370
371 def deinit(self):
372 import xpcom
373 xpcom._xpcom.DeinitCOM()
374
375 def queryInterface(self, obj, klazzName):
376 import xpcom.components
377 return obj.queryInterface(getattr(xpcom.components.interfaces, klazzName))
378
379class PlatformWEBSERVICE:
380 def __init__(self, params):
381 sys.path.append(os.path.join(VboxSdkDir,'bindings', 'webservice', 'python', 'lib'))
382 # not really needed, but just fail early if misconfigured
383 import VirtualBox_services
384 import VirtualBox_wrappers
385 from VirtualBox_wrappers import IWebsessionManager2
386
387 if params is not None:
388 self.user = params.get("user", "")
389 self.password = params.get("password", "")
390 self.url = params.get("url", "")
391 else:
392 self.user = ""
393 self.password = ""
394 self.url = None
395 self.vbox = None
396
397 def getSessionObject(self, vbox):
398 return self.wsmgr.getSessionObject(vbox)
399
400 def getVirtualBox(self):
401 return self.connect(self.url, self.user, self.password)
402
403 def connect(self, url, user, passwd):
404 if self.vbox is not None:
405 self.disconnect()
406 from VirtualBox_wrappers import IWebsessionManager2
407 if url is None:
408 url = ""
409 self.url = url
410 if user is None:
411 user = ""
412 self.user = user
413 if passwd is None:
414 passwd = ""
415 self.password = passwd
416 self.wsmgr = IWebsessionManager2(self.url)
417 self.vbox = self.wsmgr.logon(self.user, self.password)
418 if not self.vbox.handle:
419 raise Exception("cannot connect to '"+self.url+"' as '"+self.user+"'")
420 return self.vbox
421
422 def disconnect(self):
423 if self.vbox is not None and self.wsmgr is not None:
424 self.wsmgr.logoff(self.vbox)
425 self.vbox = None
426 self.wsmgr = None
427
428 def getType(self):
429 return 'WEBSERVICE'
430
431 def getRemote(self):
432 return True
433
434 def getArray(self, obj, field):
435 return obj.__getattr__(field)
436
437 def initPerThread(self):
438 pass
439
440 def deinitPerThread(self):
441 pass
442
443 def createCallback(self, iface, impl, arg):
444 raise Exception("no callbacks for webservices")
445
446 def waitForEvents(self, timeout):
447 # Webservices cannot do that yet
448 pass
449
450 def interruptWaitEvents(self, timeout):
451 # Webservices cannot do that yet
452 pass
453
454 def deinit(self):
455 try:
456 disconnect()
457 except:
458 pass
459
460 def queryInterface(self, obj, klazzName):
461 # wrong, need to test if class indeed implements this interface
462 return globals()[klazzName](obj.mgr, obj.handle)
463
464class SessionManager:
465 def __init__(self, mgr):
466 self.mgr = mgr
467
468 def getSessionObject(self, vbox):
469 return self.mgr.platform.getSessionObject(vbox)
470
471class VirtualBoxManager:
472 def __init__(self, style, platparams):
473 if style is None:
474 if sys.platform == 'win32':
475 style = "MSCOM"
476 else:
477 style = "XPCOM"
478
479
480 exec "self.platform = Platform"+style+"(platparams)"
481 # for webservices, enums are symbolic
482 self.constants = VirtualBoxReflectionInfo(style == "WEBSERVICE")
483 self.type = self.platform.getType()
484 self.remote = self.platform.getRemote()
485 self.style = style
486 self.mgr = SessionManager(self)
487
488 try:
489 self.vbox = self.platform.getVirtualBox()
490 except NameError,ne:
491 print "Installation problem: check that appropriate libs in place"
492 traceback.print_exc()
493 raise ne
494 except Exception,e:
495 print "init exception: ",e
496 traceback.print_exc()
497 if self.remote:
498 self.vbox = None
499 else:
500 raise e
501
502 def getArray(self, obj, field):
503 return self.platform.getArray(obj, field)
504
505 def getVirtualBox(self):
506 return self.platform.getVirtualBox()
507
508 def __del__(self):
509 self.deinit()
510
511 def deinit(self):
512 if hasattr(self, "vbox"):
513 del self.vbox
514 self.vbox = None
515 if hasattr(self, "platform"):
516 self.platform.deinit()
517 self.platform = None
518
519 def initPerThread(self):
520 self.platform.initPerThread()
521
522 def openMachineSession(self, machineId):
523 session = self.mgr.getSessionObject(self.vbox)
524 try:
525 self.vbox.openExistingSession(session, machineId)
526 except:
527 self.vbox.openSession(session, machineId)
528 return session
529
530 def closeMachineSession(self, session):
531 if session is not None:
532 session.close()
533
534 def deinitPerThread(self):
535 self.platform.deinitPerThread()
536
537 def createCallback(self, iface, impl, arg):
538 return self.platform.createCallback(iface, impl, arg)
539
540 def waitForEvents(self, timeout):
541 return self.platform.waitForEvents(timeout)
542
543 def interruptWaitEvents(self):
544 return self.platform.interruptWaitEvents()
545
546 def getPerfCollector(self, vbox):
547 return PerfCollector(self, vbox)
548
549 def getBinDir(self):
550 global VboxBinDir
551 return VboxBinDir
552
553 def getSdkDir(self):
554 global VboxSdkDir
555 return VboxSdkDir
556
557 def queryInterface(self, obj, klazzName):
558 return self.platform.queryInterface(obj, klazzName)
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