VirtualBox

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

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

Python: OSX SDK searching

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