VirtualBox

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

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

Python WS: use symbolic enumeration values, not numerical

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.5 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
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
262 # generate capitalized version of callbacks - that's how Python COM
263 # looks them up on Windows
264 for m in dir(impl):
265 if m.startswith("on"):
266 str += " "+ComifyName(m)+"=BaseClass."+m+"\n"
267
268 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
269 str += "result = win32com.server.util.wrap("+iface+"Impl())\n"
270 exec (str,d,d)
271 return d['result']
272
273 def waitForEvents(self, timeout):
274 from win32api import GetCurrentThreadId
275 from win32event import MsgWaitForMultipleObjects, \
276 QS_ALLINPUT, WAIT_TIMEOUT, WAIT_OBJECT_0
277 from pythoncom import PumpWaitingMessages
278
279 if (self.tid != GetCurrentThreadId()):
280 raise Exception("wait for events from the same thread you inited!")
281
282 rc = MsgWaitForMultipleObjects(self.handles, 0, timeout, QS_ALLINPUT)
283 if rc >= WAIT_OBJECT_0 and rc < WAIT_OBJECT_0+len(self.handles):
284 # is it possible?
285 pass
286 elif rc==WAIT_OBJECT_0 + len(self.handles):
287 # Waiting messages
288 PumpWaitingMessages()
289 else:
290 # Timeout
291 pass
292
293 def deinit(self):
294 import pythoncom
295 from win32file import CloseHandle
296
297 for h in self.handles:
298 if h is not None:
299 CloseHandle(h)
300 self.handles = None
301 pythoncom.CoUninitialize()
302 pass
303
304
305class PlatformXPCOM:
306 def __init__(self, params):
307 sys.path.append(VboxSdkDir+'/bindings/xpcom/python/')
308 import xpcom.vboxxpcom
309 import xpcom
310 import xpcom.components
311
312 def getSessionObject(self, vbox):
313 import xpcom.components
314 return xpcom.components.classes["@virtualbox.org/Session;1"].createInstance()
315
316 def getVirtualBox(self):
317 import xpcom.components
318 return xpcom.components.classes["@virtualbox.org/VirtualBox;1"].createInstance()
319
320 def getType(self):
321 return 'XPCOM'
322
323 def getRemote(self):
324 return False
325
326 def getArray(self, obj, field):
327 return obj.__getattr__('get'+ComifyName(field))()
328
329 def initPerThread(self):
330 pass
331
332 def deinitPerThread(self):
333 pass
334
335 def createCallback(self, iface, impl, arg):
336 d = {}
337 d['BaseClass'] = impl
338 d['arg'] = arg
339 str = ""
340 str += "import xpcom.components\n"
341 str += "class "+iface+"Impl(BaseClass):\n"
342 str += " _com_interfaces_ = xpcom.components.interfaces."+iface+"\n"
343 str += " def __init__(self): BaseClass.__init__(self, arg)\n"
344 str += "result = "+iface+"Impl()\n"
345 exec (str,d,d)
346 return d['result']
347
348 def waitForEvents(self, timeout):
349 import xpcom
350 xpcom._xpcom.WaitForEvents(timeout)
351
352 def deinit(self):
353 import xpcom
354 xpcom._xpcom.DeinitCOM()
355
356class PlatformWEBSERVICE:
357 def __init__(self, params):
358 sys.path.append(os.path.join(VboxSdkDir,'bindings', 'webservice', 'python', 'lib'))
359 # not really needed, but just fail early if misconfigured
360 import VirtualBox_services
361 import VirtualBox_wrappers
362 from VirtualBox_wrappers import IWebsessionManager2
363
364 if params is not None:
365 self.user = params.get("user", "")
366 self.password = params.get("password", "")
367 self.url = params.get("url", "")
368 else:
369 self.user = ""
370 self.password = ""
371 self.url = None
372 self.vbox = None
373
374 def getSessionObject(self, vbox):
375 return self.wsmgr.getSessionObject(vbox)
376
377 def getVirtualBox(self):
378 return self.connect(self.url, self.user, self.password)
379
380 def connect(self, url, user, passwd):
381 if self.vbox is not None:
382 self.disconnect()
383 from VirtualBox_wrappers import IWebsessionManager2
384 if url is None:
385 url = ""
386 self.url = url
387 if user is None:
388 user = ""
389 self.user = user
390 if passwd is None:
391 passwd = ""
392 self.password = passwd
393 self.wsmgr = IWebsessionManager2(self.url)
394 self.vbox = self.wsmgr.logon(self.user, self.password)
395 if not self.vbox.handle:
396 raise Exception("cannot connect to '"+self.url+"' as '"+self.user+"'")
397 return self.vbox
398
399 def disconnect(self):
400 if self.vbox is not None and self.wsmgr is not None:
401 self.wsmgr.logoff(self.vbox)
402 self.vbox = None
403 self.wsmgr = None
404
405 def getType(self):
406 return 'WEBSERVICE'
407
408 def getRemote(self):
409 return True
410
411 def getArray(self, obj, field):
412 return obj.__getattr__(field)
413
414 def initPerThread(self):
415 pass
416
417 def deinitPerThread(self):
418 pass
419
420 def createCallback(self, iface, impl, arg):
421 raise Exception("no callbacks for webservices")
422
423 def waitForEvents(self, timeout):
424 # Webservices cannot do that yet
425 pass
426
427 def deinit(self):
428 try:
429 disconnect()
430 except:
431 pass
432
433class SessionManager:
434 def __init__(self, mgr):
435 self.mgr = mgr
436
437 def getSessionObject(self, vbox):
438 return self.mgr.platform.getSessionObject(vbox)
439
440class VirtualBoxManager:
441 def __init__(self, style, platparams):
442 if style is None:
443 if sys.platform == 'win32':
444 style = "MSCOM"
445 else:
446 style = "XPCOM"
447
448
449 exec "self.platform = Platform"+style+"(platparams)"
450 # for webservices, enums are symbolic
451 self.constants = VirtualBoxReflectionInfo(style == "WEBSERVICE")
452 self.type = self.platform.getType()
453 self.remote = self.platform.getRemote()
454 self.style = style
455 self.mgr = SessionManager(self)
456
457 try:
458 self.vbox = self.platform.getVirtualBox()
459 except NameError,ne:
460 print "Installation problem: check that appropriate libs in place"
461 traceback.print_exc()
462 raise ne
463 except Exception,e:
464 print "init exception: ",e
465 traceback.print_exc()
466 if self.remote:
467 self.vbox = None
468 else:
469 raise e
470
471 def getArray(self, obj, field):
472 return self.platform.getArray(obj, field)
473
474 def getVirtualBox(self):
475 return self.platform.getVirtualBox()
476
477 def __del__(self):
478 self.deinit()
479
480 def deinit(self):
481 if hasattr(self, "vbox"):
482 del self.vbox
483 self.vbox = None
484 if hasattr(self, "platform"):
485 self.platform.deinit()
486 self.platform = None
487
488 def initPerThread(self):
489 self.platform.initPerThread()
490
491 def openMachineSession(self, machineId):
492 session = self.mgr.getSessionObject(self.vbox)
493 self.vbox.openSession(session, machineId)
494 return session
495
496 def closeMachineSession(self, session):
497 session.close()
498
499 def deinitPerThread(self):
500 self.platform.deinitPerThread()
501
502 def createCallback(self, iface, impl, arg):
503 return self.platform.createCallback(iface, impl, arg)
504
505 def waitForEvents(self, timeout):
506 return self.platform.waitForEvents(timeout)
507
508 def getPerfCollector(self, vbox):
509 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