From 16dc0e5ef2c86a315a0d09fb186dd1616df1444e Mon Sep 17 00:00:00 2001 From: Jochen Breuer Date: Wed, 6 Sep 2017 10:16:51 +0200 Subject: [PATCH] Catching error when PIDfile cannot be deleted Usually the PIDfile is locate in /run. If Salt is not started with root permissions, it is not able to delete the PIDfile in /run. It should be safe to just ignore this error, since Salt overwrites the PIDfile on the next start. --- salt/utils/parsers.py | 8 +++++- tests/unit/utils/test_parsers.py | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py index 925ec9f4e4..d8c5068874 100644 --- a/salt/utils/parsers.py +++ b/salt/utils/parsers.py @@ -966,7 +966,13 @@ class DaemonMixIn(six.with_metaclass(MixInMeta, object)): # We've loaded and merged options into the configuration, it's safe # to query about the pidfile if self.check_pidfile(): - os.unlink(self.config['pidfile']) + try: + os.unlink(self.config['pidfile']) + except OSError as err: + # This happens when running salt-master as a non-root user + # and can be ignored, since salt-master is able to + # overwrite the PIDfile on the next start. + pass def set_pidfile(self): from salt.utils.process import set_pidfile diff --git a/tests/unit/utils/test_parsers.py b/tests/unit/utils/test_parsers.py index 43488e894c..8168b3e6e3 100644 --- a/tests/unit/utils/test_parsers.py +++ b/tests/unit/utils/test_parsers.py @@ -5,6 +5,7 @@ # Import python libs from __future__ import absolute_import +import logging # Import Salt Testing Libs from tests.support.unit import skipIf, TestCase @@ -21,6 +22,7 @@ import salt.utils.parsers import salt.log.setup as log import salt.config import salt.syspaths +from salt.utils.parsers import DaemonMixIn class ErrorMock(object): # pylint: disable=too-few-public-methods @@ -958,5 +960,57 @@ class SaltAPIParserTestCase(LogSettingsParserTests): self.addCleanup(delattr, self, 'parser') +@skipIf(NO_MOCK, NO_MOCK_REASON) +class DaemonMixInTestCase(TestCase): + ''' + Tests the PIDfile deletion in the DaemonMixIn. + ''' + + def setUp(self): + ''' + Setting up + ''' + # Set PID + self.pid = '/some/fake.pid' + + # Setup mixin + self.mixin = salt.utils.parsers.DaemonMixIn() + self.mixin.config = {} + self.mixin.config['pidfile'] = self.pid + + # logger + self.logger = logging.getLogger('salt.utils.parsers') + + def test_pid_file_deletion(self): + ''' + PIDfile deletion without exception. + ''' + with patch('os.unlink', MagicMock()) as os_unlink: + with patch('os.path.isfile', MagicMock(return_value=True)): + with patch.object(self.logger, 'info') as mock_logger: + self.mixin._mixin_before_exit() + assert mock_logger.call_count == 0 + assert os_unlink.call_count == 1 + + # Hide the class from unittest framework when it searches for TestCase classes in the module del LogSettingsParserTests + + +if __name__ == '__main__': + from integration import run_tests # pylint: disable=import-error,wrong-import-position + run_tests(MasterOptionParserTestCase, + MinionOptionParserTestCase, + ProxyMinionOptionParserTestCase, + SyndicOptionParserTestCase, + SaltCMDOptionParserTestCase, + SaltCPOptionParserTestCase, + SaltKeyOptionParserTestCase, + SaltCallOptionParserTestCase, + SaltRunOptionParserTestCase, + SaltSSHOptionParserTestCase, + SaltCloudParserTestCase, + SPMParserTestCase, + SaltAPIParserTestCase, + DaemonMixInTestCase, + needs_daemon=False) -- 2.13.6