diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 84dbaca39854..1575dd56abda 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -163,6 +163,9 @@ sudo cp $IMAGE_CONFIGS/hostname/hostname-config.service $FILESYSTEM_ROOT/etc/sy sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostname-config.service sudo cp $IMAGE_CONFIGS/hostname/hostname-config.sh $FILESYSTEM_ROOT/usr/bin/ +# Copy miscellaneous scripts +sudo cp $IMAGE_CONFIGS/misc/docker-wait-any $FILESYSTEM_ROOT/usr/bin/ + # Copy updategraph script and service file j2 files/build_templates/updategraph.service.j2 | sudo tee $FILESYSTEM_ROOT/etc/systemd/system/updategraph.service sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable updategraph.service diff --git a/files/build_templates/swss.service.j2 b/files/build_templates/swss.service.j2 index d01a8fdbd22e..56c0c1ca98b6 100644 --- a/files/build_templates/swss.service.j2 +++ b/files/build_templates/swss.service.j2 @@ -41,8 +41,7 @@ ExecStartPre=/etc/init.d/xpnet.sh start ExecStartPre=/usr/bin/{{docker_container_name}}.sh start ExecStartPre=/usr/bin/syncd.sh start -ExecStartPre=/usr/bin/{{docker_container_name}}.sh start -ExecStart=/bin/bash -c "sleep 5; while true; do if [ x\"$(docker inspect -f {{'{{'}}.State.Running{{'}}'}} {{docker_container_name}})\" != x\"true\" ] || [ x\"$(docker inspect -f {{'{{'}}.State.Running{{'}}'}} syncd)\" != x\"true\" ]; then break; fi; sleep 1; done" +ExecStart=/bin/bash -c "sleep 5; /usr/bin/docker-wait-any {{docker_container_name}} syncd" ExecStop=/usr/bin/{{docker_container_name}}.sh stop ExecStopPost=/usr/bin/syncd.sh stop diff --git a/files/image_config/misc/docker-wait-any b/files/image_config/misc/docker-wait-any new file mode 100755 index 000000000000..ed8d2d9c083d --- /dev/null +++ b/files/image_config/misc/docker-wait-any @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +""" + docker-wait-any + + This script takes one or more Docker container names as arguments, + and it will block indefinitely while all of the specified containers + are running. If any of the specified containers stop, the script will + exit. + + This script was created because the 'docker wait' command is lacking + this functionality. It will block until ALL specified containers have + stopped running. Here, we spawn multiple threads and wait on one + container per thread. If any of the threads exit, the entire + application will exit. + + NOTE: This script is written against docker-py version 1.6.0. Newer + versions of docker-py have a different API. +""" + +import sys +import threading +from docker import Client + +# Instantiate a global event to share among our threads +g_thread_exit_event = threading.Event() + + +def usage(): + print("Usage: {} [ ...]".format(sys.argv[0])) + sys.exit(1) + + +def wait_for_container(docker_client, container_name): + docker_client.wait(container_name) + + print("No longer waiting on container '{}'".format(container_name)) + + # Signal the main thread to exit + g_thread_exit_event.set() + + +def main(): + thread_list = [] + + docker_client = Client(base_url='unix://var/run/docker.sock') + + # Ensure we were passed at least one argument + if len(sys.argv) < 2: + usage() + + container_names = sys.argv[1:] + + for container_name in container_names: + t = threading.Thread(target=wait_for_container, args=[docker_client, container_name]) + t.daemon = True + t.start() + thread_list.append(t) + + # Wait until we receive an event signifying one of the containers has stopped + g_thread_exit_event.wait() + sys.exit(0) + +if __name__ == '__main__': + main()