// WriteTask writes a task to a ResponseWriter. func WriteTask( ctx types.Context, config gofig.Config, w http.ResponseWriter, store types.Store, task *types.Task, okStatus int) error { if store.GetBool("async") { WriteJSON(w, http.StatusAccepted, task) return nil } exeTimeoutDur, err := time.ParseDuration( config.GetString(types.ConfigServerTasksExeTimeout)) if err != nil { exeTimeoutDur = time.Duration(time.Second * 60) } exeTimeout := time.NewTimer(exeTimeoutDur) select { case <-services.TaskWaitC(ctx, task.ID): if task.Error != nil { return task.Error } WriteJSON(w, okStatus, task.Result) case <-exeTimeout.C: WriteJSON(w, http.StatusRequestTimeout, task) } return nil }
// UpdateLogLevel updates the log level based on the config. func UpdateLogLevel(config gofig.Config) { ll, err := log.ParseLevel(config.GetString(types.ConfigLogLevel)) if err != nil { return } log.SetLevel(ll) }
func startTimeout(config gofig.Config) time.Duration { dur, err := time.ParseDuration( config.GetString("rexray.module.startTimeout")) if err != nil { return time.Duration(10) * time.Second } return dur }
func printKeys(title string, c types.Config, t *testing.T) { for _, k := range c.AllKeys() { if title == "" { t.Logf(k) } else { t.Logf("%s - %s", title, k) } } }
func setHost( ctx apitypes.Context, config gofig.Config, host string) apitypes.Context { ctx = ctx.WithValue(context.HostKey, host) ctx.WithField("host", host).Debug("set host in context") config.Set(apitypes.ConfigHost, host) ctx.WithField("host", host).Debug("set host in config") return ctx }
// Init initializes the service. func (s *globalTaskService) Init(ctx types.Context, config gofig.Config) error { s.tasks = map[int]*task{} s.config = config s.resultSchemaValidationEnabled = config.GetBool( types.ConfigSchemaResponseValidationEnabled) ctx.WithField("enabled", s.resultSchemaValidationEnabled).Debug( "configured result schema validation") return nil }
func assertConfigEqualToJSONCompact( c1 types.Config, j2 string, t *testing.T) (types.Config, types.Config, bool) { var err error var j1 string if j1, err = c1.ToJSONCompact(); err != nil { t.Error(err) return nil, nil, false } return assertJSONEqual(j1, j2, t) }
func assertOsDrivers1(t *testing.T, c types.Config) { od := c.GetStringSlice("rexray.osDrivers") if od == nil { t.Fatalf("osDrivers == nil") } if len(od) != 1 { t.Fatalf("len(osDrivers) != 1; == %d", len(od)) } if od[0] != "linux" { t.Fatalf("od[0] != linux; == %v", od[0]) } }
func getTestConfigs( t *testing.T, driver string, config gofig.Config) (map[int]string, []gofig.Config) { libstorageConfigMap := map[string]interface{}{ "server": map[string]interface{}{ "services": map[string]interface{}{ driver: map[string]interface{}{ "libstorage": map[string]interface{}{ "storage": map[string]interface{}{ "driver": driver, }, }, }, }, }, } initTestConfigs(libstorageConfigMap) libstorageConfig := map[string]interface{}{ "libstorage": libstorageConfigMap, } yamlBuf, err := yaml.Marshal(libstorageConfig) assert.NoError(t, err) assert.NoError(t, config.ReadConfig(bytes.NewReader(yamlBuf))) configNames := map[int]string{} configs := []gofig.Config{} if tcpTest { configNames[len(configNames)] = "tcp" configs = append(configs, config.Scope("libstorage.tests.tcp")) } if tcpTLSTest { configNames[len(configNames)] = "tcpTLS" configs = append(configs, config.Scope("libstorage.tests.tcpTLS")) } if sockTest { configNames[len(configNames)] = "unix" configs = append(configs, config.Scope("libstorage.tests.unix")) } if sockTLSTest { configNames[len(configNames)] = "unixTLS" configs = append(configs, config.Scope("libstorage.tests.unixTLS")) } return configNames, configs }
// InitializeDefaultModules initializes the default modules. func InitializeDefaultModules( ctx apitypes.Context, config gofig.Config) (<-chan error, error) { modTypesRwl.RLock() defer modTypesRwl.RUnlock() var ( err error mod *Instance errs <-chan error ) // enable path caching for the modules config.Set(apitypes.ConfigIgVolOpsPathCacheEnabled, true) ctx, config, errs, err = util.ActivateLibStorage(ctx, config) if err != nil { return nil, err } modConfigs, err := getConfiguredModules(ctx, config) if err != nil { return nil, err } ctx.WithField("len(modConfigs)", len(modConfigs)).Debug( "got configured modules") for _, mc := range modConfigs { ctx.WithField("name", mc.Name).Debug( "creating libStorage client for module instance") if mc.Client, err = util.NewClient(ctx, mc.Config); err != nil { panic(err) } if mod, err = InitializeModule(ctx, mc); err != nil { return nil, err } modInstances[mod.Name] = mod } return errs, nil }
func activateLibStorage( ctx apitypes.Context, config gofig.Config) (apitypes.Context, gofig.Config, <-chan error, error) { var ( host string isRunning bool ) if host = config.GetString(apitypes.ConfigHost); host == "" { if host, isRunning = IsLocalServerActive(ctx, config); isRunning { ctx = setHost(ctx, config, host) } } if host == "" && !isRunning { return ctx, config, nil, errors.New("libStorage host config missing") } return ctx, config, nil, nil }
func assertStorageDrivers(t *testing.T, c types.Config) { sd := c.GetStringSlice("rexray.storageDrivers") if sd == nil { t.Fatalf("storageDrivers == nil") } if len(sd) != 2 { t.Fatalf("len(storageDrivers) != 2; == %d", len(sd)) } if sd[0] != "ec2" { t.Fatalf("sd[0] != ec2; == %v", sd[0]) } if sd[1] != "xtremio" { t.Fatalf("sd[1] != xtremio; == %v", sd[1]) } }
func isSet( config gofig.Config, key string, roots ...string) bool { for _, r := range roots { rk := strings.Replace(key, "libstorage.", fmt.Sprintf("%s.", r), 1) if config.IsSet(rk) { return true } } if config.IsSet(key) { return true } return false }
func getConfiguredModules( ctx apitypes.Context, c gofig.Config) ([]*Config, error) { mods := c.Get("rexray.modules") modMap, ok := mods.(map[string]interface{}) if !ok { return nil, goof.New("invalid format rexray.modules") } ctx.WithField("count", len(modMap)).Debug("got modules map") modConfigs := []*Config{} for name := range modMap { name = strings.ToLower(name) ctx.WithField("name", name).Debug("processing module config") sc := c.Scope(fmt.Sprintf("rexray.modules.%s", name)) if disabled := sc.GetBool("disabled"); disabled { ctx.WithField("name", name).Debug("ignoring disabled module config") continue } mc := &Config{ Name: name, Type: strings.ToLower(sc.GetString("type")), Description: sc.GetString("desc"), Address: sc.GetString("host"), Config: sc, } ctx.WithFields(log.Fields{ "name": mc.Name, "type": mc.Type, "desc": mc.Description, "addr": mc.Address, }).Info("created new mod config") modConfigs = append(modConfigs, mc) } return modConfigs, nil }
func (c *scopedConfig) Scope(scope interface{}) types.Config { szScope := toString(scope) if log.GetLevel() == log.DebugLevel { scopes := []string{} var p types.Config = c for { scopes = append(scopes, p.GetScope()) p = p.Parent() if p == nil { break } } log.WithFields(log.Fields{ "new": szScope, "parentScopes": strings.Join(scopes, ","), }).Debug("created scoped scope") } return &scopedConfig{Config: c, scope: szScope} }
func getString( config gofig.Config, key string, roots ...string) string { var val string for _, r := range roots { rk := strings.Replace(key, "libstorage.", fmt.Sprintf("%s.", r), 1) if val = config.GetString(rk); val != "" { return val } } val = config.GetString(key) if val != "" { return val } return "" }
// initDefaultLibStorageServices initializes the config object with a default // libStorage service if one is not present. // // TODO Move this into libStorage in libStorage 0.1.2 func initDefaultLibStorageServices( ctx apitypes.Context, config gofig.Config) error { if config.IsSet(apitypes.ConfigServices) { ctx.Debug( "libStorage auto service mode disabled; services defined") return nil } serviceName := config.GetString(apitypes.ConfigService) if serviceName == "" { ctx.Debug( "libStorage auto service mode disabled; service name empty") return nil } ctx.WithField("driver", serviceName).Info( "libStorage auto service mode enabled") buf := &bytes.Buffer{} fmt.Fprintf(buf, defaultServiceConfigFormat, serviceName) if err := config.ReadConfig(buf); err != nil { return err } return nil }
// BackCompat ensures keys can be used from old configurations. func BackCompat(config gofig.Config) { checks := [][]string{ {ConfigIgVolOpsMountPreempt, ConfigOldIntegrationVolMountPreempt}, {ConfigIgVolOpsCreateDisable, ConfigOldIntegrationVolCreateDisable}, {ConfigIgVolOpsRemoveDisable, ConfigOldIntegrationVolRemoveDisable}, {ConfigIgVolOpsUnmountIgnoreUsed, ConfigOldIntegrationVolUnmountIgnoreUsed}, {ConfigIgVolOpsPathCacheEnabled, ConfigOldIntegrationVolPathCache}, {ConfigIgVolOpsCreateDefaultFsType, ConfigOldDockerFsType}, {ConfigIgVolOpsCreateDefaultType, ConfigOldDockerVolumeType}, {ConfigIgVolOpsCreateDefaultIOPS, ConfigOldDockerIOPS}, {ConfigIgVolOpsCreateDefaultSize, ConfigOldDockerSize}, {ConfigIgVolOpsCreateDefaultAZ, ConfigOldDockerAvailabilityZone}, {ConfigIgVolOpsMountPath, ConfigOldDockerMountDirPath}, {ConfigIgVolOpsMountRootPath, ConfigOldDockerLinuxVolumeRootPath}, } for _, check := range checks { if !config.IsSet(check[0]) && config.IsSet(check[1]) { log.Debug(config.Get(check[1])) config.Set(check[0], config.Get(check[1])) } } }
func printConfig(title string, c types.Config, t *testing.T) { for _, k := range c.AllKeys() { if title == "" { t.Logf("%s=%v", k, c.Get(k)) } else { t.Logf("%s - %s=%v", title, k, c.Get(k)) } } }
func assertConfigsEqual(c1 types.Config, c2 types.Config, t *testing.T) bool { printConfig("c1", c1, t) t.Log("") printConfig("c2", c2, t) t.Log("") c1Keys := c1.AllKeys() c2Keys := c2.AllKeys() for _, k := range c1Keys { c1v := c1.Get(k) c2v := c2.Get(k) if !reflect.DeepEqual(c1v, c2v) { t.Logf("%s != in both configs; "+ "c1v:type=%[2]T,val=%[2]v; "+ "c2v:type=%[3]T,val=%[3]v", k, c1v, c2v) return false } } for _, k := range c2Keys { c1v := c1.Get(k) c2v := c2.Get(k) if !reflect.DeepEqual(c1v, c2v) { t.Logf("%s != in both configs; "+ "c1v:type=%[2]T,val=%[2]v; "+ "c2v:type=%[3]T,val=%[3]v", k, c1v, c2v) return false } } return true }
// RootDir returns the path to the VFS root directory. func RootDir(config gofig.Config) string { return config.GetString("vfs.root") }
// IsLocalServerActive returns a flag indicating whether or not a local // libStorage is already running. func IsLocalServerActive( ctx apitypes.Context, config gofig.Config) (host string, running bool) { var ( isLocal bool specFile = SpecFilePath() ) if gotil.FileExists(specFile) { if h, _ := ReadSpecFile(); h != "" { host = h logHostSpec(ctx, host, "read spec file") defer func() { if running || !isLocal { return } host = "" os.RemoveAll(specFile) ctx.WithField("specFile", specFile).Info( "removed invalid spec file") }() } } if host == "" { host = config.GetString(apitypes.ConfigHost) } if host == "" { return "", false } proto, addr, err := gotil.ParseAddress(host) if err != nil { return "", false } switch proto { case "unix": isLocal = true ctx.WithField("sock", addr).Debug("is local unix server active") var sockExists, isActive bool if sockExists = gotil.FileExists(addr); sockExists { if isActive = IsAddressActive(proto, addr); !isActive { os.RemoveAll(addr) ctx.WithField("sockFile", addr).Info( "removed invalid sock file") } } return host, isActive case "tcp": m := localHostRX.FindStringSubmatch(addr) if len(m) < 3 { return "", false } isLocal = true port, err := strconv.Atoi(m[2]) if err != nil { return "", false } ctx.WithField("port", port).Debug("is local tcp server active") return host, IsAddressActive(proto, addr) } return "", false }
// New returns a new libStorage client. func New(goCtx gocontext.Context, config gofig.Config) (types.Client, error) { if config == nil { var err error if config, err = apicnfg.NewConfig(); err != nil { return nil, err } } config = config.Scope(types.ConfigClient) types.BackCompat(config) var ( c *client err error ) c = &client{ctx: context.New(goCtx), config: config} c.ctx = c.ctx.WithValue(context.ClientKey, c) logFields := log.Fields{} logConfig, err := utils.ParseLoggingConfig( config, logFields, "libstorage.client") if err != nil { return nil, err } // always update the server context's log level context.SetLogLevel(c.ctx, logConfig.Level) c.ctx.WithFields(logFields).Info("configured logging") if config.IsSet(types.ConfigService) { c.ctx = c.ctx.WithValue( context.ServiceKey, config.GetString(types.ConfigService)) } storDriverName := config.GetString(types.ConfigStorageDriver) if storDriverName == "" { c.ctx.Warn("no storage driver found") } else { if c.sd, err = registry.NewStorageDriver(storDriverName); err != nil { return nil, err } if err = c.sd.Init(c.ctx, config); err != nil { return nil, err } if papi, ok := c.sd.(types.ProvidesAPIClient); ok { c.api = papi.API() } if pxli, pxliOk := c.sd.(types.ProvidesStorageExecutorCLI); pxliOk { c.xli = pxli.XCLI() } c.ctx.Info("storage driver initialized") } // if the API or XLI are nil, then the storage driver is not the libStorage // storage driver, and we should jump avoid any more initialization if c.api == nil || c.xli == nil { c.ctx.Info("created libStorage client") return c, nil } osDriverName := config.GetString(types.ConfigOSDriver) if osDriverName == "" { c.ctx.Warn("no os driver found") } else { if c.od, err = registry.NewOSDriver(osDriverName); err != nil { return nil, err } if err = c.od.Init(c.ctx, config); err != nil { return nil, err } c.ctx.Info("os driver initialized") } intDriverName := config.GetString(types.ConfigIntegrationDriver) if intDriverName == "" { c.ctx.Warn("no integration driver found") } else { if c.id, err = registry.NewIntegrationDriver( intDriverName); err != nil { return nil, err } if err := c.id.Init(c.ctx, config); err != nil { return nil, err } c.ctx.Info("integration driver initialized") } c.ctx.Info("created libStorage client") return c, nil }
func newServer(goCtx gocontext.Context, config gofig.Config) (*server, error) { adminTokenUUID, err := types.NewUUID() if err != nil { return nil, err } adminToken := adminTokenUUID.String() serverName := randomServerName() ctx := context.New(goCtx) ctx = ctx.WithValue(context.ServerKey, serverName) ctx = ctx.WithValue(context.AdminTokenKey, adminToken) if lvl, ok := context.GetLogLevel(ctx); ok { switch lvl { case log.DebugLevel: ctx = context.WithValue( ctx, gournal.LevelKey(), gournal.DebugLevel) case log.InfoLevel: ctx = context.WithValue( ctx, gournal.LevelKey(), gournal.InfoLevel) case log.WarnLevel: ctx = context.WithValue( ctx, gournal.LevelKey(), gournal.WarnLevel) case log.ErrorLevel: ctx = context.WithValue( ctx, gournal.LevelKey(), gournal.ErrorLevel) case log.FatalLevel: ctx = context.WithValue( ctx, gournal.LevelKey(), gournal.FatalLevel) case log.PanicLevel: ctx = context.WithValue( ctx, gournal.LevelKey(), gournal.PanicLevel) } } if logger, ok := ctx.Value(context.LoggerKey).(*log.Logger); ok { ctx = context.WithValue( ctx, gournal.AppenderKey(), glogrus.NewWithOptions( logger.Out, logger.Level, logger.Formatter)) } if config == nil { var err error if config, err = apicnfg.NewConfig(); err != nil { return nil, err } } config = config.Scope(types.ConfigServer) s := &server{ ctx: ctx, name: serverName, adminToken: adminToken, config: config, closeSignal: make(chan int), closedSignal: make(chan int), closeOnce: &sync.Once{}, } if logger, ok := s.ctx.Value(context.LoggerKey).(*log.Logger); ok { s.PrintServerStartupHeader(logger.Out) } else { s.PrintServerStartupHeader(os.Stdout) } if lvl, err := log.ParseLevel( config.GetString(types.ConfigLogLevel)); err == nil { context.SetLogLevel(s.ctx, lvl) } logFields := log.Fields{} logConfig, err := utils.ParseLoggingConfig( config, logFields, "libstorage.server") if err != nil { return nil, err } // always update the server context's log level context.SetLogLevel(s.ctx, logConfig.Level) s.ctx.WithFields(logFields).Info("configured logging") s.ctx.Info("initializing server") if err := s.initEndpoints(s.ctx); err != nil { return nil, err } s.ctx.Info("initialized endpoints") if err := services.Init(s.ctx, s.config); err != nil { return nil, err } s.ctx.Info("initialized services") if logConfig.HTTPRequests || logConfig.HTTPResponses { s.logHTTPEnabled = true s.logHTTPRequests = logConfig.HTTPRequests s.logHTTPResponses = logConfig.HTTPResponses s.stdOut = getLogIO(logConfig.Stdout, types.ConfigLogStdout) s.stdErr = getLogIO(logConfig.Stderr, types.ConfigLogStderr) } s.initGlobalMiddleware() if err := s.initRouters(); err != nil { return nil, err } servers = append(servers, s) return s, nil }
// BackCompat ensures keys can be used from old configurations. func BackCompat(config gofig.Config) { ec2Checks := [][]string{ {ConfigEBSAccessKey, ConfigEC2AccessKey}, {ConfigEBSSecretKey, ConfigEC2SecretKey}, {ConfigEBSRegion, ConfigEC2Region}, {ConfigEBSEndpoint, ConfigEC2Endpoint}, {ConfigEBSMaxRetries, ConfigEC2MaxRetries}, {ConfigEBSTag, ConfigEC2Tag}, {ConfigEBSRexrayTag, ConfigEC2RexrayTag}, {ConfigEBSKmsKeyID, ConfigEC2KmsKeyID}, } for _, check := range ec2Checks { if !config.IsSet(check[0]) && config.IsSet(check[1]) { log.Debug(config.Get(check[1])) config.Set(check[0], config.Get(check[1])) } } awsChecks := [][]string{ {ConfigEBSAccessKey, ConfigAWSAccessKey}, {ConfigEBSSecretKey, ConfigAWSSecretKey}, {ConfigEBSRegion, ConfigAWSRegion}, {ConfigEBSEndpoint, ConfigAWSEndpoint}, {ConfigEBSMaxRetries, ConfigAWSMaxRetries}, {ConfigEBSTag, ConfigAWSTag}, {ConfigEBSRexrayTag, ConfigAWSRexrayTag}, {ConfigEBSKmsKeyID, ConfigAWSKmsKeyID}, } for _, check := range awsChecks { if !config.IsSet(check[0]) && config.IsSet(check[1]) { log.Debug(config.Get(check[1])) config.Set(check[0], config.Get(check[1])) } } }
func assertString(t *testing.T, c types.Config, key, expected string) { v := c.GetString(key) if v != expected { t.Fatalf("%s != %s; == %v", key, expected, v) } }
// ActivateLibStorage activates libStorage and returns a possibly mutated // context. func ActivateLibStorage( ctx apitypes.Context, config gofig.Config) (apitypes.Context, gofig.Config, <-chan error, error) { config = config.Scope("rexray") // set the `libstorage.service` property to the value of // `rexray.storageDrivers` if the former is not defined and the // latter is if !config.IsSet(apitypes.ConfigService) && config.IsSet("rexray.storageDrivers") { if sd := config.GetStringSlice("rexray.storageDrivers"); len(sd) > 0 { config.Set(apitypes.ConfigService, sd[0]) } else if sd := config.GetString("rexray.storageDrivers"); sd != "" { config.Set(apitypes.ConfigService, sd) } } if !config.IsSet(apitypes.ConfigIgVolOpsMountPath) { config.Set(apitypes.ConfigIgVolOpsMountPath, LibFilePath("volumes")) } var ( err error errs <-chan error ) ctx, config, errs, err = activateLibStorage(ctx, config) if err != nil { return ctx, config, errs, err } return ctx, config, errs, nil }
// DeviceScanType gets the configured device scan type. func DeviceScanType(config gofig.Config) types.DeviceScanType { return types.ParseDeviceScanType(config.GetInt(types.ConfigDeviceScanType)) }
// DeviceAttachTimeout gets the configured device attach timeout. func DeviceAttachTimeout(config gofig.Config) time.Duration { return utils.DeviceAttachTimeout( config.GetString(types.ConfigDeviceAttachTimeout)) }
func readConfigFile(config gofig.Config, path string) error { if !gotil.FileExists(path) { return nil } return config.ReadConfigFile(path) }