VirtualBox

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

Last change on this file since 99401 was 99401, checked in by vboxsync, 22 months ago

Validation Kit/vboxwrappers: Also enroll MOKs for Secure Boot for 7.0 builds >= r156564 when Secure Boot is enabled; otherwise Guest Additions tests will fail. Warn for older 7.0 builds.

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