VirtualBox

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

Last change on this file since 63746 was 63746, checked in by vboxsync, 8 years ago

ValidationKit/tdStorageBenchmark: Add option to test the different host I/O cache settings for each controller

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

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