storages.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package sysutils
  15. import (
  16. "io/ioutil"
  17. "path/filepath"
  18. "strconv"
  19. "yunion.io/x/pkg/errors"
  20. )
  21. type SStorage struct {
  22. Device string
  23. Rotational bool
  24. Size int64
  25. ReadOnly bool
  26. Removable bool
  27. Partition bool
  28. Scheduler string
  29. }
  30. const (
  31. sysBlockDir = "/sys/class/block"
  32. )
  33. func DetectStorageType() (string, error) {
  34. ss, err := DetectStorages()
  35. if err != nil {
  36. return "", errors.Wrap(err, "DetectStorages")
  37. }
  38. var hdd, ssd int
  39. for _, s := range ss {
  40. if s.Partition {
  41. continue
  42. }
  43. if s.Removable {
  44. continue
  45. }
  46. if s.Rotational {
  47. hdd++
  48. } else {
  49. ssd++
  50. }
  51. }
  52. if hdd > 0 && ssd > 0 {
  53. return "hybrid", nil
  54. } else if hdd > 0 {
  55. return "hdd", nil
  56. } else if ssd > 0 {
  57. return "ssd", nil
  58. } else {
  59. return "", nil
  60. }
  61. }
  62. func DetectStorages() ([]SStorage, error) {
  63. files, err := ioutil.ReadDir(sysBlockDir)
  64. if err != nil {
  65. return nil, errors.Wrap(err, "ReadDir /sys/class/block")
  66. }
  67. ret := make([]SStorage, 0)
  68. for _, f := range files {
  69. s := detectStorage(filepath.Join(sysBlockDir, f.Name()), f.Name())
  70. ret = append(ret, s)
  71. }
  72. return ret, nil
  73. }
  74. func detectStorage(path string, name string) SStorage {
  75. s := SStorage{
  76. Device: name,
  77. }
  78. sizeBytes, _ := ioutil.ReadFile(filepath.Join(path, "size"))
  79. s.Size, _ = strconv.ParseInt(string(sizeBytes), 10, 64)
  80. removableBytes, _ := ioutil.ReadFile(filepath.Join(path, "removable"))
  81. if len(removableBytes) > 0 && removableBytes[0] == '0' {
  82. s.Removable = false
  83. } else {
  84. s.Removable = true
  85. }
  86. roBytes, _ := ioutil.ReadFile(filepath.Join(path, "ro"))
  87. if len(roBytes) > 0 && roBytes[0] == '0' {
  88. s.ReadOnly = false
  89. } else {
  90. s.ReadOnly = true
  91. }
  92. partitionBytes, _ := ioutil.ReadFile(filepath.Join(path, "partition"))
  93. if len(partitionBytes) > 0 && partitionBytes[0] == '1' {
  94. s.Partition = true
  95. } else {
  96. s.Partition = false
  97. }
  98. rotationalBytes, _ := ioutil.ReadFile(filepath.Join(path, "queue/rotational"))
  99. if len(rotationalBytes) > 0 && rotationalBytes[0] == '0' {
  100. s.Rotational = false
  101. } else {
  102. s.Rotational = true
  103. }
  104. schedulerBytes, _ := ioutil.ReadFile(filepath.Join(path, "queue/scheduler"))
  105. s.Scheduler = string(schedulerBytes)
  106. return s
  107. }