[Pkg-systemd-maintainers] Bug#709842: [PATCH] Add new helper dh_installsystemd

Joey Hess joeyh at debian.org
Mon Jun 10 21:10:59 BST 2013


Michael Stapelberg wrote:
> Another important reason is that packages might only ship a service file
> without actually shipping a sysvinit script. This affects not so much
> actual daemons which are mandated by policy to ship a sysvinit script,
> but for example dbus-activated services.

I don't see how that's a problem; if there's no init script
dh_installinit would just handle the systemd part.

> While a package can have multiple init scripts, my point is that there
> is no 1:1 relationship between an init script and a systemd unit file.

I don't see that as particularly a problem with putting this into
dh_installinit.

> Triggers work well when all files are equal. In our case, service files
> have different requirements. Some of them don’t need to be enabled at
> all (e.g. static service files, or services which currently in sysvinit
> use $service_DISABLED=true in /etc/default/$service).

And you can't tell this from looking at the files?

> Is it guaranteed that our trigger ran before postinst is executed?

Don't think so.

> >> +=item B<--assume-sysv-present>
> >> +
> >> +When running B<dh_installsystemd> before B<dh_installinit>, init scripts might
> >> +not be installed yet and thus cannot be found by B<dh_installsystemd>. By
> >> +specifying B<--assume-sysv-present>, start/stop/restart will be done through
> >> +invoke-rc.d, i.e. no systemd-specific code will be generated.
> >
> > Why would anyone ever want to reorder the commands and use this
> > option?
> There are cases which require an alias (= symlink) to be present. This
> symlink is created by deb-systemd-enable. Take NetworkManager as an
> example: its upstream service file is called NetworkManager.service,
> whereas the init script is called
> /etc/init.d/network-manager. Therefore, using “invoke-rc.d
> network-manager start” (note the hyphen and capitalization) will not
> work, unless deb-systemd-enable is invoked _before_ invoke-rc.d.
> 
> This might also happen with other projects, so we should be able to
> handle it.

Hmm, so you need to run before dh_installinit so you can get the call to
deb-systemd-enable into the postinst before the call to invoke-rc.d?

But at the same time, you want to run after dh_installinit, so you can
tell when there is a corresponding init script for a service file.

> > All the above-quoted stuff is really ugly to put into debhelper. Do I
> > really want debhelper to need to play catch-up to format changes in
> > systemd files? To encode heuristics about getty? I don't think that's
> > appropriate.
> Note that the unit file format is covered by systemd’s interface
> stability promise:
> http://www.freedesktop.org/wiki/Software/systemd/InterfaceStabilityPromise/
> 
> Therefore I consider it extremely unlikely that this will
> break. Unfortunately, there is no better solution than re-implementing
> this, because systemd’s own tools rely on already having a running
> systemd available
> 
> If you feel really strongly about this and we should put dh_systemd into
> a separate package, please let us know. We thought it’d be nice for
> package maintainers to make things just work™, without modifications to
> their packages :).

That's not what I was trying to say. I like debhelper commands to be
thin wrappers around programs that handle the heavy lifting and the
domain-specific knowledge. This is why debhelper has a per-command LOC
limit.

If that were moved out to a serparate program, which would look perhaps
something like [1], dh_systemd would be a lot shorter, and then
we could perhaps make a better decision about whether or not it belongs
inside dh_installinit.

> +	if [ -x "/usr/bin/deb-systemd-helper" ]; then

Oh yeah, something else I don't like doing in debhelper is encoding the
current location in PATH of commands. Similar autoscripts use which

[1]

#!/usr/bin/perl
# Finds systemd service files installed in a directory, or listed
# on the command line. Outputs a list, which includes other service
# files listed in Also= lines of the found files. Indicates when
# service files have a corresponding sysvinit script.

# Extracts the Also= or Alias= line(s) from a unit file.
# In case this produces horribly wrong results, you can pass --no-also, but
# that should really not be necessary. Please report bugs to
# pkg-systemd-maintainers.
sub extract_key {
	my ($unit_path, $key) = @_;
	my @values;
	my $fh;

	if ($dh{NO_ALSO}) {
		return @values;
	}

	if (!open($fh, '<', $unit_path)) {
		warning("Cannot open($unit_path) for extracting the Also= line(s)");
		return;
	}
	while (my $line = <$fh>) {
		chomp($line);

		if ($line =~ /^\s*$key=(.+)$/i) {
			@values = (@values, shellwords($1));
		}
	}
	close($fh);
	return @values;
}

	find({
		wanted => sub {
			my $name = $File::Find::name;
			return unless -f $name;
			return unless $name =~ m,^$tmpdir/lib/systemd/system/[^/]+$,;
			push @installed_units, $name;
		},
		no_chdir => 1,
	}, $tmpdir);

	# Handle either only the unit files which were passed as arguments or
	# all unit files that are installed in this package.
	my @args = @ARGV > 0 ? @ARGV : @installed_units;

	# This hash prevents us from looping forever in the following while loop.
	# An actual real-world example of such a loop is systemd’s
	# systemd-readahead-drop.service, which contains
	# Also=systemd-readahead-collect.service, and that file in turn
	# contains Also=systemd-readahead-drop.service, thus forming an endless
	# loop.
	my %seen;

	# We use while/shift because we push to the list in the body.
	while (@args) {
		my $name = shift @args;
		my $base = basename($name);

		# Skip template service files like e.g. getty at .service.
		# Enabling, disabling, starting or stopping those services
		# without specifying the instance (e.g. getty at ttyS0.service) is
		# not useful.
		if ($name =~ /\@/) {
			return;
		}

		# Handle all unit files specified via Also= explicitly.
		# This is not necessary for enabling, but for disabling, as we
		# cannot read the unit file when disabling (it was already
		# deleted).
		my @also = grep { !exists($seen{$_}) } extract_key($name, 'Also');
		$seen{$_} = 1 for @also;
		@args = (@args, @also);

		$aliases{$name} = [ extract_key($name, 'Alias') ];
		my @sysv = grep {
				my $base = $_;
				$base =~ s/\.service$//g;
				-f "$tmpdir/etc/init.d/$base"
			} ($base, @{$aliases{$name}});
		if (@sysv > 0 || $dh{ASSUME_SYSV_PRESENT}) {
			$unitfiles{$name} = 'sysv';
		} else {
			$unitfiles{$name} = 'systemd-only';
		}
	}

-- 
see shy jo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 828 bytes
Desc: Digital signature
URL: <http://alioth-lists.debian.net/pipermail/pkg-systemd-maintainers/attachments/20130610/e0a486d5/attachment-0001.sig>


More information about the Pkg-systemd-maintainers mailing list