Merge lp:~smoser/curtin/trunk.install-deps into lp:~curtin-dev/curtin/trunk

Proposed by Scott Moser
Status: Work in progress
Proposed branch: lp:~smoser/curtin/trunk.install-deps
Merge into: lp:~curtin-dev/curtin/trunk
Diff against target: 233 lines (+206/-1)
3 files modified
curtin/commands/main.py (+7/-1)
doc/devel/README-vmtest.txt (+16/-0)
tools/install-curtin-deps (+183/-0)
To merge this branch: bzr merge lp:~smoser/curtin/trunk.install-deps
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
curtin developers Pending
Review via email: mp+280053@code.launchpad.net

Commit message

document patching images with curtin depends and provide tool

official vmtest should run with images as close to maas images as possible.
Thus, this should not be used for official tests.

However, developer use can patch the images that are used for boot, and
can dramatically decrease install time by installing curtin dependencies.

Example real world improvement even with a local proxy these are the install boot times before and after:
  PreciseTestBasic 66.22 37.79
  TrustyTestBasic 66.74 45.41
  VividTestAllindata 142.34 114.37
  VividTestBasic 76.89 50.03
  VividTestBonding 61.81 36.52
  VividTestLvm 73.47 48.32
  WilyTestBasic 78.65 53.53
  WilyTestBonding 64.48 38.70
  WilyTestLvm 87.24 51.62

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ryan Harper (raharper) wrote :

Some nits in comments

lp:~smoser/curtin/trunk.install-deps updated
322. By Scott Moser

fix english

323. By Scott Moser

fix usage

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~smoser/curtin/trunk.install-deps updated
324. By Scott Moser

fix pep8

325. By Scott Moser

remove copied / bad code

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

Ryan,
 with regard to knowing / determining if this has already been patched before, i dont really know. I just added it as a quick way for developer to improve test speed.

One thign we could potentially do is create the modified image as a .qcow referencing the original.
then something like:
   CURTIN_VMTEST_PATCH_IMAGE=1 make vmtests
could look for a 'root-image.patched.img' file and use it. Then the original would be un-modified, and easily select between the two. the sync image woudl also be made to create the patched image if not present.

The above doesn't grow well if there are multiple different ways you can patch an image, though.

but i do like the qcow backed delta file. performance coudl potentially suffer some, but not likely much.

Revision history for this message
Scott Moser (smoser) wrote :

Now that we have the improved syncing, and our mirror creates and knows about vmtest.root-image and vmtest.root-tgz, we could also make it create 'vmtest.root-image-prepped'.

We can make the creation of and use of that 'vmtest.root-iamge.prepped' to be done only if VMTEST_USE_PREPPED_IMAGES=1

The result would be that someone can use that for faster development and then run vmtest without it to get more 'official'.

Unmerged revisions

325. By Scott Moser

remove copied / bad code

324. By Scott Moser

fix pep8

323. By Scott Moser

fix usage

322. By Scott Moser

fix english

321. By Scott Moser

document patching images with curtin depends and provide tool

official vmtest should run with images as close to maas images as possible.
Thus, this should not be used for official tests.

However, developer use can patch the images that are used for boot, and
can dramatically decrease install time by installing curtin dependencies.

Example real world improvement even with a local proxy:
  # test before after
  PreciseTestBasic 66.22 37.79
  TrustyTestBasic 66.74 45.41
  VividTestAllindata 142.34 114.37
  VividTestBasic 76.89 50.03
  VividTestBonding 61.81 36.52
  VividTestLvm 73.47 48.32
  WilyTestBasic 78.65 53.53
  WilyTestBonding 64.48 38.70
  WilyTestLvm 87.24 51.62

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'curtin/commands/main.py'
2--- curtin/commands/main.py 2015-11-18 21:29:57 +0000
3+++ curtin/commands/main.py 2015-12-09 18:02:39 +0000
4@@ -109,7 +109,13 @@
5 # bad usage will be reported by the real reporter
6 return
7
8- ret = install_deps(verbosity=verbosity)
9+ # This is less than perfect, it is here for patching a root image
10+ # with 'curtin --install-deps'. Better would be to provide
11+ # 'curtin install-deps' with --no-allow-daemons and then use that.
12+ val = os.environ.get("CURTIN_INSTALL_DEPS_DAEMONS", "1")
13+ allow_daemons = val.strip().lower() not in ("0", "false")
14+
15+ ret = install_deps(verbosity=verbosity, allow_daemons=allow_daemons)
16
17 if ret != 0 or install_only:
18 sys.exit(ret)
19
20=== modified file 'doc/devel/README-vmtest.txt'
21--- doc/devel/README-vmtest.txt 2015-12-01 01:27:21 +0000
22+++ doc/devel/README-vmtest.txt 2015-12-09 18:02:39 +0000
23@@ -94,6 +94,22 @@
24 'apt_proxy' environment variable. If that is not set it will
25 look at the host's apt config and read 'Acquire::HTTP::Proxy'
26
27+== Patching root image with deps for faster install ==
28+IMAGES_DIR defines the directory where the stream mirror exists.
29+the tool install-curtin-deps can patch these so each install does not have
30+to do that work.
31+The root images are read from IMAGES_DIR which defaults to /srv/images.
32+
33+ IMAGE_DIR=/srv/images
34+ for img in $(find "${IMAGE_DIR" -type f -name "root-image"); do
35+ echo "working on $img"
36+ if [ '!' -f "$img.dist" ]; then
37+ cp --sparse=always "$img" "$img.dist.tmp" &&
38+ mv "$img.dist.tmp" "$img.dist" || break;
39+ fi
40+ ./tools/install-curtin-deps "$img" || break;
41+ done
42+
43 == Environment Variables ==
44 Some environment variables affect the running of vmtest
45 * apt_proxy:
46
47=== added file 'tools/install-curtin-deps'
48--- tools/install-curtin-deps 1970-01-01 00:00:00 +0000
49+++ tools/install-curtin-deps 2015-12-09 18:02:39 +0000
50@@ -0,0 +1,183 @@
51+#!/bin/bash
52+
53+VERBOSITY=0
54+TEMP_D=""
55+WORKING_D=""
56+
57+error() { echo "$@" 1>&2; }
58+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
59+
60+Usage() {
61+ cat <<EOF
62+Usage: ${0##*/} target
63+
64+Install curtin dependencies into target. Target can be a path to a root
65+filesystem (/your/mounted/root) or a filesystem image (.img).
66+
67+options:
68+ -v | --verbose increase verbosity
69+EOF
70+}
71+
72+bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; }
73+cleanup() {
74+ [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
75+ [ -z "$WORKING_D" -o ! -d "$WORKING_D" ] || rm -Rf "$WORKING_D"
76+}
77+
78+debug() {
79+ local level=${1}; shift;
80+ [ "${level}" -gt "${VERBOSITY}" ] && return
81+ error "${@}"
82+}
83+
84+hascmd() {
85+ local cmd="$1" envref="$2" t=""
86+ shift 2
87+ if [ -n "${envref}" -a -n "${!envref}" ]; then
88+ cmd="${!envref}"
89+ _RET="$cmd"
90+ return 0
91+ elif [ -x "$cmd" -a -f "$x" ]; then
92+ t=$(readlink -f "$cmd") ||
93+ { error "failed to get full path to $cmd"; return 1; }
94+ _RET="$t"
95+ return
96+ elif t=$(which "$cmd" 2>/dev/null); then
97+ _RET="$t"
98+ return
99+ else
100+ for t in "$@"; do
101+ [ -x "$t" -a -f "$t" ] && t=$(readlink -f "$t") &&
102+ _RET="$t" && return
103+ done
104+ fi
105+ return 1
106+}
107+
108+find_apt_proxy() {
109+ # pick an apt proxy for the guest
110+ local out=""
111+
112+ # if user set uncommon 'apt_proxy', then trust it
113+ [ -n "$apt_proxy" ] && echo "$apt_proxy" && return 0
114+
115+ # see if the host has an apt proxy configured, and use it
116+ if command -v apt-config >/dev/null 2>&1; then
117+ out=$(apt-config shell x Acquire::HTTP::Proxy) &&
118+ out=$(sh -c 'eval $1 && echo $x' -- "$out") && [ -n "$out" ] &&
119+ echo "$out" && return
120+ fi
121+
122+ return 1
123+}
124+
125+main() {
126+ local short_opts="hv"
127+ local long_opts="help,verbose"
128+ local getopt_out=""
129+ getopt_out=$(getopt --name "${0##*/}" \
130+ --options "${short_opts}" --long "${long_opts}" -- "$@") &&
131+ eval set -- "${getopt_out}" ||
132+ { bad_Usage; return; }
133+
134+ local cur="" next="" curtin=""
135+ local sudo="" target_in="" proxy=""
136+
137+ while [ $# -ne 0 ]; do
138+ cur="$1"; next="$2";
139+ case "$cur" in
140+ -h|--help) Usage ; exit 0;;
141+ -v|--verbose) VERBOSITY=$((${VERBOSITY}+1)); vflags="${vflags}v";;
142+ --) shift; break;;
143+ esac
144+ shift;
145+ done
146+
147+ [ $# -eq 1 ] ||
148+ { bad_Usage "got $# args ($*). Expected only 1"; return 1; }
149+ target_in="$1"
150+ [ -f "$target_in" -o -d "$target_in" ] ||
151+ { bad_Usage "$target_in: not a file or directory"; return; }
152+ target=$(readlink -f "$target_in") ||
153+ { error "failed to get full path to $target_in"; return 1; }
154+
155+ trap cleanup EXIT
156+
157+ [ "$(id -u)" = "0" ] && sudo="" || sudo="sudo"
158+ [ -z "$vflags" ] || vflags="-${vflags}"
159+
160+ hascmd curtin CURTIN ${0%/*}/../bin/curtin ./bin/curtin &&
161+ curtin="$_RET" || {
162+ error "no curtin in path";
163+ return 1;
164+ }
165+ if [ -d "$target" ]; then
166+ debug 1 "using curtin=$curtin"
167+ install_deps "$target" "$curtin"
168+ else
169+ local micb=""
170+ hascmd mount-image-callback MOUNT_IMAGE_CALLBACK && micb="$_RET" || {
171+ error "no mount-image-callback. install cloud-image-utils.";
172+ return 1;
173+ }
174+
175+ $sudo ${apt_proxy:+apt_proxy="$apt_proxy"} \
176+ $micb --system-resolvconf --proc "$target" -- \
177+ "$0" ${vflags} _MOUNTPOINT_ || {
178+ error "failed to apply to target"
179+ return 1
180+ }
181+ fi
182+
183+}
184+
185+install_deps() {
186+ local rootd="$1" curtin="$2" wdir=""
187+ [ -d "$rootd/tmp" ] || { error "$rootd does not have /tmp"; return 1; }
188+ debug 2 "installing into $rootd with $curtin"
189+ local t chroot="chroot" ret=""
190+ t=$(readlink -f "$rootd") ||
191+ { error "failed getting full path to $rootd"; return 1; }
192+ rootd="$t"
193+ if [ "$rootd" = "/" ]; then
194+ chroot=""
195+ fi
196+
197+ local proxy=""
198+ proxy=$(find_apt_proxy) && [ -n "$proxy" ] &&
199+ export http_proxy="$proxy" &&
200+ debug 1 "using apt proxy=$proxy"
201+
202+ exed=$(mktemp -d "$rootd/tmp/${0##*/}.XXXXXX") ||
203+ { error "failed to get tmpdir in ${rootd}/tmp"; return 1; }
204+ WORKING_D="$exed"
205+ # wdir is the path inside the chroot. exed is the path from outside.
206+ wdir="${exed#${rootd%/}}"
207+
208+ $curtin pack -- curtin --install-deps > "$exed/packed" || {
209+ error "failed to curtin pack: $curtin pack -- curtin --install-deps";
210+ return 1;
211+ }
212+ chmod 755 "$exed/packed" ||
213+ { error "failed to give exe to $exed/packed"; return 1; }
214+
215+ local fix_update_initramfs=false uix="$rootd/usr/sbin/update-initramfs"
216+ if [ -x "$uix" ]; then
217+ mv "$uix" "$uix.dist" && fix_update_initramfs=true
218+ ln -sf /bin/true "$uix" || { mv "$uix.dist" "$uix" && return 1; }
219+ fi
220+ CURTIN_INSTALL_DEPS_DAEMONS=false LANG=C $chroot "$rootd" \
221+ "$wdir/packed" "--prefix=$wdir/x"
222+ ret=$?
223+ [ $ret -eq 0 ] || error "failed to run pack inside $rootd";
224+ if $fix_update_initramfs; then
225+ rm -f "$uix"
226+ mv "$uix.dist" "$uix"
227+ fi
228+ return $ret
229+}
230+
231+
232+main "$@"
233+# vi: ts=4 expandtab

Subscribers

People subscribed via source and target branches