Ambari Server Install
See the Ambari documentation relative to Software Requirements before executing this module.
module.exports = header: 'Ambari Server Install', handler: ({options}) ->
Identities
By default, the "ambari-server" package does not create any identities.
@system.group header: 'Group', options.group
@system.group header: 'Group Hadoop', options.hadoop_group
@system.user header: 'User', options.user
IPTables
Service | Port | Proto | Parameter |
---|---|---|---|
Ambari Server | 8080 | tcp | HTTP Port |
Ambari Server | 8842 | tcp | HTTPS Port |
IPTables rules are only inserted if the parameter "iptables.action" is set to "start" (default value).
port = options.config[unless options.config['api.ssl'] then 'client.api.port' else 'client.api.ssl.port']
@tools.iptables
rules: [
{ chain: 'INPUT', jump: 'ACCEPT', dport: port, protocol: 'tcp', state: 'NEW', comment: "Ambari REST SSL" }
]
if: options.iptables
Package & Repository
Declare the Ambari custom repository. Install Ambari server package.
@service
header: 'Package'
name: 'ambari-server'
startup: true
@service
header: 'Mysql Connector'
name: 'mysql-connector-java'
if: options.db.engine is 'mysql'
Non-Root
@file
header: 'Sudo'
if: options.sudo
target: '/etc/sudoers.d/ambari_server'
content: """
# Ambari Commands
ambari ALL=(ALL) NOPASSWD:SETENV: /bin/mkdir -p /etc/security/keytabs, /bin/chmod * /etc/security/keytabs/*.keytab, /bin/chown * /etc/security/keytabs/*.keytab, /bin/chgrp * /etc/security/keytabs/*.keytab, /bin/rm -f /etc/security/keytabs/*.keytab, /bin/cp -p -f /var/lib/ambari-server/data/tmp/* /etc/security/keytabs/*.keytab
Defaults exempt_group = ambari
Defaults !env_reset,env_delete-=PATH
Defaults: ambari !requiretty
"""
@system.remove
header: 'Clean Sudo'
unless: options.sudo
target: '/etc/sudoers.d/ambari_server'
Database
Prepare the Ambari Database.
@call header: 'DB', ->
Wait for database to listen
@call 'ryba/commons/db_admin/wait', once: true, options.wait_db_admin
Password is stored inside a file which location is referenced by the property "server.jdbc.user.passwd" in the configuration file. The permissione "660" match the ones generated by "ambari-server setup".
@file
header: 'Stash Password'
unless: options.master_key
target: options.config['server.jdbc.user.passwd']
content: options.db.password
backup: true
mode: 0o0640
# Note, for same reason, `ambari-server setup-security` keep re-generating
# the stashed password file even if it uses the encrypted database located
# in "/var/lib/ambari-sever/keys".
# @system.remove
# header: 'Clean Stash Password'
# if: options.master_key
# target: '/etc/ambari-server/conf/password.dat'
Create the database hosting the Ambari data with restrictive user permissions.
@db.user options.db, database: null,
header: 'User'
if: options.db.engine in ['mysql', 'mariadb', 'postgresql']
@db.database options.db,
header: 'Database'
user: options.db.username
if: options.db.engine in ['mysql', 'mariadb', 'postgresql']
@db.schema options.db,
header: 'Schema'
if: options.db.engine is 'postgresql'
schema: options.db.schema or options.db.database
database: options.db.database
owner: options.db.username
Load the database with initial data
switch options.db.engine
when 'mysql', 'mariadb'
load = db.cmd(options.db, null) + '< /var/lib/ambari-server/resources/Ambari-DDL-MySQL-CREATE.sql'
created = db.cmd(options.db, 'show tables') + '| grep clusters'
when 'postgresql'
load = db.cmd(options.db, null) + '< /var/lib/ambari-server/resources/Ambari-DDL-Postgres-CREATE.sql'
created = db.cmd(options.db, null) + 'show tables | grep clusters'
@system.execute
header: 'Init'
cmd: load
unless_exec: created
Hive DB
@call header: 'Hive DB', if: !!options.db_hive, ->
@db.user options.db_hive, database: null,
header: 'User'
if: options.db_hive.engine in ['mysql', 'mariadb', 'postgresql']
@db.database options.db_hive,
header: 'Database'
user: options.db_hive.username
if: options.db_hive.engine in ['mysql', 'mariadb', 'postgresql']
@db.schema options.db_hive,
header: 'Schema'
if: options.db_hive.engine is 'postgresql'
schema: options.db_hive.schema or options.db_hive.database
database: options.db_hive.database
owner: options.db_hive.username
Oozie DB
@call header: 'Oozie DB', if: !!options.db_oozie, ->
@db.user options.db_oozie, database: null,
header: 'User'
if: options.db_oozie.engine in ['mysql', 'mariadb', 'postgresql']
@db.database options.db_oozie,
header: 'Database'
user: options.db_oozie.username
if: options.db_oozie.engine in ['mysql', 'mariadb', 'postgresql']
@db.schema options.db_oozie,
header: 'Schema'
if: options.db_oozie.engine is 'postgresql'
schema: options.db_oozie.schema or options.db_oozie.database
database: options.db_oozie.database
owner: options.db_oozie.username
Ranger DB
@call header: 'Ranger DB', if: !!options.db_ranger, ->
@db.user options.db_ranger, database: null,
header: 'User'
if: options.db_ranger.engine in ['mysql', 'mariadb', 'postgresql']
@db.database options.db_ranger,
header: 'Database'
user: options.db_ranger.username
if: options.db_ranger.engine in ['mysql', 'mariadb', 'postgresql']
@db.schema options.db_ranger,
header: 'Schema'
if: options.db_ranger.engine is 'postgresql'
schema: options.db_ranger.schema or options.db_ranger.database
database: options.db_ranger.database
owner: options.db_ranger.username
Hive DB
@call header: 'Hive DB', if: !!options.db_hive, ->
@db.user options.db_hive, database: null,
header: 'User'
if: options.db_hive.engine in ['mysql', 'mariadb', 'postgresql']
@db.database options.db_hive,
header: 'Database'
user: options.db_hive.username
if: options.db_hive.engine in ['mysql', 'mariadb', 'postgresql']
@db.schema options.db_hive,
header: 'Schema'
if: options.db_hive.engine is 'postgresql'
schema: options.db_hive.schema or options.db_hive.database
database: options.db_hive.database
owner: options.db_hive.username
Oozie DB
@call header: 'Oozie DB', if: !!options.db_oozie, ->
@db.user options.db_oozie, database: null,
header: 'User'
if: options.db_oozie.engine in ['mysql', 'mariadb', 'postgresql']
@db.database options.db_oozie,
header: 'Database'
user: options.db_oozie.username
if: options.db_oozie.engine in ['mysql', 'mariadb', 'postgresql']
@db.schema options.db_oozie,
header: 'Schema'
if: options.db_oozie.engine is 'postgresql'
schema: options.db_oozie.schema or options.db_oozie.database
database: options.db_oozie.database
owner: options.db_oozie.username
Ranger DB
@call header: 'Ranger DB', if: !!options.db_ranger, ->
@db.user options.db_ranger, database: null,
header: 'User'
if: options.db_ranger.engine in ['mysql', 'mariadb', 'postgresql']
@db.database options.db_ranger,
header: 'Database'
user: options.db_ranger.username
if: options.db_ranger.engine in ['mysql', 'mariadb', 'postgresql']
@db.schema options.db_ranger,
header: 'Schema'
if: options.db_ranger.engine is 'postgresql'
schema: options.db_ranger.schema or options.db_ranger.database
database: options.db_ranger.database
owner: options.db_ranger.username
Configuration
Merge used defined configuration. This could be used to set up LDAP or Active Directory Authentication. The permissions "644" are the ones generated by the "ambari-server setup" command.
@file.properties
header: 'Config'
target: "#{options.conf_dir}/ambari.properties"
content: options.config
merge: true
comment: true
backup: true
mode: 0o0644
Upload SSL Cert & Key
Upload and register the SSL certificate and private key respectively defined by the "ssl.cert" and "ssl.key".
The public certificate is generated with the same permission and ownership as
with the ambari-server setup-security
command: user "root", group "ambari"
and mode "644".
Restrictive ownership and permission are enforced on the private key. We might want to move it into a different location (eg "/etc/security/certs") as Ambari will store and work on a copy.
@call header: 'SSL', ->
@file
header: 'Cert'
source: options.ssl.cert.source
local: options.ssl.cert.local
target: "#{options.conf_dir}/cert.pem"
uid: 'root'
gid: options.group.name
mode: 0o0644
@file
header: 'Key'
source: options.ssl.key.source
local: options.ssl.key.local
target: "#{options.conf_dir}/key.pem"
mode: 0o0600
@file
header: 'CACert'
source: options.ssl.cacert.source
local: options.ssl.cacert.local
target: "#{options.conf_dir}/cacert.pem"
mode: 0o0644
@java.keystore_add
keystore: "#{options.truststore.target}"
storepass: "#{options.truststore.password}"
caname: "#{options.truststore.caname}"
cacert: "#{options.conf_dir}/cacert.pem"
JAAS
Note, Ambari will change ownership to root.
@krb5.addprinc options.krb5.admin,
header: 'JAAS'
if: options.jaas?.enabled
principal: options.jaas.principal.replace '_HOST', options.fqdn
keytab: options.jaas.keytab
randkey: true
uid: 'root'
gid: options.group.name
mode: 0o660
MPack
for name, mpack of options.mpacks
mpack.target ?= "/var/tmp/#{path.basename mpack.source}"
mpack.purge ?= true
@file.download
header: "Download #{name}"
if: mpack.enabled
source: mpack.source
target: mpack.target
@system.execute
header: "Register #{name}"
if: mpack.enabled
unless_exists: "/var/lib/ambari-server/resources/mpacks/#{path.basename mpack.source, '.tar.gz'}"
cmd: """
yes | ambari-server install-mpack \
--mpack=#{mpack.target} \
#{if mpack.purge then '--purge' else ''} --verbose
"""
Setup
Password encryption is activated if the property "master_key" is configured. By default the passwords to access the Ambari database and the LDAP server are stored in a plain text configuration file. if Password encryption is activated, Ambari will store information inside "/var/lib/ambari-server/keys".
Be carefull, notes from Ambari 2.4.2:
Options "jdbc-db" and "jdbc-driver" prevent the setup script from modifying the properties file.
Option "cluster-name" does nothing
@call header: 'Setup', -> props = {} # @call (options, callback) -> # ssh = @ssh options.ssh # properties ssh, '/etc/ambari-server/conf/ambari.properties', {}, (err, data) -> # throw err if err # for k, v of data # props[k] ?= {} # props[k].org = v # callback() @system.execute shy: true cmd: """ ambari-server setup \ -s \ -j #{options.java_home} \ --database=#{if options.db.engine in ['mysql','mariadb'] then 'mysql' else options.db.engine } \ --databasehost=#{options.db.host} \ --databaseport=#{options.db.port} \ --databasename=#{options.db.database} \ --databaseusername=#{options.db.username} \ --databasepassword=#{options.db.password} \ --enable-lzo-under-gpl-license ambari-server setup \ --jdbc-db=mysql \ --jdbc-driver=/usr/share/java/mysql-connector-java.jar [ -n "#{options.master_key}" ] && ambari-server setup-security \ --security-option=encrypt-passwords \ --master-key=#{options.master_key} \ --master-key-persist=true # --cluster-name=#{options.cluster_name} """ @system.execute # if: options.config['api.ssl'] is 'true' shy: true cmd: """ ambari-server setup-security \ --security-option=setup-https \ --api-ssl=#{options.config['api.ssl']} \ --api-ssl-port=#{options.config['client.api.ssl.port']} \ --pem-password= \ --import-cert-path="#{options.conf_dir}/cert.pem" \ --import-key-path="#{options.conf_dir}/key.pem" """ @system.execute shy: true cmd: """ ambari-server setup-security \ --security-option=setup-truststore \ --truststore-path=#{options.truststore.target} \ --truststore-type=#{options.truststore.type} \ --truststore-password=#{options.truststore.password} \ --truststore-reconfigure """ @system.execute shy: true if: options.jaas?.enabled cmd: """ ambari-server setup-security \ --security-option=setup-kerberos-jaas \ --jaas-principal="#{options.jaas?.principal}" \ --jaas-keytab="#{options.jaas?.keytab}" """ # @call (_, callback) -> # ssh = @ssh options.ssh # properties ssh, '/etc/ambari-server/conf/ambari.properties', {}, (err, data) -> # throw err if err # for k, v of data # props[k] ?= {} # props[k].new = v # callback() @call (_, callback) -> status = false for k, v of props if v.org isnt v.new @log message: "Option #{k} was #{JSON.stringify v.org} and is now #{JSON.stringify v.new}", level: 'INFO', module: 'ryba/lib/file/properties' unless v.org is v.new status = true callback null, status
Start
Start the service or restart it if there were any changes.
@service
header: 'Start'
name: 'ambari-server'
state: ['started', 'restarted']
if: -> @status()
@call 'ryba/ambari/server/wait', once: true, options.wait
Admin Credentials
checkurl = url.format
protocol: unless options.config['api.ssl'] then 'http' else 'https'
hostname: options.fqdn
port: options.config[unless options.config['api.ssl'] then 'client.api.port' else 'client.api.ssl.port']
pathname: '/api/v1/clusters'
changeurl = url.format
protocol: unless options.config['api.ssl'] then 'http' else 'https'
hostname: options.fqdn
port: options.config[unless options.config['api.ssl'] then 'client.api.port' else 'client.api.ssl.port']
pathname: '/api/v1/users/admin'
cred = "admin:#{options.current_admin_password}"
json = JSON.stringify "Users":
"user_name": "admin"
"password": "#{options.admin_password}"
"old_password": "#{options.current_admin_password}"
@system.execute
header: 'Admin Credentials'
if_exec: """
curl -f -k -u #{cred} #{checkurl}
"""
cmd: """
curl -f -k -i -u #{cred} -H "X-Requested-By: ambari" -X PUT -d '#{json}' #{changeurl}
"""
Dependencies
path = require 'path'
url = require 'url'
misc = require '@nikitajs/core/lib/misc'
db = require '@nikitajs/core/lib/misc/db'
properties = require '@nikitajs/core/lib/file/properties/read'