Merge lp:~tobijk/livecd-rootfs/image-sets into lp:livecd-rootfs

Proposed by Tobias Koch
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
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

    https://bazaar.launchpad.net/~tobijk/livecd-rootfs/image-sets/view/head:/live-build/ubuntu-cpc/README.cpc.md

In order to try out the hook generation, change to

    live-build/ubuntu-cpc/hooks.d

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.

To post a comment you must log in.
Revision history for this message
Dan Watkins (oddbloke) wrote :

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.)

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
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

review: Needs Fixing
Revision history for this message
Tobias Koch (tobijk) wrote :

Thank you @philroche, let me know if this works or if anything needs further clarification.

Revision history for this message
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_authentication.chroot => chroot/ssh_authentication.chroot
...
[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_authentication.chroot

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.

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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.yaml.

I also updated

https://code.launchpad.net/~cloudware/livecd-rootfs/+git/cpc_packaging.extra/+merge/356266

to match these changes.

@daniel-thewatkins, @philroche, I believe I have addressed your concerns, as well. Please have another look.

Revision history for this message
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.

review: Approve
Revision history for this message
Dan Watkins (oddbloke) wrote :

Thanks!

review: Approve
Revision history for this message
Philip Roche (philroche) wrote :

Happy to go merge with the two current approvals

review: Abstain
Revision history for this message
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.

review: Needs Fixing
Revision history for this message
Tobias Koch (tobijk) wrote :

Also revamped this taking into account @xnox's comments on

https://code.launchpad.net/~tobijk/livecd-rootfs/snap-coherence/+merge/358632

Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
Tobias Koch (tobijk) wrote :

So is that a veto? Subsystem maintainers are +1.

Revision history for this message
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.

review: Needs Fixing
Revision history for this message
Tobias Koch (tobijk) wrote :

@vorlon, I have made the necessary changes. Please check, if you are ok with this. Thanks!

Revision history for this message
Steve Langasek (vorlon) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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}"

Subscribers

People subscribed via source and target branches