VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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