Skip to content

Commit

Permalink
Add container for GNMI (sonic-net#115)
Browse files Browse the repository at this point in the history
Why I did it
We need two containers, one for telemetry, another one for gnmi native write.

How I did it
Add a new docker, docker-sonic-gnmi

How to verify it
Build image, and check containers with KVM environment.
  • Loading branch information
ganglyu committed Oct 25, 2022
1 parent f1b4b60 commit 781ecdd
Show file tree
Hide file tree
Showing 22 changed files with 311 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile.work
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ SONIC_BUILD_INSTRUCTION := $(MAKE) \
DOCKER_LOCKFILE_SAVE=$(DOCKER_LOCKFILE_SAVE) \
SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD=$(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD) \
SONIC_INCLUDE_SYSTEM_TELEMETRY=$(INCLUDE_SYSTEM_TELEMETRY) \
SONIC_INCLUDE_SYSTEM_GNMI=$(INCLUDE_SYSTEM_GNMI) \
SONIC_INCLUDE_GNMI_TEST=$(INCLUDE_GNMI_TEST) \
INCLUDE_DHCP_RELAY=$(INCLUDE_DHCP_RELAY) \
INCLUDE_MACSEC=$(INCLUDE_MACSEC) \
Expand Down
35 changes: 35 additions & 0 deletions dockers/docker-sonic-gnmi/Dockerfile.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %}
FROM docker-config-engine-bullseye-{{DOCKER_USERNAME}}:{{DOCKER_USERTAG}}

ARG docker_container_name
ARG image_version
RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf

## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive

# Pass the image_version to container
ENV IMAGE_VERSION=$image_version

RUN apt-get update

{% if docker_sonic_gnmi_debs.strip() -%}
# Copy locally-built Debian package dependencies
{{ copy_files("debs/", docker_sonic_gnmi_debs.split(' '), "/debs/") }}

# Install locally-built Debian packages and implicitly install their dependencies
{{ install_debian_packages(docker_sonic_gnmi_debs.split(' ')) }}
{%- endif %}

RUN apt-get clean -y && \
apt-get autoclean - && \
apt-get autoremove -y && \
rm -rf /debs

COPY ["start.sh", "gnmi-native.sh", "dialout.sh", "/usr/bin/"]
COPY ["telemetry_vars.j2", "/usr/share/sonic/templates/"]
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
COPY ["critical_processes", "/etc/supervisor"]

ENTRYPOINT ["/usr/local/bin/supervisord"]
5 changes: 5 additions & 0 deletions dockers/docker-sonic-gnmi/base_image_files/monit_gnmi
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###############################################################################
## Monit configuration for gnmi container
###############################################################################
check program container_memory_telemetry with path "/usr/bin/memory_checker gnmi 419430400"
if status == 3 for 10 times within 20 cycles then exec "/usr/bin/restart_service gnmi" repeat every 2 cycles
1 change: 1 addition & 0 deletions dockers/docker-sonic-gnmi/critical_processes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
program:gnmi-native
6 changes: 6 additions & 0 deletions dockers/docker-sonic-gnmi/dialout.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

# Start with default config
export CVL_SCHEMA_PATH=/usr/sbin/schema
exec /usr/sbin/dialout_client_cli -insecure -logtostderr -v 2

74 changes: 74 additions & 0 deletions dockers/docker-sonic-gnmi/gnmi-native.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env bash

EXIT_TELEMETRY_VARS_FILE_NOT_FOUND=1
TELEMETRY_VARS_FILE=/usr/share/sonic/templates/telemetry_vars.j2

if [ ! -f "$TELEMETRY_VARS_FILE" ]; then
echo "Telemetry vars template file not found"
exit $EXIT_TELEMETRY_VARS_FILE_NOT_FOUND
fi

# Try to read telemetry and certs config from ConfigDB.
# Use default value if no valid config exists
TELEMETRY_VARS=$(sonic-cfggen -d -t $TELEMETRY_VARS_FILE)
TELEMETRY_VARS=${TELEMETRY_VARS//[\']/\"}
X509=$(echo $TELEMETRY_VARS | jq -r '.x509')
GNMI=$(echo $TELEMETRY_VARS | jq -r '.gnmi')
CERTS=$(echo $TELEMETRY_VARS | jq -r '.certs')

TELEMETRY_ARGS=" -logtostderr"
export CVL_SCHEMA_PATH=/usr/sbin/schema

if [ -n "$CERTS" ]; then
SERVER_CRT=$(echo $CERTS | jq -r '.server_crt')
SERVER_KEY=$(echo $CERTS | jq -r '.server_key')
if [ -z $SERVER_CRT ] || [ -z $SERVER_KEY ]; then
TELEMETRY_ARGS+=" --insecure"
else
TELEMETRY_ARGS+=" --server_crt $SERVER_CRT --server_key $SERVER_KEY "
fi

CA_CRT=$(echo $CERTS | jq -r '.ca_crt')
if [ ! -z $CA_CRT ]; then
TELEMETRY_ARGS+=" --ca_crt $CA_CRT"
fi
elif [ -n "$X509" ]; then
SERVER_CRT=$(echo $X509 | jq -r '.server_crt')
SERVER_KEY=$(echo $X509 | jq -r '.server_key')
if [ -z $SERVER_CRT ] || [ -z $SERVER_KEY ]; then
TELEMETRY_ARGS+=" --insecure"
else
TELEMETRY_ARGS+=" --server_crt $SERVER_CRT --server_key $SERVER_KEY "
fi

CA_CRT=$(echo $X509 | jq -r '.ca_crt')
if [ ! -z $CA_CRT ]; then
TELEMETRY_ARGS+=" --ca_crt $CA_CRT"
fi
else
TELEMETRY_ARGS+=" --noTLS"
fi

# If no configuration entry exists for TELEMETRY, create one default port
if [ -z "$GNMI" ]; then
PORT=8080
else
PORT=$(echo $GNMI | jq -r '.port')
fi
TELEMETRY_ARGS+=" --port $PORT"

CLIENT_AUTH=$(echo $GNMI | jq -r '.client_auth')
if [ -z $CLIENT_AUTH ] || [ $CLIENT_AUTH == "false" ]; then
TELEMETRY_ARGS+=" --allow_no_client_auth"
fi

LOG_LEVEL=$(echo $GNMI | jq -r '.log_level')
if [ ! -z $LOG_LEVEL ]; then
TELEMETRY_ARGS+=" -v=$LOG_LEVEL"
else
TELEMETRY_ARGS+=" -v=2"
fi

TELEMETRY_ARGS+=" -gnmi_native_write=true"

exec /usr/sbin/telemetry ${TELEMETRY_ARGS}
14 changes: 14 additions & 0 deletions dockers/docker-sonic-gnmi/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

if [ "${RUNTIME_OWNER}" == "" ]; then
RUNTIME_OWNER="kube"
fi

CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py"
if test -f ${CTR_SCRIPT}
then
${CTR_SCRIPT} -f gnmi -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION}
fi

mkdir -p /var/sonic
echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status
51 changes: 51 additions & 0 deletions dockers/docker-sonic-gnmi/supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[supervisord]
logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true

[eventlistener:dependent-startup]
command=python3 -m supervisord_dependent_startup
autostart=true
autorestart=unexpected
startretries=0
exitcodes=0,3
events=PROCESS_STATE
buffer_size=1024

[eventlistener:supervisor-proc-exit-listener]
command=/usr/bin/supervisor-proc-exit-listener --container-name telemetry
events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING
autostart=true
autorestart=false
buffer_size=1024

[program:rsyslogd]
command=/usr/sbin/rsyslogd -n -iNONE
priority=1
autostart=false
autorestart=true
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true

[program:start]
command=/usr/bin/start.sh
priority=2
autostart=false
autorestart=false
startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=rsyslogd:running

[program:gnmi-native]
command=/usr/bin/gnmi-native.sh
priority=3
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=start:exited

5 changes: 5 additions & 0 deletions dockers/docker-sonic-gnmi/telemetry_vars.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"certs": {% if "certs" in GNMI.keys() %}{{ GNMI["certs"] }}{% else %}""{% endif %},
"gnmi" : {% if "gnmi" in GNMI.keys() %}{{ GNMI["gnmi"] }}{% else %}""{% endif %},
"x509" : {% if "x509" in DEVICE_METADATA.keys() %}{{ DEVICE_METADATA["x509"] }}{% else %}""{% endif %}
}
2 changes: 2 additions & 0 deletions dockers/docker-sonic-telemetry/telemetry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ else
TELEMETRY_ARGS+=" -v=2"
fi

TELEMETRY_ARGS+=" -gnmi_native_write=false"

exec /usr/sbin/telemetry ${TELEMETRY_ARGS}
16 changes: 16 additions & 0 deletions files/build_templates/gnmi.service.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[Unit]
Description=GNMI container
Requires=database.service
After=database.service swss.service syncd.service
Before=ntp-config.service
BindsTo=sonic.target
After=sonic.target
StartLimitIntervalSec=1200
StartLimitBurst=3

[Service]
User={{ sonicadmin_user }}
ExecStartPre=/usr/local/bin/{{docker_container_name}}.sh start
ExecStart=/usr/local/bin/{{docker_container_name}}.sh wait
ExecStop=/usr/local/bin/{{docker_container_name}}.sh stop
RestartSec=30
11 changes: 11 additions & 0 deletions files/build_templates/gnmi.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Unit]
Description=Delays gnmi container until SONiC has started
PartOf=gnmi.service

[Timer]
OnUnitActiveSec=0 sec
OnBootSec=3min 30 sec
Unit=gnmi.service

[Install]
WantedBy=timers.target sonic.target sonic-delayed.target
3 changes: 2 additions & 1 deletion files/build_templates/init_cfg.json.j2
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
{%- if include_sflow == "y" %}{% do features.append(("sflow", "disabled", false, "enabled")) %}{% endif %}
{%- if include_macsec == "y" %}{% do features.append(("macsec", "disabled", false, "enabled")) %}{% endif %}
{%- if include_system_telemetry == "y" %}{% do features.append(("telemetry", "enabled", true, "enabled")) %}{% endif %}
{%- if include_system_gnmi == "y" %}{% do features.append(("gnmi", "enabled", true, "enabled")) %}{% endif %}
"FEATURE": {
{# has_timer field if set, will start the feature systemd .timer unit instead of .service unit #}
{%- for feature, state, has_timer, autorestart in features %}
Expand All @@ -70,7 +71,7 @@
"check_up_status" : "false",
{%- endif %}
{%- if include_kubernetes == "y" %}
{%- if feature in ["lldp", "pmon", "radv", "eventd", "snmp", "telemetry"] %}
{%- if feature in ["lldp", "pmon", "radv", "eventd", "snmp", "telemetry", "gnmi"] %}
"set_owner": "kube", {% else %}
"set_owner": "local", {% endif %} {% endif %}
"high_mem_alert": "disabled"
Expand Down
6 changes: 6 additions & 0 deletions files/build_templates/sonic_debian_extension.j2
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,7 @@ sudo LANG=C cp $SCRIPTS_DIR/radv.sh $FILESYSTEM_ROOT/usr/local/bin/radv.sh
sudo LANG=C cp $SCRIPTS_DIR/database.sh $FILESYSTEM_ROOT/usr/local/bin/database.sh
sudo LANG=C cp $SCRIPTS_DIR/snmp.sh $FILESYSTEM_ROOT/usr/local/bin/snmp.sh
sudo LANG=C cp $SCRIPTS_DIR/telemetry.sh $FILESYSTEM_ROOT/usr/local/bin/telemetry.sh
sudo LANG=C cp $SCRIPTS_DIR/gnmi.sh $FILESYSTEM_ROOT/usr/local/bin/gnmi.sh
sudo LANG=C cp $SCRIPTS_DIR/mgmt-framework.sh $FILESYSTEM_ROOT/usr/local/bin/mgmt-framework.sh
sudo LANG=C cp $SCRIPTS_DIR/asic_status.sh $FILESYSTEM_ROOT/usr/local/bin/asic_status.sh
sudo LANG=C cp $SCRIPTS_DIR/asic_status.py $FILESYSTEM_ROOT/usr/local/bin/asic_status.py
Expand All @@ -893,6 +894,11 @@ sudo cp $BUILD_TEMPLATES/telemetry.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM
echo "telemetry.timer" | sudo tee -a $GENERATED_SERVICE_FILE
{% endif %}

{% if include_system_gnmi == 'y' %}
sudo cp $BUILD_TEMPLATES/gnmi.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM
echo "gnmi.timer" | sudo tee -a $GENERATED_SERVICE_FILE
{% endif %}

{% if include_mgmt_framework == 'y' %}
sudo cp $BUILD_TEMPLATES/mgmt-framework.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM
echo "mgmt-framework.timer" | sudo tee -a $GENERATED_SERVICE_FILE
Expand Down
1 change: 1 addition & 0 deletions files/image_config/logrotate/rsyslog.j2
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
/var/log/syslog
/var/log/teamd.log
/var/log/telemetry.log
/var/log/gnmi.log
/var/log/frr/bgpd.log
/var/log/frr/zebra.log
/var/log/swss/sairedis*.rec
Expand Down
6 changes: 6 additions & 0 deletions files/image_config/rsyslog/rsyslog.d/00-sonic.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ if $programname contains "teamd_" then {
stop
}

## gnmi rules
if $programname contains "gnmi#" then {
/var/log/gnmi.log
stop
}

## telemetry rules
if $msg startswith " telemetry" or ($msg startswith " dialout" )then {
/var/log/telemetry.log
Expand Down
1 change: 1 addition & 0 deletions files/scripts/gnmi.sh
3 changes: 3 additions & 0 deletions rules/config
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ DEFAULT_VS_PREPARE_MEM = yes
# INCLUDE_SYSTEM_TELEMETRY - build docker-sonic-telemetry for system telemetry support
INCLUDE_SYSTEM_TELEMETRY = y

# INCLUDE_SYSTEM_GNMI - build docker-sonic-gnmi for system gnmi support
INCLUDE_SYSTEM_GNMI = y

# INCLUDE_GNMI_TEST - build docker-gnmi-test for gnmi test container
INCLUDE_GNMI_TEST = y

Expand Down
11 changes: 11 additions & 0 deletions rules/docker-gnmi.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

DPATH := $($(DOCKER_GNMI)_PATH)
DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-gnmi.mk rules/docker-gnmi.dep
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
DEP_FILES += $(shell git ls-files $(DPATH))

$(DOCKER_GNMI)_CACHE_MODE := GIT_CONTENT_SHA
$(DOCKER_GNMI)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
$(DOCKER_GNMI)_DEP_FILES := $(DEP_FILES)

$(eval $(call add_dbg_docker,$(DOCKER_GNMI),$(DOCKER_GNMI_DBG)))
37 changes: 37 additions & 0 deletions rules/docker-gnmi.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# docker image for gnmi agent

DOCKER_GNMI_STEM = docker-sonic-gnmi
DOCKER_GNMI = $(DOCKER_GNMI_STEM).gz
DOCKER_GNMI_DBG = $(DOCKER_GNMI_STEM)-$(DBG_IMAGE_MARK).gz

$(DOCKER_GNMI)_PATH = $(DOCKERS_PATH)/$(DOCKER_GNMI_STEM)

$(DOCKER_GNMI)_DEPENDS += $(SONIC_MGMT_COMMON)
$(DOCKER_GNMI)_DEPENDS += $(SONIC_TELEMETRY)
$(DOCKER_GNMI)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BULLSEYE)_DBG_DEPENDS)

$(DOCKER_GNMI)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BULLSEYE)

$(DOCKER_GNMI)_VERSION = 1.0.0
$(DOCKER_GNMI)_PACKAGE_NAME = gnmi

$(DOCKER_GNMI)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BULLSEYE)_DBG_IMAGE_PACKAGES)

SONIC_DOCKER_IMAGES += $(DOCKER_GNMI)
ifeq ($(INCLUDE_SYSTEM_GNMI), y)
SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_GNMI)
endif

SONIC_DOCKER_DBG_IMAGES += $(DOCKER_GNMI_DBG)
ifeq ($(INCLUDE_SYSTEM_GNMI), y)
SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_GNMI_DBG)
endif

$(DOCKER_GNMI)_CONTAINER_NAME = gnmi
$(DOCKER_GNMI)_RUN_OPT += --privileged -t
$(DOCKER_GNMI)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
$(DOCKER_GNMI)_RUN_OPT += -v /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro
$(DOCKER_GNMI)_RUN_OPT += -v /var/run/dbus:/var/run/dbus:rw

$(DOCKER_GNMI)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
$(DOCKER_GNMI)_BASE_IMAGE_FILES += monit_gnmi:/etc/monit/conf.d
6 changes: 6 additions & 0 deletions slave.mk
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ ifeq ($(SONIC_INCLUDE_SYSTEM_TELEMETRY),y)
INCLUDE_SYSTEM_TELEMETRY = y
endif

ifeq ($(SONIC_INCLUDE_SYSTEM_GNMI),y)
INCLUDE_SYSTEM_GNMI = y
endif

ifeq ($(SONIC_INCLUDE_GNMI_TEST),y)
INCLUDE_GNMI_TEST = y
endif
Expand Down Expand Up @@ -383,6 +387,7 @@ $(info "VS_PREPARE_MEM" : "$(VS_PREPARE_MEM)")
$(info "INCLUDE_MGMT_FRAMEWORK" : "$(INCLUDE_MGMT_FRAMEWORK)")
$(info "INCLUDE_ICCPD" : "$(INCLUDE_ICCPD)")
$(info "INCLUDE_SYSTEM_TELEMETRY" : "$(INCLUDE_SYSTEM_TELEMETRY)")
$(info "INCLUDE_SYSTEM_GNMI" : "$(INCLUDE_SYSTEM_GNMI)")
$(info "INCLUDE_GNMI_TEST" : "$(INCLUDE_GNMI_TEST)")
$(info "ENABLE_HOST_SERVICE_ON_START" : "$(ENABLE_HOST_SERVICE_ON_START)")
$(info "INCLUDE_RESTAPI" : "$(INCLUDE_RESTAPI)")
Expand Down Expand Up @@ -1187,6 +1192,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
export enable_dhcp_graph_service="$(ENABLE_DHCP_GRAPH_SERVICE)"
export enable_ztp="$(ENABLE_ZTP)"
export include_system_telemetry="$(INCLUDE_SYSTEM_TELEMETRY)"
export include_system_gnmi="$(INCLUDE_SYSTEM_GNMI)"
export include_gnmi_test="$(INCLUDE_GNMI_TEST)"
export include_restapi="$(INCLUDE_RESTAPI)"
export include_nat="$(INCLUDE_NAT)"
Expand Down
Loading

0 comments on commit 781ecdd

Please sign in to comment.