Skip to content

Commit

Permalink
[API][WIP] Moved service manager out to its own system
Browse files Browse the repository at this point in the history
  • Loading branch information
bmeck authored and indexzero committed Oct 9, 2011
1 parent 61651a7 commit 6f68823
Show file tree
Hide file tree
Showing 6 changed files with 515 additions and 0 deletions.
79 changes: 79 additions & 0 deletions lib/foreverd/adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
function ForeverServiceAdapter(service) {
this.service = service;
}
//
// This should install assets to appropriate places for initialization,
// configuration, and storage
//
// The script will be used on startup to load ForeverService
//
// ForeverService should listen on something that the management events
// can respond to in full duplex
//
// The installed adapter should send the following events in dnode protocol
// to the ForeverService and invoke methods as appropriate
//
ForeverServiceAdapter.prototype.install = function install() {
throw new Error('not implemented');
}
//
// This should do a rollback of install completely except for logs
//
ForeverServiceAdapter.prototype.uninstall = function uninstall() {
throw new Error('not implemented');
}
//
// This should call back with an array of [{file:...,options:...},] to pass to Monitors
// this will be invoked when foreverd is created (not started)
//
ForeverServiceAdapter.prototype.load = function load(callback) {
throw new Error('not implemented');
}
//
// This should tell the OS to start the service
// this will not start any applications
// make sure the adapter is installed and sending events to foreverd's listener
//
ForeverServiceAdapter.prototype.start = function start(monitors) {
throw new Error('not implemented');
}
//
// This should tell the OS to start the service
// this will not stop any applications
// make sure the adapter is installed and sending events to foreverd's listener
//
ForeverServiceAdapter.prototype.stop = function stop(monitors) {
throw new Error('not implemented');
}
//
// This should tell the OS to reply with info about applications in the service
// this will not change any applications
// make sure the adapter is installed and sending events to foreverd's listener
//
ForeverServiceAdapter.prototype.status = function status(monitors) {
throw new Error('not implemented');
}
//
// This should tell the OS to restart the service
// this will not restart any applications
// make sure the adapter is installed and sending events to foreverd's listener
//
ForeverServiceAdapter.prototype.restart = function restart(monitors) {
throw new Error('not implemented');
}
//
// This should tell the OS to pause the service
// this will prevent any addition or removal of applications
// make sure the adapter is installed and sending events to foreverd's listener
//
ForeverServiceAdapter.prototype.pause = function pause(monitors) {
throw new Error('not implemented');
}
//
// This should tell the OS to resume the service
// this will enable any addition or removal of applications
// make sure the adapter is installed and sending events to foreverd's listener
//
ForeverServiceAdapter.prototype.resume = function resume(monitors) {
throw new Error('not implemented');
}
86 changes: 86 additions & 0 deletions lib/foreverd/adapter/systemv/foreverd
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/bin/bash
#
# initd-example Node init.d
#
# chkconfig: 345 80 20
# description: Node init.d example
# processname: node
# pidfile: /var/run/initd-example.pid
# logfile: /var/log/initd-example.log
#

# Source function library.
. /lib/lsb/init-functions
PATH=$PATH:/usr/local/bin

NAME=foreverd
pidfile=/var/run/$NAME.pid
logfile=/var/log/$NAME.log
forever_dir=/var/local/forever # Forever root directory.

node=node
foreverd=`which foreverd`
awk=awk
sed=sed

start() {
echo "Starting $NAME: "

if [ "$id" = "" ]; then
# Create the log and pid files, making sure that the target use has access to them
touch $logfile
chown $USER $logfile

# Launch the application
$foreverd -p $forever_dir
else
echo "Instance already running"
fi
RETVAL=$?
}

restart() {
echo -n "Restarting $NAME: "
if [ "$id" != "" ]; then
$foreverd -p $forever_dir
RETVAL=$?
else
start
fi
}

stop() {
echo -n "Shutting down $NAME: "
if [ "$id" != "" ]; then
$foreverd -p $forever_dir
else
echo "Instance is not running";
fi
RETVAL=$?
}

getForeverId() {
local pid=$(pidofproc -p $pidfile)
$foreverd list -p $forever_dir | $sed -e 's/\x1b\[[0-9; ]*m//g' | $awk "\$4 == \"$pid]\" { gsub(/[\[\]]/, \"\", \$1); print \$1; }"
}
id=$(getForeverId)

case "$1" in
start)
start
;;
stop)
stop
;;
status)
$foreverd list -p $forever_dir
;;
restart)
restart
;;
*)
echo "Usage: {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL
122 changes: 122 additions & 0 deletions lib/foreverd/adapter/systemv/systemv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
var util = require('util');
var forever = require('../../../forever');
var ForeverServiceAdapter = require('../adapter');

//
// Classic init.d script adapter
// Sometimes called inittab, but its origin is called systemv
//
function SystemVAdapter(service) {
ForeverServiceAdapter.call(this);
this.daemonized = false;
}
util.inherits(SystemVAdapter, ForeverServiceAdapter);

SystemVAdapter.prototype.install = function install(callback) {
//
// Copy the init.d script to the right location
// TODO Distribution fixes?
//
forever.config.set('root', path.join('/var', 'local', 'foreverd'));
var initdPath = path.join('/etc', 'init.d', 'foreverd');
try {
fs.mkdirSync(forever.config.get('root'), 0777);
fs.mkdirSync(path.join(forever.config.get('root'), 'services'), 0777);
var script = fs.createReadStream(path.join(__dirname, 'foreverd'));
var target = fs.createWriteStream(initdPath, {
flags: 'w',
mode: 0777
});
}
catch (e) {
if (e.code !== 'EEXIST') {
return callback(e);
}
}
script.pipe(target);
script.on('end', function() {
forever.log.info('Adding init.d script to run levels');
try {
var directories = fs.readdirSync('/etc');
directories.forEach(function (directory) {
var match = directory.match(/^rc(\d+)\.d$/);
if(match) {
var kill_or_start = {0:true, 1:true, 6:true}[match[1]] ? 'K' : 'S';
fs.symlinkSync(initdPath, path.join('/etc',directory,kill_or_start+'20foreverd'));
}
});
}
catch (e) {
if (e.code !== 'EEXIST') {
return callback(e);
}
}
});
}

SystemVAdapter.prototype.start = function start(callback) {
if(this.daemonized) {
return callback();
}
var self = this;
var pidFilePath = path.join('/var','run', 'foreverd.pid');
var logFilePath = path.join('/var','log','foreverd');
process.on('exit', function removePIDFile() {
try{
fs.unlinkSync(pidFilePath);
}
catch(err) {
//we are exiting anyway. this may have some noexist error already
}
})
fs.open(logFilePath, 'w+', function serviceLogOpened(err, logFile) {
if(err) {
throw err;
}
try {
daemon.start(logFile);
daemon.lock(pidFilePath);
}
catch (err) {
return callback(err);
}
self.daemonized = true;
callback();
});
}
//
//
//
SystemVAdapter.prototype.load = function load(callback) {
forever.config.set('root', path.join('/var', 'local', 'foreverd'));
var serviceFiles = fs.readdirSync(path.join(forever.config.get('root'), 'services'));
var services = [];
if (serviceFiles.length !== 0) {
serviceFiles.forEach(function loadServiceFiles(serviceFile, index) {
var serviceFilePath = path.join(forever.config.get('root'), 'services', serviceFile);
var service = JSON.parse(fs.readFileSync(serviceFilePath));
var file = service.file;
var options = service.options;
options.minUptime = 200;
services.push({
file:service.file,
options:service.options
})
});
}
callback(services);
}

SystemVAdapter.prototype.add = function add(file, options, callback) {
//
// Add descriptor to our service list
// this is just a json file in $root/services/*.json
//
var service = {
file: file,
options: options || {}
};
options.appendLog = true;
var filePath = path.join(forever.config.get('root'), 'services', options.uid + '.json');
fs.writeFile(filePath, JSON.stringify(service), callback);
}
13 changes: 13 additions & 0 deletions lib/foreverd/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

// App management
/add --options x.json `forever options`
/list
/remove/:pattern

// Service management
/install
/uninstall
/start/:pattern?
/stop/:pattern?
/restart/:pattern?
/status/:pattern?
Loading

0 comments on commit 6f68823

Please sign in to comment.