Skip to content
This repository has been archived by the owner on Oct 22, 2021. It is now read-only.

Create pidfile and "bpm pid" command #11

Merged
merged 4 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
log "github.com/sirupsen/logrus"
"os"

cmd "code.cloudfoundry.org/quarks-container-run/cmd/containerrun"
Expand All @@ -10,6 +11,7 @@ import (
func main() {
pkg.WriteBPMscript()
if err := cmd.NewDefaultContainerRunCmd().Execute(); err != nil {
log.Errorf("container-run failed: %v", err)
os.Exit(1)
}
}
41 changes: 25 additions & 16 deletions pkg/containerrun/bpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ func WriteBPMscript() error {
script := `#!/bin/bash

function usage {
echo "usage: $0 [start|stop|quit|term|running] JOBNAME [-p PROCESSNAME]"
echo "usage: $0 [start|stop|quit|term|pid|running] JOBNAME [-p PROCESSNAME]"
exit 1
}

if [ $# != 2 -a $# != 4 ]; then
usage
fi
if [ "$1" != "start" -a "$1" != "stop" -a "$1" != "running" -a \
"$1" != "quit" -a "$1" != "term" ]
"$1" != "pid" -a "$1" != "quit" -a "$1" != "term" ]
then
usage
fi
Expand All @@ -37,6 +37,17 @@ if [ $# == 4 ]; then
PROCESS="$4"
fi

if [ "$CMD" == "pid" ]; then
PIDFILE="/var/vcap/sys/run/bpm/${JOB}/${PROCESS}.pid"
if [ -f "${PIDFILE}" ]; then
cat "${PIDFILE}"; echo
exit 0
else
echo "Process is not running"
exit 1
fi
fi

CONTAINER_RUN="/var/vcap/data/${JOB}/${PROCESS}_containerrun"
if [ "$CMD" == "running" ]; then
# Print yes/no if stdout is a tty
Expand All @@ -47,20 +58,18 @@ if [ "$CMD" == "running" ]; then
test -t 1 && echo "no"
exit 1
fi
else
# "term" is the same as "stop", except we won't wait
ACTION="${CMD/term/stop}"
# Send "START", "STOP", or "QUIT" over UDP to the unix socket
# with a 1 seconds timeout to establish the connection.
echo "${ACTION^^}" | nc -w 1 -uU "${CONTAINER_RUN}.sock"
if [ "${CMD}" == "stop" ]; then
for i in $(seq 30); do
test ! -f "${CONTAINER_RUN}.running" && exit 0
sleep 1
done
echo Process did not stop within 30 seconds
exit 1
fi
fi

# "term" is the same as "stop", except we won't wait
ACTION="${CMD/term/stop}"
echo "${ACTION^^}" | nc -w 1 -uU "${CONTAINER_RUN}.sock"
if [ "${CMD}" == "stop" ]; then
for i in $(seq 30); do
test ! -f "${CONTAINER_RUN}.running" && exit 0
sleep 1
done
echo Process did not stop within 30 seconds
exit 1
fi
`
if _, err := os.Stat(fileName); !os.IsNotExist(err) {
Expand Down
48 changes: 40 additions & 8 deletions pkg/containerrun/containerrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"os"
"os/exec"
"os/signal"
"path/filepath"
"strconv"
"strings"
"sync"
"syscall"
Expand Down Expand Up @@ -51,6 +53,12 @@ type CmdRun func(
postStartConditionCommandArgs []string,
) error

var basePath string = "/var/vcap"

func SetBasePath(newPath string) {
basePath = newPath
}

func Run(
runner Runner,
conditionRunner Runner,
Expand Down Expand Up @@ -231,7 +239,7 @@ func watchForCommands(
errors chan error,
commands chan processCommand,
) error {
sockAddr := fmt.Sprintf("/var/vcap/data/%s/%s_containerrun.sock", jobName, processName)
sockAddr := fmt.Sprintf("%s/data/%s/%s_containerrun.sock", basePath, jobName, processName)

go func() {
for {
Expand Down Expand Up @@ -346,21 +354,38 @@ func startMainProcess(
}
processRegistry.Register(process)

sentinel := fmt.Sprintf("/var/vcap/data/%s/%s_containerrun.running", jobName, processName)
file, _ := os.Create(sentinel)
_ = file.Close()
sentinel := fmt.Sprintf("%s/data/%s/%s_containerrun.running", basePath, jobName, processName)
err = os.MkdirAll(filepath.Dir(sentinel), 0755)
if err != nil {
return err
}
err = ioutil.WriteFile(sentinel, nil, 0755)
jandubois marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}
pidfile := fmt.Sprintf("%s/sys/run/bpm/%s/%s.pid", basePath, jobName, processName)
err = os.MkdirAll(filepath.Dir(pidfile), 0755)
if err != nil {
return err
}
err = ioutil.WriteFile(pidfile, []byte(strconv.Itoa(process.Pid())), 0755)
if err != nil {
return err
}

go func() {
if err := process.Wait(); err != nil {
log.Debugf("Process has failed with error: %s\n", err)
processRegistry.Unregister(process)
os.Remove(sentinel)
_ = os.Remove(sentinel)
_ = os.Remove(pidfile)
errors <- &runErr{err}
return
}
log.Debugln("Process has ended normally")
processRegistry.Unregister(process)
os.Remove(sentinel)
_ = os.Remove(sentinel)
_ = os.Remove(pidfile)
done <- struct{}{}
}()

Expand Down Expand Up @@ -468,7 +493,7 @@ func (cr *ContainerRunner) run(
if err := cmd.Start(); err != nil {
return nil, fmt.Errorf("failed to run command: %v", err)
}
return NewContainerProcess(cmd.Process), nil
return NewContainerProcess(cmd.Process, cmd.Process.Pid), nil
}

// ConditionRunner satisfies the Runner interface. It represents a runner for a post-start
Expand Down Expand Up @@ -521,6 +546,7 @@ func (cr *ConditionRunner) RunContext(

// Process is the interface that wraps the Signal and Wait methods of a process.
type Process interface {
Pid() int
Signal(os.Signal) error
Wait() error
}
Expand All @@ -534,12 +560,14 @@ type OSProcess interface {
// ContainerProcess satisfies the Process interface.
type ContainerProcess struct {
process OSProcess
pid int
}

// NewContainerProcess constructs a new ContainerProcess.
func NewContainerProcess(process OSProcess) *ContainerProcess {
func NewContainerProcess(process OSProcess, pid int) *ContainerProcess {
return &ContainerProcess{
process: process,
pid: pid,
}
}

Expand Down Expand Up @@ -567,6 +595,10 @@ func (p *ContainerProcess) Wait() error {
return nil
}

func (p *ContainerProcess) Pid() int {
return p.pid
}

// Stdio represents the STDOUT and STDERR to be used by a process.
type Stdio struct {
Out io.Writer
Expand Down
Loading