//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,
	}
}
Beispiel #2
0
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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
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
}
Beispiel #5
0
// 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
}
Beispiel #6
0
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)
}