2017-01-29 13:33:33 -06:00
|
|
|
#!/bin/bash
|
|
|
|
|
2020-01-26 15:56:42 -06:00
|
|
|
# single instance containers are still supported (even though it might not look like it)
|
2020-02-26 02:56:54 -06:00
|
|
|
# if no instance number is passed to this script, $DEV will simply be unset, resulting in docker
|
2020-01-26 15:56:42 -06:00
|
|
|
# commands being sent to the base container name. E.g. `docker start database$DEV` simply starts
|
|
|
|
# the container `database` if no instance number is passed since `$DEV` is not defined
|
|
|
|
|
|
|
|
|
|
|
|
{%- if docker_container_name == "database" %}
|
|
|
|
link_namespace() {
|
|
|
|
# Makes namespace of a docker container available in
|
|
|
|
# /var/run/netns so it can be managed with iproute2
|
|
|
|
|
|
|
|
mkdir -p /var/run/netns
|
|
|
|
PID="$(docker inspect -f {{"'{{.State.Pid}}'"}} "{{docker_container_name}}$DEV")"
|
|
|
|
|
2020-03-31 12:06:19 -05:00
|
|
|
PIDS=`ip netns pids "$NET_NS" 2>/dev/null`
|
|
|
|
if [ "$?" -eq "0" ]; then # namespace exists
|
|
|
|
if `echo $PIDS | grep --quiet -w $PID`; then # namespace is correctly linked
|
2020-01-26 15:56:42 -06:00
|
|
|
return 0
|
|
|
|
else # if it's incorrectly linked remove it
|
2020-03-31 12:06:19 -05:00
|
|
|
ip netns delete $NET_NS
|
2020-01-26 15:56:42 -06:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2020-03-31 12:06:19 -05:00
|
|
|
ln -s /proc/$PID/ns/net /var/run/netns/$NET_NS
|
2020-01-26 15:56:42 -06:00
|
|
|
}
|
|
|
|
{%- endif %}
|
|
|
|
|
2017-09-14 10:43:02 -05:00
|
|
|
function getMountPoint()
|
|
|
|
{
|
2018-11-02 09:20:07 -05:00
|
|
|
echo $1 | python -c "import sys, json, os; mnts = [x for x in json.load(sys.stdin)[0]['Mounts'] if x['Destination'] == '/usr/share/sonic/hwsku']; print '' if len(mnts) == 0 else os.path.basename(mnts[0]['Source'])" 2>/dev/null
|
|
|
|
}
|
|
|
|
|
|
|
|
function getBootType()
|
|
|
|
{
|
2019-06-26 14:46:58 -05:00
|
|
|
# same code snippet in files/scripts/syncd.sh
|
|
|
|
case "$(cat /proc/cmdline)" in
|
|
|
|
*SONIC_BOOT_TYPE=warm*)
|
2018-11-02 09:20:07 -05:00
|
|
|
TYPE='warm'
|
|
|
|
;;
|
2019-06-26 14:46:58 -05:00
|
|
|
*SONIC_BOOT_TYPE=fastfast*)
|
2018-12-04 12:11:24 -06:00
|
|
|
TYPE='fastfast'
|
|
|
|
;;
|
2019-06-26 14:46:58 -05:00
|
|
|
*SONIC_BOOT_TYPE=fast*|*fast-reboot*)
|
2018-12-04 12:11:24 -06:00
|
|
|
TYPE='fast'
|
|
|
|
;;
|
2018-11-02 09:20:07 -05:00
|
|
|
*)
|
2018-11-22 17:13:35 -06:00
|
|
|
TYPE='cold'
|
2018-11-02 09:20:07 -05:00
|
|
|
esac
|
2018-12-04 12:11:24 -06:00
|
|
|
echo "${TYPE}"
|
2017-09-14 10:43:02 -05:00
|
|
|
}
|
|
|
|
|
2018-11-22 17:13:35 -06:00
|
|
|
function preStartAction()
|
|
|
|
{
|
|
|
|
{%- if docker_container_name == "database" %}
|
|
|
|
WARM_DIR=/host/warmboot
|
2019-01-10 16:09:04 -06:00
|
|
|
if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then
|
2018-12-04 12:11:24 -06:00
|
|
|
# Load redis content from /host/warmboot/dump.rdb
|
2020-03-31 12:06:19 -05:00
|
|
|
docker cp $WARM_DIR/dump.rdb database$DEV:/var/lib/redis/dump.rdb
|
2018-11-22 17:13:35 -06:00
|
|
|
else
|
|
|
|
# Create an emtpy file and overwrite any RDB if already there
|
|
|
|
echo -n > /tmp/dump.rdb
|
2020-03-31 12:06:19 -05:00
|
|
|
docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/
|
2018-11-22 17:13:35 -06:00
|
|
|
fi
|
2019-10-10 11:24:18 -05:00
|
|
|
{%- elif docker_container_name == "snmp" %}
|
2020-03-31 12:06:19 -05:00
|
|
|
sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s)
|
2018-11-22 17:13:35 -06:00
|
|
|
{%- else %}
|
|
|
|
: # nothing
|
|
|
|
{%- endif %}
|
|
|
|
}
|
|
|
|
|
2017-09-14 10:43:02 -05:00
|
|
|
function postStartAction()
|
|
|
|
{
|
2018-02-26 13:23:29 -06:00
|
|
|
{%- if docker_container_name == "database" %}
|
2020-01-26 15:56:42 -06:00
|
|
|
if [ "$DEV" ]; then
|
2020-04-21 19:09:41 -05:00
|
|
|
docker exec -i database$DEV sysctl -w net.ipv6.conf.all.disable_ipv6=0
|
2020-01-26 15:56:42 -06:00
|
|
|
link_namespace $DEV
|
|
|
|
fi
|
2018-11-22 17:13:35 -06:00
|
|
|
# Wait until redis starts
|
2020-03-31 12:06:19 -05:00
|
|
|
/usr/bin/docker exec database$DEV ping_pong_db_insts
|
2019-01-10 16:09:04 -06:00
|
|
|
if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then
|
2018-11-22 17:13:35 -06:00
|
|
|
rm -f $WARM_DIR/dump.rdb
|
|
|
|
else
|
2020-03-05 17:35:35 -06:00
|
|
|
# If there is a config_db.json dump file, load it.
|
2020-03-31 12:06:19 -05:00
|
|
|
if [ -r /etc/sonic/config_db$DEV.json ]; then
|
2020-03-05 17:35:35 -06:00
|
|
|
if [ -r /etc/sonic/init_cfg.json ]; then
|
2020-03-31 12:06:19 -05:00
|
|
|
sonic-netns-exec "$NET_NS" sonic-cfggen -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db$DEV.json --write-to-db
|
2020-03-05 17:35:35 -06:00
|
|
|
else
|
2020-03-31 12:06:19 -05:00
|
|
|
sonic-netns-exec "$NET_NS" sonic-cfggen -j /etc/sonic/config_db$DEV.json --write-to-db
|
2020-03-05 17:35:35 -06:00
|
|
|
fi
|
2018-11-22 17:13:35 -06:00
|
|
|
fi
|
|
|
|
|
2019-12-04 16:10:19 -06:00
|
|
|
if [[ "$BOOT_TYPE" == "fast" ]]; then
|
|
|
|
# set the key to expire in 3 minutes
|
2020-03-31 12:06:19 -05:00
|
|
|
/usr/bin/sonic-netns-exec "$NET_NS" sonic-db-cli STATE_DB SET "FAST_REBOOT|system" "1" "EX" "180"
|
2019-12-04 16:10:19 -06:00
|
|
|
fi
|
|
|
|
|
2020-03-31 12:06:19 -05:00
|
|
|
/usr/bin/sonic-netns-exec "$NET_NS" sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
|
2018-11-02 09:20:07 -05:00
|
|
|
fi
|
2019-04-30 16:46:18 -05:00
|
|
|
|
|
|
|
if [[ -x /usr/bin/db_migrator.py ]]; then
|
|
|
|
# Migrate the DB to the latest schema version if needed
|
|
|
|
/usr/bin/db_migrator.py -o migrate
|
|
|
|
fi
|
2018-02-26 13:23:29 -06:00
|
|
|
{%- elif docker_container_name == "swss" %}
|
2020-03-31 12:06:19 -05:00
|
|
|
docker exec swss$DEV rm -f /ready # remove cruft
|
2019-01-10 16:09:04 -06:00
|
|
|
if [[ "$BOOT_TYPE" == "fast" ]] && [[ -d /host/fast-reboot ]]; then
|
2020-03-31 12:06:19 -05:00
|
|
|
test -e /host/fast-reboot/fdb.json && docker cp /host/fast-reboot/fdb.json swss$DEV:/
|
|
|
|
test -e /host/fast-reboot/arp.json && docker cp /host/fast-reboot/arp.json swss$DEV:/
|
|
|
|
test -e /host/fast-reboot/default_routes.json && docker cp /host/fast-reboot/default_routes.json swss$DEV:/
|
2018-02-26 13:23:29 -06:00
|
|
|
rm -fr /host/fast-reboot
|
|
|
|
fi
|
2020-03-31 12:06:19 -05:00
|
|
|
docker exec swss$DEV touch /ready # signal swssconfig.sh to go
|
2018-06-22 12:48:44 -05:00
|
|
|
{%- elif docker_container_name == "pmon" %}
|
|
|
|
|
|
|
|
DEVPATH="/usr/share/sonic/device"
|
|
|
|
REBOOT="platform_reboot"
|
|
|
|
PSENSOR="/usr/local/bin/platform_sensors.py"
|
|
|
|
if [ -d ${DEVPATH}/${PLATFORM} ] && [ -f $PSENSOR ]; then
|
|
|
|
exist=`docker exec -i pmon ls /usr/bin/platform_sensors.py "$@" 2>/dev/null`
|
|
|
|
if [ -z "$exist" ]; then
|
|
|
|
docker cp $PSENSOR pmon:/usr/bin/
|
|
|
|
fi
|
|
|
|
fi
|
2018-02-26 13:23:29 -06:00
|
|
|
{%- else %}
|
2018-02-26 19:42:20 -06:00
|
|
|
: # nothing
|
2017-12-19 18:02:26 -06:00
|
|
|
{%- endif %}
|
2017-09-14 10:43:02 -05:00
|
|
|
}
|
|
|
|
|
2018-10-12 10:39:06 -05:00
|
|
|
start() {
|
2018-11-22 17:13:35 -06:00
|
|
|
# Obtain boot type from kernel arguments
|
|
|
|
BOOT_TYPE=`getBootType`
|
|
|
|
|
2018-10-12 10:39:06 -05:00
|
|
|
# Obtain our platform as we will mount directories with these names in each docker
|
2020-03-31 12:06:19 -05:00
|
|
|
PLATFORM=`sonic-netns-exec "$NET_NS" sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`
|
2017-09-14 10:43:02 -05:00
|
|
|
|
2018-10-12 10:39:06 -05:00
|
|
|
{%- if docker_container_name == "database" %}
|
|
|
|
# Don't mount HWSKU in {{docker_container_name}} container.
|
|
|
|
HWSKU=""
|
|
|
|
{%- else %}
|
|
|
|
# Obtain our HWSKU as we will mount directories with these names in each docker
|
2020-03-31 12:06:19 -05:00
|
|
|
HWSKU=`sonic-netns-exec "$NET_NS" sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
|
2018-10-12 10:39:06 -05:00
|
|
|
{%- endif %}
|
2017-02-27 02:13:36 -06:00
|
|
|
|
2020-01-26 15:56:42 -06:00
|
|
|
DOCKERCHECK=`docker inspect --type container {{docker_container_name}}$DEV 2>/dev/null`
|
2017-01-29 13:33:33 -06:00
|
|
|
if [ "$?" -eq "0" ]; then
|
2019-03-19 22:14:07 -05:00
|
|
|
{%- if docker_container_name == "database" %}
|
|
|
|
DOCKERMOUNT=""
|
|
|
|
{%- else %}
|
2017-09-14 10:43:02 -05:00
|
|
|
DOCKERMOUNT=`getMountPoint "$DOCKERCHECK"`
|
2019-03-19 22:14:07 -05:00
|
|
|
{%- endif %}
|
|
|
|
if [ x"$DOCKERMOUNT" == x"$HWSKU" ]; then
|
|
|
|
{%- if docker_container_name == "database" %}
|
2020-01-26 15:56:42 -06:00
|
|
|
echo "Starting existing {{docker_container_name}}$DEV container"
|
2019-03-19 22:14:07 -05:00
|
|
|
{%- else %}
|
2020-01-26 15:56:42 -06:00
|
|
|
echo "Starting existing {{docker_container_name}}$DEV container with HWSKU $HWSKU"
|
2019-03-19 22:14:07 -05:00
|
|
|
{%- endif %}
|
2018-11-22 17:13:35 -06:00
|
|
|
preStartAction
|
2020-01-26 15:56:42 -06:00
|
|
|
docker start {{docker_container_name}}$DEV
|
|
|
|
postStartAction
|
2018-11-02 09:20:07 -05:00
|
|
|
exit $?
|
2017-09-14 10:43:02 -05:00
|
|
|
fi
|
|
|
|
|
|
|
|
# docker created with a different HWSKU, remove and recreate
|
2020-01-26 15:56:42 -06:00
|
|
|
echo "Removing obsolete {{docker_container_name}}$DEV container with HWSKU $DOCKERMOUNT"
|
|
|
|
docker rm -f {{docker_container_name}}$DEV
|
2017-09-14 10:43:02 -05:00
|
|
|
fi
|
2017-03-23 14:18:52 -05:00
|
|
|
|
2020-01-26 15:56:42 -06:00
|
|
|
{%- if docker_container_name == "database" %}
|
|
|
|
echo "Creating new {{docker_container_name}}$DEV container"
|
create multiple Redis DB instances based on CONFIG at /etc/sonic/database_config.json (#2182)
this is the first step to moving different databases tables into different database instances
in this PR, only handle multiple database instances creation based on user configuration at /etc/sonic/database_config.json
we keep current method to create single database instance if no extra/new DATABASE configuration exist in database_config.json file.
if user try to configure more db instances at database_config.json , we create those new db instances along with the original db instance existing today.
The configuration is as below, later we can add more db related information if needed:
{
...
"DATABASE": {
"redis-db-01" : {
"port" : "6380",
"database": ["APPL_DB", "STATE_DB"]
},
"redis-db-02" : {
"port" : "6381",
"database":["ASIC_DB"]
},
}
...
}
The detail description is at design doc at Azure/SONiC#271
The main idea is : when database.sh started, we check the configuration and generate corresponding scripts.
rc.local service handle old_config copy when loading new images, there is no dependency between rc.local and database service today, for safety and make sure the copy operation are done before database try to read it, we make database service run after rc.local
Then database docker started, we check the configuration and generate corresponding scripts/.conf in database docker as well.
based on those conf, we create databases instances as required.
at last, we ping_pong check database are up and continue
Signed-off-by: Dong Zhang d.zhang@alibaba-inc.com
2019-08-28 13:15:10 -05:00
|
|
|
# if database_config exists in old_config, use it; otherwise use the default one in new image
|
|
|
|
if [ -f /etc/sonic/old_config/database_config.json ]; then
|
|
|
|
echo "Use database_config.json from old system..."
|
|
|
|
mv /etc/sonic/old_config/database_config.json /etc/sonic/
|
|
|
|
fi
|
2020-01-26 15:56:42 -06:00
|
|
|
{%- else %}
|
|
|
|
echo "Creating new {{docker_container_name}}$DEV container with HWSKU $HWSKU"
|
|
|
|
{%- endif %}
|
|
|
|
|
|
|
|
if [ -z "$DEV" ]; then
|
|
|
|
NET="host"
|
|
|
|
else
|
2020-02-26 02:56:54 -06:00
|
|
|
{%- if docker_container_name == "database" %}
|
2020-01-26 15:56:42 -06:00
|
|
|
NET="bridge"
|
|
|
|
{%- else %}
|
|
|
|
NET="container:database$DEV"
|
|
|
|
{%- endif %}
|
|
|
|
fi
|
2020-03-31 12:06:19 -05:00
|
|
|
{%- if docker_container_name == "bgp" %}
|
|
|
|
if [ "$DEV" ]; then
|
|
|
|
if [ ! -d "/etc/sonic/frr/$DEV" ]; then
|
|
|
|
mkdir /etc/sonic/frr/$DEV
|
|
|
|
cp -r /etc/sonic/frr/*.conf /etc/sonic/frr/$DEV
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
{%- endif %}
|
2019-06-05 13:19:56 -05:00
|
|
|
{%- if sonic_asic_platform == "mellanox" %}
|
2019-06-26 14:46:58 -05:00
|
|
|
# TODO: Mellanox will remove the --tmpfs exception after SDK socket path changed in new SDK version
|
2017-09-14 10:43:02 -05:00
|
|
|
{%- endif %}
|
2018-11-22 17:13:35 -06:00
|
|
|
docker create {{docker_image_run_opt}} \
|
2020-01-26 15:56:42 -06:00
|
|
|
--net=$NET \
|
2020-02-26 02:56:54 -06:00
|
|
|
--uts=host \{# W/A: this should be set per-docker, for those dockers which really need host's UTS namespace #}
|
2019-07-04 00:13:55 -05:00
|
|
|
{%- if install_debug_image == "y" %}
|
|
|
|
-v /src:/src:ro -v /debug:/debug:rw \
|
|
|
|
{%- endif %}
|
2017-05-05 19:44:36 -05:00
|
|
|
{%- if '--log-driver=json-file' in docker_image_run_opt or '--log-driver' not in docker_image_run_opt %}
|
2017-09-14 10:43:02 -05:00
|
|
|
--log-opt max-size=2M --log-opt max-file=5 \
|
2018-04-02 22:24:59 -05:00
|
|
|
{%- endif %}
|
2019-03-06 20:51:46 -06:00
|
|
|
{%- if sonic_asic_platform == "mellanox" %}
|
|
|
|
{%- if docker_container_name == "syncd" %}
|
2018-04-02 22:24:59 -05:00
|
|
|
-v /var/log/mellanox/sniffer:/var/log/mellanox/sniffer:rw \
|
2020-03-09 14:36:56 -05:00
|
|
|
-v mlnx_sdk_socket:/var/run/sx_sdk \
|
|
|
|
-v mlnx_sdk_ready:/tmp \
|
2019-06-05 13:19:56 -05:00
|
|
|
-v /dev/shm:/dev/shm:rw \
|
2020-03-09 14:36:56 -05:00
|
|
|
-e SX_API_SOCKET_FILE=/var/run/sx_sdk/sx_api.sock \
|
2019-06-14 19:38:24 -05:00
|
|
|
{%- elif docker_container_name == "pmon" %}
|
|
|
|
-v /var/run/hw-management:/var/run/hw-management:rw \
|
2020-03-09 14:36:56 -05:00
|
|
|
-v mlnx_sdk_socket:/var/run/sx_sdk \
|
|
|
|
-v mlnx_sdk_ready:/tmp \
|
|
|
|
-e SX_API_SOCKET_FILE=/var/run/sx_sdk/sx_api.sock \
|
2019-06-14 19:38:24 -05:00
|
|
|
-v /dev/shm:/dev/shm:rw \
|
2019-06-05 13:19:56 -05:00
|
|
|
{%- else %}
|
|
|
|
--tmpfs /tmp \
|
2019-03-06 20:51:46 -06:00
|
|
|
{%- endif %}
|
2017-05-05 19:44:36 -05:00
|
|
|
{%- endif %}
|
2020-03-31 12:06:19 -05:00
|
|
|
{%- if docker_container_name == "bgp" %}
|
|
|
|
-v /etc/sonic/frr/$DEV:/etc/frr:rw \
|
|
|
|
{%- endif %}
|
|
|
|
-v /var/run/redis$DEV:/var/run/redis:rw \
|
2017-09-14 10:43:02 -05:00
|
|
|
-v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \
|
2017-09-12 16:13:27 -05:00
|
|
|
{%- if docker_container_name != "database" %}
|
2020-03-31 12:06:19 -05:00
|
|
|
-v /usr/share/sonic/device/$PLATFORM/$HWSKU/$DEV:/usr/share/sonic/hwsku:ro \
|
2017-09-12 16:13:27 -05:00
|
|
|
{%- endif %}
|
2019-06-05 13:19:56 -05:00
|
|
|
{%- if sonic_asic_platform != "mellanox" %}
|
2018-01-17 01:20:13 -06:00
|
|
|
--tmpfs /tmp \
|
2019-06-05 13:19:56 -05:00
|
|
|
{%- endif %}
|
2018-01-17 01:20:13 -06:00
|
|
|
--tmpfs /var/tmp \
|
2020-01-26 15:56:42 -06:00
|
|
|
--name={{docker_container_name}}$DEV {{docker_image_name}}:latest || {
|
2018-07-24 23:46:55 -05:00
|
|
|
echo "Failed to docker run" >&1
|
|
|
|
exit 4
|
|
|
|
}
|
2017-09-14 10:43:02 -05:00
|
|
|
|
2018-11-22 17:13:35 -06:00
|
|
|
preStartAction
|
2020-03-31 12:06:19 -05:00
|
|
|
docker start {{docker_container_name}}$DEV
|
2017-09-14 10:43:02 -05:00
|
|
|
postStartAction
|
2017-01-29 13:33:33 -06:00
|
|
|
}
|
|
|
|
|
2019-03-08 12:59:41 -06:00
|
|
|
wait() {
|
2020-01-26 15:56:42 -06:00
|
|
|
docker wait {{docker_container_name}}$DEV
|
[oneimage]: Fix race condition in systemd container services (#421)
When Type=simple, systemd will consider the service activated immediately
after specified in ExecStart process is started. If there is downstream
service depending on the state prepared in ExecStart, there will be race condition.
For example, issue #390. In this case, database.service calls database.sh, which
calls docker run or docker start -a to start database container. However, systemd
considers database.service successfully started at the time database.sh begins,
not after docker run finishes. As database.service is consider started, bgp.service
can be started. The redis database, which bgp service depends on, might or might not
have been started at this time point.
To fix this issue (and still keeping the functionality to monitor docker status with
systemd), we split the ExecStart process into an ExecStartPre part and an ExecStart
part. docker run is splitted into docker run -d then docker attach , while docker start
-a is splitted into docker start and then docker attach. In this way, we make sure
the downstream services are blocked until container is successfully started.
2017-03-22 15:04:48 -05:00
|
|
|
}
|
|
|
|
|
2017-01-29 13:33:33 -06:00
|
|
|
stop() {
|
2020-01-26 15:56:42 -06:00
|
|
|
docker stop {{docker_container_name}}$DEV
|
|
|
|
{%- if docker_container_name == "database" %}
|
2020-03-31 12:06:19 -05:00
|
|
|
if [ "$DEV" ]; then
|
|
|
|
ip netns delete "$NET_NS"
|
|
|
|
fi
|
2020-01-26 15:56:42 -06:00
|
|
|
{%- endif %}
|
2017-01-29 13:33:33 -06:00
|
|
|
}
|
|
|
|
|
2020-01-26 15:56:42 -06:00
|
|
|
OP=$1
|
|
|
|
DEV=$2 # namespace/device number to operate on
|
2020-03-31 12:06:19 -05:00
|
|
|
if [ "$DEV" ]; then
|
|
|
|
NET_NS="asic$DEV" #name of the network namespace
|
|
|
|
else
|
|
|
|
NET_NS=""
|
|
|
|
fi
|
2020-01-26 15:56:42 -06:00
|
|
|
|
2017-01-29 13:33:33 -06:00
|
|
|
case "$1" in
|
2020-01-26 15:56:42 -06:00
|
|
|
start|wait|stop)
|
|
|
|
$1
|
|
|
|
;;
|
2017-01-29 13:33:33 -06:00
|
|
|
*)
|
2020-02-26 02:56:54 -06:00
|
|
|
echo "Usage: $0 {start namespace(optional)|wait namespace(optional)|stop namespace(optional)}"
|
2017-01-29 13:33:33 -06:00
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|