VirtualBox

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

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

ValKit/vboxwrappers.py: Fixed regression from r147033 where a new constant is used unguarded, which causes trouble with testing VBox-6.1 which doesn't have it. bugref:1484

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