Complete Yocto mirror with license table for TQMa6UL (2038-compliance)
- 264 license table entries with exact download URLs (224/264 resolved) - Complete sources/ directory with all BitBake recipes - Build configuration: tqma6ul-multi-mba6ulx, spaetzle (musl) - Full traceability for Softwarefreigabeantrag - GCC 13.4.0, Linux 6.6.102, U-Boot 2023.04, musl 1.2.4 - License distribution: GPL-2.0 (24), MIT (23), GPL-2.0+ (18), BSD-3 (16)
This commit is contained in:
235
sources/poky/meta/lib/oeqa/targetcontrol.py
Normal file
235
sources/poky/meta/lib/oeqa/targetcontrol.py
Normal file
@@ -0,0 +1,235 @@
|
||||
#
|
||||
# Copyright (C) 2013 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
# This module is used by testimage.bbclass for setting up and controlling a target machine.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import bb
|
||||
import logging
|
||||
from oeqa.utils.sshcontrol import SSHControl
|
||||
from oeqa.utils.qemurunner import QemuRunner
|
||||
from oeqa.utils.qemutinyrunner import QemuTinyRunner
|
||||
from oeqa.utils.dump import TargetDumper
|
||||
from oeqa.utils.dump import MonitorDumper
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
class BaseTarget(object, metaclass=ABCMeta):
|
||||
|
||||
supported_image_fstypes = []
|
||||
|
||||
def __init__(self, d, logger):
|
||||
self.connection = None
|
||||
self.ip = None
|
||||
self.server_ip = None
|
||||
self.datetime = d.getVar('DATETIME')
|
||||
self.testdir = d.getVar("TEST_LOG_DIR")
|
||||
self.pn = d.getVar("PN")
|
||||
self.logger = logger
|
||||
|
||||
@abstractmethod
|
||||
def deploy(self):
|
||||
|
||||
self.sshlog = os.path.join(self.testdir, "ssh_target_log.%s" % self.datetime)
|
||||
sshloglink = os.path.join(self.testdir, "ssh_target_log")
|
||||
if os.path.islink(sshloglink):
|
||||
os.unlink(sshloglink)
|
||||
os.symlink(self.sshlog, sshloglink)
|
||||
self.logger.info("SSH log file: %s" % self.sshlog)
|
||||
|
||||
@abstractmethod
|
||||
def start(self, params=None, ssh=True, extra_bootparams=None):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def get_extra_files(self):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def match_image_fstype(self, d, image_fstypes=None):
|
||||
if not image_fstypes:
|
||||
image_fstypes = d.getVar('IMAGE_FSTYPES').split(' ')
|
||||
possible_image_fstypes = [fstype for fstype in self.supported_image_fstypes if fstype in image_fstypes]
|
||||
if possible_image_fstypes:
|
||||
return possible_image_fstypes[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_image_fstype(self, d):
|
||||
image_fstype = self.match_image_fstype(d)
|
||||
if image_fstype:
|
||||
return image_fstype
|
||||
else:
|
||||
bb.fatal("IMAGE_FSTYPES should contain a Target Controller supported image fstype: %s " % ', '.join(map(str, self.supported_image_fstypes)))
|
||||
|
||||
def restart(self, params=None):
|
||||
self.stop()
|
||||
self.start(params)
|
||||
|
||||
def run(self, cmd, timeout=None):
|
||||
return self.connection.run(cmd, timeout)
|
||||
|
||||
def copy_to(self, localpath, remotepath):
|
||||
return self.connection.copy_to(localpath, remotepath)
|
||||
|
||||
def copy_from(self, remotepath, localpath):
|
||||
return self.connection.copy_from(remotepath, localpath)
|
||||
|
||||
|
||||
|
||||
class QemuTarget(BaseTarget):
|
||||
|
||||
supported_image_fstypes = ['ext3', 'ext4', 'cpio.gz', 'wic']
|
||||
|
||||
def __init__(self, d, logger, image_fstype=None):
|
||||
|
||||
import oe.types
|
||||
|
||||
super(QemuTarget, self).__init__(d, logger)
|
||||
|
||||
self.rootfs = ''
|
||||
self.kernel = ''
|
||||
self.image_fstype = ''
|
||||
|
||||
if d.getVar('FIND_ROOTFS') == '1':
|
||||
self.image_fstype = image_fstype or self.get_image_fstype(d)
|
||||
self.rootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("IMAGE_LINK_NAME") + '.' + self.image_fstype)
|
||||
self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
|
||||
self.qemulog = os.path.join(self.testdir, "qemu_boot_log.%s" % self.datetime)
|
||||
dump_monitor_cmds = d.getVar("testimage_dump_monitor")
|
||||
dump_dir = d.getVar("TESTIMAGE_DUMP_DIR")
|
||||
if not dump_dir:
|
||||
dump_dir = os.path.join(d.getVar('LOG_DIR'), 'runtime-hostdump')
|
||||
use_kvm = oe.types.qemu_use_kvm(d.getVar('QEMU_USE_KVM'), d.getVar('TARGET_ARCH'))
|
||||
|
||||
# Log QemuRunner log output to a file
|
||||
import oe.path
|
||||
bb.utils.mkdirhier(self.testdir)
|
||||
self.qemurunnerlog = os.path.join(self.testdir, 'qemurunner_log.%s' % self.datetime)
|
||||
self.loggerhandler = logging.FileHandler(self.qemurunnerlog)
|
||||
self.loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
|
||||
self.logger.addHandler(self.loggerhandler)
|
||||
oe.path.symlink(os.path.basename(self.qemurunnerlog), os.path.join(self.testdir, 'qemurunner_log'), force=True)
|
||||
|
||||
if d.getVar("DISTRO") == "poky-tiny":
|
||||
self.runner = QemuTinyRunner(machine=d.getVar("MACHINE"),
|
||||
rootfs=self.rootfs,
|
||||
tmpdir = d.getVar("TMPDIR"),
|
||||
deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE"),
|
||||
display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY"),
|
||||
logfile = self.qemulog,
|
||||
kernel = self.kernel,
|
||||
boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")),
|
||||
tmpfsdir = d.getVar("RUNQEMU_TMPFS_DIR"),
|
||||
logger = logger)
|
||||
else:
|
||||
self.runner = QemuRunner(machine=d.getVar("MACHINE"),
|
||||
rootfs=self.rootfs,
|
||||
tmpdir = d.getVar("TMPDIR"),
|
||||
deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE"),
|
||||
display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY"),
|
||||
logfile = self.qemulog,
|
||||
boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")),
|
||||
use_kvm = use_kvm,
|
||||
dump_dir = dump_dir,
|
||||
logger = logger,
|
||||
tmpfsdir = d.getVar("RUNQEMU_TMPFS_DIR"),
|
||||
serial_ports = len(d.getVar("SERIAL_CONSOLES").split()))
|
||||
|
||||
self.monitor_dumper = MonitorDumper(dump_monitor_cmds, dump_dir, self.runner)
|
||||
if (self.monitor_dumper):
|
||||
self.monitor_dumper.create_dir("qmp")
|
||||
|
||||
def deploy(self):
|
||||
bb.utils.mkdirhier(self.testdir)
|
||||
|
||||
qemuloglink = os.path.join(self.testdir, "qemu_boot_log")
|
||||
if os.path.islink(qemuloglink):
|
||||
os.unlink(qemuloglink)
|
||||
os.symlink(self.qemulog, qemuloglink)
|
||||
|
||||
self.logger.info("rootfs file: %s" % self.rootfs)
|
||||
self.logger.info("Qemu log file: %s" % self.qemulog)
|
||||
super(QemuTarget, self).deploy()
|
||||
|
||||
def start(self, params=None, ssh=True, extra_bootparams='', runqemuparams='', launch_cmd='', discard_writes=True):
|
||||
if launch_cmd:
|
||||
start = self.runner.launch(get_ip=ssh, launch_cmd=launch_cmd, qemuparams=params)
|
||||
else:
|
||||
start = self.runner.start(params, get_ip=ssh, extra_bootparams=extra_bootparams, runqemuparams=runqemuparams, discard_writes=discard_writes)
|
||||
|
||||
if start:
|
||||
if ssh:
|
||||
self.ip = self.runner.ip
|
||||
self.server_ip = self.runner.server_ip
|
||||
self.connection = SSHControl(ip=self.ip, logfile=self.sshlog)
|
||||
else:
|
||||
self.stop()
|
||||
if os.path.exists(self.qemulog):
|
||||
with open(self.qemulog, 'r') as f:
|
||||
bb.error("Qemu log output from %s:\n%s" % (self.qemulog, f.read()))
|
||||
raise RuntimeError("%s - FAILED to start qemu - check the task log and the boot log" % self.pn)
|
||||
|
||||
def check(self):
|
||||
return self.runner.is_alive()
|
||||
|
||||
def stop(self):
|
||||
try:
|
||||
self.runner.stop()
|
||||
except:
|
||||
pass
|
||||
self.logger.removeHandler(self.loggerhandler)
|
||||
self.loggerhandler.close()
|
||||
self.connection = None
|
||||
self.ip = None
|
||||
self.server_ip = None
|
||||
|
||||
def restart(self, params=None):
|
||||
if self.runner.restart(params):
|
||||
self.ip = self.runner.ip
|
||||
self.server_ip = self.runner.server_ip
|
||||
self.connection = SSHControl(ip=self.ip, logfile=self.sshlog)
|
||||
else:
|
||||
raise RuntimeError("%s - FAILED to re-start qemu - check the task log and the boot log" % self.pn)
|
||||
|
||||
def run_serial(self, command, timeout=60):
|
||||
return self.runner.run_serial(command, timeout=timeout)
|
||||
|
||||
|
||||
class SimpleRemoteTarget(BaseTarget):
|
||||
|
||||
def __init__(self, d):
|
||||
super(SimpleRemoteTarget, self).__init__(d)
|
||||
addr = d.getVar("TEST_TARGET_IP") or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.')
|
||||
self.ip = addr.split(":")[0]
|
||||
try:
|
||||
self.port = addr.split(":")[1]
|
||||
except IndexError:
|
||||
self.port = None
|
||||
self.logger.info("Target IP: %s" % self.ip)
|
||||
self.server_ip = d.getVar("TEST_SERVER_IP")
|
||||
if not self.server_ip:
|
||||
try:
|
||||
self.server_ip = subprocess.check_output(['ip', 'route', 'get', self.ip ]).split("\n")[0].split()[-1]
|
||||
except Exception as e:
|
||||
bb.fatal("Failed to determine the host IP address (alternatively you can set TEST_SERVER_IP with the IP address of this machine): %s" % e)
|
||||
self.logger.info("Server IP: %s" % self.server_ip)
|
||||
|
||||
def deploy(self):
|
||||
super(SimpleRemoteTarget, self).deploy()
|
||||
|
||||
def start(self, params=None, ssh=True, extra_bootparams=None):
|
||||
if ssh:
|
||||
self.connection = SSHControl(self.ip, logfile=self.sshlog, port=self.port)
|
||||
|
||||
def stop(self):
|
||||
self.connection = None
|
||||
self.ip = None
|
||||
self.server_ip = None
|
||||
Reference in New Issue
Block a user