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

@@ -73,7 +73,7 @@ func (s *ISCSIService) ApplyConfiguration(targets []models.ISCSITarget) error {
func (s *ISCSIService) createTarget(target models.ISCSITarget) error {
// Use targetcli to create target
// Format: targetcli /iscsi create <IQN>
cmd := exec.Command("sudo", "-n", s.targetcliPath, "/iscsi", "create", target.IQN)
cmd := exec.Command(s.targetcliPath, "/iscsi", "create", target.IQN)
output, err := cmd.CombinedOutput()
if err != nil {
// Target might already exist, which is OK
@@ -88,13 +88,13 @@ func (s *ISCSIService) createTarget(target models.ISCSITarget) error {
// Enable TPG1 (Target Portal Group 1)
// Disable authentication
cmd = exec.Command("sudo", "-n", s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1", "set", "attribute", "authentication=0")
cmd = exec.Command(s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1", "set", "attribute", "authentication=0")
if output, err := cmd.CombinedOutput(); err != nil {
fmt.Printf("warning: failed to set authentication=0: %v (output: %s)\n", err, string(output))
}
// Enable generate_node_acls (allow all initiators if no ACLs specified)
cmd = exec.Command("sudo", "-n", s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1", "set", "attribute", "generate_node_acls=1")
cmd = exec.Command(s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1", "set", "attribute", "generate_node_acls=1")
if output, err := cmd.CombinedOutput(); err != nil {
fmt.Printf("warning: failed to set generate_node_acls=1: %v (output: %s)\n", err, string(output))
} else {
@@ -102,20 +102,20 @@ func (s *ISCSIService) createTarget(target models.ISCSITarget) error {
}
// Create portal if not exists (listen on all interfaces, port 3260)
cmd = exec.Command("sudo", "-n", s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "create")
cmd = exec.Command(s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "create")
if err := cmd.Run(); err != nil {
// Portal might already exist, which is OK
// Check if portal exists
cmd = exec.Command("sudo", "-n", s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "ls")
cmd = exec.Command(s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "ls")
output, err2 := cmd.Output()
if err2 != nil || len(strings.TrimSpace(string(output))) == 0 {
// No portal exists, try to create with specific IP
// Get system IP
systemIP, _ := s.getSystemIP()
cmd = exec.Command("sudo", "-n", s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "create", systemIP)
cmd = exec.Command(s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "create", systemIP)
if err3 := cmd.Run(); err3 != nil {
// Try with 0.0.0.0 (all interfaces)
cmd = exec.Command("sudo", "-n", s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "create", "0.0.0.0")
cmd = exec.Command(s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1/portals", "create", "0.0.0.0")
if err4 := cmd.Run(); err4 != nil {
// Log but don't fail - portal might already exist
fmt.Printf("warning: failed to create portal: %v", err4)
@@ -125,7 +125,7 @@ func (s *ISCSIService) createTarget(target models.ISCSITarget) error {
}
// Save configuration
cmd = exec.Command("sudo", "-n", s.targetcliPath, "saveconfig")
cmd = exec.Command(s.targetcliPath, "saveconfig")
cmd.Run() // Ignore errors
return nil
@@ -141,7 +141,7 @@ func (s *ISCSIService) configureACLs(target models.ISCSITarget) error {
return fmt.Errorf("set generate_node_acls: %w", err)
}
// Disable authentication for open access
cmd = exec.Command("sudo", "-n", s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1", "set", "attribute", "authentication=0")
cmd = exec.Command(s.targetcliPath, "/iscsi/"+target.IQN+"/tpg1", "set", "attribute", "authentication=0")
cmd.Run() // Ignore errors
return nil
}

View File

@@ -61,7 +61,7 @@ func (s *NFSService) ApplyConfiguration(exports []models.NFSExport) error {
finalTmpPath := s.exportsPath + ".atlas.tmp"
// Use sudo tee to write directly to /etc (requires root permissions)
teeCmd := exec.Command("sudo", "-n", "tee", finalTmpPath)
teeCmd := exec.Command("tee", finalTmpPath)
teeCmd.Stdin = strings.NewReader(config)
var teeStderr bytes.Buffer
teeCmd.Stderr = &teeStderr
@@ -73,13 +73,13 @@ func (s *NFSService) ApplyConfiguration(exports []models.NFSExport) error {
}
// Set proper permissions on temp file
chmodCmd := exec.Command("sudo", "-n", "chmod", "644", finalTmpPath)
chmodCmd := exec.Command("chmod", "644", finalTmpPath)
_ = chmodCmd.Run() // Ignore errors, might already have correct permissions
// Backup existing exports using sudo
backupPath := s.exportsPath + ".backup"
if _, err := os.Stat(s.exportsPath); err == nil {
cpCmd := exec.Command("sudo", "-n", "cp", s.exportsPath, backupPath)
cpCmd := exec.Command("cp", s.exportsPath, backupPath)
if err := cpCmd.Run(); err != nil {
// Non-fatal, log but continue
// Try direct copy as fallback
@@ -89,7 +89,7 @@ func (s *NFSService) ApplyConfiguration(exports []models.NFSExport) error {
// Atomically replace exports file using sudo
// Use cp + rm instead of mv for better cross-device compatibility
cpCmd := exec.Command("sudo", "-n", "cp", finalTmpPath, s.exportsPath)
cpCmd := exec.Command("cp", finalTmpPath, s.exportsPath)
cpStderr := bytes.Buffer{}
cpCmd.Stderr = &cpStderr
if err := cpCmd.Run(); err != nil {
@@ -100,7 +100,7 @@ func (s *NFSService) ApplyConfiguration(exports []models.NFSExport) error {
}
// Remove temp file after successful copy
rmCmd := exec.Command("sudo", "-n", "rm", "-f", finalTmpPath)
rmCmd := exec.Command("rm", "-f", finalTmpPath)
_ = rmCmd.Run() // Ignore errors, file might not exist
// Reload NFS exports with error recovery
@@ -163,7 +163,7 @@ func (s *NFSService) generateExports(exports []models.NFSExport) (string, error)
func (s *NFSService) reloadExports() error {
// Use exportfs -ra to reload all exports (requires root)
// Try with sudo first
cmd := exec.Command("sudo", "-n", "exportfs", "-ra")
cmd := exec.Command("exportfs", "-ra")
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
@@ -239,7 +239,7 @@ func (s *NFSService) applyZFSShareNFS(exports []models.NFSExport) error {
for _, export := range exports {
if !export.Enabled {
// Disable sharenfs for disabled exports
cmd := exec.Command("sudo", "-n", zfsPath, "set", "sharenfs=off", export.Dataset)
cmd := exec.Command(zfsPath, "set", "sharenfs=off", export.Dataset)
if err := cmd.Run(); err != nil {
// Log but continue - might not have permission or dataset doesn't exist
continue
@@ -310,7 +310,7 @@ func (s *NFSService) applyZFSShareNFS(exports []models.NFSExport) error {
}
// Set sharenfs property using sudo (atlas user has permission via sudoers)
cmd := exec.Command("sudo", "-n", zfsPath, "set", fmt.Sprintf("sharenfs=%s", sharenfsValue.String()), export.Dataset)
cmd := exec.Command(zfsPath, "set", fmt.Sprintf("sharenfs=%s", sharenfsValue.String()), export.Dataset)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {