VirtualBox

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

Last change on this file since 98102 was 97673, checked in by vboxsync, 2 years ago

Validation Kit: Fixed lots of warnings, based on pylint 2.12.2.

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