func (d *nfsDriver) Create(locator api.VolumeLocator, opt *api.CreateOptions, spec *api.VolumeSpec) (api.VolumeID, error) { // Validate options. if spec.Format != "nfs" { return "", errors.New("Unsupported filesystem format: " + string(spec.Format)) } if spec.BlockSize != 0 { log.Println("NFS driver will ignore the blocksize option.") } out, err := exec.Command("uuidgen").Output() if err != nil { log.Println(err) return "", err } volumeID := string(out) volumeID = strings.TrimSuffix(volumeID, "\n") // Create a directory on the NFS server with this UUID. err = os.MkdirAll(nfsMountPath+volumeID, 0744) if err != nil { log.Println(err) return "", err } // Persist the volume spec. We use this for all subsequent operations on // this volume ID. err = d.put(volumeID, &nfsVolume{Id: api.VolumeID(volumeID), Device: nfsMountPath + volumeID, Spec: *spec, Locator: locator}) return api.VolumeID(volumeID), err }
func TestSnapEnumerate(t *testing.T) { snapID := api.VolumeID(snapName) id := api.VolumeID(volName) vol := api.Volume{ ID: id, Locator: api.VolumeLocator{Name: volName, VolumeLabels: labels}, State: api.VolumeAvailable, Spec: &api.VolumeSpec{}, } err := e.CreateVol(&vol) assert.NoError(t, err, "Failed in CreateVol") snap := api.Volume{ ID: snapID, Locator: api.VolumeLocator{Name: volName, VolumeLabels: labels}, State: api.VolumeAvailable, Spec: &api.VolumeSpec{}, Source: &api.Source{Parent: id}, } err = e.CreateVol(&snap) assert.NoError(t, err, "Failed in CreateSnap") snaps, err := e.SnapEnumerate([]api.VolumeID{id}, nil) assert.NoError(t, err, "Failed in Enumerate") assert.Equal(t, len(snaps), 1, "Number of snaps returned in enumerate should be 1") if len(snaps) == 1 { assert.Equal(t, snaps[0].ID, snap.ID, "Invalid snap returned in Enumerate") } snaps, err = e.SnapEnumerate([]api.VolumeID{id}, labels) assert.NoError(t, err, "Failed in Enumerate") assert.Equal(t, len(snaps), 1, "Number of snaps returned in enumerate should be 1") if len(snaps) == 1 { assert.Equal(t, snaps[0].ID, snap.ID, "Invalid snap returned in Enumerate") } snaps, err = e.SnapEnumerate(nil, labels) assert.NoError(t, err, "Failed in Enumerate") assert.True(t, len(snaps) >= 1, "Number of snaps returned in enumerate should be at least 1") if len(snaps) == 1 { assert.Equal(t, snaps[0].ID, snap.ID, "Invalid snap returned in Enumerate") } snaps, err = e.SnapEnumerate(nil, nil) assert.NoError(t, err, "Failed in Enumerate") assert.True(t, len(snaps) >= 1, "Number of snaps returned in enumerate should be at least 1") if len(snaps) == 1 { assert.Equal(t, snaps[0].ID, snap.ID, "Invalid snap returned in Enumerate") } err = e.DeleteVol(snapID) assert.NoError(t, err, "Failed in Delete") snaps, err = e.SnapEnumerate([]api.VolumeID{id}, labels) assert.NotNil(t, snaps, "Inspect returned nil snaps") assert.Equal(t, len(snaps), 0, "Number of snaps returned in enumerate should be 0") err = e.DeleteVol(id) assert.NoError(t, err, "Failed in Delete") }
func (v *VolDriver) volumeMount(c *cli.Context) { v.volumeOptions(c) fn := "mount" if len(c.Args()) < 1 { missingParameter(c, fn, "volumeID", "Invalid number of arguments") return } volumeID := c.Args()[0] path := c.String("path") if path == "" { missingParameter(c, fn, "path", "Target mount path") return } err := v.volDriver.Mount(api.VolumeID(volumeID), path) if err != nil { cmdError(c, fn, err) return } fmtOutput(c, &Format{UUID: []string{volumeID}}) }
func (vd *volApi) parseVolumeID(r *http.Request) (api.VolumeID, error) { vars := mux.Vars(r) if id, ok := vars["id"]; ok { return api.VolumeID(id), nil } return api.BadVolumeID, fmt.Errorf("could not parse snap ID") }
func (d *driver) Create(locator api.VolumeLocator, source *api.Source, spec *api.VolumeSpec) (api.VolumeID, error) { volumeID := uuid.New() volumeID = strings.TrimSuffix(volumeID, "\n") // Create a directory on the NFS server with this UUID. volPath := path.Join(nfsMountPath, volumeID) err := os.MkdirAll(volPath, 0744) if err != nil { log.Println(err) return api.BadVolumeID, err } if source != nil { if len(source.Seed) != 0 { seed, err := seed.New(source.Seed, spec.ConfigLabels) if err != nil { log.Warnf("Failed to initailize seed from %q : %v", source.Seed, err) return api.BadVolumeID, err } err = seed.Load(volPath) if err != nil { log.Warnf("Failed to seed from %q to %q: %v", source.Seed, nfsMountPath, err) return api.BadVolumeID, err } } } f, err := os.Create(path.Join(nfsMountPath, string(volumeID)+nfsBlockFile)) if err != nil { log.Println(err) return api.BadVolumeID, err } defer f.Close() err = f.Truncate(int64(spec.Size)) if err != nil { log.Println(err) return api.BadVolumeID, err } v := &api.Volume{ ID: api.VolumeID(volumeID), Source: source, Locator: locator, Ctime: time.Now(), Spec: spec, LastScan: time.Now(), Format: "nfs", State: api.VolumeAvailable, Status: api.Up, DevicePath: path.Join(nfsMountPath, string(volumeID)+nfsBlockFile), } err = d.CreateVol(v) if err != nil { return api.BadVolumeID, err } return v.ID, err }
func TestEnumerate(t *testing.T) { id := api.VolumeID(volName) vol := api.Volume{ ID: id, Locator: api.VolumeLocator{Name: volName, VolumeLabels: labels}, State: api.VolumeAvailable, Spec: &api.VolumeSpec{}, } err := store.CreateVol(&vol) assert.NoError(t, err, "Failed in CreateVol") vols, err := store.Enumerate(api.VolumeLocator{}, nil) assert.NoError(t, err, "Failed in Enumerate") assert.Equal(t, 1, len(vols), "Number of volumes returned in enumerate should be 1") vols, err = store.Enumerate(api.VolumeLocator{Name: volName}, nil) assert.NoError(t, err, "Failed in Enumerate") assert.Equal(t, 1, len(vols), "Number of volumes returned in enumerate should be 1") if len(vols) == 1 { assert.Equal(t, vols[0].ID, vol.ID, "Invalid volume returned in Enumerate") } vols, err = store.Enumerate(api.VolumeLocator{VolumeLabels: labels}, nil) assert.NoError(t, err, "Failed in Enumerate") assert.Equal(t, len(vols), 1, "Number of volumes returned in enumerate should be 1") if len(vols) == 1 { assert.Equal(t, vols[0].ID, vol.ID, "Invalid volume returned in Enumerate") } err = store.DeleteVol(id) assert.NoError(t, err, "Failed in Delete") vols, err = store.Enumerate(api.VolumeLocator{Name: volName}, nil) assert.Equal(t, len(vols), 0, "Number of volumes returned in enumerate should be 0") }
func snapEnumerate(t *testing.T, ctx *Context) { fmt.Println("snapEnumerate") snaps, err := ctx.SnapEnumerate(nil, nil) assert.NoError(t, err, "Failed in snapEnumerate") assert.NotNil(t, snaps, "Nil snaps") assert.Equal(t, 1, len(snaps), "Expect 1 snaps actual %v snaps", len(snaps)) assert.Equal(t, snaps[0].ID, ctx.snapID, "Expect snapID %v actual %v", ctx.snapID, snaps[0].ID) labels := snaps[0].Locator.VolumeLabels snaps, err = ctx.SnapEnumerate([]api.VolumeID{ctx.volID}, nil) assert.NoError(t, err, "Failed in snapEnumerate") assert.NotNil(t, snaps, "Nil snaps") assert.Equal(t, len(snaps), 1, "Expect 1 snap actual %v snaps", len(snaps)) assert.Equal(t, snaps[0].ID, ctx.snapID, "Expect snapID %v actual %v", ctx.snapID, snaps[0].ID) snaps, err = ctx.SnapEnumerate([]api.VolumeID{api.VolumeID("shouldNotExist")}, nil) assert.Equal(t, len(snaps), 0, "Expect 0 snap actual %v snaps", len(snaps)) snaps, err = ctx.SnapEnumerate(nil, labels) assert.NoError(t, err, "Failed in snapEnumerate") assert.NotNil(t, snaps, "Nil snaps") assert.Equal(t, len(snaps), 1, "Expect 1 snap actual %v snaps", len(snaps)) assert.Equal(t, snaps[0].ID, ctx.snapID, "Expect snapID %v actual %v", ctx.snapID, snaps[0].ID) }
func (v *volDriver) snapCreate(context *cli.Context) { var err error var labels api.Labels fn := "snapCreate" if len(context.Args()) != 1 { missingParameter(context, fn, "volumeID", "Invalid number of arguments") return } volumeID := api.VolumeID(context.Args()[0]) v.volumeOptions(context) if l := context.String("label"); l != "" { if labels, err = processLabels(l); err != nil { cmdError(context, fn, err) return } } locator := api.VolumeLocator{ Name: context.String("name"), VolumeLabels: labels, } readonly := context.Bool("readonly") id, err := v.volDriver.Snapshot(volumeID, readonly, locator) if err != nil { cmdError(context, fn, err) return } fmtOutput(context, &Format{UUID: []string{string(id)}}) }
func (v *volumeDriver) Create( volumeLocator api.VolumeLocator, source *api.Source, spec *api.VolumeSpec, ) (api.VolumeID, error) { volumeID := strings.TrimSpace(string(uuid.New())) dirPath := filepath.Join(v.baseDirPath, volumeID) if err := os.MkdirAll(dirPath, 0777); err != nil { return api.BadVolumeID, err } volume := &api.Volume{ ID: api.VolumeID(volumeID), Locator: volumeLocator, Ctime: time.Now(), Spec: spec, LastScan: time.Now(), Format: "fuse", State: api.VolumeAvailable, Status: api.Up, DevicePath: dirPath, } if err := v.CreateVol(volume); err != nil { return api.BadVolumeID, err } if err := v.UpdateVol(volume); err != nil { return api.BadVolumeID, err } return volume.ID, nil }
// Snapshot create new subvolume from volume func (d *driver) Snapshot(volumeID api.VolumeID, readonly bool, locator api.VolumeLocator) (api.VolumeID, error) { vols, err := d.Inspect([]api.VolumeID{volumeID}) if err != nil { return api.BadVolumeID, err } if len(vols) != 1 { return api.BadVolumeID, fmt.Errorf("Failed to inspect %v len %v", volumeID, len(vols)) } snapID := uuid.New() vols[0].ID = api.VolumeID(snapID) vols[0].Parent = volumeID vols[0].Locator = locator vols[0].Ctime = time.Now() err = d.CreateVol(&vols[0]) if err != nil { return api.BadVolumeID, err } chaos.Now(koStrayCreate) err = d.btrfs.Create(snapID, string(volumeID)) if err != nil { return api.BadVolumeID, err } return vols[0].ID, nil }
// Create a new subvolume. The volume spec is not taken into account. func (d *driver) Create(locator api.VolumeLocator, options *api.CreateOptions, spec *api.VolumeSpec) (api.VolumeID, error) { if spec.Format != "btrfs" && spec.Format != "" { return api.BadVolumeID, fmt.Errorf("Filesystem format (%v) must be %v", spec.Format, "btrfs") } volumeID := uuid.New() v := &api.Volume{ ID: api.VolumeID(volumeID), Locator: locator, Ctime: time.Now(), Spec: spec, LastScan: time.Now(), Format: "btrfs", State: api.VolumeAvailable, } err := d.CreateVol(v) if err != nil { return api.BadVolumeID, err } err = d.btrfs.Create(volumeID, "") if err != nil { return api.BadVolumeID, err } v.DevicePath, err = d.btrfs.Get(volumeID, "") if err != nil { return v.ID, err } err = d.UpdateVol(v) return v.ID, err }
func (d *Driver) Snapshot(volumeID api.VolumeID, readonly bool, locator api.VolumeLocator) (api.VolumeID, error) { dryRun := false vols, err := d.DefaultEnumerator.Inspect([]api.VolumeID{volumeID}) if err != nil { return api.BadVolumeID, err } if len(vols) != 1 { return api.BadVolumeID, fmt.Errorf("Failed to inspect %v len %v", volumeID, len(vols)) } awsID := string(volumeID) request := &ec2.CreateSnapshotInput{ VolumeID: &awsID, DryRun: &dryRun, } snap, err := d.ec2.CreateSnapshot(request) chaos.Now(koStrayCreate) vols[0].ID = api.VolumeID(*snap.SnapshotID) vols[0].Parent = volumeID vols[0].Locator = locator vols[0].Ctime = time.Now() chaos.Now(koStrayCreate) err = d.CreateVol(&vols[0]) if err != nil { return api.BadVolumeID, err } return vols[0].ID, nil }
func (d *driver) Create(locator api.VolumeLocator, source *api.Source, spec *api.VolumeSpec) (api.VolumeID, error) { volumeID := uuid.New() volumeID = strings.TrimSuffix(volumeID, "\n") // Create a directory on the Local machine with this UUID. err := os.MkdirAll(path.Join(volumeBase, string(volumeID)), 0744) if err != nil { logrus.Println(err) return api.BadVolumeID, err } v := &api.Volume{ ID: api.VolumeID(volumeID), Locator: locator, Ctime: time.Now(), Spec: spec, LastScan: time.Now(), Format: "vfs", State: api.VolumeAvailable, Status: api.Up, DevicePath: path.Join(volumeBase, string(volumeID)), } err = d.CreateVol(v) if err != nil { return api.BadVolumeID, err } err = d.UpdateVol(v) return v.ID, err }
func (d *awsDriver) Create(l api.VolumeLocator, opt *api.CreateOptions, spec *api.VolumeSpec) (api.VolumeID, error) { availabilityZone := "us-west-1a" sz := int64(spec.Size / (1024 * 1024 * 1024)) iops := mapIops(spec.Cos) req := &ec2.CreateVolumeInput{ AvailabilityZone: &availabilityZone, Size: &sz, IOPS: &iops} v, err := d.ec2.CreateVolume(req) if err != nil { return api.VolumeID(""), err } // Persist the volume spec. We use this for all subsequent operations on // this volume ID. err = d.put(string(*v.VolumeID), &awsVolume{spec: *spec}) return api.VolumeID(*v.VolumeID), err }
// Create a new Vol for the specific volume spev.c. // It returns a system generated VolumeID that uniquely identifies the volume func (v *volumeClient) Create(locator api.VolumeLocator, source *api.Source, spec *api.VolumeSpec) (api.VolumeID, error) { var response api.VolumeCreateResponse createReq := api.VolumeCreateRequest{ Locator: locator, Source: source, Spec: spec, } err := v.c.Post().Resource(volumePath).Body(&createReq).Do().Unmarshal(&response) if err != nil { return api.VolumeID(""), err } if response.Error != "" { return api.VolumeID(""), errors.New(response.Error) } return response.ID, nil }
func makeRequest(t *testing.T) { c, err := NewDriverClient(btrfs.Name) if err != nil { t.Fatalf("Failed to create client: %v", err) } d := c.VolumeDriver() _, err = d.Stats(api.VolumeID("foo")) if err != nil { t.Fatalf("Failed to create client: %v", err) } }
func (d *driver) volFromName(name string) (*volumeInfo, error) { v, err := volume.Get(d.name) if err != nil { return nil, fmt.Errorf("Cannot locate volume driver for %s: %s", d.name, err.Error()) } volumes, err := v.Inspect([]types.VolumeID{types.VolumeID(name)}) if err != nil || len(volumes) == 0 { return nil, fmt.Errorf("Cannot locate volume %s", name) } return &volumeInfo{vol: &volumes[0]}, nil }
func makeRequest(t *testing.T) { c, err := NewDriverClient(nfs.Name) if err != nil { t.Fatalf("Failed to create client: %v", err) } d := c.VolumeDriver() _, err = d.Inspect([]api.VolumeID{api.VolumeID("foo")}) if err != nil { t.Fatalf("Failed to create client: %v", err) } }
func snapInspect(t *testing.T, ctx *Context) { fmt.Println("snapInspect") snaps, err := ctx.Inspect([]api.VolumeID{ctx.snapID}) assert.NoError(t, err, "Failed in Inspect") assert.NotNil(t, snaps, "Nil snaps") assert.Equal(t, len(snaps), 1, "Expect 1 snaps actual %v snaps", len(snaps)) assert.Equal(t, snaps[0].ID, ctx.snapID, "Expect snapID %v actual %v", ctx.snapID, snaps[0].ID) snaps, err = ctx.Inspect([]api.VolumeID{api.VolumeID("shouldNotExist")}) assert.Equal(t, 0, len(snaps), "Expect 0 snaps actual %v snaps", len(snaps)) }
func inspect(t *testing.T, ctx *Context) { fmt.Println("inspect") vols, err := ctx.Inspect([]api.VolumeID{ctx.volID}) assert.NoError(t, err, "Failed in Inspect") assert.NotNil(t, vols, "Nil vols") assert.Equal(t, len(vols), 1, "Expect 1 volume actual %v volumes", len(vols)) assert.Equal(t, vols[0].ID, ctx.volID, "Expect volID %v actual %v", ctx.volID, vols[0].ID) vols, err = ctx.Inspect([]api.VolumeID{api.VolumeID("shouldNotExist")}) assert.Equal(t, 0, len(vols), "Expect 0 volume actual %v volumes", len(vols)) }
func (vd *volDriver) snapEnumerate(w http.ResponseWriter, r *http.Request) { var err error var labels api.Labels var ids []api.VolumeID var snaps []api.VolumeSnap method := "snapEnumerate" d, err := volume.Get(vd.name) if err != nil { vd.notFound(w, r) return } params := r.URL.Query() v := params[string(api.OptLabel)] if v != nil { if err = json.Unmarshal([]byte(v[0]), &labels); err != nil { e := fmt.Errorf("Failed to parse parse VolumeLabels: %s", err.Error()) vd.sendError(vd.name, method, w, e.Error(), http.StatusBadRequest) } } v, ok := params[string(api.OptSnapID)] if ok && v != nil { sids := make([]api.SnapID, len(params)) for i, s := range v { sids[i] = api.SnapID(s) } snaps, err = d.SnapInspect(sids) if err != nil { e := fmt.Errorf("Failed to inspect snaps: %s", err.Error()) vd.sendError(vd.name, method, w, e.Error(), http.StatusBadRequest) return } } else { v, ok = params[string(api.OptVolumeID)] if v != nil && ok { ids = make([]api.VolumeID, len(params)) for i, s := range v { ids[i] = api.VolumeID(s) } } snaps, err = d.SnapEnumerate(ids, labels) if err != nil { e := fmt.Errorf("Failed to enumerate snaps: %s", err.Error()) vd.sendError(vd.name, method, w, e.Error(), http.StatusBadRequest) return } } json.NewEncoder(w).Encode(snaps) }
func (vd *volApi) enumerate(w http.ResponseWriter, r *http.Request) { var locator api.VolumeLocator var configLabels api.Labels var err error var vols []api.Volume method := "enumerate" d, err := volume.Get(vd.name) if err != nil { notFound(w, r) return } params := r.URL.Query() v := params[string(api.OptName)] if v != nil { locator.Name = v[0] } v = params[string(api.OptLabel)] if v != nil { if err = json.Unmarshal([]byte(v[0]), &locator.VolumeLabels); err != nil { e := fmt.Errorf("Failed to parse parse VolumeLabels: %s", err.Error()) vd.sendError(vd.name, method, w, e.Error(), http.StatusBadRequest) } } v = params[string(api.OptConfigLabel)] if v != nil { if err = json.Unmarshal([]byte(v[0]), &configLabels); err != nil { e := fmt.Errorf("Failed to parse parse configLabels: %s", err.Error()) vd.sendError(vd.name, method, w, e.Error(), http.StatusBadRequest) } } v = params[string(api.OptVolumeID)] if v != nil { ids := make([]api.VolumeID, len(v)) for i, s := range v { ids[i] = api.VolumeID(s) } vols, err = d.Inspect(ids) if err != nil { e := fmt.Errorf("Failed to inspect volumeID: %s", err.Error()) vd.sendError(vd.name, method, w, e.Error(), http.StatusBadRequest) return } } else { vols, _ = d.Enumerate(locator, configLabels) } json.NewEncoder(w).Encode(vols) }
func (d *driver) volFromName(name string) (*volumeInfo, error) { v, err := volume.Get(d.name) if err != nil { return nil, fmt.Errorf("Cannot locate volume driver for %s: %s", d.name, err.Error()) } vols, err := v.Inspect([]api.VolumeID{api.VolumeID(name)}) if err == nil && len(vols) == 1 { return &volumeInfo{vol: &vols[0]}, nil } vols, err = v.Enumerate(api.VolumeLocator{Name: name}, nil) if err == nil && len(vols) == 1 { return &volumeInfo{vol: &vols[0]}, nil } return nil, fmt.Errorf("Cannot locate volume %s", name) }
func (v *volDriver) volumeDelete(c *cli.Context) { fn := "delete" if len(c.Args()) < 1 { missingParameter(c, fn, "volumeID", "Invalid number of arguments") return } volumeID := c.Args()[0] v.volumeOptions(c) err := v.volDriver.Delete(api.VolumeID(volumeID)) if err != nil { cmdError(c, fn, err) return } fmtOutput(c, &Format{UUID: []string{c.Args()[0]}}) }
func (v *volDriver) volumeAlerts(context *cli.Context) { v.volumeOptions(context) fn := "alerts" if len(context.Args()) != 1 { missingParameter(context, fn, "volumeID", "Invalid number of arguments") return } alerts, err := v.volDriver.Alerts(api.VolumeID(context.Args()[0])) if err != nil { cmdError(context, fn, err) return } cmdOutput(context, alerts) }
// Create aws volume from spec. func (d *Driver) Create( locator api.VolumeLocator, source *api.Source, spec *api.VolumeSpec) (api.VolumeID, error) { var snapID *string // Spec size is in bytes, translate to GiB. sz := int64(spec.Size / (1024 * 1024 * 1024)) iops, volType := mapCos(spec.Cos) if source != nil && string(source.Parent) != "" { id := string(source.Parent) snapID = &id } dryRun := false encrypted := false req := &ec2.CreateVolumeInput{ AvailabilityZone: &d.md.zone, DryRun: &dryRun, Encrypted: &encrypted, Size: &sz, Iops: iops, VolumeType: volType, SnapshotId: snapID, } vol, err := d.ec2.CreateVolume(req) if err != nil { log.Warnf("Failed in CreateVolumeRequest :%v", err) return api.BadVolumeID, err } v := &api.Volume{ ID: api.VolumeID(*vol.VolumeId), Locator: locator, Ctime: time.Now(), Spec: spec, Source: source, LastScan: time.Now(), Format: "none", State: api.VolumeAvailable, Status: api.Up, } err = d.UpdateVol(v) err = d.waitStatus(v.ID, ec2.VolumeStateAvailable) return v.ID, err }
// Create aws volume from spec. func (d *Driver) Create( locator api.VolumeLocator, opt *api.CreateOptions, spec *api.VolumeSpec) (api.VolumeID, error) { var snapID *string // Spec size is in bytes, translate to GiB. sz := int64(spec.Size / (1024 * 1024 * 1024)) iops, volType := mapCos(spec.Cos) if string(opt.CreateFromSnap) != "" { id := string(opt.CreateFromSnap) snapID = &id } dryRun := false encrypted := false req := &ec2.CreateVolumeInput{ AvailabilityZone: &d.md.zone, DryRun: &dryRun, Encrypted: &encrypted, Size: &sz, IOPS: iops, VolumeType: volType, SnapshotID: snapID, } vol, err := d.ec2.CreateVolume(req) if err != nil { log.Warnf("Failed in CreateVolumeRequest :%v", err) return api.BadVolumeID, err } v := &api.Volume{ ID: api.VolumeID(*vol.VolumeID), Locator: locator, Ctime: time.Now(), Spec: spec, LastScan: time.Now(), Format: "none", State: api.VolumeAvailable, Status: api.Up, } err = d.UpdateVol(v) log.Infof("Created volume %v", v.ID) return v.ID, err }
func (v *volDriver) volumeFormat(context *cli.Context) { v.volumeOptions(context) fn := "format" if len(context.Args()) < 1 { missingParameter(context, fn, "volumeID", "Invalid number of arguments") return } volumeID := context.Args()[0] err := v.volDriver.Format(api.VolumeID(volumeID)) if err != nil { cmdError(context, fn, err) return } fmtOutput(context, &Format{UUID: []string{volumeID}}) }
func (v *volDriver) volumeAttach(c *cli.Context) { fn := "attach" if len(c.Args()) < 1 { missingParameter(c, fn, "volumeID", "Invalid number of arguments") return } v.volumeOptions(c) volumeID := c.Args()[0] devicePath, err := v.volDriver.Attach(api.VolumeID(volumeID)) if err != nil { cmdError(c, fn, err) return } fmtOutput(c, &Format{Result: devicePath}) }
func (d *driver) Create(locator api.VolumeLocator, opt *api.CreateOptions, spec *api.VolumeSpec) (api.VolumeID, error) { volumeID := uuid.New() volumeID = strings.TrimSuffix(volumeID, "\n") // Create a directory on the NFS server with this UUID. err := os.MkdirAll(nfsMountPath+volumeID, 0744) if err != nil { log.Println(err) return api.BadVolumeID, err } f, err := os.Create(nfsMountPath + volumeID + nfsBlockFile) if err != nil { log.Println(err) return api.BadVolumeID, err } defer f.Close() err = f.Truncate(int64(spec.Size)) if err != nil { log.Println(err) return api.BadVolumeID, err } v := &api.Volume{ ID: api.VolumeID(volumeID), Locator: locator, Ctime: time.Now(), Spec: spec, LastScan: time.Now(), Format: "nfs", State: api.VolumeAvailable, DevicePath: path.Join(nfsMountPath, string(volumeID), nfsBlockFile), } err = d.CreateVol(v) if err != nil { return api.BadVolumeID, err } err = d.UpdateVol(v) return v.ID, err }