func (d *driver) Volumes( ctx types.Context, opts *types.VolumesOpts) ([]*types.Volume, error) { context.MustSession(ctx) iid, iidOK := context.InstanceID(ctx) if iidOK { if iid.ID == "" { return nil, goof.New("missing instance ID") } } volJSONPaths, err := d.getVolJSONs() if err != nil { return nil, err } volumes := []*types.Volume{} for _, volJSONPath := range volJSONPaths { v, err := readVolume(volJSONPath) if err != nil { return nil, err } if opts.Attachments > 0 { v.AttachmentState = 0 } volumes = append(volumes, v) } return utils.SortVolumeByID(volumes), nil }
func (d *driver) mustRegion(ctx types.Context) *string { if iid, ok := context.InstanceID(ctx); ok { if v, ok := iid.Fields[efs.InstanceIDFieldRegion]; ok && v != "" { return &v } } return d.region }
func (d *driver) Login(ctx types.Context) (interface{}, error) { sess := &session{} if iid, ok := context.InstanceID(ctx); ok { sess.id = iid.String() } ctx.Debugf("vfs login=%s", sess.id) return sess, nil }
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) }
func (d *driver) mustAvailabilityZone(ctx types.Context) *string { if iid, ok := context.InstanceID(ctx); ok { if v, ok := iid.Fields[efs.InstanceIDFieldAvailabilityZone]; ok { if v != "" { return &v } } } return nil }
func toServiceInfo( ctx types.Context, service types.StorageService, store types.Store) (*types.ServiceInfo, error) { d := service.Driver() var instance *types.Instance if store.GetBool("instance") { if _, ok := context.InstanceID(ctx); !ok { return nil, utils.NewMissingInstanceIDError(service.Name()) } var err error instance, err = d.InstanceInspect(ctx, store) if err != nil { return nil, err } } st, err := d.Type(ctx) if err != nil { return nil, err } nd, err := d.NextDeviceInfo(ctx) if err != nil { return nil, err } return &types.ServiceInfo{ Name: service.Name(), Instance: instance, Driver: &types.DriverInfo{ Name: d.Name(), Type: st, NextDevice: nd, }, }, nil }
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) }
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 getFilteredVolumes( ctx types.Context, req *http.Request, store types.Store, storSvc types.StorageService, opts *types.VolumesOpts, filter *types.Filter) (types.VolumeMap, error) { var ( filterOp types.FilterOperator filterLeft string filterRight string objMap = types.VolumeMap{} ) iid, iidOK := context.InstanceID(ctx) if opts.Attachments.RequiresInstanceID() && !iidOK { return nil, utils.NewMissingInstanceIDError(storSvc.Name()) } ctx.WithField("attachments", opts.Attachments).Debug("querying volumes") objs, err := storSvc.Driver().Volumes(ctx, opts) if err != nil { return nil, err } if filter != nil { filterOp = filter.Op filterLeft = strings.ToLower(filter.Left) filterRight = strings.ToLower(filter.Right) } for _, obj := range objs { lf := log.Fields{ "attachments": opts.Attachments, "volumeID": obj.ID, "volumeName": obj.Name, } if filterOp == types.FilterEqualityMatch && filterLeft == "name" { ctx.WithFields(lf).Debug("checking name filter") if !strings.EqualFold(obj.Name, filterRight) { ctx.WithFields(lf).Debug("omitted volume due to name filter") continue } } if !handleVolAttachments(ctx, lf, iid, obj, opts.Attachments) { continue } if OnVolume != nil { ctx.WithFields(lf).Debug("invoking OnVolume handler") ok, err := OnVolume(ctx, req, store, obj) if err != nil { return nil, err } if !ok { continue } } objMap[obj.ID] = obj } return objMap, nil }
func (c *client) httpDo( ctx types.Context, method, path string, payload, reply interface{}) (*http.Response, error) { reqBody, err := encPayload(payload) if err != nil { return nil, err } url := fmt.Sprintf("http://%s%s", c.host, path) req, err := http.NewRequest(method, url, reqBody) if err != nil { return nil, err } ctx = context.RequireTX(ctx) tx := context.MustTransaction(ctx) ctx = ctx.WithValue(transactionHeaderKey, tx) if iid, ok := context.InstanceID(ctx); ok { ctx = ctx.WithValue(instanceIDHeaderKey, iid) } else if iidMap, ok := ctx.Value( context.AllInstanceIDsKey).(types.InstanceIDMap); ok { if len(iidMap) > 0 { var iids []fmt.Stringer for _, iid := range iidMap { iids = append(iids, iid) } ctx = ctx.WithValue(instanceIDHeaderKey, iids) } } if lds, ok := context.LocalDevices(ctx); ok { ctx = ctx.WithValue(localDevicesHeaderKey, lds) } else if ldsMap, ok := ctx.Value( context.AllLocalDevicesKey).(types.LocalDevicesMap); ok { if len(ldsMap) > 0 { var ldsess []fmt.Stringer for _, lds := range ldsMap { ldsess = append(ldsess, lds) } ctx = ctx.WithValue(localDevicesHeaderKey, ldsess) } } for key := range context.CustomHeaderKeys() { var headerName string switch tk := key.(type) { case string: headerName = tk case fmt.Stringer: headerName = tk.String() default: headerName = fmt.Sprintf("%v", key) } if headerName == "" { continue } val := ctx.Value(key) switch tv := val.(type) { case string: req.Header.Add(headerName, tv) case fmt.Stringer: req.Header.Add(headerName, tv.String()) case []string: for _, sv := range tv { req.Header.Add(headerName, sv) } case []fmt.Stringer: for _, sv := range tv { req.Header.Add(headerName, sv.String()) } default: if val != nil { req.Header.Add(headerName, fmt.Sprintf("%v", val)) } } } c.logRequest(req) res, err := ctxhttp.Do(ctx, &c.Client, req) if err != nil { return nil, err } defer c.setServerName(res) c.logResponse(res) if res.StatusCode > 299 { httpErr, err := goof.DecodeHTTPError(res.Body) if err != nil { return res, goof.WithField("status", res.StatusCode, "http error") } return res, httpErr } if req.Method != http.MethodHead && reply != nil { if err := decRes(res.Body, reply); err != nil { return nil, err } } return res, nil }