VirtualBox

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

Last change on this file since 99180 was 99180, checked in by vboxsync, 23 months ago

Validation Kit/vboxwrappers: Fixed non-trunk builds; MOK (Machine Owner Key) list handling through the UEFI store only is available in trunk.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette