// 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") }
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 }
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 }
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 }
// 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 }
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 (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 }