VirtualBox

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

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

typo

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