Merge lp:~smoser/cloud-init/trunk.disable-clouddinit into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Scott Moser on 2016-03-01
Status: Merged
Merged at revision: 1171
Proposed branch: lp:~smoser/cloud-init/trunk.disable-clouddinit
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 412 lines (+232/-41)
11 files modified
packages/bddeb (+6/-5)
packages/debian/cloud-init.postinst (+17/-0)
packages/debian/cloud-init.preinst (+22/-0)
packages/debian/rules.in (+3/-1)
setup.py (+46/-31)
systemd/cloud-config.service (+1/-1)
systemd/cloud-final.service (+1/-1)
systemd/cloud-init-generator (+128/-0)
systemd/cloud-init-local.service (+1/-1)
systemd/cloud-init.service (+1/-1)
systemd/cloud-init.target (+6/-0)
To merge this branch: bzr merge lp:~smoser/cloud-init/trunk.disable-clouddinit
Reviewer Review Type Date Requested Status
Dimitri John Ledkov 2016-03-01 Pending
cloud-init commiters 2016-03-01 Pending
Review via email: mp+287580@code.launchpad.net

Commit Message

systemd: Add cloud-init generator and allow disabling of cloud-init

This adds a generator that enables cloud-init if it is not found to
be disabled. It can be disabled via either the kernel command line
(/proc/cmdline with cloud-init=disabled) or presense of
/etc/cloud/cloud-init.disabled.

Also each of the service files now Wants the cloud-init target, making
them more of a group.

To post a comment you must log in.
Scott Moser (smoser) wrote :

This still needs doc, and probably need to review the kernel command line with other parts of cloud-init consumption for consistency, but the general implementation seems to work.

Ryan Harper (raharper) wrote :

Do you expect this to run pre-systemd (precise or trusty)?

1173. By Scott Moser on 2016-03-03

consume KERNEL_CMDLINE even if set to "". explain 'container'

Scott Moser (smoser) wrote :

should still work.
The upstart jobs are still there.

1174. By Scott Moser on 2016-03-03

merge with trunk

1175. By Scott Moser on 2016-03-03

do not duplicate '-generator' in log ame

1176. By Scott Moser on 2016-03-03

generator: be more clear on where kernel cmdline came from

1177. By Scott Moser on 2016-03-03

cloud-init.target should not do anything

no wants or after or before.

1178. By Scott Moser on 2016-03-04

merge with trunk

1179. By Scott Moser on 2016-03-04

support nocheck in building.

1180. By Scott Moser on 2016-03-04

packages/bddeb: copy all files in packages/debian/

just copy all the files that are there. makes adding files easier.

1181. By Scott Moser on 2016-03-04

mention link path in generator

1182. By Scott Moser on 2016-03-04

postinst/preinst: cleanup old multi-user.target enabled files

also, actually enable the services.
now this will have them enabled in the cloud-init.target.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'packages/bddeb'
2--- packages/bddeb 2015-02-10 20:32:32 +0000
3+++ packages/bddeb 2016-03-04 05:04:21 +0000
4@@ -1,5 +1,6 @@
5 #!/usr/bin/env python3
6
7+import glob
8 import os
9 import shutil
10 import sys
11@@ -105,11 +106,11 @@
12 util.abs_join(deb_dir, 'rules'),
13 params={'python': python, 'pyver': pyver})
14
15- # Just copy the following directly
16- for base_fn in ['dirs', 'copyright', 'compat']:
17- shutil.copy(util.abs_join(find_root(),
18- 'packages', 'debian', base_fn),
19- util.abs_join(deb_dir, base_fn))
20+ # Just copy any other files directly (including .in)
21+ pdeb_d = util.abs_join(find_root(), 'packages', 'debian')
22+ for f in [os.path.join(pdeb_d, f) for f in os.listdir(pdeb_d)]:
23+ if os.path.isfile(f):
24+ shutil.copy(f, util.abs_join(deb_dir, os.path.basename(f)))
25
26
27 def main():
28
29=== added file 'packages/debian/cloud-init.postinst'
30--- packages/debian/cloud-init.postinst 1970-01-01 00:00:00 +0000
31+++ packages/debian/cloud-init.postinst 2016-03-04 05:04:21 +0000
32@@ -0,0 +1,17 @@
33+#!/bin/sh
34+set -x
35+cleanup_lp1552999() {
36+ local oldver="$1" last_bad_ver="0.7.7~bzr1178"
37+ dpkg --compare-versions "$oldver" le "$last_bad_ver" || return 0
38+ local edir="/etc/systemd/system/multi-user.target.wants"
39+ rm -f "$edir/cloud-config.service" "$edir/cloud-final.service" \
40+ "$edir/cloud-init-local.service" "$edir/cloud-init.service"
41+}
42+
43+
44+#DEBHELPER#
45+
46+if [ "$1" = "configure" ]; then
47+ oldver="$2"
48+ cleanup_lp1552999 "$oldver"
49+fi
50
51=== added file 'packages/debian/cloud-init.preinst'
52--- packages/debian/cloud-init.preinst 1970-01-01 00:00:00 +0000
53+++ packages/debian/cloud-init.preinst 2016-03-04 05:04:21 +0000
54@@ -0,0 +1,22 @@
55+#!/bin/sh
56+# vi: ts=4 expandtab
57+
58+set -x
59+cleanup_lp1552999() {
60+ local oldver="$1" last_bad_ver="0.7.7~bzr1178"
61+ dpkg --compare-versions "$oldver" le "$last_bad_ver" || return 0
62+ local hdir="/var/lib/systemd/deb-systemd-helper-enabled"
63+ hdir="$hdir/multi-user.target.wants"
64+ local edir="/etc/systemd/system/multi-user.target.wants"
65+ rm -f "$hdir/cloud-config.service" "$hdir/cloud-final.service" \
66+ "$hdir/cloud-init-local.service" "$hdir/cloud-init.service"
67+}
68+
69+
70+if [ "$1" = "upgrade" ]; then
71+ oldver="$2"
72+ cleanup_lp1552999 "$oldver"
73+fi
74+set +x
75+
76+#DEBHELPER#
77
78=== modified file 'packages/debian/rules.in'
79--- packages/debian/rules.in 2016-03-04 00:10:18 +0000
80+++ packages/debian/rules.in 2016-03-04 05:04:21 +0000
81@@ -12,8 +12,10 @@
82 install -d debian/cloud-init/etc/rsyslog.d
83 cp tools/21-cloudinit.conf debian/cloud-init/etc/rsyslog.d/21-cloudinit.conf
84
85+ifeq (,$(findstring nocheck,$(DEB_BUILD_OPTIONS)))
86 override_dh_auto_test:
87- http_proxy= make check
88+ http_proxy= make check
89+endif
90
91 override_dh_systemd_start:
92 dh_systemd_start --no-restart-on-upgrade --no-start
93
94=== modified file 'setup.py'
95--- setup.py 2015-07-21 12:06:11 +0000
96+++ setup.py 2016-03-04 05:04:21 +0000
97@@ -45,39 +45,50 @@
98 stdout = None
99 stderr = None
100 sp = subprocess.Popen(cmd, stdout=stdout,
101- stderr=stderr, stdin=None,
102- universal_newlines=True)
103+ stderr=stderr, stdin=None,
104+ universal_newlines=True)
105 (out, err) = sp.communicate()
106 ret = sp.returncode
107 if ret not in [0]:
108- raise RuntimeError("Failed running %s [rc=%s] (%s, %s)"
109- % (cmd, ret, out, err))
110+ raise RuntimeError("Failed running %s [rc=%s] (%s, %s)" %
111+ (cmd, ret, out, err))
112 return (out, err)
113
114
115-def systemd_unitdir():
116- cmd = ['pkg-config', '--variable=systemdsystemunitdir', 'systemd']
117+def pkg_config_read(library, var):
118+ fallbacks = {
119+ 'systemd': {
120+ 'systemdsystemunitdir': '/lib/systemd/system',
121+ 'systemdsystemgeneratordir': '/lib/systemd/system-generators',
122+ }
123+ }
124+ cmd = ['pkg-config', '--variable=%s' % var, library]
125 try:
126 (path, err) = tiny_p(cmd)
127 except:
128- return '/lib/systemd/system'
129+ return fallbacks[library][var]
130 return str(path).strip()
131
132+
133 INITSYS_FILES = {
134 'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
135 'sysvinit_freebsd': [f for f in glob('sysvinit/freebsd/*') if is_f(f)],
136 'sysvinit_deb': [f for f in glob('sysvinit/debian/*') if is_f(f)],
137- 'systemd': [f for f in glob('systemd/*') if is_f(f)],
138+ 'systemd': [f for f in (glob('systemd/*.service') +
139+ glob('systemd/*.target')) if is_f(f)],
140+ 'systemd.generators': [f for f in glob('systemd/*-generator') if is_f(f)],
141 'upstart': [f for f in glob('upstart/*') if is_f(f)],
142 }
143 INITSYS_ROOTS = {
144 'sysvinit': '/etc/rc.d/init.d',
145 'sysvinit_freebsd': '/usr/local/etc/rc.d',
146 'sysvinit_deb': '/etc/init.d',
147- 'systemd': systemd_unitdir(),
148+ 'systemd': pkg_config_read('systemd', 'systemdsystemunitdir'),
149+ 'systemd.generators': pkg_config_read('systemd',
150+ 'systemdsystemgeneratordir'),
151 'upstart': '/etc/init/',
152 }
153-INITSYS_TYPES = sorted(list(INITSYS_ROOTS.keys()))
154+INITSYS_TYPES = sorted([f.partition(".")[0] for f in INITSYS_ROOTS.keys()])
155
156 # Install everything in the right location and take care of Linux (default) and
157 # FreeBSD systems.
158@@ -122,9 +133,8 @@
159 user_options = install.user_options + [
160 # This will magically show up in member variable 'init_sys'
161 ('init-system=', None,
162- ('init system(s) to configure (%s) [default: None]') %
163- (", ".join(INITSYS_TYPES))
164- ),
165+ ('init system(s) to configure (%s) [default: None]' %
166+ (", ".join(INITSYS_TYPES)))),
167 ]
168
169 def initialize_options(self):
170@@ -138,7 +148,8 @@
171 self.init_system = self.init_system.split(",")
172
173 if len(self.init_system) == 0:
174- raise DistutilsArgError(("You must specify one of (%s) when"
175+ raise DistutilsArgError(
176+ ("You must specify one of (%s) when"
177 " specifying init system(s)!") % (", ".join(INITSYS_TYPES)))
178
179 bad = [f for f in self.init_system if f not in INITSYS_TYPES]
180@@ -147,8 +158,12 @@
181 "Invalid --init-system: %s" % (','.join(bad)))
182
183 for system in self.init_system:
184- self.distribution.data_files.append(
185- (INITSYS_ROOTS[system], INITSYS_FILES[system]))
186+ # add data files for anything that starts with '<system>.'
187+ datakeys = [k for k in INITSYS_ROOTS
188+ if k.partition(".")[0] == system]
189+ for k in datakeys:
190+ self.distribution.data_files.append(
191+ (INITSYS_ROOTS[k], INITSYS_FILES[k]))
192 # Force that command to reinitalize (with new file list)
193 self.distribution.reinitialize_command('install_data', True)
194
195@@ -182,18 +197,18 @@
196 requirements.append('cheetah')
197
198
199-setuptools.setup(name='cloud-init',
200- version=get_version(),
201- description='EC2 initialisation magic',
202- author='Scott Moser',
203- author_email='scott.moser@canonical.com',
204- url='http://launchpad.net/cloud-init/',
205- packages=setuptools.find_packages(exclude=['tests']),
206- scripts=['bin/cloud-init',
207- 'tools/cloud-init-per',
208- ],
209- license='GPLv3',
210- data_files=data_files,
211- install_requires=requirements,
212- cmdclass=cmdclass,
213- )
214+setuptools.setup(
215+ name='cloud-init',
216+ version=get_version(),
217+ description='EC2 initialisation magic',
218+ author='Scott Moser',
219+ author_email='scott.moser@canonical.com',
220+ url='http://launchpad.net/cloud-init/',
221+ packages=setuptools.find_packages(exclude=['tests']),
222+ scripts=['bin/cloud-init',
223+ 'tools/cloud-init-per'],
224+ license='GPLv3',
225+ data_files=data_files,
226+ install_requires=requirements,
227+ cmdclass=cmdclass,
228+ )
229
230=== modified file 'systemd/cloud-config.service'
231--- systemd/cloud-config.service 2015-04-09 15:54:01 +0000
232+++ systemd/cloud-config.service 2016-03-04 05:04:21 +0000
233@@ -13,4 +13,4 @@
234 StandardOutput=journal+console
235
236 [Install]
237-WantedBy=multi-user.target
238+WantedBy=cloud-init.target
239
240=== modified file 'systemd/cloud-final.service'
241--- systemd/cloud-final.service 2015-11-30 20:33:28 +0000
242+++ systemd/cloud-final.service 2016-03-04 05:04:21 +0000
243@@ -14,4 +14,4 @@
244 StandardOutput=journal+console
245
246 [Install]
247-WantedBy=multi-user.target
248+WantedBy=cloud-init.target
249
250=== added file 'systemd/cloud-init-generator'
251--- systemd/cloud-init-generator 1970-01-01 00:00:00 +0000
252+++ systemd/cloud-init-generator 2016-03-04 05:04:21 +0000
253@@ -0,0 +1,128 @@
254+#!/bin/sh
255+set -f
256+
257+LOG=""
258+DEBUG_LEVEL=1
259+LOG_D="/run"
260+ENABLE="enabled"
261+DISABLE="disabled"
262+CLOUD_SYSTEM_TARGET="/lib/systemd/system/cloud-init.target"
263+CLOUD_TARGET_NAME="cloud-init.target"
264+# lxc sets 'container', but lets make that explicitly a global
265+CONTAINER="${container}"
266+
267+debug() {
268+ local lvl="$1"
269+ shift
270+ [ "$lvl" -gt "$DEBUG_LEVEL" ] && return
271+ if [ -z "$LOG" ]; then
272+ local log="$LOG_D/${0##*/}.log"
273+ { : > "$log"; } >/dev/null 2>&1 && LOG="$log" ||
274+ LOG="/dev/kmsg"
275+ fi
276+ echo "$@" >> "$LOG"
277+}
278+
279+etc_file() {
280+ local pprefix="${1:-/etc/cloud/cloud-init.}"
281+ _RET="unset"
282+ [ -f "${pprefix}$ENABLE" ] && _RET="$ENABLE" && return 0
283+ [ -f "${pprefix}$DISABLE" ] && _RET="$DISABLE" && return 0
284+ return 0
285+}
286+
287+read_proc_cmdline() {
288+ if [ "$CONTAINER" = "lxc" ]; then
289+ _RET_MSG="ignored: \$container=$CONTAINER"
290+ _RET=""
291+ return 0
292+ fi
293+
294+ if systemd-detect-virt --container --quiet; then
295+ _RET_MSG="ignored: detect-virt is container"
296+ _RET=""
297+ return 0
298+ fi
299+
300+ _RET_MSG="/proc/cmdline"
301+ read _RET < /proc/cmdline
302+}
303+
304+kernel_cmdline() {
305+ local cmdline="" tok=""
306+ if [ -n "${KERNEL_CMDLINE+x}" ]; then
307+ # use KERNEL_CMDLINE if present in environment even if empty
308+ cmdline=${KERNEL_CMDLINE}
309+ debug 1 "kernel command line from env KERNEL_CMDLINE: $cmdline"
310+ elif read_proc_cmdline; then
311+ read_proc_cmdline && cmdline="$_RET"
312+ debug 1 "kernel command line ($_RET_MSG): $cmdline"
313+ fi
314+ _RET="unset"
315+ cmdline=" $cmdline "
316+ tok=${cmdline##* cloud-init=}
317+ [ "$tok" = "$cmdline" ] && _RET="unset"
318+ tok=${tok%% *}
319+ [ "$tok" = "$ENABLE" -o "$tok" = "$DISABLE" ] && _RET="$tok"
320+ return 0
321+}
322+
323+default() {
324+ _RET="$ENABLE"
325+}
326+
327+main() {
328+ local normal_d="$1" early_d="$2" late_d="$3"
329+ local target_name="multi-user.target" gen_d="$early_d"
330+ local link_path="$gen_d/${target_name}.wants/${CLOUD_TARGET_NAME}"
331+
332+ debug 1 "$0 normal=$normal_d early=$early_d late=$late_d"
333+ debug 2 "$0 $*"
334+
335+ local search result="error" ret=""
336+ for search in kernel_cmdline etc_file default; do
337+ if $search; then
338+ debug 1 "$search found $_RET"
339+ [ "$_RET" = "$ENABLE" -o "$_RET" = "$DISABLE" ] &&
340+ result=$_RET && break
341+ else
342+ ret=$?
343+ debug 0 "search $search returned $ret"
344+ fi
345+ done
346+
347+ if [ "$result" = "$ENABLE" ]; then
348+ if [ -e "$link_path" ]; then
349+ debug 1 "already enabled: no change needed"
350+ else
351+ [ -d "${link_path%/*}" ] || mkdir -p "${link_path%/*}" ||
352+ debug 0 "failed to make dir $link_path"
353+ if ln -snf "$CLOUD_SYSTEM_TARGET" "$link_path"; then
354+ debug 1 "enabled via $link_path -> $CLOUD_SYSTEM_TARGET"
355+ else
356+ ret=$?
357+ debug 0 "[$ret] enable failed:" \
358+ "ln $CLOUD_SYSTEM_TARGET $link_path"
359+ fi
360+ fi
361+ elif [ "$result" = "$DISABLE" ]; then
362+ if [ -f "$link_path" ]; then
363+ if rm -f "$link_path"; then
364+ debug 1 "disabled. removed existing $link_path"
365+ else
366+ ret=$?
367+ debug 0 "[$ret] disable failed, remove $link_path"
368+ fi
369+ else
370+ debug 1 "already disabled: no change needed [no $link_path]"
371+ fi
372+ else
373+ debug 0 "unexpected result '$result'"
374+ ret=3
375+ fi
376+ return $ret
377+}
378+
379+main "$@"
380+
381+# vi: ts=4 expandtab
382
383=== modified file 'systemd/cloud-init-local.service'
384--- systemd/cloud-init-local.service 2013-09-20 23:04:49 +0000
385+++ systemd/cloud-init-local.service 2016-03-04 05:04:21 +0000
386@@ -13,4 +13,4 @@
387 StandardOutput=journal+console
388
389 [Install]
390-WantedBy=multi-user.target
391+WantedBy=cloud-init.target
392
393=== modified file 'systemd/cloud-init.service'
394--- systemd/cloud-init.service 2015-04-09 15:54:01 +0000
395+++ systemd/cloud-init.service 2016-03-04 05:04:21 +0000
396@@ -15,4 +15,4 @@
397 StandardOutput=journal+console
398
399 [Install]
400-WantedBy=multi-user.target
401+WantedBy=cloud-init.target
402
403=== added file 'systemd/cloud-init.target'
404--- systemd/cloud-init.target 1970-01-01 00:00:00 +0000
405+++ systemd/cloud-init.target 2016-03-04 05:04:21 +0000
406@@ -0,0 +1,6 @@
407+# cloud-init target is enabled by cloud-init-generator
408+# To disable it you can either:
409+# a.) boot with kernel cmdline of 'cloudinit=disabled'
410+# b.) touch a file /etc/cloud/cloud-init.disabled
411+[Unit]
412+Description=Cloud-init target