コード例 #1
0
ファイル: storage.go プロジェクト: robnolen/rexray
func getInstanceID(cfg *config.Config) (string, error) {

	cmd := newCmd(cfg, "/usr/bin/xenstore-read", "name")
	cmdOut, err := cmd.Output()

	if err != nil {
		return "",
			errors.WithFields(eff(errors.Fields{
				"cmd.Path": cmd.Path,
				"cmd.Args": cmd.Args,
				"cmd.Out":  cmdOut,
			}), "error getting instance id")
	}

	instanceID := strings.Replace(string(cmdOut), "\n", "", -1)

	validInstanceID := regexp.MustCompile(`^instance-`)
	valid := validInstanceID.MatchString(instanceID)
	if !valid {
		return "", errors.WithFields(eff(errors.Fields{
			"instanceId": instanceID}), "error matching instance id")
	}

	instanceID = strings.Replace(instanceID, "instance-", "", 1)
	return instanceID, nil
}
コード例 #2
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) AttachVolume(runAsync bool, volumeID, instanceID string) ([]*storage.VolumeAttachment, error) {

	fields := eff(map[string]interface{}{
		"runAsync":   runAsync,
		"volumeId":   volumeID,
		"instanceId": instanceID,
	})

	if volumeID == "" {
		return nil, errors.WithFields(fields, "volumeId is required")
	}

	mapVolumeSdcParam := &types.MapVolumeSdcParam{
		SdcID: driver.Sdc.Sdc.ID,
		AllowMultipleMappings: "false",
		AllSdcs:               "",
	}

	volumes, err := driver.getVolume(volumeID, "")
	if err != nil {
		return nil, errors.WithFieldsE(fields, "error getting volume", err)
	}

	if len(volumes) == 0 {
		return nil, errors.WithFields(fields, "no volumes returned")
	}

	targetVolume := goscaleio.NewVolume(driver.Client)
	targetVolume.Volume = volumes[0]

	err = targetVolume.MapVolumeSdc(mapVolumeSdcParam)
	if err != nil {
		return nil, errors.WithFieldsE(fields, "error mapping volume sdc", err)
	}

	_, err = waitMount(volumes[0].ID)
	if err != nil {
		fields["volumeId"] = volumes[0].ID
		return nil, errors.WithFieldsE(
			fields, "error waiting on volume to mount", err)
	}

	volumeAttachment, err := driver.GetVolumeAttach(volumeID, instanceID)
	if err != nil {
		return nil, errors.WithFieldsE(
			fields, "error getting volume attachments", err)
	}

	log.WithFields(log.Fields{
		"provider":   ProviderName,
		"volumeId":   volumeID,
		"instanceId": instanceID,
	}).Debug("attached volume to instance")
	return volumeAttachment, nil
}
コード例 #3
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) DetachVolume(runAsync bool, volumeID, instanceID string) error {
	fields := eff(map[string]interface{}{
		"runAsync":   runAsync,
		"volumeId":   volumeID,
		"instanceId": instanceID,
	})

	if volumeID == "" {
		return errors.WithFields(fields, "volumeId is required")
	}
	volume, err := driver.GetVolume(volumeID, "")
	if err != nil {
		return errors.WithFieldsE(fields, "error getting volume", err)
	}

	fields["instanceId"] = volume[0].Attachments[0].InstanceID
	resp := volumeattach.Delete(
		driver.Client, volume[0].Attachments[0].InstanceID, volumeID)
	if resp.Err != nil {
		return errors.WithFieldsE(fields, "error deleting volume", err)
	}

	if !runAsync {
		log.WithFields(fields).Debug("waiting for volume to detach")
		err = driver.waitVolumeDetach(volumeID)
		if err != nil {
			return errors.WithFieldsE(
				fields, "error waiting for volume to detach", err)
		}
	}

	log.WithFields(fields).Debug("volume detached")
	return nil
}
コード例 #4
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) GetVolumeAttach(volumeID, instanceID string) ([]*storage.VolumeAttachment, error) {

	fields := eff(map[string]interface{}{
		"volumeId":   volumeID,
		"instanceId": instanceID,
	})

	if volumeID == "" {
		return []*storage.VolumeAttachment{},
			errors.WithFields(fields, "volumeId is required")
	}
	volume, err := driver.GetVolume(volumeID, "")
	if err != nil {
		return []*storage.VolumeAttachment{},
			errors.WithFieldsE(fields, "error getting volume attach", err)
	}

	if instanceID != "" {
		var attached bool
		for _, volumeAttachment := range volume[0].Attachments {
			if volumeAttachment.InstanceID == instanceID {
				return volume[0].Attachments, nil
			}
		}
		if !attached {
			return []*storage.VolumeAttachment{}, nil
		}
	}
	return volume[0].Attachments, nil
}
コード例 #5
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) RemoveVolume(volumeID string) error {

	fields := eff(map[string]interface{}{
		"volumeId": volumeID,
	})

	if volumeID == "" {
		return errors.WithFields(fields, "volumeId is required")
	}

	volumes, err := driver.getVolume(volumeID, "")
	if err != nil {
		return errors.WithFieldsE(fields, "error getting volume", err)
	}

	targetVolume := goscaleio.NewVolume(driver.Client)
	targetVolume.Volume = volumes[0]

	err = targetVolume.RemoveVolume("ONLY_ME")
	if err != nil {
		return errors.WithFieldsE(fields, "error removing volume", err)
	}

	log.WithFields(fields).Debug("removed volume")
	return nil
}
コード例 #6
0
ファイル: storage.go プロジェクト: robnolen/rexray
func Init(conf *config.Config) (storage.Driver, error) {

	instanceDocument, err := getInstanceIdendityDocument()
	if err != nil {
		return nil, errors.WithFields(ef(), "error getting instance id doc")
	}

	auth := aws.Auth{AccessKey: conf.AwsAccessKey, SecretKey: conf.AwsSecretKey}
	region := conf.AwsRegion
	if region == "" {
		region = instanceDocument.Region
	}
	ec2Instance := ec2.New(
		auth,
		aws.Regions[region],
	)

	// table := InitDD(auth, aws.Regions[instanceDocument.Region])

	driver := &Driver{
		EC2Instance:      ec2Instance,
		InstanceDocument: instanceDocument,
		Config:           conf,
		// DDTable:          table,
	}

	log.WithField("provider", ProviderName).Debug(
		"storage driver initialized")

	return driver, nil
}
コード例 #7
0
ファイル: storage.go プロジェクト: robnolen/rexray
func waitMount(volumeID string) (*goscaleio.SdcMappedVolume, error) {

	timeout := make(chan bool, 1)
	go func() {
		time.Sleep(10 * time.Second)
		timeout <- true
	}()

	successCh := make(chan *goscaleio.SdcMappedVolume, 1)
	errorCh := make(chan error, 1)
	go func(volumeID string) {
		log.WithField("provider", ProviderName).Debug("waiting for volume mount")
		for {
			sdcMappedVolumes, err := goscaleio.GetLocalVolumeMap()
			if err != nil {
				errorCh <- errors.WithFieldE(
					"provider", ProviderName,
					"problem getting local volume mappings", err)
				return
			}

			sdcMappedVolume := &goscaleio.SdcMappedVolume{}
			var foundVolume bool
			for _, sdcMappedVolume = range sdcMappedVolumes {
				if sdcMappedVolume.VolumeID == volumeID && sdcMappedVolume.SdcDevice != "" {
					foundVolume = true
					break
				}
			}

			if foundVolume {
				successCh <- sdcMappedVolume
				return
			}
			time.Sleep(100 * time.Millisecond)
		}

	}(volumeID)

	select {
	case sdcMappedVolume := <-successCh:
		log.WithFields(log.Fields{
			"provider": ProviderName,
			"volumeId": sdcMappedVolume.VolumeID,
			"volume":   sdcMappedVolume.SdcDevice,
		}).Debug("got sdcMappedVolume")
		return sdcMappedVolume, nil
	case err := <-errorCh:
		return &goscaleio.SdcMappedVolume{}, err
	case <-timeout:
		return &goscaleio.SdcMappedVolume{}, errors.WithFields(
			ef(), "timed out waiting for mount")
	}

}
コード例 #8
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) DetachVolume(runAsync bool, volumeID string, blank string) error {

	fields := eff(map[string]interface{}{
		"runAsync": runAsync,
		"volumeId": volumeID,
		"blank":    blank,
	})

	if volumeID == "" {
		return errors.WithFields(fields, "volumeId is required")
	}

	volumes, err := driver.getVolume(volumeID, "")
	if err != nil {
		return errors.WithFieldsE(fields, "error getting volume", err)
	}

	if len(volumes) == 0 {
		return errors.WithFields(fields, "no volumes returned")
	}

	targetVolume := goscaleio.NewVolume(driver.Client)
	targetVolume.Volume = volumes[0]

	unmapVolumeSdcParam := &types.UnmapVolumeSdcParam{
		SdcID:                driver.Sdc.Sdc.ID,
		IgnoreScsiInitiators: "true",
		AllSdcs:              "",
	}

	// need to detect if unmounted first
	err = targetVolume.UnmapVolumeSdc(unmapVolumeSdcParam)
	if err != nil {
		return errors.WithFieldsE(fields, "error unmapping volume sdc", err)
	}

	log.WithFields(log.Fields{
		"provider": ProviderName,
		"volumeId": volumeID}).Debug("detached volume")
	return nil
}
コード例 #9
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) RemoveVolume(volumeID string) error {
	fields := eff(map[string]interface{}{
		"volumeId": volumeID,
	})
	if volumeID == "" {
		return errors.WithFields(fields, "volumeId is required")
	}
	res := volumes.Delete(driver.ClientBlockStorage, volumeID)
	if res.Err != nil {
		return errors.WithFieldsE(fields, "error removing volume", res.Err)
	}

	log.WithFields(fields).Debug("removed volume")
	return nil
}
コード例 #10
0
ファイル: storage.go プロジェクト: robnolen/rexray
func getInstanceRegion(cfg *config.Config) (string, error) {
	cmd := newCmd(
		cfg, "/usr/bin/xenstore-read",
		"vm-data/provider_data/region")

	cmdOut, err := cmd.Output()
	if err != nil {
		return "",
			errors.WithFields(eff(errors.Fields{
				"cmd.Path": cmd.Path,
				"cmd.Args": cmd.Args,
				"cmd.Out":  cmdOut,
			}), "error getting instance region")
	}

	region := strings.Replace(string(cmdOut), "\n", "", -1)
	return region, nil
}
コード例 #11
0
ファイル: module.go プロジェクト: robnolen/rexray
func InitializeModule(
	modTypeId int32,
	modConfig *ModuleConfig) (*ModuleInstance, error) {

	modInstancesRwl.Lock()
	defer modInstancesRwl.Unlock()

	lf := log.Fields{
		"typeId":  modTypeId,
		"address": modConfig.Address,
	}

	mt, modTypeExists := modTypes[modTypeId]
	if !modTypeExists {
		return nil, errors.WithFields(lf, "unknown module type")
	}

	lf["typeName"] = mt.Name
	lf["ignoreFailOnInit"] = mt.IgnoreFailOnInit

	modInstId := atomic.AddInt32(&nextModInstanceId, 1)
	mod, initErr := mt.InitFunc(modInstId, modConfig)
	if initErr != nil {
		atomic.AddInt32(&nextModInstanceId, -1)
		return nil, initErr
	}

	modInst := &ModuleInstance{
		Id:          modInstId,
		Type:        mt,
		TypeId:      mt.Id,
		Inst:        mod,
		Name:        mod.Name(),
		Config:      modConfig,
		Description: mod.Description(),
	}
	modInstances[modInstId] = modInst

	lf["id"] = modInstId
	log.WithFields(lf).Info("initialized module instance")

	return modInst, nil
}
コード例 #12
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) waitVolumeAttach(volumeID string) error {

	fields := eff(map[string]interface{}{
		"volumeId": volumeID,
	})

	if volumeID == "" {
		return errors.WithFields(fields, "volumeId is required")
	}
	for {
		volume, err := driver.GetVolume(volumeID, "")
		if err != nil {
			return errors.WithFieldsE(fields, "error getting volume", err)
		}
		if volume[0].Status == "in-use" {
			break
		}
		time.Sleep(1 * time.Second)
	}

	return nil
}
コード例 #13
0
ファイル: storage.go プロジェクト: robnolen/rexray
func (driver *Driver) CreateVolume(
	runAsync bool,
	volumeName string,
	volumeID string,
	snapshotID string,
	volumeType string,
	IOPS int64,
	size int64,
	availabilityZone string) (*storage.Volume, error) {

	fields := map[string]interface{}{
		"provider":         ProviderName,
		"runAsync":         runAsync,
		"volumeName":       volumeName,
		"volumeId":         volumeID,
		"snapshotId":       snapshotID,
		"volumeType":       volumeType,
		"iops":             IOPS,
		"size":             size,
		"availabilityZone": availabilityZone,
	}

	if volumeID != "" && runAsync {
		return nil, errors.WithFields(fields,
			"cannot create volume from volume & run async")
	}

	if snapshotID != "" {
		snapshot, err := driver.GetSnapshot("", snapshotID, "")
		if err != nil {
			return nil,
				errors.WithFieldsE(fields, "error getting snapshot", err)
		}

		if len(snapshot) == 0 {
			return nil,
				errors.WithFields(fields, "snapshot array is empty")
		}

		volSize := snapshot[0].VolumeSize
		sizeInt, err := strconv.Atoi(volSize)
		if err != nil {
			f := errors.Fields{
				"volumeSize": volSize,
			}
			for k, v := range fields {
				f[k] = v
			}
			return nil,
				errors.WithFieldsE(f, "error casting volume size", err)
		}
		size = int64(sizeInt)
	}

	var volume []*storage.Volume
	var err error
	if volumeID != "" {
		volume, err = driver.GetVolume(volumeID, "")
		if err != nil {
			return nil, errors.WithFields(fields, "error getting volume")
		}

		if len(volume) == 0 {
			return nil,
				errors.WithFields(fields, "volume array is empty")
		}

		volSize := volume[0].Size
		sizeInt, err := strconv.Atoi(volSize)
		if err != nil {
			f := errors.Fields{
				"volumeSize": volSize,
			}
			for k, v := range fields {
				f[k] = v
			}
			return nil,
				errors.WithFieldsE(f, "error casting volume size", err)
		}
		size = int64(sizeInt)

		volumeID := volume[0].VolumeID
		snapshot, err := driver.CreateSnapshot(
			false, fmt.Sprintf("temp-%s", volumeID), volumeID, "")
		if err != nil {
			return nil,
				errors.WithFields(fields, "error creating snapshot")
		}

		snapshotID = snapshot[0].SnapshotID

		if availabilityZone == "" {
			availabilityZone = volume[0].AvailabilityZone
		}

	}

	if size != 0 && size < minSize {
		size = minSize
	}

	options := &volumes.CreateOpts{
		Name:         volumeName,
		Size:         int(size),
		SnapshotID:   snapshotID,
		VolumeType:   volumeType,
		Availability: availabilityZone,
	}
	resp, err := volumes.Create(driver.ClientBlockStorage, options).Extract()
	if err != nil {
		return nil,
			errors.WithFields(fields, "error creating volume")
	}

	if !runAsync {
		log.Debug("waiting for volume creation to complete")
		err = volumes.WaitForStatus(driver.ClientBlockStorage, resp.ID, "available", 120)
		if err != nil {
			return nil,
				errors.WithFields(fields,
					"error waiting for volume creation to complete")
		}

		if volumeID != "" {
			err := driver.RemoveSnapshot(snapshotID)
			if err != nil {
				return nil,
					errors.WithFields(fields,
						"error removing snapshot")
			}
		}
	}

	fields["volumeId"] = resp.ID
	fields["volumeName"] = ""

	volume, err = driver.GetVolume(resp.ID, "")
	if err != nil {
		return nil, errors.WithFields(fields,
			"error removing snapshot")
	}

	log.WithFields(fields).Debug("created volume")
	return volume[0], nil
}
コード例 #14
0
ファイル: storage.go プロジェクト: robnolen/rexray
func Init(cfg *config.Config) (storage.Driver, error) {

	fields := eff(map[string]interface{}{
		"endpoint":         cfg.XtremIoEndpoint,
		"userName":         cfg.XtremIoUserName,
		"deviceMapper":     cfg.XtremIoDeviceMapper,
		"multipath":        cfg.XtremIoMultipath,
		"remoteManagement": cfg.XtremIoRemoteManagement,
		"insecure":         cfg.XtremIoInsecure,
	})

	if cfg.XtremIoPassword == "" {
		fields["password"] = ""
	} else {
		fields["password"] = "******"
	}

	if !isXtremIOAttached() && !cfg.XtremIoRemoteManagement {
		return nil, errors.WithFields(fields, "device not detected")
	}

	client, cErr := xtio.NewClientWithArgs(
		cfg.XtremIoEndpoint,
		cfg.XtremIoInsecure,
		cfg.XtremIoUserName,
		cfg.XtremIoPassword)

	if cErr != nil {
		return nil,
			errors.WithFieldsE(fields, "error creating xtremio client", cErr)
	}

	var iqn string
	var ini xtio.Initiator
	if !cfg.XtremIoRemoteManagement {
		var iqnErr error
		iqn, iqnErr = getIQN()
		if iqnErr != nil {
			return nil, iqnErr
		}

		var iniErr error
		ini, iniErr = client.GetInitiator("", iqn)
		if iniErr != nil {
			return nil, iniErr
		}
	}

	useDeviceMapper, _ := strconv.ParseBool(os.Getenv("REXRAY_XTREMIO_DM"))
	useMultipath, _ := strconv.ParseBool(os.Getenv("REXRAY_XTREMIO_MULTIPATH"))

	driver := &Driver{
		Client:          client,
		Initiator:       ini,
		UseDeviceMapper: useDeviceMapper,
		UseMultipath:    useMultipath,
		Config:          cfg,
		VolumesByNAA:    map[string]xtio.Volume{},
	}

	log.WithField("provider", ProviderName).Debug(
		"storage driver initialized")

	return driver, nil
}
コード例 #15
0
ファイル: module.go プロジェクト: robnolen/rexray
func StartModule(modInstId int32) error {

	modInstancesRwl.RLock()
	defer modInstancesRwl.RUnlock()

	lf := map[string]interface{}{"id": modInstId}

	mod, modExists := modInstances[modInstId]

	if !modExists {
		return errors.WithFields(lf, "unknown module instance")
	}

	lf["id"] = mod.Id
	lf["typeId"] = mod.Type.Id
	lf["typeName"] = mod.Type.Name
	lf["address"] = mod.Config.Address

	started := make(chan bool)
	timeout := make(chan bool)
	startError := make(chan error)

	go func() {

		defer func() {
			r := recover()
			m := "error starting module"

			errMsg := fmt.Sprintf(
				"Error starting module type %d, %d-%s at %s",
				mod.TypeId, mod.Id, mod.Name, mod.Config.Address)

			if r == nil {
				startError <- errors.New(errMsg)
				return
			}

			switch x := r.(type) {
			case string:
				lf["inner"] = x
				startError <- errors.WithFields(lf, m)
			case error:
				startError <- errors.WithFieldsE(lf, m, x)
			default:
				startError <- errors.WithFields(lf, m)
			}
		}()

		sErr := mod.Inst.Start()
		if sErr != nil {
			startError <- sErr
		} else {
			started <- true
		}
	}()

	go func() {
		time.Sleep(3 * time.Second)
		timeout <- true
	}()

	select {
	case <-started:
		mod.IsStarted = true
		log.WithFields(lf).Info("started module")
	case <-timeout:
		log.WithFields(lf).Debug("timed out while monitoring module start")
	case sErr := <-startError:
		return sErr
	}

	return nil
}