Пример #1
0
// LocalDevices returns a map of the system's local devices.
func (d *driver) LocalDevices(
	ctx types.Context, opts types.Store) (*types.LocalDevices, error) {

	if ld, ok := context.LocalDevices(ctx); ok {
		return ld, nil
	}
	return nil, goof.New("missing local devices")
}
Пример #2
0
func (d *driver) Volumes(
	ctx types.Context,
	opts *types.VolumesOpts) ([]*types.Volume, error) {

	xiid := executor.GetInstanceID()

	if serviceName, ok := context.ServiceName(ctx); ok && serviceName == Name {
		if ld, ok := context.LocalDevices(ctx); ok {
			ldm := ld.DeviceMap

			if opts.Attachments {

				iid := context.MustInstanceID(ctx)
				if iid.ID == xiid.ID {

					d.volumes[0].Attachments = []*types.VolumeAttachment{
						&types.VolumeAttachment{
							DeviceName: "/dev/xvda",
							MountPoint: ldm["/dev/xvda"],
							InstanceID: iid,
							Status:     "attached",
							VolumeID:   d.volumes[0].ID,
						},
						&types.VolumeAttachment{
							DeviceName: "/dev/xvdb",
							MountPoint: ldm["/dev/xvdb"],
							InstanceID: iid,
							Status:     "attached",
							VolumeID:   d.volumes[1].ID,
						},
						&types.VolumeAttachment{
							DeviceName: "/dev/xvdc",
							MountPoint: ldm["/dev/xvdc"],
							InstanceID: iid,
							Status:     "attached",
							VolumeID:   d.volumes[2].ID,
						},
					}
				}
			}

		}
	}

	return d.volumes, nil
}
Пример #3
0
func (d *driver) VolumeInspect(
	ctx types.Context,
	volumeID string,
	opts *types.VolumeInspectOpts) (*types.Volume, error) {

	if volumeID == "" {
		return nil, goof.New("no volumeID specified")
	}

	sdcMappedVolumes := make(map[string]string)
	if opts.Attachments.Requested() {
		if ld, ok := context.LocalDevices(ctx); ok {
			sdcMappedVolumes = ld.DeviceMap
		}
	}

	volumes, err := d.getVolume(volumeID, "", opts.Attachments)
	if err != nil {
		return nil, err
	}

	if len(volumes) == 0 {
		return nil, nil
	}

	mapStoragePoolName, err := d.getStoragePoolIDs()
	if err != nil {
		return nil, err
	}

	mapProtectionDomainName, err := d.getProtectionDomainIDs()
	if err != nil {
		return nil, err
	}

	getStoragePoolName := func(ID string) string {
		if pool, ok := mapStoragePoolName[ID]; ok {
			return pool.Name
		}
		return ""
	}

	getProtectionDomainName := func(poolID string) string {
		var ok bool
		var pool *siotypes.StoragePool

		if pool, ok = mapStoragePoolName[poolID]; !ok {
			return ""
		}

		if protectionDomain, ok := mapProtectionDomainName[pool.ProtectionDomainID]; ok {
			return protectionDomain.Name
		}
		return ""
	}

	var volumesSD []*types.Volume
	for _, volume := range volumes {
		var attachmentsSD []*types.VolumeAttachment
		for _, attachment := range volume.MappedSdcInfo {
			var deviceName string
			if _, exists := sdcMappedVolumes[volume.ID]; exists {
				deviceName = sdcMappedVolumes[volume.ID]
			}
			instanceID := &types.InstanceID{
				ID:     attachment.SdcID,
				Driver: d.Name(),
			}
			attachmentSD := &types.VolumeAttachment{
				VolumeID:   volume.ID,
				InstanceID: instanceID,
				DeviceName: deviceName,
				Status:     "",
			}
			attachmentsSD = append(attachmentsSD, attachmentSD)
		}

		var IOPS int64
		if len(volume.MappedSdcInfo) > 0 {
			IOPS = int64(volume.MappedSdcInfo[0].LimitIops)
		}
		volumeSD := &types.Volume{
			Name:             volume.Name,
			ID:               volume.ID,
			AvailabilityZone: getProtectionDomainName(volume.StoragePoolID),
			Status:           "",
			Type:             getStoragePoolName(volume.StoragePoolID),
			IOPS:             IOPS,
			Size:             int64(volume.SizeInKb / 1024 / 1024),
			Attachments:      attachmentsSD,
		}
		volumesSD = append(volumesSD, volumeSD)
	}

	return volumesSD[0], nil
}
Пример #4
0
func (d *driver) Volumes(
	ctx types.Context,
	opts *types.VolumesOpts) ([]*types.Volume, error) {

	sdcMappedVolumes := make(map[string]string)
	if opts.Attachments.Devices() {
		if ld, ok := context.LocalDevices(ctx); ok {
			sdcMappedVolumes = ld.DeviceMap
		}
	}

	mapStoragePoolName, err := d.getStoragePoolIDs()
	if err != nil {
		return nil, err
	}

	mapProtectionDomainName, err := d.getProtectionDomainIDs()
	if err != nil {
		return nil, err
	}

	getStoragePoolName := func(ID string) string {
		if pool, ok := mapStoragePoolName[ID]; ok {
			return pool.Name
		}
		return ""
	}

	getProtectionDomainName := func(poolID string) string {
		var ok bool
		var pool *siotypes.StoragePool

		if pool, ok = mapStoragePoolName[poolID]; !ok {
			return ""
		}

		if pd, ok := mapProtectionDomainName[pool.ProtectionDomainID]; ok {
			return pd.Name
		}
		return ""
	}

	volumes, err := d.getVolume("", "", 0)
	if err != nil {
		return []*types.Volume{}, err
	}

	var volumesSD []*types.Volume
	for _, volume := range volumes {
		var attachmentsSD []*types.VolumeAttachment
		if opts.Attachments.Requested() {
			for _, attachment := range volume.MappedSdcInfo {
				instanceID := &types.InstanceID{
					ID:     attachment.SdcID,
					Driver: d.Name(),
				}
				attachmentSD := &types.VolumeAttachment{
					VolumeID:   volume.ID,
					InstanceID: instanceID,
					Status:     "",
				}
				if devName, ok := sdcMappedVolumes[volume.ID]; ok {
					attachmentSD.DeviceName = devName
				}
				attachmentsSD = append(attachmentsSD, attachmentSD)
			}
		}

		var IOPS int64
		if len(volume.MappedSdcInfo) > 0 {
			IOPS = int64(volume.MappedSdcInfo[0].LimitIops)
		}
		volumeSD := &types.Volume{
			Name:             volume.Name,
			ID:               volume.ID,
			AvailabilityZone: getProtectionDomainName(volume.StoragePoolID),
			Status:           "",
			Type:             getStoragePoolName(volume.StoragePoolID),
			IOPS:             IOPS,
			Size:             int64(volume.SizeInKb / 1024 / 1024),
			Attachments:      attachmentsSD,
		}
		volumesSD = append(volumesSD, volumeSD)
	}

	return volumesSD, nil
}
Пример #5
0
// Volumes returns all volumes or a filtered list of volumes.
func (d *driver) getVolumeMapping(ctx types.Context) ([]*types.Volume, error) {

	var (
		err         error
		mapDiskByID map[string]string
		mas         []*vboxw.IMediumAttachment
		m           *vboxc.Machine
		iid         = context.MustInstanceID(ctx)
	)

	m, err = d.findMachineByInstanceID(ctx, iid)
	if err != nil {
		return nil, err
	}

	if err := m.Refresh(); err != nil {
		return nil, err
	}
	defer m.Release()

	ld, ok := context.LocalDevices(ctx)
	if !ok {
		return nil, goof.New("missing local devices")
	}
	mapDiskByID = ld.DeviceMap

	mas, err = m.GetMediumAttachments()
	if err != nil {
		return nil, err
	}

	var blockDevices []*types.Volume
	for _, ma := range mas {
		medium := d.vbox.NewMedium(ma.Medium)
		defer medium.Release()

		mid, err := medium.GetID()
		if err != nil {
			return nil, err
		}
		smid := strings.Split(mid, "-")
		if len(smid) == 0 {
			continue
		}

		location, err := medium.GetLocation()
		if err != nil {
			return nil, err
		}

		var bdn string
		var ok bool
		if bdn, ok = mapDiskByID[smid[0]]; !ok {
			continue
		}
		sdBlockDevice := &types.Volume{
			Name:   bdn,
			ID:     mid,
			Status: location,
		}
		blockDevices = append(blockDevices, sdBlockDevice)

	}
	return blockDevices, nil
}
Пример #6
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
}
Пример #7
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
}
Пример #8
0
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
}