// 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 }
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 *driver) getVolumeByID(volumeID string) (*types.Volume, error) { volJSONPath := d.getVolPath(volumeID) if !gotil.FileExists(volJSONPath) { return nil, utils.NewNotFoundError(volumeID) } return readVolume(volJSONPath) }
func (d *driver) getSnapshotByID(snapshotID string) (*types.Snapshot, error) { snapJSONPath := d.getSnapPath(snapshotID) if !gotil.FileExists(snapJSONPath) { return nil, utils.NewNotFoundError(snapshotID) } return readSnapshot(snapJSONPath) }
func (r *router) volumeDetach( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { service := context.MustService(ctx) if _, ok := context.InstanceID(ctx); !ok { return utils.NewMissingInstanceIDError(service.Name()) } run := func( ctx types.Context, svc types.StorageService) (interface{}, error) { v, err := svc.Driver().VolumeDetach( ctx, store.GetString("volumeID"), &types.VolumeDetachOpts{ Force: store.GetBool("force"), Opts: store, }) if err != nil { return nil, err } if v == nil { return nil, nil } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(v.ID) } } if v.AttachmentState == 0 { v.AttachmentState = types.VolumeAvailable } return v, nil } return httputils.WriteTask( ctx, r.config, w, store, service.TaskExecute(ctx, run, nil), http.StatusResetContent) }
func (r *router) volumeAttach( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { service := context.MustService(ctx) if _, ok := context.InstanceID(ctx); !ok { return utils.NewMissingInstanceIDError(service.Name()) } run := func( ctx types.Context, svc types.StorageService) (interface{}, error) { v, attTokn, err := svc.Driver().VolumeAttach( ctx, store.GetString("volumeID"), &types.VolumeAttachOpts{ NextDevice: store.GetStringPtr("nextDeviceName"), Force: store.GetBool("force"), Opts: store, }) if err != nil { return nil, err } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(v.ID) } } if v.AttachmentState == 0 { v.AttachmentState = types.VolumeAttached } return &types.VolumeAttachResponse{ Volume: v, AttachToken: attTokn, }, nil } return httputils.WriteTask( ctx, r.config, w, store, service.TaskExecute(ctx, run, schema.VolumeAttachResponseSchema), http.StatusOK) }
// ExecutorInfoInspect returns the executor info for the provided name. func ExecutorInfoInspect(name string, data bool) (*ExecutorInfoEx, error) { ei, ok := executors[name] if !ok { return nil, utils.NewNotFoundError(name) } if !data { return ei, nil } bd, ok := _bindata[ei.Name] if !ok { return nil, utils.NewNotFoundError(name) } a, err := bd() if err != nil { return nil, err } ei.Data = a.bytes return ei, nil }
func (d *driver) VolumeInspect( ctx types.Context, volumeID string, opts *types.VolumeInspectOpts) (*types.Volume, error) { for _, v := range d.volumes { if strings.ToLower(v.ID) == strings.ToLower(volumeID) { return v, nil } } return nil, utils.NewNotFoundError(volumeID) }
func (r *router) volumeCreate( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { service := context.MustService(ctx) run := func( ctx types.Context, svc types.StorageService) (interface{}, error) { v, err := svc.Driver().VolumeCreate( ctx, store.GetString("name"), &types.VolumeCreateOpts{ AvailabilityZone: store.GetStringPtr("availabilityZone"), IOPS: store.GetInt64Ptr("iops"), Size: store.GetInt64Ptr("size"), Type: store.GetStringPtr("type"), Encrypted: store.GetBoolPtr("encrypted"), EncryptionKey: store.GetStringPtr("encryptionKey"), Opts: store, }) if err != nil { return nil, err } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(v.ID) } } if v.AttachmentState == 0 { v.AttachmentState = types.VolumeAvailable } return v, nil } return httputils.WriteTask( ctx, r.config, w, store, service.TaskExecute(ctx, run, schema.VolumeSchema), http.StatusCreated) }
func (d *driver) SnapshotRemove( ctx types.Context, snapshotID string, opts types.Store) error { context.MustSession(ctx) snapJSONPath := d.getSnapPath(snapshotID) if !gotil.FileExists(snapJSONPath) { return utils.NewNotFoundError(snapshotID) } os.Remove(snapJSONPath) return nil }
func (d *driver) VolumeRemove( ctx types.Context, volumeID string, opts types.Store) error { context.MustSession(ctx) volJSONPath := d.getVolPath(volumeID) if !gotil.FileExists(volJSONPath) { return utils.NewNotFoundError(volumeID) } os.Remove(volJSONPath) return nil }
func (r *router) volumeCopy( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { service := context.MustService(ctx) run := func( ctx types.Context, svc types.StorageService) (interface{}, error) { v, err := svc.Driver().VolumeCopy( ctx, store.GetString("volumeID"), store.GetString("volumeName"), store) if err != nil { return nil, err } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(v.ID) } } if v.AttachmentState == 0 { v.AttachmentState = types.VolumeAvailable } return v, nil } return httputils.WriteTask( ctx, r.config, w, store, service.TaskExecute(ctx, run, schema.VolumeSchema), http.StatusCreated) }
// Handle is the type's Handler function. func (h *serviceValidator) Handle( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { if !store.IsSet("service") { return utils.NewStoreKeyErr("service") } serviceName := store.GetString("service") service := services.GetStorageService(ctx, serviceName) if service == nil { return utils.NewNotFoundError(serviceName) } ctx = context.WithStorageService(ctx, service) return h.handler(ctx, w, req, store) }
// 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 }
func (d *driver) volumeInspectByIDOrName( ctx types.Context, volumeID, volumeName string, attachments types.VolumeAttachmentsTypes, opts types.Store) (*types.Volume, error) { if volumeID != "" && volumeName != "" { return nil, goof.New("specify either volumeID or volumeName") } client := context.MustClient(ctx) var obj *types.Volume if volumeID != "" { var err error obj, err = d.volumeInspectByID(ctx, volumeID, attachments, opts) if err != nil { return nil, err } } else { objs, err := client.Storage().Volumes( ctx, &types.VolumesOpts{Attachments: 0}) if err != nil { return nil, err } for _, o := range objs { if strings.EqualFold(volumeName, o.Name) { obj, err = d.volumeInspectByID(ctx, o.ID, attachments, opts) if err != nil { return nil, err } break } } } if obj == nil { return nil, utils.NewNotFoundError( fmt.Sprintf("volumeID=%s,volumeName=%s", volumeID, volumeName)) } return obj, nil }
func (r *router) volumeDetachAll( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { var ( taskIDs []int tasks = map[string]*types.Task{} opts = &types.VolumesOpts{Opts: store} reply types.ServiceVolumeMap = map[string]types.VolumeMap{} replyRWL = &sync.Mutex{} ) for service := range services.StorageServices(ctx) { run := func( ctx types.Context, svc types.StorageService) (interface{}, error) { ctx = context.WithStorageService(ctx, svc) if _, ok := context.InstanceID(ctx); !ok { return nil, utils.NewMissingInstanceIDError(service.Name()) } var err error if ctx, err = context.WithStorageSession(ctx); err != nil { return nil, err } driver := svc.Driver() volumes, err := driver.Volumes(ctx, opts) if err != nil { return nil, err } // check here var volumeMap types.VolumeMap = map[string]*types.Volume{} defer func() { if len(volumeMap) > 0 { replyRWL.Lock() defer replyRWL.Unlock() reply[service.Name()] = volumeMap } }() for _, volume := range volumes { v, err := driver.VolumeDetach( ctx, volume.ID, &types.VolumeDetachOpts{ Force: store.GetBool("force"), Opts: store, }) if err != nil { return nil, err } if err != nil { return nil, err } if v == nil { continue } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(v.ID) } } if v.AttachmentState == 0 { v.AttachmentState = types.VolumeAvailable } volumeMap[v.ID] = v } return nil, nil } task := service.TaskExecute(ctx, run, nil) taskIDs = append(taskIDs, task.ID) tasks[service.Name()] = task } run := func(ctx types.Context) (interface{}, error) { services.TaskWaitAll(ctx, taskIDs...) for _, v := range tasks { if v.Error != nil { return nil, utils.NewBatchProcessErr(reply, v.Error) } } return reply, nil } return httputils.WriteTask( ctx, r.config, w, store, services.TaskExecute(ctx, run, schema.ServiceVolumeMapSchema), http.StatusResetContent) }
func (r *router) volumeInspect( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { attachments := store.GetAttachments() service := context.MustService(ctx) iid, iidOK := context.InstanceID(ctx) if !iidOK && attachments.RequiresInstanceID() { return utils.NewMissingInstanceIDError(service.Name()) } opts := &types.VolumeInspectOpts{ Attachments: attachments, Opts: store, } var run types.StorageTaskRunFunc if store.IsSet("byName") { run = func( ctx types.Context, svc types.StorageService) (interface{}, error) { vols, err := svc.Driver().Volumes( ctx, &types.VolumesOpts{ Attachments: attachments, Opts: store, }) if err != nil { return nil, err } volID := store.GetString("volumeID") for _, v := range vols { if strings.EqualFold(v.Name, volID) { if !handleVolAttachments(ctx, nil, iid, v, attachments) { return nil, utils.NewNotFoundError(volID) } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(volID) } } return v, nil } } return nil, utils.NewNotFoundError(volID) } } else { run = func( ctx types.Context, svc types.StorageService) (interface{}, error) { v, err := svc.Driver().VolumeInspect( ctx, store.GetString("volumeID"), opts) if err != nil { return nil, err } if !handleVolAttachments(ctx, nil, iid, v, attachments) { return nil, utils.NewNotFoundError(v.ID) } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(v.ID) } } return v, nil } } return httputils.WriteTask( ctx, r.config, w, store, service.TaskExecute(ctx, run, schema.VolumeSchema), http.StatusOK) }
func (r *router) volumeDetachAllForService( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { service := context.MustService(ctx) if _, ok := context.InstanceID(ctx); !ok { return utils.NewMissingInstanceIDError(service.Name()) } var reply types.VolumeMap = map[string]*types.Volume{} run := func( ctx types.Context, svc types.StorageService) (interface{}, error) { driver := svc.Driver() volumes, err := driver.Volumes(ctx, &types.VolumesOpts{Opts: store}) if err != nil { return nil, err } for _, volume := range volumes { v, err := driver.VolumeDetach( ctx, volume.ID, &types.VolumeDetachOpts{ Force: store.GetBool("force"), Opts: store, }) if err != nil { return nil, utils.NewBatchProcessErr(reply, err) } if err != nil { return nil, err } if v == nil { continue } if OnVolume != nil { ok, err := OnVolume(ctx, req, store, v) if err != nil { return nil, err } if !ok { return nil, utils.NewNotFoundError(v.ID) } } if v.AttachmentState == 0 { v.AttachmentState = types.VolumeAvailable } reply[v.ID] = v } return reply, nil } return httputils.WriteTask( ctx, r.config, w, store, service.TaskExecute(ctx, run, schema.VolumeMapSchema), http.StatusResetContent) }