1# 2# SPDX-License-Identifier: MIT 3# 4 5from oeqa.selftest.case import OESelftestTestCase 6from oeqa.core.decorator import OETestTag 7from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu 8from oeqa.utils.sshcontrol import SSHControl 9import glob 10import os 11import json 12 13class ImageFeatures(OESelftestTestCase): 14 15 test_user = 'tester' 16 root_user = 'root' 17 18 @OETestTag("runqemu") 19 def test_non_root_user_can_connect_via_ssh_without_password(self): 20 """ 21 Summary: Check if non root user can connect via ssh without password 22 Expected: 1. Connection to the image via ssh using root user without providing a password should be allowed. 23 2. Connection to the image via ssh using tester user without providing a password should be allowed. 24 Product: oe-core 25 Author: Ionut Chisanovici <ionutx.chisanovici@intel.com> 26 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 27 """ 28 29 features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh empty-root-password allow-empty-password allow-root-login"\n' 30 features += 'INHERIT += "extrausers"\n' 31 features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user) 32 self.write_config(features) 33 34 # Build a core-image-minimal 35 bitbake('core-image-minimal') 36 37 with runqemu("core-image-minimal") as qemu: 38 # Attempt to ssh with each user into qemu with empty password 39 for user in [self.root_user, self.test_user]: 40 ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user) 41 status, output = ssh.run("true") 42 self.assertEqual(status, 0, 'ssh to user %s failed with %s' % (user, output)) 43 44 @OETestTag("runqemu") 45 def test_all_users_can_connect_via_ssh_without_password(self): 46 """ 47 Summary: Check if all users can connect via ssh without password 48 Expected: 1. Connection to the image via ssh using root user without providing a password should NOT be allowed. 49 2. Connection to the image via ssh using tester user without providing a password should be allowed. 50 Product: oe-core 51 Author: Ionut Chisanovici <ionutx.chisanovici@intel.com> 52 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 53 """ 54 55 features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh allow-empty-password allow-root-login"\n' 56 features += 'INHERIT += "extrausers"\n' 57 features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user) 58 self.write_config(features) 59 60 # Build a core-image-minimal 61 bitbake('core-image-minimal') 62 63 with runqemu("core-image-minimal") as qemu: 64 # Attempt to ssh with each user into qemu with empty password 65 for user in [self.root_user, self.test_user]: 66 ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user) 67 status, output = ssh.run("true") 68 if user == 'root': 69 self.assertNotEqual(status, 0, 'ssh to user root was allowed when it should not have been') 70 else: 71 self.assertEqual(status, 0, 'ssh to user tester failed with %s' % output) 72 73 74 def test_wayland_support_in_image(self): 75 """ 76 Summary: Check Wayland support in image 77 Expected: 1. Wayland image can be build 78 2. Wayland feature can be installed 79 Product: oe-core 80 Author: Ionut Chisanovici <ionutx.chisanovici@intel.com> 81 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 82 """ 83 84 distro_features = get_bb_var('DISTRO_FEATURES') 85 if not ('opengl' in distro_features and 'wayland' in distro_features): 86 self.skipTest('neither opengl nor wayland present on DISTRO_FEATURES so core-image-weston cannot be built') 87 88 # Build a core-image-weston 89 bitbake('core-image-weston') 90 91 def test_bmap(self): 92 """ 93 Summary: Check bmap support 94 Expected: 1. core-image-minimal can be build with bmap support 95 2. core-image-minimal is sparse 96 Product: oe-core 97 Author: Ed Bartosh <ed.bartosh@linux.intel.com> 98 """ 99 100 features = 'IMAGE_FSTYPES += " ext4 ext4.bmap ext4.bmap.gz"' 101 self.write_config(features) 102 103 image_name = 'core-image-minimal' 104 bitbake(image_name) 105 106 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 107 link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 108 image_path = os.path.join(deploy_dir_image, "%s.ext4" % link_name) 109 bmap_path = "%s.bmap" % image_path 110 gzip_path = "%s.gz" % bmap_path 111 112 # check if result image, bmap and bmap.gz files are in deploy directory 113 self.assertTrue(os.path.exists(image_path)) 114 self.assertTrue(os.path.exists(bmap_path)) 115 self.assertTrue(os.path.exists(gzip_path)) 116 117 # check if result image is sparse 118 image_stat = os.stat(image_path) 119 self.assertGreater(image_stat.st_size, image_stat.st_blocks * 512) 120 121 # check if the resulting gzip is valid 122 self.assertTrue(runCmd('gzip -t %s' % gzip_path)) 123 124 def test_hypervisor_fmts(self): 125 """ 126 Summary: Check various hypervisor formats 127 Expected: 1. core-image-minimal can be built with vmdk, vdi and 128 qcow2 support. 129 2. qemu-img says each image has the expected format 130 Product: oe-core 131 Author: Tom Rini <trini@konsulko.com> 132 """ 133 134 img_types = [ 'vmdk', 'vdi', 'qcow2' ] 135 features = "" 136 for itype in img_types: 137 features += 'IMAGE_FSTYPES += "wic.%s"\n' % itype 138 self.write_config(features) 139 140 image_name = 'core-image-minimal' 141 bitbake(image_name) 142 143 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 144 link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 145 for itype in img_types: 146 image_path = os.path.join(deploy_dir_image, "%s.wic.%s" % 147 (link_name, itype)) 148 149 # check if result image file is in deploy directory 150 self.assertTrue(os.path.exists(image_path)) 151 152 # check if result image is vmdk 153 sysroot = get_bb_var('STAGING_DIR_NATIVE', 'core-image-minimal') 154 result = runCmd('qemu-img info --output json %s' % image_path, 155 native_sysroot=sysroot) 156 try: 157 data = json.loads(result.output) 158 self.assertEqual(data.get('format'), itype, 159 msg="Unexpected format in '%s'" % (result.output)) 160 except json.decoder.JSONDecodeError: 161 self.fail("Could not parse '%ss'" % result.output) 162 163 def test_long_chain_conversion(self): 164 """ 165 Summary: Check for chaining many CONVERSION_CMDs together 166 Expected: 1. core-image-minimal can be built with 167 ext4.bmap.gz.bz2.lzo.xz.u-boot and also create a 168 sha256sum 169 2. The above image has a valid sha256sum 170 Product: oe-core 171 Author: Tom Rini <trini@konsulko.com> 172 """ 173 174 conv = "ext4.bmap.gz.bz2.lzo.xz.u-boot" 175 features = 'IMAGE_FSTYPES += "%s %s.sha256sum"' % (conv, conv) 176 self.write_config(features) 177 178 image_name = 'core-image-minimal' 179 bitbake(image_name) 180 181 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 182 link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 183 image_path = os.path.join(deploy_dir_image, "%s.%s" % 184 (link_name, conv)) 185 186 # check if resulting image is in the deploy directory 187 self.assertTrue(os.path.exists(image_path)) 188 self.assertTrue(os.path.exists(image_path + ".sha256sum")) 189 190 # check if the resulting sha256sum agrees 191 self.assertTrue(runCmd('cd %s;sha256sum -c %s.%s.sha256sum' % 192 (deploy_dir_image, link_name, conv))) 193 194 def test_image_fstypes(self): 195 """ 196 Summary: Check if image of supported image fstypes can be built 197 Expected: core-image-minimal can be built for various image types 198 Product: oe-core 199 Author: Ed Bartosh <ed.bartosh@linux.intel.com> 200 """ 201 image_name = 'core-image-minimal' 202 203 all_image_types = set(get_bb_var("IMAGE_TYPES", image_name).split()) 204 skip_image_types = set(('container', 'elf', 'f2fs', 'multiubi', 'tar.zst', 'wic.zst')) 205 img_types = all_image_types - skip_image_types 206 207 config = 'IMAGE_FSTYPES += "%s"\n'\ 208 'MKUBIFS_ARGS ?= "-m 2048 -e 129024 -c 2047"\n'\ 209 'UBINIZE_ARGS ?= "-m 2048 -p 128KiB -s 512"' % ' '.join(img_types) 210 self.write_config(config) 211 212 bitbake(image_name) 213 214 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 215 link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 216 for itype in img_types: 217 image_path = os.path.join(deploy_dir_image, "%s.%s" % (link_name, itype)) 218 # check if result image is in deploy directory 219 self.assertTrue(os.path.exists(image_path), 220 "%s image %s doesn't exist" % (itype, image_path)) 221 222 def test_useradd_static(self): 223 config = """ 224USERADDEXTENSION = "useradd-staticids" 225USERADD_ERROR_DYNAMIC = "skip" 226USERADD_UID_TABLES += "files/static-passwd" 227USERADD_GID_TABLES += "files/static-group" 228""" 229 self.write_config(config) 230 bitbake("core-image-base") 231 232 def test_no_busybox_base_utils(self): 233 config = """ 234# Enable wayland 235DISTRO_FEATURES:append = " pam opengl wayland" 236 237# Switch to systemd 238DISTRO_FEATURES:append = " systemd" 239VIRTUAL-RUNTIME_init_manager = "systemd" 240VIRTUAL-RUNTIME_initscripts = "" 241VIRTUAL-RUNTIME_syslog = "" 242VIRTUAL-RUNTIME_login_manager = "shadow-base" 243DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" 244 245# Replace busybox 246PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils" 247VIRTUAL-RUNTIME_base-utils = "packagegroup-core-base-utils" 248VIRTUAL-RUNTIME_base-utils-hwclock = "util-linux-hwclock" 249VIRTUAL-RUNTIME_base-utils-syslog = "" 250 251# Skip busybox 252SKIP_RECIPE[busybox] = "Don't build this" 253""" 254 self.write_config(config) 255 256 bitbake("--graphviz core-image-weston") 257 258 def test_image_gen_debugfs(self): 259 """ 260 Summary: Check debugfs generation 261 Expected: 1. core-image-minimal can be build with IMAGE_GEN_DEBUGFS variable set 262 2. debug filesystem is created when variable set 263 3. debug symbols available 264 Product: oe-core 265 Author: Humberto Ibarra <humberto.ibarra.lopez@intel.com> 266 Yeoh Ee Peng <ee.peng.yeoh@intel.com> 267 """ 268 269 image_name = 'core-image-minimal' 270 features = 'IMAGE_GEN_DEBUGFS = "1"\n' 271 features += 'IMAGE_FSTYPES_DEBUGFS = "tar.bz2"\n' 272 features += 'MACHINE = "genericx86-64"\n' 273 self.write_config(features) 274 275 bitbake(image_name) 276 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 277 dbg_tar_file = os.path.join(deploy_dir_image, "*-dbg.rootfs.tar.bz2") 278 debug_files = glob.glob(dbg_tar_file) 279 self.assertNotEqual(len(debug_files), 0, 'debug filesystem not generated at %s' % dbg_tar_file) 280 result = runCmd('cd %s; tar xvf %s' % (deploy_dir_image, dbg_tar_file)) 281 self.assertEqual(result.status, 0, msg='Failed to extract %s: %s' % (dbg_tar_file, result.output)) 282 result = runCmd('find %s -name %s' % (deploy_dir_image, "udevadm")) 283 self.assertTrue("udevadm" in result.output, msg='Failed to find udevadm: %s' % result.output) 284 dbg_symbols_targets = result.output.splitlines() 285 self.assertTrue(dbg_symbols_targets, msg='Failed to split udevadm: %s' % dbg_symbols_targets) 286 for t in dbg_symbols_targets: 287 result = runCmd('objdump --syms %s | grep debug' % t) 288 self.assertTrue("debug" in result.output, msg='Failed to find debug symbol: %s' % result.output) 289 290 def test_empty_image(self): 291 """Test creation of image with no packages""" 292 bitbake('test-empty-image') 293 res_dir = get_bb_var('DEPLOY_DIR_IMAGE') 294 images = os.path.join(res_dir, "test-empty-image-*.manifest") 295 result = glob.glob(images) 296 with open(result[1],"r") as f: 297 self.assertEqual(len(f.read().strip()),0) 298