func (d *driver) VolumeCreate( ctx types.Context, name string, opts *types.VolumeCreateOpts) (*types.Volume, error) { if name == "Volume 010" { return nil, goof.WithFieldE( "iops", opts.IOPS, "iops required", goof.WithFieldE( "size", opts.Size, "size required", goof.New("bzzzzT BROKEN"), ), ) } lenVols := len(d.volumes) volume := &types.Volume{ Name: name, ID: fmt.Sprintf("vol-%03d", lenVols+1), Fields: map[string]string{}, } if opts.AvailabilityZone != nil { volume.AvailabilityZone = *opts.AvailabilityZone } if opts.Type != nil { volume.Type = *opts.Type } if opts.Size != nil { volume.Size = *opts.Size } if opts.IOPS != nil { volume.IOPS = *opts.IOPS } if customFields := opts.Opts.GetStore("opts"); customFields != nil { if customFields.IsSet("owner") { volume.Fields["owner"] = customFields.GetString("owner") } if customFields.IsSet("priority") { volume.Fields["priority"] = customFields.GetString("priority") } } d.volumes = append(d.volumes, volume) return volume, nil }
func (d *driver) CreateSnapshot( notUsed bool, snapshotName, volumeID, description string) ([]*core.Snapshot, error) { volume, err := d.client.GetVolume(volumeID, "") if err != nil { return nil, goof.WithFieldE("volumeID", volumeID, "error getting volume", err) } //getfolder of volume req := &xtio.NewSnapshotOptions{ SnapList: xtio.NewSnapListItems(volume.Name, snapshotName), FolderID: "/", } postSnapshotsResp, err := d.client.NewSnapshot(req) if err != nil { return nil, err } index := getIndex(postSnapshotsResp.Links[0].Href) snapshot, err := d.GetSnapshot("", index, "") if err != nil { return nil, err } return snapshot, nil }
func (d *driver) RemoveSnapshot(snapshotID string) error { err := d.client.DeleteSnapshot(snapshotID, "") if err != nil { return goof.WithFieldE("snapshotID", snapshotID, "error deleting snapshot", err) } return nil }
func waitMount(volumeID string) (*goscaleio.SdcMappedVolume, error) { timeout := make(chan bool, 1) go func() { time.Sleep(10 * time.Second) timeout <- true }() successCh := make(chan *goscaleio.SdcMappedVolume, 1) errorCh := make(chan error, 1) go func(volumeID string) { log.WithField("provider", providerName).Debug("waiting for volume mount") for { sdcMappedVolumes, err := goscaleio.GetLocalVolumeMap() if err != nil { errorCh <- goof.WithFieldE( "provider", providerName, "problem getting local volume mappings", err) return } sdcMappedVolume := &goscaleio.SdcMappedVolume{} var foundVolume bool for _, sdcMappedVolume = range sdcMappedVolumes { if sdcMappedVolume.VolumeID == volumeID && sdcMappedVolume.SdcDevice != "" { foundVolume = true break } } if foundVolume { successCh <- sdcMappedVolume return } time.Sleep(100 * time.Millisecond) } }(volumeID) select { case sdcMappedVolume := <-successCh: log.WithFields(log.Fields{ "provider": providerName, "volumeId": sdcMappedVolume.VolumeID, "volume": sdcMappedVolume.SdcDevice, }).Debug("got sdcMappedVolume") return sdcMappedVolume, nil case err := <-errorCh: return &goscaleio.SdcMappedVolume{}, err case <-timeout: return &goscaleio.SdcMappedVolume{}, goof.WithFields( ef(), "timed out waiting for mount") } }
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 (d *driver) RemoveSnapshot(snapshotID string) error { resp := snapshots.Delete(d.clientBlockStorage, snapshotID) if resp.Err != nil { return goof.WithFieldE( "snapshotId", snapshotID, "error removing snapshot", resp.Err) } log.WithField("snapshotId", snapshotID).Debug("removed snapshot") return nil }
func (d *driver) DetachVolume(notUsed bool, volumeID string, blank string, notused bool) error { if volumeID == "" { return errors.ErrMissingVolumeID } volumes, err := d.GetVolume(volumeID, "") if err != nil { return err } if len(volumes) == 0 { return errors.ErrNoVolumesReturned } if d.multipath() { _, _ = exec.Command("/sbin/multipath", "-f", fmt.Sprintf("3%s", volumes[0].NetworkName)).Output() } if err := d.updateInitiatorsSig(); err != nil { return err } mapInitiatorNamesByID := make(map[string]string) for _, initiator := range d.initiatorsByName { mapInitiatorNamesByID[strconv.Itoa(initiator.Index)] = initiator.Name } for _, attachment := range volumes[0].Attachments { var initiatorName string var ok bool if initiatorName, ok = mapInitiatorNamesByID[attachment.InstanceID]; !ok { continue } lunMaps, err := d.getLunMaps( initiatorName, attachment.VolumeID) if err != nil { return err } if len(lunMaps) == 0 { continue } index := getIndex(lunMaps[0].Href) if err = d.client.DeleteLunMap(index, ""); err != nil { return goof.WithFieldE("index", index, "error deleting lun map", err) } } log.Println("Detached volume", volumeID) return nil }
func (d *driver) Init(r *core.RexRay) error { d.r = r var err error if d.zone, err = getCurrentZone(); err != nil { return goof.WithError("error getting current zone", err) } if d.project, err = getCurrentProjectID(); err != nil { return goof.WithError("error getting current project ID", err) } serviceAccountJSON, err := ioutil.ReadFile(d.r.Config.GetString("gce.keyfile")) if err != nil { log.WithField("provider", providerName).Fatalf("Could not read service account credentials file, %s => {%s}", d.r.Config.GetString("gce.keyfile"), err) return err } config, err := google.JWTConfigFromJSON(serviceAccountJSON, compute.ComputeScope, ) if err != nil { goof.WithFieldE("provider", providerName, "could not create JWT Config From JSON", err) return err } client, err := compute.New(config.Client(context.Background())) if err != nil { log.WithField("provider", providerName).Fatalf("Could not create compute client => {%s}", err) return err } d.client = client instanceID, err := getCurrentInstanceID() if err != nil { log.WithField("provider", providerName).Fatalf("Could not get current instance => {%s}", err) return err } d.currentInstanceID = instanceID log.WithField("provider", providerName).Info("storage driver initialized") return nil }
func (d *driver) DetachVolume(notUsed bool, volumeID string, blank string, notused bool) error { if volumeID == "" { return errors.ErrMissingVolumeID } volumes, err := d.GetVolume(volumeID, "") if err != nil { return err } if len(volumes) == 0 { return errors.ErrNoVolumesReturned } if err = d.detachVolume(volumeID, ""); err != nil { return goof.WithFieldE("volumeID", volumeID, "error detaching volume", err) } log.Println("Detached volume", volumeID) return nil }
func (d *driver) AttachVolume( runAsync bool, volumeID, instanceID string, force bool) ([]*core.VolumeAttachment, error) { if volumeID == "" { return nil, errors.ErrMissingVolumeID } volumes, err := d.GetVolume(volumeID, "") if err != nil { return nil, err } if len(volumes) == 0 { return nil, errors.ErrNoVolumesReturned } if len(volumes[0].Attachments) > 0 && !force { return nil, goof.New("volume already attached to a host") } else if len(volumes[0].Attachments) > 0 && force { if err := d.DetachVolume(false, volumeID, "", true); err != nil { return nil, err } } if err := d.attachVolume(volumeID, ""); err != nil { return nil, goof.WithFieldE("volumeID", volumeID, "error attaching volume", err) } d.rescanScsiHosts() volumeAttachment, err := d.GetVolumeAttach(volumeID, instanceID) if err != nil { return nil, err } return volumeAttachment, nil }