Azure disk: dealing with missing disk probe
Signed-off-by: Huamin Chen <hchen@redhat.com>
This commit is contained in:
@@ -31,6 +31,7 @@ import (
|
||||
type ioHandler interface {
|
||||
ReadDir(dirname string) ([]os.FileInfo, error)
|
||||
WriteFile(filename string, data []byte, perm os.FileMode) error
|
||||
Readlink(name string) (string, error)
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
// VHD disks under sysfs are like /sys/bus/scsi/devices/3:0:1:0
|
||||
// return empty string if no disk is found
|
||||
// exclude those used by azure as resource and OS root in /dev/disk/azure
|
||||
func listAzureDiskPath(io ioHandler) []string {
|
||||
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) {
|
||||
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
|
||||
sys_path := "/sys/bus/scsi/devices"
|
||||
if dirs, err := io.ReadDir(sys_path); err == nil {
|
||||
for _, f := range dirs {
|
||||
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, ":")
|
||||
if len(arr) < 4 {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
// as observed, targets 0-3 are used by OS disks. Skip them
|
||||
if target > 3 {
|
||||
l, err := strconv.Atoi(arr[3])
|
||||
if lun == l {
|
||||
// find the matching LUN
|
||||
// read vendor and model to ensure it is a VHD disk
|
||||
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 {
|
||||
// unknown path format, continue to read the next one
|
||||
glog.Errorf("failed to parse lun from %v (%v), err %v", arr[3], name, err)
|
||||
glog.Errorf("failed to cat device vendor and model, err: %v", err)
|
||||
continue
|
||||
}
|
||||
if lun == l {
|
||||
// find the matching LUN
|
||||
// read vendor and model to ensure it is a VHD disk
|
||||
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 {
|
||||
glog.Errorf("failed to cat device vendor and model, err: %v", err)
|
||||
continue
|
||||
matched, err := regexp.MatchString("^MSFT[ ]{0,}\nVIRTUAL DISK[ ]{0,}\n$", strings.ToUpper(string(out)))
|
||||
if err != nil || !matched {
|
||||
glog.V(4).Infof("doesn't match VHD, output %v, error %v", string(out), err)
|
||||
continue
|
||||
}
|
||||
// find a disk, validate name
|
||||
dir := path.Join(sys_path, name, "block")
|
||||
if dev, err := io.ReadDir(dir); err == nil {
|
||||
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 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 {
|
||||
if !found {
|
||||
return "/dev/" + dev[0].Name(), nil
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user