VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

  • 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 Oracle Corporation
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#
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
314class PlatformXPCOM:
315 def __init__(self, params):
316 sys.path.append(VboxSdkDir+'/bindings/xpcom/python/')
317 import xpcom.vboxxpcom
318 import xpcom
319 import xpcom.components
320
321 def getSessionObject(self, vbox):
322 import xpcom.components
323 return xpcom.components.classes["@virtualbox.org/Session;1"].createInstance()
324
325 def getVirtualBox(self):
326 import xpcom.components
327 return xpcom.components.classes["@virtualbox.org/VirtualBox;1"].createInstance()
328
329 def getType(self):
330 return 'XPCOM'
331
332 def getRemote(self):
333 return False
334
335 def getArray(self, obj, field):
336 return obj.__getattr__('get'+ComifyName(field))()
337
338 def initPerThread(self):
339 import xpcom
340 xpcom._xpcom.AttachThread()
341
342 def deinitPerThread(self):
343 import xpcom
344 xpcom._xpcom.DetachThread()
345
346 def createCallback(self, iface, impl, arg):
347 d = {}
348 d['BaseClass'] = impl
349 d['arg'] = arg
350 str = ""
351 str += "import xpcom.components\n"
352 str += "class "+iface+"Impl(BaseClass):\n"
353 str += " _com_interfaces_ = xpcom.components.interfaces."+iface+"\n"
354 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
355 str += "result = xpcom.components.classes['@virtualbox.org/CallbackWrapper;1'].createInstance()\n"
356 str += "result.setLocalObject("+iface+"Impl())\n"
357 exec (str,d,d)
358 return d['result']
359
360 def waitForEvents(self, timeout):
361 import xpcom
362 xpcom._xpcom.WaitForEvents(timeout)
363
364 def interruptWaitEvents(self):
365 import xpcom
366 xpcom._xpcom.InterruptWait()
367
368 def deinit(self):
369 import xpcom
370 xpcom._xpcom.DeinitCOM()
371
372class PlatformWEBSERVICE:
373 def __init__(self, params):
374 sys.path.append(os.path.join(VboxSdkDir,'bindings', 'webservice', 'python', 'lib'))
375 # not really needed, but just fail early if misconfigured
376 import VirtualBox_services
377 import VirtualBox_wrappers
378 from VirtualBox_wrappers import IWebsessionManager2
379
380 if params is not None:
381 self.user = params.get("user", "")
382 self.password = params.get("password", "")
383 self.url = params.get("url", "")
384 else:
385 self.user = ""
386 self.password = ""
387 self.url = None
388 self.vbox = None
389
390 def getSessionObject(self, vbox):
391 return self.wsmgr.getSessionObject(vbox)
392
393 def getVirtualBox(self):
394 return self.connect(self.url, self.user, self.password)
395
396 def connect(self, url, user, passwd):
397 if self.vbox is not None:
398 self.disconnect()
399 from VirtualBox_wrappers import IWebsessionManager2
400 if url is None:
401 url = ""
402 self.url = url
403 if user is None:
404 user = ""
405 self.user = user
406 if passwd is None:
407 passwd = ""
408 self.password = passwd
409 self.wsmgr = IWebsessionManager2(self.url)
410 self.vbox = self.wsmgr.logon(self.user, self.password)
411 if not self.vbox.handle:
412 raise Exception("cannot connect to '"+self.url+"' as '"+self.user+"'")
413 return self.vbox
414
415 def disconnect(self):
416 if self.vbox is not None and self.wsmgr is not None:
417 self.wsmgr.logoff(self.vbox)
418 self.vbox = None
419 self.wsmgr = None
420
421 def getType(self):
422 return 'WEBSERVICE'
423
424 def getRemote(self):
425 return True
426
427 def getArray(self, obj, field):
428 return obj.__getattr__(field)
429
430 def initPerThread(self):
431 pass
432
433 def deinitPerThread(self):
434 pass
435
436 def createCallback(self, iface, impl, arg):
437 raise Exception("no callbacks for webservices")
438
439 def waitForEvents(self, timeout):
440 # Webservices cannot do that yet
441 pass
442
443 def interruptWaitEvents(self, timeout):
444 # Webservices cannot do that yet
445 pass
446
447 def deinit(self):
448 try:
449 disconnect()
450 except:
451 pass
452
453class SessionManager:
454 def __init__(self, mgr):
455 self.mgr = mgr
456
457 def getSessionObject(self, vbox):
458 return self.mgr.platform.getSessionObject(vbox)
459
460class VirtualBoxManager:
461 def __init__(self, style, platparams):
462 if style is None:
463 if sys.platform == 'win32':
464 style = "MSCOM"
465 else:
466 style = "XPCOM"
467
468
469 exec "self.platform = Platform"+style+"(platparams)"
470 # for webservices, enums are symbolic
471 self.constants = VirtualBoxReflectionInfo(style == "WEBSERVICE")
472 self.type = self.platform.getType()
473 self.remote = self.platform.getRemote()
474 self.style = style
475 self.mgr = SessionManager(self)
476
477 try:
478 self.vbox = self.platform.getVirtualBox()
479 except NameError,ne:
480 print "Installation problem: check that appropriate libs in place"
481 traceback.print_exc()
482 raise ne
483 except Exception,e:
484 print "init exception: ",e
485 traceback.print_exc()
486 if self.remote:
487 self.vbox = None
488 else:
489 raise e
490
491 def getArray(self, obj, field):
492 return self.platform.getArray(obj, field)
493
494 def getVirtualBox(self):
495 return self.platform.getVirtualBox()
496
497 def __del__(self):
498 self.deinit()
499
500 def deinit(self):
501 if hasattr(self, "vbox"):
502 del self.vbox
503 self.vbox = None
504 if hasattr(self, "platform"):
505 self.platform.deinit()
506 self.platform = None
507
508 def initPerThread(self):
509 self.platform.initPerThread()
510
511 def openMachineSession(self, machineId):
512 session = self.mgr.getSessionObject(self.vbox)
513 self.vbox.openSession(session, machineId)
514 return session
515
516 def closeMachineSession(self, session):
517 session.close()
518
519 def deinitPerThread(self):
520 self.platform.deinitPerThread()
521
522 def createCallback(self, iface, impl, arg):
523 return self.platform.createCallback(iface, impl, arg)
524
525 def waitForEvents(self, timeout):
526 return self.platform.waitForEvents(timeout)
527
528 def interruptWaitEvents(self):
529 return self.platform.interruptWaitEvents()
530
531 def getPerfCollector(self, vbox):
532 return PerfCollector(self, vbox)
533
534 def getBinDir(self):
535 global VboxBinDir
536 return VboxBinDir
537
538 def getSdkDir(self):
539 global VboxSdkDir
540 return VboxSdkDir
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