Commit f58540d3 authored by Christoph Berg's avatar Christoph Berg Committed by Christoph Berg

pg_ctlcluster: Redirect requests to systemd when invoked as root

pg_ctlcluster: Redirect requests to systemd when invoked as root and no
extra pg_ctl or postgres options are given.
Starting running clusters and stopping stopped clusters will return 0
now (was 2 in the native implementation).
parent 44f36070
......@@ -14,6 +14,10 @@ postgresql-common (171) UNRELEASED; urgency=medium
* pg_buildext: Replace multiple occurrences of PGVERSION on the same line,
and implement replacing for debian/tests/control.in.
* t/015_start_stop.t: Validate pg_ctlcluster/systemctl exit codes.
* pg_ctlcluster: Redirect requests to systemd when invoked as root and no
extra pg_ctl or postgres options are given.
Starting running clusters and stopping stopped clusters will return 0 now
(was 2 in the native implementation).
[ Martin Pitt ]
* pg_upgradecluster: Fix "ANALZYE" typo.
......
......@@ -582,8 +582,13 @@ foreach my $guc (@pgoptions) {
}
# notify systemd about the new cluster
if (not exists $ENV{'PG_CLUSTER_CONF_ROOT'} and $startconf eq 'auto' and -d '/var/run/systemd/system' and $euid == 0) {
system 'systemctl daemon-reload';
if (not exists $ENV{'PG_CLUSTER_CONF_ROOT'} and $startconf eq 'auto' and -d '/run/systemd/system') {
if ($> == 0) {
system 'systemctl daemon-reload';
} elsif (-t 1) {
print "Warning: systemd does not know about the new cluster yet. Operations like \"service postgresql start\" will not handle it. To fix, run:\n";
print " sudo systemctl daemon-reload\n";
}
}
# start it if requested
......
......@@ -108,7 +108,7 @@ sub cluster_port_ready {
}
if ($out =~ 'FATAL:') {
print STDERR "WARNING: connection to the database failed, disabling startup checks:\n$out\n";
print STDERR "Warning: connection to the database failed, disabling startup checks:\n$out\n";
return cluster_port_running $v, $c, $p;
}
return !$result;
......@@ -320,12 +320,13 @@ sub promote {
# main
#
my ($bindir);
my ($skip_systemctl_redirect, $bindir);
exit 1 unless GetOptions ('o|options=s' => \@postmaster_auxoptions,
'f|force' => \$force,
'm|mode=s' => \$mode,
'foreground' => \$foreground,
'skip-systemctl-redirect' => \$skip_systemctl_redirect,
'stdlog' => \$stdlog,
'bindir=s' => \$bindir,
);
......@@ -391,15 +392,43 @@ if (($< == 0 or $> == 0) and $info{'configuid'} != 0 and
error "Config owner ($configowner:$info{configuid}) and data owner ($dataowner:$info{owneruid}) do not match, and config owner is not root";
}
# WIP:
## redirect the request through systemd (if we are root and we are not a direct pid 1 child)
#if ($> == 0 and getppid() != 1 and -d '/var/run/systemd/system' and not exists $ENV{_SYSTEMCTL_SKIP_REDIRECT} and not exists $ENV{'PG_CLUSTER_CONF_ROOT'}) {
# if ($action =~ /^(start|stop|restart)$/) {
# print "Redirecting $1 request to systemctl\n";
# system ('systemctl', $1, "postgresql\@$version-$cluster");
# exit $? >> 8;
# }
#}
# redirect the request through systemd
if (not $skip_systemctl_redirect and getppid() != 1 and # not run from init
-d '/run/systemd/system' and not exists $ENV{_SYSTEMCTL_SKIP_REDIRECT} and # systemd is running
not exists $ENV{'PG_CLUSTER_CONF_ROOT'} and # not handling user clusters
$action =~ /^(start|stop|restart)$/ # redirect only these actions
) {
$action = $1; # untaint
system 'systemctl', 'is-active', '-q', "postgresql\@$version-$cluster";
my $unit_active = $? == 0;
# if extra options are given, proceed with pg_ctlcluster with a warning
if (@postmaster_auxoptions != 0 or @pg_ctl_opts_from_cli != 0) { # extra options given
print "Notice: extra pg_ctl/postgres options given, bypassing systemctl for $action operation\n" if (-t 1);
# if we are root, redirect to systemctl unless stopping a cluster running outside systemd
} elsif ($> == 0) {
if ($action eq 'stop' and not $unit_active) {
# proceed with pg_ctlcluster
} else {
print "Redirecting $action request to systemctl\n" if (-t 1);
system 'systemctl', $action, "postgresql\@$version-$cluster";
exit $? >> 8;
# program end
}
# as non-root, raise an error on restarting a cluster running from systemd
} elsif ($action eq 'restart' and $unit_active) {
error "cluster is running from systemd, can only restart it as root. Try instead:\n sudo systemctl $action postgresql\@$version-$cluster";
# program end
# otherwise just raise a warning on start and restart as non-root
} elsif (-t 1) {
if ($action =~ /start/) {
print "Warning: the cluster will not be running as a systemd service. Consider using systemctl:\n";
} elsif ($unit_active) { # on stop, warn when running from systemd
print "Warning: stopping the cluster using pg_ctlcluster will mark the systemd unit as failed. Consider using systemctl:\n";
}
print " sudo systemctl $action postgresql\@$version-$cluster\n";
}
}
# recreate missing standard log dir
if ($> == 0 && ! -e '/var/log/postgresql' &&
......
......@@ -104,8 +104,13 @@ if ($info{statstempdir}) {
}
# notify systemd when an autostarted cluster went away
if ($startconf eq 'auto' and -d '/var/run/systemd/system' and $> == 0) {
system 'systemctl daemon-reload';
if (not exists $ENV{'PG_CLUSTER_CONF_ROOT'} and $startconf eq 'auto' and -d '/run/systemd/system') {
if ($> == 0) {
system 'systemctl daemon-reload';
} elsif (-t 1) {
print "Warning: systemd was not informed about the removed yet. Operations like \"service postgresql start\" might fail. To fix, run:\n";
print " sudo systemctl daemon-reload\n";
}
}
exit 0;
......
......@@ -13,9 +13,9 @@ Before=postgresql.service
[Service]
Type=forking
# @: use "postgresql@%i" as process name
ExecStart=@/usr/bin/pg_ctlcluster postgresql@%i %i start
ExecStop=/usr/bin/pg_ctlcluster -m fast %i stop
ExecReload=/usr/bin/pg_ctlcluster %i reload
ExecStart=@/usr/bin/pg_ctlcluster postgresql@%i --skip-systemctl-redirect %i start
ExecStop=/usr/bin/pg_ctlcluster --skip-systemctl-redirect -m fast %i stop
ExecReload=/usr/bin/pg_ctlcluster --skip-systemctl-redirect %i reload
PIDFile=/var/run/postgresql/%i.pid
SyslogIdentifier=postgresql@%i
# prevent OOM killer from choosing the postmaster (individual backends will
......
......@@ -126,7 +126,7 @@ if [ -z "${NO_TMPFS:-}" ]; then
chown postgres:postgres /var/run/postgresql ; chmod 2775 /var/run/postgresql
fi
if [ -d /var/run/systemd/system ]; then
if [ -d /run/systemd/system ]; then
systemctl daemon-reload # poke generator to forget the system's clusters
fi
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment