You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2014/12/12 02:14:41 UTC
ambari git commit: AMBARI-8343. Components should indicate Security
State (via ambari-agent). (Robert Levas via yusaku)
Repository: ambari
Updated Branches:
refs/heads/trunk 8235e7d63 -> 5cba41704
AMBARI-8343. Components should indicate Security State (via ambari-agent). (Robert Levas via yusaku)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5cba4170
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5cba4170
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5cba4170
Branch: refs/heads/trunk
Commit: 5cba41704c4a5c1defbba522253b00e5a2b8a345
Parents: 8235e7d
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Thu Dec 11 17:14:11 2014 -0800
Committer: Yusaku Sako <yu...@hortonworks.com>
Committed: Thu Dec 11 17:14:11 2014 -0800
----------------------------------------------------------------------
.../src/main/python/ambari_agent/ActionQueue.py | 4 ++
.../ambari_agent/CustomServiceOrchestrator.py | 31 ++++++++++++
.../test/python/ambari_agent/TestActionQueue.py | 17 +++++--
.../TestCustomServiceOrchestrator.py | 51 ++++++++++++++++++++
4 files changed, 99 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/5cba4170/ambari-agent/src/main/python/ambari_agent/ActionQueue.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/ActionQueue.py b/ambari-agent/src/main/python/ambari_agent/ActionQueue.py
index fbde26f..b60736d 100644
--- a/ambari-agent/src/main/python/ambari_agent/ActionQueue.py
+++ b/ambari-agent/src/main/python/ambari_agent/ActionQueue.py
@@ -329,6 +329,7 @@ class ActionQueue(threading.Thread):
# For custom services, responsibility to determine service status is
# delegated to python scripts
component_status_result = self.customServiceOrchestrator.requestComponentStatus(command)
+ component_security_status_result = self.customServiceOrchestrator.requestComponentSecurityState(command)
if component_status_result['exitcode'] == 0:
component_status = LiveStatus.LIVE_STATUS
@@ -340,6 +341,9 @@ class ActionQueue(threading.Thread):
result = livestatus.build(forsed_component_status= component_status)
+ # Add security state to the result
+ result['securityState'] = component_security_status_result
+
if component_extra is not None and len(component_extra) != 0:
if component_extra.has_key('alerts'):
result['alerts'] = component_extra['alerts']
http://git-wip-us.apache.org/repos/asf/ambari/blob/5cba4170/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py b/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
index 08dddae..61997f2 100644
--- a/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
+++ b/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
@@ -41,6 +41,7 @@ class CustomServiceOrchestrator():
SCRIPT_TYPE_PYTHON = "PYTHON"
COMMAND_NAME_STATUS = "STATUS"
+ COMMAND_NAME_SECURITY_STATUS = "SECURITY_STATUS"
CUSTOM_ACTION_COMMAND = 'ACTIONEXECUTE'
CUSTOM_COMMAND_COMMAND = 'CUSTOM_COMMAND'
@@ -229,6 +230,36 @@ class CustomServiceOrchestrator():
override_output_files=override_output_files)
return res
+ def requestComponentSecurityState(self, command):
+ """
+ Determines the current security state of the component
+ A command will be issued to trigger the security_status check and the result of this check will
+ returned to the caller. If the component lifecycle script has no security_status method the
+ check will return non zero exit code and "UNKNOWN" will be returned.
+ """
+ override_output_files=True # by default, we override status command output
+ if logger.level == logging.DEBUG:
+ override_output_files = False
+ security_check_res = self.runCommand(command, self.status_commands_stdout,
+ self.status_commands_stderr, self.COMMAND_NAME_SECURITY_STATUS,
+ override_output_files=override_output_files)
+ result = 'UNKNOWN'
+
+ if security_check_res is None:
+ logger.warn("The return value of the security_status check was empty, the security status is unknown")
+ elif 'exitcode' not in security_check_res:
+ logger.warn("Missing 'exitcode' value from the security_status check result, the security status is unknown")
+ elif security_check_res['exitcode'] != 0:
+ logger.debug("The 'exitcode' value from the security_status check result indicated the check routine failed to properly execute, the security status is unknown")
+ elif 'structuredOut' not in security_check_res:
+ logger.warn("Missing 'structuredOut' value from the security_status check result, the security status is unknown")
+ elif 'securityState' not in security_check_res['structuredOut']:
+ logger.warn("Missing 'securityState' value from the security_status check structuredOut data set, the security status is unknown")
+ else:
+ result = security_check_res['structuredOut']['securityState']
+
+ return result
+
def resolve_script_path(self, base_dir, script, script_type):
"""
Incapsulates logic of script location determination.
http://git-wip-us.apache.org/repos/asf/ambari/blob/5cba4170/ambari-agent/src/test/python/ambari_agent/TestActionQueue.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestActionQueue.py b/ambari-agent/src/test/python/ambari_agent/TestActionQueue.py
index 52b586b..9aeb024 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestActionQueue.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestActionQueue.py
@@ -520,24 +520,31 @@ class TestActionQueue(TestCase):
@patch.object(ActionQueue, "status_update_callback")
@patch.object(StackVersionsFileHandler, "read_stack_version")
@patch.object(CustomServiceOrchestrator, "requestComponentStatus")
+ @patch.object(CustomServiceOrchestrator, "requestComponentSecurityState")
@patch.object(ActionQueue, "execute_command")
@patch.object(LiveStatus, "build")
@patch.object(CustomServiceOrchestrator, "__init__")
def test_execute_status_command(self, CustomServiceOrchestrator_mock,
- build_mock, execute_command_mock,
+ build_mock, execute_command_mock, requestComponentSecurityState_mock,
requestComponentStatus_mock, read_stack_version_mock,
status_update_callback):
CustomServiceOrchestrator_mock.return_value = None
dummy_controller = MagicMock()
actionQueue = ActionQueue(AmbariConfig().getConfig(), dummy_controller)
- build_mock.return_value = "dummy report"
+ build_mock.return_value = {'dummy report': '' }
requestComponentStatus_mock.reset_mock()
- requestComponentStatus_mock.return_value = {'exitcode': 0}
+ requestComponentStatus_mock.return_value = {'exitcode': 0 }
+
+ requestComponentSecurityState_mock.reset_mock()
+ requestComponentSecurityState_mock.return_value = 'UNKNOWN'
+
actionQueue.execute_status_command(self.status_command)
report = actionQueue.result()
- expected = 'dummy report'
+ expected = {'dummy report': '',
+ 'securityState' : 'UNKNOWN'}
+
self.assertEqual(len(report['componentStatus']), 1)
self.assertEqual(report['componentStatus'][0], expected)
self.assertTrue(requestComponentStatus_mock.called)
@@ -545,10 +552,12 @@ class TestActionQueue(TestCase):
@patch.object(ActionQueue, "status_update_callback")
@patch.object(StackVersionsFileHandler, "read_stack_version")
@patch.object(CustomServiceOrchestrator, "requestComponentStatus")
+ @patch.object(CustomServiceOrchestrator, "requestComponentSecurityState")
@patch.object(ActionQueue, "execute_command")
@patch.object(LiveStatus, "build")
@patch.object(CustomServiceOrchestrator, "__init__")
def test_execute_status_command_with_alerts(self, CustomServiceOrchestrator_mock,
+ requestComponentSecurityState_mock,
build_mock, execute_command_mock,
requestComponentStatus_mock, read_stack_version_mock,
status_update_callback):
http://git-wip-us.apache.org/repos/asf/ambari/blob/5cba4170/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py b/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
index 24ee259..46c0166 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
@@ -476,6 +476,57 @@ class TestCustomServiceOrchestrator(TestCase):
status = orchestrator.requestComponentStatus(status_command)
self.assertEqual(runCommand_mock.return_value, status)
+ @patch.object(CustomServiceOrchestrator, "runCommand")
+ @patch.object(FileCache, "__init__")
+ def test_requestComponentSecurityState(self, FileCache_mock, runCommand_mock):
+ FileCache_mock.return_value = None
+ status_command = {
+ "serviceName" : 'HDFS',
+ "commandType" : "STATUS_COMMAND",
+ "clusterName" : "",
+ "componentName" : "DATANODE",
+ 'configurations':{}
+ }
+ dummy_controller = MagicMock()
+ orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
+ # Test securityState
+ runCommand_mock.return_value = {
+ 'exitcode' : 0,
+ 'structuredOut' : {'securityState': 'UNSECURED'}
+ }
+
+ status = orchestrator.requestComponentSecurityState(status_command)
+ self.assertEqual('UNSECURED', status)
+
+ # Test case where exit code indicates failure
+ runCommand_mock.return_value = {
+ "exitcode" : 1
+ }
+ status = orchestrator.requestComponentSecurityState(status_command)
+ self.assertEqual('UNKNOWN', status)
+
+ @patch.object(FileCache, "__init__")
+ def test_requestComponentSecurityState_realFailure(self, FileCache_mock):
+ '''
+ Tests the case where the CustomServiceOrchestrator attempts to call a service's security_status
+ method, but fails to do so because the script or method was not found.
+ :param FileCache_mock:
+ :return:
+ '''
+ FileCache_mock.return_value = None
+ status_command = {
+ "serviceName" : 'BOGUS_SERVICE',
+ "commandType" : "STATUS_COMMAND",
+ "clusterName" : "",
+ "componentName" : "DATANODE",
+ 'configurations':{}
+ }
+ dummy_controller = MagicMock()
+ orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
+
+ status = orchestrator.requestComponentSecurityState(status_command)
+ self.assertEqual('UNKNOWN', status)
+
@patch.object(CustomServiceOrchestrator, "dump_command_to_json")
@patch.object(FileCache, "__init__")