Merge lp:~racb/maas/multi-soc-ephemerals into lp:maas/trunk

Proposed by Robie Basak on 2012-11-16
Status: Merged
Approved by: Robie Basak on 2012-12-04
Approved revision: 1358
Merged at revision: 1394
Proposed branch: lp:~racb/maas/multi-soc-ephemerals
Merge into: lp:maas/trunk
Diff against target: 98 lines (+47/-13)
1 file modified
scripts/maas-import-ephemerals (+47/-13)
To merge this branch: bzr merge lp:~racb/maas/multi-soc-ephemerals
Reviewer Review Type Date Requested Status
Gavin Panella (community) 2012-11-16 Approve on 2012-11-19
Scott Moser 2012-11-16 Pending
Review via email: mp+134715@code.launchpad.net

Commit Message

Add multi-SoC support to ephemeral image import

If ephemeral image tarballs contain a subarch/ directory, then import the
linux and initrd.gz files for each subarch as TFTP commissioning images into
MAAS.

If subarch/ does not exist, behave exactly the same as before.

This allows armhf SoCs that require different kernels to all be supported
by a single armhf ephemeral image with multiple kernels installed within it.

Description of the Change

I'd like this to end up in a Precise SRU, so that we can enable other ARM server systems based on non-highbank SoCs as they become available.

There are no flag days. We can generate ephemeral images with subarch/ directories whenever we need. When a MAAS installation uses the updated import script and the ephemeral image has a subarch/ directory, it'll all just start working.

To post a comment you must log in.
Robie Basak (racb) wrote :

Example of subarch ephemeral image entries:

quantal-ephemeral-maas-armhf-initrd
quantal-ephemeral-maas-armhf-vmlinuz
quantal-ephemeral-maas-armhf.img
subarch/
subarch/armadaxp/
subarch/armadaxp/initrd.gz
subarch/armadaxp/linux
subarch/highbank/
subarch/highbank/initrd.gz
subarch/highbank/linux

I went with initrd.gz as this is what seems to be used internally within maas-import-ephemerals. However, note that the expectation of a file ending in ".gz" is that gunzip will work on it, but in the case of armadaxp, there is an extra "uInitrd" wrapper (created by u-boot's mkimage) that breaks this expectation. Using "initrd" instead of "initrd.gz" universally would be better, but it is possibly not practical to make this change everywhere now.

The alternative would be to ship it as uInitrd and uImage inside subarch/armadaxp and have maas-import-ephemerals rename it as needed.

Gavin Panella (allenap) wrote :

Thanks for doing this Robie. However, it's untested, and shell script. I'm very reluctant to +1 any more shell script into production parts of MAAS, tested or not, but without tests it's got no hope. Can you move this logic into Python - or just about anything other than shell script - such that it can also be tested without having to drive pencils into our temples?

review: Needs Fixing
Scott Moser (smoser) wrote :

some things:
 * use more quotes. example 'cp $src/subarch/$subarch/initrd.gz' needs to be quoted to avoid shell expansion (space in 'src' for example).
 * generally i think that $(subcmd) is used here rather than `subcmd`. just try to keep consistent.
 * uniq_major_arches uses global 'arch' destroying its contents. needs to declare 'local' for arch.
 * subarches needs 'local' on variables.
 * 'mv' on line 40 can be made (i think) to avoid the race condition of "check then move".
   see '--target-directory' and '--no-target-directory'

generally looks reasonable and most of hte above are nitpick. and i'm not opposed to writing these things in python.

Gavin Panella (allenap) wrote :

Despite the dread I feel, I'll +1 this because we don't have the means
right now to refactor with confidence, nor do we have the time to go
through indeterminable QA iterations after a rewrite (it might be fine
on the first go, but we can't have much confidence in that).

I assume this will be well exercised before it gets SRU'd?

[1]

+    for arch in "$@"; do echo $arch; done|cut -f1 -d/|uniq

You could save a process here:

    for arch in "$@"; do echo "${arch%%/*}"; done | uniq

[2]

+            $major_arch/*) echo "$candidate"|cut -f2 -d/ ;;

Similar thing to [1] here:

            $major_arch/*) echo "${candidate#*/}" ;;

[3]

+    for arch in `uniq_major_arches $ARCHES`; do
...
+        for subarch in `subarches $arch $ARCHES`; do

Beware that errors from these new functions won't do anything; command
substitution hides errors. I think they're simple enough that won't
fail, but it's worth knowing for the future.

[4]

+    for arch in "$@"; do echo $arch; done|cut -f1 -d/|uniq

Fwiw, if $arch is -e, -E or -n, echo will absorb it as flag. Afaik
there's no way to avoid this, other than to use printf:

    for arch in "$@"; do printf "%s\n" $arch; done|cut -f1 -d/|uniq

Which gives me an idea of how to make this simpler:

    printf "%s\n" "$@" | uniq

review: Approve
lp:~racb/maas/multi-soc-ephemerals updated on 2012-11-23
1355. By Robie Basak on 2012-11-23

Quote all shell variables

This excludes ARCHES, as it is whitespace-separated. As a result, any
arch with a space in the name is broken anyway.

1356. By Robie Basak on 2012-11-23

Use $() instead of ``

1357. By Robie Basak on 2012-11-23

Declare local variables to avoid clobbering globals

1358. By Robie Basak on 2012-11-23

Use parameter expansions instead of cut

Robie Basak (racb) wrote :

Thanks for the reviews!

I've made all requested changes except:

Gavin> printf; as discussed, we couldn't find this use documented anywhere so I have left the echo instead.

Scott> "check then move" race; this race exists for all the other checks and moves in the script already, and I didn't want to break the existing pattern as I felt that would make the code less readable for no real gain. Multiple concurrent calls to maas-import-ephemerals are already broken anyway, so I'm not sure that we need to care about that race. I'll merge unless you object?

Julian Edwards (julian-edwards) wrote :

JFLI!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'scripts/maas-import-ephemerals'
2--- scripts/maas-import-ephemerals 2012-11-08 14:37:46 +0000
3+++ scripts/maas-import-ephemerals 2012-11-23 11:03:21 +0000
4@@ -91,6 +91,32 @@
5 }
6
7
8+uniq_major_arches() {
9+ # print on stdout a uniq set of arches out of the list of arch/subarch
10+ # pairs supplied in $@
11+ # Eg. armhf/highbank armhf/armadaxp i386/generic amd64/generic ->
12+ # "armhf\ni386\namd64\n"
13+ local arch
14+ for arch in "$@"; do echo "${arch%%/*}"; done|uniq
15+}
16+
17+
18+subarches() {
19+ # print on stdout a list of subarches available for a given major arch $1
20+ # given a list of arch/subarch pairs in $2-
21+ # Eg. armhf armhf/highbank armhf/armadaxp i386/generic ->
22+ # "highbank\narmadaxp\n"
23+ local major_arch="$1" candidate
24+ shift
25+ for candidate in "$@"; do
26+ case "$candidate" in
27+ "$major_arch"/*) echo "${candidate#*/}" ;;
28+ *) ;;
29+ esac
30+ done
31+}
32+
33+
34 query_remote() {
35 # query /query data at CLOUD_IMAGES_ARCHIVE
36 # returns 7 values prefixed with 'r_'
37@@ -238,6 +264,9 @@
38 [ -z "$initrd" ] || mv "$initrd" "$wd/initrd.gz" ||
39 { error "failed to move extracted initrd to $wd/initrd.gz"; return 1; }
40
41+ [ ! -d "$exdir/subarch" ] || mv "$exdir/subarch" "$wd/" ||
42+ { error "failed to move extracted subarch to $wd/subarch"; return 1; }
43+
44 rm -Rf "$exdir" || { error "failed to cleanup extraction dir"; return 1; }
45 { [ -z "$rmtar" ] || rm "$rmtar"; } ||
46 { error "failed to remove temporary tarball $rmtar"; return 1; }
47@@ -304,10 +333,16 @@
48 # deletes it.
49 tmpdir="$(mktemp -d)"
50
51- copy_first_available "$src/linux" "$src/kernel" "$tmpdir/linux" ||
52- return 1
53- copy_first_available "$src/initrd.gz" "$src/initrd" "$tmpdir/initrd.gz" ||
54- return 1
55+ if [ -f "$src/subarch/$subarch/linux" -a \
56+ -f "$src/subarch/$subarch/initrd.gz" ]; then
57+ cp "$src/subarch/$subarch/linux" "$tmpdir/linux" || return 1
58+ cp "$src/subarch/$subarch/initrd.gz" "$tmpdir/initrd.gz" || return 1
59+ else
60+ copy_first_available "$src/linux" "$src/kernel" "$tmpdir/linux" ||
61+ return 1
62+ copy_first_available "$src/initrd.gz" "$src/initrd" "$tmpdir/initrd.gz" ||
63+ return 1
64+ fi
65
66 local cmd out=""
67 cmd=( maas-provision install-pxe-image
68@@ -361,10 +396,7 @@
69
70 updates=0
71 for release in $RELEASES; do
72- for arch_tuple in $ARCHES; do
73- arch="${arch_tuple%%/*}"
74- subarch="${arch_tuple#*/}"
75-
76+ for arch in $(uniq_major_arches $ARCHES); do
77 query_local "$arch" "$release" "$BUILD_NAME" ||
78 fail "failed to query local for $release/$arch"
79 query_remote "$arch" "$release" "$BUILD_NAME" ||
80@@ -405,11 +437,13 @@
81 name="${l_name}"
82 fi
83
84- # Even if there was no need to update the image, we make sure it
85- # gets installed.
86- debug 1 "adding images for $release/$arch/$subarch to maas"
87- install_tftp_image "$fpfinal_d" "$arch" "$subarch" "$release" ||
88- fail "failed to install ftp image [$info]"
89+ for subarch in $(subarches "$arch" $ARCHES); do
90+ # Even if there was no need to update the image, we make sure
91+ # it gets installed.
92+ debug 1 "adding images for $release/$arch/$subarch to maas"
93+ install_tftp_image "$fpfinal_d" "$arch" "$subarch" "$release" ||
94+ fail "failed to install tftp image [$info]"
95+ done
96
97 target_name="${TARGET_NAME_PREFIX}${name}"
98 rel_tgt="../${final_d}/tgt.conf"