VirtualBox

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

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

ValidationKit/testdriver/vboxwrappers.py: deregister event handler relatively early to avoid racing against VM process termination, which causes otherwise annoying spurious complaints about no longer existing event objects

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