xref: /OK3568_Linux_fs/yocto/poky/meta/lib/oeqa/selftest/cases/imagefeatures.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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