func (d *driver) VolumeRemove( ctx types.Context, volumeID string, opts types.Store) error { ctx.WithFields(log.Fields{ "volumeID": volumeID, }).Debug("mockDriver.VolumeRemove") var xToRemove int var volume *types.Volume for x, v := range d.volumes { if strings.ToLower(v.ID) == strings.ToLower(volumeID) { volume = v xToRemove = x break } } if volume == nil { return utils.NewNotFoundError(volumeID) } d.volumes = append(d.volumes[:xToRemove], d.volumes[xToRemove+1:]...) return nil }
func (d *idm) List( ctx types.Context, opts types.Store) ([]types.VolumeMapping, error) { fields := log.Fields{ "opts": opts} ctx.WithFields(fields).Debug("listing volumes") volMaps, err := d.IntegrationDriver.List(ctx.Join(d.ctx), opts) if err != nil { return nil, err } volMapsWithNames := []types.VolumeMapping{} for _, vm := range volMaps { if vm.VolumeName() != "" { volMapsWithNames = append(volMapsWithNames, vm) } } if !d.pathCacheEnabled() { return volMapsWithNames, nil } for _, vm := range volMapsWithNames { vmn := vm.VolumeName() if !d.isCounted(vmn) && vm.MountPoint() != "" { d.initCount(vmn) } } return volMapsWithNames, nil }
func (d *idm) Mount( ctx types.Context, volumeID, volumeName string, opts *types.VolumeMountOpts) (string, *types.Volume, error) { opts.Preempt = d.preempt() fields := log.Fields{ "volumeName": volumeName, "volumeID": volumeID, "opts": opts} ctx.WithFields(fields).Debug("mounting volume") mp, vol, err := d.IntegrationDriver.Mount( ctx.Join(d.ctx), volumeID, volumeName, opts) if err != nil { return "", nil, err } // if the volume has attachments assign the new mount point to the // MountPoint field of the first attachment element if len(vol.Attachments) > 0 { vol.Attachments[0].MountPoint = mp } d.incCount(volumeName) return mp, vol, err }
// Init initializes the driver. func (d *driver) Init(ctx types.Context, config gofig.Config) error { d.config = config fields := map[string]interface{}{ "provider": vbox.Name, "moduleName": vbox.Name, "endpoint": d.endpoint(), "userName": d.username(), "tls": d.tls(), "volumePath": d.volumePath(), "controllerName": d.controllerName(), "machineNameOrId": d.machineNameID(""), } ctx.Info("initializing driver: ", fields) d.vbox = vboxc.New(d.username(), d.password(), d.endpoint(), d.tls(), d.controllerName()) if err := d.vbox.Logon(); err != nil { return goof.WithFieldsE(fields, "error logging in", err) } ctx.WithFields(fields).Info("storage driver initialized") return nil }
// Handle is the type's Handler function. func (h *queryParamsHandler) Handle( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { for k, v := range req.URL.Query() { ctx.WithFields(log.Fields{ "key": k, "value": v, "len(value)": len(v), }).Debug("query param") switch len(v) { case 0: store.Set(k, true) case 1: if len(v[0]) == 0 { store.Set(k, true) } else { if i, err := strconv.ParseInt(v[0], 10, 64); err == nil { store.Set(k, i) } else if b, err := strconv.ParseBool(v[0]); err == nil { store.Set(k, b) } else { store.Set(k, v[0]) } } default: store.Set(k, v) } } return h.handler(ctx, w, req, store) }
// // VolumeDetach detaches a volume. func (d *driver) VolumeDetach( ctx types.Context, volumeID string, opts *types.VolumeDetachOpts) (*types.Volume, error) { fields := eff(map[string]interface{}{ "moduleName": ctx, "volumeId": volumeID, }) if volumeID == "" { return nil, goof.WithFields(fields, "volumeId is required for VolumeDetach") } vols, err := d.getVolume(ctx, volumeID, "", types.VolAttReqTrue) if err != nil { return nil, err } resp := volumeattach.Delete( d.client, vols[0].Attachments[0].InstanceID.ID, volumeID) if resp.Err != nil { return nil, goof.WithFieldsE(fields, "error detaching volume", resp.Err) } ctx.WithFields(fields).Debug("waiting for volume to detach") volume, err := d.waitVolumeAttachStatus(ctx, volumeID, false) if err == nil { return volume, nil } log.WithFields(fields).Debug("volume detached") return nil, nil }
func (s *server) createMux(ctx types.Context) *mux.Router { m := mux.NewRouter() for _, apiRouter := range s.routers { for _, r := range apiRouter.Routes() { ctx := ctx.WithValue(context.RouteKey, r) f := s.makeHTTPHandler(ctx, r) mr := m.Path(r.GetPath()) mr = mr.Name(r.GetName()) mr = mr.Methods(r.GetMethod()) mr = mr.Queries(r.GetQueries()...) mr.Handler(f) if l, ok := context.GetLogLevel(ctx); ok && l >= log.DebugLevel { ctx.WithFields(log.Fields{ "path": r.GetPath(), "method": r.GetMethod(), "queries": r.GetQueries(), "len(queries)": len(r.GetQueries()), }).Debug("registered route") } else { ctx.Info("registered route") } } } return m }
// Validate validates the provided data (d) against the provided schema (s). func Validate(ctx types.Context, s, d []byte) error { if ctx == nil { log.StandardLogger().WithFields(log.Fields{ "schema": string(s), "body": string(d), }).Debug("validating schema") } else { ctx.WithFields(log.Fields{ "schema": string(s), "body": string(d), }).Debug("validating schema") } validator, err := getSchemaValidator(s) if err != nil { return err } if len(d) == 0 { d = []byte("{}") } data, err := ucl.Parse(bytes.NewReader(d)) if err != nil { return err } return validator.Validate(data) }
// Inspect returns a specific volume as identified by the provided // volume name. func (d *driver) Inspect( ctx types.Context, volumeName string, opts types.Store) (types.VolumeMapping, error) { fields := log.Fields{ "volumeName": volumeName, "opts": opts} ctx.WithFields(fields).Info("inspecting volume") objs, err := d.List(ctx, opts) if err != nil { return nil, err } var obj types.VolumeMapping for _, o := range objs { if strings.ToLower(volumeName) == strings.ToLower(o.VolumeName()) { obj = o break } } if obj == nil { return nil, utils.NewNotFoundError(volumeName) } fields = log.Fields{ "volumeName": volumeName, "volume": obj} ctx.WithFields(fields).Info("volume inspected") return obj, nil }
func (d *driver) SnapshotRemove( ctx types.Context, snapshotID string, opts types.Store) error { ctx.WithFields(log.Fields{ "snapshotID": snapshotID, }).Debug("mockDriver.SnapshotRemove") var xToRemove int var snapshot *types.Snapshot for x, s := range d.snapshots { if strings.ToLower(s.ID) == strings.ToLower(snapshotID) { snapshot = s xToRemove = x break } } if snapshot == nil { return utils.NewNotFoundError(snapshotID) } d.snapshots = append(d.snapshots[:xToRemove], d.snapshots[xToRemove+1:]...) return nil }
// Create will create a new volume with the volumeName and opts. func (d *driver) Create( ctx types.Context, volumeName string, opts *types.VolumeCreateOpts) (*types.Volume, error) { if volumeName == "" { return nil, goof.New("missing volume name or ID") } optsNew := &types.VolumeCreateOpts{} az := d.availabilityZone() optsNew.AvailabilityZone = &az i, _ := strconv.Atoi(d.size()) size := int64(i) optsNew.Size = &size volumeType := d.volumeType() optsNew.Type = &volumeType io, _ := strconv.Atoi(d.iops()) IOPS := int64(io) optsNew.IOPS = &IOPS if opts.Opts.IsSet("availabilityZone") { az = opts.Opts.GetString("availabilityZone") } if opts.Opts.IsSet("size") { size = opts.Opts.GetInt64("size") } if opts.Opts.IsSet("volumeType") { volumeType = opts.Opts.GetString("volumeType") } if opts.Opts.IsSet("type") { volumeType = opts.Opts.GetString("type") } if opts.Opts.IsSet("iops") { IOPS = opts.Opts.GetInt64("iops") } optsNew.Opts = opts.Opts ctx.WithFields(log.Fields{ "volumeName": volumeName, "availabilityZone": az, "size": size, "volumeType": volumeType, "IOPS": IOPS, "opts": opts}).Info("creating volume") client := context.MustClient(ctx) vol, err := client.Storage().VolumeCreate(ctx, volumeName, optsNew) if err != nil { return nil, err } ctx.WithFields(log.Fields{ "volumeName": volumeName, "vol": vol}).Info("volume created") return vol, nil }
// Volumes returns all volumes or a filtered list of volumes. func (d *driver) Volumes( ctx types.Context, opts *types.VolumesOpts) ([]*types.Volume, error) { svc := mustSession(ctx) fileSystems, err := d.getAllFileSystems(svc) if err != nil { return nil, err } var volumesSD []*types.Volume for _, fileSystem := range fileSystems { // Make sure that name is popullated if fileSystem.Name == nil { ctx.WithFields(log.Fields{ "filesystemid": *fileSystem.FileSystemId, }).Warn("missing EFS filesystem name") continue } // Only volumes with partition prefix if !strings.HasPrefix(*fileSystem.Name, d.tag+tagDelimiter) { continue } // Only volumes in "available" state if *fileSystem.LifeCycleState != awsefs.LifeCycleStateAvailable { continue } volumeSD := &types.Volume{ Name: d.getPrintableName(*fileSystem.Name), ID: *fileSystem.FileSystemId, Size: *fileSystem.SizeInBytes.Value, Attachments: nil, } var atts []*types.VolumeAttachment if opts.Attachments.Requested() { atts, err = d.getVolumeAttachments( ctx, *fileSystem.FileSystemId, opts.Attachments) if err != nil { return nil, err } } if len(atts) > 0 { volumeSD.Attachments = atts } volumesSD = append(volumesSD, volumeSD) } return volumesSD, nil }
// VolumeInspect inspects a single volume. func (d *driver) VolumeInspect( ctx types.Context, volumeID string, opts *types.VolumeInspectOpts) (*types.Volume, error) { resp, err := mustSession(ctx).DescribeFileSystems( &awsefs.DescribeFileSystemsInput{FileSystemId: aws.String(volumeID)}) if err != nil { return nil, err } if len(resp.FileSystems) == 0 { return nil, types.ErrNotFound{} } fileSystem := resp.FileSystems[0] // Only volumes in "available" state if *fileSystem.LifeCycleState != awsefs.LifeCycleStateAvailable { return nil, nil } // Name is optional via tag so make sure it exists var fileSystemName string if fileSystem.Name != nil { fileSystemName = *fileSystem.Name } else { ctx.WithFields(log.Fields{ "filesystemid": *fileSystem.FileSystemId, }).Warn("missing EFS filesystem name") } volume := &types.Volume{ Name: d.getPrintableName(fileSystemName), ID: *fileSystem.FileSystemId, Size: *fileSystem.SizeInBytes.Value, Attachments: nil, } var atts []*types.VolumeAttachment if opts.Attachments.Requested() { atts, err = d.getVolumeAttachments( ctx, *fileSystem.FileSystemId, opts.Attachments) if err != nil { return nil, err } } if len(atts) > 0 { volume.Attachments = atts } return volume, nil }
func (d *idm) Inspect( ctx types.Context, volumeName string, opts types.Store) (types.VolumeMapping, error) { fields := log.Fields{ "volumeName": volumeName, "opts": opts} ctx.WithFields(fields).Debug("inspecting volume") return d.IntegrationDriver.Inspect(ctx.Join(d.ctx), volumeName, opts) }
// LocalDevices returns a map of the system's local devices. func (d *driver) LocalDevices( ctx types.Context, opts *types.LocalDevicesOpts) (*types.LocalDevices, error) { ctx.WithFields(log.Fields{ "vfs.root": d.rootDir, "dev.path": d.devFilePath, }).Debug("config info") var devFileRWL *sync.RWMutex func() { devFileLocksRWL.RLock() defer devFileLocksRWL.RUnlock() devFileRWL = devFileLocks[d.devFilePath] }() devFileRWL.Lock() defer devFileRWL.Unlock() if !gotil.FileExists(d.devFilePath) { return nil, goof.New("device file missing") } f, err := os.Open(d.devFilePath) if err != nil { return nil, err } defer f.Close() localDevs := map[string]string{} scn := bufio.NewScanner(f) for { if !scn.Scan() { break } m := devRX.FindSubmatch(scn.Bytes()) if len(m) == 0 { continue } dev := m[1] var mountPoint []byte if len(m) > 2 { mountPoint = m[2] } localDevs[string(dev)] = string(mountPoint) } return &types.LocalDevices{Driver: vfs.Name, DeviceMap: localDevs}, nil }
func (d *idm) Detach( ctx types.Context, volumeName string, opts *types.VolumeDetachOpts) error { fields := log.Fields{ "volumeName": volumeName, "opts": opts} ctx.WithFields(fields).Debug("detaching volume") return d.IntegrationDriver.Detach(ctx.Join(d.ctx), volumeName, opts) }
// StartModule starts the module with the provided instance name. func StartModule(ctx apitypes.Context, config gofig.Config, name string) error { modInstancesRwl.RLock() defer modInstancesRwl.RUnlock() name = strings.ToLower(name) lf := map[string]interface{}{"name": name} mod, modExists := modInstances[name] if !modExists { return goof.WithFields(lf, "unknown module instance") } lf["typeName"] = mod.Type.Name lf["address"] = mod.Config.Address started := make(chan bool) timeout := make(chan bool) startError := make(chan error) go func() { sErr := mod.Inst.Start() if sErr != nil { startError <- sErr } else { started <- true } }() go func() { time.Sleep(startTimeout(config)) timeout <- true }() select { case <-started: mod.IsStarted = true ctx.WithFields(lf).Info("started module") case <-timeout: return goof.New("timed out while monitoring module start") case sErr := <-startError: return sErr } return nil }
func (d *driver) Init(ctx types.Context, config gofig.Config) error { d.config = config ctx.WithFields(log.Fields{ types.ConfigIgVolOpsMountRootPath: d.volumeRootPath(), types.ConfigIgVolOpsCreateDefaultType: d.volumeType(), types.ConfigIgVolOpsCreateDefaultIOPS: d.iops(), types.ConfigIgVolOpsCreateDefaultSize: d.size(), types.ConfigIgVolOpsCreateDefaultAZ: d.availabilityZone(), types.ConfigIgVolOpsCreateDefaultFsType: d.fsType(), types.ConfigIgVolOpsMountPath: d.mountDirPath(), types.ConfigIgVolOpsCreateImplicit: d.volumeCreateImplicit(), }).Info("docker integration driver successfully initialized") return nil }
func (d *idm) Remove( ctx types.Context, volumeName string, opts types.Store) error { fields := log.Fields{ "volumeName": volumeName, "opts": opts} ctx.WithFields(fields).Debug("removing volume") if d.disableRemove() { ctx.Debug("disableRemove skipped deletion") return nil } return d.IntegrationDriver.Remove(ctx.Join(d.ctx), volumeName, opts) }
func (d *idm) Create( ctx types.Context, volumeName string, opts *types.VolumeCreateOpts) (*types.Volume, error) { fields := log.Fields{ "volumeName": volumeName, "opts": opts} ctx.WithFields(fields).Debug("creating volume") if d.disableCreate() { ctx.Debug("disableRemove skipped creation") return nil, nil } return d.IntegrationDriver.Create(ctx.Join(d.ctx), volumeName, opts) }
func (c *client) updateExecutor(ctx types.Context) error { if c.isController() { return utils.NewUnsupportedForClientTypeError( c.clientType, "updateExecutor") } ctx.Debug("updating executor") lsxi := c.lsxCache.GetExecutorInfo(types.LSX.Name()) if lsxi == nil { return goof.WithField("lsx", types.LSX, "unknown executor") } ctx.Debug("waiting on executor lock") if err := c.lsxMutexWait(); err != nil { return err } defer func() { ctx.Debug("signalling executor lock") if err := c.lsxMutexSignal(); err != nil { panic(err) } }() if !types.LSX.Exists() { ctx.Debug("executor does not exist, download executor") return c.downloadExecutor(ctx) } ctx.Debug("executor exists, getting local checksum") checksum, err := c.getExecutorChecksum(ctx) if err != nil { return err } if lsxi.MD5Checksum != checksum { ctx.WithFields(log.Fields{ "remoteChecksum": lsxi.MD5Checksum, "localChecksum": checksum, }).Debug("executor checksums do not match, download executor") return c.downloadExecutor(ctx) } return nil }
func (d *driver) Format( ctx types.Context, deviceName string, opts *types.DeviceFormatOpts) error { fsType, err := probeFsType(deviceName) if err != nil && err != errUnknownFileSystem { return err } fsDetected := fsType != "" ctx.WithFields(log.Fields{ "fsDetected": fsDetected, "fsType": fsType, "deviceName": deviceName, "overwriteFs": opts.OverwriteFS, "driverName": driverName}).Info("probe information") if opts.OverwriteFS || !fsDetected { switch opts.NewFSType { case "ext4": if err := exec.Command( "mkfs.ext4", "-F", deviceName).Run(); err != nil { return goof.WithFieldE( "deviceName", deviceName, "error creating filesystem", err) } case "xfs": if err := exec.Command( "mkfs.xfs", "-f", deviceName).Run(); err != nil { return goof.WithFieldE( "deviceName", deviceName, "error creating filesystem", err) } default: return errUnsupportedFileSystem } } return nil }
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 }
// Path will return the mounted path of the volumeName or volumeID. func (d *driver) Path( ctx types.Context, volumeID, volumeName string, opts types.Store) (string, error) { ctx.WithFields(log.Fields{ "volumeName": volumeName, "volumeID": volumeID, "opts": opts}).Info("getting path to volume") vol, err := d.volumeInspectByIDOrName( ctx, volumeID, volumeName, types.VolAttReqTrue, opts) if err != nil { return "", err } else if vol == nil { return "", utils.NewNotFoundError( fmt.Sprintf("volumeID=%s,volumeName=%s", volumeID, volumeName)) } if len(vol.Attachments) == 0 { return "", nil } client := context.MustClient(ctx) mounts, err := client.OS().Mounts( ctx, vol.Attachments[0].DeviceName, "", opts) if err != nil { return "", err } if len(mounts) == 0 { return "", nil } volPath := d.volumeMountPath(mounts[0].MountPoint) ctx.WithFields(log.Fields{ "volPath": volPath, "vol": vol}).Info("returning path to volume") return volPath, nil }
// InitializeModule initializes a module. func InitializeModule( ctx apitypes.Context, modConfig *Config) (*Instance, error) { modInstancesRwl.Lock() defer modInstancesRwl.Unlock() ctx.WithField("name", modConfig.Name).Debug("initializing module instance") typeName := strings.ToLower(modConfig.Type) lf := log.Fields{ "typeName": typeName, "address": modConfig.Address, } mt, modTypeExists := modTypes[typeName] if !modTypeExists { return nil, goof.WithFields(lf, "unknown module type") } mod, initErr := mt.InitFunc(ctx, modConfig) if initErr != nil { return nil, initErr } modName := mod.Name() modInst := &Instance{ Type: mt, TypeName: typeName, Inst: mod, Name: modName, Config: modConfig, Description: mod.Description(), } modInstances[modName] = modInst lf["name"] = modName ctx.WithFields(lf).Info("initialized module instance") return modInst, nil }
func (d *idm) Init(ctx types.Context, config gofig.Config) error { if err := d.IntegrationDriver.Init(ctx, config); err != nil { return err } d.ctx = ctx d.config = config d.used = map[string]int{} d.initPathCache(ctx) ctx.WithFields(log.Fields{ types.ConfigIgVolOpsPathCacheEnabled: d.pathCacheEnabled(), types.ConfigIgVolOpsPathCacheAsync: d.pathCacheAsync(), types.ConfigIgVolOpsUnmountIgnoreUsed: d.ignoreUsedCount(), types.ConfigIgVolOpsMountPreempt: d.preempt(), types.ConfigIgVolOpsCreateDisable: d.disableCreate(), types.ConfigIgVolOpsRemoveDisable: d.disableRemove(), }).Info("libStorage integration driver successfully initialized") return nil }
// // VolumeAttach attaches a volume and provides a token clients can use // // to validate that device has appeared locally. func (d *driver) VolumeAttach( ctx types.Context, volumeID string, opts *types.VolumeAttachOpts) (*types.Volume, string, error) { iid := context.MustInstanceID(ctx) fields := eff(map[string]interface{}{ "volumeId": volumeID, "instanceId": iid.ID, }) if opts.Force { if _, err := d.VolumeDetach(ctx, volumeID, &types.VolumeDetachOpts{}); err != nil { return nil, "", err } } options := &volumeattach.CreateOpts{ VolumeID: volumeID, } if opts.NextDevice != nil { options.Device = *opts.NextDevice } volumeAttach, err := volumeattach.Create(d.client, iid.ID, options).Extract() if err != nil { return nil, "", goof.WithFieldsE( fields, "error attaching volume", err) } ctx.WithFields(fields).Debug("waiting for volume to attach") volume, err := d.waitVolumeAttachStatus(ctx, volumeID, true) if err != nil { return nil, "", goof.WithFieldsE( fields, "error waiting for volume to attach", err) } return volume, volumeAttach.Device, nil }
func (d *driver) VolumeCopy( ctx types.Context, volumeID, volumeName string, opts types.Store) (*types.Volume, error) { ctx.WithFields(log.Fields{ "volumeID": volumeID, "volumeName": volumeName, }).Debug("mockDriver.VolumeCopy") lenVols := len(d.volumes) var ogvol *types.Volume for _, v := range d.volumes { if strings.ToLower(v.ID) == strings.ToLower(volumeID) { ogvol = v break } } volume := &types.Volume{ Name: volumeName, ID: fmt.Sprintf("vol-%03d", lenVols+1), AvailabilityZone: ogvol.AvailabilityZone, Type: ogvol.Type, Size: ogvol.Size, Fields: map[string]string{}, } for k, v := range ogvol.Fields { volume.Fields[k] = v } d.volumes = append(d.volumes, volume) return volume, nil }
func (d *idm) Path( ctx types.Context, volumeID, volumeName string, opts types.Store) (string, error) { fields := log.Fields{ "volumeName": volumeName, "volumeID": volumeID, "opts": opts} ctx.WithFields(fields).Debug("getting path to volume") if !d.pathCacheEnabled() { return d.IntegrationDriver.Path( ctx.Join(d.ctx), volumeID, volumeName, opts) } if !d.isCounted(volumeName) { ctx.WithFields(fields).Debug("skipping path lookup") return "", nil } return d.IntegrationDriver.Path(ctx.Join(d.ctx), volumeID, volumeName, opts) }
func (d *idm) Unmount( ctx types.Context, volumeID, volumeName string, opts types.Store) (*types.Volume, error) { fields := log.Fields{ "volumeName": volumeName, "volumeID": volumeID, "opts": opts} ctx.WithFields(fields).Debug("unmounting volume") if d.ignoreUsedCount() || d.resetCount(volumeName) || !d.isCounted(volumeName) { d.initCount(volumeName) return d.IntegrationDriver.Unmount( ctx.Join(d.ctx), volumeID, volumeName, opts) } d.decCount(volumeName) return nil, nil }