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