瀏覽代碼

Work on deb and rpm packages, both seem to work now, #1476

Torkel Ödegaard 10 年之前
父節點
當前提交
0db55b6194
共有 10 個文件被更改,包括 202 次插入121 次删除
  1. 2 1
      Gruntfile.js
  2. 12 10
      build.go
  3. 6 0
      docker/rpmtest/Dockerfile
  4. 10 0
      docker/rpmtest/build.sh
  5. 13 0
      main.go
  6. 24 0
      pkg/cmd/web.go
  7. 2 0
      pkg/setting/data/log/grafana.log
  8. 132 72
      scripts/init.sh
  9. 0 1
      tasks/distribute_task.js
  10. 1 37
      tasks/options/compress.js

+ 2 - 1
Gruntfile.js

@@ -8,7 +8,8 @@ module.exports = function (grunt) {
     srcDir: 'src',
     destDir: 'dist',
     tempDir: 'tmp',
-    docsDir: 'docs/'
+    docsDir: 'docs/',
+    arch: grunt.option('arch') || 'x86_64',
   };
 
   // load plugins

+ 12 - 10
build.go

@@ -73,11 +73,11 @@ func main() {
 			test("./pkg/...")
 
 		case "package":
-			clean()
+			//clean()
 			//verifyGitRepoIsClean()
-			test("./pkg/...")
-			build(".", []string{})
-			buildFrontend()
+			//test("./pkg/...")
+			//build(".", []string{})
+			//buildFrontend()
 			createRpmAndDeb()
 
 		case "build-ui":
@@ -121,24 +121,22 @@ func createRpmAndDeb() {
 	runError("mkdir", "-p", configDir)
 
 	// copy sample ini file to /etc/opt/grafana
-	runError("cp", "conf/sample.ini", filepath.Join(configDir, "grafana.ini"))
+	configFile := filepath.Join(configDir, "grafana.ini")
+	runError("cp", "conf/sample.ini", configFile)
 	// copy release files
 	runError("cp", "-a", filepath.Join(workingDir, "tmp")+"/.", versionFolder)
 
-	fmt.Printf("PackageDir: %v\n", versionFolder)
-
 	GeneratePostInstallScript(postInstallScriptPath.Name())
-	fmt.Printf("script_path: %v\n", postInstallScriptPath.Name())
 
 	args := []string{
 		"-s", "dir",
-		"-t", "deb",
 		"--description", "Grafana",
 		"-C", packageRoot,
 		"--vendor", "Grafana",
 		"--url", "http://grafana.org",
 		"--license", "Apache 2.0",
 		"--maintainer", "contact@grafana.org",
+		"--config-files", filepath.Join(configRoot, "grafana.ini"),
 		"--after-install", postInstallScriptPath.Name(),
 		"--name", "grafana",
 		"--version", version,
@@ -146,7 +144,11 @@ func createRpmAndDeb() {
 		".",
 	}
 
-	runPrint("fpm", args...)
+	fmt.Println("Creating debian package")
+	runPrint("fpm", append([]string{"-t", "deb"}, args...)...)
+
+	fmt.Println("Creating redhat/centos package")
+	runPrint("fpm", append([]string{"-t", "rpm"}, args...)...)
 }
 
 func GeneratePostInstallScript(path string) {

+ 6 - 0
docker/rpmtest/Dockerfile

@@ -0,0 +1,6 @@
+FROM centos:7
+
+RUN yum install -y initscripts
+
+ADD *.rpm /tmp/
+

+ 10 - 0
docker/rpmtest/build.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+
+cp Dockerfile ../../dist
+cd ../../dist
+
+docker build --tag "grafana/rpmtest" .
+
+rm Dockerfile
+
+docker run -i -t grafana/rpmtest /bin/bash

+ 13 - 0
main.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"os"
+	"os/signal"
 	"runtime"
 	"strconv"
 
@@ -27,6 +28,13 @@ func main() {
 	setting.BuildCommit = commit
 	setting.BuildStamp = buildstampInt64
 
+	go func() {
+		c := make(chan os.Signal, 1)
+		signal.Notify(c, os.Interrupt)
+		<-c
+		os.Exit(0)
+	}()
+
 	app := cli.NewApp()
 	app.Name = "Grafana Backend"
 	app.Usage = "grafana web"
@@ -46,7 +54,12 @@ func main() {
 			Name:  "config",
 			Usage: "path to grafana.ini config file",
 		},
+		cli.StringFlag{
+			Name:  "pidfile",
+			Usage: "path to pidfile",
+		},
 	}...)
+
 	app.Run(os.Args)
 
 	log.Close()

+ 24 - 0
pkg/cmd/web.go

@@ -5,8 +5,12 @@ package cmd
 
 import (
 	"fmt"
+	"io/ioutil"
 	"net/http"
+	"os"
 	"path"
+	"path/filepath"
+	"strconv"
 
 	"github.com/Unknwon/macaron"
 	"github.com/codegangsta/cli"
@@ -68,6 +72,7 @@ func mapStatic(m *macaron.Macaron, dir string, prefix string) {
 
 func runWeb(c *cli.Context) {
 	initRuntime(c)
+	writePIDFile(c)
 
 	social.NewOAuthService()
 	eventpublisher.Init()
@@ -92,3 +97,22 @@ func runWeb(c *cli.Context) {
 		log.Fatal(4, "Fail to start server: %v", err)
 	}
 }
+
+func writePIDFile(c *cli.Context) {
+	path := c.GlobalString("pidfile")
+	if path == "" {
+		return
+	}
+
+	// Ensure the required directory structure exists.
+	err := os.MkdirAll(filepath.Dir(path), 0700)
+	if err != nil {
+		log.Fatal(3, "Failed to verify pid directory", err)
+	}
+
+	// Retrieve the PID and write it.
+	pid := strconv.Itoa(os.Getpid())
+	if err := ioutil.WriteFile(path, []byte(pid), 0644); err != nil {
+		log.Fatal(3, "Failed to write pidfile", err)
+	}
+}

+ 2 - 0
pkg/setting/data/log/grafana.log

@@ -4,3 +4,5 @@
 2015/03/03 10:09:13 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
 2015/03/03 10:09:34 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
 2015/03/03 10:15:20 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
+2015/03/03 12:29:29 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
+2015/03/03 12:33:09 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER

+ 132 - 72
scripts/init.sh

@@ -1,19 +1,21 @@
-#!/bin/sh
+#! /usr/bin/env bash
+
 ### BEGIN INIT INFO
 # Provides:          grafana
-# Required-Start:    $local_fs $remote_fs $network
-# Required-Stop:     $local_fs $remote_fs $network
+# Required-Start:    $all
+# Required-Stop:     $remote_fs $syslog
 # Default-Start:     2 3 4 5
 # Default-Stop:      0 1 6
-# Short-Description: Starts grafana at startup
-# Description:       Starts grafana at startup
+# Short-Description: Start grafana at boot time
 ### END INIT INFO
 
+#  tested on
+#  1. New lsb that define start-stop-daemon
+#  3. Centos with initscripts package installed
 
-# Documentation available at
-# http://refspecs.linuxfoundation.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptfunc.html
-# Debian provides some extra functions though
-. /lib/lsb/init-functions
+if [ -r /lib/lsb/init-functions ]; then
+    source /lib/lsb/init-functions
+fi
 
 DAEMON_NAME="grafana"
 DAEMON_USER="grafana"
@@ -24,85 +26,143 @@ DAEMON_PID="/var/run/${DAEMON_NAME}.pid"
 DAEMON_NICE=0
 DAEMON_LOG='/var/log/grafana/grafana.log'
 
-[ -r "/etc/default/${DAEMON_NAME}" ] && . "/etc/default/${DAEMON_NAME}"
+# If the daemon is not there, then exit.
+[ -x $DAEMON_PATH ] || exit 5
+
+if [ "x$STDOUT" == "x" ]; then
+    STDOUT=/tmp/grafana.log
+fi
+
+function pidofproc() {
+    if [ $# -ne 3 ]; then
+        echo "Expected three arguments, e.g. $0 -p pidfile daemon-name"
+    fi
+
+    pid=`pgrep -f $3`
+    local pidfile=`cat $2`
+
+    if [ "x$pidfile" == "x" ]; then
+        return 1
+    fi
+
+    if [ "x$pid" != "x" -a "$pidfile" == "$pid" ]; then
+        return 0
+    fi
+
+    return 1
+}
+
+function killproc() {
+    if [ $# -ne 3 ]; then
+        echo "Expected three arguments, e.g. $0 -p pidfile signal"
+    fi
+
+    pid=`cat $2`
+
+    kill -s $3 $pid
+}
+
+function log_failure_msg() {
+    echo "$@" "[ FAILED ]"
+}
+
+function log_success_msg() {
+    echo "$@" "[ OK ]"
+}
 
 do_start() {
-  local result
+  cd $DAEMON_PWD
+
+  # Checked the PID file exists and check the actual status of process
+  if [ -e $DAEMON_PID ]; then
+    pidofproc -p $DAEMON_PID $DAEMON_PATH > /dev/null 2>&1 && status="0" || status="$?"
+    # If the status is SUCCESS then don't need to start again.
+    if [ "x$status" = "x0" ]; then
+      log_failure_msg "$DAEMON_NAME process is running"
+      exit 1 # Exit
+    fi
+  fi
+  # Start the daemon.
+  log_success_msg "Starting the process" "$DAEMON_NAME"
 
-        pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
-        if [ $? -eq 0 ]; then
-                log_warning_msg "${DAEMON_NAME} is already started"
-                result=0
-        else
-                log_daemon_msg "Starting ${DAEMON_DESC}" "${DAEMON_NAME}"
-                touch "${DAEMON_LOG}"
-                chown $DAEMON_USER "${DAEMON_LOG}"
-                chmod u+rw "${DAEMON_LOG}"
-                if [ -z "${DAEMON_USER}" ]; then
-                        start-stop-daemon --start --quiet --oknodo --background \
-                                --nicelevel $DAEMON_NICE \
-                                --chdir "${DAEMON_PWD}" \
-                                --pidfile "${DAEMON_PID}" --make-pidfile \
-                                --exec "${DAEMON_PATH}" -- $DAEMON_OPTS
-                        result=$?
-                else
-                        start-stop-daemon --start --quiet --oknodo --background \
-                                --nicelevel $DAEMON_NICE \
-                                --chdir "${DAEMON_PWD}" \
-                                --pidfile "${DAEMON_PID}" --make-pidfile \
-                                --chuid "${DAEMON_USER}" \
-                                --exec  "${DAEMON_PATH}" -- $DAEMON_OPTS
-                        result=$?
-                fi
-                log_end_msg $result
-        fi
-        return $result
+  # Start the daemon with the help of start-stop-daemon
+  # Log the message appropriately
+  if which start-stop-daemon > /dev/null 2>&1; then
+    start-stop-daemon \
+      --start --quiet --oknodo --background \
+      --nicelevel $DAEMON_NICE \
+      --chdir "${DAEMON_PWD}" \
+      --pidfile "${DAEMON_PID}" --make-pidfile \
+      --chuid "${DAEMON_USER}" \
+      --exec  "${DAEMON_PATH}" -- $DAEMON_OPTS
+    result=$?
+  else
+    touch ${DAEMON_PID}
+    chown $DAEMON_USER "${DAEMON_PID}"
+    #daemon --user $DAEMON_USER --pidfile $DAEMON_PID nohup $DAEMON_PATH $DAEMON_OPTS
+    su -s /bin/sh -c "nohup ${DAEMON_PATH} --pidfile=${DAEMON_PID} ${DAEMON_OPTS} >> $STDOUT 3>&1 &" $DAEMON_USER
+  fi
+
+  log_success_msg "$DAEMON_NAME process was started"
 }
 
 do_stop() {
-        local result
-
-        pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
-        if [ $? -ne 0 ]; then
-                log_warning_msg "${DAEMON_NAME} is not started"
-                result=0
-        else
-                log_daemon_msg "Stopping ${DAEMON_DESC}" "${DAEMON_NAME}"
-                killproc -p "${DAEMON_PID}" "${DAEMON_PATH}"
-                result=$?
-                log_end_msg $result
-                rm "${DAEMON_PID}"
-        fi
-        return $result
+  local result
+
+  pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
+  if [ $? -ne 0 ]; then
+    log_failure_msg "${DAEMON_NAME} is not started"
+    result=0
+  else
+    log_success_msg "Stopping ${DAEMON_NAME}"
+    killproc -p "${DAEMON_PID}" SIGTERM
+    result=$?
+    if [ $result = 0 ]; then
+      log_success_msg "Stopped ${DAEMON_NAME}"
+      rm "${DAEMON_PID}"
+    fi
+  fi
+
+  return $result
 }
 
 do_restart() {
-        local result
-        do_stop
-        result=$?
-        if [ $result = 0 ]; then
-                do_start
-                result=$?
-        fi
-        return $result
+  local result
+  do_stop
+  result=$?
+  sleep 2
+  if [ $result = 0 ]; then
+    do_start
+    result=$?
+  fi
+  return $result
 }
 
 do_status() {
-        local result
-        status_of_proc -p "${DAEMON_PID}" "${DAEMON_PATH}" "${DAEMON_NAME}"
-        result=$?
-        return $result
+  if [ -e $DEAMON_PID ]; then
+    pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
+    if [ $? -ne 0 ]; then
+      log_failure_msg "$DAEMON_NAME Process is not running"
+      exit 1
+    else
+      log_success_msg "$DAEMON_NAME Process is running"
+      exit 0
+    fi
+  else
+    log_failure_msg "$DAEMON_NAME Process is not running"
+    exit 3
+  fi
 }
 
 do_usage() {
-        echo $"Usage: $0 {start | stop | restart | status}"
-        exit 1
+  echo $"Usage: $0 {start | stop | restart | status}"
+  exit 1
 }
 
 case "$1" in
-start)   do_start;   exit $? ;;
-stop)    do_stop;    exit $? ;;
-restart) do_restart; exit $? ;;
-status)  do_status;  exit $? ;;
-*)       do_usage;   exit  1 ;;
+  start)   do_start;   exit $? ;;
+  stop)    do_stop;    exit $? ;;
+  restart) do_restart; exit $? ;;
+  status)  do_status;  exit $? ;;
+  *)       do_usage;   exit  1 ;;
 esac

+ 0 - 1
tasks/distribute_task.js

@@ -5,7 +5,6 @@ module.exports = function(grunt) {
   grunt.registerTask('release', [
     'build',
     'build-post-process',
-    'compress:zip_release',
     'compress:tgz_release',
   ]);
 

+ 1 - 37
tasks/options/compress.js

@@ -1,23 +1,5 @@
 module.exports = function(config) {
   return {
-    zip: {
-      options: {
-        archive: '<%= destDir %>/<%= pkg.name %>-latest.zip'
-      },
-      files : [
-        {
-          expand: true,
-          cwd: '<%= tempDir %>',
-          src: ['**/*'],
-          dest: '<%= pkg.name %>/',
-        },
-        {
-          expand: true,
-          dest: '<%= pkg.name %>/',
-          src: ['LICENSE.md', 'README.md', 'NOTICE.md'],
-        }
-      ]
-    },
     tgz: {
       options: {
         archive: '<%= destDir %>/<%= pkg.name %>-latest.tar.gz'
@@ -36,27 +18,9 @@ module.exports = function(config) {
         }
       ]
     },
-    zip_release: {
-      options: {
-        archive: '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.zip'
-      },
-      files : [
-        {
-          expand: true,
-          cwd: '<%= tempDir %>',
-          src: ['**/*'],
-          dest: '<%= pkg.name %>-<%= pkg.version %>/',
-        },
-        {
-          expand: true,
-          src: ['LICENSE.md', 'README.md', 'NOTICE.md'],
-          dest: '<%= pkg.name %>-<%= pkg.version %>/',
-        }
-      ]
-    },
     tgz_release: {
       options: {
-        archive: '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.tar.gz'
+        archive: '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.<%= arch %>.tar.gz'
       },
       files : [
         {