VirtualBox

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

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

vboxwrappers.py: SessionWrapper.powerOff: Moved the deregistration of the event handler to before we try power off the VM as XPCOM/python/someone seems to deadlock occationally if we do it while the call is running.

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