diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/ValidationKit/tests/installation | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/ValidationKit/tests/installation')
4 files changed, 1488 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/tests/installation/Makefile.kmk b/src/VBox/ValidationKit/tests/installation/Makefile.kmk new file mode 100644 index 00000000..b901296f --- /dev/null +++ b/src/VBox/ValidationKit/tests/installation/Makefile.kmk @@ -0,0 +1,52 @@ +# $Id: Makefile.kmk $ +## @file +# VirtualBox Validation Kit - Automatic guest OS installation tests. +# + +# +# Copyright (C) 2006-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 +# + +SUB_DEPTH = ../../../../.. +include $(KBUILD_PATH)/subheader.kmk + + +INSTALLS += ValidationKitInstallationTests +ValidationKitInstallationTests_TEMPLATE = VBoxValidationKitR3 +ValidationKitInstallationTests_INST = $(INST_VALIDATIONKIT)tests/installation/ +ValidationKitInstallationTests_EXEC_SOURCES := \ + $(PATH_SUB_CURRENT)/tdGuestOsInstTest1.py \ + $(PATH_SUB_CURRENT)/tdGuestOsInstOs2.py \ + $(PATH_SUB_CURRENT)/tdGuestOsUnattendedInst1.py + +VBOX_VALIDATIONKIT_PYTHON_SOURCES += $(ValidationKitInstallationTests_EXEC_SOURCES) + +$(evalcall def_vbox_validationkit_process_python_sources) +include $(FILE_KBUILD_SUB_FOOTER) diff --git a/src/VBox/ValidationKit/tests/installation/tdGuestOsInstOs2.py b/src/VBox/ValidationKit/tests/installation/tdGuestOsInstOs2.py new file mode 100755 index 00000000..caba4e76 --- /dev/null +++ b/src/VBox/ValidationKit/tests/installation/tdGuestOsInstOs2.py @@ -0,0 +1,258 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# $Id: tdGuestOsInstOs2.py $ + +""" +VirtualBox Validation Kit - OS/2 install 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 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 + + +class tdGuestOsInstOs2(vbox.TestDriver): + """ + OS/2 unattended installation. + + Scenario: + - Create new VM that corresponds specified installation ISO image + - Create HDD that corresponds to OS type that will be installed + - Set VM boot order: HDD, Floppy, ISO + - Start VM: sinse there is no OS installed on HDD, VM will booted from floppy + - After first reboot VM will continue installation from HDD automatically + - Wait for incomming TCP connection (guest should initiate such a + connection in case installation has been completed successfully) + """ + + ksSataController = 'SATA Controller' + ksIdeController = 'IDE Controller' + + # VM parameters required to run ISO image. + # Format: (cBytesHdd, sKind) + kaoVmParams = { + 'acp2-txs.iso': ( 2*1024*1024*1024, 'OS2', ksIdeController ), + 'mcp2-txs.iso': ( 2*1024*1024*1024, 'OS2', ksIdeController ), + } + + def __init__(self): + """ + Reinitialize child class instance. + """ + vbox.TestDriver.__init__(self) + + self.sVmName = 'TestVM' + self.sHddName = 'TestHdd.vdi' + self.sIso = None + self.sFloppy = None + self.sIsoPathBase = os.path.join(self.sResourcePath, '4.2', 'isos') + self.fEnableIOAPIC = True + self.cCpus = 1 + self.fEnableNestedPaging = True + self.fEnablePAE = False + self.asExtraData = [] + + # + # Overridden methods. + # + + def showUsage(self): + """ + Extend usage info + """ + rc = vbox.TestDriver.showUsage(self) + reporter.log(' --install-iso <ISO file name>') + reporter.log(' --cpus <# CPUs>') + reporter.log(' --no-ioapic') + reporter.log(' --no-nested-paging') + reporter.log(' --pae') + reporter.log(' --set-extradata <key>:value') + reporter.log(' Set VM extra data. This command line option might be used multiple times.') + return rc + + def parseOption(self, asArgs, iArg): + """ + Extend standard options set + """ + if asArgs[iArg] == '--install-iso': + iArg += 1 + if iArg >= len(asArgs): raise base.InvalidOption('The "--install-iso" option requires an argument') + self.sIso = asArgs[iArg] + elif asArgs[iArg] == '--cpus': + iArg += 1 + if iArg >= len(asArgs): raise base.InvalidOption('The "--cpus" option requires an argument') + self.cCpus = int(asArgs[iArg]) + elif asArgs[iArg] == '--no-ioapic': + self.fEnableIOAPIC = False + elif asArgs[iArg] == '--no-nested-paging': + self.fEnableNestedPaging = False + elif asArgs[iArg] == '--pae': + self.fEnablePAE = True + elif asArgs[iArg] == '--extra-mem': + self.fEnablePAE = True + elif asArgs[iArg] == '--set-extradata': + iArg = self.requireMoreArgs(1, asArgs, iArg) + self.asExtraData.append(asArgs[iArg]) + else: + return vbox.TestDriver.parseOption(self, asArgs, iArg) + + return iArg + 1 + + def actionConfig(self): + """ + Configure pre-conditions. + """ + + if not self.importVBoxApi(): + return False + + assert self.sIso is not None + if self.sIso not in self.kaoVmParams: + reporter.log('Error: unknown ISO image specified: %s' % self.sIso) + return False + + # Get VM params specific to ISO image + cBytesHdd, sKind, sController = self.kaoVmParams[self.sIso] + + # Create VM itself + eNic0AttachType = vboxcon.NetworkAttachmentType_NAT + self.sIso = os.path.join(self.sIsoPathBase, self.sIso) + assert os.path.isfile(self.sIso) + + self.sFloppy = os.path.join(self.sIsoPathBase, os.path.splitext(self.sIso)[0] + '.img') + + oVM = self.createTestVM(self.sVmName, 1, sKind = sKind, sDvdImage = self.sIso, cCpus = self.cCpus, + sFloppy = self.sFloppy, eNic0AttachType = eNic0AttachType) + assert oVM is not None + + oSession = self.openSession(oVM) + + # Create HDD + sHddPath = os.path.join(self.sScratchPath, self.sHddName) + fRc = True + if sController == self.ksSataController: + fRc = oSession.setStorageControllerType(vboxcon.StorageControllerType_IntelAhci, sController) + + fRc = fRc and oSession.createAndAttachHd(sHddPath, cb = cBytesHdd, + sController = sController, iPort = 0, fImmutable=False) + if sController == self.ksSataController: + fRc = fRc and oSession.setStorageControllerPortCount(sController, 1) + + # Set proper boot order + fRc = fRc and oSession.setBootOrder(1, vboxcon.DeviceType_HardDisk) + fRc = fRc and oSession.setBootOrder(2, vboxcon.DeviceType_Floppy) + + # Enable HW virt + fRc = fRc and oSession.enableVirtEx(True) + + # Enable I/O APIC + fRc = fRc and oSession.enableIoApic(self.fEnableIOAPIC) + + # Enable Nested Paging + fRc = fRc and oSession.enableNestedPaging(self.fEnableNestedPaging) + + # Enable PAE + fRc = fRc and oSession.enablePae(self.fEnablePAE) + + # Remote desktop + oSession.setupVrdp(True) + + # Set extra data + if self.asExtraData: + for sExtraData in self.asExtraData: + try: + sKey, sValue = sExtraData.split(':') + except ValueError: + raise base.InvalidOption('Invalid extradata specified: %s' % sExtraData) + reporter.log('Set extradata: %s => %s' % (sKey, sValue)) + fRc = fRc and oSession.setExtraData(sKey, sValue) + + fRc = fRc and oSession.saveSettings() + fRc = oSession.close() + assert fRc is True + + return vbox.TestDriver.actionConfig(self) + + def actionExecute(self): + """ + Execute the testcase itself. + """ + if not self.importVBoxApi(): + return False + return self.testDoInstallGuestOs() + + # + # Test execution helpers. + # + + def testDoInstallGuestOs(self): + """ + Install guest OS and wait for result + """ + reporter.testStart('Installing %s' % (os.path.basename(self.sIso),)) + + 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, _ = self.startVmAndConnectToTxsViaTcp(self.sVmName, fCdWait = False, cMsTimeout = cMsTimeout) + if oSession is not None: + # Wait until guest reported success + reporter.log('Guest reported success') + reporter.testDone() + fRc = self.terminateVmBySession(oSession) + return fRc is True + reporter.error('Installation of %s has failed' % (self.sIso,)) + reporter.testDone() + return False + +if __name__ == '__main__': + sys.exit(tdGuestOsInstOs2().main(sys.argv)); + diff --git a/src/VBox/ValidationKit/tests/installation/tdGuestOsInstTest1.py b/src/VBox/ValidationKit/tests/installation/tdGuestOsInstTest1.py new file mode 100755 index 00000000..9c5c4ceb --- /dev/null +++ b/src/VBox/ValidationKit/tests/installation/tdGuestOsInstTest1.py @@ -0,0 +1,409 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# $Id: tdGuestOsInstTest1.py $ + +""" +VirtualBox Validation Kit - Guest OS 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 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; + + +class InstallTestVm(vboxtestvms.TestVm): + """ Installation test VM. """ + + ## @name The primary controller, to which the disk will be attached. + ## @{ + ksScsiController = 'SCSI Controller' + ksSataController = 'SATA Controller' + ksIdeController = 'IDE Controller' + ## @} + + ## @name VM option flags (OR together). + ## @{ + kf32Bit = 0x01; + kf64Bit = 0x02; + # most likely for ancient Linux kernels assuming that AMD processors have always an I/O-APIC + kfReqIoApic = 0x10; + kfReqIoApicSmp = 0x20; + kfReqPae = 0x40; + kfIdeIrqDelay = 0x80; + kfUbuntuNewAmdBug = 0x100; + kfNoWin81Paravirt = 0x200; + ## @} + + ## IRQ delay extra data config for win2k VMs. + kasIdeIrqDelay = [ 'VBoxInternal/Devices/piix3ide/0/Config/IRQDelay:1', ]; + + ## Install ISO path relative to the testrsrc root. + ksIsoPathBase = os.path.join('4.2', 'isos'); + + + def __init__(self, oSet, sVmName, sKind, sInstallIso, sHdCtrlNm, cGbHdd, fFlags): + vboxtestvms.TestVm.__init__(self, sVmName, oSet = oSet, sKind = sKind, sHddControllerType = sHdCtrlNm, + fRandomPvPMode = (fFlags & self.kfNoWin81Paravirt) == 0); + self.sDvdImage = os.path.join(self.ksIsoPathBase, sInstallIso); + self.cGbHdd = cGbHdd; + self.fInstVmFlags = fFlags; + if fFlags & self.kfReqPae: + self.fPae = True; + if fFlags & (self.kfReqIoApic | self.kfReqIoApicSmp): + self.fIoApic = True; + + # Tweaks + self.iOptRamAdjust = 0; + self.asExtraData = []; + if fFlags & self.kfIdeIrqDelay: + self.asExtraData = self.kasIdeIrqDelay; + + def detatchAndDeleteHd(self, oTestDrv): + """ + Detaches and deletes the HD. + Returns success indicator, error info logged. + """ + fRc = False; + oVM = oTestDrv.getVmByName(self.sVmName); + if oVM is not None: + oSession = oTestDrv.openSession(oVM); + if oSession is not None: + (fRc, oHd) = oSession.detachHd(self.sHddControllerType, iPort = 0, iDevice = 0); + if fRc is True and oHd is not None: + fRc = oSession.saveSettings(); + fRc = fRc and oTestDrv.oVBox.deleteHdByMedium(oHd); + fRc = fRc and oSession.saveSettings(); # Necessary for media reg? + fRc = oSession.close() and fRc; + return fRc; + + 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.TestVm.getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode); + + # + # Make sure there is no HD from the previous run attached nor taking + # up storage on the host. + # + if fRc is True: + fRc = self.detatchAndDeleteHd(oTestDrv); + + # + # Check for ubuntu installer vs. AMD host CPU. + # + if fRc is True and (self.fInstVmFlags & self.kfUbuntuNewAmdBug): + if self.isHostCpuAffectedByUbuntuNewAmdBug(oTestDrv): + return (None, None); # (skip) + + # + # Make adjustments to the default config, and adding a fresh HD. + # + if fRc is True: + oSession = oTestDrv.openSession(oVM); + if oSession is not None: + if self.sHddControllerType == self.ksSataController: + fRc = fRc and oSession.setStorageControllerType(vboxcon.StorageControllerType_IntelAhci, + self.sHddControllerType); + fRc = fRc and oSession.setStorageControllerPortCount(self.sHddControllerType, 1); + elif self.sHddControllerType == self.ksScsiController: + fRc = fRc and oSession.setStorageControllerType(vboxcon.StorageControllerType_LsiLogic, + self.sHddControllerType); + try: + sHddPath = os.path.join(os.path.dirname(oVM.settingsFilePath), + '%s-%s-%s.vdi' % (self.sVmName, sVirtMode, cCpus,)); + except: + reporter.errorXcpt(); + sHddPath = None; + fRc = False; + + fRc = fRc and oSession.createAndAttachHd(sHddPath, + cb = self.cGbHdd * 1024*1024*1024, + sController = self.sHddControllerType, + iPort = 0, + fImmutable = False); + + # Set proper boot order + 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: + fRc = fRc and oSession.setRamSize(oSession.o.machine.memorySize + self.iOptRamAdjust); + + # Set extra data + for sExtraData in self.asExtraData: + try: + sKey, sValue = sExtraData.split(':') + except ValueError: + raise base.InvalidOption('Invalid extradata specified: %s' % sExtraData) + reporter.log('Set extradata: %s => %s' % (sKey, sValue)) + fRc = fRc and oSession.setExtraData(sKey, sValue) + + # Other variations? + + # Save the settings. + fRc = fRc and oSession.saveSettings() + fRc = oSession.close() and fRc; + else: + fRc = False; + if fRc is not True: + oVM = None; + + # Done. + return (fRc, oVM) + + + + + +class tdGuestOsInstTest1(vbox.TestDriver): + """ + Guest OS installation tests. + + Scenario: + - Create new VM that corresponds specified installation ISO image. + - Create HDD that corresponds to OS type that will be installed. + - Boot VM from ISO image (i.e. install guest OS). + - Wait for incomming TCP connection (guest should initiate such a + connection in case installation has been completed successfully). + """ + + + 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); + oSet.aoTestVms.extend([ + # pylint: disable=line-too-long + InstallTestVm(oSet, 'tst-fedora4', 'Fedora', 'fedora4-txs.iso', InstallTestVm.ksIdeController, 8, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-fedora5', 'Fedora', 'fedora5-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfReqPae | InstallTestVm.kfReqIoApicSmp), + InstallTestVm(oSet, 'tst-fedora6', 'Fedora', 'fedora6-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfReqIoApic), + InstallTestVm(oSet, 'tst-fedora7', 'Fedora', 'fedora7-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfUbuntuNewAmdBug | InstallTestVm.kfReqIoApic), + InstallTestVm(oSet, 'tst-fedora9', 'Fedora', 'fedora9-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-fedora18-64', 'Fedora_64', 'fedora18-x64-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-fedora18', 'Fedora', 'fedora18-txs.iso', InstallTestVm.ksScsiController, 8, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-ols6', 'Oracle', 'ols6-i386-txs.iso', InstallTestVm.ksSataController, 12, InstallTestVm.kf32Bit | InstallTestVm.kfReqPae), + InstallTestVm(oSet, 'tst-ols6-64', 'Oracle_64', 'ols6-x86_64-txs.iso', InstallTestVm.ksSataController, 12, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-rhel5', 'RedHat', 'rhel5-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfReqPae | InstallTestVm.kfReqIoApic), + InstallTestVm(oSet, 'tst-suse102', 'OpenSUSE', 'opensuse102-txs.iso', InstallTestVm.ksIdeController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfReqIoApic), + ## @todo InstallTestVm(oSet, 'tst-ubuntu606', 'Ubuntu', 'ubuntu606-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit), + ## @todo InstallTestVm(oSet, 'tst-ubuntu710', 'Ubuntu', 'ubuntu710-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-ubuntu804', 'Ubuntu', 'ubuntu804-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfUbuntuNewAmdBug | InstallTestVm.kfReqPae | InstallTestVm.kfReqIoApic), + InstallTestVm(oSet, 'tst-ubuntu804-64', 'Ubuntu_64', 'ubuntu804-amd64-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-ubuntu904', 'Ubuntu', 'ubuntu904-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfUbuntuNewAmdBug | InstallTestVm.kfReqPae), + InstallTestVm(oSet, 'tst-ubuntu904-64', 'Ubuntu_64', 'ubuntu904-amd64-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf64Bit), + #InstallTestVm(oSet, 'tst-ubuntu1404', 'Ubuntu', 'ubuntu1404-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfUbuntuNewAmdBug | InstallTestVm.kfReqPae), bird: Is 14.04 one of the 'older ones'? + InstallTestVm(oSet, 'tst-ubuntu1404', 'Ubuntu', 'ubuntu1404-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit | InstallTestVm.kfReqPae), + InstallTestVm(oSet, 'tst-ubuntu1404-64','Ubuntu_64', 'ubuntu1404-amd64-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-debian7', 'Debian', 'debian-7.0.0-txs.iso', InstallTestVm.ksSataController, 8, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-debian7-64', 'Debian_64', 'debian-7.0.0-x64-txs.iso', InstallTestVm.ksScsiController, 8, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-vista-64', 'WindowsVista_64', 'vista-x64-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-vista-32', 'WindowsVista', 'vista-x86-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-w7-64', 'Windows7_64', 'win7-x64-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-w7-32', 'Windows7', 'win7-x86-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-w2k3', 'Windows2003', 'win2k3ent-txs.iso', InstallTestVm.ksIdeController, 25, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-w2k', 'Windows2000', 'win2ksp0-txs.iso', InstallTestVm.ksIdeController, 25, InstallTestVm.kf32Bit | InstallTestVm.kfIdeIrqDelay), + InstallTestVm(oSet, 'tst-w2ksp4', 'Windows2000', 'win2ksp4-txs.iso', InstallTestVm.ksIdeController, 25, InstallTestVm.kf32Bit | InstallTestVm.kfIdeIrqDelay), + InstallTestVm(oSet, 'tst-wxp', 'WindowsXP', 'winxppro-txs.iso', InstallTestVm.ksIdeController, 25, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-wxpsp2', 'WindowsXP', 'winxpsp2-txs.iso', InstallTestVm.ksIdeController, 25, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-wxp64', 'WindowsXP_64', 'winxp64-txs.iso', InstallTestVm.ksIdeController, 25, InstallTestVm.kf64Bit), + ## @todo disable paravirt for Windows 8.1 guests as long as it's not fixed in the code + InstallTestVm(oSet, 'tst-w81-32', 'Windows81', 'win81-x86-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf32Bit), + InstallTestVm(oSet, 'tst-w81-64', 'Windows81_64', 'win81-x64-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf64Bit), + InstallTestVm(oSet, 'tst-w10-32', 'Windows10', 'win10-x86-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf32Bit | InstallTestVm.kfReqPae), + InstallTestVm(oSet, 'tst-w10-64', 'Windows10_64', 'win10-x64-txs.iso', InstallTestVm.ksSataController, 25, InstallTestVm.kf64Bit), + # pylint: enable=line-too-long + ]); + self.oTestVmSet = oSet; + + + + # + # Overridden methods. + # + + def showUsage(self): + """ + Extend usage info + """ + rc = vbox.TestDriver.showUsage(self) + reporter.log(''); + reporter.log('tdGuestOsInstTest1 options:'); + reporter.log(' --ioapic, --no-ioapic'); + reporter.log(' Enable or disable the I/O apic.'); + reporter.log(' Default: --ioapic'); + reporter.log(' --pae, --no-pae'); + reporter.log(' Enable or disable PAE support for 32-bit guests.'); + reporter.log(' Default: Guest dependent.'); + 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(' --set-extradata <key>:value') + reporter.log(' Set VM extra data. This command line option might be used multiple times.') + reporter.log('obsolete:'); + reporter.log(' --nested-paging, --no-nested-paging'); + reporter.log(' --raw-mode'); + reporter.log(' --cpus <# CPUs>'); + reporter.log(' --install-iso <ISO file name>'); + + return rc + + def parseOption(self, asArgs, iArg): + """ + Extend standard options set + """ + + if False is True: + pass; + elif asArgs[iArg] == '--ioapic': + for oTestVm in self.oTestVmSet.aoTestVms: + oTestVm.fIoApic = True; + elif asArgs[iArg] == '--no-ioapic': + for oTestVm in self.oTestVmSet.aoTestVms: + oTestVm.fIoApic = False; + elif asArgs[iArg] == '--pae': + for oTestVm in self.oTestVmSet.aoTestVms: + oTestVm.fPae = True; + elif asArgs[iArg] == '--no-pae': + for oTestVm in self.oTestVmSet.aoTestVms: + oTestVm.fPae = False; + elif asArgs[iArg] == '--ram-adjust': + iArg = self.requireMoreArgs(1, asArgs, iArg); + for oTestVm in self.oTestVmSet.aoTestVms: + oTestVm.iOptRamAdjust = int(asArgs[iArg]); + elif asArgs[iArg] == '--set-extradata': + iArg = self.requireMoreArgs(1, asArgs, iArg) + for oTestVm in self.oTestVmSet.aoTestVms: + oTestVm.asExtraData.append(asArgs[iArg]); + + # legacy, to be removed once TM is reconfigured. + elif asArgs[iArg] == '--install-iso': + self.legacyOptions(); + iArg = self.requireMoreArgs(1, asArgs, iArg); + for oTestVm in self.oTestVmSet.aoTestVms: + oTestVm.fSkip = os.path.basename(oTestVm.sDvdImage) != asArgs[iArg]; + elif asArgs[iArg] == '--cpus': + self.legacyOptions(); + iArg = self.requireMoreArgs(1, asArgs, iArg); + self.oTestVmSet.acCpus = [ int(asArgs[iArg]), ]; + elif asArgs[iArg] == '--raw-mode': + self.legacyOptions(); + self.oTestVmSet.asVirtModes = [ 'raw', ]; + elif asArgs[iArg] == '--nested-paging': + self.legacyOptions(); + self.oTestVmSet.asVirtModes = [ 'hwvirt-np', ]; + elif asArgs[iArg] == '--no-nested-paging': + self.legacyOptions(); + self.oTestVmSet.asVirtModes = [ 'hwvirt', ]; + else: + return vbox.TestDriver.parseOption(self, asArgs, iArg) + + return iArg + 1 + + def legacyOptions(self): + """ Enables legacy option mode. """ + if not self.fLegacyOptions: + self.fLegacyOptions = True; + self.oTestVmSet.asVirtModes = [ 'hwvirt', ]; + self.oTestVmSet.acCpus = [ 1, ]; + return True; + + def actionConfig(self): + if not self.importVBoxApi(): # So we can use the constant below. + return False; + return self.oTestVmSet.actionConfig(self, eNic0AttachType = vboxcon.NetworkAttachmentType_NAT); + + def actionExecute(self): + """ + Execute the testcase. + """ + return self.oTestVmSet.actionExecute(self, self.testOneVmConfig) + + def testOneVmConfig(self, oVM, oTestVm): + """ + Install guest OS and wait for result + """ + + self.logVmInfo(oVM) + reporter.testStart('Installing %s' % (oTestVm.sVmName,)) + + 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, _ = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False, cMsTimeout = cMsTimeout); + if oSession is not None: + # The guest has connected to TXS, so we're done (for now anyways). + reporter.log('Guest reported success') + ## @todo Do save + restore. + + reporter.testDone() + fRc = self.terminateVmBySession(oSession) + return fRc is True + + reporter.error('Installation of %s has failed' % (oTestVm.sVmName,)) + oTestVm.detatchAndDeleteHd(self); # Save space. + reporter.testDone() + return False + +if __name__ == '__main__': + sys.exit(tdGuestOsInstTest1().main(sys.argv)) + 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)) |