diff options
Diffstat (limited to '')
-rwxr-xr-x | src/VBox/ValidationKit/tests/installation/tdGuestOsUnattendedInst1.py | 769 |
1 files changed, 769 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/tests/installation/tdGuestOsUnattendedInst1.py b/src/VBox/ValidationKit/tests/installation/tdGuestOsUnattendedInst1.py new file mode 100755 index 00000000..cdc2ef59 --- /dev/null +++ b/src/VBox/ValidationKit/tests/installation/tdGuestOsUnattendedInst1.py @@ -0,0 +1,769 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# $Id: tdGuestOsUnattendedInst1.py $ + +""" +VirtualBox Validation Kit - Guest OS unattended installation tests. +""" + +__copyright__ = \ +""" +Copyright (C) 2010-2023 Oracle and/or its affiliates. + +This file is part of VirtualBox base platform packages, as +available from https://www.virtualbox.org. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, in version 3 of the +License. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, see <https://www.gnu.org/licenses>. + +The contents of this file may alternatively be used under the terms +of the Common Development and Distribution License Version 1.0 +(CDDL), a copy of it is provided in the "COPYING.CDDL" file included +in the VirtualBox distribution, in which case the provisions of the +CDDL are applicable instead of those of the GPL. + +You may elect to license modified versions of this file under the +terms and conditions of either the GPL or the CDDL or both. + +SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +""" +__version__ = "$Revision: 155244 $" + + +# Standard Python imports. +import copy; +import os; +import sys; + + +# Only the main script needs to modify the path. +try: __file__ +except: __file__ = sys.argv[0] +g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +sys.path.append(g_ksValidationKitDir) + +# Validation Kit imports. +from testdriver import vbox; +from testdriver import base; +from testdriver import reporter; +from testdriver import vboxcon; +from testdriver import vboxtestvms; +from common import utils; + +# Sub-test driver imports. +sys.path.append(os.path.join(g_ksValidationKitDir, 'tests', 'additions')); +from tdAddGuestCtrl import SubTstDrvAddGuestCtrl; +from tdAddSharedFolders1 import SubTstDrvAddSharedFolders1; + + +class UnattendedVm(vboxtestvms.BaseTestVm): + """ Unattended Installation test VM. """ + + ## @name VM option flags (OR together). + ## @{ + kfUbuntuAvx2Crash = 0x0001; ##< Disables AVX2 as ubuntu 16.04 think it means AVX512 is available and compiz crashes. + kfNoGAs = 0x0002; ##< No guest additions installation possible. + kfKeyFile = 0x0004; ##< ISO requires a .key file containing the product key. + kfNeedCom1 = 0x0008; ##< Need serial port, typically for satifying the windows kernel debugger. + + kfIdeIrqDelay = 0x1000; + kfUbuntuNewAmdBug = 0x2000; + kfNoWin81Paravirt = 0x4000; + kfAvoidNetwork = 0x8000; + ## @} + + ## kfUbuntuAvx2Crash: Extra data that disables AVX2. + kasUbuntuAvx2Crash = [ '/CPUM/IsaExts/AVX2:0', ]; + + ## IRQ delay extra data config for win2k VMs. + kasIdeIrqDelay = [ 'VBoxInternal/Devices/piix3ide/0/Config/IRQDelay:1', ]; + + def __init__(self, oSet, sVmName, sKind, sInstallIso, fFlags = 0): + vboxtestvms.BaseTestVm.__init__(self, sVmName, oSet = oSet, sKind = sKind, + fRandomPvPModeCrap = (fFlags & self.kfNoWin81Paravirt) == 0); + self.sInstallIso = sInstallIso; + self.fInstVmFlags = fFlags; + + # Adjustments over the defaults. + self.iOptRamAdjust = 0; + self.fOptIoApic = None; + self.fOptPae = None; + self.fOptInstallAdditions = False; + self.asOptExtraData = []; + if fFlags & self.kfUbuntuAvx2Crash: + self.asOptExtraData += self.kasUbuntuAvx2Crash; + if fFlags & self.kfIdeIrqDelay: + self.asOptExtraData += self.kasIdeIrqDelay; + if fFlags & self.kfNeedCom1: + self.fCom1RawFile = True; + + def _unattendedConfigure(self, oIUnattended, oTestDrv): # type: (Any, vbox.TestDriver) -> bool + """ + Configures the unattended install object. + + The ISO attribute has been set and detectIsoOS has been done, the rest of the + setup is done here. + + Returns True on success, False w/ errors logged on failure. + """ + + # + # Make it install the TXS. + # + try: oIUnattended.installTestExecService = True; + except: return reporter.errorXcpt(); + try: oIUnattended.validationKitIsoPath = oTestDrv.sVBoxValidationKitIso; + except: return reporter.errorXcpt(); + oTestDrv.processPendingEvents(); + + # + # Avoid using network during unattended install (stalls Debian installs). + # + if self.fInstVmFlags & UnattendedVm.kfAvoidNetwork: + try: oIUnattended.avoidUpdatesOverNetwork = True; + except: return reporter.errorXcpt(); + + # + # Install GAs? + # + if self.fOptInstallAdditions: + if (self.fInstVmFlags & self.kfNoGAs) == 0: + try: oIUnattended.installGuestAdditions = True; + except: return reporter.errorXcpt(); + try: oIUnattended.additionsIsoPath = oTestDrv.getGuestAdditionsIso(); + except: return reporter.errorXcpt(); + oTestDrv.processPendingEvents(); + else: + reporter.log("Warning! Ignoring request to install Guest Additions as kfNoGAs is set!"); + + # + # Product key? + # + if self.fInstVmFlags & UnattendedVm.kfKeyFile: + sKeyFile = ''; + sKey = ''; + try: + sKeyFile = oIUnattended.isoPath + '.key'; + oFile = utils.openNoInherit(sKeyFile); + for sLine in oFile: + sLine = sLine.strip(); + if sLine and not sLine.startswith(';') and not sLine.startswith('#') and not sLine.startswith('//'): + sKey = sLine; + break; + oFile.close(); + except: + return reporter.errorXcpt('sKeyFile=%s' % (sKeyFile,)); + if not sKey: + return reporter.error('No key in keyfile (%s)!' % (sKeyFile,)); + try: oIUnattended.productKey = sKey; + except: return reporter.errorXcpt(); + + return True; + + def _unattendedDoIt(self, oIUnattended, oVM, oTestDrv): # type: (Any, Any, vbox.TestDriver) -> bool + """ + Does the unattended installation preparing, media construction and VM reconfiguration. + + Returns True on success, False w/ errors logged on failure. + """ + + # Associate oVM with the installer: + try: + oIUnattended.machine = oVM; + except: + return reporter.errorXcpt(); + oTestDrv.processPendingEvents(); + + # Prepare and log it: + try: + oIUnattended.prepare(); + except: + return reporter.errorXcpt("IUnattended.prepare failed"); + oTestDrv.processPendingEvents(); + + reporter.log('IUnattended attributes after prepare():'); + self._unattendedLogIt(oIUnattended, oTestDrv); + + # Create media: + try: + oIUnattended.constructMedia(); + except: + return reporter.errorXcpt("IUnattended.constructMedia failed"); + oTestDrv.processPendingEvents(); + + # Reconfigure the VM: + try: + oIUnattended.reconfigureVM(); + except: + return reporter.errorXcpt("IUnattended.reconfigureVM failed"); + oTestDrv.processPendingEvents(); + + return True; + + def _unattendedLogIt(self, oIUnattended, oTestDrv): + """ + Logs the attributes of the unattended installation object. + """ + fRc = True; + asAttribs = ( 'isoPath', 'user', 'password', 'fullUserName', 'productKey', 'additionsIsoPath', 'installGuestAdditions', + 'validationKitIsoPath', 'installTestExecService', 'timeZone', 'locale', 'language', 'country', 'proxy', + 'packageSelectionAdjustments', 'hostname', 'auxiliaryBasePath', 'imageIndex', 'machine', + 'scriptTemplatePath', 'postInstallScriptTemplatePath', 'postInstallCommand', + 'extraInstallKernelParameters', 'detectedOSTypeId', 'detectedOSVersion', 'detectedOSLanguages', + 'detectedOSFlavor', 'detectedOSHints', ); + for sAttrib in asAttribs: + try: + oValue = getattr(oIUnattended, sAttrib); + except: + fRc = reporter.errorXcpt('sAttrib=%s' % sAttrib); + else: + reporter.log('%s: %s' % (sAttrib.rjust(32), oValue,)); + oTestDrv.processPendingEvents(); + return fRc; + + + # + # Overriden methods. + # + + def getResourceSet(self): + asRet = []; + if not os.path.isabs(self.sInstallIso): + asRet.append(self.sInstallIso); + if self.fInstVmFlags & UnattendedVm.kfKeyFile: + asRet.append(self.sInstallIso + '.key'); + return asRet; + + def _createVmDoIt(self, oTestDrv, eNic0AttachType, sDvdImage): + # + # Use HostOnly networking for ubuntu and debian VMs to prevent them from + # downloading updates and doing database updates during installation. + # We want predicable results. + # + if eNic0AttachType is None: + if self.isLinux() \ + and ( 'ubuntu' in self.sKind.lower() + or 'debian' in self.sKind.lower()): + eNic0AttachType = vboxcon.NetworkAttachmentType_HostOnly; + + # Also use it for windows xp to prevent it from ever going online. + if self.sKind in ('WindowsXP','WindowsXP_64',): + eNic0AttachType = vboxcon.NetworkAttachmentType_HostOnly; + + # + # Use host-only networks instead of host-only adapters for trunk builds on Mac OS. + # + if eNic0AttachType == vboxcon.NetworkAttachmentType_HostOnly \ + and utils.getHostOs() == 'darwin' \ + and oTestDrv.fpApiVer >= 7.0: + eNic0AttachType = vboxcon.NetworkAttachmentType_HostOnlyNetwork; + + return vboxtestvms.BaseTestVm._createVmDoIt(self, oTestDrv, eNic0AttachType, sDvdImage); # pylint: disable=protected-access + + + def _createVmPost(self, oTestDrv, oVM, eNic0AttachType, sDvdImage): + # + # Adjust the ram, I/O APIC and stuff. + # + oSession = oTestDrv.openSession(oVM); + if oSession is None: + return None; + + fRc = True; + + ## Set proper boot order - IUnattended::reconfigureVM does this, doesn't it? + #fRc = fRc and oSession.setBootOrder(1, vboxcon.DeviceType_HardDisk) + #fRc = fRc and oSession.setBootOrder(2, vboxcon.DeviceType_DVD) + + # Adjust memory if requested. + if self.iOptRamAdjust != 0: + try: cMbRam = oSession.o.machine.memorySize; + except: fRc = reporter.errorXcpt(); + else: + fRc = oSession.setRamSize(cMbRam + self.iOptRamAdjust) and fRc; + + # I/O APIC: + if self.fOptIoApic is not None: + fRc = oSession.enableIoApic(self.fOptIoApic) and fRc; + + # I/O APIC: + if self.fOptPae is not None: + fRc = oSession.enablePae(self.fOptPae) and fRc; + + # Set extra data + for sExtraData in self.asOptExtraData: + sKey, sValue = sExtraData.split(':'); + reporter.log('Set extradata: %s => %s' % (sKey, sValue)) + fRc = oSession.setExtraData(sKey, sValue) and fRc; + + # Save the settings. + fRc = fRc and oSession.saveSettings() + fRc = oSession.close() and fRc; + + return oVM if fRc else None; + + def _skipVmTest(self, oTestDrv, oVM): + _ = oVM; + # + # Check for ubuntu installer vs. AMD host CPU. + # + if self.fInstVmFlags & self.kfUbuntuNewAmdBug: + if self.isHostCpuAffectedByUbuntuNewAmdBug(oTestDrv): + return True; + + return vboxtestvms.BaseTestVm._skipVmTest(self, oTestDrv, oVM); # pylint: disable=protected-access + + + def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None): + # + # Do the standard reconfig in the base class first, it'll figure out + # if we can run the VM as requested. + # + (fRc, oVM) = vboxtestvms.BaseTestVm.getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode); + if fRc is True: + # + # Make sure there is no HD from the previous run attached nor taking + # up storage on the host. + # + fRc = self.recreateRecommendedHdd(oVM, oTestDrv); + if fRc is True: + # + # Set up unattended installation. + # + try: + oIUnattended = oTestDrv.oVBox.createUnattendedInstaller(); + except: + fRc = reporter.errorXcpt(); + if fRc is True: + fRc = self.unattendedDetectOs(oIUnattended, oTestDrv); + if fRc is True: + fRc = self._unattendedConfigure(oIUnattended, oTestDrv); + if fRc is True: + fRc = self._unattendedDoIt(oIUnattended, oVM, oTestDrv); + + # Done. + return (fRc, oVM) + + def isLoggedOntoDesktop(self): + # + # Normally all unattended installations should end up on the desktop. + # An exception is a minimal install, but we currently don't support that. + # + return True; + + def getTestUser(self): + # Default unattended installation user (parent knowns its password). + return 'vboxuser'; + + + # + # Our methods. + # + + def unattendedDetectOs(self, oIUnattended, oTestDrv): # type: (Any, vbox.TestDriver) -> bool + """ + Does the detectIsoOS operation and checks that the detect OSTypeId matches. + + Returns True on success, False w/ errors logged on failure. + """ + + # + # Point the installer at the ISO and do the detection. + # + sInstallIso = self.sInstallIso + if not os.path.isabs(sInstallIso): + sInstallIso = os.path.join(oTestDrv.sResourcePath, sInstallIso); + + try: + oIUnattended.isoPath = sInstallIso; + except: + return reporter.errorXcpt('sInstallIso=%s' % (sInstallIso,)); + + try: + oIUnattended.detectIsoOS(); + except: + if oTestDrv.oVBoxMgr.xcptIsNotEqual(None, oTestDrv.oVBoxMgr.statuses.E_NOTIMPL): + return reporter.errorXcpt('sInstallIso=%s' % (sInstallIso,)); + + # + # Get and log the result. + # + # Note! Current (6.0.97) fails with E_NOTIMPL even if it does some work. + # + try: + sDetectedOSTypeId = oIUnattended.detectedOSTypeId; + sDetectedOSVersion = oIUnattended.detectedOSVersion; + sDetectedOSFlavor = oIUnattended.detectedOSFlavor; + sDetectedOSLanguages = oIUnattended.detectedOSLanguages; + sDetectedOSHints = oIUnattended.detectedOSHints; + except: + return reporter.errorXcpt('sInstallIso=%s' % (sInstallIso,)); + + reporter.log('detectIsoOS result for "%s" (vm %s):' % (sInstallIso, self.sVmName)); + reporter.log(' DetectedOSTypeId: %s' % (sDetectedOSTypeId,)); + reporter.log(' DetectedOSVersion: %s' % (sDetectedOSVersion,)); + reporter.log(' DetectedOSFlavor: %s' % (sDetectedOSFlavor,)); + reporter.log(' DetectedOSLanguages: %s' % (sDetectedOSLanguages,)); + reporter.log(' DetectedOSHints: %s' % (sDetectedOSHints,)); + + # + # Check if the OS type matches. + # + if self.sKind != sDetectedOSTypeId: + return reporter.error('sInstallIso=%s: DetectedOSTypeId is %s, expected %s' + % (sInstallIso, sDetectedOSTypeId, self.sKind)); + + return True; + + +class tdGuestOsInstTest1(vbox.TestDriver): + """ + Unattended Guest OS installation tests using IUnattended. + + Scenario: + - Create a new VM with default settings using IMachine::applyDefaults. + - Setup unattended installation using IUnattended. + - Start the VM and do the installation. + - Wait for TXS to report for service. + - If installing GAs: + - Wait for GAs to report operational runlevel. + - Save & restore state. + - If installing GAs: + - Test guest properties (todo). + - Test guest controls. + - Test shared folders. + """ + + + def __init__(self): + """ + Reinitialize child class instance. + """ + vbox.TestDriver.__init__(self) + self.fLegacyOptions = False; + assert self.fEnableVrdp; # in parent driver. + + # + # Our install test VM set. + # + oSet = vboxtestvms.TestVmSet(self.oTestVmManager, fIgnoreSkippedVm = True); + # pylint: disable=line-too-long + oSet.aoTestVms.extend([ + # + # Windows. The older windows ISOs requires a keyfile (for xp sp3 + # pick a key from the PID.INF file on the ISO). + # + UnattendedVm(oSet, 'tst-xp-32', 'WindowsXP', '6.0/uaisos/en_winxp_pro_x86_build2600_iso.img', UnattendedVm.kfKeyFile), # >=2GiB + UnattendedVm(oSet, 'tst-xpsp2-32', 'WindowsXP', '6.0/uaisos/en_winxp_pro_with_sp2.iso', UnattendedVm.kfKeyFile), # >=2GiB + UnattendedVm(oSet, 'tst-xpsp3-32', 'WindowsXP', '6.0/uaisos/en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428.iso', UnattendedVm.kfKeyFile), # >=2GiB + UnattendedVm(oSet, 'tst-xp-64', 'WindowsXP_64', '6.0/uaisos/en_win_xp_pro_x64_vl.iso', UnattendedVm.kfKeyFile), # >=3GiB + UnattendedVm(oSet, 'tst-xpsp2-64', 'WindowsXP_64', '6.0/uaisos/en_win_xp_pro_x64_with_sp2_vl_x13-41611.iso', UnattendedVm.kfKeyFile), # >=3GiB + #fixme: UnattendedVm(oSet, 'tst-xpchk-64', 'WindowsXP_64', '6.0/uaisos/en_windows_xp_professional_x64_chk.iso', UnattendedVm.kfKeyFile | UnattendedVm.kfNeedCom1), # >=3GiB + # No key files needed: + UnattendedVm(oSet, 'tst-vista-32', 'WindowsVista', '6.0/uaisos/en_windows_vista_ee_x86_dvd_vl_x13-17271.iso'), # >=6GiB + UnattendedVm(oSet, 'tst-vista-64', 'WindowsVista_64', '6.0/uaisos/en_windows_vista_enterprise_x64_dvd_vl_x13-17316.iso'), # >=8GiB + UnattendedVm(oSet, 'tst-vistasp1-32', 'WindowsVista', '6.0/uaisos/en_windows_vista_enterprise_with_service_pack_1_x86_dvd_x14-55954.iso'), # >=6GiB + UnattendedVm(oSet, 'tst-vistasp1-64', 'WindowsVista_64', '6.0/uaisos/en_windows_vista_enterprise_with_service_pack_1_x64_dvd_x14-55934.iso'), # >=9GiB + UnattendedVm(oSet, 'tst-vistasp2-32', 'WindowsVista', '6.0/uaisos/en_windows_vista_enterprise_sp2_x86_dvd_342329.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-vistasp2-64', 'WindowsVista_64', '6.0/uaisos/en_windows_vista_enterprise_sp2_x64_dvd_342332.iso'), # >=10GiB + UnattendedVm(oSet, 'tst-w7-32', 'Windows7', '6.0/uaisos/en_windows_7_enterprise_x86_dvd_x15-70745.iso'), # >=6GiB + UnattendedVm(oSet, 'tst-w7-64', 'Windows7_64', '6.0/uaisos/en_windows_7_enterprise_x64_dvd_x15-70749.iso'), # >=10GiB + UnattendedVm(oSet, 'tst-w7sp1-32', 'Windows7', '6.0/uaisos/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso'), # >=6GiB + UnattendedVm(oSet, 'tst-w7sp1-64', 'Windows7_64', '6.0/uaisos/en_windows_7_enterprise_with_sp1_x64_dvd_u_677651.iso'), # >=8GiB + UnattendedVm(oSet, 'tst-w8-32', 'Windows8', '6.0/uaisos/en_windows_8_enterprise_x86_dvd_917587.iso'), # >=6GiB + UnattendedVm(oSet, 'tst-w8-64', 'Windows8_64', '6.0/uaisos/en_windows_8_enterprise_x64_dvd_917522.iso'), # >=9GiB + UnattendedVm(oSet, 'tst-w81-32', 'Windows81', '6.0/uaisos/en_windows_8_1_enterprise_x86_dvd_2791510.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-w81-64', 'Windows81_64', '6.0/uaisos/en_windows_8_1_enterprise_x64_dvd_2791088.iso'), # >=8GiB + UnattendedVm(oSet, 'tst-w10-1507-32', 'Windows10', '6.0/uaisos/en_windows_10_pro_10240_x86_dvd.iso'), # >=6GiB + UnattendedVm(oSet, 'tst-w10-1507-64', 'Windows10_64', '6.0/uaisos/en_windows_10_pro_10240_x64_dvd.iso'), # >=9GiB + UnattendedVm(oSet, 'tst-w10-1511-32', 'Windows10', '6.0/uaisos/en_windows_10_enterprise_version_1511_updated_feb_2016_x86_dvd_8378870.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-w10-1511-64', 'Windows10_64', '6.0/uaisos/en_windows_10_enterprise_version_1511_x64_dvd_7224901.iso'), # >=9GiB + UnattendedVm(oSet, 'tst-w10-1607-32', 'Windows10', '6.0/uaisos/en_windows_10_enterprise_version_1607_updated_jul_2016_x86_dvd_9060097.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-w10-1607-64', 'Windows10_64', '6.0/uaisos/en_windows_10_enterprise_version_1607_updated_jul_2016_x64_dvd_9054264.iso'), # >=9GiB + UnattendedVm(oSet, 'tst-w10-1703-32', 'Windows10', '6.0/uaisos/en_windows_10_enterprise_version_1703_updated_march_2017_x86_dvd_10188981.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-w10-1703-64', 'Windows10_64', '6.0/uaisos/en_windows_10_enterprise_version_1703_updated_march_2017_x64_dvd_10189290.iso'), # >=10GiB + UnattendedVm(oSet, 'tst-w10-1709-32', 'Windows10', '6.0/uaisos/en_windows_10_multi-edition_vl_version_1709_updated_sept_2017_x86_dvd_100090759.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-w10-1709-64', 'Windows10_64', '6.0/uaisos/en_windows_10_multi-edition_vl_version_1709_updated_sept_2017_x64_dvd_100090741.iso'), # >=10GiB + UnattendedVm(oSet, 'tst-w10-1803-32', 'Windows10', '6.0/uaisos/en_windows_10_business_editions_version_1803_updated_march_2018_x86_dvd_12063341.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-w10-1803-64', 'Windows10_64', '6.0/uaisos/en_windows_10_business_editions_version_1803_updated_march_2018_x64_dvd_12063333.iso'), # >=10GiB + UnattendedVm(oSet, 'tst-w10-1809-32', 'Windows10', '6.0/uaisos/en_windows_10_business_edition_version_1809_updated_sept_2018_x86_dvd_2f92403b.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-w10-1809-64', 'Windows10_64', '6.0/uaisos/en_windows_10_business_edition_version_1809_updated_sept_2018_x64_dvd_f0b7dc68.iso'), # >=10GiB + UnattendedVm(oSet, 'tst-w10-1903-32', 'Windows10', '6.0/uaisos/en_windows_10_business_editions_version_1903_x86_dvd_ca4f0f49.iso'), # >=7GiB + UnattendedVm(oSet, 'tst-w10-1903-64', 'Windows10_64', '6.0/uaisos/en_windows_10_business_editions_version_1903_x64_dvd_37200948.iso'), # >=10GiB + # + # Ubuntu + # + ## @todo 15.10 fails with grub install error. + #UnattendedVm(oSet, 'tst-ubuntu-15.10-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-15.10-desktop-amd64.iso'), + UnattendedVm(oSet, 'tst-ubuntu-16.04-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.04-desktop-amd64.iso', # ~5GiB + UnattendedVm.kfUbuntuAvx2Crash), + UnattendedVm(oSet, 'tst-ubuntu-16.04-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.04-desktop-i386.iso'), # >=4.5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.1-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.04.1-desktop-amd64.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.1-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.04.1-desktop-i386.iso'), # >=4.5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.2-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.04.2-desktop-amd64.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.2-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.04.2-desktop-i386.iso'), # >=4.5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.3-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.04.3-desktop-amd64.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.3-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.04.3-desktop-i386.iso'), # >=4.5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.4-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.04.4-desktop-amd64.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.4-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.04.4-desktop-i386.iso'), # >=4.5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.5-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.04.5-desktop-amd64.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.5-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.04.5-desktop-i386.iso'), # >=4.5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.6-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.04.6-desktop-amd64.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.04.6-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.04.6-desktop-i386.iso'), # >=4.5GiB + UnattendedVm(oSet, 'tst-ubuntu-16.10-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-16.10-desktop-amd64.iso'), # >=5.5GiB + ## @todo 16.10-32 doesn't ask for an IP, so it always fails. + #UnattendedVm(oSet, 'tst-ubuntu-16.10-32', 'Ubuntu', '6.0/uaisos/ubuntu-16.10-desktop-i386.iso'), # >=5.5GiB? + UnattendedVm(oSet, 'tst-ubuntu-17.04-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-17.04-desktop-amd64.iso'), # >=5GiB + UnattendedVm(oSet, 'tst-ubuntu-17.04-32', 'Ubuntu', '6.0/uaisos/ubuntu-17.04-desktop-i386.iso'), # >=4.5GiB + ## @todo ubuntu 17.10, 18.04 & 18.10 do not work. They misses all the the build tools (make, gcc, perl, ++) + ## and has signed kmods: + UnattendedVm(oSet, 'tst-ubuntu-17.10-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-17.10-desktop-amd64.iso', # >=4Gib + UnattendedVm.kfNoGAs), + UnattendedVm(oSet, 'tst-ubuntu-18.04-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-18.04-desktop-amd64.iso', # >=6GiB + UnattendedVm.kfNoGAs), + # 18.10 hangs reading install DVD during "starting partitioner..." + #UnattendedVm(oSet, 'tst-ubuntu-18.10-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-18.10-desktop-amd64.iso', + # UnattendedVm.kfNoGAs), + UnattendedVm(oSet, 'tst-ubuntu-19.04-64', 'Ubuntu_64', '6.0/uaisos/ubuntu-19.04-desktop-amd64.iso', # >=6GiB + UnattendedVm.kfNoGAs), + UnattendedVm(oSet, 'tst-debian-9.3-64', 'Debian_64', '6.0/uaisos/debian-9.3.0-amd64-DVD-1.iso', # >=6GiB? + UnattendedVm.kfAvoidNetwork | UnattendedVm.kfNoGAs), + UnattendedVm(oSet, 'tst-debian-9.4-64', 'Debian_64', '6.0/uaisos/debian-9.4.0-amd64-DVD-1.iso', # >=6GiB? + UnattendedVm.kfAvoidNetwork | UnattendedVm.kfNoGAs), + UnattendedVm(oSet, 'tst-debian-10.0-64', 'Debian_64', '6.0/uaisos/debian-10.0.0-amd64-DVD-1.iso', # >=6GiB? + UnattendedVm.kfAvoidNetwork), + # + # OS/2. + # + UnattendedVm(oSet, 'tst-acp2', 'OS2Warp45', '7.0/uaisos/acp2_us_cd2.iso'), # ~400MiB + ## @todo mcp2 too? + ]); + # pylint: enable=line-too-long + self.oTestVmSet = oSet; + + # For option parsing: + self.aoSelectedVms = oSet.aoTestVms # type: list(UnattendedVm) + + # Number of VMs to test in parallel: + self.cInParallel = 1; + + # Whether to do the save-and-restore test. + self.fTestSaveAndRestore = True; + + # + # Sub-test drivers. + # + self.addSubTestDriver(SubTstDrvAddSharedFolders1(self)); + self.addSubTestDriver(SubTstDrvAddGuestCtrl(self)); + + + # + # Overridden methods. + # + + def showUsage(self): + """ + Extend usage info + """ + rc = vbox.TestDriver.showUsage(self) + reporter.log(''); + reporter.log('tdGuestOsUnattendedInst1 options:'); + reporter.log(' --parallel <num>'); + reporter.log(' Number of VMs to test in parallel.'); + reporter.log(' Default: 1'); + reporter.log(''); + reporter.log(' Options for working on selected test VMs:'); + reporter.log(' --select <vm1[:vm2[:..]]>'); + reporter.log(' Selects a test VM for the following configuration alterations.'); + reporter.log(' Default: All possible test VMs'); + reporter.log(' --copy <old-vm>=<new-vm>'); + reporter.log(' Creates and selects <new-vm> as a copy of <old-vm>.'); + reporter.log(' --guest-type <guest-os-type>'); + reporter.log(' Sets the guest-os type of the currently selected test VM.'); + reporter.log(' --install-iso <ISO file name>'); + reporter.log(' Sets ISO image to use for the selected test VM.'); + reporter.log(' --ram-adjust <MBs>'); + reporter.log(' Adjust the VM ram size by the given delta. Both negative and positive'); + reporter.log(' values are accepted.'); + reporter.log(' --max-cpus <# CPUs>'); + reporter.log(' Sets the maximum number of guest CPUs for the selected VM.'); + reporter.log(' --set-extradata <key>:value'); + reporter.log(' Set VM extra data for the selected VM. Can be repeated.'); + reporter.log(' --ioapic, --no-ioapic'); + reporter.log(' Enable or disable the I/O apic for the selected VM.'); + reporter.log(' --pae, --no-pae'); + reporter.log(' Enable or disable PAE support (32-bit guests only) for the selected VM.'); + return rc + + def parseOption(self, asArgs, iArg): + """ + Extend standard options set + """ + + if asArgs[iArg] == '--parallel': + iArg = self.requireMoreArgs(1, asArgs, iArg); + self.cInParallel = int(asArgs[iArg]); + if self.cInParallel <= 0: + self.cInParallel = 1; + elif asArgs[iArg] == '--select': + iArg = self.requireMoreArgs(1, asArgs, iArg); + self.aoSelectedVms = []; + for sTestVm in asArgs[iArg].split(':'): + oTestVm = self.oTestVmSet.findTestVmByName(sTestVm); + if not oTestVm: + raise base.InvalidOption('Unknown test VM: %s' % (sTestVm,)); + self.aoSelectedVms.append(oTestVm); + elif asArgs[iArg] == '--copy': + iArg = self.requireMoreArgs(1, asArgs, iArg); + asNames = asArgs[iArg].split('='); + if len(asNames) != 2 or not asNames[0] or not asNames[1]: + raise base.InvalidOption('The --copy option expects value on the form "old=new": %s' % (asArgs[iArg],)); + oOldTestVm = self.oTestVmSet.findTestVmByName(asNames[0]); + if not oOldTestVm: + raise base.InvalidOption('Unknown test VM: %s' % (asNames[0],)); + oNewTestVm = copy.deepcopy(oOldTestVm); + oNewTestVm.sVmName = asNames[1]; + self.oTestVmSet.aoTestVms.append(oNewTestVm); + self.aoSelectedVms = [oNewTestVm]; + elif asArgs[iArg] == '--guest-type': + iArg = self.requireMoreArgs(1, asArgs, iArg); + for oTestVm in self.aoSelectedVms: + oTestVm.sKind = asArgs[iArg]; + elif asArgs[iArg] == '--install-iso': + iArg = self.requireMoreArgs(1, asArgs, iArg); + for oTestVm in self.aoSelectedVms: + oTestVm.sInstallIso = asArgs[iArg]; + elif asArgs[iArg] == '--ram-adjust': + iArg = self.requireMoreArgs(1, asArgs, iArg); + for oTestVm in self.aoSelectedVms: + oTestVm.iOptRamAdjust = int(asArgs[iArg]); + elif asArgs[iArg] == '--max-cpus': + iArg = self.requireMoreArgs(1, asArgs, iArg); + for oTestVm in self.aoSelectedVms: + oTestVm.iOptMaxCpus = int(asArgs[iArg]); + elif asArgs[iArg] == '--set-extradata': + iArg = self.requireMoreArgs(1, asArgs, iArg) + sExtraData = asArgs[iArg]; + try: _, _ = sExtraData.split(':'); + except: raise base.InvalidOption('Invalid extradata specified: %s' % (sExtraData, )); + for oTestVm in self.aoSelectedVms: + oTestVm.asOptExtraData.append(sExtraData); + elif asArgs[iArg] == '--ioapic': + for oTestVm in self.aoSelectedVms: + oTestVm.fOptIoApic = True; + elif asArgs[iArg] == '--no-ioapic': + for oTestVm in self.aoSelectedVms: + oTestVm.fOptIoApic = False; + elif asArgs[iArg] == '--pae': + for oTestVm in self.aoSelectedVms: + oTestVm.fOptPae = True; + elif asArgs[iArg] == '--no-pae': + for oTestVm in self.aoSelectedVms: + oTestVm.fOptPae = False; + elif asArgs[iArg] == '--install-additions': + for oTestVm in self.aoSelectedVms: + oTestVm.fOptInstallAdditions = True; + elif asArgs[iArg] == '--no-install-additions': + for oTestVm in self.aoSelectedVms: + oTestVm.fOptInstallAdditions = False; + else: + return vbox.TestDriver.parseOption(self, asArgs, iArg); + return iArg + 1; + + def actionConfig(self): + if not self.importVBoxApi(): # So we can use the constant below. + return False; + return self.oTestVmSet.actionConfig(self); + + def actionExecute(self): + """ + Execute the testcase. + """ + return self.oTestVmSet.actionExecute(self, self.testOneVmConfig) + + def testOneVmConfig(self, oVM, oTestVm): # type: (Any, UnattendedVm) -> bool + """ + Install guest OS and wait for result + """ + + self.logVmInfo(oVM) + reporter.testStart('Installing %s%s' % (oTestVm.sVmName, ' with GAs' if oTestVm.fOptInstallAdditions else '')) + + cMsTimeout = 40*60000; + if not reporter.isLocal(): ## @todo need to figure a better way of handling timeouts on the testboxes ... + cMsTimeout = 180 * 60000; # will be adjusted down. + + oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False, cMsTimeout = cMsTimeout); + #oSession = self.startVmByName(oTestVm.sVmName); # (for quickly testing waitForGAs) + if oSession is not None: + # The guest has connected to TXS. + reporter.log('Guest reported success via TXS.'); + reporter.testDone(); + + fRc = True; + # Kudge: GAs doesn't come up correctly, so we have to reboot the guest first: + # Looks like VBoxService isn't there. + if oTestVm.fOptInstallAdditions: + reporter.testStart('Rebooting'); + fRc, oTxsSession = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession); + reporter.testDone(); + + # If we're installing GAs, wait for them to come online: + if oTestVm.fOptInstallAdditions and fRc is True: + reporter.testStart('Guest additions'); + aenmRunLevels = [vboxcon.AdditionsRunLevelType_Userland,]; + if oTestVm.isLoggedOntoDesktop(): + aenmRunLevels.append(vboxcon.AdditionsRunLevelType_Desktop); + fRc = self.waitForGAs(oSession, cMsTimeout = cMsTimeout / 2, aenmWaitForRunLevels = aenmRunLevels, + aenmWaitForActive = (vboxcon.AdditionsFacilityType_VBoxGuestDriver, + vboxcon.AdditionsFacilityType_VBoxService,)); + reporter.testDone(); + + # Now do a save & restore test: + if fRc is True and self.fTestSaveAndRestore: + fRc, oSession, oTxsSession = self.testSaveAndRestore(oSession, oTxsSession, oTestVm); + + # Test GAs if requested: + if oTestVm.fOptInstallAdditions and fRc is True: + for oSubTstDrv in self.aoSubTstDrvs: + if oSubTstDrv.fEnabled: + reporter.testStart(oSubTstDrv.sTestName); + fRc2, oTxsSession = oSubTstDrv.testIt(oTestVm, oSession, oTxsSession); + reporter.testDone(fRc2 is None); + if fRc2 is False: + fRc = False; + + if oSession is not None: + fRc = self.terminateVmBySession(oSession) and fRc; + return fRc is True + + reporter.error('Installation of %s has failed' % (oTestVm.sVmName,)) + #oTestVm.detatchAndDeleteHd(self); # Save space. + reporter.testDone() + return False + + def testSaveAndRestore(self, oSession, oTxsSession, oTestVm): + """ + Tests saving and restoring the VM. + """ + _ = oTestVm; + reporter.testStart('Save'); + ## @todo + reporter.testDone(); + reporter.testStart('Restore'); + ## @todo + reporter.testDone(); + return (True, oSession, oTxsSession); + +if __name__ == '__main__': + sys.exit(tdGuestOsInstTest1().main(sys.argv)) |