VirtualBox

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

Last change on this file since 57968 was 57968, checked in by vboxsync, 9 years ago

ValidationKit: some fixes/adjustments for MAC address generation based on the host's IP, adding sanity checks and logging if the address looks fishy.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 105.4 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 57968 2015-09-30 14:10:00Z vboxsync $
3# pylint: disable=C0302
4
5"""
6VirtualBox Wrapper Classes
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2015 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: 57968 $"
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 OHCI 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_EHCI);
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 EHCI to %s for "%s"' % (fEnable, self.sName));
1061 self.oTstDrv.processPendingEvents();
1062 return fRc;
1063
1064 def enableUsbXhci(self, fEnable):
1065 """
1066 Enables or disables the USB XHCI controller. Error information is logged.
1067 """
1068 fRc = True;
1069 try:
1070 if fEnable:
1071 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1072 if cXhciCtls == 0:
1073 self.o.machine.addUSBController('XHCI', vboxcon.USBControllerType_XHCI);
1074 else:
1075 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1076 if cXhciCtls == 1:
1077 self.o.machine.RemoveUSBController('XHCI');
1078 except:
1079 reporter.errorXcpt('failed to change XHCI to %s for "%s"' % (fEnable, self.sName));
1080 fRc = False;
1081 else:
1082 reporter.log('changed XHCI to %s for "%s"' % (fEnable, self.sName));
1083 self.oTstDrv.processPendingEvents();
1084 return fRc;
1085
1086 def setFirmwareType(self, eType):
1087 """
1088 Sets the firmware type.
1089 Returns True on success and False on failure. Error information is logged.
1090 """
1091 fRc = True;
1092 try:
1093 self.o.machine.firmwareType = eType;
1094 except:
1095 reporter.errorXcpt('failed to set firmwareType=%s for "%s"' % (eType, self.sName));
1096 fRc = False;
1097 else:
1098 reporter.log('set firmwareType=%s for "%s"' % (eType, self.sName));
1099 self.oTstDrv.processPendingEvents();
1100 return fRc;
1101
1102 def setupBootLogo(self, fEnable, cMsLogoDisplay = 0):
1103 """
1104 Sets up the boot logo. fEnable toggles the fade and boot menu
1105 settings as well as the mode.
1106 """
1107 fRc = True;
1108 try:
1109 self.o.machine.BIOSSettings.logoFadeIn = not fEnable;
1110 self.o.machine.BIOSSettings.logoFadeOut = not fEnable;
1111 self.o.machine.BIOSSettings.logoDisplayTime = cMsLogoDisplay;
1112 if fEnable:
1113 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_Disabled;
1114 else:
1115 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_MessageAndMenu;
1116 except:
1117 reporter.errorXcpt('failed to set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1118 fRc = False;
1119 else:
1120 reporter.log('set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1121 self.oTstDrv.processPendingEvents();
1122 return fRc;
1123
1124 def setupVrdp(self, fEnable, uPort = None):
1125 """
1126 Configures VRDP.
1127 """
1128 fRc = True;
1129 try:
1130 if self.fpApiVer >= 4.0:
1131 self.o.machine.VRDEServer.enabled = fEnable;
1132 else:
1133 self.o.machine.VRDPServer.enabled = fEnable;
1134 except:
1135 reporter.errorXcpt('failed to set VRDEServer::enabled=%s for "%s"' % (fEnable, self.sName));
1136 fRc = False;
1137
1138 if uPort is not None and fRc:
1139 try:
1140 if self.fpApiVer >= 4.0:
1141 self.o.machine.VRDEServer.setVRDEProperty("TCP/Ports", str(uPort));
1142 else:
1143 self.o.machine.VRDPServer.ports = str(uPort);
1144 except:
1145 reporter.errorXcpt('failed to set VRDEServer::ports=%s for "%s"' % (uPort, self.sName));
1146 fRc = False;
1147 if fRc:
1148 reporter.log('set VRDEServer.enabled/ports=%s/%s for "%s"' % (fEnable, uPort, self.sName));
1149 self.oTstDrv.processPendingEvents();
1150 return fRc;
1151
1152 def getNicDriverNameFromType(self, eNicType):
1153 """
1154 Helper that translate the adapter type into a driver name.
1155 """
1156 if eNicType == vboxcon.NetworkAdapterType_Am79C970A \
1157 or eNicType == vboxcon.NetworkAdapterType_Am79C973:
1158 sName = 'pcnet';
1159 elif eNicType == vboxcon.NetworkAdapterType_I82540EM \
1160 or eNicType == vboxcon.NetworkAdapterType_I82543GC \
1161 or eNicType == vboxcon.NetworkAdapterType_I82545EM:
1162 sName = 'e1000';
1163 elif eNicType == vboxcon.NetworkAdapterType_Virtio:
1164 sName = 'virtio-net';
1165 else:
1166 reporter.error('Unknown adapter type "%s" (VM: "%s")' % (eNicType, self.sName));
1167 sName = 'pcnet';
1168 return sName;
1169
1170 def setupNatForwardingForTxs(self, iNic = 0, iHostPort = 5042):
1171 """
1172 Sets up NAT forwarding for port 5042 if applicable, cleans up if not.
1173 """
1174 try:
1175 oNic = self.o.machine.getNetworkAdapter(iNic);
1176 except:
1177 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1178 return False;
1179
1180 # Nuke the old setup for all possible adapter types (in case we're
1181 # called after it changed).
1182 for sName in ('pcnet', 'e1000', 'virtio-net'):
1183 for sConfig in ('VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic), \
1184 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)):
1185 try:
1186 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), '');
1187 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '');
1188 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '');
1189 except:
1190 reporter.errorXcpt();
1191
1192 # Set up port forwarding if NAT attachment.
1193 try:
1194 eAttType = oNic.attachmentType;
1195 except:
1196 reporter.errorXcpt('attachmentType on %s failed for "%s"' % (iNic, self.sName));
1197 return False;
1198 if eAttType != vboxcon.NetworkAttachmentType_NAT:
1199 return True;
1200
1201 try:
1202 eNicType = oNic.adapterType;
1203 fTraceEnabled = oNic.traceEnabled;
1204 except:
1205 reporter.errorXcpt('attachmentType/traceEnabled on %s failed for "%s"' % (iNic, self.sName));
1206 return False;
1207
1208 if self.fpApiVer >= 4.1:
1209 try:
1210 if self.fpApiVer >= 4.2:
1211 oNatEngine = oNic.NATEngine;
1212 else:
1213 oNatEngine = oNic.natDriver;
1214 except:
1215 reporter.errorXcpt('Failed to get INATEngine data on "%s"' % (self.sName));
1216 return False;
1217 try: oNatEngine.removeRedirect('txs');
1218 except: pass;
1219 try:
1220 oNatEngine.addRedirect('txs', vboxcon.NATProtocol_TCP, '127.0.0.1', '%s' % (iHostPort), '', '5042');
1221 except:
1222 reporter.errorXcpt('Failed to add a addRedirect redirect on "%s"' % (self.sName));
1223 return False;
1224
1225 else:
1226 sName = self.getNicDriverNameFromType(eNicType);
1227 if fTraceEnabled:
1228 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic)
1229 else:
1230 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)
1231
1232 try:
1233 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), 'TCP');
1234 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '%s' % (iHostPort));
1235 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '5042');
1236 except:
1237 reporter.errorXcpt('Failed to set NAT extra data on "%s"' % (self.sName));
1238 return False;
1239 return True;
1240
1241 def setNicType(self, eType, iNic = 0):
1242 """
1243 Sets the NIC type of the specified NIC.
1244 Returns True on success and False on failure. Error information is logged.
1245 """
1246 try:
1247 try:
1248 oNic = self.o.machine.getNetworkAdapter(iNic);
1249 except:
1250 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1251 return False;
1252 try:
1253 oNic.adapterType = eType;
1254 except:
1255 reporter.errorXcpt('failed to set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1256 return False;
1257 finally:
1258 self.oTstDrv.processPendingEvents();
1259
1260 if not self.setupNatForwardingForTxs(iNic):
1261 return False;
1262 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1263 return True;
1264
1265 def setNicTraceEnabled(self, fTraceEnabled, sTraceFile, iNic = 0):
1266 """
1267 Sets the NIC trace enabled flag and file path.
1268 Returns True on success and False on failure. Error information is logged.
1269 """
1270 try:
1271 try:
1272 oNic = self.o.machine.getNetworkAdapter(iNic);
1273 except:
1274 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1275 return False;
1276 try:
1277 oNic.traceEnabled = fTraceEnabled;
1278 oNic.traceFile = sTraceFile;
1279 except:
1280 reporter.errorXcpt('failed to set NIC trace flag on slot %s to %s for VM "%s"' \
1281 % (iNic, fTraceEnabled, self.sName));
1282 return False;
1283 finally:
1284 self.oTstDrv.processPendingEvents();
1285
1286 if not self.setupNatForwardingForTxs(iNic):
1287 return False;
1288 reporter.log('set NIC trace on slot %s to "%s" (path "%s") for VM "%s"' %
1289 (iNic, fTraceEnabled, sTraceFile, self.sName));
1290 return True;
1291
1292 def getDefaultNicName(self, eAttachmentType):
1293 """
1294 Return the default network / interface name for the NIC attachment type.
1295 """
1296 sRetName = '';
1297 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1298 if self.oTstDrv.sDefBridgedNic is not None:
1299 sRetName = self.oTstDrv.sDefBridgedNic;
1300 else:
1301 sRetName = 'eth0';
1302 try:
1303 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1304 for oHostNic in aoHostNics:
1305 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_Bridged \
1306 and oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1307 sRetName = oHostNic.name;
1308 break;
1309 except:
1310 reporter.errorXcpt();
1311 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1312 try:
1313 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1314 for oHostNic in aoHostNics:
1315 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_HostOnly:
1316 if oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1317 sRetName = oHostNic.name;
1318 break;
1319 if sRetName == '':
1320 sRetName = oHostNic.name;
1321 except:
1322 reporter.errorXcpt();
1323 if sRetName == '':
1324 sRetName = 'HostInterfaceNetwork-vboxnet0';
1325 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1326 sRetName = 'VBoxTest';
1327 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1328 sRetName = '';
1329 else:
1330 reporter.error('eAttachmentType=%s is not known' % (eAttachmentType));
1331 return sRetName;
1332
1333 def setNicAttachment(self, eAttachmentType, sName = None, iNic = 0):
1334 """
1335 Sets the attachment type of the specified NIC.
1336 Returns True on success and False on failure. Error information is logged.
1337 """
1338 try:
1339 oNic = self.o.machine.getNetworkAdapter(iNic);
1340 except:
1341 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1342 return False;
1343
1344 try:
1345 if eAttachmentType is not None:
1346 try:
1347 if self.fpApiVer >= 4.1:
1348 oNic.attachmentType = eAttachmentType;
1349 else:
1350 if eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1351 oNic.attachToNAT();
1352 elif eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1353 oNic.attachToBridgedInterface();
1354 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1355 oNic.attachToInternalNetwork();
1356 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1357 oNic.attachToHostOnlyInterface();
1358 else:
1359 raise base.GenError("eAttachmentType=%s is invalid" % (eAttachmentType));
1360 except:
1361 reporter.errorXcpt('failed to set the attachment type on slot %s to %s for VM "%s"' \
1362 % (iNic, eAttachmentType, self.sName));
1363 return False;
1364 else:
1365 try:
1366 eAttachmentType = oNic.attachmentType;
1367 except:
1368 reporter.errorXcpt('failed to get the attachment type on slot %s for VM "%s"' % (iNic, self.sName));
1369 return False;
1370 finally:
1371 self.oTstDrv.processPendingEvents();
1372
1373 if sName is not None:
1374 # Resolve the special 'default' name.
1375 if sName == 'default':
1376 sName = self.getDefaultNicName(eAttachmentType);
1377
1378 # The name translate to different attributes depending on the
1379 # attachment type.
1380 try:
1381 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1382 ## @todo check this out on windows, may have to do a
1383 # translation of the name there or smth IIRC.
1384 try:
1385 if self.fpApiVer >= 4.1:
1386 oNic.bridgedInterface = sName;
1387 else:
1388 oNic.hostInterface = sName;
1389 except:
1390 reporter.errorXcpt('failed to set the hostInterface property on slot %s to "%s" for VM "%s"' \
1391 % (iNic, sName, self.sName));
1392 return False;
1393 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1394 try:
1395 if self.fpApiVer >= 4.1:
1396 oNic.hostOnlyInterface = sName;
1397 else:
1398 oNic.hostInterface = sName;
1399 except:
1400 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1401 % (iNic, sName, self.sName));
1402 return False;
1403 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1404 try:
1405 oNic.internalNetwork = sName;
1406 except:
1407 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1408 % (iNic, sName, self.sName));
1409 return False;
1410 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1411 try:
1412 oNic.NATNetwork = sName;
1413 except:
1414 reporter.errorXcpt('failed to set the NATNetwork property on slot %s to "%s" for VM "%s"' \
1415 % (iNic, sName, self.sName));
1416 return False;
1417 finally:
1418 self.oTstDrv.processPendingEvents();
1419
1420 if not self.setupNatForwardingForTxs(iNic):
1421 return False;
1422 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eAttachmentType, self.sName));
1423 return True;
1424
1425 def setNicMacAddress(self, sMacAddr, iNic = 0):
1426 """
1427 Sets the MAC address of the specified NIC.
1428 Returns True on success and False on failure. Error information is logged.
1429 """
1430
1431 # Resolve missing MAC address prefix
1432 cchMacAddr = len(sMacAddr)
1433 if cchMacAddr > 0 and cchMacAddr < 12:
1434 sHostName = ''
1435 try:
1436 sHostName = socket.getfqdn()
1437 sHostIP = socket.gethostbyname(sHostName)
1438 abHostIP = socket.inet_aton(sHostIP)
1439 if ord(abHostIP[0]) == 127 \
1440 or ord(abHostIP[0]) == 169 and ord(abHostIP[1]) == 254 \
1441 or ord(abHostIP[0]) == 192 and ord(abHostIP[1]) == 168 and ord(abHostIP[2]) == 56:
1442 reporter.log('warning: host IP for "%s" is %s, most likely not unique.' % (sHostName, sHostIP))
1443 except:
1444 reporter.errorXcpt('failed to determine the host IP for "%s".' % (sHostName,))
1445 abHostIP = array.array('B', (0x80, 0x86, 0x00, 0x00)).tostring()
1446 sDefaultMac = '%02X%02X%02X%02X%02X%02X' \
1447 % (0x02, ord(abHostIP[0]), ord(abHostIP[1]), ord(abHostIP[2]), ord(abHostIP[3]), iNic)
1448 sMacAddr = sDefaultMac[0:(12 - cchMacAddr)] + sMacAddr
1449
1450 # Get the NIC object and try set it address.
1451 try:
1452 oNic = self.o.machine.getNetworkAdapter(iNic);
1453 except:
1454 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1455 return False;
1456
1457 try:
1458 oNic.MACAddress = sMacAddr;
1459 except:
1460 reporter.errorXcpt('failed to set the MAC address on slot %s to "%s" for VM "%s"' \
1461 % (iNic, sMacAddr, self.sName));
1462 return False;
1463
1464 reporter.log('set MAC address on slot %s to %s for VM "%s"' % (iNic, sMacAddr, self.sName));
1465 return True;
1466
1467 def setRamSize(self, cMB):
1468 """
1469 Set the RAM size of the VM.
1470 Returns True on success and False on failure. Error information is logged.
1471 """
1472 fRc = True;
1473 try:
1474 self.o.machine.memorySize = cMB;
1475 except:
1476 reporter.errorXcpt('failed to set the RAM size of "%s" to %s' % (self.sName, cMB));
1477 fRc = False;
1478 else:
1479 reporter.log('set the RAM size of "%s" to %s' % (self.sName, cMB));
1480 self.oTstDrv.processPendingEvents();
1481 return fRc;
1482
1483 def setVRamSize(self, cMB):
1484 """
1485 Set the RAM size of the VM.
1486 Returns True on success and False on failure. Error information is logged.
1487 """
1488 fRc = True;
1489 try:
1490 self.o.machine.VRAMSize = cMB;
1491 except:
1492 reporter.errorXcpt('failed to set the VRAM size of "%s" to %s' % (self.sName, cMB));
1493 fRc = False;
1494 else:
1495 reporter.log('set the VRAM size of "%s" to %s' % (self.sName, cMB));
1496 self.oTstDrv.processPendingEvents();
1497 return fRc;
1498
1499 def setCpuCount(self, cCpus):
1500 """
1501 Set the number of CPUs.
1502 Returns True on success and False on failure. Error information is logged.
1503 """
1504 fRc = True;
1505 try:
1506 self.o.machine.CPUCount = cCpus;
1507 except:
1508 reporter.errorXcpt('failed to set the CPU count of "%s" to %s' % (self.sName, cCpus));
1509 fRc = False;
1510 else:
1511 reporter.log('set the CPU count of "%s" to %s' % (self.sName, cCpus));
1512 self.oTstDrv.processPendingEvents();
1513 return fRc;
1514
1515 def ensureControllerAttached(self, sController):
1516 """
1517 Makes sure the specified controller is attached to the VM, attaching it
1518 if necessary.
1519 """
1520 try:
1521 try:
1522 self.o.machine.getStorageControllerByName(sController);
1523 except:
1524 iType = _ControllerNameToBus(sController);
1525 try:
1526 self.o.machine.addStorageController(sController, iType);
1527 reporter.log('added storage controller "%s" (type %s) to %s' % (sController, iType, self.sName));
1528 except:
1529 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, iType, self.sName) );
1530 return False;
1531 finally:
1532 self.oTstDrv.processPendingEvents();
1533 return True;
1534
1535 def setStorageControllerPortCount(self, sController, iPortCount):
1536 """
1537 Set maximum ports count for storage controller
1538 """
1539 try:
1540 oCtl = self.o.machine.getStorageControllerByName(sController)
1541 oCtl.portCount = iPortCount
1542 self.oTstDrv.processPendingEvents()
1543 reporter.log('set controller "%s" port count to value %d' % (sController, iPortCount))
1544 return True
1545 except:
1546 reporter.log('unable to set storage controller "%s" ports count to %d' % (sController, iPortCount))
1547
1548 return False
1549
1550 def setBootOrder(self, iPosition, eType):
1551 """
1552 Set guest boot order type
1553 @param iPosition boot order position
1554 @param eType device type (vboxcon.DeviceType_HardDisk,
1555 vboxcon.DeviceType_DVD, vboxcon.DeviceType_Floppy)
1556 """
1557 try:
1558 self.o.machine.setBootOrder(iPosition, eType)
1559 except:
1560 return reporter.errorXcpt('Unable to set boot order.')
1561
1562 reporter.log('Set boot order [%d] for device %s' % (iPosition, str(eType)))
1563 self.oTstDrv.processPendingEvents();
1564
1565 return True
1566
1567 def setStorageControllerType(self, eType, sController = "IDE Controller"):
1568 """
1569 Similar to ensureControllerAttached, except it will change the type.
1570 """
1571 try:
1572 oCtl = self.o.machine.getStorageControllerByName(sController);
1573 except:
1574 iType = _ControllerNameToBus(sController);
1575 try:
1576 oCtl = self.o.machine.addStorageController(sController, iType);
1577 reporter.log('added storage controller "%s" (type %s) to %s' % (sController, iType, self.sName));
1578 except:
1579 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, iType, self.sName) );
1580 return False;
1581 try:
1582 oCtl.controllerType = eType;
1583 except:
1584 reporter.errorXcpt('failed to set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1585 return False;
1586 reporter.log('set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1587 self.oTstDrv.processPendingEvents();
1588 return True;
1589
1590 def attachDvd(self, sImage = None, sController = "IDE Controller", iPort = 1, iDevice = 0):
1591 """
1592 Attaches a DVD drive to a VM, optionally with an ISO inserted.
1593 Returns True on success and False on failure. Error information is logged.
1594 """
1595 # Input validation.
1596 if sImage is not None and not self.oTstDrv.isResourceFile(sImage)\
1597 and not os.path.isabs(sImage): ## fixme - testsuite unzip ++
1598 reporter.fatal('"%s" is not in the resource set' % (sImage));
1599 return None;
1600
1601 if not self.ensureControllerAttached(sController):
1602 return False;
1603
1604 # Find/register the image if specified.
1605 oImage = None;
1606 sImageUuid = "";
1607 if sImage is not None:
1608 sFullName = self.oTstDrv.getFullResourceName(sImage)
1609 try:
1610 oImage = self.oVBox.findDVDImage(sFullName);
1611 except:
1612 try:
1613 if self.fpApiVer >= 4.1:
1614 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly, False);
1615 elif self.fpApiVer >= 4.0:
1616 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly);
1617 else:
1618 oImage = self.oVBox.openDVDImage(sFullName, "");
1619 except vbox.ComException, oXcpt:
1620 if oXcpt.errno != -1:
1621 reporter.errorXcpt('failed to open DVD image "%s" xxx' % (sFullName));
1622 else:
1623 reporter.errorXcpt('failed to open DVD image "%s" yyy' % (sFullName));
1624 return False;
1625 except:
1626 reporter.errorXcpt('failed to open DVD image "%s"' % (sFullName));
1627 return False;
1628 try:
1629 sImageUuid = oImage.id;
1630 except:
1631 reporter.errorXcpt('failed to get the UUID of "%s"' % (sFullName));
1632 return False;
1633
1634 # Attach the DVD.
1635 fRc = True;
1636 try:
1637 if self.fpApiVer >= 4.0:
1638 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, oImage);
1639 else:
1640 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, sImageUuid);
1641 except:
1642 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1643 % (sController, iPort, iDevice, sImageUuid, self.sName) );
1644 fRc = False;
1645 else:
1646 reporter.log('attached DVD to %s, image="%s"' % (self.sName, sImage));
1647 self.oTstDrv.processPendingEvents();
1648 return fRc;
1649
1650 def attachHd(self, sHd, sController = "IDE Controller", iPort = 0, iDevice = 0, fImmutable = True, fForceResource = True):
1651 """
1652 Attaches a HD to a VM.
1653 Returns True on success and False on failure. Error information is logged.
1654 """
1655 # Input validation.
1656 if fForceResource and not self.oTstDrv.isResourceFile(sHd):
1657 reporter.fatal('"%s" is not in the resource set' % (sHd,));
1658 return None;
1659
1660 if not self.ensureControllerAttached(sController):
1661 return False;
1662
1663 # Find the HD, registering it if necessary (as immutable).
1664 if fForceResource:
1665 sFullName = self.oTstDrv.getFullResourceName(sHd);
1666 else:
1667 sFullName = sHd;
1668 try:
1669 oHd = self.oVBox.findHardDisk(sFullName);
1670 except:
1671 try:
1672 if self.fpApiVer >= 4.1:
1673 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
1674 elif self.fpApiVer >= 4.0:
1675 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
1676 else:
1677 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
1678 except:
1679 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
1680 return False;
1681 try:
1682 if fImmutable:
1683 oHd.type = vboxcon.MediumType_Immutable;
1684 else:
1685 oHd.type = vboxcon.MediumType_Normal;
1686 except:
1687 if fImmutable:
1688 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1689 else:
1690 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1691 return False;
1692
1693 # Attach it.
1694 fRc = True;
1695 try:
1696 if self.fpApiVer >= 4.0:
1697 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1698 else:
1699 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1700 except:
1701 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1702 % (sController, iPort, iDevice, oHd.id, self.sName) );
1703 fRc = False;
1704 else:
1705 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1706 self.oTstDrv.processPendingEvents();
1707 return fRc;
1708
1709 def createBaseHd(self, sHd, sFmt = "VDI", cb = 10*1024*1024*1024):
1710 """
1711 Creates a base HD.
1712 Returns Medium object on success and None on failure. Error information is logged.
1713 """
1714 try:
1715 if self.fpApiVer >= 5.0:
1716 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1717 else:
1718 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1719 oProgressXpcom = oHd.createBaseStorage(cb, (vboxcon.MediumVariant_Standard, ))
1720 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create base disk %s' % (sHd));
1721 oProgress.wait();
1722 oProgress.logResult();
1723 except:
1724 reporter.errorXcpt('failed to create base hd "%s"' % (sHd));
1725 oHd = None
1726
1727 return oHd;
1728
1729 def createDiffHd(self, oParentHd, sHd, sFmt = "VDI"):
1730 """
1731 Creates a differencing HD.
1732 Returns Medium object on success and None on failure. Error information is logged.
1733 """
1734 try:
1735 if self.fpApiVer >= 5.0:
1736 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1737 else:
1738 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1739 oProgressXpcom = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
1740 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
1741 oProgress.wait();
1742 oProgress.logResult();
1743 except:
1744 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
1745 oHd = None
1746
1747 return oHd;
1748
1749 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, \
1750 iPort = 0, iDevice = 0, fImmutable = True):
1751 """
1752 Creates and attaches a HD to a VM.
1753 Returns True on success and False on failure. Error information is logged.
1754 """
1755 if not self.ensureControllerAttached(sController):
1756 return False;
1757
1758 oHd = self.createBaseHd(sHd, sFmt, cb)
1759 if oHd is None:
1760 return False;
1761
1762 fRc = True;
1763 try:
1764 if fImmutable:
1765 oHd.type = vboxcon.MediumType_Immutable;
1766 else:
1767 oHd.type = vboxcon.MediumType_Normal;
1768 except:
1769 if fImmutable:
1770 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1771 else:
1772 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1773 fRc = False;
1774
1775 # Attach it.
1776 if fRc is True:
1777 try:
1778 if self.fpApiVer >= 4.0:
1779 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1780 else:
1781 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1782 except:
1783 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1784 % (sController, iPort, iDevice, oHd.id, self.sName) );
1785 fRc = False;
1786 else:
1787 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1788
1789 # Delete disk in case of an error
1790 if fRc is False:
1791 try:
1792 oProgressCom = oHd.deleteStorage();
1793 except:
1794 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
1795 else:
1796 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
1797 oProgress.wait();
1798 oProgress.logResult();
1799
1800 self.oTstDrv.processPendingEvents();
1801 return fRc;
1802
1803 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
1804 """
1805 Detaches a HD, if attached, and returns a reference to it (IMedium).
1806
1807 In order to delete the detached medium, the caller must first save
1808 the changes made in this session.
1809
1810 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
1811 your standard success indicator. Error information is logged.
1812 """
1813
1814 # What's attached?
1815 try:
1816 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
1817 except:
1818 if self.oVBoxMgr.xcptIsOurXcptKind() \
1819 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
1820 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
1821 return (True, None);
1822 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
1823 % (iPort, iDevice, sController)), None);
1824 # Detach it.
1825 try:
1826 self.o.machine.detachDevice(sController, iPort, iDevice);
1827 except:
1828 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
1829 % (sController, iPort, iDevice, self.sName) ), None);
1830 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
1831 return (True, oHd);
1832
1833 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
1834 """
1835 Attaches a floppy image to a VM.
1836 Returns True on success and False on failure. Error information is logged.
1837 """
1838 # Input validation.
1839 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
1840 ##if not self.oTstDrv.isResourceFile(sFloppy):
1841 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
1842 ## return None;
1843
1844 if not self.ensureControllerAttached(sController):
1845 return False;
1846
1847 # Find the floppy image, registering it if necessary (as immutable).
1848 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
1849 try:
1850 oFloppy = self.oVBox.findFloppyImage(sFullName);
1851 except:
1852 try:
1853 if self.fpApiVer >= 4.1:
1854 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
1855 elif self.fpApiVer >= 4.0:
1856 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
1857 else:
1858 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
1859 except:
1860 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
1861 return False;
1862 ## @todo the following works but causes trouble below (asserts in main).
1863 #try:
1864 # oFloppy.type = vboxcon.MediumType_Immutable;
1865 #except:
1866 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
1867 # return False;
1868
1869 # Attach it.
1870 fRc = True;
1871 try:
1872 if self.fpApiVer >= 4.0:
1873 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
1874 else:
1875 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
1876 except:
1877 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
1878 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
1879 fRc = False;
1880 else:
1881 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
1882 self.oTstDrv.processPendingEvents();
1883 return fRc;
1884
1885 def setupNic(self, sType, sXXX):
1886 """
1887 Attaches a HD to a VM.
1888 Returns True on success and False on failure. Error information is logged.
1889 """
1890 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
1891 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
1892 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
1893 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
1894 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
1895 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
1896 else:
1897 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
1898 return False;
1899 ## @todo Implement me!
1900 if enmType is not None: pass
1901 return True;
1902
1903 def setupPreferredConfig(self): # pylint: disable=R0914
1904 """
1905 Configures the VM according to the preferences of the guest type.
1906 """
1907 try:
1908 sOsTypeId = self.o.machine.OSTypeId;
1909 except:
1910 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
1911 return False;
1912
1913 try:
1914 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
1915 except:
1916 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
1917 return False;
1918
1919 # get the attributes.
1920 try:
1921 #sFamilyId = oOsType.familyId;
1922 #f64Bit = oOsType.is64Bit;
1923 fIoApic = oOsType.recommendedIOAPIC;
1924 fVirtEx = oOsType.recommendedVirtEx;
1925 cMBRam = oOsType.recommendedRAM;
1926 cMBVRam = oOsType.recommendedVRAM;
1927 #cMBHdd = oOsType.recommendedHDD;
1928 eNicType = oOsType.adapterType;
1929 if self.fpApiVer >= 3.2:
1930 if self.fpApiVer >= 4.2:
1931 fPae = oOsType.recommendedPAE;
1932 fUsbHid = oOsType.recommendedUSBHID;
1933 fHpet = oOsType.recommendedHPET;
1934 eStorCtlType = oOsType.recommendedHDStorageController;
1935 else:
1936 fPae = oOsType.recommendedPae;
1937 fUsbHid = oOsType.recommendedUsbHid;
1938 fHpet = oOsType.recommendedHpet;
1939 eStorCtlType = oOsType.recommendedHdStorageController;
1940 eFirmwareType = oOsType.recommendedFirmware;
1941 else:
1942 fPae = False;
1943 fUsbHid = False;
1944 fHpet = False;
1945 eFirmwareType = -1;
1946 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
1947 except:
1948 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
1949 self.oTstDrv.processPendingEvents();
1950 return False;
1951 self.oTstDrv.processPendingEvents();
1952
1953 # Do the setting. Continue applying settings on error in case the
1954 # caller ignores the return code
1955 fRc = True;
1956 if not self.enableIoApic(fIoApic): fRc = False;
1957 if not self.enableVirtEx(fVirtEx): fRc = False;
1958 if not self.enablePae(fPae): fRc = False;
1959 if not self.setRamSize(cMBRam): fRc = False;
1960 if not self.setVRamSize(cMBVRam): fRc = False;
1961 if not self.setNicType(eNicType, 0): fRc = False;
1962 if self.fpApiVer >= 3.2:
1963 if not self.setFirmwareType(eFirmwareType): fRc = False;
1964 if not self.enableUsbHid(fUsbHid): fRc = False;
1965 if not self.enableHpet(fHpet): fRc = False;
1966 if eStorCtlType == vboxcon.StorageControllerType_PIIX3 \
1967 or eStorCtlType == vboxcon.StorageControllerType_PIIX4 \
1968 or eStorCtlType == vboxcon.StorageControllerType_ICH6:
1969 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
1970 fRc = False;
1971
1972 return fRc;
1973
1974 def addUsbDeviceFilter(self, sName, sVendorId, sProductId):
1975 """
1976 Creates a USB device filter and inserts it into the VM.
1977 Returns True on success.
1978 Returns False on failure (logged).
1979 """
1980 fRc = True;
1981
1982 try:
1983 usbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
1984 usbDevFilter.active = True;
1985 usbDevFilter.vendorId = sVendorId;
1986 usbDevFilter.productId = sProductId;
1987 try:
1988 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, usbDevFilter);
1989 except:
1990 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
1991 % (0, self.sName) );
1992 fRc = False;
1993 else:
1994 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
1995 except:
1996 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
1997 % (sName, self.sName) );
1998 fRc = False;
1999 return fRc;
2000
2001 def getGuestPropertyValue(self, sName):
2002 """
2003 Gets a guest property value.
2004 Returns the value on success, None on failure (logged).
2005 """
2006 try:
2007 sValue = self.o.machine.getGuestPropertyValue(sName);
2008 except:
2009 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2010 return None;
2011 return sValue;
2012
2013 def setGuestPropertyValue(self, sName, sValue):
2014 """
2015 Sets a guest property value.
2016 Returns the True on success, False on failure (logged).
2017 """
2018 try:
2019 self.o.machine.setGuestPropertyValue(sName, sValue);
2020 except:
2021 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2022 return False;
2023 return True;
2024
2025 def delGuestPropertyValue(self, sName):
2026 """
2027 Deletes a guest property value.
2028 Returns the True on success, False on failure (logged).
2029 """
2030 try:
2031 oMachine = self.o.machine;
2032 if self.fpApiVer >= 4.2:
2033 oMachine.deleteGuestProperty(sName);
2034 else:
2035 oMachine.setGuestPropertyValue(sName, '');
2036 except:
2037 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2038 return False;
2039 return True;
2040
2041 def setExtraData(self, sKey, sValue):
2042 """
2043 Sets extra data.
2044 Returns the True on success, False on failure (logged).
2045 """
2046 try:
2047 self.o.machine.setExtraData(sKey, sValue);
2048 except:
2049 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2050 return False;
2051 return True;
2052
2053 def getExtraData(self, sKey):
2054 """
2055 Gets extra data.
2056 Returns value on success, None on failure.
2057 """
2058 try:
2059 sValue = self.o.machine.getExtraData(sKey)
2060 except:
2061 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue))
2062 return None
2063 return sValue
2064
2065 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2066 """
2067 Sets up the teleporter for the VM.
2068 Returns True on success, False on failure (logged).
2069 """
2070 try:
2071 self.o.machine.teleporterAddress = sAddress;
2072 self.o.machine.teleporterPort = uPort;
2073 self.o.machine.teleporterPassword = sPassword;
2074 self.o.machine.teleporterEnabled = fEnabled;
2075 except:
2076 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2077 return False;
2078 return True;
2079
2080 def enableTeleporter(self, fEnable=True):
2081 """
2082 Enables or disables the teleporter of the VM.
2083 Returns True on success, False on failure (logged).
2084 """
2085 try:
2086 self.o.machine.teleporterEnabled = fEnable;
2087 except:
2088 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2089 return False;
2090 return True;
2091
2092 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2093 """
2094 Wrapper around the IConsole::teleport() method.
2095 Returns a progress object on success, None on failure (logged).
2096 """
2097 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2098 try:
2099 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2100 except:
2101 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2102 return None;
2103 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2104
2105 def getOsType(self):
2106 """
2107 Gets the IGuestOSType interface for the machine.
2108
2109 return IGuestOSType interface on success, None + errorXcpt on failure.
2110 No exceptions raised.
2111 """
2112 try:
2113 sOsTypeId = self.o.machine.OSTypeId;
2114 except:
2115 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2116 return None;
2117
2118 try:
2119 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2120 except:
2121 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2122 return None;
2123
2124 return oOsType;
2125
2126 def setOsType(self, sNewTypeId):
2127 """
2128 Changes the OS type.
2129
2130 returns True on success, False + errorXcpt on failure.
2131 No exceptions raised.
2132 """
2133 try:
2134 self.o.machine.OSTypeId = sNewTypeId;
2135 except:
2136 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2137 return False;
2138 return True;
2139
2140
2141 def setParavirtProvider(self, iProvider):
2142 """
2143 Sets a paravirtualisation provider.
2144 Returns the True on success, False on failure (logged).
2145 """
2146 try:
2147 self.o.machine.paravirtProvider = iProvider
2148 except:
2149 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2150 return False;
2151 return True;
2152
2153
2154
2155 #
2156 # IConsole wrappers.
2157 #
2158
2159 def powerOff(self, fFudgeOnFailure = True):
2160 """
2161 Powers off the VM.
2162
2163 Returns True on success.
2164 Returns False on IConsole::powerDown() failure.
2165 Returns None if the progress object returns failure.
2166 """
2167 try:
2168 oProgress = self.o.console.powerDown();
2169 except:
2170 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2171 if fFudgeOnFailure:
2172 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2173 self.waitForTask(1000); # fudge
2174 return False;
2175
2176 rc = self.oTstDrv.waitOnProgress(oProgress);
2177 if rc < 0:
2178 self.close();
2179 if fFudgeOnFailure:
2180 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2181 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2182 return None;
2183
2184 # Wait for the VM to really power off or we'll fail to open a new session to it.
2185 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2186 return self.waitForTask(30 * 1000); # fudge
2187
2188 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2189 """
2190 Restores the given snapshot.
2191
2192 Returns True on success.
2193 Returns False on IMachine::restoreSnapshot() failure.
2194 Returns None if the progress object returns failure.
2195 """
2196 try:
2197 if self.fpApiVer >= 5.0:
2198 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2199 else:
2200 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2201 except:
2202 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2203 if fFudgeOnFailure:
2204 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2205 self.waitForTask(1000); # fudge
2206 return False;
2207
2208 rc = self.oTstDrv.waitOnProgress(oProgress);
2209 if rc < 0:
2210 self.close();
2211 if fFudgeOnFailure:
2212 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2213 return None;
2214
2215 return self.waitForTask(30 * 1000);
2216
2217 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2218 """
2219 Deletes the given snapshot merging the diff image into the base.
2220
2221 Returns True on success.
2222 Returns False on IMachine::deleteSnapshot() failure.
2223 """
2224 try:
2225 if self.fpApiVer >= 5.0:
2226 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2227 else:
2228 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2229 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2230 oProgress.wait(cMsTimeout);
2231 oProgress.logResult();
2232 except:
2233 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2234 if fFudgeOnFailure:
2235 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2236 self.waitForTask(1000); # fudge
2237 return False;
2238
2239 return True;
2240
2241 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2242 """
2243 Takes a snapshot with the given name
2244
2245 Returns True on success.
2246 Returns False on IMachine::takeSnapshot() or VM state change failure.
2247 """
2248 try:
2249 if fPause is True \
2250 and self.oVM.state is vboxcon.MachineState_Running:
2251 self.o.console.pause();
2252 if self.fpApiVer >= 5.0:
2253 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2254 else:
2255 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2256 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2257 oProgress.wait(cMsTimeout);
2258 oProgress.logResult();
2259 except:
2260 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2261 if fFudgeOnFailure:
2262 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2263 self.waitForTask(1000); # fudge
2264 return False;
2265
2266 if fPause is True \
2267 and self.oVM.state is vboxcon.MachineState_Paused:
2268 self.o.console.resume();
2269
2270 return True;
2271
2272 def findSnapshot(self, sName):
2273 """
2274 Returns the snapshot object with the given name
2275
2276 Returns snapshot object on success.
2277 Returns None if there is no snapshot with the given name.
2278 """
2279 return self.oVM.findSnapshot(sName);
2280
2281 def takeScreenshot(self, sFilename, iScreenId=0):
2282 """
2283 Take screenshot from the given display and save it to specified file.
2284
2285 Returns True on success
2286 Returns False on failure.
2287 """
2288 try:
2289 if self.fpApiVer >= 5.0:
2290 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2291 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2292 vboxcon.BitmapFormat_PNG)
2293 else:
2294 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2295 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2296 except:
2297 reporter.logXcpt("Unable to take screenshot")
2298 return False
2299
2300 oFile = open(sFilename, 'wb')
2301 oFile.write(aPngData)
2302 oFile.close()
2303
2304 return True
2305
2306 #
2307 # Other methods.
2308 #
2309
2310 def getPrimaryIp(self):
2311 """
2312 Tries to obtain the primary IP address of the guest via the guest
2313 properties.
2314
2315 Returns IP address on success.
2316 Returns empty string on failure.
2317 """
2318 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2319 if vbox.isIpAddrValid(sIpAddr):
2320 return sIpAddr;
2321 return '';
2322
2323 def getPid(self):
2324 """
2325 Gets the process ID for the direct session unless it's ourselves.
2326 """
2327 if self.uPid is None and self.o is not None and self.fRemoteSession:
2328 try:
2329 if self.fpApiVer >= 4.2:
2330 uPid = self.o.machine.sessionPID;
2331 else:
2332 uPid = self.o.machine.sessionPid;
2333 if uPid != os.getpid() and uPid != 0xffffffff:
2334 self.uPid = uPid;
2335 except Exception, oXcpt:
2336 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
2337 try:
2338 if self.fpApiVer >= 4.2:
2339 uPid = self.oVM.sessionPID;
2340 else:
2341 uPid = self.oVM.sessionPid;
2342 if uPid != os.getpid() and uPid != 0xffffffff:
2343 self.uPid = uPid;
2344 except:
2345 reporter.log2Xcpt();
2346 else:
2347 reporter.log2Xcpt();
2348 if self.uPid is not None:
2349 reporter.log2('getPid: %u' % (self.uPid,));
2350 self.oTstDrv.pidFileAdd(self.uPid);
2351 return self.uPid;
2352
2353 def addLogsToReport(self, cReleaseLogs = 1):
2354 """
2355 Retrieves and adds the release and debug logs to the test report.
2356 """
2357 fRc = True;
2358
2359 # Add each of the requested release logs to the report.
2360 for iLog in range(0, cReleaseLogs):
2361 try:
2362 if self.fpApiVer >= 3.2:
2363 sLogFile = self.oVM.queryLogFilename(iLog);
2364 elif iLog > 0:
2365 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
2366 else:
2367 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
2368 except:
2369 reporter.logXcpt('iLog=%s' % (iLog,));
2370 fRc = False;
2371 else:
2372 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
2373 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
2374 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2375
2376 # Now for the hardened windows startup log.
2377 try:
2378 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxStartup.log');
2379 except:
2380 reporter.logXcpt();
2381 fRc = False;
2382 else:
2383 if os.path.isfile(sLogFile):
2384 reporter.addLogFile(sLogFile, 'log/release/vm', '%s startup log' % (self.sName, ),
2385 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2386
2387 # Now for the debug log.
2388 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
2389 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
2390 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
2391
2392 return fRc;
2393
2394 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
2395 """
2396 Create an instance of the given ConsoleEventHandlerBase sub-class and
2397 register it.
2398
2399 The new instance is returned on success. None is returned on error.
2400 """
2401
2402 # We need a console object.
2403 try:
2404 oConsole = self.o.console;
2405 except Exception, oXcpt:
2406 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
2407 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
2408 return None;
2409
2410 # Add the base class arguments.
2411 dArgsCopy = dArgs.copy() if dArgs is not None else dict();
2412 dArgsCopy['oSession'] = self;
2413 dArgsCopy['oConsole'] = oConsole;
2414 sLogSuffix = 'on %s' % (self.sName,)
2415 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
2416 oConsole, 'IConsole', 'IConsoleCallback',
2417 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
2418
2419 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
2420 """
2421 Enables the testing part of the VMMDev.
2422
2423 Returns True on success and False on failure. Error information is logged.
2424 """
2425 fRc = True;
2426 try:
2427 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
2428 '1' if fEnabled else '');
2429 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
2430 '1' if fEnableMMIO and fEnabled else '');
2431 except:
2432 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
2433 fRc = False;
2434 else:
2435 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
2436 self.oTstDrv.processPendingEvents();
2437 return fRc;
2438
2439 #
2440 # Test eXecution Service methods.
2441 #
2442
2443 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, sMacAddr = None, fNatForwardingForTxs = False):
2444 """
2445 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
2446 addresses are specified, we'll get the IP from the guest additions.
2447
2448 Returns a TxsConnectTask object on success, None + log on failure.
2449 """
2450 # If the VM is configured with a NAT interface, connect to local host.
2451 fReversedSetup = False;
2452 fUseNatForTxs = False;
2453 if sIpAddr == None:
2454 try:
2455 oNic = self.oVM.getNetworkAdapter(0);
2456 if oNic.attachmentType == vboxcon.NetworkAttachmentType_NAT:
2457 fUseNatForTxs = True;
2458 except:
2459 reporter.errorXcpt();
2460 return None;
2461 if fUseNatForTxs:
2462 fReversedSetup = not fNatForwardingForTxs;
2463 sIpAddr = '127.0.0.1';
2464
2465 # Kick off the task.
2466 try:
2467 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup);
2468 except:
2469 reporter.errorXcpt();
2470 oTask = None;
2471 return oTask;
2472
2473 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
2474 """
2475 Attempts to connect to a TXS instance.
2476
2477 Returns True if a connection was established, False if not (only grave
2478 failures are logged as errors).
2479
2480 Note! The timeout is more of a guideline...
2481 """
2482
2483 if sHostname is None or sHostname.strip() == '':
2484 raise base.GenError('Empty sHostname is not implemented yet');
2485
2486 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
2487 cMsIdleFudge = cMsTimeout / 2);
2488 if oTxsSession is None:
2489 return False;
2490
2491 # Wait for the connect task to time out.
2492 self.oTstDrv.addTask(oTxsSession);
2493 self.oTstDrv.processPendingEvents();
2494 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
2495 self.oTstDrv.removeTask(oTxsSession);
2496 if oRc != oTxsSession:
2497 if oRc is not None:
2498 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
2499 self.oTstDrv.processPendingEvents();
2500 oTxsSession.cancelTask(); # this is synchronous
2501 return False;
2502
2503 # Check the status.
2504 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
2505 if not oTxsSession.isSuccess():
2506 return False;
2507
2508 reporter.log2('Disconnecting from TXS...');
2509 return oTxsSession.syncDisconnect();
2510
2511
2512
2513class TxsConnectTask(TdTaskBase):
2514 """
2515 Class that takes care of connecting to a VM.
2516 """
2517
2518 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
2519 """ Class for looking for IPv4 address changes on interface 0."""
2520 def __init__(self, dArgs):
2521 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs); # pylint: disable=W0233
2522 self.oParentTask = dArgs['oParentTask'];
2523 self.sMachineId = dArgs['sMachineId'];
2524
2525 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags):
2526 """Look for IP address."""
2527 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags));
2528 if sMachineId == self.sMachineId \
2529 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
2530 self.oParentTask._setIp(sValue); # pylint: disable=W0212
2531
2532
2533 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup):
2534 TdTaskBase.__init__(self, utils.getCallerName());
2535 self.cMsTimeout = cMsTimeout;
2536 self.sIpAddr = None;
2537 self.sNextIpAddr = None;
2538 self.sMacAddr = sMacAddr;
2539 self.fReversedSetup = fReversedSetup;
2540 self.oVBox = oSession.oVBox;
2541 self.oVBoxEventHandler = None;
2542 self.oTxsSession = None;
2543 self.fpApiVer = oSession.fpApiVer;
2544
2545 # Skip things we don't implement.
2546 if sMacAddr is not None:
2547 reporter.error('TxsConnectTask does not implement sMacAddr yet');
2548 raise base.GenError();
2549
2550 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
2551 if fReversedSetup is True:
2552 self._openTcpSession(sIpAddr, fReversedSetup = True);
2553 elif sIpAddr is not None and sIpAddr.strip() != '':
2554 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2555 else:
2556 #
2557 # If we've got no IP address, register callbacks that listens for
2558 # the primary network adaptor of the VM to set a IPv4 guest prop.
2559 # Note! The order in which things are done here is kind of important.
2560 #
2561
2562 # 0. The caller zaps the property before starting the VM.
2563 #try:
2564 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2565 #except:
2566 # reporter.logXcpt();
2567
2568 # 1. Register the callback / event listener object.
2569 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
2570 self.oVBoxEventHandler = self.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
2571
2572 # 2. Query the guest properties.
2573 try:
2574 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2575 except:
2576 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
2577 self._deregisterEventHandler();
2578 raise;
2579 else:
2580 if sIpAddr is not None:
2581 self._setIp(sIpAddr);
2582 # end __init__
2583
2584 def __del__(self):
2585 """ Make sure we deregister the callback. """
2586 self._deregisterEventHandler();
2587 return TdTaskBase.__del__(self);
2588
2589 def toString(self):
2590 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
2591 ' oTxsSession=%s oVBoxEventHandler=%s, oVBox=%s>' \
2592 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
2593 self.oTxsSession, self.oVBoxEventHandler, self.oVBox);
2594
2595 def _deregisterEventHandler(self):
2596 """Deregisters the event handler."""
2597 fRc = True;
2598 if self.oVBoxEventHandler is not None:
2599 fRc = self.oVBoxEventHandler.unregister();
2600 self.oVBoxEventHandler = None;
2601 return fRc;
2602
2603 def _setIp(self, sIpAddr, fInitCall = False):
2604 """Called when we get an IP. Will create a TXS session and signal the task."""
2605 sIpAddr = sIpAddr.strip();
2606
2607 if sIpAddr is not None \
2608 and sIpAddr != '':
2609 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
2610 try:
2611 for s in sIpAddr.split('.'):
2612 i = int(s);
2613 if str(i) != s:
2614 raise Exception();
2615 except:
2616 reporter.fatalXcpt();
2617 else:
2618 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2619 return None;
2620
2621 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
2622 else:
2623 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
2624 return None;
2625
2626 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
2627 """
2628 Calls txsclient.openTcpSession and switches our task to reflect the
2629 state of the subtask.
2630 """
2631 self.oCv.acquire();
2632 if self.oTxsSession is None:
2633 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' % \
2634 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
2635 self.sIpAddr = sIpAddr;
2636 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, \
2637 fReversedSetup, cMsIdleFudge);
2638 self.oTxsSession.setTaskOwner(self);
2639 else:
2640 self.sNextIpAddr = sIpAddr;
2641 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
2642 self.oCv.release();
2643 return None;
2644
2645 def notifyAboutReadyTask(self, oTxsSession):
2646 """
2647 Called by the TXS session task when it's done.
2648
2649 We'll signal the task completed or retry depending on the result.
2650 """
2651
2652 self.oCv.acquire();
2653
2654 # Disassociate ourselves with the session (avoid cyclic ref)
2655 oTxsSession.setTaskOwner(None);
2656 fSuccess = oTxsSession.isSuccess();
2657 if self.oTxsSession is not None:
2658 if not fSuccess:
2659 self.oTxsSession = None;
2660 if fSuccess and self.fReversedSetup:
2661 self.sIpAddr = oTxsSession.oTransport.sHostname;
2662 else:
2663 fSuccess = False;
2664
2665 # Signal done, or retry?
2666 if fSuccess \
2667 or self.fReversedSetup \
2668 or self.getAgeAsMs() >= self.cMsTimeout:
2669 self.signalTaskLocked();
2670 else:
2671 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
2672 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2673
2674 self.oCv.release();
2675 return True;
2676
2677 #
2678 # Public methods
2679 #
2680
2681 def getResult(self):
2682 """
2683 Returns the connected TXS session object on success.
2684 Returns None on failure or if the task has not yet completed.
2685 """
2686 self.oCv.acquire();
2687 oTxsSession = self.oTxsSession;
2688 self.oCv.release();
2689
2690 if oTxsSession is not None and not oTxsSession.isSuccess():
2691 oTxsSession = None;
2692 return oTxsSession;
2693
2694 def cancelTask(self):
2695 """ Cancels the task. """
2696 self.oCv.acquire();
2697 if not self.fSignalled:
2698 oTxsSession = self.oTxsSession;
2699 if oTxsSession is not None:
2700 self.oCv.release();
2701 oTxsSession.setTaskOwner(None);
2702 oTxsSession.cancelTask();
2703 oTxsSession.waitForTask(1000);
2704 self.oCv.acquire();
2705 self.signalTaskLocked();
2706 self.oCv.release();
2707 return True;
2708
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