VirtualBox

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

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

ValidationKit: bugref:8345 fix incorrect use of direct API call, replacing by helper for future use

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

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