func (d *idm) initPathCache(ctx types.Context) {
	if !d.pathCacheEnabled() {
		ctx.Info("path cache initializion disabled")
		return
	}

	if name, ok := context.ServiceName(ctx); !ok || name == "" {
		ctx.Info("path cache initializion disabled; no service name in ctx")
		return
	}

	f := func(async bool) {
		ctx.WithField("async", async).Info("initializing the path cache")
		_, err := d.List(ctx, apiutils.NewStoreWithData(initPathCacheMap))
		if err != nil {
			ctx.WithField("async", async).WithError(err).Error(
				"error initializing the path cache")
		} else {
			ctx.WithField("async", async).Debug("initialized the path cache")
		}
	}

	if d.pathCacheAsync() {
		go f(true)
	} else {
		f(false)
	}
}
func (c *client) NextDevice(
	ctx types.Context,
	opts types.Store) (string, error) {

	if c.isController() {
		return "", utils.NewUnsupportedForClientTypeError(
			c.clientType, "NextDevice")
	}

	if supported, _ := c.Supported(ctx, opts); !supported {
		return "", errExecutorNotSupported
	}

	ctx = context.RequireTX(ctx.Join(c.ctx))

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return "", goof.New("missing service name")
	}

	si, err := c.getServiceInfo(serviceName)
	if err != nil {
		return "", err
	}
	driverName := si.Driver.Name

	out, err := c.runExecutor(ctx, driverName, types.LSXCmdNextDevice)
	if err != nil {
		return "", err
	}

	ctx.Debug("xli nextdevice success")
	return gotil.Trim(string(out)), nil
}
func (d *driver) VolumeAttach(
	ctx types.Context,
	volumeID string,
	opts *types.VolumeAttachOpts) (*types.Volume, string, error) {

	if d.isController() {
		return nil, "", utils.NewUnsupportedForClientTypeError(
			d.clientType, "VolumeAttach")
	}

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, "", goof.New("missing service name")
	}

	nextDevice, err := d.NextDevice(ctx, utils.NewStore())
	if err != nil {
		return nil, "", err
	}

	var nextDevicePtr *string
	if nextDevice != "" {
		nextDevicePtr = &nextDevice
	}

	req := &types.VolumeAttachRequest{
		NextDeviceName: nextDevicePtr,
		Force:          opts.Force,
		Opts:           opts.Opts.Map(),
	}

	return d.client.VolumeAttach(ctx, serviceName, volumeID, req)
}
func (c *client) Supported(
	ctx types.Context,
	opts types.Store) (bool, error) {

	if c.isController() {
		return false, utils.NewUnsupportedForClientTypeError(
			c.clientType, "Supported")
	}

	ctx = context.RequireTX(ctx.Join(c.ctx))

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return false, goof.New("missing service name")
	}

	si, err := c.getServiceInfo(serviceName)
	if err != nil {
		return false, err
	}
	driverName := strings.ToLower(si.Driver.Name)

	// check to see if the driver's executor is supported on this host
	if ok := c.supportedCache.IsSet(driverName); ok {
		return c.supportedCache.GetBool(driverName), nil
	}

	out, err := c.runExecutor(ctx, driverName, types.LSXCmdSupported)
	if err != nil {
		if err == types.ErrNotImplemented {
			ctx.WithField("serviceDriver", driverName).Warn(
				"supported cmd not implemented")
			c.supportedCache.Set(driverName, true)
			ctx.WithField("supported", true).Debug("cached supported flag")
			return true, nil
		}
		return false, err
	}

	if len(out) == 0 {
		return false, nil
	}

	out = bytes.TrimSpace(out)
	b, err := strconv.ParseBool(string(out))
	if err != nil {
		return false, err
	}

	c.supportedCache.Set(driverName, b)
	ctx.WithField("supported", b).Debug("cached supported flag")
	return b, nil
}
func (d *driver) SnapshotRemove(
	ctx types.Context,
	snapshotID string,
	opts types.Store) error {

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return goof.New("missing service name")
	}

	return d.client.SnapshotRemove(ctx, serviceName, snapshotID)
}
func (d *driver) Type(ctx types.Context) (types.StorageType, error) {

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return "", goof.New("missing service name")
	}

	si, err := d.getServiceInfo(serviceName)
	if err != nil {
		return "", err
	}
	return si.Driver.Type, nil
}
func (d *driver) VolumeInspect(
	ctx types.Context,
	volumeID string,
	opts *types.VolumeInspectOpts) (*types.Volume, error) {

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	return d.client.VolumeInspect(ctx, serviceName, volumeID, opts.Attachments)
}
func (d *driver) NextDeviceInfo(
	ctx types.Context) (*types.NextDeviceInfo, error) {

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	si, err := d.getServiceInfo(serviceName)
	if err != nil {
		return nil, err
	}
	return si.Driver.NextDevice, nil
}
func (d *driver) InstanceInspect(
	ctx types.Context,
	opts types.Store) (*types.Instance, error) {

	if d.isController() {
		return nil, utils.NewUnsupportedForClientTypeError(
			d.clientType, "InstanceInspect")
	}

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	return d.client.InstanceInspect(ctx, serviceName)
}
Example #10
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
}
func (d *driver) VolumeSnapshot(
	ctx types.Context,
	volumeID, snapshotName string,
	opts types.Store) (*types.Snapshot, error) {

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	req := &types.VolumeSnapshotRequest{
		SnapshotName: snapshotName,
		Opts:         opts.Map(),
	}

	return d.client.VolumeSnapshot(ctx, serviceName, volumeID, req)
}
func (c *client) WaitForDevice(
	ctx types.Context,
	opts *types.WaitForDeviceOpts) (bool, *types.LocalDevices, error) {

	if c.isController() {
		return false, nil, utils.NewUnsupportedForClientTypeError(
			c.clientType, "WaitForDevice")
	}

	if supported, _ := c.Supported(ctx, opts.Opts); !supported {
		return false, nil, errExecutorNotSupported
	}

	ctx = context.RequireTX(ctx.Join(c.ctx))

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return false, nil, goof.New("missing service name")
	}

	si, err := c.getServiceInfo(serviceName)
	if err != nil {
		return false, nil, err
	}
	driverName := si.Driver.Name

	out, err := c.runExecutor(
		ctx, driverName, types.LSXCmdWaitForDevice,
		opts.ScanType.String(), opts.Token, opts.Timeout.String())

	if err != types.ErrTimedOut {
		return false, nil, err
	}

	matched := err == nil

	ld, err := unmarshalLocalDevices(ctx, out)
	if err != nil {
		return false, nil, err
	}

	ctx.Debug("xli waitfordevice success")
	return matched, ld, nil
}
func (d *driver) SnapshotCopy(
	ctx types.Context,
	snapshotID, snapshotName, destinationID string,
	opts types.Store) (*types.Snapshot, error) {

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	req := &types.SnapshotCopyRequest{
		SnapshotName:  snapshotName,
		DestinationID: destinationID,
		Opts:          opts.Map(),
	}

	return d.client.SnapshotCopy(ctx, serviceName, snapshotID, req)
}
Example #14
0
// List returns all available volume mappings.
func (d *driver) List(
	ctx types.Context,
	opts types.Store) ([]types.VolumeMapping, error) {

	client := context.MustClient(ctx)
	vols, err := client.Storage().Volumes(
		ctx,
		&types.VolumesOpts{
			Attachments: opts.GetAttachments(),
			Opts:        opts,
		},
	)
	if err != nil {
		return nil, err
	}

	serviceName, serviceNameOK := context.ServiceName(ctx)
	if !serviceNameOK {
		return nil, goof.New("service name is missing")
	}

	volMaps := []types.VolumeMapping{}
	for _, v := range vols {
		vs := make(map[string]interface{})
		vs["name"] = v.Name
		vs["size"] = v.Size
		vs["iops"] = v.IOPS
		vs["type"] = v.Type
		vs["availabilityZone"] = v.AvailabilityZone
		vs["fields"] = v.Fields
		vs["service"] = serviceName
		vs["server"] = serviceName
		volMaps = append(volMaps, &volumeMapping{
			Name:             v.Name,
			VolumeMountPoint: v.MountPoint(),
			VolumeStatus:     vs,
		})
	}

	return volMaps, nil
}
func (c *client) LocalDevices(
	ctx types.Context,
	opts *types.LocalDevicesOpts) (*types.LocalDevices, error) {

	if c.isController() {
		return nil, utils.NewUnsupportedForClientTypeError(
			c.clientType, "LocalDevices")
	}

	if supported, _ := c.Supported(ctx, opts.Opts); !supported {
		return nil, errExecutorNotSupported
	}

	ctx = context.RequireTX(ctx.Join(c.ctx))

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	si, err := c.getServiceInfo(serviceName)
	if err != nil {
		return nil, err
	}
	driverName := si.Driver.Name

	out, err := c.runExecutor(
		ctx, driverName, types.LSXCmdLocalDevices, opts.ScanType.String())
	if err != nil {
		return nil, err
	}

	ld, err := unmarshalLocalDevices(ctx, out)
	if err != nil {
		return nil, err
	}

	ctx.Debug("xli localdevices success")
	return ld, nil
}
func (d *driver) Volumes(
	ctx types.Context,
	opts *types.VolumesOpts) ([]*types.Volume, error) {

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	objMap, err := d.client.VolumesByService(ctx, serviceName, opts.Attachments)
	if err != nil {
		return nil, err
	}

	objs := []*types.Volume{}
	for _, o := range objMap {
		objs = append(objs, o)
	}

	return objs, nil
}
func (d *driver) VolumeCreateFromSnapshot(
	ctx types.Context,
	snapshotID, volumeName string,
	opts *types.VolumeCreateOpts) (*types.Volume, error) {

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	req := &types.VolumeCreateRequest{
		Name:             volumeName,
		AvailabilityZone: opts.AvailabilityZone,
		IOPS:             opts.IOPS,
		Size:             opts.Size,
		Type:             opts.Type,
		Opts:             opts.Opts.Map(),
	}

	return d.client.VolumeCreateFromSnapshot(ctx, serviceName, snapshotID, req)
}
func (d *driver) VolumeDetach(
	ctx types.Context,
	volumeID string,
	opts *types.VolumeDetachOpts) (*types.Volume, error) {

	if d.isController() {
		return nil, utils.NewUnsupportedForClientTypeError(
			d.clientType, "VolumeDetach")
	}

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	req := &types.VolumeDetachRequest{
		Force: opts.Force,
		Opts:  opts.Opts.Map(),
	}

	return d.client.VolumeDetach(ctx, serviceName, volumeID, req)
}
func (d *driver) Snapshots(
	ctx types.Context,
	opts types.Store) ([]*types.Snapshot, error) {

	ctx = d.requireCtx(ctx)
	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	objMap, err := d.client.SnapshotsByService(ctx, serviceName)

	if err != nil {
		return nil, err
	}

	objs := []*types.Snapshot{}
	for _, o := range objMap {
		objs = append(objs, o)
	}

	return objs, nil
}
func (c *client) InstanceID(
	ctx types.Context,
	opts types.Store) (*types.InstanceID, error) {

	if c.isController() {
		return nil, utils.NewUnsupportedForClientTypeError(
			c.clientType, "InstanceID")
	}

	if supported, _ := c.Supported(ctx, opts); !supported {
		return nil, errExecutorNotSupported
	}

	ctx = context.RequireTX(ctx.Join(c.ctx))

	serviceName, ok := context.ServiceName(ctx)
	if !ok {
		return nil, goof.New("missing service name")
	}

	si, err := c.getServiceInfo(serviceName)
	if err != nil {
		return nil, err
	}
	driverName := strings.ToLower(si.Driver.Name)

	// check to see if the driver's instance ID is cached
	if iid := c.instanceIDCache.GetInstanceID(driverName); iid != nil {
		return iid, nil
	}

	out, err := c.runExecutor(ctx, driverName, types.LSXCmdInstanceID)
	if err != nil {
		return nil, err
	}

	iid := &types.InstanceID{}
	if err := iid.UnmarshalText(out); err != nil {
		return nil, err
	}

	ctx = ctx.WithValue(context.InstanceIDKey, iid)

	if iid.HasMetadata() {
		ctx.Debug("sending instanceID in API.InstanceInspect call")
		instance, err := c.InstanceInspect(ctx, serviceName)
		if err != nil {
			return nil, err
		}
		ctx.Debug("received instanceID from API.InstanceInspect call")
		iid.ID = instance.InstanceID.ID
		iid.Fields = instance.InstanceID.Fields
		iid.DeleteMetadata()
	}

	c.instanceIDCache.Set(driverName, iid)
	ctx.Debug("cached instanceID")

	ctx.Debug("xli instanceID success")
	return iid, nil
}