platypush/bin/platyvenv

260 lines
6.4 KiB
Bash
Executable File

#!/bin/bash
##############################################################################
# This script allows you to easily manage Platypush instances through Python #
# virtual environment. You can build environments from a config.yaml file #
# and automatically managed the required dependencies, as well as start, #
# stop and remove them #
# #
# @author: Fabio Manganiello <blacklight86@gmail.com> #
# @licence: MIT #
##############################################################################
workdir=$HOME/.local/share/platypush/venv
function build {
cfgfile=
while getopts ':c:' opt; do
case ${opt} in
c)
cfgfile=$OPTARG;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1;;
:)
echo "Option -$OPTARG requires the path to a Platypush configuration file" >&2
exit 1;;
esac
done
if [[ -z "$cfgfile" ]]; then
echo "Usage: $0 build -c <path-to-platypush-config-file>" >&2
exit 1
fi
echo "Parsing configuration file"
deps=()
includes=()
while read -r line; do
echo ${line} | egrep '``pip install .+?``' > /dev/null 2>&1
if (( $? != 0 )); then
continue
fi
dep=$(echo ${line} | sed -r -e 's/.*``pip install (.+?)``.*/\1/')
deps+=("$dep")
done <<< $(python <<EOF
from platypush.config import Config
from platypush.context import get_plugin, get_backend, register_backends
Config.init('`realpath ${cfgfile}`')
register_backends()
backend_config = Config.get_backends()
for name in Config.get_backends().keys():
backend = get_backend(name)
print(backend.__doc__)
for name in Config.get_plugins().keys():
try:
plugin = get_plugin(name)
print(plugin.__doc__)
except:
pass
EOF
)
while read -r include; do
includes+=(${include})
done <<< $(python <<EOF
from platypush.config import Config
from platypush.context import get_plugin, get_backend, register_backends
Config.init('`realpath ${cfgfile}`')
for include in Config._included_files:
print(include)
EOF
)
device_id=$(python <<EOF
from platypush.config import Config
Config.init('`realpath ${cfgfile}`')
print(Config.get('device_id'))
EOF
)
envdir=${workdir}/${device_id}
etcdir=${envdir}/etc/platypush
echo "Preparing virtual environment for device $device_id"
mkdir -p "$envdir"
mkdir -p "$etcdir"
srcdir=`dirname "$cfgfile"`
for ((i=0; $i < ${#includes[@]}; i++)); do
incdir=`dirname "${includes[$i]}"`
incdir=`realpath --relative-to="$srcdir" "$incdir"`
destdir="$etcdir/$incdir"
mkdir -p "$destdir"
cp "${includes[$i]}" "$destdir"
done
cp "$cfgfile" "$etcdir/config.yaml"
cfgfile=${etcdir}/config.yaml
python3 -m venv ${envdir}
cd ${envdir}
source ${envdir}/bin/activate
echo "Installing required dependencies"
for ((i=0; $i < ${#deps[@]}; i++)); do
echo ${deps[$i]}
done | sort -u | while read dep; do
pip install ${dep}
done
pip install --upgrade git+https://git.platypush.tech/platypush/platypush.git
echo "Platypush virtual environment prepared under $envdir"
}
function start {
if [[ -z "$1" ]]; then
echo "Usage: $0 start <env-name>" >&2
exit 1
fi
env=$1
envdir=${workdir}/${env}
logsdir=${envdir}/var/log/platypush
rundir=${envdir}/var/run
pidfile=${rundir}/platypush.pid
cfgfile=${envdir}/etc/platypush/config.yaml
if [[ ! -d "$envdir" ]]; then
echo "No such directory: $envdir" >&2
exit 1
fi
mkdir -p ${logsdir}
mkdir -p ${rundir}
if [[ -f "$pidfile" ]]; then
pid=`cat "$pidfile"`
if ps -p ${pid} | grep platypush; then
echo "Another instance (PID $pid) is running, please stop that instance first"
exit 1
fi
echo "A PID file was found but the process doesn't seem to be running, starting anyway"
rm -f "$pidfile"
fi
python3 -m venv ${envdir}
cd ${envdir}
source bin/activate
bin/platypush -c "$cfgfile" -P "$pidfile" > ${logsdir}/stdout.log 2> ${logsdir}/stderr.log &
start_time=`date +'%s'`
timeout=30
while :; do
[[ -f "$pidfile" ]] && break
now=`date +'%s'`
let elapsed=$now-$start_time
if (( ${elapsed} >= ${timeout} )); then
echo "Platypush instance '$env' didn't start within $timeout seconds" >&2
exit 1
fi
echo -n '.'
sleep 1
done
pid=`cat "$pidfile"`
echo
echo "Platypush environment $env started with PID $pid, logs dir: $logsdir"
}
function stop {
if [[ -z "$1" ]]; then
echo "Usage: $0 stop <env-name>" >&2
exit 1
fi
env=$1
envdir=${workdir}/${env}
rundir=${envdir}/var/run
pidfile=${rundir}/platypush.pid
if [[ ! -d "$envdir" ]]; then
echo "No such directory: $envdir" >&2
exit 1
fi
if [[ ! -f "$pidfile" ]]; then
echo "No pidfile found for instance "${env}""
exit 1
fi
pid=`cat "$pidfile"`
pids="$pid `ps --no-headers -o pid= --ppid $pid`"
kill -9 ${pids}
rm -f "$pidfile"
echo "Instance '$env' with PID $pid stopped"
}
function rme {
if [[ -z "$1" ]]; then
echo "Usage: $0 rm <env-name>" >&2
exit 1
fi
envdir=${workdir}/$1
rundir=${envdir}/var/run
pidfile=${rundir}/platypush.pid
if [[ ! -d "$envdir" ]]; then
echo "No such directory: $envdir" >&2
exit 1
fi
if [[ -f "$pidfile" ]]; then
if ps -p `cat "$pidfile"` | grep platypush; then
echo "Another instance (PID $pidfile) is running, please stop that instance first"
exit 1
fi
echo "A PID file was found but the process doesn't seem to be running, removing anyway"
fi
rm -rf "$envdir"
echo "$envdir removed"
}
function usage {
echo "Usage: $0 <build|start|stop|rm> [options]" >&2
exit 1
}
if (( $# < 1 )); then
usage
fi
action=$1
shift
mkdir -p ${workdir}
case ${action} in
'build') build;;
'start') start $*;;
'stop') stop $*;;
'rm') rme $*;;
*) usage;;
esac