VirtualBox

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

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

ValidationKit/testdriver/vboxwrappers.py: Fix method names (for real this time, mixed up the casing)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 105.8 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxwrappers.py 58889 2015-11-26 20:11:02Z 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: 58889 $"
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 if self.oConsoleEventHandler is not None:
564 self.oConsoleEventHandler.unregister();
565 self.oConsoleEventHandler = None;
566
567 if self.o is not None:
568 try:
569 self.close();
570 reporter.log('close session %s' % (self.o));
571 except:
572 pass;
573 self.o = None;
574
575 TdTaskBase.__del__(self);
576
577 def toString(self):
578 return '<%s: sUuid=%s, sName=%s, uPid=%s, sDbgCreated=%s, fRemoteSession=%s, oSession=%s,' \
579 ' oConsoleEventHandler=%s, oVM=%s >' \
580 % (type(self).__name__, self.sUuid, self.sName, self.uPid, self.sDbgCreated, self.fRemoteSession,
581 self.o, self.oConsoleEventHandler, self.oVM,);
582
583 def __str__(self):
584 return self.toString();
585
586 #
587 # TdTaskBase overrides.
588 #
589
590 def __pollTask(self):
591 """ Internal poller """
592 # Poll for events after doing the remote GetState call, otherwise we
593 # might end up sleepless because XPCOM queues a cleanup event.
594 try:
595 try:
596 eState = self.o.machine.state;
597 except Exception, oXcpt:
598 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
599 reporter.logXcpt();
600 return True;
601 finally:
602 self.oTstDrv.processPendingEvents();
603
604 # Switch
605 if eState == vboxcon.MachineState_Running:
606 return False;
607 if eState == vboxcon.MachineState_Paused:
608 return False;
609 if eState == vboxcon.MachineState_Teleporting:
610 return False;
611 if eState == vboxcon.MachineState_LiveSnapshotting:
612 return False;
613 if eState == vboxcon.MachineState_Starting:
614 return False;
615 if eState == vboxcon.MachineState_Stopping:
616 return False;
617 if eState == vboxcon.MachineState_Saving:
618 return False;
619 if eState == vboxcon.MachineState_Restoring:
620 return False;
621 if eState == vboxcon.MachineState_TeleportingPausedVM:
622 return False;
623 if eState == vboxcon.MachineState_TeleportingIn:
624 return False;
625
626 # *Beeep* fudge!
627 if self.fpApiVer < 3.2 \
628 and eState == vboxcon.MachineState_PoweredOff \
629 and self.getAgeAsMs() < 3000:
630 return False;
631
632 reporter.log('SessionWrapper::pollTask: eState=%s' % (eState));
633 return True;
634
635
636 def pollTask(self, fLocked = False):
637 """
638 Overrides TdTaskBase.pollTask().
639
640 This method returns False while the VM is online and running normally.
641 """
642 fRc = self.__pollTask();
643
644 # HACK ALERT: Lazily try registering the console event handler if
645 # we're not ready.
646 if not fRc and self.oConsoleEventHandler is None:
647 self.registerEventHandlerForTask();
648
649 # HACK ALERT: Lazily try get the PID and add it to the PID file.
650 if not fRc and self.uPid is None:
651 self.getPid();
652
653 return fRc;
654
655 def waitForTask(self, cMsTimeout = 0):
656 """
657 Overrides TdTaskBase.waitForTask().
658 Process XPCOM/COM events while waiting.
659 """
660 msStart = base.timestampMilli();
661 fState = self.pollTask(False);
662 while not fState:
663 cMsElapsed = base.timestampMilli() - msStart;
664 if cMsElapsed > cMsTimeout:
665 break;
666 try: self.oVBoxMgr.waitForEvents(cMsTimeout - cMsElapsed);
667 except KeyboardInterrupt: raise;
668 except: pass;
669 fState = self.pollTask(False);
670 return fState;
671
672 def setTaskOwner(self, oOwner):
673 """
674 HACK ALERT!
675 Overrides TdTaskBase.setTaskOwner() so we can try call
676 registerEventHandlerForTask() again when when the testdriver calls
677 addTask() after VM has been spawned. Related to pollTask() above.
678
679 The testdriver must not add the task too early for this to work!
680 """
681 if oOwner is not None:
682 self.registerEventHandlerForTask()
683 return TdTaskBase.setTaskOwner(self, oOwner);
684
685
686 #
687 # Task helpers.
688 #
689
690 def registerEventHandlerForTask(self):
691 """
692 Registers the console event handlers for working the task state.
693 """
694 if self.oConsoleEventHandler is not None:
695 return True;
696 self.oConsoleEventHandler = self.registerDerivedEventHandler(vbox.SessionConsoleEventHandler, {}, False);
697 return self.oConsoleEventHandler is not None;
698
699
700 def assertPoweredOff(self):
701 """
702 Asserts that the VM is powered off, reporting an error if not.
703 Returns True if powered off, False + error msg if not.
704 """
705 try:
706 try:
707 eState = self.oVM.state;
708 except Exception:
709 reporter.errorXcpt();
710 return True;
711 finally:
712 self.oTstDrv.processPendingEvents();
713
714 if eState == vboxcon.MachineState_PoweredOff:
715 return True;
716 reporter.error('Expected machine state "PoweredOff", machine is in the "%s" state instead.'
717 % (_nameMachineState(eState),));
718 return False;
719
720
721 def getMachineStateWithName(self):
722 """
723 Gets the current machine state both as a constant number/whatever and
724 as a human readable string. On error, the constants will be set to
725 None and the string will be the error message.
726 """
727 try:
728 eState = self.oVM.state;
729 except:
730 return (None, '[error getting state: %s]' % (self.oVBoxMgr.xcptToString(),));
731 finally:
732 self.oTstDrv.processPendingEvents();
733 return (eState, _nameMachineState(eState));
734
735 def reportPrematureTermination(self, sPrefix = ''):
736 """
737 Reports a premature virtual machine termination.
738 Returns False to facilitate simpler error paths.
739 """
740
741 reporter.error(sPrefix + 'The virtual machine terminated prematurely!!');
742 (enmState, sStateNm) = self.getMachineStateWithName();
743 reporter.error(sPrefix + 'Machine state: %s' % (sStateNm,));
744
745 if enmState is not None \
746 and enmState == vboxcon.MachineState_Aborted \
747 and self.uPid is not None:
748 #
749 # Look for process crash info.
750 #
751 def addCrashFile(sLogFile, fBinary):
752 """ processCollectCrashInfo callback. """
753 reporter.addLogFile(sLogFile, 'crash/dump/vm' if fBinary else 'crash/report/vm');
754 utils.processCollectCrashInfo(self.uPid, reporter.log, addCrashFile);
755
756 return False;
757
758
759
760 #
761 # ISession / IMachine / ISomethingOrAnother wrappers.
762 #
763
764 def close(self):
765 """
766 Closes the session if it's open and removes it from the
767 vbox.TestDriver.aoRemoteSessions list.
768 Returns success indicator.
769 """
770 fRc = True;
771 if self.o is not None:
772 # Get the pid in case we need to kill the process later on.
773 self.getPid();
774
775 # Try close it.
776 try:
777 if self.fpApiVer < 3.3:
778 self.o.close();
779 else:
780 self.o.unlockMachine();
781 self.o = None;
782 except KeyboardInterrupt:
783 raise;
784 except:
785 # Kludge to ignore VBoxSVC's closing of our session when the
786 # direct session closes / VM process terminates. Fun!
787 try: fIgnore = self.o.state == vboxcon.SessionState_Unlocked;
788 except: fIgnore = False;
789 if not fIgnore:
790 reporter.errorXcpt('ISession::unlockMachine failed on %s' % (self.o));
791 fRc = False;
792
793 # Remove it from the remote session list if applicable (not 100% clean).
794 if fRc and self.fRemoteSession:
795 try:
796 if self in self.oTstDrv.aoRemoteSessions:
797 reporter.log2('SessionWrapper::close: Removing myself from oTstDrv.aoRemoteSessions');
798 self.oTstDrv.aoRemoteSessions.remove(self)
799 except:
800 reporter.logXcpt();
801
802 if self.uPid is not None:
803 self.oTstDrv.pidFileRemove(self.uPid);
804
805 self.oTstDrv.processPendingEvents();
806 return fRc;
807
808 def saveSettings(self, fClose = False):
809 """
810 Saves the settings and optionally closes the session.
811 Returns success indicator.
812 """
813 try:
814 try:
815 self.o.machine.saveSettings();
816 except:
817 reporter.errorXcpt('saveSettings failed on %s' % (self.o));
818 return False;
819 finally:
820 self.oTstDrv.processPendingEvents();
821 if fClose:
822 return self.close();
823 return True;
824
825 def discardSettings(self, fClose = False):
826 """
827 Discards the settings and optionally closes the session.
828 """
829 try:
830 try:
831 self.o.machine.discardSettings();
832 except:
833 reporter.errorXcpt('discardSettings failed on %s' % (self.o));
834 return False;
835 finally:
836 self.oTstDrv.processPendingEvents();
837 if fClose:
838 return self.close();
839 return True;
840
841 def enableVirtEx(self, fEnable):
842 """
843 Enables or disables AMD-V/VT-x.
844 Returns True on success and False on failure. Error information is logged.
845 """
846 # Enable/disable it.
847 fRc = True;
848 try:
849 self.o.machine.setHWVirtExProperty(vboxcon.HWVirtExPropertyType_Enabled, fEnable);
850 except:
851 reporter.errorXcpt('failed to set HWVirtExPropertyType_Enabled=%s for "%s"' % (fEnable, self.sName));
852 fRc = False;
853 else:
854 reporter.log('set HWVirtExPropertyType_Enabled=%s for "%s"' % (fEnable, self.sName));
855
856 # Force/unforce it.
857 if fRc and hasattr(vboxcon, 'HWVirtExPropertyType_Force'):
858 try:
859 self.o.machine.setHWVirtExProperty(vboxcon.HWVirtExPropertyType_Force, fEnable);
860 except:
861 reporter.errorXcpt('failed to set HWVirtExPropertyType_Force=%s for "%s"' % (fEnable, self.sName));
862 fRc = False;
863 else:
864 reporter.log('set HWVirtExPropertyType_Force=%s for "%s"' % (fEnable, self.sName));
865 else:
866 reporter.log('Warning! vboxcon has no HWVirtExPropertyType_Force attribute.');
867 ## @todo Modify CFGM to do the same for old VBox versions?
868
869 self.oTstDrv.processPendingEvents();
870 return fRc;
871
872 def enableNestedPaging(self, fEnable):
873 """
874 Enables or disables nested paging..
875 Returns True on success and False on failure. Error information is logged.
876 """
877 ## @todo Add/remove force CFGM thing, we don't want fallback logic when testing.
878 fRc = True;
879 try:
880 self.o.machine.setHWVirtExProperty(vboxcon.HWVirtExPropertyType_NestedPaging, fEnable);
881 except:
882 reporter.errorXcpt('failed to set HWVirtExPropertyType_NestedPaging=%s for "%s"' % (fEnable, self.sName));
883 fRc = False;
884 else:
885 reporter.log('set HWVirtExPropertyType_NestedPaging=%s for "%s"' % (fEnable, self.sName));
886 self.oTstDrv.processPendingEvents();
887 return fRc;
888
889 def enableLongMode(self, fEnable):
890 """
891 Enables or disables LongMode.
892 Returns True on success and False on failure. Error information is logged.
893 """
894 # Supported.
895 if self.fpApiVer < 4.2 or not hasattr(vboxcon, 'HWVirtExPropertyType_LongMode'):
896 return True;
897
898 # Enable/disable it.
899 fRc = True;
900 try:
901 self.o.machine.setCPUProperty(vboxcon.CPUPropertyType_LongMode, fEnable);
902 except:
903 reporter.errorXcpt('failed to set CPUPropertyType_LongMode=%s for "%s"' % (fEnable, self.sName));
904 fRc = False;
905 else:
906 reporter.log('set CPUPropertyType_LongMode=%s for "%s"' % (fEnable, self.sName));
907 self.oTstDrv.processPendingEvents();
908 return fRc;
909
910 def enablePae(self, fEnable):
911 """
912 Enables or disables PAE
913 Returns True on success and False on failure. Error information is logged.
914 """
915 fRc = True;
916 try:
917 if self.fpApiVer >= 3.2: # great, ain't it?
918 self.o.machine.setCPUProperty(vboxcon.CPUPropertyType_PAE, fEnable);
919 else:
920 self.o.machine.setCpuProperty(vboxcon.CpuPropertyType_PAE, fEnable);
921 except:
922 reporter.errorXcpt('failed to set CPUPropertyType_PAE=%s for "%s"' % (fEnable, self.sName));
923 fRc = False;
924 else:
925 reporter.log('set CPUPropertyType_PAE=%s for "%s"' % (fEnable, self.sName));
926 self.oTstDrv.processPendingEvents();
927 return fRc;
928
929 def enableIoApic(self, fEnable):
930 """
931 Enables or disables the IO-APIC
932 Returns True on success and False on failure. Error information is logged.
933 """
934 fRc = True;
935 try:
936 self.o.machine.BIOSSettings.IOAPICEnabled = fEnable;
937 except:
938 reporter.errorXcpt('failed to set BIOSSettings.IOAPICEnabled=%s for "%s"' % (fEnable, self.sName));
939 fRc = False;
940 else:
941 reporter.log('set BIOSSettings.IOAPICEnabled=%s for "%s"' % (fEnable, self.sName));
942 self.oTstDrv.processPendingEvents();
943 return fRc;
944
945 def enableHpet(self, fEnable):
946 """
947 Enables or disables the HPET
948 Returns True on success and False on failure. Error information is logged.
949 """
950 fRc = True;
951 try:
952 if self.fpApiVer >= 4.2:
953 self.o.machine.HPETEnabled = fEnable;
954 else:
955 self.o.machine.hpetEnabled = fEnable;
956 except:
957 reporter.errorXcpt('failed to set HpetEnabled=%s for "%s"' % (fEnable, self.sName));
958 fRc = False;
959 else:
960 reporter.log('set HpetEnabled=%s for "%s"' % (fEnable, self.sName));
961 self.oTstDrv.processPendingEvents();
962 return fRc;
963
964 def enableUsbHid(self, fEnable):
965 """
966 Enables or disables the USB HID
967 Returns True on success and False on failure. Error information is logged.
968 """
969 fRc = True;
970 try:
971 if fEnable:
972 if self.fpApiVer >= 4.3:
973 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
974 if cOhciCtls == 0:
975 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
976 else:
977 self.o.machine.usbController.enabled = True;
978
979 if self.fpApiVer >= 4.2:
980 self.o.machine.pointingHIDType = vboxcon.PointingHIDType_ComboMouse;
981 self.o.machine.keyboardHIDType = vboxcon.KeyboardHIDType_ComboKeyboard;
982 else:
983 self.o.machine.pointingHidType = vboxcon.PointingHidType_ComboMouse;
984 self.o.machine.keyboardHidType = vboxcon.KeyboardHidType_ComboKeyboard;
985 else:
986 if self.fpApiVer >= 4.2:
987 self.o.machine.pointingHIDType = vboxcon.PointingHIDType_PS2Mouse;
988 self.o.machine.keyboardHIDType = vboxcon.KeyboardHIDType_PS2Keyboard;
989 else:
990 self.o.machine.pointingHidType = vboxcon.PointingHidType_PS2Mouse;
991 self.o.machine.keyboardHidType = vboxcon.KeyboardHidType_PS2Keyboard;
992 except:
993 reporter.errorXcpt('failed to change UsbHid to %s for "%s"' % (fEnable, self.sName));
994 fRc = False;
995 else:
996 reporter.log('changed UsbHid to %s for "%s"' % (fEnable, self.sName));
997 self.oTstDrv.processPendingEvents();
998 return fRc;
999
1000 def enableUsbOhci(self, fEnable):
1001 """
1002 Enables or disables the USB OHCI controller
1003 Returns True on success and False on failure. Error information is logged.
1004 """
1005 fRc = True;
1006 try:
1007 if fEnable:
1008 if self.fpApiVer >= 4.3:
1009 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1010 if cOhciCtls == 0:
1011 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1012 else:
1013 self.o.machine.usbController.enabled = True;
1014 else:
1015 if self.fpApiVer >= 4.3:
1016 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1017 if cOhciCtls == 1:
1018 self.o.machine.removeUSBController('OHCI');
1019 else:
1020 self.o.machine.usbController.enabled = False;
1021 except:
1022 reporter.errorXcpt('failed to change OHCI to %s for "%s"' % (fEnable, self.sName));
1023 fRc = False;
1024 else:
1025 reporter.log('changed OHCI to %s for "%s"' % (fEnable, self.sName));
1026 self.oTstDrv.processPendingEvents();
1027 return fRc;
1028
1029 def enableUsbEhci(self, fEnable):
1030 """
1031 Enables or disables the USB EHCI controller, enables also OHCI if it is still disabled.
1032 Returns True on success and False on failure. Error information is logged.
1033 """
1034 fRc = True;
1035 try:
1036 if fEnable:
1037 if self.fpApiVer >= 4.3:
1038 cOhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_OHCI);
1039 if cOhciCtls == 0:
1040 self.o.machine.addUSBController('OHCI', vboxcon.USBControllerType_OHCI);
1041
1042 cEhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_EHCI);
1043 if cEhciCtls == 0:
1044 self.o.machine.addUSBController('EHCI', vboxcon.USBControllerType_EHCI);
1045 else:
1046 self.o.machine.usbController.enabled = True;
1047 self.o.machine.usbController.enabledEHCI = True;
1048 else:
1049 if self.fpApiVer >= 4.3:
1050 cEhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_EHCI);
1051 if cEhciCtls == 1:
1052 self.o.machine.removeUSBController('EHCI');
1053 else:
1054 self.o.machine.usbController.enabledEHCI = False;
1055 except:
1056 reporter.errorXcpt('failed to change EHCI to %s for "%s"' % (fEnable, self.sName));
1057 fRc = False;
1058 else:
1059 reporter.log('changed EHCI to %s for "%s"' % (fEnable, self.sName));
1060 self.oTstDrv.processPendingEvents();
1061 return fRc;
1062
1063 def enableUsbXhci(self, fEnable):
1064 """
1065 Enables or disables the USB XHCI controller. Error information is logged.
1066 """
1067 fRc = True;
1068 try:
1069 if fEnable:
1070 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1071 if cXhciCtls == 0:
1072 self.o.machine.addUSBController('XHCI', vboxcon.USBControllerType_XHCI);
1073 else:
1074 cXhciCtls = self.o.machine.getUSBControllerCountByType(vboxcon.USBControllerType_XHCI);
1075 if cXhciCtls == 1:
1076 self.o.machine.removeUSBController('XHCI');
1077 except:
1078 reporter.errorXcpt('failed to change XHCI to %s for "%s"' % (fEnable, self.sName));
1079 fRc = False;
1080 else:
1081 reporter.log('changed XHCI to %s for "%s"' % (fEnable, self.sName));
1082 self.oTstDrv.processPendingEvents();
1083 return fRc;
1084
1085 def setFirmwareType(self, eType):
1086 """
1087 Sets the firmware type.
1088 Returns True on success and False on failure. Error information is logged.
1089 """
1090 fRc = True;
1091 try:
1092 self.o.machine.firmwareType = eType;
1093 except:
1094 reporter.errorXcpt('failed to set firmwareType=%s for "%s"' % (eType, self.sName));
1095 fRc = False;
1096 else:
1097 reporter.log('set firmwareType=%s for "%s"' % (eType, self.sName));
1098 self.oTstDrv.processPendingEvents();
1099 return fRc;
1100
1101 def setupBootLogo(self, fEnable, cMsLogoDisplay = 0):
1102 """
1103 Sets up the boot logo. fEnable toggles the fade and boot menu
1104 settings as well as the mode.
1105 """
1106 fRc = True;
1107 try:
1108 self.o.machine.BIOSSettings.logoFadeIn = not fEnable;
1109 self.o.machine.BIOSSettings.logoFadeOut = not fEnable;
1110 self.o.machine.BIOSSettings.logoDisplayTime = cMsLogoDisplay;
1111 if fEnable:
1112 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_Disabled;
1113 else:
1114 self.o.machine.BIOSSettings.bootMenuMode = vboxcon.BIOSBootMenuMode_MessageAndMenu;
1115 except:
1116 reporter.errorXcpt('failed to set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1117 fRc = False;
1118 else:
1119 reporter.log('set logoFadeIn/logoFadeOut/bootMenuMode=%s for "%s"' % (fEnable, self.sName));
1120 self.oTstDrv.processPendingEvents();
1121 return fRc;
1122
1123 def setupVrdp(self, fEnable, uPort = None):
1124 """
1125 Configures VRDP.
1126 """
1127 fRc = True;
1128 try:
1129 if self.fpApiVer >= 4.0:
1130 self.o.machine.VRDEServer.enabled = fEnable;
1131 else:
1132 self.o.machine.VRDPServer.enabled = fEnable;
1133 except:
1134 reporter.errorXcpt('failed to set VRDEServer::enabled=%s for "%s"' % (fEnable, self.sName));
1135 fRc = False;
1136
1137 if uPort is not None and fRc:
1138 try:
1139 if self.fpApiVer >= 4.0:
1140 self.o.machine.VRDEServer.setVRDEProperty("TCP/Ports", str(uPort));
1141 else:
1142 self.o.machine.VRDPServer.ports = str(uPort);
1143 except:
1144 reporter.errorXcpt('failed to set VRDEServer::ports=%s for "%s"' % (uPort, self.sName));
1145 fRc = False;
1146 if fRc:
1147 reporter.log('set VRDEServer.enabled/ports=%s/%s for "%s"' % (fEnable, uPort, self.sName));
1148 self.oTstDrv.processPendingEvents();
1149 return fRc;
1150
1151 def getNicDriverNameFromType(self, eNicType):
1152 """
1153 Helper that translate the adapter type into a driver name.
1154 """
1155 if eNicType == vboxcon.NetworkAdapterType_Am79C970A \
1156 or eNicType == vboxcon.NetworkAdapterType_Am79C973:
1157 sName = 'pcnet';
1158 elif eNicType == vboxcon.NetworkAdapterType_I82540EM \
1159 or eNicType == vboxcon.NetworkAdapterType_I82543GC \
1160 or eNicType == vboxcon.NetworkAdapterType_I82545EM:
1161 sName = 'e1000';
1162 elif eNicType == vboxcon.NetworkAdapterType_Virtio:
1163 sName = 'virtio-net';
1164 else:
1165 reporter.error('Unknown adapter type "%s" (VM: "%s")' % (eNicType, self.sName));
1166 sName = 'pcnet';
1167 return sName;
1168
1169 def setupNatForwardingForTxs(self, iNic = 0, iHostPort = 5042):
1170 """
1171 Sets up NAT forwarding for port 5042 if applicable, cleans up if not.
1172 """
1173 try:
1174 oNic = self.o.machine.getNetworkAdapter(iNic);
1175 except:
1176 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1177 return False;
1178
1179 # Nuke the old setup for all possible adapter types (in case we're
1180 # called after it changed).
1181 for sName in ('pcnet', 'e1000', 'virtio-net'):
1182 for sConfig in ('VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic), \
1183 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)):
1184 try:
1185 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), '');
1186 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '');
1187 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '');
1188 except:
1189 reporter.errorXcpt();
1190
1191 # Set up port forwarding if NAT attachment.
1192 try:
1193 eAttType = oNic.attachmentType;
1194 except:
1195 reporter.errorXcpt('attachmentType on %s failed for "%s"' % (iNic, self.sName));
1196 return False;
1197 if eAttType != vboxcon.NetworkAttachmentType_NAT:
1198 return True;
1199
1200 try:
1201 eNicType = oNic.adapterType;
1202 fTraceEnabled = oNic.traceEnabled;
1203 except:
1204 reporter.errorXcpt('attachmentType/traceEnabled on %s failed for "%s"' % (iNic, self.sName));
1205 return False;
1206
1207 if self.fpApiVer >= 4.1:
1208 try:
1209 if self.fpApiVer >= 4.2:
1210 oNatEngine = oNic.NATEngine;
1211 else:
1212 oNatEngine = oNic.natDriver;
1213 except:
1214 reporter.errorXcpt('Failed to get INATEngine data on "%s"' % (self.sName));
1215 return False;
1216 try: oNatEngine.removeRedirect('txs');
1217 except: pass;
1218 try:
1219 oNatEngine.addRedirect('txs', vboxcon.NATProtocol_TCP, '127.0.0.1', '%s' % (iHostPort), '', '5042');
1220 except:
1221 reporter.errorXcpt('Failed to add a addRedirect redirect on "%s"' % (self.sName));
1222 return False;
1223
1224 else:
1225 sName = self.getNicDriverNameFromType(eNicType);
1226 if fTraceEnabled:
1227 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/AttachedDriver/Config' % (sName, iNic)
1228 else:
1229 sConfig = 'VBoxInternal/Devices/%s/%u/LUN#0/Config' % (sName, iNic)
1230
1231 try:
1232 self.o.machine.setExtraData('%s/txs/Protocol' % (sConfig), 'TCP');
1233 self.o.machine.setExtraData('%s/txs/HostPort' % (sConfig), '%s' % (iHostPort));
1234 self.o.machine.setExtraData('%s/txs/GuestPort' % (sConfig), '5042');
1235 except:
1236 reporter.errorXcpt('Failed to set NAT extra data on "%s"' % (self.sName));
1237 return False;
1238 return True;
1239
1240 def setNicType(self, eType, iNic = 0):
1241 """
1242 Sets the NIC type of the specified NIC.
1243 Returns True on success and False on failure. Error information is logged.
1244 """
1245 try:
1246 try:
1247 oNic = self.o.machine.getNetworkAdapter(iNic);
1248 except:
1249 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1250 return False;
1251 try:
1252 oNic.adapterType = eType;
1253 except:
1254 reporter.errorXcpt('failed to set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1255 return False;
1256 finally:
1257 self.oTstDrv.processPendingEvents();
1258
1259 if not self.setupNatForwardingForTxs(iNic):
1260 return False;
1261 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eType, self.sName));
1262 return True;
1263
1264 def setNicTraceEnabled(self, fTraceEnabled, sTraceFile, iNic = 0):
1265 """
1266 Sets the NIC trace enabled flag and file path.
1267 Returns True on success and False on failure. Error information is logged.
1268 """
1269 try:
1270 try:
1271 oNic = self.o.machine.getNetworkAdapter(iNic);
1272 except:
1273 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1274 return False;
1275 try:
1276 oNic.traceEnabled = fTraceEnabled;
1277 oNic.traceFile = sTraceFile;
1278 except:
1279 reporter.errorXcpt('failed to set NIC trace flag on slot %s to %s for VM "%s"' \
1280 % (iNic, fTraceEnabled, self.sName));
1281 return False;
1282 finally:
1283 self.oTstDrv.processPendingEvents();
1284
1285 if not self.setupNatForwardingForTxs(iNic):
1286 return False;
1287 reporter.log('set NIC trace on slot %s to "%s" (path "%s") for VM "%s"' %
1288 (iNic, fTraceEnabled, sTraceFile, self.sName));
1289 return True;
1290
1291 def getDefaultNicName(self, eAttachmentType):
1292 """
1293 Return the default network / interface name for the NIC attachment type.
1294 """
1295 sRetName = '';
1296 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1297 if self.oTstDrv.sDefBridgedNic is not None:
1298 sRetName = self.oTstDrv.sDefBridgedNic;
1299 else:
1300 sRetName = 'eth0';
1301 try:
1302 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1303 for oHostNic in aoHostNics:
1304 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_Bridged \
1305 and oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1306 sRetName = oHostNic.name;
1307 break;
1308 except:
1309 reporter.errorXcpt();
1310 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1311 try:
1312 aoHostNics = self.oVBoxMgr.getArray(self.oVBox.host, 'networkInterfaces');
1313 for oHostNic in aoHostNics:
1314 if oHostNic.interfaceType == vboxcon.HostNetworkInterfaceType_HostOnly:
1315 if oHostNic.status == vboxcon.HostNetworkInterfaceStatus_Up:
1316 sRetName = oHostNic.name;
1317 break;
1318 if sRetName == '':
1319 sRetName = oHostNic.name;
1320 except:
1321 reporter.errorXcpt();
1322 if sRetName == '':
1323 sRetName = 'HostInterfaceNetwork-vboxnet0';
1324 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1325 sRetName = 'VBoxTest';
1326 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1327 sRetName = '';
1328 else:
1329 reporter.error('eAttachmentType=%s is not known' % (eAttachmentType));
1330 return sRetName;
1331
1332 def setNicAttachment(self, eAttachmentType, sName = None, iNic = 0):
1333 """
1334 Sets the attachment type of the specified NIC.
1335 Returns True on success and False on failure. Error information is logged.
1336 """
1337 try:
1338 oNic = self.o.machine.getNetworkAdapter(iNic);
1339 except:
1340 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1341 return False;
1342
1343 try:
1344 if eAttachmentType is not None:
1345 try:
1346 if self.fpApiVer >= 4.1:
1347 oNic.attachmentType = eAttachmentType;
1348 else:
1349 if eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1350 oNic.attachToNAT();
1351 elif eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1352 oNic.attachToBridgedInterface();
1353 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1354 oNic.attachToInternalNetwork();
1355 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1356 oNic.attachToHostOnlyInterface();
1357 else:
1358 raise base.GenError("eAttachmentType=%s is invalid" % (eAttachmentType));
1359 except:
1360 reporter.errorXcpt('failed to set the attachment type on slot %s to %s for VM "%s"' \
1361 % (iNic, eAttachmentType, self.sName));
1362 return False;
1363 else:
1364 try:
1365 eAttachmentType = oNic.attachmentType;
1366 except:
1367 reporter.errorXcpt('failed to get the attachment type on slot %s for VM "%s"' % (iNic, self.sName));
1368 return False;
1369 finally:
1370 self.oTstDrv.processPendingEvents();
1371
1372 if sName is not None:
1373 # Resolve the special 'default' name.
1374 if sName == 'default':
1375 sName = self.getDefaultNicName(eAttachmentType);
1376
1377 # The name translate to different attributes depending on the
1378 # attachment type.
1379 try:
1380 if eAttachmentType == vboxcon.NetworkAttachmentType_Bridged:
1381 ## @todo check this out on windows, may have to do a
1382 # translation of the name there or smth IIRC.
1383 try:
1384 if self.fpApiVer >= 4.1:
1385 oNic.bridgedInterface = sName;
1386 else:
1387 oNic.hostInterface = sName;
1388 except:
1389 reporter.errorXcpt('failed to set the hostInterface property on slot %s to "%s" for VM "%s"' \
1390 % (iNic, sName, self.sName));
1391 return False;
1392 elif eAttachmentType == vboxcon.NetworkAttachmentType_HostOnly:
1393 try:
1394 if self.fpApiVer >= 4.1:
1395 oNic.hostOnlyInterface = sName;
1396 else:
1397 oNic.hostInterface = sName;
1398 except:
1399 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1400 % (iNic, sName, self.sName));
1401 return False;
1402 elif eAttachmentType == vboxcon.NetworkAttachmentType_Internal:
1403 try:
1404 oNic.internalNetwork = sName;
1405 except:
1406 reporter.errorXcpt('failed to set the internalNetwork property on slot %s to "%s" for VM "%s"' \
1407 % (iNic, sName, self.sName));
1408 return False;
1409 elif eAttachmentType == vboxcon.NetworkAttachmentType_NAT:
1410 try:
1411 oNic.NATNetwork = sName;
1412 except:
1413 reporter.errorXcpt('failed to set the NATNetwork property on slot %s to "%s" for VM "%s"' \
1414 % (iNic, sName, self.sName));
1415 return False;
1416 finally:
1417 self.oTstDrv.processPendingEvents();
1418
1419 if not self.setupNatForwardingForTxs(iNic):
1420 return False;
1421 reporter.log('set NIC type on slot %s to %s for VM "%s"' % (iNic, eAttachmentType, self.sName));
1422 return True;
1423
1424 def setNicMacAddress(self, sMacAddr, iNic = 0):
1425 """
1426 Sets the MAC address of the specified NIC.
1427 Returns True on success and False on failure. Error information is logged.
1428 """
1429
1430 # Resolve missing MAC address prefix
1431 cchMacAddr = len(sMacAddr)
1432 if cchMacAddr > 0 and cchMacAddr < 12:
1433 sHostName = ''
1434 try:
1435 sHostName = socket.getfqdn()
1436 if not '.' in sHostName:
1437 # somewhat misconfigured system, needs expensive approach to guessing FQDN
1438 for aAI in socket.getaddrinfo(sHostName, None):
1439 sName, _ = socket.getnameinfo(aAI[4], 0)
1440 if '.' in sName and not set(sName).issubset(set('0123456789.')):
1441 sHostName = sName
1442 break
1443
1444 sHostIP = socket.gethostbyname(sHostName)
1445 abHostIP = socket.inet_aton(sHostIP)
1446 if ord(abHostIP[0]) == 127 \
1447 or ord(abHostIP[0]) == 169 and ord(abHostIP[1]) == 254 \
1448 or ord(abHostIP[0]) == 192 and ord(abHostIP[1]) == 168 and ord(abHostIP[2]) == 56:
1449 reporter.log('warning: host IP for "%s" is %s, most likely not unique.' % (sHostName, sHostIP))
1450 except:
1451 reporter.errorXcpt('failed to determine the host IP for "%s".' % (sHostName,))
1452 abHostIP = array.array('B', (0x80, 0x86, 0x00, 0x00)).tostring()
1453 sDefaultMac = '%02X%02X%02X%02X%02X%02X' \
1454 % (0x02, ord(abHostIP[0]), ord(abHostIP[1]), ord(abHostIP[2]), ord(abHostIP[3]), iNic)
1455 sMacAddr = sDefaultMac[0:(12 - cchMacAddr)] + sMacAddr
1456
1457 # Get the NIC object and try set it address.
1458 try:
1459 oNic = self.o.machine.getNetworkAdapter(iNic);
1460 except:
1461 reporter.errorXcpt('getNetworkAdapter(%s) failed for "%s"' % (iNic, self.sName));
1462 return False;
1463
1464 try:
1465 oNic.MACAddress = sMacAddr;
1466 except:
1467 reporter.errorXcpt('failed to set the MAC address on slot %s to "%s" for VM "%s"' \
1468 % (iNic, sMacAddr, self.sName));
1469 return False;
1470
1471 reporter.log('set MAC address on slot %s to %s for VM "%s"' % (iNic, sMacAddr, self.sName));
1472 return True;
1473
1474 def setRamSize(self, cMB):
1475 """
1476 Set the RAM size of the VM.
1477 Returns True on success and False on failure. Error information is logged.
1478 """
1479 fRc = True;
1480 try:
1481 self.o.machine.memorySize = cMB;
1482 except:
1483 reporter.errorXcpt('failed to set the RAM size of "%s" to %s' % (self.sName, cMB));
1484 fRc = False;
1485 else:
1486 reporter.log('set the RAM size of "%s" to %s' % (self.sName, cMB));
1487 self.oTstDrv.processPendingEvents();
1488 return fRc;
1489
1490 def setVRamSize(self, cMB):
1491 """
1492 Set the RAM size of the VM.
1493 Returns True on success and False on failure. Error information is logged.
1494 """
1495 fRc = True;
1496 try:
1497 self.o.machine.VRAMSize = cMB;
1498 except:
1499 reporter.errorXcpt('failed to set the VRAM size of "%s" to %s' % (self.sName, cMB));
1500 fRc = False;
1501 else:
1502 reporter.log('set the VRAM size of "%s" to %s' % (self.sName, cMB));
1503 self.oTstDrv.processPendingEvents();
1504 return fRc;
1505
1506 def setCpuCount(self, cCpus):
1507 """
1508 Set the number of CPUs.
1509 Returns True on success and False on failure. Error information is logged.
1510 """
1511 fRc = True;
1512 try:
1513 self.o.machine.CPUCount = cCpus;
1514 except:
1515 reporter.errorXcpt('failed to set the CPU count of "%s" to %s' % (self.sName, cCpus));
1516 fRc = False;
1517 else:
1518 reporter.log('set the CPU count of "%s" to %s' % (self.sName, cCpus));
1519 self.oTstDrv.processPendingEvents();
1520 return fRc;
1521
1522 def ensureControllerAttached(self, sController):
1523 """
1524 Makes sure the specified controller is attached to the VM, attaching it
1525 if necessary.
1526 """
1527 try:
1528 try:
1529 self.o.machine.getStorageControllerByName(sController);
1530 except:
1531 iType = _ControllerNameToBus(sController);
1532 try:
1533 self.o.machine.addStorageController(sController, iType);
1534 reporter.log('added storage controller "%s" (type %s) to %s' % (sController, iType, self.sName));
1535 except:
1536 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, iType, self.sName) );
1537 return False;
1538 finally:
1539 self.oTstDrv.processPendingEvents();
1540 return True;
1541
1542 def setStorageControllerPortCount(self, sController, iPortCount):
1543 """
1544 Set maximum ports count for storage controller
1545 """
1546 try:
1547 oCtl = self.o.machine.getStorageControllerByName(sController)
1548 oCtl.portCount = iPortCount
1549 self.oTstDrv.processPendingEvents()
1550 reporter.log('set controller "%s" port count to value %d' % (sController, iPortCount))
1551 return True
1552 except:
1553 reporter.log('unable to set storage controller "%s" ports count to %d' % (sController, iPortCount))
1554
1555 return False
1556
1557 def setBootOrder(self, iPosition, eType):
1558 """
1559 Set guest boot order type
1560 @param iPosition boot order position
1561 @param eType device type (vboxcon.DeviceType_HardDisk,
1562 vboxcon.DeviceType_DVD, vboxcon.DeviceType_Floppy)
1563 """
1564 try:
1565 self.o.machine.setBootOrder(iPosition, eType)
1566 except:
1567 return reporter.errorXcpt('Unable to set boot order.')
1568
1569 reporter.log('Set boot order [%d] for device %s' % (iPosition, str(eType)))
1570 self.oTstDrv.processPendingEvents();
1571
1572 return True
1573
1574 def setStorageControllerType(self, eType, sController = "IDE Controller"):
1575 """
1576 Similar to ensureControllerAttached, except it will change the type.
1577 """
1578 try:
1579 oCtl = self.o.machine.getStorageControllerByName(sController);
1580 except:
1581 iType = _ControllerNameToBus(sController);
1582 try:
1583 oCtl = self.o.machine.addStorageController(sController, iType);
1584 reporter.log('added storage controller "%s" (type %s) to %s' % (sController, iType, self.sName));
1585 except:
1586 reporter.errorXcpt('addStorageController("%s",%s) failed on "%s"' % (sController, iType, self.sName) );
1587 return False;
1588 try:
1589 oCtl.controllerType = eType;
1590 except:
1591 reporter.errorXcpt('failed to set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1592 return False;
1593 reporter.log('set controller type of "%s" on "%s" to %s' % (sController, self.sName, eType) );
1594 self.oTstDrv.processPendingEvents();
1595 return True;
1596
1597 def attachDvd(self, sImage = None, sController = "IDE Controller", iPort = 1, iDevice = 0):
1598 """
1599 Attaches a DVD drive to a VM, optionally with an ISO inserted.
1600 Returns True on success and False on failure. Error information is logged.
1601 """
1602 # Input validation.
1603 if sImage is not None and not self.oTstDrv.isResourceFile(sImage)\
1604 and not os.path.isabs(sImage): ## fixme - testsuite unzip ++
1605 reporter.fatal('"%s" is not in the resource set' % (sImage));
1606 return None;
1607
1608 if not self.ensureControllerAttached(sController):
1609 return False;
1610
1611 # Find/register the image if specified.
1612 oImage = None;
1613 sImageUuid = "";
1614 if sImage is not None:
1615 sFullName = self.oTstDrv.getFullResourceName(sImage)
1616 try:
1617 oImage = self.oVBox.findDVDImage(sFullName);
1618 except:
1619 try:
1620 if self.fpApiVer >= 4.1:
1621 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly, False);
1622 elif self.fpApiVer >= 4.0:
1623 oImage = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_DVD, vboxcon.AccessMode_ReadOnly);
1624 else:
1625 oImage = self.oVBox.openDVDImage(sFullName, "");
1626 except vbox.ComException, oXcpt:
1627 if oXcpt.errno != -1:
1628 reporter.errorXcpt('failed to open DVD image "%s" xxx' % (sFullName));
1629 else:
1630 reporter.errorXcpt('failed to open DVD image "%s" yyy' % (sFullName));
1631 return False;
1632 except:
1633 reporter.errorXcpt('failed to open DVD image "%s"' % (sFullName));
1634 return False;
1635 try:
1636 sImageUuid = oImage.id;
1637 except:
1638 reporter.errorXcpt('failed to get the UUID of "%s"' % (sFullName));
1639 return False;
1640
1641 # Attach the DVD.
1642 fRc = True;
1643 try:
1644 if self.fpApiVer >= 4.0:
1645 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, oImage);
1646 else:
1647 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_DVD, sImageUuid);
1648 except:
1649 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1650 % (sController, iPort, iDevice, sImageUuid, self.sName) );
1651 fRc = False;
1652 else:
1653 reporter.log('attached DVD to %s, image="%s"' % (self.sName, sImage));
1654 self.oTstDrv.processPendingEvents();
1655 return fRc;
1656
1657 def attachHd(self, sHd, sController = "IDE Controller", iPort = 0, iDevice = 0, fImmutable = True, fForceResource = True):
1658 """
1659 Attaches a HD to a VM.
1660 Returns True on success and False on failure. Error information is logged.
1661 """
1662 # Input validation.
1663 if fForceResource and not self.oTstDrv.isResourceFile(sHd):
1664 reporter.fatal('"%s" is not in the resource set' % (sHd,));
1665 return None;
1666
1667 if not self.ensureControllerAttached(sController):
1668 return False;
1669
1670 # Find the HD, registering it if necessary (as immutable).
1671 if fForceResource:
1672 sFullName = self.oTstDrv.getFullResourceName(sHd);
1673 else:
1674 sFullName = sHd;
1675 try:
1676 oHd = self.oVBox.findHardDisk(sFullName);
1677 except:
1678 try:
1679 if self.fpApiVer >= 4.1:
1680 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
1681 elif self.fpApiVer >= 4.0:
1682 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
1683 else:
1684 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
1685 except:
1686 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
1687 return False;
1688 try:
1689 if fImmutable:
1690 oHd.type = vboxcon.MediumType_Immutable;
1691 else:
1692 oHd.type = vboxcon.MediumType_Normal;
1693 except:
1694 if fImmutable:
1695 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1696 else:
1697 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1698 return False;
1699
1700 # Attach it.
1701 fRc = True;
1702 try:
1703 if self.fpApiVer >= 4.0:
1704 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1705 else:
1706 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1707 except:
1708 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1709 % (sController, iPort, iDevice, oHd.id, self.sName) );
1710 fRc = False;
1711 else:
1712 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1713 self.oTstDrv.processPendingEvents();
1714 return fRc;
1715
1716 def createBaseHd(self, sHd, sFmt = "VDI", cb = 10*1024*1024*1024):
1717 """
1718 Creates a base HD.
1719 Returns Medium object on success and None on failure. Error information is logged.
1720 """
1721 try:
1722 if self.fpApiVer >= 5.0:
1723 oHd = self.oVBox.createMedium(sFmt, sHd, vboxcon.AccessMode_ReadWrite, vboxcon.DeviceType_HardDisk);
1724 else:
1725 oHd = self.oVBox.createHardDisk(sFmt, sHd);
1726 oProgressXpcom = oHd.createBaseStorage(cb, (vboxcon.MediumVariant_Standard, ))
1727 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create base disk %s' % (sHd));
1728 oProgress.wait();
1729 oProgress.logResult();
1730 except:
1731 reporter.errorXcpt('failed to create base hd "%s"' % (sHd));
1732 oHd = None
1733
1734 return oHd;
1735
1736 def createDiffHd(self, oParentHd, sHd, sFmt = "VDI"):
1737 """
1738 Creates a differencing 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 = oParentHd.createDiffStorage(oHd, (vboxcon.MediumVariant_Standard, ))
1747 oProgress = ProgressWrapper(oProgressXpcom, self.oVBoxMgr, self.oTstDrv, 'create diff disk %s' % (sHd));
1748 oProgress.wait();
1749 oProgress.logResult();
1750 except:
1751 reporter.errorXcpt('failed to create diff hd "%s"' % (sHd));
1752 oHd = None
1753
1754 return oHd;
1755
1756 def createAndAttachHd(self, sHd, sFmt = "VDI", sController = "IDE Controller", cb = 10*1024*1024*1024, \
1757 iPort = 0, iDevice = 0, fImmutable = True):
1758 """
1759 Creates and attaches a HD to a VM.
1760 Returns True on success and False on failure. Error information is logged.
1761 """
1762 if not self.ensureControllerAttached(sController):
1763 return False;
1764
1765 oHd = self.createBaseHd(sHd, sFmt, cb)
1766 if oHd is None:
1767 return False;
1768
1769 fRc = True;
1770 try:
1771 if fImmutable:
1772 oHd.type = vboxcon.MediumType_Immutable;
1773 else:
1774 oHd.type = vboxcon.MediumType_Normal;
1775 except:
1776 if fImmutable:
1777 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
1778 else:
1779 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
1780 fRc = False;
1781
1782 # Attach it.
1783 if fRc is True:
1784 try:
1785 if self.fpApiVer >= 4.0:
1786 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1787 else:
1788 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1789 except:
1790 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1791 % (sController, iPort, iDevice, oHd.id, self.sName) );
1792 fRc = False;
1793 else:
1794 reporter.log('attached "%s" to %s' % (sHd, self.sName));
1795
1796 # Delete disk in case of an error
1797 if fRc is False:
1798 try:
1799 oProgressCom = oHd.deleteStorage();
1800 except:
1801 reporter.errorXcpt('deleteStorage() for disk %s failed' % (sHd,));
1802 else:
1803 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'delete disk %s' % (sHd));
1804 oProgress.wait();
1805 oProgress.logResult();
1806
1807 self.oTstDrv.processPendingEvents();
1808 return fRc;
1809
1810 def detachHd(self, sController = "IDE Controller", iPort = 0, iDevice = 0):
1811 """
1812 Detaches a HD, if attached, and returns a reference to it (IMedium).
1813
1814 In order to delete the detached medium, the caller must first save
1815 the changes made in this session.
1816
1817 Returns (fRc, oHd), where oHd is None unless fRc is True, and fRc is
1818 your standard success indicator. Error information is logged.
1819 """
1820
1821 # What's attached?
1822 try:
1823 oHd = self.o.machine.getMedium(sController, iPort, iDevice);
1824 except:
1825 if self.oVBoxMgr.xcptIsOurXcptKind() \
1826 and self.oVBoxMgr.xcptIsEqual(None, self.oVBoxMgr.constants.VBOX_E_OBJECT_NOT_FOUND):
1827 reporter.log('No HD attached (to %s %s:%s)' % (sController, iPort, iDevice));
1828 return (True, None);
1829 return (reporter.errorXcpt('Error getting media at port %s, device %s, on %s.'
1830 % (iPort, iDevice, sController)), None);
1831 # Detach it.
1832 try:
1833 self.o.machine.detachDevice(sController, iPort, iDevice);
1834 except:
1835 return (reporter.errorXcpt('detachDevice("%s",%s,%s) failed on "%s"' \
1836 % (sController, iPort, iDevice, self.sName) ), None);
1837 reporter.log('detached HD ("%s",%s,%s) from %s' % (sController, iPort, iDevice, self.sName));
1838 return (True, oHd);
1839
1840 def attachFloppy(self, sFloppy, sController = "Floppy Controller", iPort = 0, iDevice = 0):
1841 """
1842 Attaches a floppy image to a VM.
1843 Returns True on success and False on failure. Error information is logged.
1844 """
1845 # Input validation.
1846 ## @todo Fix this wrt to bootsector-xxx.img from the validationkit.zip.
1847 ##if not self.oTstDrv.isResourceFile(sFloppy):
1848 ## reporter.fatal('"%s" is not in the resource set' % (sFloppy));
1849 ## return None;
1850
1851 if not self.ensureControllerAttached(sController):
1852 return False;
1853
1854 # Find the floppy image, registering it if necessary (as immutable).
1855 sFullName = self.oTstDrv.getFullResourceName(sFloppy);
1856 try:
1857 oFloppy = self.oVBox.findFloppyImage(sFullName);
1858 except:
1859 try:
1860 if self.fpApiVer >= 4.1:
1861 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly, False);
1862 elif self.fpApiVer >= 4.0:
1863 oFloppy = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_Floppy, vboxcon.AccessMode_ReadOnly);
1864 else:
1865 oFloppy = self.oVBox.openFloppyImage(sFullName, "");
1866 except:
1867 reporter.errorXcpt('failed to open floppy "%s"' % (sFullName));
1868 return False;
1869 ## @todo the following works but causes trouble below (asserts in main).
1870 #try:
1871 # oFloppy.type = vboxcon.MediumType_Immutable;
1872 #except:
1873 # reporter.errorXcpt('failed to make floppy "%s" immutable' % (sFullName));
1874 # return False;
1875
1876 # Attach it.
1877 fRc = True;
1878 try:
1879 if self.fpApiVer >= 4.0:
1880 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy);
1881 else:
1882 self.o.machine.attachDevice(sController, iPort, iDevice, vboxcon.DeviceType_Floppy, oFloppy.id);
1883 except:
1884 reporter.errorXcpt('attachDevice("%s",%s,%s,Floppy,"%s") failed on "%s"' \
1885 % (sController, iPort, iDevice, oFloppy.id, self.sName) );
1886 fRc = False;
1887 else:
1888 reporter.log('attached "%s" to %s' % (sFloppy, self.sName));
1889 self.oTstDrv.processPendingEvents();
1890 return fRc;
1891
1892 def setupNic(self, sType, sXXX):
1893 """
1894 Attaches a HD to a VM.
1895 Returns True on success and False on failure. Error information is logged.
1896 """
1897 if sType == "PCNet": enmType = vboxcon.NetworkAdapterType_Am79C973;
1898 elif sType == "PCNetOld": enmType = vboxcon.NetworkAdapterType_Am79C970A;
1899 elif sType == "E1000": enmType = vboxcon.NetworkAdapterType_I82545EM; # MT Server
1900 elif sType == "E1000Desk": enmType = vboxcon.NetworkAdapterType_I82540EM; # MT Desktop
1901 elif sType == "E1000Srv2": enmType = vboxcon.NetworkAdapterType_I82543GC; # T Server
1902 elif sType == "Virtio": enmType = vboxcon.NetworkAdapterType_Virtio;
1903 else:
1904 reporter.error('Invalid NIC type: "%s" (sXXX=%s)' % (sType, sXXX));
1905 return False;
1906 ## @todo Implement me!
1907 if enmType is not None: pass
1908 return True;
1909
1910 def setupPreferredConfig(self): # pylint: disable=R0914
1911 """
1912 Configures the VM according to the preferences of the guest type.
1913 """
1914 try:
1915 sOsTypeId = self.o.machine.OSTypeId;
1916 except:
1917 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
1918 return False;
1919
1920 try:
1921 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
1922 except:
1923 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
1924 return False;
1925
1926 # get the attributes.
1927 try:
1928 #sFamilyId = oOsType.familyId;
1929 #f64Bit = oOsType.is64Bit;
1930 fIoApic = oOsType.recommendedIOAPIC;
1931 fVirtEx = oOsType.recommendedVirtEx;
1932 cMBRam = oOsType.recommendedRAM;
1933 cMBVRam = oOsType.recommendedVRAM;
1934 #cMBHdd = oOsType.recommendedHDD;
1935 eNicType = oOsType.adapterType;
1936 if self.fpApiVer >= 3.2:
1937 if self.fpApiVer >= 4.2:
1938 fPae = oOsType.recommendedPAE;
1939 fUsbHid = oOsType.recommendedUSBHID;
1940 fHpet = oOsType.recommendedHPET;
1941 eStorCtlType = oOsType.recommendedHDStorageController;
1942 else:
1943 fPae = oOsType.recommendedPae;
1944 fUsbHid = oOsType.recommendedUsbHid;
1945 fHpet = oOsType.recommendedHpet;
1946 eStorCtlType = oOsType.recommendedHdStorageController;
1947 eFirmwareType = oOsType.recommendedFirmware;
1948 else:
1949 fPae = False;
1950 fUsbHid = False;
1951 fHpet = False;
1952 eFirmwareType = -1;
1953 eStorCtlType = vboxcon.StorageControllerType_PIIX4;
1954 except:
1955 reporter.errorXcpt('exception reading IGuestOSType(%s) attribute' % (sOsTypeId));
1956 self.oTstDrv.processPendingEvents();
1957 return False;
1958 self.oTstDrv.processPendingEvents();
1959
1960 # Do the setting. Continue applying settings on error in case the
1961 # caller ignores the return code
1962 fRc = True;
1963 if not self.enableIoApic(fIoApic): fRc = False;
1964 if not self.enableVirtEx(fVirtEx): fRc = False;
1965 if not self.enablePae(fPae): fRc = False;
1966 if not self.setRamSize(cMBRam): fRc = False;
1967 if not self.setVRamSize(cMBVRam): fRc = False;
1968 if not self.setNicType(eNicType, 0): fRc = False;
1969 if self.fpApiVer >= 3.2:
1970 if not self.setFirmwareType(eFirmwareType): fRc = False;
1971 if not self.enableUsbHid(fUsbHid): fRc = False;
1972 if not self.enableHpet(fHpet): fRc = False;
1973 if eStorCtlType == vboxcon.StorageControllerType_PIIX3 \
1974 or eStorCtlType == vboxcon.StorageControllerType_PIIX4 \
1975 or eStorCtlType == vboxcon.StorageControllerType_ICH6:
1976 if not self.setStorageControllerType(eStorCtlType, "IDE Controller"):
1977 fRc = False;
1978
1979 return fRc;
1980
1981 def addUsbDeviceFilter(self, sName, sVendorId, sProductId):
1982 """
1983 Creates a USB device filter and inserts it into the VM.
1984 Returns True on success.
1985 Returns False on failure (logged).
1986 """
1987 fRc = True;
1988
1989 try:
1990 usbDevFilter = self.o.machine.USBDeviceFilters.createDeviceFilter(sName);
1991 usbDevFilter.active = True;
1992 usbDevFilter.vendorId = sVendorId;
1993 usbDevFilter.productId = sProductId;
1994 try:
1995 self.o.machine.USBDeviceFilters.insertDeviceFilter(0, usbDevFilter);
1996 except:
1997 reporter.errorXcpt('insertDeviceFilter(%s) failed on "%s"' \
1998 % (0, self.sName) );
1999 fRc = False;
2000 else:
2001 reporter.log('inserted USB device filter "%s" to %s' % (sName, self.sName));
2002 except:
2003 reporter.errorXcpt('createDeviceFilter("%s") failed on "%s"' \
2004 % (sName, self.sName) );
2005 fRc = False;
2006 return fRc;
2007
2008 def getGuestPropertyValue(self, sName):
2009 """
2010 Gets a guest property value.
2011 Returns the value on success, None on failure (logged).
2012 """
2013 try:
2014 sValue = self.o.machine.getGuestPropertyValue(sName);
2015 except:
2016 reporter.errorXcpt('IMachine::getGuestPropertyValue("%s") failed' % (sName));
2017 return None;
2018 return sValue;
2019
2020 def setGuestPropertyValue(self, sName, sValue):
2021 """
2022 Sets a guest property value.
2023 Returns the True on success, False on failure (logged).
2024 """
2025 try:
2026 self.o.machine.setGuestPropertyValue(sName, sValue);
2027 except:
2028 reporter.errorXcpt('IMachine::setGuestPropertyValue("%s","%s") failed' % (sName, sValue));
2029 return False;
2030 return True;
2031
2032 def delGuestPropertyValue(self, sName):
2033 """
2034 Deletes a guest property value.
2035 Returns the True on success, False on failure (logged).
2036 """
2037 try:
2038 oMachine = self.o.machine;
2039 if self.fpApiVer >= 4.2:
2040 oMachine.deleteGuestProperty(sName);
2041 else:
2042 oMachine.setGuestPropertyValue(sName, '');
2043 except:
2044 reporter.errorXcpt('Unable to delete guest property "%s"' % (sName,));
2045 return False;
2046 return True;
2047
2048 def setExtraData(self, sKey, sValue):
2049 """
2050 Sets extra data.
2051 Returns the True on success, False on failure (logged).
2052 """
2053 try:
2054 self.o.machine.setExtraData(sKey, sValue);
2055 except:
2056 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue));
2057 return False;
2058 return True;
2059
2060 def getExtraData(self, sKey):
2061 """
2062 Gets extra data.
2063 Returns value on success, None on failure.
2064 """
2065 try:
2066 sValue = self.o.machine.getExtraData(sKey)
2067 except:
2068 reporter.errorXcpt('IMachine::setExtraData("%s","%s") failed' % (sKey, sValue))
2069 return None
2070 return sValue
2071
2072 def setupTeleporter(self, fEnabled=True, uPort = 6500, sAddress = '', sPassword = ''):
2073 """
2074 Sets up the teleporter for the VM.
2075 Returns True on success, False on failure (logged).
2076 """
2077 try:
2078 self.o.machine.teleporterAddress = sAddress;
2079 self.o.machine.teleporterPort = uPort;
2080 self.o.machine.teleporterPassword = sPassword;
2081 self.o.machine.teleporterEnabled = fEnabled;
2082 except:
2083 reporter.errorXcpt('setupTeleporter(%s, %s, %s, %s)' % (fEnabled, sPassword, uPort, sAddress));
2084 return False;
2085 return True;
2086
2087 def enableTeleporter(self, fEnable=True):
2088 """
2089 Enables or disables the teleporter of the VM.
2090 Returns True on success, False on failure (logged).
2091 """
2092 try:
2093 self.o.machine.teleporterEnabled = fEnable;
2094 except:
2095 reporter.errorXcpt('IMachine::teleporterEnabled=%s failed' % (fEnable));
2096 return False;
2097 return True;
2098
2099 def teleport(self, sHostname = 'localhost', uPort = 6500, sPassword = 'password', cMsMaxDowntime = 250):
2100 """
2101 Wrapper around the IConsole::teleport() method.
2102 Returns a progress object on success, None on failure (logged).
2103 """
2104 reporter.log2('"%s"::teleport(%s,%s,%s,%s)...' % (self.sName, sHostname, uPort, sPassword, cMsMaxDowntime));
2105 try:
2106 oProgress = self.o.console.teleport(sHostname, uPort, sPassword, cMsMaxDowntime)
2107 except:
2108 reporter.errorXcpt('IConsole::teleport(%s,%s,%s,%s) failed' % (sHostname, uPort, sPassword, cMsMaxDowntime));
2109 return None;
2110 return ProgressWrapper(oProgress, self.oVBoxMgr, self.oTstDrv, 'teleport %s' % (self.sName,));
2111
2112 def getOsType(self):
2113 """
2114 Gets the IGuestOSType interface for the machine.
2115
2116 return IGuestOSType interface on success, None + errorXcpt on failure.
2117 No exceptions raised.
2118 """
2119 try:
2120 sOsTypeId = self.o.machine.OSTypeId;
2121 except:
2122 reporter.errorXcpt('failed to obtain the OSTypeId for "%s"' % (self.sName));
2123 return None;
2124
2125 try:
2126 oOsType = self.oVBox.getGuestOSType(sOsTypeId);
2127 except:
2128 reporter.errorXcpt('getGuestOSType("%s") failed for "%s"' % (sOsTypeId, self.sName));
2129 return None;
2130
2131 return oOsType;
2132
2133 def setOsType(self, sNewTypeId):
2134 """
2135 Changes the OS type.
2136
2137 returns True on success, False + errorXcpt on failure.
2138 No exceptions raised.
2139 """
2140 try:
2141 self.o.machine.OSTypeId = sNewTypeId;
2142 except:
2143 reporter.errorXcpt('failed to set the OSTypeId for "%s" to "%s"' % (self.sName, sNewTypeId));
2144 return False;
2145 return True;
2146
2147
2148 def setParavirtProvider(self, iProvider):
2149 """
2150 Sets a paravirtualisation provider.
2151 Returns the True on success, False on failure (logged).
2152 """
2153 try:
2154 self.o.machine.paravirtProvider = iProvider
2155 except:
2156 reporter.errorXcpt('Unable to set paravirtualisation provider "%s"' % (iProvider,))
2157 return False;
2158 return True;
2159
2160
2161
2162 #
2163 # IConsole wrappers.
2164 #
2165
2166 def powerOff(self, fFudgeOnFailure = True):
2167 """
2168 Powers off the VM.
2169
2170 Returns True on success.
2171 Returns False on IConsole::powerDown() failure.
2172 Returns None if the progress object returns failure.
2173 """
2174 try:
2175 oProgress = self.o.console.powerDown();
2176 except:
2177 reporter.logXcpt('IConsole::powerDown failed on %s' % (self.sName));
2178 if fFudgeOnFailure:
2179 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2180 self.waitForTask(1000); # fudge
2181 return False;
2182
2183 rc = self.oTstDrv.waitOnProgress(oProgress);
2184 if rc < 0:
2185 self.close();
2186 if fFudgeOnFailure:
2187 vbox.reportError(oProgress, 'powerDown for "%s" failed' % (self.sName));
2188 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2189 return None;
2190
2191 # Wait for the VM to really power off or we'll fail to open a new session to it.
2192 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2193 return self.waitForTask(30 * 1000); # fudge
2194
2195 def restoreSnapshot(self, oSnapshot, fFudgeOnFailure = True):
2196 """
2197 Restores the given snapshot.
2198
2199 Returns True on success.
2200 Returns False on IMachine::restoreSnapshot() failure.
2201 Returns None if the progress object returns failure.
2202 """
2203 try:
2204 if self.fpApiVer >= 5.0:
2205 oProgress = self.o.machine.restoreSnapshot(oSnapshot);
2206 else:
2207 oProgress = self.o.console.restoreSnapshot(oSnapshot);
2208 except:
2209 reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
2210 if fFudgeOnFailure:
2211 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2212 self.waitForTask(1000); # fudge
2213 return False;
2214
2215 rc = self.oTstDrv.waitOnProgress(oProgress);
2216 if rc < 0:
2217 self.close();
2218 if fFudgeOnFailure:
2219 vbox.reportError(oProgress, 'restoreSnapshot for "%s" failed' % (self.sName));
2220 return None;
2221
2222 return self.waitForTask(30 * 1000);
2223
2224 def deleteSnapshot(self, oSnapshot, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2225 """
2226 Deletes the given snapshot merging the diff image into the base.
2227
2228 Returns True on success.
2229 Returns False on IMachine::deleteSnapshot() failure.
2230 """
2231 try:
2232 if self.fpApiVer >= 5.0:
2233 oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
2234 else:
2235 oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
2236 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
2237 oProgress.wait(cMsTimeout);
2238 oProgress.logResult();
2239 except:
2240 reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
2241 if fFudgeOnFailure:
2242 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2243 self.waitForTask(1000); # fudge
2244 return False;
2245
2246 return True;
2247
2248 def takeSnapshot(self, sName, sDescription = '', fPause = True, fFudgeOnFailure = True, cMsTimeout = 30 * 1000):
2249 """
2250 Takes a snapshot with the given name
2251
2252 Returns True on success.
2253 Returns False on IMachine::takeSnapshot() or VM state change failure.
2254 """
2255 try:
2256 if fPause is True \
2257 and self.oVM.state is vboxcon.MachineState_Running:
2258 self.o.console.pause();
2259 if self.fpApiVer >= 5.0:
2260 (oProgressCom, _) = self.o.machine.takeSnapshot(sName, sDescription, True);
2261 else:
2262 oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
2263 oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
2264 oProgress.wait(cMsTimeout);
2265 oProgress.logResult();
2266 except:
2267 reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
2268 if fFudgeOnFailure:
2269 self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
2270 self.waitForTask(1000); # fudge
2271 return False;
2272
2273 if fPause is True \
2274 and self.oVM.state is vboxcon.MachineState_Paused:
2275 self.o.console.resume();
2276
2277 return True;
2278
2279 def findSnapshot(self, sName):
2280 """
2281 Returns the snapshot object with the given name
2282
2283 Returns snapshot object on success.
2284 Returns None if there is no snapshot with the given name.
2285 """
2286 return self.oVM.findSnapshot(sName);
2287
2288 def takeScreenshot(self, sFilename, iScreenId=0):
2289 """
2290 Take screenshot from the given display and save it to specified file.
2291
2292 Returns True on success
2293 Returns False on failure.
2294 """
2295 try:
2296 if self.fpApiVer >= 5.0:
2297 iWidth, iHeight, _, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2298 aPngData = self.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
2299 vboxcon.BitmapFormat_PNG)
2300 else:
2301 iWidth, iHeight, _, _, _ = self.o.console.display.getScreenResolution(iScreenId)
2302 aPngData = self.o.console.display.takeScreenShotPNGToArray(iScreenId, iWidth, iHeight)
2303 except:
2304 reporter.logXcpt("Unable to take screenshot")
2305 return False
2306
2307 oFile = open(sFilename, 'wb')
2308 oFile.write(aPngData)
2309 oFile.close()
2310
2311 return True
2312
2313 #
2314 # Other methods.
2315 #
2316
2317 def getPrimaryIp(self):
2318 """
2319 Tries to obtain the primary IP address of the guest via the guest
2320 properties.
2321
2322 Returns IP address on success.
2323 Returns empty string on failure.
2324 """
2325 sIpAddr = self.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2326 if vbox.isIpAddrValid(sIpAddr):
2327 return sIpAddr;
2328 return '';
2329
2330 def getPid(self):
2331 """
2332 Gets the process ID for the direct session unless it's ourselves.
2333 """
2334 if self.uPid is None and self.o is not None and self.fRemoteSession:
2335 try:
2336 if self.fpApiVer >= 4.2:
2337 uPid = self.o.machine.sessionPID;
2338 else:
2339 uPid = self.o.machine.sessionPid;
2340 if uPid != os.getpid() and uPid != 0xffffffff:
2341 self.uPid = uPid;
2342 except Exception, oXcpt:
2343 if vbox.ComError.equal(oXcpt, vbox.ComError.E_UNEXPECTED):
2344 try:
2345 if self.fpApiVer >= 4.2:
2346 uPid = self.oVM.sessionPID;
2347 else:
2348 uPid = self.oVM.sessionPid;
2349 if uPid != os.getpid() and uPid != 0xffffffff:
2350 self.uPid = uPid;
2351 except:
2352 reporter.log2Xcpt();
2353 else:
2354 reporter.log2Xcpt();
2355 if self.uPid is not None:
2356 reporter.log2('getPid: %u' % (self.uPid,));
2357 self.oTstDrv.pidFileAdd(self.uPid);
2358 return self.uPid;
2359
2360 def addLogsToReport(self, cReleaseLogs = 1):
2361 """
2362 Retrieves and adds the release and debug logs to the test report.
2363 """
2364 fRc = True;
2365
2366 # Add each of the requested release logs to the report.
2367 for iLog in range(0, cReleaseLogs):
2368 try:
2369 if self.fpApiVer >= 3.2:
2370 sLogFile = self.oVM.queryLogFilename(iLog);
2371 elif iLog > 0:
2372 sLogFile = '%s/VBox.log' % (self.oVM.logFolder,);
2373 else:
2374 sLogFile = '%s/VBox.log.%u' % (self.oVM.logFolder, iLog);
2375 except:
2376 reporter.logXcpt('iLog=%s' % (iLog,));
2377 fRc = False;
2378 else:
2379 if sLogFile is not None and sLogFile != '': # the None bit is for a 3.2.0 bug.
2380 reporter.addLogFile(sLogFile, 'log/release/vm', '%s #%u' % (self.sName, iLog),
2381 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2382
2383 # Now for the hardened windows startup log.
2384 try:
2385 sLogFile = os.path.join(self.oVM.logFolder, 'VBoxStartup.log');
2386 except:
2387 reporter.logXcpt();
2388 fRc = False;
2389 else:
2390 if os.path.isfile(sLogFile):
2391 reporter.addLogFile(sLogFile, 'log/release/vm', '%s startup log' % (self.sName, ),
2392 sAltName = '%s-%s' % (self.sName, os.path.basename(sLogFile),));
2393
2394 # Now for the debug log.
2395 if self.sLogFile is not None and os.path.isfile(self.sLogFile):
2396 reporter.addLogFile(self.sLogFile, 'log/debug/vm', '%s debug' % (self.sName, ),
2397 sAltName = '%s-%s' % (self.sName, os.path.basename(self.sLogFile),));
2398
2399 return fRc;
2400
2401 def registerDerivedEventHandler(self, oSubClass, dArgs = None, fMustSucceed = True):
2402 """
2403 Create an instance of the given ConsoleEventHandlerBase sub-class and
2404 register it.
2405
2406 The new instance is returned on success. None is returned on error.
2407 """
2408
2409 # We need a console object.
2410 try:
2411 oConsole = self.o.console;
2412 except Exception, oXcpt:
2413 if fMustSucceed or vbox.ComError.notEqual(oXcpt, vbox.ComError.E_UNEXPECTED):
2414 reporter.errorXcpt('Failed to get ISession::console for "%s"' % (self.sName, ));
2415 return None;
2416
2417 # Add the base class arguments.
2418 dArgsCopy = dArgs.copy() if dArgs is not None else dict();
2419 dArgsCopy['oSession'] = self;
2420 dArgsCopy['oConsole'] = oConsole;
2421 sLogSuffix = 'on %s' % (self.sName,)
2422 return oSubClass.registerDerivedEventHandler(self.oVBoxMgr, self.fpApiVer, oSubClass, dArgsCopy,
2423 oConsole, 'IConsole', 'IConsoleCallback',
2424 fMustSucceed = fMustSucceed, sLogSuffix = sLogSuffix);
2425
2426 def enableVmmDevTestingPart(self, fEnabled, fEnableMMIO = False):
2427 """
2428 Enables the testing part of the VMMDev.
2429
2430 Returns True on success and False on failure. Error information is logged.
2431 """
2432 fRc = True;
2433 try:
2434 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled',
2435 '1' if fEnabled else '');
2436 self.o.machine.setExtraData('VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO',
2437 '1' if fEnableMMIO and fEnabled else '');
2438 except:
2439 reporter.errorXcpt('VM name "%s", fEnabled=%s' % (self.sName, fEnabled));
2440 fRc = False;
2441 else:
2442 reporter.log('set VMMDevTesting=%s for "%s"' % (fEnabled, self.sName));
2443 self.oTstDrv.processPendingEvents();
2444 return fRc;
2445
2446 #
2447 # Test eXecution Service methods.
2448 #
2449
2450 def txsConnectViaTcp(self, cMsTimeout = 10*60000, sIpAddr = None, sMacAddr = None, fNatForwardingForTxs = False):
2451 """
2452 Connects to the TXS using TCP/IP as transport. If no IP or MAC is
2453 addresses are specified, we'll get the IP from the guest additions.
2454
2455 Returns a TxsConnectTask object on success, None + log on failure.
2456 """
2457 # If the VM is configured with a NAT interface, connect to local host.
2458 fReversedSetup = False;
2459 fUseNatForTxs = False;
2460 if sIpAddr == None:
2461 try:
2462 oNic = self.oVM.getNetworkAdapter(0);
2463 if oNic.attachmentType == vboxcon.NetworkAttachmentType_NAT:
2464 fUseNatForTxs = True;
2465 except:
2466 reporter.errorXcpt();
2467 return None;
2468 if fUseNatForTxs:
2469 fReversedSetup = not fNatForwardingForTxs;
2470 sIpAddr = '127.0.0.1';
2471
2472 # Kick off the task.
2473 try:
2474 oTask = TxsConnectTask(self, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup);
2475 except:
2476 reporter.errorXcpt();
2477 oTask = None;
2478 return oTask;
2479
2480 def txsTryConnectViaTcp(self, cMsTimeout, sHostname, fReversed = False):
2481 """
2482 Attempts to connect to a TXS instance.
2483
2484 Returns True if a connection was established, False if not (only grave
2485 failures are logged as errors).
2486
2487 Note! The timeout is more of a guideline...
2488 """
2489
2490 if sHostname is None or sHostname.strip() == '':
2491 raise base.GenError('Empty sHostname is not implemented yet');
2492
2493 oTxsSession = txsclient.tryOpenTcpSession(cMsTimeout, sHostname, fReversedSetup = fReversed,
2494 cMsIdleFudge = cMsTimeout / 2);
2495 if oTxsSession is None:
2496 return False;
2497
2498 # Wait for the connect task to time out.
2499 self.oTstDrv.addTask(oTxsSession);
2500 self.oTstDrv.processPendingEvents();
2501 oRc = self.oTstDrv.waitForTasks(cMsTimeout);
2502 self.oTstDrv.removeTask(oTxsSession);
2503 if oRc != oTxsSession:
2504 if oRc is not None:
2505 reporter.log('oRc=%s, expected %s' % (oRc, oTxsSession));
2506 self.oTstDrv.processPendingEvents();
2507 oTxsSession.cancelTask(); # this is synchronous
2508 return False;
2509
2510 # Check the status.
2511 reporter.log2('TxsSession is ready, isSuccess() -> %s.' % (oTxsSession.isSuccess(),));
2512 if not oTxsSession.isSuccess():
2513 return False;
2514
2515 reporter.log2('Disconnecting from TXS...');
2516 return oTxsSession.syncDisconnect();
2517
2518
2519
2520class TxsConnectTask(TdTaskBase):
2521 """
2522 Class that takes care of connecting to a VM.
2523 """
2524
2525 class TxsConnectTaskVBoxCallback(vbox.VirtualBoxEventHandlerBase):
2526 """ Class for looking for IPv4 address changes on interface 0."""
2527 def __init__(self, dArgs):
2528 vbox.VirtualBoxEventHandlerBase.__init__(self, dArgs); # pylint: disable=W0233
2529 self.oParentTask = dArgs['oParentTask'];
2530 self.sMachineId = dArgs['sMachineId'];
2531
2532 def onGuestPropertyChange(self, sMachineId, sName, sValue, sFlags):
2533 """Look for IP address."""
2534 reporter.log2('onGuestPropertyChange(,%s,%s,%s,%s)' % (sMachineId, sName, sValue, sFlags));
2535 if sMachineId == self.sMachineId \
2536 and sName == '/VirtualBox/GuestInfo/Net/0/V4/IP':
2537 self.oParentTask._setIp(sValue); # pylint: disable=W0212
2538
2539
2540 def __init__(self, oSession, cMsTimeout, sIpAddr, sMacAddr, fReversedSetup):
2541 TdTaskBase.__init__(self, utils.getCallerName());
2542 self.cMsTimeout = cMsTimeout;
2543 self.sIpAddr = None;
2544 self.sNextIpAddr = None;
2545 self.sMacAddr = sMacAddr;
2546 self.fReversedSetup = fReversedSetup;
2547 self.oVBox = oSession.oVBox;
2548 self.oVBoxEventHandler = None;
2549 self.oTxsSession = None;
2550 self.fpApiVer = oSession.fpApiVer;
2551
2552 # Skip things we don't implement.
2553 if sMacAddr is not None:
2554 reporter.error('TxsConnectTask does not implement sMacAddr yet');
2555 raise base.GenError();
2556
2557 reporter.log2('TxsConnectTask: sIpAddr=%s fReversedSetup=%s' % (sIpAddr, fReversedSetup))
2558 if fReversedSetup is True:
2559 self._openTcpSession(sIpAddr, fReversedSetup = True);
2560 elif sIpAddr is not None and sIpAddr.strip() != '':
2561 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2562 else:
2563 #
2564 # If we've got no IP address, register callbacks that listens for
2565 # the primary network adaptor of the VM to set a IPv4 guest prop.
2566 # Note! The order in which things are done here is kind of important.
2567 #
2568
2569 # 0. The caller zaps the property before starting the VM.
2570 #try:
2571 # oSession.delGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2572 #except:
2573 # reporter.logXcpt();
2574
2575 # 1. Register the callback / event listener object.
2576 dArgs = {'oParentTask':self, 'sMachineId':oSession.o.machine.id};
2577 self.oVBoxEventHandler = self.oVBox.registerDerivedEventHandler(self.TxsConnectTaskVBoxCallback, dArgs);
2578
2579 # 2. Query the guest properties.
2580 try:
2581 sIpAddr = oSession.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/0/V4/IP');
2582 except:
2583 reporter.errorXcpt('IMachine::getGuestPropertyValue("/VirtualBox/GuestInfo/Net/0/V4/IP") failed');
2584 self._deregisterEventHandler();
2585 raise;
2586 else:
2587 if sIpAddr is not None:
2588 self._setIp(sIpAddr);
2589 # end __init__
2590
2591 def __del__(self):
2592 """ Make sure we deregister the callback. """
2593 self._deregisterEventHandler();
2594 return TdTaskBase.__del__(self);
2595
2596 def toString(self):
2597 return '<%s cMsTimeout=%s, sIpAddr=%s, sNextIpAddr=%s, sMacAddr=%s, fReversedSetup=%s,' \
2598 ' oTxsSession=%s oVBoxEventHandler=%s, oVBox=%s>' \
2599 % (TdTaskBase.toString(self), self.cMsTimeout, self.sIpAddr, self.sNextIpAddr, self.sMacAddr, self.fReversedSetup,
2600 self.oTxsSession, self.oVBoxEventHandler, self.oVBox);
2601
2602 def _deregisterEventHandler(self):
2603 """Deregisters the event handler."""
2604 fRc = True;
2605 if self.oVBoxEventHandler is not None:
2606 fRc = self.oVBoxEventHandler.unregister();
2607 self.oVBoxEventHandler = None;
2608 return fRc;
2609
2610 def _setIp(self, sIpAddr, fInitCall = False):
2611 """Called when we get an IP. Will create a TXS session and signal the task."""
2612 sIpAddr = sIpAddr.strip();
2613
2614 if sIpAddr is not None \
2615 and sIpAddr != '':
2616 if vbox.isIpAddrValid(sIpAddr) or fInitCall:
2617 try:
2618 for s in sIpAddr.split('.'):
2619 i = int(s);
2620 if str(i) != s:
2621 raise Exception();
2622 except:
2623 reporter.fatalXcpt();
2624 else:
2625 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2626 return None;
2627
2628 reporter.log('TxsConnectTask: Ignoring Bad ip "%s"' % (sIpAddr));
2629 else:
2630 reporter.log2('TxsConnectTask: Ignoring empty ip "%s"' % (sIpAddr));
2631 return None;
2632
2633 def _openTcpSession(self, sIpAddr, uPort = None, fReversedSetup = False, cMsIdleFudge = 0):
2634 """
2635 Calls txsclient.openTcpSession and switches our task to reflect the
2636 state of the subtask.
2637 """
2638 self.oCv.acquire();
2639 if self.oTxsSession is None:
2640 reporter.log2('_openTcpSession: sIpAddr=%s, uPort=%d, fReversedSetup=%s' % \
2641 (sIpAddr, uPort if uPort is not None else 0, fReversedSetup));
2642 self.sIpAddr = sIpAddr;
2643 self.oTxsSession = txsclient.openTcpSession(self.cMsTimeout, sIpAddr, uPort, \
2644 fReversedSetup, cMsIdleFudge);
2645 self.oTxsSession.setTaskOwner(self);
2646 else:
2647 self.sNextIpAddr = sIpAddr;
2648 reporter.log2('_openTcpSession: sNextIpAddr=%s' % (sIpAddr,));
2649 self.oCv.release();
2650 return None;
2651
2652 def notifyAboutReadyTask(self, oTxsSession):
2653 """
2654 Called by the TXS session task when it's done.
2655
2656 We'll signal the task completed or retry depending on the result.
2657 """
2658
2659 self.oCv.acquire();
2660
2661 # Disassociate ourselves with the session (avoid cyclic ref)
2662 oTxsSession.setTaskOwner(None);
2663 fSuccess = oTxsSession.isSuccess();
2664 if self.oTxsSession is not None:
2665 if not fSuccess:
2666 self.oTxsSession = None;
2667 if fSuccess and self.fReversedSetup:
2668 self.sIpAddr = oTxsSession.oTransport.sHostname;
2669 else:
2670 fSuccess = False;
2671
2672 # Signal done, or retry?
2673 if fSuccess \
2674 or self.fReversedSetup \
2675 or self.getAgeAsMs() >= self.cMsTimeout:
2676 self.signalTaskLocked();
2677 else:
2678 sIpAddr = self.sNextIpAddr if self.sNextIpAddr is not None else self.sIpAddr;
2679 self._openTcpSession(sIpAddr, cMsIdleFudge = 5000);
2680
2681 self.oCv.release();
2682 return True;
2683
2684 #
2685 # Public methods
2686 #
2687
2688 def getResult(self):
2689 """
2690 Returns the connected TXS session object on success.
2691 Returns None on failure or if the task has not yet completed.
2692 """
2693 self.oCv.acquire();
2694 oTxsSession = self.oTxsSession;
2695 self.oCv.release();
2696
2697 if oTxsSession is not None and not oTxsSession.isSuccess():
2698 oTxsSession = None;
2699 return oTxsSession;
2700
2701 def cancelTask(self):
2702 """ Cancels the task. """
2703 self.oCv.acquire();
2704 if not self.fSignalled:
2705 oTxsSession = self.oTxsSession;
2706 if oTxsSession is not None:
2707 self.oCv.release();
2708 oTxsSession.setTaskOwner(None);
2709 oTxsSession.cancelTask();
2710 oTxsSession.waitForTask(1000);
2711 self.oCv.acquire();
2712 self.signalTaskLocked();
2713 self.oCv.release();
2714 return True;
2715
Note: See TracBrowser for help on using the repository browser.

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