Skip to content

Commit

Permalink
Merge pull request #88 from logcabin/issue-74
Browse files Browse the repository at this point in the history
Close #74: init script & RPM spec file
  • Loading branch information
ongardie committed Jan 30, 2015
2 parents 35b46b5 + 4697768 commit e20208d
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 23 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Expand Up @@ -12,9 +12,11 @@ before_install:
chmod 0600 travisci_rsa &&
mv travisci_rsa ~/.ssh/id_rsa ||
echo "Failed to set up SSH key for doxygen output"
- sudo apt-get update -qq
- sudo apt-get install -y protobuf-compiler libprotobuf-dev
- sudo apt-get install -y libcrypto++-dev
- sudo apt-get --no-install-recommends install -y doxygen
- sudo apt-get install -y rpm
- echo "HTML_TIMESTAMP = no" >> docs/Doxyfile
script:
- scons NUMCPUS=2
Expand All @@ -28,3 +30,4 @@ script:
else
echo "Not pushing doxygen, sons docs=$DOCS_STATUS, TRAVIS_BRANCH=$TRAVIS_BRANCH, TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST";
fi
- scons rpm
38 changes: 20 additions & 18 deletions Examples/SConscript
Expand Up @@ -2,26 +2,28 @@ Import('env')

libs = [ "pthread", "protobuf", "rt", "cryptopp" ]

env.Program("Benchmark",
["Benchmark.cc", "#build/liblogcabin.a"],
LIBS = libs)
env.Default([
env.Program("Benchmark",
["Benchmark.cc", "#build/liblogcabin.a"],
LIBS = libs),

env.Program("DumpTree",
["DumpTree.cc", "#build/liblogcabin.a"],
LIBS = libs)
env.Program("DumpTree",
["DumpTree.cc", "#build/liblogcabin.a"],
LIBS = libs),

env.Program("HelloWorld",
["HelloWorld.cc", "#build/liblogcabin.a"],
LIBS = libs)
env.Program("HelloWorld",
["HelloWorld.cc", "#build/liblogcabin.a"],
LIBS = libs),

env.Program("Reconfigure",
["Reconfigure.cc", "#build/liblogcabin.a"],
LIBS = libs)
env.Program("Reconfigure",
["Reconfigure.cc", "#build/liblogcabin.a"],
LIBS = libs),

env.Program("ServerStats",
["ServerStats.cc", "#build/liblogcabin.a"],
LIBS = libs)
env.Program("ServerStats",
["ServerStats.cc", "#build/liblogcabin.a"],
LIBS = libs),

env.Program("SmokeTest",
["SmokeTest.cc", "#build/liblogcabin.a"],
LIBS = libs)
env.Program("SmokeTest",
["SmokeTest.cc", "#build/liblogcabin.a"],
LIBS = libs),
])
107 changes: 104 additions & 3 deletions SConstruct
Expand Up @@ -19,7 +19,7 @@ opts.AddVariables(
)

env = Environment(options = opts,
tools = ['default', 'protoc'],
tools = ['default', 'protoc', 'packaging'],
ENV = os.environ)
Help(opts.GenerateHelpText(env))

Expand Down Expand Up @@ -114,15 +114,16 @@ PhonyTargets(doc = "doxygen docs/Doxyfile")
PhonyTargets(docs = "doxygen docs/Doxyfile")
PhonyTargets(tags = "ctags -R --exclude=build --exclude=docs .")

env.StaticLibrary("build/logcabin",
clientlib = env.StaticLibrary("build/logcabin",
(object_files['Client'] +
object_files['Tree'] +
object_files['Protocol'] +
object_files['RPC'] +
object_files['Event'] +
object_files['Core']))
env.Default(clientlib)

env.Program("build/LogCabin",
daemon = env.Program("build/LogCabin",
(["build/Server/Main.cc"] +
object_files['Server'] +
object_files['Storage'] +
Expand All @@ -132,3 +133,103 @@ env.Program("build/LogCabin",
object_files['Event'] +
object_files['Core']),
LIBS = [ "pthread", "protobuf", "rt", "cryptopp" ])
env.Default(daemon)


### scons install target

env.InstallAs('/etc/init.d/logcabin', 'scripts/logcabin-init-redhat')
env.InstallAs('/usr/bin/logcabind', 'build/LogCabin')
env.InstallAs('/usr/bin/logcabin-benchmark', 'build/Examples/Benchmark')
env.InstallAs('/usr/bin/logcabin-dumptree', 'build/Examples/DumpTree')
env.InstallAs('/usr/bin/logcabin-helloworld', 'build/Examples/HelloWorld')
env.InstallAs('/usr/bin/logcabin-reconfigure', 'build/Examples/Reconfigure')
env.InstallAs('/usr/bin/logcabin-serverstats', 'build/Examples/ServerStats')
env.InstallAs('/usr/bin/logcabin-smoketest', 'build/Examples/SmokeTest')
env.Alias('install', ['/etc', '/usr'])


#### 'scons rpm' target

# monkey-patch for SCons.Tool.packaging.rpm.collectintargz, which tries to put
# way too many files into the source tarball (the source tarball should only
# contain the installed files, since we're not building it)
def decent_collectintargz(target, source, env):
tarball = env['SOURCE_URL'].split('/')[-1]
from SCons.Tool.packaging import src_targz
tarball = src_targz.package(env, source=source, target=tarball,
PACKAGEROOT=env['PACKAGEROOT'])
return target, tarball
import SCons.Tool.packaging.rpm as RPMPackager
RPMPackager.collectintargz = decent_collectintargz

# set the install target in the .spec file to just copy over the files that
# 'scons install' would install. Default scons behavior is to invoke scons in
# the source tarball, which doesn't make a ton of sense unless you're doing the
# build in there.
install_commands = []
for target in env.FindInstalledFiles():
parent = target.get_dir()
source = target.sources[0]
install_commands.append('mkdir -p $RPM_BUILD_ROOT%s' % parent)
install_commands.append('cp %s $RPM_BUILD_ROOT%s' % (source, target))

VERSION = '0.0.1-alpha.0'
# https://fedoraproject.org/wiki/Packaging:NamingGuidelines#NonNumericRelease
RPM_VERSION = '0.0.1'
RPM_RELEASE = '0.1.alpha.0'
PACKAGEROOT = 'logcabin-%s' % RPM_VERSION

rpms=RPMPackager.package(env,
target = ['logcabin-%s' % RPM_VERSION],
source = env.FindInstalledFiles(),
X_RPM_INSTALL = '\n'.join(install_commands),
PACKAGEROOT = PACKAGEROOT,
NAME = 'logcabin',
VERSION = RPM_VERSION,
PACKAGEVERSION = RPM_RELEASE,
LICENSE = 'ISC',
SUMMARY = 'LogCabin is clustered consensus deamon',
X_RPM_GROUP = 'Application/logcabin',
DESCRIPTION =
'LogCabin is a distributed system that provides a small amount of\n'
'highly replicated, consistent storage. It is a reliable place for\n'
'other distributed systems to store their core metadata and\n'
'is helpful in solving cluster management issues. Although its key\n'
'functionality is in place, LogCabin is not yet recommended\n'
'for actual use.',
)

# Rename .rpm files into build/
def rename(env, target, source):
for (t, s) in zip(target, source):
os.rename(str(s), str(t))

# Rename files used to build .rpm files
def remove_sources(env, target, source):
garbage = set()
for s in source:
garbage.update(s.sources)
for s2 in s.sources:
garbage.update(s2.sources)
for g in list(garbage):
if str(g).endswith('.spec'):
garbage.update(g.sources)
for g in garbage:
if env['VERBOSE'] == '1':
print 'rm %s' % g
os.remove(str(g))

# Rename PACKAGEROOT directory and subdirectories (should be empty)
def remove_packageroot(env, target, source):
if env['VERBOSE'] == '1':
print 'rm -r %s' % PACKAGEROOT
import shutil
shutil.rmtree(str(PACKAGEROOT))

# Wrap cleanup around (moved) RPM targets
rpms = env.Command(['build/%s' % str(rpm) for rpm in rpms],
rpms,
[rename, remove_sources, remove_packageroot])

env.Alias('rpm', rpms)
17 changes: 16 additions & 1 deletion Server/Main.cc
Expand Up @@ -41,6 +41,7 @@ class OptionParser {
, debugLogFilename() // empty for default
, pidFilename() // empty for none
, serverId(1)
, testConfig(false)
{
while (true) {
static struct option longOptions[] = {
Expand All @@ -51,9 +52,10 @@ class OptionParser {
{"id", required_argument, NULL, 'i'},
{"log", required_argument, NULL, 'l'},
{"pidfile", required_argument, NULL, 'p'},
{"test", no_argument, NULL, 't'},
{0, 0, 0, 0}
};
int c = getopt_long(argc, argv, "bc:dhi:l:p:", longOptions, NULL);
int c = getopt_long(argc, argv, "bc:dhi:l:p:t", longOptions, NULL);

// Detect the end of the options.
if (c == -1)
Expand Down Expand Up @@ -81,6 +83,9 @@ class OptionParser {
case 'p':
pidFilename = optarg;
break;
case 't':
testConfig = true;
break;
case '?':
default:
// getopt_long already printed an error message.
Expand Down Expand Up @@ -122,6 +127,9 @@ class OptionParser {
std::cout << " -p, --pidfile <file> "
<< "Write process ID to <file>"
<< std::endl;
std::cout << " -t, --test "
<< "Check the configuration file for (basic) errors and exit"
<< std::endl;
}

int& argc;
Expand All @@ -132,6 +140,7 @@ class OptionParser {
std::string debugLogFilename;
std::string pidFilename;
uint64_t serverId;
bool testConfig;
};

/**
Expand Down Expand Up @@ -232,6 +241,12 @@ main(int argc, char** argv)
// Parse command line args.
OptionParser options(argc, argv);

if (options.testConfig) {
Server::Globals globals;
globals.config.readFile(options.configFilename.c_str());
return 0;
}

// Set debug log file
if (!options.debugLogFilename.empty()) {
FILE* debugLog = fopen(options.debugLogFilename.c_str(), "a");
Expand Down
106 changes: 106 additions & 0 deletions scripts/logcabin-init-redhat
@@ -0,0 +1,106 @@
#!/bin/sh
#
# logcabin Startup script for logcabin
#
# chkconfig: - 85 15
# processname: logcabind
# config: /etc/logcabin/logcabin.conf
# config: /etc/sysconfig/logcabin
# pidfile: /var/run/logcabin.pid
# description: logcabin is clustered consensus deamon
#
### BEGIN INIT INFO
# Provides: logcabin
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop logcabin
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/logcabin ]; then
# each daemon should have a variable myid defined here
. /etc/sysconfig/logcabin
fi

prog=logcabin
logcabin=${LOGCABIN-/usr/bin/logcabind}
conffile=${CONFFILE-/etc/logcabin.conf}
lockfile=${LOCKFILE-/var/lock/subsys/logcabin}
pidfile=${PIDFILE-/var/run/logcabin.pid}
DAEMON_COREFILE_LIMIT='unlimited'
RETVAL=0

start() {
echo -n $"Starting $prog: "
daemon ${logcabin} --daemon --id ${myid} --config ${conffile} --log /var/log/${prog}.log --pidfile ${pidfile}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch ${lockfile}
return $RETVAL
}

stop() {
echo -n $"Stopping $prog: "
killproc -p ${pidfile} ${prog}
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}

reload() {
echo -n $"Reloading $prog: "
killproc -p ${pidfile} ${prog} -HUP
RETVAL=$?
echo
}

configtest() {
${logcabin} -t -c ${conffile} $FLAG
RETVAL=$?
return $RETVAL
}

rh_status() {
status -p ${pidfile} ${logcabin}
}

# See how we were called.
case "$1" in
start)
rh_status >/dev/null 2>&1 && exit 0
start
;;
stop)
stop
;;
status)
rh_status
RETVAL=$?
;;
restart)
configtest || exit $RETVAL
stop
start
;;
condrestart|try-restart)
if rh_status >/dev/null 2>&1; then
stop
start
fi
;;
force-reload|reload)
reload
;;
configtest)
configtest
;;
*)
echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|upgrade|reload|status|help|configtest}"
RETVAL=2
esac

exit $RETVAL
4 changes: 3 additions & 1 deletion test/SConscript
Expand Up @@ -25,7 +25,7 @@ def GetTestFiles(src_dirs, variant_dir):
variant_dir=variant_dir)
for src_dir in src_dirs])

env.Program("test",
testrunner = env.Program("test",
(["TestRunner.cc", "gtest-all.o"] +
object_files['Server'] +
object_files['Storage'] +
Expand All @@ -49,3 +49,5 @@ env.Program("test",
CPPPATH = env["CPPPATH"] + ["#gtest/include"],
# -fno-access-control allows tests to access private members
CXXFLAGS = env["CXXFLAGS"] + ["-fno-access-control"])

env.Default(testrunner)

0 comments on commit e20208d

Please sign in to comment.