blob: 56ae48ce64b4f3c49e982e7a580c3e0a18aa9047 [file] [log] [blame]
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001#
2# SPDX-License-Identifier: MIT
3#
4
5from oeqa.selftest.case import OESelftestTestCase
6from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu
7
Andrew Geissler595f6302022-01-24 19:11:47 +00008def getline_qemu(out, line):
9 for l in out.split('\n'):
10 if line in l:
11 return l
12
13def getline(res, line):
14 return getline_qemu(res.output, line)
15
Patrick Williams0ca19cc2021-08-16 14:03:13 -050016class OverlayFSTests(OESelftestTestCase):
17 """Overlayfs class usage tests"""
18
Patrick Williams0ca19cc2021-08-16 14:03:13 -050019 def add_overlay_conf_to_machine(self):
20 machine_inc = """
21OVERLAYFS_MOUNT_POINT[mnt-overlay] = "/mnt/overlay"
22"""
23 self.set_machine_config(machine_inc)
24
25 def test_distro_features_missing(self):
26 """
27 Summary: Check that required DISTRO_FEATURES are set
28 Expected: Fail when either systemd or overlayfs are not in DISTRO_FEATURES
29 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
30 """
31
32 config = """
33IMAGE_INSTALL:append = " overlayfs-user"
34"""
35 overlayfs_recipe_append = """
36inherit overlayfs
37"""
38 self.write_config(config)
39 self.add_overlay_conf_to_machine()
40 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
41
42 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +000043 line = getline(res, "overlayfs-user was skipped: missing required distro features")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050044 self.assertTrue("overlayfs" in res.output, msg=res.output)
45 self.assertTrue("systemd" in res.output, msg=res.output)
46 self.assertTrue("ERROR: Required build target 'core-image-minimal' has no buildable providers." in res.output, msg=res.output)
47
48 def test_not_all_units_installed(self):
49 """
50 Summary: Test QA check that we have required mount units in the image
51 Expected: Fail because mount unit for overlay partition is not installed
52 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
53 """
54
55 config = """
56IMAGE_INSTALL:append = " overlayfs-user"
57DISTRO_FEATURES += "systemd overlayfs"
58"""
59
60 self.write_config(config)
61 self.add_overlay_conf_to_machine()
62
63 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler9aee5002022-03-30 16:27:02 +000064 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 -050065 self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
Andrew Geissler9aee5002022-03-30 16:27:02 +000066 line = getline(res, "Not all mount paths and units are installed in the image")
Patrick Williams0ca19cc2021-08-16 14:03:13 -050067 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
68
69 def test_mount_unit_not_set(self):
70 """
71 Summary: Test whether mount unit was set properly
72 Expected: Fail because mount unit was not set
73 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
74 """
75
76 config = """
77IMAGE_INSTALL:append = " overlayfs-user"
78DISTRO_FEATURES += "systemd overlayfs"
79"""
80
81 self.write_config(config)
82
83 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +000084 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 -050085 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
86
87 def test_wrong_mount_unit_set(self):
88 """
89 Summary: Test whether mount unit was set properly
90 Expected: Fail because not the correct flag used for mount unit
91 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
92 """
93
94 config = """
95IMAGE_INSTALL:append = " overlayfs-user"
96DISTRO_FEATURES += "systemd overlayfs"
97"""
98
99 wrong_machine_config = """
100OVERLAYFS_MOUNT_POINT[usr-share-overlay] = "/usr/share/overlay"
101"""
102
103 self.write_config(config)
104 self.set_machine_config(wrong_machine_config)
105
106 res = bitbake('core-image-minimal', ignore_status=True)
Andrew Geissler595f6302022-01-24 19:11:47 +0000107 line = getline(res, "Missing required mount point for OVERLAYFS_MOUNT_POINT[mnt-overlay] in your MACHINE configuration")
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500108 self.assertTrue(line and line.startswith("Parsing recipes...ERROR:"), msg=res.output)
109
Andrew Geissler9aee5002022-03-30 16:27:02 +0000110 def _test_correct_image(self, recipe, data):
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500111 """
112 Summary: Check that we can create an image when all parameters are
113 set correctly
114 Expected: Image is created successfully
115 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
116 """
117
118 config = """
119IMAGE_INSTALL:append = " overlayfs-user systemd-machine-units"
120DISTRO_FEATURES += "systemd overlayfs"
121
122# Use systemd as init manager
123VIRTUAL-RUNTIME_init_manager = "systemd"
124
125# enable overlayfs in the kernel
126KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
127"""
128
Andrew Geissler595f6302022-01-24 19:11:47 +0000129 overlayfs_recipe_append = """
130OVERLAYFS_WRITABLE_PATHS[mnt-overlay] += "/usr/share/another-overlay-mount"
131
132SYSTEMD_SERVICE:${PN} += " \
133 my-application.service \
134"
135
136do_install:append() {
137 install -d ${D}${systemd_system_unitdir}
138 cat <<EOT > ${D}${systemd_system_unitdir}/my-application.service
139[Unit]
140Description=Sample application start-up unit
141After=overlayfs-user-overlays.service
142Requires=overlayfs-user-overlays.service
143
144[Service]
145Type=oneshot
146ExecStart=/bin/true
147RemainAfterExit=true
148
149[Install]
150WantedBy=multi-user.target
151EOT
152}
153"""
154
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500155 self.write_config(config)
156 self.add_overlay_conf_to_machine()
Andrew Geissler9aee5002022-03-30 16:27:02 +0000157 self.write_recipeinc(recipe, data)
Andrew Geissler595f6302022-01-24 19:11:47 +0000158 self.write_recipeinc('overlayfs-user', overlayfs_recipe_append)
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500159
160 bitbake('core-image-minimal')
161
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500162 with runqemu('core-image-minimal') as qemu:
Andrew Geissler595f6302022-01-24 19:11:47 +0000163 # Check that application service started
164 status, output = qemu.run_serial("systemctl status my-application")
165 self.assertTrue("active (exited)" in output, msg=output)
166
167 # Check that overlay mounts are dependencies of our application unit
168 status, output = qemu.run_serial("systemctl list-dependencies my-application")
169 self.assertTrue("overlayfs-user-overlays.service" in output, msg=output)
170
171 status, output = qemu.run_serial("systemctl list-dependencies overlayfs-user-overlays")
172 self.assertTrue("usr-share-another\\x2doverlay\\x2dmount.mount" in output, msg=output)
173 self.assertTrue("usr-share-my\\x2dapplication.mount" in output, msg=output)
174
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500175 # Check that we have /mnt/overlay fs mounted as tmpfs and
176 # /usr/share/my-application as an overlay (see overlayfs-user recipe)
177 status, output = qemu.run_serial("/bin/mount -t tmpfs,overlay")
178
179 line = getline_qemu(output, "on /mnt/overlay")
180 self.assertTrue(line and line.startswith("tmpfs"), msg=output)
181
182 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/my-application")
183 self.assertTrue(line and line.startswith("overlay"), msg=output)
Andrew Geissler595f6302022-01-24 19:11:47 +0000184
185 line = getline_qemu(output, "upperdir=/mnt/overlay/upper/usr/share/another-overlay-mount")
186 self.assertTrue(line and line.startswith("overlay"), msg=output)
187
Andrew Geissler9aee5002022-03-30 16:27:02 +0000188 def test_correct_image_fstab(self):
189 """
190 Summary: Check that we can create an image when all parameters are
191 set correctly via fstab
192 Expected: Image is created successfully
193 Author: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
194 """
195
196 base_files_append = """
197do_install:append() {
198 cat <<EOT >> ${D}${sysconfdir}/fstab
199tmpfs /mnt/overlay tmpfs mode=1777,strictatime,nosuid,nodev 0 0
200EOT
201}
202"""
203
204 self._test_correct_image('base-files', base_files_append)
205
206 def test_correct_image_unit(self):
207 """
208 Summary: Check that we can create an image when all parameters are
209 set correctly via mount unit
210 Expected: Image is created successfully
211 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
212 """
213
214 systemd_machine_unit_append = """
215SYSTEMD_SERVICE:${PN} += " \
216 mnt-overlay.mount \
217"
218
219do_install:append() {
220 install -d ${D}${systemd_system_unitdir}
221 cat <<EOT > ${D}${systemd_system_unitdir}/mnt-overlay.mount
222[Unit]
223Description=Tmpfs directory
224DefaultDependencies=no
225
226[Mount]
227What=tmpfs
228Where=/mnt/overlay
229Type=tmpfs
230Options=mode=1777,strictatime,nosuid,nodev
231
232[Install]
233WantedBy=multi-user.target
234EOT
235}
236
237"""
238
239 self._test_correct_image('systemd-machine-units', systemd_machine_unit_append)
240
Andrew Geissler595f6302022-01-24 19:11:47 +0000241class OverlayFSEtcRunTimeTests(OESelftestTestCase):
242 """overlayfs-etc class tests"""
243
244 def test_all_required_variables_set(self):
245 """
246 Summary: Check that required variables are set
247 Expected: Fail when any of required variables is missing
248 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
249 """
250
251 configBase = """
252DISTRO_FEATURES += "systemd"
253
254# Use systemd as init manager
255VIRTUAL-RUNTIME_init_manager = "systemd"
256
257# enable overlayfs in the kernel
258KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
259
260# Image configuration for overlayfs-etc
261EXTRA_IMAGE_FEATURES += "overlayfs-etc"
262IMAGE_FEATURES:remove = "package-management"
263"""
264 configMountPoint = """
265OVERLAYFS_ETC_MOUNT_POINT = "/data"
266"""
267 configDevice = """
268OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p1"
269"""
270
271 self.write_config(configBase)
272 res = bitbake('core-image-minimal', ignore_status=True)
273 line = getline(res, "OVERLAYFS_ETC_MOUNT_POINT must be set in your MACHINE configuration")
274 self.assertTrue(line, msg=res.output)
275
276 self.append_config(configMountPoint)
277 res = bitbake('core-image-minimal', ignore_status=True)
278 line = getline(res, "OVERLAYFS_ETC_DEVICE must be set in your MACHINE configuration")
279 self.assertTrue(line, msg=res.output)
280
281 self.append_config(configDevice)
282 res = bitbake('core-image-minimal', ignore_status=True)
283 line = getline(res, "OVERLAYFS_ETC_FSTYPE should contain a valid file system type on /dev/mmcblk0p1")
284 self.assertTrue(line, msg=res.output)
285
286 def test_image_feature_conflict(self):
287 """
288 Summary: Overlayfs-etc is not allowed to be used with package-management
289 Expected: Feature conflict
290 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
291 """
292
293 config = """
294DISTRO_FEATURES += "systemd"
295
296# Use systemd as init manager
297VIRTUAL-RUNTIME_init_manager = "systemd"
298
299# enable overlayfs in the kernel
300KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
301EXTRA_IMAGE_FEATURES += "overlayfs-etc"
302EXTRA_IMAGE_FEATURES += "package-management"
303"""
304
305 self.write_config(config)
306
307 res = bitbake('core-image-minimal', ignore_status=True)
308 line = getline(res, "contains conflicting IMAGE_FEATURES")
309 self.assertTrue("overlayfs-etc" in res.output, msg=res.output)
310 self.assertTrue("package-management" in res.output, msg=res.output)
311
312 def test_image_feature_is_missing_class_included(self):
313 configAppend = """
314INHERIT += "overlayfs-etc"
315"""
316 self.run_check_image_feature(configAppend)
317
318 def test_image_feature_is_missing(self):
319 self.run_check_image_feature()
320
321 def run_check_image_feature(self, appendToConfig=""):
322 """
323 Summary: Overlayfs-etc class is not applied when image feature is not set
324 even if we inherit it directly,
325 Expected: Image is created successfully but /etc is not an overlay
326 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
327 """
328
329 config = f"""
330DISTRO_FEATURES += "systemd"
331
332# Use systemd as init manager
333VIRTUAL-RUNTIME_init_manager = "systemd"
334
335# enable overlayfs in the kernel
336KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
337
338IMAGE_FSTYPES += "wic"
339WKS_FILE = "overlayfs_etc.wks.in"
340
341EXTRA_IMAGE_FEATURES += "read-only-rootfs"
342# Image configuration for overlayfs-etc
343OVERLAYFS_ETC_MOUNT_POINT = "/data"
344OVERLAYFS_ETC_DEVICE = "/dev/sda3"
345{appendToConfig}
346"""
347
348 self.write_config(config)
349
350 bitbake('core-image-minimal')
351
352 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
353 status, output = qemu.run_serial("/bin/mount")
354
355 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
356 self.assertFalse(line, msg=output)
357
358 def test_sbin_init_preinit(self):
359 self.run_sbin_init(False)
360
361 def test_sbin_init_original(self):
362 self.run_sbin_init(True)
363
364 def run_sbin_init(self, origInit):
365 """
366 Summary: Confirm we can replace original init and mount overlay on top of /etc
367 Expected: Image is created successfully and /etc is mounted as an overlay
368 Author: Vyacheslav Yurkov <uvv.mail@gmail.com>
369 """
370
371 config = """
372DISTRO_FEATURES += "systemd"
373
374# Use systemd as init manager
375VIRTUAL-RUNTIME_init_manager = "systemd"
376
377# enable overlayfs in the kernel
378KERNEL_EXTRA_FEATURES:append = " features/overlayfs/overlayfs.scc"
379
380IMAGE_FSTYPES += "wic"
381OVERLAYFS_INIT_OPTION = "{OVERLAYFS_INIT_OPTION}"
382WKS_FILE = "overlayfs_etc.wks.in"
383
384EXTRA_IMAGE_FEATURES += "read-only-rootfs"
385# Image configuration for overlayfs-etc
386EXTRA_IMAGE_FEATURES += "overlayfs-etc"
387IMAGE_FEATURES:remove = "package-management"
388OVERLAYFS_ETC_MOUNT_POINT = "/data"
389OVERLAYFS_ETC_FSTYPE = "ext4"
390OVERLAYFS_ETC_DEVICE = "/dev/sda3"
391OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "{OVERLAYFS_ETC_USE_ORIG_INIT_NAME}"
392"""
393
394 args = {
395 'OVERLAYFS_INIT_OPTION': "" if origInit else "init=/sbin/preinit",
396 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': int(origInit == True)
397 }
398
399 self.write_config(config.format(**args))
400
401 bitbake('core-image-minimal')
402 testFile = "/etc/my-test-data"
403
404 with runqemu('core-image-minimal', image_fstype='wic', discard_writes=False) as qemu:
405 status, output = qemu.run_serial("/bin/mount")
406
407 line = getline_qemu(output, "/dev/sda3")
408 self.assertTrue("/data" in output, msg=output)
409
410 line = getline_qemu(output, "upperdir=/data/overlay-etc/upper")
411 self.assertTrue(line and line.startswith("/data/overlay-etc/upper on /etc type overlay"), msg=output)
412
413 status, output = qemu.run_serial("touch " + testFile)
414 status, output = qemu.run_serial("sync")
415 status, output = qemu.run_serial("ls -1 " + testFile)
416 line = getline_qemu(output, testFile)
417 self.assertTrue(line and line.startswith(testFile), msg=output)
418
419 # Check that file exists in /etc after reboot
420 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
421 status, output = qemu.run_serial("ls -1 " + testFile)
422 line = getline_qemu(output, testFile)
423 self.assertTrue(line and line.startswith(testFile), msg=output)