VirtualBox

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

Last change on this file since 53624 was 53415, checked in by vboxsync, 10 years ago

correct fix

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