Skip to content

Commit cac2cf5

Browse files
authored
[storage_backend] Add backend acl service (#14229) (#14281)
1 parent 32ac9b0 commit cac2cf5

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

files/build_templates/sonic_debian_extension.j2

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,11 @@ sudo cp $IMAGE_CONFIGS/config-chassisdb/config-chassisdb $FILESYSTEM_ROOT/usr/bi
586586
echo "config-chassisdb.service" | sudo tee -a $GENERATED_SERVICE_FILE
587587
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-chassisdb.service
588588

589+
# Copy backend-acl script and service file
590+
sudo cp $IMAGE_CONFIGS/backend_acl/backend-acl.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/backend-acl.service
591+
sudo cp $IMAGE_CONFIGS/backend_acl/backend_acl.py $FILESYSTEM_ROOT/usr/bin/backend_acl.py
592+
echo "backend-acl.service" | sudo tee -a $GENERATED_SERVICE_FILE
593+
589594
# Copy SNMP configuration files
590595
sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/
591596

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[Unit]
2+
Description=Enable backend acl on storage backend ToRs
3+
After=swss.service
4+
BindsTo=sonic.target
5+
After=sonic.target
6+
7+
[Service]
8+
Type=oneshot
9+
ExecStart=/usr/bin/backend_acl.py
10+
11+
[Install]
12+
WantedBy=sonic.target
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python
2+
3+
import os
4+
import subprocess
5+
import syslog
6+
import time
7+
8+
from swsscommon.swsscommon import SonicV2Connector
9+
10+
SYSLOG_IDENTIFIER = os.path.basename(__file__)
11+
12+
SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
13+
14+
def log_info(msg):
15+
syslog.openlog(SYSLOG_IDENTIFIER)
16+
syslog.syslog(syslog.LOG_INFO, msg)
17+
syslog.closelog()
18+
19+
def run_command(cmd, return_cmd=False):
20+
log_info("executing cmd = {}".format(cmd))
21+
proc = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE)
22+
out, err = proc.communicate()
23+
if return_cmd:
24+
if err:
25+
return "Unknown"
26+
27+
if len(out) > 0:
28+
return out.strip().decode('utf-8')
29+
30+
def _get_device_type():
31+
"""
32+
Get device type
33+
"""
34+
device_type = run_command([SONIC_CFGGEN_PATH, '-m', '-v', 'DEVICE_METADATA.localhost.type'], return_cmd=True)
35+
return device_type
36+
37+
def _is_storage_device():
38+
"""
39+
Check if the device is a storage device or not
40+
"""
41+
storage_device = run_command([SONIC_CFGGEN_PATH, '-d', '-v', 'DEVICE_METADATA.localhost.storage_device'], return_cmd=True)
42+
return storage_device == "true"
43+
44+
def _is_acl_table_present():
45+
"""
46+
Check if acl table exists
47+
"""
48+
acl_table = run_command([SONIC_CFGGEN_PATH, '-d', '-v', 'ACL_TABLE.DATAACL'], return_cmd=True)
49+
return (acl_table != "Unknown" and bool(acl_table))
50+
51+
def _is_switch_table_present():
52+
state_db = SonicV2Connector(host='127.0.0.1')
53+
state_db.connect(state_db.STATE_DB, False)
54+
table_present = False
55+
wait_time = 0
56+
TIMEOUT = 120
57+
STEP = 10
58+
59+
while wait_time < TIMEOUT:
60+
if state_db.exists(state_db.STATE_DB, 'SWITCH_CAPABILITY|switch'):
61+
table_present = True
62+
break
63+
time.sleep(STEP)
64+
wait_time += STEP
65+
if not table_present:
66+
log_info("Switch table not present")
67+
return table_present
68+
69+
def load_backend_acl(device_type):
70+
"""
71+
Load acl on backend storage device
72+
"""
73+
BACKEND_ACL_TEMPLATE_FILE = os.path.join('/', "usr", "share", "sonic", "templates", "backend_acl.j2")
74+
BACKEND_ACL_FILE = os.path.join('/', "etc", "sonic", "backend_acl.json")
75+
76+
# this acl needs to be loaded only on a storage backend ToR. acl load will fail if the switch table isn't present
77+
if _is_storage_device() and _is_acl_table_present() and _is_switch_table_present():
78+
if os.path.isfile(BACKEND_ACL_TEMPLATE_FILE):
79+
run_command(['sudo', SONIC_CFGGEN_PATH, '-d', '-t', '{},{}'.format(BACKEND_ACL_TEMPLATE_FILE, BACKEND_ACL_FILE)])
80+
if os.path.isfile(BACKEND_ACL_FILE):
81+
run_command(['acl-loader', 'update', 'incremental', BACKEND_ACL_FILE])
82+
else:
83+
log_info("Skipping backend acl load - conditions not met")
84+
85+
def main():
86+
device_type = _get_device_type()
87+
if device_type != "BackEndToRRouter":
88+
log_info("Skipping backend acl load on unsupported device type: {}".format(device_type))
89+
return
90+
91+
load_backend_acl(device_type)
92+
93+
if __name__ == "__main__":
94+
main()

0 commit comments

Comments
 (0)