Background
The Stack definitions can be found in the source tree at /ambari-server/src/main/resources/stacks
. After you install the Ambari Server, the Stack definitions can be found at /var/lib/ambari-server/resources/stacks
Structure
The structure of a Stack definition is as follows:
|_ stacks |_ <stack_name> |_ <stack_version> metainfo.xml |_ hooks |_ repos repoinfo.xml |_ services |_ <service_name> metainfo.xml metrics.json |_ configuration {configuration files} |_ package {files, scripts, templates}
Defining a Service and Components
The metainfo.xml
file in a Service describes the service, the components of the service and the management scripts to use for executing commands. A component of a service can be either a MASTER, SLAVE or CLIENT category. The <category> tells Ambari what default commands should be available to manage and monitor the component.
For each Component you specify the <commandScript> to use when executing commands. There is a defined set of default commands the component must support.
Component Category | Default Commands |
---|---|
MASTER | install, start, stop, configure, status |
SLAVE | install, start, stop, configure, status |
CLIENT | install, configure, status |
Ambari supports different types of commands scripts, for example PYTHON and PUPPET. The type is used to know how to execute the command scripts. You can also create custom commands if there are other commands beyond the default your component needs to support.
For example, in the YARN Service describes the ResourceManager component as follows in metainfo.xml
:
<component> <name>RESOURCEMANAGER</name> <category>MASTER</category> <commandScript> <script>scripts/resourcemanager.py</script> <scriptType>PYTHON</scriptType> <timeout>600</timeout> </commandScript> <customCommands> <customCommand> <name>DECOMMISSION</name> <commandScript> <script>scripts/resourcemanager.py</script> <scriptType>PYTHON</scriptType> <timeout>600</timeout> </commandScript> </customCommand> </customCommands> </component>
The ResourceManager is a MASTER component, and the command script is scripts/resourcemanager.py
, which can be found in the services/YARN/package
directory. That command script is PYTHON and that script implements the default commands as python methods. This is the install method for the default INSTALL command:
class Resourcemanager(Script): def install(self, env): self.install_packages(env) self.configure(env)
You can also see a custom command is defined DECOMMISSION, which means there is also a decommission method in that python command script:
def decommission(self, env): import params ... Execute(yarn_refresh_cmd, user=yarn_user ) pass
Using Stack Inheritance
Stacks can extend other Stacks in order to share command scripts and configurations. This reduces duplication of code across Stacks with the following:
- define repositories for the child Stack
- add new Services in the child Stack (not in the parent Stack)
- override command scripts of the parent Services
- override configurations of the parent Services
For example, the HDP 2.1 Stack extends HDP 2.0.6 Stack so only the changes applicable to HDP 2.1 Stack are present in that Stack definition. This extension is defined in the metainfo.xml for HDP 2.1 Stack:
<metainfo> <versions> <active>true</active> </versions> <extends>2.0.6</extends> </metainfo>
Example: Implementing a Custom Client Service
In this example, we will create a custom service called "TESTSRV", add it to an existing Stack definition and use the Ambari APIs to install/configure the service. This service is a CLIENT so it has two commands: install and configure.
Create and Add the Service
On the Ambari Server, browse to the
/var/lib/ambari-server/resources/stacks/HDP/2.0.6/services
directory. In this case, we will browse to the HDP 2.0 Stack definition.cd /var/lib/ambari-server/resources/stacks/HDP/2.0.6/services
Create a directory named
/var/lib/ambari-server/resources/stacks/HDP/2.0.6/services/TESTSRV
that will contain the service definition for TESTSRV.mkdir /var/lib/ambari-server/resources/stacks/HDP/2.0.6/services/TESTSRV
Browse to the newly created
TESTSRV
directory, create ametainfo.xml
file that describes the new service. For example:<?xml version="1.0"?> <metainfo> <schemaVersion>2.0</schemaVersion> <services> <service> <name>TESTSRV</name> <comment>A New Test Service</comment> <version>0.1.0</version> <components> <component> <name>TEST_CLIENT</name> <category>CLIENT</category> <commandScript> <script>scripts/test_client.py</script> <scriptType>PYTHON</scriptType> <timeout>600</timeout> </commandScript> </component> </components> <osSpecifics> <osSpecific> <osFamily>any</osFamily> </osSpecific> </osSpecifics> </service> </services> </metainfo>
- In the above, my service name is "TESTSRV", and it contains one component "TEST_CLIENT" that is of component category "CLIENT". That client is managed via the command script
scripts/test_client.py
. Next, let's create that command script. Create a directory for the command script
/var/lib/ambari-server/resources/stacks/HDP/2.0.6/servi
ces/
TESTSRV
/
package/scripts
that we designated in the service metainfo.mkdir -p /var/lib/ambari-server/resources/stacks/HDP/2.0.6/services/TESTSRV/package/scripts
Browse to the scripts directory and create the
test_client.py
file. For example:import sys from resource_management import * class TestClient(Script): def install(self, env): print 'Install the client'; def configure(self, env): print 'Configure the client'; if __name__ == "__main__": TestClient().execute()
Now, restart Ambari Server for this new service definition to be distributed to all the Agents in the cluster.
ambari-server restart
Install the Service into the Cluster
Add the Service to the Cluster.
POST /api/v1/clusters/MyCluster/services { "ServiceInfo": { "service_name":"TESTSRV" } }
Add the Components to the Service. In this case, add TEST_CLIENT to TESTSRV.
POST /api/v1/clusters/MyCluster/services/TESTSRV/components/TEST_CLIENT
Install the component on a host. For example, on the
c6403.ambari.apache.org
host, first create the component resource, then have Ambari install the component. This will end up calling theinstall()
method in the command script.POST /api/v1/clusters/MyCluster/hosts/c6403.ambari.apache.org/host_components/TEST_CLIENT
PUT /api/v1/clusters/MyCluster/hosts/c6403.ambari.apache.org/host_components/TEST_CLIENT { "RequestInfo":{ "context":"Install Test Srv"}, "Body":{ "HostRoles":{ "state":"INSTALLED" } } }
Use the following to configure the client on the host. This will end up calling the
configure()
method in the command script.POST /api/v1/clusters/MyCluster/requests { "RequestInfo" : { "command" : "CONFIGURE", "context" : "Config Test Srv Client" }, "Requests/resource_filters": [{ "service_name" : "TESTSRV", "component_name" : "TEST_CLIENT", "hosts" : "c6403.ambari.apache.org" }] }
If you want to see which hosts the component is installed.
GET /api/v1/clusters/MyCluster/components/TEST_CLIENT