X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=main.go;h=6089e74b7dd0e69b065770f82a108ebd5a42f2ee;hb=17ab6663d5522bf4db3e6cce70352f8ba4379e99;hp=8d49babef23e1b7e069be6391d7de28392a6118e;hpb=61cd1a97e20d58e77470610cb8ee0bd2d5b6d395;p=src%2Fxds%2Fxds-server.git diff --git a/main.go b/main.go index 8d49bab..6089e74 100644 --- a/main.go +++ b/main.go @@ -7,13 +7,14 @@ import ( "os" "os/exec" "os/signal" - "strings" + "path/filepath" "syscall" "time" "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" "github.com/iotbzh/xds-server/lib/crosssdk" + "github.com/iotbzh/xds-server/lib/folder" "github.com/iotbzh/xds-server/lib/model" "github.com/iotbzh/xds-server/lib/syncthing" "github.com/iotbzh/xds-server/lib/webserver" @@ -40,17 +41,18 @@ var AppSubVersion = "unknown-dev" // Context holds the XDS server context type Context struct { - ProgName string - Cli *cli.Context - Config *xdsconfig.Config - Log *logrus.Logger - SThg *st.SyncThing - SThgCmd *exec.Cmd - SThgInotCmd *exec.Cmd - MFolder *model.Folder - SDKs *crosssdk.SDKs - WWWServer *webserver.Server - Exit chan os.Signal + ProgName string + Cli *cli.Context + Config *xdsconfig.Config + Log *logrus.Logger + LogLevelSilly bool + SThg *st.SyncThing + SThgCmd *exec.Cmd + SThgInotCmd *exec.Cmd + MFolders *model.Folders + SDKs *crosssdk.SDKs + WWWServer *webserver.Server + Exit chan os.Signal } // NewContext Create a new instance of XDS server @@ -70,12 +72,15 @@ func NewContext(cliCtx *cli.Context) *Context { } log.Formatter = &logrus.TextFormatter{} + sillyVal, sillyLog := os.LookupEnv("XDS_LOG_SILLY") + // Define default configuration ctx := Context{ - ProgName: cliCtx.App.Name, - Cli: cliCtx, - Log: log, - Exit: make(chan os.Signal, 1), + ProgName: cliCtx.App.Name, + Cli: cliCtx, + Log: log, + LogLevelSilly: (sillyLog && sillyVal == "1"), + Exit: make(chan os.Signal, 1), } // register handler on SIGTERM / exit @@ -98,7 +103,15 @@ func handlerSigTerm(ctx *Context) { ctx.Log.Infof("Stoping Web server...") ctx.WWWServer.Stop() } - os.Exit(1) + os.Exit(0) +} + +// Helper function to log message on both stdout and logger +func logPrint(ctx *Context, format string, args ...interface{}) { + fmt.Printf(format, args...) + if ctx.Log.Out != os.Stdout { + ctx.Log.Infof(format, args...) + } } // XDS Server application main routine @@ -111,38 +124,60 @@ func xdsApp(cliCtx *cli.Context) error { // Load config cfg, err := xdsconfig.Init(ctx.Cli, ctx.Log) if err != nil { - return cli.NewExitError(err, 2) + return cli.NewExitError(err, -2) } ctx.Config = cfg - // TODO allow to redirect stdout/sterr into logs file - //logFilename := filepath.Join(ctx.Config.FileConf.LogsDir + "xds-server.log") + // Logs redirected into a file when logfile option or logsDir config is set + ctx.Config.LogVerboseOut = os.Stderr + if ctx.Config.FileConf.LogsDir != "" { + if ctx.Config.Options.LogFile != "stdout" { + logFile := ctx.Config.Options.LogFile + + fdL, err := os.OpenFile(logFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + msgErr := fmt.Sprintf("Cannot create log file %s", logFile) + return cli.NewExitError(msgErr, int(syscall.EPERM)) + } + ctx.Log.Out = fdL + + logPrint(ctx, "Logging file: %s\n", logFile) + } - // FIXME - add a builder interface and support other builder type (eg. native) - builderType := "syncthing" + logFileHTTPReq := filepath.Join(ctx.Config.FileConf.LogsDir, "xds-server-verbose.log") + fdLH, err := os.OpenFile(logFileHTTPReq, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + msgErr := fmt.Sprintf("Cannot create log file %s", logFileHTTPReq) + return cli.NewExitError(msgErr, int(syscall.EPERM)) + } + ctx.Config.LogVerboseOut = fdLH - switch builderType { - case "syncthing": + logPrint(ctx, "Logging file for HTTP requests: %s\n", logFileHTTPReq) + } - // Start local instance of Syncthing and Syncthing-notify + // Create syncthing instance when section "syncthing" is present in config.json + if ctx.Config.FileConf.SThgConf != nil { ctx.SThg = st.NewSyncThing(ctx.Config, ctx.Log) + } + // Start local instance of Syncthing and Syncthing-notify + if ctx.SThg != nil { ctx.Log.Infof("Starting Syncthing...") ctx.SThgCmd, err = ctx.SThg.Start() if err != nil { - return cli.NewExitError(err, 2) + return cli.NewExitError(err, -4) } - fmt.Printf("Syncthing started (PID %d)\n", ctx.SThgCmd.Process.Pid) + logPrint(ctx, "Syncthing started (PID %d)\n", ctx.SThgCmd.Process.Pid) ctx.Log.Infof("Starting Syncthing-inotify...") ctx.SThgInotCmd, err = ctx.SThg.StartInotify() if err != nil { - return cli.NewExitError(err, 2) + return cli.NewExitError(err, -4) } - fmt.Printf("Syncthing-inotify started (PID %d)\n", ctx.SThgInotCmd.Process.Pid) + logPrint(ctx, "Syncthing-inotify started (PID %d)\n", ctx.SThgInotCmd.Process.Pid) // Establish connection with local Syncthing (retry if connection fail) - fmt.Printf("Establishing connection with Syncthing...\n") + logPrint(ctx, "Establishing connection with Syncthing...\n") time.Sleep(2 * time.Second) maxRetry := 30 retry := maxRetry @@ -156,60 +191,40 @@ func xdsApp(cliCtx *cli.Context) error { retry-- } if err != nil || retry == 0 { - return cli.NewExitError(err, 2) - } - - // Retrieve Syncthing config - id, err := ctx.SThg.IDGet() - if err != nil { - return cli.NewExitError(err, 2) - } - - if ctx.Config.Builder, err = xdsconfig.NewBuilderConfig(id); err != nil { - return cli.NewExitError(err, 2) - } - - // Retrieve initial Syncthing config - - // FIXME: cannot retrieve default SDK, need to save on disk or somewhere - // else all config to be able to restore it. - defaultSdk := "" - stCfg, err := ctx.SThg.ConfigGet() - if err != nil { - return cli.NewExitError(err, 2) + return cli.NewExitError(err, -4) } - for _, stFld := range stCfg.Folders { - relativePath := strings.TrimPrefix(stFld.RawPath, ctx.Config.ShareRootDir) - if relativePath == "" { - relativePath = stFld.RawPath - } - newFld := xdsconfig.NewFolderConfig(stFld.ID, stFld.Label, ctx.Config.ShareRootDir, strings.TrimRight(relativePath, "/"), defaultSdk) - ctx.Config.Folders = ctx.Config.Folders.Update(xdsconfig.FoldersConfig{newFld}) + // FIXME: do we still need Builder notion ? if no cleanup + if ctx.Config.Builder, err = xdsconfig.NewBuilderConfig(ctx.SThg.MyID); err != nil { + return cli.NewExitError(err, -4) } + ctx.Config.SupportedSharing[folder.TypeCloudSync] = true + } - // Init model folder - ctx.MFolder = model.NewFolder(ctx.Config, ctx.SThg) + // Init model folder + ctx.MFolders = model.FoldersNew(ctx.Config, ctx.SThg) - default: - err = fmt.Errorf("Unsupported builder type") - return cli.NewExitError(err, 3) + // Load initial folders config from disk + if err := ctx.MFolders.LoadConfig(); err != nil { + return cli.NewExitError(err, -5) } // Init cross SDKs ctx.SDKs, err = crosssdk.Init(ctx.Config, ctx.Log) if err != nil { - return cli.NewExitError(err, 2) + return cli.NewExitError(err, -6) } - // Create and start Web Server - ctx.WWWServer = webserver.New(ctx.Config, ctx.MFolder, ctx.SDKs, ctx.Log) + // Create Web Server + ctx.WWWServer = webserver.New(ctx.Config, ctx.MFolders, ctx.SDKs, ctx.Log, ctx.LogLevelSilly) + + // Run Web Server until exit requested (blocking call) if err = ctx.WWWServer.Serve(); err != nil { ctx.Log.Println(err) - return cli.NewExitError(err, 3) + return cli.NewExitError(err, -7) } - return cli.NewExitError("Program exited ", 4) + return cli.NewExitError("Program exited ", -99) } // main @@ -243,6 +258,17 @@ func main() { Usage: "logging level (supported levels: panic, fatal, error, warn, info, debug)\n\t", EnvVar: "LOG_LEVEL", }, + cli.StringFlag{ + Name: "logfile", + Value: "stdout", + Usage: "filename where logs will be redirected (default stdout)\n\t", + EnvVar: "LOG_FILENAME", + }, + cli.BoolFlag{ + Name: "no-folderconfig, nfc", + Usage: fmt.Sprintf("Do not read folder config file (%s)\n\t", xdsconfig.FoldersConfigFilename), + EnvVar: "NO_FOLDERCONFIG", + }, } // only one action: Web Server