blob: 714637ec1e2326d4dfdc6415db5b133208f00da5 [file] [log] [blame]
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001#
2# Copyright (c) 2015, Intel Corporation.
Brad Bishopd7bf8c12018-02-25 22:55:05 -05003#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: GPL-2.0-only
Brad Bishopd7bf8c12018-02-25 22:55:05 -05005#
6# AUTHORS
7# Ed Bartosh <ed.bartosh@linux.intel.com>
8
9"""Test cases for wic."""
10
11import os
12import sys
13import unittest
14
15from glob import glob
16from shutil import rmtree, copy
17from functools import wraps, lru_cache
18from tempfile import NamedTemporaryFile
19
20from oeqa.selftest.case import OESelftestTestCase
21from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu
Brad Bishopd7bf8c12018-02-25 22:55:05 -050022
23
24@lru_cache(maxsize=32)
25def get_host_arch(recipe):
26 """A cached call to get_bb_var('HOST_ARCH', <recipe>)"""
27 return get_bb_var('HOST_ARCH', recipe)
28
29
30def only_for_arch(archs, image='core-image-minimal'):
31 """Decorator for wrapping test cases that can be run only for specific target
32 architectures. A list of compatible architectures is passed in `archs`.
33 Current architecture will be determined by parsing bitbake output for
34 `image` recipe.
35 """
36 def wrapper(func):
37 @wraps(func)
38 def wrapped_f(*args, **kwargs):
39 arch = get_host_arch(image)
40 if archs and arch not in archs:
41 raise unittest.SkipTest("Testcase arch dependency not met: %s" % arch)
42 return func(*args, **kwargs)
43 wrapped_f.__name__ = func.__name__
44 return wrapped_f
45 return wrapper
46
Andrew Geissler82c905d2020-04-13 13:39:40 -050047def extract_files(debugfs_output):
48 """
49 extract file names from the output of debugfs -R 'ls -p',
50 which looks like this:
51
52 /2/040755/0/0/.//\n
53 /2/040755/0/0/..//\n
54 /11/040700/0/0/lost+found^M//\n
55 /12/040755/1002/1002/run//\n
56 /13/040755/1002/1002/sys//\n
57 /14/040755/1002/1002/bin//\n
58 /80/040755/1002/1002/var//\n
59 /92/040755/1002/1002/tmp//\n
60 """
61 # NOTE the occasional ^M in file names
62 return [line.split('/')[5].strip() for line in \
63 debugfs_output.strip().split('/\n')]
64
65def files_own_by_root(debugfs_output):
66 for line in debugfs_output.strip().split('/\n'):
67 if line.split('/')[3:5] != ['0', '0']:
68 print(debugfs_output)
69 return False
70 return True
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080072class WicTestCase(OESelftestTestCase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050073 """Wic test class."""
74
Brad Bishopd7bf8c12018-02-25 22:55:05 -050075 image_is_ready = False
Brad Bishopd7bf8c12018-02-25 22:55:05 -050076 wicenv_cache = {}
77
78 def setUpLocal(self):
79 """This code is executed before each test method."""
Brad Bishopc4ea0752018-11-15 14:30:15 -080080 self.resultdir = self.builddir + "/wic-tmp/"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080081 super(WicTestCase, self).setUpLocal()
Brad Bishopd7bf8c12018-02-25 22:55:05 -050082
83 # Do this here instead of in setUpClass as the base setUp does some
84 # clean up which can result in the native tools built earlier in
85 # setUpClass being unavailable.
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080086 if not WicTestCase.image_is_ready:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050087 if get_bb_var('USE_NLS') == 'yes':
88 bitbake('wic-tools')
89 else:
90 self.skipTest('wic-tools cannot be built due its (intltool|gettext)-native dependency and NLS disable')
91
92 bitbake('core-image-minimal')
Andrew Geissler82c905d2020-04-13 13:39:40 -050093 bitbake('core-image-minimal-mtdutils')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080094 WicTestCase.image_is_ready = True
Brad Bishopd7bf8c12018-02-25 22:55:05 -050095
96 rmtree(self.resultdir, ignore_errors=True)
97
98 def tearDownLocal(self):
99 """Remove resultdir as it may contain images."""
100 rmtree(self.resultdir, ignore_errors=True)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800101 super(WicTestCase, self).tearDownLocal()
102
103 def _get_image_env_path(self, image):
104 """Generate and obtain the path to <image>.env"""
105 if image not in WicTestCase.wicenv_cache:
106 self.assertEqual(0, bitbake('%s -c do_rootfs_wicenv' % image).status)
107 bb_vars = get_bb_vars(['STAGING_DIR', 'MACHINE'], image)
108 stdir = bb_vars['STAGING_DIR']
109 machine = bb_vars['MACHINE']
110 WicTestCase.wicenv_cache[image] = os.path.join(stdir, machine, 'imgdata')
111 return WicTestCase.wicenv_cache[image]
112
113class Wic(WicTestCase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500114
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500115 def test_version(self):
116 """Test wic --version"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800117 runCmd('wic --version')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500118
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500119 def test_help(self):
120 """Test wic --help and wic -h"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800121 runCmd('wic --help')
122 runCmd('wic -h')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500123
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500124 def test_createhelp(self):
125 """Test wic create --help"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800126 runCmd('wic create --help')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500127
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500128 def test_listhelp(self):
129 """Test wic list --help"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800130 runCmd('wic list --help')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500131
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500132 def test_help_create(self):
133 """Test wic help create"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800134 runCmd('wic help create')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500135
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500136 def test_help_list(self):
137 """Test wic help list"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800138 runCmd('wic help list')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500139
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500140 def test_help_overview(self):
141 """Test wic help overview"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800142 runCmd('wic help overview')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500143
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500144 def test_help_plugins(self):
145 """Test wic help plugins"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800146 runCmd('wic help plugins')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500147
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500148 def test_help_kickstart(self):
149 """Test wic help kickstart"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800150 runCmd('wic help kickstart')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500151
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500152 def test_list_images(self):
153 """Test wic list images"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800154 runCmd('wic list images')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500155
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500156 def test_list_source_plugins(self):
157 """Test wic list source-plugins"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800158 runCmd('wic list source-plugins')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500159
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500160 def test_listed_images_help(self):
161 """Test wic listed images help"""
162 output = runCmd('wic list images').output
163 imagelist = [line.split()[0] for line in output.splitlines()]
164 for image in imagelist:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800165 runCmd('wic list %s help' % image)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500166
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500167 def test_unsupported_subcommand(self):
168 """Test unsupported subcommand"""
169 self.assertNotEqual(0, runCmd('wic unsupported', ignore_status=True).status)
170
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500171 def test_no_command(self):
172 """Test wic without command"""
173 self.assertEqual(1, runCmd('wic', ignore_status=True).status)
174
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500175 def test_build_image_name(self):
176 """Test wic create wictestdisk --image-name=core-image-minimal"""
177 cmd = "wic create wictestdisk --image-name=core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800178 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500179 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
180
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500181 @only_for_arch(['i586', 'i686', 'x86_64'])
182 def test_gpt_image(self):
183 """Test creation of core-image-minimal with gpt table and UUID boot"""
184 cmd = "wic create directdisk-gpt --image-name core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800185 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500186 self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
187
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500188 @only_for_arch(['i586', 'i686', 'x86_64'])
189 def test_iso_image(self):
190 """Test creation of hybrid iso image with legacy and EFI boot"""
191 config = 'INITRAMFS_IMAGE = "core-image-minimal-initramfs"\n'\
192 'MACHINE_FEATURES_append = " efi"\n'\
193 'DEPENDS_pn-core-image-minimal += "syslinux"\n'
194 self.append_config(config)
Brad Bishopc4ea0752018-11-15 14:30:15 -0800195 bitbake('core-image-minimal core-image-minimal-initramfs')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500196 self.remove_config(config)
197 cmd = "wic create mkhybridiso --image-name core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800198 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500199 self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.direct")))
200 self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.iso")))
201
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500202 @only_for_arch(['i586', 'i686', 'x86_64'])
203 def test_qemux86_directdisk(self):
204 """Test creation of qemux-86-directdisk image"""
205 cmd = "wic create qemux86-directdisk -e core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800206 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500207 self.assertEqual(1, len(glob(self.resultdir + "qemux86-directdisk-*direct")))
208
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500209 @only_for_arch(['i586', 'i686', 'x86_64'])
210 def test_mkefidisk(self):
211 """Test creation of mkefidisk image"""
212 cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800213 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500214 self.assertEqual(1, len(glob(self.resultdir + "mkefidisk-*direct")))
215
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500216 @only_for_arch(['i586', 'i686', 'x86_64'])
217 def test_bootloader_config(self):
218 """Test creation of directdisk-bootloader-config image"""
219 config = 'DEPENDS_pn-core-image-minimal += "syslinux"\n'
220 self.append_config(config)
221 bitbake('core-image-minimal')
222 self.remove_config(config)
223 cmd = "wic create directdisk-bootloader-config -e core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800224 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500225 self.assertEqual(1, len(glob(self.resultdir + "directdisk-bootloader-config-*direct")))
226
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500227 @only_for_arch(['i586', 'i686', 'x86_64'])
228 def test_systemd_bootdisk(self):
229 """Test creation of systemd-bootdisk image"""
230 config = 'MACHINE_FEATURES_append = " efi"\n'
231 self.append_config(config)
232 bitbake('core-image-minimal')
233 self.remove_config(config)
234 cmd = "wic create systemd-bootdisk -e core-image-minimal -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800235 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500236 self.assertEqual(1, len(glob(self.resultdir + "systemd-bootdisk-*direct")))
237
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500238 def test_efi_bootpart(self):
239 """Test creation of efi-bootpart image"""
240 cmd = "wic create mkefidisk -e core-image-minimal -o %s" % self.resultdir
241 kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal')
242 self.append_config('IMAGE_EFI_BOOT_FILES = "%s;kernel"\n' % kimgtype)
243 runCmd(cmd)
244 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
245 images = glob(self.resultdir + "mkefidisk-*.direct")
246 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
247 self.assertIn("kernel",result.output)
248
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500249 def test_sdimage_bootpart(self):
250 """Test creation of sdimage-bootpart image"""
251 cmd = "wic create sdimage-bootpart -e core-image-minimal -o %s" % self.resultdir
252 kimgtype = get_bb_var('KERNEL_IMAGETYPE', 'core-image-minimal')
253 self.write_config('IMAGE_BOOT_FILES = "%s"\n' % kimgtype)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800254 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500255 self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct")))
256
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500257 @only_for_arch(['i586', 'i686', 'x86_64'])
258 def test_default_output_dir(self):
259 """Test default output location"""
260 for fname in glob("directdisk-*.direct"):
261 os.remove(fname)
262 config = 'DEPENDS_pn-core-image-minimal += "syslinux"\n'
263 self.append_config(config)
264 bitbake('core-image-minimal')
265 self.remove_config(config)
266 cmd = "wic create directdisk -e core-image-minimal"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800267 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500268 self.assertEqual(1, len(glob("directdisk-*.direct")))
269
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500270 @only_for_arch(['i586', 'i686', 'x86_64'])
271 def test_build_artifacts(self):
272 """Test wic create directdisk providing all artifacts."""
273 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
274 'wic-tools')
275 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
276 'core-image-minimal'))
277 bbvars = {key.lower(): value for key, value in bb_vars.items()}
278 bbvars['resultdir'] = self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800279 runCmd("wic create directdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500280 "-b %(staging_datadir)s "
281 "-k %(deploy_dir_image)s "
282 "-n %(recipe_sysroot_native)s "
283 "-r %(image_rootfs)s "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800284 "-o %(resultdir)s" % bbvars)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500285 self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
286
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500287 def test_compress_gzip(self):
288 """Test compressing an image with gzip"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800289 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500290 "--image-name core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800291 "-c gzip -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500292 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.gz")))
293
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500294 def test_compress_bzip2(self):
295 """Test compressing an image with bzip2"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800296 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500297 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800298 "-c bzip2 -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500299 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.bz2")))
300
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500301 def test_compress_xz(self):
302 """Test compressing an image with xz"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800303 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500304 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800305 "--compress-with=xz -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500306 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct.xz")))
307
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500308 def test_wrong_compressor(self):
309 """Test how wic breaks if wrong compressor is provided"""
310 self.assertEqual(2, runCmd("wic create wictestdisk "
311 "--image-name=core-image-minimal "
312 "-c wrong -o %s" % self.resultdir,
313 ignore_status=True).status)
314
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500315 def test_debug_short(self):
316 """Test -D option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800317 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500318 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800319 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500320 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
321
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500322 def test_debug_long(self):
323 """Test --debug option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800324 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500325 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800326 "--debug -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500327 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
328
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500329 def test_skip_build_check_short(self):
330 """Test -s option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800331 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500332 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800333 "-s -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500334 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
335
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500336 def test_skip_build_check_long(self):
337 """Test --skip-build-check option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800338 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500339 "--image-name=core-image-minimal "
340 "--skip-build-check "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800341 "--outdir %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500342 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
343
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500344 def test_build_rootfs_short(self):
345 """Test -f option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800346 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500347 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800348 "-f -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500349 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
350
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500351 def test_build_rootfs_long(self):
352 """Test --build-rootfs option"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800353 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500354 "--image-name=core-image-minimal "
355 "--build-rootfs "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800356 "--outdir %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500357 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct")))
358
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500359 @only_for_arch(['i586', 'i686', 'x86_64'])
360 def test_rootfs_indirect_recipes(self):
361 """Test usage of rootfs plugin with rootfs recipes"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800362 runCmd("wic create directdisk-multi-rootfs "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500363 "--image-name=core-image-minimal "
364 "--rootfs rootfs1=core-image-minimal "
365 "--rootfs rootfs2=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800366 "--outdir %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500367 self.assertEqual(1, len(glob(self.resultdir + "directdisk-multi-rootfs*.direct")))
368
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500369 @only_for_arch(['i586', 'i686', 'x86_64'])
370 def test_rootfs_artifacts(self):
371 """Test usage of rootfs plugin with rootfs paths"""
372 bb_vars = get_bb_vars(['STAGING_DATADIR', 'RECIPE_SYSROOT_NATIVE'],
373 'wic-tools')
374 bb_vars.update(get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_ROOTFS'],
375 'core-image-minimal'))
376 bbvars = {key.lower(): value for key, value in bb_vars.items()}
377 bbvars['wks'] = "directdisk-multi-rootfs"
378 bbvars['resultdir'] = self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800379 runCmd("wic create %(wks)s "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500380 "--bootimg-dir=%(staging_datadir)s "
381 "--kernel-dir=%(deploy_dir_image)s "
382 "--native-sysroot=%(recipe_sysroot_native)s "
383 "--rootfs-dir rootfs1=%(image_rootfs)s "
384 "--rootfs-dir rootfs2=%(image_rootfs)s "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800385 "--outdir %(resultdir)s" % bbvars)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500386 self.assertEqual(1, len(glob(self.resultdir + "%(wks)s-*.direct" % bbvars)))
387
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500388 def test_exclude_path(self):
389 """Test --exclude-path wks option."""
390
391 oldpath = os.environ['PATH']
392 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
393
394 try:
395 wks_file = 'temp.wks'
396 with open(wks_file, 'w') as wks:
397 rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal')
398 wks.write("""
399part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path usr
400part /usr --source rootfs --ondisk mmcblk0 --fstype=ext4 --rootfs-dir %s/usr
401part /etc --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path bin/ --rootfs-dir %s/usr"""
402 % (rootfs_dir, rootfs_dir))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800403 runCmd("wic create %s -e core-image-minimal -o %s" \
404 % (wks_file, self.resultdir))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500405
406 os.remove(wks_file)
407 wicout = glob(self.resultdir + "%s-*direct" % 'temp')
408 self.assertEqual(1, len(wicout))
409
410 wicimg = wicout[0]
411
412 # verify partition size with wic
413 res = runCmd("parted -m %s unit b p 2>/dev/null" % wicimg)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500414
415 # parse parted output which looks like this:
416 # BYT;\n
417 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
418 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
419 partlns = res.output.splitlines()[2:]
420
421 self.assertEqual(3, len(partlns))
422
423 for part in [1, 2, 3]:
424 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
425 partln = partlns[part-1].split(":")
426 self.assertEqual(7, len(partln))
427 start = int(partln[1].rstrip("B")) / 512
428 length = int(partln[3].rstrip("B")) / 512
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800429 runCmd("dd if=%s of=%s skip=%d count=%d" %
430 (wicimg, part_file, start, length))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500431
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500432 # Test partition 1, should contain the normal root directories, except
433 # /usr.
434 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
435 os.path.join(self.resultdir, "selftest_img.part1"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500436 files = extract_files(res.output)
437 self.assertIn("etc", files)
438 self.assertNotIn("usr", files)
439
440 # Partition 2, should contain common directories for /usr, not root
441 # directories.
442 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
443 os.path.join(self.resultdir, "selftest_img.part2"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500444 files = extract_files(res.output)
445 self.assertNotIn("etc", files)
446 self.assertNotIn("usr", files)
447 self.assertIn("share", files)
448
449 # Partition 3, should contain the same as partition 2, including the bin
450 # directory, but not the files inside it.
451 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % \
452 os.path.join(self.resultdir, "selftest_img.part3"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500453 files = extract_files(res.output)
454 self.assertNotIn("etc", files)
455 self.assertNotIn("usr", files)
456 self.assertIn("share", files)
457 self.assertIn("bin", files)
458 res = runCmd("debugfs -R 'ls -p bin' %s 2>/dev/null" % \
459 os.path.join(self.resultdir, "selftest_img.part3"))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500460 files = extract_files(res.output)
461 self.assertIn(".", files)
462 self.assertIn("..", files)
463 self.assertEqual(2, len(files))
464
465 for part in [1, 2, 3]:
466 part_file = os.path.join(self.resultdir, "selftest_img.part%d" % part)
467 os.remove(part_file)
468
469 finally:
470 os.environ['PATH'] = oldpath
471
Andrew Geissler82c905d2020-04-13 13:39:40 -0500472 def test_include_path(self):
473 """Test --include-path wks option."""
474
475 oldpath = os.environ['PATH']
476 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
477
478 try:
479 include_path = os.path.join(self.resultdir, 'test-include')
480 os.makedirs(include_path)
481 with open(os.path.join(include_path, 'test-file'), 'w') as t:
482 t.write("test\n")
483 wks_file = os.path.join(include_path, 'temp.wks')
484 with open(wks_file, 'w') as wks:
485 rootfs_dir = get_bb_var('IMAGE_ROOTFS', 'core-image-minimal')
486 wks.write("""
487part /part1 --source rootfs --ondisk mmcblk0 --fstype=ext4
488part /part2 --source rootfs --ondisk mmcblk0 --fstype=ext4 --include-path %s"""
489 % (include_path))
490 runCmd("wic create %s -e core-image-minimal -o %s" \
491 % (wks_file, self.resultdir))
492
493 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
494 part2 = glob(os.path.join(self.resultdir, 'temp-*.direct.p2'))[0]
495
496 # Test partition 1, should not contain 'test-file'
497 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
498 files = extract_files(res.output)
499 self.assertNotIn('test-file', files)
500 self.assertEqual(True, files_own_by_root(res.output))
501
502 # Test partition 2, should contain 'test-file'
503 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part2))
504 files = extract_files(res.output)
505 self.assertIn('test-file', files)
506 self.assertEqual(True, files_own_by_root(res.output))
507
508 finally:
509 os.environ['PATH'] = oldpath
510
511 def test_include_path_embeded(self):
512 """Test --include-path wks option."""
513
514 oldpath = os.environ['PATH']
515 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
516
517 try:
518 include_path = os.path.join(self.resultdir, 'test-include')
519 os.makedirs(include_path)
520 with open(os.path.join(include_path, 'test-file'), 'w') as t:
521 t.write("test\n")
522 wks_file = os.path.join(include_path, 'temp.wks')
523 with open(wks_file, 'w') as wks:
524 wks.write("""
525part / --source rootfs --fstype=ext4 --include-path %s --include-path core-image-minimal-mtdutils export/"""
526 % (include_path))
527 runCmd("wic create %s -e core-image-minimal -o %s" \
528 % (wks_file, self.resultdir))
529
530 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
531
532 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
533 files = extract_files(res.output)
534 self.assertIn('test-file', files)
535 self.assertEqual(True, files_own_by_root(res.output))
536
537 res = runCmd("debugfs -R 'ls -p /export/etc/' %s 2>/dev/null" % (part1))
538 files = extract_files(res.output)
539 self.assertIn('passwd', files)
540 self.assertEqual(True, files_own_by_root(res.output))
541
542 finally:
543 os.environ['PATH'] = oldpath
544
545 def test_include_path_errors(self):
546 """Test --include-path wks option error handling."""
547 wks_file = 'temp.wks'
548
549 # Absolute argument.
550 with open(wks_file, 'w') as wks:
551 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils /export")
552 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
553 % (wks_file, self.resultdir), ignore_status=True).status)
554 os.remove(wks_file)
555
556 # Argument pointing to parent directory.
557 with open(wks_file, 'w') as wks:
558 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils ././..")
559 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
560 % (wks_file, self.resultdir), ignore_status=True).status)
561 os.remove(wks_file)
562
563 # 3 Argument pointing to parent directory.
564 with open(wks_file, 'w') as wks:
565 wks.write("part / --source rootfs --fstype=ext4 --include-path core-image-minimal-mtdutils export/ dummy")
566 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
567 % (wks_file, self.resultdir), ignore_status=True).status)
568 os.remove(wks_file)
569
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500570 def test_exclude_path_errors(self):
571 """Test --exclude-path wks option error handling."""
572 wks_file = 'temp.wks'
573
574 # Absolute argument.
575 with open(wks_file, 'w') as wks:
576 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path /usr")
577 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
578 % (wks_file, self.resultdir), ignore_status=True).status)
579 os.remove(wks_file)
580
581 # Argument pointing to parent directory.
582 with open(wks_file, 'w') as wks:
583 wks.write("part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --exclude-path ././..")
584 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
585 % (wks_file, self.resultdir), ignore_status=True).status)
586 os.remove(wks_file)
587
Andrew Geissler82c905d2020-04-13 13:39:40 -0500588 def test_permissions(self):
589 """Test permissions are respected"""
590
591 oldpath = os.environ['PATH']
592 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
593
594 t_normal = """
595part / --source rootfs --fstype=ext4
596"""
597 t_exclude = """
598part / --source rootfs --fstype=ext4 --exclude-path=home
599"""
600 t_multi = """
601part / --source rootfs --ondisk sda --fstype=ext4
602part /export --source rootfs --rootfs=core-image-minimal-mtdutils --fstype=ext4
603"""
604 t_change = """
605part / --source rootfs --ondisk sda --fstype=ext4 --exclude-path=etc/   
606part /etc --source rootfs --fstype=ext4 --change-directory=etc
607"""
608 tests = [t_normal, t_exclude, t_multi, t_change]
609
610 try:
611 for test in tests:
612 include_path = os.path.join(self.resultdir, 'test-include')
613 os.makedirs(include_path)
614 wks_file = os.path.join(include_path, 'temp.wks')
615 with open(wks_file, 'w') as wks:
616 wks.write(test)
617 runCmd("wic create %s -e core-image-minimal -o %s" \
618 % (wks_file, self.resultdir))
619
620 for part in glob(os.path.join(self.resultdir, 'temp-*.direct.p*')):
621 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part))
622 self.assertEqual(True, files_own_by_root(res.output))
623
624 rmtree(self.resultdir, ignore_errors=True)
625
626 finally:
627 os.environ['PATH'] = oldpath
628
629 def test_change_directory(self):
630 """Test --change-directory wks option."""
631
632 oldpath = os.environ['PATH']
633 os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
634
635 try:
636 include_path = os.path.join(self.resultdir, 'test-include')
637 os.makedirs(include_path)
638 wks_file = os.path.join(include_path, 'temp.wks')
639 with open(wks_file, 'w') as wks:
640 wks.write("part /etc --source rootfs --fstype=ext4 --change-directory=etc")
641 runCmd("wic create %s -e core-image-minimal -o %s" \
642 % (wks_file, self.resultdir))
643
644 part1 = glob(os.path.join(self.resultdir, 'temp-*.direct.p1'))[0]
645
646 res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part1))
647 files = extract_files(res.output)
648 self.assertIn('passwd', files)
649
650 finally:
651 os.environ['PATH'] = oldpath
652
653 def test_change_directory_errors(self):
654 """Test --change-directory wks option error handling."""
655 wks_file = 'temp.wks'
656
657 # Absolute argument.
658 with open(wks_file, 'w') as wks:
659 wks.write("part / --source rootfs --fstype=ext4 --change-directory /usr")
660 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
661 % (wks_file, self.resultdir), ignore_status=True).status)
662 os.remove(wks_file)
663
664 # Argument pointing to parent directory.
665 with open(wks_file, 'w') as wks:
666 wks.write("part / --source rootfs --fstype=ext4 --change-directory ././..")
667 self.assertNotEqual(0, runCmd("wic create %s -e core-image-minimal -o %s" \
668 % (wks_file, self.resultdir), ignore_status=True).status)
669 os.remove(wks_file)
670
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800671class Wic2(WicTestCase):
672
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500673 def test_bmap_short(self):
674 """Test generation of .bmap file -m option"""
675 cmd = "wic create wictestdisk -e core-image-minimal -m -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800676 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500677 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
678 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap")))
679
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500680 def test_bmap_long(self):
681 """Test generation of .bmap file --bmap option"""
682 cmd = "wic create wictestdisk -e core-image-minimal --bmap -o %s" % self.resultdir
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800683 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500684 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
685 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct.bmap")))
686
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500687 def test_image_env(self):
688 """Test generation of <image>.env files."""
689 image = 'core-image-minimal'
690 imgdatadir = self._get_image_env_path(image)
691
692 bb_vars = get_bb_vars(['IMAGE_BASENAME', 'WICVARS'], image)
693 basename = bb_vars['IMAGE_BASENAME']
694 self.assertEqual(basename, image)
695 path = os.path.join(imgdatadir, basename) + '.env'
696 self.assertTrue(os.path.isfile(path))
697
698 wicvars = set(bb_vars['WICVARS'].split())
699 # filter out optional variables
700 wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES',
Brad Bishop96ff1982019-08-19 13:50:42 -0400701 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE',
Andrew Geissler82c905d2020-04-13 13:39:40 -0500702 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME',
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500703 'APPEND', 'IMAGE_EFI_BOOT_FILES'))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500704 with open(path) as envfile:
705 content = dict(line.split("=", 1) for line in envfile)
706 # test if variables used by wic present in the .env file
707 for var in wicvars:
708 self.assertTrue(var in content, "%s is not in .env file" % var)
709 self.assertTrue(content[var])
710
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500711 def test_image_vars_dir_short(self):
712 """Test image vars directory selection -v option"""
713 image = 'core-image-minimal'
714 imgenvdir = self._get_image_env_path(image)
715 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
716
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800717 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500718 "--image-name=%s -v %s -n %s -o %s"
719 % (image, imgenvdir, native_sysroot,
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800720 self.resultdir))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500721 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
722
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500723 def test_image_vars_dir_long(self):
724 """Test image vars directory selection --vars option"""
725 image = 'core-image-minimal'
726 imgenvdir = self._get_image_env_path(image)
727 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
728
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800729 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500730 "--image-name=%s "
731 "--vars %s "
732 "--native-sysroot %s "
733 "--outdir %s"
734 % (image, imgenvdir, native_sysroot,
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800735 self.resultdir))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500736 self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*direct")))
737
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500738 @only_for_arch(['i586', 'i686', 'x86_64'])
739 def test_wic_image_type(self):
740 """Test building wic images by bitbake"""
741 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
742 'MACHINE_FEATURES_append = " efi"\n'
743 self.append_config(config)
744 self.assertEqual(0, bitbake('wic-image-minimal').status)
745 self.remove_config(config)
746
747 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
748 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
749 machine = bb_vars['MACHINE']
750 prefix = os.path.join(deploy_dir, 'wic-image-minimal-%s.' % machine)
751 # check if we have result image and manifests symlinks
752 # pointing to existing files
753 for suffix in ('wic', 'manifest'):
754 path = prefix + suffix
755 self.assertTrue(os.path.islink(path))
756 self.assertTrue(os.path.isfile(os.path.realpath(path)))
757
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500758 @only_for_arch(['i586', 'i686', 'x86_64'])
759 def test_qemu(self):
760 """Test wic-image-minimal under qemu"""
761 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
762 'MACHINE_FEATURES_append = " efi"\n'
763 self.append_config(config)
764 self.assertEqual(0, bitbake('wic-image-minimal').status)
765 self.remove_config(config)
766
767 with runqemu('wic-image-minimal', ssh=False) as qemu:
Andrew Geissler99467da2019-02-25 18:54:23 -0600768 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' " \
769 "-e '/dev/root /|/dev/sda2 /' -e '/dev/sda3 /media' -e '/dev/sda4 /mnt'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400770 status, output = qemu.run_serial(cmd)
Andrew Geissler99467da2019-02-25 18:54:23 -0600771 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
772 self.assertEqual(output, '4')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400773 cmd = "grep UUID= /etc/fstab"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500774 status, output = qemu.run_serial(cmd)
775 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400776 self.assertEqual(output, 'UUID=2c71ef06-a81d-4735-9d3a-379b69c6bdba\t/media\text4\tdefaults\t0\t0')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500777
778 @only_for_arch(['i586', 'i686', 'x86_64'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500779 def test_qemu_efi(self):
780 """Test core-image-minimal efi image under qemu"""
781 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "mkefidisk.wks"\n'
782 self.append_config(config)
783 self.assertEqual(0, bitbake('core-image-minimal ovmf').status)
784 self.remove_config(config)
785
786 with runqemu('core-image-minimal', ssh=False,
787 runqemuparams='ovmf', image_fstype='wic') as qemu:
788 cmd = "grep sda. /proc/partitions |wc -l"
789 status, output = qemu.run_serial(cmd)
790 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
791 self.assertEqual(output, '3')
792
793 @staticmethod
794 def _make_fixed_size_wks(size):
795 """
796 Create a wks of an image with a single partition. Size of the partition is set
797 using --fixed-size flag. Returns a tuple: (path to wks file, wks image name)
798 """
799 with NamedTemporaryFile("w", suffix=".wks", delete=False) as tempf:
800 wkspath = tempf.name
801 tempf.write("part " \
802 "--source rootfs --ondisk hda --align 4 --fixed-size %d "
803 "--fstype=ext4\n" % size)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500804
805 return wkspath
806
807 def _get_wic_partitions(self, wkspath, native_sysroot=None, ignore_status=False):
808 p = runCmd("wic create %s -e core-image-minimal -o %s" % (wkspath, self.resultdir),
809 ignore_status=ignore_status)
810
811 if p.status:
812 return (p, None)
813
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500814 wksname = os.path.splitext(os.path.basename(wkspath))[0]
815
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500816 wicout = glob(self.resultdir + "%s-*direct" % wksname)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500817
818 if not wicout:
819 return (p, None)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500820
821 wicimg = wicout[0]
822
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500823 if not native_sysroot:
824 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800825
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500826 # verify partition size with wic
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500827 res = runCmd("parted -m %s unit kib p 2>/dev/null" % wicimg,
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800828 native_sysroot=native_sysroot)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500829
830 # parse parted output which looks like this:
831 # BYT;\n
832 # /var/tmp/wic/build/tmpfwvjjkf_-201611101222-hda.direct:200MiB:file:512:512:msdos::;\n
833 # 1:0.00MiB:200MiB:200MiB:ext4::;\n
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500834 return (p, res.output.splitlines()[2:])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500835
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500836 def test_fixed_size(self):
837 """
838 Test creation of a simple image with partition size controlled through
839 --fixed-size flag
840 """
841 wkspath = Wic2._make_fixed_size_wks(200)
842 _, partlns = self._get_wic_partitions(wkspath)
843 os.remove(wkspath)
844
845 self.assertEqual(partlns, [
846 "1:4.00kiB:204804kiB:204800kiB:ext4::;",
847 ])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500848
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500849 def test_fixed_size_error(self):
850 """
851 Test creation of a simple image with partition size controlled through
852 --fixed-size flag. The size of partition is intentionally set to 1MiB
853 in order to trigger an error in wic.
854 """
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500855 wkspath = Wic2._make_fixed_size_wks(1)
856 p, _ = self._get_wic_partitions(wkspath, ignore_status=True)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500857 os.remove(wkspath)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500858
859 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
860
861 def test_offset(self):
862 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
863
864 with NamedTemporaryFile("w", suffix=".wks") as tempf:
865 # Test that partitions are placed at the correct offsets, default KB
866 tempf.write("bootloader --ptable gpt\n" \
867 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
868 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n")
869 tempf.flush()
870
871 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
872 self.assertEqual(partlns, [
873 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
874 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
875 ])
876
877 with NamedTemporaryFile("w", suffix=".wks") as tempf:
878 # Test that partitions are placed at the correct offsets, same with explicit KB
879 tempf.write("bootloader --ptable gpt\n" \
880 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
881 "part /bar --ondisk hda --offset 102432K --fixed-size 100M --fstype=ext4\n")
882 tempf.flush()
883
884 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
885 self.assertEqual(partlns, [
886 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
887 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
888 ])
889
890 with NamedTemporaryFile("w", suffix=".wks") as tempf:
891 # Test that partitions are placed at the correct offsets using MB
892 tempf.write("bootloader --ptable gpt\n" \
893 "part / --source rootfs --ondisk hda --offset 32K --fixed-size 100M --fstype=ext4\n" \
894 "part /bar --ondisk hda --offset 101M --fixed-size 100M --fstype=ext4\n")
895 tempf.flush()
896
897 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
898 self.assertEqual(partlns, [
899 "1:32.0kiB:102432kiB:102400kiB:ext4:primary:;",
900 "2:103424kiB:205824kiB:102400kiB:ext4:primary:;",
901 ])
902
903 with NamedTemporaryFile("w", suffix=".wks") as tempf:
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500904 # Test that partitions can be placed on a 512 byte sector boundary
905 tempf.write("bootloader --ptable gpt\n" \
906 "part / --source rootfs --ondisk hda --offset 65s --fixed-size 99M --fstype=ext4\n" \
907 "part /bar --ondisk hda --offset 102432 --fixed-size 100M --fstype=ext4\n")
908 tempf.flush()
909
910 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
911 self.assertEqual(partlns, [
912 "1:32.5kiB:101408kiB:101376kiB:ext4:primary:;",
913 "2:102432kiB:204832kiB:102400kiB:ext4:primary:;",
914 ])
915
916 with NamedTemporaryFile("w", suffix=".wks") as tempf:
917 # Test that a partition can be placed immediately after a MSDOS partition table
918 tempf.write("bootloader --ptable msdos\n" \
919 "part / --source rootfs --ondisk hda --offset 1s --fixed-size 100M --fstype=ext4\n")
920 tempf.flush()
921
922 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
923 self.assertEqual(partlns, [
924 "1:0.50kiB:102400kiB:102400kiB:ext4::;",
925 ])
926
927 with NamedTemporaryFile("w", suffix=".wks") as tempf:
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500928 # Test that image creation fails if the partitions would overlap
929 tempf.write("bootloader --ptable gpt\n" \
930 "part / --source rootfs --ondisk hda --offset 32 --fixed-size 100M --fstype=ext4\n" \
931 "part /bar --ondisk hda --offset 102431 --fixed-size 100M --fstype=ext4\n")
932 tempf.flush()
933
934 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
935 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
936
937 with NamedTemporaryFile("w", suffix=".wks") as tempf:
938 # Test that partitions are not allowed to overlap with the booloader
939 tempf.write("bootloader --ptable gpt\n" \
940 "part / --source rootfs --ondisk hda --offset 8 --fixed-size 100M --fstype=ext4\n")
941 tempf.flush()
942
943 p, _ = self._get_wic_partitions(tempf.name, ignore_status=True)
944 self.assertNotEqual(p.status, 0, "wic exited successfully when an error was expected:\n%s" % p.output)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500945
Andrew Geissler5a43b432020-06-13 10:46:56 -0500946 def test_extra_space(self):
947 native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "wic-tools")
948
949 with NamedTemporaryFile("w", suffix=".wks") as tempf:
950 tempf.write("bootloader --ptable gpt\n" \
951 "part / --source rootfs --ondisk hda --extra-space 200M --fstype=ext4\n")
952 tempf.flush()
953
954 _, partlns = self._get_wic_partitions(tempf.name, native_sysroot)
955 self.assertEqual(len(partlns), 1)
956 size = partlns[0].split(':')[3]
957 self.assertRegex(size, r'^[0-9]+kiB$')
958 size = int(size[:-3])
959 self.assertGreaterEqual(size, 204800)
960
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500961 @only_for_arch(['i586', 'i686', 'x86_64'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500962 def test_rawcopy_plugin_qemu(self):
963 """Test rawcopy plugin in qemu"""
964 # build ext4 and wic images
965 for fstype in ("ext4", "wic"):
966 config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' % fstype
967 self.append_config(config)
968 self.assertEqual(0, bitbake('core-image-minimal').status)
969 self.remove_config(config)
970
971 with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu:
972 cmd = "grep sda. /proc/partitions |wc -l"
973 status, output = qemu.run_serial(cmd)
974 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
975 self.assertEqual(output, '2')
976
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500977 def test_rawcopy_plugin(self):
978 """Test rawcopy plugin"""
979 img = 'core-image-minimal'
980 machine = get_bb_var('MACHINE', img)
981 with NamedTemporaryFile("w", suffix=".wks") as wks:
982 wks.writelines(['part /boot --active --source bootimg-pcbios\n',
983 'part / --source rawcopy --sourceparams="file=%s-%s.ext4" --use-uuid\n'\
984 % (img, machine),
985 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
986 wks.flush()
987 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800988 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500989 wksname = os.path.splitext(os.path.basename(wks.name))[0]
990 out = glob(self.resultdir + "%s-*direct" % wksname)
991 self.assertEqual(1, len(out))
992
Brad Bishop96ff1982019-08-19 13:50:42 -0400993 @only_for_arch(['i586', 'i686', 'x86_64'])
994 def test_biosplusefi_plugin_qemu(self):
995 """Test biosplusefi plugin in qemu"""
Brad Bishop08902b02019-08-20 09:16:51 -0400996 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n'
997 self.append_config(config)
998 self.assertEqual(0, bitbake('core-image-minimal').status)
999 self.remove_config(config)
Brad Bishop96ff1982019-08-19 13:50:42 -04001000
1001 with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu:
1002 # Check that we have ONLY two /dev/sda* partitions (/boot and /)
1003 cmd = "grep sda. /proc/partitions | wc -l"
1004 status, output = qemu.run_serial(cmd)
1005 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1006 self.assertEqual(output, '2')
1007 # Check that /dev/sda1 is /boot and that either /dev/root OR /dev/sda2 is /
1008 cmd = "mount | grep '^/dev/' | cut -f1,3 -d ' ' | egrep -c -e '/dev/sda1 /boot' -e '/dev/root /|/dev/sda2 /'"
1009 status, output = qemu.run_serial(cmd)
1010 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1011 self.assertEqual(output, '2')
1012 # Check that /boot has EFI bootx64.efi (required for EFI)
1013 cmd = "ls /boot/EFI/BOOT/bootx64.efi | wc -l"
1014 status, output = qemu.run_serial(cmd)
1015 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1016 self.assertEqual(output, '1')
1017 # Check that "BOOTABLE" flag is set on boot partition (required for PC-Bios)
1018 # Trailing "cat" seems to be required; otherwise run_serial() sends back echo of the input command
1019 cmd = "fdisk -l /dev/sda | grep /dev/sda1 | awk {print'$2'} | cat"
1020 status, output = qemu.run_serial(cmd)
1021 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1022 self.assertEqual(output, '*')
1023
1024 @only_for_arch(['i586', 'i686', 'x86_64'])
1025 def test_biosplusefi_plugin(self):
1026 """Test biosplusefi plugin"""
1027 # Wic generation below may fail depending on the order of the unittests
1028 # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory
1029 # which may or may not exists depending on what was built already
1030 # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir()
1031 # will raise with "Couldn't find correct bootimg_dir"
1032 # The easiest way to work-around this issue is to make sure we already built an image here, hence the bitbake call
Brad Bishop08902b02019-08-20 09:16:51 -04001033 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_biosplusefi_plugin.wks"\nMACHINE_FEATURES_append = " efi"\n'
1034 self.append_config(config)
1035 self.assertEqual(0, bitbake('core-image-minimal').status)
1036 self.remove_config(config)
Brad Bishop96ff1982019-08-19 13:50:42 -04001037
1038 img = 'core-image-minimal'
1039 with NamedTemporaryFile("w", suffix=".wks") as wks:
1040 wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n',
1041 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\
1042 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
1043 wks.flush()
1044 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
1045 runCmd(cmd)
1046 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1047 out = glob(self.resultdir + "%s-*.direct" % wksname)
1048 self.assertEqual(1, len(out))
1049
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001050 def test_fs_types(self):
1051 """Test filesystem types for empty and not empty partitions"""
1052 img = 'core-image-minimal'
1053 with NamedTemporaryFile("w", suffix=".wks") as wks:
1054 wks.writelines(['part ext2 --fstype ext2 --source rootfs\n',
1055 'part btrfs --fstype btrfs --source rootfs --size 40M\n',
1056 'part squash --fstype squashfs --source rootfs\n',
1057 'part swap --fstype swap --size 1M\n',
1058 'part emptyvfat --fstype vfat --size 1M\n',
1059 'part emptymsdos --fstype msdos --size 1M\n',
1060 'part emptyext2 --fstype ext2 --size 1M\n',
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001061 'part emptybtrfs --fstype btrfs --size 150M\n'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001062 wks.flush()
1063 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001064 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001065 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1066 out = glob(self.resultdir + "%s-*direct" % wksname)
1067 self.assertEqual(1, len(out))
1068
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001069 def test_kickstart_parser(self):
1070 """Test wks parser options"""
1071 with NamedTemporaryFile("w", suffix=".wks") as wks:
1072 wks.writelines(['part / --fstype ext3 --source rootfs --system-id 0xFF '\
1073 '--overhead-factor 1.2 --size 100k\n'])
1074 wks.flush()
1075 cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001076 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001077 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1078 out = glob(self.resultdir + "%s-*direct" % wksname)
1079 self.assertEqual(1, len(out))
1080
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001081 def test_image_bootpart_globbed(self):
1082 """Test globbed sources with image-bootpart plugin"""
1083 img = "core-image-minimal"
1084 cmd = "wic create sdimage-bootpart -e %s -o %s" % (img, self.resultdir)
1085 config = 'IMAGE_BOOT_FILES = "%s*"' % get_bb_var('KERNEL_IMAGETYPE', img)
1086 self.append_config(config)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001087 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001088 self.remove_config(config)
1089 self.assertEqual(1, len(glob(self.resultdir + "sdimage-bootpart-*direct")))
1090
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001091 def test_sparse_copy(self):
1092 """Test sparse_copy with FIEMAP and SEEK_HOLE filemap APIs"""
1093 libpath = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib', 'wic')
1094 sys.path.insert(0, libpath)
1095 from filemap import FilemapFiemap, FilemapSeek, sparse_copy, ErrorNotSupp
1096 with NamedTemporaryFile("w", suffix=".wic-sparse") as sparse:
1097 src_name = sparse.name
1098 src_size = 1024 * 10
1099 sparse.truncate(src_size)
1100 # write one byte to the file
1101 with open(src_name, 'r+b') as sfile:
1102 sfile.seek(1024 * 4)
1103 sfile.write(b'\x00')
1104 dest = sparse.name + '.out'
1105 # copy src file to dest using different filemap APIs
1106 for api in (FilemapFiemap, FilemapSeek, None):
1107 if os.path.exists(dest):
1108 os.unlink(dest)
1109 try:
1110 sparse_copy(sparse.name, dest, api=api)
1111 except ErrorNotSupp:
1112 continue # skip unsupported API
1113 dest_stat = os.stat(dest)
1114 self.assertEqual(dest_stat.st_size, src_size)
1115 # 8 blocks is 4K (physical sector size)
1116 self.assertEqual(dest_stat.st_blocks, 8)
1117 os.unlink(dest)
1118
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001119 def test_wic_ls(self):
1120 """Test listing image content using 'wic ls'"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001121 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001122 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001123 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001124 images = glob(self.resultdir + "wictestdisk-*.direct")
1125 self.assertEqual(1, len(images))
1126
1127 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1128
1129 # list partitions
1130 result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001131 self.assertEqual(3, len(result.output.split('\n')))
1132
1133 # list directory content of the first partition
1134 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001135 self.assertEqual(6, len(result.output.split('\n')))
1136
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001137 def test_wic_cp(self):
1138 """Test copy files and directories to the the wic image."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001139 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001140 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001141 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001142 images = glob(self.resultdir + "wictestdisk-*.direct")
1143 self.assertEqual(1, len(images))
1144
1145 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1146
1147 # list directory content of the first partition
1148 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001149 self.assertEqual(6, len(result.output.split('\n')))
1150
1151 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
1152 testfile.write("test")
1153
1154 # copy file to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001155 runCmd("wic cp %s %s:1/ -n %s" % (testfile.name, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001156
1157 # check if file is there
1158 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001159 self.assertEqual(7, len(result.output.split('\n')))
1160 self.assertTrue(os.path.basename(testfile.name) in result.output)
1161
1162 # prepare directory
1163 testdir = os.path.join(self.resultdir, 'wic-test-cp-dir')
1164 testsubdir = os.path.join(testdir, 'subdir')
1165 os.makedirs(os.path.join(testsubdir))
1166 copy(testfile.name, testdir)
1167
1168 # copy directory to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001169 runCmd("wic cp %s %s:1/ -n %s" % (testdir, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001170
1171 # check if directory is there
1172 result = runCmd("wic ls %s:1/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001173 self.assertEqual(8, len(result.output.split('\n')))
1174 self.assertTrue(os.path.basename(testdir) in result.output)
1175
Andrew Geissler82c905d2020-04-13 13:39:40 -05001176 # copy the file from the partition and check if it success
1177 dest = '%s-cp' % testfile.name
1178 runCmd("wic cp %s:1/%s %s -n %s" % (images[0],
1179 os.path.basename(testfile.name), dest, sysroot))
1180 self.assertTrue(os.path.exists(dest))
1181
1182
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001183 def test_wic_rm(self):
1184 """Test removing files and directories from the the wic image."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001185 runCmd("wic create mkefidisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001186 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001187 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001188 images = glob(self.resultdir + "mkefidisk-*.direct")
1189 self.assertEqual(1, len(images))
1190
1191 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1192
1193 # list directory content of the first partition
1194 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001195 self.assertIn('\nBZIMAGE ', result.output)
1196 self.assertIn('\nEFI <DIR> ', result.output)
1197
1198 # remove file
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001199 runCmd("wic rm %s:1/bzimage -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001200
1201 # remove directory
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001202 runCmd("wic rm %s:1/efi -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001203
1204 # check if they're removed
1205 result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001206 self.assertNotIn('\nBZIMAGE ', result.output)
1207 self.assertNotIn('\nEFI <DIR> ', result.output)
1208
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001209 def test_mkfs_extraopts(self):
1210 """Test wks option --mkfs-extraopts for empty and not empty partitions"""
1211 img = 'core-image-minimal'
1212 with NamedTemporaryFile("w", suffix=".wks") as wks:
1213 wks.writelines(
1214 ['part ext2 --fstype ext2 --source rootfs --mkfs-extraopts "-D -F -i 8192"\n',
1215 "part btrfs --fstype btrfs --source rootfs --size 40M --mkfs-extraopts='--quiet'\n",
1216 'part squash --fstype squashfs --source rootfs --mkfs-extraopts "-no-sparse -b 4096"\n',
1217 'part emptyvfat --fstype vfat --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
1218 'part emptymsdos --fstype msdos --size 1M --mkfs-extraopts "-S 1024 -s 64"\n',
1219 'part emptyext2 --fstype ext2 --size 1M --mkfs-extraopts "-D -F -i 8192"\n',
1220 'part emptybtrfs --fstype btrfs --size 100M --mkfs-extraopts "--mixed -K"\n'])
1221 wks.flush()
1222 cmd = "wic create %s -e %s -o %s" % (wks.name, img, self.resultdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001223 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001224 wksname = os.path.splitext(os.path.basename(wks.name))[0]
1225 out = glob(self.resultdir + "%s-*direct" % wksname)
1226 self.assertEqual(1, len(out))
1227
1228 def test_expand_mbr_image(self):
1229 """Test wic write --expand command for mbr image"""
1230 # build an image
1231 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "directdisk.wks"\n'
1232 self.append_config(config)
1233 self.assertEqual(0, bitbake('core-image-minimal').status)
1234
1235 # get path to the image
1236 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'MACHINE'])
1237 deploy_dir = bb_vars['DEPLOY_DIR_IMAGE']
1238 machine = bb_vars['MACHINE']
1239 image_path = os.path.join(deploy_dir, 'core-image-minimal-%s.wic' % machine)
1240
1241 self.remove_config(config)
1242
1243 try:
1244 # expand image to 1G
1245 new_image_path = None
1246 with NamedTemporaryFile(mode='wb', suffix='.wic.exp',
1247 dir=deploy_dir, delete=False) as sparse:
1248 sparse.truncate(1024 ** 3)
1249 new_image_path = sparse.name
1250
1251 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1252 cmd = "wic write -n %s --expand 1:0 %s %s" % (sysroot, image_path, new_image_path)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001253 runCmd(cmd)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001254
1255 # check if partitions are expanded
1256 orig = runCmd("wic ls %s -n %s" % (image_path, sysroot))
1257 exp = runCmd("wic ls %s -n %s" % (new_image_path, sysroot))
1258 orig_sizes = [int(line.split()[3]) for line in orig.output.split('\n')[1:]]
1259 exp_sizes = [int(line.split()[3]) for line in exp.output.split('\n')[1:]]
1260 self.assertEqual(orig_sizes[0], exp_sizes[0]) # first partition is not resized
1261 self.assertTrue(orig_sizes[1] < exp_sizes[1])
1262
1263 # Check if all free space is partitioned
1264 result = runCmd("%s/usr/sbin/sfdisk -F %s" % (sysroot, new_image_path))
1265 self.assertTrue("0 B, 0 bytes, 0 sectors" in result.output)
1266
1267 os.rename(image_path, image_path + '.bak')
1268 os.rename(new_image_path, image_path)
1269
1270 # Check if it boots in qemu
1271 with runqemu('core-image-minimal', ssh=False) as qemu:
1272 cmd = "ls /etc/"
1273 status, output = qemu.run_serial('true')
1274 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))
1275 finally:
1276 if os.path.exists(new_image_path):
1277 os.unlink(new_image_path)
1278 if os.path.exists(image_path + '.bak'):
1279 os.rename(image_path + '.bak', image_path)
1280
1281 def test_wic_ls_ext(self):
1282 """Test listing content of the ext partition using 'wic ls'"""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001283 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001284 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001285 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001286 images = glob(self.resultdir + "wictestdisk-*.direct")
1287 self.assertEqual(1, len(images))
1288
1289 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1290
1291 # list directory content of the second ext4 partition
1292 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001293 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(
1294 set(line.split()[-1] for line in result.output.split('\n') if line)))
1295
1296 def test_wic_cp_ext(self):
1297 """Test copy files and directories to the ext partition."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001298 runCmd("wic create wictestdisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001299 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001300 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001301 images = glob(self.resultdir + "wictestdisk-*.direct")
1302 self.assertEqual(1, len(images))
1303
1304 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1305
1306 # list directory content of the ext4 partition
1307 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001308 dirs = set(line.split()[-1] for line in result.output.split('\n') if line)
1309 self.assertTrue(set(['bin', 'home', 'proc', 'usr', 'var', 'dev', 'lib', 'sbin']).issubset(dirs))
1310
1311 with NamedTemporaryFile("w", suffix=".wic-cp") as testfile:
1312 testfile.write("test")
1313
1314 # copy file to the partition
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001315 runCmd("wic cp %s %s:2/ -n %s" % (testfile.name, images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001316
1317 # check if file is there
1318 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001319 newdirs = set(line.split()[-1] for line in result.output.split('\n') if line)
1320 self.assertEqual(newdirs.difference(dirs), set([os.path.basename(testfile.name)]))
1321
Andrew Geissler82c905d2020-04-13 13:39:40 -05001322 # check if the file to copy is in the partition
1323 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
1324 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
1325
1326 # copy file from the partition, replace the temporary file content with it and
1327 # check for the file size to validate the copy
1328 runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot))
1329 self.assertTrue(os.stat(testfile.name).st_size > 0)
1330
1331
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001332 def test_wic_rm_ext(self):
1333 """Test removing files from the ext partition."""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001334 runCmd("wic create mkefidisk "
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001335 "--image-name=core-image-minimal "
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001336 "-D -o %s" % self.resultdir)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001337 images = glob(self.resultdir + "mkefidisk-*.direct")
1338 self.assertEqual(1, len(images))
1339
1340 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1341
1342 # list directory content of the /etc directory on ext4 partition
1343 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001344 self.assertTrue('fstab' in [line.split()[-1] for line in result.output.split('\n') if line])
1345
1346 # remove file
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001347 runCmd("wic rm %s:2/etc/fstab -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001348
1349 # check if it's removed
1350 result = runCmd("wic ls %s:2/etc/ -n %s" % (images[0], sysroot))
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001351 self.assertTrue('fstab' not in [line.split()[-1] for line in result.output.split('\n') if line])
Brad Bishop6dbb3162019-11-25 09:41:34 -05001352
1353 # remove non-empty directory
1354 runCmd("wic rm -r %s:2/etc/ -n %s" % (images[0], sysroot))
1355
1356 # check if it's removed
1357 result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
1358 self.assertTrue('etc' not in [line.split()[-1] for line in result.output.split('\n') if line])