VirtualBox

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

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

valkit/vboxwrappers.py: Use common.netutils functions for getting the host IP and name.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 125.0 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 72298 2018-05-23 12:24:41Z 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: 72298 $"
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 enablePae(self, fEnable):
998 """
999 Enables or disables PAE
1000 Returns True on success and False on failure. Error information is logged.
1001 """
1002 fRc = True;
1003 try:
1004 if self.fpApiVer >= 3.2: # great, ain't it?
1005 self.o.machine.setCPUProperty(vboxcon.CPUPropertyType_PAE, fEnable);
1006 else:
1007 self.o.machine.setCpuProperty(vboxcon.CpuPropertyType_PAE, fEnable);
1008 except:
1009 reporter.errorXcpt('failed to set CPUPropertyType_PAE=%s for "%s"' % (fEnable, self.sName));
1010 fRc = False;
1011 else:
1012 reporter.log('set CPUPropertyType_PAE=%s for "%s"' % (fEnable, self.sName));
1013 self.oTstDrv.processPendingEvents();
1014 return fRc;
1015
1016 def enableIoApic(self, fEnable):
1017 """
1018 Enables or disables the IO-APIC
1019 Returns True on success and False on failure. Error information is logged.
1020 """
1021 fRc = True;
1022 try:
1023 self.o.machine.BIOSSettings.IOAPICEnabled = fEnable;
1024 except:
1025 reporter.errorXcpt('failed to set BIOSSettings.IOAPICEnabled=%s for "%s"' % (fEnable, self.sName));
1026 fRc = False;
1027 else:
1028 reporter.log('set BIOSSettings.IOAPICEnabled=%s for "%s"' % (fEnable, self.sName));
1029 self.oTstDrv.processPendingEvents();
1030 return fRc;
1031
1032 def enableHpet(self, fEnable):
1033 """
1034 Enables or disables the HPET
1035 Returns True on success and False on failure. Error information is logged.
1036 """
1037 fRc = True;
1038 try:
1039 if self.fpApiVer >= 4.2:
1040 self.o.machine.HPETEnabled = fEnable;
1041 else:
1042 self.o.machine.hpetEnabled = fEnable;
1043 except:
1044 reporter.errorXcpt('failed to set HpetEnabled=%s for "%s"' % (fEnable, self.sName));
1045 fRc = False;
1046 else:
1047 reporter.log('set HpetEnabled=%s for "%s"' % (fEnable, self.sName));
1048 self.oTstDrv.processPendingEvents();
1049 return fRc;
1050
1051 def enableUsbHid(self, fEnable):
1052 """
1053 Enables or disables the USB HID
1054 Returns True on success and False on failure. Error information is logged.
1055 """
1056 fRc = True;
1057 try:
1058 if fEnable:
1059 if self.fpApiVer >= 4.3:
1060 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1061 if cOhciCtls == 0:
1062 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1063 else:
1064 self.o.machine.usbController.enabled = True;
1065
1066 if self.fpApiVer >= 4.2:
1067 self.o.machine.pointingHIDType = vboxcon.PointingHIDType_ComboMouse;
1068 self.o.machine.keyboardHIDType = vboxcon.KeyboardHIDType_ComboKeyboard;
1069 else:
1070 self.o.machine.pointingHidType = vboxcon.PointingHidType_ComboMouse;
1071 self.o.machine.keyboardHidType = vboxcon.KeyboardHidType_ComboKeyboard;
1072 else:
1073 if self.fpApiVer >= 4.2:
1074 self.o.machine.pointingHIDType = vboxcon.PointingHIDType_PS2Mouse;
1075 self.o.machine.keyboardHIDType = vboxcon.KeyboardHIDType_PS2Keyboard;
1076 else:
1077 self.o.machine.pointingHidType = vboxcon.PointingHidType_PS2Mouse;
1078 self.o.machine.keyboardHidType = vboxcon.KeyboardHidType_PS2Keyboard;
1079 except:
1080 reporter.errorXcpt('failed to change UsbHid to %s for "%s"' % (fEnable, self.sName));
1081 fRc = False;
1082 else:
1083 reporter.log('changed UsbHid to %s for "%s"' % (fEnable, self.sName));
1084 self.oTstDrv.processPendingEvents();
1085 return fRc;
1086
1087 def enableUsbOhci(self, fEnable):
1088 """
1089 Enables or disables the USB OHCI controller
1090 Returns True on success and False on failure. Error information is logged.
1091 """
1092 fRc = True;
1093 try:
1094 if fEnable:
1095 if self.fpApiVer >= 4.3:
1096 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1097 if cOhciCtls == 0:
1098 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1099 else:
1100 self.o.machine.usbController.enabled = True;
1101 else:
1102 if self.fpApiVer >= 4.3:
1103 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1104 if cOhciCtls == 1:
1105 self.o.machine.removeUSBController('OHCI');
1106 else:
1107 self.o.machine.usbController.enabled = False;
1108 except:
1109 reporter.errorXcpt('failed to change OHCI to %s for "%s"' % (fEnable, self.sName));
1110 fRc = False;
1111 else:
1112 reporter.log('changed OHCI to %s for "%s"' % (fEnable, self.sName));
1113 self.oTstDrv.processPendingEvents();
1114 return fRc;
1115
1116 def enableUsbEhci(self, fEnable):
1117 """
1118 Enables or disables the USB EHCI controller, enables also OHCI if it is still disabled.
1119 Returns True on success and False on failure. Error information is logged.
1120 """
1121 fRc = True;
1122 try:
1123 if fEnable:
1124 if self.fpApiVer >= 4.3:
1125 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1126 if cOhciCtls == 0:
1127 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1128
1129 cEhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_EHCI);
1130 if cEhciCtls == 0:
1131 self.o.machine.addUSBController('EHCI', vboxcon.USBControllerType_EHCI);
1132 else:
1133 self.o.machine.usbController.enabled = True;
1134 self.o.machine.usbController.enabledEHCI = True;
1135 else:
1136 if self.fpApiVer >= 4.3:
1137 cEhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_EHCI);
1138 if cEhciCtls == 1:
1139 self.o.machine.removeUSBController('EHCI');
1140 else:
1141 self.o.machine.usbController.enabledEHCI = False;
1142 except:
1143 reporter.errorXcpt('failed to change EHCI to %s for "%s"' % (fEnable, self.sName));
1144 fRc = False;
1145 else:
1146 reporter.log('changed EHCI to %s for "%s"' % (fEnable, self.sName));
1147 self.oTstDrv.processPendingEvents();
1148 return fRc;
1149
1150 def enableUsbXhci(self, fEnable):
1151 """
1152 Enables or disables the USB XHCI controller. Error information is logged.
1153 """
1154 fRc = True;
1155 try:
1156 if fEnable:
1157 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1158 if cXhciCtls == 0:
1159 self.o.machine.addUSBController('XHCI', vboxcon.USBControllerType_XHCI);
1160 else:
1161 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1162 if cXhciCtls == 1:
1163 self.o.machine.removeUSBController('XHCI');
1164 except:
1165 reporter.errorXcpt('failed to change XHCI to %s for "%s"' % (fEnable, self.sName));
1166 fRc = False;
1167 else:
1168 reporter.log('changed XHCI to %s for "%s"' % (fEnable, self.sName));
1169 self.oTstDrv.processPendingEvents();
1170 return fRc;
1171
1172 def setFirmwareType(self, eType):
1173 """
1174 Sets the firmware type.
1175 Returns True on success and False on failure. Error information is logged.
1176 """
1177 fRc = True;
1178 try:
1179 self.o.machine.firmwareType = eType;
1180 except:
1181 reporter.errorXcpt('failed to set firmwareType=%s for "%s"' % (eType, self.sName));
1182 fRc = False;
1183 else:
1184 reporter.log('set firmwareType=%s for "%s"' % (eType, self.sName));
1185 self.oTstDrv.processPendingEvents();
1186 return fRc;
1187
1188 def setChipsetType(self, eType):
1189 """
1190 Sets the chipset type.
1191 Returns True on success and False on failure. Error information is logged.
1192 """
1193 fRc = True;
1194 try:
1195 self.o.machine.chipsetType = eType;
1196 except:
1197 reporter.errorXcpt('failed to set chipsetType=%s for "%s"' % (eType, self.sName));
1198 fRc = False;
1199 else:
1200 reporter.log('set chipsetType=%s for "%s"' % (eType, self.sName));
1201 self.oTstDrv.processPendingEvents();
1202 return fRc;
1203
1204 def setupBootLogo(self, fEnable, cMsLogoDisplay = 0):
1205 """
1206 Sets up the boot logo. fEnable toggles the fade and boot menu
1207 settings as well as the mode.
1208 """
1209 fRc = True;
1210 try:
1211 self.o.machine.BIOSSettings.logoFadeIn = not fEnable;
1212 self.o.machine.BIOSSettings.logoFadeOut = not fEnable;
1213 self.o.machine.BIOSSettings.logoDisplayTime = cMsLogoDisplay;
1214 if fEnable:
1215 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_Disabled;
1216 else:
1217 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_MessageAndMenu;
1218 except:
1219 reporter.errorXcpt('failed to set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1220 fRc = False;
1221 else:
1222 reporter.log('set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1223 self.oTstDrv.processPendingEvents();
1224 return fRc;
1225
1226 def setupVrdp(self, fEnable, uPort = None):
1227 """
1228 Configures VRDP.
1229 """
1230 fRc = True;
1231 try:
1232 if self.fpApiVer >= 4.0:
1233 self.o.machine.VRDEServer.enabled = fEnable;
1234 else:
1235 self.o.machine.VRDPServer.enabled = fEnable;
1236 except:
1237 reporter.errorXcpt('failed to set VRDEServer::enabled=%s for "%s"' % (fEnable, self.sName));
1238 fRc = False;
1239
1240 if uPort is not None and fRc:
1241 try:
1242 if self.fpApiVer >= 4.0:
1243 self.o.machine.VRDEServer.setVRDEProperty("TCP/Ports", str(uPort));
1244 else:
1245 self.o.machine.VRDPServer.ports = str(uPort);
1246 except:
1247 reporter.errorXcpt('failed to set VRDEServer::ports=%s for "%s"' % (uPort, self.sName));
1248 fRc = False;
1249 if fRc:
1250 reporter.log('set VRDEServer.enabled/ports=%s/%s for "%s"' % (fEnable, uPort, self.sName));
1251 self.oTstDrv.processPendingEvents();
1252 return fRc;
1253
1254 def getNicDriverNameFromType(self, eNicType):
1255 """
1256 Helper that translate the adapter type into a driver name.
1257 """
1258 if eNicType == vboxcon.NetworkAdapterType_Am79C970A \
1259 or eNicType == vboxcon.NetworkAdapterType_Am79C973:
1260 sName = 'pcnet';
1261 elif eNicType == vboxcon.NetworkAdapterType_I82540EM \
1262 or eNicType == vboxcon.NetworkAdapterType_I82543GC \
1263 or eNicType == vboxcon.NetworkAdapterType_I82545EM:
1264 sName = 'e1000';
1265 elif eNicType == vboxcon.NetworkAdapterType_Virtio:
1266 sName = 'virtio-net';
1267 else:
1268 reporter.error('Unknown adapter type "%s" (VM: "%s")' % (eNicType, self.sName));
1269 sName = 'pcnet';
1270 return sName;
1271
1272 def setupNatForwardingForTxs(self, iNic = 0, iHostPort = 5042):
1273 """
1274 Sets up NAT forwarding for port 5042 if applicable, cleans up if not.
1275 """
1276 try:
1277 oNic = self.o.machine.getNetworkAdapter(iNic);
1278 except:
1279 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1280 return False;
1281
1282 # Nuke the old setup for all possible adapter types (in case we're
1283 # called after it changed).
1284 for sName in ('pcnet', 'e1000', 'virtio-net'):
1285 for sConfig in ('VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic), \
1286 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)):
1287 try:
1288 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), '');
1289 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '');
1290 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '');
1291 except:
1292 reporter.errorXcpt();
1293
1294 # Set up port forwarding if NAT attachment.
1295 try:
1296 eAttType = oNic.attachmentType;
1297 except:
1298 reporter.errorXcpt('attachmentType on %s failed for "%s"' % (iNic, self.sName));
1299 return False;
1300 if eAttType != vboxcon.NetworkAttachmentType_NAT:
1301 return True;
1302
1303 try:
1304 eNicType = oNic.adapterType;
1305 fTraceEnabled = oNic.traceEnabled;
1306 except:
1307 reporter.errorXcpt('attachmentType/traceEnabled on %s failed for "%s"' % (iNic, self.sName));
1308 return False;
1309
1310 if self.fpApiVer >= 4.1:
1311 try:
1312 if self.fpApiVer >= 4.2:
1313 oNatEngine = oNic.NATEngine;
1314 else:
1315 oNatEngine = oNic.natDriver;
1316 except:
1317 reporter.errorXcpt('Failed to get INATEngine data on "%s"' % (self.sName));
1318 return False;
1319 try: oNatEngine.removeRedirect('txs');
1320 except: pass;
1321 try:
1322 oNatEngine.addRedirect('txs', vboxcon.NATProtocol_TCP, '127.0.0.1', '%s' % (iHostPort), '', '5042');
1323 except:
1324 reporter.errorXcpt('Failed to add a addRedirect redirect on "%s"' % (self.sName));
1325 return False;
1326
1327 else:
1328 sName = self.getNicDriverNameFromType(eNicType);
1329 if fTraceEnabled:
1330 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic)
1331 else:
1332 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)
1333
1334 try:
1335 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), 'TCP');
1336 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '%s' % (iHostPort));
1337 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '5042');
1338 except:
1339 reporter.errorXcpt('Failed to set NAT extra data on "%s"' % (self.sName));
1340 return False;
1341 return True;
1342
1343 def setNicType(self, eType, iNic = 0):
1344 """
1345 Sets the NIC type of the specified NIC.
1346 Returns True on success and False on failure. Error information is logged.
1347 """
1348 try:
1349 try:
1350 oNic = self.o.machine.getNetworkAdapter(iNic);
1351 except:
1352 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1353 return False;
1354 try:
1355 oNic.adapterType = eType;
1356 except:
1357 reporter.errorXcpt('failed to set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1358 return False;
1359 finally:
1360 self.oTstDrv.processPendingEvents();
1361
1362 if not self.setupNatForwardingForTxs(iNic):
1363 return False;
1364 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1365 return True;
1366
1367 def setNicTraceEnabled(self, fTraceEnabled, sTraceFile, iNic = 0):
1368 """
1369 Sets the NIC trace enabled flag and file path.
1370 Returns True on success and False on failure. Error information is logged.
1371 """
1372 try:
1373 try:
1374 oNic = self.o.machine.getNetworkAdapter(iNic);
1375 except:
1376 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1377 return False;
1378 try:
1379 oNic.traceEnabled = fTraceEnabled;
1380 oNic.traceFile = sTraceFile;
1381 except:
1382 reporter.errorXcpt('failed to set NIC trace flag on slot %s to %s for VM "%s"' \
1383 % (iNic, fTraceEnabled, self.sName));
1384 return False;
1385 finally:
1386 self.oTstDrv.processPendingEvents();
1387
1388 if not self.setupNatForwardingForTxs(iNic):
1389 return False;
1390 reporter.log('set NIC trace on slot %s to "%s" (path "%s") for VM "%s"' %
1391 (iNic, fTraceEnabled, sTraceFile, self.sName));
1392 return True;
1393
1394 def getDefaultNicName(self, eAttachmentType):
1395 """
1396 Return the default network / interface name for the NIC attachment type.
1397 """
1398 sRetName = '';
1399 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1400 if self.oTstDrv.sDefBridgedNic is not None:
1401 sRetName = self.oTstDrv.sDefBridgedNic;
1402 else:
1403 sRetName = 'eth0';
1404 try:
1405 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1406 for oHostNic in aoHostNics:
1407 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_Bridged \
1408 and oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1409 sRetName = oHostNic.name;
1410 break;
1411 except:
1412 reporter.errorXcpt();
1413 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1414 try:
1415 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1416 for oHostNic in aoHostNics:
1417 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_HostOnly:
1418 if oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1419 sRetName = oHostNic.name;
1420 break;
1421 if sRetName == '':
1422 sRetName = oHostNic.name;
1423 except:
1424 reporter.errorXcpt();
1425 if sRetName == '':
1426 sRetName = 'HostInterfaceNetwork-vboxnet0';
1427 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1428 sRetName = 'VBoxTest';
1429 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1430 sRetName = '';
1431 else:
1432 reporter.error('eAttachmentType=%s is not known' % (eAttachmentType));
1433 return sRetName;
1434
1435 def setNicAttachment(self, eAttachmentType, sName = None, iNic = 0):
1436 """
1437 Sets the attachment type of the specified NIC.
1438 Returns True on success and False on failure. Error information is logged.
1439 """
1440 try:
1441 oNic = self.o.machine.getNetworkAdapter(iNic);
1442 except:
1443 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1444 return False;
1445
1446 try:
1447 if eAttachmentType is not None:
1448 try:
1449 if self.fpApiVer >= 4.1:
1450 oNic.attachmentType = eAttachmentType;
1451 else:
1452 if eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1453 oNic.attachToNAT();
1454 elif eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1455 oNic.attachToBridgedInterface();
1456 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1457 oNic.attachToInternalNetwork();
1458 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1459 oNic.attachToHostOnlyInterface();
1460 else:
1461 raise base.GenError("eAttachmentType=%s is invalid" % (eAttachmentType));
1462 except:
1463 reporter.errorXcpt('failed to set the attachment type on slot %s to %s for VM "%s"' \
1464 % (iNic, eAttachmentType, self.sName));
1465 return False;
1466 else:
1467 try:
1468 eAttachmentType = oNic.attachmentType;
1469 except:
1470 reporter.errorXcpt('failed to get the attachment type on slot %s for VM "%s"' % (iNic, self.sName));
1471 return False;
1472 finally:
1473 self.oTstDrv.processPendingEvents();
1474
1475 if sName is not None:
1476 # Resolve the special 'default' name.
1477 if sName == 'default':
1478 sName = self.getDefaultNicName(eAttachmentType);
1479
1480 # The name translate to different attributes depending on the
1481 # attachment type.
1482 try:
1483 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1484 ## @todo check this out on windows, may have to do a
1485 # translation of the name there or smth IIRC.
1486 try:
1487 if self.fpApiVer >= 4.1:
1488 oNic.bridgedInterface = sName;
1489 else:
1490 oNic.hostInterface = sName;
1491 except:
1492 reporter.errorXcpt('failed to set the hostInterface property on slot %s to "%s" for VM "%s"' \
1493 % (iNic, sName, self.sName));
1494 return False;
1495 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1496 try:
1497 if self.fpApiVer >= 4.1:
1498 oNic.hostOnlyInterface = sName;
1499 else:
1500 oNic.hostInterface = sName;
1501 except:
1502 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1503 % (iNic, sName, self.sName));
1504 return False;
1505 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1506 try:
1507 oNic.internalNetwork = sName;
1508 except:
1509 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1510 % (iNic, sName, self.sName));
1511 return False;
1512 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1513 try:
1514 oNic.NATNetwork = sName;
1515 except:
1516 reporter.errorXcpt('failed to set the NATNetwork property on slot %s to "%s" for VM "%s"' \
1517 % (iNic, sName, self.sName));
1518 return False;
1519 finally:
1520 self.oTstDrv.processPendingEvents();
1521
1522 if not self.setupNatForwardingForTxs(iNic):
1523 return False;
1524 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eAttachmentType, self.sName));
1525 return True;
1526
1527 def setNicMacAddress(self, sMacAddr, iNic = 0):
1528 """
1529 Sets the MAC address of the specified NIC.
1530 Returns True on success and False on failure. Error information is logged.
1531 """
1532
1533 # Resolve missing MAC address prefix by feeding in the host IP address bytes.
1534 cchMacAddr = len(sMacAddr);
1535 if cchMacAddr > 0 and cchMacAddr < 12:
1536 sHostIP = netutils.getPrimaryHostIp();
1537 abHostIP = socket.inet_aton(sHostIP);
1538 if sys.version_info[0] < 3:
1539 abHostIP = (ord(abHostIP[0]), ord(abHostIP[1]), ord(abHostIP[2]), ord(abHostIP[3]));
1540
1541 if abHostIP[0] == 127 \
1542 or (abHostIP[0] == 169 and abHostIP[1] == 254) \
1543 or (abHostIP[0] == 192 and abHostIP[1] == 168 and abHostIP[2] == 56):
1544 return reporter.error('host IP for "%s" is %s, most likely not unique.' % (netutils.getHostnameFqdn(), sHostIP,));
1545
1546 sDefaultMac = '%02X%02X%02X%02X%02X%02X' % (0x02, abHostIP[0], abHostIP[1], abHostIP[2], abHostIP[3], iNic);
1547 sMacAddr = sDefaultMac[0:(12 - cchMacAddr)] + sMacAddr;
1548
1549 # Get the NIC object and try set it address.
1550 try:
1551 oNic = self.o.machine.getNetworkAdapter(iNic);
1552 except:
1553 return reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName,));
1554
1555 try:
1556 oNic.MACAddress = sMacAddr;
1557 except:
1558 return reporter.errorXcpt('failed to set the MAC address on slot %s to "%s" for VM "%s"'
1559 % (iNic, sMacAddr, self.sName));
1560
1561 reporter.log('set MAC address on slot %s to %s for VM "%s"' % (iNic, sMacAddr, self.sName,));
1562 return True;
1563
1564 def setRamSize(self, cMB):
1565 """
1566 Set the RAM size of the VM.
1567 Returns True on success and False on failure. Error information is logged.
1568 """
1569 fRc = True;
1570 try:
1571 self.o.machine.memorySize = cMB;
1572 except:
1573 reporter.errorXcpt('failed to set the RAM size of "%s" to %s' % (self.sName, cMB));
1574 fRc = False;
1575 else:
1576 reporter.log('set the RAM size of "%s" to %s' % (self.sName, cMB));
1577 self.oTstDrv.processPendingEvents();
1578 return fRc;
1579
1580 def setVRamSize(self, cMB):
1581 """
1582 Set the RAM size of the VM.
1583 Returns True on success and False on failure. Error information is logged.
1584 """
1585 fRc = True;
1586 try:
1587 self.o.machine.VRAMSize = cMB;
1588 except:
1589 reporter.errorXcpt('failed to set the VRAM size of "%s" to %s' % (self.sName, cMB));
1590 fRc = False;
1591 else:
1592 reporter.log('set the VRAM size of "%s" to %s' % (self.sName, cMB));
1593 self.oTstDrv.processPendingEvents();
1594 return fRc;
1595
1596 def setCpuCount(self, cCpus):
1597 """
1598 Set the number of CPUs.
1599 Returns True on success and False on failure. Error information is logged.
1600 """
1601 fRc = True;
1602 try:
1603 self.o.machine.CPUCount = cCpus;
1604 except:
1605 reporter.errorXcpt('failed to set the CPU count of "%s" to %s' % (self.sName, cCpus));
1606 fRc = False;
1607 else:
1608 reporter.log('set the CPU count of "%s" to %s' % (self.sName, cCpus));
1609 self.oTstDrv.processPendingEvents();
1610 return fRc;
1611
1612 def getCpuCount(self):
1613 """
1614 Returns the number of CPUs.
1615 Returns the number of CPUs on success and 0 on failure. Error information is logged.
1616 """
1617 cCpus = 0;
1618 try:
1619 cCpus = self.o.machine.CPUCount;
1620 except:
1621 reporter.errorXcpt('failed to get the CPU count of "%s"' % (self.sName,));
1622
1623 self.oTstDrv.processPendingEvents();
1624 return cCpus;
1625
1626 def ensureControllerAttached(self, sController):
1627 """
1628 Makes sure the specified controller is attached to the VM, attaching it
1629 if necessary.
1630 """
1631 try:
1632 try:
1633 self.o.machine.getStorageControllerByName(sController);
1634 except:
1635 (eBus, eType) = _ControllerNameToBusAndType(sController);
1636 try:
1637 oCtl = self.o.machine.addStorageController(sController, eBus);
1638 except:
1639 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, eBus, self.sName) );
1640 return False;
1641 else:
1642 try:
1643 oCtl.controllerType = eType;
1644 reporter.log('added storage controller "%s" (bus %s, type %s) to %s'
1645 % (sController, eBus, eType, self.sName));
1646 except:
1647 reporter.errorXcpt('controllerType = %s on ("%s" / %s) failed on "%s"'
1648 % (eType, sController, eBus, self.sName) );
1649 return False;
1650 finally:
1651 self.oTstDrv.processPendingEvents();
1652 return True;
1653
1654 def setStorageControllerPortCount(self, sController, iPortCount):
1655 """
1656 Set maximum ports count for storage controller
1657 """
1658 try:
1659 oCtl = self.o.machine.getStorageControllerByName(sController)
1660 oCtl.portCount = iPortCount
1661 self.oTstDrv.processPendingEvents()
1662 reporter.log('set controller "%s" port count to value %d' % (sController, iPortCount))
1663 return True
1664 except:
1665 reporter.log('unable to set storage controller "%s" ports count to %d' % (sController, iPortCount))
1666
1667 return False
1668
1669 def setStorageControllerHostIoCache(self, sController, fUseHostIoCache):
1670 """
1671 Set maximum ports count for storage controller
1672 """
1673 try:
1674 oCtl = self.o.machine.getStorageControllerByName(sController);
1675 oCtl.useHostIOCache = fUseHostIoCache;
1676 self.oTstDrv.processPendingEvents();
1677 reporter.log('set controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1678 return True;
1679 except:
1680 reporter.log('unable to set storage controller "%s" host I/O cache setting to %r' % (sController, fUseHostIoCache));
1681
1682 return False;
1683
1684 def setBootOrder(self, iPosition, eType):
1685 """
1686 Set guest boot order type
1687 @param iPosition boot order position
1688 @param eType device type (vboxcon.DeviceType_HardDisk,
1689 vboxcon.DeviceType_DVD, vboxcon.DeviceType_Floppy)
1690 """
1691 try:
1692 self.o.machine.setBootOrder(iPosition, eType)
1693 except:
1694 return reporter.errorXcpt('Unable to set boot order.')
1695
1696 reporter.log('Set boot order [%d] for device %s' % (iPosition, str(eType)))
1697 self.oTstDrv.processPendingEvents();
1698
1699 return True
1700
1701 def setStorageControllerType(self, eType, sController = "IDE Controller"):
1702 """
1703 Similar to ensureControllerAttached, except it will change the type.
1704 """
1705 try:
1706 oCtl = self.o.machine.getStorageControllerByName(sController);
1707 except:
1708 (eBus, _) = _ControllerNameToBusAndType(sController);
1709 try:
1710 oCtl = self.o.machine.addStorageController(sController, eBus);
1711 reporter.log('added storage controller "%s" (bus %s) to %s' % (sController, eBus, self.sName));
1712 except:
1713 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, eBus, self.sName) );
1714 return False;
1715 try:
1716 oCtl.controllerType = eType;
1717 except:
1718 reporter.errorXcpt('failed to set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1719 return False;
1720 reporter.log('set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1721 self.oTstDrv.processPendingEvents();
1722 return True;
1723
1724 def attachDvd(self, sImage = None, sController = "IDE Controller", iPort = 1, iDevice = 0):
1725 """
1726 Attaches a DVD drive to a VM, optionally with an ISO inserted.
1727 Returns True on success and False on failure. Error information is logged.
1728 """
1729 # Input validation.
1730 if sImage is not None and not self.oTstDrv.isResourceFile(sImage)\
1731 and not os.path.isabs(sImage): ## fixme - testsuite unzip ++
1732 reporter.fatal('"%s" is not in the resource set' % (sImage));
1733 return None;
1734
1735 if not self.ensureControllerAttached(sController):
1736 return False;
1737
1738 # Find/register the image if specified.
1739 oImage = None;
1740 sImageUuid = "";
1741 if sImage is not None:
1742 sFullName = self.oTstDrv.getFullResourceName(sImage)
1743 try:
1744 oImage = self.oVBox.findDVDImage(sFullName);
1745 except:
1746 try:
1747 if self.fpApiVer >= 4.1:
1748 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly, False);
1749 elif self.fpApiVer >= 4.0:
1750 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly);
1751 else:
1752 oImage = self.oVBox.openDVDImage(sFullName, "");
1753 except vbox.ComException as oXcpt:
1754 if oXcpt.errno != -1:
1755 reporter.errorXcpt('failed to open DVD image "%s" xxx' % (sFullName));
1756 else:
1757 reporter.errorXcpt('failed to open DVD image "%s" yyy' % (sFullName));
1758 return False;
1759 except:
1760 reporter.errorXcpt('failed to open DVD image "%s"' % (sFullName));
1761 return False;
1762 try:
1763 sImageUuid = oImage.id;
1764 except:
1765 reporter.errorXcpt('failed to get the UUID of "%s"' % (sFullName));
1766 return False;
1767
1768 # Attach the DVD.
1769 fRc = True;
1770 try:
1771 if self.fpApiVer >= 4.0:
1772 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, oImage);
1773 else:
1774 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, sImageUuid);
1775 except:
1776 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1777 % (sController, iPort, iDevice, sImageUuid, self.sName) );
1778 fRc = False;
1779 else:
1780 reporter.log('attached DVD to %s, image="%s"' % (self.sName, sImage));
1781 self.oTstDrv.processPendingEvents();
1782 return fRc;
1783
1784 def attachHd(self, sHd, sController = "IDE Controller", iPort = 0, iDevice = 0, fImmutable = True, fForceResource = True):
1785 """
1786 Attaches a HD to a VM.
1787 Returns True on success and False on failure. Error information is logged.
1788 """
1789 # Input validation.
1790 if fForceResource and not self.oTstDrv.isResourceFile(sHd):
1791 reporter.fatal('"%s" is not in the resource set' % (sHd,));
1792 return None;
1793
1794 if not self.ensureControllerAttached(sController):
1795 return False;
1796
1797 # Find the HD, registering it if necessary (as immutable).
1798 if fForceResource:
1799 sFullName = self.oTstDrv.getFullResourceName(sHd);
1800 else:
1801 sFullName = sHd;
1802 try:
1803 oHd = self.oVBox.findHardDisk(sFullName);
1804 except:
1805 try:
1806 if self.fpApiVer >= 4.1:
1807 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
1808 elif self.fpApiVer >= 4.0:
1809 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
1810 else:
1811 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
1812 except:
1813 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
1814 return False;
1815 try:
1816 if fImmutable:
1817 oHd.type = vboxcon.MediumType_Immutable;
1818 else:
1819 oHd.type = vboxcon.MediumType_Normal;
1820 except:
1821 if fImmutable:
1822 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1823 else:
1824 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1825 return False;
1826
1827 # Attach it.
1828 fRc = True;
1829 try:
1830 if self.fpApiVer >= 4.0:
1831 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1832 else:
1833 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1834 except:
1835 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1836 % (sController, iPort, iDevice, oHd.id, self.sName) );
1837 fRc = False;
1838 else:
1839 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1840 self.oTstDrv.processPendingEvents();
1841 return fRc;
1842
1843 def createBaseHd(self, sHd, sFmt = "VDI", cb = 10*1024*1024*1024, cMsTimeout = 60000, tMediumVariant = None):
1844 """
1845 Creates a base HD.
1846 Returns Medium object on success and None on failure. Error information is logged.
1847 """
1848 if tMediumVariant is None:
1849 tMediumVariant = (vboxcon.MediumVariant_Standard, );
1850
1851 try:
1852 if self.fpApiVer >= 5.0:
1853 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1854 else:
1855 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1856 oProgressXpcom = oHd.createBaseStorage(cb, tMediumVariant);
1857 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create base disk %s' % (sHd));
1858 oProgress.wait(cMsTimeout);
1859 oProgress.logResult();
1860 except:
1861 reporter.errorXcpt('failed to create base hd "%s"' % (sHd));
1862 oHd = None
1863
1864 return oHd;
1865
1866 def createDiffHd(self, oParentHd, sHd, sFmt = "VDI"):
1867 """
1868 Creates a differencing HD.
1869 Returns Medium object on success and None on failure. Error information is logged.
1870 """
1871 # Detect the proper format if requested
1872 if sFmt is None:
1873 try:
1874 oHdFmt = oParentHd.mediumFormat;
1875 lstCaps = self.oVBoxMgr.getArray(oHdFmt, 'capabilities');
1876 if vboxcon.MediumFormatCapabilities_Differencing in lstCaps:
1877 sFmt = oHdFmt.id;
1878 else:
1879 sFmt = 'VDI';
1880 except:
1881 reporter.errorXcpt('failed to get preferred diff format for "%s"' % (sHd));
1882 return None;
1883 try:
1884 if self.fpApiVer >= 5.0:
1885 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1886 else:
1887 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1888 oProgressXpcom = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
1889 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
1890 oProgress.wait();
1891 oProgress.logResult();
1892 except:
1893 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
1894 oHd = None
1895
1896 return oHd;
1897
1898 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, # pylint: disable=R0913
1899 iPort = 0, iDevice = 0, fImmutable = True, cMsTimeout = 60000, tMediumVariant = None):
1900 """
1901 Creates and attaches a HD to a VM.
1902 Returns True on success and False on failure. Error information is logged.
1903 """
1904 if not self.ensureControllerAttached(sController):
1905 return False;
1906
1907 oHd = self.createBaseHd(sHd, sFmt, cb, cMsTimeout, tMediumVariant);
1908 if oHd is None:
1909 return False;
1910
1911 fRc = True;
1912 try:
1913 if fImmutable:
1914 oHd.type = vboxcon.MediumType_Immutable;
1915 else:
1916 oHd.type = vboxcon.MediumType_Normal;
1917 except:
1918 if fImmutable:
1919 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1920 else:
1921 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1922 fRc = False;
1923
1924 # Attach it.
1925 if fRc is True:
1926 try:
1927 if self.fpApiVer >= 4.0:
1928 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1929 else:
1930 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1931 except:
1932 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1933 % (sController, iPort, iDevice, oHd.id, self.sName) );
1934 fRc = False;
1935 else:
1936 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1937
1938 # Delete disk in case of an error
1939 if fRc is False:
1940 try:
1941 oProgressCom = oHd.deleteStorage();
1942 except:
1943 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
1944 else:
1945 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
1946 oProgress.wait();
1947 oProgress.logResult();
1948
1949 self.oTstDrv.processPendingEvents();
1950 return fRc;
1951
1952 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
1953 """
1954 Detaches a HD, if attached, and returns a reference to it (IMedium).
1955
1956 In order to delete the detached medium, the caller must first save
1957 the changes made in this session.
1958
1959 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
1960 your standard success indicator. Error information is logged.
1961 """
1962
1963 # What's attached?
1964 try:
1965 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
1966 except:
1967 if self.oVBoxMgr.xcptIsOurXcptKind() \
1968 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
1969 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
1970 return (True, None);
1971 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
1972 % (iPort, iDevice, sController)), None);
1973 # Detach it.
1974 try:
1975 self.o.machine.detachDevice(sController, iPort, iDevice);
1976 except:
1977 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
1978 % (sController, iPort, iDevice, self.sName) ), None);
1979 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
1980 return (True, oHd);
1981
1982 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
1983 """
1984 Attaches a floppy image to a VM.
1985 Returns True on success and False on failure. Error information is logged.
1986 """
1987 # Input validation.
1988 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
1989 ##if not self.oTstDrv.isResourceFile(sFloppy):
1990 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
1991 ## return None;
1992
1993 if not self.ensureControllerAttached(sController):
1994 return False;
1995
1996 # Find the floppy image, registering it if necessary (as immutable).
1997 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
1998 try:
1999 oFloppy = self.oVBox.findFloppyImage(sFullName);
2000 except:
2001 try:
2002 if self.fpApiVer >= 4.1:
2003 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
2004 elif self.fpApiVer >= 4.0:
2005 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
2006 else:
2007 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
2008 except:
2009 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
2010 return False;
2011 ## @todo the following works but causes trouble below (asserts in main).
2012 #try:
2013 # oFloppy.type = vboxcon.MediumType_Immutable;
2014 #except:
2015 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
2016 # return False;
2017
2018 # Attach it.
2019 fRc = True;
2020 try:
2021 if self.fpApiVer >= 4.0:
2022 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
2023 else:
2024 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
2025 except:
2026 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
2027 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
2028 fRc = False;
2029 else:
2030 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
2031 self.oTstDrv.processPendingEvents();
2032 return fRc;
2033
2034 def setupNic(self, sType, sXXX):
2035 """
2036 Sets up a NIC to a VM.
2037 Returns True on success and False on failure. Error information is logged.
2038 """
2039 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
2040 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
2041 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
2042 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
2043 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
2044 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
2045 else:
2046 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
2047 return False;
2048 ## @todo Implement me!
2049 if enmType is not None: pass
2050 return True;
2051
2052 def setupAudio(self, eAudioControllerType, fEnable = True, eAudioDriverType = None):
2053 """
2054 Sets up audio.
2055
2056 :param eAudioControllerType: The audio controller type (vboxcon.AudioControllerType_XXX).
2057 :param fEnable: Whether to enable or disable the audio controller (default enable).
2058 :param eAudioDriverType: The audio driver type (vboxcon.AudioDriverType_XXX), picks something suitable
2059 if None is passed (default).
2060 """
2061 try: oAudioAdapter = self.o.machine.audioAdapter;
2062 except: return reporter.errorXcpt('Failed to get the audio adapter.');
2063
2064 try: oAudioAdapter.audioController = eAudioControllerType;
2065 except: return reporter.errorXcpt('Failed to set the audio controller to %s.' % (eAudioControllerType,));
2066
2067 if eAudioDriverType is None:
2068 sHost = utils.getHostOs()
2069 if sHost == 'darwin': eAudioDriverType = vboxcon.AudioDriverType_CoreAudio;
2070 elif sHost == 'win': eAudioDriverType = vboxcon.AudioDriverType_DirectSound;
2071 elif sHost == 'linux': eAudioDriverType = vboxcon.AudioDriverType_Pulse;
2072 elif sHost == 'solaris': eAudioDriverType = vboxcon.AudioDriverType_OSS;
2073 else:
2074 reporter.error('PORTME: Do not know which audio driver to pick for: %s!' % (sHost,));
2075 eAudioDriverType = vboxcon.AudioDriverType_Null;
2076
2077 try: oAudioAdapter.audioDriver = eAudioDriverType;
2078 except: return reporter.errorXcpt('Failed to set the audio driver to %s.' % (eAudioDriverType,))
2079
2080 try: oAudioAdapter.enabled = fEnable;
2081 except: return reporter.errorXcpt('Failed to set the "enabled" property to %s.' % (fEnable,));
2082
2083 reporter.log('set audio adapter type to %d, driver to %d, and enabled to %s'
2084 % (eAudioControllerType, eAudioDriverType, fEnable,));
2085 self.oTstDrv.processPendingEvents();
2086 return True;
2087
2088 def setupPreferredConfig(self): # pylint: disable=R0914
2089 """
2090 Configures the VM according to the preferences of the guest type.
2091 """
2092 try:
2093 sOsTypeId = self.o.machine.OSTypeId;
2094 except:
2095 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2096 return False;
2097
2098 try:
2099 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2100 except:
2101 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2102 return False;
2103
2104 # get the attributes.
2105 try:
2106 #sFamilyId = oOsType.familyId;
2107 #f64Bit = oOsType.is64Bit;
2108 fIoApic = oOsType.recommendedIOAPIC;
2109 fVirtEx = oOsType.recommendedVirtEx;
2110 cMBRam = oOsType.recommendedRAM;
2111 cMBVRam = oOsType.recommendedVRAM;
2112 #cMBHdd = oOsType.recommendedHDD;
2113 eNicType = oOsType.adapterType;
2114 if self.fpApiVer >= 3.2:
2115 if self.fpApiVer >= 4.2:
2116 fPae = oOsType.recommendedPAE;
2117 fUsbHid = oOsType.recommendedUSBHID;
2118 fHpet = oOsType.recommendedHPET;
2119 eStorCtlType = oOsType.recommendedHDStorageController;
2120 else:
2121 fPae = oOsType.recommendedPae;
2122 fUsbHid = oOsType.recommendedUsbHid;
2123 fHpet = oOsType.recommendedHpet;
2124 eStorCtlType = oOsType.recommendedHdStorageController;
2125 eFirmwareType = oOsType.recommendedFirmware;
2126 else:
2127 fPae = False;
2128 fUsbHid = False;
2129 fHpet = False;
2130 eFirmwareType = -1;
2131 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
2132 if self.fpApiVer >= 4.0:
2133 eAudioCtlType = oOsType.recommendedAudioController;
2134 except:
2135 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
2136 self.oTstDrv.processPendingEvents();
2137 return False;
2138 self.oTstDrv.processPendingEvents();
2139
2140 # Do the setting. Continue applying settings on error in case the
2141 # caller ignores the return code
2142 fRc = True;
2143 if not self.enableIoApic(fIoApic): fRc = False;
2144 if not self.enableVirtEx(fVirtEx): fRc = False;
2145 if not self.enablePae(fPae): fRc = False;
2146 if not self.setRamSize(cMBRam): fRc = False;
2147 if not self.setVRamSize(cMBVRam): fRc = False;
2148 if not self.setNicType(eNicType, 0): fRc = False;
2149 if self.fpApiVer >= 3.2:
2150 if not self.setFirmwareType(eFirmwareType): fRc = False;
2151 if not self.enableUsbHid(fUsbHid): fRc = False;
2152 if not self.enableHpet(fHpet): fRc = False;
2153 if eStorCtlType == vboxcon.StorageControllerType_PIIX3 \
2154 or eStorCtlType == vboxcon.StorageControllerType_PIIX4 \
2155 or eStorCtlType == vboxcon.StorageControllerType_ICH6:
2156 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
2157 fRc = False;
2158 if self.fpApiVer >= 4.0:
2159 if not self.setupAudio(eAudioCtlType): fRc = False;
2160
2161 return fRc;
2162
2163 def addUsbDeviceFilter(self, sName, sVendorId = None, sProductId = None, sRevision = None, # pylint: disable=R0913
2164 sManufacturer = None, sProduct = None, sSerialNumber = None,
2165 sPort = None, sRemote = None):
2166 """
2167 Creates a USB device filter and inserts it into the VM.
2168 Returns True on success.
2169 Returns False on failure (logged).
2170 """
2171 fRc = True;
2172
2173 try:
2174 oUsbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
2175 oUsbDevFilter.active = True;
2176 if sVendorId is not None:
2177 oUsbDevFilter.vendorId = sVendorId;
2178 if sProductId is not None:
2179 oUsbDevFilter.productId = sProductId;
2180 if sRevision is not None:
2181 oUsbDevFilter.revision = sRevision;
2182 if sManufacturer is not None:
2183 oUsbDevFilter.manufacturer = sManufacturer;
2184 if sProduct is not None:
2185 oUsbDevFilter.product = sProduct;
2186 if sSerialNumber is not None:
2187 oUsbDevFilter.serialnumber = sSerialNumber;
2188 if sPort is not None:
2189 oUsbDevFilter.port = sPort;
2190 if sRemote is not None:
2191 oUsbDevFilter.remote = sRemote;
2192 try:
2193 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, oUsbDevFilter);
2194 except:
2195 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
2196 % (0, self.sName) );
2197 fRc = False;
2198 else:
2199 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
2200 except:
2201 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
2202 % (sName, self.sName) );
2203 fRc = False;
2204 return fRc;
2205
2206 def getGuestPropertyValue(self, sName):
2207 """
2208 Gets a guest property value.
2209 Returns the value on success, None on failure (logged).
2210 """
2211 try:
2212 sValue = self.o.machine.getGuestPropertyValue(sName);
2213 except:
2214 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2215 return None;
2216 return sValue;
2217
2218 def setGuestPropertyValue(self, sName, sValue):
2219 """
2220 Sets a guest property value.
2221 Returns the True on success, False on failure (logged).
2222 """
2223 try:
2224 self.o.machine.setGuestPropertyValue(sName, sValue);
2225 except:
2226 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2227 return False;
2228 return True;
2229
2230 def delGuestPropertyValue(self, sName):
2231 """
2232 Deletes a guest property value.
2233 Returns the True on success, False on failure (logged).
2234 """
2235 try:
2236 oMachine = self.o.machine;
2237 if self.fpApiVer >= 4.2:
2238 oMachine.deleteGuestProperty(sName);
2239 else:
2240 oMachine.setGuestPropertyValue(sName, '');
2241 except:
2242 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2243 return False;
2244 return True;
2245
2246 def setExtraData(self, sKey, sValue):
2247 """
2248 Sets extra data.
2249 Returns the True on success, False on failure (logged).
2250 """
2251 try:
2252 self.o.machine.setExtraData(sKey, sValue);
2253 except:
2254 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2255 return False;
2256 return True;
2257
2258 def getExtraData(self, sKey):
2259 """
2260 Gets extra data.
2261 Returns value on success, None on failure.
2262 """
2263 try:
2264 sValue = self.o.machine.getExtraData(sKey)
2265 except:
2266 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue))
2267 return None
2268 return sValue
2269
2270 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2271 """
2272 Sets up the teleporter for the VM.
2273 Returns True on success, False on failure (logged).
2274 """
2275 try:
2276 self.o.machine.teleporterAddress = sAddress;
2277 self.o.machine.teleporterPort = uPort;
2278 self.o.machine.teleporterPassword = sPassword;
2279 self.o.machine.teleporterEnabled = fEnabled;
2280 except:
2281 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2282 return False;
2283 return True;
2284
2285 def enableTeleporter(self, fEnable=True):
2286 """
2287 Enables or disables the teleporter of the VM.
2288 Returns True on success, False on failure (logged).
2289 """
2290 try:
2291 self.o.machine.teleporterEnabled = fEnable;
2292 except:
2293 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2294 return False;
2295 return True;
2296
2297 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2298 """
2299 Wrapper around the IConsole::teleport() method.
2300 Returns a progress object on success, None on failure (logged).
2301 """
2302 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2303 try:
2304 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2305 except:
2306 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2307 return None;
2308 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2309
2310 def getOsType(self):
2311 """
2312 Gets the IGuestOSType interface for the machine.
2313
2314 return IGuestOSType interface on success, None + errorXcpt on failure.
2315 No exceptions raised.
2316 """
2317 try:
2318 sOsTypeId = self.o.machine.OSTypeId;
2319 except:
2320 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2321 return None;
2322
2323 try:
2324 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2325 except:
2326 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2327 return None;
2328
2329 return oOsType;
2330
2331 def setOsType(self, sNewTypeId):
2332 """
2333 Changes the OS type.
2334
2335 returns True on success, False + errorXcpt on failure.
2336 No exceptions raised.
2337 """
2338 try:
2339 self.o.machine.OSTypeId = sNewTypeId;
2340 except:
2341 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2342 return False;
2343 return True;
2344
2345
2346 def setParavirtProvider(self, iProvider):
2347 """
2348 Sets a paravirtualisation provider.
2349 Returns the True on success, False on failure (logged).
2350 """
2351 try:
2352 self.o.machine.paravirtProvider = iProvider
2353 except:
2354 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2355 return False;
2356 return True;
2357
2358
2359 def setupSerialToRawFile(self, iSerialPort, sRawFile):
2360 """
2361 Enables the given serial port (zero based) and redirects it to sRawFile.
2362 Returns the True on success, False on failure (logged).
2363 """
2364 try:
2365 oPort = self.o.machine.getSerialPort(iSerialPort);
2366 except:
2367 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2368 else:
2369 try:
2370 oPort.path = sRawFile;
2371 except:
2372 fRc = reporter.errorXcpt('failed to set the "path" property on serial port #%u to "%s"'
2373 % (iSerialPort, sRawFile));
2374 else:
2375 try:
2376 oPort.hostMode = vboxcon.PortMode_RawFile;
2377 except:
2378 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_RawFile'
2379 % (iSerialPort,));
2380 else:
2381 try:
2382 oPort.enabled = True;
2383 except:
2384 fRc = reporter.errorXcpt('failed to set the "enable" property on serial port #%u to True'
2385 % (iSerialPort,));
2386 else:
2387 reporter.log('set SerialPort[%s].enabled/hostMode/path=True/RawFile/%s' % (iSerialPort, sRawFile,));
2388 fRc = True;
2389 self.oTstDrv.processPendingEvents();
2390 return fRc;
2391
2392
2393 def enableSerialPort(self, iSerialPort):
2394 """
2395 Enables the given serial port setting the initial port mode to disconnected.
2396 """
2397 try:
2398 oPort = self.o.machine.getSerialPort(iSerialPort);
2399 except:
2400 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2401 else:
2402 try:
2403 oPort.hostMode = vboxcon.PortMode_Disconnected;
2404 except:
2405 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_Disconnected'
2406 % (iSerialPort,));
2407 else:
2408 try:
2409 oPort.enabled = True;
2410 except:
2411 fRc = reporter.errorXcpt('failed to set the "enable" property on serial port #%u to True'
2412 % (iSerialPort,));
2413 else:
2414 reporter.log('set SerialPort[%s].enabled/hostMode/=True/Disconnected' % (iSerialPort,));
2415 fRc = True;
2416 self.oTstDrv.processPendingEvents();
2417 return fRc;
2418
2419
2420 def changeSerialPortAttachment(self, iSerialPort, ePortMode, sPath, fServer):
2421 """
2422 Changes the attachment of the given serial port to the attachment config given.
2423 """
2424 try:
2425 oPort = self.o.machine.getSerialPort(iSerialPort);
2426 except:
2427 fRc = reporter.errorXcpt('failed to get serial port #%u' % (iSerialPort,));
2428 else:
2429 try:
2430 # Change port mode to disconnected first so changes get picked up by a potentially running VM.
2431 oPort.hostMode = vboxcon.PortMode_Disconnected;
2432 except:
2433 fRc = reporter.errorXcpt('failed to set the "hostMode" property on serial port #%u to PortMode_Disconnected'
2434 % (iSerialPort,));
2435 else:
2436 try:
2437 oPort.path = sPath;
2438 oPort.server = fServer;
2439 oPort.hostMode = ePortMode;
2440 except:
2441 fRc = reporter.errorXcpt('failed to configure the serial port');
2442 else:
2443 reporter.log('set SerialPort[%s].hostMode/path/server=%s/%s/%s'
2444 % (iSerialPort, ePortMode, sPath, fServer));
2445 fRc = True;
2446 self.oTstDrv.processPendingEvents();
2447 return fRc;
2448
2449 #
2450 # IConsole wrappers.
2451 #
2452
2453 def powerOff(self, fFudgeOnFailure = True):
2454 """
2455 Powers off the VM.
2456
2457 Returns True on success.
2458 Returns False on IConsole::powerDown() failure.
2459 Returns None if the progress object returns failure.
2460 """
2461 #
2462 # Deregister event handler before we power off the VM, otherwise we're
2463 # racing for VM process termination and cause misleading spurious
2464 # error messages in the event handling code, because the event objects
2465 # disappear.
2466 #
2467 # Note! Doing this before powerDown to try prevent numerous smoketest
2468 # timeouts on XPCOM hosts.
2469 #
2470 self.deregisterEventHandlerForTask();
2471
2472
2473 # Try power if off.
2474 try:
2475 oProgress = self.o.console.powerDown();
2476 except:
2477 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2478 if fFudgeOnFailure:
2479 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2480 self.waitForTask(1000); # fudge
2481 return False;
2482
2483 # Wait on power off operation to complete.
2484 rc = self.oTstDrv.waitOnProgress(oProgress);
2485 if rc < 0:
2486 self.close();
2487 if fFudgeOnFailure:
2488 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2489 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2490 return None;
2491
2492 # Wait for the VM to really power off or we'll fail to open a new session to it.
2493 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2494 return self.waitForTask(30 * 1000); # fudge
2495
2496 def saveState(self, fPause = True):
2497 """
2498 Saves state of the VM.
2499
2500 Returns True on success.
2501 Returns False on IConsole::saveState() failure.
2502 Returns None if the progress object returns Failure.
2503 """
2504
2505 if fPause is True \
2506 and self.oVM.state is vboxcon.MachineState_Running:
2507 self.o.console.pause();
2508 if self.oVM.state is not vboxcon.MachineState_Paused:
2509 reporter.error('pause for "%s" failed' % (self.sName));
2510 # Try saving state.
2511 try:
2512 if self.fpApiVer >= 5.0:
2513 oProgress = self.o.machine.saveState()
2514 else:
2515 oProgress = self.o.console.saveState()
2516 except:
2517 reporter.logXcpt('IMachine::saveState failed on %s' % (self.sName));
2518 return False;
2519
2520 # Wait for saving state operation to complete.
2521 rc = self.oTstDrv.waitOnProgress(oProgress);
2522 if rc < 0:
2523 self.close();
2524 return None;
2525
2526 # Wait for the VM to really terminate or we'll fail to open a new session to it.
2527 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2528 return self.waitForTask(30 * 1000); # fudge
2529
2530 def discardSavedState(self, fRemove = True):
2531 """
2532 Discards saved state of the VM.
2533
2534 Returns True on success.
2535 Returns False on IConsole::discardSaveState() failure.
2536 """
2537
2538 try:
2539 if self.fpApiVer >= 5.0:
2540 self.o.machine.discardSavedState(fRemove)
2541 else:
2542 self.o.console.discardSavedState(fRemove)
2543 except:
2544 reporter.logXcpt('IMachine::discardSavedState failed on %s' % (self.sName))
2545 return False
2546 return True
2547
2548 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2549 """
2550 Restores the given snapshot.
2551
2552 Returns True on success.
2553 Returns False on IMachine::restoreSnapshot() failure.
2554 Returns None if the progress object returns failure.
2555 """
2556 try:
2557 if self.fpApiVer >= 5.0:
2558 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2559 else:
2560 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2561 except:
2562 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2563 if fFudgeOnFailure:
2564 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2565 self.waitForTask(1000); # fudge
2566 return False;
2567
2568 rc = self.oTstDrv.waitOnProgress(oProgress);
2569 if rc < 0:
2570 self.close();
2571 if fFudgeOnFailure:
2572 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2573 return None;
2574
2575 return self.waitForTask(30 * 1000);
2576
2577 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2578 """
2579 Deletes the given snapshot merging the diff image into the base.
2580
2581 Returns True on success.
2582 Returns False on IMachine::deleteSnapshot() failure.
2583 """
2584 try:
2585 if self.fpApiVer >= 5.0:
2586 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2587 else:
2588 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2589 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2590 oProgress.wait(cMsTimeout);
2591 oProgress.logResult();
2592 except:
2593 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2594 if fFudgeOnFailure:
2595 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2596 self.waitForTask(1000); # fudge
2597 return False;
2598
2599 return True;
2600
2601 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2602 """
2603 Takes a snapshot with the given name
2604
2605 Returns True on success.
2606 Returns False on IMachine::takeSnapshot() or VM state change failure.
2607 """
2608 try:
2609 if fPause is True \
2610 and self.oVM.state is vboxcon.MachineState_Running:
2611 self.o.console.pause();
2612 if self.fpApiVer >= 5.0:
2613 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2614 else:
2615 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2616 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2617 oProgress.wait(cMsTimeout);
2618 oProgress.logResult();
2619 except:
2620 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2621 if fFudgeOnFailure:
2622 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2623 self.waitForTask(1000); # fudge
2624 return False;
2625
2626 if fPause is True \
2627 and self.oVM.state is vboxcon.MachineState_Paused:
2628 self.o.console.resume();
2629
2630 return True;
2631
2632 def findSnapshot(self, sName):
2633 """
2634 Returns the snapshot object with the given name
2635
2636 Returns snapshot object on success.
2637 Returns None if there is no snapshot with the given name.
2638 """
2639 return self.oVM.findSnapshot(sName);
2640
2641 def takeScreenshot(self, sFilename, iScreenId=0):
2642 """
2643 Take screenshot from the given display and save it to specified file.
2644
2645 Returns True on success
2646 Returns False on failure.
2647 """
2648 try:
2649 if self.fpApiVer >= 5.0:
2650 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2651 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2652 vboxcon.BitmapFormat_PNG)
2653 else:
2654 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2655 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2656 except:
2657 reporter.logXcpt("Unable to take screenshot")
2658 return False
2659
2660 oFile = open(sFilename, 'wb')
2661 oFile.write(aPngData)
2662 oFile.close()
2663
2664 return True
2665
2666 def attachUsbDevice(self, sUuid, sCaptureFilename = None):
2667 """
2668 Attach given USB device UUID to the VM.
2669
2670 Returns True on success
2671 Returns False on failure.
2672 """
2673 fRc = True;
2674 try:
2675 if sCaptureFilename is None:
2676 self.o.console.attachUSBDevice(sUuid, '');
2677 else:
2678 self.o.console.attachUSBDevice(sUuid, sCaptureFilename);
2679 except:
2680 reporter.logXcpt('Unable to attach USB device %s' % (sUuid,));
2681 fRc = False;
2682
2683 return fRc;
2684
2685 def detachUsbDevice(self, sUuid):
2686 """
2687 Detach given USB device UUID from the VM.
2688
2689 Returns True on success
2690 Returns False on failure.
2691 """
2692 fRc = True;
2693 try:
2694 _ = self.o.console.detachUSBDevice(sUuid);
2695 except:
2696 reporter.logXcpt('Unable to detach USB device %s' % (sUuid,));
2697 fRc = False;
2698
2699 return fRc;
2700
2701
2702 #
2703 # IMachineDebugger wrappers.
2704 #
2705
2706 def queryOsKernelLog(self):
2707 """
2708 Tries to get the OS kernel log using the VM debugger interface.
2709
2710 Returns string containing the kernel log on success.
2711 Returns None on failure.
2712 """
2713 sOsKernelLog = None;
2714 try:
2715 self.o.console.debugger.loadPlugIn('all');
2716 except:
2717 reporter.logXcpt('Unable to load debugger plugins');
2718 else:
2719 try:
2720 sOsDetected = self.o.console.debugger.detectOS();
2721 except:
2722 reporter.logXcpt('Failed to detect the guest OS');
2723 else:
2724 try:
2725 sOsKernelLog = self.o.console.debugger.queryOSKernelLog(0);
2726 except:
2727 reporter.logXcpt('Unable to get the guest OS (%s) kernel log' % (sOsDetected,));
2728 return sOsKernelLog;
2729
2730 def queryDbgInfo(self, sItem, sArg = '', sDefault = None):
2731 """
2732 Simple wrapper around IMachineDebugger::info.
2733
2734 Returns string on success, sDefault on failure (logged).
2735 """
2736 try:
2737 return self.o.console.debugger.info(sItem, sArg);
2738 except:
2739 reporter.logXcpt('Unable to query "%s" with arg "%s"' % (sItem, sArg,));
2740 return sDefault;
2741
2742 def queryDbgInfoVgaText(self, sArg = 'all'):
2743 """
2744 Tries to get the 'info vgatext' output, provided we're in next mode.
2745
2746 Returns string containing text on success.
2747 Returns None on failure or not text mode.
2748 """
2749 sVgaText = None;
2750 try:
2751 sVgaText = self.o.console.debugger.info('vgatext', sArg);
2752 if sVgaText.startswith('Not in text mode!'):
2753 sVgaText = None;
2754 except:
2755 reporter.logXcpt('Unable to query vgatext with arg "%s"' % (sArg,));
2756 return sVgaText;
2757
2758 def queryDbgGuestStack(self, iCpu = 0):
2759 """
2760 Returns the guest stack for the given VCPU.
2761
2762 Returns string containing the guest stack for the selected VCPU on success.
2763 Returns None on failure.
2764 """
2765
2766 #
2767 # Load all plugins first and try to detect the OS so we can
2768 # get nicer stack traces.
2769 #
2770 try:
2771 self.o.console.debugger.loadPlugIn('all');
2772 except:
2773 reporter.logXcpt('Unable to load debugger plugins');
2774 else:
2775 try:
2776 sOsDetected = self.o.console.debugger.detectOS();
2777 _ = sOsDetected;
2778 except:
2779 reporter.logXcpt('Failed to detect the guest OS');
2780
2781 sGuestStack = None;
2782 try:
2783 sGuestStack = self.o.console.debugger.dumpGuestStack(iCpu);
2784 except:
2785 reporter.logXcpt('Unable to query guest stack for CPU %s' % (iCpu, ));
2786
2787 return sGuestStack;
2788
2789
2790 #
2791 # Other methods.
2792 #
2793
2794 def getPrimaryIp(self):
2795 """
2796 Tries to obtain the primary IP address of the guest via the guest
2797 properties.
2798
2799 Returns IP address on success.
2800 Returns empty string on failure.
2801 """
2802 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2803 if vbox.isIpAddrValid(sIpAddr):
2804 return sIpAddr;
2805 return '';
2806
2807 def getPid(self):
2808 """
2809 Gets the process ID for the direct session unless it's ourselves.
2810 """
2811 if self.uPid is None and self.o is not None and self.fRemoteSession:
2812 try:
2813 if self.fpApiVer >= 4.2:
2814 uPid = self.o.machine.sessionPID;
2815 else:
2816 uPid = self.o.machine.sessionPid;
2817 if uPid != os.getpid() and uPid != 0xffffffff:
2818 self.uPid = uPid;
2819 except Exception as oXcpt:
2820 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
2821 try:
2822 if self.fpApiVer >= 4.2:
2823 uPid = self.oVM.sessionPID;
2824 else:
2825 uPid = self.oVM.sessionPid;
2826 if uPid != os.getpid() and uPid != 0xffffffff:
2827 self.uPid = uPid;
2828 except:
2829 reporter.log2Xcpt();
2830 else:
2831 reporter.log2Xcpt();
2832 if self.uPid is not None:
2833 reporter.log2('getPid: %u' % (self.uPid,));
2834 self.fPidFile = self.oTstDrv.pidFileAdd(self.uPid, 'vm_%s' % (self.sName,), # Set-uid-to-root is similar to SUDO.
2835 fSudo = True);
2836 return self.uPid;
2837
2838 def addLogsToReport(self, cReleaseLogs = 1):
2839 """
2840 Retrieves and adds the release and debug logs to the test report.
2841 """
2842 fRc = True;
2843
2844 # Add each of the requested release logs to the report.
2845 for iLog in range(0, cReleaseLogs):
2846 try:
2847 if self.fpApiVer >= 3.2:
2848 sLogFile = self.oVM.queryLogFilename(iLog);
2849 elif iLog > 0:
2850 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
2851 else:
2852 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
2853 except:
2854 reporter.logXcpt('iLog=%s' % (iLog,));
2855 fRc = False;
2856 else:
2857 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
2858 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
2859 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2860
2861 # Now for the hardened windows startup log.
2862 try:
2863 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxHardening.log');
2864 except:
2865 reporter.logXcpt();
2866 fRc = False;
2867 else:
2868 if os.path.isfile(sLogFile):
2869 reporter.addLogFile(sLogFile, 'log/release/vm', '%s hardening log' % (self.sName, ),
2870 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2871
2872 # Now for the debug log.
2873 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
2874 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
2875 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
2876
2877 return fRc;
2878
2879 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
2880 """
2881 Create an instance of the given ConsoleEventHandlerBase sub-class and
2882 register it.
2883
2884 The new instance is returned on success. None is returned on error.
2885 """
2886
2887 # We need a console object.
2888 try:
2889 oConsole = self.o.console;
2890 except Exception as oXcpt:
2891 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
2892 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
2893 return None;
2894
2895 # Add the base class arguments.
2896 dArgsCopy = dArgs.copy() if dArgs is not None else dict();
2897 dArgsCopy['oSession'] = self;
2898 dArgsCopy['oConsole'] = oConsole;
2899 sLogSuffix = 'on %s' % (self.sName,)
2900 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
2901 oConsole, 'IConsole', 'IConsoleCallback',
2902 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
2903
2904 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
2905 """
2906 Enables the testing part of the VMMDev.
2907
2908 Returns True on success and False on failure. Error information is logged.
2909 """
2910 fRc = True;
2911 try:
2912 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
2913 '1' if fEnabled else '');
2914 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
2915 '1' if fEnableMMIO and fEnabled else '');
2916 except:
2917 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
2918 fRc = False;
2919 else:
2920 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
2921 self.oTstDrv.processPendingEvents();
2922 return fRc;
2923
2924 #
2925 # Test eXecution Service methods.
2926 #
2927
2928 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, sMacAddr = None, fNatForwardingForTxs = False):
2929 """
2930 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
2931 addresses are specified, we'll get the IP from the guest additions.
2932
2933 Returns a TxsConnectTask object on success, None + log on failure.
2934 """
2935 # If the VM is configured with a NAT interface, connect to local host.
2936 fReversedSetup = False;
2937 fUseNatForTxs = False;
2938 if sIpAddr is None:
2939 try:
2940 oNic = self.oVM.getNetworkAdapter(0);
2941 if oNic.attachmentType == vboxcon.NetworkAttachmentType_NAT:
2942 fUseNatForTxs = True;
2943 except:
2944 reporter.errorXcpt();
2945 return None;
2946 if fUseNatForTxs:
2947 fReversedSetup = not fNatForwardingForTxs;
2948 sIpAddr = '127.0.0.1';
2949
2950 # Kick off the task.
2951 try:
2952 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup);
2953 except:
2954 reporter.errorXcpt();
2955 oTask = None;
2956 return oTask;
2957
2958 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
2959 """
2960 Attempts to connect to a TXS instance.
2961
2962 Returns True if a connection was established, False if not (only grave
2963 failures are logged as errors).
2964
2965 Note! The timeout is more of a guideline...
2966 """
2967
2968 if sHostname is None or sHostname.strip() == '':
2969 raise base.GenError('Empty sHostname is not implemented yet');
2970
2971 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
2972 cMsIdleFudge = cMsTimeout // 2);
2973 if oTxsSession is None:
2974 return False;
2975
2976 # Wait for the connect task to time out.
2977 self.oTstDrv.addTask(oTxsSession);
2978 self.oTstDrv.processPendingEvents();
2979 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
2980 self.oTstDrv.removeTask(oTxsSession);
2981 if oRc != oTxsSession:
2982 if oRc is not None:
2983 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
2984 self.oTstDrv.processPendingEvents();
2985 oTxsSession.cancelTask(); # this is synchronous
2986 return False;
2987
2988 # Check the status.
2989 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
2990 if not oTxsSession.isSuccess():
2991 return False;
2992
2993 reporter.log2('Disconnecting from TXS...');
2994 return oTxsSession.syncDisconnect();
2995
2996
2997
2998class TxsConnectTask(TdTaskBase):
2999 """
3000 Class that takes care of connecting to a VM.
3001 """
3002
3003 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
3004 """ Class for looking for IPv4 address changes on interface 0."""
3005 def __init__(self, dArgs):
3006 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs); # pylint: disable=W0233
3007 self.oParentTask = dArgs['oParentTask'];
3008 self.sMachineId = dArgs['sMachineId'];
3009
3010 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags):
3011 """Look for IP address."""
3012 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags));
3013 if sMachineId == self.sMachineId \
3014 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
3015 oParentTask = self.oParentTask;
3016 if oParentTask:
3017 oParentTask._setIp(sValue); # pylint: disable=W0212
3018
3019
3020 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup):
3021 TdTaskBase.__init__(self, utils.getCallerName());
3022 self.cMsTimeout = cMsTimeout;
3023 self.sIpAddr = None;
3024 self.sNextIpAddr = None;
3025 self.sMacAddr = sMacAddr;
3026 self.fReversedSetup = fReversedSetup;
3027 self.oVBoxEventHandler = None;
3028 self.oTxsSession = None;
3029
3030 # Skip things we don't implement.
3031 if sMacAddr is not None:
3032 reporter.error('TxsConnectTask does not implement sMacAddr yet');
3033 raise base.GenError();
3034
3035 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
3036 if fReversedSetup is True:
3037 self._openTcpSession(sIpAddr, fReversedSetup = True);
3038 elif sIpAddr is not None and sIpAddr.strip() != '':
3039 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3040 else:
3041 #
3042 # If we've got no IP address, register callbacks that listens for
3043 # the primary network adaptor of the VM to set a IPv4 guest prop.
3044 # Note! The order in which things are done here is kind of important.
3045 #
3046
3047 # 0. The caller zaps the property before starting the VM.
3048 #try:
3049 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3050 #except:
3051 # reporter.logXcpt();
3052
3053 # 1. Register the callback / event listener object.
3054 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
3055 self.oVBoxEventHandler = oSession.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
3056
3057 # 2. Query the guest properties.
3058 try:
3059 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
3060 except:
3061 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
3062 self._deregisterEventHandler();
3063 raise;
3064 else:
3065 if sIpAddr is not None:
3066 self._setIp(sIpAddr);
3067 # end __init__
3068
3069 def __del__(self):
3070 """ Make sure we deregister the callback. """
3071 self._deregisterEventHandler();
3072 return TdTaskBase.__del__(self);
3073
3074 def toString(self):
3075 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
3076 ' oTxsSession=%s oVBoxEventHandler=%s>' \
3077 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
3078 self.oTxsSession, self.oVBoxEventHandler);
3079
3080 def _deregisterEventHandler(self):
3081 """Deregisters the event handler."""
3082 fRc = True;
3083 oVBoxEventHandler = self.oVBoxEventHandler;
3084 if oVBoxEventHandler is not None:
3085 self.oVBoxEventHandler = None;
3086 fRc = oVBoxEventHandler.unregister();
3087 oVBoxEventHandler.oParentTask = None; # Try avoid cylic deps.
3088 return fRc;
3089
3090 def _setIp(self, sIpAddr, fInitCall = False):
3091 """Called when we get an IP. Will create a TXS session and signal the task."""
3092 sIpAddr = sIpAddr.strip();
3093
3094 if sIpAddr is not None \
3095 and sIpAddr != '':
3096 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
3097 try:
3098 for s in sIpAddr.split('.'):
3099 i = int(s);
3100 if str(i) != s:
3101 raise Exception();
3102 except:
3103 reporter.fatalXcpt();
3104 else:
3105 reporter.log('TxsConnectTask: opening session to ip "%s"' % (sIpAddr));
3106 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3107 return None;
3108
3109 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
3110 else:
3111 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
3112 return None;
3113
3114 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
3115 """
3116 Calls txsclient.openTcpSession and switches our task to reflect the
3117 state of the subtask.
3118 """
3119 self.oCv.acquire();
3120 if self.oTxsSession is None:
3121 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' % \
3122 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
3123 self.sIpAddr = sIpAddr;
3124 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, \
3125 fReversedSetup, cMsIdleFudge);
3126 self.oTxsSession.setTaskOwner(self);
3127 else:
3128 self.sNextIpAddr = sIpAddr;
3129 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
3130 self.oCv.release();
3131 return None;
3132
3133 def notifyAboutReadyTask(self, oTxsSession):
3134 """
3135 Called by the TXS session task when it's done.
3136
3137 We'll signal the task completed or retry depending on the result.
3138 """
3139
3140 self.oCv.acquire();
3141
3142 # Disassociate ourselves with the session (avoid cyclic ref)
3143 oTxsSession.setTaskOwner(None);
3144 fSuccess = oTxsSession.isSuccess();
3145 if self.oTxsSession is not None:
3146 if not fSuccess:
3147 self.oTxsSession = None;
3148 if fSuccess and self.fReversedSetup:
3149 self.sIpAddr = oTxsSession.oTransport.sHostname;
3150 else:
3151 fSuccess = False;
3152
3153 # Signal done, or retry?
3154 fDeregister = False;
3155 if fSuccess \
3156 or self.fReversedSetup \
3157 or self.getAgeAsMs() >= self.cMsTimeout:
3158 self.signalTaskLocked();
3159 fDeregister = True;
3160 else:
3161 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
3162 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
3163
3164 self.oCv.release();
3165
3166 # If we're done, deregister the callback (w/o owning lock). It will
3167 if fDeregister:
3168 self._deregisterEventHandler();
3169 return True;
3170
3171 #
3172 # Public methods
3173 #
3174
3175 def getResult(self):
3176 """
3177 Returns the connected TXS session object on success.
3178 Returns None on failure or if the task has not yet completed.
3179 """
3180 self.oCv.acquire();
3181 oTxsSession = self.oTxsSession;
3182 self.oCv.release();
3183
3184 if oTxsSession is not None and not oTxsSession.isSuccess():
3185 oTxsSession = None;
3186 return oTxsSession;
3187
3188 def cancelTask(self):
3189 """ Cancels the task. """
3190 self._deregisterEventHandler(); # (make sure to avoid cyclic fun)
3191 self.oCv.acquire();
3192 if not self.fSignalled:
3193 oTxsSession = self.oTxsSession;
3194 if oTxsSession is not None:
3195 self.oCv.release();
3196 oTxsSession.setTaskOwner(None);
3197 oTxsSession.cancelTask();
3198 oTxsSession.waitForTask(1000);
3199 self.oCv.acquire();
3200 self.signalTaskLocked();
3201 self.oCv.release();
3202 return True;
3203
Note: See TracBrowser for help on using the repository browser.

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