func (driver *Driver) AttachVolume(runAsync bool, volumeID, instanceID string) ([]*storagedriver.VolumeAttachment, error) { nextDeviceName, err := driver.GetDeviceNextAvailable() if err != nil { return nil, err } options := &volumeattach.CreateOpts{ Device: nextDeviceName, VolumeID: volumeID, } _, err = volumeattach.Create(driver.Client, instanceID, options).Extract() if err != nil { return nil, err } if !runAsync { log.Println("Waiting for volume attachment to complete") err = driver.waitVolumeAttach(volumeID) if err != nil { return nil, err } } volumeAttachment, err := driver.GetVolumeAttach(volumeID, instanceID) if err != nil { return nil, err } log.Println(fmt.Sprintf("Attached volume %s to instance %s", volumeID, instanceID)) return volumeAttachment, nil }
// Attaches given cinder volume to the compute running kubelet func (os *OpenStack) AttachDisk(instanceID string, diskName string) (string, error) { disk, err := os.getVolume(diskName) if err != nil { return "", err } cClient, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{ Region: os.region, }) if err != nil || cClient == nil { glog.Errorf("Unable to initialize nova client for region: %s", os.region) return "", err } if len(disk.Attachments) > 0 && disk.Attachments[0]["server_id"] != nil { if instanceID == disk.Attachments[0]["server_id"] { glog.V(4).Infof("Disk: %q is already attached to compute: %q", diskName, instanceID) return disk.ID, nil } else { errMsg := fmt.Sprintf("Disk %q is attached to a different compute: %q, should be detached before proceeding", diskName, disk.Attachments[0]["server_id"]) glog.Errorf(errMsg) return "", errors.New(errMsg) } } // add read only flag here if possible spothanis _, err = volumeattach.Create(cClient, instanceID, &volumeattach.CreateOpts{ VolumeID: disk.ID, }).Extract() if err != nil { glog.Errorf("Failed to attach %s volume to %s compute", diskName, instanceID) return "", err } glog.V(2).Infof("Successfully attached %s volume to %s compute", diskName, instanceID) return disk.ID, nil }
func createVolumeAttachment(t *testing.T, computeClient *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, serverId string, volumeId string) { va, err := volumeattach.Create(computeClient, serverId, &volumeattach.CreateOpts{ VolumeID: volumeId, }).Extract() th.AssertNoErr(t, err) defer func() { err = volumes.WaitForStatus(blockClient, volumeId, "in-use", 60) th.AssertNoErr(t, err) err = volumeattach.Delete(computeClient, serverId, va.ID).ExtractErr() th.AssertNoErr(t, err) err = volumes.WaitForStatus(blockClient, volumeId, "available", 60) th.AssertNoErr(t, err) }() }
func (d *driver) AttachVolume( runAsync bool, volumeID, instanceID string, force bool) ([]*core.VolumeAttachment, error) { fields := eff(map[string]interface{}{ "runAsync": runAsync, "volumeId": volumeID, "instanceId": instanceID, }) nextDeviceName, err := d.GetDeviceNextAvailable() if err != nil { return nil, goof.WithFieldsE( fields, "error getting next available device", err) } if force { if err := d.DetachVolume(false, volumeID, "", true); err != nil { return nil, err } } options := &volumeattach.CreateOpts{ Device: nextDeviceName, VolumeID: volumeID, } _, err = volumeattach.Create(d.client, instanceID, options).Extract() if err != nil { return nil, goof.WithFieldsE( fields, "error attaching volume", err) } if !runAsync { log.WithFields(fields).Debug("waiting for volume to attach") err = d.waitVolumeAttach(volumeID) if err != nil { return nil, goof.WithFieldsE( fields, "error waiting for volume to detach", err) } } volumeAttachment, err := d.GetVolumeAttach(volumeID, instanceID) if err != nil { return nil, err } log.WithFields(fields).Debug("volume attached") return volumeAttachment, nil }
func attachVolumesToInstance(computeClient *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, serverId string, vols []interface{}) error { if len(vols) > 0 { for _, v := range vols { va := v.(map[string]interface{}) volumeId := va["volume_id"].(string) device := va["device"].(string) s := "" if serverId != "" { s = serverId } else if va["server_id"] != "" { s = va["server_id"].(string) } else { return fmt.Errorf("Unable to determine server ID to attach volume.") } vaOpts := &volumeattach.CreateOpts{ Device: device, VolumeID: volumeId, } if _, err := volumeattach.Create(computeClient, s, vaOpts).Extract(); err != nil { return err } stateConf := &resource.StateChangeConf{ Pending: []string{"attaching", "available"}, Target: "in-use", Refresh: VolumeV1StateRefreshFunc(blockClient, va["volume_id"].(string)), Timeout: 30 * time.Minute, Delay: 5 * time.Second, MinTimeout: 2 * time.Second, } if _, err := stateConf.WaitForState(); err != nil { return err } log.Printf("[INFO] Attached volume %s to instance %s", volumeId, serverId) } } return nil }
// // VolumeAttach attaches a volume and provides a token clients can use // // to validate that device has appeared locally. func (d *driver) VolumeAttach( ctx types.Context, volumeID string, opts *types.VolumeAttachOpts) (*types.Volume, string, error) { iid := context.MustInstanceID(ctx) fields := eff(map[string]interface{}{ "volumeId": volumeID, "instanceId": iid.ID, }) if opts.Force { if _, err := d.VolumeDetach(ctx, volumeID, &types.VolumeDetachOpts{}); err != nil { return nil, "", err } } options := &volumeattach.CreateOpts{ VolumeID: volumeID, } if opts.NextDevice != nil { options.Device = *opts.NextDevice } volumeAttach, err := volumeattach.Create(d.client, iid.ID, options).Extract() if err != nil { return nil, "", goof.WithFieldsE( fields, "error attaching volume", err) } ctx.WithFields(fields).Debug("waiting for volume to attach") volume, err := d.waitVolumeAttachStatus(ctx, volumeID, true) if err != nil { return nil, "", goof.WithFieldsE( fields, "error waiting for volume to attach", err) } return volume, volumeAttach.Device, nil }
// Create requests the creation of a new volume attachment on the server func Create(client *gophercloud.ServiceClient, serverID string, opts os.CreateOptsBuilder) os.CreateResult { return os.Create(client, serverID, opts) }