VirtualBox

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

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

ValidationKit/tdStorageBenchmark: Support testing different depths of diff images

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 115.2 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 63761 2016-09-08 09:49:41Z 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: 63761 $"
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 # Detect the proper format if requested
1841 if sFmt is None:
1842 try:
1843 oHdFmt = oParentHd.mediumFormat;
1844 lstCaps = self.oVBoxMgr.getArray(oHdFmt, 'capabilities');
1845 if vboxcon.MediumFormatCapabilities_Differencing in lstCaps:
1846 sFmt = oHdFmt.id;
1847 else:
1848 sFmt = 'VDI';
1849 except:
1850 reporter.errorXcpt('failed to get preferred diff format for "%s"' % (sHd));
1851 return None;
1852 try:
1853 if self.fpApiVer >= 5.0:
1854 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1855 else:
1856 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1857 oProgressXpcom = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
1858 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
1859 oProgress.wait();
1860 oProgress.logResult();
1861 except:
1862 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
1863 oHd = None
1864
1865 return oHd;
1866
1867 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, # pylint: disable=R0913
1868 iPort = 0, iDevice = 0, fImmutable = True, cMsTimeout = 60000, tMediumVariant = None):
1869 """
1870 Creates and attaches a HD to a VM.
1871 Returns True on success and False on failure. Error information is logged.
1872 """
1873 if not self.ensureControllerAttached(sController):
1874 return False;
1875
1876 oHd = self.createBaseHd(sHd, sFmt, cb, cMsTimeout, tMediumVariant);
1877 if oHd is None:
1878 return False;
1879
1880 fRc = True;
1881 try:
1882 if fImmutable:
1883 oHd.type = vboxcon.MediumType_Immutable;
1884 else:
1885 oHd.type = vboxcon.MediumType_Normal;
1886 except:
1887 if fImmutable:
1888 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1889 else:
1890 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1891 fRc = False;
1892
1893 # Attach it.
1894 if fRc is True:
1895 try:
1896 if self.fpApiVer >= 4.0:
1897 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1898 else:
1899 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1900 except:
1901 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1902 % (sController, iPort, iDevice, oHd.id, self.sName) );
1903 fRc = False;
1904 else:
1905 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1906
1907 # Delete disk in case of an error
1908 if fRc is False:
1909 try:
1910 oProgressCom = oHd.deleteStorage();
1911 except:
1912 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
1913 else:
1914 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
1915 oProgress.wait();
1916 oProgress.logResult();
1917
1918 self.oTstDrv.processPendingEvents();
1919 return fRc;
1920
1921 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
1922 """
1923 Detaches a HD, if attached, and returns a reference to it (IMedium).
1924
1925 In order to delete the detached medium, the caller must first save
1926 the changes made in this session.
1927
1928 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
1929 your standard success indicator. Error information is logged.
1930 """
1931
1932 # What's attached?
1933 try:
1934 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
1935 except:
1936 if self.oVBoxMgr.xcptIsOurXcptKind() \
1937 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
1938 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
1939 return (True, None);
1940 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
1941 % (iPort, iDevice, sController)), None);
1942 # Detach it.
1943 try:
1944 self.o.machine.detachDevice(sController, iPort, iDevice);
1945 except:
1946 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
1947 % (sController, iPort, iDevice, self.sName) ), None);
1948 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
1949 return (True, oHd);
1950
1951 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
1952 """
1953 Attaches a floppy image to a VM.
1954 Returns True on success and False on failure. Error information is logged.
1955 """
1956 # Input validation.
1957 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
1958 ##if not self.oTstDrv.isResourceFile(sFloppy):
1959 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
1960 ## return None;
1961
1962 if not self.ensureControllerAttached(sController):
1963 return False;
1964
1965 # Find the floppy image, registering it if necessary (as immutable).
1966 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
1967 try:
1968 oFloppy = self.oVBox.findFloppyImage(sFullName);
1969 except:
1970 try:
1971 if self.fpApiVer >= 4.1:
1972 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
1973 elif self.fpApiVer >= 4.0:
1974 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
1975 else:
1976 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
1977 except:
1978 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
1979 return False;
1980 ## @todo the following works but causes trouble below (asserts in main).
1981 #try:
1982 # oFloppy.type = vboxcon.MediumType_Immutable;
1983 #except:
1984 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
1985 # return False;
1986
1987 # Attach it.
1988 fRc = True;
1989 try:
1990 if self.fpApiVer >= 4.0:
1991 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
1992 else:
1993 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
1994 except:
1995 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
1996 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
1997 fRc = False;
1998 else:
1999 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
2000 self.oTstDrv.processPendingEvents();
2001 return fRc;
2002
2003 def setupNic(self, sType, sXXX):
2004 """
2005 Attaches a HD to a VM.
2006 Returns True on success and False on failure. Error information is logged.
2007 """
2008 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
2009 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
2010 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
2011 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
2012 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
2013 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
2014 else:
2015 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
2016 return False;
2017 ## @todo Implement me!
2018 if enmType is not None: pass
2019 return True;
2020
2021 def setupAudio(self, eAudioCtlType):
2022 """
2023 Set guest audio controller type and host audio adapter to null
2024 @param eAudioCtlType device type (vboxcon.AudioControllerType_SB16,
2025 vboxcon.AudioControllerType_AC97, vboxcon.AudioControllerType_HDA)
2026 """
2027 try:
2028 oAudioAdapter = self.o.machine.audioAdapter;
2029
2030 oAudioAdapter.audioController = eAudioCtlType;
2031 oAudioAdapter.audioDriver = vboxcon.AudioDriverType_Null;
2032 # Disable by default
2033 oAudioAdapter.enabled = False;
2034 except:
2035 return reporter.errorXcpt('Unable to set audio adapter.')
2036
2037 reporter.log('set audio adapter type to %d' % (eAudioCtlType))
2038 self.oTstDrv.processPendingEvents();
2039
2040 return True
2041
2042 def setupPreferredConfig(self): # pylint: disable=R0914
2043 """
2044 Configures the VM according to the preferences of the guest type.
2045 """
2046 try:
2047 sOsTypeId = self.o.machine.OSTypeId;
2048 except:
2049 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2050 return False;
2051
2052 try:
2053 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2054 except:
2055 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2056 return False;
2057
2058 # get the attributes.
2059 try:
2060 #sFamilyId = oOsType.familyId;
2061 #f64Bit = oOsType.is64Bit;
2062 fIoApic = oOsType.recommendedIOAPIC;
2063 fVirtEx = oOsType.recommendedVirtEx;
2064 cMBRam = oOsType.recommendedRAM;
2065 cMBVRam = oOsType.recommendedVRAM;
2066 #cMBHdd = oOsType.recommendedHDD;
2067 eNicType = oOsType.adapterType;
2068 if self.fpApiVer >= 3.2:
2069 if self.fpApiVer >= 4.2:
2070 fPae = oOsType.recommendedPAE;
2071 fUsbHid = oOsType.recommendedUSBHID;
2072 fHpet = oOsType.recommendedHPET;
2073 eStorCtlType = oOsType.recommendedHDStorageController;
2074 else:
2075 fPae = oOsType.recommendedPae;
2076 fUsbHid = oOsType.recommendedUsbHid;
2077 fHpet = oOsType.recommendedHpet;
2078 eStorCtlType = oOsType.recommendedHdStorageController;
2079 eFirmwareType = oOsType.recommendedFirmware;
2080 else:
2081 fPae = False;
2082 fUsbHid = False;
2083 fHpet = False;
2084 eFirmwareType = -1;
2085 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
2086 if self.fpApiVer >= 4.0:
2087 eAudioCtlType = oOsType.recommendedAudioController;
2088 except:
2089 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
2090 self.oTstDrv.processPendingEvents();
2091 return False;
2092 self.oTstDrv.processPendingEvents();
2093
2094 # Do the setting. Continue applying settings on error in case the
2095 # caller ignores the return code
2096 fRc = True;
2097 if not self.enableIoApic(fIoApic): fRc = False;
2098 if not self.enableVirtEx(fVirtEx): fRc = False;
2099 if not self.enablePae(fPae): fRc = False;
2100 if not self.setRamSize(cMBRam): fRc = False;
2101 if not self.setVRamSize(cMBVRam): fRc = False;
2102 if not self.setNicType(eNicType, 0): fRc = False;
2103 if self.fpApiVer >= 3.2:
2104 if not self.setFirmwareType(eFirmwareType): fRc = False;
2105 if not self.enableUsbHid(fUsbHid): fRc = False;
2106 if not self.enableHpet(fHpet): fRc = False;
2107 if eStorCtlType == vboxcon.StorageControllerType_PIIX3 \
2108 or eStorCtlType == vboxcon.StorageControllerType_PIIX4 \
2109 or eStorCtlType == vboxcon.StorageControllerType_ICH6:
2110 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
2111 fRc = False;
2112 if self.fpApiVer >= 4.0:
2113 if not self.setupAudio(eAudioCtlType): fRc = False;
2114
2115 return fRc;
2116
2117 def addUsbDeviceFilter(self, sName, sVendorId = None, sProductId = None, sRevision = None, # pylint: disable=R0913
2118 sManufacturer = None, sProduct = None, sSerialNumber = None,
2119 sPort = None, sRemote = None):
2120 """
2121 Creates a USB device filter and inserts it into the VM.
2122 Returns True on success.
2123 Returns False on failure (logged).
2124 """
2125 fRc = True;
2126
2127 try:
2128 oUsbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
2129 oUsbDevFilter.active = True;
2130 if sVendorId is not None:
2131 oUsbDevFilter.vendorId = sVendorId;
2132 if sProductId is not None:
2133 oUsbDevFilter.productId = sProductId;
2134 if sRevision is not None:
2135 oUsbDevFilter.revision = sRevision;
2136 if sManufacturer is not None:
2137 oUsbDevFilter.manufacturer = sManufacturer;
2138 if sProduct is not None:
2139 oUsbDevFilter.product = sProduct;
2140 if sSerialNumber is not None:
2141 oUsbDevFilter.serialnumber = sSerialNumber;
2142 if sPort is not None:
2143 oUsbDevFilter.port = sPort;
2144 if sRemote is not None:
2145 oUsbDevFilter.remote = sRemote;
2146 try:
2147 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, oUsbDevFilter);
2148 except:
2149 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
2150 % (0, self.sName) );
2151 fRc = False;
2152 else:
2153 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
2154 except:
2155 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
2156 % (sName, self.sName) );
2157 fRc = False;
2158 return fRc;
2159
2160 def getGuestPropertyValue(self, sName):
2161 """
2162 Gets a guest property value.
2163 Returns the value on success, None on failure (logged).
2164 """
2165 try:
2166 sValue = self.o.machine.getGuestPropertyValue(sName);
2167 except:
2168 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2169 return None;
2170 return sValue;
2171
2172 def setGuestPropertyValue(self, sName, sValue):
2173 """
2174 Sets a guest property value.
2175 Returns the True on success, False on failure (logged).
2176 """
2177 try:
2178 self.o.machine.setGuestPropertyValue(sName, sValue);
2179 except:
2180 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2181 return False;
2182 return True;
2183
2184 def delGuestPropertyValue(self, sName):
2185 """
2186 Deletes a guest property value.
2187 Returns the True on success, False on failure (logged).
2188 """
2189 try:
2190 oMachine = self.o.machine;
2191 if self.fpApiVer >= 4.2:
2192 oMachine.deleteGuestProperty(sName);
2193 else:
2194 oMachine.setGuestPropertyValue(sName, '');
2195 except:
2196 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2197 return False;
2198 return True;
2199
2200 def setExtraData(self, sKey, sValue):
2201 """
2202 Sets extra data.
2203 Returns the True on success, False on failure (logged).
2204 """
2205 try:
2206 self.o.machine.setExtraData(sKey, sValue);
2207 except:
2208 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2209 return False;
2210 return True;
2211
2212 def getExtraData(self, sKey):
2213 """
2214 Gets extra data.
2215 Returns value on success, None on failure.
2216 """
2217 try:
2218 sValue = self.o.machine.getExtraData(sKey)
2219 except:
2220 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue))
2221 return None
2222 return sValue
2223
2224 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2225 """
2226 Sets up the teleporter for the VM.
2227 Returns True on success, False on failure (logged).
2228 """
2229 try:
2230 self.o.machine.teleporterAddress = sAddress;
2231 self.o.machine.teleporterPort = uPort;
2232 self.o.machine.teleporterPassword = sPassword;
2233 self.o.machine.teleporterEnabled = fEnabled;
2234 except:
2235 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2236 return False;
2237 return True;
2238
2239 def enableTeleporter(self, fEnable=True):
2240 """
2241 Enables or disables the teleporter of the VM.
2242 Returns True on success, False on failure (logged).
2243 """
2244 try:
2245 self.o.machine.teleporterEnabled = fEnable;
2246 except:
2247 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2248 return False;
2249 return True;
2250
2251 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2252 """
2253 Wrapper around the IConsole::teleport() method.
2254 Returns a progress object on success, None on failure (logged).
2255 """
2256 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2257 try:
2258 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2259 except:
2260 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2261 return None;
2262 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2263
2264 def getOsType(self):
2265 """
2266 Gets the IGuestOSType interface for the machine.
2267
2268 return IGuestOSType interface on success, None + errorXcpt on failure.
2269 No exceptions raised.
2270 """
2271 try:
2272 sOsTypeId = self.o.machine.OSTypeId;
2273 except:
2274 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2275 return None;
2276
2277 try:
2278 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2279 except:
2280 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2281 return None;
2282
2283 return oOsType;
2284
2285 def setOsType(self, sNewTypeId):
2286 """
2287 Changes the OS type.
2288
2289 returns True on success, False + errorXcpt on failure.
2290 No exceptions raised.
2291 """
2292 try:
2293 self.o.machine.OSTypeId = sNewTypeId;
2294 except:
2295 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2296 return False;
2297 return True;
2298
2299
2300 def setParavirtProvider(self, iProvider):
2301 """
2302 Sets a paravirtualisation provider.
2303 Returns the True on success, False on failure (logged).
2304 """
2305 try:
2306 self.o.machine.paravirtProvider = iProvider
2307 except:
2308 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2309 return False;
2310 return True;
2311
2312
2313
2314 #
2315 # IConsole wrappers.
2316 #
2317
2318 def powerOff(self, fFudgeOnFailure = True):
2319 """
2320 Powers off the VM.
2321
2322 Returns True on success.
2323 Returns False on IConsole::powerDown() failure.
2324 Returns None if the progress object returns failure.
2325 """
2326 #
2327 # Deregister event handler before we power off the VM, otherwise we're
2328 # racing for VM process termination and cause misleading spurious
2329 # error messages in the event handling code, because the event objects
2330 # disappear.
2331 #
2332 # Note! Doing this before powerDown to try prevent numerous smoketest
2333 # timeouts on XPCOM hosts.
2334 #
2335 self.deregisterEventHandlerForTask();
2336
2337
2338 # Try power if off.
2339 try:
2340 oProgress = self.o.console.powerDown();
2341 except:
2342 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2343 if fFudgeOnFailure:
2344 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2345 self.waitForTask(1000); # fudge
2346 return False;
2347
2348 # Wait on power off operation to complete.
2349 rc = self.oTstDrv.waitOnProgress(oProgress);
2350 if rc < 0:
2351 self.close();
2352 if fFudgeOnFailure:
2353 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2354 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2355 return None;
2356
2357 # Wait for the VM to really power off or we'll fail to open a new session to it.
2358 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2359 return self.waitForTask(30 * 1000); # fudge
2360
2361 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2362 """
2363 Restores the given snapshot.
2364
2365 Returns True on success.
2366 Returns False on IMachine::restoreSnapshot() failure.
2367 Returns None if the progress object returns failure.
2368 """
2369 try:
2370 if self.fpApiVer >= 5.0:
2371 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2372 else:
2373 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2374 except:
2375 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2376 if fFudgeOnFailure:
2377 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2378 self.waitForTask(1000); # fudge
2379 return False;
2380
2381 rc = self.oTstDrv.waitOnProgress(oProgress);
2382 if rc < 0:
2383 self.close();
2384 if fFudgeOnFailure:
2385 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2386 return None;
2387
2388 return self.waitForTask(30 * 1000);
2389
2390 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2391 """
2392 Deletes the given snapshot merging the diff image into the base.
2393
2394 Returns True on success.
2395 Returns False on IMachine::deleteSnapshot() failure.
2396 """
2397 try:
2398 if self.fpApiVer >= 5.0:
2399 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2400 else:
2401 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2402 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2403 oProgress.wait(cMsTimeout);
2404 oProgress.logResult();
2405 except:
2406 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2407 if fFudgeOnFailure:
2408 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2409 self.waitForTask(1000); # fudge
2410 return False;
2411
2412 return True;
2413
2414 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2415 """
2416 Takes a snapshot with the given name
2417
2418 Returns True on success.
2419 Returns False on IMachine::takeSnapshot() or VM state change failure.
2420 """
2421 try:
2422 if fPause is True \
2423 and self.oVM.state is vboxcon.MachineState_Running:
2424 self.o.console.pause();
2425 if self.fpApiVer >= 5.0:
2426 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2427 else:
2428 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2429 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2430 oProgress.wait(cMsTimeout);
2431 oProgress.logResult();
2432 except:
2433 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2434 if fFudgeOnFailure:
2435 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2436 self.waitForTask(1000); # fudge
2437 return False;
2438
2439 if fPause is True \
2440 and self.oVM.state is vboxcon.MachineState_Paused:
2441 self.o.console.resume();
2442
2443 return True;
2444
2445 def findSnapshot(self, sName):
2446 """
2447 Returns the snapshot object with the given name
2448
2449 Returns snapshot object on success.
2450 Returns None if there is no snapshot with the given name.
2451 """
2452 return self.oVM.findSnapshot(sName);
2453
2454 def takeScreenshot(self, sFilename, iScreenId=0):
2455 """
2456 Take screenshot from the given display and save it to specified file.
2457
2458 Returns True on success
2459 Returns False on failure.
2460 """
2461 try:
2462 if self.fpApiVer >= 5.0:
2463 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2464 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2465 vboxcon.BitmapFormat_PNG)
2466 else:
2467 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2468 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2469 except:
2470 reporter.logXcpt("Unable to take screenshot")
2471 return False
2472
2473 oFile = open(sFilename, 'wb')
2474 oFile.write(aPngData)
2475 oFile.close()
2476
2477 return True
2478
2479 #
2480 # IMachineDebugger wrappers.
2481 #
2482
2483 def queryOsKernelLog(self):
2484 """
2485 Tries to get the OS kernel log using the VM debugger interface.
2486
2487 Returns string containing the kernel log on success.
2488 Returns None on failure.
2489 """
2490 sOsKernelLog = None;
2491 try:
2492 self.o.console.debugger.loadPlugIn('all');
2493 except:
2494 reporter.logXcpt('Unable to load debugger plugins');
2495 else:
2496 try:
2497 sOsDetected = self.o.console.debugger.detectOS();
2498 except:
2499 reporter.logXcpt('Failed to detect the guest OS');
2500 else:
2501 try:
2502 sOsKernelLog = self.o.console.debugger.queryOSKernelLog(0);
2503 except:
2504 reporter.logXcpt('Unable to get the guest OS (%s) kernel log' % (sOsDetected,));
2505 return sOsKernelLog;
2506
2507 def queryDbgInfo(self, sItem, sArg = '', sDefault = None):
2508 """
2509 Simple wrapper around IMachineDebugger::info.
2510
2511 Returns string on success, sDefault on failure (logged).
2512 """
2513 try:
2514 return self.o.console.debugger.info(sItem, sArg);
2515 except:
2516 reporter.logXcpt('Unable to query "%s" with arg "%s"' % (sItem, sArg,));
2517 return sDefault;
2518
2519 def queryDbgInfoVgaText(self, sArg = 'all'):
2520 """
2521 Tries to get the 'info vgatext' output, provided we're in next mode.
2522
2523 Returns string containing text on success.
2524 Returns None on failure or not text mode.
2525 """
2526 sVgaText = None;
2527 try:
2528 sVgaText = self.o.console.debugger.info('vgatext', sArg);
2529 if sVgaText.startswith('Not in text mode!'):
2530 sVgaText = None;
2531 except:
2532 reporter.logXcpt('Unable to query vgatext with arg "%s"' % (sArg,));
2533 return sVgaText;
2534
2535 def queryDbgGuestStack(self, iCpu = 0):
2536 """
2537 Returns the guest stack for the given VCPU.
2538
2539 Returns string containing the guest stack for the selected VCPU on success.
2540 Returns None on failure.
2541 """
2542
2543 #
2544 # Load all plugins first and try to detect the OS so we can
2545 # get nicer stack traces.
2546 #
2547 try:
2548 self.o.console.debugger.loadPlugIn('all');
2549 except:
2550 reporter.logXcpt('Unable to load debugger plugins');
2551 else:
2552 try:
2553 sOsDetected = self.o.console.debugger.detectOS();
2554 _ = sOsDetected;
2555 except:
2556 reporter.logXcpt('Failed to detect the guest OS');
2557
2558 sGuestStack = None;
2559 try:
2560 sGuestStack = self.o.console.debugger.dumpGuestStack(iCpu);
2561 except:
2562 reporter.logXcpt('Unable to query guest stack for CPU %s' % (iCpu, ));
2563
2564 return sGuestStack;
2565
2566
2567 #
2568 # Other methods.
2569 #
2570
2571 def getPrimaryIp(self):
2572 """
2573 Tries to obtain the primary IP address of the guest via the guest
2574 properties.
2575
2576 Returns IP address on success.
2577 Returns empty string on failure.
2578 """
2579 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2580 if vbox.isIpAddrValid(sIpAddr):
2581 return sIpAddr;
2582 return '';
2583
2584 def getPid(self):
2585 """
2586 Gets the process ID for the direct session unless it's ourselves.
2587 """
2588 if self.uPid is None and self.o is not None and self.fRemoteSession:
2589 try:
2590 if self.fpApiVer >= 4.2:
2591 uPid = self.o.machine.sessionPID;
2592 else:
2593 uPid = self.o.machine.sessionPid;
2594 if uPid != os.getpid() and uPid != 0xffffffff:
2595 self.uPid = uPid;
2596 except Exception, oXcpt:
2597 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
2598 try:
2599 if self.fpApiVer >= 4.2:
2600 uPid = self.oVM.sessionPID;
2601 else:
2602 uPid = self.oVM.sessionPid;
2603 if uPid != os.getpid() and uPid != 0xffffffff:
2604 self.uPid = uPid;
2605 except:
2606 reporter.log2Xcpt();
2607 else:
2608 reporter.log2Xcpt();
2609 if self.uPid is not None:
2610 reporter.log2('getPid: %u' % (self.uPid,));
2611 self.oTstDrv.pidFileAdd(self.uPid);
2612 return self.uPid;
2613
2614 def addLogsToReport(self, cReleaseLogs = 1):
2615 """
2616 Retrieves and adds the release and debug logs to the test report.
2617 """
2618 fRc = True;
2619
2620 # Add each of the requested release logs to the report.
2621 for iLog in range(0, cReleaseLogs):
2622 try:
2623 if self.fpApiVer >= 3.2:
2624 sLogFile = self.oVM.queryLogFilename(iLog);
2625 elif iLog > 0:
2626 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
2627 else:
2628 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
2629 except:
2630 reporter.logXcpt('iLog=%s' % (iLog,));
2631 fRc = False;
2632 else:
2633 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
2634 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
2635 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2636
2637 # Now for the hardened windows startup log.
2638 try:
2639 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxHardening.log');
2640 except:
2641 reporter.logXcpt();
2642 fRc = False;
2643 else:
2644 if os.path.isfile(sLogFile):
2645 reporter.addLogFile(sLogFile, 'log/release/vm', '%s hardening log' % (self.sName, ),
2646 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2647
2648 # Now for the debug log.
2649 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
2650 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
2651 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
2652
2653 return fRc;
2654
2655 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
2656 """
2657 Create an instance of the given ConsoleEventHandlerBase sub-class and
2658 register it.
2659
2660 The new instance is returned on success. None is returned on error.
2661 """
2662
2663 # We need a console object.
2664 try:
2665 oConsole = self.o.console;
2666 except Exception, oXcpt:
2667 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
2668 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
2669 return None;
2670
2671 # Add the base class arguments.
2672 dArgsCopy = dArgs.copy() if dArgs is not None else dict();
2673 dArgsCopy['oSession'] = self;
2674 dArgsCopy['oConsole'] = oConsole;
2675 sLogSuffix = 'on %s' % (self.sName,)
2676 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
2677 oConsole, 'IConsole', 'IConsoleCallback',
2678 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
2679
2680 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
2681 """
2682 Enables the testing part of the VMMDev.
2683
2684 Returns True on success and False on failure. Error information is logged.
2685 """
2686 fRc = True;
2687 try:
2688 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
2689 '1' if fEnabled else '');
2690 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
2691 '1' if fEnableMMIO and fEnabled else '');
2692 except:
2693 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
2694 fRc = False;
2695 else:
2696 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
2697 self.oTstDrv.processPendingEvents();
2698 return fRc;
2699
2700 #
2701 # Test eXecution Service methods.
2702 #
2703
2704 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, sMacAddr = None, fNatForwardingForTxs = False):
2705 """
2706 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
2707 addresses are specified, we'll get the IP from the guest additions.
2708
2709 Returns a TxsConnectTask object on success, None + log on failure.
2710 """
2711 # If the VM is configured with a NAT interface, connect to local host.
2712 fReversedSetup = False;
2713 fUseNatForTxs = False;
2714 if sIpAddr is None:
2715 try:
2716 oNic = self.oVM.getNetworkAdapter(0);
2717 if oNic.attachmentType == vboxcon.NetworkAttachmentType_NAT:
2718 fUseNatForTxs = True;
2719 except:
2720 reporter.errorXcpt();
2721 return None;
2722 if fUseNatForTxs:
2723 fReversedSetup = not fNatForwardingForTxs;
2724 sIpAddr = '127.0.0.1';
2725
2726 # Kick off the task.
2727 try:
2728 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup);
2729 except:
2730 reporter.errorXcpt();
2731 oTask = None;
2732 return oTask;
2733
2734 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
2735 """
2736 Attempts to connect to a TXS instance.
2737
2738 Returns True if a connection was established, False if not (only grave
2739 failures are logged as errors).
2740
2741 Note! The timeout is more of a guideline...
2742 """
2743
2744 if sHostname is None or sHostname.strip() == '':
2745 raise base.GenError('Empty sHostname is not implemented yet');
2746
2747 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
2748 cMsIdleFudge = cMsTimeout / 2);
2749 if oTxsSession is None:
2750 return False;
2751
2752 # Wait for the connect task to time out.
2753 self.oTstDrv.addTask(oTxsSession);
2754 self.oTstDrv.processPendingEvents();
2755 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
2756 self.oTstDrv.removeTask(oTxsSession);
2757 if oRc != oTxsSession:
2758 if oRc is not None:
2759 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
2760 self.oTstDrv.processPendingEvents();
2761 oTxsSession.cancelTask(); # this is synchronous
2762 return False;
2763
2764 # Check the status.
2765 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
2766 if not oTxsSession.isSuccess():
2767 return False;
2768
2769 reporter.log2('Disconnecting from TXS...');
2770 return oTxsSession.syncDisconnect();
2771
2772
2773
2774class TxsConnectTask(TdTaskBase):
2775 """
2776 Class that takes care of connecting to a VM.
2777 """
2778
2779 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
2780 """ Class for looking for IPv4 address changes on interface 0."""
2781 def __init__(self, dArgs):
2782 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs); # pylint: disable=W0233
2783 self.oParentTask = dArgs['oParentTask'];
2784 self.sMachineId = dArgs['sMachineId'];
2785
2786 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags):
2787 """Look for IP address."""
2788 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags));
2789 if sMachineId == self.sMachineId \
2790 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
2791 self.oParentTask._setIp(sValue); # pylint: disable=W0212
2792
2793
2794 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup):
2795 TdTaskBase.__init__(self, utils.getCallerName());
2796 self.cMsTimeout = cMsTimeout;
2797 self.sIpAddr = None;
2798 self.sNextIpAddr = None;
2799 self.sMacAddr = sMacAddr;
2800 self.fReversedSetup = fReversedSetup;
2801 self.oVBox = oSession.oVBox;
2802 self.oVBoxEventHandler = None;
2803 self.oTxsSession = None;
2804 self.fpApiVer = oSession.fpApiVer;
2805
2806 # Skip things we don't implement.
2807 if sMacAddr is not None:
2808 reporter.error('TxsConnectTask does not implement sMacAddr yet');
2809 raise base.GenError();
2810
2811 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
2812 if fReversedSetup is True:
2813 self._openTcpSession(sIpAddr, fReversedSetup = True);
2814 elif sIpAddr is not None and sIpAddr.strip() != '':
2815 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2816 else:
2817 #
2818 # If we've got no IP address, register callbacks that listens for
2819 # the primary network adaptor of the VM to set a IPv4 guest prop.
2820 # Note! The order in which things are done here is kind of important.
2821 #
2822
2823 # 0. The caller zaps the property before starting the VM.
2824 #try:
2825 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2826 #except:
2827 # reporter.logXcpt();
2828
2829 # 1. Register the callback / event listener object.
2830 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
2831 self.oVBoxEventHandler = self.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
2832
2833 # 2. Query the guest properties.
2834 try:
2835 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2836 except:
2837 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
2838 self._deregisterEventHandler();
2839 raise;
2840 else:
2841 if sIpAddr is not None:
2842 self._setIp(sIpAddr);
2843 # end __init__
2844
2845 def __del__(self):
2846 """ Make sure we deregister the callback. """
2847 self._deregisterEventHandler();
2848 return TdTaskBase.__del__(self);
2849
2850 def toString(self):
2851 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
2852 ' oTxsSession=%s oVBoxEventHandler=%s, oVBox=%s>' \
2853 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
2854 self.oTxsSession, self.oVBoxEventHandler, self.oVBox);
2855
2856 def _deregisterEventHandler(self):
2857 """Deregisters the event handler."""
2858 fRc = True;
2859 if self.oVBoxEventHandler is not None:
2860 fRc = self.oVBoxEventHandler.unregister();
2861 self.oVBoxEventHandler = None;
2862 return fRc;
2863
2864 def _setIp(self, sIpAddr, fInitCall = False):
2865 """Called when we get an IP. Will create a TXS session and signal the task."""
2866 sIpAddr = sIpAddr.strip();
2867
2868 if sIpAddr is not None \
2869 and sIpAddr != '':
2870 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
2871 try:
2872 for s in sIpAddr.split('.'):
2873 i = int(s);
2874 if str(i) != s:
2875 raise Exception();
2876 except:
2877 reporter.fatalXcpt();
2878 else:
2879 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2880 return None;
2881
2882 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
2883 else:
2884 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
2885 return None;
2886
2887 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
2888 """
2889 Calls txsclient.openTcpSession and switches our task to reflect the
2890 state of the subtask.
2891 """
2892 self.oCv.acquire();
2893 if self.oTxsSession is None:
2894 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' % \
2895 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
2896 self.sIpAddr = sIpAddr;
2897 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, \
2898 fReversedSetup, cMsIdleFudge);
2899 self.oTxsSession.setTaskOwner(self);
2900 else:
2901 self.sNextIpAddr = sIpAddr;
2902 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
2903 self.oCv.release();
2904 return None;
2905
2906 def notifyAboutReadyTask(self, oTxsSession):
2907 """
2908 Called by the TXS session task when it's done.
2909
2910 We'll signal the task completed or retry depending on the result.
2911 """
2912
2913 self.oCv.acquire();
2914
2915 # Disassociate ourselves with the session (avoid cyclic ref)
2916 oTxsSession.setTaskOwner(None);
2917 fSuccess = oTxsSession.isSuccess();
2918 if self.oTxsSession is not None:
2919 if not fSuccess:
2920 self.oTxsSession = None;
2921 if fSuccess and self.fReversedSetup:
2922 self.sIpAddr = oTxsSession.oTransport.sHostname;
2923 else:
2924 fSuccess = False;
2925
2926 # Signal done, or retry?
2927 if fSuccess \
2928 or self.fReversedSetup \
2929 or self.getAgeAsMs() >= self.cMsTimeout:
2930 self.signalTaskLocked();
2931 else:
2932 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
2933 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2934
2935 self.oCv.release();
2936 return True;
2937
2938 #
2939 # Public methods
2940 #
2941
2942 def getResult(self):
2943 """
2944 Returns the connected TXS session object on success.
2945 Returns None on failure or if the task has not yet completed.
2946 """
2947 self.oCv.acquire();
2948 oTxsSession = self.oTxsSession;
2949 self.oCv.release();
2950
2951 if oTxsSession is not None and not oTxsSession.isSuccess():
2952 oTxsSession = None;
2953 return oTxsSession;
2954
2955 def cancelTask(self):
2956 """ Cancels the task. """
2957 self.oCv.acquire();
2958 if not self.fSignalled:
2959 oTxsSession = self.oTxsSession;
2960 if oTxsSession is not None:
2961 self.oCv.release();
2962 oTxsSession.setTaskOwner(None);
2963 oTxsSession.cancelTask();
2964 oTxsSession.waitForTask(1000);
2965 self.oCv.acquire();
2966 self.signalTaskLocked();
2967 self.oCv.release();
2968 return True;
2969
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