| #!/usr/bin/env python |
| |
| ''' |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ''' |
| import string |
| import random |
| import os |
| from unittest import TestCase |
| from ambari_agent.StatusCheck import StatusCheck |
| import AmbariConfig |
| import logging |
| from mock.mock import patch, Mock |
| |
| |
| USERNAME_LENGTH=10 |
| USERNAME_CHARS=string.ascii_uppercase +string.ascii_lowercase + string.digits + '-_' |
| |
| PID_DIR='/pids_dir' |
| |
| COMPONENT_LIVE = 'LIVE_COMPONENT' |
| COMPONENT_LIVE_PID = 'live_' + StatusCheck.USER_PATTERN + '_comp.pid' |
| |
| COMPONENT_DEAD = 'DEAD_COMPONENT' |
| COMPONENT_DEAD_PID = 'dead_' + StatusCheck.USER_PATTERN + '_comp.pid' |
| |
| class TestStatusCheck(TestCase): |
| |
| logger = logging.getLogger() |
| |
| def generateUserName(self): |
| return ''.join(random.choice(USERNAME_CHARS) for x in range(USERNAME_LENGTH)) |
| |
| def setUp(self): |
| |
| self.pidPathesVars = [ |
| {'var' : '', |
| 'defaultValue' : PID_DIR} |
| ] |
| |
| self.serviceToPidDict = { |
| COMPONENT_LIVE : COMPONENT_LIVE_PID, |
| COMPONENT_DEAD : COMPONENT_DEAD_PID |
| } |
| |
| live_user = self.generateUserName() |
| self.logger.info('Live user: ' + live_user) |
| self.live_pid_file_name = string.replace(COMPONENT_LIVE_PID, StatusCheck.USER_PATTERN, live_user) |
| self.live_pid_full_path = PID_DIR + os.sep + self.live_pid_file_name |
| |
| dead_user = self.generateUserName() |
| self.logger.info('Dead user: ' + live_user) |
| self.dead_pid_file_name = string.replace(COMPONENT_DEAD_PID, StatusCheck.USER_PATTERN, dead_user) |
| self.dead_pid_full_path = PID_DIR + os.sep + self.dead_pid_file_name |
| |
| self.pidFilesDict = {self.live_pid_file_name : self.live_pid_full_path, |
| self.dead_pid_file_name : self.dead_pid_full_path} |
| |
| self.is_live_values = {self.live_pid_full_path : True, |
| self.dead_pid_full_path : False} |
| |
| self.servicesToLinuxUser = {COMPONENT_LIVE : 'live_user', |
| COMPONENT_DEAD : 'dead_user'} |
| |
| self.globalConfig = {'live_user' : live_user, |
| 'dead_user' : dead_user} |
| |
| |
| # Ensure that status checker return True for running process |
| @patch.object(StatusCheck, 'getIsLive') |
| def test_live(self, get_is_live_mock): |
| |
| statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars, |
| self.globalConfig, self.servicesToLinuxUser) |
| |
| self.assertTrue(StatusCheck.USER_PATTERN in self.serviceToPidDict[COMPONENT_LIVE]) |
| self.assertTrue(StatusCheck.USER_PATTERN in self.serviceToPidDict[COMPONENT_DEAD]) |
| |
| statusCheck.pidFilesDict = self.pidFilesDict |
| |
| get_is_live_mock.side_effect = lambda pid_path : self.is_live_values[pid_path] |
| |
| status = statusCheck.getStatus(COMPONENT_LIVE) |
| self.assertEqual(status, True) |
| |
| @patch.object(logger, 'info') |
| def test_dont_relog_serToPidDict(self, logger_info_mock): |
| TestStatusCheck.timesLogged = 0 |
| |
| def my_side_effect(*args, **kwargs): |
| TestStatusCheck.timesLogged += args[0].find('Service to pid dictionary: ')+1 |
| |
| |
| logger_info_mock.side_effect = my_side_effect |
| |
| # call this three times |
| statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars, |
| self.globalConfig, self.servicesToLinuxUser) |
| statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars, |
| self.globalConfig, self.servicesToLinuxUser) |
| statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars, |
| self.globalConfig, self.servicesToLinuxUser) |
| # logged not more then once |
| self.assert_(TestStatusCheck.timesLogged <= 1, "test_dont_relog_serToPidDict logged more then once") |
| |
| # Ensure that status checker return True for running process even if multiple |
| # pids for a service component exist |
| @patch.object(StatusCheck, 'getIsLive') |
| def test_live_if_multiple_pids(self, get_is_live_mock): |
| |
| one_more_pid_file_name = string.replace(COMPONENT_LIVE_PID, StatusCheck.USER_PATTERN, |
| 'any_other_linux_user') |
| one_more_pid_full_path = PID_DIR + os.sep + one_more_pid_file_name |
| |
| self.pidFilesDict[one_more_pid_file_name] = one_more_pid_full_path |
| self.is_live_values[one_more_pid_full_path] = False |
| |
| statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars, |
| self.globalConfig, self.servicesToLinuxUser) |
| |
| statusCheck.pidFilesDict = self.pidFilesDict |
| |
| get_is_live_mock.side_effect = lambda pid_path : self.is_live_values[pid_path] |
| |
| status = statusCheck.getStatus(COMPONENT_LIVE) |
| self.assertEqual(status, True) |
| |
| # Ensure that status checker prints error message if there is no linux user |
| # for service, which pid depends on user |
| @patch.object(StatusCheck, 'getIsLive') |
| @patch.object(logger, "error") |
| def test_no_user_mapping(self, error_mock, get_is_live_mock): |
| |
| |
| badServiceToPidDict = self.serviceToPidDict.copy() |
| badServiceToPidDict['BAD_COMPONENT'] = 'prefix' + StatusCheck.USER_PATTERN |
| |
| statusCheck = StatusCheck(badServiceToPidDict, self.pidPathesVars, |
| self.globalConfig, self.servicesToLinuxUser) |
| |
| statusCheck.pidFilesDict = self.pidFilesDict |
| |
| get_is_live_mock.side_effect = lambda pid_path : self.is_live_values[pid_path] |
| |
| status = statusCheck.getStatus(COMPONENT_LIVE) |
| self.assertTrue(error_mock.called) |
| |
| # Ensure that status checker return False for dead process |
| @patch.object(StatusCheck, 'getIsLive') |
| def test_dead(self, get_is_live_mock): |
| statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars, |
| self.globalConfig, self.servicesToLinuxUser) |
| |
| statusCheck.pidFilesDict = self.pidFilesDict |
| |
| get_is_live_mock.side_effect = lambda pid_path : self.is_live_values[pid_path] |
| status = statusCheck.getStatus(COMPONENT_DEAD) |
| self.assertEqual(status, False) |