github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/qrm-plugins/io/handlers/iocost/utils.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package iocost
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"strings"
    25  
    26  	"github.com/kubewharf/katalyst-core/pkg/util/general"
    27  )
    28  
    29  func getDevicesIdToModel(deviceNames []string) (map[string]DevModel, error) {
    30  	devsIDToModel := make(map[string]DevModel, len(deviceNames))
    31  	for _, devName := range deviceNames {
    32  		_, err := os.Stat(fmt.Sprintf("/sys/block/%s/device", devName))
    33  		if os.IsNotExist(err) {
    34  			continue
    35  		}
    36  
    37  		devIDFile := fmt.Sprintf("/sys/block/%s/dev", devName)
    38  		devIDBytes, err := ioutil.ReadFile(devIDFile)
    39  		if err != nil {
    40  			general.Errorf("failed to ReadFile %s, err %v", devIDFile, err)
    41  			continue
    42  		}
    43  		devID := strings.TrimSpace(string(devIDBytes))
    44  
    45  		modelBytes, err := ioutil.ReadFile(fmt.Sprintf("/sys/block/%s/device/model", devName))
    46  		if err != nil {
    47  			if strings.HasPrefix(devName, "vd") {
    48  				devsIDToModel[devID] = DevModelVirtualdisk
    49  			}
    50  			continue
    51  		}
    52  
    53  		model := strings.TrimSpace(string(modelBytes))
    54  		if strings.HasPrefix(strings.ToLower(model), "qemu") {
    55  			devsIDToModel[devID] = DevModelVirtualdisk
    56  		} else {
    57  			devsIDToModel[devID] = DevModel(model)
    58  		}
    59  	}
    60  
    61  	return devsIDToModel, nil
    62  }
    63  
    64  func getAllDeviceNames() ([]string, error) {
    65  	files, err := ioutil.ReadDir("/sys/block")
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	allDeviceNames := make([]string, 0, len(files))
    71  	for _, fi := range files {
    72  		allDeviceNames = append(allDeviceNames, fi.Name())
    73  	}
    74  
    75  	return allDeviceNames, nil
    76  }
    77  
    78  func getDeviceNameFromID(targetDevID string) (string, bool, error) {
    79  	allDeviceNames, err := getAllDeviceNames()
    80  	if err != nil {
    81  		return "", false, err
    82  	}
    83  
    84  	for _, devName := range allDeviceNames {
    85  		_, err := os.Stat(fmt.Sprintf("/sys/block/%s/device", devName))
    86  		if os.IsNotExist(err) {
    87  			continue
    88  		}
    89  
    90  		devIDFile := fmt.Sprintf("/sys/block/%s/dev", devName)
    91  		devIDBytes, err := ioutil.ReadFile(devIDFile)
    92  		if err != nil {
    93  			general.Errorf("failed to ReadFile %s, err %v", devIDFile, err)
    94  			continue
    95  		}
    96  		devID := strings.TrimSpace(string(devIDBytes))
    97  
    98  		if devID == targetDevID {
    99  			return devName, true, nil
   100  		}
   101  	}
   102  
   103  	return "", false, nil
   104  }
   105  
   106  func getDeviceType(deviceName, rotationalFilePath string) (DeviceType, error) {
   107  	/* Check if the device name starts with "sd"
   108  	 * sd means scsi devices.
   109  	 * Currently, only HDD/SSD could be scsi device.
   110  	 */
   111  	// Step1, the device should be scsi device.
   112  	if !strings.HasPrefix(deviceName, "sd") {
   113  		return Unknown, fmt.Errorf("not scsi disk")
   114  	}
   115  
   116  	// Step2, if it is scsi device, then check rotational
   117  	// if rotational = 1, then HDD, else SSD.
   118  	cleanedRotationalFilePath := filepath.Clean(rotationalFilePath)
   119  	contents, err := ioutil.ReadFile(cleanedRotationalFilePath)
   120  	if err != nil {
   121  		if os.IsNotExist(err) {
   122  			return Unknown, nil
   123  		}
   124  		return Unknown, err
   125  	}
   126  
   127  	rotational := strings.TrimSpace(string(contents))
   128  	switch rotational {
   129  	case "1":
   130  		return HDD, nil
   131  	case "0":
   132  		return SSD, nil
   133  	default:
   134  		return Unknown, fmt.Errorf("unknown rotational status")
   135  	}
   136  }