summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Brandstetter <christian.brandstetter@est.fujitsu.com>2018-07-25 13:09:47 +0200
committerDobroslaw Zybort <dobroslaw.zybort@ts.fujitsu.com>2018-10-05 15:42:57 +0200
commit392b325a73693c3d6b1efe6b3bced0ca0ca3570b (patch)
treeb5f004c0cdb25b6e31ff6e86cc52d8e762450864
parentc8b9b81f61a2b7b49bb32d6865afbc6153b37db2 (diff)
Add tooling for building Docker image
Notes
Notes (review): Code-Review+2: Witold Bedyk <witold.bedyk@est.fujitsu.com> Workflow+1: Amir Mofakhar <amir@mofakhar.info> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Sat, 06 Oct 2018 07:01:32 +0000 Reviewed-on: https://review.openstack.org/585712 Project: openstack/monasca-notification Branch: refs/heads/master
-rw-r--r--docker/Dockerfile38
-rw-r--r--docker/README.rst138
-rwxr-xr-xdocker/build_image.sh147
-rw-r--r--docker/health_check.py27
-rw-r--r--docker/notification.yaml.j2154
-rw-r--r--docker/start.sh41
6 files changed, 545 insertions, 0 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..dc5a7a7
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,38 @@
1ARG DOCKER_IMAGE=monasca/notification
2ARG APP_REPO=https://git.openstack.org/openstack/monasca-notification
3
4# Branch, tag or git hash to build from.
5ARG REPO_VERSION=master
6ARG CONSTRAINTS_BRANCH=master
7ARG COMMON_VERSION=master
8
9# Extra Python3 dependencies.
10ARG EXTRA_DEPS="netaddr gevent==1.3.5 greenlet"
11
12# Always start from `monasca-base` image and use specific tag of it.
13ARG BASE_TAG=master
14FROM monasca/base:$BASE_TAG
15
16# Environment variables used for our service or wait scripts.
17ENV \
18 KAFKA_URI=kafka:9092 \
19 KAFKA_WAIT_FOR_TOPICS=retry-notifications,alarm-state-transitions,alarm-notifications,60-seconds-notifications \
20 ZOOKEEPER_URL=zookeeper:2181 \
21 ALARM_PROCESSORS=2 \
22 NOTIFICATION_PROCESSORS=2 \
23 RETRY_INTERVAL=30 \
24 RETRY_MAX_ATTEMPTS=5 \
25 MYSQL_DB_HOST=mysql \
26 MYSQL_DB_PORT=3306 \
27 MYSQL_DB_USERNAME=notification \
28 MYSQL_DB_PASSWORD=password \
29 MYSQL_DB_DATABASE=mon \
30 STATSD_HOST=monasca-statsd \
31 STATSD_PORT=8125 \
32 STAY_ALIVE_ON_FAILURE="false"
33
34# Copy all neccessary files to proper locations.
35COPY notification.yaml.j2 /etc/monasca/
36
37# Implement start script in `start.sh` file.
38CMD ["/start.sh"]
diff --git a/docker/README.rst b/docker/README.rst
new file mode 100644
index 0000000..1f09de2
--- /dev/null
+++ b/docker/README.rst
@@ -0,0 +1,138 @@
1=====================================
2Docker image for Monasca notification
3=====================================
4The Monasca notification image is based on the monasca-base image.
5
6
7Building monasca-base image
8===========================
9See https://github.com/openstack/monasca-common/tree/master/docker/README.rst
10
11
12Building Monasca notification image
13===================================
14
15Example:
16 $ ./build_image.sh <repository_version> <upper_constains_branch> <common_version>
17
18Requirements from monasca-base image
19~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20health_check.py
21 This file will be used for checking the status of the Monasca persister
22 application.
23
24
25Scripts
26~~~~~~~
27start.sh
28 In this starting script provide all steps that lead to the proper service
29 start. Including usage of wait scripts and templating of configuration
30 files. You also could provide the ability to allow running container after
31 service died for easier debugging.
32
33build_image.sh
34 Please read detailed build description inside the script.
35
36
37Environment variables
38~~~~~~~~~~~~~~~~~~~~~
39============================== ======================================================================================== ================================================
40Variable Default Description
41============================== ======================================================================================== ================================================
42KAFKA_URI kafka:9092 The host and port for kafka
43KAFKA_WAIT_FOR_TOPICS retry-notifications,alarm-state-transitions,alarm-notifications,60-seconds-notifications Topics to wait on at startup
44KAFKA_WAIT_RETRIES 24 Number of kafka connect attempts
45KAFKA_WAIT_DELAY 5 Seconds to wait between attempts
46ZOOKEEPER_URL zookeeper:2181 URL to Zookeeper
47ALARM_PROCESSORS 2 Number of alarm processing threads
48NOTIFICATION_PROCESSORS 2 Number of notification processing threads
49RETRY_INTERVAL 30 Retry interval in seconds
50RETRY_MAX_ATTEMPTS 5 Max number of notification retries
51LOG_LEVEL WARN Logging level
52STATSD_HOST monasca-statsd Monasca agent StatsD host for self-monitoring
53STATSD_PORT 8125 Monasca agent StatsD port for self-monitoring
54NF_PLUGINS <not set> See below "Notification Plugins"
55MYSQL_DB_HOST mysql The host for MySQL
56MYSQL_DB_PORT 3306 The port for MySQL
57MYSQL_DB_USERNAME notification The MySQL username
58MYSQL_DB_PASSWORD password The MySQL password
59MYSQL_DB_DATABASE mon The MySQL database name
60STAY_ALIVE_ON_FAILURE false If true, container runs 2 hours even start fails
61============================== ======================================================================================== ================================================
62
63
64Notification Plugins
65--------------------
66A list of notification plugins can be provided by setting NF_PLUGINS to a comma-separated list of plugin names
67e.g. email,webhook,hipchat.
68
69
70Email
71-----
72Name: email
73
74This plugin sends email notifications when an alarm is triggered.
75
76Options:
77 * NF_EMAIL_SERVER: SMTP server address, required, unset by default
78 * NF_EMAIL_PORT: SMTP server port, default: 25
79 * NF_EMAIL_USER: SMTP username, optional, unset by default
80 * NF_EMAIL_PASSWORD, SMTP password, required only if NF_EMAIL_USER is set
81 * NF_EMAIL_FROM_ADDR: "from" field for emails sent, e.g. "Name" <name@example.com>
82
83
84Webhook
85-------
86Name: webhook
87
88This plugin calls a webhook when an alarm is triggered. Specific parameters, like the URL to load, are part of the notification rather than the notification plugin.
89
90Options:
91 * NF_WEBHOOK_TIMEOUT: timeout in seconds, default: 5
92
93
94PagerDuty
95---------
96Name: pagerduty
97
98Creates a PagerDuty event for the given alarm.
99
100Options:
101 * NF_PAGERDUTY_TIMEOUT: timeout in seconds, default: 5
102 * NF_PAGERDUTY_URL: PagerDuty Event API endpoint, defaults to official URL
103
104
105HipChat
106-------
107Name: hipchat
108
109Notifies via a HipChat message to some room. Authentication and destination details are configured with the notification.
110
111Options:
112 * NF_HIPCHAT_TIMEOUT: timeout in seconds, default: 5
113 * NF_HIPCHAT_SSL_CERTS: path to SSL certs, default: system certs
114 * NF_HIPCHAT_INSECURE: if true, don't verify SSL
115 * NF_HIPCHAT_PROXY: if set, use the given HTTP(S) proxy server to send notifications
116
117
118Slack
119-----
120Name: slack
121
122Notifies via a Slack message.
123
124Options:
125 * NF_SLACK_TIMEOUT: timeout in seconds, default: 5
126 * NF_SLACK_CERTS: path to SSL certs, default: system certs
127 * NF_SLACK_INSECURE: if true, don't verify SSL
128 * NF_SLACK_PROXY: if set, use the given HTTP(S) proxy server to send notifications
129
130
131Provide Configuration templates
132~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
133* notification.yaml.j2
134
135
136Links
137~~~~~
138https://github.com/openstack/monasca-notification/blob/master/README.rst
diff --git a/docker/build_image.sh b/docker/build_image.sh
new file mode 100755
index 0000000..0f54b83
--- /dev/null
+++ b/docker/build_image.sh
@@ -0,0 +1,147 @@
1#!/bin/bash
2
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15# TODO(Dobroslaw): move this script to monasca-common/docker folder
16# and leave here small script to download it and execute using env variables
17# to minimize code duplication.
18
19set -x # Print each script step.
20set -eo pipefail # Exit the script if any statement returns error.
21
22# This script is used for building Docker image with proper labels
23# and proper version of monasca-common.
24#
25# Example usage:
26# $ ./build_image.sh <repository_version> <upper_constains_branch> <common_version>
27#
28# Everything after `./build_image.sh` is optional and by default configured
29# to get versions from `Dockerfile`.
30#
31# To build from master branch (default):
32# $ ./build_image.sh
33# To build specific version run this script in the following way:
34# $ ./build_image.sh stable/queens
35# Building from specific commit:
36# $ ./build_image.sh cb7f226
37# When building from a tag monasca-common will be used in version available
38# in upper constraint file:
39# $ ./build_image.sh 2.5.0
40# To build image from Gerrit patch sets that is targeting branch stable/queens:
41# $ ./build_image.sh refs/changes/51/558751/1 stable/queens
42#
43# If you want to build image with custom monasca-common version you need
44# to provide it as in the following example:
45# $ ./build_image.sh master master refs/changes/19/595719/3
46
47[ -z "$DOCKER_IMAGE" ] && \
48 DOCKER_IMAGE=$(\grep DOCKER_IMAGE Dockerfile | cut -f2 -d"=")
49
50: "${REPO_VERSION:=$1}"
51[ -z "$REPO_VERSION" ] && \
52 REPO_VERSION=$(\grep REPO_VERSION Dockerfile | cut -f2 -d"=")
53# Let's stick to more readable version and disable SC2001 here.
54# shellcheck disable=SC2001
55REPO_VERSION_CLEAN=$(echo "$REPO_VERSION" | sed 's|/|-|g')
56
57[ -z "$APP_REPO" ] && APP_REPO=$(\grep APP_REPO Dockerfile | cut -f2 -d"=")
58GITHUB_REPO=$(echo "$APP_REPO" | sed 's/git.openstack.org/github.com/' | \
59 sed 's/ssh:/https:/')
60
61if [ -z "$CONSTRAINTS_FILE" ]; then
62 CONSTRAINTS_FILE=$(\grep CONSTRAINTS_FILE Dockerfile | cut -f2 -d"=") || true
63 : "${CONSTRAINTS_FILE:=http://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}"
64fi
65
66: "${CONSTRAINTS_BRANCH:=$2}"
67[ -z "$CONSTRAINTS_BRANCH" ] && \
68 CONSTRAINTS_BRANCH=$(\grep CONSTRAINTS_BRANCH Dockerfile | cut -f2 -d"=")
69
70# When using stable version of repository use same stable constraints file.
71case "$REPO_VERSION" in
72 *stable*)
73 CONSTRAINTS_BRANCH_CLEAN="$REPO_VERSION"
74 # Get monasca-common version from stable upper constraints file.
75 CONSTRAINTS_TMP_FILE=$(mktemp)
76 wget --output-document "$CONSTRAINTS_TMP_FILE" \
77 "$CONSTRAINTS_FILE"?h="$CONSTRAINTS_BRANCH_CLEAN"
78 UPPER_COMMON=$(\grep 'monasca-common' "$CONSTRAINTS_TMP_FILE")
79 # Get only version part from monasca-common.
80 UPPER_COMMON_VERSION="${UPPER_COMMON##*===}"
81 rm -rf "$CONSTRAINTS_TMP_FILE"
82 ;;
83 *)
84 CONSTRAINTS_BRANCH_CLEAN="$CONSTRAINTS_BRANCH"
85 ;;
86esac
87
88# Monasca-common variables.
89if [ -z "$COMMON_REPO" ]; then
90 COMMON_REPO=$(\grep COMMON_REPO Dockerfile | cut -f2 -d"=") || true
91 : "${COMMON_REPO:=https://git.openstack.org/openstack/monasca-common}"
92fi
93
94: "${COMMON_VERSION:=$3}"
95if [ -z "$COMMON_VERSION" ]; then
96 COMMON_VERSION=$(\grep COMMON_VERSION Dockerfile | cut -f2 -d"=") || true
97 if [ "$UPPER_COMMON_VERSION" ]; then
98 # Common from upper constraints file.
99 COMMON_VERSION="$UPPER_COMMON_VERSION"
100 fi
101fi
102
103# Clone project to temporary directory for getting proper commit number from
104# branches and tags. We need this for setting proper image labels.
105# Docker does not allow to get any data from inside of system when building
106# image.
107TMP_DIR=$(mktemp -d)
108(
109 cd "$TMP_DIR"
110 # This many steps are needed to support gerrit patch sets.
111 git init
112 git remote add origin "$APP_REPO"
113 git fetch origin "$REPO_VERSION"
114 git reset --hard FETCH_HEAD
115)
116GIT_COMMIT=$(git -C "$TMP_DIR" rev-parse HEAD)
117[ -z "${GIT_COMMIT}" ] && echo "No git commit hash found" && exit 1
118rm -rf "$TMP_DIR"
119
120# Do the same for monasca-common.
121COMMON_TMP_DIR=$(mktemp -d)
122(
123 cd "$COMMON_TMP_DIR"
124 # This many steps are needed to support gerrit patch sets.
125 git init
126 git remote add origin "$COMMON_REPO"
127 git fetch origin "$COMMON_VERSION"
128 git reset --hard FETCH_HEAD
129)
130COMMON_GIT_COMMIT=$(git -C "$COMMON_TMP_DIR" rev-parse HEAD)
131[ -z "${COMMON_GIT_COMMIT}" ] && echo "No git commit hash found" && exit 1
132rm -rf "$COMMON_TMP_DIR"
133
134CREATION_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
135
136docker build --no-cache \
137 --build-arg CREATION_TIME="$CREATION_TIME" \
138 --build-arg GITHUB_REPO="$GITHUB_REPO" \
139 --build-arg APP_REPO="$APP_REPO" \
140 --build-arg REPO_VERSION="$REPO_VERSION" \
141 --build-arg GIT_COMMIT="$GIT_COMMIT" \
142 --build-arg CONSTRAINTS_FILE="$CONSTRAINTS_FILE" \
143 --build-arg CONSTRAINTS_BRANCH="$CONSTRAINTS_BRANCH_CLEAN" \
144 --build-arg COMMON_REPO="$COMMON_REPO" \
145 --build-arg COMMON_VERSION="$COMMON_VERSION" \
146 --build-arg COMMON_GIT_COMMIT="$COMMON_GIT_COMMIT" \
147 --tag "$DOCKER_IMAGE":"$REPO_VERSION_CLEAN" .
diff --git a/docker/health_check.py b/docker/health_check.py
new file mode 100644
index 0000000..d71e75f
--- /dev/null
+++ b/docker/health_check.py
@@ -0,0 +1,27 @@
1#!/usr/bin/env python
2# coding=utf-8
3
4# (C) Copyright 2018 FUJITSU LIMITED
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
18"""Health check will returns 0 when service is working properly."""
19
20
21def main():
22 """health check for Monasca-notification"""
23 #TODO wait for health check endpoint ...
24 return 0
25
26if __name__ == '__main__':
27 main()
diff --git a/docker/notification.yaml.j2 b/docker/notification.yaml.j2
new file mode 100644
index 0000000..cf54754
--- /dev/null
+++ b/docker/notification.yaml.j2
@@ -0,0 +1,154 @@
1# (C) Copyright 2017 Hewlett Packard Enterprise Development LP
2# Copyright 2018 Fujitsu LIMITED
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16kafka:
17 url: {{ KAFKA_URI | default('kafka:9092') }}
18 group: "monasca-notification"
19 alarm_topic: "alarm-state-transitions"
20 notification_topic: "alarm-notifications"
21 notification_retry_topic: "retry-notifications"
22 periodic:
23 60: 60-seconds-notifications
24 max_offset_lag: 600 # In seconds, undefined for none
25
26mysql:
27 host: "{{ MYSQL_DB_HOST | default('mysql') }}"
28 port: {{ MYSQL_DB_PORT | default('3306') }}
29 user: "{{ MYSQL_DB_USERNAME | default('notification') }}"
30 passwd: "{{ MYSQL_DB_PASSWORD | default('password') }}"
31 db: "{{ MYSQL_DB_DATABASE | default('mon') }}"
32
33notification_types:
34{% if NF_PLUGINS %}
35 {% set plugins = NF_PLUGINS.split(',')|map('trim')|list %}
36 plugins:
37 {% if 'email' in plugins %}
38 - monasca_notification.plugins.email_notifier:EmailNotifier
39 {% endif %}
40 {% if 'webhook' in plugins %}
41 - monasca_notification.plugins.webhook_notifier:WebhookNotifier
42 {% endif %}
43 {% if 'pagerduty' in plugins %}
44 - monasca_notification.plugins.pagerduty_notifier:PagerdutyNotifier
45 {% endif %}
46 {% if 'hipchat' in plugins %}
47 - monasca_notification.plugins.hipchat_notifier:HipChatNotifier
48 {% endif %}
49 {% if 'slack' in plugins %}
50 - monasca_notification.plugins.slack_notifier:SlackNotifier
51 {% endif %}
52{% else %}
53 plugins: []
54 {% set plugins = [] %}
55{% endif %}
56
57{% if 'email' in plugins %}
58 email:
59 server: "{{ NF_EMAIL_SERVER }}"
60 port: {{ NF_EMAIL_PORT | default(25) }}
61 user: "{{ NF_EMAIL_USER }}"
62 password: "{{ NF_EMAIL_PASSWORD }}"
63 timeout: {{ NF_EMAIL_TIMEOUT | default(15) }}
64 from_addr: "{{ NF_EMAIL_FROM_ADDR }}"
65 grafana_url: "{{ NF_EMAIL_GRAFANA_URL }}"
66{% endif -%}
67
68{% if 'webhook' in plugins %}
69 webhook:
70 timeout: {{ NF_WEBHOOK_TIMEOUT | default(5) }}
71{% endif -%}
72
73{% if 'pagerduty' in plugins %}
74 pagerduty:
75 timeout: {{ NF_PAGERDUTY_TIMEOUT | default(5) }}
76 url: "{{ NF_PAGERDUTY_URL | default('https://events.pagerduty.com/generic/2010-04-15/create_event.json') }}"
77{% endif -%}
78
79{% if 'hipchat' in plugins %}
80 hipchat:
81 timeout: {{ NF_HIPCHAT_TIMEOUT | default(5) }}
82 ca_certs: "{{ NF_HIPCHAT_SSL_CERTS | default('/etc/ssl/certs/ca-certificates.crt') }}"
83 insecure: {{ NF_HIPCHAT_INSECURE | default('false') }}
84 {% if NF_HIPCHAT_PROXY %}
85 proxy: {{ NF_HIPCHAT_PROXY }}
86 {% endif %}
87 {% if NF_HIPCHAT_TEMPLATE %}
88 template: "{{ NF_HIPCHAT_TEMPLATE }}"
89 {% endif %}
90{% endif -%}
91
92{% if 'slack' in plugins %}
93 slack:
94 timeout: {{ NF_SLACK_TIMEOUT | default(5) }}
95 ca_certs: "{{ NF_SLACK_CA_CERTS | default('/etc/ssl/certs/ca-certificates.crt') }}"
96 insecure: {{ NF_SLACK_INSECURE | default('false') }}
97 {% if NF_SLACK_PROXY %}
98 proxy: {{ NF_SLACK_PROXY }}
99 {% endif %}
100{% endif %}
101
102processors:
103 alarm:
104 number: {{ ALARM_PROCESSORS | default(2) }}
105
106 # In seconds, undefined for none. Alarms older than this are not processed
107 ttl: 14400
108 notification:
109 number: {{ NOTIFICATION_PROCESSORS | default(2) }}
110
111retry:
112 interval: {{ RETRY_INTERVAL | default(30) }}
113 max_attempts: {{ RETRY_MAX_ATTEMPTS | default(5) }}
114
115queues:
116 alarms_size: 256
117 finished_size: 256
118 notifications_size: 256
119 sent_notifications_size: 50
120
121zookeeper:
122 url: "{{ ZOOKEEPER_URL | default('zookeeper:2181') }}"
123 notification_path: "/notification/alarms"
124 notification_retry_path: "/notification/retry"
125 periodic_path:
126 60: /notification/60_seconds
127
128logging: # Used in logging.dictConfig
129 version: 1
130 disable_existing_loggers: False
131 formatters:
132 default:
133 format: "%(asctime)s %(levelname)s %(name)s %(message)s"
134 handlers:
135 console:
136 class: logging.StreamHandler
137 formatter: default
138 loggers:
139 kazoo:
140 level: WARN
141 kafka:
142 level: WARN
143 statsd:
144 level: WARN
145 root:
146 handlers:
147 - console
148 level: {{ LOG_LEVEL | default('WARN') }}
149
150{% if STATSD_HOST and STATSD_PORT %}
151statsd:
152 host: "{{ STATSD_HOST }}"
153 port: {{ STATSD_PORT }}
154{% endif %}
diff --git a/docker/start.sh b/docker/start.sh
new file mode 100644
index 0000000..9a72353
--- /dev/null
+++ b/docker/start.sh
@@ -0,0 +1,41 @@
1#!/bin/sh
2
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15# Starting script.
16# All checks and configuration templating you need to do before service
17# could be safely started should be added in this file.
18
19set -eo pipefail # Exit the script if any statement returns error.
20
21# Test services we need before starting our service.
22echo "Start script: waiting for needed services"
23python3 /kafka_wait_for_topics.py
24python3 /mysql_check.py
25
26# Template all config files before start, it will use env variables.
27# Read usage examples: https://pypi.org/project/Templer/
28echo "Start script: creating config files from templates"
29templer -v -f /etc/monasca/notification.yaml.j2 /etc/monasca/notification.yaml
30
31# Start our service.
32echo "Start script: starting container"
33monasca-notification /etc/monasca/notification.yaml
34
35# Allow server to stay alive in case of failure for 2 hours for debugging.
36EXIT_CODE=$?
37if [ $EXIT_CODE != 0 ] && [ "$STAY_ALIVE_ON_FAILURE" = "true" ]; then
38 echo "Service died, waiting 120 min before exiting"
39 sleep 7200
40fi
41exit $EXIT_CODE