#!/usr/bin/perl -w

=head1 NAME

    mk-zookeeper-files - создание файлов для пакета с zookeeper

=head1 DESCRIPTION

    config, init, директории
    мониторинг от ubic 

    если указан параметр servers=server1,server2,... делается конфиг для zookeeper с репликацией

=cut

use strict;
use warnings;

use SvnRelease::MkFiles;

my $mkfiles = SvnRelease::MkFiles->new(
    files => [
        {tmpl => 'zookeeper_cfg', file => "/etc/zookeeper/[% instance %]/zoo.cfg", },
        {tmpl => 'enviroment_cfg', file => "/etc/zookeeper/[% instance %]/environment", },
        {tmpl => 'log4j_cfg', file => "/etc/zookeeper/[% instance %]/log4j.properties", },

        {tmpl => 'zookeeper_init', file => "/etc/init/zookeeper-[% instance %].conf", },
        {tmpl => 'monrun_conf', file => "/etc/monrun/conf.d/zookeeper-[% instance %].conf", },

        {dir => '/opt/zookeeper.[% instance %]', owner => 'zookeeper:zookeeper', perm => 0755, },

        {dir => '/var/log/zookeeper.[% instance %]/', owner => 'zookeeper:zookeeper', perm => 0755, },

        {tmpl => 'bin_zk_cli', file => "/usr/bin/zk-cli-[% instance %]", perm => 0755, },
        {tmpl => 'bin_zk_check', file => "/usr/bin/zk-check-[% instance %]", perm => 0755, },

        {tmpl => 'debian_preinst', file => "/DEBIAN/preinst", perm => 0755, },
        {tmpl => 'debian_postinst', file => "/DEBIAN/postinst", perm => 0755, },
        ],
    templates_fh => \*DATA,
    substvars => {
        'zookeeper:Depends' => join(', ',
                                'zookeeper (>= 3.4)',
                                'python-zookeeper',
                                'netcat',
                                'upstart',
            ),
    },
    );

my ($instance, @dummy) = $mkfiles->parse_options("instance_name");
if (@dummy || $instance !~ /^[a-z0-9_\-]+$/) {
    $mkfiles->usage();
}

$mkfiles->{vars}->{instance} = $instance;
$mkfiles->{vars}->{port} ||= 2181;

$mkfiles->mk();


__DATA__
<< zookeeper_cfg
tickTime=2000
dataDir=/opt/zookeeper.[% instance %]/
clientPort=[% port %]
initLimit=5
syncLimit=2
[% IF max_connections.defined %]maxClientCnxns=[% max_connections %][% END %]

[% FOR server = servers.split(',') %]server.[% loop.count() %]=[% server %]:[% cluster_port || 2182 %]:[% election_port || 2183 %]
[% END %]

autopurge.purgeInterval=1
autopurge.snapRetainCount=8

# To avoid seeks ZooKeeper allocates space in the transaction log file in
# blocks of preAllocSize kilobytes. The default block size is 64M. One reason
# for changing the size of the blocks is to reduce the block size if snapshots
# are taken more often. (Also, see snapCount).
#preAllocSize=131072


<< enviroment_cfg
ZOOCFGDIR=/etc/zookeeper/[% instance %]

# seems, that log4j requires the log4j.properties file to be in the classpath
CLASSPATH="$ZOOCFGDIR:/usr/share/java/jline.jar:/usr/share/java/log4j-1.2.jar:/usr/share/java/xercesImpl.jar:/usr/share/java/xmlParserAPIs.jar:/usr/share/java/netty.jar:/usr/share/java/slf4j-api.jar:/usr/share/java/slf4j-log4j12.jar:/usr/share/java/zookeeper.jar"

ZOOCFG="$ZOOCFGDIR/zoo.cfg"
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
ZOO_LOG_DIR=/var/log/zookeeper.[% instance %]
#ZOO_LOG_FILE=zookeeper.log

USER=zookeeper
GROUP=zookeeper
PIDFILE=/var/run/zookeeper-[% instance %].pid

JAVA=/usr/bin/java
ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
JMXLOCALONLY=false
JAVA_OPTS="-Xms3072M \
    -Xmx8G \
    -Xloggc:$ZOO_LOG_DIR/zookeeper-gc.log \
    -XX:+UseGCLogFileRotation \
    -XX:NumberOfGCLogFiles=16 \
    -XX:GCLogFileSize=16M \
    -verbose:gc \
    -XX:+PrintGCTimeStamps \
    -XX:+PrintGCDateStamps \
    -XX:+PrintGCDetails \
    -XX:+PrintTenuringDistribution \
    -XX:+PrintGCApplicationStoppedTime \
    -XX:+PrintGCApplicationConcurrentTime \
    -XX:+PrintSafepointStatistics \
    -XX:+UseParNewGC \
    -XX:+UseConcMarkSweepGC \
    -XX:+CMSParallelRemarkEnabled"


<< log4j_cfg
# Format is "<default threshold> (, <appender>)+
# Example with rolling log file
#log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE

log4j.rootLogger=${zookeeper.root.logger}

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n

log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLINGFILE.Threshold=DEBUG
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/zookeeper.log
log4j.appender.ROLLINGFILE.Append=true

log4j.appender.ROLLINGFILE.MaxFileSize=1GB
log4j.appender.ROLLINGFILE.MaxBackupIndex=10

log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n

#log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.FILE.DatePattern='.'yyyy-ww

log4j.logger.org.apache.zookeeper=Warn
log4j.logger.org.apache.zookeeper.server=Debug
log4j.logger.org.apache.zookeeper.server.NIOServerCnxnFactory=Warn
log4j.logger.org.apache.zookeeper.server.ZooKeeperServer=Warn
log4j.logger.org.apache.zookeeper.server.NIOServerCnxn=Error
log4j.logger.org.apache.zookeeper.server.FinalRequestProcessor=Info
log4j.logger.org.apache.zookeeper.server.quorum.CommitProcessor=Info
log4j.logger.org.apache.zookeeper.server.persistence.FileTxnSnapLog=Info
log4j.logger.org.apache.zookeeper.server.DataTree=Info
log4j.logger.org.apache.zookeeper.server.quorum.Leader=Info
log4j.logger.org.apache.zookeeper.server.PrepRequestProcessor=Warn


<< zookeeper_init

description "Zookeeper for [% instance %]"

start on (local-filesystems and net-device-up IFACE!=lo)
respawn
respawn limit 100 10
limit as 20000000000 24000000000
limit nofile 65536 65536

script
    . /etc/zookeeper/[% instance %]/environment
    exec start-stop-daemon --start --chuid "$USER" --pidfile "$PIDFILE" --exec "$JAVA" -- \
            $JAVA_OPTS \
            -Dzookeeper.log.dir="$ZOO_LOG_DIR" \
            -Dzookeeper.root.logger="$ZOO_LOG4J_PROP" \
            -cp "$CLASSPATH" \
            -Dcom.sun.management.jmxremote \
            -Dcom.sun.management.jmxremote.local.only="$JMXLOCALONLY" \
            "$ZOOMAIN" "$ZOOCFG"
end script


<< monrun_conf
[zookeeper-[% instance %]]
execution_interval=60
execution_timeout=30
command=/usr/bin/zk-check-ppc 2>/dev/null
type=zookeeper


<< bin_zk_cli
#!/bin/bash

source /etc/zookeeper/[% instance %]/environment

set -x
exec $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
   -cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS org.apache.zookeeper.ZooKeeperMain "$@"


<< bin_zk_check
#!/usr/bin/env python2

import argparse
import zookeeper
from socket import getfqdn
from time import time


def main():
    parser = argparse.ArgumentParser(description='Check zookeeper instance by creating and deleting test node')
    parser.add_argument('--server', dest='server', type=str, default='127.0.0.1:[% port %]', action='store', help='server:port to connect')
    args=parser.parse_args()
    
    hostname = getfqdn().replace('.', '_')
    epoch = str(int(time()))
    node_path = '/zk_check_%s' % hostname

    zookeeper.set_debug_level(zookeeper.LOG_LEVEL_ERROR)
    
    zk = zookeeper.init(args.server)
    try:
        if not zookeeper.exists(zk, node_path) is not None:
            acl_all=[{'scheme': 'world', 'perms': 31, 'id': 'anyone'}]
            zookeeper.create(zk, node_path, epoch, acl_all)
        value, _ = zookeeper.get(zk, node_path)
        if value != epoch:
            raise Exception('Value saved to node does not coincide value read from node')
        zookeeper.delete(zk, node_path)
    except Exception, e:
        print '2; Failed to create and delete zookeeper node: %s' % str(e)
    else:
        zookeeper.close(zk)
        print '0; OK'


if __name__ == '__main__':
   main()


<< debian_preinst
#!/bin/bash -e

. /usr/share/debconf/confmodule

if ! getent group zookeeper >/dev/null; then
    addgroup --system zookeeper >/dev/null
fi

if ! getent passwd zookeeper >/dev/null; then
    adduser --system --disabled-login --ingroup zookeeper --home /home/zookeeper/ --gecos "System user for zookeeper" --shell /bin/bash zookeeper >/dev/null
fi


<< debian_postinst
#!/bin/bash -e

. /usr/share/debconf/confmodule

chown zookeeper: /opt/zookeeper.[% instance %]
chown zookeeper: /var/log/zookeeper.[% instance %]

if ! test -f /opt/zookeeper.[% instance %]/myid; then
    grep "=$(hostname -f):" /etc/zookeeper/[% instance %]/zoo.cfg | sed -r 's/server.([0-9]+).*/\1/' > /opt/zookeeper.[% instance %]/myid
fi


