VirtualBox

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

Last change on this file since 61655 was 61569, checked in by vboxsync, 9 years ago

build fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 111.5 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 61569 2016-06-08 10:01:57Z 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: 61569 $"
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 getCpuCount(self):
1529 """
1530 Returns the number of CPUs.
1531 Returns the number of CPUs on success and 0 on failure. Error information is logged.
1532 """
1533 cCpus = 0;
1534 try:
1535 cCpus = self.o.machine.CPUCount;
1536 except:
1537 reporter.errorXcpt('failed to get the CPU count of "%s"' % (self.sName,));
1538
1539 self.oTstDrv.processPendingEvents();
1540 return cCpus;
1541
1542 def ensureControllerAttached(self, sController):
1543 """
1544 Makes sure the specified controller is attached to the VM, attaching it
1545 if necessary.
1546 """
1547 try:
1548 try:
1549 self.o.machine.getStorageControllerByName(sController);
1550 except:
1551 iType = _ControllerNameToBus(sController);
1552 try:
1553 self.o.machine.addStorageController(sController, iType);
1554 reporter.log('added storage controller "%s" (type %s) to %s' % (sController, iType, self.sName));
1555 except:
1556 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, iType, self.sName) );
1557 return False;
1558 finally:
1559 self.oTstDrv.processPendingEvents();
1560 return True;
1561
1562 def setStorageControllerPortCount(self, sController, iPortCount):
1563 """
1564 Set maximum ports count for storage controller
1565 """
1566 try:
1567 oCtl = self.o.machine.getStorageControllerByName(sController)
1568 oCtl.portCount = iPortCount
1569 self.oTstDrv.processPendingEvents()
1570 reporter.log('set controller "%s" port count to value %d' % (sController, iPortCount))
1571 return True
1572 except:
1573 reporter.log('unable to set storage controller "%s" ports count to %d' % (sController, iPortCount))
1574
1575 return False
1576
1577 def setBootOrder(self, iPosition, eType):
1578 """
1579 Set guest boot order type
1580 @param iPosition boot order position
1581 @param eType device type (vboxcon.DeviceType_HardDisk,
1582 vboxcon.DeviceType_DVD, vboxcon.DeviceType_Floppy)
1583 """
1584 try:
1585 self.o.machine.setBootOrder(iPosition, eType)
1586 except:
1587 return reporter.errorXcpt('Unable to set boot order.')
1588
1589 reporter.log('Set boot order [%d] for device %s' % (iPosition, str(eType)))
1590 self.oTstDrv.processPendingEvents();
1591
1592 return True
1593
1594 def setStorageControllerType(self, eType, sController = "IDE Controller"):
1595 """
1596 Similar to ensureControllerAttached, except it will change the type.
1597 """
1598 try:
1599 oCtl = self.o.machine.getStorageControllerByName(sController);
1600 except:
1601 iType = _ControllerNameToBus(sController);
1602 try:
1603 oCtl = self.o.machine.addStorageController(sController, iType);
1604 reporter.log('added storage controller "%s" (type %s) to %s' % (sController, iType, self.sName));
1605 except:
1606 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, iType, self.sName) );
1607 return False;
1608 try:
1609 oCtl.controllerType = eType;
1610 except:
1611 reporter.errorXcpt('failed to set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1612 return False;
1613 reporter.log('set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1614 self.oTstDrv.processPendingEvents();
1615 return True;
1616
1617 def attachDvd(self, sImage = None, sController = "IDE Controller", iPort = 1, iDevice = 0):
1618 """
1619 Attaches a DVD drive to a VM, optionally with an ISO inserted.
1620 Returns True on success and False on failure. Error information is logged.
1621 """
1622 # Input validation.
1623 if sImage is not None and not self.oTstDrv.isResourceFile(sImage)\
1624 and not os.path.isabs(sImage): ## fixme - testsuite unzip ++
1625 reporter.fatal('"%s" is not in the resource set' % (sImage));
1626 return None;
1627
1628 if not self.ensureControllerAttached(sController):
1629 return False;
1630
1631 # Find/register the image if specified.
1632 oImage = None;
1633 sImageUuid = "";
1634 if sImage is not None:
1635 sFullName = self.oTstDrv.getFullResourceName(sImage)
1636 try:
1637 oImage = self.oVBox.findDVDImage(sFullName);
1638 except:
1639 try:
1640 if self.fpApiVer >= 4.1:
1641 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly, False);
1642 elif self.fpApiVer >= 4.0:
1643 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly);
1644 else:
1645 oImage = self.oVBox.openDVDImage(sFullName, "");
1646 except vbox.ComException, oXcpt:
1647 if oXcpt.errno != -1:
1648 reporter.errorXcpt('failed to open DVD image "%s" xxx' % (sFullName));
1649 else:
1650 reporter.errorXcpt('failed to open DVD image "%s" yyy' % (sFullName));
1651 return False;
1652 except:
1653 reporter.errorXcpt('failed to open DVD image "%s"' % (sFullName));
1654 return False;
1655 try:
1656 sImageUuid = oImage.id;
1657 except:
1658 reporter.errorXcpt('failed to get the UUID of "%s"' % (sFullName));
1659 return False;
1660
1661 # Attach the DVD.
1662 fRc = True;
1663 try:
1664 if self.fpApiVer >= 4.0:
1665 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, oImage);
1666 else:
1667 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, sImageUuid);
1668 except:
1669 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1670 % (sController, iPort, iDevice, sImageUuid, self.sName) );
1671 fRc = False;
1672 else:
1673 reporter.log('attached DVD to %s, image="%s"' % (self.sName, sImage));
1674 self.oTstDrv.processPendingEvents();
1675 return fRc;
1676
1677 def attachHd(self, sHd, sController = "IDE Controller", iPort = 0, iDevice = 0, fImmutable = True, fForceResource = True):
1678 """
1679 Attaches a HD to a VM.
1680 Returns True on success and False on failure. Error information is logged.
1681 """
1682 # Input validation.
1683 if fForceResource and not self.oTstDrv.isResourceFile(sHd):
1684 reporter.fatal('"%s" is not in the resource set' % (sHd,));
1685 return None;
1686
1687 if not self.ensureControllerAttached(sController):
1688 return False;
1689
1690 # Find the HD, registering it if necessary (as immutable).
1691 if fForceResource:
1692 sFullName = self.oTstDrv.getFullResourceName(sHd);
1693 else:
1694 sFullName = sHd;
1695 try:
1696 oHd = self.oVBox.findHardDisk(sFullName);
1697 except:
1698 try:
1699 if self.fpApiVer >= 4.1:
1700 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
1701 elif self.fpApiVer >= 4.0:
1702 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
1703 else:
1704 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
1705 except:
1706 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
1707 return False;
1708 try:
1709 if fImmutable:
1710 oHd.type = vboxcon.MediumType_Immutable;
1711 else:
1712 oHd.type = vboxcon.MediumType_Normal;
1713 except:
1714 if fImmutable:
1715 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1716 else:
1717 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1718 return False;
1719
1720 # Attach it.
1721 fRc = True;
1722 try:
1723 if self.fpApiVer >= 4.0:
1724 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1725 else:
1726 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1727 except:
1728 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1729 % (sController, iPort, iDevice, oHd.id, self.sName) );
1730 fRc = False;
1731 else:
1732 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1733 self.oTstDrv.processPendingEvents();
1734 return fRc;
1735
1736 def createBaseHd(self, sHd, sFmt = "VDI", cb = 10*1024*1024*1024):
1737 """
1738 Creates a base HD.
1739 Returns Medium object on success and None on failure. Error information is logged.
1740 """
1741 try:
1742 if self.fpApiVer >= 5.0:
1743 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1744 else:
1745 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1746 oProgressXpcom = oHd.createBaseStorage(cb, (vboxcon.MediumVariant_Standard, ))
1747 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create base disk %s' % (sHd));
1748 oProgress.wait();
1749 oProgress.logResult();
1750 except:
1751 reporter.errorXcpt('failed to create base hd "%s"' % (sHd));
1752 oHd = None
1753
1754 return oHd;
1755
1756 def createDiffHd(self, oParentHd, sHd, sFmt = "VDI"):
1757 """
1758 Creates a differencing HD.
1759 Returns Medium object on success and None on failure. Error information is logged.
1760 """
1761 try:
1762 if self.fpApiVer >= 5.0:
1763 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1764 else:
1765 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1766 oProgressXpcom = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
1767 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
1768 oProgress.wait();
1769 oProgress.logResult();
1770 except:
1771 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
1772 oHd = None
1773
1774 return oHd;
1775
1776 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, \
1777 iPort = 0, iDevice = 0, fImmutable = True):
1778 """
1779 Creates and attaches a HD to a VM.
1780 Returns True on success and False on failure. Error information is logged.
1781 """
1782 if not self.ensureControllerAttached(sController):
1783 return False;
1784
1785 oHd = self.createBaseHd(sHd, sFmt, cb)
1786 if oHd is None:
1787 return False;
1788
1789 fRc = True;
1790 try:
1791 if fImmutable:
1792 oHd.type = vboxcon.MediumType_Immutable;
1793 else:
1794 oHd.type = vboxcon.MediumType_Normal;
1795 except:
1796 if fImmutable:
1797 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1798 else:
1799 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1800 fRc = False;
1801
1802 # Attach it.
1803 if fRc is True:
1804 try:
1805 if self.fpApiVer >= 4.0:
1806 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1807 else:
1808 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1809 except:
1810 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1811 % (sController, iPort, iDevice, oHd.id, self.sName) );
1812 fRc = False;
1813 else:
1814 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1815
1816 # Delete disk in case of an error
1817 if fRc is False:
1818 try:
1819 oProgressCom = oHd.deleteStorage();
1820 except:
1821 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
1822 else:
1823 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
1824 oProgress.wait();
1825 oProgress.logResult();
1826
1827 self.oTstDrv.processPendingEvents();
1828 return fRc;
1829
1830 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
1831 """
1832 Detaches a HD, if attached, and returns a reference to it (IMedium).
1833
1834 In order to delete the detached medium, the caller must first save
1835 the changes made in this session.
1836
1837 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
1838 your standard success indicator. Error information is logged.
1839 """
1840
1841 # What's attached?
1842 try:
1843 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
1844 except:
1845 if self.oVBoxMgr.xcptIsOurXcptKind() \
1846 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
1847 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
1848 return (True, None);
1849 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
1850 % (iPort, iDevice, sController)), None);
1851 # Detach it.
1852 try:
1853 self.o.machine.detachDevice(sController, iPort, iDevice);
1854 except:
1855 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
1856 % (sController, iPort, iDevice, self.sName) ), None);
1857 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
1858 return (True, oHd);
1859
1860 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
1861 """
1862 Attaches a floppy image to a VM.
1863 Returns True on success and False on failure. Error information is logged.
1864 """
1865 # Input validation.
1866 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
1867 ##if not self.oTstDrv.isResourceFile(sFloppy):
1868 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
1869 ## return None;
1870
1871 if not self.ensureControllerAttached(sController):
1872 return False;
1873
1874 # Find the floppy image, registering it if necessary (as immutable).
1875 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
1876 try:
1877 oFloppy = self.oVBox.findFloppyImage(sFullName);
1878 except:
1879 try:
1880 if self.fpApiVer >= 4.1:
1881 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
1882 elif self.fpApiVer >= 4.0:
1883 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
1884 else:
1885 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
1886 except:
1887 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
1888 return False;
1889 ## @todo the following works but causes trouble below (asserts in main).
1890 #try:
1891 # oFloppy.type = vboxcon.MediumType_Immutable;
1892 #except:
1893 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
1894 # return False;
1895
1896 # Attach it.
1897 fRc = True;
1898 try:
1899 if self.fpApiVer >= 4.0:
1900 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
1901 else:
1902 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
1903 except:
1904 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
1905 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
1906 fRc = False;
1907 else:
1908 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
1909 self.oTstDrv.processPendingEvents();
1910 return fRc;
1911
1912 def setupNic(self, sType, sXXX):
1913 """
1914 Attaches a HD to a VM.
1915 Returns True on success and False on failure. Error information is logged.
1916 """
1917 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
1918 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
1919 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
1920 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
1921 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
1922 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
1923 else:
1924 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
1925 return False;
1926 ## @todo Implement me!
1927 if enmType is not None: pass
1928 return True;
1929
1930 def setupAudio(self, eAudioCtlType):
1931 """
1932 Set guest audio controller type and host audio adapter to null
1933 @param eAudioCtlType device type (vboxcon.AudioControllerType_SB16,
1934 vboxcon.AudioControllerType_AC97, vboxcon.AudioControllerType_HDA)
1935 """
1936 try:
1937 oAudioAdapter = self.o.machine.audioAdapter;
1938
1939 oAudioAdapter.audioController = eAudioCtlType;
1940 oAudioAdapter.audioDriver = vboxcon.AudioDriverType_Null;
1941 # Disable by default
1942 oAudioAdapter.enabled = False;
1943 except:
1944 return reporter.errorXcpt('Unable to set audio adapter.')
1945
1946 reporter.log('set audio adapter type to %d' % (eAudioCtlType))
1947 self.oTstDrv.processPendingEvents();
1948
1949 return True
1950
1951 def setupPreferredConfig(self): # pylint: disable=R0914
1952 """
1953 Configures the VM according to the preferences of the guest type.
1954 """
1955 try:
1956 sOsTypeId = self.o.machine.OSTypeId;
1957 except:
1958 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
1959 return False;
1960
1961 try:
1962 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
1963 except:
1964 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
1965 return False;
1966
1967 # get the attributes.
1968 try:
1969 #sFamilyId = oOsType.familyId;
1970 #f64Bit = oOsType.is64Bit;
1971 fIoApic = oOsType.recommendedIOAPIC;
1972 fVirtEx = oOsType.recommendedVirtEx;
1973 cMBRam = oOsType.recommendedRAM;
1974 cMBVRam = oOsType.recommendedVRAM;
1975 #cMBHdd = oOsType.recommendedHDD;
1976 eNicType = oOsType.adapterType;
1977 if self.fpApiVer >= 3.2:
1978 if self.fpApiVer >= 4.2:
1979 fPae = oOsType.recommendedPAE;
1980 fUsbHid = oOsType.recommendedUSBHID;
1981 fHpet = oOsType.recommendedHPET;
1982 eStorCtlType = oOsType.recommendedHDStorageController;
1983 else:
1984 fPae = oOsType.recommendedPae;
1985 fUsbHid = oOsType.recommendedUsbHid;
1986 fHpet = oOsType.recommendedHpet;
1987 eStorCtlType = oOsType.recommendedHdStorageController;
1988 eFirmwareType = oOsType.recommendedFirmware;
1989 else:
1990 fPae = False;
1991 fUsbHid = False;
1992 fHpet = False;
1993 eFirmwareType = -1;
1994 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
1995 if self.fpApiVer >= 4.0:
1996 eAudioCtlType = oOsType.recommendedAudioController;
1997 except:
1998 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
1999 self.oTstDrv.processPendingEvents();
2000 return False;
2001 self.oTstDrv.processPendingEvents();
2002
2003 # Do the setting. Continue applying settings on error in case the
2004 # caller ignores the return code
2005 fRc = True;
2006 if not self.enableIoApic(fIoApic): fRc = False;
2007 if not self.enableVirtEx(fVirtEx): fRc = False;
2008 if not self.enablePae(fPae): fRc = False;
2009 if not self.setRamSize(cMBRam): fRc = False;
2010 if not self.setVRamSize(cMBVRam): fRc = False;
2011 if not self.setNicType(eNicType, 0): fRc = False;
2012 if self.fpApiVer >= 3.2:
2013 if not self.setFirmwareType(eFirmwareType): fRc = False;
2014 if not self.enableUsbHid(fUsbHid): fRc = False;
2015 if not self.enableHpet(fHpet): fRc = False;
2016 if eStorCtlType == vboxcon.StorageControllerType_PIIX3 \
2017 or eStorCtlType == vboxcon.StorageControllerType_PIIX4 \
2018 or eStorCtlType == vboxcon.StorageControllerType_ICH6:
2019 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
2020 fRc = False;
2021 if self.fpApiVer >= 4.0:
2022 if not self.setupAudio(eAudioCtlType): fRc = False;
2023
2024 return fRc;
2025
2026 def addUsbDeviceFilter(self, sName, sVendorId = None, sProductId = None, sRevision = None, # pylint: disable=R0913
2027 sManufacturer = None, sProduct = None, sSerialNumber = None,
2028 sPort = None, sRemote = None):
2029 """
2030 Creates a USB device filter and inserts it into the VM.
2031 Returns True on success.
2032 Returns False on failure (logged).
2033 """
2034 fRc = True;
2035
2036 try:
2037 oUsbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
2038 oUsbDevFilter.active = True;
2039 if sVendorId is not None:
2040 oUsbDevFilter.vendorId = sVendorId;
2041 if sProductId is not None:
2042 oUsbDevFilter.productId = sProductId;
2043 if sRevision is not None:
2044 oUsbDevFilter.revision = sRevision;
2045 if sManufacturer is not None:
2046 oUsbDevFilter.manufacturer = sManufacturer;
2047 if sProduct is not None:
2048 oUsbDevFilter.product = sProduct;
2049 if sSerialNumber is not None:
2050 oUsbDevFilter.serialnumber = sSerialNumber;
2051 if sPort is not None:
2052 oUsbDevFilter.port = sPort;
2053 if sRemote is not None:
2054 oUsbDevFilter.remote = sRemote;
2055 try:
2056 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, oUsbDevFilter);
2057 except:
2058 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
2059 % (0, self.sName) );
2060 fRc = False;
2061 else:
2062 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
2063 except:
2064 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
2065 % (sName, self.sName) );
2066 fRc = False;
2067 return fRc;
2068
2069 def getGuestPropertyValue(self, sName):
2070 """
2071 Gets a guest property value.
2072 Returns the value on success, None on failure (logged).
2073 """
2074 try:
2075 sValue = self.o.machine.getGuestPropertyValue(sName);
2076 except:
2077 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2078 return None;
2079 return sValue;
2080
2081 def setGuestPropertyValue(self, sName, sValue):
2082 """
2083 Sets a guest property value.
2084 Returns the True on success, False on failure (logged).
2085 """
2086 try:
2087 self.o.machine.setGuestPropertyValue(sName, sValue);
2088 except:
2089 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2090 return False;
2091 return True;
2092
2093 def delGuestPropertyValue(self, sName):
2094 """
2095 Deletes a guest property value.
2096 Returns the True on success, False on failure (logged).
2097 """
2098 try:
2099 oMachine = self.o.machine;
2100 if self.fpApiVer >= 4.2:
2101 oMachine.deleteGuestProperty(sName);
2102 else:
2103 oMachine.setGuestPropertyValue(sName, '');
2104 except:
2105 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2106 return False;
2107 return True;
2108
2109 def setExtraData(self, sKey, sValue):
2110 """
2111 Sets extra data.
2112 Returns the True on success, False on failure (logged).
2113 """
2114 try:
2115 self.o.machine.setExtraData(sKey, sValue);
2116 except:
2117 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2118 return False;
2119 return True;
2120
2121 def getExtraData(self, sKey):
2122 """
2123 Gets extra data.
2124 Returns value on success, None on failure.
2125 """
2126 try:
2127 sValue = self.o.machine.getExtraData(sKey)
2128 except:
2129 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue))
2130 return None
2131 return sValue
2132
2133 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2134 """
2135 Sets up the teleporter for the VM.
2136 Returns True on success, False on failure (logged).
2137 """
2138 try:
2139 self.o.machine.teleporterAddress = sAddress;
2140 self.o.machine.teleporterPort = uPort;
2141 self.o.machine.teleporterPassword = sPassword;
2142 self.o.machine.teleporterEnabled = fEnabled;
2143 except:
2144 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2145 return False;
2146 return True;
2147
2148 def enableTeleporter(self, fEnable=True):
2149 """
2150 Enables or disables the teleporter of the VM.
2151 Returns True on success, False on failure (logged).
2152 """
2153 try:
2154 self.o.machine.teleporterEnabled = fEnable;
2155 except:
2156 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2157 return False;
2158 return True;
2159
2160 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2161 """
2162 Wrapper around the IConsole::teleport() method.
2163 Returns a progress object on success, None on failure (logged).
2164 """
2165 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2166 try:
2167 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2168 except:
2169 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2170 return None;
2171 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2172
2173 def getOsType(self):
2174 """
2175 Gets the IGuestOSType interface for the machine.
2176
2177 return IGuestOSType interface on success, None + errorXcpt on failure.
2178 No exceptions raised.
2179 """
2180 try:
2181 sOsTypeId = self.o.machine.OSTypeId;
2182 except:
2183 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2184 return None;
2185
2186 try:
2187 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2188 except:
2189 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2190 return None;
2191
2192 return oOsType;
2193
2194 def setOsType(self, sNewTypeId):
2195 """
2196 Changes the OS type.
2197
2198 returns True on success, False + errorXcpt on failure.
2199 No exceptions raised.
2200 """
2201 try:
2202 self.o.machine.OSTypeId = sNewTypeId;
2203 except:
2204 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2205 return False;
2206 return True;
2207
2208
2209 def setParavirtProvider(self, iProvider):
2210 """
2211 Sets a paravirtualisation provider.
2212 Returns the True on success, False on failure (logged).
2213 """
2214 try:
2215 self.o.machine.paravirtProvider = iProvider
2216 except:
2217 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2218 return False;
2219 return True;
2220
2221
2222
2223 #
2224 # IConsole wrappers.
2225 #
2226
2227 def powerOff(self, fFudgeOnFailure = True):
2228 """
2229 Powers off the VM.
2230
2231 Returns True on success.
2232 Returns False on IConsole::powerDown() failure.
2233 Returns None if the progress object returns failure.
2234 """
2235 #
2236 # Deregister event handler before we power off the VM, otherwise we're
2237 # racing for VM process termination and cause misleading spurious
2238 # error messages in the event handling code, because the event objects
2239 # disappear.
2240 #
2241 # Note! Doing this before powerDown to try prevent numerous smoketest
2242 # timeouts on XPCOM hosts.
2243 #
2244 self.deregisterEventHandlerForTask();
2245
2246
2247 # Try power if off.
2248 try:
2249 oProgress = self.o.console.powerDown();
2250 except:
2251 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2252 if fFudgeOnFailure:
2253 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2254 self.waitForTask(1000); # fudge
2255 return False;
2256
2257 # Wait on power off operation to complete.
2258 rc = self.oTstDrv.waitOnProgress(oProgress);
2259 if rc < 0:
2260 self.close();
2261 if fFudgeOnFailure:
2262 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2263 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2264 return None;
2265
2266 # Wait for the VM to really power off or we'll fail to open a new session to it.
2267 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2268 return self.waitForTask(30 * 1000); # fudge
2269
2270 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2271 """
2272 Restores the given snapshot.
2273
2274 Returns True on success.
2275 Returns False on IMachine::restoreSnapshot() failure.
2276 Returns None if the progress object returns failure.
2277 """
2278 try:
2279 if self.fpApiVer >= 5.0:
2280 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2281 else:
2282 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2283 except:
2284 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2285 if fFudgeOnFailure:
2286 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2287 self.waitForTask(1000); # fudge
2288 return False;
2289
2290 rc = self.oTstDrv.waitOnProgress(oProgress);
2291 if rc < 0:
2292 self.close();
2293 if fFudgeOnFailure:
2294 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2295 return None;
2296
2297 return self.waitForTask(30 * 1000);
2298
2299 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2300 """
2301 Deletes the given snapshot merging the diff image into the base.
2302
2303 Returns True on success.
2304 Returns False on IMachine::deleteSnapshot() failure.
2305 """
2306 try:
2307 if self.fpApiVer >= 5.0:
2308 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2309 else:
2310 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2311 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2312 oProgress.wait(cMsTimeout);
2313 oProgress.logResult();
2314 except:
2315 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2316 if fFudgeOnFailure:
2317 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2318 self.waitForTask(1000); # fudge
2319 return False;
2320
2321 return True;
2322
2323 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2324 """
2325 Takes a snapshot with the given name
2326
2327 Returns True on success.
2328 Returns False on IMachine::takeSnapshot() or VM state change failure.
2329 """
2330 try:
2331 if fPause is True \
2332 and self.oVM.state is vboxcon.MachineState_Running:
2333 self.o.console.pause();
2334 if self.fpApiVer >= 5.0:
2335 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2336 else:
2337 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2338 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2339 oProgress.wait(cMsTimeout);
2340 oProgress.logResult();
2341 except:
2342 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2343 if fFudgeOnFailure:
2344 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2345 self.waitForTask(1000); # fudge
2346 return False;
2347
2348 if fPause is True \
2349 and self.oVM.state is vboxcon.MachineState_Paused:
2350 self.o.console.resume();
2351
2352 return True;
2353
2354 def findSnapshot(self, sName):
2355 """
2356 Returns the snapshot object with the given name
2357
2358 Returns snapshot object on success.
2359 Returns None if there is no snapshot with the given name.
2360 """
2361 return self.oVM.findSnapshot(sName);
2362
2363 def takeScreenshot(self, sFilename, iScreenId=0):
2364 """
2365 Take screenshot from the given display and save it to specified file.
2366
2367 Returns True on success
2368 Returns False on failure.
2369 """
2370 try:
2371 if self.fpApiVer >= 5.0:
2372 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2373 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2374 vboxcon.BitmapFormat_PNG)
2375 else:
2376 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2377 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2378 except:
2379 reporter.logXcpt("Unable to take screenshot")
2380 return False
2381
2382 oFile = open(sFilename, 'wb')
2383 oFile.write(aPngData)
2384 oFile.close()
2385
2386 return True
2387
2388 #
2389 # IMachineDebugger wrappers.
2390 #
2391
2392 def queryOsKernelLog(self):
2393 """
2394 Tries to get the OS kernel log using the VM debugger interface.
2395
2396 Returns string containing the kernel log on success.
2397 Returns None on failure.
2398 """
2399 sOsKernelLog = None;
2400 try:
2401 self.o.console.debugger.loadPlugIn('all');
2402 except:
2403 reporter.logXcpt('Unable to load debugger plugins');
2404 else:
2405 try:
2406 sOsDetected = self.o.console.debugger.detectOS();
2407 except:
2408 reporter.logXcpt('Failed to detect the guest OS');
2409 else:
2410 try:
2411 sOsKernelLog = self.o.console.debugger.queryOSKernelLog(0);
2412 except:
2413 reporter.logXcpt('Unable to get the guest OS (%s) kernel log' % (sOsDetected,));
2414 return sOsKernelLog;
2415
2416 def queryDbgInfo(self, sItem, sArg = '', sDefault = None):
2417 """
2418 Simple wrapper around IMachineDebugger::info.
2419
2420 Returns string on success, sDefault on failure (logged).
2421 """
2422 try:
2423 return self.o.console.debugger.info(sItem, sArg);
2424 except:
2425 reporter.logXcpt('Unable to query "%s" with arg "%s"' % (sItem, sArg,));
2426 return sDefault;
2427
2428 def queryDbgInfoVgaText(self, sArg = 'all'):
2429 """
2430 Tries to get the 'info vgatext' output, provided we're in next mode.
2431
2432 Returns string containing text on success.
2433 Returns None on failure or not text mode.
2434 """
2435 sVgaText = None;
2436 try:
2437 sVgaText = self.o.console.debugger.info('vgatext', sArg);
2438 if sVgaText.startswith('Not in text mode!'):
2439 sVgaText = None;
2440 except:
2441 reporter.logXcpt('Unable to query vgatext with arg "%s"' % (sArg,));
2442 return sVgaText;
2443
2444 def queryDbgGuestStack(self, iCpu = 0):
2445 """
2446 Returns the guest stack for the given VCPU.
2447
2448 Returns string containing the guest stack for the selected VCPU on success.
2449 Returns None on failure.
2450 """
2451
2452 #
2453 # Load all plugins first and try to detect the OS so we can
2454 # get nicer stack traces.
2455 #
2456 try:
2457 self.o.console.debugger.loadPlugIn('all');
2458 except:
2459 reporter.logXcpt('Unable to load debugger plugins');
2460 else:
2461 try:
2462 sOsDetected = self.o.console.debugger.detectOS();
2463 _ = sOsDetected;
2464 except:
2465 reporter.logXcpt('Failed to detect the guest OS');
2466
2467 sGuestStack = None;
2468 try:
2469 sGuestStack = self.o.console.debugger.dumpGuestStack(iCpu);
2470 except:
2471 reporter.logXcpt('Unable to query guest stack for CPU %s' % (iCpu, ));
2472
2473 return sGuestStack;
2474
2475
2476 #
2477 # Other methods.
2478 #
2479
2480 def getPrimaryIp(self):
2481 """
2482 Tries to obtain the primary IP address of the guest via the guest
2483 properties.
2484
2485 Returns IP address on success.
2486 Returns empty string on failure.
2487 """
2488 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2489 if vbox.isIpAddrValid(sIpAddr):
2490 return sIpAddr;
2491 return '';
2492
2493 def getPid(self):
2494 """
2495 Gets the process ID for the direct session unless it's ourselves.
2496 """
2497 if self.uPid is None and self.o is not None and self.fRemoteSession:
2498 try:
2499 if self.fpApiVer >= 4.2:
2500 uPid = self.o.machine.sessionPID;
2501 else:
2502 uPid = self.o.machine.sessionPid;
2503 if uPid != os.getpid() and uPid != 0xffffffff:
2504 self.uPid = uPid;
2505 except Exception, oXcpt:
2506 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
2507 try:
2508 if self.fpApiVer >= 4.2:
2509 uPid = self.oVM.sessionPID;
2510 else:
2511 uPid = self.oVM.sessionPid;
2512 if uPid != os.getpid() and uPid != 0xffffffff:
2513 self.uPid = uPid;
2514 except:
2515 reporter.log2Xcpt();
2516 else:
2517 reporter.log2Xcpt();
2518 if self.uPid is not None:
2519 reporter.log2('getPid: %u' % (self.uPid,));
2520 self.oTstDrv.pidFileAdd(self.uPid);
2521 return self.uPid;
2522
2523 def addLogsToReport(self, cReleaseLogs = 1):
2524 """
2525 Retrieves and adds the release and debug logs to the test report.
2526 """
2527 fRc = True;
2528
2529 # Add each of the requested release logs to the report.
2530 for iLog in range(0, cReleaseLogs):
2531 try:
2532 if self.fpApiVer >= 3.2:
2533 sLogFile = self.oVM.queryLogFilename(iLog);
2534 elif iLog > 0:
2535 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
2536 else:
2537 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
2538 except:
2539 reporter.logXcpt('iLog=%s' % (iLog,));
2540 fRc = False;
2541 else:
2542 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
2543 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
2544 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2545
2546 # Now for the hardened windows startup log.
2547 try:
2548 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxStartup.log');
2549 except:
2550 reporter.logXcpt();
2551 fRc = False;
2552 else:
2553 if os.path.isfile(sLogFile):
2554 reporter.addLogFile(sLogFile, 'log/release/vm', '%s startup log' % (self.sName, ),
2555 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2556
2557 # Now for the debug log.
2558 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
2559 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
2560 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
2561
2562 return fRc;
2563
2564 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
2565 """
2566 Create an instance of the given ConsoleEventHandlerBase sub-class and
2567 register it.
2568
2569 The new instance is returned on success. None is returned on error.
2570 """
2571
2572 # We need a console object.
2573 try:
2574 oConsole = self.o.console;
2575 except Exception, oXcpt:
2576 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
2577 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
2578 return None;
2579
2580 # Add the base class arguments.
2581 dArgsCopy = dArgs.copy() if dArgs is not None else dict();
2582 dArgsCopy['oSession'] = self;
2583 dArgsCopy['oConsole'] = oConsole;
2584 sLogSuffix = 'on %s' % (self.sName,)
2585 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
2586 oConsole, 'IConsole', 'IConsoleCallback',
2587 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
2588
2589 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
2590 """
2591 Enables the testing part of the VMMDev.
2592
2593 Returns True on success and False on failure. Error information is logged.
2594 """
2595 fRc = True;
2596 try:
2597 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
2598 '1' if fEnabled else '');
2599 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
2600 '1' if fEnableMMIO and fEnabled else '');
2601 except:
2602 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
2603 fRc = False;
2604 else:
2605 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
2606 self.oTstDrv.processPendingEvents();
2607 return fRc;
2608
2609 #
2610 # Test eXecution Service methods.
2611 #
2612
2613 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, sMacAddr = None, fNatForwardingForTxs = False):
2614 """
2615 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
2616 addresses are specified, we'll get the IP from the guest additions.
2617
2618 Returns a TxsConnectTask object on success, None + log on failure.
2619 """
2620 # If the VM is configured with a NAT interface, connect to local host.
2621 fReversedSetup = False;
2622 fUseNatForTxs = False;
2623 if sIpAddr is None:
2624 try:
2625 oNic = self.oVM.getNetworkAdapter(0);
2626 if oNic.attachmentType == vboxcon.NetworkAttachmentType_NAT:
2627 fUseNatForTxs = True;
2628 except:
2629 reporter.errorXcpt();
2630 return None;
2631 if fUseNatForTxs:
2632 fReversedSetup = not fNatForwardingForTxs;
2633 sIpAddr = '127.0.0.1';
2634
2635 # Kick off the task.
2636 try:
2637 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup);
2638 except:
2639 reporter.errorXcpt();
2640 oTask = None;
2641 return oTask;
2642
2643 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
2644 """
2645 Attempts to connect to a TXS instance.
2646
2647 Returns True if a connection was established, False if not (only grave
2648 failures are logged as errors).
2649
2650 Note! The timeout is more of a guideline...
2651 """
2652
2653 if sHostname is None or sHostname.strip() == '':
2654 raise base.GenError('Empty sHostname is not implemented yet');
2655
2656 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
2657 cMsIdleFudge = cMsTimeout / 2);
2658 if oTxsSession is None:
2659 return False;
2660
2661 # Wait for the connect task to time out.
2662 self.oTstDrv.addTask(oTxsSession);
2663 self.oTstDrv.processPendingEvents();
2664 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
2665 self.oTstDrv.removeTask(oTxsSession);
2666 if oRc != oTxsSession:
2667 if oRc is not None:
2668 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
2669 self.oTstDrv.processPendingEvents();
2670 oTxsSession.cancelTask(); # this is synchronous
2671 return False;
2672
2673 # Check the status.
2674 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
2675 if not oTxsSession.isSuccess():
2676 return False;
2677
2678 reporter.log2('Disconnecting from TXS...');
2679 return oTxsSession.syncDisconnect();
2680
2681
2682
2683class TxsConnectTask(TdTaskBase):
2684 """
2685 Class that takes care of connecting to a VM.
2686 """
2687
2688 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
2689 """ Class for looking for IPv4 address changes on interface 0."""
2690 def __init__(self, dArgs):
2691 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs); # pylint: disable=W0233
2692 self.oParentTask = dArgs['oParentTask'];
2693 self.sMachineId = dArgs['sMachineId'];
2694
2695 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags):
2696 """Look for IP address."""
2697 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags));
2698 if sMachineId == self.sMachineId \
2699 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
2700 self.oParentTask._setIp(sValue); # pylint: disable=W0212
2701
2702
2703 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup):
2704 TdTaskBase.__init__(self, utils.getCallerName());
2705 self.cMsTimeout = cMsTimeout;
2706 self.sIpAddr = None;
2707 self.sNextIpAddr = None;
2708 self.sMacAddr = sMacAddr;
2709 self.fReversedSetup = fReversedSetup;
2710 self.oVBox = oSession.oVBox;
2711 self.oVBoxEventHandler = None;
2712 self.oTxsSession = None;
2713 self.fpApiVer = oSession.fpApiVer;
2714
2715 # Skip things we don't implement.
2716 if sMacAddr is not None:
2717 reporter.error('TxsConnectTask does not implement sMacAddr yet');
2718 raise base.GenError();
2719
2720 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
2721 if fReversedSetup is True:
2722 self._openTcpSession(sIpAddr, fReversedSetup = True);
2723 elif sIpAddr is not None and sIpAddr.strip() != '':
2724 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2725 else:
2726 #
2727 # If we've got no IP address, register callbacks that listens for
2728 # the primary network adaptor of the VM to set a IPv4 guest prop.
2729 # Note! The order in which things are done here is kind of important.
2730 #
2731
2732 # 0. The caller zaps the property before starting the VM.
2733 #try:
2734 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2735 #except:
2736 # reporter.logXcpt();
2737
2738 # 1. Register the callback / event listener object.
2739 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
2740 self.oVBoxEventHandler = self.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
2741
2742 # 2. Query the guest properties.
2743 try:
2744 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2745 except:
2746 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
2747 self._deregisterEventHandler();
2748 raise;
2749 else:
2750 if sIpAddr is not None:
2751 self._setIp(sIpAddr);
2752 # end __init__
2753
2754 def __del__(self):
2755 """ Make sure we deregister the callback. """
2756 self._deregisterEventHandler();
2757 return TdTaskBase.__del__(self);
2758
2759 def toString(self):
2760 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
2761 ' oTxsSession=%s oVBoxEventHandler=%s, oVBox=%s>' \
2762 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
2763 self.oTxsSession, self.oVBoxEventHandler, self.oVBox);
2764
2765 def _deregisterEventHandler(self):
2766 """Deregisters the event handler."""
2767 fRc = True;
2768 if self.oVBoxEventHandler is not None:
2769 fRc = self.oVBoxEventHandler.unregister();
2770 self.oVBoxEventHandler = None;
2771 return fRc;
2772
2773 def _setIp(self, sIpAddr, fInitCall = False):
2774 """Called when we get an IP. Will create a TXS session and signal the task."""
2775 sIpAddr = sIpAddr.strip();
2776
2777 if sIpAddr is not None \
2778 and sIpAddr != '':
2779 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
2780 try:
2781 for s in sIpAddr.split('.'):
2782 i = int(s);
2783 if str(i) != s:
2784 raise Exception();
2785 except:
2786 reporter.fatalXcpt();
2787 else:
2788 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2789 return None;
2790
2791 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
2792 else:
2793 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
2794 return None;
2795
2796 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
2797 """
2798 Calls txsclient.openTcpSession and switches our task to reflect the
2799 state of the subtask.
2800 """
2801 self.oCv.acquire();
2802 if self.oTxsSession is None:
2803 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' % \
2804 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
2805 self.sIpAddr = sIpAddr;
2806 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, \
2807 fReversedSetup, cMsIdleFudge);
2808 self.oTxsSession.setTaskOwner(self);
2809 else:
2810 self.sNextIpAddr = sIpAddr;
2811 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
2812 self.oCv.release();
2813 return None;
2814
2815 def notifyAboutReadyTask(self, oTxsSession):
2816 """
2817 Called by the TXS session task when it's done.
2818
2819 We'll signal the task completed or retry depending on the result.
2820 """
2821
2822 self.oCv.acquire();
2823
2824 # Disassociate ourselves with the session (avoid cyclic ref)
2825 oTxsSession.setTaskOwner(None);
2826 fSuccess = oTxsSession.isSuccess();
2827 if self.oTxsSession is not None:
2828 if not fSuccess:
2829 self.oTxsSession = None;
2830 if fSuccess and self.fReversedSetup:
2831 self.sIpAddr = oTxsSession.oTransport.sHostname;
2832 else:
2833 fSuccess = False;
2834
2835 # Signal done, or retry?
2836 if fSuccess \
2837 or self.fReversedSetup \
2838 or self.getAgeAsMs() >= self.cMsTimeout:
2839 self.signalTaskLocked();
2840 else:
2841 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
2842 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2843
2844 self.oCv.release();
2845 return True;
2846
2847 #
2848 # Public methods
2849 #
2850
2851 def getResult(self):
2852 """
2853 Returns the connected TXS session object on success.
2854 Returns None on failure or if the task has not yet completed.
2855 """
2856 self.oCv.acquire();
2857 oTxsSession = self.oTxsSession;
2858 self.oCv.release();
2859
2860 if oTxsSession is not None and not oTxsSession.isSuccess():
2861 oTxsSession = None;
2862 return oTxsSession;
2863
2864 def cancelTask(self):
2865 """ Cancels the task. """
2866 self.oCv.acquire();
2867 if not self.fSignalled:
2868 oTxsSession = self.oTxsSession;
2869 if oTxsSession is not None:
2870 self.oCv.release();
2871 oTxsSession.setTaskOwner(None);
2872 oTxsSession.cancelTask();
2873 oTxsSession.waitForTask(1000);
2874 self.oCv.acquire();
2875 self.signalTaskLocked();
2876 self.oCv.release();
2877 return True;
2878
Note: See TracBrowser for help on using the repository browser.

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