diff options
Diffstat (limited to 'lib/syncthing')
-rw-r--r-- | lib/syncthing/st.go | 126 |
1 files changed, 95 insertions, 31 deletions
diff --git a/lib/syncthing/st.go b/lib/syncthing/st.go index e513876..5976e2f 100644 --- a/lib/syncthing/st.go +++ b/lib/syncthing/st.go @@ -2,9 +2,12 @@ package st import ( "encoding/json" + "io" "io/ioutil" "os" "path" + "path/filepath" + "regexp" "strings" "syscall" "time" @@ -22,47 +25,65 @@ import ( // SyncThing . type SyncThing struct { BaseURL string - ApiKey string + APIKey string Home string STCmd *exec.Cmd STICmd *exec.Cmd // Private fields binDir string + logsDir string exitSTChan chan ExitChan exitSTIChan chan ExitChan client *common.HTTPClient log *logrus.Logger } -// Monitor process exit +// ExitChan Channel used for process exit type ExitChan struct { status int err error } // NewSyncThing creates a new instance of Syncthing -//func NewSyncThing(url string, apiKey string, home string, log *logrus.Logger) *SyncThing { -func NewSyncThing(conf *xdsconfig.SyncThingConf, log *logrus.Logger) *SyncThing { - url := conf.GuiAddress - apiKey := conf.GuiAPIKey - home := conf.Home +func NewSyncThing(conf *xdsconfig.Config, log *logrus.Logger) *SyncThing { + var url, apiKey, home, binDir string + var err error + + stCfg := conf.FileConf.SThgConf + if stCfg != nil { + url = stCfg.GuiAddress + apiKey = stCfg.GuiAPIKey + home = stCfg.Home + binDir = stCfg.BinDir + } + + if url == "" { + url = "http://localhost:8384" + } + if url[0:7] != "http://" { + url = "http://" + url + } + + if home == "" { + home = "/mnt/share" + } + + if binDir == "" { + if binDir, err = filepath.Abs(filepath.Dir(os.Args[0])); err != nil { + binDir = "/usr/local/bin" + } + } s := SyncThing{ BaseURL: url, - ApiKey: apiKey, + APIKey: apiKey, Home: home, - binDir: conf.BinDir, + binDir: binDir, + logsDir: conf.FileConf.LogsDir, log: log, } - if s.BaseURL == "" { - s.BaseURL = "http://localhost:8384" - } - if s.BaseURL[0:7] != "http://" { - s.BaseURL = "http://" + s.BaseURL - } - return &s } @@ -84,28 +105,43 @@ func (s *SyncThing) startProc(exeName string, args []string, env []string, eChan cmd.Env = append(cmd.Env, ev) } + // open log file + var outfile *os.File + logFilename := filepath.Join(s.logsDir, exeName+".log") + if s.logsDir != "" { + outfile, err := os.Create(logFilename) + if err != nil { + return nil, fmt.Errorf("Cannot create log file %s", logFilename) + } + + cmdOut, err := cmd.StdoutPipe() + if err != nil { + return nil, fmt.Errorf("Pipe stdout error for : %s", err) + } + + go io.Copy(outfile, cmdOut) + } + err = cmd.Start() if err != nil { return nil, err } *eChan = make(chan ExitChan, 1) - go func(c *exec.Cmd) { + go func(c *exec.Cmd, oF *os.File) { status := 0 - cmdOut, err := c.StdoutPipe() - if err == nil { - s.log.Errorf("Pipe stdout error for : %s", err) - } else if cmdOut != nil { - stdOutput, _ := ioutil.ReadAll(cmdOut) - fmt.Printf("STDOUT: %s\n", stdOutput) - } sts, err := c.Process.Wait() if !sts.Success() { s := sts.Sys().(syscall.WaitStatus) status = s.ExitStatus() } + if oF != nil { + oF.Close() + } + s.log.Debugf("%s exited with status %d, err %v", exeName, status, err) + *eChan <- ExitChan{status, err} - }(cmd) + }(cmd, outfile) return cmd, nil } @@ -113,14 +149,19 @@ func (s *SyncThing) startProc(exeName string, args []string, env []string, eChan // Start Starts syncthing process func (s *SyncThing) Start() (*exec.Cmd, error) { var err error + + s.log.Infof(" ST home=%s", s.Home) + s.log.Infof(" ST url=%s", s.BaseURL) + args := []string{ "--home=" + s.Home, "-no-browser", "--gui-address=" + s.BaseURL, } - if s.ApiKey != "" { - args = append(args, "-gui-apikey=\""+s.ApiKey+"\"") + if s.APIKey != "" { + args = append(args, "-gui-apikey=\""+s.APIKey+"\"") + s.log.Infof(" ST apikey=%s", s.APIKey) } if s.log.Level == logrus.DebugLevel { args = append(args, "-verbose") @@ -132,38 +173,58 @@ func (s *SyncThing) Start() (*exec.Cmd, error) { s.STCmd, err = s.startProc("syncthing", args, env, &s.exitSTChan) + // Use autogenerated apikey if not set by config.json + if s.APIKey == "" { + if fd, err := os.Open(filepath.Join(s.Home, "config.xml")); err == nil { + defer fd.Close() + if b, err := ioutil.ReadAll(fd); err == nil { + re := regexp.MustCompile("<apikey>(.*)</apikey>") + key := re.FindStringSubmatch(string(b)) + if len(key) >= 1 { + s.APIKey = key[1] + } + } + } + } + return s.STCmd, err } // StartInotify Starts syncthing-inotify process func (s *SyncThing) StartInotify() (*exec.Cmd, error) { var err error + exeName := "syncthing-inotify" + + s.log.Infof(" STI url=%s", s.BaseURL) args := []string{ - "--home=" + s.Home, "-target=" + s.BaseURL, } + if s.APIKey != "" { + args = append(args, "-api="+s.APIKey) + s.log.Infof("%s uses apikey=%s", exeName, s.APIKey) + } if s.log.Level == logrus.DebugLevel { args = append(args, "-verbosity=4") } env := []string{} - s.STICmd, err = s.startProc("syncthing-inotify", args, env, &s.exitSTIChan) + s.STICmd, err = s.startProc(exeName, args, env, &s.exitSTIChan) return s.STICmd, err } func (s *SyncThing) stopProc(pname string, proc *os.Process, exit chan ExitChan) { if err := proc.Signal(os.Interrupt); err != nil { - s.log.Errorf("Proc interrupt %s error: %s", pname, err.Error()) + s.log.Infof("Proc interrupt %s error: %s", pname, err.Error()) select { case <-exit: case <-time.After(time.Second): // A bigger bonk on the head. if err := proc.Signal(os.Kill); err != nil { - s.log.Errorf("Proc term %s error: %s", pname, err.Error()) + s.log.Infof("Proc term %s error: %s", pname, err.Error()) } <-exit } @@ -207,6 +268,9 @@ func (s *SyncThing) Connect() error { if s.client == nil { return fmt.Errorf("ERROR: cannot connect to Syncthing (null client)") } + + s.client.SetLogger(s.log) + return nil } |