unblock: systemd/215-9

Martin Pitt mpitt at debian.org
Tue Jan 13 11:07:00 GMT 2015


Package: release.debian.org
Severity: normal
User: release.debian.org at packages.debian.org
Usertags: unblock

I just uploaded systemd 215-9 to unstable with two RC and some other
fixes. I attach the full debdiff between 215-8 and -9, but as usual I
also link to the individual commits on anonscm.  Note that there are
zero changes for the udebs (for d-i).

Annotated changelog:

| systemd (215-9) unstable; urgency=medium
| 
|   [ Didier Roche ]
|   * Add display managers autopkgtests.

This is quite a delicate logic which got introduced in 215-8. This
adds automatic tests. No impact at all on binary packages or on
installations.

http://anonscm.debian.org/cgit/pkg-systemd/systemd.git/commit/?id=f72429642fd

|   * Reset display-manager symlink to match /e/X/d-d-m even if
|     display-manager.service was removed. Adapt the autopkgtests for it.

This is a rather simple fix which fixes one corner case spotted by the
tests. It has been in experimental and in Ubuntu for quite some time.

http://anonscm.debian.org/cgit/pkg-systemd/systemd.git/commit/?id=67417fc1

|   [ Martin Pitt ]
|   * Prefer-etc-X11-default-display-manager-if-present.patch: Drop wrong
|     copy&paste'd comment, fix log strings. Thanks Adam D. Barratt.

This came up in the unblock request for 215-8. It just fixes text in
comments and two log warnings.

http://anonscm.debian.org/cgit/pkg-systemd/systemd.git/commit/?id=dc0a50b23

|   * Log all members of cyclic dependencies (loops) even with quiet on the
|     kernel cmdline. (Closes: #770504)

Non-RC bug, but trivial change and pre-approved by release team in #773183.

http://anonscm.debian.org/cgit/pkg-systemd/systemd.git/commit/?id=6f3e3ee

|   * Don't auto-clean PrivateTmp dir in /var/tmp; in Debian we don't want to
|     clean /var/tmp/ automatically. (Closes: #773313)

Non-RC bug, but trivial change. Not pre-approved, but this brings
systemd in line with Debian Policy wrt. /var/tmp/.

http://anonscm.debian.org/cgit/pkg-systemd/systemd.git/commit/?id=78d97ace0

|   [ Michael Biebl ]
|   * sysv-generator: handle Provides: for non-virtual facility names.
|     (Closes: #774335)

RC bug.

http://anonscm.debian.org/cgit/pkg-systemd/systemd.git/commit/?id=7024b5117a

|   * Fix systemd-remount-fs.service to not fail on remounting /usr if /usr
|     isn't mounted yet. This happens with initramfs-tools < 0.118 which we
|     might not get into Jessie any more. (Closes: #742048)

RC bug.

http://anonscm.debian.org/cgit/pkg-systemd/systemd.git/commit/?id=b9782ef44

Thanks for considering!

Martin


unblock systemd/215-9

-- 
Martin Pitt                        | http://www.piware.de
Ubuntu Developer (www.ubuntu.com)  | Debian Developer  (www.debian.org)
-------------- next part --------------
diff --git a/debian/changelog b/debian/changelog
index 2dd4744..61ef555 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,27 @@
+systemd (215-9) unstable; urgency=medium
+
+  [ Didier Roche ]
+  * Add display managers autopkgtests.
+  * Reset display-manager symlink to match /e/X/d-d-m even if
+    display-manager.service was removed. Adapt the autopkgtests for it.
+
+  [ Martin Pitt ]
+  * Prefer-etc-X11-default-display-manager-if-present.patch: Drop wrong
+    copy&paste'd comment, fix log strings. Thanks Adam D. Barratt.
+  * Log all members of cyclic dependencies (loops) even with quiet on the
+    kernel cmdline. (Closes: #770504)
+  * Don't auto-clean PrivateTmp dir in /var/tmp; in Debian we don't want to
+    clean /var/tmp/ automatically. (Closes: #773313)
+
+  [ Michael Biebl ]
+  * sysv-generator: handle Provides: for non-virtual facility names.
+    (Closes: #774335)
+  * Fix systemd-remount-fs.service to not fail on remounting /usr if /usr
+    isn't mounted yet. This happens with initramfs-tools < 0.118 which we
+    might not get into Jessie any more. (Closes: #742048)
+
+ -- Martin Pitt <mpitt at debian.org>  Tue, 13 Jan 2015 11:24:43 +0100
+
 systemd (215-8) unstable; urgency=medium
 
   [ Didier Roche ]
diff --git a/debian/patches/Fix-usr-remount-failure-for-split-usr.patch b/debian/patches/Fix-usr-remount-failure-for-split-usr.patch
new file mode 100644
index 0000000..6481b2c
--- /dev/null
+++ b/debian/patches/Fix-usr-remount-failure-for-split-usr.patch
@@ -0,0 +1,64 @@
+From: Michael Biebl <biebl at debian.org>
+Date: Tue, 13 Jan 2015 08:25:00 +0100
+Subject: Fix /usr remount failure for split /usr
+
+Fix systemd-remount-fs.service to not fail on remounting /usr if /usr isn't
+mounted yet. This happens with initramfs-tools < 0.118 which we might not get
+into Jessie any more.
+
+This can be dropped when /usr always gets mounted from initramfs.
+
+Bug-Debian: https://bugs.debian.org/742048
+---
+ src/remount-fs/remount-fs.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
+index 847637a..82a1596 100644
+--- a/src/remount-fs/remount-fs.c
++++ b/src/remount-fs/remount-fs.c
+@@ -34,6 +34,32 @@
+ #include "mount-setup.h"
+ #include "exit-status.h"
+ 
++static bool is_mounted(const char *dev_path) {
++        _cleanup_free_ char *parent_path = NULL;
++        struct stat st, pst;
++        int r;
++
++        parent_path = strjoin(dev_path, "/..", NULL);
++
++        r = stat(dev_path, &st);
++        if (r < 0)
++                return false;
++
++        r = stat(parent_path, &pst);
++        if (r < 0)
++                return false;
++
++        /*
++         * This code to check if a given path is a mountpoint is
++         * borrowed from util-linux' mountpoint tool.
++         */
++        if ((st.st_dev != pst.st_dev) ||
++            (st.st_dev == pst.st_dev && st.st_ino == pst.st_ino))
++                return true;
++
++        return false;
++}
++
+ /* Goes through /etc/fstab and remounts all API file systems, applying
+  * options that are in /etc/fstab that systemd might not have
+  * respected */
+@@ -83,6 +109,11 @@ int main(int argc, char *argv[]) {
+                     !path_equal(me->mnt_dir, "/usr"))
+                         continue;
+ 
++                /* Skip /usr if it hasn't been mounted by the initrd */
++                if (path_equal(me->mnt_dir, "/usr") &&
++                    !is_mounted("/usr"))
++                        continue;
++
+                 log_debug("Remounting %s", me->mnt_dir);
+ 
+                 pid = fork();
diff --git a/debian/patches/Prefer-etc-X11-default-display-manager-if-present.patch b/debian/patches/Prefer-etc-X11-default-display-manager-if-present.patch
index b4bd19b..13a660b 100644
--- a/debian/patches/Prefer-etc-X11-default-display-manager-if-present.patch
+++ b/debian/patches/Prefer-etc-X11-default-display-manager-if-present.patch
@@ -6,17 +6,17 @@ Add a generator to ensure /etc/X11/default-display-manager is controlling
 which display-manager is started.
 ---
  Makefile.am                                        |  11 ++-
- src/default-display-manager-generator/Makefile     |  28 ++++++
- .../default-display-manager-generator.c            | 105 +++++++++++++++++++++
- 3 files changed, 143 insertions(+), 1 deletion(-)
+ src/default-display-manager-generator/Makefile     |  24 +++++
+ .../default-display-manager-generator.c            | 103 +++++++++++++++++++++
+ 3 files changed, 137 insertions(+), 1 deletion(-)
  create mode 100644 src/default-display-manager-generator/Makefile
  create mode 100644 src/default-display-manager-generator/default-display-manager-generator.c
 
 diff --git a/Makefile.am b/Makefile.am
-index ec5b871..b607a4a 100644
+index 6f4df22..9d83771 100644
 --- a/Makefile.am
 +++ b/Makefile.am
-@@ -402,7 +402,8 @@ systemgenerator_PROGRAMS = \
+@@ -387,7 +387,8 @@ systemgenerator_PROGRAMS = \
  	systemd-getty-generator \
  	systemd-fstab-generator \
  	systemd-system-update-generator \
@@ -26,7 +26,7 @@ index ec5b871..b607a4a 100644
  
  dist_bashcompletion_DATA = \
  	shell-completion/bash/busctl \
-@@ -2190,6 +2191,14 @@ systemd_delta_LDADD = \
+@@ -1965,6 +1966,14 @@ systemd_delta_LDADD = \
  	libsystemd-shared.la
  
  # ------------------------------------------------------------------------------
@@ -43,10 +43,10 @@ index ec5b871..b607a4a 100644
  
 diff --git a/src/default-display-manager-generator/Makefile b/src/default-display-manager-generator/Makefile
 new file mode 100644
-index 0000000..b29b937
+index 0000000..3a4bbbe
 --- /dev/null
 +++ b/src/default-display-manager-generator/Makefile
-@@ -0,0 +1,28 @@
+@@ -0,0 +1,24 @@
 +#  This file is part of systemd.
 +#
 +#  Copyright 2014 Canonical
@@ -64,10 +64,6 @@ index 0000000..b29b937
 +#  You should have received a copy of the GNU Lesser General Public License
 +#  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 +
-+# This file is a dirty trick to simplify compilation from within
-+# emacs. This file is not intended to be distributed. So, don't touch
-+# it, even better ignore it!
-+
 +all:
 +	$(MAKE) -C ..
 +
@@ -77,10 +73,10 @@ index 0000000..b29b937
 +.PHONY: all clean
 diff --git a/src/default-display-manager-generator/default-display-manager-generator.c b/src/default-display-manager-generator/default-display-manager-generator.c
 new file mode 100644
-index 0000000..2fe9521
+index 0000000..930a67e
 --- /dev/null
 +++ b/src/default-display-manager-generator/default-display-manager-generator.c
-@@ -0,0 +1,105 @@
+@@ -0,0 +1,103 @@
 +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 +
 +/***
@@ -136,10 +132,8 @@ index 0000000..2fe9521
 +        default_dm = strstrip(basename(default_dm_path));
 +
 +        r = readlink_value(dm_service_unit, &enabled_dm_unit);
-+        if (r < 0) {
-+                log_warning("No default display manager unit service enabled, setup is manual or a sysvinit file");
-+                return 0;
-+        }
++        if (r < 0)
++                enabled_dm_unit = strdup("");
 +
 +        /* all is fine if the info matches */
 +        if (streq(strappenda(default_dm, ".service"), enabled_dm_unit))
@@ -149,10 +143,10 @@ index 0000000..2fe9521
 +
 +        /* we only create the alias symlink for non sysvinit services */
 +        if (access(target_unit_path, F_OK) < 0 && (errno == ENOENT)) {
-+                log_warning("%s doesn't seem to be a system unit, we disable the systemd enabled display manager", target_unit_path);
++                log_warning("%s is not a systemd unit, we disable the systemd enabled display manager", target_unit_path);
 +                target_unit_path = "/dev/null";
 +        } else {
-+                log_warning("%s point at %s while the default systemd unit is %s. Reconfiguring %s as default.",
++                log_warning("%s points at %s while the default systemd unit is %s. Reconfiguring %s as default.",
 +                            default_dm_file, default_dm, enabled_dm_unit, default_dm);
 +        }
 +
diff --git a/debian/patches/Raise-level-of-Found-dependency.-lines.patch b/debian/patches/Raise-level-of-Found-dependency.-lines.patch
new file mode 100644
index 0000000..8bbb0f6
--- /dev/null
+++ b/debian/patches/Raise-level-of-Found-dependency.-lines.patch
@@ -0,0 +1,38 @@
+From: =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= <zbyszek at in.waw.pl>
+Date: Sun, 2 Nov 2014 12:10:42 -0500
+Subject: Raise level of 'Found dependency...' lines
+
+This way they always show up together with 'Found ordering cycle...'.
+Ordering cycles are a serious error and a major pain to debug. If
+quiet is enabled, only the first and the last line of output are
+shown:
+
+systemd[1]: Found ordering cycle on basic.target/start
+systemd[1]: Breaking ordering cycle by deleting job timers.target/start
+systemd[1]: Job timers.target/start deleted to break ordering cycle starting with basic.target/start
+
+which isn't particularly enlightening. So just show the whole message
+at the same level.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1158206
+---
+ src/core/transaction.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/core/transaction.c b/src/core/transaction.c
+index 805d40a..b9bbec2 100644
+--- a/src/core/transaction.c
++++ b/src/core/transaction.c
+@@ -377,9 +377,9 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
+                 for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) {
+ 
+                         /* logging for j not k here here to provide consistent narrative */
+-                        log_info_unit(j->unit->id,
+-                                      "Found dependency on %s/%s",
+-                                      k->unit->id, job_type_to_string(k->type));
++                        log_warning_unit(j->unit->id,
++                                         "Found dependency on %s/%s",
++                                         k->unit->id, job_type_to_string(k->type));
+ 
+                         if (!delete && hashmap_get(tr->jobs, k->unit) &&
+                             !unit_matters_to_anchor(k->unit, k)) {
diff --git a/debian/patches/series b/debian/patches/series
index fd1aacd..80256e6 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -122,6 +122,9 @@ shared-add-readlink_value.patch
 util-allow-strappenda-to-take-any-number-of-args.patch
 journal-do-server_vacuum-for-sigusr1.patch
 journalctl-correct-help-text-for-until.patch
+Raise-level-of-Found-dependency.-lines.patch
+systemd-tmpfiles-Fix-IGNORE_DIRECTORY_PATH-age-handl.patch
+sysv-generator-handle-Provides-for-non-virtual-facil.patch
 
 ## Debian specific patches:
 Add-back-support-for-Debian-specific-config-files.patch
@@ -173,3 +176,4 @@ sysv-generator-Avoid-wrong-dependencies-for-failing-.patch
 Prefer-etc-X11-default-display-manager-if-present.patch
 core-Fix-bind-error-message.patch
 core-Make-binding-notify-private-dbus-socket-more-ro.patch
+Fix-usr-remount-failure-for-split-usr.patch
diff --git a/debian/patches/systemd-tmpfiles-Fix-IGNORE_DIRECTORY_PATH-age-handl.patch b/debian/patches/systemd-tmpfiles-Fix-IGNORE_DIRECTORY_PATH-age-handl.patch
new file mode 100644
index 0000000..859847d
--- /dev/null
+++ b/debian/patches/systemd-tmpfiles-Fix-IGNORE_DIRECTORY_PATH-age-handl.patch
@@ -0,0 +1,39 @@
+From 9ed2a35e93f4a9e82585f860f54cdcbbdf3e1f86 Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard at nod.at>
+Date: Tue, 9 Sep 2014 11:09:37 +0200
+Subject: [PATCH] systemd-tmpfiles: Fix IGNORE_DIRECTORY_PATH age handling
+
+If one has a config like:
+d /tmp 1777 root root -
+X /tmp/important_mount
+
+All files below /tmp/important_mount will be deleted as the
+/tmp/important_mount item will spuriously inherit a max age of 0
+from /tmp.
+/tmp has a max age of 0 but age_set is (of course) false.
+
+This affects also the PrivateTmp feature of systemd.
+All tmp files of such services will be deleted unconditionally
+and can cause service failures and data loss.
+
+Fix this by checking ->age_set in the IGNORE_DIRECTORY_PATH logic.
+---
+ src/tmpfiles/tmpfiles.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
+index f9830c4..7eafd6b 100644
+--- a/src/tmpfiles/tmpfiles.c
++++ b/src/tmpfiles/tmpfiles.c
+@@ -1576,7 +1576,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
+                                 candidate_item = j;
+                 }
+ 
+-                if (candidate_item) {
++                if (candidate_item && candidate_item->age_set) {
+                         i->age = candidate_item->age;
+                         i->age_set = true;
+                 }
+-- 
+2.1.3
+
diff --git a/debian/patches/sysv-generator-handle-Provides-for-non-virtual-facil.patch b/debian/patches/sysv-generator-handle-Provides-for-non-virtual-facil.patch
new file mode 100644
index 0000000..77c4c12
--- /dev/null
+++ b/debian/patches/sysv-generator-handle-Provides-for-non-virtual-facil.patch
@@ -0,0 +1,68 @@
+From: Michael Biebl <biebl at debian.org>
+Date: Mon, 5 Jan 2015 09:49:44 +0100
+Subject: sysv-generator: handle Provides: for non-virtual facility names
+
+The list of provided facility names as specified via Provides: in the
+LSB header was originally implemented by adding those facilities to the
+Names= property via unit_add_name().
+
+In commit 95ed3294c632f5606327149f10cef1eb34422862 the internal SysV
+support was replaced by a generator and support for parsing the Names=
+option had been removed from the unit file parsing in v186.
+As a result, Provides: for non-virtual facility was dropped when
+introducing the sysv-generator.
+
+Since quite a few SysV init scripts still use that functionality (at
+least in distros like Debian which have a large body of SysV init
+scripts), add back support by making those facility names available via
+symlinks to the unit filename to ensure correct orderings between
+SysV init scripts which use those facility names.
+
+Bug-Debian: https://bugs.debian.org/774335
+---
+ src/sysv-generator/sysv-generator.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
+index da6b4f6..2f116fb 100644
+--- a/src/sysv-generator/sysv-generator.c
++++ b/src/sysv-generator/sysv-generator.c
+@@ -118,6 +118,27 @@ static int add_symlink(const char *service, const char *where) {
+         return 1;
+ }
+ 
++static int add_alias(const char *service, const char *alias) {
++        _cleanup_free_ char *link = NULL;
++        int r;
++
++        assert(service);
++        assert(alias);
++
++        link = strjoin(arg_dest, "/", alias, NULL);
++        if (!link)
++                return log_oom();
++
++        r = symlink(service, link);
++        if (r < 0) {
++                if (errno == EEXIST)
++                        return 0;
++                return -errno;
++        }
++
++        return 1;
++}
++
+ static int generate_unit_file(SysvStub *s) {
+         char *unit;
+         char **p;
+@@ -477,7 +498,9 @@ static int load_sysv(SysvStub *s) {
+                                         if (r == 0)
+                                                 continue;
+ 
+-                                        if (unit_name_to_type(m) != UNIT_SERVICE) {
++                                        if (unit_name_to_type(m) == UNIT_SERVICE) {
++                                                r = add_alias(s->name, m);
++                                        } else {
+                                                 /* NB: SysV targets
+                                                  * which are provided
+                                                  * by a service are
diff --git a/debian/tests/control b/debian/tests/control
index 501052e..cd03367 100644
--- a/debian/tests/control
+++ b/debian/tests/control
@@ -11,3 +11,7 @@ Depends: python3-systemd
 Tests: boot-and-services
 Depends: lightdm, cron, network-manager, busybox-static
 Restrictions: needs-root, isolation-machine, needs-recommends, breaks-testbed
+
+Tests: display-managers
+Depends: systemd, lightdm
+Restrictions: needs-root, isolation-machine, needs-recommends, breaks-testbed
diff --git a/debian/tests/display-managers b/debian/tests/display-managers
new file mode 100755
index 0000000..d45b2b8
--- /dev/null
+++ b/debian/tests/display-managers
@@ -0,0 +1,302 @@
+#!/usr/bin/python3
+# autopkgtest check: Boot with systemd and check different dm configurations
+# (C) 2014 Canonical Ltd.
+# Author: Didier Roche <didrocks at ubuntu.com>
+
+from contextlib import suppress
+import fileinput
+import os
+import subprocess
+import shutil
+import sys
+import unittest
+from time import sleep
+
+DDM_CONFIG_PATH = "/etc/X11/default-display-manager"
+SYSTEMD_DEFAULT_DM_PATH = "/etc/systemd/system/display-manager.service"
+SYSTEMD_SYSTEM_UNIT_DIR = "/lib/systemd/system"
+LIGHTDM_SYSTEMD_UNIT_PATH = os.path.join(SYSTEMD_SYSTEM_UNIT_DIR, 'lightdm.service')
+
+
+class DisplayManagersTest(unittest.TestCase):
+    '''Check that multiple dm configurations are handled'''
+
+    def setUp(self):
+        super().setUp()
+        with suppress(FileNotFoundError):
+            os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        with suppress(FileNotFoundError):
+            os.remove(DDM_CONFIG_PATH)
+        subprocess.check_call('apt-get install -y --reinstall lightdm 2>&1', shell=True)
+        # Remove all Conditional ExecStartPre= as we want to check systemd logic, not unit
+        for line in fileinput.input([LIGHTDM_SYSTEMD_UNIT_PATH], inplace=True):
+            if not line.startswith('ExecStartPre='):
+                print(line)
+        self.files_to_clean = []
+
+    def tearDown(self):
+        for f in self.files_to_clean:
+            os.remove(f)
+        super().tearDown()
+
+    def test_one_systemd(self):
+        '''one systemd dm is started'''
+
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('lightdm'))
+
+    def test_multiple_systemd(self):
+        '''only default systemd dm is started'''
+
+        self.create_systemd_dm_unit("systemddm")
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('lightdm'))
+        self.assertFalse(self.is_active_unit('systemddm'))
+
+    def test_multiple_systemd_ddmconfig_match(self):
+        '''display-manager symlink respect ddm config and starts right unit'''
+
+        # lightdm was the default
+        self.create_systemd_dm_unit("systemddm", make_ddm_default="systemddm")
+        self.reload_state()
+
+        self.assertFalse(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('systemddm'))
+
+    def test_multiple_systemd_ddmconfig_match_no_symlink(self):
+        '''create a display-manager symlink to matching systemd unit ddm config'''
+
+        # lightdm was the default
+        self.create_systemd_dm_unit("systemddm", make_ddm_default="systemddm")
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        self.reload_state()
+
+        self.assertFalse(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('systemddm'))
+
+    def test_one_systemd_no_ddmconfig(self):
+        '''without any ddm config, the default systemd unit via symlink is still the default'''
+
+        os.remove(DDM_CONFIG_PATH)
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('lightdm'))
+
+    def test_one_systemd_masked_symlink_with_ddmconfig(self):
+        '''a masked symlink will be updated to match systemd ddmconfig unit'''
+
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('lightdm'))
+
+    def test_one_systemd_masked_symlink_no_ddmconfig(self):
+        '''without any ddm config, a masked symlinked will stayed masked'''
+
+        os.remove(DDM_CONFIG_PATH)
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
+        self.reload_state()
+
+        self.assertFalse(self.is_active_unit('lightdm'))
+
+    def test_multiple_systemd_wrong_ddmconfig(self):
+        '''ddm config matches no systemd unit, don't start any of them'''
+
+        self.create_systemd_dm_unit("systemddm", make_ddm_default="systemddm_doesnt_match")
+        self.reload_state()
+
+        self.assertFalse(self.is_active_unit('lightdm'))
+        self.assertFalse(self.is_active_unit('systemddm'))
+
+    def test_one_init(self):
+        '''one init dm is started'''
+
+        # fake removing lightdm (or we shoud remove all processes under lightdm)
+        os.remove(DDM_CONFIG_PATH)
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        os.remove(LIGHTDM_SYSTEMD_UNIT_PATH)
+        self.create_init_dm("initdm", make_ddm_default="initdm")
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('initdm'))
+
+    def test_multiple_init(self):
+        '''all init dms are enabled, regardless of ddm'''
+
+        # this enable to keep previous init behavior,
+        # especially when they don't support ddm config like nodm
+        os.remove(DDM_CONFIG_PATH)
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        os.remove(LIGHTDM_SYSTEMD_UNIT_PATH)
+        self.create_init_dm("initdm", make_ddm_default="initdm")
+        self.create_init_dm("otherinitdm")
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('initdm'))
+        self.assertTrue(self.is_active_unit('otherinitdm'))
+
+    def test_multiple_init_no_ddm(self):
+        '''all init dms are enabled, without any ddm file'''
+
+        os.remove(DDM_CONFIG_PATH)
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        os.remove(LIGHTDM_SYSTEMD_UNIT_PATH)
+        self.create_init_dm("initdm")
+        self.create_init_dm("otherinitdm")
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('initdm'))
+        self.assertTrue(self.is_active_unit('otherinitdm'))
+
+    def test_systemd_matches_ddm_and_init(self):
+        '''default ddm config systemd is enabled as well as all inits'''
+
+        # lightdm is the default
+        self.create_init_dm("initdm")
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('initdm'))
+
+    def test_systemd_and_init_matches_ddm(self):
+        '''default ddm init prevents systemd units to start'''
+
+        self.create_init_dm("initdm", make_ddm_default="initdm")
+        self.reload_state()
+
+        self.assertFalse(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('initdm'))
+
+    def test_no_ddmconfig_multiple_systemd_and_init(self):
+        '''no ddm config let default systemd and all init dms enabled'''
+
+        os.remove(DDM_CONFIG_PATH)
+        self.create_systemd_dm_unit("systemddm")
+        self.create_init_dm("initdm")
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('initdm'))
+        self.assertFalse(self.is_active_unit('systemddm'))
+
+    def test_no_ddmconfig_no_default_systemd_and_init(self):
+        '''no ddm config default systemd unit will only have init dms enabled'''
+
+        os.remove(DDM_CONFIG_PATH)
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        self.create_systemd_dm_unit("systemddm")
+        self.create_init_dm("initdm")
+        self.reload_state()
+
+        self.assertFalse(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('initdm'))
+        self.assertFalse(self.is_active_unit('systemddm'))
+
+    # NOTE: I think init shouldn't start in that case
+    def test_one_systemd_one_init_masked_symlink_with_ddmconfig(self):
+        '''a masked symlink will be updated to match systemd ddmconfig systemd unit and init is started'''
+
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
+        self.create_init_dm("initdm")
+        self.reload_state()
+
+        self.assertTrue(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('initdm'))
+
+    # NOTE: I think init shouldn't start in that case
+    def test_one_systemd_one_init_masked_symlink_no_ddmconfig(self):
+        '''without any ddm config, a masked symlinked will stayed masked, but init will be started'''
+
+        os.remove(DDM_CONFIG_PATH)
+        os.remove(SYSTEMD_DEFAULT_DM_PATH)
+        os.symlink("/dev/null", SYSTEMD_DEFAULT_DM_PATH)
+        self.create_init_dm("initdm")
+        self.reload_state()
+
+        self.assertFalse(self.is_active_unit('lightdm'))
+        self.assertTrue(self.is_active_unit('initdm'))
+
+    # Helper methods
+
+    def create_systemd_dm_unit(self, name, make_ddm_default=None):
+        dest_unit = "{}.service".format(os.path.join(SYSTEMD_SYSTEM_UNIT_DIR, name))
+        shutil.copy(LIGHTDM_SYSTEMD_UNIT_PATH, dest_unit)
+        # remove BusName to avoid conflicts
+        for line in fileinput.input([LIGHTDM_SYSTEMD_UNIT_PATH], inplace=True):
+            if not line.startswith('BusName='):
+                print(line)
+        self.files_to_clean.append(dest_unit)
+
+        if make_ddm_default:
+            self.make_ddm_default(make_ddm_default)
+
+    def create_init_dm(self, name, make_ddm_default=None):
+        init_script = "/etc/init.d/{}".format(name)
+        with open(init_script, 'w') as f:
+            f.write('''#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          {service}
+# Required-Start:    $local_fs $remote_fs dbus
+# Required-Stop:     $local_fs $remote_fs dbus
+# Should-Start:      $named
+# Should-Stop:       $named
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Start {service}
+### END INIT INFO
+exit 0'''.format(service=name))
+            os.fchmod(f.fileno(), 0o755)
+        self.files_to_clean.append(init_script)
+
+        rc2_link = "/etc/rc2.d/S05{}".format(name)
+        os.symlink("../init.d/{}".format(name), rc2_link)
+        self.files_to_clean.append(rc2_link)
+
+        insserv_script = "/etc/insserv.conf.d/{}".format(name)
+        with open(insserv_script, 'w') as f:
+            f.write("$x-display-manager {}".format(name))
+        self.files_to_clean.append(insserv_script)
+        if make_ddm_default:
+            self.make_ddm_default(make_ddm_default)
+
+    def make_ddm_default(self, binary_name):
+        with open(DDM_CONFIG_PATH, 'w') as f:
+            f.write("/usr/bin/{}".format(binary_name))
+
+    def is_active_unit(self, unit):
+        '''Check that given unit is active'''
+
+        if subprocess.call(['systemctl', '-q', 'is-active', unit]) != 0:
+            return False
+        return True
+
+    def reload_state(self):
+        subprocess.check_call(['systemctl', 'daemon-reload'])
+        subprocess.check_call(['systemctl', 'default'])
+        sleep(2)  # a more robust way would be to loop over remaining jobs to process
+
+
+def boot_with_systemd():
+    '''Reboot with systemd as init
+
+    In case something else is currently running in the testbed
+    '''
+    if subprocess.call(['systemctl', 'status'], stdout=subprocess.PIPE,
+                       stderr=subprocess.PIPE) != 0:
+        print('Installing systemd-sysv and rebooting...')
+        subprocess.check_call('apt-get -y install systemd-sysv 2>&1',
+                              shell=True)
+        subprocess.check_call(['autopkgtest-reboot', 'boot-systemd'])
+
+
+if __name__ == '__main__':
+    if not os.getenv('ADT_REBOOT_MARK'):
+        boot_with_systemd()
+
+    unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
+                                                     verbosity=2))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.alioth.debian.org/pipermail/pkg-systemd-maintainers/attachments/20150113/166cb515/attachment-0001.sig>


More information about the Pkg-systemd-maintainers mailing list