run as superuser
Some checks failed
CI / test-build (push) Has been cancelled

This commit is contained in:
2025-12-20 19:29:41 +00:00
parent 6202ef8e83
commit b1a47685f9
4 changed files with 42 additions and 95 deletions

View File

@@ -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