Skip to content

Commit 73dd38a

Browse files
authored
[dhcp_server] Add dhcpservd to dhcp_server container (#16560)
Why I did it Part implementation of dhcp_server. HLD: sonic-net/SONiC#1282. Add dhcpservd to dhcp_server container. How I did it Add installing required pkg (psutil) in Dockerfile. Add copying required file to container in Dockerfile (kea-dhcp related and dhcpservd related) Add critical_process and supervisor config. Add support for generating kea config (only in dhcpservd.py) and updating lease table (in dhcpservd.py and lease_update.sh) How to verify it Build image with setting INCLUDE_DHCP_SERVER to y and enabled dhcp_server feature after installed image, container start as expected. Enter container and found that all processes defined in supervisor configuration running as expected. Kill processes defined in critical_processes, container exist.
1 parent 1dd0bec commit 73dd38a

33 files changed

+2139
-5
lines changed

dockers/docker-dhcp-server/Dockerfile.j2

+19-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ FROM docker-config-engine-bullseye-{{DOCKER_USERNAME}}:{{DOCKER_USERTAG}}
33

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

78
## Make apt-get non-interactive
89
ENV DEBIAN_FRONTEND=noninteractive
@@ -13,6 +14,7 @@ ENV IMAGE_VERSION=$image_version
1314
RUN apt-get update && \
1415
apt-get install -f -y \
1516
tcpdump \
17+
python3-dev \
1618
# For kea build environment
1719
automake \
1820
libtool \
@@ -47,7 +49,9 @@ RUN echo "/usr/local/lib/kea/hooks" > /etc/ld.so.conf.d/kea.conf && \
4749
RUN cd /usr/local/sbin && rm -f kea-admin kea-ctrl-agent kea-dhcp-ddns kea-dhcp6 keactrl
4850
# Remove hook lib we don't need
4951
RUN cd /usr/local/lib/kea/hooks && rm -f libdhcp_bootp.so libdhcp_flex_option.so libdhcp_stat_cmds.so
50-
# RUN pip3 install psutil
52+
RUN pip3 install psutil
53+
# TODO issue on remote rsyslog server in non-host container
54+
RUN rm -f /etc/supervisor/conf.d/containercfgd.conf
5155

5256
{% if docker_dhcp_server_debs.strip() -%}
5357
# Copy locally-built Debian package dependencies
@@ -57,23 +61,36 @@ RUN cd /usr/local/lib/kea/hooks && rm -f libdhcp_bootp.so libdhcp_flex_option.so
5761
{{ install_debian_packages(docker_dhcp_server_debs.split(' ')) }}
5862
{%- endif %}
5963

64+
{% if docker_dhcp_server_whls.strip() %}
65+
# Copy locally-built Python wheel dependencies
66+
{{ copy_files("python-wheels/", docker_dhcp_server_whls.split(' '), "/python-wheels/") }}
67+
68+
# Install locally-built Python wheel dependencies
69+
{{ install_python_wheels(docker_dhcp_server_whls.split(' ')) }}
70+
{% endif %}
71+
6072
# Remove build stuff we don't need
6173
RUN apt-get remove -y devscripts \
6274
automake \
6375
libtool \
6476
pkg-config \
6577
build-essential \
78+
python3-dev \
6679
ccache
6780

6881
RUN apt-get clean -y && \
6982
apt-get autoclean -y && \
7083
apt-get autoremove -y && \
7184
rm -rf /debs
7285

73-
COPY ["docker_init.sh", "/usr/bin/"]
86+
COPY ["docker_init.sh", "start.sh", "/usr/bin/"]
7487
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
7588
COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
89+
COPY ["port-name-alias-map.txt.j2", "rsyslog/rsyslog.conf.j2", "kea-dhcp4.conf.j2", "/usr/share/sonic/templates/"]
7690
COPY ["critical_processes", "/etc/supervisor/"]
91+
COPY ["lease_update.sh", "/etc/kea/"]
92+
COPY ["kea-dhcp4-init.conf", "/etc/kea/kea-dhcp4.conf"]
7793
COPY ["cli", "/cli/"]
94+
COPY ["rsyslog/default.conf", "/etc/rsyslog.d"]
7895

7996
ENTRYPOINT ["/usr/bin/docker_init.sh"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
group:dhcp-server-ipv4

dockers/docker-dhcp-server/docker_init.sh

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
#!/usr/bin/env bash
22

3+
4+
# Generate supervisord config file
5+
mkdir -p /etc/supervisor/conf.d/
6+
# Generate kea folder
7+
mkdir -p /etc/kea/
8+
udp_server_ip=$(ip -j -4 addr list lo scope host | jq -r -M '.[0].addr_info[0].local')
9+
hostname=$(hostname)
10+
# Generate the following files from templates:
11+
# port-to-alias name map
12+
sonic-cfggen -d -t /usr/share/sonic/templates/rsyslog.conf.j2 \
13+
-a "{\"udp_server_ip\": \"$udp_server_ip\", \"hostname\": \"$hostname\"}" \
14+
> /etc/rsyslog.conf
15+
sonic-cfggen -d -t /usr/share/sonic/templates/port-name-alias-map.txt.j2,/tmp/port-name-alias-map.txt
16+
17+
# Make the script that waits for all interfaces to come up executable
18+
chmod +x /etc/kea/lease_update.sh /usr/bin/start.sh
319
# The docker container should start this script as PID 1, so now that supervisord is
420
# properly configured, we exec /usr/local/bin/supervisord so that it runs as PID 1 for the
521
# duration of the container's lifetime
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"Dhcp4": {
3+
"hooks-libraries": [
4+
{
5+
"library": "/usr/local/lib/kea/hooks/libdhcp_run_script.so",
6+
"parameters": {
7+
"name": "/etc/kea/lease_update.sh",
8+
"sync": false
9+
}
10+
}
11+
],
12+
"interfaces-config": {
13+
"interfaces": ["eth0"]
14+
},
15+
"control-socket": {
16+
"socket-type": "unix",
17+
"socket-name": "/run/kea/kea4-ctrl-socket"
18+
},
19+
"lease-database": {
20+
"type": "memfile",
21+
"persist": true,
22+
"name": "/tmp/kea-lease.csv",
23+
"lfc-interval": 3600
24+
},
25+
"subnet4": [],
26+
"loggers": [
27+
{
28+
"name": "kea-dhcp4",
29+
"output_options": [
30+
{
31+
"output": "/tmp/kea-dhcp.log",
32+
"pattern": "%-5p %m\n"
33+
}
34+
],
35+
"severity": "INFO",
36+
"debuglevel": 0
37+
}
38+
]
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{%- set default_lease_time = 900 -%}
2+
{
3+
"Dhcp4": {
4+
"hooks-libraries": [
5+
{
6+
"library": "/usr/local/lib/kea/hooks/libdhcp_run_script.so",
7+
"parameters": {
8+
"name": "{{ lease_update_script_path }}",
9+
"sync": false
10+
}
11+
}
12+
],
13+
"interfaces-config": {
14+
"interfaces": [
15+
"eth0"
16+
]
17+
},
18+
"control-socket": {
19+
"socket-type": "unix",
20+
"socket-name": "/run/kea/kea4-ctrl-socket"
21+
},
22+
"lease-database": {
23+
"type": "memfile",
24+
"persist": true,
25+
"name": "{{ lease_path }}",
26+
"lfc-interval": 3600
27+
},
28+
"subnet4": [
29+
{%- set add_subnet_preceding_comma = { 'flag': False } %}
30+
{%- for subnet_info in subnets %}
31+
{%- if add_subnet_preceding_comma.flag -%},{%- endif -%}
32+
{%- set _dummy = add_subnet_preceding_comma.update({'flag': True}) %}
33+
{
34+
"subnet": "{{ subnet_info["subnet"] }}",
35+
"pools": [
36+
{%- set add_pool_preceding_comma = { 'flag': False } %}
37+
{%- for pool in subnet_info["pools"] %}
38+
{%- if add_pool_preceding_comma.flag -%},{%- endif -%}
39+
{%- set _dummy = add_pool_preceding_comma.update({'flag': True}) %}
40+
{
41+
"pool": "{{ pool["range"] }}",
42+
"client-class": "{{ pool["client_class"] }}"
43+
}
44+
{%- endfor%}
45+
],
46+
"option-data": [
47+
{
48+
"name": "routers",
49+
"data": "{{ subnet_info["gateway"] if "gateway" in subnet_info else subnet_info["server_id"] }}"
50+
},
51+
{
52+
"name": "dhcp-server-identifier",
53+
"data": "{{ subnet_info["server_id"] }}"
54+
}
55+
],
56+
"valid-lifetime": {{ subnet_info["lease_time"] if "lease_time" in subnet_info else default_lease_time }},
57+
"reservations": []
58+
}
59+
{%- endfor %}
60+
],
61+
"loggers": [
62+
{
63+
"name": "kea-dhcp4",
64+
"output_options": [
65+
{
66+
"output": "/var/log/kea-dhcp.log",
67+
"pattern": "%-5p %m\n"
68+
}
69+
],
70+
"severity": "INFO",
71+
"debuglevel": 0
72+
}
73+
]{%- if client_classes -%},
74+
"client-classes": [
75+
{%- set add_preceding_comma = { 'flag': False } %}
76+
{%- for class in client_classes %}
77+
{%- if add_preceding_comma.flag -%},{%- endif -%}
78+
{%- set _dummy = add_preceding_comma.update({'flag': True}) %}
79+
{
80+
"name": "{{ class["name"] }}",
81+
"test": "{{ class["condition"] }}"
82+
}
83+
{%- endfor %}
84+
]
85+
{%- endif %}
86+
}
87+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
# This script would run once kea-dhcp4 lease change (defined in kea-dhcp4.conf),
3+
# it is to find running process dhcpservd.py, and send SIGUSR1 signal to this
4+
# process to inform it to update lease table in state_db (defined in dhcpservd.py)
5+
6+
pid=`ps aux | grep 'dhcpservd' | grep -nv 'grep' | awk '{print $2}'`
7+
if [ -z "$pid" ]; then
8+
logger -p daemon.error Cannot find running dhcpservd.py.
9+
else
10+
# Send SIGUSR1 signal to dhcpservd.py
11+
kill -s 10 ${pid}
12+
fi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{# Generate port name-alias map for isc-dhcp-relay to parse. Each line contains one #}
2+
{# name-alias pair of the form "<name> <alias>" #}
3+
{% for port, config in PORT.items() %}
4+
{{- port }} {% if "alias" in config %}{{ config["alias"] }}{% else %}{{ port }}{% endif %} {{- "\n" -}}
5+
{% endfor -%}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#
2+
# First some standard log files. Log by facility.
3+
#
4+
5+
# Log all facilities to /var/log/syslog except cron, auth
6+
# and authpriv. They are noisy - log them to their own files
7+
*.*;cron,auth,authpriv.none -/var/log/syslog
8+
auth,authpriv.* /var/log/auth.log
9+
cron.* /var/log/cron.log
10+
11+
#
12+
# Emergencies are sent to everybody logged in.
13+
#
14+
*.emerg :omusrmsg:*
15+
16+
# The named pipe /dev/xconsole is for the `xconsole' utility. To use it,
17+
# you must invoke `xconsole' with the `-file' option:
18+
#
19+
# $ xconsole -file /dev/xconsole [...]
20+
#
21+
# NOTE: adjust the list below, or you'll go crazy if you have a reasonably
22+
# busy site..
23+
#
24+
#daemon.*;mail.*;\
25+
# news.err;\
26+
# *.=debug;*.=info;\
27+
# *.=notice;*.=warn |/dev/xconsole
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
###############################################################################
2+
# Managed by Ansible
3+
# file: ansible/roles/acs/templates/rsyslog.conf.j2
4+
###############################################################################
5+
#
6+
# /etc/rsyslog.conf Configuration file for rsyslog.
7+
#
8+
# For more information see
9+
# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html
10+
11+
12+
#################
13+
#### MODULES ####
14+
#################
15+
16+
$ModLoad imuxsock # provides support for local system logging
17+
18+
{% set gconf = (SYSLOG_CONFIG | d({})).get('GLOBAL', {}) -%}
19+
{% set rate_limit_interval = gconf.get('rate_limit_interval') %}
20+
{% set rate_limit_burst = gconf.get('rate_limit_burst') %}
21+
22+
{% if rate_limit_interval is not none %}
23+
$SystemLogRateLimitInterval {{ rate_limit_interval }}
24+
{% endif %}
25+
{% if rate_limit_burst is not none %}
26+
$SystemLogRateLimitBurst {{ rate_limit_burst }}
27+
{% endif %}
28+
29+
$ModLoad imklog # provides kernel logging support
30+
#$ModLoad immark # provides --MARK-- message capability
31+
32+
# provides UDP syslog reception
33+
$ModLoad imudp
34+
$UDPServerAddress {{udp_server_ip}} #bind to localhost before udp server run
35+
$UDPServerRun 514
36+
37+
# provides TCP syslog reception
38+
#$ModLoad imtcp
39+
#$InputTCPServerRun 514
40+
41+
42+
###########################
43+
#### GLOBAL DIRECTIVES ####
44+
###########################
45+
{% set format = gconf.get('format', 'standard') -%}
46+
{% set fw_name = gconf.get('welf_firewall_name', hostname) -%}
47+
#
48+
# Use traditional timestamp format.
49+
# To enable high precision timestamps, comment out the following line.
50+
#
51+
#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
52+
53+
# Define a custom template
54+
$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% dhcp_server#%syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"
55+
$ActionFileDefaultTemplate SONiCFileFormat
56+
57+
template(name="WelfRemoteFormat" type="string" string="%TIMESTAMP% id=firewall time=\"%timereported\
58+
:::date-year%-%timereported:::date-month%-%timereported:::date-day% %timereported:::date-hour%:%timereported:::date-minute%:%timereported\
59+
:::date-second%\" fw=\"{{ fw_name }}\" pri=%syslogpriority% msg=\"%syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\"\n")
60+
61+
#
62+
# Set the default permissions for all log files.
63+
#
64+
$FileOwner root
65+
$FileGroup adm
66+
$FileCreateMode 0640
67+
$DirCreateMode 0755
68+
$Umask 0022
69+
70+
#
71+
# Where to place spool and state files
72+
#
73+
$WorkDirectory /var/spool/rsyslog
74+
75+
#
76+
# Include all config files in /etc/rsyslog.d/
77+
#
78+
$IncludeConfig /etc/rsyslog.d/*.conf
79+
80+
#
81+
# Suppress duplicate messages and report "message repeated n times"
82+
#
83+
$RepeatedMsgReduction on
84+
85+
###############
86+
#### RULES ####
87+
###############
88+
89+
#
90+
# Remote syslog logging
91+
#
92+
93+
# The omfwd plug-in provides the core functionality of traditional message
94+
# forwarding via UDP and plain TCP. It is a built-in module that does not need
95+
# to be loaded.
96+
# TODO rsyslog issue in bridge mode container, don't update to remote server for now

dockers/docker-dhcp-server/start.sh

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
3+
if [ "${RUNTIME_OWNER}" == "" ]; then
4+
RUNTIME_OWNER="kube"
5+
fi
6+
7+
# This script is to basicly check for if this starting-container can be allowed
8+
# to run based on current state, and owner & version of this starting container.
9+
# If allowed, update feature info in state_db and then processes in supervisord.conf
10+
# after this process can start up.
11+
CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py"
12+
if test -f ${CTR_SCRIPT}
13+
then
14+
${CTR_SCRIPT} -f dhcp_server -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION}
15+
fi
16+
17+
TZ=$(cat /etc/timezone)
18+
rm -rf /etc/localtime
19+
ln -sf /usr/share/zoneinfo/$TZ /etc/localtime

0 commit comments

Comments
 (0)