-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
docker_image_ctl.j2
811 lines (744 loc) · 34.6 KB
/
docker_image_ctl.j2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
#!/bin/bash
# single instance containers are still supported (even though it might not look like it)
# if no instance number is passed to this script, $DEV will simply be unset, resulting in docker
# 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}}'"}} "${DOCKERNAME}")"
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
return 0
else # if it's incorrectly linked remove it
ip netns delete $NET_NS
fi
fi
ln -s /proc/$PID/ns/net /var/run/netns/$NET_NS
}
{%- endif %}
function updateSyslogConf()
{
# On multiNPU platforms, change the syslog target ip to docker0 ip to allow logs from containers
# running on the namespace to reach the rsyslog service running on the host
# 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="$DOCKERNAME"
TMP_FILE="/tmp/rsyslog.$CONTAINER_NAME.conf"
{%- if docker_container_name == "database" %}
python -c "import jinja2, os; paths=['/usr/share/sonic/templates']; loader = jinja2.FileSystemLoader(paths); env = jinja2.Environment(loader=loader, trim_blocks=True); template_file='/usr/share/sonic/templates/rsyslog-container.conf.j2'; template = env.get_template(os.path.basename(template_file)); data=template.render({\"target_ip\":\"$TARGET_IP\",\"container_name\":\"$CONTAINER_NAME\"}); print(data)" > $TMP_FILE
{%- else %}
sonic-cfggen -t /usr/share/sonic/templates/rsyslog-container.conf.j2 -a "{\"target_ip\": \"$TARGET_IP\", \"container_name\": \"$CONTAINER_NAME\" }" > $TMP_FILE
{%- endif %}
docker cp $TMP_FILE ${DOCKERNAME}:/etc/rsyslog.conf
rm -rf $TMP_FILE
fi
}
function ebtables_config()
{
if [[ "$DEV" && $DATABASE_TYPE != "dpudb" ]]; then
# Install ebtables filter in namespaces on multi-asic.
ip netns exec $NET_NS ebtables-restore < /etc/ebtables.filter.cfg
else
if [[ ! ($NUM_ASIC -gt 1) ]]; then
# Install ebtables filter in host for single asic.
ebtables-restore < /etc/ebtables.filter.cfg
fi
fi
}
function getMountPoint()
{
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.abspath(mnts[0]['Source']))" 2>/dev/null
}
function getBootType()
{
# same code snippet in files/scripts/syncd.sh
case "$(cat /proc/cmdline)" in
*SONIC_BOOT_TYPE=warm*)
TYPE='warm'
;;
*SONIC_BOOT_TYPE=fastfast*)
TYPE='fastfast'
;;
*SONIC_BOOT_TYPE=fast*|*fast-reboot*)
TYPE='fast'
;;
*)
TYPE='cold'
esac
echo "${TYPE}"
}
function preStartAction()
{
{%- if docker_container_name == "database" %}
WARM_DIR=/host/warmboot
if [ "$DATABASE_TYPE" != "chassisdb" ]; then
if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast" || "$BOOT_TYPE" == "fast") && -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/
docker cp /tmp/dump.rdb database$DEV:/var/lib/redis_bmp/
fi
fi
{%- elif docker_container_name == "pde" %}
if [[ $(/bin/systemctl status swss | grep -c running) -gt 0 ]]; then
echo "Stopping SWSS before starting PDE"
systemctl stop swss
fi
if [[ $(/bin/systemctl status watchdog-control.service | grep -c running) -gt 0 ]]; then
echo "Stopping watchdog-control.service before starting PDE"
systemctl stop watchdog-control.service
fi
{%- elif docker_container_name == "snmp" %}
$SONIC_DB_CLI STATE_DB HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s)
{%- else %}
: # nothing
{%- endif %}
updateSyslogConf
}
{%- if docker_container_name == "database" %}
function setPlatformLagIdBoundaries()
{
docker exec -i ${DOCKERNAME} $SONIC_DB_CLI CHASSIS_APP_DB SET "SYSTEM_LAG_ID_START" "$lag_id_start"
docker exec -i ${DOCKERNAME} $SONIC_DB_CLI CHASSIS_APP_DB SET "SYSTEM_LAG_ID_END" "$lag_id_end"
docker exec -i ${DOCKERNAME} $SONIC_DB_CLI CHASSIS_APP_DB EVAL "
local start_id = tonumber(ARGV[1])
local end_id = tonumber(ARGV[2])
for id = start_id,end_id do
redis.call('rpush','SYSTEM_LAG_IDS_FREE_LIST', tostring(id))
end" 0 $lag_id_start $lag_id_end
}
function waitForAllInstanceDatabaseConfigJsonFilesReady()
{
if [ ! -z "$DEV" ]; then
cnt=0
SONIC_DB_GLOBAL_JSON="/var/run/redis/sonic-db/database_global.json"
if [ -f "$SONIC_DB_GLOBAL_JSON" ]; then
# Create a separate python script to get a list of location of all instance database_config.json file
redis_database_cfg_list=`/usr/bin/python -c "import sys; import os; import json; f=open(sys.argv[1]); \
global_db_dir = os.path.dirname(sys.argv[1]); data=json.load(f); \
print(\" \".join([os.path.normpath(global_db_dir+'/'+elem['include']) \
for elem in data['INCLUDES'] if 'namespace' in elem])); f.close()" $SONIC_DB_GLOBAL_JSON`
for file in $redis_database_cfg_list
do
while [ ! -f $file ]
do
sleep 1
cnt=$(( $cnt + 1))
if [ $cnt -ge 60 ]; then
echo "Error: $file not found"
break
fi
done
done
fi
# Delay a second to allow all instance database_config.json files to be completely generated and fully accessible.
# This delay is needed to make sure that the database_config.json files are correctly rendered from j2 template
# files ( renderning takes some time )
sleep 1
fi
}
{%- endif %}
function postStartAction()
{
{%- if docker_container_name == "database" %}
CHASSISDB_CONF="/usr/share/sonic/device/$PLATFORM/chassisdb.conf"
[ -f $CHASSISDB_CONF ] && source $CHASSISDB_CONF
if [[ "$DEV" && $DATABASE_TYPE != "dpudb" ]]; then
# Enable the forwarding on eth0 interface in namespace.
SYSCTL_NET_CONFIG="/etc/sysctl.d/sysctl-net.conf"
docker exec -i database$DEV sed -i -e "s/^net.ipv4.conf.eth0.forwarding=0/net.ipv4.conf.eth0.forwarding=1/;
s/^net.ipv6.conf.eth0.forwarding=0/net.ipv6.conf.eth0.forwarding=1/" $SYSCTL_NET_CONFIG
docker exec -i database$DEV sysctl --system -e
link_namespace $DEV
if [[ -n "$midplane_subnet" ]]; then
# Use /16 for loopback interface
ip netns exec "$NET_NS" ip addr add 127.0.0.1/16 dev lo
ip netns exec "$NET_NS" ip addr del 127.0.0.1/8 dev lo
slot_id=$(python3 -c 'import sonic_platform.platform; platform_chassis = sonic_platform.platform.Platform().get_chassis(); print(platform_chassis.get_my_slot())' 2>/dev/null)
supervisor_slot_id=$(python3 -c 'import sonic_platform.platform; platform_chassis = sonic_platform.platform.Platform().get_chassis(); print(platform_chassis.get_supervisor_slot())' 2>/dev/null)
# Create eth1 in database instance
if [[ "${slot_id}" == "${supervisor_slot_id}" ]]; then
ip link add name ns-eth1"$NET_NS" type veth peer name eth1@"$NET_NS"
ip link set dev eth1@"$NET_NS" master br1
ip link set dev eth1@"$NET_NS" up
# For chassis system where Linux bridge is used on supervisor for midplane communication
# assign alternate name as eth1-midplane for generic design
ip link property add dev br1 altname eth1-midplane
else
ip link add name ns-eth1"$NET_NS" link eth1-midplane type macvlan mode bridge
fi
# Create eth1 in database instance
ip link set dev ns-eth1"$NET_NS" netns "$NET_NS"
ip netns exec "$NET_NS" ip link set ns-eth1"$NET_NS" name eth1
# Configure IP address and enable eth1
slot_ip_address=`echo $midplane_subnet | awk -F. '{print $1 "." $2}'`.$slot_id.$(($DEV + 10))
slot_subnet_mask=${midplane_subnet#*/}
ip netns exec "$NET_NS" ip addr add $slot_ip_address/$slot_subnet_mask dev eth1
ip netns exec "$NET_NS" ip link set dev eth1 up
# Allow localnet routing on the new interfaces if midplane is using a
# subnet in the 127/8 range.
if [[ "${midplane_subnet#127}" != "$midplane_subnet" ]]; then
ip netns exec "$NET_NS" bash -c "echo 1 > /proc/sys/net/ipv4/conf/eth1/route_localnet"
fi
fi
fi
# Setup ebtables configuration
{%- if sonic_asic_platform != "vs" %}
ebtables_config
{%- endif %}
# 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
# sonic-db-cli try to initialize the global database. If in multiasic platform, inital global
# database will try to access to all other instance database-config.json. If other instance
# database-config.json files are not ready yet, it will generate the sonic-db-cli core files.
waitForAllInstanceDatabaseConfigJsonFilesReady
until [[ ($(docker exec -i database$DEV pgrep -x -c supervisord) -gt 0) && ($($SONIC_DB_CLI PING | grep -c PONG) -gt 0) &&
($(docker exec -i database$DEV sonic-db-cli PING | grep -c PONG) -gt 0) ]]; do
sleep 1;
done
if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast" || "$BOOT_TYPE" == "fast") && -f $WARM_DIR/dump.rdb ]]; then
# retain the dump file from last boot for debugging purposes
mv $WARM_DIR/dump.rdb $WARM_DIR/dump.rdb.old
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
if [[ "$BOOT_TYPE" == "fast" ]]; then
# Flush ASIC DB. On fast-boot there should be nothing in there.
# In the older versions there has been an issue where a queued FDB event might get into ASIC_DB causing syncd crash at boot.
$SONIC_DB_CLI ASIC_DB FLUSHDB
# this is the case when base OS version does not support fast-reboot with reconciliation logic (dump.rdb is absent)
# In this case, we need to set the flag to indicate fast-reboot is in progress. Set the key to expire in 3 minutes
$SONIC_DB_CLI STATE_DB SET "FAST_REBOOT|system" "1" "EX" "180"
fi
fi
if [ -e /tmp/pending_config_migration ] || [ -e /tmp/pending_config_initialization ]; then
# this is first boot to a new image, config-setup execution is pending.
# for warmboot case, DB is loaded but migration is still pending
# For firstbboot/fast/cold reboot case, DB contains nothing at this point
# unset CONFIG_DB_INITIALIZED to indicate pending config load and migration
# This flag will be set to "1" after DB migration/initialization is completed as part of config-setup
$SONIC_DB_CLI CONFIG_DB SET "CONFIG_DB_INITIALIZED" "0"
else
$SONIC_DB_CLI CONFIG_DB SET "CONFIG_DB_INITIALIZED" "0"
# this is not a first time boot to a new image. Datbase container starts w/ old pre-existing config
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
fi
fi
# set CONFIG_DB_INITIALIZED to indicate end of config load and migration
$SONIC_DB_CLI CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1"
fi
# In SUP, enforce CHASSIS_APP_DB.tsa_enabled to be in sync with BGP_DEVICE_GLOBAL.STATE.tsa_enabled
if [[ -z "$DEV" ]] && [[ -f /etc/sonic/chassisdb.conf ]]; then
tsa_cfg="$($SONIC_DB_CLI CONFIG_DB HGET "BGP_DEVICE_GLOBAL|STATE" "tsa_enabled")"
if [[ -n "$tsa_cfg" ]]; then
docker exec -i ${DOCKERNAME} $SONIC_DB_CLI CHASSIS_APP_DB HMSET "BGP_DEVICE_GLOBAL|STATE" tsa_enabled ${tsa_cfg}
OP_CODE=$?
if [ $OP_CODE -ne 0 ]; then
echo "Err: Cmd failed (exit code $OP_CODE). CHASSIS_APP_DB and CONFIG_DB may be incosistent wrt tsa_enabled"
fi
fi
fi
# Add redis UDS to the redis group and give read/write access to the group
REDIS_BMP_SOCK="/var/run/redis/redis_bmp.sock"
chgrp -f redis $REDIS_BMP_SOCK && chmod -f 0760 $REDIS_BMP_SOCK
REDIS_SOCK="/var/run/redis${DEV}/redis.sock"
else
until [[ ($(docker exec -i ${DOCKERNAME} pgrep -x -c supervisord) -gt 0) &&
($(docker exec -i ${DOCKERNAME} $SONIC_DB_CLI CHASSIS_APP_DB PING | grep -c True) -gt 0) ]]; do
sleep 1
done
if [[ -n "$lag_id_start" && -n "$lag_id_end" ]]; then
setPlatformLagIdBoundaries
fi
REDIS_SOCK="/var/run/redis-chassis/redis_chassis.sock"
fi
chgrp -f redis $REDIS_SOCK && chmod -f 0760 $REDIS_SOCK
{%- elif docker_container_name == "swss" %}
# Wait until swss container state is Running
until [[ ($(docker inspect -f {{"'{{.State.Running}}'"}} swss$DEV) == "true") ]]; do
sleep 0.1
done
echo "swss container is up and running"
docker exec swss$DEV rm -f /ready # remove cruft
if [[ "$BOOT_TYPE" == "fast" ]] && [[ -d /host/fast-reboot ]]; then
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:/
test -e /host/fast-reboot/media_config.json && docker cp /host/fast-reboot/media_config.json swss$DEV:/
rm -fr /host/fast-reboot
fi
docker exec swss$DEV touch /ready # signal swssconfig.sh to go
# Re-confirm that file is indeed created and log an error if not
docker exec swss$DEV test -f /ready && echo "File swss:/ready created" || echo "Error: File swss:/ready doesn't exist"
{%- 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
{%- elif docker_container_name == "eventd" %}
export EVENTD_STATE=$(sonic-db-cli -s CONFIG_DB HGET 'FEATURE|eventd' 'state')
j2 -f json --import-env=ENVIRONMENT /usr/share/sonic/templates/rsyslog_plugin/rsyslog_plugin.conf.j2 /usr/share/sonic/templates/rsyslog_plugin/events_info.json > /etc/rsyslog.d/host_events.conf
j2 -f json --import-env=ENVIRONMENT /usr/share/sonic/templates/rsyslog_plugin/rsyslog_plugin.conf.j2 /usr/share/sonic/templates/rsyslog_plugin/syncd_events_info.json > /etc/rsyslog.d/syncd_events.conf
systemctl restart rsyslog
{%- else %}
: # nothing
{%- endif %}
}
start() {
# Obtain boot type from kernel arguments
BOOT_TYPE=`getBootType`
# 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
source $ASIC_CONF
fi
# Default rsyslog target IP for single ASIC platform
{%- if docker_container_name == "dhcp_server" %}
SYSLOG_TARGET_IP=$(docker network inspect bridge --format={{ "'{{(index .IPAM.Config 0).Gateway}}'" }})
{%- else %}
SYSLOG_TARGET_IP=127.0.0.1
{%- endif %}
if [[ ($NUM_ASIC -gt 1) ]]; then
SYSLOG_TARGET_IP=$(docker network inspect bridge --format={{ "'{{(index .IPAM.Config 0).Gateway}}'" }})
fi
PLATFORM_ENV_CONF=/usr/share/sonic/device/$PLATFORM/platform_env.conf
if [ -f "$PLATFORM_ENV_CONF" ]; then
source $PLATFORM_ENV_CONF
fi
# Parse the platform.json file to get the platform specific information
PLATFORM_JSON=/usr/share/sonic/device/$PLATFORM/platform.json
if [ -f "$PLATFORM_JSON" ]; then
NUM_DPU=$(jq -r '.DPUS | length' $PLATFORM_JSON 2>/dev/null)
jq -e '.DPU' $PLATFORM_JSON >/dev/null
if [[ $? -eq 0 ]]; then
IS_DPU_DEVICE="true"
else
IS_DPU_DEVICE="false"
fi
fi
{%- if sonic_asic_platform == "broadcom" %}
{%- if docker_container_name == "syncd" %}
# Set the SYNCD_SHM_SIZE if this variable not defined
BRCM_PLATFORM_COMMON_DIR=/usr/share/sonic/device/x86_64-broadcom_common
SYNCD_SHM_INI=$BRCM_PLATFORM_COMMON_DIR/syncd_shm.ini
readline=$(grep '0x14e4' /proc/linux-kernel-bde)
bcm_chip_id=${readline#*0x14e4:0x}
bcm_chip_id=${bcm_chip_id::3}
if [ -z "$SYNCD_SHM_SIZE" ]; then
if [ -z "$bcm_chip_id" ]; then
echo "Cannot get Broadcom Chip Id. Skip set SYNCD_SHM_SIZE."
elif [ -f "$SYNCD_SHM_INI" ] && [ "$(grep -m1 "^${bcm_chip_id}=" $SYNCD_SHM_INI)" ]; then
SYNCD_SHM_SIZE=`grep -m1 "^${bcm_chip_id}=" $SYNCD_SHM_INI | awk -F= '{print $2}'`
else
echo "Cannot get SYNCD_SHM_SIZE for chip: [${bcm_chip_id}] in $SYNCD_SHM_INI. Skip set SYNCD_SHM_SIZE."
fi
fi
{%- endif %}
{%- endif %}
{%- if docker_container_name == "gbsyncd" %}
GBSYNCD_CONF=/usr/share/sonic/device/$PLATFORM/gbsyncd.ini
GBSYNCD_PLATFORM=gbsyncd-vs
if [ -f "$GBSYNCD_CONF" ]; then
while IFS="=" read -r key value; do
case "$key" in
platform)
GBSYNCD_PLATFORM="$value"
;;
esac
done < "$GBSYNCD_CONF"
fi
{%- endif %}
{%- if docker_container_name == "database" %}
# Don't mount HWSKU in {{docker_container_name}} container.
HWSKU=""
MOUNTPATH=""
{%- else %}
# Obtain our HWSKU as we will mount directories with these names in each docker
HWSKU=${HWSKU:-`$SONIC_CFGGEN -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`}
MOUNTPATH="/usr/share/sonic/device/$PLATFORM/$HWSKU"
if [ "$DEV" ]; then
MOUNTPATH="$MOUNTPATH/$DEV"
fi
{%- endif %}
{%- if docker_container_name == "swss" %}
# Insert "create_only_config_db_buffers" attribute
HWSKU_FOLDER="/usr/share/sonic/device/$PLATFORM/$HWSKU"
if [ -d "$HWSKU_FOLDER" ]; then
CREATE_ONLY_CONFIG_DB_BUFFERS_JSON="$HWSKU_FOLDER/create_only_config_db_buffers.json"
if [ -f "$CREATE_ONLY_CONFIG_DB_BUFFERS_JSON" ]; then
$SONIC_DB_CLI CONFIG_DB HSET 'DEVICE_METADATA|localhost' create_only_config_db_buffers true
fi
fi
{%- endif %}
DOCKERCHECK=`docker inspect --type container ${DOCKERNAME} 2>/dev/null`
if [ "$?" -eq "0" ]; then
{%- if docker_container_name == "database" and sonic_asic_platform == "vs" %}
echo "Removing existing ${DOCKERNAME} container"
docker rm -f ${DOCKERNAME}
{%- else %}
{%- if docker_container_name == "database" %}
DOCKERMOUNT=""
{%- else %}
DOCKERMOUNT=`getMountPoint "$DOCKERCHECK"`
{%- endif %}
if [ x"$DOCKERMOUNT" == x"$MOUNTPATH" ]; then
CONTAINER_EXISTS="yes"
preStartAction
{%- if docker_container_name == "database" %}
echo "Starting existing ${DOCKERNAME} container"
docker start ${DOCKERNAME}
{%- else %}
echo "Starting existing ${DOCKERNAME} container with HWSKU $HWSKU"
/usr/local/bin/container start ${DOCKERNAME}
{%- endif %}
postStartAction
exit $?
fi
# docker created with a different HWSKU, remove and recreate
echo "Removing obsolete ${DOCKERNAME} container with HWSKU $DOCKERMOUNT"
docker rm -f ${DOCKERNAME}
{%- endif %}
fi
{%- if docker_container_name == "database" %}
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
{%- else %}
echo "Creating new ${DOCKERNAME} container with HWSKU $HWSKU"
{%- endif %}
{%- if docker_container_name == "swss" %}
# Generate the asic_table.json and peripheral_table.json
if [ ! -f /etc/sonic/asic_table.json ] && [ -f /usr/share/sonic/templates/asic_table.j2 ]; then
sonic-cfggen -d -t /usr/share/sonic/templates/asic_table.j2 > /etc/sonic/asic_table.json 2> errorlog.txt
if [[ $? -ne 0 ]] ; then
echo "sonic-cfggen failed to render asic_table.json"
echo "$(cat errorlog.txt)"
sonic-cfggen -a '{"DEVICE_METADATA":{"localhost":{"platform":"'$PLATFORM'"}}}' -t /usr/share/sonic/templates/asic_table.j2 > /etc/sonic/asic_table.json
fi
fi
if [ ! -f /etc/sonic/peripheral_table.json ] && [ -f /usr/share/sonic/device/$PLATFORM/port_peripheral_config.j2 ]; then
sonic-cfggen -d -t /usr/share/sonic/device/$PLATFORM/port_peripheral_config.j2 > /etc/sonic/peripheral_table.json 2> errorlog.txt
if [[ $? -ne 0 ]] ; then
echo "sonic-cfggen failed to render peripheral_table.json"
echo "$(cat errorlog.txt)"
sonic-cfggen -a '{"DEVICE_METADATA":{"localhost":{"platform":"'$PLATFORM'"}}}' -t /usr/share/sonic/device/$PLATFORM/port_peripheral_config.j2 > /etc/sonic/peripheral_table.json
fi
fi
if [ ! -f /etc/sonic/zero_profiles.json ] && [ -f /usr/share/sonic/templates/zero_profiles.j2 ]; then
sonic-cfggen -d -t /usr/share/sonic/device/$PLATFORM/zero_profiles.j2 > /etc/sonic/zero_profiles.json 2> errorlog.txt
if [[ $? -ne 0 ]] ; then
echo "sonic-cfggen failed to render zero_profiles.json"
echo "$(cat errorlog.txt)"
sonic-cfggen -t /usr/share/sonic/device/$PLATFORM/zero_profiles.j2 > /etc/sonic/zero_profiles.json
fi
fi
{%- if enable_asan == "y" %}
mkdir -p /var/log/asan
{%- endif %}
{%- endif %}
# In Multi ASIC platforms the global database config file database_global.json will exist.
# Parse the file and get the include path for the database_config.json files used in
# various namesapces. The database_config paths are relative to the DIR of SONIC_DB_GLOBAL_JSON.
SONIC_DB_GLOBAL_JSON="/var/run/redis/sonic-db/database_global.json"
if [ -f "$SONIC_DB_GLOBAL_JSON" ]; then
# TODO Create a separate python script with the below logic and invoke it here.
redis_dir_list=`/usr/bin/python -c "import sys; import os; import json; f=open(sys.argv[1]); \
global_db_dir = os.path.dirname(sys.argv[1]); data=json.load(f); \
print(\" \".join([os.path.normpath(global_db_dir+'/'+elem['include']).partition('sonic-db')[0]\
for elem in data['INCLUDES'] if 'namespace' in elem or 'container_name' in elem ])); f.close()" $SONIC_DB_GLOBAL_JSON`
fi
{%- if docker_container_name == "database" %}
start_chassis_db=0
chassis_db_address=""
chassisdb_config="/usr/share/sonic/device/$PLATFORM/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" || $DATABASE_TYPE == "dpudb" ]]; then
NET="host"
# For Multi-ASIC platform we have to mount the redis paths for database instances running in different
# namespaces, into the single instance dockers like snmp, pmon on linux host. These global dockers
# will need to get/set tables from databases in different namespaces.
# /var/run/redis0 ---> mounted as --> /var/run/redis0
# /var/run/redis1 ---> mounted as --> /var/run/redis1 .. etc
# The below logic extracts the base DIR's where database_config.json's for various namespaces exist.
# redis_dir_list is a string of form "/var/run/redis0/ /var/run/redis1/ /var/run/redis2/"
{%- if docker_container_name != "database" %}
if [ -n "$redis_dir_list" ]; then
for redis_dir in $redis_dir_list
do
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 "
DB_OPT=$DB_OPT" --env DATABASE_TYPE=$DATABASE_TYPE "
DB_OPT=$DB_OPT" --env NUM_DPU=$NUM_DPU "
DB_OPT=$DB_OPT" --env IS_DPU_DEVICE=$IS_DPU_DEVICE "
if [[ "$DEV" ]]; then
DB_OPT=$DB_OPT" -v /var/run/redis$DEV:/var/run/redis$DEV:rw "
fi
fi
{%- endif %}
else
# This part of code is applicable for Multi-ASIC platforms. Here we mount the namespace specific
# redis directory into the docker running in that namespace. Below eg: is for namespace "asic1"
# /var/run/redis1 ---> mounted as --> /var/run/redis1
# redis_dir_list is a string of form "/var/run/redis0/ /var/run/redis1/ /var/run/redis2/"
if [ -n "$redis_dir_list" ]; then
id=`expr $DEV + 1`
redis_dir=`echo $redis_dir_list | cut -d " " -f $id`
REDIS_MNT=" -v $redis_dir:$redis_dir:rw "
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" %}
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 %}
NAMESPACE_ID="$DEV"
if [[ $DATABASE_TYPE == "dpudb" ]]; then
NAMESPACE_ID=""
fi
{%- if sonic_asic_platform == "mellanox" %}
# TODO: Mellanox will remove the --tmpfs exception after SDK socket path changed in new SDK version
{%- endif %}
docker create {{docker_image_run_opt}} \
{%- if docker_container_name != "dhcp_server" %}
--net=$NET \
{%- endif %}
-e RUNTIME_OWNER=local \
--uts=host \{# W/A: this should be set per-docker, for those dockers which really need host's UTS namespace #}
{%- if install_debug_image == "y" %}
-v /src:/src:ro -v /debug:/debug:rw \
{%- endif %}
{%- if '--log-driver=json-file' in docker_image_run_opt or '--log-driver' not in docker_image_run_opt %}
--log-opt max-size=2M --log-opt max-file=5 \
{%- endif %}
{%- if sonic_asic_platform == "mellanox" %}
{%- if docker_container_name == "syncd" %}
-v /var/log/mellanox:/var/log/mellanox:rw \
-v /var/log/sdk_dbg:/var/log/sdk_dbg:rw \
-v mlnx_sdk_socket:/var/run/sx_sdk \
-v /tmp/nv-syncd-shared/:/tmp \
-v /dev/shm:/dev/shm:rw \
-v /var/log/sai_failure_dump:/var/log/sai_failure_dump:rw \
-e SX_API_SOCKET_FILE=/var/run/sx_sdk/sx_api.sock \
{%- elif docker_container_name == "pmon" %}
-v /var/run/hw-management:/var/run/hw-management:rw \
-v mlnx_sdk_socket:/var/run/sx_sdk \
-v /tmp/nv-syncd-shared/:/tmp \
-v /dev/shm:/dev/shm:rw \
-e SX_API_SOCKET_FILE=/var/run/sx_sdk/sx_api.sock \
-v /dev/shm:/dev/shm:rw \
{%- else %}
{%- if mount_default_tmpfs|default("n") == "y" %}
--tmpfs /tmp \
{%- endif %}
{%- endif %}
{%- endif %}
{%- if sonic_asic_platform == "broadcom" %}
{%- if docker_container_name == "syncd" %}
--shm-size=${SYNCD_SHM_SIZE:-64m} \
-v /var/run/docker-syncd$DEV:/var/run/sswsyncd \
{%- endif %}
{%- endif %}
{%- if docker_container_name == "pmon" %}
-v /usr/share/sonic/firmware:/usr/share/sonic/firmware:rw \
{%- endif %}
{%- if docker_container_name == "swss" %}
-e ASIC_VENDOR={{ sonic_asic_platform }} \
{%- endif -%}
{%- if docker_container_name in ["swss", "syncd"] and enable_asan == "y" %}
-v /var/log/asan/:/var/log/asan \
{%- endif -%}
{%- 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 \
-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 /etc/fips/fips_enable:/etc/fips/fips_enable:ro \
-v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \
-v /usr/share/sonic/templates/rsyslog-container.conf.j2:/usr/share/sonic/templates/rsyslog-container.conf.j2:ro \
{%- if sonic_asic_platform != "mellanox" %}
{%- if mount_default_tmpfs|default("n") == "y" %}
--tmpfs /tmp \
{%- endif %}
{%- endif %}
{%- if mount_default_tmpfs|default("n") == "y" %}
--tmpfs /var/tmp \
{%- endif %}
--env "NAMESPACE_ID"="$NAMESPACE_ID" \
--env "NAMESPACE_PREFIX"="$NAMESPACE_PREFIX" \
--env "NAMESPACE_COUNT"="$NUM_ASIC" \
--env "DEV"="$DEV" \
--env "CONTAINER_NAME"=$DOCKERNAME \
--env "SYSLOG_TARGET_IP"=$SYSLOG_TARGET_IP \
--env "PLATFORM"=$PLATFORM \
--name=$DOCKERNAME \
{%- if docker_container_name == "gbsyncd" %}
-v /var/run/docker-syncd$DEV:/var/run/sswsyncd \
"docker-$GBSYNCD_PLATFORM":latest \
{%- elif docker_image_name is defined %}
{{docker_image_name}}:latest \
{%- else %}
{{docker_image_id}} \
{%- endif %}
|| {
echo "Failed to docker run" >&1
exit 4
}
preStartAction
{%- if docker_container_name == "database" %}
docker start $DOCKERNAME
{%- else %}
/usr/local/bin/container start ${DOCKERNAME}
{%- endif %}
postStartAction
}
wait() {
{%- if docker_container_name == "database" %}
docker wait $DOCKERNAME
{%- else %}
/usr/local/bin/container wait $DOCKERNAME
{%- endif %}
}
stop() {
{%- if docker_container_name == "database" %}
docker stop $DOCKERNAME
if [[ "$DEV" && $DATABASE_TYPE != "dpudb" ]]; then
ip netns delete "$NET_NS"
fi
{%- else %}
container_id=$(docker ps --filter "name=$DOCKERNAME" --quiet)
if [ -z "$container_id" ]; then
echo "container stop $DOCKERNAME - No such container: $DOCKERNAME"
else
{%- if docker_container_name == "teamd" %}
# Longer timeout of 60 sec to wait for Portchannels to be cleaned.
/usr/local/bin/container stop -t 60 $DOCKERNAME
{%- elif docker_container_name in ["swss", "syncd"] and enable_asan == "y" %}
/usr/local/bin/container stop -t 60 $DOCKERNAME
{%- else %}
/usr/local/bin/container stop $DOCKERNAME
{%- endif %}
fi
{%- endif %}
}
kill() {
{%- if docker_container_name == "database" %}
docker kill $DOCKERNAME
if [[ "$DEV" && $DATABASE_TYPE != "dpudb" ]]; then
ip netns delete "$NET_NS"
fi
{%- else %}
/usr/local/bin/container kill $DOCKERNAME
{%- 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
if [[ "$DEV" == *"dpu"* ]]; then
DATABASE_TYPE="dpudb"
fi
{%- endif %}
NAMESPACE_PREFIX="asic"
DOCKERNAME=$DOCKERNAME$DEV
CONTAINER_EXISTS="no"
if [[ "$DEV" && $DATABASE_TYPE != "dpudb" ]]; then
NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace
SONIC_CFGGEN="sonic-cfggen -n $NET_NS"
SONIC_DB_CLI="sonic-db-cli -n $NET_NS"
else
NET_NS=""
SONIC_CFGGEN="sonic-cfggen"
SONIC_DB_CLI="sonic-db-cli"
fi
# read SONiC immutable variables
[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment
case "$1" in
start|wait|stop|kill)
$1
;;
*)
echo "Usage: $0 {start namespace(optional)|wait namespace(optional)|stop namespace(optional)}"
exit 1
;;
esac