Commit c00b136c authored by Hemant Kumar's avatar Hemant Kumar

Check for available volume before attach/delete in EBS

We should check for available volume before performing attach or delete of EBS volume. This will make sure that we do not blow up API quota of mutable operations in AWS and stay a good citizen.
parent 40212c17
......@@ -1716,6 +1716,12 @@ func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName,
ec2Device := "/dev/xvd" + string(mountDevice)
if !alreadyAttached {
available, err := c.checkIfAvailable(disk, "attaching", awsInstance.awsID)
if !available {
attachEnded = true
return "", err
}
request := &ec2.AttachVolumeInput{
Device: aws.String(ec2Device),
InstanceId: aws.String(awsInstance.awsID),
......@@ -1948,9 +1954,48 @@ func (c *Cloud) DeleteDisk(volumeName KubernetesVolumeID) (bool, error) {
if err != nil {
return false, err
}
available, err := c.checkIfAvailable(awsDisk, "deleting", "")
if !available {
return false, err
}
return awsDisk.deleteVolume()
}
func (c *Cloud) checkIfAvailable(disk *awsDisk, opName string, instance string) (bool, error) {
info, err := disk.describeVolume()
if err != nil {
glog.Errorf("Error describing volume %q: %q", disk.awsID, err)
// if for some reason we can not describe volume we will return error
return false, err
}
volumeState := aws.StringValue(info.State)
opError := fmt.Sprintf("Error %s EBS volume %q", opName, disk.awsID)
if len(instance) != 0 {
opError = fmt.Sprintf("%q to instance %q", opError, instance)
}
// Only available volumes can be attached or deleted
if volumeState != "available" {
// Volume is attached somewhere else and we can not attach it here
if len(info.Attachments) > 0 {
attachment := info.Attachments[0]
attachErr := fmt.Errorf("%s since volume is currently attached to %q", opError, aws.StringValue(attachment.InstanceId))
glog.Error(attachErr)
return false, attachErr
}
attachErr := fmt.Errorf("%s since volume is in %q state", opError, volumeState)
glog.Error(attachErr)
return false, attachErr
}
return true, nil
}
func (c *Cloud) GetLabelsForVolume(pv *v1.PersistentVolume) (map[string]string, error) {
// Ignore any volumes that are being provisioned
if pv.Spec.AWSElasticBlockStore.VolumeID == volume.ProvisionedVolumeName {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment