Skip to content

Commit

Permalink
Auto-Detect Running Service
Browse files Browse the repository at this point in the history
This patch handles issue #589 so that a REX-Ray client will
automatically detect a running libStorage service if it was started by
REX-Ray, even via embedded mode. This means that even if the REX-Ray
configuration file relies on auto-service mode where a host is not
explicitly defined, if a libStorage server is started in this manner,
subsequent REX-Ray executions will not start additional servers, instead
attaching to the existing service.
  • Loading branch information
akutz committed Dec 4, 2016
1 parent 4e778fa commit 5322db1
Showing 1 changed file with 77 additions and 16 deletions.
93 changes: 77 additions & 16 deletions util/util.go
Expand Up @@ -5,10 +5,12 @@ import (
"io"
"os"
"os/exec"
"path"
"regexp"
"strconv"
"time"

log "github.com/Sirupsen/logrus"
gofig "github.com/akutz/gofig/types"
"github.com/akutz/gotil"
apiversion "github.com/codedellemc/libstorage/api"
Expand Down Expand Up @@ -51,6 +53,7 @@ var (
runDirPath string
etcDirPath string
pidFilePath string
spcFilePath string
)

func init() {
Expand All @@ -77,6 +80,7 @@ func Prefix(p string) {
runDirPath = ""
etcDirPath = ""
pidFilePath = ""
spcFilePath = ""

prefix = p
}
Expand Down Expand Up @@ -146,13 +150,13 @@ func LibDirPath() string {
// LibFilePath returns the path to a file inside the REX-Ray lib directory
// with the provided file name.
func LibFilePath(fileName string) string {
return fmt.Sprintf("%s/%s", LibDirPath(), fileName)
return path.Join(LibDirPath(), fileName)
}

// RunFilePath returns the path to a file inside the REX-Ray run directory
// with the provided file name.
func RunFilePath(fileName string) string {
return fmt.Sprintf("%s/%s", RunDirPath(), fileName)
return path.Join(RunDirPath(), fileName)
}

// BinDirPath returns the path to the REX-Ray bin directory.
Expand All @@ -167,29 +171,37 @@ func BinDirPath() string {
// PidFilePath returns the path to the REX-Ray PID file.
func PidFilePath() string {
if pidFilePath == "" {
pidFilePath = fmt.Sprintf("%s/rexray.pid", RunDirPath())
pidFilePath = RunFilePath("rexray.pid")
}
return pidFilePath
}

// SpecFilePath returns the path to the REX-Ray spec file.
func SpecFilePath() string {
if spcFilePath == "" {
spcFilePath = RunFilePath("rexray.spec")
}
return spcFilePath
}

// BinFilePath returns the path to the REX-Ray executable.
func BinFilePath() string {
if binFilePath == "" {
binFilePath = fmt.Sprintf("%s/rexray", BinDirPath())
binFilePath = path.Join(BinDirPath(), "rexray")
}
return binFilePath
}

// EtcFilePath returns the path to a file inside the REX-Ray etc directory
// with the provided file name.
func EtcFilePath(fileName string) string {
return fmt.Sprintf("%s/%s", EtcDirPath(), fileName)
return path.Join(EtcDirPath(), fileName)
}

// LogFilePath returns the path to a file inside the REX-Ray log directory
// with the provided file name.
func LogFilePath(fileName string) string {
return fmt.Sprintf("%s/%s", LogDirPath(), fileName)
return path.Join(LogDirPath(), fileName)
}

// LogFile returns a writer to a file inside the REX-Ray log directory
Expand All @@ -211,30 +223,39 @@ func StdOutAndLogFile(fileName string) (io.Writer, error) {

// WritePidFile writes the current process ID to the REX-Ray PID file.
func WritePidFile(pid int) error {

if pid < 0 {
pid = os.Getpid()
}

return gotil.WriteStringToFile(fmt.Sprintf("%d", pid), PidFilePath())
}

// ReadPidFile reads the REX-Ray PID from the PID file.
func ReadPidFile() (int, error) {

pidStr, pidStrErr := gotil.ReadFileToString(PidFilePath())
if pidStrErr != nil {
return -1, pidStrErr
}

pid, atoiErr := strconv.Atoi(pidStr)
if atoiErr != nil {
return -1, atoiErr
}

return pid, nil
}

// WriteSpecFile writes the current host address to the REX-Ray spec file.
func WriteSpecFile(host string) error {
return gotil.WriteStringToFile(host, SpecFilePath())
}

// ReadSpecFile reads the REX-Ray host address from the spec file.
func ReadSpecFile() (string, error) {
host, err := gotil.ReadFileToString(SpecFilePath())
if err != nil {
return "", err
}
return gotil.Trim(host), nil
}

// PrintVersion prints the current version information to the provided writer.
func PrintVersion(out io.Writer) {
fmt.Fprintln(out, "REX-Ray")
Expand Down Expand Up @@ -289,7 +310,18 @@ var localHostRX = regexp.MustCompile(
func IsLocalServerActive(
ctx apitypes.Context, config gofig.Config) (host string, running bool) {

host = config.GetString(apitypes.ConfigHost)
if gotil.FileExists(SpecFilePath()) {
if h, _ := ReadSpecFile(); h != "" {
host = h
ctx.WithFields(log.Fields{
"path": SpecFilePath(),
"host": host,
}).Debug("read spec file")
}
}
if host == "" {
host = config.GetString(apitypes.ConfigHost)
}
if host == "" {
return "", false
}
Expand Down Expand Up @@ -355,15 +387,15 @@ func ActivateLibStorage(
if !config.GetBool(apitypes.ConfigEmbedded) {
ctx.WithField(
"host", host,
).Debug("not starting embeddded server; embedded mode disabled")
).Debug("not starting embedded server; embedded mode disabled")
return ctx, config, nil, nil
}
}

if host, isRunning = IsLocalServerActive(ctx, config); isRunning {
ctx = ctx.WithValue(context.HostKey, host)
ctx.WithField("host", host).Debug(
"not starting embeddded server; already running")
"not starting embedded server; already running")
return ctx, config, nil, nil
}

Expand All @@ -381,14 +413,43 @@ func ActivateLibStorage(
return ctx, config, nil, err
}

wroteSpecFile := false

go func() {
if err := <-errs; err != nil {
err := <-errs
if err != nil {
ctx.Error(err)
}
if wroteSpecFile {
if err := os.Remove(SpecFilePath()); err == nil {
ctx.WithFields(log.Fields{
"path": SpecFilePath(),
"host": host,
}).Debug("removed spec file")
}
}
}()

if host == "" {
config.Set(apitypes.ConfigHost, server.Addrs()[0])
host = server.Addrs()[0]
ctx.WithField("host", host).Debug("got host from new server address")
}

if h := config.GetString(apitypes.ConfigHost); h == "" {
config.Set(apitypes.ConfigHost, host)
ctx.WithField("host", host).Debug("set host in config")
}

// write the host to the spec file so that other rex-ray invocations can
// find it, even if running as an embedded libStorage server
if !gotil.FileExists(SpecFilePath()) {
if err := WriteSpecFile(host); err == nil {
ctx.WithFields(log.Fields{
"path": SpecFilePath(),
"host": host,
}).Debug("created spec file")
wroteSpecFile = true
}
}

return ctx, config, errs, nil
Expand Down

0 comments on commit 5322db1

Please sign in to comment.