Merge pull request #57549 from andyzhangx/azurediskid-fix

Automatic merge from submit-queue (batch tested with PRs 56382, 57549). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

fix azure disk not available issue when device name changed

**What this PR does / why we need it**:
There is possibility that device name(`/dev/sd*`) would change when attach/detach data disk in Azure VM according to  [Troubleshoot Linux VM device name change](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/troubleshoot-device-names-problems). 
And We did hit this issue, see customer [case](https://github.com/Azure/acs-engine/issues/1918). 
This PR would use `/dev/disk/by-id` instead of `/dev/sd*` for azure disk and `/dev/disk/by-id` would not change even device name changed.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #57444

**Special notes for your reviewer**:
In a customer [case](https://github.com/Azure/acs-engine/issues/1918), customer is unable to use azure disk in StatefulSet since /dev/sd* changed after detach/attach disk. 
we are using `/dev/sd*`(code is [here](https://github.com/kubernetes/kubernetes/blob/master/pkg/volume/azure_dd/azure_common_linux.go#L140)) to "mount -bind" k8s path, while `/dev/sd*` could be changed when VM is attach/detaching data disks, see [Troubleshoot Linux VM device name change](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/troubleshoot-device-names-problems)
And I have also checked related AWS, GCE code, they are using `/dev/disk/by-id/` other than `/dev/sd*`, see [aws code](https://github.com/kubernetes/kubernetes/blob/master/pkg/volume/aws_ebs/aws_util.go#L228)  
[gce code](https://github.com/kubernetes/kubernetes/blob/master/pkg/volume/gce_pd/gce_util.go#L278)

**Release note**:

```
fix azure disk not available when device name changed
```
/sig azure
/assign @rootfs 
@karataliu @brendandburns @khenidak
This commit is contained in:
Kubernetes Submit Queue 2018-01-04 06:40:34 -08:00 committed by GitHub
commit d8680a3c43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -19,6 +19,7 @@ limitations under the License.
package azure_dd package azure_dd
import ( import (
"fmt"
"path" "path"
"strconv" "strconv"
libstrings "strings" libstrings "strings"
@ -45,6 +46,28 @@ func listAzureDiskPath(io ioHandler) []string {
return azureDiskList return azureDiskList
} }
// getDiskLinkByDevName get disk link by device name from devLinkPath, e.g. /dev/disk/azure/, /dev/disk/by-id/
func getDiskLinkByDevName(io ioHandler, devLinkPath, devName string) (string, error) {
dirs, err := io.ReadDir(devLinkPath)
glog.V(12).Infof("azureDisk - begin to find %s from %s", devName, devLinkPath)
if err == nil {
for _, f := range dirs {
diskPath := devLinkPath + f.Name()
glog.V(12).Infof("azureDisk - begin to Readlink: %s", diskPath)
link, linkErr := io.Readlink(diskPath)
if linkErr != nil {
glog.Warningf("azureDisk - read link (%s) error: %v", diskPath, linkErr)
continue
}
if libstrings.HasSuffix(link, devName) {
return diskPath, nil
}
}
return "", fmt.Errorf("device name(%s) is not found under %s", devName, devLinkPath)
}
return "", fmt.Errorf("read %s error: %v", devLinkPath, err)
}
func scsiHostRescan(io ioHandler, exec mount.Exec) { func scsiHostRescan(io ioHandler, exec mount.Exec) {
scsi_path := "/sys/class/scsi_host/" scsi_path := "/sys/class/scsi_host/"
if dirs, err := io.ReadDir(scsi_path); err == nil { if dirs, err := io.ReadDir(scsi_path); err == nil {
@ -129,15 +152,25 @@ func findDiskByLunWithConstraint(lun int, io ioHandler, azureDisks []string) (st
dir := path.Join(sys_path, name, "block") dir := path.Join(sys_path, name, "block")
if dev, err := io.ReadDir(dir); err == nil { if dev, err := io.ReadDir(dir); err == nil {
found := false found := false
devName := dev[0].Name()
for _, diskName := range azureDisks { for _, diskName := range azureDisks {
glog.V(12).Infof("azure disk - validating disk %q with sys disk %q", dev[0].Name(), diskName) glog.V(12).Infof("azureDisk - validating disk %q with sys disk %q", devName, diskName)
if string(dev[0].Name()) == diskName { if devName == diskName {
found = true found = true
break break
} }
} }
if !found { if !found {
return "/dev/" + dev[0].Name(), nil devLinkPaths := []string{"/dev/disk/azure/scsi1/", "/dev/disk/by-id/"}
for _, devLinkPath := range devLinkPaths {
diskPath, err := getDiskLinkByDevName(io, devLinkPath, devName)
if err == nil {
glog.V(4).Infof("azureDisk - found %s by %s under %s", diskPath, devName, devLinkPath)
return diskPath, nil
}
glog.Warningf("azureDisk - getDiskLinkByDevName by %s under %s failed, error: %v", devName, devLinkPath, err)
}
return "/dev/" + devName, nil
} }
} }
} }