blob: 57a8c8bdb6eb9fa87c48ba0599758dc0b96e513d [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 Williams0ca19cc2021-08-16 14:03:13 -050010
Andrew Geissler595f6302022-01-24 19:11:47 +000011def getline_qemu(out, line):
12 for l in out.split('\n'):
13 if line in l:
14 return l
15
16def getline(res, line):
17 return getline_qemu(res.output, line)
18
Patrick Williams0ca19cc2021-08-16 14:03:13 -050019class OverlayFSTests(OESelftestTestCase):
20 """Overlayfs class usage tests"""
21
Patrick Williams0ca19cc2021-08-16 14:03:13 -050022 def add_overlay_conf_to_machine(self):
23 machine_inc = """
24OVERLAYFS_MOUNT_POINT[mnt-overlay] = "/mnt/overlay"
25"""
26 self.set_machine_config(machine_inc)
27
28 def test_distro_features_missing(self):
29 """
30 Summary: Check that required DISTRO_FEATURES are set
31 Expected: Fail when either systemd or overlayfs are not in DISTRO_FEATURES
32 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
33 """
34
35 config = """
36IMAGE_INSTALL:append = " overlayfs-user"
37"""
38 overlayfs_recipe_append = """
39inherit overlayfs
40"""
41 self.write_config(config)
42 self.add_overlay_conf_to_machine()
43 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
44
45 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +000046 line = getline(res, "overlayfs-user was skipped: missing required distro features")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050047 self.assertTrue("overlayfs" in res.output, msg=res.output)
48 self.assertTrue("systemd" in res.output, msg=res.output)
49 self.assertTrue("ERROR: Required build target 'core-image-minimal' has no buildable providers." in res.output, msg=res.output)
50
51 def test_not_all_units_installed(self):
52 """
53 Summary: Test QA check that we have required mount units in the image
54 Expected: Fail because mount unit for overlay partition is not installed
55 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
56 """
57
58 config = """
59IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -050060DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -050061"""
62
63 self.write_config(config)
64 self.add_overlay_conf_to_machine()
65
66 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geisslerd5838332022-05-27 11:33:10 -050067 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 -050068 self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
Andrew Geissler9aee5002022-03-30 16:27:02 +000069 line = getline(res, "Not all mount paths and units are installed in the image")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050070 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
71
Andrew Geisslerd5838332022-05-27 11:33:10 -050072 def test_not_all_units_installed_but_qa_skipped(self):
73 """
74 Summary: Test skipping the QA check
75 Expected: Image is created successfully
76 Author: Claudius Heine <ch@denx.de>
77 """
78
79 config = """
80IMAGE_INSTALL:append = " overlayfs-user"
81DISTRO_FEATURES += "systemd overlayfs"
82OVERLAYFS_QA_SKIP[mnt-overlay] = "mount-configured"
83"""
84
85 self.write_config(config)
86 self.add_overlay_conf_to_machine()
87
88 bitbake('core-image-minimal')
89
Patrick Williams0ca19cc2021-08-16 14:03:13 -050090 def test_mount_unit_not_set(self):
91 """
92 Summary: Test whether mount unit was set properly
93 Expected: Fail because mount unit was not set
94 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
95 """
96
97 config = """
98IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -050099DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500100"""
101
102 self.write_config(config)
103
104 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000105 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 -0500106 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
107
108 def test_wrong_mount_unit_set(self):
109 """
110 Summary: Test whether mount unit was set properly
111 Expected: Fail because not the correct flag used for mount unit
112 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
113 """
114
115 config = """
116IMAGE_INSTALL:append = " overlayfs-user"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500117DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500118"""
119
120 wrong_machine_config = """
121OVERLAYFS_MOUNT_POINT[usr-share-overlay] = "/usr/share/overlay"
122"""
123
124 self.write_config(config)
125 self.set_machine_config(wrong_machine_config)
126
127 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000128 line = getline(res, "Missing required mount point for OVERLAYFS_MOUNT_POINT[mnt-overlay] in your MACHINE configuration")
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500129 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
130
Andrew Geissler9aee5002022-03-30 16:27:02 +0000131 def _test_correct_image(self, recipe, data):
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500132 """
133 Summary: Check that we can create an image when all parameters are
134 set correctly
135 Expected: Image is created successfully
136 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
137 """
138
139 config = """
140IMAGE_INSTALL:append = " overlayfs-user systemd-machine-units"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500141DISTRO_FEATURES:append = " systemd overlayfs"
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500142
143# Use systemd as init manager
144VIRTUAL-RUNTIME_init_manager = "systemd"
145
146# enable overlayfs in the kernel
147KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
148"""
149
Andrew Geissler595f6302022-01-24 19:11:47 +0000150 overlayfs_recipe_append = """
151OVERLAYFS_WRITABLE_PATHS[mnt-overlay] += "/usr/share/another-overlay-mount"
152
153SYSTEMD_SERVICE:${PN} += " \
154 my-application.service \
155"
156
157do_install:append() {
158 install -d ${D}${systemd_system_unitdir}
159 cat <<EOT > ${D}${systemd_system_unitdir}/my-application.service
160[Unit]
161Description=Sample application start-up unit
162After=overlayfs-user-overlays.service
163Requires=overlayfs-user-overlays.service
164
165[Service]
166Type=oneshot
167ExecStart=/bin/true
168RemainAfterExit=true
169
170[Install]
171WantedBy=multi-user.target
172EOT
173}
174"""
175
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500176 self.write_config(config)
177 self.add_overlay_conf_to_machine()
Andrew Geissler9aee5002022-03-30 16:27:02 +0000178 self.write_recipeinc(recipe, data)
Andrew Geissler595f6302022-01-24 19:11:47 +0000179 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500180
181 bitbake('core-image-minimal')
182
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500183 with runqemu('core-image-minimal') as qemu:
Andrew Geissler595f6302022-01-24 19:11:47 +0000184 # Check that application service started
185 status, output = qemu.run_serial("systemctl status my-application")
186 self.assertTrue("active (exited)" in output, msg=output)
187
188 # Check that overlay mounts are dependencies of our application unit
189 status, output = qemu.run_serial("systemctl list-dependencies my-application")
190 self.assertTrue("overlayfs-user-overlays.service" in output, msg=output)
191
192 status, output = qemu.run_serial("systemctl list-dependencies overlayfs-user-overlays")
193 self.assertTrue("usr-share-another\\x2doverlay\\x2dmount.mount" in output, msg=output)
194 self.assertTrue("usr-share-my\\x2dapplication.mount" in output, msg=output)
195
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500196 # Check that we have /mnt/overlay fs mounted as tmpfs and
197 # /usr/share/my-application as an overlay (see overlayfs-user recipe)
198 status, output = qemu.run_serial("/bin/mount -t tmpfs,overlay")
199
200 line = getline_qemu(output, "on /mnt/overlay")
201 self.assertTrue(line and line.startswith("tmpfs"), msg=output)
202
203 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/my-application")
204 self.assertTrue(line and line.startswith("overlay"), msg=output)
Andrew Geissler595f6302022-01-24 19:11:47 +0000205
206 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/another-overlay-mount")
207 self.assertTrue(line and line.startswith("overlay"), msg=output)
208
Patrick Williams45852732022-04-02 08:58:32 -0500209 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000210 def test_correct_image_fstab(self):
211 """
212 Summary: Check that we can create an image when all parameters are
213 set correctly via fstab
214 Expected: Image is created successfully
215 Author: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
216 """
217
218 base_files_append = """
219do_install:append() {
220 cat <<EOT >> ${D}${sysconfdir}/fstab
221tmpfs /mnt/overlay tmpfs mode=1777,strictatime,nosuid,nodev 0 0
222EOT
223}
224"""
225
226 self._test_correct_image('base-files', base_files_append)
227
Patrick Williams45852732022-04-02 08:58:32 -0500228 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000229 def test_correct_image_unit(self):
230 """
231 Summary: Check that we can create an image when all parameters are
232 set correctly via mount unit
233 Expected: Image is created successfully
234 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
235 """
236
237 systemd_machine_unit_append = """
238SYSTEMD_SERVICE:${PN} += " \
239 mnt-overlay.mount \
240"
241
242do_install:append() {
243 install -d ${D}${systemd_system_unitdir}
244 cat <<EOT > ${D}${systemd_system_unitdir}/mnt-overlay.mount
245[Unit]
246Description=Tmpfs directory
247DefaultDependencies=no
248
249[Mount]
250What=tmpfs
251Where=/mnt/overlay
252Type=tmpfs
253Options=mode=1777,strictatime,nosuid,nodev
254
255[Install]
256WantedBy=multi-user.target
257EOT
258}
259
260"""
261
262 self._test_correct_image('systemd-machine-units', systemd_machine_unit_append)
263
Patrick Williams45852732022-04-02 08:58:32 -0500264@OETestTag("runqemu")
Andrew Geissler595f6302022-01-24 19:11:47 +0000265class OverlayFSEtcRunTimeTests(OESelftestTestCase):
266 """overlayfs-etc class tests"""
267
268 def test_all_required_variables_set(self):
269 """
270 Summary: Check that required variables are set
271 Expected: Fail when any of required variables is missing
272 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
273 """
274
275 configBase = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500276DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000277
278# Use systemd as init manager
279VIRTUAL-RUNTIME_init_manager = "systemd"
280
281# enable overlayfs in the kernel
282KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
283
284# Image configuration for overlayfs-etc
285EXTRA_IMAGE_FEATURES += "overlayfs-etc"
286IMAGE_FEATURES:remove = "package-management"
287"""
288 configMountPoint = """
289OVERLAYFS_ETC_MOUNT_POINT = "/data"
290"""
291 configDevice = """
292OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p1"
293"""
294
295 self.write_config(configBase)
296 res = bitbake('core-image-minimal', ignore_status=True)
297 line = getline(res, "OVERLAYFS_ETC_MOUNT_POINT must be set in your MACHINE configuration")
298 self.assertTrue(line, msg=res.output)
299
300 self.append_config(configMountPoint)
301 res = bitbake('core-image-minimal', ignore_status=True)
302 line = getline(res, "OVERLAYFS_ETC_DEVICE must be set in your MACHINE configuration")
303 self.assertTrue(line, msg=res.output)
304
305 self.append_config(configDevice)
306 res = bitbake('core-image-minimal', ignore_status=True)
307 line = getline(res, "OVERLAYFS_ETC_FSTYPE should contain a valid file system type on /dev/mmcblk0p1")
308 self.assertTrue(line, msg=res.output)
309
310 def test_image_feature_conflict(self):
311 """
312 Summary: Overlayfs-etc is not allowed to be used with package-management
313 Expected: Feature conflict
314 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
315 """
316
317 config = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500318DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000319
320# Use systemd as init manager
321VIRTUAL-RUNTIME_init_manager = "systemd"
322
323# enable overlayfs in the kernel
324KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
325EXTRA_IMAGE_FEATURES += "overlayfs-etc"
326EXTRA_IMAGE_FEATURES += "package-management"
327"""
328
329 self.write_config(config)
330
331 res = bitbake('core-image-minimal', ignore_status=True)
332 line = getline(res, "contains conflicting IMAGE_FEATURES")
333 self.assertTrue("overlayfs-etc" in res.output, msg=res.output)
334 self.assertTrue("package-management" in res.output, msg=res.output)
335
Andrew Geissler595f6302022-01-24 19:11:47 +0000336 def test_image_feature_is_missing(self):
Andrew Geissler595f6302022-01-24 19:11:47 +0000337 """
338 Summary: Overlayfs-etc class is not applied when image feature is not set
Andrew Geissler595f6302022-01-24 19:11:47 +0000339 Expected: Image is created successfully but /etc is not an overlay
340 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
341 """
342
Andrew Geissler87f5cff2022-09-30 13:13:31 -0500343 config = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500344DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000345
346# Use systemd as init manager
347VIRTUAL-RUNTIME_init_manager = "systemd"
348
349# enable overlayfs in the kernel
350KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
351
352IMAGE_FSTYPES += "wic"
353WKS_FILE = "overlayfs_etc.wks.in"
354
355EXTRA_IMAGE_FEATURES += "read-only-rootfs"
356# Image configuration for overlayfs-etc
357OVERLAYFS_ETC_MOUNT_POINT = "/data"
358OVERLAYFS_ETC_DEVICE = "/dev/sda3"
Andrew Geissler595f6302022-01-24 19:11:47 +0000359"""
360
361 self.write_config(config)
362
363 bitbake('core-image-minimal')
364
365 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
366 status, output = qemu.run_serial("/bin/mount")
367
368 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
369 self.assertFalse(line, msg=output)
370
371 def test_sbin_init_preinit(self):
372 self.run_sbin_init(False)
373
374 def test_sbin_init_original(self):
375 self.run_sbin_init(True)
376
377 def run_sbin_init(self, origInit):
378 """
379 Summary: Confirm we can replace original init and mount overlay on top of /etc
380 Expected: Image is created successfully and /etc is mounted as an overlay
381 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
382 """
383
Andrew Geissler87f5cff2022-09-30 13:13:31 -0500384 config = self.get_working_config()
385
386 args = {
387 'OVERLAYFS_INIT_OPTION': "" if origInit else "init=/sbin/preinit",
388 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': int(origInit == True)
389 }
390
391 self.write_config(config.format(**args))
392
393 bitbake('core-image-minimal')
394 testFile = "/etc/my-test-data"
395
396 with runqemu('core-image-minimal', image_fstype='wic', discard_writes=False) as qemu:
397 status, output = qemu.run_serial("/bin/mount")
398
399 line = getline_qemu(output, "/dev/sda3")
400 self.assertTrue("/data" in output, msg=output)
401
402 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
403 self.assertTrue(line and line.startswith("/data/overlay-etc/upper on /etc type overlay"), msg=output)
404
405 # check that lower layer is not available
406 status, output = qemu.run_serial("ls -1 /data/overlay-etc/lower")
407 line = getline_qemu(output, "No such file or directory")
408 self.assertTrue(line, msg=output)
409
410 status, output = qemu.run_serial("touch " + testFile)
411 status, output = qemu.run_serial("sync")
412 status, output = qemu.run_serial("ls -1 " + testFile)
413 line = getline_qemu(output, testFile)
414 self.assertTrue(line and line.startswith(testFile), msg=output)
415
416 # Check that file exists in /etc after reboot
417 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
418 status, output = qemu.run_serial("ls -1 " + testFile)
419 line = getline_qemu(output, testFile)
420 self.assertTrue(line and line.startswith(testFile), msg=output)
421
422 def test_lower_layer_access(self):
423 """
424 Summary: Test that lower layer of /etc is available read-only when configured
425 Expected: Can't write to lower layer. The files on lower and upper different after
426 modification
427 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
428 """
429
430 config = self.get_working_config()
431
432 configLower = """
433OVERLAYFS_ETC_EXPOSE_LOWER = "1"
434IMAGE_INSTALL:append = " overlayfs-user"
435"""
436 testFile = "lower-layer-test.txt"
437
438 args = {
439 'OVERLAYFS_INIT_OPTION': "",
440 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': 1
441 }
442
443 self.write_config(config.format(**args))
444
445 self.append_config(configLower)
446 bitbake('core-image-minimal')
447
448 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
449 status, output = qemu.run_serial("echo \"Modified in upper\" > /etc/" + testFile)
450 status, output = qemu.run_serial("diff /etc/" + testFile + " /data/overlay-etc/lower/" + testFile)
451 line = getline_qemu(output, "Modified in upper")
452 self.assertTrue(line, msg=output)
453 line = getline_qemu(output, "Original file")
454 self.assertTrue(line, msg=output)
455
456 status, output = qemu.run_serial("touch /data/overlay-etc/lower/ro-test.txt")
457 line = getline_qemu(output, "Read-only file system")
458 self.assertTrue(line, msg=output)
459
460 def get_working_config(self):
461 return """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500462DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000463
464# Use systemd as init manager
465VIRTUAL-RUNTIME_init_manager = "systemd"
466
467# enable overlayfs in the kernel
468KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
469
470IMAGE_FSTYPES += "wic"
471OVERLAYFS_INIT_OPTION = "{OVERLAYFS_INIT_OPTION}"
472WKS_FILE = "overlayfs_etc.wks.in"
473
474EXTRA_IMAGE_FEATURES += "read-only-rootfs"
475# Image configuration for overlayfs-etc
476EXTRA_IMAGE_FEATURES += "overlayfs-etc"
477IMAGE_FEATURES:remove = "package-management"
478OVERLAYFS_ETC_MOUNT_POINT = "/data"
479OVERLAYFS_ETC_FSTYPE = "ext4"
480OVERLAYFS_ETC_DEVICE = "/dev/sda3"
481OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "{OVERLAYFS_ETC_USE_ORIG_INIT_NAME}"
482"""