From 560f691096083cce002097260bc1a205087a940e Mon Sep 17 00:00:00 2001 From: Ross McDonald Date: Tue, 24 Nov 2015 17:53:48 -0600 Subject: [PATCH] A few updates: - Re-enabling support for ARM builds in `build.py`. - Improved `build.py`'s iteration and package version. - Fixed minor bug with logrotate file path in `build.py`. - Improved installation pre and post install/uninstall scripts by adding distribution-specific logic to account for quirks between the different package managers. - Added post-install as post-trans script for RPM builds due to the order of RPM upgrade commands (issue where init scripts were removed when upgrading). - Added explicit backup to pre-install script to ensure legacy configuration survive an upgrade. --- build.py | 116 ++++++++++++++++++++++---------------- scripts/post-install.sh | 89 ++++++++++++++++++----------- scripts/post-uninstall.sh | 55 +++++++++++++----- scripts/pre-install.sh | 22 +++++--- 4 files changed, 178 insertions(+), 104 deletions(-) diff --git a/build.py b/build.py index 6ac1bb3cae..7c0fe0a5fd 100755 --- a/build.py +++ b/build.py @@ -3,7 +3,6 @@ # This is the InfluxDB build script. # # Current caveats: -# - Does not currently build ARM builds/packages # - Does not checkout the correct commit/branch (for now, you will need to do so manually) # - Has external dependencies for packaging (fpm) and uploading (boto) # @@ -43,9 +42,9 @@ DEFAULT_CONFIG = "etc/config.sample.toml" # META-PACKAGE VARIABLES PACKAGE_LICENSE = "MIT" PACKAGE_URL = "https://github.com/influxdb/influxdb" -MAINTAINER = "InfluxData" +MAINTAINER = "support@influxdb.com" VENDOR = "InfluxData" -DESCRIPTION = "A distributed time-series database." +DESCRIPTION = "Distributed time-series database." # SCRIPT START prereqs = [ 'git', 'go' ] @@ -61,34 +60,37 @@ fpm_common_args = "-f -s dir --log error \ --maintainer {} \ --config-files {} \ --config-files {} \ + --directories {} \ + --directories {} \ --description \"{}\"".format( - VENDOR, - PACKAGE_URL, - POSTINST_SCRIPT, - PREINST_SCRIPT, - POSTUNINST_SCRIPT, - PACKAGE_LICENSE, - MAINTAINER, - CONFIG_DIR, - LOGROTATE_DIR, - DESCRIPTION) + VENDOR, + PACKAGE_URL, + POSTINST_SCRIPT, + PREINST_SCRIPT, + POSTUNINST_SCRIPT, + PACKAGE_LICENSE, + MAINTAINER, + CONFIG_DIR + '/influxdb.conf', + LOGROTATE_DIR + '/influxdb', + LOG_DIR, + DATA_DIR, + DESCRIPTION) targets = { 'influx' : './cmd/influx/main.go', 'influxd' : './cmd/influxd/main.go', 'influx_stress' : './cmd/influx_stress/influx_stress.go', 'influx_inspect' : './cmd/influx_inspect/*.go', - 'influx_tsm' : './cmd/influx_tsm/main.go', + 'influx_tsm' : './cmd/influx_tsm/*.go', } supported_builds = { - # TODO(rossmcdonald): Add support for multiple GOARM values 'darwin': [ "amd64", "386" ], # Windows is not currently supported in InfluxDB 0.9.5 due to use of mmap # 'windows': [ "amd64", "386", "arm" ], 'linux': [ "amd64", "386", "arm" ] } -supported_go = [ '1.5.1', '1.4.2' ] + supported_packages = { "darwin": [ "tar", "zip" ], "linux": [ "deb", "rpm", "tar", "zip" ], @@ -103,18 +105,20 @@ def run(command, allow_failure=False, shell=False): else: out = subprocess.check_output(command.split(), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: + print "" print "" print "Executed command failed!" print "-- Command run was: {}".format(command) print "-- Failure was: {}".format(e.output) if allow_failure: print "Continuing..." - return out + return None else: print "" print "Stopping." sys.exit(1) except OSError as e: + print "" print "" print "Invalid command!" print "-- Command run was: {}".format(command) @@ -152,7 +156,10 @@ def get_current_branch(): return out.strip() def get_system_arch(): - return os.uname()[4] + arch = os.uname()[4] + if arch == "x86_64": + arch = "amd64" + return arch def get_system_platform(): if sys.platform.startswith("linux"): @@ -179,12 +186,12 @@ def check_path_for(b): def check_environ(build_dir = None): print "\nChecking environment:" - for v in [ "GOPATH", "GOBIN" ]: + for v in [ "GOPATH", "GOBIN", "GOROOT" ]: print "\t- {} -> {}".format(v, os.environ.get(v)) cwd = os.getcwd() if build_dir == None and os.environ.get("GOPATH") and os.environ.get("GOPATH") not in cwd: - print "\n!! WARNING: Your current directory is not under your GOPATH! This probably won't work." + print "\n!! WARNING: Your current directory is not under your GOPATH. This may lead to build failures." def check_prereqs(): print "\nChecking for dependencies:" @@ -282,7 +289,8 @@ def build(version=None, rc=None, race=False, clean=False, - outdir="."): + outdir=".", + goarm_version="6"): print "-------------------------" print "" print "Build plan:" @@ -293,6 +301,8 @@ def build(version=None, print "\t- branch: {}".format(branch) print "\t- platform: {}".format(platform) print "\t- arch: {}".format(arch) + if arch == 'arm' and goarm_version: + print "\t- ARM version: {}".format(goarm_version) print "\t- nightly? {}".format(str(nightly).lower()) print "\t- race enabled? {}".format(str(race).lower()) print "" @@ -312,10 +322,11 @@ def build(version=None, for b, c in targets.iteritems(): print "\t- Building '{}'...".format(os.path.join(outdir, b)), build_command = "" - build_command += "GOOS={} GOOARCH={} ".format(platform, arch) - if arch == "arm": - # TODO(rossmcdonald): Add GOARM variables for ARM builds - build_command += "GOOARM={} ".format(6) + build_command += "GOOS={} GOARCH={} ".format(platform, arch) + if arch == "arm" and goarm_version: + if goarm_version not in ["5", "6", "7", "arm64"]: + print "!! Invalid ARM build version: {}".format(goarm_version) + build_command += "GOARM={} ".format(goarm_version) build_command += "go build -o {} ".format(os.path.join(outdir, b)) if race: build_command += "-race " @@ -331,7 +342,7 @@ def build(version=None, build_command += "-X main.branch={} ".format(branch) build_command += "-X main.commit={}\" ".format(get_current_commit()) build_command += c - out = run(build_command, shell=True) + run(build_command, shell=True) print "[ DONE ]" print "" @@ -373,8 +384,8 @@ def package_scripts(build_root): os.chmod(os.path.join(build_root, SCRIPT_DIR[1:], INIT_SCRIPT.split('/')[1]), 0644) shutil.copyfile(SYSTEMD_SCRIPT, os.path.join(build_root, SCRIPT_DIR[1:], SYSTEMD_SCRIPT.split('/')[1])) os.chmod(os.path.join(build_root, SCRIPT_DIR[1:], SYSTEMD_SCRIPT.split('/')[1]), 0644) - shutil.copyfile(LOGROTATE_SCRIPT, os.path.join(build_root, SCRIPT_DIR[1:], LOGROTATE_SCRIPT.split('/')[1])) - os.chmod(os.path.join(build_root, SCRIPT_DIR[1:], LOGROTATE_SCRIPT.split('/')[1]), 0644) + shutil.copyfile(LOGROTATE_SCRIPT, os.path.join(build_root, LOGROTATE_DIR[1:], "influxdb")) + os.chmod(os.path.join(build_root, LOGROTATE_DIR[1:], "influxdb"), 0644) shutil.copyfile(DEFAULT_CONFIG, os.path.join(build_root, CONFIG_DIR[1:], "influxdb.conf")) os.chmod(os.path.join(build_root, CONFIG_DIR[1:], "influxdb.conf"), 0644) @@ -426,6 +437,8 @@ def build_packages(build_output, version, nightly=False, rc=None, iteration=1): for package_type in supported_packages[p]: print "\t- Packaging directory '{}' as '{}'...".format(build_root, package_type), name = "influxdb" + package_version = version + package_iteration = iteration if package_type in ['zip', 'tar']: if nightly: name = '{}-nightly_{}_{}'.format(name, p, a) @@ -434,25 +447,19 @@ def build_packages(build_output, version, nightly=False, rc=None, iteration=1): if package_type == 'tar': # Add `tar.gz` to path to ensure a small package size current_location = os.path.join(current_location, name + '.tar.gz') - if package_type == 'deb' and rc: - # For debs with an RC, just append to version number - version += "-rc{}".format(rc) - fpm_command = "fpm {} --name {} -a {} -t {} --version {} -C {} -p {} ".format( + if rc is not None: + package_iteration = "0.rc{}".format(rc) + fpm_command = "fpm {} --name {} -a {} -t {} --version {} --iteration {} -C {} -p {} ".format( fpm_common_args, name, a, package_type, - version, + package_version, + package_iteration, build_root, current_location) if package_type == "rpm": - fpm_command += "--depends coreutils " - # For rpms with RC, add to iteration for adherence to Fedora packaging standard: - # http://fedoraproject.org/wiki/Packaging%3aNamingGuidelines#NonNumericRelease - if rc: - fpm_command += "--iteration 0.{}.rc{} ".format(iteration, rc) - else: - fpm_command += "--iteration 1 ".format(iteration) + fpm_command += "--depends coreutils --rpm-posttrans {}".format(POSTINST_SCRIPT) out = run(fpm_command, shell=True) matches = re.search(':path=>"(.*)"', out) outfile = None @@ -462,10 +469,8 @@ def build_packages(build_output, version, nightly=False, rc=None, iteration=1): print "[ COULD NOT DETERMINE OUTPUT ]" else: # Strip nightly version (the unix epoch) from filename - if nightly and package_type == 'deb': - outfile = rename_file(outfile, outfile.replace("{}".format(version), "nightly")) - elif nightly and package_type == 'rpm': - outfile = rename_file(outfile, outfile.replace("{}-1".format(version), "nightly")) + if nightly and package_type in ['deb', 'rpm']: + outfile = rename_file(outfile, outfile.replace("{}-{}".format(version, iteration), "nightly")) outfiles.append(os.path.join(os.getcwd(), outfile)) print "[ DONE ]" # Display MD5 hash for generated package @@ -482,18 +487,20 @@ def print_usage(): print "Options:" print "\t --outdir= \n\t\t- Send build output to a specified path. Defaults to ./build." print "\t --arch= \n\t\t- Build for specified architecture. Acceptable values: x86_64|amd64, 386, arm, or all" + print "\t --goarm= \n\t\t- Build for specified ARM version (when building for ARM). Default value is: 6" print "\t --platform= \n\t\t- Build for specified platform. Acceptable values: linux, windows, darwin, or all" print "\t --version= \n\t\t- Version information to apply to build metadata. If not specified, will be pulled from repo tag." print "\t --commit= \n\t\t- Use specific commit for build (currently a NOOP)." print "\t --branch= \n\t\t- Build from a specific branch (currently a NOOP)." print "\t --rc= \n\t\t- Whether or not the build is a release candidate (affects version information)." + print "\t --iteration= \n\t\t- The iteration to display on the package output (defaults to 0 for RC's, and 1 otherwise)." print "\t --race \n\t\t- Whether the produced build should have race detection enabled." print "\t --package \n\t\t- Whether the produced builds should be packaged for the target platform(s)." print "\t --nightly \n\t\t- Whether the produced build is a nightly (affects version information)." print "\t --update \n\t\t- Whether dependencies should be updated prior to building." print "\t --test \n\t\t- Run Go tests. Will not produce a build." print "\t --parallel \n\t\t- Run Go tests in parallel up to the count specified." - print "\t --timeout \n\t\t- Timeout for Go tests. Default 480s" + print "\t --timeout \n\t\t- Timeout for Go tests. Defaults to 480s." print "\t --clean \n\t\t- Clean the build output directory prior to creating build." print "" @@ -520,6 +527,7 @@ def main(): timeout = None iteration = 1 no_vet = False + goarm_version = "6" for arg in sys.argv[1:]: if '--outdir' in arg: @@ -574,6 +582,9 @@ def main(): iteration = arg.split("=")[1] elif '--no-vet' in arg: no_vet = True + elif '--goarm' in arg: + # Signifies GOARM flag to pass to build command when compiling for ARM + goarm_version = arg.split("=")[1] elif '--help' in arg: print_usage() return 0 @@ -599,12 +610,16 @@ def main(): if not branch: branch = get_current_branch() if not target_arch: - target_arch = get_system_arch() + if 'arm' in get_system_arch(): + # Prevent uname from reporting ARM arch (eg 'armv7l') + target_arch = "arm" + else: + target_arch = get_system_arch() if not target_platform: target_platform = get_system_platform() - - if target_arch == "x86_64": - target_arch = "amd64" + if rc or nightly: + # If a release candidate or nightly, set iteration to 0 (instead of 1) + iteration = 0 build_output = {} # TODO(rossmcdonald): Prepare git repo for build (checking out correct branch/commit, etc.) @@ -645,7 +660,8 @@ def main(): rc=rc, race=race, clean=clean, - outdir=od) + outdir=od, + goarm_version=goarm_version) build_output.get(platform).update( { arch : od } ) # Build packages diff --git a/scripts/post-install.sh b/scripts/post-install.sh index dffb9225ea..507759eea2 100644 --- a/scripts/post-install.sh +++ b/scripts/post-install.sh @@ -1,43 +1,66 @@ -#!/bin/sh +#!/bin/bash + BIN_DIR=/usr/bin DATA_DIR=/var/lib/influxdb LOG_DIR=/var/log/influxdb SCRIPT_DIR=/usr/lib/influxdb/scripts LOGROTATE_DIR=/etc/logrotate.d -if ! id influxdb >/dev/null 2>&1; then - useradd --system -U -M influxdb -s /bin/false -d $DATA_DIR -fi -chmod a+rX $BIN_DIR/influx* - -mkdir -p $LOG_DIR -chown -R -L influxdb:influxdb $LOG_DIR -mkdir -p $DATA_DIR -chown -R -L influxdb:influxdb $DATA_DIR - -test -f /etc/default/influxdb || touch /etc/default/influxdb - -# Remove legacy logrotate file -test -f $LOGROTATE_DIR/influxd && rm -f $LOGROTATE_DIR/influxd - -# Remove legacy symlink -test -h /etc/init.d/influxdb && rm -f /etc/init.d/influxdb - -# Systemd -if which systemctl > /dev/null 2>&1 ; then - cp $SCRIPT_DIR/influxdb.service /lib/systemd/system/influxdb.service - systemctl enable influxdb - -# Sysv -else +function install_init { cp -f $SCRIPT_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 +} + +function install_systemd { + cp -f $SCRIPT_DIR/influxdb.service /lib/systemd/system/influxdb.service + systemctl enable influxdb +} + +function install_update_rcd { + update-rc.d influxdb defaults +} + +function install_chkconfig { + chkconfig --add influxdb +} + +id influxdb &>/dev/null +if [[ $? -ne 0 ]]; then + useradd --system -U -M influxdb -s /bin/false -d $DATA_DIR fi -exit +chown -R -L influxdb:influxdb $DATA_DIR +chown -R -L influxdb:influxdb $LOG_DIR + +# Add defaults file, if it doesn't exist +if [[ ! -f /etc/default/influxdb ]]; then + touch /etc/default/influxdb +fi + +# Remove legacy symlink, if it exists +if [[ -L /etc/init.d/influxdb ]]; then + rm -f /etc/init.d/influxdb +fi + +# Distribution-specific logic +if [[ -f /etc/redhat-release ]]; then + # RHEL-variant logic + which systemctl &>/dev/null + if [[ $? -eq 0 ]]; then + install_systemd + else + # Assuming sysv + install_init + install_chkconfig + fi +elif [[ -f /etc/lsb-release ]]; then + # Debian/Ubuntu logic + which systemctl &>/dev/null + if [[ $? -eq 0 ]]; then + install_systemd + else + # Assuming sysv + install_init + install_update_rcd + fi +fi diff --git a/scripts/post-uninstall.sh b/scripts/post-uninstall.sh index 6003b291fa..4f57d2e968 100644 --- a/scripts/post-uninstall.sh +++ b/scripts/post-uninstall.sh @@ -1,17 +1,46 @@ -#!/bin/sh -rm -f /etc/default/influxdb +#!/bin/bash -# Systemd -if which systemctl > /dev/null 2>&1 ; then +function disable_systemd { systemctl disable influxdb rm -f /lib/systemd/system/influxdb.service -# Sysv -else - if which update-rc.d > /dev/null 2>&1 ; then - update-rc.d -f influxdb remove - else - chkconfig --del influxdb - fi - rm -f /etc/init.d/influxdb -fi +} +function disable_update_rcd { + update-rc.d -f influxdb remove + rm -f /etc/init.d/influxdb +} + +function disable_chkconfig { + chkconfig --del influxdb + rm -f /etc/init.d/influxdb +} + +if [[ -f /etc/redhat-release ]]; then + # RHEL-variant logic + if [[ "$1" = "0" ]]; then + # InfluxDB is no longer installed, remove from init system + rm -f /etc/default/influxdb + + which systemctl &>/dev/null + if [[ $? -eq 0 ]]; then + disable_systemd + else + # Assuming sysv + disable_chkconfig + fi + fi +elif [[ -f /etc/lsb-release ]]; then + # Debian/Ubuntu logic + if [[ "$1" != "upgrade" ]]; then + # Remove/purge + rm -f /etc/default/influxdb + + which systemctl &>/dev/null + if [[ $? -eq 0 ]]; then + disable_systemd + else + # Assuming sysv + disable_update_rcd + fi + fi +fi diff --git a/scripts/pre-install.sh b/scripts/pre-install.sh index 6d2017f2a4..d57ff0f71b 100755 --- a/scripts/pre-install.sh +++ b/scripts/pre-install.sh @@ -1,10 +1,16 @@ -#!/bin/sh +#!/bin/bash -# Copy existing configuration if pre-existing installation is found -test -f /etc/opt/influxdb/influxdb.conf -if [ $? -eq 0 ]; then - mkdir /etc/influxdb - cp -a /etc/opt/influxdb/* /etc/influxdb/ +if [[ -d /etc/opt/influxdb ]]; then + # Legacy configuration found + if [[ ! -d /etc/influxdb ]]; then + # New configuration does not exist, move legacy configuration to new location + echo -e "Please note, InfluxDB's configuration is now located at '/etc/influxdb' (previously '/etc/opt/influxdb')." + mv -vn /etc/opt/influxdb /etc/influxdb + + if [[ -f /etc/influxdb/influxdb.conf ]]; then + backup_name="influxdb.conf.$(date +%s).backup" + echo "A backup of your current configuration can be found at: /etc/influxdb/$backup_name" + cp -a /etc/influxdb/influxdb.conf /etc/influxdb/$backup_name + fi + fi fi - -exit