Blame SOURCES/bz1736746-podman-drop-in-support.patch

734564
From 462ada6164cb77c81f5291d88287d68506d38056 Mon Sep 17 00:00:00 2001
734564
From: Damien Ciabrini <dciabrin@redhat.com>
734564
Date: Tue, 9 Jul 2019 23:14:21 +0200
734564
Subject: [PATCH] Generate addition drop-in dependencies for podman containers
734564
734564
When podman creates a container, it creates two additional systemd
734564
scope files dynamically:
734564
734564
  - libpod-conmon-<CONTAINERID>.scope - runs a conmon process that
734564
    tracks a container's pid1 into a dedicated pidfile.
734564
  - libpod-<CONTAINERID>.scope - created dynamically by runc,
734564
    for cgroups accounting
734564
734564
On shutdown, it can happen that systemd stops those scope early,
734564
which in turn sends a SIGTERM to pacemaker-managed containers
734564
before pacemaker has scheduled any stop operation. That
734564
confuses the cluster and may break shutdown.
734564
734564
Add a new option in the resource-agent to inject additional
734564
dependencies into the dynamically created scope files, so that
734564
systemd is not allowed to stop scopes before the pacemaker
734564
service itself is stopped.
734564
734564
When that option is enabled, the scopes look like:
734564
734564
    # podman ps | grep galera
734564
    c329819a1227  192.168.122.8:8787/rhosp15/openstack-mariadb:latest                     dumb-init -- /bin...  About an hour ago  Up About an hour ago         galera-bundle-podman-0
734564
734564
    # systemctl cat libpod*c329819a1227*
734564
    # /run/systemd/transient/libpod-conmon-c329819a1227ec548d678861994ef755b1fde9a244e1e4d966d17674df88ce7b.scope
734564
    # This is a transient unit file, created programmatically via the systemd API. Do not edit.
734564
    [Scope]
734564
    Slice=machine.slice
734564
    Delegate=yes
734564
734564
    [Unit]
734564
    DefaultDependencies=no
734564
734564
    # /run/systemd/transient/libpod-conmon-c329819a1227ec548d678861994ef755b1fde9a244e1e4d966d17674df88ce7b.scope.d/dep.conf
734564
    [Unit]
734564
    Before=pacemaker.service
734564
734564
    # /run/systemd/transient/libpod-c329819a1227ec548d678861994ef755b1fde9a244e1e4d966d17674df88ce7b.scope
734564
    # This is a transient unit file, created programmatically via the systemd API. Do not edit.
734564
    [Unit]
734564
    Description=libcontainer container c329819a1227ec548d678861994ef755b1fde9a244e1e4d966d17674df88ce7b
734564
734564
    [Scope]
734564
    Slice=machine.slice
734564
    Delegate=yes
734564
    MemoryAccounting=yes
734564
    CPUAccounting=yes
734564
    BlockIOAccounting=yes
734564
734564
    [Unit]
734564
    DefaultDependencies=no
734564
734564
    # /run/systemd/transient/libpod-c329819a1227ec548d678861994ef755b1fde9a244e1e4d966d17674df88ce7b.scope.d/dep.conf
734564
    [Unit]
734564
    Before=pacemaker.service
734564
734564
Effectively, this prevents systemd from managing the shutdown of any
734564
pacemaker-managed podman container.
734564
734564
Related: rhbz#1726442
734564
---
734564
 heartbeat/podman | 82 +++++++++++++++++++++++++++++++++++++++++++++++-
734564
 1 file changed, 81 insertions(+), 1 deletion(-)
734564
734564
diff --git a/heartbeat/podman b/heartbeat/podman
734564
index 8fc2c4695..8a916eb8c 100755
734564
--- a/heartbeat/podman
734564
+++ b/heartbeat/podman
734564
@@ -158,6 +158,16 @@ to have the particular one persist when this happens.
734564
 <shortdesc lang="en">reuse container</shortdesc>
734564
 <content type="boolean" default="${OCF_RESKEY_reuse_default}"/>
734564
 </parameter>
734564
+
734564
+<parameter name="drop_in_dependency" required="0" unique="0">
734564
+<longdesc lang="en">
734564
+Use transient drop-in files to add extra dependencies to the systemd
734564
+scopes associated to the container. During reboot, this prevents systemd
734564
+to stop the container before pacemaker.
734564
+</longdesc>
734564
+<shortdesc lang="en">drop-in dependency</shortdesc>
734564
+<content type="boolean"/>
734564
+</parameter>
734564
 </parameters>
734564
 
734564
 <actions>
734564
@@ -273,8 +283,57 @@ podman_create_mounts() {
734564
 	IFS="$oldIFS"
734564
 }
734564
 
734564
+podman_container_id()
734564
+{
734564
+	# Retrieve the container ID by doing a "podman ps" rather than
734564
+	# a "podman inspect", because the latter has performance issues
734564
+	# under IO load.
734564
+	# We could have run "podman start $CONTAINER" to get the ID back
734564
+	# but if the container is stopped, the command will return a
734564
+	# name instead of a container ID. This would break us.
734564
+	podman ps --no-trunc --format '{{.ID}} {{.Names}}' | grep -F -w -m1 "$CONTAINER" | cut -d' ' -f1
734564
+}
734564
+
734564
+
734564
+create_transient_drop_in_dependency()
734564
+{
734564
+	local cid=$1
734564
+	local rc=$OCF_SUCCESS
734564
+
734564
+	if [ -z "$cid" ]; then
734564
+		ocf_log error "Container ID not found for \"$CONTAINER\". Not creating drop-in dependency"
734564
+		return $OCF_ERR_GENERIC
734564
+	fi
734564
+
734564
+	ocf_log info "Creating drop-in dependency for \"$CONTAINER\" ($cid)"
734564
+	for scope in "libpod-$cid.scope.d" "libpod-conmon-$cid.scope.d"; do
734564
+		if [ $rc -eq $OCF_SUCCESS ] && [ ! -d /run/systemd/transient/"$scope" ]; then
734564
+			mkdir -p /run/systemd/transient/"$scope" && \
734564
+			echo -e "[Unit]\nBefore=pacemaker.service" > /run/systemd/transient/"$scope"/dep.conf && \
734564
+			chmod ago+r /run/systemd/transient/"$scope" /run/systemd/transient/"$scope"/dep.conf
734564
+			rc=$?
734564
+		fi
734564
+	done
734564
+
734564
+	if [ $rc -ne $OCF_SUCCESS ]; then
734564
+		ocf_log error "Could not create drop-in dependency for \"$CONTAINER\" ($cid)"
734564
+	else
734564
+		systemctl daemon-reload
734564
+		rc=$?
734564
+		if [ $rc -ne $OCF_SUCCESS ]; then
734564
+			ocf_log error "Could not refresh service definition after creating drop-in for \"$CONTAINER\""
734564
+		fi
734564
+	fi
734564
+
734564
+	return $rc
734564
+}
734564
+
734564
+
734564
 podman_start()
734564
 {
734564
+	local cid
734564
+	local rc
734564
+
734564
 	podman_create_mounts
734564
 	local run_opts="-d --name=${CONTAINER}"
734564
 	# check to see if the container has already started
734564
@@ -306,8 +365,17 @@ podman_start()
734564
 		ocf_log info "running container $CONTAINER for the first time"
734564
 		ocf_run podman run $run_opts $OCF_RESKEY_image $OCF_RESKEY_run_cmd
734564
 	fi
734564
+	rc=$?
734564
 
734564
-	if [ $? -ne 0 ]; then
734564
+	# if the container was stopped or didn't exist before, systemd
734564
+	# removed the libpod* scopes. So always try to recreate the drop-ins
734564
+	if [ $rc -eq 0 ] && ocf_is_true "$OCF_RESKEY_drop_in_dependency"; then
734564
+		cid=$(podman_container_id)
734564
+		create_transient_drop_in_dependency "$cid"
734564
+		rc=$?
734564
+	fi
734564
+
734564
+	if [ $rc -ne 0 ]; then
734564
 		ocf_exit_reason "podman failed to launch container"
734564
 		return $OCF_ERR_GENERIC
734564
 	fi
734564
@@ -353,6 +421,8 @@ podman_stop()
734564
 	else
734564
 		ocf_log debug "waiting $timeout second[s] before killing container"
734564
 		ocf_run podman stop -t=$timeout $CONTAINER
734564
+		# on stop, systemd will automatically delete any transient
734564
+		# drop-in conf that has been created earlier
734564
 	fi
734564
 
734564
 	if [ $? -ne 0 ]; then
734564
@@ -456,6 +526,16 @@ CONTAINER=$OCF_RESKEY_name
734564
 # exec command to be non-empty
734564
 : ${OCF_RESKEY_monitor_cmd:=/bin/true}
734564
 
734564
+# When OCF_RESKEY_drop_in_dependency is not populated, we
734564
+# look at another file-based way of enabling the option.
734564
+# Otherwise, consider it disabled.
734564
+if [ -z "$OCF_RESKEY_drop_in_dependency" ]; then
734564
+	if [ -f "/etc/sysconfig/podman_drop_in" ] || \
734564
+	   [ -f "/etc/default/podman_drop_in" ]; then
734564
+		OCF_RESKEY_drop_in_dependency=yes
734564
+	fi
734564
+fi
734564
+
734564
 case $__OCF_ACTION in
734564
 meta-data) meta_data
734564
 		exit $OCF_SUCCESS;;