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