You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by dm...@apache.org on 2013/11/11 21:53:18 UTC
git commit: AMBARI-3744. Integrate CustomServiceOrchestrator and new
command format at the agent side
Updated Branches:
refs/heads/trunk ccf874f4a -> 44a6d2f70
AMBARI-3744. Integrate CustomServiceOrchestrator and new command format at the agent side
Project: http://git-wip-us.apache.org/repos/asf/incubator-ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ambari/commit/44a6d2f7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ambari/tree/44a6d2f7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ambari/diff/44a6d2f7
Branch: refs/heads/trunk
Commit: 44a6d2f70269780c2074bfc6c5457711bdf0b9ad
Parents: ccf874f
Author: Lisnichenko Dmitro <dl...@hortonworks.com>
Authored: Mon Nov 11 22:52:23 2013 +0200
Committer: Lisnichenko Dmitro <dl...@hortonworks.com>
Committed: Mon Nov 11 22:52:23 2013 +0200
----------------------------------------------------------------------
.gitignore | 1 +
.../src/main/python/ambari_agent/ActionQueue.py | 50 +++++++---
.../ambari_agent/CustomServiceOrchestrator.py | 54 +++--------
.../src/main/python/ambari_agent/FileCache.py | 6 +-
ambari-agent/src/test/python/TestActionQueue.py | 57 ++++++++++++
.../python/TestCustomServiceOrchestrator.py | 96 +++++++++++++++++++-
ambari-agent/src/test/python/TestFileCache.py | 68 ++++++++++++++
ambari-agent/src/test/python/TestMain.py | 1 +
.../HDP/2.0._/services/HBASE/metainfo.xml | 91 +++++++++++++++++++
.../HBASE/package/scripts/hbase_client.py | 38 ++++++++
.../HBASE/package/scripts/hbase_master.py | 38 ++++++++
.../HBASE/package/scripts/hbase_regionserver.py | 38 ++++++++
.../HBASE/package/scripts/hbase_service.py | 38 ++++++++
13 files changed, 514 insertions(+), 62 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index f4274d9..681002b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ target
.hgtags
derby.log
pass.txt
+ambari-agent/src/test/python/dummy_files/current-stack
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/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 a796368..8944e51 100644
--- a/ambari-agent/src/main/python/ambari_agent/ActionQueue.py
+++ b/ambari-agent/src/main/python/ambari_agent/ActionQueue.py
@@ -31,6 +31,7 @@ import PuppetExecutor
import PythonExecutor
from ActualConfigHandler import ActualConfigHandler
from CommandStatusDict import CommandStatusDict
+from CustomServiceOrchestrator import CustomServiceOrchestrator
logger = logging.getLogger()
@@ -55,6 +56,9 @@ class ActionQueue(threading.Thread):
COMPLETED_STATUS = 'COMPLETED'
FAILED_STATUS = 'FAILED'
+ COMMAND_FORMAT_V1 = "1.0"
+ COMMAND_FORMAT_V2 = "2.0"
+
def __init__(self, config, controller):
super(ActionQueue, self).__init__()
self.commandQueue = Queue.Queue()
@@ -65,6 +69,7 @@ class ActionQueue(threading.Thread):
self.sh = shellRunner()
self._stop = threading.Event()
self.tmpdir = config.get('agent', 'prefix')
+ self.customServiceOrchestrator = CustomServiceOrchestrator(config)
def stop(self):
self._stop.set()
@@ -103,16 +108,33 @@ class ActionQueue(threading.Thread):
logger.warn(err)
+ def determine_command_format_version(self, command):
+ """
+ Returns either COMMAND_FORMAT_V1 or COMMAND_FORMAT_V2
+ """
+ try:
+ if command['commandParams']['schema_version'] == self.COMMAND_FORMAT_V2:
+ return self.COMMAND_FORMAT_V2
+ else:
+ return self.COMMAND_FORMAT_V1
+ except KeyError:
+ pass # ignore
+ return self.COMMAND_FORMAT_V1 # Fallback
+
+
def execute_command(self, command):
'''
Executes commands of type EXECUTION_COMMAND
'''
clusterName = command['clusterName']
commandId = command['commandId']
+ command_format = self.determine_command_format_version(command)
- logger.info("Executing command with id = " + str(commandId) +\
- " for role = " + command['role'] + " of " +\
- "cluster " + clusterName)
+ message = "Executing command with id = {commandId} for role = {role} of " \
+ "cluster {cluster}. Command format={command_format}".format(
+ commandId = str(commandId), role=command['role'],
+ cluster=clusterName, command_format=command_format)
+ logger.info(message)
logger.debug(pprint.pformat(command))
taskId = command['taskId']
@@ -124,17 +146,19 @@ class ActionQueue(threading.Thread):
'status': self.IN_PROGRESS_STATUS
})
self.commandStatuses.put_command_status(command, in_progress_status)
- # TODO: Add CustomServiceOrchestrator call somewhere here
# running command
- # Create a new instance of executor for the current thread
- puppetExecutor = PuppetExecutor.PuppetExecutor(
- self.config.get('puppet', 'puppetmodules'),
- self.config.get('puppet', 'puppet_home'),
- self.config.get('puppet', 'facter_home'),
- self.config.get('agent', 'prefix'), self.config)
- commandresult = puppetExecutor.runCommand(command, in_progress_status['tmpout'],
- in_progress_status['tmperr'])
-
+ if command_format == self.COMMAND_FORMAT_V1:
+ # Create a new instance of executor for the current thread
+ puppetExecutor = PuppetExecutor.PuppetExecutor(
+ self.config.get('puppet', 'puppetmodules'),
+ self.config.get('puppet', 'puppet_home'),
+ self.config.get('puppet', 'facter_home'),
+ self.config.get('agent', 'prefix'), self.config)
+ commandresult = puppetExecutor.runCommand(command, in_progress_status['tmpout'],
+ in_progress_status['tmperr'])
+ else:
+ commandresult = self.customServiceOrchestrator.runCommand(command,
+ in_progress_status['tmpout'], in_progress_status['tmperr'])
# dumping results
status = self.COMPLETED_STATUS
if commandresult['exitcode'] != 0:
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/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 e6032cf..2074b35 100644
--- a/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
+++ b/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py
@@ -48,19 +48,18 @@ class CustomServiceOrchestrator():
def runCommand(self, command, tmpoutfile, tmperrfile):
try:
- # TODO: Adjust variables
- service_name = command['serviceName']
component_name = command['role']
- stack_name = command['stackName'] # TODO: add at the server side
- stack_version = command['stackVersion'] # TODO: add at the server side
- script_type = command['scriptType'] # TODO: add at the server side
- script = command['script']
+ stack_name = command['hostLevelParams']['stack_name']
+ stack_version = command['hostLevelParams']['stack_version']
+ script_type = command['commandParams']['script_type']
+ script = command['commandParams']['script']
command_name = command['roleCommand']
- timeout = int(command['timeout']) # TODO: add at the server side
+ timeout = int(command['commandParams']['command_timeout'])
+ metadata_folder = command['commandParams']['service_metadata_folder']
base_dir = self.file_cache.get_service_base_dir(
- stack_name, stack_version, service_name, component_name)
+ stack_name, stack_version, metadata_folder, component_name)
script_path = self.resolve_script_path(base_dir, script, script_type)
- if script_type == self.SCRIPT_TYPE_PYTHON:
+ if script_type.upper() == self.SCRIPT_TYPE_PYTHON:
json_path = self.dump_command_to_json(command)
script_params = [command_name, json_path, base_dir]
ret = self.python_executor.run_file(
@@ -76,7 +75,7 @@ class CustomServiceOrchestrator():
ret = {
'stdout' : message,
'stderr' : message,
- 'exitCode': 1,
+ 'exitcode': 1,
}
return ret
@@ -96,37 +95,10 @@ class CustomServiceOrchestrator():
"""
Converts command to json file and returns file path
"""
- command_id = command['commandId']
- file_path = os.path.join(self.tmp_dir, "command-{0}.json".format(command_id))
- with open(file_path, "w") as f:
+ task_id = command['taskId']
+ file_path = os.path.join(self.tmp_dir, "command-{0}.json".format(task_id))
+ # Command json contains passwords, that's why we need proper permissions
+ with os.fdopen(os.open(file_path, os.O_WRONLY | os.O_CREAT,0600), 'w') as f:
content = json.dumps(command)
f.write(content)
return file_path
-
-
-def main():
- """
- May be used for manual testing if needed
- """
- config = AmbariConfig().getConfig()
- orchestrator = CustomServiceOrchestrator(config)
- config.set('agent', 'prefix', "/tmp")
- command = {
- "serviceName" : "HBASE",
- "role" : "HBASE_MASTER",
- "stackName" : "HDP",
- "stackVersion" : "1.2.0",
- "scriptType" : "PYTHON",
- "script" : "/tmp/1.py",
- "roleCommand" : "START",
- "timeout": 600
- }
-
- result = orchestrator.runCommand(command, "/tmp/out-1.txt", "/tmp/err-1.txt")
- pprint.pprint(result)
- pass
-
-
-
-if __name__ == "__main__":
- main()
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-agent/src/main/python/ambari_agent/FileCache.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/FileCache.py b/ambari-agent/src/main/python/ambari_agent/FileCache.py
index dbef708..c02f217 100644
--- a/ambari-agent/src/main/python/ambari_agent/FileCache.py
+++ b/ambari-agent/src/main/python/ambari_agent/FileCache.py
@@ -19,16 +19,12 @@ limitations under the License.
'''
-# TODO: Update class description
-
-
import logging
import Queue
import threading
import pprint
import os
import json
-from ServiceComponentMetadata import ServiceComponentMetadata
from AgentException import AgentException
logger = logging.getLogger()
@@ -50,7 +46,7 @@ class FileCache():
Returns a base directory for service
"""
metadata_path = os.path.join(self.cache_dir, "stacks", str(stack_name),
- str(stack_version), str(service))
+ str(stack_version), "services", str(service))
if not os.path.isdir(metadata_path):
# TODO: Metadata downloading will be implemented at Phase 2
# As of now, all stack definitions are packaged and distributed with
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-agent/src/test/python/TestActionQueue.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/TestActionQueue.py b/ambari-agent/src/test/python/TestActionQueue.py
index 31643b2..98817e9 100644
--- a/ambari-agent/src/test/python/TestActionQueue.py
+++ b/ambari-agent/src/test/python/TestActionQueue.py
@@ -31,6 +31,7 @@ from threading import Thread
from mock.mock import patch, MagicMock, call
from ambari_agent.StackVersionsFileHandler import StackVersionsFileHandler
+from ambari_agent.CustomServiceOrchestrator import CustomServiceOrchestrator
class TestActionQueue(TestCase):
@@ -361,3 +362,59 @@ class TestActionQueue(TestCase):
expected = 'dummy report'
self.assertEqual(len(report['componentStatus']), 1)
self.assertEqual(report['componentStatus'][0], expected)
+
+
+ def test_determine_command_format_version(self):
+ v1_command = {
+ 'commandParams': {
+ 'schema_version': '1.0'
+ }
+ }
+ v2_command = {
+ 'commandParams': {
+ 'schema_version': '2.0'
+ }
+ }
+ current_command = {
+ # Absent 'commandParams' section
+ }
+ actionQueue = ActionQueue(AmbariConfig().getConfig(), 'dummy_controller')
+ self.assertEqual(actionQueue.determine_command_format_version(v1_command),
+ ActionQueue.COMMAND_FORMAT_V1)
+ self.assertEqual(actionQueue.determine_command_format_version(v2_command),
+ ActionQueue.COMMAND_FORMAT_V2)
+ self.assertEqual(actionQueue.determine_command_format_version(current_command),
+ ActionQueue.COMMAND_FORMAT_V1)
+
+
+ @patch.object(ActionQueue, "determine_command_format_version")
+ @patch("__builtin__.open")
+ @patch.object(PuppetExecutor, "runCommand")
+ @patch.object(CustomServiceOrchestrator, "runCommand")
+ @patch.object(ActionQueue, "status_update_callback")
+ def test_command_execution_depending_on_command_format(self,
+ status_update_callback_mock,
+ custom_ex_runCommand_mock,
+ puppet_runCommand_mock, open_mock,
+ determine_command_format_version_mock):
+ actionQueue = ActionQueue(AmbariConfig().getConfig(), 'dummy_controller')
+ ret = {
+ 'stdout' : '',
+ 'stderr' : '',
+ 'exitcode': 1,
+ }
+ puppet_runCommand_mock.return_value = ret
+ determine_command_format_version_mock.return_value = \
+ ActionQueue.COMMAND_FORMAT_V1
+ actionQueue.execute_command(self.datanode_install_command)
+ self.assertTrue(puppet_runCommand_mock.called)
+ self.assertFalse(custom_ex_runCommand_mock.called)
+
+ puppet_runCommand_mock.reset_mock()
+
+ custom_ex_runCommand_mock.return_value = ret
+ determine_command_format_version_mock.return_value = \
+ ActionQueue.COMMAND_FORMAT_V2
+ actionQueue.execute_command(self.datanode_install_command)
+ self.assertFalse(puppet_runCommand_mock.called)
+ self.assertTrue(custom_ex_runCommand_mock.called)
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-agent/src/test/python/TestCustomServiceOrchestrator.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/TestCustomServiceOrchestrator.py b/ambari-agent/src/test/python/TestCustomServiceOrchestrator.py
index e4a430d..b9aab2a 100644
--- a/ambari-agent/src/test/python/TestCustomServiceOrchestrator.py
+++ b/ambari-agent/src/test/python/TestCustomServiceOrchestrator.py
@@ -18,6 +18,7 @@ See the License for the specific language governing permissions and
limitations under the License.
'''
import ConfigParser
+import os
import pprint
@@ -28,10 +29,13 @@ import time
from threading import Thread
from PythonExecutor import PythonExecutor
+from CustomServiceOrchestrator import CustomServiceOrchestrator
from AmbariConfig import AmbariConfig
from mock.mock import MagicMock, patch
import StringIO
import sys
+from AgentException import AgentException
+from FileCache import FileCache
class TestCustomServiceOrchestrator(TestCase):
@@ -42,9 +46,95 @@ class TestCustomServiceOrchestrator(TestCase):
sys.stdout = out
# generate sample config
tmpdir = tempfile.gettempdir()
- config = ConfigParser.RawConfigParser()
- config.add_section('agent')
- config.set('agent', 'prefix', tmpdir)
+ self.config = ConfigParser.RawConfigParser()
+ self.config.add_section('agent')
+ self.config.set('agent', 'prefix', tmpdir)
+ self.config.set('agent', 'cache_dir', "/cachedir")
+
+
+ def test_dump_command_to_json(self):
+ command = {
+ 'commandType': 'EXECUTION_COMMAND',
+ 'role': u'DATANODE',
+ 'roleCommand': u'INSTALL',
+ 'commandId': '1-1',
+ 'taskId': 3,
+ 'clusterName': u'cc',
+ 'serviceName': u'HDFS',
+ 'configurations':{'global' : {}},
+ 'configurationTags':{'global' : { 'tag': 'v1' }}
+ }
+ config = AmbariConfig().getConfig()
+ tempdir = tempfile.gettempdir()
+ config.set('agent', 'prefix', tempdir)
+ orchestrator = CustomServiceOrchestrator(config)
+ file = orchestrator.dump_command_to_json(command)
+ self.assertTrue(os.path.exists(file))
+ self.assertTrue(os.path.getsize(file) > 0)
+ self.assertEqual(oct(os.stat(file).st_mode & 0777), '0600')
+ os.unlink(file)
+
+
+ @patch("os.path.exists")
+ def test_resolve_script_path(self, exists_mock):
+ config = AmbariConfig().getConfig()
+ orchestrator = CustomServiceOrchestrator(config)
+ # Testing existing path
+ exists_mock.return_value = True
+ path = orchestrator.\
+ resolve_script_path("/HBASE", "scripts/hbase_master.py", "PYTHON")
+ self.assertEqual("/HBASE/package/scripts/hbase_master.py", path)
+ # Testing not existing path
+ exists_mock.return_value = False
+ try:
+ orchestrator.resolve_script_path("/HBASE",
+ "scripts/hbase_master.py", "PYTHON")
+ self.fail('ExpectedException not thrown')
+ except AgentException:
+ pass # Expected
+
+
+ @patch.object(CustomServiceOrchestrator, "resolve_script_path")
+ @patch.object(FileCache, "get_service_base_dir")
+ @patch.object(CustomServiceOrchestrator, "dump_command_to_json")
+ @patch.object(PythonExecutor, "run_file")
+ def test_runCommand(self, run_file_mock, dump_command_to_json_mock,
+ get_service_base_dir_mock, resolve_script_path_mock):
+ command = {
+ 'role' : 'REGION_SERVER',
+ 'hostLevelParams' : {
+ 'stack_name' : 'HDP',
+ 'stack_version' : '2.0.7',
+ },
+ 'commandParams': {
+ 'script_type': 'PYTHON',
+ 'script': 'scripts/hbase_regionserver.py',
+ 'command_timeout': '600',
+ 'service_metadata_folder' : 'HBASE'
+ },
+ 'roleCommand': 'INSTALL'
+ }
+ get_service_base_dir_mock.return_value = "/basedir/"
+ resolve_script_path_mock.return_value = "/basedir/scriptpath"
+ orchestrator = CustomServiceOrchestrator(self.config)
+ # normal run case
+ run_file_mock.return_value = {
+ 'stdout' : 'sss',
+ 'stderr' : 'eee',
+ 'exitcode': 0,
+ }
+ ret = orchestrator.runCommand(command, "out.txt", "err.txt")
+ self.assertEqual(ret['exitcode'], 0)
+ self.assertTrue(run_file_mock.called)
+
+ run_file_mock.reset_mock()
+ # unknown script type case
+ command['commandParams']['script_type'] = "PUPPET"
+ ret = orchestrator.runCommand(command, "out.txt", "err.txt")
+ self.assertEqual(ret['exitcode'], 1)
+ self.assertFalse(run_file_mock.called)
+ self.assertTrue("Unknown script type" in ret['stdout'])
+ pass
def tearDown(self):
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-agent/src/test/python/TestFileCache.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/TestFileCache.py b/ambari-agent/src/test/python/TestFileCache.py
new file mode 100644
index 0000000..8426012
--- /dev/null
+++ b/ambari-agent/src/test/python/TestFileCache.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python2.6
+
+'''
+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 ConfigParser
+import os
+
+import pprint
+
+from unittest import TestCase
+import threading
+import tempfile
+import time
+from threading import Thread
+
+from PythonExecutor import PythonExecutor
+from CustomServiceOrchestrator import CustomServiceOrchestrator
+from FileCache import FileCache
+from AmbariConfig import AmbariConfig
+from mock.mock import MagicMock, patch
+import StringIO
+import sys
+from ambari_agent import AgentException
+
+
+class TestFileCache(TestCase):
+
+ def setUp(self):
+ # disable stdout
+ out = StringIO.StringIO()
+ sys.stdout = out
+ # generate sample config
+ tmpdir = tempfile.gettempdir()
+ self.config = ConfigParser.RawConfigParser()
+ self.config.add_section('agent')
+ self.config.set('agent', 'prefix', tmpdir)
+ self.config.set('agent', 'cache_dir', "/var/lib/ambari-agent/cache")
+
+
+ @patch("os.path.isdir")
+ def test_get_service_base_dir(self, isdir_mock):
+ fileCache = FileCache(self.config)
+ isdir_mock.return_value = True
+ base = fileCache.get_service_base_dir("HDP", "2.0.7",
+ "HBASE", "REGION_SERVER")
+ self.assertEqual(base, "/var/lib/ambari-agent/cache/stacks/HDP/2.0.7/services/HBASE")
+
+
+ def tearDown(self):
+ # enable stdout
+ sys.stdout = sys.__stdout__
+
+
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-agent/src/test/python/TestMain.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/TestMain.py b/ambari-agent/src/test/python/TestMain.py
index 0313b9c..b9ae2b9 100644
--- a/ambari-agent/src/test/python/TestMain.py
+++ b/ambari-agent/src/test/python/TestMain.py
@@ -94,6 +94,7 @@ class TestMain(unittest.TestCase):
# Testing with default setup (config file does not contain loglevel entry)
# Log level should not be changed
+ config.set('agent', 'loglevel', None)
main.update_log_level(config)
self.assertFalse(setLevel_mock.called)
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml
new file mode 100644
index 0000000..0ba9741
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/metainfo.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<metainfo>
+ <schemaVersion>2.0</schemaVersion>
+ <services>
+ <service>
+ <name>HBASE</name>
+ <comment>Non-relational distributed database and centralized service for configuration management &
+ synchronization
+ </comment>
+ <version>0.96.0.2.0.6.0</version>
+ <components>
+ <component>
+ <name>HBASE_MASTER</name>
+ <category>MASTER</category>
+ <commandScript>
+ <script>scripts/hbase_master.py</script>
+ <scriptType>PYTHON</scriptType>
+ <timeout>600</timeout>
+ </commandScript>
+ </component>
+
+ <component>
+ <name>HBASE_REGIONSERVER</name>
+ <category>SLAVE</category>
+ <commandScript>
+ <script>scripts/hbase_regionserver.py</script>
+ <scriptType>PYTHON</scriptType>
+ </commandScript>
+ <customCommands>
+ <customCommand>
+ <name>DECOMMISSION_REGIONSERVER</name>
+ <commandScript>
+ <script>scripts/hbase_regionserver.py</script>
+ <scriptType>PYTHON</scriptType>
+ <timeout>600</timeout>
+ </commandScript>
+ </customCommand>
+ </customCommands>
+ </component>
+
+ <component>
+ <name>HBASE_CLIENT</name>
+ <category>CLIENT</category>
+ </component>
+ <commandScript>
+ <script>scripts/hbase_client.py</script>
+ <scriptType>PYTHON</scriptType>
+ </commandScript>
+ </components>
+
+ <osSpecificPackages>
+ <osSpecificPackage>
+ <osType>centos6</osType>
+ <packages>
+ <package>
+ <type>rpm</type>
+ <name>hbase</name>
+ </package>
+ </packages>
+ </osSpecificPackage>
+ </osSpecificPackages>
+
+ <customCommands>
+ <customCommand>
+ <name>SERVICE_CHECK</name>
+ <commandScript>
+ <script>scripts/hbase_service.py</script>
+ <scriptType>PYTHON</scriptType>
+ <timeout>300</timeout>
+ </commandScript>
+ </customCommand>
+ </customCommands>
+ </service>
+ </services>
+</metainfo>
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_client.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_client.py b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_client.py
new file mode 100644
index 0000000..9b7cdec
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_client.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+from resource_management import *
+
+class Client(Script):
+
+ def install(self):
+ print "Install!"
+
+ def start(self):
+ print "Start!"
+
+ def stop(self):
+ print "Stop!"
+
+ def configure(self):
+ print "Configure!"
+
+if __name__ == "__main__":
+ Client().execute()
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_master.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_master.py b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_master.py
new file mode 100644
index 0000000..d9e2ae0
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_master.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+from resource_management import *
+
+class Master(Script):
+
+ def install(self):
+ print "Install!"
+
+ def start(self):
+ print "Start!"
+
+ def stop(self):
+ print "Stop!"
+
+ def configure(self):
+ print "Configure!"
+
+if __name__ == "__main__":
+ Master().execute()
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py
new file mode 100644
index 0000000..5073686
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_regionserver.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+from resource_management import *
+
+class RegionServer(Script):
+
+ def install(self):
+ print "Install!"
+
+ def start(self):
+ print "Start!"
+
+ def stop(self):
+ print "Stop!"
+
+ def configure(self):
+ print "Configure!"
+
+if __name__ == "__main__":
+ RegionServer().execute()
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/44a6d2f7/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_service.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_service.py b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_service.py
new file mode 100644
index 0000000..b4d5d5b
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0._/services/HBASE/package/scripts/hbase_service.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+from resource_management import *
+
+class Service(Script):
+
+ def install(self):
+ print "Install!"
+
+ def start(self):
+ print "Start!"
+
+ def stop(self):
+ print "Stop!"
+
+ def configure(self):
+ print "Configure!"
+
+if __name__ == "__main__":
+ Service().execute()