VirtualBox

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

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

vboxwrappers.py: VBoxStartup.log -> VBoxHardening.log

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

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