VirtualBox

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

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

ValKit/vboxwrappers.py: The onGuestPropertyChange signature was changed in the base class in r150443, made the TxsConnectTaskVBoxCallback child match. bugref:10185

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