blob: dfd9f1486d07ef970632783f8780953ad18f76d1 [file] [log] [blame]
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001#
Patrick Williams92b42cb2022-09-03 06:53:57 -05002# Copyright OpenEmbedded Contributors
3#
Patrick Williams0ca19cc2021-08-16 14:03:13 -05004# SPDX-License-Identifier: MIT
5#
6
7from oeqa.selftest.case import OESelftestTestCase
Patrick Williams45852732022-04-02 08:58:32 -05008from oeqa.utils.commands import bitbake, runqemu
9from oeqa.core.decorator import OETestTag
Patrick Williams7784c422022-11-17 07:29:11 -060010from oeqa.core.decorator.data import skipIfNotMachine
Patrick Williams0ca19cc2021-08-16 14:03:13 -050011
Andrew Geissler595f6302022-01-24 19:11:47 +000012def getline_qemu(out, line):
13 for l in out.split('\n'):
14 if line in l:
15 return l
16
17def getline(res, line):
18 return getline_qemu(res.output, line)
19
Patrick Williams0ca19cc2021-08-16 14:03:13 -050020class OverlayFSTests(OESelftestTestCase):
21 """Overlayfs class usage tests"""
22
Patrick Williams0ca19cc2021-08-16 14:03:13 -050023 def add_overlay_conf_to_machine(self):
24 machine_inc = """
25OVERLAYFS_MOUNT_POINT[mnt-overlay] = "/mnt/overlay"
26"""
27 self.set_machine_config(machine_inc)
28
29 def test_distro_features_missing(self):
30 """
31 Summary: Check that required DISTRO_FEATURES are set
32 Expected: Fail when either systemd or overlayfs are not in DISTRO_FEATURES
33 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
34 """
35
36 config = """
37IMAGE_INSTALL:append = " overlayfs-user"
38"""
39 overlayfs_recipe_append = """
40inherit overlayfs
41"""
42 self.write_config(config)
43 self.add_overlay_conf_to_machine()
44 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
45
46 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +000047 line = getline(res, "overlayfs-user was skipped: missing required distro features")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050048 self.assertTrue("overlayfs" in res.output, msg=res.output)
49 self.assertTrue("systemd" in res.output, msg=res.output)
50 self.assertTrue("ERROR: Required build target 'core-image-minimal' has no buildable providers." in res.output, msg=res.output)
51
52 def test_not_all_units_installed(self):
53 """
54 Summary: Test QA check that we have required mount units in the image
55 Expected: Fail because mount unit for overlay partition is not installed
56 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
57 """
58
59 config = """
60IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -050061DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -050062"""
63
64 self.write_config(config)
65 self.add_overlay_conf_to_machine()
66
67 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geisslerd5838332022-05-27 11:33:10 -050068 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 -050069 self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
Andrew Geissler9aee5002022-03-30 16:27:02 +000070 line = getline(res, "Not all mount paths and units are installed in the image")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050071 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
72
Andrew Geisslerd5838332022-05-27 11:33:10 -050073 def test_not_all_units_installed_but_qa_skipped(self):
74 """
75 Summary: Test skipping the QA check
76 Expected: Image is created successfully
77 Author: Claudius Heine <ch@denx.de>
78 """
79
80 config = """
81IMAGE_INSTALL:append = " overlayfs-user"
82DISTRO_FEATURES += "systemd overlayfs"
83OVERLAYFS_QA_SKIP[mnt-overlay] = "mount-configured"
84"""
85
86 self.write_config(config)
87 self.add_overlay_conf_to_machine()
88
89 bitbake('core-image-minimal')
90
Patrick Williams0ca19cc2021-08-16 14:03:13 -050091 def test_mount_unit_not_set(self):
92 """
93 Summary: Test whether mount unit was set properly
94 Expected: Fail because mount unit was not set
95 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
96 """
97
98 config = """
99IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500100DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500101"""
102
103 self.write_config(config)
104
105 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000106 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 -0500107 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
108
109 def test_wrong_mount_unit_set(self):
110 """
111 Summary: Test whether mount unit was set properly
112 Expected: Fail because not the correct flag used for mount unit
113 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
114 """
115
116 config = """
117IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500118DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500119"""
120
121 wrong_machine_config = """
122OVERLAYFS_MOUNT_POINT[usr-share-overlay] = "/usr/share/overlay"
123"""
124
125 self.write_config(config)
126 self.set_machine_config(wrong_machine_config)
127
128 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000129 line = getline(res, "Missing required mount point for OVERLAYFS_MOUNT_POINT[mnt-overlay] in your MACHINE configuration")
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500130 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
131
Andrew Geissler9aee5002022-03-30 16:27:02 +0000132 def _test_correct_image(self, recipe, data):
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500133 """
134 Summary: Check that we can create an image when all parameters are
135 set correctly
136 Expected: Image is created successfully
137 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
138 """
139
140 config = """
141IMAGE_INSTALL:append = " overlayfs-user systemd-machine-units"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500142DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500143
144# Use systemd as init manager
145VIRTUAL-RUNTIME_init_manager = "systemd"
146
147# enable overlayfs in the kernel
148KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
149"""
150
Andrew Geissler595f6302022-01-24 19:11:47 +0000151 overlayfs_recipe_append = """
152OVERLAYFS_WRITABLE_PATHS[mnt-overlay] += "/usr/share/another-overlay-mount"
153
154SYSTEMD_SERVICE:${PN} += " \
155 my-application.service \
156"
157
158do_install:append() {
159 install -d ${D}${systemd_system_unitdir}
160 cat <<EOT > ${D}${systemd_system_unitdir}/my-application.service
161[Unit]
162Description=Sample application start-up unit
163After=overlayfs-user-overlays.service
164Requires=overlayfs-user-overlays.service
165
166[Service]
167Type=oneshot
168ExecStart=/bin/true
169RemainAfterExit=true
170
171[Install]
172WantedBy=multi-user.target
173EOT
174}
175"""
176
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500177 self.write_config(config)
178 self.add_overlay_conf_to_machine()
Andrew Geissler9aee5002022-03-30 16:27:02 +0000179 self.write_recipeinc(recipe, data)
Andrew Geissler595f6302022-01-24 19:11:47 +0000180 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500181
182 bitbake('core-image-minimal')
183
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500184 with runqemu('core-image-minimal') as qemu:
Andrew Geissler595f6302022-01-24 19:11:47 +0000185 # Check that application service started
186 status, output = qemu.run_serial("systemctl status my-application")
187 self.assertTrue("active (exited)" in output, msg=output)
188
189 # Check that overlay mounts are dependencies of our application unit
190 status, output = qemu.run_serial("systemctl list-dependencies my-application")
191 self.assertTrue("overlayfs-user-overlays.service" in output, msg=output)
192
193 status, output = qemu.run_serial("systemctl list-dependencies overlayfs-user-overlays")
194 self.assertTrue("usr-share-another\\x2doverlay\\x2dmount.mount" in output, msg=output)
195 self.assertTrue("usr-share-my\\x2dapplication.mount" in output, msg=output)
196
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500197 # Check that we have /mnt/overlay fs mounted as tmpfs and
198 # /usr/share/my-application as an overlay (see overlayfs-user recipe)
199 status, output = qemu.run_serial("/bin/mount -t tmpfs,overlay")
200
201 line = getline_qemu(output, "on /mnt/overlay")
202 self.assertTrue(line and line.startswith("tmpfs"), msg=output)
203
204 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/my-application")
205 self.assertTrue(line and line.startswith("overlay"), msg=output)
Andrew Geissler595f6302022-01-24 19:11:47 +0000206
207 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/another-overlay-mount")
208 self.assertTrue(line and line.startswith("overlay"), msg=output)
209
Patrick Williams45852732022-04-02 08:58:32 -0500210 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000211 def test_correct_image_fstab(self):
212 """
213 Summary: Check that we can create an image when all parameters are
214 set correctly via fstab
215 Expected: Image is created successfully
216 Author: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
217 """
218
219 base_files_append = """
220do_install:append() {
221 cat <<EOT >> ${D}${sysconfdir}/fstab
222tmpfs /mnt/overlay tmpfs mode=1777,strictatime,nosuid,nodev 0 0
223EOT
224}
225"""
226
227 self._test_correct_image('base-files', base_files_append)
228
Patrick Williams45852732022-04-02 08:58:32 -0500229 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000230 def test_correct_image_unit(self):
231 """
232 Summary: Check that we can create an image when all parameters are
233 set correctly via mount unit
234 Expected: Image is created successfully
235 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
236 """
237
238 systemd_machine_unit_append = """
239SYSTEMD_SERVICE:${PN} += " \
240 mnt-overlay.mount \
241"
242
243do_install:append() {
244 install -d ${D}${systemd_system_unitdir}
245 cat <<EOT > ${D}${systemd_system_unitdir}/mnt-overlay.mount
246[Unit]
247Description=Tmpfs directory
248DefaultDependencies=no
249
250[Mount]
251What=tmpfs
252Where=/mnt/overlay
253Type=tmpfs
254Options=mode=1777,strictatime,nosuid,nodev
255
256[Install]
257WantedBy=multi-user.target
258EOT
259}
260
261"""
262
263 self._test_correct_image('systemd-machine-units', systemd_machine_unit_append)
264
Patrick Williams45852732022-04-02 08:58:32 -0500265@OETestTag("runqemu")
Andrew Geissler595f6302022-01-24 19:11:47 +0000266class OverlayFSEtcRunTimeTests(OESelftestTestCase):
267 """overlayfs-etc class tests"""
268
269 def test_all_required_variables_set(self):
270 """
271 Summary: Check that required variables are set
272 Expected: Fail when any of required variables is missing
273 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
274 """
275
276 configBase = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500277DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000278
279# Use systemd as init manager
280VIRTUAL-RUNTIME_init_manager = "systemd"
281
282# enable overlayfs in the kernel
283KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
284
285# Image configuration for overlayfs-etc
286EXTRA_IMAGE_FEATURES += "overlayfs-etc"
287IMAGE_FEATURES:remove = "package-management"
288"""
289 configMountPoint = """
290OVERLAYFS_ETC_MOUNT_POINT = "/data"
291"""
292 configDevice = """
293OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p1"
294"""
295
296 self.write_config(configBase)
297 res = bitbake('core-image-minimal', ignore_status=True)
298 line = getline(res, "OVERLAYFS_ETC_MOUNT_POINT must be set in your MACHINE configuration")
299 self.assertTrue(line, msg=res.output)
300
301 self.append_config(configMountPoint)
302 res = bitbake('core-image-minimal', ignore_status=True)
303 line = getline(res, "OVERLAYFS_ETC_DEVICE must be set in your MACHINE configuration")
304 self.assertTrue(line, msg=res.output)
305
306 self.append_config(configDevice)
307 res = bitbake('core-image-minimal', ignore_status=True)
308 line = getline(res, "OVERLAYFS_ETC_FSTYPE should contain a valid file system type on /dev/mmcblk0p1")
309 self.assertTrue(line, msg=res.output)
310
311 def test_image_feature_conflict(self):
312 """
313 Summary: Overlayfs-etc is not allowed to be used with package-management
314 Expected: Feature conflict
315 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
316 """
317
318 config = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500319DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000320
321# Use systemd as init manager
322VIRTUAL-RUNTIME_init_manager = "systemd"
323
324# enable overlayfs in the kernel
325KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
326EXTRA_IMAGE_FEATURES += "overlayfs-etc"
327EXTRA_IMAGE_FEATURES += "package-management"
328"""
329
330 self.write_config(config)
331
332 res = bitbake('core-image-minimal', ignore_status=True)
333 line = getline(res, "contains conflicting IMAGE_FEATURES")
334 self.assertTrue("overlayfs-etc" in res.output, msg=res.output)
335 self.assertTrue("package-management" in res.output, msg=res.output)
336
Patrick Williams7784c422022-11-17 07:29:11 -0600337 # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14963
338 @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
Andrew Geissler595f6302022-01-24 19:11:47 +0000339 def test_image_feature_is_missing(self):
Andrew Geissler595f6302022-01-24 19:11:47 +0000340 """
341 Summary: Overlayfs-etc class is not applied when image feature is not set
Andrew Geissler595f6302022-01-24 19:11:47 +0000342 Expected: Image is created successfully but /etc is not an overlay
343 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
344 """
345
Andrew Geissler87f5cff2022-09-30 13:13:31 -0500346 config = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500347DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000348
349# Use systemd as init manager
350VIRTUAL-RUNTIME_init_manager = "systemd"
351
352# enable overlayfs in the kernel
353KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
354
355IMAGE_FSTYPES += "wic"
356WKS_FILE = "overlayfs_etc.wks.in"
357
358EXTRA_IMAGE_FEATURES += "read-only-rootfs"
359# Image configuration for overlayfs-etc
360OVERLAYFS_ETC_MOUNT_POINT = "/data"
361OVERLAYFS_ETC_DEVICE = "/dev/sda3"
Andrew Geissler595f6302022-01-24 19:11:47 +0000362"""
363
364 self.write_config(config)
365
366 bitbake('core-image-minimal')
367
368 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
369 status, output = qemu.run_serial("/bin/mount")
370
371 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
372 self.assertFalse(line, msg=output)
373
Patrick Williams7784c422022-11-17 07:29:11 -0600374 @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
Andrew Geissler595f6302022-01-24 19:11:47 +0000375 def test_sbin_init_preinit(self):
376 self.run_sbin_init(False)
377
Patrick Williams7784c422022-11-17 07:29:11 -0600378 @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
Andrew Geissler595f6302022-01-24 19:11:47 +0000379 def test_sbin_init_original(self):
380 self.run_sbin_init(True)
381
382 def run_sbin_init(self, origInit):
383 """
384 Summary: Confirm we can replace original init and mount overlay on top of /etc
385 Expected: Image is created successfully and /etc is mounted as an overlay
386 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
387 """
388
Andrew Geissler87f5cff2022-09-30 13:13:31 -0500389 config = self.get_working_config()
390
391 args = {
392 'OVERLAYFS_INIT_OPTION': "" if origInit else "init=/sbin/preinit",
393 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': int(origInit == True)
394 }
395
396 self.write_config(config.format(**args))
397
398 bitbake('core-image-minimal')
399 testFile = "/etc/my-test-data"
400
401 with runqemu('core-image-minimal', image_fstype='wic', discard_writes=False) as qemu:
402 status, output = qemu.run_serial("/bin/mount")
403
404 line = getline_qemu(output, "/dev/sda3")
405 self.assertTrue("/data" in output, msg=output)
406
407 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
408 self.assertTrue(line and line.startswith("/data/overlay-etc/upper on /etc type overlay"), msg=output)
409
410 # check that lower layer is not available
411 status, output = qemu.run_serial("ls -1 /data/overlay-etc/lower")
412 line = getline_qemu(output, "No such file or directory")
413 self.assertTrue(line, msg=output)
414
415 status, output = qemu.run_serial("touch " + testFile)
416 status, output = qemu.run_serial("sync")
417 status, output = qemu.run_serial("ls -1 " + testFile)
418 line = getline_qemu(output, testFile)
419 self.assertTrue(line and line.startswith(testFile), msg=output)
420
421 # Check that file exists in /etc after reboot
422 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
423 status, output = qemu.run_serial("ls -1 " + testFile)
424 line = getline_qemu(output, testFile)
425 self.assertTrue(line and line.startswith(testFile), msg=output)
426
Patrick Williams7784c422022-11-17 07:29:11 -0600427 @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
Andrew Geissler87f5cff2022-09-30 13:13:31 -0500428 def test_lower_layer_access(self):
429 """
430 Summary: Test that lower layer of /etc is available read-only when configured
431 Expected: Can't write to lower layer. The files on lower and upper different after
432 modification
433 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
434 """
435
436 config = self.get_working_config()
437
438 configLower = """
439OVERLAYFS_ETC_EXPOSE_LOWER = "1"
440IMAGE_INSTALL:append = " overlayfs-user"
441"""
442 testFile = "lower-layer-test.txt"
443
444 args = {
445 'OVERLAYFS_INIT_OPTION': "",
446 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': 1
447 }
448
449 self.write_config(config.format(**args))
450
451 self.append_config(configLower)
452 bitbake('core-image-minimal')
453
454 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
455 status, output = qemu.run_serial("echo \"Modified in upper\" > /etc/" + testFile)
456 status, output = qemu.run_serial("diff /etc/" + testFile + " /data/overlay-etc/lower/" + testFile)
457 line = getline_qemu(output, "Modified in upper")
458 self.assertTrue(line, msg=output)
459 line = getline_qemu(output, "Original file")
460 self.assertTrue(line, msg=output)
461
462 status, output = qemu.run_serial("touch /data/overlay-etc/lower/ro-test.txt")
463 line = getline_qemu(output, "Read-only file system")
464 self.assertTrue(line, msg=output)
465
466 def get_working_config(self):
467 return """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500468DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000469
470# Use systemd as init manager
471VIRTUAL-RUNTIME_init_manager = "systemd"
472
473# enable overlayfs in the kernel
474KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
475
476IMAGE_FSTYPES += "wic"
477OVERLAYFS_INIT_OPTION = "{OVERLAYFS_INIT_OPTION}"
478WKS_FILE = "overlayfs_etc.wks.in"
479
480EXTRA_IMAGE_FEATURES += "read-only-rootfs"
481# Image configuration for overlayfs-etc
482EXTRA_IMAGE_FEATURES += "overlayfs-etc"
483IMAGE_FEATURES:remove = "package-management"
484OVERLAYFS_ETC_MOUNT_POINT = "/data"
485OVERLAYFS_ETC_FSTYPE = "ext4"
486OVERLAYFS_ETC_DEVICE = "/dev/sda3"
487OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "{OVERLAYFS_ETC_USE_ORIG_INIT_NAME}"
488"""