VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py@ 70490

Last change on this file since 70490 was 70490, checked in by vboxsync, 7 years ago

testdrivers/vbox.py,vboxwrappers.py: Adjustments for NT 3.1 (buslogic, s/vboxtxt-readme.txt/VBOXTXTREADME.TXT/).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 119.1 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 70490 2018-01-08 22:14:41Z vboxsync $
3# pylint: disable=C0302
4
5"""
6VirtualBox Wrapper Classes
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2017 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 70490 $"
31
32
33# Standard Python imports.
34import os
35import socket
36
37# Validation Kit imports.
38from common import utils;
39from testdriver import base;
40from testdriver import reporter;
41from testdriver import txsclient;
42from testdriver import vboxcon;
43from testdriver import vbox;
44from testdriver.base import TdTaskBase;
45
46
47def _ControllerNameToBusAndType(sController):
48 """ Translate a controller name to a storage bus. """
49 if sController == "IDE Controller":
50 eBus = vboxcon.StorageBus_IDE;
51 eType = vboxcon.StorageControllerType_PIIX4;
52 elif sController == "SATA Controller":
53 eBus = vboxcon.StorageBus_SATA;
54 eType = vboxcon.StorageControllerType_IntelAhci;
55 elif sController == "Floppy Controller":
56 eType = vboxcon.StorageControllerType_I82078;
57 eBus = vboxcon.StorageBus_Floppy;
58 elif sController == "SAS Controller":
59 eBus = vboxcon.StorageBus_SAS;
60 eType = vboxcon.StorageControllerType_LsiLogicSas;
61 elif sController == "SCSI Controller":
62 eBus = vboxcon.StorageBus_SCSI;
63 eType = vboxcon.StorageControllerType_LsiLogic;
64 elif sController == "BusLogic SCSI Controller":
65 eBus = vboxcon.StorageBus_SCSI;
66 eType = vboxcon.StorageControllerType_BusLogic;
67 elif sController == "NVMe Controller":
68 eBus = vboxcon.StorageBus_PCIe;
69 eType = vboxcon.StorageControllerType_NVMe;
70 else:
71 eBus = vboxcon.StorageBus_Null;
72 eType = vboxcon.StorageControllerType_Null;
73 return (eBus, eType);
74
75
76def _nameMachineState(eState):
77 """ Gets the name (string) of a machine state."""
78 if eState == vboxcon.MachineState_PoweredOff: return 'PoweredOff';
79 if eState == vboxcon.MachineState_Saved: return 'Saved';
80 if eState == vboxcon.MachineState_Teleported: return 'Teleported';
81 if eState == vboxcon.MachineState_Aborted: return 'Aborted';
82 if eState == vboxcon.MachineState_Running: return 'Running';
83 if eState == vboxcon.MachineState_Paused: return 'Paused';
84 if eState == vboxcon.MachineState_Stuck: return 'GuruMeditation';
85 if eState == vboxcon.MachineState_Teleporting: return 'Teleporting';
86 if eState == vboxcon.MachineState_LiveSnapshotting: return 'LiveSnapshotting';
87 if eState == vboxcon.MachineState_Starting: return 'Starting';
88 if eState == vboxcon.MachineState_Stopping: return 'Stopping';
89 if eState == vboxcon.MachineState_Saving: return 'Saving';
90 if eState == vboxcon.MachineState_Restoring: return 'Restoring';
91 if eState == vboxcon.MachineState_TeleportingPausedVM: return 'TeleportingPausedVM';
92 if eState == vboxcon.MachineState_TeleportingIn: return 'TeleportingIn';
93 if eState == vboxcon.MachineState_FaultTolerantSyncing: return 'FaultTolerantSyncing';
94 if eState == vboxcon.MachineState_DeletingSnapshotOnline: return 'DeletingSnapshotOnline';
95 if eState == vboxcon.MachineState_DeletingSnapshotPaused: return 'DeletingSnapshotPaused';
96 if eState == vboxcon.MachineState_RestoringSnapshot: return 'RestoringSnapshot';
97 if eState == vboxcon.MachineState_DeletingSnapshot: return 'DeletingSnapshot';
98 if eState == vboxcon.MachineState_SettingUp: return 'SettingUp';
99 return 'Unknown-%s' % (eState,);
100
101
102class VirtualBoxWrapper(object): # pylint: disable=R0903
103 """
104 Wrapper around the IVirtualBox object that adds some (hopefully) useful
105 utility methods
106
107 The real object can be accessed thru the o member. That said, members can
108 be accessed directly as well.
109 """
110
111 def __init__(self, oVBox, oVBoxMgr, fpApiVer, oTstDrv):
112 self.o = oVBox;
113 self.oVBoxMgr = oVBoxMgr;
114 self.fpApiVer = fpApiVer;
115 self.oTstDrv = oTstDrv;
116
117 def __getattr__(self, sName):
118 # Try ourselves first.
119 try:
120 oAttr = self.__dict__[sName];
121 except:
122 #try:
123 # oAttr = dir(self)[sName];
124 #except AttributeError:
125 oAttr = getattr(self.o, sName);
126 return oAttr;
127
128 #
129 # Utilities.
130 #
131
132 def registerDerivedEventHandler(self, oSubClass, dArgs = None):
133 """
134 Create an instance of the given VirtualBoxEventHandlerBase sub-class
135 and register it.
136
137 The new instance is returned on success. None is returned on error.
138 """
139 dArgsCopy = dArgs.copy() if dArgs is not None else dict();
140 dArgsCopy['oVBox'] = self;
141 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
142 self.o, 'IVirtualBox', 'IVirtualBoxCallback');
143
144 def deleteHdByLocation(self, sHdLocation):
145 """
146 Deletes a disk image from the host, given it's location.
147 Returns True on success and False on failure. Error information is logged.
148 """
149 try:
150 oIMedium = self.o.findHardDisk(sHdLocation);
151 except:
152 try:
153 if self.fpApiVer >= 4.1:
154 oIMedium = self.o.openMedium(sHdLocation, vboxcon.DeviceType_HardDisk,
155 vboxcon.AccessMode_ReadWrite, False);
156 elif self.fpApiVer >= 4.0:
157 oIMedium = self.o.openMedium(sHdLocation, vboxcon.DeviceType_HardDisk,
158 vboxcon.AccessMode_ReadWrite);
159 else:
160 oIMedium = self.o.openHardDisk(sHdLocation, vboxcon.AccessMode_ReadOnly, False, "", False, "");
161 except:
162 return reporter.errorXcpt('failed to open hd "%s"' % (sHdLocation));
163 return self.deleteHdByMedium(oIMedium)
164
165 def deleteHdByMedium(self, oIMedium):
166 """
167 Deletes a disk image from the host, given an IMedium reference.
168 Returns True on success and False on failure. Error information is logged.
169 """
170 try: oProgressCom = oIMedium.deleteStorage();
171 except: return reporter.errorXcpt('deleteStorage() for disk %s failed' % (oIMedium,));
172 try: oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (oIMedium.location));
173 except: return reporter.errorXcpt();
174 oProgress.wait();
175 oProgress.logResult();
176 return oProgress.isSuccess();
177
178
179
180class ProgressWrapper(TdTaskBase):
181 """
182 Wrapper around a progress object for making it a task and providing useful
183 utility methods.
184 The real progress object can be accessed thru the o member.
185 """
186
187 def __init__(self, oProgress, oVBoxMgr, oTstDrv, sName):
188 TdTaskBase.__init__(self, utils.getCallerName());
189 self.o = oProgress;
190 self.oVBoxMgr = oVBoxMgr;
191 self.oTstDrv = oTstDrv;
192 self.sName = sName;
193
194 def toString(self):
195 return '<%s sName=%s, oProgress=%s >' \
196 % (TdTaskBase.toString(self), self.sName, self.o);
197
198 #
199 # TdTaskBase overrides.
200 #
201
202 def pollTask(self, fLocked = False):
203 """
204 Overrides TdTaskBase.pollTask().
205
206 This method returns False until the progress object has completed.
207 """
208 self.doQuickApiTest();
209 try:
210 try:
211 if self.o.completed:
212 return True;
213 except:
214 pass;
215 finally:
216 self.oTstDrv.processPendingEvents();
217 return False;
218
219 def waitForTask(self, cMsTimeout = 0):
220 """
221 Overrides TdTaskBase.waitForTask().
222 Process XPCOM/COM events while waiting.
223 """
224 msStart = base.timestampMilli();
225 fState = self.pollTask(False);
226 while not fState:
227 cMsElapsed = base.timestampMilli() - msStart;
228 if cMsElapsed > cMsTimeout:
229 break;
230 cMsToWait = cMsTimeout - cMsElapsed;
231 if cMsToWait > 500:
232 cMsToWait = 500;
233 try:
234 self.o.waitForCompletion(cMsToWait);
235 except KeyboardInterrupt: raise;
236 except: pass;
237 reporter.doPollWork('ProgressWrapper.waitForTask');
238 fState = self.pollTask(False);
239 return fState;
240
241 #
242 # Utility methods.
243 #
244
245 def isSuccess(self):
246 """
247 Tests if the progress object completed successfully.
248 Returns True on success, False on failure or incomplete.
249 """
250 if not self.isCompleted():
251 return False;
252 return self.getResult() >= 0;
253
254 def isCompleted(self):
255 """
256 Wrapper around IProgress.completed.
257 """
258 return self.pollTask();
259
260 def isCancelable(self):
261 """
262 Wrapper around IProgress.cancelable.
263 """
264 try:
265 fRc = self.o.cancelable;
266 except:
267 reporter.logXcpt();
268 fRc = False;
269 return fRc;
270
271 def wasCanceled(self):
272 """
273 Wrapper around IProgress.canceled.
274 """
275 try:
276 fRc = self.o.canceled;
277 except:
278 reporter.logXcpt(self.sName);
279 fRc = False;
280 return fRc;
281
282 def cancel(self):
283 """
284 Wrapper around IProgress.cancel()
285 Returns True on success, False on failure (logged as error).
286 """
287 try:
288 self.o.cancel();
289 except:
290 reporter.errorXcpt(self.sName);
291 return False;
292 return True;
293
294 def getResult(self):
295 """
296 Wrapper around IProgress.resultCode.
297 """
298 try:
299 iRc = self.o.resultCode;
300 except:
301 reporter.logXcpt(self.sName);
302 iRc = -1;
303 return iRc;
304
305 def getErrInfoResultCode(self):
306 """
307 Wrapper around IProgress.errorInfo.resultCode.
308
309 Returns the string on success, -1 on bad objects (logged as error), and
310 -2 on missing errorInfo object.
311 """
312 iRc = -1;
313 try:
314 oErrInfo = self.o.errorInfo;
315 except:
316 reporter.errorXcpt(self.sName);
317 else:
318 if oErrInfo is None:
319 iRc = -2;
320 else:
321 try:
322 iRc = oErrInfo.resultCode;
323 except:
324 reporter.errorXcpt();
325 return iRc;
326
327 def getErrInfoText(self):
328 """
329 Wrapper around IProgress.errorInfo.text.
330
331 Returns the string on success, None on failure. Missing errorInfo is
332 not logged as an error, all other failures are.
333 """
334 sText = None;
335 try:
336 oErrInfo = self.o.errorInfo;
337 except:
338 reporter.log2Xcpt(self.sName);
339 else:
340 if oErrInfo is not None:
341 try:
342 sText = oErrInfo.text;
343 except:
344 reporter.errorXcpt();
345 return sText;
346
347 def stringifyErrorInfo(self):
348 """
349 Formats IProgress.errorInfo into a string.
350 """
351 try:
352 oErrInfo = self.o.errorInfo;
353 except:
354 reporter.logXcpt(self.sName);
355 sErr = 'no error info';
356 else:
357 sErr = vbox.stringifyErrorInfo(oErrInfo);
358 return sErr;
359
360 def stringifyResult(self):
361 """
362 Stringify the result.
363 """
364 if self.isCompleted():
365 if self.wasCanceled():
366 sRet = 'Progress %s: Canceled, hrc=%s' % (self.sName, vbox.ComError.toString(self.getResult()));
367 elif self.getResult() == 0:
368 sRet = 'Progress %s: Success' % (self.sName,);
369 elif self.getResult() > 0:
370 sRet = 'Progress %s: Success (hrc=%s)' % (self.sName, vbox.ComError.toString(self.getResult()));
371 else:
372 sRet = 'Progress %s: Failed! %s' % (self.sName, self.stringifyErrorInfo());
373 else:
374 sRet = 'Progress %s: Not completed yet...' % (self.sName);
375 return sRet;
376
377 def logResult(self, fIgnoreErrors = False):
378 """ Logs the result. """
379 sText = self.stringifyResult();
380 if self.isCompleted() and self.getResult() < 0 \
381 and fIgnoreErrors is False:
382 return reporter.error(sText);
383 return reporter.log(sText);
384
385 def waitOnProgress(self, cMsInterval = 1000):
386 """
387 See vbox.TestDriver.waitOnProgress.
388 """
389 self.doQuickApiTest();
390 return self.oTstDrv.waitOnProgress(self.o, cMsInterval);
391
392 def wait(self, cMsTimeout = 60000, fErrorOnTimeout = True, cMsInterval = 1000):
393 """
394 Wait on the progress object for a while.
395
396 Returns the resultCode of the progress object if completed.
397 Returns -1 on timeout, logged as error if fErrorOnTimeout is set.
398 Returns -2 is the progress object is invalid or waitForCompletion
399 fails (logged as errors).
400 """
401 msStart = base.timestampMilli();
402 while True:
403 self.oTstDrv.processPendingEvents();
404 self.doQuickApiTest();
405 try:
406 if self.o.completed:
407 break;
408 except:
409 reporter.errorXcpt(self.sName);
410 return -2;
411 self.oTstDrv.processPendingEvents();
412
413 cMsElapsed = base.timestampMilli() - msStart;
414 if cMsElapsed > cMsTimeout:
415 if fErrorOnTimeout:
416 reporter.error('Timing out after waiting for %u s on "%s"' % (cMsTimeout / 1000, self.sName))
417 return -1;
418
419 try:
420 self.o.waitForCompletion(cMsInterval);
421 except:
422 reporter.errorXcpt(self.sName);
423 return -2;
424 reporter.doPollWork('ProgressWrapper.wait');
425
426 try:
427 rc = self.o.resultCode;
428 except:
429 rc = -2;
430 reporter.errorXcpt(self.sName);
431 self.oTstDrv.processPendingEvents();
432 return rc;
433
434 def waitForOperation(self, iOperation, cMsTimeout = 60000, fErrorOnTimeout = True, cMsInterval = 1000, \
435 fIgnoreErrors = False):
436 """
437 Wait for the completion of a operation.
438
439 Negative iOperation values are relative to operationCount (this
440 property may changed at runtime).
441
442 Returns 0 if the operation completed normally.
443 Returns -1 on timeout, logged as error if fErrorOnTimeout is set.
444 Returns -2 is the progress object is invalid or waitForCompletion
445 fails (logged as errors).
446 Returns -3 if if the operation completed with an error, this is logged
447 as an error.
448 """
449 msStart = base.timestampMilli();
450 while True:
451 self.oTstDrv.processPendingEvents();
452 self.doQuickApiTest();
453 try:
454 iCurrentOperation = self.o.operation;
455 cOperations = self.o.operationCount;
456 if iOperation >= 0:
457 iRealOperation = iOperation;
458 else:
459 iRealOperation = cOperations + iOperation;
460
461 if iCurrentOperation > iRealOperation:
462 return 0;
463 if iCurrentOperation == iRealOperation \
464 and iRealOperation >= cOperations - 1 \
465 and self.o.completed:
466 if self.o.resultCode < 0:
467 self.logResult(fIgnoreErrors);
468 return -3;
469 return 0;
470 except:
471 if fIgnoreErrors:
472 reporter.logXcpt();
473 else:
474 reporter.errorXcpt();
475 return -2;
476 self.oTstDrv.processPendingEvents();
477
478 cMsElapsed = base.timestampMilli() - msStart;
479 if cMsElapsed > cMsTimeout:
480 if fErrorOnTimeout:
481 if fIgnoreErrors:
482 reporter.log('Timing out after waiting for %u s on "%s" operation %d' \
483 % (cMsTimeout / 1000, self.sName, iOperation))
484 else:
485 reporter.error('Timing out after waiting for %u s on "%s" operation %d' \
486 % (cMsTimeout / 1000, self.sName, iOperation))
487 return -1;
488
489 try:
490 self.o.waitForOperationCompletion(iRealOperation, cMsInterval);
491 except:
492 if fIgnoreErrors:
493 reporter.logXcpt(self.sName);
494 else:
495 reporter.errorXcpt(self.sName);
496 return -2;
497 reporter.doPollWork('ProgressWrapper.waitForOperation');
498 # Not reached.
499
500 def doQuickApiTest(self):
501 """
502 Queries everything that is stable and easy to get at and checks that
503 they don't throw errors.
504 """
505 if True is True:
506 try:
507 iPct = self.o.operationPercent;
508 sDesc = self.o.description;
509 fCancelable = self.o.cancelable;
510 cSecsRemain = self.o.timeRemaining;
511 fCanceled = self.o.canceled;
512 fCompleted = self.o.completed;
513 iOp = self.o.operation;
514 cOps = self.o.operationCount;
515 iOpPct = self.o.operationPercent;
516 sOpDesc = self.o.operationDescription;
517 except:
518 reporter.errorXcpt('%s: %s' % (self.sName, self.o,));
519 return False;
520 try:
521 # Very noisy -- only enable for debugging purposes.
522 #reporter.log2('%s: op=%u/%u/%s: %u%%; total=%u%% cancel=%s/%s compl=%s rem=%us; desc=%s' \
523 # % (self.sName, iOp, cOps, sOpDesc, iOpPct, iPct, fCanceled, fCancelable, fCompleted, \
524 # cSecsRemain, sDesc));
525 _ = iPct; _ = sDesc; _ = fCancelable; _ = cSecsRemain; _ = fCanceled; _ = fCompleted; _ = iOp;
526 _ = cOps; _ = iOpPct; _ = sOpDesc;
527 except:
528 reporter.errorXcpt();
529 return False;
530
531 return True;
532
533
534class SessionWrapper(TdTaskBase):
535 """
536 Wrapper around a machine session. The real session object can be accessed
537 thru the o member (short is good, right :-).
538 """
539
540 def __init__(self, oSession, oVM, oVBox, oVBoxMgr, oTstDrv, fRemoteSession, sFallbackName = None, sLogFile = None):
541 """
542 Initializes the session wrapper.
543 """
544 TdTaskBase.__init__(self, utils.getCallerName());
545 self.o = oSession;
546 self.oVBox = oVBox;
547 self.oVBoxMgr = oVBoxMgr;
548 self.oVM = oVM; # Not the session machine. Useful backdoor...
549 self.oTstDrv = oTstDrv;
550 self.fpApiVer = oTstDrv.fpApiVer;
551 self.fRemoteSession = fRemoteSession;
552 self.sLogFile = sLogFile;
553 self.oConsoleEventHandler = None;
554 self.uPid = None;
555 self.fPidFile = True;
556 self.fHostMemoryLow = False; # see signalHostMemoryLow; read-only for outsiders.
557
558 try:
559 self.sName = oSession.machine.name;
560 except:
561 if sFallbackName is not None:
562 self.sName = sFallbackName;
563 else:
564 try: self.sName = str(oSession.machine);
565 except: self.sName = 'is-this-vm-already-off'
566
567 try:
568 self.sUuid = oSession.machine.id;
569 except:
570 self.sUuid = None;
571
572 # Try cache the SessionPID.
573 self.getPid();
574
575 def __del__(self):
576 """
577 Destructor that makes sure the callbacks are deregistered and
578 that the session is closed.
579 """
580 self.deregisterEventHandlerForTask();
581
582 if self.o is not None:
583 try:
584 self.close();
585 reporter.log('close session %s' % (self.o));
586 except:
587 pass;
588 self.o = None;
589
590 TdTaskBase.__del__(self);
591
592 def toString(self):
593 return '<%s: sUuid=%s, sName=%s, uPid=%s, sDbgCreated=%s, fRemoteSession=%s, oSession=%s,' \
594 ' oConsoleEventHandler=%s, oVM=%s >' \
595 % (type(self).__name__, self.sUuid, self.sName, self.uPid, self.sDbgCreated, self.fRemoteSession,
596 self.o, self.oConsoleEventHandler, self.oVM,);
597
598 def __str__(self):
599 return self.toString();
600
601 #
602 # TdTaskBase overrides.
603 #
604
605 def __pollTask(self):
606 """ Internal poller """
607 # Poll for events after doing the remote GetState call, otherwise we
608 # might end up sleepless because XPCOM queues a cleanup event.
609 try:
610 try:
611 eState = self.o.machine.state;
612 except Exception, oXcpt:
613 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
614 reporter.logXcpt();
615 return True;
616 finally:
617 self.oTstDrv.processPendingEvents();
618
619 # Switch
620 if eState == vboxcon.MachineState_Running:
621 return False;
622 if eState == vboxcon.MachineState_Paused:
623 return False;
624 if eState == vboxcon.MachineState_Teleporting:
625 return False;
626 if eState == vboxcon.MachineState_LiveSnapshotting:
627 return False;
628 if eState == vboxcon.MachineState_Starting:
629 return False;
630 if eState == vboxcon.MachineState_Stopping:
631 return False;
632 if eState == vboxcon.MachineState_Saving:
633 return False;
634 if eState == vboxcon.MachineState_Restoring:
635 return False;
636 if eState == vboxcon.MachineState_TeleportingPausedVM:
637 return False;
638 if eState == vboxcon.MachineState_TeleportingIn:
639 return False;
640
641 # *Beeep* fudge!
642 if self.fpApiVer < 3.2 \
643 and eState == vboxcon.MachineState_PoweredOff \
644 and self.getAgeAsMs() < 3000:
645 return False;
646
647 reporter.log('SessionWrapper::pollTask: eState=%s' % (eState));
648 return True;
649
650
651 def pollTask(self, fLocked = False):
652 """
653 Overrides TdTaskBase.pollTask().
654
655 This method returns False while the VM is online and running normally.
656 """
657
658 # Call super to check if the task was signalled by runtime error or similar,
659 # if not then check the VM state via __pollTask.
660 fRc = super(SessionWrapper, self).pollTask(fLocked);
661 if not fRc:
662 fRc = self.__pollTask();
663
664 # HACK ALERT: Lazily try registering the console event handler if
665 # we're not ready.
666 if not fRc and self.oConsoleEventHandler is None:
667 self.registerEventHandlerForTask();
668
669 # HACK ALERT: Lazily try get the PID and add it to the PID file.
670 if not fRc and self.uPid is None:
671 self.getPid();
672
673 return fRc;
674
675 def waitForTask(self, cMsTimeout = 0):
676 """
677 Overrides TdTaskBase.waitForTask().
678 Process XPCOM/COM events while waiting.
679 """
680 msStart = base.timestampMilli();
681 fState = self.pollTask(False);
682 while not fState:
683 cMsElapsed = base.timestampMilli() - msStart;
684 if cMsElapsed > cMsTimeout:
685 break;
686 cMsSleep = cMsTimeout - cMsElapsed;
687 if cMsSleep > 10000:
688 cMsSleep = 10000;
689 try: self.oVBoxMgr.waitForEvents(cMsSleep);
690 except KeyboardInterrupt: raise;
691 except: pass;
692 reporter.doPollWork('SessionWrapper.waitForTask');
693 fState = self.pollTask(False);
694 return fState;
695
696 def setTaskOwner(self, oOwner):
697 """
698 HACK ALERT!
699 Overrides TdTaskBase.setTaskOwner() so we can try call
700 registerEventHandlerForTask() again when when the testdriver calls
701 addTask() after VM has been spawned. Related to pollTask() above.
702
703 The testdriver must not add the task too early for this to work!
704 """
705 if oOwner is not None:
706 self.registerEventHandlerForTask()
707 return TdTaskBase.setTaskOwner(self, oOwner);
708
709
710 #
711 # Task helpers.
712 #
713
714 def registerEventHandlerForTask(self):
715 """
716 Registers the console event handlers for working the task state.
717 """
718 if self.oConsoleEventHandler is not None:
719 return True;
720 self.oConsoleEventHandler = self.registerDerivedEventHandler(vbox.SessionConsoleEventHandler, {}, False);
721 return self.oConsoleEventHandler is not None;
722
723 def deregisterEventHandlerForTask(self):
724 """
725 Deregisters the console event handlers.
726 """
727 if self.oConsoleEventHandler is not None:
728 self.oConsoleEventHandler.unregister();
729 self.oConsoleEventHandler = None;
730
731 def signalHostMemoryLow(self):
732 """
733 Used by a runtime error event handler to indicate that we're low on memory.
734 Signals the task.
735 """
736 self.fHostMemoryLow = True;
737 self.signalTask();
738 return True;
739
740 def needsPoweringOff(self):
741 """
742 Examins the machine state to see if the VM needs powering off.
743 """
744 try:
745 try:
746 eState = self.o.machine.state;
747 except Exception, oXcpt:
748 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
749 reporter.logXcpt();
750 return False;
751 finally:
752 self.oTstDrv.processPendingEvents();
753
754 # Switch
755 if eState == vboxcon.MachineState_Running:
756 return True;
757 if eState == vboxcon.MachineState_Paused:
758 return True;
759 if eState == vboxcon.MachineState_Stuck:
760 return True;
761 if eState == vboxcon.MachineState_Teleporting:
762 return True;
763 if eState == vboxcon.MachineState_LiveSnapshotting:
764 return True;
765 if eState == vboxcon.MachineState_Starting:
766 return True;
767 if eState == vboxcon.MachineState_Saving:
768 return True;
769 if eState == vboxcon.MachineState_Restoring:
770 return True;
771 if eState == vboxcon.MachineState_TeleportingPausedVM:
772 return True;
773 if eState == vboxcon.MachineState_TeleportingIn:
774 return True;
775 if eState == vboxcon.MachineState_FaultTolerantSyncing:
776 return True;
777 return False;
778
779 def assertPoweredOff(self):
780 """
781 Asserts that the VM is powered off, reporting an error if not.
782 Returns True if powered off, False + error msg if not.
783 """
784 try:
785 try:
786 eState = self.oVM.state;
787 except Exception:
788 reporter.errorXcpt();
789 return True;
790 finally:
791 self.oTstDrv.processPendingEvents();
792
793 if eState == vboxcon.MachineState_PoweredOff:
794 return True;
795 reporter.error('Expected machine state "PoweredOff", machine is in the "%s" state instead.'
796 % (_nameMachineState(eState),));
797 return False;
798
799 def getMachineStateWithName(self):
800 """
801 Gets the current machine state both as a constant number/whatever and
802 as a human readable string. On error, the constants will be set to
803 None and the string will be the error message.
804 """
805 try:
806 eState = self.oVM.state;
807 except:
808 return (None, '[error getting state: %s]' % (self.oVBoxMgr.xcptToString(),));
809 finally:
810 self.oTstDrv.processPendingEvents();
811 return (eState, _nameMachineState(eState));
812
813 def reportPrematureTermination(self, sPrefix = ''):
814 """
815 Reports a premature virtual machine termination.
816 Returns False to facilitate simpler error paths.
817 """
818
819 reporter.error(sPrefix + 'The virtual machine terminated prematurely!!');
820 (enmState, sStateNm) = self.getMachineStateWithName();
821 reporter.error(sPrefix + 'Machine state: %s' % (sStateNm,));
822
823 if enmState is not None \
824 and enmState == vboxcon.MachineState_Aborted \
825 and self.uPid is not None:
826 #
827 # Look for process crash info.
828 #
829 def addCrashFile(sLogFile, fBinary):
830 """ processCollectCrashInfo callback. """
831 reporter.addLogFile(sLogFile, 'crash/dump/vm' if fBinary else 'crash/report/vm');
832 utils.processCollectCrashInfo(self.uPid, reporter.log, addCrashFile);
833
834 return False;
835
836
837
838 #
839 # ISession / IMachine / ISomethingOrAnother wrappers.
840 #
841
842 def close(self):
843 """
844 Closes the session if it's open and removes it from the
845 vbox.TestDriver.aoRemoteSessions list.
846 Returns success indicator.
847 """
848 fRc = True;
849 if self.o is not None:
850 # Get the pid in case we need to kill the process later on.
851 self.getPid();
852
853 # Try close it.
854 try:
855 if self.fpApiVer < 3.3:
856 self.o.close();
857 else:
858 self.o.unlockMachine();
859 self.o = None;
860 except KeyboardInterrupt:
861 raise;
862 except:
863 # Kludge to ignore VBoxSVC's closing of our session when the
864 # direct session closes / VM process terminates. Fun!
865 try: fIgnore = self.o.state == vboxcon.SessionState_Unlocked;
866 except: fIgnore = False;
867 if not fIgnore:
868 reporter.errorXcpt('ISession::unlockMachine failed on %s' % (self.o));
869 fRc = False;
870
871 # Remove it from the remote session list if applicable (not 100% clean).
872 if fRc and self.fRemoteSession:
873 try:
874 if self in self.oTstDrv.aoRemoteSessions:
875 reporter.log2('SessionWrapper::close: Removing myself from oTstDrv.aoRemoteSessions');
876 self.oTstDrv.aoRemoteSessions.remove(self)
877 except:
878 reporter.logXcpt();
879
880 if self.uPid is not None and self.fPidFile:
881 self.oTstDrv.pidFileRemove(self.uPid);
882 self.fPidFile = False;
883
884 # It's only logical to deregister the event handler after the session
885 # is closed. It also avoids circular references between the session
886 # and the listener, which causes trouble with garbage collection.
887 self.deregisterEventHandlerForTask();
888
889 self.oTstDrv.processPendingEvents();
890 return fRc;
891
892 def saveSettings(self, fClose = False):
893 """
894 Saves the settings and optionally closes the session.
895 Returns success indicator.
896 """
897 try:
898 try:
899 self.o.machine.saveSettings();
900 except:
901 reporter.errorXcpt('saveSettings failed on %s' % (self.o));
902 return False;
903 finally:
904 self.oTstDrv.processPendingEvents();
905 if fClose:
906 return self.close();
907 return True;
908
909 def discardSettings(self, fClose = False):
910 """
911 Discards the settings and optionally closes the session.
912 """
913 try:
914 try:
915 self.o.machine.discardSettings();
916 except:
917 reporter.errorXcpt('discardSettings failed on %s' % (self.o));
918 return False;
919 finally:
920 self.oTstDrv.processPendingEvents();
921 if fClose:
922 return self.close();
923 return True;
924
925 def enableVirtEx(self, fEnable):
926 """
927 Enables or disables AMD-V/VT-x.
928 Returns True on success and False on failure. Error information is logged.
929 """
930 # Enable/disable it.
931 fRc = True;
932 try:
933 self.o.machine.setHWVirtExProperty(vboxcon.HWVirtExPropertyType_Enabled, fEnable);
934 except:
935 reporter.errorXcpt('failed to set HWVirtExPropertyType_Enabled=%s for "%s"' % (fEnable, self.sName));
936 fRc = False;
937 else:
938 reporter.log('set HWVirtExPropertyType_Enabled=%s for "%s"' % (fEnable, self.sName));
939
940 # Force/unforce it.
941 if fRc and hasattr(vboxcon, 'HWVirtExPropertyType_Force'):
942 try:
943 self.o.machine.setHWVirtExProperty(vboxcon.HWVirtExPropertyType_Force, fEnable);
944 except:
945 reporter.errorXcpt('failed to set HWVirtExPropertyType_Force=%s for "%s"' % (fEnable, self.sName));
946 fRc = False;
947 else:
948 reporter.log('set HWVirtExPropertyType_Force=%s for "%s"' % (fEnable, self.sName));
949 else:
950 reporter.log('Warning! vboxcon has no HWVirtExPropertyType_Force attribute.');
951 ## @todo Modify CFGM to do the same for old VBox versions?
952
953 self.oTstDrv.processPendingEvents();
954 return fRc;
955
956 def enableNestedPaging(self, fEnable):
957 """
958 Enables or disables nested paging..
959 Returns True on success and False on failure. Error information is logged.
960 """
961 ## @todo Add/remove force CFGM thing, we don't want fallback logic when testing.
962 fRc = True;
963 try:
964 self.o.machine.setHWVirtExProperty(vboxcon.HWVirtExPropertyType_NestedPaging, fEnable);
965 except:
966 reporter.errorXcpt('failed to set HWVirtExPropertyType_NestedPaging=%s for "%s"' % (fEnable, self.sName));
967 fRc = False;
968 else:
969 reporter.log('set HWVirtExPropertyType_NestedPaging=%s for "%s"' % (fEnable, self.sName));
970 self.oTstDrv.processPendingEvents();
971 return fRc;
972
973 def enableLongMode(self, fEnable):
974 """
975 Enables or disables LongMode.
976 Returns True on success and False on failure. Error information is logged.
977 """
978 # Supported.
979 if self.fpApiVer < 4.2 or not hasattr(vboxcon, 'HWVirtExPropertyType_LongMode'):
980 return True;
981
982 # Enable/disable it.
983 fRc = True;
984 try:
985 self.o.machine.setCPUProperty(vboxcon.CPUPropertyType_LongMode, fEnable);
986 except:
987 reporter.errorXcpt('failed to set CPUPropertyType_LongMode=%s for "%s"' % (fEnable, self.sName));
988 fRc = False;
989 else:
990 reporter.log('set CPUPropertyType_LongMode=%s for "%s"' % (fEnable, self.sName));
991 self.oTstDrv.processPendingEvents();
992 return fRc;
993
994 def enablePae(self, fEnable):
995 """
996 Enables or disables PAE
997 Returns True on success and False on failure. Error information is logged.
998 """
999 fRc = True;
1000 try:
1001 if self.fpApiVer >= 3.2: # great, ain't it?
1002 self.o.machine.setCPUProperty(vboxcon.CPUPropertyType_PAE, fEnable);
1003 else:
1004 self.o.machine.setCpuProperty(vboxcon.CpuPropertyType_PAE, fEnable);
1005 except:
1006 reporter.errorXcpt('failed to set CPUPropertyType_PAE=%s for "%s"' % (fEnable, self.sName));
1007 fRc = False;
1008 else:
1009 reporter.log('set CPUPropertyType_PAE=%s for "%s"' % (fEnable, self.sName));
1010 self.oTstDrv.processPendingEvents();
1011 return fRc;
1012
1013 def enableIoApic(self, fEnable):
1014 """
1015 Enables or disables the IO-APIC
1016 Returns True on success and False on failure. Error information is logged.
1017 """
1018 fRc = True;
1019 try:
1020 self.o.machine.BIOSSettings.IOAPICEnabled = fEnable;
1021 except:
1022 reporter.errorXcpt('failed to set BIOSSettings.IOAPICEnabled=%s for "%s"' % (fEnable, self.sName));
1023 fRc = False;
1024 else:
1025 reporter.log('set BIOSSettings.IOAPICEnabled=%s for "%s"' % (fEnable, self.sName));
1026 self.oTstDrv.processPendingEvents();
1027 return fRc;
1028
1029 def enableHpet(self, fEnable):
1030 """
1031 Enables or disables the HPET
1032 Returns True on success and False on failure. Error information is logged.
1033 """
1034 fRc = True;
1035 try:
1036 if self.fpApiVer >= 4.2:
1037 self.o.machine.HPETEnabled = fEnable;
1038 else:
1039 self.o.machine.hpetEnabled = fEnable;
1040 except:
1041 reporter.errorXcpt('failed to set HpetEnabled=%s for "%s"' % (fEnable, self.sName));
1042 fRc = False;
1043 else:
1044 reporter.log('set HpetEnabled=%s for "%s"' % (fEnable, self.sName));
1045 self.oTstDrv.processPendingEvents();
1046 return fRc;
1047
1048 def enableUsbHid(self, fEnable):
1049 """
1050 Enables or disables the USB HID
1051 Returns True on success and False on failure. Error information is logged.
1052 """
1053 fRc = True;
1054 try:
1055 if fEnable:
1056 if self.fpApiVer >= 4.3:
1057 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1058 if cOhciCtls == 0:
1059 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1060 else:
1061 self.o.machine.usbController.enabled = True;
1062
1063 if self.fpApiVer >= 4.2:
1064 self.o.machine.pointingHIDType = vboxcon.PointingHIDType_ComboMouse;
1065 self.o.machine.keyboardHIDType = vboxcon.KeyboardHIDType_ComboKeyboard;
1066 else:
1067 self.o.machine.pointingHidType = vboxcon.PointingHidType_ComboMouse;
1068 self.o.machine.keyboardHidType = vboxcon.KeyboardHidType_ComboKeyboard;
1069 else:
1070 if self.fpApiVer >= 4.2:
1071 self.o.machine.pointingHIDType = vboxcon.PointingHIDType_PS2Mouse;
1072 self.o.machine.keyboardHIDType = vboxcon.KeyboardHIDType_PS2Keyboard;
1073 else:
1074 self.o.machine.pointingHidType = vboxcon.PointingHidType_PS2Mouse;
1075 self.o.machine.keyboardHidType = vboxcon.KeyboardHidType_PS2Keyboard;
1076 except:
1077 reporter.errorXcpt('failed to change UsbHid to %s for "%s"' % (fEnable, self.sName));
1078 fRc = False;
1079 else:
1080 reporter.log('changed UsbHid to %s for "%s"' % (fEnable, self.sName));
1081 self.oTstDrv.processPendingEvents();
1082 return fRc;
1083
1084 def enableUsbOhci(self, fEnable):
1085 """
1086 Enables or disables the USB OHCI controller
1087 Returns True on success and False on failure. Error information is logged.
1088 """
1089 fRc = True;
1090 try:
1091 if fEnable:
1092 if self.fpApiVer >= 4.3:
1093 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1094 if cOhciCtls == 0:
1095 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1096 else:
1097 self.o.machine.usbController.enabled = True;
1098 else:
1099 if self.fpApiVer >= 4.3:
1100 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1101 if cOhciCtls == 1:
1102 self.o.machine.removeUSBController('OHCI');
1103 else:
1104 self.o.machine.usbController.enabled = False;
1105 except:
1106 reporter.errorXcpt('failed to change OHCI to %s for "%s"' % (fEnable, self.sName));
1107 fRc = False;
1108 else:
1109 reporter.log('changed OHCI to %s for "%s"' % (fEnable, self.sName));
1110 self.oTstDrv.processPendingEvents();
1111 return fRc;
1112
1113 def enableUsbEhci(self, fEnable):
1114 """
1115 Enables or disables the USB EHCI controller, enables also OHCI if it is still disabled.
1116 Returns True on success and False on failure. Error information is logged.
1117 """
1118 fRc = True;
1119 try:
1120 if fEnable:
1121 if self.fpApiVer >= 4.3:
1122 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1123 if cOhciCtls == 0:
1124 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1125
1126 cEhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_EHCI);
1127 if cEhciCtls == 0:
1128 self.o.machine.addUSBController('EHCI', vboxcon.USBControllerType_EHCI);
1129 else:
1130 self.o.machine.usbController.enabled = True;
1131 self.o.machine.usbController.enabledEHCI = True;
1132 else:
1133 if self.fpApiVer >= 4.3:
1134 cEhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_EHCI);
1135 if cEhciCtls == 1:
1136 self.o.machine.removeUSBController('EHCI');
1137 else:
1138 self.o.machine.usbController.enabledEHCI = False;
1139 except:
1140 reporter.errorXcpt('failed to change EHCI to %s for "%s"' % (fEnable, self.sName));
1141 fRc = False;
1142 else:
1143 reporter.log('changed EHCI to %s for "%s"' % (fEnable, self.sName));
1144 self.oTstDrv.processPendingEvents();
1145 return fRc;
1146
1147 def enableUsbXhci(self, fEnable):
1148 """
1149 Enables or disables the USB XHCI controller. Error information is logged.
1150 """
1151 fRc = True;
1152 try:
1153 if fEnable:
1154 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1155 if cXhciCtls == 0:
1156 self.o.machine.addUSBController('XHCI', vboxcon.USBControllerType_XHCI);
1157 else:
1158 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1159 if cXhciCtls == 1:
1160 self.o.machine.removeUSBController('XHCI');
1161 except:
1162 reporter.errorXcpt('failed to change XHCI to %s for "%s"' % (fEnable, self.sName));
1163 fRc = False;
1164 else:
1165 reporter.log('changed XHCI to %s for "%s"' % (fEnable, self.sName));
1166 self.oTstDrv.processPendingEvents();
1167 return fRc;
1168
1169 def setFirmwareType(self, eType):
1170 """
1171 Sets the firmware type.
1172 Returns True on success and False on failure. Error information is logged.
1173 """
1174 fRc = True;
1175 try:
1176 self.o.machine.firmwareType = eType;
1177 except:
1178 reporter.errorXcpt('failed to set firmwareType=%s for "%s"' % (eType, self.sName));
1179 fRc = False;
1180 else:
1181 reporter.log('set firmwareType=%s for "%s"' % (eType, self.sName));
1182 self.oTstDrv.processPendingEvents();
1183 return fRc;
1184
1185 def setChipsetType(self, eType):
1186 """
1187 Sets the chipset type.
1188 Returns True on success and False on failure. Error information is logged.
1189 """
1190 fRc = True;
1191 try:
1192 self.o.machine.chipsetType = eType;
1193 except:
1194 reporter.errorXcpt('failed to set chipsetType=%s for "%s"' % (eType, self.sName));
1195 fRc = False;
1196 else:
1197 reporter.log('set chipsetType=%s for "%s"' % (eType, self.sName));
1198 self.oTstDrv.processPendingEvents();
1199 return fRc;
1200
1201 def setupBootLogo(self, fEnable, cMsLogoDisplay = 0):
1202 """
1203 Sets up the boot logo. fEnable toggles the fade and boot menu
1204 settings as well as the mode.
1205 """
1206 fRc = True;
1207 try:
1208 self.o.machine.BIOSSettings.logoFadeIn = not fEnable;
1209 self.o.machine.BIOSSettings.logoFadeOut = not fEnable;
1210 self.o.machine.BIOSSettings.logoDisplayTime = cMsLogoDisplay;
1211 if fEnable:
1212 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_Disabled;
1213 else:
1214 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_MessageAndMenu;
1215 except:
1216 reporter.errorXcpt('failed to set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1217 fRc = False;
1218 else:
1219 reporter.log('set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1220 self.oTstDrv.processPendingEvents();
1221 return fRc;
1222
1223 def setupVrdp(self, fEnable, uPort = None):
1224 """
1225 Configures VRDP.
1226 """
1227 fRc = True;
1228 try:
1229 if self.fpApiVer >= 4.0:
1230 self.o.machine.VRDEServer.enabled = fEnable;
1231 else:
1232 self.o.machine.VRDPServer.enabled = fEnable;
1233 except:
1234 reporter.errorXcpt('failed to set VRDEServer::enabled=%s for "%s"' % (fEnable, self.sName));
1235 fRc = False;
1236
1237 if uPort is not None and fRc:
1238 try:
1239 if self.fpApiVer >= 4.0:
1240 self.o.machine.VRDEServer.setVRDEProperty("TCP/Ports", str(uPort));
1241 else:
1242 self.o.machine.VRDPServer.ports = str(uPort);
1243 except:
1244 reporter.errorXcpt('failed to set VRDEServer::ports=%s for "%s"' % (uPort, self.sName));
1245 fRc = False;
1246 if fRc:
1247 reporter.log('set VRDEServer.enabled/ports=%s/%s for "%s"' % (fEnable, uPort, self.sName));
1248 self.oTstDrv.processPendingEvents();
1249 return fRc;
1250
1251 def getNicDriverNameFromType(self, eNicType):
1252 """
1253 Helper that translate the adapter type into a driver name.
1254 """
1255 if eNicType == vboxcon.NetworkAdapterType_Am79C970A \
1256 or eNicType == vboxcon.NetworkAdapterType_Am79C973:
1257 sName = 'pcnet';
1258 elif eNicType == vboxcon.NetworkAdapterType_I82540EM \
1259 or eNicType == vboxcon.NetworkAdapterType_I82543GC \
1260 or eNicType == vboxcon.NetworkAdapterType_I82545EM:
1261 sName = 'e1000';
1262 elif eNicType == vboxcon.NetworkAdapterType_Virtio:
1263 sName = 'virtio-net';
1264 else:
1265 reporter.error('Unknown adapter type "%s" (VM: "%s")' % (eNicType, self.sName));
1266 sName = 'pcnet';
1267 return sName;
1268
1269 def setupNatForwardingForTxs(self, iNic = 0, iHostPort = 5042):
1270 """
1271 Sets up NAT forwarding for port 5042 if applicable, cleans up if not.
1272 """
1273 try:
1274 oNic = self.o.machine.getNetworkAdapter(iNic);
1275 except:
1276 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1277 return False;
1278
1279 # Nuke the old setup for all possible adapter types (in case we're
1280 # called after it changed).
1281 for sName in ('pcnet', 'e1000', 'virtio-net'):
1282 for sConfig in ('VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic), \
1283 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)):
1284 try:
1285 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), '');
1286 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '');
1287 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '');
1288 except:
1289 reporter.errorXcpt();
1290
1291 # Set up port forwarding if NAT attachment.
1292 try:
1293 eAttType = oNic.attachmentType;
1294 except:
1295 reporter.errorXcpt('attachmentType on %s failed for "%s"' % (iNic, self.sName));
1296 return False;
1297 if eAttType != vboxcon.NetworkAttachmentType_NAT:
1298 return True;
1299
1300 try:
1301 eNicType = oNic.adapterType;
1302 fTraceEnabled = oNic.traceEnabled;
1303 except:
1304 reporter.errorXcpt('attachmentType/traceEnabled on %s failed for "%s"' % (iNic, self.sName));
1305 return False;
1306
1307 if self.fpApiVer >= 4.1:
1308 try:
1309 if self.fpApiVer >= 4.2:
1310 oNatEngine = oNic.NATEngine;
1311 else:
1312 oNatEngine = oNic.natDriver;
1313 except:
1314 reporter.errorXcpt('Failed to get INATEngine data on "%s"' % (self.sName));
1315 return False;
1316 try: oNatEngine.removeRedirect('txs');
1317 except: pass;
1318 try:
1319 oNatEngine.addRedirect('txs', vboxcon.NATProtocol_TCP, '127.0.0.1', '%s' % (iHostPort), '', '5042');
1320 except:
1321 reporter.errorXcpt('Failed to add a addRedirect redirect on "%s"' % (self.sName));
1322 return False;
1323
1324 else:
1325 sName = self.getNicDriverNameFromType(eNicType);
1326 if fTraceEnabled:
1327 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic)
1328 else:
1329 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)
1330
1331 try:
1332 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), 'TCP');
1333 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '%s' % (iHostPort));
1334 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '5042');
1335 except:
1336 reporter.errorXcpt('Failed to set NAT extra data on "%s"' % (self.sName));
1337 return False;
1338 return True;
1339
1340 def setNicType(self, eType, iNic = 0):
1341 """
1342 Sets the NIC type of the specified NIC.
1343 Returns True on success and False on failure. Error information is logged.
1344 """
1345 try:
1346 try:
1347 oNic = self.o.machine.getNetworkAdapter(iNic);
1348 except:
1349 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1350 return False;
1351 try:
1352 oNic.adapterType = eType;
1353 except:
1354 reporter.errorXcpt('failed to set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1355 return False;
1356 finally:
1357 self.oTstDrv.processPendingEvents();
1358
1359 if not self.setupNatForwardingForTxs(iNic):
1360 return False;
1361 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1362 return True;
1363
1364 def setNicTraceEnabled(self, fTraceEnabled, sTraceFile, iNic = 0):
1365 """
1366 Sets the NIC trace enabled flag and file path.
1367 Returns True on success and False on failure. Error information is logged.
1368 """
1369 try:
1370 try:
1371 oNic = self.o.machine.getNetworkAdapter(iNic);
1372 except:
1373 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1374 return False;
1375 try:
1376 oNic.traceEnabled = fTraceEnabled;
1377 oNic.traceFile = sTraceFile;
1378 except:
1379 reporter.errorXcpt('failed to set NIC trace flag on slot %s to %s for VM "%s"' \
1380 % (iNic, fTraceEnabled, self.sName));
1381 return False;
1382 finally:
1383 self.oTstDrv.processPendingEvents();
1384
1385 if not self.setupNatForwardingForTxs(iNic):
1386 return False;
1387 reporter.log('set NIC trace on slot %s to "%s" (path "%s") for VM "%s"' %
1388 (iNic, fTraceEnabled, sTraceFile, self.sName));
1389 return True;
1390
1391 def getDefaultNicName(self, eAttachmentType):
1392 """
1393 Return the default network / interface name for the NIC attachment type.
1394 """
1395 sRetName = '';
1396 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1397 if self.oTstDrv.sDefBridgedNic is not None:
1398 sRetName = self.oTstDrv.sDefBridgedNic;
1399 else:
1400 sRetName = 'eth0';
1401 try:
1402 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1403 for oHostNic in aoHostNics:
1404 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_Bridged \
1405 and oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1406 sRetName = oHostNic.name;
1407 break;
1408 except:
1409 reporter.errorXcpt();
1410 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1411 try:
1412 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1413 for oHostNic in aoHostNics:
1414 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_HostOnly:
1415 if oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1416 sRetName = oHostNic.name;
1417 break;
1418 if sRetName == '':
1419 sRetName = oHostNic.name;
1420 except:
1421 reporter.errorXcpt();
1422 if sRetName == '':
1423 sRetName = 'HostInterfaceNetwork-vboxnet0';
1424 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1425 sRetName = 'VBoxTest';
1426 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1427 sRetName = '';
1428 else:
1429 reporter.error('eAttachmentType=%s is not known' % (eAttachmentType));
1430 return sRetName;
1431
1432 def setNicAttachment(self, eAttachmentType, sName = None, iNic = 0):
1433 """
1434 Sets the attachment type of the specified NIC.
1435 Returns True on success and False on failure. Error information is logged.
1436 """
1437 try:
1438 oNic = self.o.machine.getNetworkAdapter(iNic);
1439 except:
1440 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1441 return False;
1442
1443 try:
1444 if eAttachmentType is not None:
1445 try:
1446 if self.fpApiVer >= 4.1:
1447 oNic.attachmentType = eAttachmentType;
1448 else:
1449 if eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1450 oNic.attachToNAT();
1451 elif eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1452 oNic.attachToBridgedInterface();
1453 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1454 oNic.attachToInternalNetwork();
1455 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1456 oNic.attachToHostOnlyInterface();
1457 else:
1458 raise base.GenError("eAttachmentType=%s is invalid" % (eAttachmentType));
1459 except:
1460 reporter.errorXcpt('failed to set the attachment type on slot %s to %s for VM "%s"' \
1461 % (iNic, eAttachmentType, self.sName));
1462 return False;
1463 else:
1464 try:
1465 eAttachmentType = oNic.attachmentType;
1466 except:
1467 reporter.errorXcpt('failed to get the attachment type on slot %s for VM "%s"' % (iNic, self.sName));
1468 return False;
1469 finally:
1470 self.oTstDrv.processPendingEvents();
1471
1472 if sName is not None:
1473 # Resolve the special 'default' name.
1474 if sName == 'default':
1475 sName = self.getDefaultNicName(eAttachmentType);
1476
1477 # The name translate to different attributes depending on the
1478 # attachment type.
1479 try:
1480 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1481 ## @todo check this out on windows, may have to do a
1482 # translation of the name there or smth IIRC.
1483 try:
1484 if self.fpApiVer >= 4.1:
1485 oNic.bridgedInterface = sName;
1486 else:
1487 oNic.hostInterface = sName;
1488 except:
1489 reporter.errorXcpt('failed to set the hostInterface property on slot %s to "%s" for VM "%s"' \
1490 % (iNic, sName, self.sName));
1491 return False;
1492 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1493 try:
1494 if self.fpApiVer >= 4.1:
1495 oNic.hostOnlyInterface = sName;
1496 else:
1497 oNic.hostInterface = sName;
1498 except:
1499 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1500 % (iNic, sName, self.sName));
1501 return False;
1502 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1503 try:
1504 oNic.internalNetwork = sName;
1505 except:
1506 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1507 % (iNic, sName, self.sName));
1508 return False;
1509 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1510 try:
1511 oNic.NATNetwork = sName;
1512 except:
1513 reporter.errorXcpt('failed to set the NATNetwork property on slot %s to "%s" for VM "%s"' \
1514 % (iNic, sName, self.sName));
1515 return False;
1516 finally:
1517 self.oTstDrv.processPendingEvents();
1518
1519 if not self.setupNatForwardingForTxs(iNic):
1520 return False;
1521 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eAttachmentType, self.sName));
1522 return True;
1523
1524 def setNicMacAddress(self, sMacAddr, iNic = 0):
1525 """
1526 Sets the MAC address of the specified NIC.
1527 Returns True on success and False on failure. Error information is logged.
1528 """
1529
1530 # Resolve missing MAC address prefix
1531 cchMacAddr = len(sMacAddr)
1532 if cchMacAddr > 0 and cchMacAddr < 12:
1533 sHostName = ''
1534 try:
1535 sHostName = socket.getfqdn()
1536 if '.' not in sHostName and not sHostName.startswith('localhost'):
1537 # somewhat misconfigured system, needs expensive approach to guessing FQDN
1538 for aAI in socket.getaddrinfo(sHostName, None):
1539 sName, _ = socket.getnameinfo(aAI[4], 0)
1540 if '.' in sName and not set(sName).issubset(set('0123456789.')) and not sName.startswith('localhost'):
1541 sHostName = sName
1542 break
1543
1544 sHostIP = socket.gethostbyname(sHostName)
1545 abHostIP = socket.inet_aton(sHostIP)
1546 if ord(abHostIP[0]) == 127 \
1547 or (ord(abHostIP[0]) == 169 and ord(abHostIP[1]) == 254) \
1548 or (ord(abHostIP[0]) == 192 and ord(abHostIP[1]) == 168 and ord(abHostIP[2]) == 56):
1549 reporter.log('warning: host IP for "%s" is %s, most likely not unique.' % (sHostName, sHostIP))
1550 except:
1551 reporter.errorXcpt('failed to determine the host IP for "%s".' % (sHostName,))
1552 return False
1553 sDefaultMac = '%02X%02X%02X%02X%02X%02X' \
1554 % (0x02, ord(abHostIP[0]), ord(abHostIP[1]), ord(abHostIP[2]), ord(abHostIP[3]), iNic)
1555 sMacAddr = sDefaultMac[0:(12 - cchMacAddr)] + sMacAddr
1556
1557 # Get the NIC object and try set it address.
1558 try:
1559 oNic = self.o.machine.getNetworkAdapter(iNic)
1560 except:
1561 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName))
1562 return False
1563
1564 try:
1565 oNic.MACAddress = sMacAddr
1566 except:
1567 reporter.errorXcpt('failed to set the MAC address on slot %s to "%s" for VM "%s"' \
1568 % (iNic, sMacAddr, self.sName))
1569 return False
1570
1571 reporter.log('set MAC address on slot %s to %s for VM "%s"' % (iNic, sMacAddr, self.sName))
1572 return True
1573
1574 def setRamSize(self, cMB):
1575 """
1576 Set the RAM size of the VM.
1577 Returns True on success and False on failure. Error information is logged.
1578 """
1579 fRc = True;
1580 try:
1581 self.o.machine.memorySize = cMB;
1582 except:
1583 reporter.errorXcpt('failed to set the RAM size of "%s" to %s' % (self.sName, cMB));
1584 fRc = False;
1585 else:
1586 reporter.log('set the RAM size of "%s" to %s' % (self.sName, cMB));
1587 self.oTstDrv.processPendingEvents();
1588 return fRc;
1589
1590 def setVRamSize(self, cMB):
1591 """
1592 Set the RAM size of the VM.
1593 Returns True on success and False on failure. Error information is logged.
1594 """
1595 fRc = True;
1596 try:
1597 self.o.machine.VRAMSize = cMB;
1598 except:
1599 reporter.errorXcpt('failed to set the VRAM size of "%s" to %s' % (self.sName, cMB));
1600 fRc = False;
1601 else:
1602 reporter.log('set the VRAM size of "%s" to %s' % (self.sName, cMB));
1603 self.oTstDrv.processPendingEvents();
1604 return fRc;
1605
1606 def setCpuCount(self, cCpus):
1607 """
1608 Set the number of CPUs.
1609 Returns True on success and False on failure. Error information is logged.
1610 """
1611 fRc = True;
1612 try:
1613 self.o.machine.CPUCount = cCpus;
1614 except:
1615 reporter.errorXcpt('failed to set the CPU count of "%s" to %s' % (self.sName, cCpus));
1616 fRc = False;
1617 else:
1618 reporter.log('set the CPU count of "%s" to %s' % (self.sName, cCpus));
1619 self.oTstDrv.processPendingEvents();
1620 return fRc;
1621
1622 def getCpuCount(self):
1623 """
1624 Returns the number of CPUs.
1625 Returns the number of CPUs on success and 0 on failure. Error information is logged.
1626 """
1627 cCpus = 0;
1628 try:
1629 cCpus = self.o.machine.CPUCount;
1630 except:
1631 reporter.errorXcpt('failed to get the CPU count of "%s"' % (self.sName,));
1632
1633 self.oTstDrv.processPendingEvents();
1634 return cCpus;
1635
1636 def ensureControllerAttached(self, sController):
1637 """
1638 Makes sure the specified controller is attached to the VM, attaching it
1639 if necessary.
1640 """
1641 try:
1642 try:
1643 self.o.machine.getStorageControllerByName(sController);
1644 except:
1645 (eBus, eType) = _ControllerNameToBusAndType(sController);
1646 try:
1647 oCtl = self.o.machine.addStorageController(sController, eBus);
1648 except:
1649 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, eBus, self.sName) );
1650 return False;
1651 else:
1652 try:
1653 oCtl.controllerType = eType;
1654 reporter.log('added storage controller "%s" (bus %s, type %s) to %s'
1655 % (sController, eBus, eType, self.sName));
1656 except:
1657 reporter.errorXcpt('controllerType = %s on ("%s" / %s) failed on "%s"'
1658 % (eType, sController, eBus, self.sName) );
1659 return False;
1660 finally:
1661 self.oTstDrv.processPendingEvents();
1662 return True;
1663
1664 def setStorageControllerPortCount(self, sController, iPortCount):
1665 """
1666 Set maximum ports count for storage controller
1667 """
1668 try:
1669 oCtl = self.o.machine.getStorageControllerByName(sController)
1670 oCtl.portCount = iPortCount
1671 self.oTstDrv.processPendingEvents()
1672 reporter.log('set controller "%s" port count to value %d' % (sController, iPortCount))
1673 return True
1674 except:
1675 reporter.log('unable to set storage controller "%s" ports count to %d' % (sController, iPortCount))
1676
1677 return False
1678
1679 def setStorageControllerHostIoCache(self, sController, fUseHostIoCache):
1680 """
1681 Set maximum ports count for storage controller
1682 """
1683 try:
1684 oCtl = self.o.machine.getStorageControllerByName(sController);
1685 oCtl.useHostIOCache = fUseHostIoCache;
1686 self.oTstDrv.processPendingEvents();
1687 reporter.log('set controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1688 return True;
1689 except:
1690 reporter.log('unable to set storage controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1691
1692 return False;
1693
1694 def setBootOrder(self, iPosition, eType):
1695 """
1696 Set guest boot order type
1697 @param iPosition boot order position
1698 @param eType device type (vboxcon.DeviceType_HardDisk,
1699 vboxcon.DeviceType_DVD, vboxcon.DeviceType_Floppy)
1700 """
1701 try:
1702 self.o.machine.setBootOrder(iPosition, eType)
1703 except:
1704 return reporter.errorXcpt('Unable to set boot order.')
1705
1706 reporter.log('Set boot order [%d] for device %s' % (iPosition, str(eType)))
1707 self.oTstDrv.processPendingEvents();
1708
1709 return True
1710
1711 def setStorageControllerType(self, eType, sController = "IDE Controller"):
1712 """
1713 Similar to ensureControllerAttached, except it will change the type.
1714 """
1715 try:
1716 oCtl = self.o.machine.getStorageControllerByName(sController);
1717 except:
1718 (eBus, _) = _ControllerNameToBusAndType(sController);
1719 try:
1720 oCtl = self.o.machine.addStorageController(sController, eBus);
1721 reporter.log('added storage controller "%s" (bus %s) to %s' % (sController, eBus, self.sName));
1722 except:
1723 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, eBus, self.sName) );
1724 return False;
1725 try:
1726 oCtl.controllerType = eType;
1727 except:
1728 reporter.errorXcpt('failed to set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1729 return False;
1730 reporter.log('set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1731 self.oTstDrv.processPendingEvents();
1732 return True;
1733
1734 def attachDvd(self, sImage = None, sController = "IDE Controller", iPort = 1, iDevice = 0):
1735 """
1736 Attaches a DVD drive to a VM, optionally with an ISO inserted.
1737 Returns True on success and False on failure. Error information is logged.
1738 """
1739 # Input validation.
1740 if sImage is not None and not self.oTstDrv.isResourceFile(sImage)\
1741 and not os.path.isabs(sImage): ## fixme - testsuite unzip ++
1742 reporter.fatal('"%s" is not in the resource set' % (sImage));
1743 return None;
1744
1745 if not self.ensureControllerAttached(sController):
1746 return False;
1747
1748 # Find/register the image if specified.
1749 oImage = None;
1750 sImageUuid = "";
1751 if sImage is not None:
1752 sFullName = self.oTstDrv.getFullResourceName(sImage)
1753 try:
1754 oImage = self.oVBox.findDVDImage(sFullName);
1755 except:
1756 try:
1757 if self.fpApiVer >= 4.1:
1758 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly, False);
1759 elif self.fpApiVer >= 4.0:
1760 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly);
1761 else:
1762 oImage = self.oVBox.openDVDImage(sFullName, "");
1763 except vbox.ComException, oXcpt:
1764 if oXcpt.errno != -1:
1765 reporter.errorXcpt('failed to open DVD image "%s" xxx' % (sFullName));
1766 else:
1767 reporter.errorXcpt('failed to open DVD image "%s" yyy' % (sFullName));
1768 return False;
1769 except:
1770 reporter.errorXcpt('failed to open DVD image "%s"' % (sFullName));
1771 return False;
1772 try:
1773 sImageUuid = oImage.id;
1774 except:
1775 reporter.errorXcpt('failed to get the UUID of "%s"' % (sFullName));
1776 return False;
1777
1778 # Attach the DVD.
1779 fRc = True;
1780 try:
1781 if self.fpApiVer >= 4.0:
1782 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, oImage);
1783 else:
1784 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, sImageUuid);
1785 except:
1786 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1787 % (sController, iPort, iDevice, sImageUuid, self.sName) );
1788 fRc = False;
1789 else:
1790 reporter.log('attached DVD to %s, image="%s"' % (self.sName, sImage));
1791 self.oTstDrv.processPendingEvents();
1792 return fRc;
1793
1794 def attachHd(self, sHd, sController = "IDE Controller", iPort = 0, iDevice = 0, fImmutable = True, fForceResource = True):
1795 """
1796 Attaches a HD to a VM.
1797 Returns True on success and False on failure. Error information is logged.
1798 """
1799 # Input validation.
1800 if fForceResource and not self.oTstDrv.isResourceFile(sHd):
1801 reporter.fatal('"%s" is not in the resource set' % (sHd,));
1802 return None;
1803
1804 if not self.ensureControllerAttached(sController):
1805 return False;
1806
1807 # Find the HD, registering it if necessary (as immutable).
1808 if fForceResource:
1809 sFullName = self.oTstDrv.getFullResourceName(sHd);
1810 else:
1811 sFullName = sHd;
1812 try:
1813 oHd = self.oVBox.findHardDisk(sFullName);
1814 except:
1815 try:
1816 if self.fpApiVer >= 4.1:
1817 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
1818 elif self.fpApiVer >= 4.0:
1819 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
1820 else:
1821 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
1822 except:
1823 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
1824 return False;
1825 try:
1826 if fImmutable:
1827 oHd.type = vboxcon.MediumType_Immutable;
1828 else:
1829 oHd.type = vboxcon.MediumType_Normal;
1830 except:
1831 if fImmutable:
1832 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1833 else:
1834 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1835 return False;
1836
1837 # Attach it.
1838 fRc = True;
1839 try:
1840 if self.fpApiVer >= 4.0:
1841 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1842 else:
1843 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1844 except:
1845 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1846 % (sController, iPort, iDevice, oHd.id, self.sName) );
1847 fRc = False;
1848 else:
1849 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1850 self.oTstDrv.processPendingEvents();
1851 return fRc;
1852
1853 def createBaseHd(self, sHd, sFmt = "VDI", cb = 10*1024*1024*1024, cMsTimeout = 60000, tMediumVariant = None):
1854 """
1855 Creates a base HD.
1856 Returns Medium object on success and None on failure. Error information is logged.
1857 """
1858 if tMediumVariant is None:
1859 tMediumVariant = (vboxcon.MediumVariant_Standard, );
1860
1861 try:
1862 if self.fpApiVer >= 5.0:
1863 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1864 else:
1865 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1866 oProgressXpcom = oHd.createBaseStorage(cb, tMediumVariant);
1867 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create base disk %s' % (sHd));
1868 oProgress.wait(cMsTimeout);
1869 oProgress.logResult();
1870 except:
1871 reporter.errorXcpt('failed to create base hd "%s"' % (sHd));
1872 oHd = None
1873
1874 return oHd;
1875
1876 def createDiffHd(self, oParentHd, sHd, sFmt = "VDI"):
1877 """
1878 Creates a differencing HD.
1879 Returns Medium object on success and None on failure. Error information is logged.
1880 """
1881 # Detect the proper format if requested
1882 if sFmt is None:
1883 try:
1884 oHdFmt = oParentHd.mediumFormat;
1885 lstCaps = self.oVBoxMgr.getArray(oHdFmt, 'capabilities');
1886 if vboxcon.MediumFormatCapabilities_Differencing in lstCaps:
1887 sFmt = oHdFmt.id;
1888 else:
1889 sFmt = 'VDI';
1890 except:
1891 reporter.errorXcpt('failed to get preferred diff format for "%s"' % (sHd));
1892 return None;
1893 try:
1894 if self.fpApiVer >= 5.0:
1895 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1896 else:
1897 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1898 oProgressXpcom = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
1899 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
1900 oProgress.wait();
1901 oProgress.logResult();
1902 except:
1903 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
1904 oHd = None
1905
1906 return oHd;
1907
1908 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, # pylint: disable=R0913
1909 iPort = 0, iDevice = 0, fImmutable = True, cMsTimeout = 60000, tMediumVariant = None):
1910 """
1911 Creates and attaches a HD to a VM.
1912 Returns True on success and False on failure. Error information is logged.
1913 """
1914 if not self.ensureControllerAttached(sController):
1915 return False;
1916
1917 oHd = self.createBaseHd(sHd, sFmt, cb, cMsTimeout, tMediumVariant);
1918 if oHd is None:
1919 return False;
1920
1921 fRc = True;
1922 try:
1923 if fImmutable:
1924 oHd.type = vboxcon.MediumType_Immutable;
1925 else:
1926 oHd.type = vboxcon.MediumType_Normal;
1927 except:
1928 if fImmutable:
1929 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1930 else:
1931 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1932 fRc = False;
1933
1934 # Attach it.
1935 if fRc is True:
1936 try:
1937 if self.fpApiVer >= 4.0:
1938 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1939 else:
1940 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1941 except:
1942 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1943 % (sController, iPort, iDevice, oHd.id, self.sName) );
1944 fRc = False;
1945 else:
1946 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1947
1948 # Delete disk in case of an error
1949 if fRc is False:
1950 try:
1951 oProgressCom = oHd.deleteStorage();
1952 except:
1953 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
1954 else:
1955 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
1956 oProgress.wait();
1957 oProgress.logResult();
1958
1959 self.oTstDrv.processPendingEvents();
1960 return fRc;
1961
1962 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
1963 """
1964 Detaches a HD, if attached, and returns a reference to it (IMedium).
1965
1966 In order to delete the detached medium, the caller must first save
1967 the changes made in this session.
1968
1969 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
1970 your standard success indicator. Error information is logged.
1971 """
1972
1973 # What's attached?
1974 try:
1975 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
1976 except:
1977 if self.oVBoxMgr.xcptIsOurXcptKind() \
1978 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
1979 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
1980 return (True, None);
1981 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
1982 % (iPort, iDevice, sController)), None);
1983 # Detach it.
1984 try:
1985 self.o.machine.detachDevice(sController, iPort, iDevice);
1986 except:
1987 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
1988 % (sController, iPort, iDevice, self.sName) ), None);
1989 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
1990 return (True, oHd);
1991
1992 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
1993 """
1994 Attaches a floppy image to a VM.
1995 Returns True on success and False on failure. Error information is logged.
1996 """
1997 # Input validation.
1998 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
1999 ##if not self.oTstDrv.isResourceFile(sFloppy):
2000 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
2001 ## return None;
2002
2003 if not self.ensureControllerAttached(sController):
2004 return False;
2005
2006 # Find the floppy image, registering it if necessary (as immutable).
2007 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
2008 try:
2009 oFloppy = self.oVBox.findFloppyImage(sFullName);
2010 except:
2011 try:
2012 if self.fpApiVer >= 4.1:
2013 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
2014 elif self.fpApiVer >= 4.0:
2015 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
2016 else:
2017 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
2018 except:
2019 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
2020 return False;
2021 ## @todo the following works but causes trouble below (asserts in main).
2022 #try:
2023 # oFloppy.type = vboxcon.MediumType_Immutable;
2024 #except:
2025 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
2026 # return False;
2027
2028 # Attach it.
2029 fRc = True;
2030 try:
2031 if self.fpApiVer >= 4.0:
2032 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
2033 else:
2034 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
2035 except:
2036 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
2037 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
2038 fRc = False;
2039 else:
2040 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
2041 self.oTstDrv.processPendingEvents();
2042 return fRc;
2043
2044 def setupNic(self, sType, sXXX):
2045 """
2046 Attaches a HD to a VM.
2047 Returns True on success and False on failure. Error information is logged.
2048 """
2049 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
2050 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
2051 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
2052 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
2053 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
2054 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
2055 else:
2056 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
2057 return False;
2058 ## @todo Implement me!
2059 if enmType is not None: pass
2060 return True;
2061
2062 def setupAudio(self, eAudioCtlType):
2063 """
2064 Set guest audio controller type and host audio adapter to null
2065 @param eAudioCtlType device type (vboxcon.AudioControllerType_SB16,
2066 vboxcon.AudioControllerType_AC97, vboxcon.AudioControllerType_HDA)
2067 """
2068 try:
2069 oAudioAdapter = self.o.machine.audioAdapter;
2070
2071 oAudioAdapter.audioController = eAudioCtlType;
2072
2073 sHost = utils.getHostOs()
2074 if sHost == 'darwin': oAudioAdapter.audioDriver = vboxcon.AudioDriverType_CoreAudio;
2075 elif sHost == 'win': oAudioAdapter.audioDriver = vboxcon.AudioDriverType_DirectSound;
2076 elif sHost == 'linux': oAudioAdapter.audioDriver = vboxcon.AudioDriverType_Pulse;
2077 elif sHost == 'solaris': oAudioAdapter.audioDriver = vboxcon.AudioDriverType_OSS;
2078 else:
2079 reporter.error('Unsupported host "%s".' % (sHost,));
2080 oAudioAdapter.audioDriver = vboxcon.AudioDriverType_Null;
2081
2082 # Disable by default
2083 oAudioAdapter.enabled = False;
2084 except:
2085 return reporter.errorXcpt('Unable to set audio adapter.')
2086
2087 reporter.log('set audio adapter type to %d' % (eAudioCtlType))
2088 self.oTstDrv.processPendingEvents();
2089
2090 return True
2091
2092 def setupPreferredConfig(self): # pylint: disable=R0914
2093 """
2094 Configures the VM according to the preferences of the guest type.
2095 """
2096 try:
2097 sOsTypeId = self.o.machine.OSTypeId;
2098 except:
2099 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2100 return False;
2101
2102 try:
2103 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2104 except:
2105 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2106 return False;
2107
2108 # get the attributes.
2109 try:
2110 #sFamilyId = oOsType.familyId;
2111 #f64Bit = oOsType.is64Bit;
2112 fIoApic = oOsType.recommendedIOAPIC;
2113 fVirtEx = oOsType.recommendedVirtEx;
2114 cMBRam = oOsType.recommendedRAM;
2115 cMBVRam = oOsType.recommendedVRAM;
2116 #cMBHdd = oOsType.recommendedHDD;
2117 eNicType = oOsType.adapterType;
2118 if self.fpApiVer >= 3.2:
2119 if self.fpApiVer >= 4.2:
2120 fPae = oOsType.recommendedPAE;
2121 fUsbHid = oOsType.recommendedUSBHID;
2122 fHpet = oOsType.recommendedHPET;
2123 eStorCtlType = oOsType.recommendedHDStorageController;
2124 else:
2125 fPae = oOsType.recommendedPae;
2126 fUsbHid = oOsType.recommendedUsbHid;
2127 fHpet = oOsType.recommendedHpet;
2128 eStorCtlType = oOsType.recommendedHdStorageController;
2129 eFirmwareType = oOsType.recommendedFirmware;
2130 else:
2131 fPae = False;
2132 fUsbHid = False;
2133 fHpet = False;
2134 eFirmwareType = -1;
2135 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
2136 if self.fpApiVer >= 4.0:
2137 eAudioCtlType = oOsType.recommendedAudioController;
2138 except:
2139 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
2140 self.oTstDrv.processPendingEvents();
2141 return False;
2142 self.oTstDrv.processPendingEvents();
2143
2144 # Do the setting. Continue applying settings on error in case the
2145 # caller ignores the return code
2146 fRc = True;
2147 if not self.enableIoApic(fIoApic): fRc = False;
2148 if not self.enableVirtEx(fVirtEx): fRc = False;
2149 if not self.enablePae(fPae): fRc = False;
2150 if not self.setRamSize(cMBRam): fRc = False;
2151 if not self.setVRamSize(cMBVRam): fRc = False;
2152 if not self.setNicType(eNicType, 0): fRc = False;
2153 if self.fpApiVer >= 3.2:
2154 if not self.setFirmwareType(eFirmwareType): fRc = False;
2155 if not self.enableUsbHid(fUsbHid): fRc = False;
2156 if not self.enableHpet(fHpet): fRc = False;
2157 if eStorCtlType == vboxcon.StorageControllerType_PIIX3 \
2158 or eStorCtlType == vboxcon.StorageControllerType_PIIX4 \
2159 or eStorCtlType == vboxcon.StorageControllerType_ICH6:
2160 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
2161 fRc = False;
2162 if self.fpApiVer >= 4.0:
2163 if not self.setupAudio(eAudioCtlType): fRc = False;
2164
2165 return fRc;
2166
2167 def addUsbDeviceFilter(self, sName, sVendorId = None, sProductId = None, sRevision = None, # pylint: disable=R0913
2168 sManufacturer = None, sProduct = None, sSerialNumber = None,
2169 sPort = None, sRemote = None):
2170 """
2171 Creates a USB device filter and inserts it into the VM.
2172 Returns True on success.
2173 Returns False on failure (logged).
2174 """
2175 fRc = True;
2176
2177 try:
2178 oUsbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
2179 oUsbDevFilter.active = True;
2180 if sVendorId is not None:
2181 oUsbDevFilter.vendorId = sVendorId;
2182 if sProductId is not None:
2183 oUsbDevFilter.productId = sProductId;
2184 if sRevision is not None:
2185 oUsbDevFilter.revision = sRevision;
2186 if sManufacturer is not None:
2187 oUsbDevFilter.manufacturer = sManufacturer;
2188 if sProduct is not None:
2189 oUsbDevFilter.product = sProduct;
2190 if sSerialNumber is not None:
2191 oUsbDevFilter.serialnumber = sSerialNumber;
2192 if sPort is not None:
2193 oUsbDevFilter.port = sPort;
2194 if sRemote is not None:
2195 oUsbDevFilter.remote = sRemote;
2196 try:
2197 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, oUsbDevFilter);
2198 except:
2199 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
2200 % (0, self.sName) );
2201 fRc = False;
2202 else:
2203 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
2204 except:
2205 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
2206 % (sName, self.sName) );
2207 fRc = False;
2208 return fRc;
2209
2210 def getGuestPropertyValue(self, sName):
2211 """
2212 Gets a guest property value.
2213 Returns the value on success, None on failure (logged).
2214 """
2215 try:
2216 sValue = self.o.machine.getGuestPropertyValue(sName);
2217 except:
2218 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2219 return None;
2220 return sValue;
2221
2222 def setGuestPropertyValue(self, sName, sValue):
2223 """
2224 Sets a guest property value.
2225 Returns the True on success, False on failure (logged).
2226 """
2227 try:
2228 self.o.machine.setGuestPropertyValue(sName, sValue);
2229 except:
2230 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2231 return False;
2232 return True;
2233
2234 def delGuestPropertyValue(self, sName):
2235 """
2236 Deletes a guest property value.
2237 Returns the True on success, False on failure (logged).
2238 """
2239 try:
2240 oMachine = self.o.machine;
2241 if self.fpApiVer >= 4.2:
2242 oMachine.deleteGuestProperty(sName);
2243 else:
2244 oMachine.setGuestPropertyValue(sName, '');
2245 except:
2246 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2247 return False;
2248 return True;
2249
2250 def setExtraData(self, sKey, sValue):
2251 """
2252 Sets extra data.
2253 Returns the True on success, False on failure (logged).
2254 """
2255 try:
2256 self.o.machine.setExtraData(sKey, sValue);
2257 except:
2258 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2259 return False;
2260 return True;
2261
2262 def getExtraData(self, sKey):
2263 """
2264 Gets extra data.
2265 Returns value on success, None on failure.
2266 """
2267 try:
2268 sValue = self.o.machine.getExtraData(sKey)
2269 except:
2270 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue))
2271 return None
2272 return sValue
2273
2274 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2275 """
2276 Sets up the teleporter for the VM.
2277 Returns True on success, False on failure (logged).
2278 """
2279 try:
2280 self.o.machine.teleporterAddress = sAddress;
2281 self.o.machine.teleporterPort = uPort;
2282 self.o.machine.teleporterPassword = sPassword;
2283 self.o.machine.teleporterEnabled = fEnabled;
2284 except:
2285 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2286 return False;
2287 return True;
2288
2289 def enableTeleporter(self, fEnable=True):
2290 """
2291 Enables or disables the teleporter of the VM.
2292 Returns True on success, False on failure (logged).
2293 """
2294 try:
2295 self.o.machine.teleporterEnabled = fEnable;
2296 except:
2297 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2298 return False;
2299 return True;
2300
2301 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2302 """
2303 Wrapper around the IConsole::teleport() method.
2304 Returns a progress object on success, None on failure (logged).
2305 """
2306 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2307 try:
2308 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2309 except:
2310 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2311 return None;
2312 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2313
2314 def getOsType(self):
2315 """
2316 Gets the IGuestOSType interface for the machine.
2317
2318 return IGuestOSType interface on success, None + errorXcpt on failure.
2319 No exceptions raised.
2320 """
2321 try:
2322 sOsTypeId = self.o.machine.OSTypeId;
2323 except:
2324 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2325 return None;
2326
2327 try:
2328 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2329 except:
2330 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2331 return None;
2332
2333 return oOsType;
2334
2335 def setOsType(self, sNewTypeId):
2336 """
2337 Changes the OS type.
2338
2339 returns True on success, False + errorXcpt on failure.
2340 No exceptions raised.
2341 """
2342 try:
2343 self.o.machine.OSTypeId = sNewTypeId;
2344 except:
2345 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2346 return False;
2347 return True;
2348
2349
2350 def setParavirtProvider(self, iProvider):
2351 """
2352 Sets a paravirtualisation provider.
2353 Returns the True on success, False on failure (logged).
2354 """
2355 try:
2356 self.o.machine.paravirtProvider = iProvider
2357 except:
2358 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2359 return False;
2360 return True;
2361
2362
2363
2364 #
2365 # IConsole wrappers.
2366 #
2367
2368 def powerOff(self, fFudgeOnFailure = True):
2369 """
2370 Powers off the VM.
2371
2372 Returns True on success.
2373 Returns False on IConsole::powerDown() failure.
2374 Returns None if the progress object returns failure.
2375 """
2376 #
2377 # Deregister event handler before we power off the VM, otherwise we're
2378 # racing for VM process termination and cause misleading spurious
2379 # error messages in the event handling code, because the event objects
2380 # disappear.
2381 #
2382 # Note! Doing this before powerDown to try prevent numerous smoketest
2383 # timeouts on XPCOM hosts.
2384 #
2385 self.deregisterEventHandlerForTask();
2386
2387
2388 # Try power if off.
2389 try:
2390 oProgress = self.o.console.powerDown();
2391 except:
2392 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2393 if fFudgeOnFailure:
2394 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2395 self.waitForTask(1000); # fudge
2396 return False;
2397
2398 # Wait on power off operation to complete.
2399 rc = self.oTstDrv.waitOnProgress(oProgress);
2400 if rc < 0:
2401 self.close();
2402 if fFudgeOnFailure:
2403 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2404 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2405 return None;
2406
2407 # Wait for the VM to really power off or we'll fail to open a new session to it.
2408 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2409 return self.waitForTask(30 * 1000); # fudge
2410
2411 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2412 """
2413 Restores the given snapshot.
2414
2415 Returns True on success.
2416 Returns False on IMachine::restoreSnapshot() failure.
2417 Returns None if the progress object returns failure.
2418 """
2419 try:
2420 if self.fpApiVer >= 5.0:
2421 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2422 else:
2423 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2424 except:
2425 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2426 if fFudgeOnFailure:
2427 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2428 self.waitForTask(1000); # fudge
2429 return False;
2430
2431 rc = self.oTstDrv.waitOnProgress(oProgress);
2432 if rc < 0:
2433 self.close();
2434 if fFudgeOnFailure:
2435 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2436 return None;
2437
2438 return self.waitForTask(30 * 1000);
2439
2440 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2441 """
2442 Deletes the given snapshot merging the diff image into the base.
2443
2444 Returns True on success.
2445 Returns False on IMachine::deleteSnapshot() failure.
2446 """
2447 try:
2448 if self.fpApiVer >= 5.0:
2449 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2450 else:
2451 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2452 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2453 oProgress.wait(cMsTimeout);
2454 oProgress.logResult();
2455 except:
2456 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2457 if fFudgeOnFailure:
2458 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2459 self.waitForTask(1000); # fudge
2460 return False;
2461
2462 return True;
2463
2464 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2465 """
2466 Takes a snapshot with the given name
2467
2468 Returns True on success.
2469 Returns False on IMachine::takeSnapshot() or VM state change failure.
2470 """
2471 try:
2472 if fPause is True \
2473 and self.oVM.state is vboxcon.MachineState_Running:
2474 self.o.console.pause();
2475 if self.fpApiVer >= 5.0:
2476 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2477 else:
2478 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2479 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2480 oProgress.wait(cMsTimeout);
2481 oProgress.logResult();
2482 except:
2483 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2484 if fFudgeOnFailure:
2485 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2486 self.waitForTask(1000); # fudge
2487 return False;
2488
2489 if fPause is True \
2490 and self.oVM.state is vboxcon.MachineState_Paused:
2491 self.o.console.resume();
2492
2493 return True;
2494
2495 def findSnapshot(self, sName):
2496 """
2497 Returns the snapshot object with the given name
2498
2499 Returns snapshot object on success.
2500 Returns None if there is no snapshot with the given name.
2501 """
2502 return self.oVM.findSnapshot(sName);
2503
2504 def takeScreenshot(self, sFilename, iScreenId=0):
2505 """
2506 Take screenshot from the given display and save it to specified file.
2507
2508 Returns True on success
2509 Returns False on failure.
2510 """
2511 try:
2512 if self.fpApiVer >= 5.0:
2513 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2514 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2515 vboxcon.BitmapFormat_PNG)
2516 else:
2517 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2518 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2519 except:
2520 reporter.logXcpt("Unable to take screenshot")
2521 return False
2522
2523 oFile = open(sFilename, 'wb')
2524 oFile.write(aPngData)
2525 oFile.close()
2526
2527 return True
2528
2529 def attachUsbDevice(self, sUuid, sCaptureFilename = None):
2530 """
2531 Attach given USB device UUID to the VM.
2532
2533 Returns True on success
2534 Returns False on failure.
2535 """
2536 fRc = True;
2537 try:
2538 if sCaptureFilename is None:
2539 self.o.console.attachUSBDevice(sUuid, '');
2540 else:
2541 self.o.console.attachUSBDevice(sUuid, sCaptureFilename);
2542 except:
2543 reporter.logXcpt('Unable to attach USB device %s' % (sUuid,));
2544 fRc = False;
2545
2546 return fRc;
2547
2548 def detachUsbDevice(self, sUuid):
2549 """
2550 Detach given USB device UUID from the VM.
2551
2552 Returns True on success
2553 Returns False on failure.
2554 """
2555 fRc = True;
2556 try:
2557 _ = self.o.console.detachUSBDevice(sUuid);
2558 except:
2559 reporter.logXcpt('Unable to detach USB device %s' % (sUuid,));
2560 fRc = False;
2561
2562 return fRc;
2563
2564
2565 #
2566 # IMachineDebugger wrappers.
2567 #
2568
2569 def queryOsKernelLog(self):
2570 """
2571 Tries to get the OS kernel log using the VM debugger interface.
2572
2573 Returns string containing the kernel log on success.
2574 Returns None on failure.
2575 """
2576 sOsKernelLog = None;
2577 try:
2578 self.o.console.debugger.loadPlugIn('all');
2579 except:
2580 reporter.logXcpt('Unable to load debugger plugins');
2581 else:
2582 try:
2583 sOsDetected = self.o.console.debugger.detectOS();
2584 except:
2585 reporter.logXcpt('Failed to detect the guest OS');
2586 else:
2587 try:
2588 sOsKernelLog = self.o.console.debugger.queryOSKernelLog(0);
2589 except:
2590 reporter.logXcpt('Unable to get the guest OS (%s) kernel log' % (sOsDetected,));
2591 return sOsKernelLog;
2592
2593 def queryDbgInfo(self, sItem, sArg = '', sDefault = None):
2594 """
2595 Simple wrapper around IMachineDebugger::info.
2596
2597 Returns string on success, sDefault on failure (logged).
2598 """
2599 try:
2600 return self.o.console.debugger.info(sItem, sArg);
2601 except:
2602 reporter.logXcpt('Unable to query "%s" with arg "%s"' % (sItem, sArg,));
2603 return sDefault;
2604
2605 def queryDbgInfoVgaText(self, sArg = 'all'):
2606 """
2607 Tries to get the 'info vgatext' output, provided we're in next mode.
2608
2609 Returns string containing text on success.
2610 Returns None on failure or not text mode.
2611 """
2612 sVgaText = None;
2613 try:
2614 sVgaText = self.o.console.debugger.info('vgatext', sArg);
2615 if sVgaText.startswith('Not in text mode!'):
2616 sVgaText = None;
2617 except:
2618 reporter.logXcpt('Unable to query vgatext with arg "%s"' % (sArg,));
2619 return sVgaText;
2620
2621 def queryDbgGuestStack(self, iCpu = 0):
2622 """
2623 Returns the guest stack for the given VCPU.
2624
2625 Returns string containing the guest stack for the selected VCPU on success.
2626 Returns None on failure.
2627 """
2628
2629 #
2630 # Load all plugins first and try to detect the OS so we can
2631 # get nicer stack traces.
2632 #
2633 try:
2634 self.o.console.debugger.loadPlugIn('all');
2635 except:
2636 reporter.logXcpt('Unable to load debugger plugins');
2637 else:
2638 try:
2639 sOsDetected = self.o.console.debugger.detectOS();
2640 _ = sOsDetected;
2641 except:
2642 reporter.logXcpt('Failed to detect the guest OS');
2643
2644 sGuestStack = None;
2645 try:
2646 sGuestStack = self.o.console.debugger.dumpGuestStack(iCpu);
2647 except:
2648 reporter.logXcpt('Unable to query guest stack for CPU %s' % (iCpu, ));
2649
2650 return sGuestStack;
2651
2652
2653 #
2654 # Other methods.
2655 #
2656
2657 def getPrimaryIp(self):
2658 """
2659 Tries to obtain the primary IP address of the guest via the guest
2660 properties.
2661
2662 Returns IP address on success.
2663 Returns empty string on failure.
2664 """
2665 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2666 if vbox.isIpAddrValid(sIpAddr):
2667 return sIpAddr;
2668 return '';
2669
2670 def getPid(self):
2671 """
2672 Gets the process ID for the direct session unless it's ourselves.
2673 """
2674 if self.uPid is None and self.o is not None and self.fRemoteSession:
2675 try:
2676 if self.fpApiVer >= 4.2:
2677 uPid = self.o.machine.sessionPID;
2678 else:
2679 uPid = self.o.machine.sessionPid;
2680 if uPid != os.getpid() and uPid != 0xffffffff:
2681 self.uPid = uPid;
2682 except Exception, oXcpt:
2683 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
2684 try:
2685 if self.fpApiVer >= 4.2:
2686 uPid = self.oVM.sessionPID;
2687 else:
2688 uPid = self.oVM.sessionPid;
2689 if uPid != os.getpid() and uPid != 0xffffffff:
2690 self.uPid = uPid;
2691 except:
2692 reporter.log2Xcpt();
2693 else:
2694 reporter.log2Xcpt();
2695 if self.uPid is not None:
2696 reporter.log2('getPid: %u' % (self.uPid,));
2697 self.fPidFile = self.oTstDrv.pidFileAdd(self.uPid, 'vm_%s' % (self.sName,), # Set-uid-to-root is similar to SUDO.
2698 fSudo = True);
2699 return self.uPid;
2700
2701 def addLogsToReport(self, cReleaseLogs = 1):
2702 """
2703 Retrieves and adds the release and debug logs to the test report.
2704 """
2705 fRc = True;
2706
2707 # Add each of the requested release logs to the report.
2708 for iLog in range(0, cReleaseLogs):
2709 try:
2710 if self.fpApiVer >= 3.2:
2711 sLogFile = self.oVM.queryLogFilename(iLog);
2712 elif iLog > 0:
2713 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
2714 else:
2715 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
2716 except:
2717 reporter.logXcpt('iLog=%s' % (iLog,));
2718 fRc = False;
2719 else:
2720 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
2721 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
2722 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2723
2724 # Now for the hardened windows startup log.
2725 try:
2726 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxHardening.log');
2727 except:
2728 reporter.logXcpt();
2729 fRc = False;
2730 else:
2731 if os.path.isfile(sLogFile):
2732 reporter.addLogFile(sLogFile, 'log/release/vm', '%s hardening log' % (self.sName, ),
2733 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2734
2735 # Now for the debug log.
2736 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
2737 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
2738 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
2739
2740 return fRc;
2741
2742 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
2743 """
2744 Create an instance of the given ConsoleEventHandlerBase sub-class and
2745 register it.
2746
2747 The new instance is returned on success. None is returned on error.
2748 """
2749
2750 # We need a console object.
2751 try:
2752 oConsole = self.o.console;
2753 except Exception, oXcpt:
2754 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
2755 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
2756 return None;
2757
2758 # Add the base class arguments.
2759 dArgsCopy = dArgs.copy() if dArgs is not None else dict();
2760 dArgsCopy['oSession'] = self;
2761 dArgsCopy['oConsole'] = oConsole;
2762 sLogSuffix = 'on %s' % (self.sName,)
2763 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
2764 oConsole, 'IConsole', 'IConsoleCallback',
2765 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
2766
2767 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
2768 """
2769 Enables the testing part of the VMMDev.
2770
2771 Returns True on success and False on failure. Error information is logged.
2772 """
2773 fRc = True;
2774 try:
2775 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
2776 '1' if fEnabled else '');
2777 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
2778 '1' if fEnableMMIO and fEnabled else '');
2779 except:
2780 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
2781 fRc = False;
2782 else:
2783 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
2784 self.oTstDrv.processPendingEvents();
2785 return fRc;
2786
2787 #
2788 # Test eXecution Service methods.
2789 #
2790
2791 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, sMacAddr = None, fNatForwardingForTxs = False):
2792 """
2793 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
2794 addresses are specified, we'll get the IP from the guest additions.
2795
2796 Returns a TxsConnectTask object on success, None + log on failure.
2797 """
2798 # If the VM is configured with a NAT interface, connect to local host.
2799 fReversedSetup = False;
2800 fUseNatForTxs = False;
2801 if sIpAddr is None:
2802 try:
2803 oNic = self.oVM.getNetworkAdapter(0);
2804 if oNic.attachmentType == vboxcon.NetworkAttachmentType_NAT:
2805 fUseNatForTxs = True;
2806 except:
2807 reporter.errorXcpt();
2808 return None;
2809 if fUseNatForTxs:
2810 fReversedSetup = not fNatForwardingForTxs;
2811 sIpAddr = '127.0.0.1';
2812
2813 # Kick off the task.
2814 try:
2815 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup);
2816 except:
2817 reporter.errorXcpt();
2818 oTask = None;
2819 return oTask;
2820
2821 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
2822 """
2823 Attempts to connect to a TXS instance.
2824
2825 Returns True if a connection was established, False if not (only grave
2826 failures are logged as errors).
2827
2828 Note! The timeout is more of a guideline...
2829 """
2830
2831 if sHostname is None or sHostname.strip() == '':
2832 raise base.GenError('Empty sHostname is not implemented yet');
2833
2834 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
2835 cMsIdleFudge = cMsTimeout / 2);
2836 if oTxsSession is None:
2837 return False;
2838
2839 # Wait for the connect task to time out.
2840 self.oTstDrv.addTask(oTxsSession);
2841 self.oTstDrv.processPendingEvents();
2842 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
2843 self.oTstDrv.removeTask(oTxsSession);
2844 if oRc != oTxsSession:
2845 if oRc is not None:
2846 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
2847 self.oTstDrv.processPendingEvents();
2848 oTxsSession.cancelTask(); # this is synchronous
2849 return False;
2850
2851 # Check the status.
2852 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
2853 if not oTxsSession.isSuccess():
2854 return False;
2855
2856 reporter.log2('Disconnecting from TXS...');
2857 return oTxsSession.syncDisconnect();
2858
2859
2860
2861class TxsConnectTask(TdTaskBase):
2862 """
2863 Class that takes care of connecting to a VM.
2864 """
2865
2866 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
2867 """ Class for looking for IPv4 address changes on interface 0."""
2868 def __init__(self, dArgs):
2869 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs); # pylint: disable=W0233
2870 self.oParentTask = dArgs['oParentTask'];
2871 self.sMachineId = dArgs['sMachineId'];
2872
2873 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags):
2874 """Look for IP address."""
2875 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags));
2876 if sMachineId == self.sMachineId \
2877 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
2878 oParentTask = self.oParentTask;
2879 if oParentTask:
2880 oParentTask._setIp(sValue); # pylint: disable=W0212
2881
2882
2883 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup):
2884 TdTaskBase.__init__(self, utils.getCallerName());
2885 self.cMsTimeout = cMsTimeout;
2886 self.sIpAddr = None;
2887 self.sNextIpAddr = None;
2888 self.sMacAddr = sMacAddr;
2889 self.fReversedSetup = fReversedSetup;
2890 self.oVBoxEventHandler = None;
2891 self.oTxsSession = None;
2892
2893 # Skip things we don't implement.
2894 if sMacAddr is not None:
2895 reporter.error('TxsConnectTask does not implement sMacAddr yet');
2896 raise base.GenError();
2897
2898 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
2899 if fReversedSetup is True:
2900 self._openTcpSession(sIpAddr, fReversedSetup = True);
2901 elif sIpAddr is not None and sIpAddr.strip() != '':
2902 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2903 else:
2904 #
2905 # If we've got no IP address, register callbacks that listens for
2906 # the primary network adaptor of the VM to set a IPv4 guest prop.
2907 # Note! The order in which things are done here is kind of important.
2908 #
2909
2910 # 0. The caller zaps the property before starting the VM.
2911 #try:
2912 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2913 #except:
2914 # reporter.logXcpt();
2915
2916 # 1. Register the callback / event listener object.
2917 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
2918 self.oVBoxEventHandler = oSession.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
2919
2920 # 2. Query the guest properties.
2921 try:
2922 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2923 except:
2924 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
2925 self._deregisterEventHandler();
2926 raise;
2927 else:
2928 if sIpAddr is not None:
2929 self._setIp(sIpAddr);
2930 # end __init__
2931
2932 def __del__(self):
2933 """ Make sure we deregister the callback. """
2934 self._deregisterEventHandler();
2935 return TdTaskBase.__del__(self);
2936
2937 def toString(self):
2938 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
2939 ' oTxsSession=%s oVBoxEventHandler=%s>' \
2940 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
2941 self.oTxsSession, self.oVBoxEventHandler);
2942
2943 def _deregisterEventHandler(self):
2944 """Deregisters the event handler."""
2945 fRc = True;
2946 oVBoxEventHandler = self.oVBoxEventHandler;
2947 if oVBoxEventHandler is not None:
2948 self.oVBoxEventHandler = None;
2949 fRc = oVBoxEventHandler.unregister();
2950 oVBoxEventHandler.oParentTask = None; # Try avoid cylic deps.
2951 return fRc;
2952
2953 def _setIp(self, sIpAddr, fInitCall = False):
2954 """Called when we get an IP. Will create a TXS session and signal the task."""
2955 sIpAddr = sIpAddr.strip();
2956
2957 if sIpAddr is not None \
2958 and sIpAddr != '':
2959 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
2960 try:
2961 for s in sIpAddr.split('.'):
2962 i = int(s);
2963 if str(i) != s:
2964 raise Exception();
2965 except:
2966 reporter.fatalXcpt();
2967 else:
2968 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2969 return None;
2970
2971 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
2972 else:
2973 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
2974 return None;
2975
2976 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
2977 """
2978 Calls txsclient.openTcpSession and switches our task to reflect the
2979 state of the subtask.
2980 """
2981 self.oCv.acquire();
2982 if self.oTxsSession is None:
2983 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' % \
2984 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
2985 self.sIpAddr = sIpAddr;
2986 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, \
2987 fReversedSetup, cMsIdleFudge);
2988 self.oTxsSession.setTaskOwner(self);
2989 else:
2990 self.sNextIpAddr = sIpAddr;
2991 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
2992 self.oCv.release();
2993 return None;
2994
2995 def notifyAboutReadyTask(self, oTxsSession):
2996 """
2997 Called by the TXS session task when it's done.
2998
2999 We'll signal the task completed or retry depending on the result.
3000 """
3001
3002 self.oCv.acquire();
3003
3004 # Disassociate ourselves with the session (avoid cyclic ref)
3005 oTxsSession.setTaskOwner(None);
3006 fSuccess = oTxsSession.isSuccess();
3007 if self.oTxsSession is not None:
3008 if not fSuccess:
3009 self.oTxsSession = None;
3010 if fSuccess and self.fReversedSetup:
3011 self.sIpAddr = oTxsSession.oTransport.sHostname;
3012 else:
3013 fSuccess = False;
3014
3015 # Signal done, or retry?
3016 fDeregister = False;
3017 if fSuccess \
3018 or self.fReversedSetup \
3019 or self.getAgeAsMs() >= self.cMsTimeout:
3020 self.signalTaskLocked();
3021 fDeregister = True;
3022 else:
3023 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
3024 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3025
3026 self.oCv.release();
3027
3028 # If we're done, deregister the callback (w/o owning lock). It will
3029 if fDeregister:
3030 self._deregisterEventHandler();
3031 return True;
3032
3033 #
3034 # Public methods
3035 #
3036
3037 def getResult(self):
3038 """
3039 Returns the connected TXS session object on success.
3040 Returns None on failure or if the task has not yet completed.
3041 """
3042 self.oCv.acquire();
3043 oTxsSession = self.oTxsSession;
3044 self.oCv.release();
3045
3046 if oTxsSession is not None and not oTxsSession.isSuccess():
3047 oTxsSession = None;
3048 return oTxsSession;
3049
3050 def cancelTask(self):
3051 """ Cancels the task. """
3052 self._deregisterEventHandler(); # (make sure to avoid cyclic fun)
3053 self.oCv.acquire();
3054 if not self.fSignalled:
3055 oTxsSession = self.oTxsSession;
3056 if oTxsSession is not None:
3057 self.oCv.release();
3058 oTxsSession.setTaskOwner(None);
3059 oTxsSession.cancelTask();
3060 oTxsSession.waitForTask(1000);
3061 self.oCv.acquire();
3062 self.signalTaskLocked();
3063 self.oCv.release();
3064 return True;
3065
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