Improvements for init.d, upstart, and systemd-based systems

1. Change ownership of /onos/apps

onos-service needs write access to onos/apps/foo in order to activate
an app. This also means that ONOS itself could also activate/deactivate,
modify, or reinstall apps, which seems a bit dodgy but is probably
intended.

2. Fix sudo command line

The -b option was in the wrong place, breaking sudo on systems where
we use sudo to start onos (e.g. older debian or centos.)

3. Redirect stderr of 'type daemon' command

We want to detect whether the 'daemon' function/script is available
in init.d enviroments that support it, and we do so using the type
command. Previously we didn't redirect stderr, so this resulted
in a confusing error message being sent to stderr of whoever is
invoking the script.

4. onos.conf has changed to be more consistent with onos.initd

Previously onos.conf ignored $ONOS_GROUP and had a slightly different
structure.

5. onos.service has been added for systemd-based systems

This initial version of onos.service calls /etc/init.d/onos to start
and stop ONOS. In the future we may be able to call onos-service
directly, but we will need to make sure that permissions are set up
correctly so that onos-service can activate apps and so that ONOS
itself can write its log files.

6. A README has been added

7. Update the onos-install and onos-uninstall scripts

Related Jira issue: ONOS-5550

Change-Id: Ie72775f1d0a4082af9c5ea9b13999c427c15ffe0
diff --git a/tools/package/init/README b/tools/package/init/README
new file mode 100644
index 0000000..22a80a8
--- /dev/null
+++ b/tools/package/init/README
@@ -0,0 +1,18 @@
+ONOS "service" configuration files
+
+In order to run ONOS as a "service," whose execution is managed
+by the OS, you can install an appropriate configuration/startup file.
+
+onos.initd:     startup file for SysV/init.d-based systems
+                usually installed as /etc/init.d/onos
+
+onos.conf:      configuration for upstart-based systems
+                usually installed as /etc/init/onos.conf
+
+onos.service:   configuration for systemd-based systems
+                currently calls /etc/init.d/onos start
+                usually installed as /etc/systemd/system/onos.service
+
+The reason why onos.service currently calls /etc/init.d/onos
+is because the init.d script fixes permissions that are required
+by onos-service (such as /opt/onos/apps.)
diff --git a/tools/package/init/onos.conf b/tools/package/init/onos.conf
index ea9657e..d130afe 100644
--- a/tools/package/init/onos.conf
+++ b/tools/package/init/onos.conf
@@ -1,6 +1,8 @@
 description  "Open Network Operating System"
 author       "ON.Lab"
 
+# onos.conf: ONOS service configuration for upstart-based systems
+
 start on (net-device-up
           and local-filesystems
           and runlevel [2345])
@@ -15,13 +17,13 @@
 pre-start script
     [ -f /opt/onos/options ] && . /opt/onos/options
     ONOS_USER=${ONOS_USER:-root}
-
-    # Ensure that the environment is initialized
-    [ -d /opt/onos ] && mkdir /opt/onos/var 2>/dev/null && chown $ONOS_USER.$ONOS_USER /opt/onos/var
-    [ -d /opt/onos ] && mkdir /opt/onos/config 2>/dev/null && chown $ONOS_USER.$ONOS_USER /opt/onos/config
-    # TODO make karaf version configurable
-    [ -d /opt/onos ] && [ ! -h /opt/onos/log ] \
-         && ln -s /opt/onos/apache-karaf-3.0.5/data/log /opt/onos/log || :
+    ONOS_GROUP=${ONOS_GROUP:-$ONOS_USER}
+    # Fix permissions and symlinks
+    mkdir -p /opt/onos/var 2>/dev/null && chown $ONOS_USER:$ONOS_GROUP /opt/onos/var
+    mkdir -p /opt/onos/config 2>/dev/null && chown $ONOS_USER:$ONOS_GROUP /opt/onos/config
+    mkdir -p /opt/onos/apps 2>/dev/null && chown -R $ONOS_USER:$ONOS_GROUP /opt/onos/apps
+    [ ! -h $ONOS_OME/karaf ] && ln -s /opt/onos/apache-karaf* $ONOS_HOME/karaf || :
+    [ ! -h $ONOS_HOME/log ]  && ln -s $ONOS_HOME/karaf/data/log $ONOS_HOME/log || :
 end script
 
 pre-stop script
diff --git a/tools/package/init/onos.initd b/tools/package/init/onos.initd
index 524e172..1fecfcd 100755
--- a/tools/package/init/onos.initd
+++ b/tools/package/init/onos.initd
@@ -2,10 +2,9 @@
 # -----------------------------------------------------------------------------
 # init.d script to run ONOS
 #
-# This provides the core for an ONOS service in a variety of environments,
-# including init.d, upstart, and systemd. It can also be invoked directly.
-# If it is invoked by a boot system, environment variables will usually be
-# empty and the default values will be used.
+# This provides the core for an ONOS service in a variety of System V/init.d
+# compatible environments. It can also be invoked directly.
+# It reads configuration options from $ONOS_HOME/options
 # -----------------------------------------------------------------------------
 ### BEGIN INIT INFO
 # Provides:          onos
@@ -22,16 +21,19 @@
 [ -f $ONOS_HOME/options ] && . $ONOS_HOME/options
 ONOS_USER=${ONOS_USER:-root}
 ONOS_GROUP=${ONOS_GROUP:-$ONOS_USER}
-ONOS_OPTS=${ONOS_OPTS:-""}
+ONOS_OPTS=${ONOS_OPTS:-server}
 
 start () {
+    # Fix permissions and symlinks
     mkdir -p $ONOS_HOME/var 2>/dev/null && chown $ONOS_USER:$ONOS_GROUP $ONOS_HOME/var
     mkdir -p $ONOS_HOME/config 2>/dev/null && chown $ONOS_USER:$ONOS_GROUP $ONOS_HOME/config
-    [ ! -h $ONOS_HOME/log ]  && ln -s $ONOS_HOME/karaf/data/log $ONOS_HOME/log || :
+    mkdir -p $ONOS_HOME/apps 2>/dev/null && chown -R $ONOS_USER:$ONOS_GROUP $ONOS_HOME/apps
+    [ ! -h $ONOS_OME/karaf ] && ln -s /opt/onos/apache-karaf* $ONOS_HOME/karaf || :
+    [ ! -h $ONOS_HOME/log ] && ln -s $ONOS_HOME/karaf/data/log $ONOS_HOME/log || :
     # Start ONOS if it's not already running
     if ! status >/dev/null; then
         echo "Starting ONOS"
-        startonos $ONOS_HOME/bin/onos-service server $ONOS_OPTS
+        startonos $ONOS_HOME/bin/onos-service $ONOS_OPTS
     else
         echo "ONOS/karaf is already running"
     fi
@@ -47,21 +49,22 @@
         . /etc/init.d/functions && true
     fi
 
-    if type daemon | grep -i function >/dev/null 2>&1; then
+    if type daemon 2>/dev/null| grep -i function >/dev/null 2>&1; then
         # Use 'daemon' function if available
         # Shell metacharacters are passed as arguments to daemon
         daemon --user $ONOS_USER $cmd $* \
             \>$ONOS_HOME/var/stdout.log 2\>$ONOS_HOME/var/stderr.log \&
     elif type start-stop-daemon >/dev/null 2>&1; then
         # Use start-stop-daemon if available
-        # Warning! running as root can overwrite any linked log file
+        # Warning! Running as root can overwrite any linked log file.
         start-stop-daemon --signal INT --start --chuid $ONOS_USER \
             --background --exec $cmd -- $* \
             >$ONOS_HOME/var/stdout.log 2>$ONOS_HOME/var/stderr.log
     else
         # Fall back to using sudo
-        # Warning! running as root can overwrite any linked log file
-        sudo -E -n -u -b $ONOS_USER $cmd $* \
+        # Warning! Running as root can overwrite any linked log file.
+        # preserve Env, background, non-interactive, user $ONOS_USER
+        sudo -E -b -n -u $ONOS_USER $cmd $* \
             >$ONOS_HOME/var/stdout.log 2>$ONOS_HOME/var/stderr.log
     fi
 }
@@ -96,7 +99,7 @@
 case $1 in
     start)
         start
-	;;
+        ;;
     stop | force-stop)
         stop
         ;;
diff --git a/tools/package/init/onos.service b/tools/package/init/onos.service
new file mode 100644
index 0000000..bc9b890
--- /dev/null
+++ b/tools/package/init/onos.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Open Network Operating System
+After=network-online.target
+After=local-fs.target
+
+[Service]
+Type=forking
+ExecStart=/etc/init.d/onos start
+ExecStop=/etc/init.d/onos stop
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tools/test/bin/onos-install b/tools/test/bin/onos-install
index e9763ca..b6f9ee6 100755
--- a/tools/test/bin/onos-install
+++ b/tools/test/bin/onos-install
@@ -12,6 +12,7 @@
 - -f            : forces uninstall of currently installed ONOS
 - -u            : don't install onos.conf upstart configuration file
 - -i            : don't install /etc/init.d/onos script (also used by onos.conf)
+- -s            : don't install onos.service systemd configuration file
 - -n            : don't try to start ONOS
 - -m <settings> : pass <settings> XML file to remote maven installation
 
@@ -38,8 +39,9 @@
 while getopts fnm: o; do
     case "$o" in
         f) uninstall=true;;
-        u) noupstart=true; noinitd=true;;
-        i) noinitd=true;;
+        u) noupstart=true; noinitd=true; nosysd=true;;
+        i) noinitd=true; nosysd=true;;
+        s) nosysd=true;;
         n) nostart=true;;
         m) mvn_settings=$OPTARG;;
     esac
@@ -73,6 +75,7 @@
     # Install the configuration file(s) and set up options for debugging
     [ -n $noupstart ] && sudo cp $ONOS_INSTALL_DIR/init/onos.conf /etc/init/onos.conf
     [ -n $noinitd ] && sudo cp $ONOS_INSTALL_DIR/init/onos.initd /etc/init.d/onos
+    [ -n $nosysd ] && sudo cp $ONOS_INSTALL_DIR/init/onos.service /etc/systemd/system/onos.service
     echo 'export ONOS_OPTS=debug' > $ONOS_INSTALL_DIR/options
 
     # Set up correct user to run onos-service
diff --git a/tools/test/bin/onos-uninstall b/tools/test/bin/onos-uninstall
index cf767c4..557036f 100755
--- a/tools/test/bin/onos-uninstall
+++ b/tools/test/bin/onos-uninstall
@@ -39,6 +39,8 @@
     # Remove onos directory and init file
     [ -d $ONOS_INSTALL_DIR ] && sudo rm -fr $ONOS_INSTALL_DIR
     [ -f /etc/init/onos.conf ] && sudo rm -f /etc/init/onos.conf
+    [ -f /etc/init.d/onos ] && sudo rm -f /etc/init.d/onos
+    [ -f /etc/systemd/system/onos.service ] && sudo rm -f /etc/systemd/system/onos.service
 
     exit \${status:-0};
 "