diff --git a/src/core/src/core_logic/ServiceManager.py b/src/core/src/core_logic/ServiceManager.py index 9c8dde78..f69344cf 100644 --- a/src/core/src/core_logic/ServiceManager.py +++ b/src/core/src/core_logic/ServiceManager.py @@ -89,17 +89,18 @@ def is_service_enabled(self): # endregion # region - Service Unit Management - def create_service_unit_file(self, exec_start, desc, after="network.target", service_type="forking", wanted_by="multi-user.target"): + def create_service_unit_file(self, exec_start, desc, after="network.target", service_type="forking", timeout_start_sec="10min", wanted_by="multi-user.target"): """ Note: Service type defaults to forking because of sh to py process fork """ service_unit_content_template = "\n[Unit]" + \ "\nDescription={0}" + \ "\nAfter={1}\n" + \ "\n[Service]" + \ "\nType={2}" + \ - "\nExecStart={3}\n" + \ + "\nExecStart={3}" + \ + "\nTimeoutStartSec={4}\n" + \ "\n[Install]" + \ - "\nWantedBy={4}" - service_unit_content = service_unit_content_template.format(desc, after, service_type, exec_start, wanted_by) + "\nWantedBy={5}" + service_unit_content = service_unit_content_template.format(desc, after, service_type, exec_start, timeout_start_sec, wanted_by) service_unit_path = self.__systemd_service_unit_path.format(self.service_name) self.env_layer.file_system.write_with_retry(service_unit_path, service_unit_content) self.env_layer.run_command_output("sudo chmod 644 " + service_unit_path) # 644 = Owner: RW; Group: R; Others: R diff --git a/src/core/tests/Test_ServiceManager.py b/src/core/tests/Test_ServiceManager.py index 0eb406ff..ec4216c2 100644 --- a/src/core/tests/Test_ServiceManager.py +++ b/src/core/tests/Test_ServiceManager.py @@ -28,6 +28,8 @@ def setUp(self): self.service_manager = ServiceManager(self.runtime.env_layer, self.runtime.execution_config, self.runtime.composite_logger, self.runtime.telemetry_writer,ServiceInfo("AutoAssessment", "Auto assessment service", "path")) self.service_manager.service_name = "test_service" self.mock_systemd_service_unit_path = "/etc/systemd/system/{0}.service" + self.written_service_unit_path = None + self.written_service_unit_content = None def tearDown(self): self.runtime.stop() @@ -38,6 +40,8 @@ def mock_run_command_to_set_service_file_permission(self, cmd, no_output=False, return 0, "permissions set" def mock_write_with_retry_valid(self, file_path_or_handle, data, mode='a+'): + self.written_service_unit_path = file_path_or_handle + self.written_service_unit_content = data return def mock_invoke_systemctl(self, command, description): @@ -58,11 +62,15 @@ def mock_invoke_systemctl(self, command, description): elif "is-active" in command: return 0, "Checking if service is active" - def test_create_service_unit_file(self): + def test_create_service_unit_file_sets_ten_minute_start_timeout(self): self.service_manager.env_layer.run_command_output = self.mock_run_command_to_set_service_file_permission self.service_manager.env_layer.file_system.write_with_retry = self.mock_write_with_retry_valid self.service_manager.create_service_unit_file(exec_start="/bin/bash " + self.service_manager.service_exec_path, desc="Microsoft Azure Linux Patch Extension - Auto Assessment") + self.assertEqual("/etc/systemd/system/test_service.service", self.written_service_unit_path) + self.assertIn("\nType=forking\n", self.written_service_unit_content) + self.assertIn("\nTimeoutStartSec=10min\n", self.written_service_unit_content) + def test_start_service(self): # Set method calls self.service_manager.invoke_systemctl_called = False