mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-08 03:33:56 +00:00
AWS: Sanity checks after volume attach
In the light of issue #29324, double check that the volume was attached correctly where we expect it, before returning. Issue #29324
This commit is contained in:
parent
81240da858
commit
6a1f892c1d
@ -1271,47 +1271,50 @@ func (d *awsDisk) describeVolume() (*ec2.Volume, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// waitForAttachmentStatus polls until the attachment status is the expected value
|
// waitForAttachmentStatus polls until the attachment status is the expected value
|
||||||
// TODO(justinsb): return (bool, error)
|
// On success, it returns the last attachment state.
|
||||||
func (d *awsDisk) waitForAttachmentStatus(status string) error {
|
func (d *awsDisk) waitForAttachmentStatus(status string) (*ec2.VolumeAttachment, error) {
|
||||||
// TODO: There may be a faster way to get this when we're attaching locally
|
|
||||||
attempt := 0
|
attempt := 0
|
||||||
maxAttempts := 60
|
maxAttempts := 60
|
||||||
|
|
||||||
for {
|
for {
|
||||||
info, err := d.describeVolume()
|
info, err := d.describeVolume()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(info.Attachments) > 1 {
|
if len(info.Attachments) > 1 {
|
||||||
|
// Shouldn't happen; log so we know if it is
|
||||||
glog.Warningf("Found multiple attachments for volume: %v", info)
|
glog.Warningf("Found multiple attachments for volume: %v", info)
|
||||||
}
|
}
|
||||||
|
var attachment *ec2.VolumeAttachment
|
||||||
attachmentStatus := ""
|
attachmentStatus := ""
|
||||||
for _, attachment := range info.Attachments {
|
for _, a := range info.Attachments {
|
||||||
if attachmentStatus != "" {
|
if attachmentStatus != "" {
|
||||||
glog.Warning("Found multiple attachments: ", info)
|
// Shouldn't happen; log so we know if it is
|
||||||
|
glog.Warningf("Found multiple attachments: %v", info)
|
||||||
}
|
}
|
||||||
if attachment.State != nil {
|
if a.State != nil {
|
||||||
attachmentStatus = *attachment.State
|
attachment = a
|
||||||
|
attachmentStatus = *a.State
|
||||||
} else {
|
} else {
|
||||||
// Shouldn't happen, but don't panic...
|
// Shouldn't happen; log so we know if it is
|
||||||
glog.Warning("Ignoring nil attachment state: ", attachment)
|
glog.Warningf("Ignoring nil attachment state: %v", a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if attachmentStatus == "" {
|
if attachmentStatus == "" {
|
||||||
attachmentStatus = "detached"
|
attachmentStatus = "detached"
|
||||||
}
|
}
|
||||||
if attachmentStatus == status {
|
if attachmentStatus == status {
|
||||||
return nil
|
return attachment, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(2).Infof("Waiting for volume state: actual=%s, desired=%s", attachmentStatus, status)
|
|
||||||
|
|
||||||
attempt++
|
attempt++
|
||||||
if attempt > maxAttempts {
|
if attempt > maxAttempts {
|
||||||
glog.Warningf("Timeout waiting for volume state: actual=%s, desired=%s", attachmentStatus, status)
|
glog.Warningf("Timeout waiting for volume state: actual=%s, desired=%s", attachmentStatus, status)
|
||||||
return errors.New("Timeout waiting for volume state")
|
return nil, fmt.Errorf("Timeout waiting for volume state: actual=%s, desired=%s", attachmentStatus, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glog.V(2).Infof("Waiting for volume state: actual=%s, desired=%s", attachmentStatus, status)
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1431,7 +1434,7 @@ func (c *Cloud) AttachDisk(diskName string, instanceName string, readOnly bool)
|
|||||||
glog.V(2).Infof("AttachVolume request returned %v", attachResponse)
|
glog.V(2).Infof("AttachVolume request returned %v", attachResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = disk.waitForAttachmentStatus("attached")
|
attachment, err := disk.waitForAttachmentStatus("attached")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -1439,6 +1442,20 @@ func (c *Cloud) AttachDisk(diskName string, instanceName string, readOnly bool)
|
|||||||
// The attach operation has finished
|
// The attach operation has finished
|
||||||
attachEnded = true
|
attachEnded = true
|
||||||
|
|
||||||
|
// Double check the attachment to be 100% sure we attached the correct volume at the correct mountpoint
|
||||||
|
// It could happen otherwise that we see the volume attached from a previous/separate AttachVolume call,
|
||||||
|
// which could theoretically be against a different device (or even instance).
|
||||||
|
if attachment == nil {
|
||||||
|
// Impossible?
|
||||||
|
return "", fmt.Errorf("unexpected state: attachment nil after attached")
|
||||||
|
}
|
||||||
|
if ec2Device != aws.StringValue(attachment.Device) {
|
||||||
|
return "", fmt.Errorf("disk attachment failed: requested device %q but found %q", ec2Device, aws.StringValue(attachment.Device))
|
||||||
|
}
|
||||||
|
if awsInstance.awsID != aws.StringValue(attachment.InstanceId) {
|
||||||
|
return "", fmt.Errorf("disk attachment failed: requested instance %q but found %q", awsInstance.awsID, aws.StringValue(attachment.InstanceId))
|
||||||
|
}
|
||||||
|
|
||||||
return hostDevice, nil
|
return hostDevice, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1486,10 +1503,14 @@ func (c *Cloud) DetachDisk(diskName string, instanceName string) (string, error)
|
|||||||
return "", errors.New("no response from DetachVolume")
|
return "", errors.New("no response from DetachVolume")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = disk.waitForAttachmentStatus("detached")
|
attachment, err := disk.waitForAttachmentStatus("detached")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
if attachment != nil {
|
||||||
|
// We expect it to be nil, it is (maybe) interesting if it is not
|
||||||
|
glog.V(2).Infof("waitForAttachmentStatus returned non-nil attachment with state=detached: %v", attachment)
|
||||||
|
}
|
||||||
|
|
||||||
if mountDevice != "" {
|
if mountDevice != "" {
|
||||||
c.endAttaching(awsInstance, disk.awsID, mountDevice)
|
c.endAttaching(awsInstance, disk.awsID, mountDevice)
|
||||||
|
Loading…
Reference in New Issue
Block a user