blob: 96beb8b869bc5cbb9ea8dca536a2e685bbef3ad5 [file] [log] [blame]
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001#
2# SPDX-License-Identifier: MIT
3#
4
5from oeqa.selftest.case import OESelftestTestCase
Patrick Williams45852732022-04-02 08:58:32 -05006from oeqa.utils.commands import bitbake, runqemu
7from oeqa.core.decorator import OETestTag
Patrick Williams0ca19cc2021-08-16 14:03:13 -05008
Andrew Geissler595f6302022-01-24 19:11:47 +00009def getline_qemu(out, line):
10 for l in out.split('\n'):
11 if line in l:
12 return l
13
14def getline(res, line):
15 return getline_qemu(res.output, line)
16
Patrick Williams0ca19cc2021-08-16 14:03:13 -050017class OverlayFSTests(OESelftestTestCase):
18 """Overlayfs class usage tests"""
19
Patrick Williams0ca19cc2021-08-16 14:03:13 -050020 def add_overlay_conf_to_machine(self):
21 machine_inc = """
22OVERLAYFS_MOUNT_POINT[mnt-overlay] = "/mnt/overlay"
23"""
24 self.set_machine_config(machine_inc)
25
26 def test_distro_features_missing(self):
27 """
28 Summary: Check that required DISTRO_FEATURES are set
29 Expected: Fail when either systemd or overlayfs are not in DISTRO_FEATURES
30 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
31 """
32
33 config = """
34IMAGE_INSTALL:append = " overlayfs-user"
35"""
36 overlayfs_recipe_append = """
37inherit overlayfs
38"""
39 self.write_config(config)
40 self.add_overlay_conf_to_machine()
41 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
42
43 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +000044 line = getline(res, "overlayfs-user was skipped: missing required distro features")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050045 self.assertTrue("overlayfs" in res.output, msg=res.output)
46 self.assertTrue("systemd" in res.output, msg=res.output)
47 self.assertTrue("ERROR: Required build target 'core-image-minimal' has no buildable providers." in res.output, msg=res.output)
48
49 def test_not_all_units_installed(self):
50 """
51 Summary: Test QA check that we have required mount units in the image
52 Expected: Fail because mount unit for overlay partition is not installed
53 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
54 """
55
56 config = """
57IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -050058DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -050059"""
60
61 self.write_config(config)
62 self.add_overlay_conf_to_machine()
63
64 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geisslerd5838332022-05-27 11:33:10 -050065 line = getline(res, " Mount path /mnt/overlay not found in fstab and unit mnt-overlay.mount not found in systemd unit directories")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050066 self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
Andrew Geissler9aee5002022-03-30 16:27:02 +000067 line = getline(res, "Not all mount paths and units are installed in the image")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050068 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
69
Andrew Geisslerd5838332022-05-27 11:33:10 -050070 def test_not_all_units_installed_but_qa_skipped(self):
71 """
72 Summary: Test skipping the QA check
73 Expected: Image is created successfully
74 Author: Claudius Heine <ch@denx.de>
75 """
76
77 config = """
78IMAGE_INSTALL:append = " overlayfs-user"
79DISTRO_FEATURES += "systemd overlayfs"
80OVERLAYFS_QA_SKIP[mnt-overlay] = "mount-configured"
81"""
82
83 self.write_config(config)
84 self.add_overlay_conf_to_machine()
85
86 bitbake('core-image-minimal')
87
Patrick Williams0ca19cc2021-08-16 14:03:13 -050088 def test_mount_unit_not_set(self):
89 """
90 Summary: Test whether mount unit was set properly
91 Expected: Fail because mount unit was not set
92 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
93 """
94
95 config = """
96IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -050097DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -050098"""
99
100 self.write_config(config)
101
102 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000103 line = getline(res, "A recipe uses overlayfs class but there is no OVERLAYFS_MOUNT_POINT set in your MACHINE configuration")
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500104 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
105
106 def test_wrong_mount_unit_set(self):
107 """
108 Summary: Test whether mount unit was set properly
109 Expected: Fail because not the correct flag used for mount unit
110 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
111 """
112
113 config = """
114IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500115DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500116"""
117
118 wrong_machine_config = """
119OVERLAYFS_MOUNT_POINT[usr-share-overlay] = "/usr/share/overlay"
120"""
121
122 self.write_config(config)
123 self.set_machine_config(wrong_machine_config)
124
125 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000126 line = getline(res, "Missing required mount point for OVERLAYFS_MOUNT_POINT[mnt-overlay] in your MACHINE configuration")
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500127 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
128
Andrew Geissler9aee5002022-03-30 16:27:02 +0000129 def _test_correct_image(self, recipe, data):
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500130 """
131 Summary: Check that we can create an image when all parameters are
132 set correctly
133 Expected: Image is created successfully
134 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
135 """
136
137 config = """
138IMAGE_INSTALL:append = " overlayfs-user systemd-machine-units"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500139DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500140
141# Use systemd as init manager
142VIRTUAL-RUNTIME_init_manager = "systemd"
143
144# enable overlayfs in the kernel
145KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
146"""
147
Andrew Geissler595f6302022-01-24 19:11:47 +0000148 overlayfs_recipe_append = """
149OVERLAYFS_WRITABLE_PATHS[mnt-overlay] += "/usr/share/another-overlay-mount"
150
151SYSTEMD_SERVICE:${PN} += " \
152 my-application.service \
153"
154
155do_install:append() {
156 install -d ${D}${systemd_system_unitdir}
157 cat <<EOT > ${D}${systemd_system_unitdir}/my-application.service
158[Unit]
159Description=Sample application start-up unit
160After=overlayfs-user-overlays.service
161Requires=overlayfs-user-overlays.service
162
163[Service]
164Type=oneshot
165ExecStart=/bin/true
166RemainAfterExit=true
167
168[Install]
169WantedBy=multi-user.target
170EOT
171}
172"""
173
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500174 self.write_config(config)
175 self.add_overlay_conf_to_machine()
Andrew Geissler9aee5002022-03-30 16:27:02 +0000176 self.write_recipeinc(recipe, data)
Andrew Geissler595f6302022-01-24 19:11:47 +0000177 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500178
179 bitbake('core-image-minimal')
180
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500181 with runqemu('core-image-minimal') as qemu:
Andrew Geissler595f6302022-01-24 19:11:47 +0000182 # Check that application service started
183 status, output = qemu.run_serial("systemctl status my-application")
184 self.assertTrue("active (exited)" in output, msg=output)
185
186 # Check that overlay mounts are dependencies of our application unit
187 status, output = qemu.run_serial("systemctl list-dependencies my-application")
188 self.assertTrue("overlayfs-user-overlays.service" in output, msg=output)
189
190 status, output = qemu.run_serial("systemctl list-dependencies overlayfs-user-overlays")
191 self.assertTrue("usr-share-another\\x2doverlay\\x2dmount.mount" in output, msg=output)
192 self.assertTrue("usr-share-my\\x2dapplication.mount" in output, msg=output)
193
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500194 # Check that we have /mnt/overlay fs mounted as tmpfs and
195 # /usr/share/my-application as an overlay (see overlayfs-user recipe)
196 status, output = qemu.run_serial("/bin/mount -t tmpfs,overlay")
197
198 line = getline_qemu(output, "on /mnt/overlay")
199 self.assertTrue(line and line.startswith("tmpfs"), msg=output)
200
201 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/my-application")
202 self.assertTrue(line and line.startswith("overlay"), msg=output)
Andrew Geissler595f6302022-01-24 19:11:47 +0000203
204 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/another-overlay-mount")
205 self.assertTrue(line and line.startswith("overlay"), msg=output)
206
Patrick Williams45852732022-04-02 08:58:32 -0500207 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000208 def test_correct_image_fstab(self):
209 """
210 Summary: Check that we can create an image when all parameters are
211 set correctly via fstab
212 Expected: Image is created successfully
213 Author: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
214 """
215
216 base_files_append = """
217do_install:append() {
218 cat <<EOT >> ${D}${sysconfdir}/fstab
219tmpfs /mnt/overlay tmpfs mode=1777,strictatime,nosuid,nodev 0 0
220EOT
221}
222"""
223
224 self._test_correct_image('base-files', base_files_append)
225
Patrick Williams45852732022-04-02 08:58:32 -0500226 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000227 def test_correct_image_unit(self):
228 """
229 Summary: Check that we can create an image when all parameters are
230 set correctly via mount unit
231 Expected: Image is created successfully
232 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
233 """
234
235 systemd_machine_unit_append = """
236SYSTEMD_SERVICE:${PN} += " \
237 mnt-overlay.mount \
238"
239
240do_install:append() {
241 install -d ${D}${systemd_system_unitdir}
242 cat <<EOT > ${D}${systemd_system_unitdir}/mnt-overlay.mount
243[Unit]
244Description=Tmpfs directory
245DefaultDependencies=no
246
247[Mount]
248What=tmpfs
249Where=/mnt/overlay
250Type=tmpfs
251Options=mode=1777,strictatime,nosuid,nodev
252
253[Install]
254WantedBy=multi-user.target
255EOT
256}
257
258"""
259
260 self._test_correct_image('systemd-machine-units', systemd_machine_unit_append)
261
Patrick Williams45852732022-04-02 08:58:32 -0500262@OETestTag("runqemu")
Andrew Geissler595f6302022-01-24 19:11:47 +0000263class OverlayFSEtcRunTimeTests(OESelftestTestCase):
264 """overlayfs-etc class tests"""
265
266 def test_all_required_variables_set(self):
267 """
268 Summary: Check that required variables are set
269 Expected: Fail when any of required variables is missing
270 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
271 """
272
273 configBase = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500274DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000275
276# Use systemd as init manager
277VIRTUAL-RUNTIME_init_manager = "systemd"
278
279# enable overlayfs in the kernel
280KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
281
282# Image configuration for overlayfs-etc
283EXTRA_IMAGE_FEATURES += "overlayfs-etc"
284IMAGE_FEATURES:remove = "package-management"
285"""
286 configMountPoint = """
287OVERLAYFS_ETC_MOUNT_POINT = "/data"
288"""
289 configDevice = """
290OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p1"
291"""
292
293 self.write_config(configBase)
294 res = bitbake('core-image-minimal', ignore_status=True)
295 line = getline(res, "OVERLAYFS_ETC_MOUNT_POINT must be set in your MACHINE configuration")
296 self.assertTrue(line, msg=res.output)
297
298 self.append_config(configMountPoint)
299 res = bitbake('core-image-minimal', ignore_status=True)
300 line = getline(res, "OVERLAYFS_ETC_DEVICE must be set in your MACHINE configuration")
301 self.assertTrue(line, msg=res.output)
302
303 self.append_config(configDevice)
304 res = bitbake('core-image-minimal', ignore_status=True)
305 line = getline(res, "OVERLAYFS_ETC_FSTYPE should contain a valid file system type on /dev/mmcblk0p1")
306 self.assertTrue(line, msg=res.output)
307
308 def test_image_feature_conflict(self):
309 """
310 Summary: Overlayfs-etc is not allowed to be used with package-management
311 Expected: Feature conflict
312 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
313 """
314
315 config = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500316DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000317
318# Use systemd as init manager
319VIRTUAL-RUNTIME_init_manager = "systemd"
320
321# enable overlayfs in the kernel
322KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
323EXTRA_IMAGE_FEATURES += "overlayfs-etc"
324EXTRA_IMAGE_FEATURES += "package-management"
325"""
326
327 self.write_config(config)
328
329 res = bitbake('core-image-minimal', ignore_status=True)
330 line = getline(res, "contains conflicting IMAGE_FEATURES")
331 self.assertTrue("overlayfs-etc" in res.output, msg=res.output)
332 self.assertTrue("package-management" in res.output, msg=res.output)
333
334 def test_image_feature_is_missing_class_included(self):
335 configAppend = """
336INHERIT += "overlayfs-etc"
337"""
338 self.run_check_image_feature(configAppend)
339
340 def test_image_feature_is_missing(self):
341 self.run_check_image_feature()
342
343 def run_check_image_feature(self, appendToConfig=""):
344 """
345 Summary: Overlayfs-etc class is not applied when image feature is not set
346 even if we inherit it directly,
347 Expected: Image is created successfully but /etc is not an overlay
348 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
349 """
350
351 config = f"""
Andrew Geisslerd5838332022-05-27 11:33:10 -0500352DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000353
354# Use systemd as init manager
355VIRTUAL-RUNTIME_init_manager = "systemd"
356
357# enable overlayfs in the kernel
358KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
359
360IMAGE_FSTYPES += "wic"
361WKS_FILE = "overlayfs_etc.wks.in"
362
363EXTRA_IMAGE_FEATURES += "read-only-rootfs"
364# Image configuration for overlayfs-etc
365OVERLAYFS_ETC_MOUNT_POINT = "/data"
366OVERLAYFS_ETC_DEVICE = "/dev/sda3"
367{appendToConfig}
368"""
369
370 self.write_config(config)
371
372 bitbake('core-image-minimal')
373
374 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
375 status, output = qemu.run_serial("/bin/mount")
376
377 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
378 self.assertFalse(line, msg=output)
379
380 def test_sbin_init_preinit(self):
381 self.run_sbin_init(False)
382
383 def test_sbin_init_original(self):
384 self.run_sbin_init(True)
385
386 def run_sbin_init(self, origInit):
387 """
388 Summary: Confirm we can replace original init and mount overlay on top of /etc
389 Expected: Image is created successfully and /etc is mounted as an overlay
390 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
391 """
392
393 config = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500394DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000395
396# Use systemd as init manager
397VIRTUAL-RUNTIME_init_manager = "systemd"
398
399# enable overlayfs in the kernel
400KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
401
402IMAGE_FSTYPES += "wic"
403OVERLAYFS_INIT_OPTION = "{OVERLAYFS_INIT_OPTION}"
404WKS_FILE = "overlayfs_etc.wks.in"
405
406EXTRA_IMAGE_FEATURES += "read-only-rootfs"
407# Image configuration for overlayfs-etc
408EXTRA_IMAGE_FEATURES += "overlayfs-etc"
409IMAGE_FEATURES:remove = "package-management"
410OVERLAYFS_ETC_MOUNT_POINT = "/data"
411OVERLAYFS_ETC_FSTYPE = "ext4"
412OVERLAYFS_ETC_DEVICE = "/dev/sda3"
413OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "{OVERLAYFS_ETC_USE_ORIG_INIT_NAME}"
414"""
415
416 args = {
417 'OVERLAYFS_INIT_OPTION': "" if origInit else "init=/sbin/preinit",
418 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': int(origInit == True)
419 }
420
421 self.write_config(config.format(**args))
422
423 bitbake('core-image-minimal')
424 testFile = "/etc/my-test-data"
425
426 with runqemu('core-image-minimal', image_fstype='wic', discard_writes=False) as qemu:
427 status, output = qemu.run_serial("/bin/mount")
428
429 line = getline_qemu(output, "/dev/sda3")
430 self.assertTrue("/data" in output, msg=output)
431
432 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
433 self.assertTrue(line and line.startswith("/data/overlay-etc/upper on /etc type overlay"), msg=output)
434
435 status, output = qemu.run_serial("touch " + testFile)
436 status, output = qemu.run_serial("sync")
437 status, output = qemu.run_serial("ls -1 " + testFile)
438 line = getline_qemu(output, testFile)
439 self.assertTrue(line and line.startswith(testFile), msg=output)
440
441 # Check that file exists in /etc after reboot
442 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
443 status, output = qemu.run_serial("ls -1 " + testFile)
444 line = getline_qemu(output, testFile)
445 self.assertTrue(line and line.startswith(testFile), msg=output)