summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes-recipe/image_types_wic.bbclass1
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py43
-rw-r--r--scripts/lib/wic/plugins/source/extra_partition.py134
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
18from shutil import rmtree, copy 18from shutil import rmtree, copy
19from tempfile import NamedTemporaryFile 19from tempfile import NamedTemporaryFile
20from tempfile import TemporaryDirectory 20from tempfile import TemporaryDirectory
21from textwrap import dedent
21 22
22from oeqa.selftest.case import OESelftestTestCase 23from oeqa.selftest.case import OESelftestTestCase
23from oeqa.core.decorator import OETestTag 24from 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 @@
1import logging
2import os
3import re
4
5from glob import glob
6
7from wic import WicError
8from wic.pluginbase import SourcePlugin
9from wic.misc import exec_cmd, get_bitbake_var
10
11logger = logging.getLogger('wic')
12
13class 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