diff --git a/scripts/featured b/scripts/featured index d66e8b10..e50df9a9 100644 --- a/scripts/featured +++ b/scripts/featured @@ -26,13 +26,31 @@ PORT_INIT_TIMEOUT_SEC = 180 def run_cmd(cmd, log_err=True, raise_exception=False): try: - subprocess.check_call(cmd) + return 0, subprocess.check_output(cmd, universal_newlines=True) except Exception as err: if log_err: syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}" .format(err.cmd, err.returncode, err.output)) if raise_exception: raise + return err.returncode, str("Encouter error: {}".format(err.output)) + + +def restart_service(service_name): + """ + Restart service by name + Args: + service_name: Name of service to be restarted + """ + state, output = run_cmd(["systemctl", "is-enabled", service_name], return_res=True) + if state == 0 and output.strip() == "enabled": + syslog.syslog(syslog.LOG_INFO, "Restarting {}".format(service_name)) + run_cmd(["sudo", "systemctl", "stop", service_name]) + run_cmd(["sudo", "systemctl", "reset-failed", service_name]) + run_cmd(["sudo", "systemctl", "start", service_name], raise_exception=True) + syslog.syslog(syslog.LOG_INFO, "{} restarted successfully".format(service_name)) + else: + syslog.syslog(syslog.LOG_ERR, "Cannot restart {} because it's not enabled".format(service_name)) def signal_handler(sig, frame): @@ -414,7 +432,9 @@ class FeatureHandler(object): .format(feature.name, feature_suffixes[-1])) self.set_feature_state(feature, self.FEATURE_STATE_FAILED) return - + if feature_name == "dhcp_server": + # For dhcp_server feature change, we need to restart dhcp_relay container too + restart_service("dhcp_relay") self.set_feature_state(feature, self.FEATURE_STATE_ENABLED) def disable_feature(self, feature): @@ -438,6 +458,9 @@ class FeatureHandler(object): .format(feature.name, feature_suffixes[-1])) self.set_feature_state(feature, self.FEATURE_STATE_FAILED) return + if feature.name == "dhcp_server": + # For dhcp_server feature change, we need to restart dhcp_relay container too + restart_service("dhcp_relay") self.set_feature_state(feature, self.FEATURE_STATE_DISABLED) diff --git a/tests/featured/test_vectors.py b/tests/featured/test_vectors.py index bc0d0cac..9439735f 100644 --- a/tests/featured/test_vectors.py +++ b/tests/featured/test_vectors.py @@ -402,6 +402,196 @@ }, }, ], + [ + "SingleToRCase_DHCP_Server_Enabled", + { + "device_runtime_metadata": { + "DEVICE_RUNTIME_METADATA": { + "ETHERNET_PORTS_PRESENT": True + } + }, + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "type": "ToR", + } + }, + "FEATURE": { + "dhcp_server": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "local", + "state": "enabled" + }, + "dhcp_relay": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "kube", + "state": "enabled" + }, + "mux": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "local", + "state": "{% if 'subtype' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['subtype'] == 'DualToR' %}enabled{% else %}always_disabled{% endif %}" + }, + "telemetry": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "True", + "high_mem_alert": "disabled", + "set_owner": "kube", + "state": "enabled", + "status": "enabled" + }, + }, + }, + "expected_config_db": { + "FEATURE": { + "dhcp_server": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "local", + "state": "enabled" + }, + "dhcp_relay": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "kube", + "state": "enabled" + }, + "mux": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "local", + "state": "always_disabled" + }, + "telemetry": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "True", + "high_mem_alert": "disabled", + "set_owner": "kube", + "state": "enabled", + "status": "enabled" + }, + }, + }, + "enable_feature_subprocess_calls": [ + call(["sudo", "systemctl", "unmask", "dhcp_relay.service"]), + call(["sudo", "systemctl", "enable", "dhcp_relay.service"]), + call(["sudo", "systemctl", "start", "dhcp_relay.service"]), + call(["sudo", "systemctl", "stop", "mux.service"]), + call(["sudo", "systemctl", "disable", "mux.service"]), + call(["sudo", "systemctl", "mask", "mux.service"]), + call(["sudo", "systemctl", "unmask", "telemetry.service"]), + call(["sudo", "systemctl", "enable", "telemetry.service"]), + call(["sudo", "systemctl", "start", "telemetry.service"]), + ], + "daemon_reload_subprocess_call": [ + call(["sudo", "systemctl", "daemon-reload"]), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error') + }, + }, + ], + [ + "SingleToRCase_DHCP_Server_Disabled", + { + "device_runtime_metadata": { + "DEVICE_RUNTIME_METADATA": { + "ETHERNET_PORTS_PRESENT": True + } + }, + "config_db": { + "DEVICE_METADATA": { + "localhost": { + "type": "ToR", + } + }, + "FEATURE": { + "dhcp_server": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "local", + "state": "disabled" + }, + "dhcp_relay": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "kube", + "state": "enabled" + } + }, + }, + "expected_config_db": { + "FEATURE": { + "dhcp_server": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "local", + "state": "disabled" + }, + "dhcp_relay": { + "auto_restart": "enabled", + "has_global_scope": "True", + "has_per_asic_scope": "False", + "delayed": "False", + "high_mem_alert": "disabled", + "set_owner": "kube", + "state": "enabled" + } + }, + }, + "enable_feature_subprocess_calls": [ + call(["sudo", "systemctl", "unmask", "dhcp_relay.service"]), + call(["sudo", "systemctl", "enable", "dhcp_relay.service"]), + call(["sudo", "systemctl", "start", "dhcp_relay.service"]), + call(["sudo", "systemctl", "stop", "mux.service"]), + call(["sudo", "systemctl", "disable", "mux.service"]), + call(["sudo", "systemctl", "mask", "mux.service"]), + call(["sudo", "systemctl", "unmask", "telemetry.service"]), + call(["sudo", "systemctl", "enable", "telemetry.service"]), + call(["sudo", "systemctl", "start", "telemetry.service"]), + ], + "daemon_reload_subprocess_call": [ + call(["sudo", "systemctl", "daemon-reload"]), + ], + "popen_attributes": { + 'communicate.return_value': ('output', 'error') + }, + }, + ], [ "DualTorCaseWithNoSystemCalls", {