raidutils.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package raid
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "os"
  7. "os/exec"
  8. "strings"
  9. )
  10. // Get the next avaible RAID array name
  11. func GetNextAvailableMDDevice() (string, error) {
  12. for i := 0; i < 100; i++ {
  13. mdDevice := fmt.Sprintf("/dev/md%d", i)
  14. if _, err := os.Stat(mdDevice); os.IsNotExist(err) {
  15. return mdDevice, nil
  16. }
  17. }
  18. return "", fmt.Errorf("no available /dev/mdX devices found")
  19. }
  20. // DANGER: Wipe the whole disk given the disk path
  21. func (m *Manager) WipeDisk(diskPath string) error {
  22. // Unmount the disk
  23. isMounted, _ := DeviceIsMounted(diskPath)
  24. if isMounted {
  25. umountCmd := exec.Command("sudo", "umount", diskPath)
  26. if err := umountCmd.Run(); err != nil {
  27. return fmt.Errorf("error unmounting disk %s: %v", diskPath, err)
  28. }
  29. }
  30. // Wipe all filesystem signatures on the entire disk
  31. wipeCmd := exec.Command("sudo", "wipefs", "--all", "--force", diskPath)
  32. if err := wipeCmd.Run(); err != nil {
  33. return fmt.Errorf("error wiping filesystem signatures on %s: %v", diskPath, err)
  34. }
  35. return nil
  36. }
  37. // ClearSuperblock clears the superblock of the specified disk.
  38. func (m *Manager) ClearSuperblock(devicePath string) error {
  39. isMounted, err := DeviceIsMounted(devicePath)
  40. if err != nil {
  41. return errors.New("unable to validate if the device is unmounted: " + err.Error())
  42. }
  43. if isMounted {
  44. return errors.New("target device is mounted. Make sure it is unmounted before clearing")
  45. }
  46. cmd := exec.Command("sudo", "mdadm", "--zero-superblock", devicePath)
  47. err = cmd.Run()
  48. if err != nil {
  49. return fmt.Errorf("error clearing superblock: %v", err)
  50. }
  51. return nil
  52. }
  53. // Check if a device is mounted given the path name, like /dev/sdc
  54. func DeviceIsMounted(devicePath string) (bool, error) {
  55. // Open the mountinfo file
  56. file, err := os.Open("/proc/mounts")
  57. if err != nil {
  58. return false, fmt.Errorf("error opening /proc/mounts: %v", err)
  59. }
  60. defer file.Close()
  61. // Scan the mountinfo file line by line
  62. scanner := bufio.NewScanner(file)
  63. for scanner.Scan() {
  64. line := scanner.Text()
  65. fields := strings.Fields(line)
  66. if len(fields) >= 2 && fields[0] == devicePath {
  67. // Device is mounted
  68. return true, nil
  69. }
  70. }
  71. // Device is not mounted
  72. return false, nil
  73. }