Merge lp:~tobijk/livecd-rootfs/image-sets into lp:livecd-rootfs
- image-sets
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 1735 |
Proposed branch: | lp:~tobijk/livecd-rootfs/image-sets |
Merge into: | lp:livecd-rootfs |
Diff against target: |
565 lines (+343/-62) 18 files modified
live-build/auto/config (+13/-0) live-build/ubuntu-cpc/README.cpc.md (+68/-0) live-build/ubuntu-cpc/hooks.d/base/disk-image.binary (+3/-1) live-build/ubuntu-cpc/hooks.d/base/qcow2-image.binary (+0/-9) live-build/ubuntu-cpc/hooks.d/base/root-squashfs.binary (+0/-9) live-build/ubuntu-cpc/hooks.d/base/series/base (+7/-0) live-build/ubuntu-cpc/hooks.d/base/series/disk-image (+3/-0) live-build/ubuntu-cpc/hooks.d/base/series/qcow2 (+2/-0) live-build/ubuntu-cpc/hooks.d/base/series/root-dir (+1/-0) live-build/ubuntu-cpc/hooks.d/base/series/squashfs (+2/-0) live-build/ubuntu-cpc/hooks.d/base/series/tarball (+2/-0) live-build/ubuntu-cpc/hooks.d/base/series/vagrant (+2/-0) live-build/ubuntu-cpc/hooks.d/base/series/vmdk (+3/-0) live-build/ubuntu-cpc/hooks.d/base/vagrant.binary (+0/-9) live-build/ubuntu-cpc/hooks.d/base/vmdk-image.binary (+0/-9) live-build/ubuntu-cpc/hooks.d/base/vmdk-ova-image.binary (+0/-9) live-build/ubuntu-cpc/hooks.d/make-hooks (+237/-0) live-build/ubuntu-cpc/hooks/999-extras.binary (+0/-16) |
To merge this branch: | bzr merge lp:~tobijk/livecd-rootfs/image-sets |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Steve Langasek | Approve | ||
Philip Roche (community) | Abstain | ||
Dan Watkins (community) | Approve | ||
Francis Ginther (community) | Approve | ||
Review via email: mp+356246@code.launchpad.net |
Commit message
Use series files with dependency handling to generate hook symlinks dynamically
This patch currently only applies to the "ubuntu-cpc" project.
More and more logic has been going into the hook scripts to decide under which conditions they should run or not. As we are moving to parallelized builds of image sets, this will get even more complicated. Base hooks will have to know which image sets they belong to and modification of the dependency chain between scripts will become more complicated and prone to errors, as the number of image sets grows.
This patch introduces explicit ordering and dependency handling for scripts through the use of `series` files and an explicit syntax for dependency specification.
Description of the change
Please read
In order to try out the hook generation, change to
live-
and call `make-hooks` with different arguments, for example:
./make-hooks --hooks-dir hook-test vagrant
or
./make-hooks --hooks-dir hook-test squashfs disk-image vagrant
Take a look at hooks.d/base/series for available series files.
Tobias Koch (tobijk) wrote : | # |
Thanks a lot for the detailed review, @daniel-thewatkins! I think I have addressed everything you brought up in the new submission below. I also verified that the script works as Python3-only on Xenial.
Philip Roche (philroche) wrote : | # |
Very nice approach and the Readme is very helpful. I would like some docstrings in the python script though as I know future me will need them ;p
Apart from that I am +1
Tobias Koch (tobijk) wrote : | # |
Thank you @philroche, let me know if this works or if anything needs further clarification.
Francis Ginther (fginther) wrote : | # |
Is the intention that the execution order of hooks be identical once this change lands? That currently isn't the case and may lead to changes in the images. For example, the following generates:
./make-hooks --hooks-dir ../hooks vmdk vagrant
...
[HOOK] 005-ssh_
...
[HOOK] 016-vagrant.binary => base/vagrant.binary
But prior to this change, these two hooks were in the opposite order:
042-vagrant.binary
052-ssh_
Am I missing something (like are all the chroot hooks executed before the binary hooks)?
I also have a concern with defining the RESOURCE map in the make-hooks script (see inline comment).
Otherwise, I think this is a good approach to the problem. Thanks for working on it.
Steve Langasek (vorlon) wrote : | # |
On Thu, Oct 25, 2018 at 03:47:11PM -0000, Francis Ginther wrote:
> Am I missing something (like are all the chroot hooks executed before the
> binary hooks)?
Yes, all chroot hooks are executed before the binary hooks.
Tobias Koch (tobijk) wrote : | # |
> Am I missing something (like are all the chroot hooks executed before the
> binary hooks)?
Yes, exactly, chroot hooks and binary hooks are run in separate batches, it is not possible to interleave them. See the ACHTUNG note in the script header.
Francis Ginther (fginther) wrote : | # |
> > Am I missing something (like are all the chroot hooks executed before the
> > binary hooks)?
>
> Yes, exactly, chroot hooks and binary hooks are run in separate batches, it is
> not possible to interleave them. See the ACHTUNG note in the script header.
DOH! Thanks for already mentioning this in the comments.
My only remaining concern is the definition of the extra RESOURCES.
Tobias Koch (tobijk) wrote : | # |
@fginther, nobody reads the comments ;) I think you having missed that piece of information is really just bad documentation. I added the same note to the README, where it really belongs.
Thank you for suggesting to take out the resource mappings. That really makes a lot of sense. Following your suggestion, the script now looks for base/resources.yaml and extra/resources
I also updated
https:/
to match these changes.
@daniel-thewatkins, @philroche, I believe I have addressed your concerns, as well. Please have another look.
Francis Ginther (fginther) wrote : | # |
Thanks for working on the resource map. I'm happy with this approach.
I do prefer to use yaml.safe_load() over yaml.load(), but I think it's use is fine here considering we're only loading our own code.
Philip Roche (philroche) wrote : | # |
Happy to go merge with the two current approvals
Steve Langasek (vorlon) wrote : | # |
Apologies for taking so long to give feedback on this. I knew that such a significant refactor was owed a thorough review, and I didn't find time to do so until now.
Comments inline.
Tobias Koch (tobijk) wrote : | # |
Also revamped this taking into account @xnox's comments on
https:/
Tobias Koch (tobijk) wrote : | # |
@vorlon, thank you so much for taking the time to review this in depth!
* There is now also a series file for the qcow2 target.
* It turned out that copying resources was not even necessary, because all scripts except one reference resources relative to their location. So I have removed that part completely.
I would like to keep the series file for the chroot, because:
* I find it more consistent to have all hooks placed/generated in the same way in the CPC subproject.
* We will want to augment the syntax of the series files in the future to also take into account arch, subarch and other attributes of the build that are currently handled by case statements in the scripts and this can also be useful for chroot customization,
* This is not on the table, right now, but I can imagine that we will find it useful to drop the ability to build different image target sets together and do per target set (and arch) chroot customizations. There can be advantages to this such being able to seed all target specific packages and snaps into the chroot instead of having to mount, fiddle and re-sparsen an image.
Dan Watkins (oddbloke) wrote : | # |
On Fri, Nov 30, 2018 at 01:01:15PM -0000, Tobias Koch wrote:
> * This is not on the table, right now, but I can imagine that we will find it useful to drop the ability to build different image target sets together and do per target set (and arch) chroot customizations. There can be advantages to this such being able to seed all target specific packages and snaps into the chroot instead of having to mount, fiddle and re-sparsen an image.
+1, we definitely want to leave the door open to be able to do this in
the future.
Steve Langasek (vorlon) wrote : | # |
On Fri, Nov 30, 2018 at 02:27:22PM -0000, Dan Watkins wrote:
> On Fri, Nov 30, 2018 at 01:01:15PM -0000, Tobias Koch wrote:
> > * This is not on the table, right now, but I can imagine that we will
> > find it useful to drop the ability to build different image target
> > sets together and do per target set (and arch) chroot customizations.
> > There can be advantages to this such being able to seed all target
> > specific packages and snaps into the chroot instead of having to
> > mount, fiddle and re-sparsen an image.
> +1, we definitely want to leave the door open to be able to do this in
> the future.
I would argue, however, that until this actually *is* on the table, such
handling of chroot scripts is still just unnecessary complexity.
Tobias Koch (tobijk) wrote : | # |
So is that a veto? Subsystem maintainers are +1.
Steve Langasek (vorlon) wrote : | # |
> So is that a veto? Subsystem maintainers are +1.
Yes, I think I do have to insist that the changes to chroot hooks not be included here. Having to keep the list of chroot hooks in sync between the directory contents and the series file is error-prone, and should be avoided unless and until there is a reason to define a series that doesn't include all the chroot hooks.
Tobias Koch (tobijk) wrote : | # |
@vorlon, I have made the necessary changes. Please check, if you are ok with this. Thanks!
Steve Langasek (vorlon) : | # |
Preview Diff
1 | === modified file 'live-build/auto/config' |
2 | --- live-build/auto/config 2018-11-28 15:05:24 +0000 |
3 | +++ live-build/auto/config 2018-12-10 08:29:28 +0000 |
4 | @@ -1026,6 +1026,19 @@ |
5 | ubuntu-touch:*|ubuntu-touch-custom:*|ubuntu-core:system-image|ubuntu-desktop-next:system-image|ubuntu-cpc:*|ubuntu-server:live) |
6 | cp -af /usr/share/livecd-rootfs/live-build/${PROJECT}/* \ |
7 | config/ |
8 | + |
9 | + if [ "$PROJECT" = "ubuntu-cpc" ]; then |
10 | + case ${IMAGE_TARGETS:-} in |
11 | + "") |
12 | + config/hooks.d/make-hooks --hooks-dir config/hooks all |
13 | + ;; |
14 | + *) |
15 | + config/hooks.d/make-hooks --hooks-dir config/hooks \ |
16 | + "$IMAGE_TARGETS" |
17 | + ;; |
18 | + esac |
19 | + fi |
20 | + |
21 | if [ "$IMAGEFORMAT" = none ]; then |
22 | rm -f config/hooks/*.binary* |
23 | fi |
24 | |
25 | === added file 'live-build/ubuntu-cpc/README.cpc.md' |
26 | --- live-build/ubuntu-cpc/README.cpc.md 1970-01-01 00:00:00 +0000 |
27 | +++ live-build/ubuntu-cpc/README.cpc.md 2018-12-10 08:29:28 +0000 |
28 | @@ -0,0 +1,68 @@ |
29 | +# TL;DR |
30 | + |
31 | +In order to generate the hooks for a specific image target set, call the |
32 | +`make-hooks` script, located in `hooks.d` as |
33 | + |
34 | + ./make-hooks --hooks-dir ../hooks <image_set> |
35 | + |
36 | +where `image_set` is the name of a series file (e.g. "vagrant") without leading |
37 | +path components. Do *not* check in the `hooks` folder, it is automatically |
38 | +generated by `auto/config` during Live Build runs. |
39 | + |
40 | + |
41 | +# Hook placement and ordering |
42 | + |
43 | +Scripts live in subfolders below the `hooks.d` folder. Currently the folders |
44 | +`chroot` and `base` exist. The folder with the name `extra` is reserved for |
45 | +private scripts, which are not included in the source of livecd-rootfs. The |
46 | +scripts are not numbered, instead the order of their execution depends on the |
47 | +order in which they are listed in a *series* file. |
48 | + |
49 | +Series files are placed in subfolders `hooks.d/base/series` or |
50 | +`hooks.d/extra/series`. Each series file contains a list of scripts to be |
51 | +executed. Empty lines and lines starting with a `#` are ignored. |
52 | + |
53 | +Series files in `extra/series` override files in `base/series` with the same |
54 | +name. For example, if a series file `base/series/cloudA` exists and a series |
55 | +file `extra/series/cloudA`, then the latter will be preferred. |
56 | + |
57 | +A series file in `extra/series` may also list scripts that are located in the |
58 | +`chroot` and `base` folders. In addition, series files can *depend* on other |
59 | +series files. For example, the series files for most custom images look similar |
60 | +to this: |
61 | + |
62 | + depends disk-image |
63 | + depends extra-settings |
64 | + extra/cloudB.binary |
65 | + |
66 | +Where `disk-image` and `extra-settings` may list scripts and dependencies which |
67 | +are to be processed before the script `extra/cloudB.binary` is called. |
68 | + |
69 | +ACHTUNG: live build runs scripts with the suffix ".chroot" in a batch separate |
70 | +from scripts ending in ".binary". Even if you arrange them interleaved in your |
71 | +series files, the chroot scripts will be run before the binary scripts. |
72 | + |
73 | +# Image set selection for Live Build |
74 | + |
75 | +During a Live Build, enumerated symbolic links are generated based on the |
76 | +contents of one or more series files. The series files are selected according |
77 | +to the contents of the `IMAGE_TARGETS` environment variable. For example, in |
78 | +order to trigger the build of `squashfs` and `vagrant`, list them in the |
79 | +`IMAGE_TARGETS` variable as `squashfs,vagrant`. The separator can be a comma, |
80 | +a semi-colon or whitespace. |
81 | + |
82 | +The generation of the symbolic links is triggered from the `auto/config` script, |
83 | +from where the contents of the `IMAGE_TARGETS` environment variable are passed |
84 | +on to the `make-hooks` script. |
85 | + |
86 | + |
87 | +# Symlink generation |
88 | + |
89 | +Since Live Build itself does not know about series files, a traditional `hooks` |
90 | +folder is generated using the `make-hooks` script. The script takes as arguments |
91 | +the names of the series files to be processed. |
92 | + |
93 | +The script parses the series files and generates enumerated symbolic links for |
94 | +all entries. Per default, these are placed into a directory named `hooks` next |
95 | +to the `hooks.d` directory. This can be changed using the `--hooks-dir` |
96 | +parameter. |
97 | |
98 | === removed directory 'live-build/ubuntu-cpc/hooks' |
99 | === added directory 'live-build/ubuntu-cpc/hooks.d' |
100 | === added directory 'live-build/ubuntu-cpc/hooks.d/base' |
101 | === renamed file 'live-build/ubuntu-cpc/hooks/031-0-create-root-dir.binary' => 'live-build/ubuntu-cpc/hooks.d/base/create-root-dir.binary' |
102 | === renamed file 'live-build/ubuntu-cpc/hooks/034-disk-image-ppc64el.binary' => 'live-build/ubuntu-cpc/hooks.d/base/disk-image-ppc64el.binary' |
103 | === renamed file 'live-build/ubuntu-cpc/hooks/033-disk-image-uefi.binary' => 'live-build/ubuntu-cpc/hooks.d/base/disk-image-uefi.binary' |
104 | === renamed file 'live-build/ubuntu-cpc/hooks/032-disk-image.binary' => 'live-build/ubuntu-cpc/hooks.d/base/disk-image.binary' |
105 | --- live-build/ubuntu-cpc/hooks/032-disk-image.binary 2018-10-04 00:21:56 +0000 |
106 | +++ live-build/ubuntu-cpc/hooks.d/base/disk-image.binary 2018-12-10 08:29:28 +0000 |
107 | @@ -12,6 +12,8 @@ |
108 | BOOT_MOUNTPOINT= |
109 | ROOTPART_START=1 |
110 | |
111 | +my_d=$(dirname $(readlink -f ${0})) |
112 | + |
113 | case $ARCH:$SUBARCH in |
114 | ppc64el:*|powerpc:*) |
115 | echo "POWER disk images are handled separately" |
116 | @@ -97,7 +99,7 @@ |
117 | # not the best place for this, but neither flash-kernel nor |
118 | # u-boot have provisions for installing u-boot via maintainer |
119 | # script |
120 | - config/hooks/raspi2/mkknlimg --dtok \ |
121 | + ${my_d}/raspi2/mkknlimg --dtok \ |
122 | mountpoint/usr/lib/u-boot/rpi_2/u-boot.bin \ |
123 | mountpoint/boot/firmware/uboot.bin |
124 | ;; |
125 | |
126 | === renamed directory 'live-build/ubuntu-cpc/hooks/ovf' => 'live-build/ubuntu-cpc/hooks.d/base/ovf' |
127 | === renamed file 'live-build/ubuntu-cpc/hooks/040-qcow2-image.binary' => 'live-build/ubuntu-cpc/hooks.d/base/qcow2-image.binary' |
128 | --- live-build/ubuntu-cpc/hooks/040-qcow2-image.binary 2017-11-20 20:18:33 +0000 |
129 | +++ live-build/ubuntu-cpc/hooks.d/base/qcow2-image.binary 2018-12-10 08:29:28 +0000 |
130 | @@ -1,14 +1,5 @@ |
131 | #!/bin/bash -ex |
132 | |
133 | -case $IMAGE_TARGETS in |
134 | - ""|*qcow2*) |
135 | - ;; |
136 | - *) |
137 | - echo "Skipping qcow2 image build" |
138 | - exit 0 |
139 | - ;; |
140 | -esac |
141 | - |
142 | case $ARCH:$SUBARCH in |
143 | # Not sure if any other cloud images use subarch for something that |
144 | # should take qcow2 format, so only skipping this on raspi2 for now. |
145 | |
146 | === renamed directory 'live-build/ubuntu-cpc/hooks/raspi2' => 'live-build/ubuntu-cpc/hooks.d/base/raspi2' |
147 | === renamed file 'live-build/ubuntu-cpc/hooks/031-2-root-squashfs.binary' => 'live-build/ubuntu-cpc/hooks.d/base/root-squashfs.binary' |
148 | --- live-build/ubuntu-cpc/hooks/031-2-root-squashfs.binary 2018-06-07 23:24:29 +0000 |
149 | +++ live-build/ubuntu-cpc/hooks.d/base/root-squashfs.binary 2018-12-10 08:29:28 +0000 |
150 | @@ -3,15 +3,6 @@ |
151 | # |
152 | # Generate a squashfs root and manifest |
153 | |
154 | -case $IMAGE_TARGETS in |
155 | - ""|*squashfs*) |
156 | - ;; |
157 | - *) |
158 | - echo "Skipping squashfs build" |
159 | - exit 0 |
160 | - ;; |
161 | -esac |
162 | - |
163 | if [ -n "$SUBARCH" ]; then |
164 | echo "Skipping rootfs build for subarch flavor build" |
165 | exit 0 |
166 | |
167 | === renamed file 'live-build/ubuntu-cpc/hooks/031-1-root-xz.binary' => 'live-build/ubuntu-cpc/hooks.d/base/root-xz.binary' |
168 | === added directory 'live-build/ubuntu-cpc/hooks.d/base/series' |
169 | === added symlink 'live-build/ubuntu-cpc/hooks.d/base/series/all' |
170 | === target is u'base' |
171 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/base' |
172 | --- live-build/ubuntu-cpc/hooks.d/base/series/base 1970-01-01 00:00:00 +0000 |
173 | +++ live-build/ubuntu-cpc/hooks.d/base/series/base 2018-12-10 08:29:28 +0000 |
174 | @@ -0,0 +1,7 @@ |
175 | +depends root-dir |
176 | +depends tarball |
177 | +depends squashfs |
178 | +depends disk-image |
179 | +depends qcow2 |
180 | +depends vmdk |
181 | +depends vagrant |
182 | |
183 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/disk-image' |
184 | --- live-build/ubuntu-cpc/hooks.d/base/series/disk-image 1970-01-01 00:00:00 +0000 |
185 | +++ live-build/ubuntu-cpc/hooks.d/base/series/disk-image 2018-12-10 08:29:28 +0000 |
186 | @@ -0,0 +1,3 @@ |
187 | +base/disk-image.binary |
188 | +base/disk-image-uefi.binary |
189 | +base/disk-image-ppc64el.binary |
190 | |
191 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/qcow2' |
192 | --- live-build/ubuntu-cpc/hooks.d/base/series/qcow2 1970-01-01 00:00:00 +0000 |
193 | +++ live-build/ubuntu-cpc/hooks.d/base/series/qcow2 2018-12-10 08:29:28 +0000 |
194 | @@ -0,0 +1,2 @@ |
195 | +depends disk-image |
196 | +base/qcow2-image.binary |
197 | |
198 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/root-dir' |
199 | --- live-build/ubuntu-cpc/hooks.d/base/series/root-dir 1970-01-01 00:00:00 +0000 |
200 | +++ live-build/ubuntu-cpc/hooks.d/base/series/root-dir 2018-12-10 08:29:28 +0000 |
201 | @@ -0,0 +1,1 @@ |
202 | +base/create-root-dir.binary |
203 | |
204 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/squashfs' |
205 | --- live-build/ubuntu-cpc/hooks.d/base/series/squashfs 1970-01-01 00:00:00 +0000 |
206 | +++ live-build/ubuntu-cpc/hooks.d/base/series/squashfs 2018-12-10 08:29:28 +0000 |
207 | @@ -0,0 +1,2 @@ |
208 | +depends root-dir |
209 | +base/root-squashfs.binary |
210 | |
211 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/tarball' |
212 | --- live-build/ubuntu-cpc/hooks.d/base/series/tarball 1970-01-01 00:00:00 +0000 |
213 | +++ live-build/ubuntu-cpc/hooks.d/base/series/tarball 2018-12-10 08:29:28 +0000 |
214 | @@ -0,0 +1,2 @@ |
215 | +depends root-dir |
216 | +base/root-xz.binary |
217 | |
218 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/vagrant' |
219 | --- live-build/ubuntu-cpc/hooks.d/base/series/vagrant 1970-01-01 00:00:00 +0000 |
220 | +++ live-build/ubuntu-cpc/hooks.d/base/series/vagrant 2018-12-10 08:29:28 +0000 |
221 | @@ -0,0 +1,2 @@ |
222 | +depends disk-image |
223 | +base/vagrant.binary |
224 | |
225 | === added file 'live-build/ubuntu-cpc/hooks.d/base/series/vmdk' |
226 | --- live-build/ubuntu-cpc/hooks.d/base/series/vmdk 1970-01-01 00:00:00 +0000 |
227 | +++ live-build/ubuntu-cpc/hooks.d/base/series/vmdk 2018-12-10 08:29:28 +0000 |
228 | @@ -0,0 +1,3 @@ |
229 | +depends disk-image |
230 | +base/vmdk-image.binary |
231 | +base/vmdk-ova-image.binary |
232 | |
233 | === renamed file 'live-build/ubuntu-cpc/hooks/042-vagrant.binary' => 'live-build/ubuntu-cpc/hooks.d/base/vagrant.binary' |
234 | --- live-build/ubuntu-cpc/hooks/042-vagrant.binary 2018-10-11 10:01:48 +0000 |
235 | +++ live-build/ubuntu-cpc/hooks.d/base/vagrant.binary 2018-12-10 08:29:28 +0000 |
236 | @@ -24,15 +24,6 @@ |
237 | ;; |
238 | esac |
239 | |
240 | -case $IMAGE_TARGETS in |
241 | - ""|*vagrant*) |
242 | - ;; |
243 | - *) |
244 | - echo "Skipping Vagrant image build" |
245 | - exit 0 |
246 | - ;; |
247 | -esac |
248 | - |
249 | cur_d=${PWD} |
250 | my_d=$(dirname $(readlink -f ${0})) |
251 | |
252 | |
253 | === renamed file 'live-build/ubuntu-cpc/hooks/040-vmdk-image.binary' => 'live-build/ubuntu-cpc/hooks.d/base/vmdk-image.binary' |
254 | --- live-build/ubuntu-cpc/hooks/040-vmdk-image.binary 2018-03-20 18:30:27 +0000 |
255 | +++ live-build/ubuntu-cpc/hooks.d/base/vmdk-image.binary 2018-12-10 08:29:28 +0000 |
256 | @@ -18,15 +18,6 @@ |
257 | exit 0;; |
258 | esac |
259 | |
260 | -case ${IMAGE_TARGETS:-} in |
261 | - ""|*vmdk*) |
262 | - ;; |
263 | - *) |
264 | - echo "Skipping VMDK image build" |
265 | - exit 0 |
266 | - ;; |
267 | -esac |
268 | - |
269 | . config/functions |
270 | |
271 | if [ -e binary/boot/disk-uefi.ext4 ]; then |
272 | |
273 | === renamed file 'live-build/ubuntu-cpc/hooks/041-vmdk-ova-image.binary' => 'live-build/ubuntu-cpc/hooks.d/base/vmdk-ova-image.binary' |
274 | --- live-build/ubuntu-cpc/hooks/041-vmdk-ova-image.binary 2018-03-20 18:30:27 +0000 |
275 | +++ live-build/ubuntu-cpc/hooks.d/base/vmdk-ova-image.binary 2018-12-10 08:29:28 +0000 |
276 | @@ -32,15 +32,6 @@ |
277 | exit 0;; |
278 | esac |
279 | |
280 | -case ${IMAGE_TARGETS:-} in |
281 | - ""|*vmdk*) |
282 | - ;; |
283 | - *) |
284 | - echo "Skipping OVA image build" |
285 | - exit 0 |
286 | - ;; |
287 | -esac |
288 | - |
289 | cur_d=${PWD} |
290 | my_d=$(dirname $(readlink -f ${0})) |
291 | |
292 | |
293 | === added directory 'live-build/ubuntu-cpc/hooks.d/chroot' |
294 | === renamed file 'live-build/ubuntu-cpc/hooks/001-divert-sync.chroot_early' => 'live-build/ubuntu-cpc/hooks.d/chroot/001-divert-sync.chroot_early' |
295 | === renamed file 'live-build/ubuntu-cpc/hooks/010-write-etc-ec2-version.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/010-write-etc-ec2-version.chroot' |
296 | === renamed file 'live-build/ubuntu-cpc/hooks/020-pkg-configure.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/020-pkg-configure.chroot' |
297 | === renamed file 'live-build/ubuntu-cpc/hooks/025-create-groups.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/025-create-groups.chroot' |
298 | === renamed file 'live-build/ubuntu-cpc/hooks/052-ssh_authentication.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/052-ssh_authentication.chroot' |
299 | === renamed file 'live-build/ubuntu-cpc/hooks/060-ipv6.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/060-ipv6.chroot' |
300 | === renamed file 'live-build/ubuntu-cpc/hooks/061-open-iscsi.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/061-open-iscsi.chroot' |
301 | === renamed file 'live-build/ubuntu-cpc/hooks/099-cleanup.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/099-cleanup.chroot' |
302 | === renamed file 'live-build/ubuntu-cpc/hooks/999-cpc-fixes.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/999-cpc-fixes.chroot' |
303 | === renamed file 'live-build/ubuntu-cpc/hooks/999-undivert-sync.chroot' => 'live-build/ubuntu-cpc/hooks.d/chroot/999-undivert-sync.chroot' |
304 | === added file 'live-build/ubuntu-cpc/hooks.d/make-hooks' |
305 | --- live-build/ubuntu-cpc/hooks.d/make-hooks 1970-01-01 00:00:00 +0000 |
306 | +++ live-build/ubuntu-cpc/hooks.d/make-hooks 2018-12-10 08:29:28 +0000 |
307 | @@ -0,0 +1,237 @@ |
308 | +#!/usr/bin/env python3 |
309 | +#-*- encoding: utf-8 -*- |
310 | +""" |
311 | +This script parses a series file and its dependencies and generates a hooks |
312 | +folder containing symbolic links to the scripts that need to be invoked for |
313 | +a given image target set. |
314 | + |
315 | +For example, if you wish to build the image target sets "vmdk" and "vagrant", |
316 | +you would call this script as |
317 | + |
318 | +./make-hooks --hooks-dir hooks vmdk vagrant |
319 | + |
320 | +Scripts live in subfolders below the "hooks.d" folder. Currently the folders |
321 | +"chroot" and "base" exist. The folder with the name "extra" is reserved for |
322 | +private scripts, which are not included in the source of livecd-rootfs. The |
323 | +scripts are not numbered, instead the order of their execution depends on the |
324 | +order in which they are listed in a series file. |
325 | + |
326 | +Series files are placed into the subfolders "base/series" or "extra/series". |
327 | +Each series file contains a list of scripts to be executed. Empty lines and |
328 | +lines starting with a '#' are ignored. Series files in "extra/series" override |
329 | +files in "base/series" with the same name. For example, if a series file |
330 | +"base/series/cloudA" exists and a series file "extra/series/cloudA", then the |
331 | +latter will be preferred. |
332 | + |
333 | +A series file in "extra/series" may also list scripts that are located in the |
334 | +"chroot" and "base" folders. In addition, series files can depend on other |
335 | +series files. For example, the series files for most custom images look similar |
336 | +to this: |
337 | + |
338 | + depends disk-image |
339 | + depends extra-settings |
340 | + extra/cloudB.binary |
341 | + |
342 | +Where "disk-image" and "extra-settings" may list scripts and dependencies which |
343 | +are to be processed before the script "extra/cloudB.binary" is called. |
344 | + |
345 | +ACHTUNG: live build runs scripts with the suffix ".chroot" in a batch separate |
346 | +from scripts ending in ".binary". Even if you arrange them interleaved in your |
347 | +series files, the chroot scripts will be run before the binary scripts. |
348 | +""" |
349 | + |
350 | +import argparse |
351 | +import os |
352 | +import re |
353 | +import shutil |
354 | +import sys |
355 | +import yaml |
356 | + |
357 | +SCRIPT_DIR = os.path.normpath(os.path.dirname(os.path.realpath(sys.argv[0]))) |
358 | +HOOKS_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..", "hooks")) |
359 | + |
360 | +EXIT_OK = 0 |
361 | +EXIT_ERR = 1 |
362 | + |
363 | +class MakeHooksError(Exception): |
364 | + pass |
365 | + |
366 | +class MakeHooks: |
367 | + """This class provides series file parsing and symlink generator |
368 | + functionality.""" |
369 | + |
370 | + def __init__(self, hooks_dir=None, quiet=False): |
371 | + """The hooks_dir parameter can be used to specify the path to the |
372 | + directory, into which the hook symlinks to the actual script files |
373 | + should be placed. |
374 | + |
375 | + If quiet is set to True, info messages during symlink creation will |
376 | + be suppressed. Use this if your build is not private, but you would |
377 | + like to hide which scripts are being run. |
378 | + """ |
379 | + self._script_dir = SCRIPT_DIR |
380 | + self._hooks_dir = hooks_dir or HOOKS_DIR |
381 | + self._quiet = quiet |
382 | + self._hooks_list = [] |
383 | + self._included = set() |
384 | + |
385 | + def reset(self): |
386 | + """Reset the internal state allowing instance to be reused for |
387 | + another run.""" |
388 | + self._hooks_list.clear() |
389 | + self._included.clear() |
390 | + |
391 | + def print_usage(self): |
392 | + print( |
393 | + "CPC live build hook generator script \n" |
394 | + " \n" |
395 | + "Usage: ./make-hooks.sh [OPTIONS] <image_set> \n" |
396 | + " \n" |
397 | + "Options: \n" |
398 | + " \n" |
399 | + " --help, -h Show this message and exit. \n" |
400 | + " --quiet, -q Only show warnings and error messages. \n" |
401 | + " --hooks-dir, -d <dir> The directory where to write the symlinks.\n" |
402 | + ) |
403 | + |
404 | + def find_series_file(self, image_set): |
405 | + """Search for the series file requested in the image_set parameter. |
406 | + |
407 | + The image_set parameter should be a string containing the name of an |
408 | + image target set represented by a series file. First the "extra/series" |
409 | + folder is searched followed by the "base/series" folder. |
410 | + |
411 | + When a file with the given name is found, the search stops and the |
412 | + full path to the file is returned. |
413 | + """ |
414 | + for subdir in ["extra", "base"]: |
415 | + series_file = os.path.join(self._script_dir, subdir, "series", |
416 | + image_set) |
417 | + if os.path.isfile(series_file): |
418 | + return series_file |
419 | + return None |
420 | + |
421 | + def make_hooks(self, image_sets): |
422 | + """Entry point for parsing series files and their dependencies and |
423 | + for generating the symlinks in the hooks folder. |
424 | + |
425 | + The image_sets parameter must be an iterable containing the names of |
426 | + the series files representing the corresponding image target sets, |
427 | + e.g. "vmdk" or "vagrant". |
428 | + """ |
429 | + self.collect_chroot_hooks() |
430 | + self.collect_binary_hooks(image_sets) |
431 | + self.create_symlinks() |
432 | + |
433 | + def collect_chroot_hooks(self): |
434 | + """Chroot hooks are numbered and not explicitly mentioned in series |
435 | + files. Collect them, sort them and add them to the internal list of |
436 | + paths to hook sripts. |
437 | + """ |
438 | + chroot_hooks_dir = os.path.join(self._script_dir, "chroot") |
439 | + |
440 | + chroot_entries = os.listdir(chroot_hooks_dir) |
441 | + chroot_entries.sort() |
442 | + |
443 | + for entry in chroot_entries: |
444 | + if not (entry.endswith(".chroot_early") or |
445 | + entry.endswith(".chroot")): |
446 | + continue |
447 | + self._hooks_list.append(os.path.join("chroot", entry)) |
448 | + |
449 | + def collect_binary_hooks(self, image_sets): |
450 | + """Search the series files for the given image_sets and parse them |
451 | + and their dependencies to generate a list of hook scripts to be run |
452 | + during image build. |
453 | + |
454 | + The image_sets parameter must be an iterable containing the names of |
455 | + the series files representing the corresponding image target sets, |
456 | + e.g. "vmdk" or "vagrant". |
457 | + |
458 | + Populates the internal list of paths to hook scripts in the order in |
459 | + which the scripts are to be run. |
460 | + """ |
461 | + for image_set in image_sets: |
462 | + series_file = self.find_series_file(image_set) |
463 | + |
464 | + if not series_file: |
465 | + raise MakeHooksError( |
466 | + "Series file for image set '%s' not found." % image_set) |
467 | + |
468 | + with open(series_file, "r", encoding="utf-8") as fp: |
469 | + for line in fp: |
470 | + line = line.strip() |
471 | + if not line: |
472 | + continue |
473 | + m = re.match(r"^\s*depends\s+(\S+.*)$", line) |
474 | + if m: |
475 | + include_set = m.group(1) |
476 | + if include_set in self._included: |
477 | + continue |
478 | + self._included.add(include_set) |
479 | + self.collect_binary_hooks([include_set,]) |
480 | + continue |
481 | + if not line in self._hooks_list: |
482 | + self._hooks_list.append(line) |
483 | + |
484 | + def create_symlinks(self): |
485 | + """Once the internal list of hooks scripts has been populated by a |
486 | + call to collect_?_hooks, this method is used to populate the hooks |
487 | + folder with enumerated symbolic links to the hooks scripts. If the |
488 | + folder does not exist, it will be created. If it exists, it must be |
489 | + empty or a MakeHooksError will be thrown. |
490 | + """ |
491 | + if os.path.isdir(self._hooks_dir) and os.listdir(self._hooks_dir): |
492 | + # Only print a warning, because directory might have been created |
493 | + # by auto/config voodoo. |
494 | + sys.stderr.write("WARNING: Hooks directory exists and is not empty.\n") |
495 | + os.makedirs(self._hooks_dir, exist_ok=True) |
496 | + |
497 | + for counter, hook in enumerate(self._hooks_list, start=1): |
498 | + hook_basename = os.path.basename(hook) |
499 | + |
500 | + m = re.match(r"^\d+-(?:\d+-)?(?P<basename>.*)$", hook_basename) |
501 | + if m: |
502 | + hook_basename = m.group("basename") |
503 | + |
504 | + linkname = ("%03d-" % counter) + hook_basename |
505 | + linksrc = os.path.join(self._hooks_dir, linkname) |
506 | + linkdest = os.path.relpath(os.path.join(self._script_dir, hook), |
507 | + self._hooks_dir) |
508 | + |
509 | + if not self._quiet: |
510 | + print("[HOOK] %s => %s" % (linkname, hook)) |
511 | + os.symlink(linkdest, linksrc) |
512 | + |
513 | + def cli(self, args): |
514 | + """Command line interface to the hooks generator.""" |
515 | + parser = argparse.ArgumentParser() |
516 | + |
517 | + parser.add_argument("-q", "--quiet", dest="quiet", type=bool, |
518 | + help="Only show warnings and error messages.") |
519 | + parser.add_argument("-d", "--hooks-dir", dest="hooks_dir", type=str, |
520 | + help="The directory where to create the symlinks.") |
521 | + parser.add_argument("image_target", nargs="+", type=str, |
522 | + help="") |
523 | + |
524 | + self.reset() |
525 | + options = parser.parse_args(args) |
526 | + |
527 | + # Copy options to object attributes. |
528 | + for key, value in vars(options).items(): |
529 | + if value and hasattr(self, "_" + key): |
530 | + setattr(self, "_" + key, value) |
531 | + |
532 | + # Take remaining command line arguments, sanitize and turn into list. |
533 | + image_sets = re.sub(r";|,", " ", " ".join(options.image_target))\ |
534 | + .split() |
535 | + |
536 | + self.make_hooks(image_sets) |
537 | + |
538 | + |
539 | +if __name__ == "__main__": |
540 | + try: |
541 | + MakeHooks().cli(sys.argv[1:]) |
542 | + except MakeHooksError as e: |
543 | + sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), str(e))) |
544 | + sys.exit(EXIT_ERR) |
545 | |
546 | === removed file 'live-build/ubuntu-cpc/hooks/999-extras.binary' |
547 | --- live-build/ubuntu-cpc/hooks/999-extras.binary 2017-04-13 17:54:14 +0000 |
548 | +++ live-build/ubuntu-cpc/hooks/999-extras.binary 1970-01-01 00:00:00 +0000 |
549 | @@ -1,16 +0,0 @@ |
550 | -#!/bin/bash |
551 | -# Execute extra binary hooks. |
552 | - |
553 | -my_dir=$(dirname $(readlink -f ${0})) |
554 | -extra_d=${my_dir}/extra |
555 | - |
556 | -if [ ! -d ${my_dir}/extra ]; then |
557 | - exit 0 |
558 | -fi |
559 | - |
560 | -export IMAGE_STR="# CLOUD_IMG: This file was created/modified by the Cloud Image build process" |
561 | -export CLOUD_IMG_STR="$IMAGE_STR" |
562 | -export FS_LABEL="cloudimg-rootfs" |
563 | - |
564 | -# Cleaner execution |
565 | -/bin/run-parts --exit-on-error --regex ".*\.binary" "${extra_d}" |
Overall, I really like this. The code is well laid out, and the series concept should serve us well in the future due to its flexibility. Thanks!
(I have some inline comments on the Python script, but none of these relate to the overall behaviour of the script or this MP.)