diskutil.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. package diskinfo
  2. import (
  3. "errors"
  4. "path/filepath"
  5. "strings"
  6. "imuslab.com/bokofs/bokofsd/mod/diskinfo/blkid"
  7. "imuslab.com/bokofs/bokofsd/mod/diskinfo/df"
  8. "imuslab.com/bokofs/bokofsd/mod/diskinfo/fdisk"
  9. "imuslab.com/bokofs/bokofsd/mod/diskinfo/lsblk"
  10. )
  11. // DevicePathIsValidDisk checks if the given device path is a disk.
  12. func DevicePathIsValidDisk(path string) bool {
  13. //Make sure the path has a prefix and a trailing slash
  14. if !strings.HasPrefix(path, "/dev/") {
  15. path = "/dev/" + path
  16. }
  17. path = strings.TrimSuffix(path, "/")
  18. allBlockDevices, err := lsblk.GetLSBLKOutput()
  19. if err != nil {
  20. return false
  21. }
  22. for _, blockDevice := range allBlockDevices {
  23. if "/dev/"+blockDevice.Name == path {
  24. return blockDevice.Type == "disk"
  25. }
  26. }
  27. return false
  28. }
  29. // DevicePathIsPartition checks if the given device path is a valid partition.
  30. func DevicePathIsValidPartition(path string) bool {
  31. //Make sure the path has a prefix and a trailing slash
  32. if !strings.HasPrefix(path, "/dev/") {
  33. path = "/dev/" + path
  34. }
  35. path = strings.TrimSuffix(path, "/")
  36. allBlockDevices, err := lsblk.GetLSBLKOutput()
  37. if err != nil {
  38. return false
  39. }
  40. for _, blockDevice := range allBlockDevices {
  41. if !strings.HasPrefix(path, "/dev/"+blockDevice.Name) {
  42. //Skip this block device
  43. //This is not a partition of this block device
  44. continue
  45. }
  46. for _, child := range blockDevice.Children {
  47. if "/dev/"+child.Name == path {
  48. //As there are too many partition types
  49. //We can only check if the block device is not a disk and exists
  50. return true
  51. }
  52. }
  53. }
  54. return false
  55. }
  56. // GetDiskInfo retrieves the disk information for a given disk name.
  57. // e.g. "sda"
  58. // for partitions, use the GetPartitionInfo function
  59. func GetDiskInfo(diskname string) (*Disk, error) {
  60. if diskname == "" {
  61. return nil, errors.New("disk name is empty")
  62. }
  63. //Make sure the diskname is something like sda
  64. diskname = strings.TrimPrefix(diskname, "/dev/")
  65. //Create a new disk object
  66. thisDisk := &Disk{
  67. Name: diskname,
  68. Size: 0,
  69. BlockType: "disk",
  70. Partitions: []*Partition{},
  71. }
  72. //Try to get the disk model and identifier
  73. diskInfo, err := fdisk.GetDiskModelAndIdentifier(diskname)
  74. if err == nil {
  75. thisDisk.Model = diskInfo.Model
  76. thisDisk.Identifier = diskInfo.Identifier
  77. thisDisk.DiskLabel = diskInfo.DiskLabel
  78. }
  79. //Calculation variables for total disk used space
  80. totalDiskUseSpace := int64(0)
  81. //Populate the partitions
  82. allBlockDevices, err := lsblk.GetLSBLKOutput()
  83. if err != nil {
  84. return nil, err
  85. }
  86. for _, blockDevice := range allBlockDevices {
  87. if blockDevice.Name == diskname {
  88. thisDisk.Size = blockDevice.Size
  89. for _, partition := range blockDevice.Children {
  90. //Get the partition information from blkid
  91. partition := &Partition{
  92. Name: partition.Name,
  93. Size: partition.Size,
  94. Path: filepath.Join("/dev", partition.Name),
  95. BlockType: partition.Type,
  96. MountPoint: partition.MountPoint,
  97. }
  98. //Get the partition ID
  99. blkInfo, err := blkid.GetPartitionIDFromDevicePath(partition.Name)
  100. if err == nil {
  101. partition.UUID = blkInfo.UUID
  102. partition.PartUUID = blkInfo.PartUUID
  103. partition.PartLabel = blkInfo.PartLabel
  104. partition.BlockSize = blkInfo.BlockSize
  105. partition.BlockType = blkInfo.Type
  106. partition.FsType = blkInfo.Type
  107. }
  108. //Get the disk usage information
  109. diskUsage, err := df.GetDiskUsageByPath(partition.Name)
  110. if err == nil {
  111. partition.Used = diskUsage.Used
  112. partition.Free = diskUsage.Available
  113. }
  114. thisDisk.Partitions = append(thisDisk.Partitions, partition)
  115. }
  116. }
  117. }
  118. //Calculate the total disk used space
  119. for _, partition := range thisDisk.Partitions {
  120. totalDiskUseSpace += partition.Used
  121. }
  122. thisDisk.Used = totalDiskUseSpace
  123. thisDisk.Free = thisDisk.Size - totalDiskUseSpace
  124. return thisDisk, nil
  125. }
  126. func GetPartitionInfo(partitionName string) (*Partition, error) {
  127. partition := &Partition{
  128. Name: partitionName,
  129. }
  130. partInfo, err := blkid.GetPartitionIDFromDevicePath(partitionName)
  131. if err == nil {
  132. partition.UUID = partInfo.UUID
  133. partition.PartUUID = partInfo.PartUUID
  134. partition.PartLabel = partInfo.PartLabel
  135. partition.BlockSize = partInfo.BlockSize
  136. partition.BlockType = partInfo.Type
  137. partition.FsType = partInfo.Type
  138. }
  139. //Get the disk usage information
  140. diskUsage, err := df.GetDiskUsageByPath(partitionName)
  141. if err == nil {
  142. partition.Used = diskUsage.Used
  143. partition.Free = diskUsage.Available
  144. partition.MountPoint = diskUsage.MountedOn
  145. }
  146. return partition, nil
  147. }
  148. // GetDevicePathFromPartitionID retrieves the device path for a given partition ID.
  149. func GetDevicePathFromPartitionID(diskID string) (string, error) {
  150. if diskID == "" {
  151. return "", errors.New("disk ID is empty")
  152. }
  153. // Try to get the block device info
  154. allBlockDevices, err := lsblk.GetLSBLKOutput()
  155. if err != nil {
  156. return "", err
  157. }
  158. for _, blockDevice := range allBlockDevices {
  159. //Check each of the children to see if there is a partition with the given ID
  160. for _, child := range blockDevice.Children {
  161. if child.Name == diskID {
  162. return child.Name, nil
  163. }
  164. }
  165. }
  166. return "", errors.New("disk ID not found")
  167. }