VirtualBox

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

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

ValKit: Pylint 2.16.2 adjustments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 144.7 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 98655 2023-02-20 15:05:40Z vboxsync $
3# pylint: disable=too-many-lines
4
5"""
6VirtualBox Wrapper Classes
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2023 Oracle and/or its affiliates.
12
13This file is part of VirtualBox base platform packages, as
14available from https://www.virtualbox.org.
15
16This program is free software; you can redistribute it and/or
17modify it under the terms of the GNU General Public License
18as published by the Free Software Foundation, in version 3 of the
19License.
20
21This program is distributed in the hope that it will be useful, but
22WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program; if not, see <https://www.gnu.org/licenses>.
28
29The contents of this file may alternatively be used under the terms
30of the Common Development and Distribution License Version 1.0
31(CDDL), a copy of it is provided in the "COPYING.CDDL" file included
32in the VirtualBox distribution, in which case the provisions of the
33CDDL are applicable instead of those of the GPL.
34
35You may elect to license modified versions of this file under the
36terms and conditions of either the GPL or the CDDL or both.
37
38SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
39"""
40__version__ = "$Revision: 98655 $"
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,comparison-of-constants
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 try:
1840 oCtl.controllerType = eType;
1841 reporter.log('added storage controller "%s" (bus %s, type %s) to %s'
1842 % (sController, eBus, eType, self.sName));
1843 except:
1844 reporter.errorXcpt('controllerType = %s on ("%s" / %s) failed on "%s"'
1845 % (eType, sController, eBus, self.sName) );
1846 return False;
1847 finally:
1848 self.oTstDrv.processPendingEvents();
1849 return True;
1850
1851 def setStorageControllerPortCount(self, sController, iPortCount):
1852 """
1853 Set maximum ports count for storage controller
1854 """
1855 try:
1856 oCtl = self.o.machine.getStorageControllerByName(sController)
1857 oCtl.portCount = iPortCount
1858 self.oTstDrv.processPendingEvents()
1859 reporter.log('set controller "%s" port count to value %d' % (sController, iPortCount))
1860 return True
1861 except:
1862 reporter.log('unable to set storage controller "%s" ports count to %d' % (sController, iPortCount))
1863
1864 return False
1865
1866 def setStorageControllerHostIoCache(self, sController, fUseHostIoCache):
1867 """
1868 Set maximum ports count for storage controller
1869 """
1870 try:
1871 oCtl = self.o.machine.getStorageControllerByName(sController);
1872 oCtl.useHostIOCache = fUseHostIoCache;
1873 self.oTstDrv.processPendingEvents();
1874 reporter.log('set controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1875 return True;
1876 except:
1877 reporter.log('unable to set storage controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1878
1879 return False;
1880
1881 def setBootOrder(self, iPosition, eType):
1882 """
1883 Set guest boot order type
1884 @param iPosition boot order position
1885 @param eType device type (vboxcon.DeviceType_HardDisk,
1886 vboxcon.DeviceType_DVD, vboxcon.DeviceType_Floppy)
1887 """
1888 try:
1889 self.o.machine.setBootOrder(iPosition, eType)
1890 except:
1891 return reporter.errorXcpt('Unable to set boot order.')
1892
1893 reporter.log('Set boot order [%d] for device %s' % (iPosition, str(eType)))
1894 self.oTstDrv.processPendingEvents();
1895
1896 return True
1897
1898 def setStorageControllerType(self, eType, sController = "IDE Controller"):
1899 """
1900 Similar to ensureControllerAttached, except it will change the type.
1901 """
1902 try:
1903 oCtl = self.o.machine.getStorageControllerByName(sController);
1904 except:
1905 (eBus, _) = _ControllerNameToBusAndType(sController);
1906 try:
1907 oCtl = self.o.machine.addStorageController(sController, eBus);
1908 reporter.log('added storage controller "%s" (bus %s) to %s' % (sController, eBus, self.sName));
1909 except:
1910 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, eBus, self.sName) );
1911 return False;
1912 try:
1913 oCtl.controllerType = eType;
1914 except:
1915 reporter.errorXcpt('failed to set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1916 return False;
1917 reporter.log('set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1918 self.oTstDrv.processPendingEvents();
1919 return True;
1920
1921 def attachDvd(self, sImage = None, sController = "IDE Controller", iPort = 1, iDevice = 0):
1922 """
1923 Attaches a DVD drive to a VM, optionally with an ISO inserted.
1924 Returns True on success and False on failure. Error information is logged.
1925 """
1926 # Input validation.
1927 if sImage is not None and not self.oTstDrv.isResourceFile(sImage)\
1928 and not os.path.isabs(sImage): ## fixme - testsuite unzip ++
1929 reporter.fatal('"%s" is not in the resource set' % (sImage));
1930 return None;
1931
1932 if not self.ensureControllerAttached(sController):
1933 return False;
1934
1935 # Find/register the image if specified.
1936 oImage = None;
1937 sImageUuid = "";
1938 if sImage is not None:
1939 sFullName = self.oTstDrv.getFullResourceName(sImage)
1940 try:
1941 oImage = self.oVBox.findDVDImage(sFullName);
1942 except:
1943 try:
1944 if self.fpApiVer >= 4.1:
1945 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly, False);
1946 elif self.fpApiVer >= 4.0:
1947 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly);
1948 else:
1949 oImage = self.oVBox.openDVDImage(sFullName, "");
1950 except vbox.ComException as oXcpt:
1951 if oXcpt.errno != -1:
1952 reporter.errorXcpt('failed to open DVD image "%s" xxx' % (sFullName));
1953 else:
1954 reporter.errorXcpt('failed to open DVD image "%s" yyy' % (sFullName));
1955 return False;
1956 except:
1957 reporter.errorXcpt('failed to open DVD image "%s"' % (sFullName));
1958 return False;
1959 try:
1960 sImageUuid = oImage.id;
1961 except:
1962 reporter.errorXcpt('failed to get the UUID of "%s"' % (sFullName));
1963 return False;
1964
1965 # Attach the DVD.
1966 fRc = True;
1967 try:
1968 if self.fpApiVer >= 4.0:
1969 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, oImage);
1970 else:
1971 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, sImageUuid);
1972 except:
1973 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1974 % (sController, iPort, iDevice, sImageUuid, self.sName) );
1975 fRc = False;
1976 else:
1977 reporter.log('attached DVD to %s, image="%s"' % (self.sName, sImage));
1978 self.oTstDrv.processPendingEvents();
1979 return fRc;
1980
1981 def attachHd(self, sHd, sController = "IDE Controller", iPort = 0, iDevice = 0, fImmutable = True, fForceResource = True):
1982 """
1983 Attaches a HD to a VM.
1984 Returns True on success and False on failure. Error information is logged.
1985 """
1986 # Input validation.
1987 if fForceResource and not self.oTstDrv.isResourceFile(sHd):
1988 reporter.fatal('"%s" is not in the resource set' % (sHd,));
1989 return None;
1990
1991 if not self.ensureControllerAttached(sController):
1992 return False;
1993
1994 # Find the HD, registering it if necessary (as immutable).
1995 if fForceResource:
1996 sFullName = self.oTstDrv.getFullResourceName(sHd);
1997 else:
1998 sFullName = sHd;
1999 try:
2000 oHd = self.oVBox.findHardDisk(sFullName);
2001 except:
2002 try:
2003 if self.fpApiVer >= 4.1:
2004 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
2005 elif self.fpApiVer >= 4.0:
2006 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
2007 else:
2008 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
2009 except:
2010 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
2011 return False;
2012 try:
2013 if fImmutable:
2014 oHd.type = vboxcon.MediumType_Immutable;
2015 else:
2016 oHd.type = vboxcon.MediumType_Normal;
2017 except:
2018 if fImmutable:
2019 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
2020 else:
2021 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
2022 return False;
2023
2024 # Attach it.
2025 fRc = True;
2026 try:
2027 if self.fpApiVer >= 4.0:
2028 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
2029 else:
2030 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
2031 except:
2032 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
2033 % (sController, iPort, iDevice, oHd.id, self.sName) );
2034 fRc = False;
2035 else:
2036 reporter.log('attached "%s" to %s' % (sHd, self.sName));
2037 self.oTstDrv.processPendingEvents();
2038 return fRc;
2039
2040 def createBaseHd(self, sHd, sFmt = "VDI", cb = 10*1024*1024*1024, cMsTimeout = 60000, tMediumVariant = None):
2041 """
2042 Creates a base HD.
2043 Returns Medium object on success and None on failure. Error information is logged.
2044 """
2045 if tMediumVariant is None:
2046 tMediumVariant = (vboxcon.MediumVariant_Standard, );
2047
2048 try:
2049 if self.fpApiVer >= 5.0:
2050 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
2051 else:
2052 oHd = self.oVBox.createHardDisk(sFmt, sHd);
2053 oProgressXpcom = oHd.createBaseStorage(cb, tMediumVariant);
2054 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create base disk %s' % (sHd));
2055 oProgress.wait(cMsTimeout);
2056 oProgress.logResult();
2057 except:
2058 reporter.errorXcpt('failed to create base hd "%s"' % (sHd));
2059 oHd = None
2060
2061 return oHd;
2062
2063 def createDiffHd(self, oParentHd, sHd, sFmt = "VDI"):
2064 """
2065 Creates a differencing HD.
2066 Returns Medium object on success and None on failure. Error information is logged.
2067 """
2068 # Detect the proper format if requested
2069 if sFmt is None:
2070 try:
2071 oHdFmt = oParentHd.mediumFormat;
2072 lstCaps = self.oVBoxMgr.getArray(oHdFmt, 'capabilities');
2073 if vboxcon.MediumFormatCapabilities_Differencing in lstCaps:
2074 sFmt = oHdFmt.id;
2075 else:
2076 sFmt = 'VDI';
2077 except:
2078 reporter.errorXcpt('failed to get preferred diff format for "%s"' % (sHd));
2079 return None;
2080 try:
2081 if self.fpApiVer >= 5.0:
2082 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
2083 else:
2084 oHd = self.oVBox.createHardDisk(sFmt, sHd);
2085 oProgressXpcom = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
2086 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
2087 oProgress.wait();
2088 oProgress.logResult();
2089 except:
2090 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
2091 oHd = None
2092
2093 return oHd;
2094
2095 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, # pylint: disable=too-many-arguments
2096 iPort = 0, iDevice = 0, fImmutable = True, cMsTimeout = 60000, tMediumVariant = None):
2097 """
2098 Creates and attaches a HD to a VM.
2099 Returns True on success and False on failure. Error information is logged.
2100 """
2101 if not self.ensureControllerAttached(sController):
2102 return False;
2103
2104 oHd = self.createBaseHd(sHd, sFmt, cb, cMsTimeout, tMediumVariant);
2105 if oHd is None:
2106 return False;
2107
2108 fRc = True;
2109 try:
2110 if fImmutable:
2111 oHd.type = vboxcon.MediumType_Immutable;
2112 else:
2113 oHd.type = vboxcon.MediumType_Normal;
2114 except:
2115 if fImmutable:
2116 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
2117 else:
2118 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
2119 fRc = False;
2120
2121 # Attach it.
2122 if fRc is True:
2123 try:
2124 if self.fpApiVer >= 4.0:
2125 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
2126 else:
2127 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
2128 except:
2129 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
2130 % (sController, iPort, iDevice, oHd.id, self.sName) );
2131 fRc = False;
2132 else:
2133 reporter.log('attached "%s" to %s' % (sHd, self.sName));
2134
2135 # Delete disk in case of an error
2136 if fRc is False:
2137 try:
2138 oProgressCom = oHd.deleteStorage();
2139 except:
2140 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
2141 else:
2142 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
2143 oProgress.wait();
2144 oProgress.logResult();
2145
2146 self.oTstDrv.processPendingEvents();
2147 return fRc;
2148
2149 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
2150 """
2151 Detaches a HD, if attached, and returns a reference to it (IMedium).
2152
2153 In order to delete the detached medium, the caller must first save
2154 the changes made in this session.
2155
2156 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
2157 your standard success indicator. Error information is logged.
2158 """
2159
2160 # What's attached?
2161 try:
2162 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
2163 except:
2164 if self.oVBoxMgr.xcptIsOurXcptKind() \
2165 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
2166 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
2167 return (True, None);
2168 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
2169 % (iPort, iDevice, sController)), None);
2170 # Detach it.
2171 try:
2172 self.o.machine.detachDevice(sController, iPort, iDevice);
2173 except:
2174 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
2175 % (sController, iPort, iDevice, self.sName) ), None);
2176 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
2177 return (True, oHd);
2178
2179 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
2180 """
2181 Attaches a floppy image to a VM.
2182 Returns True on success and False on failure. Error information is logged.
2183 """
2184 # Input validation.
2185 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
2186 ##if not self.oTstDrv.isResourceFile(sFloppy):
2187 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
2188 ## return None;
2189
2190 if not self.ensureControllerAttached(sController):
2191 return False;
2192
2193 # Find the floppy image, registering it if necessary (as immutable).
2194 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
2195 try:
2196 oFloppy = self.oVBox.findFloppyImage(sFullName);
2197 except:
2198 try:
2199 if self.fpApiVer >= 4.1:
2200 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
2201 elif self.fpApiVer >= 4.0:
2202 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
2203 else:
2204 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
2205 except:
2206 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
2207 return False;
2208 ## @todo the following works but causes trouble below (asserts in main).
2209 #try:
2210 # oFloppy.type = vboxcon.MediumType_Immutable;
2211 #except:
2212 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
2213 # return False;
2214
2215 # Attach it.
2216 fRc = True;
2217 try:
2218 if self.fpApiVer >= 4.0:
2219 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
2220 else:
2221 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
2222 except:
2223 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
2224 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
2225 fRc = False;
2226 else:
2227 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
2228 self.oTstDrv.processPendingEvents();
2229 return fRc;
2230
2231 def setupNic(self, sType, sXXX):
2232 """
2233 Sets up a NIC to a VM.
2234 Returns True on success and False on failure. Error information is logged.
2235 """
2236 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
2237 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
2238 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
2239 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
2240 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
2241 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
2242 else:
2243 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
2244 return False;
2245 ## @todo Implement me!
2246 if enmType is not None: pass
2247 return True;
2248
2249 def setupAudio(self, eAudioControllerType, fEnable = True, fEnableIn = False, fEnableOut = True, eAudioDriverType = None):
2250 """
2251 Sets up audio.
2252
2253 :param eAudioControllerType: The audio controller type (vboxcon.AudioControllerType_XXX).
2254 :param fEnable: Whether to enable or disable the audio controller (default enable).
2255 :param fEnableIn: Whether to enable or disable audio input (default disable).
2256 :param fEnableOut: Whether to enable or disable audio output (default enable).
2257 :param eAudioDriverType: The audio driver type (vboxcon.AudioDriverType_XXX), picks something suitable
2258 if None is passed (default).
2259 """
2260 try:
2261 if self.fpApiVer >= 7.0:
2262 oAdapter = self.o.machine.audioSettings.adapter;
2263 else:
2264 oAdapter = self.o.machine.audioAdapter;
2265 except: return reporter.errorXcpt('Failed to get the audio adapter.');
2266
2267 try: oAdapter.audioController = eAudioControllerType;
2268 except: return reporter.errorXcpt('Failed to set the audio controller to %s.' % (eAudioControllerType,));
2269
2270 if eAudioDriverType is None:
2271 sHost = utils.getHostOs()
2272 if sHost == 'darwin': eAudioDriverType = vboxcon.AudioDriverType_CoreAudio;
2273 elif sHost == 'win': eAudioDriverType = vboxcon.AudioDriverType_DirectSound;
2274 elif sHost == 'linux': eAudioDriverType = vboxcon.AudioDriverType_Pulse;
2275 elif sHost == 'solaris': eAudioDriverType = vboxcon.AudioDriverType_OSS;
2276 else:
2277 reporter.error('PORTME: Do not know which audio driver to pick for: %s!' % (sHost,));
2278 eAudioDriverType = vboxcon.AudioDriverType_Null;
2279
2280 try: oAdapter.audioDriver = eAudioDriverType;
2281 except: return reporter.errorXcpt('Failed to set the audio driver to %s.' % (eAudioDriverType,))
2282
2283 try: oAdapter.enabled = fEnable;
2284 except: return reporter.errorXcpt('Failed to set the "enabled" property to %s.' % (fEnable,));
2285
2286 try: oAdapter.enabledIn = fEnableIn;
2287 except: return reporter.errorXcpt('Failed to set the "enabledIn" property to %s.' % (fEnable,));
2288
2289 try: oAdapter.enabledOut = fEnableOut;
2290 except: return reporter.errorXcpt('Failed to set the "enabledOut" property to %s.' % (fEnable,));
2291
2292 reporter.log('set audio adapter type to %d, driver to %d, and enabled to %s (input is %s, output is %s)'
2293 % (eAudioControllerType, eAudioDriverType, fEnable, fEnableIn, fEnableOut,));
2294 self.oTstDrv.processPendingEvents();
2295 return True;
2296
2297 def setupPreferredConfig(self): # pylint: disable=too-many-locals
2298 """
2299 Configures the VM according to the preferences of the guest type.
2300 """
2301 try:
2302 sOsTypeId = self.o.machine.OSTypeId;
2303 except:
2304 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2305 return False;
2306
2307 try:
2308 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2309 except:
2310 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2311 return False;
2312
2313 # get the attributes.
2314 try:
2315 #sFamilyId = oOsType.familyId;
2316 #f64Bit = oOsType.is64Bit;
2317 fIoApic = oOsType.recommendedIOAPIC;
2318 fVirtEx = oOsType.recommendedVirtEx;
2319 cMBRam = oOsType.recommendedRAM;
2320 cMBVRam = oOsType.recommendedVRAM;
2321 #cMBHdd = oOsType.recommendedHDD;
2322 eNicType = oOsType.adapterType;
2323 if self.fpApiVer >= 3.2:
2324 if self.fpApiVer >= 4.2:
2325 fPae = oOsType.recommendedPAE;
2326 fUsbHid = oOsType.recommendedUSBHID;
2327 fHpet = oOsType.recommendedHPET;
2328 eStorCtlType = oOsType.recommendedHDStorageController;
2329 else:
2330 fPae = oOsType.recommendedPae;
2331 fUsbHid = oOsType.recommendedUsbHid;
2332 fHpet = oOsType.recommendedHpet;
2333 eStorCtlType = oOsType.recommendedHdStorageController;
2334 eFirmwareType = oOsType.recommendedFirmware;
2335 else:
2336 fPae = False;
2337 fUsbHid = False;
2338 fHpet = False;
2339 eFirmwareType = -1;
2340 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
2341 if self.fpApiVer >= 4.0:
2342 eAudioCtlType = oOsType.recommendedAudioController;
2343 except:
2344 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
2345 self.oTstDrv.processPendingEvents();
2346 return False;
2347 self.oTstDrv.processPendingEvents();
2348
2349 # Do the setting. Continue applying settings on error in case the
2350 # caller ignores the return code
2351 fRc = True;
2352 if not self.enableIoApic(fIoApic): fRc = False;
2353 if not self.enableVirtEx(fVirtEx): fRc = False;
2354 if not self.enablePae(fPae): fRc = False;
2355 if not self.setRamSize(cMBRam): fRc = False;
2356 if not self.setVRamSize(cMBVRam): fRc = False;
2357 if not self.setNicType(eNicType, 0): fRc = False;
2358 if self.fpApiVer >= 3.2:
2359 if not self.setFirmwareType(eFirmwareType): fRc = False;
2360 if not self.enableUsbHid(fUsbHid): fRc = False;
2361 if not self.enableHpet(fHpet): fRc = False;
2362 if eStorCtlType in (vboxcon.StorageControllerType_PIIX3,
2363 vboxcon.StorageControllerType_PIIX4,
2364 vboxcon.StorageControllerType_ICH6,):
2365 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
2366 fRc = False;
2367 if self.fpApiVer >= 4.0:
2368 if not self.setupAudio(eAudioCtlType): fRc = False;
2369
2370 return fRc;
2371
2372 def addUsbDeviceFilter(self, sName, sVendorId = None, sProductId = None, sRevision = None, # pylint: disable=too-many-arguments
2373 sManufacturer = None, sProduct = None, sSerialNumber = None,
2374 sPort = None, sRemote = None):
2375 """
2376 Creates a USB device filter and inserts it into the VM.
2377 Returns True on success.
2378 Returns False on failure (logged).
2379 """
2380 fRc = True;
2381
2382 try:
2383 oUsbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
2384 oUsbDevFilter.active = True;
2385 if sVendorId is not None:
2386 oUsbDevFilter.vendorId = sVendorId;
2387 if sProductId is not None:
2388 oUsbDevFilter.productId = sProductId;
2389 if sRevision is not None:
2390 oUsbDevFilter.revision = sRevision;
2391 if sManufacturer is not None:
2392 oUsbDevFilter.manufacturer = sManufacturer;
2393 if sProduct is not None:
2394 oUsbDevFilter.product = sProduct;
2395 if sSerialNumber is not None:
2396 oUsbDevFilter.serialnumber = sSerialNumber;
2397 if sPort is not None:
2398 oUsbDevFilter.port = sPort;
2399 if sRemote is not None:
2400 oUsbDevFilter.remote = sRemote;
2401 try:
2402 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, oUsbDevFilter);
2403 except:
2404 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
2405 % (0, self.sName) );
2406 fRc = False;
2407 else:
2408 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
2409 except:
2410 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
2411 % (sName, self.sName) );
2412 fRc = False;
2413 return fRc;
2414
2415 def getGuestPropertyValue(self, sName):
2416 """
2417 Gets a guest property value.
2418 Returns the value on success, None on failure (logged).
2419 """
2420 try:
2421 sValue = self.o.machine.getGuestPropertyValue(sName);
2422 except:
2423 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2424 return None;
2425 return sValue;
2426
2427 def setGuestPropertyValue(self, sName, sValue):
2428 """
2429 Sets a guest property value.
2430 Returns the True on success, False on failure (logged).
2431 """
2432 try:
2433 self.o.machine.setGuestPropertyValue(sName, sValue);
2434 except:
2435 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2436 return False;
2437 return True;
2438
2439 def delGuestPropertyValue(self, sName):
2440 """
2441 Deletes a guest property value.
2442 Returns the True on success, False on failure (logged).
2443 """
2444 try:
2445 oMachine = self.o.machine;
2446 if self.fpApiVer >= 4.2:
2447 oMachine.deleteGuestProperty(sName);
2448 else:
2449 oMachine.setGuestPropertyValue(sName, '');
2450 except:
2451 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2452 return False;
2453 return True;
2454
2455 def setExtraData(self, sKey, sValue):
2456 """
2457 Sets extra data.
2458 Returns the True on success, False on failure (logged).
2459 """
2460 try:
2461 self.o.machine.setExtraData(sKey, sValue);
2462 except:
2463 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2464 return False;
2465 return True;
2466
2467 def getExtraData(self, sKey):
2468 """
2469 Gets extra data.
2470 Returns value on success, None on failure.
2471 """
2472 try:
2473 sValue = self.o.machine.getExtraData(sKey)
2474 except:
2475 reporter.errorXcpt('IMachine::getExtraData("%s") failed' % (sKey,))
2476 return None
2477 return sValue
2478
2479 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2480 """
2481 Sets up the teleporter for the VM.
2482 Returns True on success, False on failure (logged).
2483 """
2484 try:
2485 self.o.machine.teleporterAddress = sAddress;
2486 self.o.machine.teleporterPort = uPort;
2487 self.o.machine.teleporterPassword = sPassword;
2488 self.o.machine.teleporterEnabled = fEnabled;
2489 except:
2490 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2491 return False;
2492 return True;
2493
2494 def enableTeleporter(self, fEnable=True):
2495 """
2496 Enables or disables the teleporter of the VM.
2497 Returns True on success, False on failure (logged).
2498 """
2499 try:
2500 self.o.machine.teleporterEnabled = fEnable;
2501 except:
2502 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2503 return False;
2504 return True;
2505
2506 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2507 """
2508 Wrapper around the IConsole::teleport() method.
2509 Returns a progress object on success, None on failure (logged).
2510 """
2511 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2512 try:
2513 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2514 except:
2515 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2516 return None;
2517 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2518
2519 def getOsType(self):
2520 """
2521 Gets the IGuestOSType interface for the machine.
2522
2523 return IGuestOSType interface on success, None + errorXcpt on failure.
2524 No exceptions raised.
2525 """
2526 try:
2527 sOsTypeId = self.o.machine.OSTypeId;
2528 except:
2529 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2530 return None;
2531
2532 try:
2533 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2534 except:
2535 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2536 return None;
2537
2538 return oOsType;
2539
2540 def setOsType(self, sNewTypeId):
2541 """
2542 Changes the OS type.
2543
2544 returns True on success, False + errorXcpt on failure.
2545 No exceptions raised.
2546 """
2547 try:
2548 self.o.machine.OSTypeId = sNewTypeId;
2549 except:
2550 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2551 return False;
2552 return True;
2553
2554
2555 def setParavirtProvider(self, iProvider):
2556 """
2557 Sets a paravirtualisation provider.
2558 Returns the True on success, False on failure (logged).
2559 """
2560 try:
2561 self.o.machine.paravirtProvider = iProvider
2562 except:
2563 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2564 return False;
2565 return True;
2566
2567
2568 def setupSerialToRawFile(self, iSerialPort, sRawFile):
2569 """
2570 Enables the given serial port (zero based) and redirects it to sRawFile.
2571 Returns the True on success, False on failure (logged).
2572 """
2573 try:
2574 oPort = self.o.machine.getSerialPort(iSerialPort);
2575 except:
2576 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2577 else:
2578 try:
2579 oPort.path = sRawFile;
2580 except:
2581 fRc = reporter.errorXcpt('failed to set the "path" property on serial port #%u to "%s"'
2582 % (iSerialPort, sRawFile));
2583 else:
2584 try:
2585 oPort.hostMode = vboxcon.PortMode_RawFile;
2586 except:
2587 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_RawFile'
2588 % (iSerialPort,));
2589 else:
2590 try:
2591 oPort.enabled = True;
2592 except:
2593 fRc = reporter.errorXcpt('failed to set the "enable" property on serial port #%u to True'
2594 % (iSerialPort,));
2595 else:
2596 reporter.log('set SerialPort[%s].enabled/hostMode/path=True/RawFile/%s' % (iSerialPort, sRawFile,));
2597 fRc = True;
2598 self.oTstDrv.processPendingEvents();
2599 return fRc;
2600
2601
2602 def enableSerialPort(self, iSerialPort):
2603 """
2604 Enables the given serial port setting the initial port mode to disconnected.
2605 """
2606 try:
2607 oPort = self.o.machine.getSerialPort(iSerialPort);
2608 except:
2609 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2610 else:
2611 try:
2612 oPort.hostMode = vboxcon.PortMode_Disconnected;
2613 except:
2614 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_Disconnected'
2615 % (iSerialPort,));
2616 else:
2617 try:
2618 oPort.enabled = True;
2619 except:
2620 fRc = reporter.errorXcpt('failed to set the "enable" property on serial port #%u to True'
2621 % (iSerialPort,));
2622 else:
2623 reporter.log('set SerialPort[%s].enabled/hostMode/=True/Disconnected' % (iSerialPort,));
2624 fRc = True;
2625 self.oTstDrv.processPendingEvents();
2626 return fRc;
2627
2628
2629 def changeSerialPortAttachment(self, iSerialPort, ePortMode, sPath, fServer):
2630 """
2631 Changes the attachment of the given serial port to the attachment config given.
2632 """
2633 try:
2634 oPort = self.o.machine.getSerialPort(iSerialPort);
2635 except:
2636 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2637 else:
2638 try:
2639 # Change port mode to disconnected first so changes get picked up by a potentially running VM.
2640 oPort.hostMode = vboxcon.PortMode_Disconnected;
2641 except:
2642 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_Disconnected'
2643 % (iSerialPort,));
2644 else:
2645 try:
2646 oPort.path = sPath;
2647 oPort.server = fServer;
2648 oPort.hostMode = ePortMode;
2649 except:
2650 fRc = reporter.errorXcpt('failed to configure the serial port');
2651 else:
2652 reporter.log('set SerialPort[%s].hostMode/path/server=%s/%s/%s'
2653 % (iSerialPort, ePortMode, sPath, fServer));
2654 fRc = True;
2655 self.oTstDrv.processPendingEvents();
2656 return fRc;
2657
2658 #
2659 # IConsole wrappers.
2660 #
2661
2662 def powerOff(self, fFudgeOnFailure = True):
2663 """
2664 Powers off the VM.
2665
2666 Returns True on success.
2667 Returns False on IConsole::powerDown() failure.
2668 Returns None if the progress object returns failure.
2669 """
2670 #
2671 # Deregister event handler before we power off the VM, otherwise we're
2672 # racing for VM process termination and cause misleading spurious
2673 # error messages in the event handling code, because the event objects
2674 # disappear.
2675 #
2676 # Note! Doing this before powerDown to try prevent numerous smoketest
2677 # timeouts on XPCOM hosts.
2678 #
2679 self.deregisterEventHandlerForTask();
2680
2681
2682 # Try power if off.
2683 try:
2684 oProgress = self.o.console.powerDown();
2685 except:
2686 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2687 if fFudgeOnFailure:
2688 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2689 self.waitForTask(1000); # fudge
2690 return False;
2691
2692 # Wait on power off operation to complete.
2693 rc = self.oTstDrv.waitOnProgress(oProgress);
2694 if rc < 0:
2695 self.close();
2696 if fFudgeOnFailure:
2697 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2698 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2699 return None;
2700
2701 # Wait for the VM to really power off or we'll fail to open a new session to it.
2702 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2703 return self.waitForTask(30 * 1000); # fudge
2704
2705 def saveState(self, fPause = True):
2706 """
2707 Saves state of the VM.
2708
2709 Returns True on success.
2710 Returns False on IConsole::saveState() failure.
2711 Returns None if the progress object returns Failure.
2712 """
2713
2714 if fPause is True \
2715 and self.oVM.state is vboxcon.MachineState_Running:
2716 self.o.console.pause();
2717 if self.oVM.state is not vboxcon.MachineState_Paused:
2718 reporter.error('pause for "%s" failed' % (self.sName));
2719 # Try saving state.
2720 try:
2721 if self.fpApiVer >= 5.0:
2722 oProgress = self.o.machine.saveState()
2723 else:
2724 oProgress = self.o.console.saveState()
2725 except:
2726 reporter.logXcpt('IMachine::saveState failed on %s' % (self.sName));
2727 return False;
2728
2729 # Wait for saving state operation to complete.
2730 rc = self.oTstDrv.waitOnProgress(oProgress);
2731 if rc < 0:
2732 self.close();
2733 return None;
2734
2735 # Wait for the VM to really terminate or we'll fail to open a new session to it.
2736 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2737 return self.waitForTask(30 * 1000); # fudge
2738
2739 def discardSavedState(self, fRemove = True):
2740 """
2741 Discards saved state of the VM.
2742
2743 Returns True on success.
2744 Returns False on IConsole::discardSaveState() failure.
2745 """
2746
2747 try:
2748 if self.fpApiVer >= 5.0:
2749 self.o.machine.discardSavedState(fRemove)
2750 else:
2751 self.o.console.discardSavedState(fRemove)
2752 except:
2753 reporter.logXcpt('IMachine::discardSavedState failed on %s' % (self.sName))
2754 return False
2755 return True
2756
2757 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2758 """
2759 Restores the given snapshot.
2760
2761 Returns True on success.
2762 Returns False on IMachine::restoreSnapshot() failure.
2763 Returns None if the progress object returns failure.
2764 """
2765 try:
2766 if self.fpApiVer >= 5.0:
2767 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2768 else:
2769 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2770 except:
2771 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2772 if fFudgeOnFailure:
2773 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2774 self.waitForTask(1000); # fudge
2775 return False;
2776
2777 rc = self.oTstDrv.waitOnProgress(oProgress);
2778 if rc < 0:
2779 self.close();
2780 if fFudgeOnFailure:
2781 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2782 return None;
2783
2784 return self.waitForTask(30 * 1000);
2785
2786 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2787 """
2788 Deletes the given snapshot merging the diff image into the base.
2789
2790 Returns True on success.
2791 Returns False on IMachine::deleteSnapshot() failure.
2792 """
2793 try:
2794 if self.fpApiVer >= 5.0:
2795 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2796 else:
2797 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2798 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2799 oProgress.wait(cMsTimeout);
2800 oProgress.logResult();
2801 except:
2802 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2803 if fFudgeOnFailure:
2804 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2805 self.waitForTask(1000); # fudge
2806 return False;
2807
2808 return True;
2809
2810 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2811 """
2812 Takes a snapshot with the given name
2813
2814 Returns True on success.
2815 Returns False on IMachine::takeSnapshot() or VM state change failure.
2816 """
2817 try:
2818 if fPause is True \
2819 and self.oVM.state is vboxcon.MachineState_Running:
2820 self.o.console.pause();
2821 if self.fpApiVer >= 5.0:
2822 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2823 else:
2824 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2825 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2826 oProgress.wait(cMsTimeout);
2827 oProgress.logResult();
2828 except:
2829 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2830 if fFudgeOnFailure:
2831 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2832 self.waitForTask(1000); # fudge
2833 return False;
2834
2835 if fPause is True \
2836 and self.oVM.state is vboxcon.MachineState_Paused:
2837 self.o.console.resume();
2838
2839 return True;
2840
2841 def findSnapshot(self, sName):
2842 """
2843 Returns the snapshot object with the given name
2844
2845 Returns snapshot object on success.
2846 Returns None if there is no snapshot with the given name.
2847 """
2848 return self.oVM.findSnapshot(sName);
2849
2850 def takeScreenshot(self, sFilename, iScreenId=0):
2851 """
2852 Take screenshot from the given display and save it to specified file.
2853
2854 Returns True on success
2855 Returns False on failure.
2856 """
2857 try:
2858 if self.fpApiVer >= 5.0:
2859 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2860 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2861 vboxcon.BitmapFormat_PNG)
2862 else:
2863 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2864 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2865 except:
2866 reporter.logXcpt("Unable to take screenshot")
2867 return False
2868
2869 with open(sFilename, 'wb') as oFile: # pylint: disable=unspecified-encoding
2870 oFile.write(aPngData)
2871
2872 return True
2873
2874 def attachUsbDevice(self, sUuid, sCaptureFilename = None):
2875 """
2876 Attach given USB device UUID to the VM.
2877
2878 Returns True on success
2879 Returns False on failure.
2880 """
2881 fRc = True;
2882 try:
2883 if sCaptureFilename is None:
2884 self.o.console.attachUSBDevice(sUuid, '');
2885 else:
2886 self.o.console.attachUSBDevice(sUuid, sCaptureFilename);
2887 except:
2888 reporter.logXcpt('Unable to attach USB device %s' % (sUuid,));
2889 fRc = False;
2890
2891 return fRc;
2892
2893 def detachUsbDevice(self, sUuid):
2894 """
2895 Detach given USB device UUID from the VM.
2896
2897 Returns True on success
2898 Returns False on failure.
2899 """
2900 fRc = True;
2901 try:
2902 _ = self.o.console.detachUSBDevice(sUuid);
2903 except:
2904 reporter.logXcpt('Unable to detach USB device %s' % (sUuid,));
2905 fRc = False;
2906
2907 return fRc;
2908
2909
2910 #
2911 # IMachineDebugger wrappers.
2912 #
2913
2914 def queryOsKernelLog(self):
2915 """
2916 Tries to get the OS kernel log using the VM debugger interface.
2917
2918 Returns string containing the kernel log on success.
2919 Returns None on failure.
2920 """
2921 sOsKernelLog = None;
2922 try:
2923 self.o.console.debugger.loadPlugIn('all');
2924 except:
2925 reporter.logXcpt('Unable to load debugger plugins');
2926 else:
2927 try:
2928 sOsDetected = self.o.console.debugger.detectOS();
2929 except:
2930 reporter.logXcpt('Failed to detect the guest OS');
2931 else:
2932 try:
2933 sOsKernelLog = self.o.console.debugger.queryOSKernelLog(0);
2934 except:
2935 reporter.logXcpt('Unable to get the guest OS (%s) kernel log' % (sOsDetected,));
2936 return sOsKernelLog;
2937
2938 def queryDbgInfo(self, sItem, sArg = '', sDefault = None):
2939 """
2940 Simple wrapper around IMachineDebugger::info.
2941
2942 Returns string on success, sDefault on failure (logged).
2943 """
2944 try:
2945 return self.o.console.debugger.info(sItem, sArg);
2946 except:
2947 reporter.logXcpt('Unable to query "%s" with arg "%s"' % (sItem, sArg,));
2948 return sDefault;
2949
2950 def queryDbgInfoVgaText(self, sArg = 'all'):
2951 """
2952 Tries to get the 'info vgatext' output, provided we're in next mode.
2953
2954 Returns string containing text on success.
2955 Returns None on failure or not text mode.
2956 """
2957 sVgaText = None;
2958 try:
2959 sVgaText = self.o.console.debugger.info('vgatext', sArg);
2960 if sVgaText.startswith('Not in text mode!'):
2961 sVgaText = None;
2962 except:
2963 reporter.logXcpt('Unable to query vgatext with arg "%s"' % (sArg,));
2964 return sVgaText;
2965
2966 def queryDbgGuestStack(self, iCpu = 0):
2967 """
2968 Returns the guest stack for the given VCPU.
2969
2970 Returns string containing the guest stack for the selected VCPU on success.
2971 Returns None on failure.
2972 """
2973
2974 #
2975 # Load all plugins first and try to detect the OS so we can
2976 # get nicer stack traces.
2977 #
2978 try:
2979 self.o.console.debugger.loadPlugIn('all');
2980 except:
2981 reporter.logXcpt('Unable to load debugger plugins');
2982 else:
2983 try:
2984 sOsDetected = self.o.console.debugger.detectOS();
2985 _ = sOsDetected;
2986 except:
2987 reporter.logXcpt('Failed to detect the guest OS');
2988
2989 sGuestStack = None;
2990 try:
2991 sGuestStack = self.o.console.debugger.dumpGuestStack(iCpu);
2992 except:
2993 reporter.logXcpt('Unable to query guest stack for CPU %s' % (iCpu, ));
2994
2995 return sGuestStack;
2996
2997
2998 #
2999 # Other methods.
3000 #
3001
3002 def getPrimaryIp(self):
3003 """
3004 Tries to obtain the primary IP address of the guest via the guest
3005 properties.
3006
3007 Returns IP address on success.
3008 Returns empty string on failure.
3009 """
3010 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3011 if vbox.isIpAddrValid(sIpAddr):
3012 return sIpAddr;
3013 return '';
3014
3015 def getPid(self):
3016 """
3017 Gets the process ID for the direct session unless it's ourselves.
3018 """
3019 if self.uPid is None and self.o is not None and self.fRemoteSession:
3020 try:
3021 if self.fpApiVer >= 4.2:
3022 uPid = self.o.machine.sessionPID;
3023 else:
3024 uPid = self.o.machine.sessionPid;
3025 if uPid != os.getpid() and uPid != 0xffffffff:
3026 self.uPid = uPid;
3027 except Exception as oXcpt:
3028 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
3029 try:
3030 if self.fpApiVer >= 4.2:
3031 uPid = self.oVM.sessionPID;
3032 else:
3033 uPid = self.oVM.sessionPid;
3034 if uPid != os.getpid() and uPid != 0xffffffff:
3035 self.uPid = uPid;
3036 except:
3037 reporter.log2Xcpt();
3038 else:
3039 reporter.log2Xcpt();
3040 if self.uPid is not None:
3041 reporter.log2('getPid: %u' % (self.uPid,));
3042 self.fPidFile = self.oTstDrv.pidFileAdd(self.uPid, 'vm_%s' % (self.sName,), # Set-uid-to-root is similar to SUDO.
3043 fSudo = True);
3044 return self.uPid;
3045
3046 def addLogsToReport(self, cReleaseLogs = 1):
3047 """
3048 Retrieves and adds the release and debug logs to the test report.
3049 """
3050 fRc = True;
3051
3052 # Add each of the requested release logs to the report.
3053 for iLog in range(0, cReleaseLogs):
3054 try:
3055 if self.fpApiVer >= 3.2:
3056 sLogFile = self.oVM.queryLogFilename(iLog);
3057 elif iLog > 0:
3058 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
3059 else:
3060 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
3061 except:
3062 reporter.logXcpt('iLog=%s' % (iLog,));
3063 fRc = False;
3064 else:
3065 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
3066 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
3067 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
3068
3069 # Now for the hardened windows startup log.
3070 try:
3071 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxHardening.log');
3072 except:
3073 reporter.logXcpt();
3074 fRc = False;
3075 else:
3076 if os.path.isfile(sLogFile):
3077 reporter.addLogFile(sLogFile, 'log/release/vm', '%s hardening log' % (self.sName, ),
3078 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
3079
3080 # Now for the debug log.
3081 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
3082 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
3083 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
3084
3085 return fRc;
3086
3087 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
3088 """
3089 Create an instance of the given ConsoleEventHandlerBase sub-class and
3090 register it.
3091
3092 The new instance is returned on success. None is returned on error.
3093 """
3094
3095 # We need a console object.
3096 try:
3097 oConsole = self.o.console;
3098 except Exception as oXcpt:
3099 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
3100 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
3101 return None;
3102
3103 # Add the base class arguments.
3104 dArgsCopy = dArgs.copy() if dArgs is not None else {};
3105 dArgsCopy['oSession'] = self;
3106 dArgsCopy['oConsole'] = oConsole;
3107 sLogSuffix = 'on %s' % (self.sName,)
3108 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
3109 oConsole, 'IConsole', 'IConsoleCallback',
3110 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
3111
3112 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
3113 """
3114 Enables the testing part of the VMMDev.
3115
3116 Returns True on success and False on failure. Error information is logged.
3117 """
3118 fRc = True;
3119 try:
3120 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
3121 '1' if fEnabled else '');
3122 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
3123 '1' if fEnableMMIO and fEnabled else '');
3124 except:
3125 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
3126 fRc = False;
3127 else:
3128 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
3129 self.oTstDrv.processPendingEvents();
3130 return fRc;
3131
3132 #
3133 # Test eXecution Service methods.
3134 #
3135
3136 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, fNatForwardingForTxs = False):
3137 """
3138 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
3139 addresses are specified, we'll get the IP from the guest additions.
3140
3141 Returns a TxsConnectTask object on success, None + log on failure.
3142 """
3143 # If the VM is configured with a NAT interface, connect to local host.
3144 fReversedSetup = False;
3145 fUseNatForTxs = False;
3146 sMacAddr = None;
3147 oIDhcpServer = None;
3148 if sIpAddr is None:
3149 try:
3150 oNic = self.oVM.getNetworkAdapter(0);
3151 enmAttachmentType = oNic.attachmentType;
3152 if enmAttachmentType == vboxcon.NetworkAttachmentType_NAT:
3153 fUseNatForTxs = True;
3154 elif enmAttachmentType == vboxcon.NetworkAttachmentType_HostOnly and not sIpAddr:
3155 # Get the MAC address and find the DHCP server.
3156 sMacAddr = oNic.MACAddress;
3157 sHostOnlyNIC = oNic.hostOnlyInterface;
3158 oIHostOnlyIf = self.oVBox.host.findHostNetworkInterfaceByName(sHostOnlyNIC);
3159 sHostOnlyNet = oIHostOnlyIf.networkName;
3160 oIDhcpServer = self.oVBox.findDHCPServerByNetworkName(sHostOnlyNet);
3161 except:
3162 reporter.errorXcpt();
3163 return None;
3164
3165 if fUseNatForTxs:
3166 fReversedSetup = not fNatForwardingForTxs;
3167 sIpAddr = '127.0.0.1';
3168
3169 # Kick off the task.
3170 try:
3171 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, oIDhcpServer, fReversedSetup,
3172 fnProcessEvents = self.oTstDrv.processPendingEvents);
3173 except:
3174 reporter.errorXcpt();
3175 oTask = None;
3176 return oTask;
3177
3178 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
3179 """
3180 Attempts to connect to a TXS instance.
3181
3182 Returns True if a connection was established, False if not (only grave
3183 failures are logged as errors).
3184
3185 Note! The timeout is more of a guideline...
3186 """
3187
3188 if sHostname is None or sHostname.strip() == '':
3189 raise base.GenError('Empty sHostname is not implemented yet');
3190
3191 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
3192 cMsIdleFudge = cMsTimeout // 2,
3193 fnProcessEvents = self.oTstDrv.processPendingEvents);
3194 if oTxsSession is None:
3195 return False;
3196
3197 # Wait for the connect task to time out.
3198 self.oTstDrv.addTask(oTxsSession);
3199 self.oTstDrv.processPendingEvents();
3200 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
3201 self.oTstDrv.removeTask(oTxsSession);
3202 if oRc != oTxsSession:
3203 if oRc is not None:
3204 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
3205 self.oTstDrv.processPendingEvents();
3206 oTxsSession.cancelTask(); # this is synchronous
3207 return False;
3208
3209 # Check the status.
3210 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
3211 if not oTxsSession.isSuccess():
3212 return False;
3213
3214 reporter.log2('Disconnecting from TXS...');
3215 return oTxsSession.syncDisconnect();
3216
3217
3218
3219class TxsConnectTask(TdTaskBase):
3220 """
3221 Class that takes care of connecting to a VM.
3222 """
3223
3224 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
3225 """ Class for looking for IPv4 address changes on interface 0."""
3226 def __init__(self, dArgs):
3227 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs);
3228 self.oParentTask = dArgs['oParentTask'];
3229 self.sMachineId = dArgs['sMachineId'];
3230
3231 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags, fWasDeleted):
3232 """Look for IP address."""
3233 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags, fWasDeleted));
3234 if sMachineId == self.sMachineId \
3235 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
3236 oParentTask = self.oParentTask;
3237 if oParentTask:
3238 oParentTask._setIp(sValue); # pylint: disable=protected-access
3239
3240
3241 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, oIDhcpServer, fReversedSetup, fnProcessEvents = None):
3242 TdTaskBase.__init__(self, utils.getCallerName(), fnProcessEvents = fnProcessEvents);
3243 self.cMsTimeout = cMsTimeout;
3244 self.fnProcessEvents = fnProcessEvents;
3245 self.sIpAddr = None;
3246 self.sNextIpAddr = None;
3247 self.sMacAddr = sMacAddr;
3248 self.oIDhcpServer = oIDhcpServer;
3249 self.fReversedSetup = fReversedSetup;
3250 self.oVBoxEventHandler = None;
3251 self.oTxsSession = None;
3252
3253 # Check that the input makes sense:
3254 if (sMacAddr is None) != (oIDhcpServer is None) \
3255 or (sMacAddr and fReversedSetup) \
3256 or (sMacAddr and sIpAddr):
3257 reporter.error('TxsConnectTask sMacAddr=%s oIDhcpServer=%s sIpAddr=%s fReversedSetup=%s'
3258 % (sMacAddr, oIDhcpServer, sIpAddr, fReversedSetup,));
3259 raise base.GenError();
3260
3261 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
3262 if fReversedSetup is True:
3263 self._openTcpSession(sIpAddr, fReversedSetup = True);
3264 elif sIpAddr is not None and sIpAddr.strip() != '':
3265 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3266 else:
3267 #
3268 # If we've got no IP address, register callbacks that listens for
3269 # the primary network adaptor of the VM to set a IPv4 guest prop.
3270 # Note! The order in which things are done here is kind of important.
3271 #
3272
3273 # 0. The caller zaps the property before starting the VM.
3274 #try:
3275 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3276 #except:
3277 # reporter.logXcpt();
3278
3279 # 1. Register the callback / event listener object.
3280 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
3281 self.oVBoxEventHandler = oSession.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
3282
3283 # 2. Query the guest properties.
3284 try:
3285 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3286 except:
3287 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
3288 self._deregisterEventHandler();
3289 raise;
3290 if sIpAddr is not None:
3291 self._setIp(sIpAddr);
3292
3293 #
3294 # If the network adapter of the VM is host-only we can talk poll IDHCPServer
3295 # for the guest IP, allowing us to detect it for VMs without guest additions.
3296 # This will when we're polled.
3297 #
3298 if sMacAddr is not None:
3299 assert self.oIDhcpServer is not None;
3300
3301
3302 # end __init__
3303
3304 def __del__(self):
3305 """ Make sure we deregister the callback. """
3306 self._deregisterEventHandler();
3307 return TdTaskBase.__del__(self);
3308
3309 def toString(self):
3310 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
3311 ' oTxsSession=%s oVBoxEventHandler=%s>' \
3312 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
3313 self.oTxsSession, self.oVBoxEventHandler);
3314
3315 def _deregisterEventHandler(self):
3316 """Deregisters the event handler."""
3317 fRc = True;
3318 oVBoxEventHandler = self.oVBoxEventHandler;
3319 if oVBoxEventHandler is not None:
3320 self.oVBoxEventHandler = None;
3321 fRc = oVBoxEventHandler.unregister();
3322 oVBoxEventHandler.oParentTask = None; # Try avoid cylic deps.
3323 return fRc;
3324
3325 def _setIp(self, sIpAddr, fInitCall = False):
3326 """Called when we get an IP. Will create a TXS session and signal the task."""
3327 sIpAddr = sIpAddr.strip();
3328
3329 if sIpAddr is not None \
3330 and sIpAddr != '':
3331 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
3332 try:
3333 for s in sIpAddr.split('.'):
3334 i = int(s);
3335 if str(i) != s:
3336 raise Exception();
3337 except:
3338 reporter.fatalXcpt();
3339 else:
3340 reporter.log('TxsConnectTask: opening session to ip "%s"' % (sIpAddr));
3341 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3342 return None;
3343
3344 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
3345 else:
3346 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
3347 return None;
3348
3349 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
3350 """
3351 Calls txsclient.openTcpSession and switches our task to reflect the
3352 state of the subtask.
3353 """
3354 self.oCv.acquire();
3355 if self.oTxsSession is None:
3356 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' %
3357 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
3358 self.sIpAddr = sIpAddr;
3359 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, fReversedSetup,
3360 cMsIdleFudge, fnProcessEvents = self.fnProcessEvents);
3361 self.oTxsSession.setTaskOwner(self);
3362 else:
3363 self.sNextIpAddr = sIpAddr;
3364 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
3365 self.oCv.release();
3366 return None;
3367
3368 def notifyAboutReadyTask(self, oTxsSession):
3369 """
3370 Called by the TXS session task when it's done.
3371
3372 We'll signal the task completed or retry depending on the result.
3373 """
3374
3375 self.oCv.acquire();
3376
3377 # Disassociate ourselves with the session (avoid cyclic ref)
3378 oTxsSession.setTaskOwner(None);
3379 fSuccess = oTxsSession.isSuccess();
3380 if self.oTxsSession is not None:
3381 if not fSuccess:
3382 self.oTxsSession = None;
3383 if fSuccess and self.fReversedSetup:
3384 self.sIpAddr = oTxsSession.oTransport.sHostname;
3385 else:
3386 fSuccess = False;
3387
3388 # Signal done, or retry?
3389 fDeregister = False;
3390 if fSuccess \
3391 or self.fReversedSetup \
3392 or self.getAgeAsMs() >= self.cMsTimeout:
3393 self.signalTaskLocked();
3394 fDeregister = True;
3395 else:
3396 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
3397 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3398
3399 self.oCv.release();
3400
3401 # If we're done, deregister the callback (w/o owning lock). It will
3402 if fDeregister:
3403 self._deregisterEventHandler();
3404 return True;
3405
3406 def _pollDhcpServer(self):
3407 """
3408 Polls the DHCP server by MAC address in host-only setups.
3409 """
3410
3411 if self.sIpAddr:
3412 return False;
3413
3414 if self.oIDhcpServer is None or not self.sMacAddr:
3415 return False;
3416
3417 try:
3418 (sIpAddr, sState, secIssued, secExpire) = self.oIDhcpServer.findLeaseByMAC(self.sMacAddr, 0);
3419 except:
3420 reporter.log4Xcpt('sMacAddr=%s' % (self.sMacAddr,));
3421 return False;
3422
3423 secNow = utils.secondsSinceUnixEpoch();
3424 reporter.log2('dhcp poll: secNow=%s secExpire=%s secIssued=%s sState=%s sIpAddr=%s'
3425 % (secNow, secExpire, secIssued, sState, sIpAddr,));
3426 if secNow > secExpire or sState != 'acked' or not sIpAddr:
3427 return False;
3428
3429 reporter.log('dhcp poll: sIpAddr=%s secExpire=%s (%s TTL) secIssued=%s (%s ago)'
3430 % (sIpAddr, secExpire, secExpire - secNow, secIssued, secNow - secIssued,));
3431 self._setIp(sIpAddr);
3432 return True;
3433
3434 #
3435 # Task methods
3436 #
3437
3438 def pollTask(self, fLocked = False):
3439 """
3440 Overridden pollTask method.
3441 """
3442 self._pollDhcpServer();
3443 return TdTaskBase.pollTask(self, fLocked);
3444
3445 #
3446 # Public methods
3447 #
3448
3449 def getResult(self):
3450 """
3451 Returns the connected TXS session object on success.
3452 Returns None on failure or if the task has not yet completed.
3453 """
3454 self.oCv.acquire();
3455 oTxsSession = self.oTxsSession;
3456 self.oCv.release();
3457
3458 if oTxsSession is not None and not oTxsSession.isSuccess():
3459 oTxsSession = None;
3460 return oTxsSession;
3461
3462 def cancelTask(self):
3463 """ Cancels the task. """
3464 self._deregisterEventHandler(); # (make sure to avoid cyclic fun)
3465 self.oCv.acquire();
3466 if not self.fSignalled:
3467 oTxsSession = self.oTxsSession;
3468 if oTxsSession is not None:
3469 self.oCv.release();
3470 oTxsSession.setTaskOwner(None);
3471 oTxsSession.cancelTask();
3472 oTxsSession.waitForTask(1000);
3473 self.oCv.acquire();
3474 self.signalTaskLocked();
3475 self.oCv.release();
3476 return True;
3477
3478
3479
3480class AdditionsStatusTask(TdTaskBase):
3481 """
3482 Class that takes care of waiting till the guest additions are in a given state.
3483 """
3484
3485 class AdditionsStatusTaskCallback(vbox.EventHandlerBase):
3486 """ Class for looking for IPv4 address changes on interface 0."""
3487 def __init__(self, dArgs):
3488 self.oParentTask = dArgs['oParentTask'];
3489 vbox.EventHandlerBase.__init__(self, dArgs, self.oParentTask.oSession.fpApiVer,
3490 'AdditionsStatusTaskCallback/%s' % (self.oParentTask.oSession.sName,));
3491
3492 def handleEvent(self, oEvt):
3493 try:
3494 enmType = oEvt.type;
3495 except:
3496 reporter.errorXcpt();
3497 else:
3498 reporter.log2('AdditionsStatusTaskCallback:handleEvent: enmType=%s' % (enmType,));
3499 if enmType == vboxcon.VBoxEventType_OnGuestAdditionsStatusChanged:
3500 oParentTask = self.oParentTask;
3501 if oParentTask:
3502 oParentTask.pollTask();
3503
3504 # end
3505
3506
3507 def __init__(self, oSession, oIGuest, cMsTimeout = 120000, aenmWaitForRunLevels = None, aenmWaitForActive = None,
3508 aenmWaitForInactive = None):
3509 """
3510 aenmWaitForRunLevels - List of run level values to wait for (success if one matches).
3511 aenmWaitForActive - List facilities (type values) that must be active.
3512 aenmWaitForInactive - List facilities (type values) that must be inactive.
3513
3514 The default is to wait for AdditionsRunLevelType_Userland if all three lists
3515 are unspecified or empty.
3516 """
3517 TdTaskBase.__init__(self, utils.getCallerName());
3518 self.oSession = oSession # type: vboxwrappers.SessionWrapper
3519 self.oIGuest = oIGuest;
3520 self.cMsTimeout = cMsTimeout;
3521 self.fSucceeded = False;
3522 self.oVBoxEventHandler = None;
3523 self.aenmWaitForRunLevels = aenmWaitForRunLevels if aenmWaitForRunLevels else [];
3524 self.aenmWaitForActive = aenmWaitForActive if aenmWaitForActive else [];
3525 self.aenmWaitForInactive = aenmWaitForInactive if aenmWaitForInactive else [];
3526
3527 # Provide a sensible default if nothing is given.
3528 if not self.aenmWaitForRunLevels and not self.aenmWaitForActive and not self.aenmWaitForInactive:
3529 self.aenmWaitForRunLevels = [vboxcon.AdditionsRunLevelType_Userland,];
3530
3531 # Register the event handler on hosts which has it:
3532 if oSession.fpApiVer >= 6.1 or hasattr(vboxcon, 'VBoxEventType_OnGuestAdditionsStatusChanged'):
3533 aenmEvents = (vboxcon.VBoxEventType_OnGuestAdditionsStatusChanged,);
3534 dArgs = {
3535 'oParentTask': self,
3536 };
3537 self.oVBoxEventHandler = vbox.EventHandlerBase.registerDerivedEventHandler(oSession.oVBoxMgr,
3538 oSession.fpApiVer,
3539 self.AdditionsStatusTaskCallback,
3540 dArgs,
3541 oIGuest,
3542 'IGuest',
3543 'AdditionsStatusTaskCallback',
3544 aenmEvents = aenmEvents);
3545 reporter.log2('AdditionsStatusTask: %s' % (self.toString(), ));
3546
3547 def __del__(self):
3548 """ Make sure we deregister the callback. """
3549 self._deregisterEventHandler();
3550 self.oIGuest = None;
3551 return TdTaskBase.__del__(self);
3552
3553 def toString(self):
3554 return '<%s cMsTimeout=%s, fSucceeded=%s, aenmWaitForRunLevels=%s, aenmWaitForActive=%s, aenmWaitForInactive=%s, ' \
3555 'oVBoxEventHandler=%s>' \
3556 % (TdTaskBase.toString(self), self.cMsTimeout, self.fSucceeded, self.aenmWaitForRunLevels, self.aenmWaitForActive,
3557 self.aenmWaitForInactive, self.oVBoxEventHandler,);
3558
3559 def _deregisterEventHandler(self):
3560 """Deregisters the event handler."""
3561 fRc = True;
3562 oVBoxEventHandler = self.oVBoxEventHandler;
3563 if oVBoxEventHandler is not None:
3564 self.oVBoxEventHandler = None;
3565 fRc = oVBoxEventHandler.unregister();
3566 oVBoxEventHandler.oParentTask = None; # Try avoid cylic deps.
3567 return fRc;
3568
3569 def _poll(self):
3570 """
3571 Internal worker for pollTask() that returns the new signalled state.
3572 """
3573
3574 #
3575 # Check if any of the runlevels we wait for have been reached:
3576 #
3577 if self.aenmWaitForRunLevels:
3578 try:
3579 enmRunLevel = self.oIGuest.additionsRunLevel;
3580 except:
3581 reporter.errorXcpt();
3582 return True;
3583 if enmRunLevel not in self.aenmWaitForRunLevels:
3584 reporter.log6('AdditionsStatusTask/poll: enmRunLevel=%s not in %s' % (enmRunLevel, self.aenmWaitForRunLevels,));
3585 return False;
3586 reporter.log2('AdditionsStatusTask/poll: enmRunLevel=%s matched %s!' % (enmRunLevel, self.aenmWaitForRunLevels,));
3587
3588
3589 #
3590 # Check for the facilities that must all be active.
3591 #
3592 for enmFacility in self.aenmWaitForActive:
3593 try:
3594 (enmStatus, _) = self.oIGuest.getFacilityStatus(enmFacility);
3595 except:
3596 reporter.errorXcpt('enmFacility=%s' % (enmFacility,));
3597 return True;
3598 if enmStatus != vboxcon.AdditionsFacilityStatus_Active:
3599 reporter.log2('AdditionsStatusTask/poll: enmFacility=%s not active: %s' % (enmFacility, enmStatus,));
3600 return False;
3601
3602 #
3603 # Check for the facilities that must all be inactive or terminated.
3604 #
3605 for enmFacility in self.aenmWaitForInactive:
3606 try:
3607 (enmStatus, _) = self.oIGuest.getFacilityStatus(enmFacility);
3608 except:
3609 reporter.errorXcpt('enmFacility=%s' % (enmFacility,));
3610 return True;
3611 if enmStatus not in (vboxcon.AdditionsFacilityStatus_Inactive,
3612 vboxcon.AdditionsFacilityStatus_Terminated):
3613 reporter.log2('AdditionsStatusTask/poll: enmFacility=%s not inactive: %s' % (enmFacility, enmStatus,));
3614 return False;
3615
3616
3617 reporter.log('AdditionsStatusTask: Poll succeeded, signalling...');
3618 self.fSucceeded = True;
3619 return True;
3620
3621
3622 #
3623 # Task methods
3624 #
3625
3626 def pollTask(self, fLocked = False):
3627 """
3628 Overridden pollTask method.
3629 """
3630 if not fLocked:
3631 self.lockTask();
3632
3633 fDeregister = False;
3634 fRc = self.fSignalled;
3635 if not fRc:
3636 fRc = self._poll();
3637 if fRc or self.getAgeAsMs() >= self.cMsTimeout:
3638 self.signalTaskLocked();
3639 fDeregister = True;
3640
3641 if not fLocked:
3642 self.unlockTask();
3643
3644 # If we're done, deregister the event callback (w/o owning lock).
3645 if fDeregister:
3646 self._deregisterEventHandler();
3647 return fRc;
3648
3649 def getResult(self):
3650 """
3651 Returns true if the we succeeded.
3652 Returns false if not. If the task is signalled already, then we
3653 encountered a problem while polling.
3654 """
3655 return self.fSucceeded;
3656
3657 def cancelTask(self):
3658 """
3659 Cancels the task.
3660 Just to actively disengage the event handler.
3661 """
3662 self._deregisterEventHandler();
3663 return True;
3664
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