diff --git a/device/arista/x86_64-arista_7800_sup/chassisdb.conf b/device/arista/x86_64-arista_7800_sup/chassisdb.conf new file mode 100644 index 000000000000..3918a00c4ee9 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/chassisdb.conf @@ -0,0 +1,2 @@ +start_chassis_db=1 +chassis_db_address=127.100.1.1 diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/chassisdb.conf b/device/arista/x86_64-arista_7800r3_48cq2_lc/chassisdb.conf new file mode 100644 index 000000000000..75dc7d65703b --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/chassisdb.conf @@ -0,0 +1 @@ +chassis_db_address=127.100.1.1 diff --git a/dockers/docker-database/Dockerfile.j2 b/dockers/docker-database/Dockerfile.j2 index fcfb3b620c25..aeaa61614406 100644 --- a/dockers/docker-database/Dockerfile.j2 +++ b/dockers/docker-database/Dockerfile.j2 @@ -45,5 +45,6 @@ COPY ["database_global.json.j2", "/usr/share/sonic/templates/"] COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] COPY ["files/sysctl-net.conf", "/etc/sysctl.d/"] COPY ["critical_processes", "/etc/supervisor"] +COPY ["files/update_chassisdb_config", "/usr/local/bin/"] ENTRYPOINT ["/usr/local/bin/docker-database-init.sh"] diff --git a/dockers/docker-database/database_config.json.j2 b/dockers/docker-database/database_config.json.j2 index a24252ed810d..5e3096eaac1c 100644 --- a/dockers/docker-database/database_config.json.j2 +++ b/dockers/docker-database/database_config.json.j2 @@ -5,6 +5,12 @@ "port" : 6379, "unix_socket_path" : "/var/run/redis{{NAMESPACE_ID}}/redis.sock", "persistence_for_warm_boot" : "yes" + }, + "redis_chassis":{ + "hostname" : "redis_chassis.server", + "port": 6380, + "unix_socket_path": "/var/run/redis-chassis/redis_chassis.sock", + "persistence_for_warm_boot" : "yes" } }, "DATABASES" : { @@ -72,6 +78,11 @@ "id" : 11, "separator": "|", "instance" : "redis" + }, + "CHASSIS_APP_DB" : { + "id" : 12, + "separator": "|", + "instance" : "redis_chassis" } }, "VERSION" : "1.0" diff --git a/dockers/docker-database/docker-database-init.sh b/dockers/docker-database/docker-database-init.sh index 645a7d99272a..babb9f7924a0 100755 --- a/dockers/docker-database/docker-database-init.sh +++ b/dockers/docker-database/docker-database-init.sh @@ -19,6 +19,7 @@ fi REDIS_DIR=/var/run/redis$NAMESPACE_ID mkdir -p $REDIS_DIR/sonic-db +mkdir -p /etc/supervisor/conf.d/ if [ -f /etc/sonic/database_config$NAMESPACE_ID.json ]; then cp /etc/sonic/database_config$NAMESPACE_ID.json $REDIS_DIR/sonic-db/database_config.json @@ -26,7 +27,37 @@ else HOST_IP=$host_ip j2 /usr/share/sonic/templates/database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json fi -mkdir -p /etc/supervisor/conf.d/ +# on VoQ system, we only publish redis_chassis instance and CHASSIS_APP_DB when +# either chassisdb.conf indicates starts chassis_db or connect to chassis_db, +# and redis_chassis instance is started in different container. +# in order to do that, first we save original database config file, then +# call update_chasissdb_config to remove chassis_db config from +# the original database config file and use the modified config file to generate +# supervisord config, so that we won't start redis_chassis service. +# then we will decide to publish modified or original database config file based +# on the setting in chassisdb.conf +start_chassis_db=0 +chassis_db_address="" +chassis_db_port="" +chassisdb_config="/etc/sonic/chassisdb.conf" +[ -f $chassisdb_config ] && source $chassisdb_config + +db_cfg_file="/var/run/redis/sonic-db/database_config.json" +db_cfg_file_tmp="/var/run/redis/sonic-db/database_config.json.tmp" +cp $db_cfg_file $db_cfg_file_tmp + +if [[ $DATABASE_TYPE == "chassisdb" ]]; then + # Docker init for database-chassis + echo "Init docker-database-chassis..." + update_chassisdb_config -j $db_cfg_file_tmp -k -p $chassis_db_port + mkdir -p /var/run/redis/sonic-db + cp /etc/default/sonic-db/database_config.json /var/run/redis/sonic-db + # generate all redis server supervisord configuration file + sonic-cfggen -j $db_cfg_file_tmp -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf + rm $db_cfg_file_tmp + exec /usr/bin/supervisord + exit 0 +fi # copy/generate the database_global.json file if this is global database service in multi asic platform. if [[ $NAMESPACE_ID == "" ]] && [[ $NAMESPACE_COUNT -gt 1 ]] @@ -37,8 +68,15 @@ then j2 /usr/share/sonic/templates/database_global.json.j2 > $REDIS_DIR/sonic-db/database_global.json fi fi +# delete chassisdb config to generate supervisord config +update_chassisdb_config -j $db_cfg_file_tmp -d +sonic-cfggen -j $db_cfg_file_tmp -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf -# generate all redis server supervisord configuration file -sonic-cfggen -j /var/run/redis/sonic-db/database_config.json -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf +if [[ "$start_chassis_db" != "1" ]] && [[ -z "$chassis_db_address" ]]; then + cp $db_cfg_file_tmp $db_cfg_file +else + update_chassisdb_config -j $db_cfg_file -p $chassis_db_port +fi +rm $db_cfg_file_tmp exec /usr/bin/supervisord diff --git a/dockers/docker-database/supervisord.conf.j2 b/dockers/docker-database/supervisord.conf.j2 index 6d4557dab705..97b8a4822530 100644 --- a/dockers/docker-database/supervisord.conf.j2 +++ b/dockers/docker-database/supervisord.conf.j2 @@ -20,7 +20,7 @@ stderr_logfile=syslog {% if INSTANCES %} {% for redis_inst, redis_items in INSTANCES.iteritems() %} [program: {{ redis_inst }}] -{% if redis_items['hostname'] != '127.0.0.1' %} +{% if redis_items['hostname'] != '127.0.0.1' and redis_inst != 'redis_chassis' %} {%- set LOOPBACK_IP = '127.0.0.1' -%} {%- else -%} {%- set LOOPBACK_IP = '' -%} diff --git a/files/build_templates/config-chassisdb.service.j2 b/files/build_templates/config-chassisdb.service.j2 new file mode 100644 index 000000000000..a50d0de72fb1 --- /dev/null +++ b/files/build_templates/config-chassisdb.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Config chassis_db +After=rc-local.service +Requires=rc-local.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/config-chassisdb +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index 71decb3fa906..4d3e795c500e 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -12,7 +12,7 @@ link_namespace() { # /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")" + PID="$(docker inspect -f {{"'{{.State.Pid}}'"}} "${DOCKERNAME}")" PIDS=`ip netns pids "$NET_NS" 2>/dev/null` if [ "$?" -eq "0" ]; then # namespace exists @@ -34,11 +34,11 @@ function updateSyslogConf() # Also update the container name if [[ ($NUM_ASIC -gt 1) ]]; then TARGET_IP=$(docker network inspect bridge --format={{ "'{{(index .IPAM.Config 0).Gateway}}'" }}) - CONTAINER_NAME="{{docker_container_name}}$DEV" + CONTAINER_NAME="$DOCKERNAME" TMP_FILE="/tmp/rsyslog.$CONTAINER_NAME.conf" sonic-cfggen -t /usr/share/sonic/templates/rsyslog-container.conf.j2 -a "{\"target_ip\": \"$TARGET_IP\", \"container_name\": \"$CONTAINER_NAME\" }" > $TMP_FILE - docker cp $TMP_FILE {{docker_container_name}}$DEV:/etc/rsyslog.conf + docker cp $TMP_FILE ${DOCKERNAME}:/etc/rsyslog.conf rm -rf $TMP_FILE fi } @@ -71,13 +71,15 @@ function preStartAction() { {%- if docker_container_name == "database" %} WARM_DIR=/host/warmboot - if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then - # Load redis content from /host/warmboot/dump.rdb - docker cp $WARM_DIR/dump.rdb database$DEV:/var/lib/redis/dump.rdb - else - # Create an emtpy file and overwrite any RDB if already there - echo -n > /tmp/dump.rdb - docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/ + if [ "$DATABASE_TYPE" != "chassisdb" ]; then + if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then + # Load redis content from /host/warmboot/dump.rdb + docker cp $WARM_DIR/dump.rdb database$DEV:/var/lib/redis/dump.rdb + else + # Create an emtpy file and overwrite any RDB if already there + echo -n > /tmp/dump.rdb + docker cp /tmp/dump.rdb database$DEV:/var/lib/redis/ + fi fi {%- elif docker_container_name == "snmp" %} $SONIC_DB_CLI STATE_DB HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s) @@ -99,44 +101,51 @@ function postStartAction() link_namespace $DEV fi - # Wait until supervisord and redis starts. This change is needed - # because now database_config.json is jinja2 templated based - # and by the time file gets generated if we do redis ping - # then we catch python exception of file not valid - # that comes to syslog which is unwanted so wait till database - # config is ready and then ping - until [[ ($(docker exec -i database$DEV pgrep -x -c supervisord) -gt 0) && ($($SONIC_DB_CLI PING | grep -c PONG) -gt 0) ]]; do - sleep 1; - done - - if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then - rm -f $WARM_DIR/dump.rdb - else - # If there is a config_db.json dump file, load it. - if [ -r /etc/sonic/config_db$DEV.json ]; then - if [ -r /etc/sonic/init_cfg.json ]; then - $SONIC_CFGGEN -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db$DEV.json --write-to-db - else - $SONIC_CFGGEN -j /etc/sonic/config_db$DEV.json --write-to-db + # chassisdb starts before database starts, bypass the PING check since other + # databases are not availbale until database container is ready. + # also chassisdb doesn't support warm/fast reboot, its dump.rdb is deleted + # at service startup time, nothing need to be done here. + if [ "$DATABASE_TYPE" != "chassisdb" ]; then + # Wait until supervisord and redis starts. This change is needed + # because now database_config.json is jinja2 templated based + # and by the time file gets generated if we do redis ping + # then we catch python exception of file not valid + # that comes to syslog which is unwanted so wait till database + # config is ready and then ping + until [[ ($(docker exec -i database$DEV pgrep -x -c supervisord) -gt 0) && ($($SONIC_DB_CLI PING | grep -c PONG) -gt 0) ]]; do + sleep 1; + done + if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then + rm -f $WARM_DIR/dump.rdb + else + # If there is a config_db.json dump file, load it. + if [ -r /etc/sonic/config_db$DEV.json ]; then + if [ -r /etc/sonic/init_cfg.json ]; then + $SONIC_CFGGEN -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db$DEV.json --write-to-db + else + $SONIC_CFGGEN -j /etc/sonic/config_db$DEV.json --write-to-db + fi fi - fi - if [[ "$BOOT_TYPE" == "fast" ]]; then - # set the key to expire in 3 minutes - $SONIC_DB_CLI STATE_DB SET "FAST_REBOOT|system" "1" "EX" "180" - fi + if [[ "$BOOT_TYPE" == "fast" ]]; then + # set the key to expire in 3 minutes + $SONIC_DB_CLI STATE_DB SET "FAST_REBOOT|system" "1" "EX" "180" + fi - $SONIC_DB_CLI CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1" - fi + $SONIC_DB_CLI CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1" + fi - if [[ -x /usr/local/bin/db_migrator.py ]]; then - # Migrate the DB to the latest schema version if needed - if [ -z "$DEV" ]; then - /usr/local/bin/db_migrator.py -o migrate + if [[ -x /usr/local/bin/db_migrator.py ]]; then + # Migrate the DB to the latest schema version if needed + if [ -z "$DEV" ]; then + /usr/bin/db_migrator.py -o migrate + fi fi + # Add redis UDS to the redis group and give read/write access to the group + REDIS_SOCK="/var/run/redis${DEV}/redis.sock" + else + REDIS_SOCK="/var/run/redis-chassis/redis_chassis.sock" fi - # Add redis UDS to the redis group and give read/write access to the group - REDIS_SOCK="/var/run/redis${DEV}/redis.sock" chgrp -f redis $REDIS_SOCK && chmod -f 0760 $REDIS_SOCK {%- elif docker_container_name == "swss" %} docker exec swss$DEV rm -f /ready # remove cruft @@ -170,6 +179,7 @@ start() { # Obtain our platform as we will mount directories with these names in each docker PLATFORM=${PLATFORM:-`$SONIC_CFGGEN -H -v DEVICE_METADATA.localhost.platform`} + # Parse the device specific asic conf file, if it exists ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf if [ -f "$ASIC_CONF" ]; then @@ -183,8 +193,7 @@ start() { # Obtain our HWSKU as we will mount directories with these names in each docker HWSKU=${HWSKU:-`$SONIC_CFGGEN -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`} {%- endif %} - - DOCKERCHECK=`docker inspect --type container {{docker_container_name}}$DEV 2>/dev/null` + DOCKERCHECK=`docker inspect --type container ${DOCKERNAME} 2>/dev/null` if [ "$?" -eq "0" ]; then {%- if docker_container_name == "database" %} DOCKERMOUNT="" @@ -193,37 +202,40 @@ start() { {%- endif %} if [ x"$DOCKERMOUNT" == x"$HWSKU" ]; then {%- if docker_container_name == "database" %} - echo "Starting existing {{docker_container_name}}$DEV container" + echo "Starting existing ${DOCKERNAME} container" {%- else %} - echo "Starting existing {{docker_container_name}}$DEV container with HWSKU $HWSKU" + echo "Starting existing ${DOCKERNAME} container with HWSKU $HWSKU" {%- endif %} preStartAction - docker start {{docker_container_name}}$DEV + docker start ${DOCKERNAME} postStartAction exit $? fi # docker created with a different HWSKU, remove and recreate - echo "Removing obsolete {{docker_container_name}}$DEV container with HWSKU $DOCKERMOUNT" - docker rm -f {{docker_container_name}}$DEV + echo "Removing obsolete ${DOCKERNAME} container with HWSKU $DOCKERMOUNT" + docker rm -f ${DOCKERNAME} fi {%- if docker_container_name == "database" %} - echo "Creating new {{docker_container_name}}$DEV container" - if [ -z "$DEV" ]; then - # if database_global exists in old_config, use it; otherwise use the default one in new image - if [ -f /etc/sonic/old_config/database_global.json ]; then - echo "Use database_global.json from old system..." - mv /etc/sonic/old_config/database_global.json /etc/sonic/ + + echo "Creating new ${DOCKERNAME} container" + if [ "$DATABASE_TYPE" != "chassisdb" ]; then + if [ -z "$DEV" ]; then + # if database_global exists in old_config, use it; otherwise use the default one in new image + if [ -f /etc/sonic/old_config/database_global.json ]; then + echo "Use database_global.json from old system..." + mv /etc/sonic/old_config/database_global.json /etc/sonic/ + fi + fi + # 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$DEV.json ]; then + echo "Use database_config.json from old system..." + mv /etc/sonic/old_config/database_config$DEV.json /etc/sonic/ fi - fi - # 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$DEV.json ]; then - echo "Use database_config.json from old system..." - mv /etc/sonic/old_config/database_config$DEV.json /etc/sonic/ fi {%- else %} - echo "Creating new {{docker_container_name}}$DEV container with HWSKU $HWSKU" + echo "Creating new ${DOCKERNAME} container with HWSKU $HWSKU" {%- endif %} # In Multi ASIC platforms the global database config file database_global.json will exist. @@ -238,6 +250,19 @@ start() { for elem in data['INCLUDES'] if 'namespace' in elem])); f.close()" $SONIC_DB_GLOBAL_JSON` fi + {%- if docker_container_name == "database" %} + start_chassis_db=0 + chassis_db_address="" + chassisdb_config="/etc/sonic/chassisdb.conf" + [ -f $chassisdb_config ] && source $chassisdb_config + DB_OPT=" -v /var/run/redis-chassis:/var/run/redis-chassis:ro " + if [[ "$start_chassis_db" != "1" ]] && [[ -z "$chassis_db_address" ]]; then + DB_OPT="" + else + DB_OPT=$DB_OPT" --add-host=redis_chassis.server:$chassis_db_address " + fi + {%- endif %} + if [ -z "$DEV" ]; then NET="host" @@ -256,6 +281,14 @@ start() { REDIS_MNT=$REDIS_MNT" -v $redis_dir:$redis_dir:rw " done fi + {%- else %} + if [ "$DATABASE_TYPE" == "chassisdb" ]; then + DB_OPT=${DB_OPT/redis-chassis:ro/redis-chassis:rw} + DB_OPT=$DB_OPT" -v /var/run/redis-chassis:/var/run/redis:rw " + DB_OPT=$DB_OPT" --env DATABASE_TYPE=$DATABASE_TYPE" + else + DB_OPT=$DB_OPT" -v /var/run/redis$DEV:/var/run/redis:rw " + fi {%- endif %} else # This part of code is applicable for Multi-ASIC platforms. Here we mount the namespace specific @@ -269,9 +302,10 @@ start() { fi {%- if docker_container_name == "database" %} - NET="bridge" + DB_OPT=$DB_OPT" -v /var/run/redis$DEV:/var/run/redis:rw " {%- else %} NET="container:database$DEV" + DB_OPT="" {%- endif %} fi {%- if docker_container_name == "bgp" %} @@ -319,12 +353,15 @@ start() { {%- if docker_container_name == "bgp" %} -v /etc/sonic/frr/$DEV:/etc/frr:rw \ {%- endif %} +{%- if docker_container_name == "database" %} + $DB_OPT \ +{%- else %} -v /var/run/redis$DEV:/var/run/redis:rw \ - $REDIS_MNT \ - -v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \ -{%- if docker_container_name != "database" %} + -v /var/run/redis-chassis:/var/run/redis-chassis:ro \ -v /usr/share/sonic/device/$PLATFORM/$HWSKU/$DEV:/usr/share/sonic/hwsku:ro \ {%- endif %} + $REDIS_MNT \ + -v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \ {%- if sonic_asic_platform != "mellanox" %} --tmpfs /tmp \ {%- endif %} @@ -332,22 +369,22 @@ start() { --env "NAMESPACE_ID"="$DEV" \ --env "NAMESPACE_PREFIX"="$NAMESPACE_PREFIX" \ --env "NAMESPACE_COUNT"=$NUM_ASIC \ - --name={{docker_container_name}}$DEV {{docker_image_name}}:latest || { + --name=$DOCKERNAME {{docker_image_name}}:latest || { echo "Failed to docker run" >&1 exit 4 } preStartAction - docker start {{docker_container_name}}$DEV + docker start $DOCKERNAME postStartAction } wait() { - docker wait {{docker_container_name}}$DEV + docker wait $DOCKERNAME } stop() { - docker stop {{docker_container_name}}$DEV + docker stop $DOCKERNAME {%- if docker_container_name == "database" %} if [ "$DEV" ]; then ip netns delete "$NET_NS" @@ -355,9 +392,18 @@ stop() { {%- endif %} } +DOCKERNAME={{docker_container_name}} OP=$1 DEV=$2 # namespace/device number to operate on +{%- if docker_container_name == "database" %} +if [ "$DEV" == "chassisdb" ]; then + DATABASE_TYPE="chassisdb" + DOCKERNAME=$DOCKERNAME"-chassis" + unset DEV +fi +{%- endif %} NAMESPACE_PREFIX="asic" +DOCKERNAME=$DOCKERNAME$DEV if [ "$DEV" ]; then NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace diff --git a/files/build_templates/per_namespace/database.service.j2 b/files/build_templates/per_namespace/database.service.j2 index 396fdc6678c2..c8a59ab25bbd 100644 --- a/files/build_templates/per_namespace/database.service.j2 +++ b/files/build_templates/per_namespace/database.service.j2 @@ -4,6 +4,8 @@ Description=Database container Requires=database.service After=database.service {% endif %} +Wants=database-chassis.service +After=database-chassis.service Requires=docker.service After=docker.service After=rc-local.service diff --git a/files/build_templates/share_image/database.service.j2 b/files/build_templates/share_image/database.service.j2 new file mode 100644 index 000000000000..cc3f1b0a4364 --- /dev/null +++ b/files/build_templates/share_image/database.service.j2 @@ -0,0 +1,20 @@ +[Unit] +Description=database-chassis container +Requires=docker.service +ConditionPathExists=/etc/sonic/chassisdb.conf +After=docker.service +After=config-chassisdb.service +Requires=config-chassisdb.service +StartLimitIntervalSec=1200 +StartLimitBurst=3 + +[Service] +User=root +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start chassisdb +ExecStart=/usr/bin/{{docker_container_name}}.sh wait chassisdb +ExecStop=/usr/bin/{{docker_container_name}}.sh stop chassisdb +Restart=always +RestartSec=30 + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 2a5d9049ca29..21f143e70109 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -381,6 +381,12 @@ sudo cp $IMAGE_CONFIGS/config-setup/config-setup $FILESYSTEM_ROOT/usr/bin/config echo "config-setup.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-setup.service +# Copy config-chassisdb script and service file +j2 files/build_templates/config-chassisdb.service.j2 | sudo tee $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/config-chassisdb.service +sudo cp $IMAGE_CONFIGS/config-chassisdb/config-chassisdb $FILESYSTEM_ROOT/usr/bin/config-chassisdb +echo "config-chassisdb.service" | sudo tee -a $GENERATED_SERVICE_FILE +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-chassisdb.service + # Copy SNMP configuration files sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/ diff --git a/files/image_config/config-chassisdb/config-chassisdb b/files/image_config/config-chassisdb/config-chassisdb new file mode 100755 index 000000000000..3bdcf0a0fbe2 --- /dev/null +++ b/files/image_config/config-chassisdb/config-chassisdb @@ -0,0 +1,59 @@ +#!/bin/bash +########################################################################### +# Copyright 2020 Arista. The term "Arista" refers to Arista Inc. # +# and/or its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +########################################################################### +# SONiC chassis_db configuration # +# # +# This script is used to add chassis_db address in local hosts and # +# indicate to start database-chassis service. It should be excuted before # +# database-chassis.service started. # +# # +########################################################################### + +config_chassis_db() { + startdb_file="/etc/sonic/chassisdb.conf" + [ ! -e $startdb_file ] || rm $startdb_file + platform=$(sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + # database-chassis services will start when $chassis_config file exists + chassis_config="/usr/share/sonic/device/$platform/chassisdb.conf" + if [ ! -e $chassis_config ]; then + echo "no chassisdb.conf found, bypass config-chassisdb service" + exit 0 + fi + start_chassis_db=0 + chassis_db_address="" + source $chassis_config + if [[ "$start_chassis_db" == "1" ]]; then + cp $chassis_config $startdb_file + echo "start chassisdb" + fi + if [[ "$start_chassis_db" == "1" ]] || [[ -n "$chassis_db_address" ]]; then + if [ -z "$chassis_db_address" ]; then + echo "no user configured chassisdb address" + else + grep redis_chassis /etc/hosts + if [ $? -ne 0 ]; then + echo "$chassis_db_address redis_chassis.server" >> /etc/hosts + echo "update chassis db address to $chassis_db_address" + fi + fi + fi +} + +config_chassis_db + +exit 0 diff --git a/files/scripts/remove_chassisdb_config b/files/scripts/remove_chassisdb_config deleted file mode 100755 index 1583042ce525..000000000000 --- a/files/scripts/remove_chassisdb_config +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/python -import json -import os -import syslog -import argparse - -database_config_file = "/var/run/redis/sonic-db/database_config.json" -redis_chassis = 'redis_chassis' -chassis_db = 'CHASSIS_DB' - -def main(): - parser=argparse.ArgumentParser(description= - "Remove chassis_db config from database-config.json") - parser.add_argument("-j", "--json", help="databse-config json file", nargs='?', - const=database_config_file) - args = parser.parse_args() - jsonfile = "" - if args.json != None: - jsonfile = args.json - else: - return - data = {} - if os.path.isfile(jsonfile): - with open(jsonfile, "r") as read_file: - data = json.load(read_file) - else: - syslog.syslog(syslog.LOG_ERR, - 'config file {} does notexist'.format(jsonfile)) - return - if 'INSTANCES' in data and redis_chassis in data['INSTANCES']: - del data['INSTANCES'][redis_chassis] - if 'DATABASES' in data and chassis_db in data['DATABASES']: - del data['DATABASES'][chassis_db] - with open(jsonfile, "w") as write_file: - json.dump(data, write_file, indent=4, separators=(',', ': ')) - syslog.syslog(syslog.LOG_INFO, - 'remove chassis_db from config file {}'.format(jsonfile)) - -if __name__ == "__main__": - main() diff --git a/files/scripts/update_chassisdb_config b/files/scripts/update_chassisdb_config new file mode 100755 index 000000000000..7ed1f2284cc8 --- /dev/null +++ b/files/scripts/update_chassisdb_config @@ -0,0 +1,67 @@ +#!/usr/bin/python +import json +import os +import syslog +import argparse + +database_config_file = "/var/run/redis/sonic-db/database_config.json" +redis_chassis = 'redis_chassis' +chassis_db = 'CHASSIS_APP_DB' + +def main(): + parser = argparse.ArgumentParser(description= + "Update chassis_db config from database-config.json") + parser.add_argument("-j", "--json", help="databse-config json file", nargs='?', + const=database_config_file) + parser.add_argument("-p", "--port", help="update port number", nargs='?' ) + group = parser.add_mutually_exclusive_group() + group.add_argument("-k", "--keep", help="keep configuration", action='store_true' ) + group.add_argument("-d", "--delete", help="delete configuration", action='store_true' ) + + args = parser.parse_args() + jsonfile = "" + if args.json != None: + jsonfile = args.json + else: + return + if args.port != None: + port_number = args.port + else: + port_number = "" + if args.keep: + keep_config = True + else: + keep_config = False + if args.delete: + delete_config = True + else: + delete_config = False + data = {} + data_keep = {} + if os.path.isfile(jsonfile): + with open(jsonfile, "r") as read_file: + data = json.load(read_file) + else: + syslog.syslog(syslog.LOG_ERR, + 'config file {} does notexist'.format(jsonfile)) + return + if 'INSTANCES' in data and redis_chassis in data['INSTANCES']: + data_keep['INSTANCES'] = {} + data_keep['INSTANCES'][redis_chassis] = data['INSTANCES'][redis_chassis] + if delete_config: + del data['INSTANCES'][redis_chassis] + if 'DATABASES' in data and chassis_db in data['DATABASES']: + data_keep['DATABASES'] = {} + data_keep['DATABASES'][chassis_db] = data['DATABASES'][chassis_db] + if delete_config: + del data['DATABASES'][chassis_db] + with open(jsonfile, "w") as write_file: + data_publish = data_keep if keep_config else data + if port_number: + data_publish['INSTANCES']['redis_chassis']['port'] = int(port_number) + json.dump(data_publish, write_file, indent=4, separators=(',', ': ')) + syslog.syslog(syslog.LOG_INFO, + 'remove chassis_db from config file {}'.format(jsonfile)) + +if __name__ == "__main__": + main() diff --git a/platform/vs/docker-sonic-vs.mk b/platform/vs/docker-sonic-vs.mk index 2812c5b26dd5..13d9c33fa2da 100644 --- a/platform/vs/docker-sonic-vs.mk +++ b/platform/vs/docker-sonic-vs.mk @@ -46,7 +46,7 @@ $(DOCKER_SONIC_VS)_FILES += $(CONFIGDB_LOAD_SCRIPT) \ $(BUFFERS_CONFIG_TEMPLATE) \ $(QOS_CONFIG_TEMPLATE) \ $(SONIC_VERSION) \ - $(RM_CHASSISDB_CONFIG_SCRIPT) + $(UPDATE_CHASSISDB_CONFIG_SCRIPT) $(DOCKER_SONIC_VS)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_VS) diff --git a/platform/vs/docker-sonic-vs/Dockerfile.j2 b/platform/vs/docker-sonic-vs/Dockerfile.j2 index 9a9b7889382d..73a3c3ca4896 100644 --- a/platform/vs/docker-sonic-vs/Dockerfile.j2 +++ b/platform/vs/docker-sonic-vs/Dockerfile.j2 @@ -134,7 +134,7 @@ RUN sed -ri 's/^(save .*$)/# \1/g; ' /etc/redis/redis.conf COPY ["50-default.conf", "/etc/rsyslog.d/"] -COPY ["start.sh", "orchagent.sh", "files/remove_chassisdb_config", "/usr/bin/"] +COPY ["start.sh", "orchagent.sh", "files/update_chassisdb_config", "/usr/bin/"] COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] COPY ["files/configdb-load.sh", "/usr/bin/"] COPY ["files/arp_update", "/usr/bin/"] diff --git a/platform/vs/docker-sonic-vs/chassis_db.py b/platform/vs/docker-sonic-vs/chassis_db.py index a51a33914535..c6cc774fb0c0 100644 --- a/platform/vs/docker-sonic-vs/chassis_db.py +++ b/platform/vs/docker-sonic-vs/chassis_db.py @@ -3,11 +3,11 @@ import swsssdk import json chassisdb = swsssdk.SonicV2Connector(host='10.0.0.200', port='6380') -chassisdb.connect(chassisdb.CHASSIS_DB) +chassisdb.connect(chassisdb.CHASSIS_APP_DB) fname='/usr/share/sonic/virtual_chassis/chassis_db.json' with open(fname) as f: js = json.load(f) - client=chassisdb.get_redis_client(chassisdb.CHASSIS_DB) + client=chassisdb.get_redis_client(chassisdb.CHASSIS_APP_DB) for h, table in js.items(): for k, v in table.items(): client.hset(h, k, v) diff --git a/platform/vs/docker-sonic-vs/database_config.json b/platform/vs/docker-sonic-vs/database_config.json index 73f4c43462a6..86e8142f5084 100644 --- a/platform/vs/docker-sonic-vs/database_config.json +++ b/platform/vs/docker-sonic-vs/database_config.json @@ -73,7 +73,7 @@ "separator": "|", "instance" : "redis" }, - "CHASSIS_DB" : { + "CHASSIS_APP_DB" : { "id" : 11, "separator": "|", "instance" : "redis_chassis" diff --git a/platform/vs/docker-sonic-vs/start.sh b/platform/vs/docker-sonic-vs/start.sh index 1f30dda376e8..349c538e1daf 100755 --- a/platform/vs/docker-sonic-vs/start.sh +++ b/platform/vs/docker-sonic-vs/start.sh @@ -54,16 +54,16 @@ rm -f /var/run/rsyslogd.pid supervisorctl start rsyslogd supervisord_cfg="/etc/supervisor/conf.d/supervisord.conf" -chassis_cfg_file="/usr/share/sonic/virtual_chassis/default_config.json" -chassis_cfg_file_default="/etc/default/sonic-db/default_chassis_cfg.json" +chassisdb_cfg_file="/usr/share/sonic/virtual_chassis/default_config.json" +chassisdb_cfg_file_default="/etc/default/sonic-db/default_chassis_cfg.json" host_template="/usr/share/sonic/templates/hostname.j2" db_cfg_file="/var/run/redis/sonic-db/database_config.json" db_cfg_file_tmp="/var/run/redis/sonic-db/database_config.json.tmp" -if [ -r "$chassis_cfg_file" ]; then - echo $(sonic-cfggen -j $chassis_cfg_file -t $host_template) >> /etc/hosts +if [ -r "$chassisdb_cfg_file" ]; then + echo $(sonic-cfggen -j $chassisdb_cfg_file -t $host_template) >> /etc/hosts else - chassis_cfg_file="$chassis_cfg_file_default" + chassisdb_cfg_file="$chassisdb_cfg_file_default" echo "10.8.1.200 redis_chassis.server" >> /etc/hosts fi @@ -72,16 +72,16 @@ cp /etc/default/sonic-db/database_config.json /var/run/redis/sonic-db/ supervisorctl start redis-server -start_chassis_db=`sonic-cfggen -v DEVICE_METADATA.localhost.start_chassis_db -y $chassis_cfg_file` +start_chassis_db=`sonic-cfggen -v DEVICE_METADATA.localhost.start_chassis_db -y $chassisdb_cfg_file` if [[ "$HOSTNAME" == *"supervisor"* ]] || [ "$start_chassis_db" == "1" ]; then supervisorctl start redis-chassis python /usr/bin/chassis_db.py fi -conn_chassis_db=`sonic-cfggen -v DEVICE_METADATA.localhost.connect_to_chassis_db -y $chassis_cfg_file` +conn_chassis_db=`sonic-cfggen -v DEVICE_METADATA.localhost.connect_to_chassis_db -y $chassisdb_cfg_file` if [ "$start_chassis_db" != "1" ] && [ "$conn_chassis_db" != "1" ]; then cp $db_cfg_file $db_cfg_file_tmp - remove_chassisdb_config -j $db_cfg_file_tmp + update_chassisdb_config -j $db_cfg_file_tmp -d cp $db_cfg_file_tmp $db_cfg_file fi diff --git a/rules/docker-database.mk b/rules/docker-database.mk index 7cfd8f0bf21e..0a2f46d19223 100644 --- a/rules/docker-database.mk +++ b/rules/docker-database.mk @@ -25,3 +25,4 @@ $(DOCKER_DATABASE)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro $(DOCKER_DATABASE)_BASE_IMAGE_FILES += redis-cli:/usr/bin/redis-cli $(DOCKER_DATABASE)_BASE_IMAGE_FILES += monit_database:/etc/monit/conf.d $(DOCKER_DATABASE)_FILES += $(SYSCTL_NET_CONFIG) $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_DATABASE)_FILES += $(UPDATE_CHASSISDB_CONFIG_SCRIPT) diff --git a/rules/scripts.mk b/rules/scripts.mk index 971578db09c4..1e5275a254ba 100644 --- a/rules/scripts.mk +++ b/rules/scripts.mk @@ -20,8 +20,8 @@ $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)_PATH = files/scripts SYSCTL_NET_CONFIG = sysctl-net.conf $(SYSCTL_NET_CONFIG)_PATH = files/image_config/sysctl -RM_CHASSISDB_CONFIG_SCRIPT = remove_chassisdb_config -$(RM_CHASSISDB_CONFIG_SCRIPT)_PATH = files/scripts +UPDATE_CHASSISDB_CONFIG_SCRIPT = update_chassisdb_config +$(UPDATE_CHASSISDB_CONFIG_SCRIPT)_PATH = files/scripts SONIC_COPY_FILES += $(CONFIGDB_LOAD_SCRIPT) \ $(ARP_UPDATE_SCRIPT) \ @@ -30,4 +30,4 @@ SONIC_COPY_FILES += $(CONFIGDB_LOAD_SCRIPT) \ $(QOS_CONFIG_TEMPLATE) \ $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) \ $(SYSCTL_NET_CONFIG) \ - $(RM_CHASSISDB_CONFIG_SCRIPT) + $(UPDATE_CHASSISDB_CONFIG_SCRIPT) diff --git a/slave.mk b/slave.mk index 3e200f9ee45d..6d1829c8b365 100644 --- a/slave.mk +++ b/slave.mk @@ -892,6 +892,15 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ export multi_instance="false" j2 files/build_templates/per_namespace/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service fi + # Any service template, inside share_image directory, will be used to generate -chassis.service file. + # TODO: need better way to name the image-shared service + if [ -f files/build_templates/share_image/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 ]; then + j2 files/build_templates/share_image/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME)-chassis.service + $(if $(shell ls files/build_templates/share_image/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 2>/dev/null),\ + $(eval $(docker:-dbg.gz=.gz)_SHARE = yes) + ) + fi + j2 files/build_templates/docker_image_ctl.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh chmod +x $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh ) @@ -910,6 +919,9 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ $(eval SERVICES += "$(addsuffix @.service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME))"),\ $(eval SERVICES += "$(addsuffix .service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME))") ) + $(if $($(docker:-dbg.gz=.gz)_SHARE),\ + $(eval SERVICES += "$(addsuffix -chassis.service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME))") + ) ) export installer_services="$(SERVICES)"