VirtualBox

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

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

Python WS: docs update, minor build changes

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

© 2023 Oracle
ContactPrivacy policyTerms of Use