Apache Slider: Developing App Command Scripts¶
App command implementations follow a standard structure so that they can be invoked in an uniform manner. For any command, the python scripts are invoked as:
python SCRIPT COMMAND JSON_FILE PACKAGE_ROOT STRUCTURED_OUT_FILE LOG_LEVEL
SCRIPT
is the top level script that implements the commands for the component.COMMAND
is one of the following default commands -START
,STOP
,INSTALL
,CONFIG
,RESTART
,STATUS
or any custom commands.JSON_FILE
includes all configuration parameters and the values.PACKAGE_ROOT
is the root folder of the package. From this folder, its possible to access files, scripts, templates, packages (e.g. tarballs), etc. The Yarn-App author has complete control over the structure of the package as long as thePACKAGE_ROOT
andSCRIPT
path is known to the management tool.STRUCTURED_OUT_FILE
is the file where the script can output structured data.LOG_LEVEL
is the log level to use when executing the script - Slider defaults to INFO, use other levels while debugging
The management infrastructure is expected to automatically reports back STD_OUT and STD_ERR.
Sample:
python /apps/HBASE_ON_YARN/package/scripts/hbase_regionserver.py START /apps/commands/cmd_332/command.json /apps/HBASE_ON_YARN/package /apps/commands/cmd_332/strout.txt INFO
Note: The above is how Slider-Agent invokes the scripts. Its provided as a reference for developing the scripts themselves as well as a way to test/debug the scripts.
Structure of JSON formatted parameter¶
The parameters are organized as multi-layer name-value pairs.
{ "commandId": "Command Id as assigned by Slider", "command": "Command being executed", "commandType": "Type of command", "clusterName": "Name of the cluster", "appName": "Name of the app", "component": "Name of the component", "hostname": "Name of the host", "public_hostname": "FQDN of the host", "hostParams": { "host specific parameters common to all commands" }, "componentParams": { "component specific parameters, if any" }, "commandParams": { "command specific parameters, usually used in case of custom commands" }, "configurations": { "app-global-config": { }, "config-type-2": { }, "config-type-2": { } } }
Sample configuration parameters¶
While a script can access all the config parameters the key property bags are hostLevelParams
and configurations
.
{ "roleCommand": "START", "commandParams": { "record_config": "true", "service_package_folder": "${AGENT_WORK_ROOT}/work/app/definition/package", "script": "scripts/hbase_regionserver.py", "schema_version": "2.0", "command_timeout": "300", "script_type": "PYTHON" }, "componentName": "HBASE_REGIONSERVER", "hostname": "c6403.ambari.apache.org", "hostLevelParams": { "java_home": "/usr/jdk64/jdk1.7.0_45", "container_id": "container_1405048900371_0015_02_000003" }, "commandType": "EXECUTION_COMMAND", "clusterName": "cl1", "serviceName": "cl1", "role": "HBASE_REGIONSERVER", "taskId": 4, "public_hostname": "c6403.ambari.apache.org", "commandId": "4-1", "configurations": { "hbase-site": { "hbase.hstore.flush.retries.number": "120", "hbase.client.keyvalue.maxsize": "10485760", "hbase.hstore.compactionThreshold": "3", "hbase.rootdir": "hdfs://c6403.ambari.apache.org:8020/user/yarn/.slider/cluster/cl1/database/data", "hbase.regionserver.handler.count": "60", "hbase.regionserver.global.memstore.lowerLimit": "0.38", "hbase.hregion.memstore.block.multiplier": "2", "hbase.hregion.memstore.flush.size": "134217728", "hbase.superuser": "yarn", "hbase.zookeeper.property.clientPort": "2181", "hbase.regionserver.global.memstore.upperLimit": "0.4", "zookeeper.session.timeout": "30000", "hbase.tmp.dir": "/hadoop/yarn/local/usercache/yarn/appcache/application_1405048900371_0015/container_1405048900371_0015_02_000003/work/app/tmp", "hfile.block.cache.size": "0.40", "hbase.stagingdir": "hdfs://c6403.ambari.apache.org:8020/user/yarn/.slider/cluster/cl1/database/staging", "hbase.hregion.max.filesize": "10737418240", "hbase.regionserver.port": "0", "hbase.security.authentication": "simple", "hbase.defaults.for.version.skip": "true", "hbase.master.info.port": "52502", "hbase.zookeeper.quorum": "c6403.ambari.apache.org", "hbase.regionserver.info.port": "0", "zookeeper.znode.parent": "/services/slider/users/yarn/cl1", "hbase.hstore.blockingStoreFiles": "10", "hbase.hregion.majorcompaction": "86400000", "hbase.security.authorization": "false", "hbase.local.dir": "${hbase.tmp.dir}/local", "hbase.cluster.distributed": "true", "hbase.hregion.memstore.mslab.enabled": "true", "hbase.client.scanner.caching": "100", "hbase.zookeeper.useMulti": "true" }, "global": { "security_enabled": "false", "ganglia_server_port": "8667", "hbase_master_heapsize": "1024m", "app_root": "/hadoop/yarn/local/usercache/yarn/appcache/application_1405048900371_0015/container_1405048900371_0015_02_000003/app/install/hbase-0.98.3-hadoop2", "app_log_dir": "/hadoop/yarn/log/application_1405048900371_0015/container_1405048900371_0015_02_000003/app/log", "ganglia_server_host": "c6403.ambari.apache.org", "ganglia_server_id": "Application1", "hbase_regionserver_heapsize": "1024m", "user_group": "hadoop", "app_pid_dir": "/hadoop/yarn/local/usercache/yarn/appcache/application_1405048900371_0015/container_1405048900371_0015_02_000003/app/run", "app_install_dir": "/hadoop/yarn/local/usercache/yarn/appcache/application_1405048900371_0015/container_1405048900371_0015_02_000003/app/install", "app_user": "yarn" }, "hdfs-site": {}, "core-site": {} } }
Command scripts¶
A command script essentially implements commands. The basic structure of a script is as follows:
class HbaseMaster(Script): def install(self, env): ... def configure(self, env): ... def start(self, env): ... def stop(self, env): ... def status(self, env): ...
At this point, you are free to implement as you wish. Slider provides a rich library for basic operations needed for application commands. So the structure we suggest is:
- Create a
params.py
file to read the json config file into variables. This will allow you to provide initial validation, provide default values, or create complex values - Use the above parameters in your scripts
A params.py
file may be as follows:
from resource_management import * # server configurations config = Script.get_config() hbase_root = config['configurations']['global']['app_root'] conf_dir = format("{hbase_root}/conf") daemon_script = format("{hbase_root}/bin/hbase-daemon.sh") ...
Sample command script¶
In this example, hbase master command implementation is using the above parameter file and calling into several helper functions. Some are provided by Slider (e.g. install_package, check_process_status) and some are developed for HBase (e.g. habse_service called by start)
class HbaseMaster(Script): def install(self, env): self.install_packages(env) def configure(self, env): import params env.set_params(params) hbase(name='master') def start(self, env): import params env.set_params(params) self.configure(env) # for security hbase_service( 'master', action = 'start' ) def stop(self, env): import params env.set_params(params) hbase_service( 'master', action = 'stop' ) def status(self, env): import status_params env.set_params(status_params) pid_file = format("{pid_dir}/hbase-{hbase_user}-master.pid") check_process_status(pid_file)