VirtualBox

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

Last change on this file since 74901 was 72315, checked in by vboxsync, 7 years ago

ValidationKit: Add support for basic nested hardware-virtualization smoke tests.

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