Skip to content

Commit 0aacc45

Browse files
neethajohnmssonicbld
authored andcommitted
[storage_backend] Add backend acl service (#14229)
Why I did it This PR addresses the issue mentioned above by loading the acl config as a service on a storage backend device How I did it The new acl service is a oneshot service which will start after swss and does some retries to ensure that the SWITCH_CAPABILITY info is present before attempting to load the acl rules. The service is also bound to sonic targets which ensures that it gets restarted during minigraph reload and config reload How to verify it Build an image with the following changes and did the following tests Verified that acl is loaded successfully on a storage backend device after a switch boot up Verified that acl is loaded successfully on a storage backend ToR after minigraph load and config reload Verified that acl is not loaded if the device is not a storage backend ToR or the device does not have a DATAACL table Signed-off-by: Neetha John <[email protected]>
1 parent 5c55eb8 commit 0aacc45

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

files/build_templates/sonic_debian_extension.j2

+5
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,11 @@ sudo cp $IMAGE_CONFIGS/config-chassisdb/config-chassisdb $FILESYSTEM_ROOT/usr/bi
600600
echo "config-chassisdb.service" | sudo tee -a $GENERATED_SERVICE_FILE
601601
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-chassisdb.service
602602

603+
# Copy backend-acl script and service file
604+
sudo cp $IMAGE_CONFIGS/backend_acl/backend-acl.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/backend-acl.service
605+
sudo cp $IMAGE_CONFIGS/backend_acl/backend_acl.py $FILESYSTEM_ROOT/usr/bin/backend_acl.py
606+
echo "backend-acl.service" | sudo tee -a $GENERATED_SERVICE_FILE
607+
603608
# Copy SNMP configuration files
604609
sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/
605610

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
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)