VirtualBox

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

Last change on this file since 69776 was 69111, checked in by vboxsync, 7 years ago

(C) year

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