raidutils.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package raid
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "path/filepath"
  8. "strings"
  9. "imuslab.com/arozos/mod/disk/diskfs"
  10. )
  11. // Get the next avaible RAID array name
  12. func GetNextAvailableMDDevice() (string, error) {
  13. for i := 0; i < 100; i++ {
  14. mdDevice := fmt.Sprintf("/dev/md%d", i)
  15. if _, err := os.Stat(mdDevice); os.IsNotExist(err) {
  16. return mdDevice, nil
  17. }
  18. }
  19. return "", fmt.Errorf("no available /dev/mdX devices found")
  20. }
  21. // ClearSuperblock clears the superblock of the specified disk so it can be used safely
  22. func (m *Manager) ClearSuperblock(devicePath string) error {
  23. isMounted, err := diskfs.DeviceIsMounted(devicePath)
  24. if err != nil {
  25. return errors.New("unable to validate if the device is unmounted: " + err.Error())
  26. }
  27. if isMounted {
  28. return errors.New("target device is mounted. Make sure it is unmounted before clearing")
  29. }
  30. cmd := exec.Command("sudo", "mdadm", "--zero-superblock", devicePath)
  31. err = cmd.Run()
  32. if err != nil {
  33. return fmt.Errorf("error clearing superblock: %v", err)
  34. }
  35. return nil
  36. }
  37. // Use to restart any not-removed RAID device
  38. func (m *Manager) RestartRAIDService() error {
  39. cmd := exec.Command("sudo", "mdadm", "--assemble", "--scan")
  40. // Run the command
  41. output, err := cmd.CombinedOutput()
  42. if err != nil {
  43. if string(output) == "" {
  44. //Nothing updated in config.
  45. return nil
  46. }
  47. return fmt.Errorf("error restarting RAID device: %s", strings.TrimSpace(string(output)))
  48. }
  49. return nil
  50. }
  51. // Stop RAID device with given path
  52. func (m *Manager) StopRAIDDevice(devicePath string) error {
  53. cmd := exec.Command("sudo", "mdadm", "--stop", devicePath)
  54. // Run the command
  55. err := cmd.Run()
  56. if err != nil {
  57. return fmt.Errorf("error stopping RAID device: %v", err)
  58. }
  59. return nil
  60. }
  61. // RemoveRAIDDevice removes the specified RAID device member (disk).
  62. func (m *Manager) RemoveRAIDMember(devicePath string) error {
  63. // Construct the mdadm command to remove the RAID device
  64. cmd := exec.Command("sudo", "mdadm", "--remove", devicePath)
  65. // Run the command
  66. output, err := cmd.CombinedOutput()
  67. if err != nil {
  68. // If there was an error, return the combined output and the error message
  69. return fmt.Errorf("error removing RAID device: %s", strings.TrimSpace(string(output)))
  70. }
  71. return nil
  72. }
  73. // IsValidRAIDLevel checks if the given RAID level is valid.
  74. func IsValidRAIDLevel(level string) bool {
  75. // List of valid RAID levels
  76. validLevels := []string{"raid1", "raid0", "raid6", "raid5", "raid4", "raid10"}
  77. // Convert the RAID level to lowercase and remove any surrounding whitespace
  78. level = strings.TrimSpace(strings.ToLower(level))
  79. // Check if the level exists in the list of valid levels
  80. for _, validLevel := range validLevels {
  81. if level == validLevel {
  82. return true
  83. }
  84. }
  85. // Return false if the level is not found in the list of valid levels
  86. return false
  87. }
  88. // Get RAID device info from device path
  89. func (m *Manager) GetRAIDDeviceByDevicePath(devicePath string) (*RAIDDevice, error) {
  90. //Strip the /dev/ part if it was accidentally passed in
  91. devicePath = filepath.Base(devicePath)
  92. //Get all the raid devices
  93. rdevs, err := m.GetRAIDDevicesFromProcMDStat()
  94. if err != nil {
  95. return nil, err
  96. }
  97. //Check for match
  98. for _, rdev := range rdevs {
  99. if rdev.Name == devicePath {
  100. return &rdev, nil
  101. }
  102. }
  103. return nil, errors.New("target RAID device not found")
  104. }
  105. // Check if a RAID device exists, e.g. md0
  106. func (m *Manager) RAIDDeviceExists(devicePath string) bool {
  107. _, err := m.GetRAIDDeviceByDevicePath(devicePath)
  108. return err == nil
  109. }