diff options
-rw-r--r-- | meta/classes-recipe/image_types_wic.bbclass | 1 | ||||
-rw-r--r-- | meta/lib/oeqa/selftest/cases/wic.py | 43 | ||||
-rw-r--r-- | scripts/lib/wic/plugins/source/extra_partition.py | 134 |
3 files changed, 177 insertions, 1 deletions
diff --git a/meta/classes-recipe/image_types_wic.bbclass b/meta/classes-recipe/image_types_wic.bbclass index 6180874a4c..675aa97513 100644 --- a/meta/classes-recipe/image_types_wic.bbclass +++ b/meta/classes-recipe/image_types_wic.bbclass | |||
@@ -17,6 +17,7 @@ WICVARS ?= "\ | |||
17 | IMAGE_BOOT_FILES \ | 17 | IMAGE_BOOT_FILES \ |
18 | IMAGE_CLASSES \ | 18 | IMAGE_CLASSES \ |
19 | IMAGE_EFI_BOOT_FILES \ | 19 | IMAGE_EFI_BOOT_FILES \ |
20 | IMAGE_EXTRA_PARTITION_FILES \ | ||
20 | IMAGE_LINK_NAME \ | 21 | IMAGE_LINK_NAME \ |
21 | IMAGE_ROOTFS \ | 22 | IMAGE_ROOTFS \ |
22 | IMGDEPLOYDIR \ | 23 | IMGDEPLOYDIR \ |
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py index b1c318bd4e..e7e5dcb7e7 100644 --- a/meta/lib/oeqa/selftest/cases/wic.py +++ b/meta/lib/oeqa/selftest/cases/wic.py | |||
@@ -18,6 +18,7 @@ from glob import glob | |||
18 | from shutil import rmtree, copy | 18 | from shutil import rmtree, copy |
19 | from tempfile import NamedTemporaryFile | 19 | from tempfile import NamedTemporaryFile |
20 | from tempfile import TemporaryDirectory | 20 | from tempfile import TemporaryDirectory |
21 | from textwrap import dedent | ||
21 | 22 | ||
22 | from oeqa.selftest.case import OESelftestTestCase | 23 | from oeqa.selftest.case import OESelftestTestCase |
23 | from oeqa.core.decorator import OETestTag | 24 | from oeqa.core.decorator import OETestTag |
@@ -1021,7 +1022,7 @@ class Wic2(WicTestCase): | |||
1021 | wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES', | 1022 | wicvars = wicvars.difference(('DEPLOY_DIR_IMAGE', 'IMAGE_BOOT_FILES', |
1022 | 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE', | 1023 | 'INITRD', 'INITRD_LIVE', 'ISODIR','INITRAMFS_IMAGE', |
1023 | 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME', | 1024 | 'INITRAMFS_IMAGE_BUNDLE', 'INITRAMFS_LINK_NAME', |
1024 | 'APPEND', 'IMAGE_EFI_BOOT_FILES')) | 1025 | 'APPEND', 'IMAGE_EFI_BOOT_FILES', 'IMAGE_EXTRA_PARTITION_FILES')) |
1025 | with open(path) as envfile: | 1026 | with open(path) as envfile: |
1026 | content = dict(line.split("=", 1) for line in envfile) | 1027 | content = dict(line.split("=", 1) for line in envfile) |
1027 | # test if variables used by wic present in the .env file | 1028 | # test if variables used by wic present in the .env file |
@@ -1647,6 +1648,46 @@ INITRAMFS_IMAGE = "core-image-initramfs-boot" | |||
1647 | status, output = qemu.run_serial(cmd) | 1648 | status, output = qemu.run_serial(cmd) |
1648 | self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) | 1649 | self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) |
1649 | 1650 | ||
1651 | def test_extra_partition_plugin(self): | ||
1652 | """Test extra partition plugin""" | ||
1653 | config = dedent("""\ | ||
1654 | IMAGE_EXTRA_PARTITION_FILES_label-foo = "bar.conf;foo.conf" | ||
1655 | IMAGE_EXTRA_PARTITION_FILES_uuid-e7d0824e-cda3-4bed-9f54-9ef5312d105d = "bar.conf;foobar.conf" | ||
1656 | IMAGE_EXTRA_PARTITION_FILES = "foo/*" | ||
1657 | WICVARS:append = "\ | ||
1658 | IMAGE_EXTRA_PARTITION_FILES_label-foo \ | ||
1659 | IMAGE_EXTRA_PARTITION_FILES_uuid-e7d0824e-cda3-4bed-9f54-9ef5312d105d \ | ||
1660 | " | ||
1661 | """) | ||
1662 | self.append_config(config) | ||
1663 | |||
1664 | deploy_dir = get_bb_var('DEPLOY_DIR_IMAGE') | ||
1665 | |||
1666 | testfile = open(os.path.join(deploy_dir, "bar.conf"), "w") | ||
1667 | testfile.write("test") | ||
1668 | testfile.close() | ||
1669 | |||
1670 | os.mkdir(os.path.join(deploy_dir, "foo")) | ||
1671 | testfile = open(os.path.join(deploy_dir, "foo", "bar.conf"), "w") | ||
1672 | testfile.write("test") | ||
1673 | testfile.close() | ||
1674 | |||
1675 | with NamedTemporaryFile("w", suffix=".wks") as wks: | ||
1676 | wks.writelines(['part / --source extra_partition --ondisk sda --fstype=ext4 --label foo --align 4 --size 5M\n', | ||
1677 | 'part / --source extra_partition --ondisk sda --fstype=ext4 --uuid e7d0824e-cda3-4bed-9f54-9ef5312d105d --align 4 --size 5M\n', | ||
1678 | 'part / --source extra_partition --ondisk sda --fstype=ext4 --label bar --align 4 --size 5M\n']) | ||
1679 | wks.flush() | ||
1680 | _, wicimg = self._get_wic(wks.name) | ||
1681 | |||
1682 | result = runCmd("wic ls %s | wc -l" % wicimg) | ||
1683 | self.assertEqual('4', result.output, msg="Expect 3 partitions, not %s" % result.output) | ||
1684 | |||
1685 | for part, file in enumerate(["foo.conf", "foobar.conf", "bar.conf"]): | ||
1686 | result = runCmd("wic ls %s:%d | grep -q \"%s\"" % (wicimg, part + 1, file)) | ||
1687 | self.assertEqual(0, result.status, msg="File '%s' not found in the partition #%d" % (file, part)) | ||
1688 | |||
1689 | self.remove_config(config) | ||
1690 | |||
1650 | def test_fs_types(self): | 1691 | def test_fs_types(self): |
1651 | """Test filesystem types for empty and not empty partitions""" | 1692 | """Test filesystem types for empty and not empty partitions""" |
1652 | img = 'core-image-minimal' | 1693 | img = 'core-image-minimal' |
diff --git a/scripts/lib/wic/plugins/source/extra_partition.py b/scripts/lib/wic/plugins/source/extra_partition.py new file mode 100644 index 0000000000..d370b0107e --- /dev/null +++ b/scripts/lib/wic/plugins/source/extra_partition.py | |||
@@ -0,0 +1,134 @@ | |||
1 | import logging | ||
2 | import os | ||
3 | import re | ||
4 | |||
5 | from glob import glob | ||
6 | |||
7 | from wic import WicError | ||
8 | from wic.pluginbase import SourcePlugin | ||
9 | from wic.misc import exec_cmd, get_bitbake_var | ||
10 | |||
11 | logger = logging.getLogger('wic') | ||
12 | |||
13 | class ExtraPartitionPlugin(SourcePlugin): | ||
14 | """ | ||
15 | Populates an extra partition with files listed in the IMAGE_EXTRA_PARTITION_FILES | ||
16 | BitBake variable. Files should be deployed to the DEPLOY_DIR_IMAGE directory. | ||
17 | |||
18 | The plugin supports: | ||
19 | - Glob pattern matching for file selection. | ||
20 | - File renaming. | ||
21 | - Suffixes to specify the target partition (by label, UUID, or partname), | ||
22 | enabling multiple extra partitions to coexist. | ||
23 | |||
24 | For example: | ||
25 | |||
26 | IMAGE_EXTRA_PARTITION_FILES_label-foo = "bar.conf;foo.conf" | ||
27 | IMAGE_EXTRA_PARTITION_FILES_uuid-e7d0824e-cda3-4bed-9f54-9ef5312d105d = "bar.conf;foobar.conf" | ||
28 | IMAGE_EXTRA_PARTITION_FILES = "foo/*" | ||
29 | WICVARS:append = "\ | ||
30 | IMAGE_EXTRA_PARTITION_FILES_label-foo \ | ||
31 | IMAGE_EXTRA_PARTITION_FILES_uuid-e7d0824e-cda3-4bed-9f54-9ef5312d105d \ | ||
32 | " | ||
33 | |||
34 | """ | ||
35 | |||
36 | name = 'extra_partition' | ||
37 | image_extra_partition_files_var_name = 'IMAGE_EXTRA_PARTITION_FILES' | ||
38 | |||
39 | @classmethod | ||
40 | def do_configure_partition(cls, part, source_params, cr, cr_workdir, | ||
41 | oe_builddir, bootimg_dir, kernel_dir, | ||
42 | native_sysroot): | ||
43 | """ | ||
44 | Called before do_prepare_partition(), list the files to copy | ||
45 | """ | ||
46 | extradir = "%s/extra.%d" % (cr_workdir, part.lineno) | ||
47 | install_cmd = "install -d %s" % extradir | ||
48 | exec_cmd(install_cmd) | ||
49 | |||
50 | if not kernel_dir: | ||
51 | kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") | ||
52 | if not kernel_dir: | ||
53 | raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") | ||
54 | |||
55 | extra_files = None | ||
56 | for (fmt, id) in (("_uuid-%s", part.uuid), ("_label-%s", part.label), ("_part-name-%s", part.part_name), (None, None)): | ||
57 | if fmt: | ||
58 | var = fmt % id | ||
59 | else: | ||
60 | var = "" | ||
61 | extra_files = get_bitbake_var(cls.image_extra_partition_files_var_name + var) | ||
62 | if extra_files is not None: | ||
63 | break | ||
64 | |||
65 | if extra_files is None: | ||
66 | raise WicError('No extra files defined, %s unset for entry #%d' % (cls.image_extra_partition_files_var_name, part.lineno)) | ||
67 | |||
68 | logger.info('Extra files: %s', extra_files) | ||
69 | |||
70 | # list of tuples (src_name, dst_name) | ||
71 | deploy_files = [] | ||
72 | for src_entry in re.findall(r'[\w;\-\./\*]+', extra_files): | ||
73 | if ';' in src_entry: | ||
74 | dst_entry = tuple(src_entry.split(';')) | ||
75 | if not dst_entry[0] or not dst_entry[1]: | ||
76 | raise WicError('Malformed extra file entry: %s' % src_entry) | ||
77 | else: | ||
78 | dst_entry = (src_entry, src_entry) | ||
79 | |||
80 | logger.debug('Destination entry: %r', dst_entry) | ||
81 | deploy_files.append(dst_entry) | ||
82 | |||
83 | cls.install_task = []; | ||
84 | for deploy_entry in deploy_files: | ||
85 | src, dst = deploy_entry | ||
86 | if '*' in src: | ||
87 | # by default install files under their basename | ||
88 | entry_name_fn = os.path.basename | ||
89 | if dst != src: | ||
90 | # unless a target name was given, then treat name | ||
91 | # as a directory and append a basename | ||
92 | entry_name_fn = lambda name: \ | ||
93 | os.path.join(dst, | ||
94 | os.path.basename(name)) | ||
95 | |||
96 | srcs = glob(os.path.join(kernel_dir, src)) | ||
97 | |||
98 | logger.debug('Globbed sources: %s', ', '.join(srcs)) | ||
99 | for entry in srcs: | ||
100 | src = os.path.relpath(entry, kernel_dir) | ||
101 | entry_dst_name = entry_name_fn(entry) | ||
102 | cls.install_task.append((src, entry_dst_name)) | ||
103 | else: | ||
104 | cls.install_task.append((src, dst)) | ||
105 | |||
106 | |||
107 | @classmethod | ||
108 | def do_prepare_partition(cls, part, source_params, cr, cr_workdir, | ||
109 | oe_builddir, bootimg_dir, kernel_dir, | ||
110 | rootfs_dir, native_sysroot): | ||
111 | """ | ||
112 | Called to do the actual content population for a partition i.e. it | ||
113 | 'prepares' the partition to be incorporated into the image. | ||
114 | In this case, we copies all files listed in IMAGE_EXTRA_PARTITION_FILES variable. | ||
115 | """ | ||
116 | extradir = "%s/extra.%d" % (cr_workdir, part.lineno) | ||
117 | |||
118 | if not kernel_dir: | ||
119 | kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") | ||
120 | if not kernel_dir: | ||
121 | raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") | ||
122 | |||
123 | for task in cls.install_task: | ||
124 | src_path, dst_path = task | ||
125 | logger.debug('Install %s as %s', src_path, dst_path) | ||
126 | install_cmd = "install -m 0644 -D %s %s" \ | ||
127 | % (os.path.join(kernel_dir, src_path), | ||
128 | os.path.join(extradir, dst_path)) | ||
129 | exec_cmd(install_cmd) | ||
130 | |||
131 | logger.debug('Prepare extra partition using rootfs in %s', extradir) | ||
132 | part.prepare_rootfs(cr_workdir, oe_builddir, extradir, | ||
133 | native_sysroot, False) | ||
134 | |||