tripleo-heat-templates/deployment/neutron/kill-script
Rodolfo Alonso Hernandez 0bc1383a60 Force container deletion if namespace does not exist in service_kill
When a service is stopped using "service_kill" script and the
namespace where the container is running does not exist, the
container process should be forced to stop from the root namespace.

A namespace where a process is running, can be deleted whitout
stopping the mentioned process. "ip netns identify <PID>" then
returns an empty string (root namespace).

If the namespace where a container was executed is deleted,
"service_kill" script should execute a container related command
from the root namespace. To access to the root namespace from
inside a container, running in another namespace, it is necessary
to gain access via "nsenter", specifying the parameter "--all" to
access to all namespaces of the target process.

This patch will prevent an endless loop in Neutron DHCP agent. As
reported in the related bug, when a DHCP agent is resync, the DHCP
helper (metadata proxy) is stopped. In case this process stop raises
an exception (for example if the namespace does not exist), schedules
again a resync, creating an endless loop.

This patch combines [1] and [2] in this repository.
[1]https://review.opendev.org/#/c/714517/
[2]https://review.opendev.org/#/c/730657/

Change-Id: Ifb7dbfb93a7cf0b50ef15652d83d87f65bdb6221
Closes-Bug: #1868607
2020-05-26 13:59:42 +00:00

79 lines
1.6 KiB
Bash

#!/bin/bash
{% if debug_enabled|bool -%}
set -x
{% endif -%}
add_date() {
echo "$(date) $@"
}
# Set up script logging for debugging purpose.
# It will be taken care of by logrotate since there is the .log
# suffix.
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/var/log/neutron/kill-script.log 2>&1
SIG=$1
PID=$2
NETNS=$(ip netns identify ${PID})
{% if container_cli == 'podman' %}
if [ "x${NETNS}" == "x" ]; then
CLI="nsenter --all --preserve-credentials -t 1 podman"
SIG=9
else
CLI="nsenter --net=/run/netns/${NETNS} --preserve-credentials -m -t 1 podman"
fi
{% elif container_cli == 'docker' %}
{% if docker_additional_sockets and docker_additional_sockets|length > 0-%}
export DOCKER_HOST=unix://{{ docker_additional_sockets[0] }}
{% endif -%}
CLI='docker'
{% else %}
CLI='echo noop'
{% endif %}
kill_container() {
add_date "Stopping container $1 ($2)"
$CLI stop $2
add_date "Deleting container $1 ($2)"
$CLI rm $2
}
signal_container() {
SIGNAL=$3
if [ -z "$SIGNAL" ]; then
SIGNAL="HUP"
fi
add_date "Sending signal '$SIGNAL' to $1 ($2)"
$CLI kill --signal $SIGNAL $2
}
{% raw -%}
if [ -f /proc/$PID/cgroup ]; then
# Get container ID based on process cgroups
CT_ID=$(awk 'BEGIN {FS="[-.]"} /name=/{print $3}' /proc/$PID/cgroup)
CT_NAME=$($CLI inspect -f '{{.Name}}' $CT_ID)
case $SIG in
HUP)
signal_container $CT_NAME $CT_ID
;;
9)
kill_container $CT_NAME $CT_ID
;;
15)
signal_container $CT_NAME $CT_ID 15
;;
*)
add_date "Unknown action ${SIG} for ${CT_NAME} ${CT_ID}"
exit 1
;;
esac
else
add_date "No such PID: ${PID}"
exit 1
fi
{% endraw %}