main #1
@@ -80,6 +80,9 @@ func (s *Service) execCommand(name string, args ...string) (string, error) {
|
|||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil && useSudo {
|
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
|
// If sudo failed, try running the command directly
|
||||||
// (user might already have permissions or be root)
|
// (user might already have permissions or be root)
|
||||||
directCmd := exec.Command(name, args...)
|
directCmd := exec.Command(name, args...)
|
||||||
@@ -89,13 +92,17 @@ func (s *Service) execCommand(name string, args ...string) (string, error) {
|
|||||||
|
|
||||||
if directErr := directCmd.Run(); directErr == nil {
|
if directErr := directCmd.Run(); directErr == nil {
|
||||||
// Direct execution succeeded, return that result
|
// Direct execution succeeded, return that result
|
||||||
|
log.Printf("direct command execution succeeded (without sudo)")
|
||||||
return strings.TrimSpace(directStdout.String()), nil
|
return strings.TrimSpace(directStdout.String()), nil
|
||||||
}
|
}
|
||||||
// Both sudo and direct failed, return the original sudo error
|
// Both sudo and direct failed, return detailed error
|
||||||
return "", fmt.Errorf("%s: %v: %s", name, err, stderr.String())
|
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 "", fmt.Errorf("%s: sudo failed (%v: %s), direct execution also failed (%v: %s)", name, err, stderr.String(), directErr, directStderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("command execution failed: %s %v (error: %v, stderr: %s)", name, args, err, stderr.String())
|
||||||
return "", fmt.Errorf("%s: %v: %s", name, err, stderr.String())
|
return "", fmt.Errorf("%s: %v: %s", name, err, stderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,19 +231,41 @@ func (s *Service) CreatePool(name string, vdevs []string, options map[string]str
|
|||||||
}
|
}
|
||||||
|
|
||||||
args = append(args, name)
|
args = append(args, name)
|
||||||
args = append(args, vdevs...)
|
|
||||||
|
// Normalize vdev paths - ensure they start with /dev/ if they don't already
|
||||||
|
normalizedVdevs := make([]string, 0, len(vdevs))
|
||||||
|
for _, vdev := range vdevs {
|
||||||
|
vdev = strings.TrimSpace(vdev)
|
||||||
|
if vdev == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If vdev doesn't start with /dev/ or /, assume it's a device name and add /dev/
|
||||||
|
if !strings.HasPrefix(vdev, "/dev/") && !strings.HasPrefix(vdev, "/") {
|
||||||
|
vdev = "/dev/" + vdev
|
||||||
|
}
|
||||||
|
normalizedVdevs = append(normalizedVdevs, vdev)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(normalizedVdevs) == 0 {
|
||||||
|
return fmt.Errorf("no valid vdevs provided after normalization")
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, normalizedVdevs...)
|
||||||
|
|
||||||
// Log the command we're about to run for debugging
|
// Log the command we're about to run for debugging
|
||||||
log.Printf("executing: %s %v", s.zpoolPath, args)
|
// Note: execCommand will use sudo automatically for zpool commands
|
||||||
|
log.Printf("executing zpool create: %s %v", s.zpoolPath, args)
|
||||||
|
log.Printf("pool name: %s, original vdevs: %v, normalized vdevs: %v", name, vdevs, normalizedVdevs)
|
||||||
|
|
||||||
// Create the pool (without mountpoint to avoid mount errors)
|
// Create the pool (without mountpoint to avoid mount errors)
|
||||||
createOutput, err := s.execCommand(s.zpoolPath, args...)
|
createOutput, err := s.execCommand(s.zpoolPath, args...)
|
||||||
|
|
||||||
// Log the command output for debugging
|
// Log the command output for debugging
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("zpool create failed - output: %s, error: %v", createOutput, err)
|
log.Printf("zpool create command failed - output: %s, error: %v", createOutput, err)
|
||||||
|
log.Printf("this error might be a false positive - checking if pool was actually created...")
|
||||||
} else {
|
} else {
|
||||||
log.Printf("zpool create succeeded - output: %s", createOutput)
|
log.Printf("zpool create command succeeded - output: %s", createOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRITICAL: Always check if pool exists, even if creation reported an error
|
// CRITICAL: Always check if pool exists, even if creation reported an error
|
||||||
@@ -250,6 +279,7 @@ func (s *Service) CreatePool(name string, vdevs []string, options map[string]str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existingPools, listErr := s.ListPools(); listErr == nil {
|
if existingPools, listErr := s.ListPools(); listErr == nil {
|
||||||
|
log.Printf("checking pool existence (attempt %d/%d): found %d pools", i+1, 3, len(existingPools))
|
||||||
for _, pool := range existingPools {
|
for _, pool := range existingPools {
|
||||||
if pool.Name == name {
|
if pool.Name == name {
|
||||||
poolExists = true
|
poolExists = true
|
||||||
@@ -257,6 +287,8 @@ func (s *Service) CreatePool(name string, vdevs []string, options map[string]str
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("warning: failed to list pools during existence check (attempt %d): %v", i+1, listErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if poolExists {
|
if poolExists {
|
||||||
@@ -275,12 +307,16 @@ func (s *Service) CreatePool(name string, vdevs []string, options map[string]str
|
|||||||
err = nil
|
err = nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
// Pool doesn't exist and we have an error - return it with full context
|
// Pool doesn't exist and we have an error - return it with full context
|
||||||
log.Printf("error: pool %s creation failed and pool does not exist: %v", name, err)
|
log.Printf("error: pool %s creation failed and pool does not exist", name)
|
||||||
return fmt.Errorf("failed to create pool %s: %v", name, err)
|
log.Printf("error details: %v", err)
|
||||||
|
log.Printf("command that failed: %s %v", s.zpoolPath, args)
|
||||||
|
log.Printf("command output: %s", createOutput)
|
||||||
|
return fmt.Errorf("failed to create pool %s: %v (command: %s %v)", name, err, s.zpoolPath, args)
|
||||||
} else {
|
} else {
|
||||||
// No error reported but pool doesn't exist - this shouldn't happen
|
// No error reported but pool doesn't exist - this shouldn't happen
|
||||||
log.Printf("warning: pool %s creation reported no error but pool does not exist", name)
|
log.Printf("warning: pool %s creation reported no error but pool does not exist", name)
|
||||||
return fmt.Errorf("pool %s creation reported success but pool was not found", name)
|
log.Printf("command output: %s", createOutput)
|
||||||
|
return fmt.Errorf("pool %s creation reported success but pool was not found (command: %s %v)", name, s.zpoolPath, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pool created successfully - now set mountpoint and mount if needed
|
// Pool created successfully - now set mountpoint and mount if needed
|
||||||
|
|||||||
Reference in New Issue
Block a user