Changeset 78831 in vbox for trunk/src/VBox/ValidationKit
- Timestamp:
- May 28, 2019 4:12:03 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/testdriver/vboxtestvms.py
r78824 r78831 87 87 # Table translating from VM name core to a more detailed guest info. 88 88 # pylint: disable=C0301 89 ## @todo what's the difference between the first two columns again? 89 90 g_aaNameToDetails = \ 90 91 [ … … 191 192 192 193 194 195 class BaseTestVm(object): 196 """ 197 Base class ofr Test VMs. 198 """ 199 200 def __init__(self, # pylint: disable=R0913 201 sVmName, # type: str 202 fGrouping = 0, # type: int 203 oSet = None, # type: TestVmSet 204 sKind = None, # type: str 205 acCpusSup = None, # type: List[int] 206 asVirtModesSup = None, # type: List[str] 207 asParavirtModesSup = None, # type: List[str] 208 fRandomPvPModeCrap = False, # type: bool 209 fVmmDevTestingPart = None, # type: bool 210 fVmmDevTestingMmio = False, # type: bool 211 ): 212 self.oSet = oSet; 213 self.sVmName = sVmName; 214 self.fGrouping = fGrouping; 215 self.sKind = sKind; # Guest OS type. 216 self.acCpusSup = acCpusSup; 217 self.asVirtModesSup = asVirtModesSup; 218 self.asParavirtModesSup = asParavirtModesSup; 219 self.asParavirtModesSupOrg = asParavirtModesSup; # HACK ALERT! Trick to make the 'effing random mess not get in the 220 # way of actively selecting virtualization modes. 221 222 self.fSkip = False; # All VMs are included in the configured set by default. 223 self.fSnapshotRestoreCurrent = False; # Whether to restore execution on the current snapshot. 224 225 self.fVmmDevTestingPart = fVmmDevTestingPart; 226 self.fVmmDevTestingMmio = fVmmDevTestingMmio; 227 self.fCom1RawFile = False; 228 self.sCom1RawFile = None; # Set by createVmInner and getReconfiguredVm if fCom1RawFile is set. 229 230 # Derived stuff: 231 self.aInfo = None; 232 self.sGuestOsType = None; # ksGuestOsTypeXxxx value, API GuestOS Type is in the sKind member. 233 self._guessStuff(fRandomPvPModeCrap); 234 235 def _mkCanonicalGuestOSType(self, sType): 236 """ 237 Convert guest OS type into constant representation. 238 Raise exception if specified @param sType is unknown. 239 """ 240 if sType.lower().startswith('darwin'): 241 return g_ksGuestOsTypeDarwin 242 if sType.lower().startswith('bsd'): 243 return g_ksGuestOsTypeFreeBSD 244 if sType.lower().startswith('dos'): 245 return g_ksGuestOsTypeDOS 246 if sType.lower().startswith('linux'): 247 return g_ksGuestOsTypeLinux 248 if sType.lower().startswith('os2'): 249 return g_ksGuestOsTypeOS2 250 if sType.lower().startswith('solaris'): 251 return g_ksGuestOsTypeSolaris 252 if sType.lower().startswith('windows'): 253 return g_ksGuestOsTypeWindows 254 raise base.GenError(sWhat="unknown guest OS kind: %s" % str(sType)) 255 256 def _guessStuff(self, fRandomPvPModeCrap): 257 """ 258 Used by the constructor to guess stuff. 259 """ 260 261 sNm = self.sVmName.lower().strip(); 262 asSplit = sNm.replace('-', ' ').split(' '); 263 264 if self.sKind is None: 265 # From name. 266 for aInfo in g_aaNameToDetails: 267 if _intersects(asSplit, aInfo[g_iRegEx]): 268 self.aInfo = aInfo; 269 self.sGuestOsType = self._mkCanonicalGuestOSType(aInfo[g_iGuestOsType]) 270 self.sKind = aInfo[g_iKind]; 271 break; 272 if self.sKind is None: 273 reporter.fatal('The OS of test VM "%s" cannot be guessed' % (self.sVmName,)); 274 275 # Check for 64-bit, if required and supported. 276 if (self.aInfo[g_iFlags] & g_kiArchMask) == g_k32_64 and _intersects(asSplit, ['64', 'amd64']): 277 self.sKind = self.sKind + '_64'; 278 else: 279 # Lookup the kind. 280 for aInfo in g_aaNameToDetails: 281 if self.sKind == aInfo[g_iKind]: 282 self.aInfo = aInfo; 283 break; 284 if self.aInfo is None: 285 reporter.fatal('The OS of test VM "%s" with sKind="%s" cannot be guessed' % (self.sVmName, self.sKind)); 286 287 # Translate sKind into sGuest OS Type. 288 if self.sGuestOsType is None: 289 if self.aInfo is not None: 290 self.sGuestOsType = self._mkCanonicalGuestOSType(self.aInfo[g_iGuestOsType]) 291 elif self.sKind.find("Windows") >= 0: 292 self.sGuestOsType = g_ksGuestOsTypeWindows 293 elif self.sKind.find("Linux") >= 0: 294 self.sGuestOsType = g_ksGuestOsTypeLinux; 295 elif self.sKind.find("Solaris") >= 0: 296 self.sGuestOsType = g_ksGuestOsTypeSolaris; 297 elif self.sKind.find("DOS") >= 0: 298 self.sGuestOsType = g_ksGuestOsTypeDOS; 299 else: 300 reporter.fatal('The OS of test VM "%s", sKind="%s" cannot be guessed' % (self.sVmName, self.sKind)); 301 302 # Restrict modes and such depending on the OS. 303 if self.asVirtModesSup is None: 304 self.asVirtModesSup = list(g_asVirtModes); 305 if self.sGuestOsType in (g_ksGuestOsTypeOS2, g_ksGuestOsTypeDarwin) \ 306 or self.sKind.find('_64') > 0 \ 307 or (self.aInfo is not None and (self.aInfo[g_iFlags] & g_kiNoRaw)): 308 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw']; 309 # TEMPORARY HACK - START 310 sHostName = os.environ.get("COMPUTERNAME", None); 311 if sHostName: sHostName = sHostName.lower(); 312 else: sHostName = socket.getfqdn(); # Horribly slow on windows without IPv6 DNS/whatever. 313 if sHostName.startswith('testboxpile1'): 314 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw']; 315 # TEMPORARY HACK - END 316 317 # Restrict the CPU count depending on the OS and/or percieved SMP readiness. 318 if self.acCpusSup is None: 319 if _intersects(asSplit, ['uni']): 320 self.acCpusSup = [1]; 321 elif self.aInfo is not None: 322 self.acCpusSup = [i for i in range(self.aInfo[g_iMinCpu], self.aInfo[g_iMaxCpu]) ]; 323 else: 324 self.acCpusSup = [1]; 325 326 # Figure relevant PV modes based on the OS. 327 if self.asParavirtModesSup is None: 328 self.asParavirtModesSup = g_kdaParavirtProvidersSupported[self.sGuestOsType]; 329 ## @todo Remove this hack as soon as we've got around to explictly configure test variations 330 ## on the server side. Client side random is interesting but not the best option. 331 self.asParavirtModesSupOrg = self.asParavirtModesSup; 332 if fRandomPvPModeCrap: 333 random.seed(); 334 self.asParavirtModesSup = (random.choice(self.asParavirtModesSup),); 335 336 return True; 337 338 def _generateRawPortFilename(self, oTestDrv, sInfix, sSuffix): 339 """ Generates a raw port filename. """ 340 random.seed(); 341 sRandom = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10)); 342 return os.path.join(oTestDrv.sScratchPath, self.sVmName + sInfix + sRandom + sSuffix); 343 344 def _createVmTail(self, oTestDrv, eNic0AttachType, sDvdImage): 345 """ 346 Returns same as vbox.TestDriver.createTestVM. 347 """ 348 _ = oTestDrv; _ = eNic0AttachType; _ = sDvdImage; 349 return reporter.error('Base class _createVmTail must not be called!'); 350 351 def _childVmReconfig(self, oTestDrv, oVM, oSession): 352 """ 353 Hook into getReconfiguredVm() for children. 354 """ 355 _ = oTestDrv; _ = oVM; _ = oSession; 356 return True; 357 358 359 # 360 # Public interface. 361 # 362 363 def getMissingResources(self, sTestRsrc): 364 """ 365 Returns a list of missing resources (paths, stuff) that the VM needs. 366 """ 367 _ = sTestRsrc; 368 return []; 369 370 def createVm(self, oTestDrv, eNic0AttachType = None, sDvdImage = None): 371 """ 372 Creates the VM with defaults and the few tweaks as per the arguments. 373 374 Returns same as vbox.TestDriver.createTestVM. 375 """ 376 reporter.log2(''); 377 reporter.log2('Creating %s...' % (self.sVmName,)) 378 379 if self.fCom1RawFile: 380 self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out'); 381 382 return self._createVmTail(oTestDrv, eNic0AttachType, sDvdImage); 383 384 def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None): 385 """ 386 actionExecute worker that finds and reconfigure a test VM. 387 388 Returns (fRc, oVM) where fRc is True, None or False and oVM is a 389 VBox VM object that is only present when rc is True. 390 """ 391 392 fRc = False; 393 oVM = oTestDrv.getVmByName(self.sVmName); 394 if oVM is not None: 395 if self.fSnapshotRestoreCurrent is True: 396 fRc = True; 397 else: 398 fHostSupports64bit = oTestDrv.hasHostLongMode(); 399 if self.is64bitRequired() and not fHostSupports64bit: 400 fRc = None; # Skip the test. 401 elif self.isViaIncompatible() and oTestDrv.isHostCpuVia(): 402 fRc = None; # Skip the test. 403 elif self.isShanghaiIncompatible() and oTestDrv.isHostCpuShanghai(): 404 fRc = None; # Skip the test. 405 elif self.isP4Incompatible() and oTestDrv.isHostCpuP4(): 406 fRc = None; # Skip the test. 407 else: 408 oSession = oTestDrv.openSession(oVM); 409 if oSession is not None: 410 fRc = oSession.enableVirtEx(sVirtMode != 'raw'); 411 fRc = fRc and oSession.enableNestedPaging(sVirtMode == 'hwvirt-np'); 412 fRc = fRc and oSession.setCpuCount(cCpus); 413 if cCpus > 1: 414 fRc = fRc and oSession.enableIoApic(True); 415 416 if sParavirtMode is not None and oSession.fpApiVer >= 5.0: 417 adParavirtProviders = { 418 g_ksParavirtProviderNone : vboxcon.ParavirtProvider_None, 419 g_ksParavirtProviderDefault: vboxcon.ParavirtProvider_Default, 420 g_ksParavirtProviderLegacy : vboxcon.ParavirtProvider_Legacy, 421 g_ksParavirtProviderMinimal: vboxcon.ParavirtProvider_Minimal, 422 g_ksParavirtProviderHyperV : vboxcon.ParavirtProvider_HyperV, 423 g_ksParavirtProviderKVM : vboxcon.ParavirtProvider_KVM, 424 }; 425 fRc = fRc and oSession.setParavirtProvider(adParavirtProviders[sParavirtMode]); 426 427 fCfg64Bit = self.is64bitRequired() or (self.is64bit() and fHostSupports64bit and sVirtMode != 'raw'); 428 fRc = fRc and oSession.enableLongMode(fCfg64Bit); 429 if fCfg64Bit: # This is to avoid GUI pedantic warnings in the GUI. Sigh. 430 oOsType = oSession.getOsType(); 431 if oOsType is not None: 432 if oOsType.is64Bit and sVirtMode == 'raw': 433 assert(oOsType.id[-3:] == '_64'); 434 fRc = fRc and oSession.setOsType(oOsType.id[:-3]); 435 elif not oOsType.is64Bit and sVirtMode != 'raw': 436 fRc = fRc and oSession.setOsType(oOsType.id + '_64'); 437 438 # New serial raw file. 439 if fRc and self.fCom1RawFile: 440 self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out'); 441 utils.noxcptDeleteFile(self.sCom1RawFile); 442 fRc = oSession.setupSerialToRawFile(0, self.sCom1RawFile); 443 444 # Make life simpler for child classes. 445 if fRc: 446 fRc = self._childVmReconfig(oTestDrv, oVM, oSession); 447 448 fRc = fRc and oSession.saveSettings(); 449 if not oSession.close(): 450 fRc = False; 451 if fRc is True: 452 return (True, oVM); 453 return (fRc, None); 454 455 def getNonCanonicalGuestOsType(self): 456 """ 457 Gets the non-canonical OS type (self.sGuestOsType is canonical). 458 """ 459 return self.sKind; #self.aInfo[g_iGuestOsType]; 460 461 def isWindows(self): 462 """ Checks if it's a Windows VM. """ 463 return self.sGuestOsType == g_ksGuestOsTypeWindows; 464 465 def isOS2(self): 466 """ Checks if it's an OS/2 VM. """ 467 return self.sGuestOsType == g_ksGuestOsTypeOS2; 468 469 def isLinux(self): 470 """ Checks if it's an Linux VM. """ 471 return self.sGuestOsType == g_ksGuestOsTypeLinux; 472 473 def is64bit(self): 474 """ Checks if it's a 64-bit VM. """ 475 return self.sKind.find('_64') >= 0; 476 477 def is64bitRequired(self): 478 """ Check if 64-bit is required or not. """ 479 return (self.aInfo[g_iFlags] & g_k64) != 0; 480 481 def isLoggedOntoDesktop(self): 482 """ Checks if the test VM is logging onto a graphical desktop by default. """ 483 if self.isWindows(): 484 return True; 485 if self.isOS2(): 486 return True; 487 if self.sVmName.find('-desktop'): 488 return True; 489 return False; 490 491 def isViaIncompatible(self): 492 """ 493 Identifies VMs that doesn't work on VIA. 494 495 Returns True if NOT supported on VIA, False if it IS supported. 496 """ 497 # Oracle linux doesn't like VIA in our experience 498 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']: 499 return True; 500 # OS/2: "The system detected an internal processing error at location 501 # 0168:fff1da1f - 000e:ca1f. 0a8606fd 502 if self.isOS2(): 503 return True; 504 # Windows NT4 before SP4 won't work because of cmpxchg8b not being 505 # detected, leading to a STOP 3e(80,0,0,0). 506 if self.aInfo[g_iKind] == 'WindowsNT4': 507 if self.sVmName.find('sp') < 0: 508 return True; # no service pack. 509 if self.sVmName.find('sp0') >= 0 \ 510 or self.sVmName.find('sp1') >= 0 \ 511 or self.sVmName.find('sp2') >= 0 \ 512 or self.sVmName.find('sp3') >= 0: 513 return True; 514 # XP x64 on a physical VIA box hangs exactly like a VM. 515 if self.aInfo[g_iKind] in ['WindowsXP_64', 'Windows2003_64']: 516 return True; 517 # Vista 64 throws BSOD 0x5D (UNSUPPORTED_PROCESSOR) 518 if self.aInfo[g_iKind] in ['WindowsVista_64']: 519 return True; 520 # Solaris 11 hangs on VIA, tested on a physical box (testboxvqc) 521 if self.aInfo[g_iKind] in ['Solaris11_64']: 522 return True; 523 return False; 524 525 def isShanghaiIncompatible(self): 526 """ 527 Identifies VMs that doesn't work on Shanghai. 528 529 Returns True if NOT supported on Shanghai, False if it IS supported. 530 """ 531 # For now treat it just like VIA, to be adjusted later 532 return self.isViaIncompatible() 533 534 def isP4Incompatible(self): 535 """ 536 Identifies VMs that doesn't work on Pentium 4 / Pentium D. 537 538 Returns True if NOT supported on P4, False if it IS supported. 539 """ 540 # Stupid 1 kHz timer. Too much for antique CPUs. 541 if self.sVmName.find('rhel5') >= 0: 542 return True; 543 # Due to the boot animation the VM takes forever to boot. 544 if self.aInfo[g_iKind] == 'Windows2000': 545 return True; 546 return False; 547 548 def isHostCpuAffectedByUbuntuNewAmdBug(self, oTestDrv): 549 """ 550 Checks if the host OS is affected by older ubuntu installers being very 551 picky about which families of AMD CPUs it would run on. 552 553 The installer checks for family 15, later 16, later 20, and in 11.10 554 they remove the family check for AMD CPUs. 555 """ 556 if not oTestDrv.isHostCpuAmd(): 557 return False; 558 try: 559 (uMaxExt, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000000, 0); 560 (uFamilyModel, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000001, 0); 561 except: 562 reporter.logXcpt(); 563 return False; 564 if uMaxExt < 0x80000001 or uMaxExt > 0x8000ffff: 565 return False; 566 567 uFamily = (uFamilyModel >> 8) & 0xf 568 if uFamily == 0xf: 569 uFamily = ((uFamilyModel >> 20) & 0x7f) + 0xf; 570 ## @todo Break this down into which old ubuntu release supports exactly 571 ## which AMD family, if we care. 572 if uFamily <= 15: 573 return False; 574 reporter.log('Skipping "%s" because host CPU is a family %u AMD, which may cause trouble for the guest OS installer.' 575 % (self.sVmName, uFamily,)); 576 return True; 577 578 579 ## @todo Inherit from BaseTestVm 193 580 class TestVm(object): 194 581 """
Note:
See TracChangeset
for help on using the changeset viewer.