Solr Cloud Docker Install
module.exports = header: 'Solr Cloud Docker Install', handler: ({options}) ->
tmp_dir = options.tmp_dir ?= "/var/tmp/ryba/solr"
options.build.dir = '/tmp/solr/build'
Dependencies
@call 'masson/core/krb5_client/wait', once: true, options.wait_krb5_client
@call 'ryba/zookeeper/server/wait', once: true, options.wait_zookeeper_server
@registry.register ['file', 'jaas'], 'ryba/lib/file_jaas'
Identities
Create user and groups for solr user.
@system.group header: "Group hadoop_group", options.hadoop_group
@system.group header: 'Group', options.group
@system.user header: 'User', options.user
Layout
@system.mkdir
target: options.user.home
uid: options.user.name
gid: options.group.name
@system.mkdir
directory: options.conf_dir
uid: options.user.name
gid: options.group.name
@system.mkdir
target: options.user.home
uid: options.user.name
gid: options.group.name
Kerberos
# @krb5.addprinc options.krb5.admin,
# unless_exists: options.spnego.keytab
# header: 'Kerberos SPNEGO'
# principal: options.spnego.principal
# randkey: true
# keytab: options.spnego.keytab
# gid: options.hadoop_group.name
# mode: 0o660
@system.execute
header: 'SPNEGO'
cmd: "su -l #{options.user.name} -c 'test -r #{options.spnego.keytab}'"
@krb5.addprinc options.krb5.admin,
header: 'Solr Super User'
principal: options.admin_principal
password: options.admin_password
randkey: true
uid: options.user.name
gid: options.group.name
@file.jaas
header: 'Solr JAAS'
target: "#{options.conf_dir}/solr-server.jaas"
content:
Client:
principal: options.principal
keyTab: options.keytab
useKeyTab: true
storeKey: true
useTicketCache: true
uid: options.user.name
gid: options.group.name
@krb5.addprinc options.krb5.admin,
header: 'Solr Server User'
principal: options.principal
keytab: options.keytab
randkey: true
uid: options.user.name
gid: options.group.name
Container
Ryba support installing solr from apache official release or HDP Search repos. Priority to docker pull function to get the solr container, else a tar should be prepared in the nikita cache dir.
@call header: 'Load Container', ->
exists = false
@docker.checksum
docker: options.swarm_conf
image: options.build.image
tag: options.version
, (err, status, checksum) ->
throw err if err
exists = checksum
@docker.pull
header: 'Pull container'
if: -> not exists
tag: options.build.image
version: options.version
code_skipped: 1
@file.download
unless: -> @status(-1) or @status(-2)
binary: true
header: 'Download container'
source: options.build.source
target: "#{tmp_dir}/solr.tar"
@docker.load
header: 'Load container to docker'
unless: -> @status(-3)
if_exists: "#{tmp_dir}/solr.tar"
source: "#{tmp_dir}/solr.tar"
docker: options.swarm_conf
User Limits
@system.limits
header: 'Ulimit'
user: options.user.name
, options.user.limits
SSL
@java.keystore_add
keystore: options.keystore.target
storepass: options.keystore.password
caname: "hadoop_root_ca"
key: "#{options.ssl.key.source}"
cert: "#{options.ssl.cert.source}"
keypass: options.keystore.password
name: options.fqdn
local: true
uid: options.user.name
gid: options.group.name
mode: 0o0755
@java.keystore_add
keystore: options.truststore.target
storepass: options.truststore.password
caname: "hadoop_root_ca"
cacert: "#{options.ssl.cacert.source}"
local: options.ssl.cacert.local
uid: options.user.name
gid: options.group.name
mode: 0o0755
@call
if: options.importCerts?
, (_, cb) ->
tmp_location = "/tmp/ryba_cacert_#{Date.now()}"
{truststore} = options
@each options.importCerts, ({options}, callback) ->
{source, local, name} = options.value
@file.download
header: 'download cacert'
source: source
target: "#{tmp_location}/cacert"
local: true
@java.keystore_add
header: "add cacert to #{name}"
keystore: truststore.target
storepass: truststore.password
caname: name
cacert: "#{tmp_location}/cacert"
@next callback
@system.remove
target: tmp_location
@next cb
Cluster Specific configuration
Here we loop through the clusters definition to write container specific file configuration like solr.in.sh or solr.xml.
{clusters, hosts, fqdn, conf_dir, krb5, user, group, iptables} = options
opts = options
@each clusters, ({options}, callback) ->
counter = 0
name = options.key
config = clusters[name] # get cluster config
config_host = config.config_hosts["#{fqdn}"] # get host config for the cluster
return callback() unless config_host?
config_host.env['SOLR_AUTHENTICATION_OPTS'] ?= ''
config_host.env['SOLR_AUTHENTICATION_OPTS'] += " -D#{k}=#{v} " for k, v of config_host.auth_opts
writes = for k,v of config_host.env
match: RegExp "^.*#{k}=.*$", 'mg'
replace: "#{k}=\"#{v}\" # RYBA DON'T OVERWRITE"
append: true
@tools.iptables
if: iptables
rules: [
{ chain: 'INPUT', jump: 'ACCEPT', dport: config.port, protocol: 'tcp', state: 'NEW', comment: "Solr Cluster #{name}" }
]
@krb5.addprinc krb5.admin,
header: 'Cluster admin principal'
principal: config.admin_principal
password: config.admin_password
randkey: true
uid: user.name
gid: group.name
@system.mkdir
header: 'Solr Cluster Configuration'
target: "#{conf_dir}/clusters/#{name}"
uid: user.name
gid: group.name
mode: 0o0750
@system.mkdir
header: 'Solr Cluster Log dir'
target: config.log_dir
uid: user.name
gid: group.name
mode: 0o0750
@system.mkdir
header: 'Solr Cluster Pid dir'
target: config.pid_dir
uid: user.name
gid: group.name
mode: 0o0750
@system.tmpfs
if_os: name: ['redhat','centos'], version: '7'
mount: config.pid_dir
uid: user.name
gid: group.name
perm: '0750'
@system.mkdir
header: 'Solr Cluster Data dir'
target: config.data_dir
mode: 0o0750
@system.chown
target: config.data_dir
uid: user.name
gid: group.name
mode: 0o0750
@file
header: 'Security config'
content: JSON.stringify config_host.security
target: "#{conf_dir}/clusters/#{name}/security.json"
uid: user.name
gid: group.name
mode: 0o0750
@file
source:"#{__dirname}/../resources/cloud_docker/docker_entrypoint.sh.j2"
target: "#{conf_dir}/clusters/#{name}/docker_entrypoint.sh"
context: opts
local: true
backup: true
uid: user.name
gid: group.name
mode: 0o0750
@file.render
source:"#{__dirname}/../resources/cloud_docker/zkCli.sh.j2"
target: "#{conf_dir}/clusters/#{name}/zkCli.sh"
context: opts
local: true
backup: true
uid: user.name
gid: group.name
mode: 0o0750
@file.render
header: 'Solr Environment'
source: "#{__dirname}/../resources/cloud/solr.ini.sh.j2"
target: "#{conf_dir}/clusters/#{name}/solr.in.sh"
context: opts
write: writes
local: true
backup: true
eof: true
uid: user.name
gid: group.name
mode: 0o0750
@call
unless: (config.docker_compose_version is '1') or (not config.depends_on)
shy: true
, ->
for node in [1..config.containers]
config.service_def["node_#{node}"]['depends_on'] = ["node_#{config.master_node}"] if node != config.master_node
@call
header: 'Solr xml config'
, ->
for host in config.hosts
root = builder.create('solr').dec '1.0', 'UTF-8', true
solrcloud = root.ele 'solrcloud'
solrcloud.ele 'str', {'name':'host'}, "#{fqdn}"
solrcloud.ele 'str', {'name':'hostPort'}, "#{config.port}"
solrcloud.ele 'str', {'name':'hostContext'}, '${hostContext:solr}'
solrcloud.ele 'bool', {'name':'genericCoreNodeNames'}, '${genericCoreNodeNames:true}'
solrcloud.ele 'str', {'name':'zkCredentialsProvider'}, "#{config_host.zk_opts.zkCredentialsProvider}"
solrcloud.ele 'str', {'name':'zkACLProvider'}, "#{config_host.zk_opts.zkACLProvider}"
solrcloud.ele 'int', {'name':'zkClientTimeout'}, '${zkClientTimeout:30000}'
solrcloud.ele 'int', {'name':'distribUpdateSoTimeout'}, '${distribUpdateSoTimeout:600000}'
solrcloud.ele 'int', {'name':'distribUpdateConnTimeout'}, '${distribUpdateConnTimeout:60000}'
solrcloud.ele 'str', {'name':'zkHost'}, "#{config_host['env']['ZK_HOST']}"
shardHandlerFactory = solrcloud.ele 'shardHandlerFactory', {'name':'shardHandlerFactory','class':'HttpShardHandlerFactory'}
shardHandlerFactory.ele 'int', {'name':'socketTimeout'}, '${socketTimeout:600000}'
shardHandlerFactory.ele 'int', {'name':'connTimeout'}, '${connTimeout:60000}'
@file
if: host is fqdn
header: 'Solr Config'
target: "#{conf_dir}/clusters/#{name}/solr.xml"
uid: user.name
gid: group.name
content: root.end pretty:true
mode: 0o0750
backup: true
eof: true
@file.render
if: host is fqdn
header: 'Log4j'
source: "#{__dirname}/../resources/log4j.properties.j2"
target: "#{conf_dir}/clusters/#{name}/log4j.properties"
context: options
local: true
@call
header: "Dockerfile"
, ->
dockerfile = null
switch config.docker_compose_version
when '1'
dockerfile = clusters[name].service_def
break;
when '2'
dockerfile =
version:'2'
services: clusters[name].service_def
break;
@call ->
@file.yaml
if: fqdn is config['master'] or not options.swarm_conf?
target: "#{conf_dir}/clusters/#{name}/docker-compose.yml"
content: dockerfile
uid: user.name
gid: group.name
mode: 0o0750
@docker.compose.up
header: 'Compose up through swarm'
if: fqdn is config['master'] and options.swarm_conf?
target: "#{conf_dir}/clusters/#{name}/docker-compose.yml"
@docker.compose.up
header: 'Compose up without swarm'
docker: options.docker
unless: options.swarm_conf?
services: "node_#{hosts.indexOf(fqdn)+1}"
target: "#{conf_dir}/clusters/#{name}/docker-compose.yml"
@next callback
Dependencies
path = require 'path'
mkcmd = require '../../lib/mkcmd'
builder = require 'xmlbuilder'