VirtualBox

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

Last change on this file since 98992 was 98992, checked in by vboxsync, 21 months ago

ValidationKit: Add Linux test VMs which have Secure Boot enabled, bugref:10287.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 146.2 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 98992 2023-03-15 15:53:43Z 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: 98992 $"
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 is not None:
1250 sFullName = self.oTstDrv.getFullResourceName(sUefiMokPathPrefix) + '.der';
1251 with open(sFullName, "rb") as f:
1252 self.o.machine.nonVolatileStore.uefiVariableStore.addSignatureToMok(bytearray(f.read()), uuid.uuid4().hex, vboxcon.SignatureType_X509);
1253
1254 self.o.machine.nonVolatileStore.uefiVariableStore.secureBootEnabled = fEnable;
1255 except:
1256 reporter.errorXcpt('failed to change Secure Boot to %s for "%s"' % (fEnable, self.sName));
1257 fRc = False;
1258 else:
1259 reporter.log('changed Secure Boot to %s for "%s"' % (fEnable, self.sName));
1260 self.oTstDrv.processPendingEvents();
1261
1262 else:
1263 reporter.log('Secure Boot is only supported for API 7.0 or newer');
1264 fRc = False;
1265
1266 return fRc;
1267
1268 def setChipsetType(self, eType):
1269 """
1270 Sets the chipset type.
1271 Returns True on success and False on failure. Error information is logged.
1272 """
1273 fRc = True;
1274 try:
1275 self.o.machine.chipsetType = eType;
1276 except:
1277 reporter.errorXcpt('failed to set chipsetType=%s for "%s"' % (eType, self.sName));
1278 fRc = False;
1279 else:
1280 reporter.log('set chipsetType=%s for "%s"' % (eType, self.sName));
1281 self.oTstDrv.processPendingEvents();
1282 return fRc;
1283
1284 def setIommuType(self, eType):
1285 """
1286 Sets the IOMMU type.
1287 Returns True on success and False on failure. Error information is logged.
1288 """
1289 # Supported.
1290 if self.fpApiVer < 6.2 or not hasattr(vboxcon, 'IommuType_Intel') or not hasattr(vboxcon, 'IommuType_AMD'):
1291 return True;
1292 fRc = True;
1293 try:
1294 self.o.machine.iommuType = eType;
1295 except:
1296 reporter.errorXcpt('failed to set iommuType=%s for "%s"' % (eType, self.sName));
1297 fRc = False;
1298 else:
1299 reporter.log('set iommuType=%s for "%s"' % (eType, self.sName));
1300 self.oTstDrv.processPendingEvents();
1301 return fRc;
1302
1303 def setupBootLogo(self, fEnable, cMsLogoDisplay = 0):
1304 """
1305 Sets up the boot logo. fEnable toggles the fade and boot menu
1306 settings as well as the mode.
1307 """
1308 fRc = True;
1309 try:
1310 self.o.machine.BIOSSettings.logoFadeIn = not fEnable;
1311 self.o.machine.BIOSSettings.logoFadeOut = not fEnable;
1312 self.o.machine.BIOSSettings.logoDisplayTime = cMsLogoDisplay;
1313 if fEnable:
1314 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_Disabled;
1315 else:
1316 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_MessageAndMenu;
1317 except:
1318 reporter.errorXcpt('failed to set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1319 fRc = False;
1320 else:
1321 reporter.log('set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1322 self.oTstDrv.processPendingEvents();
1323 return fRc;
1324
1325 def setupVrdp(self, fEnable, uPort = None):
1326 """
1327 Configures VRDP.
1328 """
1329 fRc = True;
1330 try:
1331 if self.fpApiVer >= 4.0:
1332 self.o.machine.VRDEServer.enabled = fEnable;
1333 else:
1334 self.o.machine.VRDPServer.enabled = fEnable;
1335 except:
1336 reporter.errorXcpt('failed to set VRDEServer::enabled=%s for "%s"' % (fEnable, self.sName));
1337 fRc = False;
1338
1339 if uPort is not None and fRc:
1340 try:
1341 if self.fpApiVer >= 4.0:
1342 self.o.machine.VRDEServer.setVRDEProperty("TCP/Ports", str(uPort));
1343 else:
1344 self.o.machine.VRDPServer.ports = str(uPort);
1345 except:
1346 reporter.errorXcpt('failed to set VRDEServer::ports=%s for "%s"' % (uPort, self.sName));
1347 fRc = False;
1348 if fRc:
1349 reporter.log('set VRDEServer.enabled/ports=%s/%s for "%s"' % (fEnable, uPort, self.sName));
1350 self.oTstDrv.processPendingEvents();
1351 return fRc;
1352
1353 def getNicDriverNameFromType(self, eNicType):
1354 """
1355 Helper that translate the adapter type into a driver name.
1356 """
1357 if eNicType in (vboxcon.NetworkAdapterType_Am79C970A, vboxcon.NetworkAdapterType_Am79C973):
1358 sName = 'pcnet';
1359 elif eNicType in (vboxcon.NetworkAdapterType_I82540EM,
1360 vboxcon.NetworkAdapterType_I82543GC,
1361 vboxcon.NetworkAdapterType_I82545EM):
1362 sName = 'e1000';
1363 elif eNicType == vboxcon.NetworkAdapterType_Virtio:
1364 sName = 'virtio-net';
1365 else:
1366 reporter.error('Unknown adapter type "%s" (VM: "%s")' % (eNicType, self.sName));
1367 sName = 'pcnet';
1368 return sName;
1369
1370 def setupNatForwardingForTxs(self, iNic = 0, iHostPort = 5042):
1371 """
1372 Sets up NAT forwarding for port 5042 if applicable, cleans up if not.
1373 """
1374 try:
1375 oNic = self.o.machine.getNetworkAdapter(iNic);
1376 except:
1377 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1378 return False;
1379
1380 # Nuke the old setup for all possible adapter types (in case we're
1381 # called after it changed).
1382 for sName in ('pcnet', 'e1000', 'virtio-net'):
1383 for sConfig in ('VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic), \
1384 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)):
1385 try:
1386 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), '');
1387 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '');
1388 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '');
1389 except:
1390 reporter.errorXcpt();
1391
1392 # Set up port forwarding if NAT attachment.
1393 try:
1394 eAttType = oNic.attachmentType;
1395 except:
1396 reporter.errorXcpt('attachmentType on %s failed for "%s"' % (iNic, self.sName));
1397 return False;
1398 if eAttType != vboxcon.NetworkAttachmentType_NAT:
1399 return True;
1400
1401 try:
1402 eNicType = oNic.adapterType;
1403 fTraceEnabled = oNic.traceEnabled;
1404 except:
1405 reporter.errorXcpt('attachmentType/traceEnabled on %s failed for "%s"' % (iNic, self.sName));
1406 return False;
1407
1408 if self.fpApiVer >= 4.1:
1409 try:
1410 if self.fpApiVer >= 4.2:
1411 oNatEngine = oNic.NATEngine;
1412 else:
1413 oNatEngine = oNic.natDriver;
1414 except:
1415 reporter.errorXcpt('Failed to get INATEngine data on "%s"' % (self.sName));
1416 return False;
1417 try: oNatEngine.removeRedirect('txs');
1418 except: pass;
1419 try:
1420 oNatEngine.addRedirect('txs', vboxcon.NATProtocol_TCP, '127.0.0.1', '%s' % (iHostPort), '', '5042');
1421 except:
1422 reporter.errorXcpt('Failed to add a addRedirect redirect on "%s"' % (self.sName));
1423 return False;
1424
1425 else:
1426 sName = self.getNicDriverNameFromType(eNicType);
1427 if fTraceEnabled:
1428 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic)
1429 else:
1430 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)
1431
1432 try:
1433 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), 'TCP');
1434 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '%s' % (iHostPort));
1435 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '5042');
1436 except:
1437 reporter.errorXcpt('Failed to set NAT extra data on "%s"' % (self.sName));
1438 return False;
1439 return True;
1440
1441 def setNicType(self, eType, iNic = 0):
1442 """
1443 Sets the NIC type of the specified NIC.
1444 Returns True on success and False on failure. Error information is logged.
1445 """
1446 try:
1447 try:
1448 oNic = self.o.machine.getNetworkAdapter(iNic);
1449 except:
1450 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1451 return False;
1452 try:
1453 oNic.adapterType = eType;
1454 except:
1455 reporter.errorXcpt('failed to set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1456 return False;
1457 finally:
1458 self.oTstDrv.processPendingEvents();
1459
1460 if not self.setupNatForwardingForTxs(iNic):
1461 return False;
1462 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1463 return True;
1464
1465 def setNicTraceEnabled(self, fTraceEnabled, sTraceFile, iNic = 0):
1466 """
1467 Sets the NIC trace enabled flag and file path.
1468 Returns True on success and False on failure. Error information is logged.
1469 """
1470 try:
1471 try:
1472 oNic = self.o.machine.getNetworkAdapter(iNic);
1473 except:
1474 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1475 return False;
1476 try:
1477 oNic.traceEnabled = fTraceEnabled;
1478 oNic.traceFile = sTraceFile;
1479 except:
1480 reporter.errorXcpt('failed to set NIC trace flag on slot %s to %s for VM "%s"' \
1481 % (iNic, fTraceEnabled, self.sName));
1482 return False;
1483 finally:
1484 self.oTstDrv.processPendingEvents();
1485
1486 if not self.setupNatForwardingForTxs(iNic):
1487 return False;
1488 reporter.log('set NIC trace on slot %s to "%s" (path "%s") for VM "%s"' %
1489 (iNic, fTraceEnabled, sTraceFile, self.sName));
1490 return True;
1491
1492 def getDefaultNicName(self, eAttachmentType):
1493 """
1494 Return the default network / interface name for the NIC attachment type.
1495 """
1496 sRetName = '';
1497 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1498 if self.oTstDrv.sDefBridgedNic is not None:
1499 sRetName = self.oTstDrv.sDefBridgedNic;
1500 else:
1501 sRetName = 'eth0';
1502 try:
1503 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1504 for oHostNic in aoHostNics:
1505 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_Bridged \
1506 and oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1507 sRetName = oHostNic.name;
1508 break;
1509 except:
1510 reporter.errorXcpt();
1511
1512 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1513 try:
1514 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1515 for oHostNic in aoHostNics:
1516 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_HostOnly:
1517 if oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1518 sRetName = oHostNic.name;
1519 break;
1520 if sRetName == '':
1521 sRetName = oHostNic.name;
1522 except:
1523 reporter.errorXcpt();
1524 if sRetName == '':
1525 # Create a new host-only interface.
1526 reporter.log("Creating host only NIC ...");
1527 try:
1528 (oIProgress, oIHostOnly) = self.oVBox.host.createHostOnlyNetworkInterface();
1529 oProgress = ProgressWrapper(oIProgress, self.oVBoxMgr, self.oTstDrv, 'Create host only NIC');
1530 oProgress.wait();
1531 if oProgress.logResult() is False:
1532 return '';
1533 sRetName = oIHostOnly.name;
1534 except:
1535 reporter.errorXcpt();
1536 return '';
1537 reporter.log("Created host only NIC: '%s'" % (sRetName,));
1538
1539 elif self.fpApiVer >= 7.0 and eAttachmentType == vboxcon.NetworkAttachmentType_HostOnlyNetwork:
1540 aoHostNetworks = self.oVBoxMgr.getArray(self.oVBox, 'hostOnlyNetworks');
1541 if aoHostNetworks:
1542 sRetName = aoHostNetworks[0].networkName;
1543 else:
1544 try:
1545 oHostOnlyNet = self.oVBox.createHostOnlyNetwork('Host-only Test Network');
1546 oHostOnlyNet.lowerIP = '192.168.56.1';
1547 oHostOnlyNet.upperIP = '192.168.56.199';
1548 oHostOnlyNet.networkMask = '255.255.255.0';
1549 sRetName = oHostOnlyNet.networkName;
1550 except:
1551 reporter.errorXcpt();
1552 return '';
1553
1554 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1555 sRetName = 'VBoxTest';
1556
1557 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1558 sRetName = '';
1559
1560 else: ## @todo Support NetworkAttachmentType_NATNetwork
1561 reporter.error('eAttachmentType=%s is not known' % (eAttachmentType));
1562 return sRetName;
1563
1564 def setNicAttachment(self, eAttachmentType, sName = None, iNic = 0):
1565 """
1566 Sets the attachment type of the specified NIC.
1567 Returns True on success and False on failure. Error information is logged.
1568 """
1569 try:
1570 oNic = self.o.machine.getNetworkAdapter(iNic);
1571 except:
1572 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1573 return False;
1574
1575 try:
1576 if eAttachmentType is not None:
1577 try:
1578 if self.fpApiVer >= 4.1:
1579 oNic.attachmentType = eAttachmentType;
1580 else:
1581 if eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1582 oNic.attachToNAT();
1583 elif eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1584 oNic.attachToBridgedInterface();
1585 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1586 oNic.attachToInternalNetwork();
1587 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1588 oNic.attachToHostOnlyInterface();
1589 else:
1590 raise base.GenError("eAttachmentType=%s is invalid" % (eAttachmentType));
1591 except:
1592 reporter.errorXcpt('failed to set the attachment type on slot %s to %s for VM "%s"' \
1593 % (iNic, eAttachmentType, self.sName));
1594 return False;
1595 else:
1596 try:
1597 eAttachmentType = oNic.attachmentType;
1598 except:
1599 reporter.errorXcpt('failed to get the attachment type on slot %s for VM "%s"' % (iNic, self.sName));
1600 return False;
1601 finally:
1602 self.oTstDrv.processPendingEvents();
1603
1604 if sName is not None:
1605 # Resolve the special 'default' name.
1606 if sName == 'default':
1607 sName = self.getDefaultNicName(eAttachmentType);
1608
1609 # The name translate to different attributes depending on the
1610 # attachment type.
1611 try:
1612 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1613 ## @todo check this out on windows, may have to do a
1614 # translation of the name there or smth IIRC.
1615 try:
1616 if self.fpApiVer >= 4.1:
1617 oNic.bridgedInterface = sName;
1618 else:
1619 oNic.hostInterface = sName;
1620 except:
1621 reporter.errorXcpt('failed to set the hostInterface property on slot %s to "%s" for VM "%s"'
1622 % (iNic, sName, self.sName,));
1623 return False;
1624 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1625 try:
1626 if self.fpApiVer >= 4.1:
1627 oNic.hostOnlyInterface = sName;
1628 else:
1629 oNic.hostInterface = sName;
1630 except:
1631 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"'
1632 % (iNic, sName, self.sName,));
1633 return False;
1634 elif self.fpApiVer >= 7.0 and eAttachmentType == vboxcon.NetworkAttachmentType_HostOnlyNetwork:
1635 try:
1636 oNic.hostOnlyNetwork = sName;
1637 except:
1638 reporter.errorXcpt('failed to set the hostOnlyNetwork property on slot %s to "%s" for VM "%s"'
1639 % (iNic, sName, self.sName,));
1640 return False;
1641 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1642 try:
1643 oNic.internalNetwork = sName;
1644 except:
1645 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"'
1646 % (iNic, sName, self.sName,));
1647 return False;
1648 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1649 try:
1650 oNic.NATNetwork = sName;
1651 except:
1652 reporter.errorXcpt('failed to set the NATNetwork property on slot %s to "%s" for VM "%s"'
1653 % (iNic, sName, self.sName,));
1654 return False;
1655 finally:
1656 self.oTstDrv.processPendingEvents();
1657
1658 if not self.setupNatForwardingForTxs(iNic):
1659 return False;
1660 reporter.log('set NIC attachment type on slot %s to %s for VM "%s"' % (iNic, eAttachmentType, self.sName));
1661 return True;
1662
1663 def setNicLocalhostReachable(self, fReachable, iNic = 0):
1664 """
1665 Sets whether the specified NIC can reach the host or not.
1666 Only affects (enabled) NICs configured to NAT at the moment.
1667
1668 Returns True on success and False on failure. Error information is logged.
1669 """
1670 try:
1671 oNic = self.o.machine.getNetworkAdapter(iNic);
1672 except:
1673 return reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName,));
1674
1675 try:
1676 if not oNic.enabled: # NIC not enabled? Nothing to do here.
1677 return True;
1678 except:
1679 return reporter.errorXcpt('NIC enabled status (%s) failed for "%s"' % (iNic, self.sName,));
1680
1681 reporter.log('Setting "LocalhostReachable" for network adapter in slot %d to %s' % (iNic, fReachable));
1682
1683 try:
1684 oNatEngine = oNic.NATEngine;
1685 except:
1686 return reporter.errorXcpt('Getting NIC NAT engine (%s) failed for "%s"' % (iNic, self.sName,));
1687
1688 try:
1689 if hasattr(oNatEngine, "localhostReachable"):
1690 oNatEngine.localhostReachable = fReachable;
1691 else:
1692 oNatEngine.LocalhostReachable = fReachable;
1693 except:
1694 return reporter.errorXcpt('LocalhostReachable (%s) failed for "%s"' % (iNic, self.sName,));
1695
1696 return True;
1697
1698 def setNicMacAddress(self, sMacAddr, iNic = 0):
1699 """
1700 Sets the MAC address of the specified NIC.
1701
1702 The sMacAddr parameter is a string supplying the tail end of the MAC
1703 address, missing quads are supplied from a constant byte (2), the IPv4
1704 address of the host, and the NIC number.
1705
1706 Returns True on success and False on failure. Error information is logged.
1707 """
1708
1709 # Resolve missing MAC address prefix by feeding in the host IP address bytes.
1710 cchMacAddr = len(sMacAddr);
1711 if 0 < cchMacAddr < 12:
1712 sHostIP = netutils.getPrimaryHostIp();
1713 abHostIP = socket.inet_aton(sHostIP);
1714 if sys.version_info[0] < 3:
1715 abHostIP = (ord(abHostIP[0]), ord(abHostIP[1]), ord(abHostIP[2]), ord(abHostIP[3]));
1716
1717 if abHostIP[0] == 127 \
1718 or (abHostIP[0] == 169 and abHostIP[1] == 254) \
1719 or (abHostIP[0] == 192 and abHostIP[1] == 168 and abHostIP[2] == 56):
1720 return reporter.error('host IP for "%s" is %s, most likely not unique.' % (netutils.getHostnameFqdn(), sHostIP,));
1721
1722 sDefaultMac = '%02X%02X%02X%02X%02X%02X' % (0x02, abHostIP[0], abHostIP[1], abHostIP[2], abHostIP[3], iNic);
1723 sMacAddr = sDefaultMac[0:(12 - cchMacAddr)] + sMacAddr;
1724
1725 # Get the NIC object and try set it address.
1726 try:
1727 oNic = self.o.machine.getNetworkAdapter(iNic);
1728 except:
1729 return reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName,));
1730
1731 try:
1732 oNic.MACAddress = sMacAddr;
1733 except:
1734 return reporter.errorXcpt('failed to set the MAC address on slot %s to "%s" for VM "%s"'
1735 % (iNic, sMacAddr, self.sName));
1736
1737 reporter.log('set MAC address on slot %s to %s for VM "%s"' % (iNic, sMacAddr, self.sName,));
1738 return True;
1739
1740 def setRamSize(self, cMB):
1741 """
1742 Set the RAM size of the VM.
1743 Returns True on success and False on failure. Error information is logged.
1744 """
1745 fRc = True;
1746 try:
1747 self.o.machine.memorySize = cMB;
1748 except:
1749 reporter.errorXcpt('failed to set the RAM size of "%s" to %s' % (self.sName, cMB));
1750 fRc = False;
1751 else:
1752 reporter.log('set the RAM size of "%s" to %s' % (self.sName, cMB));
1753 self.oTstDrv.processPendingEvents();
1754 return fRc;
1755
1756 def setLargePages(self, fUseLargePages):
1757 """
1758 Configures whether the VM should use large pages or not.
1759 Returns True on success and False on failure. Error information is logged.
1760 """
1761 fRc = True;
1762 try:
1763 self.o.machine.setHWVirtExProperty(vboxcon.HWVirtExPropertyType_LargePages, fUseLargePages);
1764 except:
1765 reporter.errorXcpt('failed to set large pages of "%s" to %s' % (self.sName, fUseLargePages));
1766 fRc = False;
1767 else:
1768 reporter.log('set the large pages of "%s" to %s' % (self.sName, fUseLargePages));
1769 self.oTstDrv.processPendingEvents();
1770 return fRc;
1771
1772 def setVRamSize(self, cMB):
1773 """
1774 Set the RAM size of the VM.
1775 Returns True on success and False on failure. Error information is logged.
1776 """
1777 fRc = True;
1778 try:
1779 if self.fpApiVer >= 6.1 and hasattr(self.o.machine, 'graphicsAdapter'):
1780 self.o.machine.graphicsAdapter.VRAMSize = cMB;
1781 else:
1782 self.o.machine.VRAMSize = cMB;
1783 except:
1784 reporter.errorXcpt('failed to set the VRAM size of "%s" to %s' % (self.sName, cMB));
1785 fRc = False;
1786 else:
1787 reporter.log('set the VRAM size of "%s" to %s' % (self.sName, cMB));
1788 self.oTstDrv.processPendingEvents();
1789 return fRc;
1790
1791 def setVideoControllerType(self, eControllerType):
1792 """
1793 Set the video controller type of the VM.
1794 Returns True on success and False on failure. Error information is logged.
1795 """
1796 fRc = True;
1797 try:
1798 if self.fpApiVer >= 6.1 and hasattr(self.o.machine, 'graphicsAdapter'):
1799 self.o.machine.graphicsAdapter.graphicsControllerType = eControllerType;
1800 else:
1801 self.o.machine.graphicsControllerType = eControllerType;
1802 except:
1803 reporter.errorXcpt('failed to set the video controller type of "%s" to %s' % (self.sName, eControllerType));
1804 fRc = False;
1805 else:
1806 reporter.log('set the video controller type of "%s" to %s' % (self.sName, eControllerType));
1807 self.oTstDrv.processPendingEvents();
1808 return fRc;
1809
1810 def setAccelerate3DEnabled(self, fEnabled):
1811 """
1812 Set the video controller type of the VM.
1813 Returns True on success and False on failure. Error information is logged.
1814 """
1815 fRc = True;
1816 try:
1817 if self.fpApiVer >= 6.1 and hasattr(self.o.machine, 'graphicsAdapter'):
1818 self.o.machine.graphicsAdapter.accelerate3DEnabled = fEnabled;
1819 else:
1820 self.o.machine.accelerate3DEnabled = fEnabled;
1821 except:
1822 reporter.errorXcpt('failed to set the accelerate3DEnabled of "%s" to %s' % (self.sName, fEnabled));
1823 fRc = False;
1824 else:
1825 reporter.log('set the accelerate3DEnabled of "%s" to %s' % (self.sName, fEnabled));
1826 self.oTstDrv.processPendingEvents();
1827 return fRc;
1828
1829 def setCpuCount(self, cCpus):
1830 """
1831 Set the number of CPUs.
1832 Returns True on success and False on failure. Error information is logged.
1833 """
1834 fRc = True;
1835 try:
1836 self.o.machine.CPUCount = cCpus;
1837 except:
1838 reporter.errorXcpt('failed to set the CPU count of "%s" to %s' % (self.sName, cCpus));
1839 fRc = False;
1840 else:
1841 reporter.log('set the CPU count of "%s" to %s' % (self.sName, cCpus));
1842 self.oTstDrv.processPendingEvents();
1843 return fRc;
1844
1845 def getCpuCount(self):
1846 """
1847 Returns the number of CPUs.
1848 Returns the number of CPUs on success and 0 on failure. Error information is logged.
1849 """
1850 cCpus = 0;
1851 try:
1852 cCpus = self.o.machine.CPUCount;
1853 except:
1854 reporter.errorXcpt('failed to get the CPU count of "%s"' % (self.sName,));
1855
1856 self.oTstDrv.processPendingEvents();
1857 return cCpus;
1858
1859 def ensureControllerAttached(self, sController):
1860 """
1861 Makes sure the specified controller is attached to the VM, attaching it
1862 if necessary.
1863 """
1864 try:
1865 try:
1866 self.o.machine.getStorageControllerByName(sController);
1867 except:
1868 (eBus, eType) = _ControllerNameToBusAndType(sController);
1869 try:
1870 oCtl = self.o.machine.addStorageController(sController, eBus);
1871 except:
1872 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, eBus, self.sName) );
1873 return False;
1874 try:
1875 oCtl.controllerType = eType;
1876 reporter.log('added storage controller "%s" (bus %s, type %s) to %s'
1877 % (sController, eBus, eType, self.sName));
1878 except:
1879 reporter.errorXcpt('controllerType = %s on ("%s" / %s) failed on "%s"'
1880 % (eType, sController, eBus, self.sName) );
1881 return False;
1882 finally:
1883 self.oTstDrv.processPendingEvents();
1884 return True;
1885
1886 def setStorageControllerPortCount(self, sController, iPortCount):
1887 """
1888 Set maximum ports count for storage controller
1889 """
1890 try:
1891 oCtl = self.o.machine.getStorageControllerByName(sController)
1892 oCtl.portCount = iPortCount
1893 self.oTstDrv.processPendingEvents()
1894 reporter.log('set controller "%s" port count to value %d' % (sController, iPortCount))
1895 return True
1896 except:
1897 reporter.log('unable to set storage controller "%s" ports count to %d' % (sController, iPortCount))
1898
1899 return False
1900
1901 def setStorageControllerHostIoCache(self, sController, fUseHostIoCache):
1902 """
1903 Set maximum ports count for storage controller
1904 """
1905 try:
1906 oCtl = self.o.machine.getStorageControllerByName(sController);
1907 oCtl.useHostIOCache = fUseHostIoCache;
1908 self.oTstDrv.processPendingEvents();
1909 reporter.log('set controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1910 return True;
1911 except:
1912 reporter.log('unable to set storage controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1913
1914 return False;
1915
1916 def setBootOrder(self, iPosition, eType):
1917 """
1918 Set guest boot order type
1919 @param iPosition boot order position
1920 @param eType device type (vboxcon.DeviceType_HardDisk,
1921 vboxcon.DeviceType_DVD, vboxcon.DeviceType_Floppy)
1922 """
1923 try:
1924 self.o.machine.setBootOrder(iPosition, eType)
1925 except:
1926 return reporter.errorXcpt('Unable to set boot order.')
1927
1928 reporter.log('Set boot order [%d] for device %s' % (iPosition, str(eType)))
1929 self.oTstDrv.processPendingEvents();
1930
1931 return True
1932
1933 def setStorageControllerType(self, eType, sController = "IDE Controller"):
1934 """
1935 Similar to ensureControllerAttached, except it will change the type.
1936 """
1937 try:
1938 oCtl = self.o.machine.getStorageControllerByName(sController);
1939 except:
1940 (eBus, _) = _ControllerNameToBusAndType(sController);
1941 try:
1942 oCtl = self.o.machine.addStorageController(sController, eBus);
1943 reporter.log('added storage controller "%s" (bus %s) to %s' % (sController, eBus, self.sName));
1944 except:
1945 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, eBus, self.sName) );
1946 return False;
1947 try:
1948 oCtl.controllerType = eType;
1949 except:
1950 reporter.errorXcpt('failed to set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1951 return False;
1952 reporter.log('set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1953 self.oTstDrv.processPendingEvents();
1954 return True;
1955
1956 def attachDvd(self, sImage = None, sController = "IDE Controller", iPort = 1, iDevice = 0):
1957 """
1958 Attaches a DVD drive to a VM, optionally with an ISO inserted.
1959 Returns True on success and False on failure. Error information is logged.
1960 """
1961 # Input validation.
1962 if sImage is not None and not self.oTstDrv.isResourceFile(sImage)\
1963 and not os.path.isabs(sImage): ## fixme - testsuite unzip ++
1964 reporter.fatal('"%s" is not in the resource set' % (sImage));
1965 return None;
1966
1967 if not self.ensureControllerAttached(sController):
1968 return False;
1969
1970 # Find/register the image if specified.
1971 oImage = None;
1972 sImageUuid = "";
1973 if sImage is not None:
1974 sFullName = self.oTstDrv.getFullResourceName(sImage)
1975 try:
1976 oImage = self.oVBox.findDVDImage(sFullName);
1977 except:
1978 try:
1979 if self.fpApiVer >= 4.1:
1980 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly, False);
1981 elif self.fpApiVer >= 4.0:
1982 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly);
1983 else:
1984 oImage = self.oVBox.openDVDImage(sFullName, "");
1985 except vbox.ComException as oXcpt:
1986 if oXcpt.errno != -1:
1987 reporter.errorXcpt('failed to open DVD image "%s" xxx' % (sFullName));
1988 else:
1989 reporter.errorXcpt('failed to open DVD image "%s" yyy' % (sFullName));
1990 return False;
1991 except:
1992 reporter.errorXcpt('failed to open DVD image "%s"' % (sFullName));
1993 return False;
1994 try:
1995 sImageUuid = oImage.id;
1996 except:
1997 reporter.errorXcpt('failed to get the UUID of "%s"' % (sFullName));
1998 return False;
1999
2000 # Attach the DVD.
2001 fRc = True;
2002 try:
2003 if self.fpApiVer >= 4.0:
2004 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, oImage);
2005 else:
2006 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, sImageUuid);
2007 except:
2008 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
2009 % (sController, iPort, iDevice, sImageUuid, self.sName) );
2010 fRc = False;
2011 else:
2012 reporter.log('attached DVD to %s, image="%s"' % (self.sName, sImage));
2013 self.oTstDrv.processPendingEvents();
2014 return fRc;
2015
2016 def attachHd(self, sHd, sController = "IDE Controller", iPort = 0, iDevice = 0, fImmutable = True, fForceResource = True):
2017 """
2018 Attaches a HD to a VM.
2019 Returns True on success and False on failure. Error information is logged.
2020 """
2021 # Input validation.
2022 if fForceResource and not self.oTstDrv.isResourceFile(sHd):
2023 reporter.fatal('"%s" is not in the resource set' % (sHd,));
2024 return None;
2025
2026 if not self.ensureControllerAttached(sController):
2027 return False;
2028
2029 # Find the HD, registering it if necessary (as immutable).
2030 if fForceResource:
2031 sFullName = self.oTstDrv.getFullResourceName(sHd);
2032 else:
2033 sFullName = sHd;
2034 try:
2035 oHd = self.oVBox.findHardDisk(sFullName);
2036 except:
2037 try:
2038 if self.fpApiVer >= 4.1:
2039 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
2040 elif self.fpApiVer >= 4.0:
2041 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
2042 else:
2043 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
2044 except:
2045 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
2046 return False;
2047 try:
2048 if fImmutable:
2049 oHd.type = vboxcon.MediumType_Immutable;
2050 else:
2051 oHd.type = vboxcon.MediumType_Normal;
2052 except:
2053 if fImmutable:
2054 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
2055 else:
2056 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
2057 return False;
2058
2059 # Attach it.
2060 fRc = True;
2061 try:
2062 if self.fpApiVer >= 4.0:
2063 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
2064 else:
2065 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
2066 except:
2067 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
2068 % (sController, iPort, iDevice, oHd.id, self.sName) );
2069 fRc = False;
2070 else:
2071 reporter.log('attached "%s" to %s' % (sHd, self.sName));
2072 self.oTstDrv.processPendingEvents();
2073 return fRc;
2074
2075 def createBaseHd(self, sHd, sFmt = "VDI", cb = 10*1024*1024*1024, cMsTimeout = 60000, tMediumVariant = None):
2076 """
2077 Creates a base HD.
2078 Returns Medium object on success and None on failure. Error information is logged.
2079 """
2080 if tMediumVariant is None:
2081 tMediumVariant = (vboxcon.MediumVariant_Standard, );
2082
2083 try:
2084 if self.fpApiVer >= 5.0:
2085 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
2086 else:
2087 oHd = self.oVBox.createHardDisk(sFmt, sHd);
2088 oProgressXpcom = oHd.createBaseStorage(cb, tMediumVariant);
2089 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create base disk %s' % (sHd));
2090 oProgress.wait(cMsTimeout);
2091 oProgress.logResult();
2092 except:
2093 reporter.errorXcpt('failed to create base hd "%s"' % (sHd));
2094 oHd = None
2095
2096 return oHd;
2097
2098 def createDiffHd(self, oParentHd, sHd, sFmt = "VDI"):
2099 """
2100 Creates a differencing HD.
2101 Returns Medium object on success and None on failure. Error information is logged.
2102 """
2103 # Detect the proper format if requested
2104 if sFmt is None:
2105 try:
2106 oHdFmt = oParentHd.mediumFormat;
2107 lstCaps = self.oVBoxMgr.getArray(oHdFmt, 'capabilities');
2108 if vboxcon.MediumFormatCapabilities_Differencing in lstCaps:
2109 sFmt = oHdFmt.id;
2110 else:
2111 sFmt = 'VDI';
2112 except:
2113 reporter.errorXcpt('failed to get preferred diff format for "%s"' % (sHd));
2114 return None;
2115 try:
2116 if self.fpApiVer >= 5.0:
2117 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
2118 else:
2119 oHd = self.oVBox.createHardDisk(sFmt, sHd);
2120 oProgressXpcom = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
2121 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
2122 oProgress.wait();
2123 oProgress.logResult();
2124 except:
2125 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
2126 oHd = None
2127
2128 return oHd;
2129
2130 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, # pylint: disable=too-many-arguments
2131 iPort = 0, iDevice = 0, fImmutable = True, cMsTimeout = 60000, tMediumVariant = None):
2132 """
2133 Creates and attaches a HD to a VM.
2134 Returns True on success and False on failure. Error information is logged.
2135 """
2136 if not self.ensureControllerAttached(sController):
2137 return False;
2138
2139 oHd = self.createBaseHd(sHd, sFmt, cb, cMsTimeout, tMediumVariant);
2140 if oHd is None:
2141 return False;
2142
2143 fRc = True;
2144 try:
2145 if fImmutable:
2146 oHd.type = vboxcon.MediumType_Immutable;
2147 else:
2148 oHd.type = vboxcon.MediumType_Normal;
2149 except:
2150 if fImmutable:
2151 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
2152 else:
2153 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
2154 fRc = False;
2155
2156 # Attach it.
2157 if fRc is True:
2158 try:
2159 if self.fpApiVer >= 4.0:
2160 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
2161 else:
2162 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
2163 except:
2164 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
2165 % (sController, iPort, iDevice, oHd.id, self.sName) );
2166 fRc = False;
2167 else:
2168 reporter.log('attached "%s" to %s' % (sHd, self.sName));
2169
2170 # Delete disk in case of an error
2171 if fRc is False:
2172 try:
2173 oProgressCom = oHd.deleteStorage();
2174 except:
2175 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
2176 else:
2177 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
2178 oProgress.wait();
2179 oProgress.logResult();
2180
2181 self.oTstDrv.processPendingEvents();
2182 return fRc;
2183
2184 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
2185 """
2186 Detaches a HD, if attached, and returns a reference to it (IMedium).
2187
2188 In order to delete the detached medium, the caller must first save
2189 the changes made in this session.
2190
2191 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
2192 your standard success indicator. Error information is logged.
2193 """
2194
2195 # What's attached?
2196 try:
2197 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
2198 except:
2199 if self.oVBoxMgr.xcptIsOurXcptKind() \
2200 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
2201 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
2202 return (True, None);
2203 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
2204 % (iPort, iDevice, sController)), None);
2205 # Detach it.
2206 try:
2207 self.o.machine.detachDevice(sController, iPort, iDevice);
2208 except:
2209 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
2210 % (sController, iPort, iDevice, self.sName) ), None);
2211 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
2212 return (True, oHd);
2213
2214 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
2215 """
2216 Attaches a floppy image to a VM.
2217 Returns True on success and False on failure. Error information is logged.
2218 """
2219 # Input validation.
2220 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
2221 ##if not self.oTstDrv.isResourceFile(sFloppy):
2222 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
2223 ## return None;
2224
2225 if not self.ensureControllerAttached(sController):
2226 return False;
2227
2228 # Find the floppy image, registering it if necessary (as immutable).
2229 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
2230 try:
2231 oFloppy = self.oVBox.findFloppyImage(sFullName);
2232 except:
2233 try:
2234 if self.fpApiVer >= 4.1:
2235 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
2236 elif self.fpApiVer >= 4.0:
2237 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
2238 else:
2239 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
2240 except:
2241 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
2242 return False;
2243 ## @todo the following works but causes trouble below (asserts in main).
2244 #try:
2245 # oFloppy.type = vboxcon.MediumType_Immutable;
2246 #except:
2247 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
2248 # return False;
2249
2250 # Attach it.
2251 fRc = True;
2252 try:
2253 if self.fpApiVer >= 4.0:
2254 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
2255 else:
2256 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
2257 except:
2258 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
2259 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
2260 fRc = False;
2261 else:
2262 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
2263 self.oTstDrv.processPendingEvents();
2264 return fRc;
2265
2266 def setupNic(self, sType, sXXX):
2267 """
2268 Sets up a NIC to a VM.
2269 Returns True on success and False on failure. Error information is logged.
2270 """
2271 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
2272 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
2273 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
2274 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
2275 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
2276 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
2277 else:
2278 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
2279 return False;
2280 ## @todo Implement me!
2281 if enmType is not None: pass
2282 return True;
2283
2284 def setupAudio(self, eAudioControllerType, fEnable = True, fEnableIn = False, fEnableOut = True, eAudioDriverType = None):
2285 """
2286 Sets up audio.
2287
2288 :param eAudioControllerType: The audio controller type (vboxcon.AudioControllerType_XXX).
2289 :param fEnable: Whether to enable or disable the audio controller (default enable).
2290 :param fEnableIn: Whether to enable or disable audio input (default disable).
2291 :param fEnableOut: Whether to enable or disable audio output (default enable).
2292 :param eAudioDriverType: The audio driver type (vboxcon.AudioDriverType_XXX), picks something suitable
2293 if None is passed (default).
2294 """
2295 try:
2296 if self.fpApiVer >= 7.0:
2297 oAdapter = self.o.machine.audioSettings.adapter;
2298 else:
2299 oAdapter = self.o.machine.audioAdapter;
2300 except: return reporter.errorXcpt('Failed to get the audio adapter.');
2301
2302 try: oAdapter.audioController = eAudioControllerType;
2303 except: return reporter.errorXcpt('Failed to set the audio controller to %s.' % (eAudioControllerType,));
2304
2305 if eAudioDriverType is None:
2306 sHost = utils.getHostOs()
2307 if sHost == 'darwin': eAudioDriverType = vboxcon.AudioDriverType_CoreAudio;
2308 elif sHost == 'win': eAudioDriverType = vboxcon.AudioDriverType_DirectSound;
2309 elif sHost == 'linux': eAudioDriverType = vboxcon.AudioDriverType_Pulse;
2310 elif sHost == 'solaris': eAudioDriverType = vboxcon.AudioDriverType_OSS;
2311 else:
2312 reporter.error('PORTME: Do not know which audio driver to pick for: %s!' % (sHost,));
2313 eAudioDriverType = vboxcon.AudioDriverType_Null;
2314
2315 try: oAdapter.audioDriver = eAudioDriverType;
2316 except: return reporter.errorXcpt('Failed to set the audio driver to %s.' % (eAudioDriverType,))
2317
2318 try: oAdapter.enabled = fEnable;
2319 except: return reporter.errorXcpt('Failed to set the "enabled" property to %s.' % (fEnable,));
2320
2321 try: oAdapter.enabledIn = fEnableIn;
2322 except: return reporter.errorXcpt('Failed to set the "enabledIn" property to %s.' % (fEnable,));
2323
2324 try: oAdapter.enabledOut = fEnableOut;
2325 except: return reporter.errorXcpt('Failed to set the "enabledOut" property to %s.' % (fEnable,));
2326
2327 reporter.log('set audio adapter type to %d, driver to %d, and enabled to %s (input is %s, output is %s)'
2328 % (eAudioControllerType, eAudioDriverType, fEnable, fEnableIn, fEnableOut,));
2329 self.oTstDrv.processPendingEvents();
2330 return True;
2331
2332 def setupPreferredConfig(self): # pylint: disable=too-many-locals
2333 """
2334 Configures the VM according to the preferences of the guest type.
2335 """
2336 try:
2337 sOsTypeId = self.o.machine.OSTypeId;
2338 except:
2339 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2340 return False;
2341
2342 try:
2343 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2344 except:
2345 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2346 return False;
2347
2348 # get the attributes.
2349 try:
2350 #sFamilyId = oOsType.familyId;
2351 #f64Bit = oOsType.is64Bit;
2352 fIoApic = oOsType.recommendedIOAPIC;
2353 fVirtEx = oOsType.recommendedVirtEx;
2354 cMBRam = oOsType.recommendedRAM;
2355 cMBVRam = oOsType.recommendedVRAM;
2356 #cMBHdd = oOsType.recommendedHDD;
2357 eNicType = oOsType.adapterType;
2358 if self.fpApiVer >= 3.2:
2359 if self.fpApiVer >= 4.2:
2360 fPae = oOsType.recommendedPAE;
2361 fUsbHid = oOsType.recommendedUSBHID;
2362 fHpet = oOsType.recommendedHPET;
2363 eStorCtlType = oOsType.recommendedHDStorageController;
2364 else:
2365 fPae = oOsType.recommendedPae;
2366 fUsbHid = oOsType.recommendedUsbHid;
2367 fHpet = oOsType.recommendedHpet;
2368 eStorCtlType = oOsType.recommendedHdStorageController;
2369 eFirmwareType = oOsType.recommendedFirmware;
2370 else:
2371 fPae = False;
2372 fUsbHid = False;
2373 fHpet = False;
2374 eFirmwareType = -1;
2375 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
2376 if self.fpApiVer >= 4.0:
2377 eAudioCtlType = oOsType.recommendedAudioController;
2378 except:
2379 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
2380 self.oTstDrv.processPendingEvents();
2381 return False;
2382 self.oTstDrv.processPendingEvents();
2383
2384 # Do the setting. Continue applying settings on error in case the
2385 # caller ignores the return code
2386 fRc = True;
2387 if not self.enableIoApic(fIoApic): fRc = False;
2388 if not self.enableVirtEx(fVirtEx): fRc = False;
2389 if not self.enablePae(fPae): fRc = False;
2390 if not self.setRamSize(cMBRam): fRc = False;
2391 if not self.setVRamSize(cMBVRam): fRc = False;
2392 if not self.setNicType(eNicType, 0): fRc = False;
2393 if self.fpApiVer >= 3.2:
2394 if not self.setFirmwareType(eFirmwareType): fRc = False;
2395 if not self.enableUsbHid(fUsbHid): fRc = False;
2396 if not self.enableHpet(fHpet): fRc = False;
2397 if eStorCtlType in (vboxcon.StorageControllerType_PIIX3,
2398 vboxcon.StorageControllerType_PIIX4,
2399 vboxcon.StorageControllerType_ICH6,):
2400 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
2401 fRc = False;
2402 if self.fpApiVer >= 4.0:
2403 if not self.setupAudio(eAudioCtlType): fRc = False;
2404
2405 return fRc;
2406
2407 def addUsbDeviceFilter(self, sName, sVendorId = None, sProductId = None, sRevision = None, # pylint: disable=too-many-arguments
2408 sManufacturer = None, sProduct = None, sSerialNumber = None,
2409 sPort = None, sRemote = None):
2410 """
2411 Creates a USB device filter and inserts it into the VM.
2412 Returns True on success.
2413 Returns False on failure (logged).
2414 """
2415 fRc = True;
2416
2417 try:
2418 oUsbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
2419 oUsbDevFilter.active = True;
2420 if sVendorId is not None:
2421 oUsbDevFilter.vendorId = sVendorId;
2422 if sProductId is not None:
2423 oUsbDevFilter.productId = sProductId;
2424 if sRevision is not None:
2425 oUsbDevFilter.revision = sRevision;
2426 if sManufacturer is not None:
2427 oUsbDevFilter.manufacturer = sManufacturer;
2428 if sProduct is not None:
2429 oUsbDevFilter.product = sProduct;
2430 if sSerialNumber is not None:
2431 oUsbDevFilter.serialnumber = sSerialNumber;
2432 if sPort is not None:
2433 oUsbDevFilter.port = sPort;
2434 if sRemote is not None:
2435 oUsbDevFilter.remote = sRemote;
2436 try:
2437 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, oUsbDevFilter);
2438 except:
2439 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
2440 % (0, self.sName) );
2441 fRc = False;
2442 else:
2443 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
2444 except:
2445 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
2446 % (sName, self.sName) );
2447 fRc = False;
2448 return fRc;
2449
2450 def getGuestPropertyValue(self, sName):
2451 """
2452 Gets a guest property value.
2453 Returns the value on success, None on failure (logged).
2454 """
2455 try:
2456 sValue = self.o.machine.getGuestPropertyValue(sName);
2457 except:
2458 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2459 return None;
2460 return sValue;
2461
2462 def setGuestPropertyValue(self, sName, sValue):
2463 """
2464 Sets a guest property value.
2465 Returns the True on success, False on failure (logged).
2466 """
2467 try:
2468 self.o.machine.setGuestPropertyValue(sName, sValue);
2469 except:
2470 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2471 return False;
2472 return True;
2473
2474 def delGuestPropertyValue(self, sName):
2475 """
2476 Deletes a guest property value.
2477 Returns the True on success, False on failure (logged).
2478 """
2479 try:
2480 oMachine = self.o.machine;
2481 if self.fpApiVer >= 4.2:
2482 oMachine.deleteGuestProperty(sName);
2483 else:
2484 oMachine.setGuestPropertyValue(sName, '');
2485 except:
2486 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2487 return False;
2488 return True;
2489
2490 def setExtraData(self, sKey, sValue):
2491 """
2492 Sets extra data.
2493 Returns the True on success, False on failure (logged).
2494 """
2495 try:
2496 self.o.machine.setExtraData(sKey, sValue);
2497 except:
2498 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2499 return False;
2500 return True;
2501
2502 def getExtraData(self, sKey):
2503 """
2504 Gets extra data.
2505 Returns value on success, None on failure.
2506 """
2507 try:
2508 sValue = self.o.machine.getExtraData(sKey)
2509 except:
2510 reporter.errorXcpt('IMachine::getExtraData("%s") failed' % (sKey,))
2511 return None
2512 return sValue
2513
2514 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2515 """
2516 Sets up the teleporter for the VM.
2517 Returns True on success, False on failure (logged).
2518 """
2519 try:
2520 self.o.machine.teleporterAddress = sAddress;
2521 self.o.machine.teleporterPort = uPort;
2522 self.o.machine.teleporterPassword = sPassword;
2523 self.o.machine.teleporterEnabled = fEnabled;
2524 except:
2525 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2526 return False;
2527 return True;
2528
2529 def enableTeleporter(self, fEnable=True):
2530 """
2531 Enables or disables the teleporter of the VM.
2532 Returns True on success, False on failure (logged).
2533 """
2534 try:
2535 self.o.machine.teleporterEnabled = fEnable;
2536 except:
2537 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2538 return False;
2539 return True;
2540
2541 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2542 """
2543 Wrapper around the IConsole::teleport() method.
2544 Returns a progress object on success, None on failure (logged).
2545 """
2546 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2547 try:
2548 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2549 except:
2550 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2551 return None;
2552 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2553
2554 def getOsType(self):
2555 """
2556 Gets the IGuestOSType interface for the machine.
2557
2558 return IGuestOSType interface on success, None + errorXcpt on failure.
2559 No exceptions raised.
2560 """
2561 try:
2562 sOsTypeId = self.o.machine.OSTypeId;
2563 except:
2564 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2565 return None;
2566
2567 try:
2568 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2569 except:
2570 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2571 return None;
2572
2573 return oOsType;
2574
2575 def setOsType(self, sNewTypeId):
2576 """
2577 Changes the OS type.
2578
2579 returns True on success, False + errorXcpt on failure.
2580 No exceptions raised.
2581 """
2582 try:
2583 self.o.machine.OSTypeId = sNewTypeId;
2584 except:
2585 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2586 return False;
2587 return True;
2588
2589
2590 def setParavirtProvider(self, iProvider):
2591 """
2592 Sets a paravirtualisation provider.
2593 Returns the True on success, False on failure (logged).
2594 """
2595 try:
2596 self.o.machine.paravirtProvider = iProvider
2597 except:
2598 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2599 return False;
2600 return True;
2601
2602
2603 def setupSerialToRawFile(self, iSerialPort, sRawFile):
2604 """
2605 Enables the given serial port (zero based) and redirects it to sRawFile.
2606 Returns the True on success, False on failure (logged).
2607 """
2608 try:
2609 oPort = self.o.machine.getSerialPort(iSerialPort);
2610 except:
2611 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2612 else:
2613 try:
2614 oPort.path = sRawFile;
2615 except:
2616 fRc = reporter.errorXcpt('failed to set the "path" property on serial port #%u to "%s"'
2617 % (iSerialPort, sRawFile));
2618 else:
2619 try:
2620 oPort.hostMode = vboxcon.PortMode_RawFile;
2621 except:
2622 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_RawFile'
2623 % (iSerialPort,));
2624 else:
2625 try:
2626 oPort.enabled = True;
2627 except:
2628 fRc = reporter.errorXcpt('failed to set the "enable" property on serial port #%u to True'
2629 % (iSerialPort,));
2630 else:
2631 reporter.log('set SerialPort[%s].enabled/hostMode/path=True/RawFile/%s' % (iSerialPort, sRawFile,));
2632 fRc = True;
2633 self.oTstDrv.processPendingEvents();
2634 return fRc;
2635
2636
2637 def enableSerialPort(self, iSerialPort):
2638 """
2639 Enables the given serial port setting the initial port mode to disconnected.
2640 """
2641 try:
2642 oPort = self.o.machine.getSerialPort(iSerialPort);
2643 except:
2644 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2645 else:
2646 try:
2647 oPort.hostMode = vboxcon.PortMode_Disconnected;
2648 except:
2649 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_Disconnected'
2650 % (iSerialPort,));
2651 else:
2652 try:
2653 oPort.enabled = True;
2654 except:
2655 fRc = reporter.errorXcpt('failed to set the "enable" property on serial port #%u to True'
2656 % (iSerialPort,));
2657 else:
2658 reporter.log('set SerialPort[%s].enabled/hostMode/=True/Disconnected' % (iSerialPort,));
2659 fRc = True;
2660 self.oTstDrv.processPendingEvents();
2661 return fRc;
2662
2663
2664 def changeSerialPortAttachment(self, iSerialPort, ePortMode, sPath, fServer):
2665 """
2666 Changes the attachment of the given serial port to the attachment config given.
2667 """
2668 try:
2669 oPort = self.o.machine.getSerialPort(iSerialPort);
2670 except:
2671 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2672 else:
2673 try:
2674 # Change port mode to disconnected first so changes get picked up by a potentially running VM.
2675 oPort.hostMode = vboxcon.PortMode_Disconnected;
2676 except:
2677 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_Disconnected'
2678 % (iSerialPort,));
2679 else:
2680 try:
2681 oPort.path = sPath;
2682 oPort.server = fServer;
2683 oPort.hostMode = ePortMode;
2684 except:
2685 fRc = reporter.errorXcpt('failed to configure the serial port');
2686 else:
2687 reporter.log('set SerialPort[%s].hostMode/path/server=%s/%s/%s'
2688 % (iSerialPort, ePortMode, sPath, fServer));
2689 fRc = True;
2690 self.oTstDrv.processPendingEvents();
2691 return fRc;
2692
2693 #
2694 # IConsole wrappers.
2695 #
2696
2697 def powerOff(self, fFudgeOnFailure = True):
2698 """
2699 Powers off the VM.
2700
2701 Returns True on success.
2702 Returns False on IConsole::powerDown() failure.
2703 Returns None if the progress object returns failure.
2704 """
2705 #
2706 # Deregister event handler before we power off the VM, otherwise we're
2707 # racing for VM process termination and cause misleading spurious
2708 # error messages in the event handling code, because the event objects
2709 # disappear.
2710 #
2711 # Note! Doing this before powerDown to try prevent numerous smoketest
2712 # timeouts on XPCOM hosts.
2713 #
2714 self.deregisterEventHandlerForTask();
2715
2716
2717 # Try power if off.
2718 try:
2719 oProgress = self.o.console.powerDown();
2720 except:
2721 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2722 if fFudgeOnFailure:
2723 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2724 self.waitForTask(1000); # fudge
2725 return False;
2726
2727 # Wait on power off operation to complete.
2728 rc = self.oTstDrv.waitOnProgress(oProgress);
2729 if rc < 0:
2730 self.close();
2731 if fFudgeOnFailure:
2732 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2733 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2734 return None;
2735
2736 # Wait for the VM to really power off or we'll fail to open a new session to it.
2737 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2738 return self.waitForTask(30 * 1000); # fudge
2739
2740 def saveState(self, fPause = True):
2741 """
2742 Saves state of the VM.
2743
2744 Returns True on success.
2745 Returns False on IConsole::saveState() failure.
2746 Returns None if the progress object returns Failure.
2747 """
2748
2749 if fPause is True \
2750 and self.oVM.state is vboxcon.MachineState_Running:
2751 self.o.console.pause();
2752 if self.oVM.state is not vboxcon.MachineState_Paused:
2753 reporter.error('pause for "%s" failed' % (self.sName));
2754 # Try saving state.
2755 try:
2756 if self.fpApiVer >= 5.0:
2757 oProgress = self.o.machine.saveState()
2758 else:
2759 oProgress = self.o.console.saveState()
2760 except:
2761 reporter.logXcpt('IMachine::saveState failed on %s' % (self.sName));
2762 return False;
2763
2764 # Wait for saving state operation to complete.
2765 rc = self.oTstDrv.waitOnProgress(oProgress);
2766 if rc < 0:
2767 self.close();
2768 return None;
2769
2770 # Wait for the VM to really terminate or we'll fail to open a new session to it.
2771 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2772 return self.waitForTask(30 * 1000); # fudge
2773
2774 def discardSavedState(self, fRemove = True):
2775 """
2776 Discards saved state of the VM.
2777
2778 Returns True on success.
2779 Returns False on IConsole::discardSaveState() failure.
2780 """
2781
2782 try:
2783 if self.fpApiVer >= 5.0:
2784 self.o.machine.discardSavedState(fRemove)
2785 else:
2786 self.o.console.discardSavedState(fRemove)
2787 except:
2788 reporter.logXcpt('IMachine::discardSavedState failed on %s' % (self.sName))
2789 return False
2790 return True
2791
2792 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2793 """
2794 Restores the given snapshot.
2795
2796 Returns True on success.
2797 Returns False on IMachine::restoreSnapshot() failure.
2798 Returns None if the progress object returns failure.
2799 """
2800 try:
2801 if self.fpApiVer >= 5.0:
2802 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2803 else:
2804 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2805 except:
2806 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2807 if fFudgeOnFailure:
2808 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2809 self.waitForTask(1000); # fudge
2810 return False;
2811
2812 rc = self.oTstDrv.waitOnProgress(oProgress);
2813 if rc < 0:
2814 self.close();
2815 if fFudgeOnFailure:
2816 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2817 return None;
2818
2819 return self.waitForTask(30 * 1000);
2820
2821 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2822 """
2823 Deletes the given snapshot merging the diff image into the base.
2824
2825 Returns True on success.
2826 Returns False on IMachine::deleteSnapshot() failure.
2827 """
2828 try:
2829 if self.fpApiVer >= 5.0:
2830 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2831 else:
2832 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2833 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2834 oProgress.wait(cMsTimeout);
2835 oProgress.logResult();
2836 except:
2837 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2838 if fFudgeOnFailure:
2839 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2840 self.waitForTask(1000); # fudge
2841 return False;
2842
2843 return True;
2844
2845 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2846 """
2847 Takes a snapshot with the given name
2848
2849 Returns True on success.
2850 Returns False on IMachine::takeSnapshot() or VM state change failure.
2851 """
2852 try:
2853 if fPause is True \
2854 and self.oVM.state is vboxcon.MachineState_Running:
2855 self.o.console.pause();
2856 if self.fpApiVer >= 5.0:
2857 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2858 else:
2859 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2860 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2861 oProgress.wait(cMsTimeout);
2862 oProgress.logResult();
2863 except:
2864 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2865 if fFudgeOnFailure:
2866 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2867 self.waitForTask(1000); # fudge
2868 return False;
2869
2870 if fPause is True \
2871 and self.oVM.state is vboxcon.MachineState_Paused:
2872 self.o.console.resume();
2873
2874 return True;
2875
2876 def findSnapshot(self, sName):
2877 """
2878 Returns the snapshot object with the given name
2879
2880 Returns snapshot object on success.
2881 Returns None if there is no snapshot with the given name.
2882 """
2883 return self.oVM.findSnapshot(sName);
2884
2885 def takeScreenshot(self, sFilename, iScreenId=0):
2886 """
2887 Take screenshot from the given display and save it to specified file.
2888
2889 Returns True on success
2890 Returns False on failure.
2891 """
2892 try:
2893 if self.fpApiVer >= 5.0:
2894 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2895 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2896 vboxcon.BitmapFormat_PNG)
2897 else:
2898 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2899 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2900 except:
2901 reporter.logXcpt("Unable to take screenshot")
2902 return False
2903
2904 with open(sFilename, 'wb') as oFile: # pylint: disable=unspecified-encoding
2905 oFile.write(aPngData)
2906
2907 return True
2908
2909 def attachUsbDevice(self, sUuid, sCaptureFilename = None):
2910 """
2911 Attach given USB device UUID to the VM.
2912
2913 Returns True on success
2914 Returns False on failure.
2915 """
2916 fRc = True;
2917 try:
2918 if sCaptureFilename is None:
2919 self.o.console.attachUSBDevice(sUuid, '');
2920 else:
2921 self.o.console.attachUSBDevice(sUuid, sCaptureFilename);
2922 except:
2923 reporter.logXcpt('Unable to attach USB device %s' % (sUuid,));
2924 fRc = False;
2925
2926 return fRc;
2927
2928 def detachUsbDevice(self, sUuid):
2929 """
2930 Detach given USB device UUID from the VM.
2931
2932 Returns True on success
2933 Returns False on failure.
2934 """
2935 fRc = True;
2936 try:
2937 _ = self.o.console.detachUSBDevice(sUuid);
2938 except:
2939 reporter.logXcpt('Unable to detach USB device %s' % (sUuid,));
2940 fRc = False;
2941
2942 return fRc;
2943
2944
2945 #
2946 # IMachineDebugger wrappers.
2947 #
2948
2949 def queryOsKernelLog(self):
2950 """
2951 Tries to get the OS kernel log using the VM debugger interface.
2952
2953 Returns string containing the kernel log on success.
2954 Returns None on failure.
2955 """
2956 sOsKernelLog = None;
2957 try:
2958 self.o.console.debugger.loadPlugIn('all');
2959 except:
2960 reporter.logXcpt('Unable to load debugger plugins');
2961 else:
2962 try:
2963 sOsDetected = self.o.console.debugger.detectOS();
2964 except:
2965 reporter.logXcpt('Failed to detect the guest OS');
2966 else:
2967 try:
2968 sOsKernelLog = self.o.console.debugger.queryOSKernelLog(0);
2969 except:
2970 reporter.logXcpt('Unable to get the guest OS (%s) kernel log' % (sOsDetected,));
2971 return sOsKernelLog;
2972
2973 def queryDbgInfo(self, sItem, sArg = '', sDefault = None):
2974 """
2975 Simple wrapper around IMachineDebugger::info.
2976
2977 Returns string on success, sDefault on failure (logged).
2978 """
2979 try:
2980 return self.o.console.debugger.info(sItem, sArg);
2981 except:
2982 reporter.logXcpt('Unable to query "%s" with arg "%s"' % (sItem, sArg,));
2983 return sDefault;
2984
2985 def queryDbgInfoVgaText(self, sArg = 'all'):
2986 """
2987 Tries to get the 'info vgatext' output, provided we're in next mode.
2988
2989 Returns string containing text on success.
2990 Returns None on failure or not text mode.
2991 """
2992 sVgaText = None;
2993 try:
2994 sVgaText = self.o.console.debugger.info('vgatext', sArg);
2995 if sVgaText.startswith('Not in text mode!'):
2996 sVgaText = None;
2997 except:
2998 reporter.logXcpt('Unable to query vgatext with arg "%s"' % (sArg,));
2999 return sVgaText;
3000
3001 def queryDbgGuestStack(self, iCpu = 0):
3002 """
3003 Returns the guest stack for the given VCPU.
3004
3005 Returns string containing the guest stack for the selected VCPU on success.
3006 Returns None on failure.
3007 """
3008
3009 #
3010 # Load all plugins first and try to detect the OS so we can
3011 # get nicer stack traces.
3012 #
3013 try:
3014 self.o.console.debugger.loadPlugIn('all');
3015 except:
3016 reporter.logXcpt('Unable to load debugger plugins');
3017 else:
3018 try:
3019 sOsDetected = self.o.console.debugger.detectOS();
3020 _ = sOsDetected;
3021 except:
3022 reporter.logXcpt('Failed to detect the guest OS');
3023
3024 sGuestStack = None;
3025 try:
3026 sGuestStack = self.o.console.debugger.dumpGuestStack(iCpu);
3027 except:
3028 reporter.logXcpt('Unable to query guest stack for CPU %s' % (iCpu, ));
3029
3030 return sGuestStack;
3031
3032
3033 #
3034 # Other methods.
3035 #
3036
3037 def getPrimaryIp(self):
3038 """
3039 Tries to obtain the primary IP address of the guest via the guest
3040 properties.
3041
3042 Returns IP address on success.
3043 Returns empty string on failure.
3044 """
3045 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3046 if vbox.isIpAddrValid(sIpAddr):
3047 return sIpAddr;
3048 return '';
3049
3050 def getPid(self):
3051 """
3052 Gets the process ID for the direct session unless it's ourselves.
3053 """
3054 if self.uPid is None and self.o is not None and self.fRemoteSession:
3055 try:
3056 if self.fpApiVer >= 4.2:
3057 uPid = self.o.machine.sessionPID;
3058 else:
3059 uPid = self.o.machine.sessionPid;
3060 if uPid != os.getpid() and uPid != 0xffffffff:
3061 self.uPid = uPid;
3062 except Exception as oXcpt:
3063 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
3064 try:
3065 if self.fpApiVer >= 4.2:
3066 uPid = self.oVM.sessionPID;
3067 else:
3068 uPid = self.oVM.sessionPid;
3069 if uPid != os.getpid() and uPid != 0xffffffff:
3070 self.uPid = uPid;
3071 except:
3072 reporter.log2Xcpt();
3073 else:
3074 reporter.log2Xcpt();
3075 if self.uPid is not None:
3076 reporter.log2('getPid: %u' % (self.uPid,));
3077 self.fPidFile = self.oTstDrv.pidFileAdd(self.uPid, 'vm_%s' % (self.sName,), # Set-uid-to-root is similar to SUDO.
3078 fSudo = True);
3079 return self.uPid;
3080
3081 def addLogsToReport(self, cReleaseLogs = 1):
3082 """
3083 Retrieves and adds the release and debug logs to the test report.
3084 """
3085 fRc = True;
3086
3087 # Add each of the requested release logs to the report.
3088 for iLog in range(0, cReleaseLogs):
3089 try:
3090 if self.fpApiVer >= 3.2:
3091 sLogFile = self.oVM.queryLogFilename(iLog);
3092 elif iLog > 0:
3093 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
3094 else:
3095 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
3096 except:
3097 reporter.logXcpt('iLog=%s' % (iLog,));
3098 fRc = False;
3099 else:
3100 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
3101 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
3102 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
3103
3104 # Now for the hardened windows startup log.
3105 try:
3106 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxHardening.log');
3107 except:
3108 reporter.logXcpt();
3109 fRc = False;
3110 else:
3111 if os.path.isfile(sLogFile):
3112 reporter.addLogFile(sLogFile, 'log/release/vm', '%s hardening log' % (self.sName, ),
3113 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
3114
3115 # Now for the debug log.
3116 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
3117 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
3118 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
3119
3120 return fRc;
3121
3122 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
3123 """
3124 Create an instance of the given ConsoleEventHandlerBase sub-class and
3125 register it.
3126
3127 The new instance is returned on success. None is returned on error.
3128 """
3129
3130 # We need a console object.
3131 try:
3132 oConsole = self.o.console;
3133 except Exception as oXcpt:
3134 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
3135 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
3136 return None;
3137
3138 # Add the base class arguments.
3139 dArgsCopy = dArgs.copy() if dArgs is not None else {};
3140 dArgsCopy['oSession'] = self;
3141 dArgsCopy['oConsole'] = oConsole;
3142 sLogSuffix = 'on %s' % (self.sName,)
3143 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
3144 oConsole, 'IConsole', 'IConsoleCallback',
3145 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
3146
3147 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
3148 """
3149 Enables the testing part of the VMMDev.
3150
3151 Returns True on success and False on failure. Error information is logged.
3152 """
3153 fRc = True;
3154 try:
3155 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
3156 '1' if fEnabled else '');
3157 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
3158 '1' if fEnableMMIO and fEnabled else '');
3159 except:
3160 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
3161 fRc = False;
3162 else:
3163 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
3164 self.oTstDrv.processPendingEvents();
3165 return fRc;
3166
3167 #
3168 # Test eXecution Service methods.
3169 #
3170
3171 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, fNatForwardingForTxs = False):
3172 """
3173 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
3174 addresses are specified, we'll get the IP from the guest additions.
3175
3176 Returns a TxsConnectTask object on success, None + log on failure.
3177 """
3178 # If the VM is configured with a NAT interface, connect to local host.
3179 fReversedSetup = False;
3180 fUseNatForTxs = False;
3181 sMacAddr = None;
3182 oIDhcpServer = None;
3183 if sIpAddr is None:
3184 try:
3185 oNic = self.oVM.getNetworkAdapter(0);
3186 enmAttachmentType = oNic.attachmentType;
3187 if enmAttachmentType == vboxcon.NetworkAttachmentType_NAT:
3188 fUseNatForTxs = True;
3189 elif enmAttachmentType == vboxcon.NetworkAttachmentType_HostOnly and not sIpAddr:
3190 # Get the MAC address and find the DHCP server.
3191 sMacAddr = oNic.MACAddress;
3192 sHostOnlyNIC = oNic.hostOnlyInterface;
3193 oIHostOnlyIf = self.oVBox.host.findHostNetworkInterfaceByName(sHostOnlyNIC);
3194 sHostOnlyNet = oIHostOnlyIf.networkName;
3195 oIDhcpServer = self.oVBox.findDHCPServerByNetworkName(sHostOnlyNet);
3196 except:
3197 reporter.errorXcpt();
3198 return None;
3199
3200 if fUseNatForTxs:
3201 fReversedSetup = not fNatForwardingForTxs;
3202 sIpAddr = '127.0.0.1';
3203
3204 # Kick off the task.
3205 try:
3206 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, oIDhcpServer, fReversedSetup,
3207 fnProcessEvents = self.oTstDrv.processPendingEvents);
3208 except:
3209 reporter.errorXcpt();
3210 oTask = None;
3211 return oTask;
3212
3213 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
3214 """
3215 Attempts to connect to a TXS instance.
3216
3217 Returns True if a connection was established, False if not (only grave
3218 failures are logged as errors).
3219
3220 Note! The timeout is more of a guideline...
3221 """
3222
3223 if sHostname is None or sHostname.strip() == '':
3224 raise base.GenError('Empty sHostname is not implemented yet');
3225
3226 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
3227 cMsIdleFudge = cMsTimeout // 2,
3228 fnProcessEvents = self.oTstDrv.processPendingEvents);
3229 if oTxsSession is None:
3230 return False;
3231
3232 # Wait for the connect task to time out.
3233 self.oTstDrv.addTask(oTxsSession);
3234 self.oTstDrv.processPendingEvents();
3235 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
3236 self.oTstDrv.removeTask(oTxsSession);
3237 if oRc != oTxsSession:
3238 if oRc is not None:
3239 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
3240 self.oTstDrv.processPendingEvents();
3241 oTxsSession.cancelTask(); # this is synchronous
3242 return False;
3243
3244 # Check the status.
3245 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
3246 if not oTxsSession.isSuccess():
3247 return False;
3248
3249 reporter.log2('Disconnecting from TXS...');
3250 return oTxsSession.syncDisconnect();
3251
3252
3253
3254class TxsConnectTask(TdTaskBase):
3255 """
3256 Class that takes care of connecting to a VM.
3257 """
3258
3259 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
3260 """ Class for looking for IPv4 address changes on interface 0."""
3261 def __init__(self, dArgs):
3262 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs);
3263 self.oParentTask = dArgs['oParentTask'];
3264 self.sMachineId = dArgs['sMachineId'];
3265
3266 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags, fWasDeleted):
3267 """Look for IP address."""
3268 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags, fWasDeleted));
3269 if sMachineId == self.sMachineId \
3270 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
3271 oParentTask = self.oParentTask;
3272 if oParentTask:
3273 oParentTask._setIp(sValue); # pylint: disable=protected-access
3274
3275
3276 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, oIDhcpServer, fReversedSetup, fnProcessEvents = None):
3277 TdTaskBase.__init__(self, utils.getCallerName(), fnProcessEvents = fnProcessEvents);
3278 self.cMsTimeout = cMsTimeout;
3279 self.fnProcessEvents = fnProcessEvents;
3280 self.sIpAddr = None;
3281 self.sNextIpAddr = None;
3282 self.sMacAddr = sMacAddr;
3283 self.oIDhcpServer = oIDhcpServer;
3284 self.fReversedSetup = fReversedSetup;
3285 self.oVBoxEventHandler = None;
3286 self.oTxsSession = None;
3287
3288 # Check that the input makes sense:
3289 if (sMacAddr is None) != (oIDhcpServer is None) \
3290 or (sMacAddr and fReversedSetup) \
3291 or (sMacAddr and sIpAddr):
3292 reporter.error('TxsConnectTask sMacAddr=%s oIDhcpServer=%s sIpAddr=%s fReversedSetup=%s'
3293 % (sMacAddr, oIDhcpServer, sIpAddr, fReversedSetup,));
3294 raise base.GenError();
3295
3296 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
3297 if fReversedSetup is True:
3298 self._openTcpSession(sIpAddr, fReversedSetup = True);
3299 elif sIpAddr is not None and sIpAddr.strip() != '':
3300 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3301 else:
3302 #
3303 # If we've got no IP address, register callbacks that listens for
3304 # the primary network adaptor of the VM to set a IPv4 guest prop.
3305 # Note! The order in which things are done here is kind of important.
3306 #
3307
3308 # 0. The caller zaps the property before starting the VM.
3309 #try:
3310 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3311 #except:
3312 # reporter.logXcpt();
3313
3314 # 1. Register the callback / event listener object.
3315 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
3316 self.oVBoxEventHandler = oSession.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
3317
3318 # 2. Query the guest properties.
3319 try:
3320 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3321 except:
3322 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
3323 self._deregisterEventHandler();
3324 raise;
3325 if sIpAddr is not None:
3326 self._setIp(sIpAddr);
3327
3328 #
3329 # If the network adapter of the VM is host-only we can talk poll IDHCPServer
3330 # for the guest IP, allowing us to detect it for VMs without guest additions.
3331 # This will when we're polled.
3332 #
3333 if sMacAddr is not None:
3334 assert self.oIDhcpServer is not None;
3335
3336
3337 # end __init__
3338
3339 def __del__(self):
3340 """ Make sure we deregister the callback. """
3341 self._deregisterEventHandler();
3342 return TdTaskBase.__del__(self);
3343
3344 def toString(self):
3345 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
3346 ' oTxsSession=%s oVBoxEventHandler=%s>' \
3347 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
3348 self.oTxsSession, self.oVBoxEventHandler);
3349
3350 def _deregisterEventHandler(self):
3351 """Deregisters the event handler."""
3352 fRc = True;
3353 oVBoxEventHandler = self.oVBoxEventHandler;
3354 if oVBoxEventHandler is not None:
3355 self.oVBoxEventHandler = None;
3356 fRc = oVBoxEventHandler.unregister();
3357 oVBoxEventHandler.oParentTask = None; # Try avoid cylic deps.
3358 return fRc;
3359
3360 def _setIp(self, sIpAddr, fInitCall = False):
3361 """Called when we get an IP. Will create a TXS session and signal the task."""
3362 sIpAddr = sIpAddr.strip();
3363
3364 if sIpAddr is not None \
3365 and sIpAddr != '':
3366 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
3367 try:
3368 for s in sIpAddr.split('.'):
3369 i = int(s);
3370 if str(i) != s:
3371 raise Exception();
3372 except:
3373 reporter.fatalXcpt();
3374 else:
3375 reporter.log('TxsConnectTask: opening session to ip "%s"' % (sIpAddr));
3376 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3377 return None;
3378
3379 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
3380 else:
3381 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
3382 return None;
3383
3384 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
3385 """
3386 Calls txsclient.openTcpSession and switches our task to reflect the
3387 state of the subtask.
3388 """
3389 self.oCv.acquire();
3390 if self.oTxsSession is None:
3391 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' %
3392 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
3393 self.sIpAddr = sIpAddr;
3394 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, fReversedSetup,
3395 cMsIdleFudge, fnProcessEvents = self.fnProcessEvents);
3396 self.oTxsSession.setTaskOwner(self);
3397 else:
3398 self.sNextIpAddr = sIpAddr;
3399 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
3400 self.oCv.release();
3401 return None;
3402
3403 def notifyAboutReadyTask(self, oTxsSession):
3404 """
3405 Called by the TXS session task when it's done.
3406
3407 We'll signal the task completed or retry depending on the result.
3408 """
3409
3410 self.oCv.acquire();
3411
3412 # Disassociate ourselves with the session (avoid cyclic ref)
3413 oTxsSession.setTaskOwner(None);
3414 fSuccess = oTxsSession.isSuccess();
3415 if self.oTxsSession is not None:
3416 if not fSuccess:
3417 self.oTxsSession = None;
3418 if fSuccess and self.fReversedSetup:
3419 self.sIpAddr = oTxsSession.oTransport.sHostname;
3420 else:
3421 fSuccess = False;
3422
3423 # Signal done, or retry?
3424 fDeregister = False;
3425 if fSuccess \
3426 or self.fReversedSetup \
3427 or self.getAgeAsMs() >= self.cMsTimeout:
3428 self.signalTaskLocked();
3429 fDeregister = True;
3430 else:
3431 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
3432 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3433
3434 self.oCv.release();
3435
3436 # If we're done, deregister the callback (w/o owning lock). It will
3437 if fDeregister:
3438 self._deregisterEventHandler();
3439 return True;
3440
3441 def _pollDhcpServer(self):
3442 """
3443 Polls the DHCP server by MAC address in host-only setups.
3444 """
3445
3446 if self.sIpAddr:
3447 return False;
3448
3449 if self.oIDhcpServer is None or not self.sMacAddr:
3450 return False;
3451
3452 try:
3453 (sIpAddr, sState, secIssued, secExpire) = self.oIDhcpServer.findLeaseByMAC(self.sMacAddr, 0);
3454 except:
3455 reporter.log4Xcpt('sMacAddr=%s' % (self.sMacAddr,));
3456 return False;
3457
3458 secNow = utils.secondsSinceUnixEpoch();
3459 reporter.log2('dhcp poll: secNow=%s secExpire=%s secIssued=%s sState=%s sIpAddr=%s'
3460 % (secNow, secExpire, secIssued, sState, sIpAddr,));
3461 if secNow > secExpire or sState != 'acked' or not sIpAddr:
3462 return False;
3463
3464 reporter.log('dhcp poll: sIpAddr=%s secExpire=%s (%s TTL) secIssued=%s (%s ago)'
3465 % (sIpAddr, secExpire, secExpire - secNow, secIssued, secNow - secIssued,));
3466 self._setIp(sIpAddr);
3467 return True;
3468
3469 #
3470 # Task methods
3471 #
3472
3473 def pollTask(self, fLocked = False):
3474 """
3475 Overridden pollTask method.
3476 """
3477 self._pollDhcpServer();
3478 return TdTaskBase.pollTask(self, fLocked);
3479
3480 #
3481 # Public methods
3482 #
3483
3484 def getResult(self):
3485 """
3486 Returns the connected TXS session object on success.
3487 Returns None on failure or if the task has not yet completed.
3488 """
3489 self.oCv.acquire();
3490 oTxsSession = self.oTxsSession;
3491 self.oCv.release();
3492
3493 if oTxsSession is not None and not oTxsSession.isSuccess():
3494 oTxsSession = None;
3495 return oTxsSession;
3496
3497 def cancelTask(self):
3498 """ Cancels the task. """
3499 self._deregisterEventHandler(); # (make sure to avoid cyclic fun)
3500 self.oCv.acquire();
3501 if not self.fSignalled:
3502 oTxsSession = self.oTxsSession;
3503 if oTxsSession is not None:
3504 self.oCv.release();
3505 oTxsSession.setTaskOwner(None);
3506 oTxsSession.cancelTask();
3507 oTxsSession.waitForTask(1000);
3508 self.oCv.acquire();
3509 self.signalTaskLocked();
3510 self.oCv.release();
3511 return True;
3512
3513
3514
3515class AdditionsStatusTask(TdTaskBase):
3516 """
3517 Class that takes care of waiting till the guest additions are in a given state.
3518 """
3519
3520 class AdditionsStatusTaskCallback(vbox.EventHandlerBase):
3521 """ Class for looking for IPv4 address changes on interface 0."""
3522 def __init__(self, dArgs):
3523 self.oParentTask = dArgs['oParentTask'];
3524 vbox.EventHandlerBase.__init__(self, dArgs, self.oParentTask.oSession.fpApiVer,
3525 'AdditionsStatusTaskCallback/%s' % (self.oParentTask.oSession.sName,));
3526
3527 def handleEvent(self, oEvt):
3528 try:
3529 enmType = oEvt.type;
3530 except:
3531 reporter.errorXcpt();
3532 else:
3533 reporter.log2('AdditionsStatusTaskCallback:handleEvent: enmType=%s' % (enmType,));
3534 if enmType == vboxcon.VBoxEventType_OnGuestAdditionsStatusChanged:
3535 oParentTask = self.oParentTask;
3536 if oParentTask:
3537 oParentTask.pollTask();
3538
3539 # end
3540
3541
3542 def __init__(self, oSession, oIGuest, cMsTimeout = 120000, aenmWaitForRunLevels = None, aenmWaitForActive = None,
3543 aenmWaitForInactive = None):
3544 """
3545 aenmWaitForRunLevels - List of run level values to wait for (success if one matches).
3546 aenmWaitForActive - List facilities (type values) that must be active.
3547 aenmWaitForInactive - List facilities (type values) that must be inactive.
3548
3549 The default is to wait for AdditionsRunLevelType_Userland if all three lists
3550 are unspecified or empty.
3551 """
3552 TdTaskBase.__init__(self, utils.getCallerName());
3553 self.oSession = oSession # type: vboxwrappers.SessionWrapper
3554 self.oIGuest = oIGuest;
3555 self.cMsTimeout = cMsTimeout;
3556 self.fSucceeded = False;
3557 self.oVBoxEventHandler = None;
3558 self.aenmWaitForRunLevels = aenmWaitForRunLevels if aenmWaitForRunLevels else [];
3559 self.aenmWaitForActive = aenmWaitForActive if aenmWaitForActive else [];
3560 self.aenmWaitForInactive = aenmWaitForInactive if aenmWaitForInactive else [];
3561
3562 # Provide a sensible default if nothing is given.
3563 if not self.aenmWaitForRunLevels and not self.aenmWaitForActive and not self.aenmWaitForInactive:
3564 self.aenmWaitForRunLevels = [vboxcon.AdditionsRunLevelType_Userland,];
3565
3566 # Register the event handler on hosts which has it:
3567 if oSession.fpApiVer >= 6.1 or hasattr(vboxcon, 'VBoxEventType_OnGuestAdditionsStatusChanged'):
3568 aenmEvents = (vboxcon.VBoxEventType_OnGuestAdditionsStatusChanged,);
3569 dArgs = {
3570 'oParentTask': self,
3571 };
3572 self.oVBoxEventHandler = vbox.EventHandlerBase.registerDerivedEventHandler(oSession.oVBoxMgr,
3573 oSession.fpApiVer,
3574 self.AdditionsStatusTaskCallback,
3575 dArgs,
3576 oIGuest,
3577 'IGuest',
3578 'AdditionsStatusTaskCallback',
3579 aenmEvents = aenmEvents);
3580 reporter.log2('AdditionsStatusTask: %s' % (self.toString(), ));
3581
3582 def __del__(self):
3583 """ Make sure we deregister the callback. """
3584 self._deregisterEventHandler();
3585 self.oIGuest = None;
3586 return TdTaskBase.__del__(self);
3587
3588 def toString(self):
3589 return '<%s cMsTimeout=%s, fSucceeded=%s, aenmWaitForRunLevels=%s, aenmWaitForActive=%s, aenmWaitForInactive=%s, ' \
3590 'oVBoxEventHandler=%s>' \
3591 % (TdTaskBase.toString(self), self.cMsTimeout, self.fSucceeded, self.aenmWaitForRunLevels, self.aenmWaitForActive,
3592 self.aenmWaitForInactive, self.oVBoxEventHandler,);
3593
3594 def _deregisterEventHandler(self):
3595 """Deregisters the event handler."""
3596 fRc = True;
3597 oVBoxEventHandler = self.oVBoxEventHandler;
3598 if oVBoxEventHandler is not None:
3599 self.oVBoxEventHandler = None;
3600 fRc = oVBoxEventHandler.unregister();
3601 oVBoxEventHandler.oParentTask = None; # Try avoid cylic deps.
3602 return fRc;
3603
3604 def _poll(self):
3605 """
3606 Internal worker for pollTask() that returns the new signalled state.
3607 """
3608
3609 #
3610 # Check if any of the runlevels we wait for have been reached:
3611 #
3612 if self.aenmWaitForRunLevels:
3613 try:
3614 enmRunLevel = self.oIGuest.additionsRunLevel;
3615 except:
3616 reporter.errorXcpt();
3617 return True;
3618 if enmRunLevel not in self.aenmWaitForRunLevels:
3619 reporter.log6('AdditionsStatusTask/poll: enmRunLevel=%s not in %s' % (enmRunLevel, self.aenmWaitForRunLevels,));
3620 return False;
3621 reporter.log2('AdditionsStatusTask/poll: enmRunLevel=%s matched %s!' % (enmRunLevel, self.aenmWaitForRunLevels,));
3622
3623
3624 #
3625 # Check for the facilities that must all be active.
3626 #
3627 for enmFacility in self.aenmWaitForActive:
3628 try:
3629 (enmStatus, _) = self.oIGuest.getFacilityStatus(enmFacility);
3630 except:
3631 reporter.errorXcpt('enmFacility=%s' % (enmFacility,));
3632 return True;
3633 if enmStatus != vboxcon.AdditionsFacilityStatus_Active:
3634 reporter.log2('AdditionsStatusTask/poll: enmFacility=%s not active: %s' % (enmFacility, enmStatus,));
3635 return False;
3636
3637 #
3638 # Check for the facilities that must all be inactive or terminated.
3639 #
3640 for enmFacility in self.aenmWaitForInactive:
3641 try:
3642 (enmStatus, _) = self.oIGuest.getFacilityStatus(enmFacility);
3643 except:
3644 reporter.errorXcpt('enmFacility=%s' % (enmFacility,));
3645 return True;
3646 if enmStatus not in (vboxcon.AdditionsFacilityStatus_Inactive,
3647 vboxcon.AdditionsFacilityStatus_Terminated):
3648 reporter.log2('AdditionsStatusTask/poll: enmFacility=%s not inactive: %s' % (enmFacility, enmStatus,));
3649 return False;
3650
3651
3652 reporter.log('AdditionsStatusTask: Poll succeeded, signalling...');
3653 self.fSucceeded = True;
3654 return True;
3655
3656
3657 #
3658 # Task methods
3659 #
3660
3661 def pollTask(self, fLocked = False):
3662 """
3663 Overridden pollTask method.
3664 """
3665 if not fLocked:
3666 self.lockTask();
3667
3668 fDeregister = False;
3669 fRc = self.fSignalled;
3670 if not fRc:
3671 fRc = self._poll();
3672 if fRc or self.getAgeAsMs() >= self.cMsTimeout:
3673 self.signalTaskLocked();
3674 fDeregister = True;
3675
3676 if not fLocked:
3677 self.unlockTask();
3678
3679 # If we're done, deregister the event callback (w/o owning lock).
3680 if fDeregister:
3681 self._deregisterEventHandler();
3682 return fRc;
3683
3684 def getResult(self):
3685 """
3686 Returns true if the we succeeded.
3687 Returns false if not. If the task is signalled already, then we
3688 encountered a problem while polling.
3689 """
3690 return self.fSucceeded;
3691
3692 def cancelTask(self):
3693 """
3694 Cancels the task.
3695 Just to actively disengage the event handler.
3696 """
3697 self._deregisterEventHandler();
3698 return True;
3699
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