The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6206
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) ===
From 1d4cb2778c2c602ceadd81308e99e2ec7836450b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Thu, 12 Sep 2019 07:22:57 +0100 Subject: [PATCH 1/3] api: Add resources_disk_sata extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- doc/api-extensions.md | 9 +++++++++ shared/version/api.go | 1 + 2 files changed, 10 insertions(+) diff --git a/doc/api-extensions.md b/doc/api-extensions.md index 98f0a39a83..a94285efce 100644 --- a/doc/api-extensions.md +++ b/doc/api-extensions.md @@ -829,3 +829,12 @@ This introduces the concept of instances, of which currently the only type is "c ## image\_types This introduces support for a new Type field on images, indicating what type of images they are. + +## resources\_disk\_sata +Extends the disk resource API struct to include: + - Proper detection of sata devices (type) + - Device path + - Drive RPM + - Block size + - Firmware version + - Model revision diff --git a/shared/version/api.go b/shared/version/api.go index 48aa25a7d7..d6d182821d 100644 --- a/shared/version/api.go +++ b/shared/version/api.go @@ -166,6 +166,7 @@ var APIExtensions = []string{ "daemon_storage", "instances", "image_types", + "resources_disk_sata", } // APIExtensionsCount returns the number of available API extensions. From fb546cd88bfde200e685958e5140c758130d26ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Thu, 12 Sep 2019 07:23:47 +0100 Subject: [PATCH 2/3] shared/api: Extend ResourcesStorageDisk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- shared/api/resource.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shared/api/resource.go b/shared/api/resource.go index 6590398848..8b0be0220f 100644 --- a/shared/api/resource.go +++ b/shared/api/resource.go @@ -223,6 +223,14 @@ type ResourcesStorageDisk struct { WWN string `json:"wwn,omitempty" yaml:"wwn,omitempty"` NUMANode uint64 `json:"numa_node" yaml:"numa_node"` + // API extension: resources_disk_sata + DevicePath string `json:"device_path" yaml:"device_path"` + BlockSize uint64 `json:"block_size" yaml:"block_size"` + FirmwareVersion string `json:"firmware_version,omitempty" yaml:"firmware_version,omitempty"` + RPM uint64 `json:"rpm" yaml:"rpm"` + ModelRevision string `json:"model_revision,omitempty" yaml:"model_revision,omitempty"` + Serial string `json:"serial,omitempty" yaml:"serial,omitempty"` + Partitions []ResourcesStorageDiskPartition `json:"partitions" yaml:"partitions"` } From 35a2690a1e64b5a94dcaddd98dcd5f094fbd690d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com> Date: Fri, 13 Sep 2019 02:21:56 +0200 Subject: [PATCH 3/3] lxd/resources: Add extra storage fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- lxd/resources/storage.go | 125 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/lxd/resources/storage.go b/lxd/resources/storage.go index ffd5d0fa4b..0a0fe6a1ad 100644 --- a/lxd/resources/storage.go +++ b/lxd/resources/storage.go @@ -1,17 +1,104 @@ package resources import ( + "bufio" + "fmt" "io/ioutil" + "os" "path/filepath" + "strconv" "strings" "github.com/pkg/errors" + "golang.org/x/sys/unix" "github.com/lxc/lxd/shared/api" ) +var devDiskByPath = "/dev/disk/by-path" +var runUdevData = "/run/udev/data" var sysClassBlock = "/sys/class/block" +func storageAddDriveInfo(devicePath string, disk *api.ResourcesStorageDisk) error { + // Attempt to open the device path + f, err := os.Open(devicePath) + if err != nil { + if !os.IsPermission(err) && !os.IsNotExist(err) { + return err + } + } else { + defer f.Close() + fd := int(f.Fd()) + + // Retrieve the block size + res, err := unix.IoctlGetInt(fd, unix.BLKPBSZGET) + if err != nil { + return err + } + + disk.BlockSize = uint64(res) + } + + // Retrieve udev information + udevInfo := filepath.Join(runUdevData, fmt.Sprintf("b%s", disk.Device)) + if sysfsExists(udevInfo) { + // Get the udev information + f, err := os.Open(udevInfo) + if err != nil { + return errors.Wrapf(err, "Failed to open \"%s\"", udevInfo) + } + defer f.Close() + + udevInfo := bufio.NewScanner(f) + for udevInfo.Scan() { + line := strings.TrimSpace(udevInfo.Text()) + + if !strings.HasPrefix(line, "E:") { + continue + } + + fields := strings.SplitN(line, "=", 2) + if len(fields) != 2 { + continue + } + + key := strings.TrimSpace(fields[0]) + value := strings.TrimSpace(fields[1]) + + // Finer grained disk type + if key == "E:ID_ATA_SATA" && value == "1" { + disk.Type = "sata" + } + + if key == "E:ID_USB_DRIVER" && value == "usb-storage" { + disk.Type = "usb" + } + + // Model revision number + if key == "E:ID_REVISION" && disk.ModelRevision == "" { + disk.ModelRevision = value + } + + // Serial number + if key == "E:ID_SERIAL_SHORT" && disk.Serial == "" { + disk.Serial = value + } + + // Rotation per minute + if key == "E:ID_ATA_ROTATION_RATE_RPM" && disk.RPM == 0 { + valueUint, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return errors.Wrap(err, "Failed to parse RPM value") + } + + disk.RPM = valueUint + } + } + } + + return nil +} + // GetStorage returns a filled api.ResourcesStorage struct ready for use by LXD func GetStorage() (*api.ResourcesStorage, error) { storage := api.ResourcesStorage{} @@ -39,6 +126,16 @@ func GetStorage() (*api.ResourcesStorage, error) { disk := api.ResourcesStorageDisk{} disk.ID = entryName + // Firmware revision + if sysfsExists(filepath.Join(devicePath, "firmware_rev")) { + firmwareRevision, err := ioutil.ReadFile(filepath.Join(devicePath, "firmware_rev")) + if err != nil { + return nil, errors.Wrapf(err, "Failed to read \"%s\"", filepath.Join(devicePath, "firmware_rev")) + } + + disk.FirmwareVersion = strings.TrimSpace(string(firmwareRevision)) + } + // Device node diskDev, err := ioutil.ReadFile(filepath.Join(entryPath, "dev")) if err != nil { @@ -158,6 +255,34 @@ func GetStorage() (*api.ResourcesStorage, error) { disk.Partitions = append(disk.Partitions, partition) } + // Try to find the udev device path + if sysfsExists(devDiskByPath) { + links, err := ioutil.ReadDir(devDiskByPath) + if err != nil { + return nil, errors.Wrapf(err, "Failed to list the links in \"%s\"", devDiskByPath) + } + + for _, link := range links { + linkName := link.Name() + linkPath := filepath.Join(devDiskByPath, linkName) + + linkTarget, err := filepath.EvalSymlinks(linkPath) + if err != nil { + return nil, errors.Wrapf(err, "Failed to track down \"%s\"", linkPath) + } + + if linkTarget == filepath.Join("/dev", entryName) { + disk.DevicePath = linkName + } + } + } + + // Pull direct disk information + err = storageAddDriveInfo(filepath.Join("/dev", entryName), &disk) + if err != nil { + return nil, errors.Wrapf(err, "Failed to retrieve disk information from \"%s\"", filepath.Join("/dev", entryName)) + } + // Add to list storage.Disks = append(storage.Disks, disk) }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel