diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 88ea2a3995..ebdbea0071 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -609,6 +609,11 @@ sudo cp $IMAGE_CONFIGS/config-chassisdb/config-chassisdb $FILESYSTEM_ROOT/usr/bi echo "config-chassisdb.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-chassisdb.service +# Copy backend-acl script and service file +sudo cp $IMAGE_CONFIGS/backend_acl/backend-acl.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/backend-acl.service +sudo cp $IMAGE_CONFIGS/backend_acl/backend_acl.py $FILESYSTEM_ROOT/usr/bin/backend_acl.py +echo "backend-acl.service" | sudo tee -a $GENERATED_SERVICE_FILE + # Copy SNMP configuration files sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/ diff --git a/files/image_config/backend_acl/backend-acl.service b/files/image_config/backend_acl/backend-acl.service new file mode 100644 index 0000000000..0ad24231ee --- /dev/null +++ b/files/image_config/backend_acl/backend-acl.service @@ -0,0 +1,12 @@ +[Unit] +Description=Enable backend acl on storage backend ToRs +After=swss.service +BindsTo=sonic.target +After=sonic.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/backend_acl.py + +[Install] +WantedBy=sonic.target diff --git a/files/image_config/backend_acl/backend_acl.py b/files/image_config/backend_acl/backend_acl.py new file mode 100755 index 0000000000..bb22a60880 --- /dev/null +++ b/files/image_config/backend_acl/backend_acl.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python + +import os +import subprocess +import syslog +import time + +from swsscommon.swsscommon import SonicV2Connector + +SYSLOG_IDENTIFIER = os.path.basename(__file__) + +SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen' + +def log_info(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + +def run_command(cmd, return_cmd=False): + log_info("executing cmd = {}".format(cmd)) + proc = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE) + out, err = proc.communicate() + if return_cmd: + if err: + return "Unknown" + + if len(out) > 0: + return out.strip().decode('utf-8') + +def _get_device_type(): + """ + Get device type + """ + device_type = run_command([SONIC_CFGGEN_PATH, '-m', '-v', 'DEVICE_METADATA.localhost.type'], return_cmd=True) + return device_type + +def _is_storage_device(): + """ + Check if the device is a storage device or not + """ + storage_device = run_command([SONIC_CFGGEN_PATH, '-d', '-v', 'DEVICE_METADATA.localhost.storage_device'], return_cmd=True) + return storage_device == "true" + +def _is_acl_table_present(): + """ + Check if acl table exists + """ + acl_table = run_command([SONIC_CFGGEN_PATH, '-d', '-v', 'ACL_TABLE.DATAACL'], return_cmd=True) + return (acl_table != "Unknown" and bool(acl_table)) + +def _is_switch_table_present(): + state_db = SonicV2Connector(host='127.0.0.1') + state_db.connect(state_db.STATE_DB, False) + table_present = False + wait_time = 0 + TIMEOUT = 120 + STEP = 10 + + while wait_time < TIMEOUT: + if state_db.exists(state_db.STATE_DB, 'SWITCH_CAPABILITY|switch'): + table_present = True + break + time.sleep(STEP) + wait_time += STEP + if not table_present: + log_info("Switch table not present") + return table_present + +def load_backend_acl(device_type): + """ + Load acl on backend storage device + """ + BACKEND_ACL_TEMPLATE_FILE = os.path.join('/', "usr", "share", "sonic", "templates", "backend_acl.j2") + BACKEND_ACL_FILE = os.path.join('/', "etc", "sonic", "backend_acl.json") + + # this acl needs to be loaded only on a storage backend ToR. acl load will fail if the switch table isn't present + if _is_storage_device() and _is_acl_table_present() and _is_switch_table_present(): + if os.path.isfile(BACKEND_ACL_TEMPLATE_FILE): + run_command(['sudo', SONIC_CFGGEN_PATH, '-d', '-t', '{},{}'.format(BACKEND_ACL_TEMPLATE_FILE, BACKEND_ACL_FILE)]) + if os.path.isfile(BACKEND_ACL_FILE): + run_command(['acl-loader', 'update', 'incremental', BACKEND_ACL_FILE]) + else: + log_info("Skipping backend acl load - conditions not met") + +def main(): + device_type = _get_device_type() + if device_type != "BackEndToRRouter": + log_info("Skipping backend acl load on unsupported device type: {}".format(device_type)) + return + + load_backend_acl(device_type) + +if __name__ == "__main__": + main()