mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Azure disk: dealing with missing disk probe
Signed-off-by: Huamin Chen <hchen@redhat.com>
This commit is contained in:
parent
8667d7c4f1
commit
f14a0744e6
@ -171,6 +171,10 @@ func (attacher *azureDiskAttacher) WaitForAttach(spec *volume.Spec, lunStr strin
|
|||||||
err = wait.Poll(checkSleepDuration, timeout, func() (bool, error) {
|
err = wait.Poll(checkSleepDuration, timeout, func() (bool, error) {
|
||||||
glog.V(4).Infof("Checking Azure disk %q(lun %s) is attached.", volumeSource.DiskName, lunStr)
|
glog.V(4).Infof("Checking Azure disk %q(lun %s) is attached.", volumeSource.DiskName, lunStr)
|
||||||
if devicePath, err = findDiskByLun(lun, &osIOHandler{}, exe); err == nil {
|
if devicePath, err = findDiskByLun(lun, &osIOHandler{}, exe); err == nil {
|
||||||
|
if len(devicePath) == 0 {
|
||||||
|
glog.Warningf("cannot find attached Azure disk %q(lun %s) locally.", volumeSource.DiskName, lunStr)
|
||||||
|
return false, fmt.Errorf("cannot find attached Azure disk %q(lun %s) locally.", volumeSource.DiskName, lunStr)
|
||||||
|
}
|
||||||
glog.V(4).Infof("Successfully found attached Azure disk %q(lun %s, device path %s).", volumeSource.DiskName, lunStr, devicePath)
|
glog.V(4).Infof("Successfully found attached Azure disk %q(lun %s, device path %s).", volumeSource.DiskName, lunStr, devicePath)
|
||||||
return true, nil
|
return true, nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
type ioHandler interface {
|
type ioHandler interface {
|
||||||
ReadDir(dirname string) ([]os.FileInfo, error)
|
ReadDir(dirname string) ([]os.FileInfo, error)
|
||||||
WriteFile(filename string, data []byte, perm os.FileMode) error
|
WriteFile(filename string, data []byte, perm os.FileMode) error
|
||||||
|
Readlink(name string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type osIOHandler struct{}
|
type osIOHandler struct{}
|
||||||
@ -41,56 +42,83 @@ func (handler *osIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
|
|||||||
func (handler *osIOHandler) WriteFile(filename string, data []byte, perm os.FileMode) error {
|
func (handler *osIOHandler) WriteFile(filename string, data []byte, perm os.FileMode) error {
|
||||||
return ioutil.WriteFile(filename, data, perm)
|
return ioutil.WriteFile(filename, data, perm)
|
||||||
}
|
}
|
||||||
|
func (handler *osIOHandler) Readlink(name string) (string, error) {
|
||||||
|
return os.Readlink(name)
|
||||||
|
}
|
||||||
|
|
||||||
// given a LUN find the VHD device path like /dev/sdb
|
// exclude those used by azure as resource and OS root in /dev/disk/azure
|
||||||
// VHD disks under sysfs are like /sys/bus/scsi/devices/3:0:1:0
|
func listAzureDiskPath(io ioHandler) []string {
|
||||||
// return empty string if no disk is found
|
azureDiskPath := "/dev/disk/azure/"
|
||||||
|
var azureDiskList []string
|
||||||
|
if dirs, err := io.ReadDir(azureDiskPath); err == nil {
|
||||||
|
for _, f := range dirs {
|
||||||
|
name := f.Name()
|
||||||
|
diskPath := azureDiskPath + name
|
||||||
|
if link, linkErr := io.Readlink(diskPath); linkErr == nil {
|
||||||
|
sd := link[(strings.LastIndex(link, "/") + 1):]
|
||||||
|
azureDiskList = append(azureDiskList, sd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glog.V(12).Infof("Azure sys disks paths: %v", azureDiskList)
|
||||||
|
return azureDiskList
|
||||||
|
}
|
||||||
|
|
||||||
|
// given a LUN find the VHD device path like /dev/sdd
|
||||||
|
// exclude those disks used by Azure resources and OS root
|
||||||
func findDiskByLun(lun int, io ioHandler, exe exec.Interface) (string, error) {
|
func findDiskByLun(lun int, io ioHandler, exe exec.Interface) (string, error) {
|
||||||
|
azureDisks := listAzureDiskPath(io)
|
||||||
|
return findDiskByLunWithConstraint(lun, io, exe, azureDisks)
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for device /dev/sdX and validate it is a VHD
|
||||||
|
// return empty string if no disk is found
|
||||||
|
func findDiskByLunWithConstraint(lun int, io ioHandler, exe exec.Interface, azureDisks []string) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
sys_path := "/sys/bus/scsi/devices"
|
sys_path := "/sys/bus/scsi/devices"
|
||||||
if dirs, err := io.ReadDir(sys_path); err == nil {
|
if dirs, err := io.ReadDir(sys_path); err == nil {
|
||||||
for _, f := range dirs {
|
for _, f := range dirs {
|
||||||
name := f.Name()
|
name := f.Name()
|
||||||
// look for path like /sys/bus/scsi/devices/3:0:1:0
|
// look for path like /sys/bus/scsi/devices/3:0:0:1
|
||||||
arr := strings.Split(name, ":")
|
arr := strings.Split(name, ":")
|
||||||
if len(arr) < 4 {
|
if len(arr) < 4 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
target, err := strconv.Atoi(arr[0])
|
// extract LUN from the path.
|
||||||
|
// LUN is the last index of the array, i.e. 1 in /sys/bus/scsi/devices/3:0:0:1
|
||||||
|
l, err := strconv.Atoi(arr[3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("failed to parse target from %v (%v), err %v", arr[0], name, err)
|
// unknown path format, continue to read the next one
|
||||||
|
glog.Errorf("failed to parse lun from %v (%v), err %v", arr[3], name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if lun == l {
|
||||||
// as observed, targets 0-3 are used by OS disks. Skip them
|
// find the matching LUN
|
||||||
if target > 3 {
|
// read vendor and model to ensure it is a VHD disk
|
||||||
l, err := strconv.Atoi(arr[3])
|
vendor := path.Join(sys_path, name, "vendor")
|
||||||
|
model := path.Join(sys_path, name, "model")
|
||||||
|
out, err := exe.Command("cat", vendor, model).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// unknown path format, continue to read the next one
|
glog.Errorf("failed to cat device vendor and model, err: %v", err)
|
||||||
glog.Errorf("failed to parse lun from %v (%v), err %v", arr[3], name, err)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if lun == l {
|
matched, err := regexp.MatchString("^MSFT[ ]{0,}\nVIRTUAL DISK[ ]{0,}\n$", strings.ToUpper(string(out)))
|
||||||
// find the matching LUN
|
if err != nil || !matched {
|
||||||
// read vendor and model to ensure it is a VHD disk
|
glog.V(4).Infof("doesn't match VHD, output %v, error %v", string(out), err)
|
||||||
vendor := path.Join(sys_path, name, "vendor")
|
continue
|
||||||
model := path.Join(sys_path, name, "model")
|
}
|
||||||
out, err := exe.Command("cat", vendor, model).CombinedOutput()
|
// find a disk, validate name
|
||||||
if err != nil {
|
dir := path.Join(sys_path, name, "block")
|
||||||
glog.Errorf("failed to cat device vendor and model, err: %v", err)
|
if dev, err := io.ReadDir(dir); err == nil {
|
||||||
continue
|
found := false
|
||||||
|
for _, diskName := range azureDisks {
|
||||||
|
glog.V(12).Infof("validating disk %q with sys disk %q", dev[0].Name(), diskName)
|
||||||
|
if string(dev[0].Name()) == diskName {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
matched, err := regexp.MatchString("^MSFT[ ]{0,}\nVIRTUAL DISK[ ]{0,}\n$", strings.ToUpper(string(out)))
|
if !found {
|
||||||
if err != nil || !matched {
|
|
||||||
glog.V(4).Infof("doesn't match VHD, output %v, error %v", string(out), err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// find it!
|
|
||||||
dir := path.Join(sys_path, name, "block")
|
|
||||||
dev, err := io.ReadDir(dir)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("failed to read %s", dir)
|
|
||||||
} else {
|
|
||||||
return "/dev/" + dev[0].Name(), nil
|
return "/dev/" + dev[0].Name(), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,10 +53,14 @@ func (fi *fakeFileInfo) Sys() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
lun = 1
|
lun = 1
|
||||||
lunStr = "1"
|
lunStr = "1"
|
||||||
diskPath = "4:0:0:" + lunStr
|
diskPath = "4:0:0:" + lunStr
|
||||||
devName = "sda"
|
devName = "sdd"
|
||||||
|
lun1 = 2
|
||||||
|
lunStr1 = "2"
|
||||||
|
diskPath1 = "3:0:0:" + lunStr1
|
||||||
|
devName1 = "sde"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeIOHandler struct{}
|
type fakeIOHandler struct{}
|
||||||
@ -85,6 +89,11 @@ func (handler *fakeIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
|
|||||||
name: devName,
|
name: devName,
|
||||||
}
|
}
|
||||||
return []os.FileInfo{n}, nil
|
return []os.FileInfo{n}, nil
|
||||||
|
case "/sys/bus/scsi/devices/" + diskPath1 + "/block":
|
||||||
|
n := &fakeFileInfo{
|
||||||
|
name: devName1,
|
||||||
|
}
|
||||||
|
return []os.FileInfo{n}, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("bad dir")
|
return nil, fmt.Errorf("bad dir")
|
||||||
}
|
}
|
||||||
@ -93,6 +102,10 @@ func (handler *fakeIOHandler) WriteFile(filename string, data []byte, perm os.Fi
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (handler *fakeIOHandler) Readlink(name string) (string, error) {
|
||||||
|
return "/dev/azure/disk/sda", nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestIoHandler(t *testing.T) {
|
func TestIoHandler(t *testing.T) {
|
||||||
var fcmd exec.FakeCmd
|
var fcmd exec.FakeCmd
|
||||||
fcmd = exec.FakeCmd{
|
fcmd = exec.FakeCmd{
|
||||||
@ -101,16 +114,21 @@ func TestIoHandler(t *testing.T) {
|
|||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
return []byte("Msft \nVirtual Disk \n"), nil
|
return []byte("Msft \nVirtual Disk \n"), nil
|
||||||
},
|
},
|
||||||
|
// cat
|
||||||
|
func() ([]byte, error) {
|
||||||
|
return []byte("Msft \nVirtual Disk \n"), nil
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fake := exec.FakeExec{
|
fake := exec.FakeExec{
|
||||||
CommandScript: []exec.FakeCommandAction{
|
CommandScript: []exec.FakeCommandAction{
|
||||||
func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) },
|
func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||||
|
func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
disk, err := findDiskByLun(lun, &fakeIOHandler{}, &fake)
|
disk, err := findDiskByLun(lun, &fakeIOHandler{}, &fake)
|
||||||
// if no disk matches lun, exit
|
// if no disk matches lun, exit
|
||||||
if disk != "/dev/"+devName || err != nil {
|
if disk != "/dev/"+devName || err != nil {
|
||||||
t.Errorf("no data disk disk found: disk %v err %v", disk, err)
|
t.Errorf("no data disk found: disk %v err %v", disk, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user