diff --git a/package.sh b/package.sh new file mode 100755 index 0000000000..68fa4ed943 --- /dev/null +++ b/package.sh @@ -0,0 +1,242 @@ +#!/bin/bash + +########################################################################### +# Packaging script which creates debian and RPM packages. It optionally +# tags the repo with the given version. 'fpm' must be on the path. + +INSTALL_ROOT_DIR=/opt/influxdb +CONFIG_ROOT_DIR=/etc/opt/influxdb + +SAMPLE_CONFIGURATION=etc/config.sample.toml +INITD_SCRIPT=scripts/init.sh + +TMP_WORK_DIR=`mktemp -d` +POST_INSTALL_PATH=`mktemp` +ARCH=`uname -i` + +########################################################################### +# Helper functions. + +# usage prints simple usage information. +usage() { + echo -e "$0 [] [-h]\n" + cleanup_exit $1 +} + +# cleanup_exit removes all resources created during the process and exits with +# the supplied returned code. +cleanup_exit() { + rm -r $TMP_WORK_DIR + rm $POST_INSTALL_PATH + exit $1 +} + +# check_gopath sanity checks the value of the GOPATH env variable. +check_gopath() { + [ -z "$GOPATH" ] && echo "GOPATH is not set." && cleanup_exit 1 + [ ! -d "$GOPATH" ] && echo "GOPATH is not a directory." && cleanup_exit 1 + echo "GOPATH ($GOPATH) looks sane." +} + +# check_clean_tree ensures that no source file is locally modified. +check_clean_tree() { + modified=$(git ls-files --modified | wc -l) + if [ $modified -ne 0 ]; then + echo "The source tree is not clean -- aborting." + cleanup_exit 1 + fi + echo "Git tree is clean." +} + +# update_tree ensures the tree is in-sync with the repo. +update_tree() { + git pull origin master + if [ $? -ne 0 ]; then + echo "Failed to pull latest code -- aborting." + cleanup_exit 1 + fi + git fetch --tags + if [ $? -ne 0 ]; then + echo "Failed to fetch tags -- aborting." + cleanup_exit 1 + fi + echo "Git tree updated successfully." +} + +# check_tag_exists checks if the existing release already exists in the tags. +check_tag_exists () { + version=$1 + git tag | grep -q "^v$version$" + if [ $? -eq 0 ]; then + echo "Proposed version $version already exists as a tag -- aborting." + cleanup_exit 1 + fi +} + +# make_dir_tree creates the directory structure within the packages. +make_dir_tree() { + work_dir=$1 + version=$2 + mkdir -p $work_dir/$INSTALL_ROOT_DIR/versions/$version/scripts + if [ $? -ne 0 ]; then + echo "Failed to create installation directory -- aborting." + cleanup_exit 1 + fi + mkdir -p $work_dir/$CONFIG_ROOT_DIR + if [ $? -ne 0 ]; then + echo "Failed to create configuration directory -- aborting." + cleanup_exit 1 + fi +} + + +# do_build builds the code. +do_build() { + rm $GOPATH/bin/* + go install -a ./... + if [ $? -ne 0 ]; then + echo "Build failed, unable to create package -- aborting" + cleanup_exit 1 + fi + echo "Build completed successfully." +} + +# generate_postinstall_script creates the post-install script for the +# package. It must be passed the version. +generate_postinstall_script() { + version=$1 + cat <$POST_INSTALL_PATH +rm -f $INSTALL_ROOT_DIR/influxd +rm -f $INSTALL_ROOT_DIR/init.sh +ln -s $INSTALL_ROOT_DIR/versions/$version/influxd $INSTALL_ROOT_DIR/influxd +ln -s $INSTALL_ROOT_DIR/versions/$version/scripts/init.sh $INSTALL_ROOT_DIR/init.sh + +if [ ! -L /etc/init.d/influxdb ]; then + ln -sfn $INSTALL_ROOT_DIR/init.sh /etc/init.d/influxdb + chmod +x /etc/init.d/influxdb + if which update-rc.d > /dev/null 2>&1 ; then + update-rc.d -f influxdb remove + update-rc.d influxdb defaults + else + chkconfig --add influxdb + fi +fi + +if ! id influxdb >/dev/null 2>&1; then + useradd --system -U -M influxdb +fi +chown -R -L influxdb:influxdb $INSTALL_ROOT_DIR +chmod -R a+rX $INSTALL_ROOT_DIR +EOF + echo "Post-install script created successfully at $POST_INSTALL_PATH" +} + +########################################################################### +# Start the packaging process. + +if [ $# -ne 1 ]; then + usage 1 +elif [ $1 == "-h" ]; then + usage 0 +else + VERSION=$1 +fi + +echo -e "\nStarting package process...\n" + +check_gopath +check_clean_tree +update_tree +check_tag_exists $VERSION +do_build +make_dir_tree $TMP_WORK_DIR $VERSION + +########################################################################### +# Copy the assets to the installtion directories. + +cp $GOPATH/bin/* $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION +if [ $? -ne 0 ]; then + echo "Failed to copy binaries to packaging directory -- aborting." + cleanup_exit 1 +fi +echo "Binaries in $GOPATH/bin copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION" + +cp $INITD_SCRIPT $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts +if [ $? -ne 0 ]; then + echo "Failed to init.d script to packaging directory -- aborting." + cleanup_exit 1 +fi +echo "$INITD_SCRIPT copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts" + +cp $SAMPLE_CONFIGURATION $TMP_WORK_DIR/$CONFIG_ROOT_DIR +if [ $? -ne 0 ]; then + echo "Failed to copy $SAMPLE_CONFIGURATION to packaging directory -- aborting." + cleanup_exit 1 +fi + +generate_postinstall_script $VERSION + +########################################################################### +# Create the actual packages. + +echo -n "Commence creation of $ARCH packages, version $VERSION? [Y/n] " +read response +response=`echo $response | tr 'A-Z' 'a-z'` +if [ "x$response" == "xn" ]; then + echo "Packaging aborted." + cleanup_exit 1 +fi + +if [ $ARCH == "i386" ]; then + rpm_package=influxdb-$VERSION-1.i686.rpm + debian_package=influxdb_${VERSION}_i686.deb + deb_args="-a i686" + rpm_args="setarch i686" +elif [ $ARCH == "arm" ]; then + rpm_package=influxdb-$VERSION-1.armel.rpm + debian_package=influxdb_${VERSION}_armel.deb +else + rpm_package=influxdb-$VERSION-1.x86_64.rpm + debian_package=influxdb_${VERSION}_amd64.deb +fi + +COMMON_FPM_ARGS="--after-install $POST_INSTALL_PATH -n influxdb -v $VERSION -C $TMP_WORK_DIR ." +DESCRIPTION="Distributed time-series database" +$rpm_args fpm -s dir -t rpm --description "$DESCRIPTION" $COMMON_FPM_ARGS +if [ $? -ne 0 ]; then + echo "Failed to create RPM package -- aborting." + cleanup_exit 1 +fi +echo "RPM package created successfully." + +fpm -s dir -t deb $deb_args --description "$DESCRIPTION" $COMMON_FPM_ARGS +if [ $? -ne 0 ]; then + echo "Failed to create Debian package -- aborting." + cleanup_exit 1 +fi +echo "Debian package created successfully." + +########################################################################### +# Offer to tag the repo. + +echo -n "Tag source tree with v$VERSION and push to repo? [y/N] " +read response +response=`echo $response | tr 'A-Z' 'a-z'` +if [ "x$response" == "xy" ]; then + echo "Creating tag v$VERSION and pushing to repo" + git tag v$VERSION + if [ $? -ne 0 ]; then + echo "Failed to create tag v$VERSION -- aborting" + cleanup_exit 1 + fi + git push origin v$VERSION + if [ $? -ne 0 ]; then + echo "Failed to push tag v$VERSION to repo -- aborting" + cleanup_exit 1 + fi +else + echo "Not creating tag v$VERSION." +fi + +echo -e "\nPackaging process complete." +cleanup_exit 0 diff --git a/scripts/init.sh b/scripts/init.sh new file mode 100644 index 0000000000..e632fbd9f1 --- /dev/null +++ b/scripts/init.sh @@ -0,0 +1,167 @@ +#! /usr/bin/env bash + +### BEGIN INIT INFO +# Provides: influxd +# Required-Start: $all +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start influxd at boot time +### END INIT INFO + +# this init script supports three different variations: +# 1. New lsb that define start-stop-daemon +# 2. Old lsb that don't have start-stop-daemon but define, log, pidofproc and killproc +# 3. Centos installations without lsb-core installed +# +# In the third case we have to define our own functions which are very dumb +# and expect the args to be positioned correctly. + +if [ -r /lib/lsb/init-functions ]; then + source /lib/lsb/init-functions +fi + +DEFAULT=/etc/default/influxdb + +if [ -r $DEFAULT ]; then + source $DEFAULT +fi + +if [ "x$NOFILES" == "x" ]; then + NOFILES=0 +fi + +if [ $NOFILES -le 0 ]; then + NOFILES=65536 +fi + +if [ "x$STDOUT" == "x" ]; then + STDOUT=/dev/null +fi + +echo "Setting ulimit -n $NOFILES" +if ! ulimit -n $NOFILES >/dev/null 2>&1; then + echo -n "Cannot set the max number of open file descriptors" +fi + +function pidofproc() { + if [ $# -ne 3 ]; then + echo "Expected three arguments, e.g. $0 -p pidfile daemon-name" + fi + + pid=`pgrep -f $3` + local pidfile=`cat $2` + + if [ "x$pidfile" == "x" ]; then + return 1 + fi + + if [ "x$pid" != "x" -a "$pidfile" == "$pid" ]; then + return 0 + fi + + return 1 +} + +function killproc() { + if [ $# -ne 3 ]; then + echo "Expected three arguments, e.g. $0 -p pidfile signal" + fi + + pid=`cat $2` + + kill -s $3 $pid +} + +function log_failure_msg() { + echo "$@" "[ FAILED ]" +} + +function log_success_msg() { + echo "$@" "[ OK ]" +} + +# Process name ( For display ) +name=influxd + +# Daemon name, where is the actual executable +daemon=/opt/influxdb/influxd + +# pid file for the daemon +pidfile=/var/opt/influxdb/run/influxd.pid + +# Configuration file +config=/etc/opt/influxdb/config.sample.toml + +# If the daemon is not there, then exit. +[ -x $daemon ] || exit 5 + +case $1 in + start) + # Checked the PID file exists and check the actual status of process + if [ -e $pidfile ]; then + pidofproc -p $pidfile $daemon > /dev/null 2>&1 && status="0" || status="$?" + # If the status is SUCCESS then don't need to start again. + if [ "x$status" = "x0" ]; then + log_failure_msg "$name process is running" + exit 1 # Exit + fi + fi + # Start the daemon. + log_success_msg "Starting the process" "$name" + # Start the daemon with the help of start-stop-daemon + # Log the message appropriately + cd / + if which start-stop-daemon > /dev/null 2>&1; then + nohup start-stop-daemon --chuid influxdb:influxdb -d / --start --quiet --oknodo --pidfile $pidfile --exec $daemon -- -pidfile $pidfile -config $config >> $STDOUT 2>&1 & + elif set | egrep '^start_daemon' > /dev/null 2>&1; then + start_daemon -u influxdb ${daemon}-daemon -pidfile $pidfile -config $config >> $STDOUT 2>&1 + else + su -s /bin/sh -c "${daemon}-daemon -pidfile $pidfile -config $config >> $STDOUT 2>&1" influxdb + fi + log_success_msg "$name process was started" + ;; + + stop) + # Stop the daemon. + if [ -e $pidfile ]; then + pidofproc -p $pidfile $daemon > /dev/null 2>&1 && status="0" || status="$?" + if [ "$status" = 0 ]; then + if killproc -p $pidfile SIGTERM && /bin/rm -rf $pidfile; then + log_success_msg "$name process was stopped" + else + log_failure_msg "$name failed to stop service" + fi + fi + else + log_failure_msg "$name process is not running" + fi + ;; + + restart) + # Restart the daemon. + $0 stop && sleep 2 && $0 start + ;; + + status) + # Check the status of the process. + if [ -e $pidfile ]; then + if pidofproc -p $pidfile $daemon > /dev/null; then + log_success_msg "$name Process is running" + exit 0 + else + log_failure_msg "$name Process is not running" + exit 1 + fi + else + log_failure_msg "$name Process is not running" + exit 3 + fi + ;; + + *) + # For invalid arguments, print the usage message. + echo "Usage: $0 {start|stop|restart|status}" + exit 2 + ;; +esac