BIGTOP-732. Support running multiple HBase region servers

Project: http://git-wip-us.apache.org/repos/asf/bigtop/repo
Commit: http://git-wip-us.apache.org/repos/asf/bigtop/commit/2fc2307c
Tree: http://git-wip-us.apache.org/repos/asf/bigtop/tree/2fc2307c
Diff: http://git-wip-us.apache.org/repos/asf/bigtop/diff/2fc2307c

Branch: refs/heads/master
Commit: 2fc2307c743250146d30a6a81b4f1581eac2076e
Parents: a353721
Author: Sean Mackrory <[email protected]>
Authored: Thu Apr 18 13:46:13 2013 -0700
Committer: Roman Shaposhnik <[email protected]>
Committed: Wed May 1 17:51:57 2013 -0700

----------------------------------------------------------------------
 bigtop-packages/src/common/hbase/hbase.default     |    7 +
 .../src/common/hbase/regionserver-init.d.tpl       |  412 +++++++++++++++
 .../src/deb/hbase/install_init_scripts.sh          |    9 +-
 bigtop-packages/src/deb/hbase/rules                |    4 +-
 bigtop-packages/src/rpm/hbase/SPECS/hbase.spec     |   18 +-
 5 files changed, 442 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bigtop/blob/2fc2307c/bigtop-packages/src/common/hbase/hbase.default
----------------------------------------------------------------------
diff --git a/bigtop-packages/src/common/hbase/hbase.default 
b/bigtop-packages/src/common/hbase/hbase.default
index 53dee46..3371a2b 100644
--- a/bigtop-packages/src/common/hbase/hbase.default
+++ b/bigtop-packages/src/common/hbase/hbase.default
@@ -17,3 +17,10 @@ export HBASE_PID_DIR="/var/run/hbase"
 export HBASE_LOG_DIR="/var/log/hbase"
 export HBASE_IDENT_STRING=hbase
 export HBASE_THRIFT_MODE="-nonblocking"
+
+# Up to 100 region servers can be run on a single host by specifying offsets
+# here or as CLI args when using init scripts. Each offset identifies an
+# instance and is used to determine the network ports it uses. Each instance
+# will have have its own log and pid files.
+#
+# REGIONSERVER_OFFSETS="1 2 3"

http://git-wip-us.apache.org/repos/asf/bigtop/blob/2fc2307c/bigtop-packages/src/common/hbase/regionserver-init.d.tpl
----------------------------------------------------------------------
diff --git a/bigtop-packages/src/common/hbase/regionserver-init.d.tpl 
b/bigtop-packages/src/common/hbase/regionserver-init.d.tpl
new file mode 100644
index 0000000..8f45eb6
--- /dev/null
+++ b/bigtop-packages/src/common/hbase/regionserver-init.d.tpl
@@ -0,0 +1,412 @@
+#! /bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is used to run multiple instances of certain HBase daemons using 
init scripts.
+# It replaces the local-regionserver.sh and local-master.sh scripts for Bigtop 
packages.
+# By default, this script runs a single daemon normally. If offsets are 
provided, additional
+# daemons are run, identified by the offset in log and pid files, and 
listening on the default
+# port + the offset. Offsets can be provided as arguments when invoking init 
scripts directly:
+#
+#     /etc/init.d/hbase-@HBASE_DAEMON@ start 1 2 3 4
+#
+# or you can list the offsets to run in /etc/init.d/@HBASE_DAEMON@_offsets:
+#
+#    echo "@HBASE_DAEMON@_OFFSETS='1 2 3 4' >> /etc/default/hbase"
+#    sudo service hbase-$HBASE_DAEMON@ start
+#
+# Offsets specified on the command-line always override the offsets file. If 
no offsets are
+# specified on the command-line when stopping or restarting daemons, all 
running instances of the
+# daemon are stopped (regardless of the contents of the offsets file).
+
+# chkconfig: @CHKCONFIG@
+# description: Summary: HBase is the Hadoop database. Use it when you need 
random, realtime read/write access to your Big Data. This project's goal is the 
hosting of very large tables -- billions of rows X millions of columns -- atop 
clusters of commodity hardware.
+# processname: HBase
+#
+### BEGIN INIT INFO
+# Provides:          hbase-@HBASE_DAEMON@
+# Required-Start:    $network $local_fs $remote_fs
+# Required-Stop:     $remote_fs
+# Should-Start:      $named
+# Should-Stop:
+# Default-Start:     @INIT_DEFAULT_START@
+# Default-Stop:      @INIT_DEFAULT_STOP@
+# Short-Description: Hadoop HBase @HBASE_DAEMON@ daemon
+### END INIT INFO
+
+. /etc/default/hadoop
+. /etc/default/hbase
+
+# Autodetect JAVA_HOME if not defined
+. /usr/lib/bigtop-utils/bigtop-detect-javahome
+
+# Our default HBASE_HOME, HBASE_PID_DIR and HBASE_CONF_DIR
+export HBASE_HOME=${HBASE_HOME:-/usr/lib/hbase}
+export HBASE_PID_DIR=${HBASE_PID_DIR:-/var/run/hbase}
+export HBASE_LOG_DIR=${HBASE_LOG_DIR:-/var/log/hbase}
+
+install -d -m 0755 -o hbase -g hbase ${HBASE_PID_DIR}
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON_SCRIPT=$HBASE_HOME/bin/hbase-daemon.sh
+NAME=hbase-@HBASE_DAEMON@
+DESC="Hadoop HBase @HBASE_DAEMON@ daemon"
+PID_FILE=$HBASE_PID_DIR/hbase-hbase-@[email protected]
+CONF_DIR=/etc/hbase/conf
+
+DODTIME=3                   # Time to wait for the server to die, in seconds
+                            # If this value is set too low you might not
+                            # let some servers to die gracefully and
+                            # 'restart' will not work
+
+UPPERCASE_HBASE_DAEMON=$(echo @HBASE_DAEMON@ | tr '[:lower:]' '[:upper:]')
+
+ALL_OFFSET_DAEMONS_RUNNING=0
+SOME_OFFSET_DAEMONS_FAILING=1
+NO_OFFSET_DAEMONS_RUNNING=2
+INVALID_OFFSETS_PROVIDED=3
+
+# These limits are not easily configurable - they are enforced by HBase
+if [ "@HBASE_DAEMON@" == "master" ] ; then
+    FIRST_PORT=60000
+    FIRST_INFO_PORT=60010
+    OFFSET_LIMIT=10
+elif [ "@HBASE_DAEMON@" == "regionserver" ] ; then
+    FIRST_PORT=60200
+    FIRST_INFO_PORT=60300
+    OFFSET_LIMIT=100
+fi
+
+validate_offsets() {
+    for OFFSET in $1; do
+        if [[ ! $OFFSET =~ ^((0)|([1-9][0-9]{0,2}))$ ]]; then
+            echo "ERROR: All offsets must be positive integers (no leading 
zeros, max $OFFSET_LIMIT)"
+            exit $INVALID_OFFSETS_PROVIDED
+        fi
+        if [ ${OFFSET} -lt 0 ] ; then
+            echo "ERROR: Cannot start @HBASE_DAEMON@ with negative offset" >&2
+            exit $INVALID_OFFSETS_PROVIDED
+        fi
+        if [ ${OFFSET} -ge ${OFFSET_LIMIT} ] ; then
+            echo "ERROR: Cannot start @HBASE_DAEMON@ with offset higher than 
$OFFSET_LIMIT" >&2
+            exit $INVALID_OFFSETS_PROVIDED
+        fi
+    done
+}
+
+offset_pidfile() {
+    echo $HBASE_PID_DIR/hbase-hbase-$1-@[email protected]
+}
+
+OFFSETS_FROM_CLI="${*:2}"
+validate_offsets "$OFFSETS_FROM_CLI"
+if [ -n "$(eval echo \${${UPPERCASE_HBASE_DAEMON}_OFFSETS})" ] ; then
+    OFFSETS_FROM_DEFAULT="$(eval echo \${${UPPERCASE_HBASE_DAEMON}_OFFSETS})"
+    validate_offsets "$OFFSETS_FROM_DEFAULT"
+fi
+OFFSET_PID_FILES="`ls $HBASE_PID_DIR/hbase-hbase-*-@[email protected] 
2>/dev/null`"
+if [ -n "$OFFSET_PID_FILES" ] ; then
+    OFFSETS_FROM_PIDS=`echo "$OFFSET_PID_FILES" | sed 
"s#$HBASE_PID_DIR/hbase-hbase-##" | sed "s#-.*##"`
+fi
+
+multi_hbase_daemon_check_pidfiles() {
+  if [ -z "$OFFSETS_FROM_PIDS" ] ; then
+    return $NO_OFFSET_DAEMONS_RUNNING
+  fi
+  if [ -n "$OFFSETS_FROM_CLI" ] ; then
+    OFFSETS="$OFFSETS_FROM_CLI"
+  else
+    OFFSETS="$OFFSETS_FROM_PIDS"
+  fi
+
+  RESULT=$ALL_OFFSET_DAEMONS_RUNNING
+  for OFFSET in $OFFSETS; do
+    echo -n "HBase @HBASE_DAEMON@ $OFFSET: "
+    if hbase_check_pidfile `offset_pidfile $OFFSET` ; then
+      echo "running"
+    else
+      echo "not running"
+      RESULT=$SOME_OFFSET_DAEMONS_FAILING
+    fi
+  done
+  return $RESULT
+}
+
+multi_hbase_daemon_stop_pidfiles() {
+  if [ -z "$OFFSETS_FROM_PIDS" ] ; then
+    return $NO_OFFSET_DAEMONS_RUNNING
+  fi
+  if [ -n "$OFFSETS_FROM_CLI" ] ; then
+    OFFSETS="$OFFSETS_FROM_CLI"
+  else
+    OFFSETS="$OFFSETS_FROM_PIDS"
+  fi
+
+  RESULT=$NO_OFFSET_DAEMONS_RUNNING
+  for OFFSET in $OFFSETS; do
+    echo -n "Forcefully stopping HBase @HBASE_DAEMON@ $OFFSET: "
+    PID_FILE=`offset_pidfile $OFFSET`
+    hbase_stop_pidfile $PID_FILE
+    if hbase_check_pidfile $PID_FILE ; then
+      echo "ERROR."
+    else
+      echo "OK."
+      rm -f $PID_FILE
+    fi
+  done
+  return $RESULT
+}
+
+# Starts and stops multiple instances of HBase daemons
+multi_hbase_daemon() {
+    COMMAND=$1
+    OFFSETS="$OFFSETS_FROM_CLI"
+    if [ "$COMMAND" == "start" ] ; then
+        ACTION="Starting"
+        RUNNING="OK"
+        STOPPED="ERROR"
+        if [ -z "$OFFSETS_FROM_CLI" ] ; then
+            OFFSETS="$OFFSETS_FROM_DEFAULT"
+        fi
+    elif [ "$COMMAND" == "stop" ] ; then
+        ACTION="Stopping"
+        RUNNING="ERROR"
+        STOPPED="OK"
+        if [ -z "$OFFSETS_FROM_CLI" ] ; then
+            OFFSETS="$OFFSETS_FROM_PIDS"
+        fi
+    else
+        echo "ERROR: Illegal command: $COMMAND"
+        exit 1
+    fi
+
+    export HBASE_${UPPERCASE_HBASE_DAEMON}_OPTS=" "
+
+    for OFFSET in ${OFFSETS} ; do
+        echo -n "$ACTION @HBASE_DAEMON@ daemon $OFFSET: "
+        export HBASE_IDENT_STRING="hbase-${OFFSET}"
+        
LOG_FILE="$HBASE_LOG_DIR/hbase-$HBASE_IDENT_STRING-@HBASE_DAEMON@-$HOSTNAME.pid"
+        PID_FILE="$HBASE_PID_DIR/hbase-$HBASE_IDENT_STRING-@[email protected]"
+        HBASE_MULTI_ARGS="-D hbase.@[email protected]=`expr ${FIRST_PORT} + 
$OFFSET` \
+                          -D hbase.@[email protected]=`expr 
${FIRST_INFO_PORT} + ${OFFSET}`"
+        hbase_check_pidfile $PID_FILE
+        STATUS=$?
+        if [[ "$STATUS" == "0" && "$COMMAND" == "start" ]] ; then
+            echo "Already running"
+            continue
+        elif [[ "$STATUS" != "0" && "$COMMAND" == "stop" ]] ; then
+            rm -f $PID_FILE
+            echo "Already stopped"
+            continue
+        fi
+        su -s /bin/bash hbase -c "${DAEMON_SCRIPT} ${COMMAND} regionserver 
${HBASE_MULTI_ARGS} >> ${LOG_FILE}"
+        if [[ "$COMMAND" == "stop" ]] ; then
+            rm -f $PID_FILE
+        fi
+        if hbase_check_pidfile $PID_FILE ; then
+            echo "$RUNNING"
+        else
+            echo "$STOPPED"
+        fi
+    done
+    return 0
+}
+
+# Checks if the given pid represents a live process.
+# Returns 0 if the pid is a live process, 1 otherwise
+hbase_is_process_alive() {
+  local pid="$1"
+  ps -fp $pid | grep $pid | grep @HBASE_DAEMON@ > /dev/null 2>&1
+}
+
+# Check if the process associated to a pidfile is running.
+# Return 0 if the pidfile exists and the process is running, 1 otherwise
+hbase_check_pidfile() {
+  local pidfile="$1" # IN
+  local pid
+
+  pid=`cat "$pidfile" 2>/dev/null`
+  if [ "$pid" = '' ]; then
+    # The file probably does not exist or is empty. 
+    return 1
+  fi
+
+  set -- $pid
+  pid="$1"
+
+  hbase_is_process_alive $pid
+}
+
+# Kill the process associated to a pidfile
+hbase_stop_pidfile() {
+   local pidfile="$1" # IN
+   local pid
+
+   pid=`cat "$pidfile" 2>/dev/null`
+   if [ "$pid" = '' ]; then
+      # The file probably does not exist or is empty. Success
+      return 0
+   fi
+
+   set -- $pid
+   pid="$1"
+
+   # First try the easy way
+   if hbase_process_kill "$pid" 15; then
+      rm $pidfile
+      return 0
+   fi
+
+   # Otherwise try the hard way
+   if hbase_process_kill "$pid" 9; then
+      rm $pidfile
+      return 0
+   fi
+
+   return 1
+}
+
+hbase_process_kill() {
+    local pid="$1"    # IN
+    local signal="$2" # IN
+    local second
+
+    kill -$signal $pid 2>/dev/null
+
+   # Wait a bit to see if the dirty job has really been done
+    for second in 0 1 2 3 4 5 6 7 8 9 10; do
+        if hbase_is_process_alive "$pid"; then
+         # Success
+            return 0
+        fi
+
+        sleep 1
+    done
+
+   # Timeout
+    return 1
+}
+
+start() {
+    if [ -n "${OFFSETS_FROM_CLI}${OFFSETS_FROM_DEFAULT}" ] ; then
+        if hbase_check_pidfile $PID_FILE ; then
+            echo "$NAME has already been started - cannot start other 
@HBASE_DAEMON@ daemons."
+            exit 1
+        fi
+        multi_hbase_daemon "start"
+        exit $?
+    fi
+    multi_hbase_daemon_check_pidfiles > /dev/null
+    if [ "$?" != "$NO_OFFSET_DAEMONS_RUNNING" ] ; then
+      echo "Cannot start $NAME - other @HBASE_DAEMON@ daemons have already 
been started."
+      exit 1
+    fi
+    echo -n "Starting $DESC: "
+    su -s /bin/sh hbase -c "$DAEMON_SCRIPT start @HBASE_DAEMON@"
+    if hbase_check_pidfile $PID_FILE ; then
+        echo "$NAME."
+    else
+        echo "ERROR."
+    fi
+}
+stop() {
+    if [ -n "${OFFSETS_FROM_CLI}${OFFSETS_FROM_PIDS}" ] ; then
+        multi_hbase_daemon "stop"
+        return "$?"
+    fi
+
+    echo -n "Stopping $DESC: "
+    su -s /bin/sh hbase -c "$DAEMON_SCRIPT stop @HBASE_DAEMON@"
+    if hbase_check_pidfile $PID_FILE ; then
+        echo "ERROR."
+    else
+        echo "$NAME."
+    fi
+}
+
+force_stop() {
+    MULTI_HBASE_DAEMON_STATUS_TEXT=`multi_hbase_daemon_check_pidfiles`
+    MULTI_HBASE_DAEMON_STATUS=$?
+    if [ "$MULTI_HBASE_DAEMON_STATUS" == "$NO_OFFSET_DAEMONS_RUNNING" ] ; then
+        echo -n "Forcefully stopping $DESC: "
+        hbase_stop_pidfile $PID_FILE
+        if hbase_check_pidfile $PID_FILE ; then
+            echo " ERROR."
+        else
+            echo "$NAME."
+        fi
+    else
+        multi_hbase_daemon_stop_pidfiles
+    fi
+}
+
+force_reload() {
+  # check wether $DAEMON is running. If so, restart
+  hbase_check_pidfile $PID_FILE && $0 restart $OFFSETS_FROM_CLI
+}
+
+restart() {
+    echo -n "Restarting $DESC: "
+    stop
+    [ -n "$DODTIME" ] && sleep $DODTIME
+    $0 start $OFFSETS_FROM_CLI
+}
+
+status() {
+    MULTI_HBASE_DAEMON_STATUS_TEXT=`multi_hbase_daemon_check_pidfiles`
+    MULTI_HBASE_DAEMON_STATUS=$?
+    if [ "$MULTI_HBASE_DAEMON_STATUS" == "$NO_OFFSET_DAEMONS_RUNNING" ] ; then
+        echo -n "$NAME is "
+        if hbase_check_pidfile $PID_FILE ;  then
+            echo "running"
+        else
+            echo "not running."
+            exit 1
+        fi
+    else
+        IFS=''
+        echo $MULTI_HBASE_DAEMON_STATUS_TEXT
+        exit $MULTI_HBAE_DAEMONS_STATUS
+    fi
+}
+
+case "$1" in
+  start)
+        start
+  ;;
+  stop)
+        stop
+  ;;
+  force-stop)
+        force_stop
+  ;;
+  force-reload)
+        force_reload
+  ;;
+  restart)
+        restart
+  ;;
+  status)
+        status
+    ;;
+  *)
+  N=/etc/init.d/$NAME
+  echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
+  exit 1
+  ;;
+esac
+
+exit 0

http://git-wip-us.apache.org/repos/asf/bigtop/blob/2fc2307c/bigtop-packages/src/deb/hbase/install_init_scripts.sh
----------------------------------------------------------------------
diff --git a/bigtop-packages/src/deb/hbase/install_init_scripts.sh 
b/bigtop-packages/src/deb/hbase/install_init_scripts.sh
index f60059c..1f3c151 100755
--- a/bigtop-packages/src/deb/hbase/install_init_scripts.sh
+++ b/bigtop-packages/src/deb/hbase/install_init_scripts.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -27,6 +27,13 @@ for node in master regionserver rest thrift ; do
     service_pkgdir=debian/$SRC_PKG-$node
     debdir=$service_pkgdir/DEBIAN
     template="debian/service-init.d.tpl"
+    if [ "$node" == "regionserver" ] ; then
+        # Region servers start from a different template that allows
+        # them to run multiple concurrent instances of the daemon
+        template="debian/regionserver-init.d.tpl"
+        sed -i -e "s|@INIT_DEFAULT_START@|2 3 4 5|" $template
+        sed -i -e "s|@INIT_DEFAULT_STOP@|0 1 6|" $template
+    fi
 
     mkdir -p $service_pkgdir/etc/init.d/ $debdir
     sed -e "s|@HBASE_DAEMON@|$node|" -e "s|@CHKCONFIG@|$chkconfig|" $template 
> $service_pkgdir/etc/init.d/$SRC_PKG-$node

http://git-wip-us.apache.org/repos/asf/bigtop/blob/2fc2307c/bigtop-packages/src/deb/hbase/rules
----------------------------------------------------------------------
diff --git a/bigtop-packages/src/deb/hbase/rules 
b/bigtop-packages/src/deb/hbase/rules
index 9a6ddc8..9c8f68a 100755
--- a/bigtop-packages/src/deb/hbase/rules
+++ b/bigtop-packages/src/deb/hbase/rules
@@ -36,7 +36,7 @@ override_dh_auto_build:
        
 override_dh_auto_install:
        cp debian/hbase.default 
debian/${hbase_pkg_name}/etc/default/${hbase_pkg_name}
-       sh -x debian/install_hbase.sh \
+       bash -x debian/install_hbase.sh \
                --build-dir=build \
                --conf-dir=/etc/hbase/conf.dist \
                --doc-dir=usr/share/doc/${hbase_pkg_name}-doc \
@@ -56,4 +56,4 @@ override_dh_auto_install:
        find debian/tmp/usr/lib/${hbase_pkg_name}/bin 
debian/tmp/usr/lib/${hbase_pkg_name}/lib -name \*.rb -exec chmod 644 {} \;
        ### webapps should not be executable either
        find debian/tmp/usr/lib/${hbase_pkg_name}/hbase-webapps -type f -exec 
chmod 644 {} \;
-       sh debian/install_init_scripts.sh
+       bash debian/install_init_scripts.sh

http://git-wip-us.apache.org/repos/asf/bigtop/blob/2fc2307c/bigtop-packages/src/rpm/hbase/SPECS/hbase.spec
----------------------------------------------------------------------
diff --git a/bigtop-packages/src/rpm/hbase/SPECS/hbase.spec 
b/bigtop-packages/src/rpm/hbase/SPECS/hbase.spec
index d698bdf..ee15e4d 100644
--- a/bigtop-packages/src/rpm/hbase/SPECS/hbase.spec
+++ b/bigtop-packages/src/rpm/hbase/SPECS/hbase.spec
@@ -90,6 +90,7 @@ Source3: hbase.sh
 Source4: hbase.sh.suse
 Source5: hbase.default
 Source6: hbase.nofiles.conf
+Source7: regionserver-init.d.tpl
 BuildArch: noarch
 Requires: coreutils, /usr/sbin/useradd, /sbin/chkconfig, /sbin/service
 Requires: hadoop-hdfs, zookeeper >= 3.3.1, bigtop-utils >= 0.6
@@ -273,11 +274,18 @@ do
     rest) chkconfig="345 88 12" ;;
     *) chkconfig="345 89 13" ;;
   esac
-       init_file=$RPM_BUILD_ROOT/%{initd_dir}/%{name}-${service}
-       %__cp $orig_init_file $init_file
-       %__sed -i -e "s|@CHKCONFIG@|${chkconfig}|" $init_file
-       %__sed -i -e "s|@HBASE_DAEMON@|${service}|" $init_file
-       chmod 755 $init_file
+    init_file=$RPM_BUILD_ROOT/%{initd_dir}/%{name}-${service}
+    %__cp $orig_init_file $init_file
+    if [[ "$service" = "regionserver" ]] ; then
+        # Region servers start from a different template that allows
+        # them to run multiple concurrent instances of the daemon
+        %__cp %{SOURCE7} $init_file
+        %__sed -i -e "s|@INIT_DEFAULT_START@|3 4 5|" $init_file
+        %__sed -i -e "s|@INIT_DEFAULT_STOP@|0 1 2 6|" $init_file
+    fi
+    %__sed -i -e "s|@CHKCONFIG@|${chkconfig}|" $init_file
+    %__sed -i -e "s|@HBASE_DAEMON@|${service}|" $init_file
+    chmod 755 $init_file
 done
 
 # FIXME: BIGTOP-648 workaround for HBASE-6263

Reply via email to