blob: bff22f21b600342ab7a9dc5001fc73096360ad80 [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
336 def test_image_feature_is_missing_class_included(self):
337 configAppend = """
338INHERIT += "overlayfs-etc"
339"""
340 self.run_check_image_feature(configAppend)
341
342 def test_image_feature_is_missing(self):
343 self.run_check_image_feature()
344
345 def run_check_image_feature(self, appendToConfig=""):
346 """
347 Summary: Overlayfs-etc class is not applied when image feature is not set
348 even if we inherit it directly,
349 Expected: Image is created successfully but /etc is not an overlay
350 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
351 """
352
353 config = f"""
Andrew Geisslerd5838332022-05-27 11:33:10 -0500354DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000355
356# Use systemd as init manager
357VIRTUAL-RUNTIME_init_manager = "systemd"
358
359# enable overlayfs in the kernel
360KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
361
362IMAGE_FSTYPES += "wic"
363WKS_FILE = "overlayfs_etc.wks.in"
364
365EXTRA_IMAGE_FEATURES += "read-only-rootfs"
366# Image configuration for overlayfs-etc
367OVERLAYFS_ETC_MOUNT_POINT = "/data"
368OVERLAYFS_ETC_DEVICE = "/dev/sda3"
369{appendToConfig}
370"""
371
372 self.write_config(config)
373
374 bitbake('core-image-minimal')
375
376 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
377 status, output = qemu.run_serial("/bin/mount")
378
379 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
380 self.assertFalse(line, msg=output)
381
382 def test_sbin_init_preinit(self):
383 self.run_sbin_init(False)
384
385 def test_sbin_init_original(self):
386 self.run_sbin_init(True)
387
388 def run_sbin_init(self, origInit):
389 """
390 Summary: Confirm we can replace original init and mount overlay on top of /etc
391 Expected: Image is created successfully and /etc is mounted as an overlay
392 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
393 """
394
395 config = """
Andrew Geisslerd5838332022-05-27 11:33:10 -0500396DISTRO_FEATURES:append = " systemd"
Andrew Geissler595f6302022-01-24 19:11:47 +0000397
398# Use systemd as init manager
399VIRTUAL-RUNTIME_init_manager = "systemd"
400
401# enable overlayfs in the kernel
402KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
403
404IMAGE_FSTYPES += "wic"
405OVERLAYFS_INIT_OPTION = "{OVERLAYFS_INIT_OPTION}"
406WKS_FILE = "overlayfs_etc.wks.in"
407
408EXTRA_IMAGE_FEATURES += "read-only-rootfs"
409# Image configuration for overlayfs-etc
410EXTRA_IMAGE_FEATURES += "overlayfs-etc"
411IMAGE_FEATURES:remove = "package-management"
412OVERLAYFS_ETC_MOUNT_POINT = "/data"
413OVERLAYFS_ETC_FSTYPE = "ext4"
414OVERLAYFS_ETC_DEVICE = "/dev/sda3"
415OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "{OVERLAYFS_ETC_USE_ORIG_INIT_NAME}"
416"""
417
418 args = {
419 'OVERLAYFS_INIT_OPTION': "" if origInit else "init=/sbin/preinit",
420 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': int(origInit == True)
421 }
422
423 self.write_config(config.format(**args))
424
425 bitbake('core-image-minimal')
426 testFile = "/etc/my-test-data"
427
428 with runqemu('core-image-minimal', image_fstype='wic', discard_writes=False) as qemu:
429 status, output = qemu.run_serial("/bin/mount")
430
431 line = getline_qemu(output, "/dev/sda3")
432 self.assertTrue("/data" in output, msg=output)
433
434 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
435 self.assertTrue(line and line.startswith("/data/overlay-etc/upper on /etc type overlay"), msg=output)
436
437 status, output = qemu.run_serial("touch " + testFile)
438 status, output = qemu.run_serial("sync")
439 status, output = qemu.run_serial("ls -1 " + testFile)
440 line = getline_qemu(output, testFile)
441 self.assertTrue(line and line.startswith(testFile), msg=output)
442
443 # Check that file exists in /etc after reboot
444 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
445 status, output = qemu.run_serial("ls -1 " + testFile)
446 line = getline_qemu(output, testFile)
447 self.assertTrue(line and line.startswith(testFile), msg=output)