// serve starts the libStorage server, blocking the current thread until the // server is shutdown. // // char* host the golang network-style address. if no value is provided // then a random TCP port bound to localhost is used // // short argc the length of the argv array // // void* argv a pointer to an array of char* strings that represent the // drivers and corresponding service names to load. if the // array is odd-numbered then the service for the trailing // driver takes the name of the driver // // char* serve(char* host, int argc, void* argv); //export serve func serve( host *C.char, argc C.int, argv unsafe.Pointer) *C.char { iargc := int(argc) args := make([]string, iargc) pargv := argv for x := 0; x < iargc; x++ { gostr := C.GoString((*C.char)(pargv)) log.WithFields(log.Fields{ "x": x, "gostr": gostr, }).Info("parsed gostr") args[x] = gostr pargv = unsafe.Pointer(uintptr(pargv) + unsafe.Sizeof(gostr)) } szHost := C.GoString(host) log.WithFields(log.Fields{ "host": szHost, "args": args, }).Info("serving") config, err := apicfg.NewConfig() if err != nil { return C.CString(err.Error()) } if len(szHost) > 0 { os.Setenv("LIBSTORAGE_HOST", szHost) } _, errs, err := server.Serve(nil, config) if err != nil { return C.CString(err.Error()) } <-errs return nil }
// Run the server. func Run() { server.CloseOnAbort() flag.Usage = printUsage flag.Parse() if flagVersion != nil && *flagVersion { _, _, thisExeAbsPath := gotil.GetThisPathParts() fmt.Fprintf(os.Stdout, "Binary: %s\n", thisExeAbsPath) fmt.Fprint(os.Stdout, api.Version.String()) os.Exit(0) } if flagEnv != nil && *flagEnv { for _, v := range os.Environ() { fmt.Fprintf(os.Stdout, "%s\n", v) } os.Exit(0) } // if a config is specified then do not care about any other options if flagConfig != nil && gotil.FileExists(*flagConfig) { config = gofigCore.New() if err := config.ReadConfigFile(*flagConfig); err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } if flagPrintConfig != nil && *flagPrintConfig { jstr, err := config.ToJSON() if err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } fmt.Fprintln(os.Stdout, jstr) os.Exit(0) } s, errs, err := server.Serve(nil, config) if err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } err = <-errs if err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } s.Close() os.Exit(0) } cfg, err := apiconfig.NewConfig() if err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } config = cfg for _, fs := range config.FlagSets() { flag.CommandLine.AddFlagSet(fs) } if flagHelp != nil && *flagHelp { flag.Usage() } if len(flag.Args()) == 0 { flag.Usage() } if flagHost != nil { os.Setenv("LIBSTORAGE_HOST", *flagHost) } if flagLogLvl != nil { os.Setenv("LIBSTORAGE_LOGGING_LEVEL", *flagLogLvl) } if lvl, err := log.ParseLevel( config.GetString(apitypes.ConfigLogLevel)); err == nil { log.SetLevel(lvl) } if flagPrintConfig != nil && *flagPrintConfig { jstr, err := config.ToJSON() if err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } fmt.Fprintln(os.Stdout, jstr) os.Exit(0) } buf := &bytes.Buffer{} fmt.Fprintf(buf, "libstorage:\n server:\n services:\n") for _, ds := range flag.Args() { dsp := strings.Split(ds, ":") dn := dsp[0] sn := dsp[0] if len(dsp) > 1 { sn = dsp[1] } fmt.Fprintf(buf, " %s:\n driver: %s\n", sn, dn) } if err := config.ReadConfig(buf); err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } server.CloseOnAbort() _, errs, err := server.Serve(nil, config) if err != nil { fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) os.Exit(1) } <-errs }
func (th *testHarness) run( t *testing.T, clientType types.ClientType, driver string, configBuf []byte, debug, group bool, tests ...APITestFunc) { if !testing.Verbose() { buf := &bytes.Buffer{} log.StandardLogger().Out = buf defer func() { if t.Failed() { io.Copy(os.Stderr, buf) } }() } wg := &sync.WaitGroup{} if group { config := getTestConfig(t, clientType, configBuf, debug) configNames, configs := getTestConfigs(t, driver, config) for x, config := range configs { wg.Add(1) go func(x int, config gofig.Config) { defer wg.Done() server, errs, err := apiserver.Serve(nil, config) if err != nil { th.closeServers(t) t.Fatal(err) } go func() { err := <-errs if err != nil { th.closeServers(t) t.Fatalf("server (%s) error: %v", configNames[x], err) } }() th.servers = append(th.servers, server) c, err := client.New(nil, config) assert.NoError(t, err) assert.NotNil(t, c) if err != nil || c == nil { t.Fatalf("err=%v, client=%v", err, c) } for _, test := range tests { test(config, c, t) if t.Failed() && printConfigOnFail { cj, err := config.ToJSON() if err != nil { t.Fatal(err) } fmt.Printf("client.config=%s\n", cj) } } }(x, config) } } else { for _, test := range tests { config := getTestConfig(t, clientType, configBuf, debug) configNames, configs := getTestConfigs(t, driver, config) for x, config := range configs { wg.Add(1) go func(test APITestFunc, x int, config gofig.Config) { defer wg.Done() server, errs, err := apiserver.Serve(nil, config) if err != nil { th.closeServers(t) t.Fatal(err) } go func() { err := <-errs if err != nil { th.closeServers(t) t.Fatalf("server (%s) error: %v", configNames[x], err) } }() th.servers = append(th.servers, server) c, err := client.New(nil, config) if err != nil { t.Fatal(err) } assert.NoError(t, err) assert.NotNil(t, c) if c == nil { panic(fmt.Sprintf("err=%v, client=%v", err, c)) } test(config, c, t) if t.Failed() && printConfigOnFail { cj, err := config.ToJSON() if err != nil { t.Fatal(err) } fmt.Printf("client.config=%s\n", cj) } }(test, x, config) } } } wg.Wait() th.closeServers(t) }
func activateLibStorage( ctx apitypes.Context, config gofig.Config) (apitypes.Context, gofig.Config, <-chan error, error) { apiserver.DisableStartupInfo = true var ( host string err error isRunning bool errs chan error serverErrChan <-chan error server apitypes.Server ) if host = config.GetString(apitypes.ConfigHost); host != "" { if !config.GetBool(apitypes.ConfigEmbedded) { ctx.WithField( "host", host, ).Debug("not starting embedded server; embedded mode disabled") return ctx, config, nil, nil } } if host, isRunning = IsLocalServerActive(ctx, config); isRunning { ctx = setHost(ctx, config, host) ctx.WithField("host", host).Debug( "not starting embedded server; already running") return ctx, config, nil, nil } // if no host was specified then see if a set of default services need to // be initialized if host == "" { ctx.Debug("host is empty; initiliazing default services") if err = initDefaultLibStorageServices(ctx, config); err != nil { ctx.WithError(err).Error("error initializing default services") return ctx, config, nil, err } } ctx.Debug("starting embedded libStorage server") if server, serverErrChan, err = apiserver.Serve(ctx, config); err != nil { ctx.WithError(err).Error("error starting libStorage server") return ctx, config, nil, err } if host == "" { host = server.Addrs()[0] ctx.WithField("host", host).Debug("got host from new server address") } ctx = setHost(ctx, config, host) errs = make(chan error) go func() { for err := range serverErrChan { if err != nil { errs <- err } } if err := os.RemoveAll(SpecFilePath()); err == nil { logHostSpec(ctx, host, "removed spec file") } close(errs) }() // 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 err := WriteSpecFile(host); err != nil { specFile := SpecFilePath() if os.IsPermission(err) { ctx.WithError(err).Errorf( "user does not have write permissions for %s", specFile) } else { ctx.WithError(err).Errorf( "error writing spec file at %s", specFile) } //WaitUntilLibStorageStopped(ctx, serverErrChan) return ctx, config, errs, err } logHostSpec(ctx, host, "created spec file") return ctx, config, errs, nil }