summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile32
-rw-r--r--cloudinit/config/cc_final_message.py6
-rw-r--r--cloudinit/config/cc_grub_dpkg.py5
-rw-r--r--cloudinit/config/cc_landscape.py12
-rw-r--r--cloudinit/helpers.py26
-rw-r--r--cloudinit/sources/DataSourceAltCloud.py2
-rw-r--r--cloudinit/sources/DataSourceAzure.py2
-rw-r--r--cloudinit/sources/DataSourceDigitalOcean.py4
-rw-r--r--cloudinit/sources/DataSourceEc2.py2
-rw-r--r--cloudinit/sources/DataSourceMAAS.py2
-rw-r--r--cloudinit/sources/DataSourceNoCloud.py4
-rw-r--r--cloudinit/sources/DataSourceNone.py4
-rw-r--r--cloudinit/sources/DataSourceOVF.py4
-rw-r--r--cloudinit/sources/DataSourceOpenNebula.py4
-rw-r--r--cloudinit/sources/DataSourceSmartOS.py2
-rw-r--r--doc/examples/cloud-config-mount-points.txt2
-rw-r--r--doc/examples/cloud-config-rsyslog.txt4
-rwxr-xr-xpackages/bddeb11
-rw-r--r--packages/debian/cloud-init.postinst16
-rw-r--r--packages/debian/cloud-init.preinst20
-rw-r--r--packages/debian/control.in3
-rwxr-xr-xpackages/debian/rules.in14
-rwxr-xr-xsetup.py77
-rw-r--r--systemd/cloud-config.service2
-rw-r--r--systemd/cloud-final.service2
-rwxr-xr-xsystemd/cloud-init-generator128
-rw-r--r--systemd/cloud-init-local.service2
-rw-r--r--systemd/cloud-init.service2
-rw-r--r--systemd/cloud-init.target6
-rw-r--r--tests/unittests/test_datasource/test_configdrive.py20
-rw-r--r--tests/unittests/test_datasource/test_opennebula.py2
-rw-r--r--tests/unittests/test_datasource/test_smartos.py4
-rw-r--r--tests/unittests/test_distros/test_user_data_normalize.py29
-rwxr-xr-xtools/validate-yaml.py2
-rw-r--r--tox.ini1
35 files changed, 328 insertions, 130 deletions
diff --git a/Makefile b/Makefile
index 0ce535ad..32c50aee 100644
--- a/Makefile
+++ b/Makefile
@@ -1,23 +1,36 @@
CWD=$(shell pwd)
-PY_FILES=$(shell find cloudinit bin tests tools -name "*.py" -type f )
-PY_FILES+="bin/cloud-init"
+PYVER ?= 3
+noseopts ?= -v
YAML_FILES=$(shell find cloudinit bin tests tools -name "*.yaml" -type f )
YAML_FILES+=$(shell find doc/examples -name "cloud-config*.txt" -type f )
CHANGELOG_VERSION=$(shell $(CWD)/tools/read-version)
CODE_VERSION=$(shell python -c "from cloudinit import version; print version.version_string()")
-noseopts ?= -vv --nologcapture
PIP_INSTALL := pip install
+ifeq ($(PYVER),3)
+ pyflakes = pyflakes3
+ unittests = unittest3
+ yaml = yaml
+else
+ifeq ($(PYVER),2)
+ pyflakes = pyflakes
+ unittests = unittest
+else
+ pyflakes = pyflakes pyflakes3
+ unittests = unittest unittest3
+endif
+endif
+
ifeq ($(distro),)
distro = redhat
endif
all: check
-check: check_version pep8 pyflakes pyflakes3 test
+check: check_version pep8 $(pyflakes) test $(yaml)
pep8:
@$(CWD)/tools/run-pep8
@@ -30,6 +43,8 @@ pyflakes3:
unittest: clean_pyc
nosetests $(noseopts) tests/unittests
+
+unittest3: clean_pyc
nosetests3 $(noseopts) tests/unittests
pip-requirements:
@@ -40,7 +55,7 @@ pip-test-requirements:
@echo "Installing cloud-init test dependencies..."
$(PIP_INSTALL) -r "$@.txt" -q
-test: unittest
+test: $(unittests)
check_version:
@if [ "$(CHANGELOG_VERSION)" != "$(CODE_VERSION)" ]; then \
@@ -51,9 +66,6 @@ check_version:
clean_pyc:
@find . -type f -name "*.pyc" -delete
-2to3:
- 2to3 $(PY_FILES)
-
clean: clean_pyc
rm -rf /var/log/cloud-init.log /var/lib/cloud/
@@ -66,5 +78,5 @@ rpm:
deb:
./packages/bddeb
-.PHONY: test pyflakes pyflakes3 2to3 clean pep8 rpm deb yaml check_version
-.PHONY: pip-test-requirements pip-requirements clean_pyc unittest
+.PHONY: test pyflakes pyflakes3 clean pep8 rpm deb yaml check_version
+.PHONY: pip-test-requirements pip-requirements clean_pyc unittest unittest3
diff --git a/cloudinit/config/cc_final_message.py b/cloudinit/config/cc_final_message.py
index ad957e12..4a51476f 100644
--- a/cloudinit/config/cc_final_message.py
+++ b/cloudinit/config/cc_final_message.py
@@ -28,9 +28,9 @@ frequency = PER_ALWAYS
# Jinja formated default message
FINAL_MESSAGE_DEF = (
- "## template: jinja\n"
- "Cloud-init v. {{version}} finished at {{timestamp}}."
- " Datasource {{datasource}}. Up {{uptime}} seconds"
+ "## template: jinja\n"
+ "Cloud-init v. {{version}} finished at {{timestamp}}."
+ " Datasource {{datasource}}. Up {{uptime}} seconds"
)
diff --git a/cloudinit/config/cc_grub_dpkg.py b/cloudinit/config/cc_grub_dpkg.py
index acd3e60a..3c2d9985 100644
--- a/cloudinit/config/cc_grub_dpkg.py
+++ b/cloudinit/config/cc_grub_dpkg.py
@@ -37,9 +37,8 @@ def handle(name, cfg, _cloud, log, _args):
return
idevs = util.get_cfg_option_str(mycfg, "grub-pc/install_devices", None)
- idevs_empty = util.get_cfg_option_str(mycfg,
- "grub-pc/install_devices_empty",
- None)
+ idevs_empty = util.get_cfg_option_str(
+ mycfg, "grub-pc/install_devices_empty", None)
if ((os.path.exists("/dev/sda1") and not os.path.exists("/dev/sda")) or
(os.path.exists("/dev/xvda1") and not os.path.exists("/dev/xvda"))):
diff --git a/cloudinit/config/cc_landscape.py b/cloudinit/config/cc_landscape.py
index 0b9d846e..68fcb27f 100644
--- a/cloudinit/config/cc_landscape.py
+++ b/cloudinit/config/cc_landscape.py
@@ -38,12 +38,12 @@ distros = ['ubuntu']
# defaults taken from stock client.conf in landscape-client 11.07.1.1-0ubuntu2
LSC_BUILTIN_CFG = {
- 'client': {
- 'log_level': "info",
- 'url': "https://landscape.canonical.com/message-system",
- 'ping_url': "http://landscape.canonical.com/ping",
- 'data_path': "/var/lib/landscape/client",
- }
+ 'client': {
+ 'log_level': "info",
+ 'url': "https://landscape.canonical.com/message-system",
+ 'ping_url': "http://landscape.canonical.com/ping",
+ 'data_path': "/var/lib/landscape/client",
+ }
}
diff --git a/cloudinit/helpers.py b/cloudinit/helpers.py
index a6eb20fe..0cf982f3 100644
--- a/cloudinit/helpers.py
+++ b/cloudinit/helpers.py
@@ -336,19 +336,19 @@ class Paths(object):
template_dir = path_cfgs.get('templates_dir', '/etc/cloud/templates/')
self.template_tpl = os.path.join(template_dir, '%s.tmpl')
self.lookups = {
- "handlers": "handlers",
- "scripts": "scripts",
- "vendor_scripts": "scripts/vendor",
- "sem": "sem",
- "boothooks": "boothooks",
- "userdata_raw": "user-data.txt",
- "userdata": "user-data.txt.i",
- "obj_pkl": "obj.pkl",
- "cloud_config": "cloud-config.txt",
- "vendor_cloud_config": "vendor-cloud-config.txt",
- "data": "data",
- "vendordata_raw": "vendor-data.txt",
- "vendordata": "vendor-data.txt.i",
+ "handlers": "handlers",
+ "scripts": "scripts",
+ "vendor_scripts": "scripts/vendor",
+ "sem": "sem",
+ "boothooks": "boothooks",
+ "userdata_raw": "user-data.txt",
+ "userdata": "user-data.txt.i",
+ "obj_pkl": "obj.pkl",
+ "cloud_config": "cloud-config.txt",
+ "vendor_cloud_config": "vendor-cloud-config.txt",
+ "data": "data",
+ "vendordata_raw": "vendor-data.txt",
+ "vendordata": "vendor-data.txt.i",
}
# Set when a datasource becomes active
self.datasource = ds
diff --git a/cloudinit/sources/DataSourceAltCloud.py b/cloudinit/sources/DataSourceAltCloud.py
index 60d58d6d..cd61df31 100644
--- a/cloudinit/sources/DataSourceAltCloud.py
+++ b/cloudinit/sources/DataSourceAltCloud.py
@@ -284,7 +284,7 @@ class DataSourceAltCloud(sources.DataSource):
# In the future 'dsmode' like behavior can be added to offer user
# the ability to run before networking.
datasources = [
- (DataSourceAltCloud, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceAltCloud, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
]
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index b03ab895..2af0ad9b 100644
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -636,7 +636,7 @@ class NonAzureDataSource(Exception):
# Used to match classes to dependencies
datasources = [
- (DataSourceAzureNet, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceAzureNet, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
]
diff --git a/cloudinit/sources/DataSourceDigitalOcean.py b/cloudinit/sources/DataSourceDigitalOcean.py
index 5d47564d..12e863d2 100644
--- a/cloudinit/sources/DataSourceDigitalOcean.py
+++ b/cloudinit/sources/DataSourceDigitalOcean.py
@@ -101,8 +101,8 @@ class DataSourceDigitalOcean(sources.DataSource):
# Used to match classes to dependencies
datasources = [
- (DataSourceDigitalOcean, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
- ]
+ (DataSourceDigitalOcean, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+]
# Return a list of data sources that match this set of dependencies
diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
index 6a897f7d..3ef2c6af 100644
--- a/cloudinit/sources/DataSourceEc2.py
+++ b/cloudinit/sources/DataSourceEc2.py
@@ -206,7 +206,7 @@ class DataSourceEc2(sources.DataSource):
# Used to match classes to dependencies
datasources = [
- (DataSourceEc2, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceEc2, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
]
diff --git a/cloudinit/sources/DataSourceMAAS.py b/cloudinit/sources/DataSourceMAAS.py
index f18c4cee..d828f078 100644
--- a/cloudinit/sources/DataSourceMAAS.py
+++ b/cloudinit/sources/DataSourceMAAS.py
@@ -254,7 +254,7 @@ class MAASSeedDirMalformed(Exception):
# Used to match classes to dependencies
datasources = [
- (DataSourceMAAS, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceMAAS, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
]
diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py
index 4dffe6e6..4cad6877 100644
--- a/cloudinit/sources/DataSourceNoCloud.py
+++ b/cloudinit/sources/DataSourceNoCloud.py
@@ -263,8 +263,8 @@ class DataSourceNoCloudNet(DataSourceNoCloud):
# Used to match classes to dependencies
datasources = [
- (DataSourceNoCloud, (sources.DEP_FILESYSTEM, )),
- (DataSourceNoCloudNet, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceNoCloud, (sources.DEP_FILESYSTEM, )),
+ (DataSourceNoCloudNet, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
]
diff --git a/cloudinit/sources/DataSourceNone.py b/cloudinit/sources/DataSourceNone.py
index 12a8a992..d1a62b2a 100644
--- a/cloudinit/sources/DataSourceNone.py
+++ b/cloudinit/sources/DataSourceNone.py
@@ -47,8 +47,8 @@ class DataSourceNone(sources.DataSource):
# Used to match classes to dependencies
datasources = [
- (DataSourceNone, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
- (DataSourceNone, []),
+ (DataSourceNone, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceNone, []),
]
diff --git a/cloudinit/sources/DataSourceOVF.py b/cloudinit/sources/DataSourceOVF.py
index be467bad..8e97e51a 100644
--- a/cloudinit/sources/DataSourceOVF.py
+++ b/cloudinit/sources/DataSourceOVF.py
@@ -367,8 +367,8 @@ class XmlError(Exception):
# Used to match classes to dependencies
datasources = (
- (DataSourceOVF, (sources.DEP_FILESYSTEM, )),
- (DataSourceOVFNet, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceOVF, (sources.DEP_FILESYSTEM, )),
+ (DataSourceOVFNet, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
)
diff --git a/cloudinit/sources/DataSourceOpenNebula.py b/cloudinit/sources/DataSourceOpenNebula.py
index b26940d1..681f3a96 100644
--- a/cloudinit/sources/DataSourceOpenNebula.py
+++ b/cloudinit/sources/DataSourceOpenNebula.py
@@ -149,8 +149,8 @@ class BrokenContextDiskDir(Exception):
class OpenNebulaNetwork(object):
REG_DEV_MAC = re.compile(
- r'^\d+: (eth\d+):.*?link\/ether (..:..:..:..:..:..) ?',
- re.MULTILINE | re.DOTALL)
+ r'^\d+: (eth\d+):.*?link\/ether (..:..:..:..:..:..) ?',
+ re.MULTILINE | re.DOTALL)
def __init__(self, ip, context):
self.ip = ip
diff --git a/cloudinit/sources/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py
index 139ee52c..5edab152 100644
--- a/cloudinit/sources/DataSourceSmartOS.py
+++ b/cloudinit/sources/DataSourceSmartOS.py
@@ -101,7 +101,7 @@ BUILTIN_CLOUD_CONFIG = {
'ephemeral0': {'table_type': 'mbr',
'layout': False,
'overwrite': False}
- },
+ },
'fs_setup': [{'label': 'ephemeral0',
'filesystem': 'ext3',
'device': 'ephemeral0'}],
diff --git a/doc/examples/cloud-config-mount-points.txt b/doc/examples/cloud-config-mount-points.txt
index 3b45b47f..aa676c24 100644
--- a/doc/examples/cloud-config-mount-points.txt
+++ b/doc/examples/cloud-config-mount-points.txt
@@ -42,5 +42,5 @@ mount_default_fields: [ None, None, "auto", "defaults,nobootwait", "0", "2" ]
# default is to not create any swap files, because 'size' is set to 0
swap:
filename: /swap.img
- size: "auto" or size in bytes
+ size: "auto" # or size in bytes
maxsize: size in bytes
diff --git a/doc/examples/cloud-config-rsyslog.txt b/doc/examples/cloud-config-rsyslog.txt
index d54960e8..28ea1f16 100644
--- a/doc/examples/cloud-config-rsyslog.txt
+++ b/doc/examples/cloud-config-rsyslog.txt
@@ -17,7 +17,7 @@ rsyslog:
- content: "*.* @@192.0.2.1:10514"
filename: 01-example.conf
- content: |
- *.* @@syslogd.example.com
+ *.* @@syslogd.example.com
config_dir: /etc/rsyslog.d
config_filename: 20-cloud-config.conf
service_reload_command: [your, syslog, reload, command]
@@ -32,7 +32,7 @@ rsyslog:
# - content: "*.* @@192.0.2.1:10514"
# filename: 01-example.conf
# - content: |
-# *.* @@syslogd.example.com
+# *.* @@syslogd.example.com
# rsyslog_filename: 20-cloud-config.conf
# rsyslog_dir: /etc/rsyslog.d
diff --git a/packages/bddeb b/packages/bddeb
index c4efe264..c141b1ab 100755
--- a/packages/bddeb
+++ b/packages/bddeb
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
+import glob
import os
import shutil
import sys
@@ -105,11 +106,11 @@ def write_debian_folder(root, version, revno, pkgmap,
util.abs_join(deb_dir, 'rules'),
params={'python': python, 'pyver': pyver})
- # Just copy the following directly
- for base_fn in ['dirs', 'copyright', 'compat']:
- shutil.copy(util.abs_join(find_root(),
- 'packages', 'debian', base_fn),
- util.abs_join(deb_dir, base_fn))
+ # Just copy any other files directly (including .in)
+ pdeb_d = util.abs_join(find_root(), 'packages', 'debian')
+ for f in [os.path.join(pdeb_d, f) for f in os.listdir(pdeb_d)]:
+ if os.path.isfile(f):
+ shutil.copy(f, util.abs_join(deb_dir, os.path.basename(f)))
def main():
diff --git a/packages/debian/cloud-init.postinst b/packages/debian/cloud-init.postinst
new file mode 100644
index 00000000..cdd0466d
--- /dev/null
+++ b/packages/debian/cloud-init.postinst
@@ -0,0 +1,16 @@
+#!/bin/sh
+cleanup_lp1552999() {
+ local oldver="$1" last_bad_ver="0.7.7~bzr1178"
+ dpkg --compare-versions "$oldver" le "$last_bad_ver" || return 0
+ local edir="/etc/systemd/system/multi-user.target.wants"
+ rm -f "$edir/cloud-config.service" "$edir/cloud-final.service" \
+ "$edir/cloud-init-local.service" "$edir/cloud-init.service"
+}
+
+
+#DEBHELPER#
+
+if [ "$1" = "configure" ]; then
+ oldver="$2"
+ cleanup_lp1552999 "$oldver"
+fi
diff --git a/packages/debian/cloud-init.preinst b/packages/debian/cloud-init.preinst
new file mode 100644
index 00000000..3c2af06d
--- /dev/null
+++ b/packages/debian/cloud-init.preinst
@@ -0,0 +1,20 @@
+#!/bin/sh
+# vi: ts=4 expandtab
+
+cleanup_lp1552999() {
+ local oldver="$1" last_bad_ver="0.7.7~bzr1178"
+ dpkg --compare-versions "$oldver" le "$last_bad_ver" || return 0
+ local hdir="/var/lib/systemd/deb-systemd-helper-enabled"
+ hdir="$hdir/multi-user.target.wants"
+ local edir="/etc/systemd/system/multi-user.target.wants"
+ rm -f "$hdir/cloud-config.service" "$hdir/cloud-final.service" \
+ "$hdir/cloud-init-local.service" "$hdir/cloud-init.service"
+}
+
+
+if [ "$1" = "upgrade" ]; then
+ oldver="$2"
+ cleanup_lp1552999 "$oldver"
+fi
+
+#DEBHELPER#
diff --git a/packages/debian/control.in b/packages/debian/control.in
index 5fe16e43..16713577 100644
--- a/packages/debian/control.in
+++ b/packages/debian/control.in
@@ -7,6 +7,7 @@ Build-Depends: debhelper (>= 9),
dh-python,
dh-systemd,
iproute2,
+ pep8,
pyflakes,
${python},
${test_requires},
@@ -18,8 +19,8 @@ Package: cloud-init
Architecture: all
Depends: procps,
${python},
- ${requires},
${misc:Depends},
+ ${${python}:Depends}
Recommends: eatmydata, sudo, software-properties-common, gdisk
XB-Python-Version: ${python:Versions}
Description: Init scripts for cloud instances
diff --git a/packages/debian/rules.in b/packages/debian/rules.in
index d6cd23ae..cf2dd405 100755
--- a/packages/debian/rules.in
+++ b/packages/debian/rules.in
@@ -1,9 +1,8 @@
## template:basic
#!/usr/bin/make -f
-
INIT_SYSTEM ?= upstart,systemd
-PYVER ?= python${pyver}
export PYBUILD_INSTALL_ARGS=--init-system=$(INIT_SYSTEM)
+PYVER ?= python${pyver}
%:
dh $@ --with $(PYVER),systemd --buildsystem pybuild
@@ -14,6 +13,11 @@ override_dh_install:
cp tools/21-cloudinit.conf debian/cloud-init/etc/rsyslog.d/21-cloudinit.conf
override_dh_auto_test:
- # Because setup tools didn't copy data...
- [ ! -d .pybuild/pythonX.Y_?.?/build/tests ] || cp -r tests/data .pybuild/pythonX.Y_?.?/build/tests
- http_proxy= make check
+ifeq (,$(findstring nocheck,$(DEB_BUILD_OPTIONS)))
+ http_proxy= make PYVER=${pyver} check
+else
+ @echo check disabled by DEB_BUILD_OPTIONS=$(DEB_BUILD_OPTIONS)
+endif
+
+override_dh_systemd_start:
+ dh_systemd_start --no-restart-on-upgrade --no-start
diff --git a/setup.py b/setup.py
index 5f61681b..0b261dfe 100755
--- a/setup.py
+++ b/setup.py
@@ -45,39 +45,50 @@ def tiny_p(cmd, capture=True):
stdout = None
stderr = None
sp = subprocess.Popen(cmd, stdout=stdout,
- stderr=stderr, stdin=None,
- universal_newlines=True)
+ stderr=stderr, stdin=None,
+ universal_newlines=True)
(out, err) = sp.communicate()
ret = sp.returncode
if ret not in [0]:
- raise RuntimeError("Failed running %s [rc=%s] (%s, %s)"
- % (cmd, ret, out, err))
+ raise RuntimeError("Failed running %s [rc=%s] (%s, %s)" %
+ (cmd, ret, out, err))
return (out, err)
-def systemd_unitdir():
- cmd = ['pkg-config', '--variable=systemdsystemunitdir', 'systemd']
+def pkg_config_read(library, var):
+ fallbacks = {
+ 'systemd': {
+ 'systemdsystemunitdir': '/lib/systemd/system',
+ 'systemdsystemgeneratordir': '/lib/systemd/system-generators',
+ }
+ }
+ cmd = ['pkg-config', '--variable=%s' % var, library]
try:
(path, err) = tiny_p(cmd)
except:
- return '/lib/systemd/system'
+ return fallbacks[library][var]
return str(path).strip()
+
INITSYS_FILES = {
'sysvinit': [f for f in glob('sysvinit/redhat/*') if is_f(f)],
'sysvinit_freebsd': [f for f in glob('sysvinit/freebsd/*') if is_f(f)],
'sysvinit_deb': [f for f in glob('sysvinit/debian/*') if is_f(f)],
- 'systemd': [f for f in glob('systemd/*') if is_f(f)],
+ 'systemd': [f for f in (glob('systemd/*.service') +
+ glob('systemd/*.target')) if is_f(f)],
+ 'systemd.generators': [f for f in glob('systemd/*-generator') if is_f(f)],
'upstart': [f for f in glob('upstart/*') if is_f(f)],
}
INITSYS_ROOTS = {
'sysvinit': '/etc/rc.d/init.d',
'sysvinit_freebsd': '/usr/local/etc/rc.d',
'sysvinit_deb': '/etc/init.d',
- 'systemd': systemd_unitdir(),
+ 'systemd': pkg_config_read('systemd', 'systemdsystemunitdir'),
+ 'systemd.generators': pkg_config_read('systemd',
+ 'systemdsystemgeneratordir'),
'upstart': '/etc/init/',
}
-INITSYS_TYPES = sorted(list(INITSYS_ROOTS.keys()))
+INITSYS_TYPES = sorted([f.partition(".")[0] for f in INITSYS_ROOTS.keys()])
# Install everything in the right location and take care of Linux (default) and
# FreeBSD systems.
@@ -122,9 +133,8 @@ class InitsysInstallData(install):
user_options = install.user_options + [
# This will magically show up in member variable 'init_sys'
('init-system=', None,
- ('init system(s) to configure (%s) [default: None]') %
- (", ".join(INITSYS_TYPES))
- ),
+ ('init system(s) to configure (%s) [default: None]' %
+ (", ".join(INITSYS_TYPES)))),
]
def initialize_options(self):
@@ -138,7 +148,8 @@ class InitsysInstallData(install):
self.init_system = self.init_system.split(",")
if len(self.init_system) == 0:
- raise DistutilsArgError(("You must specify one of (%s) when"
+ raise DistutilsArgError(
+ ("You must specify one of (%s) when"
" specifying init system(s)!") % (", ".join(INITSYS_TYPES)))
bad = [f for f in self.init_system if f not in INITSYS_TYPES]
@@ -147,8 +158,12 @@ class InitsysInstallData(install):
"Invalid --init-system: %s" % (','.join(bad)))
for system in self.init_system:
- self.distribution.data_files.append(
- (INITSYS_ROOTS[system], INITSYS_FILES[system]))
+ # add data files for anything that starts with '<system>.'
+ datakeys = [k for k in INITSYS_ROOTS
+ if k.partition(".")[0] == system]
+ for k in datakeys:
+ self.distribution.data_files.append(
+ (INITSYS_ROOTS[k], INITSYS_FILES[k]))
# Force that command to reinitalize (with new file list)
self.distribution.reinitialize_command('install_data', True)
@@ -182,18 +197,18 @@ if sys.version_info < (3,):
requirements.append('cheetah')
-setuptools.setup(name='cloud-init',
- version=get_version(),
- description='EC2 initialisation magic',
- author='Scott Moser',
- author_email='scott.moser@canonical.com',
- url='http://launchpad.net/cloud-init/',
- packages=setuptools.find_packages(exclude=['tests']),
- scripts=['bin/cloud-init',
- 'tools/cloud-init-per',
- ],
- license='GPLv3',
- data_files=data_files,
- install_requires=requirements,
- cmdclass=cmdclass,
- )
+setuptools.setup(
+ name='cloud-init',
+ version=get_version(),
+ description='EC2 initialisation magic',
+ author='Scott Moser',
+ author_email='scott.moser@canonical.com',
+ url='http://launchpad.net/cloud-init/',
+ packages=setuptools.find_packages(exclude=['tests']),
+ scripts=['bin/cloud-init',
+ 'tools/cloud-init-per'],
+ license='GPLv3',
+ data_files=data_files,
+ install_requires=requirements,
+ cmdclass=cmdclass,
+ )
diff --git a/systemd/cloud-config.service b/systemd/cloud-config.service
index f9f1996e..45d2a63b 100644
--- a/systemd/cloud-config.service
+++ b/systemd/cloud-config.service
@@ -13,4 +13,4 @@ TimeoutSec=0
StandardOutput=journal+console
[Install]
-WantedBy=multi-user.target
+WantedBy=cloud-init.target
diff --git a/systemd/cloud-final.service b/systemd/cloud-final.service
index bcbdd36f..bfb08d4a 100644
--- a/systemd/cloud-final.service
+++ b/systemd/cloud-final.service
@@ -14,4 +14,4 @@ KillMode=process
StandardOutput=journal+console
[Install]
-WantedBy=multi-user.target
+WantedBy=cloud-init.target
diff --git a/systemd/cloud-init-generator b/systemd/cloud-init-generator
new file mode 100755
index 00000000..9d1e22f0
--- /dev/null
+++ b/systemd/cloud-init-generator
@@ -0,0 +1,128 @@
+#!/bin/sh
+set -f
+
+LOG=""
+DEBUG_LEVEL=1
+LOG_D="/run"
+ENABLE="enabled"
+DISABLE="disabled"
+CLOUD_SYSTEM_TARGET="/lib/systemd/system/cloud-init.target"
+CLOUD_TARGET_NAME="cloud-init.target"
+# lxc sets 'container', but lets make that explicitly a global
+CONTAINER="${container}"
+
+debug() {
+ local lvl="$1"
+ shift
+ [ "$lvl" -gt "$DEBUG_LEVEL" ] && return
+ if [ -z "$LOG" ]; then
+ local log="$LOG_D/${0##*/}.log"
+ { : > "$log"; } >/dev/null 2>&1 && LOG="$log" ||
+ LOG="/dev/kmsg"
+ fi
+ echo "$@" >> "$LOG"
+}
+
+etc_file() {
+ local pprefix="${1:-/etc/cloud/cloud-init.}"
+ _RET="unset"
+ [ -f "${pprefix}$ENABLE" ] && _RET="$ENABLE" && return 0
+ [ -f "${pprefix}$DISABLE" ] && _RET="$DISABLE" && return 0
+ return 0
+}
+
+read_proc_cmdline() {
+ if [ "$CONTAINER" = "lxc" ]; then
+ _RET_MSG="ignored: \$container=$CONTAINER"
+ _RET=""
+ return 0
+ fi
+
+ if systemd-detect-virt --container --quiet; then
+ _RET_MSG="ignored: detect-virt is container"
+ _RET=""
+ return 0
+ fi
+
+ _RET_MSG="/proc/cmdline"
+ read _RET < /proc/cmdline
+}
+
+kernel_cmdline() {
+ local cmdline="" tok=""
+ if [ -n "${KERNEL_CMDLINE+x}" ]; then
+ # use KERNEL_CMDLINE if present in environment even if empty
+ cmdline=${KERNEL_CMDLINE}
+ debug 1 "kernel command line from env KERNEL_CMDLINE: $cmdline"
+ elif read_proc_cmdline; then
+ read_proc_cmdline && cmdline="$_RET"
+ debug 1 "kernel command line ($_RET_MSG): $cmdline"
+ fi
+ _RET="unset"
+ cmdline=" $cmdline "
+ tok=${cmdline##* cloud-init=}
+ [ "$tok" = "$cmdline" ] && _RET="unset"
+ tok=${tok%% *}
+ [ "$tok" = "$ENABLE" -o "$tok" = "$DISABLE" ] && _RET="$tok"
+ return 0
+}
+
+default() {
+ _RET="$ENABLE"
+}
+
+main() {
+ local normal_d="$1" early_d="$2" late_d="$3"
+ local target_name="multi-user.target" gen_d="$early_d"
+ local link_path="$gen_d/${target_name}.wants/${CLOUD_TARGET_NAME}"
+
+ debug 1 "$0 normal=$normal_d early=$early_d late=$late_d"
+ debug 2 "$0 $*"
+
+ local search result="error" ret=""
+ for search in kernel_cmdline etc_file default; do
+ if $search; then
+ debug 1 "$search found $_RET"
+ [ "$_RET" = "$ENABLE" -o "$_RET" = "$DISABLE" ] &&
+ result=$_RET && break
+ else
+ ret=$?
+ debug 0 "search $search returned $ret"
+ fi
+ done
+
+ if [ "$result" = "$ENABLE" ]; then
+ if [ -e "$link_path" ]; then
+ debug 1 "already enabled: no change needed"
+ else
+ [ -d "${link_path%/*}" ] || mkdir -p "${link_path%/*}" ||
+ debug 0 "failed to make dir $link_path"
+ if ln -snf "$CLOUD_SYSTEM_TARGET" "$link_path"; then
+ debug 1 "enabled via $link_path -> $CLOUD_SYSTEM_TARGET"
+ else
+ ret=$?
+ debug 0 "[$ret] enable failed:" \
+ "ln $CLOUD_SYSTEM_TARGET $link_path"
+ fi
+ fi
+ elif [ "$result" = "$DISABLE" ]; then
+ if [ -f "$link_path" ]; then
+ if rm -f "$link_path"; then
+ debug 1 "disabled. removed existing $link_path"
+ else
+ ret=$?
+ debug 0 "[$ret] disable failed, remove $link_path"
+ fi
+ else
+ debug 1 "already disabled: no change needed [no $link_path]"
+ fi
+ else
+ debug 0 "unexpected result '$result'"
+ ret=3
+ fi
+ return $ret
+}
+
+main "$@"
+
+# vi: ts=4 expandtab
diff --git a/systemd/cloud-init-local.service b/systemd/cloud-init-local.service
index a31985c6..73aa46f6 100644
--- a/systemd/cloud-init-local.service
+++ b/systemd/cloud-init-local.service
@@ -13,4 +13,4 @@ TimeoutSec=0
StandardOutput=journal+console
[Install]
-WantedBy=multi-user.target
+WantedBy=cloud-init.target
diff --git a/systemd/cloud-init.service b/systemd/cloud-init.service
index 48920283..1f656f7f 100644
--- a/systemd/cloud-init.service
+++ b/systemd/cloud-init.service
@@ -15,4 +15,4 @@ TimeoutSec=0
StandardOutput=journal+console
[Install]
-WantedBy=multi-user.target
+WantedBy=cloud-init.target
diff --git a/systemd/cloud-init.target b/systemd/cloud-init.target
new file mode 100644
index 00000000..a63babb0
--- /dev/null
+++ b/systemd/cloud-init.target
@@ -0,0 +1,6 @@
+# cloud-init target is enabled by cloud-init-generator
+# To disable it you can either:
+# a.) boot with kernel cmdline of 'cloudinit=disabled'
+# b.) touch a file /etc/cloud/cloud-init.disabled
+[Unit]
+Description=Cloud-init target
diff --git a/tests/unittests/test_datasource/test_configdrive.py b/tests/unittests/test_datasource/test_configdrive.py
index 3954ceb3..bfd787d1 100644
--- a/tests/unittests/test_datasource/test_configdrive.py
+++ b/tests/unittests/test_datasource/test_configdrive.py
@@ -61,16 +61,16 @@ CONTENT_0 = b'This is contents of /etc/foo.cfg\n'
CONTENT_1 = b'# this is /etc/bar/bar.cfg\n'
CFG_DRIVE_FILES_V2 = {
- 'ec2/2009-04-04/meta-data.json': json.dumps(EC2_META),
- 'ec2/2009-04-04/user-data': USER_DATA,
- 'ec2/latest/meta-data.json': json.dumps(EC2_META),
- 'ec2/latest/user-data': USER_DATA,
- 'openstack/2012-08-10/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/2012-08-10/user_data': USER_DATA,
- 'openstack/content/0000': CONTENT_0,
- 'openstack/content/0001': CONTENT_1,
- 'openstack/latest/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/latest/user_data': USER_DATA}
+ 'ec2/2009-04-04/meta-data.json': json.dumps(EC2_META),
+ 'ec2/2009-04-04/user-data': USER_DATA,
+ 'ec2/latest/meta-data.json': json.dumps(EC2_META),
+ 'ec2/latest/user-data': USER_DATA,
+ 'openstack/2012-08-10/meta_data.json': json.dumps(OSTACK_META),
+ 'openstack/2012-08-10/user_data': USER_DATA,
+ 'openstack/content/0000': CONTENT_0,
+ 'openstack/content/0001': CONTENT_1,
+ 'openstack/latest/meta_data.json': json.dumps(OSTACK_META),
+ 'openstack/latest/user_data': USER_DATA}
class TestConfigDriveDataSource(TestCase):
diff --git a/tests/unittests/test_datasource/test_opennebula.py b/tests/unittests/test_datasource/test_opennebula.py
index 27adf21b..d796f030 100644
--- a/tests/unittests/test_datasource/test_opennebula.py
+++ b/tests/unittests/test_datasource/test_opennebula.py
@@ -20,7 +20,7 @@ TEST_VARS = {
'VAR7': 'single\\t',
'VAR8': 'double\\tword',
'VAR9': 'multi\\t\nline\n',
- 'VAR10': '\\', # expect \
+ 'VAR10': '\\', # expect '\'
'VAR11': '\'', # expect '
'VAR12': '$', # expect $
}
diff --git a/tests/unittests/test_datasource/test_smartos.py b/tests/unittests/test_datasource/test_smartos.py
index 616e9f0e..5c49966a 100644
--- a/tests/unittests/test_datasource/test_smartos.py
+++ b/tests/unittests/test_datasource/test_smartos.py
@@ -462,8 +462,8 @@ class TestJoyentMetadataClient(helpers.FilesystemMockingTestCase):
payloadstr = ' {0}'.format(self.response_parts['payload'])
return ('V2 {length} {crc} {request_id} '
'{command}{payloadstr}\n'.format(
- payloadstr=payloadstr,
- **self.response_parts).encode('ascii'))
+ payloadstr=payloadstr,
+ **self.response_parts).encode('ascii'))
self.metasource_data = None
diff --git a/tests/unittests/test_distros/test_user_data_normalize.py b/tests/unittests/test_distros/test_user_data_normalize.py
index e4488e2a..4525f487 100644
--- a/tests/unittests/test_distros/test_user_data_normalize.py
+++ b/tests/unittests/test_distros/test_user_data_normalize.py
@@ -6,13 +6,13 @@ from ..helpers import TestCase
bcfg = {
- 'name': 'bob',
- 'plain_text_passwd': 'ubuntu',
- 'home': "/home/ubuntu",
- 'shell': "/bin/bash",
- 'lock_passwd': True,
- 'gecos': "Ubuntu",
- 'groups': ["foo"]
+ 'name': 'bob',
+ 'plain_text_passwd': 'ubuntu',
+ 'home': "/home/ubuntu",
+ 'shell': "/bin/bash",
+ 'lock_passwd': True,
+ 'gecos': "Ubuntu",
+ 'groups': ["foo"]
}
@@ -34,16 +34,11 @@ class TestUGNormalize(TestCase):
def test_group_dict(self):
distro = self._make_distro('ubuntu')
g = {'groups': [
- {
- 'ubuntu': ['foo', 'bar'],
- 'bob': 'users',
- },
- 'cloud-users',
- {
- 'bob': 'users2',
- },
- ]
- }
+ {'ubuntu': ['foo', 'bar'],
+ 'bob': 'users'},
+ 'cloud-users',
+ {'bob': 'users2'}
+ ]}
(_users, groups) = self._norm(g, distro)
self.assertIn('ubuntu', groups)
ub_members = groups['ubuntu']
diff --git a/tools/validate-yaml.py b/tools/validate-yaml.py
index 6e164590..ed9037d9 100755
--- a/tools/validate-yaml.py
+++ b/tools/validate-yaml.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
"""Try to read a YAML file and report any errors.
"""
diff --git a/tox.ini b/tox.ini
index fd65f6ef..bd7c27dd 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,6 +13,7 @@ basepython = python3
[testenv:pyflakes]
basepython = python3
commands = {envpython} -m pyflakes {posargs:cloudinit/ tests/ tools/}
+ {envpython} -m pep8 {posargs:cloudinit/ tests/ tools/}
# https://github.com/gabrielfalcao/HTTPretty/issues/223
setenv =