blob: d686fe07ec3f6bfcaf0e3eb4586f9115f4396143 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002# Copyright (C) 2013 Intel Corporation
3#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: MIT
5#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05006
7# This module is used by testimage.bbclass for setting up and controlling a target machine.
8
9import os
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010import subprocess
11import bb
Patrick Williamsc124f4f2015-09-15 14:41:29 -050012import logging
13from oeqa.utils.sshcontrol import SSHControl
14from oeqa.utils.qemurunner import QemuRunner
15from oeqa.utils.qemutinyrunner import QemuTinyRunner
16from oeqa.utils.dump import TargetDumper
Andrew Geisslerc926e172021-05-07 16:11:35 -050017from oeqa.utils.dump import MonitorDumper
Patrick Williamsc124f4f2015-09-15 14:41:29 -050018from abc import ABCMeta, abstractmethod
19
Patrick Williamsc0f7c042017-02-23 20:41:17 -060020class BaseTarget(object, metaclass=ABCMeta):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050021
22 supported_image_fstypes = []
23
Brad Bishopd7bf8c12018-02-25 22:55:05 -050024 def __init__(self, d, logger):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050025 self.connection = None
26 self.ip = None
27 self.server_ip = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -050028 self.datetime = d.getVar('DATETIME')
29 self.testdir = d.getVar("TEST_LOG_DIR")
30 self.pn = d.getVar("PN")
Brad Bishopd7bf8c12018-02-25 22:55:05 -050031 self.logger = logger
Patrick Williamsc124f4f2015-09-15 14:41:29 -050032
33 @abstractmethod
34 def deploy(self):
35
36 self.sshlog = os.path.join(self.testdir, "ssh_target_log.%s" % self.datetime)
37 sshloglink = os.path.join(self.testdir, "ssh_target_log")
38 if os.path.islink(sshloglink):
39 os.unlink(sshloglink)
40 os.symlink(self.sshlog, sshloglink)
Patrick Williams8e7b46e2023-05-01 14:19:06 -050041 self.logger.info("SSH log file: %s" % self.sshlog)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050042
43 @abstractmethod
Patrick Williamsc0f7c042017-02-23 20:41:17 -060044 def start(self, params=None, ssh=True, extra_bootparams=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045 pass
46
47 @abstractmethod
48 def stop(self):
49 pass
50
51 @classmethod
52 def get_extra_files(self):
53 return None
54
55 @classmethod
56 def match_image_fstype(self, d, image_fstypes=None):
57 if not image_fstypes:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050058 image_fstypes = d.getVar('IMAGE_FSTYPES').split(' ')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059 possible_image_fstypes = [fstype for fstype in self.supported_image_fstypes if fstype in image_fstypes]
60 if possible_image_fstypes:
61 return possible_image_fstypes[0]
62 else:
63 return None
64
65 def get_image_fstype(self, d):
66 image_fstype = self.match_image_fstype(d)
67 if image_fstype:
68 return image_fstype
69 else:
70 bb.fatal("IMAGE_FSTYPES should contain a Target Controller supported image fstype: %s " % ', '.join(map(str, self.supported_image_fstypes)))
71
72 def restart(self, params=None):
73 self.stop()
74 self.start(params)
75
76 def run(self, cmd, timeout=None):
77 return self.connection.run(cmd, timeout)
78
79 def copy_to(self, localpath, remotepath):
80 return self.connection.copy_to(localpath, remotepath)
81
82 def copy_from(self, remotepath, localpath):
83 return self.connection.copy_from(remotepath, localpath)
84
85
86
87class QemuTarget(BaseTarget):
88
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050089 supported_image_fstypes = ['ext3', 'ext4', 'cpio.gz', 'wic']
Patrick Williamsc124f4f2015-09-15 14:41:29 -050090
Brad Bishopd7bf8c12018-02-25 22:55:05 -050091 def __init__(self, d, logger, image_fstype=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050092
Brad Bishop316dfdd2018-06-25 12:45:53 -040093 import oe.types
94
Brad Bishopd7bf8c12018-02-25 22:55:05 -050095 super(QemuTarget, self).__init__(d, logger)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050096
Brad Bishop6e60e8b2018-02-01 10:27:11 -050097 self.rootfs = ''
98 self.kernel = ''
99 self.image_fstype = ''
100
101 if d.getVar('FIND_ROOTFS') == '1':
102 self.image_fstype = image_fstype or self.get_image_fstype(d)
103 self.rootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("IMAGE_LINK_NAME") + '.' + self.image_fstype)
104 self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500105 self.qemulog = os.path.join(self.testdir, "qemu_boot_log.%s" % self.datetime)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500106 dump_target_cmds = d.getVar("testimage_dump_target")
107 dump_host_cmds = d.getVar("testimage_dump_host")
Andrew Geisslerc926e172021-05-07 16:11:35 -0500108 dump_monitor_cmds = d.getVar("testimage_dump_monitor")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500109 dump_dir = d.getVar("TESTIMAGE_DUMP_DIR")
Brad Bishop977dc1a2019-02-06 16:01:43 -0500110 if not dump_dir:
111 dump_dir = os.path.join(d.getVar('LOG_DIR'), 'runtime-hostdump')
112 use_kvm = oe.types.qemu_use_kvm(d.getVar('QEMU_USE_KVM'), d.getVar('TARGET_ARCH'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500113
114 # Log QemuRunner log output to a file
115 import oe.path
116 bb.utils.mkdirhier(self.testdir)
117 self.qemurunnerlog = os.path.join(self.testdir, 'qemurunner_log.%s' % self.datetime)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500118 self.loggerhandler = logging.FileHandler(self.qemurunnerlog)
119 self.loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
120 self.logger.addHandler(self.loggerhandler)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500121 oe.path.symlink(os.path.basename(self.qemurunnerlog), os.path.join(self.testdir, 'qemurunner_log'), force=True)
122
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500123 if d.getVar("DISTRO") == "poky-tiny":
124 self.runner = QemuTinyRunner(machine=d.getVar("MACHINE"),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500125 rootfs=self.rootfs,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500126 tmpdir = d.getVar("TMPDIR"),
127 deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE"),
128 display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY"),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129 logfile = self.qemulog,
130 kernel = self.kernel,
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500131 boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")),
Andrew Geissler3b8a17c2021-04-15 15:55:55 -0500132 tmpfsdir = d.getVar("RUNQEMU_TMPFS_DIR"),
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500133 logger = logger)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500134 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500135 self.runner = QemuRunner(machine=d.getVar("MACHINE"),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500136 rootfs=self.rootfs,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500137 tmpdir = d.getVar("TMPDIR"),
138 deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE"),
139 display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY"),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500140 logfile = self.qemulog,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500141 boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")),
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600142 use_kvm = use_kvm,
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500143 dump_dir = dump_dir,
Patrick Williams8e7b46e2023-05-01 14:19:06 -0500144 dump_host_cmds = dump_host_cmds,
Andrew Geissler82c905d2020-04-13 13:39:40 -0500145 logger = logger,
Andrew Geissler3b8a17c2021-04-15 15:55:55 -0500146 tmpfsdir = d.getVar("RUNQEMU_TMPFS_DIR"),
Andrew Geissler82c905d2020-04-13 13:39:40 -0500147 serial_ports = len(d.getVar("SERIAL_CONSOLES").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500148
149 self.target_dumper = TargetDumper(dump_target_cmds, dump_dir, self.runner)
Andrew Geisslerc926e172021-05-07 16:11:35 -0500150 self.monitor_dumper = MonitorDumper(dump_monitor_cmds, dump_dir, self.runner)
Andrew Geissler5f350902021-07-23 13:09:54 -0400151 if (self.monitor_dumper):
152 self.monitor_dumper.create_dir("qmp")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500153
154 def deploy(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600155 bb.utils.mkdirhier(self.testdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500156
157 qemuloglink = os.path.join(self.testdir, "qemu_boot_log")
158 if os.path.islink(qemuloglink):
159 os.unlink(qemuloglink)
160 os.symlink(self.qemulog, qemuloglink)
161
Patrick Williams8e7b46e2023-05-01 14:19:06 -0500162 self.logger.info("rootfs file: %s" % self.rootfs)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500163 self.logger.info("Qemu log file: %s" % self.qemulog)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500164 super(QemuTarget, self).deploy()
165
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500166 def start(self, params=None, ssh=True, extra_bootparams='', runqemuparams='', launch_cmd='', discard_writes=True):
167 if launch_cmd:
Brad Bishopc342db32019-05-15 21:57:59 -0400168 start = self.runner.launch(get_ip=ssh, launch_cmd=launch_cmd, qemuparams=params)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500169 else:
170 start = self.runner.start(params, get_ip=ssh, extra_bootparams=extra_bootparams, runqemuparams=runqemuparams, discard_writes=discard_writes)
171
172 if start:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500173 if ssh:
174 self.ip = self.runner.ip
175 self.server_ip = self.runner.server_ip
176 self.connection = SSHControl(ip=self.ip, logfile=self.sshlog)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500177 else:
178 self.stop()
179 if os.path.exists(self.qemulog):
180 with open(self.qemulog, 'r') as f:
181 bb.error("Qemu log output from %s:\n%s" % (self.qemulog, f.read()))
Brad Bishop08902b02019-08-20 09:16:51 -0400182 raise RuntimeError("%s - FAILED to start qemu - check the task log and the boot log" % self.pn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500183
184 def check(self):
185 return self.runner.is_alive()
186
187 def stop(self):
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500188 try:
189 self.runner.stop()
190 except:
191 pass
Andrew Geissler82c905d2020-04-13 13:39:40 -0500192 self.logger.removeHandler(self.loggerhandler)
Andrew Geissler475cb722020-07-10 16:00:51 -0500193 self.loggerhandler.close()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500194 self.connection = None
195 self.ip = None
196 self.server_ip = None
197
198 def restart(self, params=None):
199 if self.runner.restart(params):
200 self.ip = self.runner.ip
201 self.server_ip = self.runner.server_ip
202 self.connection = SSHControl(ip=self.ip, logfile=self.sshlog)
203 else:
Patrick Williams8e7b46e2023-05-01 14:19:06 -0500204 raise RuntimeError("%s - FAILED to re-start qemu - check the task log and the boot log" % self.pn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500205
Brad Bishop977dc1a2019-02-06 16:01:43 -0500206 def run_serial(self, command, timeout=60):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500207 return self.runner.run_serial(command, timeout=timeout)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500208
209
210class SimpleRemoteTarget(BaseTarget):
211
212 def __init__(self, d):
213 super(SimpleRemoteTarget, self).__init__(d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500214 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.')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500215 self.ip = addr.split(":")[0]
216 try:
217 self.port = addr.split(":")[1]
218 except IndexError:
219 self.port = None
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500220 self.logger.info("Target IP: %s" % self.ip)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500221 self.server_ip = d.getVar("TEST_SERVER_IP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500222 if not self.server_ip:
223 try:
224 self.server_ip = subprocess.check_output(['ip', 'route', 'get', self.ip ]).split("\n")[0].split()[-1]
225 except Exception as e:
226 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)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500227 self.logger.info("Server IP: %s" % self.server_ip)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500228
229 def deploy(self):
230 super(SimpleRemoteTarget, self).deploy()
231
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600232 def start(self, params=None, ssh=True, extra_bootparams=None):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500233 if ssh:
234 self.connection = SSHControl(self.ip, logfile=self.sshlog, port=self.port)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235
236 def stop(self):
237 self.connection = None
238 self.ip = None
239 self.server_ip = None