blob: 472746a64f4b049edf31412aab563ac8bd534b20 [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"
58DISTRO_FEATURES += "systemd overlayfs"
59"""
60
61 self.write_config(config)
62 self.add_overlay_conf_to_machine()
63
64 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler9aee5002022-03-30 16:27:02 +000065 line = getline(res, " Mount path /mnt/overlay not found in fstat 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
70 def test_mount_unit_not_set(self):
71 """
72 Summary: Test whether mount unit was set properly
73 Expected: Fail because mount unit was not set
74 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
75 """
76
77 config = """
78IMAGE_INSTALL:append = " overlayfs-user"
79DISTRO_FEATURES += "systemd overlayfs"
80"""
81
82 self.write_config(config)
83
84 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +000085 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 -050086 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
87
88 def test_wrong_mount_unit_set(self):
89 """
90 Summary: Test whether mount unit was set properly
91 Expected: Fail because not the correct flag used for mount unit
92 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
93 """
94
95 config = """
96IMAGE_INSTALL:append = " overlayfs-user"
97DISTRO_FEATURES += "systemd overlayfs"
98"""
99
100 wrong_machine_config = """
101OVERLAYFS_MOUNT_POINT[usr-share-overlay] = "/usr/share/overlay"
102"""
103
104 self.write_config(config)
105 self.set_machine_config(wrong_machine_config)
106
107 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000108 line = getline(res, "Missing required mount point for OVERLAYFS_MOUNT_POINT[mnt-overlay] in your MACHINE configuration")
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500109 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
110
Andrew Geissler9aee5002022-03-30 16:27:02 +0000111 def _test_correct_image(self, recipe, data):
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500112 """
113 Summary: Check that we can create an image when all parameters are
114 set correctly
115 Expected: Image is created successfully
116 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
117 """
118
119 config = """
120IMAGE_INSTALL:append = " overlayfs-user systemd-machine-units"
121DISTRO_FEATURES += "systemd overlayfs"
122
123# Use systemd as init manager
124VIRTUAL-RUNTIME_init_manager = "systemd"
125
126# enable overlayfs in the kernel
127KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
128"""
129
Andrew Geissler595f6302022-01-24 19:11:47 +0000130 overlayfs_recipe_append = """
131OVERLAYFS_WRITABLE_PATHS[mnt-overlay] += "/usr/share/another-overlay-mount"
132
133SYSTEMD_SERVICE:${PN} += " \
134 my-application.service \
135"
136
137do_install:append() {
138 install -d ${D}${systemd_system_unitdir}
139 cat <<EOT > ${D}${systemd_system_unitdir}/my-application.service
140[Unit]
141Description=Sample application start-up unit
142After=overlayfs-user-overlays.service
143Requires=overlayfs-user-overlays.service
144
145[Service]
146Type=oneshot
147ExecStart=/bin/true
148RemainAfterExit=true
149
150[Install]
151WantedBy=multi-user.target
152EOT
153}
154"""
155
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500156 self.write_config(config)
157 self.add_overlay_conf_to_machine()
Andrew Geissler9aee5002022-03-30 16:27:02 +0000158 self.write_recipeinc(recipe, data)
Andrew Geissler595f6302022-01-24 19:11:47 +0000159 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500160
161 bitbake('core-image-minimal')
162
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500163 with runqemu('core-image-minimal') as qemu:
Andrew Geissler595f6302022-01-24 19:11:47 +0000164 # Check that application service started
165 status, output = qemu.run_serial("systemctl status my-application")
166 self.assertTrue("active (exited)" in output, msg=output)
167
168 # Check that overlay mounts are dependencies of our application unit
169 status, output = qemu.run_serial("systemctl list-dependencies my-application")
170 self.assertTrue("overlayfs-user-overlays.service" in output, msg=output)
171
172 status, output = qemu.run_serial("systemctl list-dependencies overlayfs-user-overlays")
173 self.assertTrue("usr-share-another\\x2doverlay\\x2dmount.mount" in output, msg=output)
174 self.assertTrue("usr-share-my\\x2dapplication.mount" in output, msg=output)
175
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500176 # Check that we have /mnt/overlay fs mounted as tmpfs and
177 # /usr/share/my-application as an overlay (see overlayfs-user recipe)
178 status, output = qemu.run_serial("/bin/mount -t tmpfs,overlay")
179
180 line = getline_qemu(output, "on /mnt/overlay")
181 self.assertTrue(line and line.startswith("tmpfs"), msg=output)
182
183 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/my-application")
184 self.assertTrue(line and line.startswith("overlay"), msg=output)
Andrew Geissler595f6302022-01-24 19:11:47 +0000185
186 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/another-overlay-mount")
187 self.assertTrue(line and line.startswith("overlay"), msg=output)
188
Patrick Williams45852732022-04-02 08:58:32 -0500189 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000190 def test_correct_image_fstab(self):
191 """
192 Summary: Check that we can create an image when all parameters are
193 set correctly via fstab
194 Expected: Image is created successfully
195 Author: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
196 """
197
198 base_files_append = """
199do_install:append() {
200 cat <<EOT >> ${D}${sysconfdir}/fstab
201tmpfs /mnt/overlay tmpfs mode=1777,strictatime,nosuid,nodev 0 0
202EOT
203}
204"""
205
206 self._test_correct_image('base-files', base_files_append)
207
Patrick Williams45852732022-04-02 08:58:32 -0500208 @OETestTag("runqemu")
Andrew Geissler9aee5002022-03-30 16:27:02 +0000209 def test_correct_image_unit(self):
210 """
211 Summary: Check that we can create an image when all parameters are
212 set correctly via mount unit
213 Expected: Image is created successfully
214 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
215 """
216
217 systemd_machine_unit_append = """
218SYSTEMD_SERVICE:${PN} += " \
219 mnt-overlay.mount \
220"
221
222do_install:append() {
223 install -d ${D}${systemd_system_unitdir}
224 cat <<EOT > ${D}${systemd_system_unitdir}/mnt-overlay.mount
225[Unit]
226Description=Tmpfs directory
227DefaultDependencies=no
228
229[Mount]
230What=tmpfs
231Where=/mnt/overlay
232Type=tmpfs
233Options=mode=1777,strictatime,nosuid,nodev
234
235[Install]
236WantedBy=multi-user.target
237EOT
238}
239
240"""
241
242 self._test_correct_image('systemd-machine-units', systemd_machine_unit_append)
243
Patrick Williams45852732022-04-02 08:58:32 -0500244@OETestTag("runqemu")
Andrew Geissler595f6302022-01-24 19:11:47 +0000245class OverlayFSEtcRunTimeTests(OESelftestTestCase):
246 """overlayfs-etc class tests"""
247
248 def test_all_required_variables_set(self):
249 """
250 Summary: Check that required variables are set
251 Expected: Fail when any of required variables is missing
252 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
253 """
254
255 configBase = """
256DISTRO_FEATURES += "systemd"
257
258# Use systemd as init manager
259VIRTUAL-RUNTIME_init_manager = "systemd"
260
261# enable overlayfs in the kernel
262KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
263
264# Image configuration for overlayfs-etc
265EXTRA_IMAGE_FEATURES += "overlayfs-etc"
266IMAGE_FEATURES:remove = "package-management"
267"""
268 configMountPoint = """
269OVERLAYFS_ETC_MOUNT_POINT = "/data"
270"""
271 configDevice = """
272OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p1"
273"""
274
275 self.write_config(configBase)
276 res = bitbake('core-image-minimal', ignore_status=True)
277 line = getline(res, "OVERLAYFS_ETC_MOUNT_POINT must be set in your MACHINE configuration")
278 self.assertTrue(line, msg=res.output)
279
280 self.append_config(configMountPoint)
281 res = bitbake('core-image-minimal', ignore_status=True)
282 line = getline(res, "OVERLAYFS_ETC_DEVICE must be set in your MACHINE configuration")
283 self.assertTrue(line, msg=res.output)
284
285 self.append_config(configDevice)
286 res = bitbake('core-image-minimal', ignore_status=True)
287 line = getline(res, "OVERLAYFS_ETC_FSTYPE should contain a valid file system type on /dev/mmcblk0p1")
288 self.assertTrue(line, msg=res.output)
289
290 def test_image_feature_conflict(self):
291 """
292 Summary: Overlayfs-etc is not allowed to be used with package-management
293 Expected: Feature conflict
294 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
295 """
296
297 config = """
298DISTRO_FEATURES += "systemd"
299
300# Use systemd as init manager
301VIRTUAL-RUNTIME_init_manager = "systemd"
302
303# enable overlayfs in the kernel
304KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
305EXTRA_IMAGE_FEATURES += "overlayfs-etc"
306EXTRA_IMAGE_FEATURES += "package-management"
307"""
308
309 self.write_config(config)
310
311 res = bitbake('core-image-minimal', ignore_status=True)
312 line = getline(res, "contains conflicting IMAGE_FEATURES")
313 self.assertTrue("overlayfs-etc" in res.output, msg=res.output)
314 self.assertTrue("package-management" in res.output, msg=res.output)
315
316 def test_image_feature_is_missing_class_included(self):
317 configAppend = """
318INHERIT += "overlayfs-etc"
319"""
320 self.run_check_image_feature(configAppend)
321
322 def test_image_feature_is_missing(self):
323 self.run_check_image_feature()
324
325 def run_check_image_feature(self, appendToConfig=""):
326 """
327 Summary: Overlayfs-etc class is not applied when image feature is not set
328 even if we inherit it directly,
329 Expected: Image is created successfully but /etc is not an overlay
330 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
331 """
332
333 config = f"""
334DISTRO_FEATURES += "systemd"
335
336# Use systemd as init manager
337VIRTUAL-RUNTIME_init_manager = "systemd"
338
339# enable overlayfs in the kernel
340KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
341
342IMAGE_FSTYPES += "wic"
343WKS_FILE = "overlayfs_etc.wks.in"
344
345EXTRA_IMAGE_FEATURES += "read-only-rootfs"
346# Image configuration for overlayfs-etc
347OVERLAYFS_ETC_MOUNT_POINT = "/data"
348OVERLAYFS_ETC_DEVICE = "/dev/sda3"
349{appendToConfig}
350"""
351
352 self.write_config(config)
353
354 bitbake('core-image-minimal')
355
356 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
357 status, output = qemu.run_serial("/bin/mount")
358
359 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
360 self.assertFalse(line, msg=output)
361
362 def test_sbin_init_preinit(self):
363 self.run_sbin_init(False)
364
365 def test_sbin_init_original(self):
366 self.run_sbin_init(True)
367
368 def run_sbin_init(self, origInit):
369 """
370 Summary: Confirm we can replace original init and mount overlay on top of /etc
371 Expected: Image is created successfully and /etc is mounted as an overlay
372 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
373 """
374
375 config = """
376DISTRO_FEATURES += "systemd"
377
378# Use systemd as init manager
379VIRTUAL-RUNTIME_init_manager = "systemd"
380
381# enable overlayfs in the kernel
382KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
383
384IMAGE_FSTYPES += "wic"
385OVERLAYFS_INIT_OPTION = "{OVERLAYFS_INIT_OPTION}"
386WKS_FILE = "overlayfs_etc.wks.in"
387
388EXTRA_IMAGE_FEATURES += "read-only-rootfs"
389# Image configuration for overlayfs-etc
390EXTRA_IMAGE_FEATURES += "overlayfs-etc"
391IMAGE_FEATURES:remove = "package-management"
392OVERLAYFS_ETC_MOUNT_POINT = "/data"
393OVERLAYFS_ETC_FSTYPE = "ext4"
394OVERLAYFS_ETC_DEVICE = "/dev/sda3"
395OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "{OVERLAYFS_ETC_USE_ORIG_INIT_NAME}"
396"""
397
398 args = {
399 'OVERLAYFS_INIT_OPTION': "" if origInit else "init=/sbin/preinit",
400 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': int(origInit == True)
401 }
402
403 self.write_config(config.format(**args))
404
405 bitbake('core-image-minimal')
406 testFile = "/etc/my-test-data"
407
408 with runqemu('core-image-minimal', image_fstype='wic', discard_writes=False) as qemu:
409 status, output = qemu.run_serial("/bin/mount")
410
411 line = getline_qemu(output, "/dev/sda3")
412 self.assertTrue("/data" in output, msg=output)
413
414 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
415 self.assertTrue(line and line.startswith("/data/overlay-etc/upper on /etc type overlay"), msg=output)
416
417 status, output = qemu.run_serial("touch " + testFile)
418 status, output = qemu.run_serial("sync")
419 status, output = qemu.run_serial("ls -1 " + testFile)
420 line = getline_qemu(output, testFile)
421 self.assertTrue(line and line.startswith(testFile), msg=output)
422
423 # Check that file exists in /etc after reboot
424 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
425 status, output = qemu.run_serial("ls -1 " + testFile)
426 line = getline_qemu(output, testFile)
427 self.assertTrue(line and line.startswith(testFile), msg=output)