Merged PR 3845699: [linkmgrd]: Introduce MUX cable linkmgrd
Linkmgrd monitors link status, mux status, and link state. Has the link becomes unhealthy, linkmgrd will trigger mux switchover on a standby ToR ensuring uninterrupted service to servers/blades. This PR is initial implementation of linkmgrd. Also, docker-mux container hold packages related to maintaining and managing mux cable. It currently runs linkmgrd binary that monitor and switches the mux if needed. This PR also introduces mux-container and starts linkmgrd as startup when build is configured with INCLUDE_MUX=y Edit: linkmgrd PR will follow. signed-off-by: Tamer Ahmed <tamer.ahmed@microsoft.com> Related work items: #2315, #3146150
This commit is contained in:
parent
8138a34a0b
commit
b8f70f8986
@ -10,6 +10,7 @@
|
|||||||
# * ENABLE_ZTP: Enables zero touch provisioning.
|
# * ENABLE_ZTP: Enables zero touch provisioning.
|
||||||
# * SHUTDOWN_BGP_ON_START: Sets admin-down state for all bgp peerings after restart.
|
# * SHUTDOWN_BGP_ON_START: Sets admin-down state for all bgp peerings after restart.
|
||||||
# * INCLUDE_KUBERNETES: Allows including Kubernetes
|
# * INCLUDE_KUBERNETES: Allows including Kubernetes
|
||||||
|
# * INCLUDE_MUX: Include MUX feature/services for TOR switch.
|
||||||
# * ENABLE_PFCWD_ON_START: Enable PFC Watchdog (PFCWD) on server-facing ports
|
# * ENABLE_PFCWD_ON_START: Enable PFC Watchdog (PFCWD) on server-facing ports
|
||||||
# * by default for TOR switch.
|
# * by default for TOR switch.
|
||||||
# * ENABLE_SYNCD_RPC: Enables rpc-based syncd builds.
|
# * ENABLE_SYNCD_RPC: Enables rpc-based syncd builds.
|
||||||
@ -267,6 +268,7 @@ SONIC_BUILD_INSTRUCTION := make \
|
|||||||
HTTPS_PROXY=$(https_proxy) \
|
HTTPS_PROXY=$(https_proxy) \
|
||||||
SONIC_INCLUDE_SYSTEM_TELEMETRY=$(INCLUDE_SYSTEM_TELEMETRY) \
|
SONIC_INCLUDE_SYSTEM_TELEMETRY=$(INCLUDE_SYSTEM_TELEMETRY) \
|
||||||
SONIC_INCLUDE_RESTAPI=$(INCLUDE_RESTAPI) \
|
SONIC_INCLUDE_RESTAPI=$(INCLUDE_RESTAPI) \
|
||||||
|
SONIC_INCLUDE_MUX=$(INCLUDE_MUX) \
|
||||||
TELEMETRY_WRITABLE=$(TELEMETRY_WRITABLE) \
|
TELEMETRY_WRITABLE=$(TELEMETRY_WRITABLE) \
|
||||||
EXTRA_DOCKER_TARGETS=$(EXTRA_DOCKER_TARGETS) \
|
EXTRA_DOCKER_TARGETS=$(EXTRA_DOCKER_TARGETS) \
|
||||||
BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \
|
BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \
|
||||||
|
36
dockers/docker-mux/Dockerfile.j2
Executable file
36
dockers/docker-mux/Dockerfile.j2
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %}
|
||||||
|
FROM docker-config-engine-buster
|
||||||
|
|
||||||
|
ARG docker_container_name
|
||||||
|
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
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -f -y \
|
||||||
|
libmnl0
|
||||||
|
|
||||||
|
{% if docker_mux_debs.strip() -%}
|
||||||
|
# Copy locally-built Debian package dependencies
|
||||||
|
{{ copy_files("debs/", docker_mux_debs.split(' '), "/debs/") }}
|
||||||
|
|
||||||
|
# Install locally-built Debian packages and implicitly install their dependencies
|
||||||
|
{{ install_debian_packages(docker_mux_debs.split(' ')) }}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
## Clean up
|
||||||
|
RUN apt-get clean -y && \
|
||||||
|
apt-get autoclean -y && \
|
||||||
|
apt-get autoremove -y && \
|
||||||
|
rm -rf /debs
|
||||||
|
|
||||||
|
COPY ["docker-init.sh", "/usr/bin/"]
|
||||||
|
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
|
||||||
|
COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
|
||||||
|
COPY ["critical_processes", "/etc/supervisor/"]
|
||||||
|
|
||||||
|
## Copy all Jinja2 template files into the templates folder
|
||||||
|
COPY ["*.j2", "/usr/share/sonic/templates/"]
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/bin/docker-init.sh"]
|
1
dockers/docker-mux/critical_processes
Normal file
1
dockers/docker-mux/critical_processes
Normal file
@ -0,0 +1 @@
|
|||||||
|
program:linkmgrd
|
9
dockers/docker-mux/docker-init.sh
Executable file
9
dockers/docker-mux/docker-init.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Generate supervisord config file
|
||||||
|
mkdir -p /etc/supervisor/conf.d/
|
||||||
|
|
||||||
|
# The docker container should start this script as PID 1, so now that supervisord is
|
||||||
|
# properly configured, we exec supervisord so that it runs as PID 1 for the
|
||||||
|
# duration of the container's lifetime
|
||||||
|
exec /usr/local/bin/supervisord
|
41
dockers/docker-mux/supervisord.conf
Normal file
41
dockers/docker-mux/supervisord.conf
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
[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=100
|
||||||
|
|
||||||
|
[eventlistener:supervisor-proc-exit-listener]
|
||||||
|
command=/usr/bin/supervisor-proc-exit-listener --container-name mux
|
||||||
|
events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING
|
||||||
|
autostart=true
|
||||||
|
autorestart=unexpected
|
||||||
|
|
||||||
|
[program:rsyslogd]
|
||||||
|
command=/usr/sbin/rsyslogd -n -iNONE
|
||||||
|
priority=1
|
||||||
|
autostart=false
|
||||||
|
autorestart=unexpected
|
||||||
|
stdout_logfile=syslog
|
||||||
|
stderr_logfile=syslog
|
||||||
|
dependent_startup=true
|
||||||
|
|
||||||
|
[program:linkmgrd]
|
||||||
|
command=nice -n -20 /usr/sbin/linkmgrd -v warning
|
||||||
|
priority=2
|
||||||
|
autostart=false
|
||||||
|
autorestart=false
|
||||||
|
startsecs=0
|
||||||
|
startretries=0
|
||||||
|
stdout_logfile=syslog
|
||||||
|
stderr_logfile=syslog
|
||||||
|
dependent_startup=true
|
||||||
|
dependent_startup_wait_for=rsyslogd:running
|
||||||
|
|
@ -31,6 +31,7 @@
|
|||||||
{%- if sonic_asic_platform == "vs" %}{% do features.append(("gbsyncd", "enabled", false, "enabled")) %}{% endif %}
|
{%- if sonic_asic_platform == "vs" %}{% do features.append(("gbsyncd", "enabled", false, "enabled")) %}{% endif %}
|
||||||
{%- if include_iccpd == "y" %}{% do features.append(("iccpd", "disabled", false, "enabled")) %}{% endif %}
|
{%- if include_iccpd == "y" %}{% do features.append(("iccpd", "disabled", false, "enabled")) %}{% endif %}
|
||||||
{%- if include_mgmt_framework == "y" %}{% do features.append(("mgmt-framework", "enabled", true, "enabled")) %}{% endif %}
|
{%- if include_mgmt_framework == "y" %}{% do features.append(("mgmt-framework", "enabled", true, "enabled")) %}{% endif %}
|
||||||
|
{%- if include_mux == "y" %}{% do features.append(("mux", "enabled", false, "enabled")) %}{% endif %}
|
||||||
{%- if include_nat == "y" %}{% do features.append(("nat", "disabled", false, "enabled")) %}{% endif %}
|
{%- if include_nat == "y" %}{% do features.append(("nat", "disabled", false, "enabled")) %}{% endif %}
|
||||||
{%- if include_restapi == "y" %}{% do features.append(("restapi", "enabled", false, "enabled")) %}{% endif %}
|
{%- if include_restapi == "y" %}{% do features.append(("restapi", "enabled", false, "enabled")) %}{% endif %}
|
||||||
{%- if include_sflow == "y" %}{% do features.append(("sflow", "disabled", false, "enabled")) %}{% endif %}
|
{%- if include_sflow == "y" %}{% do features.append(("sflow", "disabled", false, "enabled")) %}{% endif %}
|
||||||
|
17
files/build_templates/mux.service.j2
Normal file
17
files/build_templates/mux.service.j2
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=MUX Cable Container
|
||||||
|
Requires=database.service updategraph.service pmon.service swss.service
|
||||||
|
After=pmon.service swss.service
|
||||||
|
StartLimitIntervalSec=1200
|
||||||
|
StartLimitBurst=3
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User={{ sonicadmin_user }}
|
||||||
|
ExecStartPre=/usr/bin/{{docker_container_name}}.sh start
|
||||||
|
ExecStart=/usr/bin/{{docker_container_name}}.sh wait
|
||||||
|
ExecStop=/usr/bin/{{docker_container_name}}.sh stop
|
||||||
|
Restart=always
|
||||||
|
RestartSec=30
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -191,3 +191,6 @@ SONIC_VERSION_CONTROL_COMPONENTS ?= none
|
|||||||
# Set the env variable ENABLE_DOCKER_BASE_PULL = y to enable pulling sonic-slave docker from registry
|
# Set the env variable ENABLE_DOCKER_BASE_PULL = y to enable pulling sonic-slave docker from registry
|
||||||
REGISTRY_PORT ?= 443
|
REGISTRY_PORT ?= 443
|
||||||
REGISTRY_SERVER ?= sonicdev-microsoft.azurecr.io
|
REGISTRY_SERVER ?= sonicdev-microsoft.azurecr.io
|
||||||
|
|
||||||
|
# INCLUDE_MUX - build docker-mux for dual ToR (Gemini)
|
||||||
|
INCLUDE_MUX = y
|
||||||
|
12
rules/docker-mux.dep
Normal file
12
rules/docker-mux.dep
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
DPATH := $($(DOCKER_MUX)_PATH)
|
||||||
|
DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-mux.mk rules/docker-mux.dep
|
||||||
|
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
|
||||||
|
DEP_FILES += $(shell git ls-files $(DPATH))
|
||||||
|
|
||||||
|
$(DOCKER_MUX)_CACHE_MODE := GIT_CONTENT_SHA
|
||||||
|
$(DOCKER_MUX)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
|
||||||
|
$(DOCKER_MUX)_DEP_FILES := $(DEP_FILES)
|
||||||
|
|
||||||
|
$(eval $(call add_dbg_docker,$(DOCKER_MUX),$(DOCKER_MUX_DBG)))
|
||||||
|
|
32
rules/docker-mux.mk
Normal file
32
rules/docker-mux.mk
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Docker image for MUX
|
||||||
|
|
||||||
|
DOCKER_MUX_STEM = docker-mux
|
||||||
|
DOCKER_MUX = $(DOCKER_MUX_STEM).gz
|
||||||
|
DOCKER_MUX_DBG = $(DOCKER_MUX_STEM)-$(DBG_IMAGE_MARK).gz
|
||||||
|
|
||||||
|
$(DOCKER_MUX)_PATH = $(DOCKERS_PATH)/$(DOCKER_MUX_STEM)
|
||||||
|
|
||||||
|
$(DOCKER_MUX)_DEPENDS = $(SONIC_LINKMGRD) $(LIBSWSSCOMMON) $(LIBHIREDIS)
|
||||||
|
$(DOCKER_MUX)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS)
|
||||||
|
$(DOCKER_MUX)_DBG_DEPENDS += $(SONIC_LINKMGRD_DBG) $(LIBSWSSCOMMON_DBG) $(LIBHIREDIS_DBG)
|
||||||
|
|
||||||
|
$(DOCKER_MUX)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES)
|
||||||
|
|
||||||
|
$(DOCKER_MUX)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE_BUSTER)
|
||||||
|
|
||||||
|
ifeq ($(INCLUDE_MUX), y)
|
||||||
|
SONIC_DOCKER_IMAGES += $(DOCKER_MUX)
|
||||||
|
SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_MUX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(INCLUDE_MUX), y)
|
||||||
|
SONIC_DOCKER_DBG_IMAGES += $(DOCKER_MUX_DBG)
|
||||||
|
SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_MUX_DBG)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(DOCKER_MUX)_CONTAINER_NAME = mux
|
||||||
|
$(DOCKER_MUX)_RUN_OPT += --privileged -t
|
||||||
|
$(DOCKER_MUX)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
|
||||||
|
$(DOCKER_ORCHAGENT)_RUN_OPT += -v /var/log/mux:/var/log/mux:rw
|
||||||
|
$(DOCKER_MUX)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
|
||||||
|
|
11
rules/linkmgrd.dep
Normal file
11
rules/linkmgrd.dep
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
SPATH := $($(SONIC_LINKMGRD)_SRC_PATH)
|
||||||
|
DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/linkmgrd.mk rules/linkmgrd.dep
|
||||||
|
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
|
||||||
|
SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files))
|
||||||
|
|
||||||
|
$(SONIC_LINKMGRD)_CACHE_MODE := GIT_CONTENT_SHA
|
||||||
|
$(SONIC_LINKMGRD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
|
||||||
|
$(SONIC_LINKMGRD)_DEP_FILES := $(DEP_FILES)
|
||||||
|
$(SONIC_LINKMGRD)_SMDEP_FILES := $(SMDEP_FILES)
|
||||||
|
$(SONIC_LINKMGRD)_SMDEP_PATHS := $(SPATH)
|
18
rules/linkmgrd.mk
Normal file
18
rules/linkmgrd.mk
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# SONiC LINK ManaGeR Daemon package
|
||||||
|
|
||||||
|
SONIC_LINKMGRD_VERSION = 1.0.0-1
|
||||||
|
SONIC_LINKMGRD_PKG_NAME = linkmgrd
|
||||||
|
|
||||||
|
export SONIC_LINKMGRD_VERSION SONIC_LINKMGRD_PKG_NAME
|
||||||
|
|
||||||
|
SONIC_LINKMGRD = sonic-$(SONIC_LINKMGRD_PKG_NAME)_$(SONIC_LINKMGRD_VERSION)_$(CONFIGURED_ARCH).deb
|
||||||
|
$(SONIC_LINKMGRD)_SRC_PATH = $(SRC_PATH)/$(SONIC_LINKMGRD_PKG_NAME)
|
||||||
|
$(SONIC_LINKMGRD)_DEPENDS = $(LIBSWSSCOMMON_DEV) $(LIBSWSSCOMMON) $(LIBHIREDIS_DEV) $(LIBHIREDIS)
|
||||||
|
|
||||||
|
SONIC_DPKG_DEBS += $(SONIC_LINKMGRD)
|
||||||
|
|
||||||
|
SONIC_LINKMGRD_DBG = sonic-$(SONIC_LINKMGRD_PKG_NAME)-dbgsym_$(SONIC_LINKMGRD_VERSION)_$(CONFIGURED_ARCH).deb
|
||||||
|
$(SONIC_LINKMGRD)_DBG_DEPENDS = $(LIBSWSSCOMMON_DEV) $(LIBSWSSCOMMON_DBG) $(LIBHIREDIS_DEV) $(LIBHIREDIS_DBG)
|
||||||
|
$(eval $(call add_derived_package,$(SONIC_LINKMGRD),$(SONIC_LINKMGRD_DBG)))
|
||||||
|
|
||||||
|
export SONIC_LINKMGRD SONIC_LINKMGRD_DBG
|
7
slave.mk
7
slave.mk
@ -153,6 +153,10 @@ INCLUDE_NAT = y
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(SONIC_INCLUDE_MUX),y)
|
||||||
|
INCLUDE_MUX = y
|
||||||
|
endif
|
||||||
|
|
||||||
include $(RULES_PATH)/functions
|
include $(RULES_PATH)/functions
|
||||||
|
|
||||||
ifeq ($(SONIC_USE_PDDF_FRAMEWORK),y)
|
ifeq ($(SONIC_USE_PDDF_FRAMEWORK),y)
|
||||||
@ -266,6 +270,7 @@ $(info "INCLUDE_RESTAPI" : "$(INCLUDE_RESTAPI)")
|
|||||||
$(info "INCLUDE_SFLOW" : "$(INCLUDE_SFLOW)")
|
$(info "INCLUDE_SFLOW" : "$(INCLUDE_SFLOW)")
|
||||||
$(info "INCLUDE_NAT" : "$(INCLUDE_NAT)")
|
$(info "INCLUDE_NAT" : "$(INCLUDE_NAT)")
|
||||||
$(info "INCLUDE_KUBERNETES" : "$(INCLUDE_KUBERNETES)")
|
$(info "INCLUDE_KUBERNETES" : "$(INCLUDE_KUBERNETES)")
|
||||||
|
$(info "INCLUDE_MUX" : "$(INCLUDE_MUX)")
|
||||||
$(info "TELEMETRY_WRITABLE" : "$(TELEMETRY_WRITABLE)")
|
$(info "TELEMETRY_WRITABLE" : "$(TELEMETRY_WRITABLE)")
|
||||||
$(info "PDDF_SUPPORT" : "$(PDDF_SUPPORT)")
|
$(info "PDDF_SUPPORT" : "$(PDDF_SUPPORT)")
|
||||||
$(info "MULTIARCH_QEMU_ENVIRON" : "$(MULTIARCH_QEMU_ENVIRON)")
|
$(info "MULTIARCH_QEMU_ENVIRON" : "$(MULTIARCH_QEMU_ENVIRON)")
|
||||||
@ -944,7 +949,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
|
|||||||
export python_swss_debs+=" $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(LIBSWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON_SWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON3_SWSSCOMMON))"
|
export python_swss_debs+=" $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(LIBSWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON_SWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON3_SWSSCOMMON))"
|
||||||
export sonic_utilities_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_UTILITIES_PY3))"
|
export sonic_utilities_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_UTILITIES_PY3))"
|
||||||
export sonic_host_services_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_HOST_SERVICES_PY3))"
|
export sonic_host_services_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_HOST_SERVICES_PY3))"
|
||||||
|
export include_mux="$(INCLUDE_MUX)"
|
||||||
$(foreach docker, $($*_DOCKERS),\
|
$(foreach docker, $($*_DOCKERS),\
|
||||||
export docker_image="$(docker)"
|
export docker_image="$(docker)"
|
||||||
export docker_image_name="$(basename $(docker))"
|
export docker_image_name="$(basename $(docker))"
|
||||||
|
Loading…
Reference in New Issue
Block a user