mirror of
				https://github.com/vyos/vyos-build.git
				synced 2025-10-01 20:28:40 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			1071 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1071 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| #
 | |
| # Copyright (C) 2019-2025, VyOS maintainers and contributors
 | |
| #
 | |
| # This program is free software; you can redistribute it and/or modify
 | |
| # it under the terms of the GNU General Public License version 2 or later as
 | |
| # published by the Free Software Foundation.
 | |
| #
 | |
| # 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 <http://www.gnu.org/licenses/>.
 | |
| #
 | |
| # File: check-qemu-install
 | |
| # Purpose:
 | |
| #  This script installs a system on a emulated qemu host to verify
 | |
| #  that the iso produced is installable and boots.
 | |
| #  after the iso is booted from disk it also tries to execute the
 | |
| #  vyos-smoketest script to verify checks there.
 | |
| #
 | |
| #  For now it will not fail on failed smoketest but will fail on
 | |
| #  install and boot errors.
 | |
| #  Arguments:
 | |
| #    iso            iso image to install
 | |
| #    [disk]         disk filename to use, if none is provided it
 | |
| #                   is autogenerated
 | |
| #    [--keep]       Keep the disk image after completion
 | |
| #    [--logfile]    name of logfile to save, defaulting to stdout
 | |
| #    [--silent]     only print on errors
 | |
| #    [--debug]      print all communication with the device
 | |
| 
 | |
| import pexpect
 | |
| import sys
 | |
| import os
 | |
| import time
 | |
| import argparse
 | |
| import subprocess
 | |
| import random
 | |
| import traceback
 | |
| import logging
 | |
| import re
 | |
| import tomli
 | |
| import shutil
 | |
| import json
 | |
| 
 | |
| from io import BytesIO
 | |
| from datetime import datetime
 | |
| 
 | |
| EXCEPTION = 0
 | |
| now = datetime.now()
 | |
| tpm_folder = '/tmp/vyos_tpm_test'
 | |
| qemu_name = 'VyOS-QEMU'
 | |
| 
 | |
| # getch.py
 | |
| KEY_F2 = chr(27) + chr(91) + chr(49) + chr(50) + chr(126)
 | |
| KEY_F10 = chr(27) + chr(91) + chr(50) + chr(49) + chr(126)
 | |
| KEY_DOWN = chr(27) + chr(91) + chr(66)
 | |
| KEY_SPACE = chr(32)
 | |
| KEY_RETURN = chr(13)
 | |
| KEY_ESC = chr(27)
 | |
| KEY_Y = chr(121)
 | |
| 
 | |
| mok_password = '1234'
 | |
| 
 | |
| parser = argparse.ArgumentParser(description='Install and start a test VyOS vm.')
 | |
| parser.add_argument('iso', help='ISO file to install')
 | |
| parser.add_argument('disk', help='name of disk image file', nargs='?',
 | |
|                             default='testinstall-{}-{}.img'.format(now.strftime('%Y%m%d-%H%M%S'),
 | |
|                                                                    "%04x" % random.randint(0,65535)))
 | |
| parser.add_argument('--keep', help='Do not remove disk-image after installation',
 | |
|                               action='store_true', default=False)
 | |
| parser.add_argument('--silent', help='Do not show output on stdout unless an error has occured',
 | |
|                               action='store_true', default=False)
 | |
| parser.add_argument('--debug', help='Send all debug output to stdout',
 | |
|                                action='store_true', default=False)
 | |
| parser.add_argument('--logfile', help='Log to file')
 | |
| parser.add_argument('--match', help='Smoketests to run')
 | |
| parser.add_argument('--uefi', help='Boot using UEFI', action='store_true', default=False)
 | |
| parser.add_argument('--vnc', help='Enable VNC', action='store_true', default=False)
 | |
| parser.add_argument('--raid', help='Perform a RAID-1 install', action='store_true', default=False)
 | |
| parser.add_argument('--configd', help='Execute testsuite with config daemon', action='store_true',
 | |
| 				default=False)
 | |
| parser.add_argument('--no-interfaces', help='Execute testsuite without interface tests to save time',
 | |
|                 action='store_true', default=False)
 | |
| parser.add_argument('--smoketest', help='Execute script based CLI smoketests',
 | |
|                 action='store_true', default=False)
 | |
| parser.add_argument('--configtest', help='Execute load/commit config tests',
 | |
| 				action='store_true', default=False)
 | |
| parser.add_argument('--tpmtest', help='Execute TPM encrypted config tests',
 | |
|                 action='store_true', default=False)
 | |
| parser.add_argument('--sbtest', help='Execute Secure Boot tests',
 | |
|                 action='store_true', default=False)
 | |
| parser.add_argument('--qemu-cmd', help='Only generate QEMU launch command',
 | |
|                 action='store_true', default=False)
 | |
| parser.add_argument('--cpu', help='Set QEMU CPU', type=int, default=2)
 | |
| parser.add_argument('--memory', help='Set QEMU memory', type=int, default=4)
 | |
| parser.add_argument('--vyconf', help='Execute testsuite with vyconfd', action='store_true',
 | |
|                     default=False)
 | |
| parser.add_argument('--no-vpp', help='Execute testsuite without VPP tests',
 | |
|                 action='store_true', default=False)
 | |
| parser.add_argument('--huge-page-size', help='Huge page size (e.g., 2M, 1G)', type=str)
 | |
| parser.add_argument('--huge-page-count', help='Number of huge pages to allocate', type=int)
 | |
| 
 | |
| args = parser.parse_args()
 | |
| 
 | |
| # This is what we requested the build to contain
 | |
| with open('data/defaults.toml', 'rb') as f:
 | |
|     vyos_defaults = tomli.load(f)
 | |
| 
 | |
| # This is what we got from the build
 | |
| manifest_file = 'build/manifest.json'
 | |
| if os.path.isfile(manifest_file):
 | |
|     with open('build/manifest.json', 'rb') as f:
 | |
|         manifest = json.load(f)
 | |
| 
 | |
|     vyos_version = manifest['build_config']['version']
 | |
|     vyos_codename = manifest['build_config']['release_train']
 | |
| 
 | |
| class StreamToLogger(object):
 | |
|     """
 | |
|     Fake file-like stream object that redirects writes to a logger instance.
 | |
|     """
 | |
|     def __init__(self, logger, log_level=logging.INFO):
 | |
|         self.logger = logger
 | |
|         self.log_level = log_level
 | |
|         self.linebuf = b''
 | |
|         self.ansi_escape = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
 | |
| 
 | |
|     def write(self, buf):
 | |
|         self.linebuf += buf
 | |
|         while b'\n' in self.linebuf:
 | |
|             f = self.linebuf.split(b'\n', 1)
 | |
|             if len(f) == 2:
 | |
|                 self.logger.debug(self.ansi_escape.sub('', f[0].decode(errors="replace").rstrip()))
 | |
|                 self.linebuf = f[1]
 | |
| 
 | |
|     def flush(self):
 | |
|         pass
 | |
| 
 | |
| OVMF_CODE = '/usr/share/OVMF/OVMF_CODE_4M.secboot.fd'
 | |
| OVMF_VARS_TMP = args.disk.replace('.img', '.efivars')
 | |
| if args.sbtest:
 | |
|     shutil.copy('/usr/share/OVMF/OVMF_VARS_4M.ms.fd', OVMF_VARS_TMP)
 | |
| 
 | |
| def get_qemu_cmd(name, enable_uefi, disk_img, raid=None, iso_img=None, tpm=False, vnc_enabled=False, secure_boot=False):
 | |
|     uefi = ""
 | |
|     uuid = "f48b60b2-e6ad-49ef-9d09-4245d0585e52"
 | |
|     machine = 'pc'
 | |
|     vga = '-vga none'
 | |
|     vnc = ''
 | |
|     if vnc_enabled:
 | |
|         vga = '-vga virtio'
 | |
|         vnc = '-vnc :0'
 | |
| 
 | |
|     if enable_uefi:
 | |
|         uefi = '-bios /usr/share/OVMF/OVMF_CODE.fd'
 | |
|         name = f'{name}-UEFI'
 | |
| 
 | |
|         if secure_boot:
 | |
|             name = f'{name}-SECURE-BOOT'
 | |
|             machine = 'q35,smm=on'
 | |
| 
 | |
|             uefi = f'-drive "if=pflash,unit=0,format=raw,readonly=on,file={OVMF_CODE}" ' \
 | |
|                    f'-drive "if=pflash,unit=1,format=raw,file={OVMF_VARS_TMP}"'
 | |
|             # Changing UEFI settings require a display
 | |
|             vga = '-vga virtio'
 | |
| 
 | |
|     cdrom = ""
 | |
|     if iso_img:
 | |
|         cdrom = f' -drive file={iso_img},format=raw,if=none,media=cdrom,id=drive-cd1,readonly=on' \
 | |
|                 f' -device ahci,id=achi0' \
 | |
|                 f' -device ide-cd,bus=achi0.0,drive=drive-cd1,id=cd1,bootindex=10'
 | |
| 
 | |
|     # RFC7042 section 2.1.2 MAC addresses used for documentation
 | |
|     macbase = '00:00:5E:00:53'
 | |
|     cmd = f'qemu-system-x86_64 \
 | |
|         -name "{name}" \
 | |
|         -smp {args.cpu},sockets=1,cores={args.cpu},threads=1 \
 | |
|         -cpu host \
 | |
|         -machine {machine},accel=kvm \
 | |
|         {uefi} \
 | |
|         -m {args.memory}G \
 | |
|         -vga none \
 | |
|         -nographic \
 | |
|         {vga} {vnc}\
 | |
|         -uuid {uuid} \
 | |
|         -cpu host \
 | |
|         {cdrom} \
 | |
|         -enable-kvm \
 | |
|         -monitor unix:/tmp/qemu-monitor-socket-{disk_img},server,nowait \
 | |
|         -netdev user,id=n0,net=192.0.2.0/24,dhcpstart=192.0.2.101,dns=192.0.2.10 -device virtio-net-pci,netdev=n0,mac={macbase}:00,romfile="" \
 | |
|         -netdev user,id=n1 -device virtio-net-pci,netdev=n1,mac={macbase}:01,romfile="" \
 | |
|         -netdev user,id=n2 -device virtio-net-pci,netdev=n2,mac={macbase}:02,romfile="" \
 | |
|         -netdev user,id=n3 -device virtio-net-pci,netdev=n3,mac={macbase}:03,romfile="" \
 | |
|         -netdev user,id=n4 -device virtio-net-pci,netdev=n4,mac={macbase}:04,romfile="" \
 | |
|         -netdev user,id=n5 -device virtio-net-pci,netdev=n5,mac={macbase}:05,romfile="" \
 | |
|         -netdev user,id=n6 -device virtio-net-pci,netdev=n6,mac={macbase}:06,romfile="" \
 | |
|         -netdev user,id=n7 -device virtio-net-pci,netdev=n7,mac={macbase}:07,romfile="" \
 | |
|         -device virtio-scsi-pci,id=scsi0 \
 | |
|         -drive format=raw,file={disk_img},if=none,media=disk,id=drive-hd1,readonly=off \
 | |
|         -device scsi-hd,bus=scsi0.0,drive=drive-hd1,id=hd1,bootindex=1'
 | |
| 
 | |
|     if raid:
 | |
|         cmd += f' -drive format=raw,file={raid},if=none,media=disk,id=drive-hd2,readonly=off' \
 | |
|                f' -device scsi-hd,bus=scsi0.0,drive=drive-hd2,id=hd2,bootindex=2'
 | |
| 
 | |
|     if tpm:
 | |
|         cmd += f' -chardev socket,id=chrtpm,path={tpm_folder}/swtpm-sock' \
 | |
|                ' -tpmdev emulator,id=tpm0,chardev=chrtpm' \
 | |
|                ' -device tpm-tis,tpmdev=tpm0'
 | |
| 
 | |
|     return cmd
 | |
| 
 | |
| def shutdownVM(c, log, message=''):
 | |
|     #################################################
 | |
|     # Powering off system
 | |
|     #################################################
 | |
|     if message:
 | |
|         log.info(message)
 | |
| 
 | |
|     c.sendline('poweroff now')
 | |
|     log.info('Shutting down virtual machine')
 | |
|     for i in range(30):
 | |
|         log.info('Waiting for shutdown...')
 | |
|         # Shutdown in qemu doesnt work first time
 | |
|         # Use this workaround
 | |
|         # https://vyos.dev/T5024
 | |
|         c.sendline('poweroff now')
 | |
|         if not c.isalive():
 | |
|             log.info('VM is shut down!')
 | |
|             break
 | |
|         time.sleep(10)
 | |
|     else:
 | |
|         tmp = 'VM Did not shut down after 300sec'
 | |
|         log.error(tmp)
 | |
|         raise Exception(tmp)
 | |
| 
 | |
| def loginVM(c, log):
 | |
|     log.info('Waiting for login prompt')
 | |
|     c.expect('[Ll]ogin:', timeout=600)
 | |
|     c.sendline(default_user)
 | |
|     c.expect('[Pp]assword:')
 | |
|     c.sendline(default_password)
 | |
|     c.expect(op_mode_prompt)
 | |
|     log.info('Logged in!')
 | |
| 
 | |
| # Setting up logger
 | |
| log = logging.getLogger()
 | |
| log.setLevel(logging.DEBUG)
 | |
| 
 | |
| stl = StreamToLogger(log)
 | |
| formatter = logging.Formatter('%(levelname)5s - %(message)s')
 | |
| 
 | |
| handler = logging.StreamHandler(sys.stdout)
 | |
| if args.silent:
 | |
|     handler.setLevel(logging.ERROR)
 | |
| elif args.debug:
 | |
|     handler.setLevel(logging.DEBUG)
 | |
| else:
 | |
|     handler.setLevel(logging.INFO)
 | |
| 
 | |
| handler.setFormatter(formatter)
 | |
| log.addHandler(handler)
 | |
| 
 | |
| if args.logfile:
 | |
|     filehandler = logging.FileHandler(args.logfile)
 | |
|     filehandler.setLevel(logging.DEBUG)
 | |
|     filehandler.setFormatter(formatter)
 | |
|     log.addHandler(filehandler)
 | |
| 
 | |
| if args.silent:
 | |
|     output = BytesIO()
 | |
| else:
 | |
|     output = sys.stdout.buffer
 | |
| 
 | |
| if not os.path.isfile(args.iso):
 | |
|     log.error('Unable to find iso image to install')
 | |
|     sys.exit(1)
 | |
| 
 | |
| if not os.path.exists('/dev/kvm'):
 | |
|     log.error('KVM not enabled on host, proceeding with software emulation')
 | |
|     sys.exit(1)
 | |
| 
 | |
| # Creating diskimage!!
 | |
| diskname_raid = None
 | |
| def gen_disk(name):
 | |
|     if not os.path.isfile(name):
 | |
|         log.info(f'Creating Disk image {name}')
 | |
|         c = subprocess.check_output(['qemu-img', 'create', name, '2G'])
 | |
|         log.debug(c.decode())
 | |
|     else:
 | |
|         log.info(f'Diskimage "{name}" already exists, using the existing one.')
 | |
| 
 | |
| if args.raid:
 | |
|     filename, ext = os.path.splitext(args.disk)
 | |
|     diskname_raid = f'{filename}_disk1{ext}'
 | |
|     # change primary diskname, too
 | |
|     args.disk = f'{filename}_disk0{ext}'
 | |
|     gen_disk(diskname_raid)
 | |
| 
 | |
| # must be called after the raid disk as args.disk name is altered in the RAID path
 | |
| gen_disk(args.disk)
 | |
| 
 | |
| # Create software emulated TPM
 | |
| def start_swtpm():
 | |
|     if not os.path.exists(tpm_folder):
 | |
|         os.mkdir(tpm_folder)
 | |
| 
 | |
|     def swtpm_thread():
 | |
|         c = subprocess.check_output([
 | |
|                 'swtpm', 'socket', '--tpmstate', f'dir={tpm_folder}',
 | |
|                 '--ctrl', f'type=unixio,path={tpm_folder}/swtpm-sock', '--tpm2', '--log', 'level=1'
 | |
|             ])
 | |
| 
 | |
|     from multiprocessing import Process
 | |
|     tpm_process = Process(target=swtpm_thread)
 | |
|     tpm_process.start()
 | |
|     return tpm_process
 | |
| 
 | |
| def toggleUEFISecureBoot(c):
 | |
|     def UEFIKeyPress(c, key):
 | |
|         UEFI_SLEEP = 1
 | |
|         c.send(key)
 | |
|         time.sleep(UEFI_SLEEP)
 | |
| 
 | |
|     # Enter UEFI
 | |
|     for ii in range(1, 10):
 | |
|         c.send(KEY_F2)
 | |
|         time.sleep(0.250)
 | |
| 
 | |
|     time.sleep(10)
 | |
| 
 | |
|     # Device Manager
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_RETURN)
 | |
| 
 | |
|     # Secure Boot Configuration
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_RETURN)
 | |
| 
 | |
|     # Attempt Secure Boot Toggle
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_RETURN)
 | |
|     UEFIKeyPress(c, KEY_RETURN)
 | |
| 
 | |
|     # Save Secure Boot
 | |
|     UEFIKeyPress(c, KEY_F10)
 | |
|     UEFIKeyPress(c, KEY_Y)
 | |
| 
 | |
|     # Go Back to Menu
 | |
|     UEFIKeyPress(c, KEY_ESC)
 | |
|     UEFIKeyPress(c, KEY_ESC)
 | |
| 
 | |
|     # Go Down for reset
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_DOWN)
 | |
|     UEFIKeyPress(c, KEY_RETURN)
 | |
| 
 | |
| if args.qemu_cmd:
 | |
|     tmp = get_qemu_cmd(qemu_name, args.uefi, args.disk, raid=diskname_raid, iso_img=args.iso, vnc_enabled=args.vnc, secure_boot=args.sbtest)
 | |
|     os.system(tmp)
 | |
|     exit(0)
 | |
| 
 | |
| test_timeout = 5 *3600 # 3 hours (in seconds)
 | |
| tpm_process = None
 | |
| try:
 | |
|     # Start TPM emulator
 | |
|     if args.tpmtest:
 | |
|         tpm_process = start_swtpm()
 | |
| 
 | |
|     #################################################
 | |
|     # Installing image to disk
 | |
|     #################################################
 | |
|     log.info('Installing system')
 | |
|     cmd = get_qemu_cmd(qemu_name, args.uefi, args.disk, raid=diskname_raid, tpm=args.tpmtest, iso_img=args.iso, vnc_enabled=args.vnc, secure_boot=args.sbtest)
 | |
|     log.debug(f'Executing command: {cmd}')
 | |
|     c = pexpect.spawn(cmd, logfile=stl, timeout=60)
 | |
| 
 | |
|     #################################################
 | |
|     # Logging into VyOS system
 | |
|     #################################################
 | |
|     op_mode_prompt = r'vyos@vyos:~\$'
 | |
|     cfg_mode_prompt = r'vyos@vyos#'
 | |
|     default_user = 'vyos'
 | |
|     default_password = 'vyos'
 | |
| 
 | |
|     if args.sbtest:
 | |
|         log.info('Disable UEFI Secure Boot for initial installation')
 | |
|         toggleUEFISecureBoot(c)
 | |
| 
 | |
|     try:
 | |
|         c.expect('Welcome to GRUB', timeout=10)
 | |
|         c.send(KEY_DOWN)
 | |
|         c.send(KEY_DOWN)
 | |
|         c.send(KEY_RETURN)
 | |
|     except pexpect.TIMEOUT:
 | |
|         log.warning('Did not find GRUB countdown window, ignoring')
 | |
| 
 | |
|     loginVM(c, log)
 | |
| 
 | |
|     #################################################
 | |
|     # Check for no private key contents within the image
 | |
|     #################################################
 | |
|     msg = 'Found private key - bailing out'
 | |
|     c.sendline(f'if sudo grep -rq "BEGIN PRIVATE KEY" /var/lib/shim-signed/mok; then echo {msg}; exit 1; fi')
 | |
|     tmp = c.expect([f'\n{msg}', op_mode_prompt])
 | |
|     if tmp == 0:
 | |
|         log.error(msg)
 | |
|         exit(1)
 | |
| 
 | |
|     #################################################
 | |
|     # Configure boot options if required
 | |
|     #################################################
 | |
|     if args.huge_page_size and args.huge_page_count:
 | |
|         c.sendline('configure')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline(f'set system option kernel memory hugepage-size {args.huge_page_size} hugepage-count {args.huge_page_count}')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('set system option kernel disable-mitigations')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('commit')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('save')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('exit')
 | |
|         c.expect(op_mode_prompt)
 | |
|     #################################################
 | |
|     # Installing into VyOS system
 | |
|     #################################################
 | |
|     log.info('Starting installer')
 | |
|     c.sendline('install image')
 | |
|     c.expect('\nWould you like to continue?.*')
 | |
|     c.sendline('y')
 | |
|     c.expect('\nWhat would you like to name this image?.*')
 | |
|     c.sendline('')
 | |
|     c.expect(f'\nPlease enter a password for the "{default_user}" user.*')
 | |
|     c.sendline('vyos')
 | |
|     c.expect(f'\nPlease confirm password for the "{default_user}" user.*')
 | |
|     c.sendline('vyos')
 | |
|     c.expect('\nWhat console should be used by default?.*')
 | |
|     c.sendline('S')
 | |
| 
 | |
|     if args.raid:
 | |
|         c.expect('\nWould you like to configure RAID-1 mirroring??.*')
 | |
|         c.sendline('y')
 | |
|         c.expect('\nWould you like to configure RAID-1 mirroring on them?.*')
 | |
|         c.sendline('y')
 | |
|         c.expect('\nInstallation will delete all data on both drives. Continue?.*')
 | |
|         c.sendline('y')
 | |
|         c.expect('\nWhich file would you like as boot config?.*')
 | |
|         c.sendline('')
 | |
|     else:
 | |
|         c.expect('\nWhich one should be used for installation?.*')
 | |
|         c.sendline('')
 | |
|         c.expect('\nInstallation will delete all data on the drive. Continue?.*')
 | |
|         c.sendline('y')
 | |
|         c.expect('\nWould you like to use all the free space on the drive?.*')
 | |
|         c.sendline('y')
 | |
|         c.expect('\nWhich file would you like as boot config?.*')
 | |
|         c.sendline('')
 | |
| 
 | |
|     c.expect(op_mode_prompt)
 | |
| 
 | |
|     if args.sbtest:
 | |
|         c.sendline('install mok')
 | |
|         c.expect('input password:.*')
 | |
|         c.sendline(mok_password)
 | |
|         c.expect('input password again:.*')
 | |
|         c.sendline(mok_password)
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|     log.info('system installed, rebooting')
 | |
|     c.sendline('reboot now')
 | |
| 
 | |
|     #################################################
 | |
|     # SHIM Mok Manager
 | |
|     #################################################
 | |
|     if args.sbtest:
 | |
|         log.info('Install Secure Boot Machine Owner Key')
 | |
|         MOK_SLEEP = 0.5
 | |
|         c.expect('BdsDxe: starting Boot00.*')
 | |
|         time.sleep(3)
 | |
|         # press any key
 | |
|         c.send(KEY_RETURN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
| 
 | |
|         # Enroll MOK
 | |
|         c.send(KEY_DOWN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
|         c.send(KEY_RETURN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
| 
 | |
|         # Continue
 | |
|         c.send(KEY_DOWN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
|         c.send(KEY_RETURN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
| 
 | |
|         # Enroll Keys
 | |
|         c.send(KEY_DOWN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
|         c.send(KEY_RETURN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
| 
 | |
|         c.sendline(mok_password)
 | |
|         c.send(KEY_RETURN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
| 
 | |
|         # Reboot
 | |
|         c.send(KEY_RETURN)
 | |
|         time.sleep(MOK_SLEEP)
 | |
| 
 | |
|     #################################################
 | |
|     # Re-Enable Secure Boot
 | |
|     #################################################
 | |
|     if args.sbtest:
 | |
|         log.info('Enable UEFI Secure Boot for initial installation')
 | |
|         toggleUEFISecureBoot(c)
 | |
| 
 | |
|     #################################################
 | |
|     # Removing CD installation media
 | |
|     #################################################
 | |
|     time.sleep(2)
 | |
|     log.info('eject installation media')
 | |
|     os.system(f'echo "eject -f drive-cd1" | socat - unix-connect:/tmp/qemu-monitor-socket-{args.disk}')
 | |
| 
 | |
|     #################################################
 | |
|     # Booting installed system
 | |
|     #################################################
 | |
|     log.info('Booting installed system')
 | |
| 
 | |
|     #################################################
 | |
|     # Logging into VyOS system
 | |
|     #################################################
 | |
|     try:
 | |
|         c.expect('The highlighted entry will be executed automatically in', timeout=10)
 | |
|         c.sendline('')
 | |
|     except pexpect.TIMEOUT:
 | |
|         log.warning('Did not find GRUB countdown window, ignoring')
 | |
| 
 | |
|     loginVM(c, log)
 | |
| 
 | |
|     #################################################
 | |
|     # Boot options require a reboot
 | |
|     #################################################
 | |
|     if args.huge_page_size and args.huge_page_count:
 | |
|         log.info('Rebooting to apply kernel boot options')
 | |
|         c.sendline('reboot now')
 | |
|         loginVM(c, log)
 | |
| 
 | |
|     ################################################
 | |
|     # Always load the WiFi simulation module
 | |
|     ################################################
 | |
|     c.sendline('sudo modprobe mac80211_hwsim')
 | |
|     c.expect(op_mode_prompt)
 | |
| 
 | |
|     # Inform smoketest about this environment
 | |
|     c.sendline('touch /tmp/vyos.smoketests.hint')
 | |
|     c.expect(op_mode_prompt)
 | |
| 
 | |
|     #################################################
 | |
|     # Start/stop config daemon
 | |
|     #################################################
 | |
|     if args.configd:
 | |
|         c.sendline('sudo systemctl restart vyos-configd.service &> /dev/null')
 | |
|     else:
 | |
|         c.sendline('sudo systemctl stop vyos-configd.service &> /dev/null')
 | |
|     c.expect(op_mode_prompt)
 | |
| 
 | |
|     #################################################
 | |
|     # Basic Configmode/Opmode switch
 | |
|     #################################################
 | |
|     log.info('Basic CLI configuration mode test')
 | |
| 
 | |
|     c.sendline('configure')
 | |
|     c.expect(cfg_mode_prompt)
 | |
|     c.sendline('exit')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show version')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show version kernel')
 | |
|     c.expect(f'{vyos_defaults["kernel_version"]}-{vyos_defaults["kernel_flavor"]}')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show version frr')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show interfaces')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('systemd-detect-virt')
 | |
|     c.expect('kvm')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show system cpu')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show system memory')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show system memory detail | no-more')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show configuration commands | match kernel')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('cat /proc/cmdline')
 | |
|     c.expect(op_mode_prompt)
 | |
|     c.sendline('show version all | grep -e "vpp" -e "vyos-1x"')
 | |
|     c.expect(op_mode_prompt)
 | |
| 
 | |
|     #################################################
 | |
|     # Verify /etc/os-release via lsb_release
 | |
|     #################################################
 | |
|     c.sendline('lsb_release --short --id 2>/dev/null')
 | |
|     c.expect('VyOS')
 | |
|     if os.path.isfile(manifest_file):
 | |
|         c.sendline('lsb_release --short --release 2>/dev/null')
 | |
|         c.expect(vyos_version)
 | |
|         c.sendline('lsb_release --short --codename 2>/dev/null')
 | |
|         c.expect(vyos_codename)
 | |
| 
 | |
|     # Ensure ephemeral key is loaded
 | |
|     vyos_kernel_key = 'VyOS build time autogenerated kernel key'
 | |
|     c.sendline(f'show log kernel | match "{vyos_kernel_key}"')
 | |
|     c.expect(f'.*{vyos_kernel_key}.*')
 | |
|     c.expect(op_mode_prompt)
 | |
| 
 | |
|     #################################################
 | |
|     # Executing test-suite
 | |
|     #################################################
 | |
|     if args.tpmtest:
 | |
|         def verify_mount():
 | |
|             # Verify encrypted and mounted
 | |
|             c.sendline('mount | grep vyos_config')
 | |
|             c.expect('/dev/mapper/vyos_config on /opt/vyatta/etc/config.*')
 | |
|             c.expect(op_mode_prompt)
 | |
| 
 | |
|         def verify_config():
 | |
|             # Verify encrypted config is loaded
 | |
|             c.sendline('show config commands | cat')
 | |
|             c.expect('set system option performance \'network-latency\'')
 | |
|             c.expect('set system option reboot-on-panic')
 | |
|             c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('Running TPM encrypted config tests')
 | |
| 
 | |
|         tpm_timeout = 600 # Give it 10 mins to encrypt
 | |
| 
 | |
|         # Verify TPM is loaded
 | |
|         c.sendline('find /dev -name tpm0')
 | |
|         c.expect('/dev/tpm0')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         # Create recovery key
 | |
|         import string
 | |
|         from random import choices
 | |
|         test_recovery_key = ''.join(choices(string.ascii_uppercase + string.digits, k=32))
 | |
| 
 | |
|         log.info('Encrypting config to TPM')
 | |
|         c.sendline('encryption enable')
 | |
|         c.expect('Automatically generate a recovery key\?.*')
 | |
|         c.sendline('n')
 | |
|         c.expect('Enter recovery key: ')
 | |
|         c.sendline(test_recovery_key)
 | |
|         c.expect('Enter size of encrypted config partition.*', timeout=30)
 | |
|         c.sendline('32')
 | |
|         c.expect('Encrypted config volume has been enabled', timeout=tpm_timeout)
 | |
|         c.expect('Backup the recovery key in a safe place!')
 | |
|         c.expect(f'Recovery key: {test_recovery_key}')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         verify_mount()
 | |
| 
 | |
|         # Add some non-default config nodes this encrypted config
 | |
|         log.info('Adding nodes for encrypted config test')
 | |
|         c.sendline('configure')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('set system option performance network-latency')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('set system option reboot-on-panic')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('commit')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('save')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('exit')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('system installed, rebooting')
 | |
|         c.sendline('reboot now')
 | |
| 
 | |
|         try:
 | |
|             c.expect('The highlighted entry will be executed automatically in', timeout=10)
 | |
|             c.sendline('')
 | |
|         except pexpect.TIMEOUT:
 | |
|             log.warning('Did not find GRUB countdown window, ignoring')
 | |
| 
 | |
|         # Check for vyos-router message
 | |
|         c.expect('.*Mounted encrypted config volume', timeout=120)
 | |
| 
 | |
|         loginVM(c, log)
 | |
| 
 | |
|         verify_mount()
 | |
|         verify_config()
 | |
| 
 | |
|         # Shutdown VM
 | |
|         shutdownVM(c, log, 'Shutdown VM for TPM fail test')
 | |
| 
 | |
|         # Clear swtpm
 | |
|         from glob import glob
 | |
|         for f in glob(f'{tpm_folder}/*'):
 | |
|             os.remove(f)
 | |
| 
 | |
|         # Shutdown kills swtpm
 | |
|         tpm_process.join()
 | |
|         tpm_process.close()
 | |
| 
 | |
|         # Start emulator again
 | |
|         tpm_process = start_swtpm()
 | |
| 
 | |
|         # Booting back into VM
 | |
|         log.info('Booting system with cleared TPM')
 | |
|         cmd = get_qemu_cmd(qemu_name, args.uefi, args.disk, raid=diskname_raid, tpm=args.tpmtest, vnc_enabled=args.vnc)
 | |
|         log.debug(f'Executing command: {cmd}')
 | |
|         c = pexpect.spawn(cmd, logfile=stl)
 | |
| 
 | |
|         try:
 | |
|             c.expect('The highlighted entry will be executed automatically in', timeout=10)
 | |
|             c.sendline('')
 | |
|         except pexpect.TIMEOUT:
 | |
|             log.warning('Did not find GRUB countdown window, ignoring')
 | |
| 
 | |
|         c.expect('.*Encrypted config volume has not been mounted', timeout=120)
 | |
| 
 | |
|         loginVM(c, log)
 | |
| 
 | |
|         # Test loading config with recovery key
 | |
|         c.sendline('encryption load')
 | |
|         c.expect('Enter recovery key: ')
 | |
|         c.sendline(test_recovery_key)
 | |
|         c.expect('Encrypted config volume has been mounted', timeout=120)
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         verify_mount()
 | |
| 
 | |
|         log.info('Loading encrypted config.boot')
 | |
|         c.sendline('configure')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('load /opt/vyatta/etc/config/config.boot')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('commit')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('exit')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         verify_config()
 | |
| 
 | |
|         # Shutdown VM
 | |
|         shutdownVM(c, log, 'Shutdown VM for non-TPM backed test')
 | |
| 
 | |
|         # Clear swtpm
 | |
|         from glob import glob
 | |
|         for f in glob(f'{tpm_folder}/*'):
 | |
|             os.remove(f)
 | |
| 
 | |
|         # Shutdown kills swtpm
 | |
|         tpm_process.join()
 | |
|         tpm_process.close()
 | |
|         tpm_process = None
 | |
| 
 | |
|         # Booting back into VM
 | |
|         log.info('Booting system without TPM')
 | |
|         cmd = get_qemu_cmd(qemu_name, args.uefi, args.disk, raid=diskname_raid, tpm=False, vnc_enabled=args.vnc)
 | |
|         log.debug(f'Executing command: {cmd}')
 | |
|         c = pexpect.spawn(cmd, logfile=stl)
 | |
| 
 | |
|         try:
 | |
|             c.expect('The highlighted entry will be executed automatically in', timeout=10)
 | |
|             c.sendline('')
 | |
|         except pexpect.TIMEOUT:
 | |
|             log.warning('Did not find GRUB countdown window, ignoring')
 | |
| 
 | |
|         loginVM(c, log)
 | |
| 
 | |
|         # New recovery key
 | |
|         test_recovery_key = ''.join(choices(string.ascii_uppercase + string.digits, k=32))
 | |
| 
 | |
|         log.info('Encrypting config')
 | |
|         c.sendline('encryption enable')
 | |
|         c.expect('Are you sure you want to proceed\?.*')
 | |
|         c.sendline('y')
 | |
|         c.expect('Enter key: ')
 | |
|         c.sendline(test_recovery_key)
 | |
|         c.expect('Enter size of encrypted config partition.*', timeout=30)
 | |
|         c.sendline('32')
 | |
|         c.expect('Encrypted config volume has been enabled', timeout=tpm_timeout)
 | |
|         c.expect('Backup the key in a safe place!')
 | |
|         c.expect(f'Key: {test_recovery_key}')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         verify_mount()
 | |
| 
 | |
|         shutdownVM(c, log, 'Shutdown VM for non-TPM config load')
 | |
| 
 | |
|         # Booting back into VM
 | |
|         log.info('Booting system without TPM')
 | |
|         cmd = get_qemu_cmd(qemu_name, args.uefi, args.disk, raid=diskname_raid, tpm=False, vnc_enabled=args.vnc)
 | |
|         log.debug(f'Executing command: {cmd}')
 | |
|         c = pexpect.spawn(cmd, logfile=stl)
 | |
| 
 | |
|         try:
 | |
|             c.expect('The highlighted entry will be executed automatically in', timeout=10)
 | |
|             c.sendline('')
 | |
|         except pexpect.TIMEOUT:
 | |
|             log.warning('Did not find GRUB countdown window, ignoring')
 | |
| 
 | |
|         c.expect('.*encrypted config volume will not be automatically mounted', timeout=120)
 | |
| 
 | |
|         loginVM(c, log)
 | |
| 
 | |
|         # Test loading config with recovery key
 | |
|         c.sendline('encryption load')
 | |
|         c.expect('Enter key: ')
 | |
|         c.sendline(test_recovery_key)
 | |
|         c.expect('Encrypted config volume has been mounted', timeout=120)
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         verify_mount()
 | |
| 
 | |
|         log.info('Loading encrypted config.boot')
 | |
|         c.sendline('configure')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('load /opt/vyatta/etc/config/config.boot')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('commit')
 | |
|         c.expect(cfg_mode_prompt)
 | |
|         c.sendline('exit')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|     elif args.raid:
 | |
|         # Verify RAID subsystem - by deleting a disk and re-create the array
 | |
|         # from scratch
 | |
|         c.sendline('cat /proc/mdstat')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         shutdownVM(c, log, f'Shutdown VM and start with empty RAID member "{args.disk}"')
 | |
| 
 | |
|         if os.path.exists(args.disk):
 | |
|             os.unlink(args.disk)
 | |
| 
 | |
|         gen_disk(args.disk)
 | |
| 
 | |
|         #################################################
 | |
|         # Booting RAID-1 system with one missing disk
 | |
|         #################################################
 | |
|         log.info('Booting RAID-1 system')
 | |
|         cmd = get_qemu_cmd(qemu_name, args.uefi, args.disk, raid=diskname_raid, vnc_enabled=args.vnc)
 | |
| 
 | |
|         # We need to swap boot indexes to boot from second harddisk so we can
 | |
|         # recreate the RAID on the first disk
 | |
|         cmd = cmd.replace('bootindex=1', 'bootindex=X')
 | |
|         cmd = cmd.replace('bootindex=2', 'bootindex=1')
 | |
|         cmd = cmd.replace('bootindex=X', 'bootindex=2')
 | |
| 
 | |
|         log.debug(f'Executing command: {cmd}')
 | |
|         c = pexpect.spawn(cmd, logfile=stl)
 | |
| 
 | |
|         #################################################
 | |
|         # Logging into VyOS system
 | |
|         #################################################
 | |
|         try:
 | |
|             c.expect('The highlighted entry will be executed automatically in', timeout=10)
 | |
|             c.sendline('')
 | |
|         except pexpect.TIMEOUT:
 | |
|             log.warning('Did not find GRUB countdown window, ignoring')
 | |
| 
 | |
|         loginVM(c, log)
 | |
| 
 | |
|         c.sendline('cat /proc/mdstat')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('Re-format new RAID member')
 | |
|         c.sendline('format by-id disk drive-hd1 like drive-hd2')
 | |
|         c.sendline('yes')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('Add member to RAID1 (md0)')
 | |
|         c.sendline('add raid md0 by-id member drive-hd1-part3')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('Now we need to wait for re-sync to complete')
 | |
| 
 | |
|         start_time = time.time()
 | |
|         timeout = 60
 | |
|         while True:
 | |
|             if (start_time + timeout) < time.time():
 | |
|                 break
 | |
|             c.sendline('cat /proc/mdstat')
 | |
|             c.expect(op_mode_prompt)
 | |
|             time.sleep(20)
 | |
| 
 | |
|         # Reboot system with new primary RAID1 disk
 | |
|         shutdownVM(c, log, f'Shutdown VM and start from recovered RAID member "{args.disk}"')
 | |
| 
 | |
|         log.info('Booting RAID-1 system')
 | |
|         cmd = get_qemu_cmd(qemu_name, args.uefi, args.disk, raid=diskname_raid, vnc_enabled=args.vnc)
 | |
|         log.debug(f'Executing command: {cmd}')
 | |
|         c = pexpect.spawn(cmd, logfile=stl)
 | |
| 
 | |
|         loginVM(c, log)
 | |
| 
 | |
|         c.sendline('cat /proc/mdstat')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|     elif args.smoketest:
 | |
|         # run default smoketest suite
 | |
|         if args.match:
 | |
|             # Remove tests that we don't want to run
 | |
|             match_str = '-o '.join([f'-name "test_*{name}*.py" ' for name in args.match.split("|")]).strip()
 | |
|             c.sendline(f'sudo find /usr/libexec/vyos/tests/smoke -maxdepth 2 -type f -name test_* ! \( {match_str} \) -delete')
 | |
|             c.expect(op_mode_prompt)
 | |
|         if args.no_interfaces:
 | |
|             # remove interface tests as they consume a lot of time
 | |
|             c.sendline('sudo rm -f /usr/libexec/vyos/tests/smoke/cli/test_interfaces_*')
 | |
|             c.expect(op_mode_prompt)
 | |
|         if args.no_vpp:
 | |
|             # remove VPP tests
 | |
|             c.sendline('sudo rm -f /usr/libexec/vyos/tests/smoke/cli/test_vpp*')
 | |
|             c.expect(op_mode_prompt)
 | |
| 
 | |
|         if args.vyconf:
 | |
|             c.sendline('sudo /usr/libexec/vyos/set_vyconf_backend.py --no-prompt &> /dev/null')
 | |
|             c.expect(op_mode_prompt)
 | |
|             log.info('Smoketests will be run using vyconfd/vyos-commitd')
 | |
| 
 | |
|         log.info('Executing VyOS smoketests')
 | |
|         c.sendline('/usr/bin/vyos-smoketest')
 | |
|         i = c.expect(['\n +Invalid command:', '\n +Set failed',
 | |
|                       'No such file or directory', r'\n\S+@\S+[$#]'], timeout=test_timeout)
 | |
| 
 | |
|         if i == 0:
 | |
|             raise Exception('Invalid command detected')
 | |
|         elif i == 1:
 | |
|             raise Exception('Set syntax failed :/')
 | |
|         elif i == 2:
 | |
|             tmp = '(W)hy (T)he (F)ace? VyOS smoketest not found!'
 | |
|             log.error(tmp)
 | |
|             raise Exception(tmp)
 | |
| 
 | |
|         c.sendline('echo EXITCODE:$\x16?')
 | |
|         i = c.expect(['EXITCODE:0', 'EXITCODE:\d+'])
 | |
|         if i == 0:
 | |
|             log.info('Smoketest finished successfully!')
 | |
|             pass
 | |
|         elif i == 1:
 | |
|             log.error('Smoketest failed :/')
 | |
|             raise Exception("Smoketest-failed, please look into debug output")
 | |
| 
 | |
|     # else, run configtest suite
 | |
|     elif args.configtest:
 | |
|         # Remove config-tests that we don't want to run
 | |
|         if args.match:
 | |
|             if args.match.startswith("!"):
 | |
|                 # Exclude mode — delete only the matched names
 | |
|                 names = args.match[1:].split("|")
 | |
|                 match_str = '-o '.join([f'-name "{name}"' for name in names])
 | |
|                 cleanup_config_dir_cmd = f'sudo find /usr/libexec/vyos/tests/config -mindepth 1 -maxdepth 1 \\( {match_str} \\) -exec rm -rf {{}} +'
 | |
|                 cleanup_config_tests_dir_cmd = f'sudo find /usr/libexec/vyos/tests/config-tests -mindepth 1 -maxdepth 1 \\( {match_str} \\) -exec rm -rf {{}} +'
 | |
|             else:
 | |
|                 # Include mode — keep only the matched names, delete the rest
 | |
|                 names = args.match.split("|")
 | |
|                 match_str = '-o '.join([f'-name "{name}"' for name in names])
 | |
|                 cleanup_config_dir_cmd = f'sudo find /usr/libexec/vyos/tests/config -mindepth 1 -maxdepth 1 ! \\( {match_str} \\) -exec rm -rf {{}} +'
 | |
|                 cleanup_config_tests_dir_cmd = f'sudo find /usr/libexec/vyos/tests/config-tests -mindepth 1 -maxdepth 1 ! \\( {match_str} \\) -exec rm -rf {{}} +'
 | |
| 
 | |
|             c.sendline(cleanup_config_dir_cmd)
 | |
|             c.expect(op_mode_prompt)
 | |
|             c.sendline(cleanup_config_tests_dir_cmd)
 | |
|             c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('Adding a legacy WireGuard default keypair for migrations')
 | |
|         c.sendline('sudo mkdir -p /config/auth/wireguard/default')
 | |
|         c.expect(op_mode_prompt)
 | |
|         c.sendline('echo "aGx+fvW916Ej7QRnBbW3QMoldhNv1u95/WHz45zDmF0=" | sudo tee /config/auth/wireguard/default/private.key')
 | |
|         c.expect(op_mode_prompt)
 | |
|         c.sendline('echo "x39C77eavJNpvYbNzPSG3n1D68rHYei6q3AEBEyL1z8=" | sudo tee /config/auth/wireguard/default/public.key')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('Generating PKI objects')
 | |
|         c.sendline(f'/usr/bin/vyos-configtest-pki')
 | |
|         c.expect(op_mode_prompt, timeout=900)
 | |
| 
 | |
|         script_file = '/config/scripts/vyos-foo-update.script'
 | |
|         c.sendline(f'echo "#!/bin/sh" > {script_file}; chmod 775 {script_file}')
 | |
|         c.expect(op_mode_prompt)
 | |
| 
 | |
|         log.info('Executing load config tests')
 | |
|         c.sendline('/usr/bin/vyos-configtest')
 | |
|         i = c.expect(['\n +Invalid command:', 'No such file or directory',
 | |
|                      r'\n\S+@\S+[$#]'], timeout=test_timeout)
 | |
| 
 | |
|         if i==0:
 | |
|             raise Exception('Invalid command detected')
 | |
|         elif i==1:
 | |
|             tmp = 'VyOS smoketest not found!'
 | |
|             log.error(tmp)
 | |
|             raise Exception(tmp)
 | |
| 
 | |
|         c.sendline('echo EXITCODE:$\x16?')
 | |
|         i = c.expect(['EXITCODE:0', 'EXITCODE:\d+'])
 | |
|         if i == 0:
 | |
|             log.info('Configtest finished successfully!')
 | |
|             pass
 | |
|         elif i == 1:
 | |
|             tmp = 'Configtest failed :/ - check debug output'
 | |
|             log.error(tmp)
 | |
|             raise Exception(tmp)
 | |
|     elif args.sbtest:
 | |
|         c.sendline('show secure-boot')
 | |
|         c.expect('SecureBoot enabled')
 | |
|         c.expect(op_mode_prompt)
 | |
|     else:
 | |
|         log.info('No testcase selected!')
 | |
| 
 | |
|     shutdownVM(c, log, 'Powering off system')
 | |
|     c.close()
 | |
| 
 | |
| except pexpect.exceptions.TIMEOUT:
 | |
|     log.error('Timeout waiting for VyOS system')
 | |
|     log.error(traceback.format_exc())
 | |
|     EXCEPTION = 1
 | |
| 
 | |
| except pexpect.exceptions.ExceptionPexpect:
 | |
|     log.error('Exeption while executing QEMU')
 | |
|     log.error('Is qemu working on this system?')
 | |
|     log.error(traceback.format_exc())
 | |
|     EXCEPTION = 1
 | |
| 
 | |
| except Exception:
 | |
|     log.error('Unknown error occured!')
 | |
|     traceback.print_exc()
 | |
|     EXCEPTION = 1
 | |
| 
 | |
| #################################################
 | |
| # Cleaning up
 | |
| #################################################
 | |
| log.info("Cleaning up")
 | |
| 
 | |
| if tpm_process:
 | |
|     tpm_process.terminate()
 | |
|     tpm_process.join()
 | |
| 
 | |
| if not args.keep:
 | |
|     log.info(f'Removing disk file: {args.disk}')
 | |
|     try:
 | |
|         os.remove(args.disk)
 | |
|         if diskname_raid:
 | |
|             os.remove(diskname_raid)
 | |
|         if args.sbtest:
 | |
|             os.remove(OVMF_VARS_TMP)
 | |
|     except Exception:
 | |
|         log.error('Exception while removing diskimage!')
 | |
|         log.error(traceback.format_exc())
 | |
|         EXCEPTION = 1
 | |
| 
 | |
| if EXCEPTION:
 | |
|     log.error('Hmm... system got an exception while processing.')
 | |
|     log.error('The ISO image is not considered usable!')
 | |
|     sys.exit(1)
 | |
| 
 | |
| sys.exit(0)
 |