This commit is contained in:
@@ -122,55 +122,14 @@ func translateZFSError(err error, operation, name string) error {
|
||||
// execCommand executes a shell command and returns output
|
||||
// For ZFS operations that require elevated privileges, it uses sudo
|
||||
func (s *Service) execCommand(name string, args ...string) (string, error) {
|
||||
// Commands that require root privileges
|
||||
privilegedCommands := []string{"zpool", "zfs"}
|
||||
useSudo := false
|
||||
|
||||
for _, cmd := range privilegedCommands {
|
||||
if strings.Contains(name, cmd) {
|
||||
useSudo = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var cmd *exec.Cmd
|
||||
if useSudo {
|
||||
// Use sudo -n (non-interactive) for privileged commands
|
||||
// This prevents password prompts and will fail if sudoers is not configured
|
||||
sudoArgs := append([]string{"-n", name}, args...)
|
||||
cmd = exec.Command("sudo", sudoArgs...)
|
||||
} else {
|
||||
cmd = exec.Command(name, args...)
|
||||
}
|
||||
// Service runs as root, no need for sudo
|
||||
cmd := exec.Command(name, args...)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil && useSudo {
|
||||
// Log that sudo failed
|
||||
log.Printf("sudo command failed, trying direct execution: %s %v (error: %v, stderr: %s)", name, args, err, stderr.String())
|
||||
|
||||
// If sudo failed, try running the command directly
|
||||
// (user might already have permissions or be root)
|
||||
directCmd := exec.Command(name, args...)
|
||||
var directStdout, directStderr bytes.Buffer
|
||||
directCmd.Stdout = &directStdout
|
||||
directCmd.Stderr = &directStderr
|
||||
|
||||
directErr := directCmd.Run()
|
||||
if directErr == nil {
|
||||
// Direct execution succeeded, return that result
|
||||
log.Printf("direct command execution succeeded (without sudo)")
|
||||
return strings.TrimSpace(directStdout.String()), nil
|
||||
}
|
||||
// Both sudo and direct failed, return the direct error (usually cleaner)
|
||||
log.Printf("both sudo and direct execution failed - sudo error: %v, direct error: %v", err, directErr)
|
||||
log.Printf("sudo stderr: %s, direct stderr: %s", stderr.String(), directStderr.String())
|
||||
// Return the direct error (usually has the actual ZFS error message)
|
||||
return "", fmt.Errorf("%s: %s", name, strings.TrimSpace(directStderr.String()))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Printf("command execution failed: %s %v (error: %v, stderr: %s)", name, args, err, stderr.String())
|
||||
@@ -650,41 +609,29 @@ func (s *Service) createMountpointWithSudo(path string) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Use sudo to create the directory with proper permissions
|
||||
// Try multiple methods to ensure directory is created
|
||||
methods := []struct {
|
||||
name string
|
||||
cmd *exec.Cmd
|
||||
}{
|
||||
{"sudo mkdir", exec.Command("sudo", "-n", "mkdir", "-p", path)},
|
||||
{"direct mkdir", exec.Command("mkdir", "-p", path)},
|
||||
}
|
||||
// Service runs as root, no need for sudo
|
||||
cmd := exec.Command("mkdir", "-p", path)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
var lastErr error
|
||||
for _, method := range methods {
|
||||
var stderr bytes.Buffer
|
||||
method.cmd.Stderr = &stderr
|
||||
|
||||
if err := method.cmd.Run(); err == nil {
|
||||
// Success - verify directory was created and set permissions
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
// Set proper permissions (755) and ownership if needed
|
||||
chmodCmd := exec.Command("sudo", "-n", "chmod", "755", path)
|
||||
_ = chmodCmd.Run() // Ignore errors, permissions might already be correct
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
lastErr = fmt.Errorf("%s failed: %v: %s", method.name, err, stderr.String())
|
||||
log.Printf("warning: %s failed: %v", method.name, lastErr)
|
||||
if err := cmd.Run(); err == nil {
|
||||
// Success - verify directory was created and set permissions
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
// Set proper permissions (755)
|
||||
chmodCmd := exec.Command("chmod", "755", path)
|
||||
_ = chmodCmd.Run() // Ignore errors, permissions might already be correct
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
log.Printf("warning: mkdir failed: %v: %s", err, stderr.String())
|
||||
}
|
||||
|
||||
// All methods failed, but check if directory exists anyway (might have been created by ZFS or another process)
|
||||
// Check if directory exists anyway (might have been created by ZFS or another process)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("all methods failed to create mountpoint %s: %v", path, lastErr)
|
||||
return fmt.Errorf("failed to create mountpoint directory %s", path)
|
||||
}
|
||||
|
||||
// DestroyPool destroys a ZFS pool
|
||||
@@ -1398,7 +1345,7 @@ func (s *Service) getDiskHealth(diskName string) map[string]string {
|
||||
}
|
||||
|
||||
// Get overall health status
|
||||
cmd := exec.Command("sudo", "-n", smartctlPath, "-H", diskPath)
|
||||
cmd := exec.Command(smartctlPath, "-H", diskPath)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
// Check if it's because SMART is not supported (common for virtual disks)
|
||||
@@ -1443,7 +1390,7 @@ func (s *Service) getDiskHealth(diskName string) map[string]string {
|
||||
}
|
||||
|
||||
// Get detailed SMART attributes
|
||||
cmd = exec.Command("sudo", "-n", smartctlPath, "-A", diskPath)
|
||||
cmd = exec.Command(smartctlPath, "-A", diskPath)
|
||||
attrOutput, err := cmd.Output()
|
||||
if err != nil {
|
||||
// Return what we have
|
||||
|
||||
Reference in New Issue
Block a user