//Reformats from volumes.Volume to types.Volume credit to github.com/MatMaul func translateVolume( volume *volumes.Volume, attachments types.VolumeAttachmentsTypes) *types.Volume { var atts []*types.VolumeAttachment if attachments.Requested() { for _, att := range volume.Attachments { lsAtt := &types.VolumeAttachment{ VolumeID: att["volume_id"].(string), InstanceID: &types.InstanceID{ ID: att["server_id"].(string), Driver: rackspace.Name}, } if attachments.Devices() { lsAtt.DeviceName = att["device"].(string) } atts = append(atts, lsAtt) } } return &types.Volume{ Name: volume.Name, ID: volume.ID, AvailabilityZone: volume.AvailabilityZone, Status: volume.Status, Type: volume.VolumeType, IOPS: 0, Size: int64(volume.Size), Attachments: atts, } }
func (d *driver) getVolume( volumeID, volumeName string, attachments types.VolumeAttachmentsTypes) ( []*siotypes.Volume, error) { volumeName = shrink(volumeName) volumes, err := d.client.GetVolume( "", volumeID, "", volumeName, attachments.Requested()) if err != nil { return nil, err } return volumes, nil }
// getVolume searches and returns a volume matching criteria func (d *driver) getVolume( ctx types.Context, volumeID string, volumeName string, attachments types.VolumeAttachmentsTypes) ([]*types.Volume, error) { if err := d.refreshSession(ctx); err != nil { return nil, err } volumes, err := d.vbox.GetMedium(volumeID, volumeName) if err != nil { return nil, err } if len(volumes) == 0 { return nil, nil } var mapDN map[string]string if attachments.Devices() { volumeMapping, err := d.getVolumeMapping(ctx) if err != nil { return nil, err } mapDN = make(map[string]string) for _, vm := range volumeMapping { mapDN[vm.ID] = vm.Name } } var volumesSD []*types.Volume for _, v := range volumes { volumeSD := &types.Volume{ Name: v.Name, ID: v.ID, Size: int64(v.LogicalSize / 1024 / 1024 / 1024), Status: v.Location, Type: string(v.DeviceType), } if attachments.Requested() { var attachmentsSD []*types.VolumeAttachment for _, mid := range v.MachineIDs { attachmentSD := &types.VolumeAttachment{ VolumeID: v.ID, InstanceID: &types.InstanceID{ ID: mid, Driver: vbox.Name, }, } if attachments.Devices() && mapDN != nil { dn, _ := mapDN[v.ID] attachmentSD.DeviceName = dn } attachmentsSD = append(attachmentsSD, attachmentSD) } volumeSD.Attachments = attachmentsSD } volumesSD = append(volumesSD, volumeSD) } return volumesSD, nil }
func (d *driver) getVolumeAttachments( ctx types.Context, volumeID string, attachments types.VolumeAttachmentsTypes) ( []*types.VolumeAttachment, error) { if !attachments.Requested() { return nil, nil } if volumeID == "" { return nil, goof.New("missing volume ID") } resp, err := mustSession(ctx).DescribeMountTargets( &awsefs.DescribeMountTargetsInput{ FileSystemId: aws.String(volumeID), }) if err != nil { return nil, err } var ( ld *types.LocalDevices ldOK bool ) if attachments.Devices() { // Get local devices map from context if ld, ldOK = context.LocalDevices(ctx); !ldOK { return nil, errGetLocDevs } } var atts []*types.VolumeAttachment for _, mountTarget := range resp.MountTargets { var ( dev string status string ) if ldOK { // TODO(kasisnu): Check lifecycle state and build the path better dev = *mountTarget.IpAddress + ":" + "/" if _, ok := ld.DeviceMap[dev]; ok { status = "Exported and Mounted" } else { status = "Exported and Unmounted" } } else { status = "Exported" } attachmentSD := &types.VolumeAttachment{ VolumeID: *mountTarget.FileSystemId, InstanceID: &types.InstanceID{ ID: *mountTarget.SubnetId, Driver: d.Name(), }, DeviceName: dev, Status: status, } atts = append(atts, attachmentSD) } return atts, nil }
// Converts EC2 API volumes to libStorage types.Volume func (d *driver) toTypesVolume( ctx types.Context, ec2vols []*awsec2.Volume, attachments types.VolumeAttachmentsTypes) ([]*types.Volume, error) { var ( ld *types.LocalDevices ldOK bool ) if attachments.Devices() { // Get local devices map from context if ld, ldOK = context.LocalDevices(ctx); !ldOK { return nil, errGetLocDevs } } var volumesSD []*types.Volume for _, volume := range ec2vols { var attachmentsSD []*types.VolumeAttachment if attachments.Requested() { // Leave attachment's device name blank if attachments is false for _, attachment := range volume.Attachments { deviceName := "" if attachments.Devices() { // Compensate for kernel volume mapping i.e. change // "/dev/sda" to "/dev/xvda" deviceName = strings.Replace( *attachment.Device, "sd", ebsUtils.NextDeviceInfo.Prefix, 1) // Keep device name if it is found in local devices if _, ok := ld.DeviceMap[deviceName]; !ok { deviceName = "" } } attachmentSD := &types.VolumeAttachment{ VolumeID: *attachment.VolumeId, InstanceID: &types.InstanceID{ ID: *attachment.InstanceId, Driver: d.Name(), }, DeviceName: deviceName, Status: *attachment.State, } attachmentsSD = append(attachmentsSD, attachmentSD) } } name := d.getName(volume.Tags) volumeSD := &types.Volume{ Name: name, ID: *volume.VolumeId, AvailabilityZone: *volume.AvailabilityZone, Encrypted: *volume.Encrypted, Status: *volume.State, Type: *volume.VolumeType, Size: *volume.Size, Attachments: attachmentsSD, } // Some volume types have no IOPS, so we get nil in volume.Iops if volume.Iops != nil { volumeSD.IOPS = *volume.Iops } volumesSD = append(volumesSD, volumeSD) } return volumesSD, nil }
func handleVolAttachments( ctx types.Context, lf log.Fields, iid *types.InstanceID, vol *types.Volume, attachments types.VolumeAttachmentsTypes) bool { if attachments == 0 { vol.Attachments = nil return true } if lf == nil { lf = log.Fields{} } f := func(s types.VolumeAttachmentStates) bool { lf["attachmentState"] = s // if the volume has no attachments and the mask indicates that // only attached volumes should be returned then omit this volume if s == types.VolumeAvailable && attachments.Attached() && !attachments.Unattached() { ctx.WithFields(lf).Debug("omitting unattached volume") return false } // if the volume has attachments and the mask indicates that // only unattached volumes should be returned then omit this volume if (s == types.VolumeAttached || s == types.VolumeUnavailable) && !attachments.Attached() && attachments.Unattached() { ctx.WithFields(lf).Debug("omitting attached volume") return false } ctx.WithFields(lf).Debug("including volume") return true } // if the attachment state has already been set by the driver then // use it to determine whether the volume should be omitted if vol.AttachmentState > 0 { ctx.WithFields(lf).Debug( "deferring to driver-specified attachment state") return f(vol.AttachmentState) } ctx.WithFields(lf).Debug("manually calculating attachment state") // if only the requesting instance's attachments are requested then // filter the volume's attachments list if attachments.Mine() { atts := []*types.VolumeAttachment{} for _, a := range vol.Attachments { alf := log.Fields{ "attDeviceName": a.DeviceName, "attDountPoint": a.MountPoint, "attVolumeID": a.VolumeID, } if strings.EqualFold(iid.ID, a.InstanceID.ID) { atts = append(atts, a) ctx.WithFields(lf).WithFields(alf).Debug( "including volume attachment") } else { ctx.WithFields(lf).WithFields(alf).Debug( "omitting volume attachment") } } vol.Attachments = atts ctx.WithFields(lf).Debug("included volume attached to instance") } // determine a volume's attachment state if len(vol.Attachments) == 0 { vol.AttachmentState = types.VolumeAvailable } else { vol.AttachmentState = types.VolumeUnavailable if iid != nil { for _, a := range vol.Attachments { if a.InstanceID != nil && strings.EqualFold(iid.ID, a.InstanceID.ID) { vol.AttachmentState = types.VolumeAttached break } } } } // use the ascertained attachment state to determine whether or not the // volume should be omitted return f(vol.AttachmentState) }