diff --git a/internal/app/wwctl/container/exec/child/main.go b/internal/app/wwctl/container/exec/child/main.go index 3052faa2..62d09a20 100644 --- a/internal/app/wwctl/container/exec/child/main.go +++ b/internal/app/wwctl/container/exec/child/main.go @@ -21,8 +21,6 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -const exitEval = `$(VALU="$?" ; if [ $VALU == 0 ]; then echo create new image; else echo no new image; fi)` - func CobraRunE(cmd *cobra.Command, args []string) (err error) { if os.Getpid() != 1 { wwlog.Error("PID is not 1: %d", os.Getpid()) @@ -36,8 +34,9 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { os.Exit(1) } conf := warewulfconf.Get() - if overlayDir == "" { - overlayDir = path.Join(conf.Paths.WWChrootdir, "overlays") + runDir := container.RunDir(containerName) + if _, err := os.Stat(runDir); os.IsNotExist(err) { + return errors.Wrap(err, "container run directory does not exist") } mountPts := conf.MountsContainer mountPts = append(container.InitMountPnts(binds), mountPts...) @@ -45,11 +44,16 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { lowerObjects := checkMountPoints(containerName, mountPts) // need to create a overlay, where the lower layer contains // the missing mount points - wwlog.Verbose("for ephermal mount use tempdir %s", overlayDir) - // ignore errors as we are doomed if a tmp dir couldn't be written - _ = os.MkdirAll(path.Join(overlayDir, "work"), os.ModePerm) - _ = os.MkdirAll(path.Join(overlayDir, "lower"), os.ModePerm) - _ = os.MkdirAll(path.Join(overlayDir, "nodeoverlay"), os.ModePerm) + wwlog.Verbose("for ephermal mount use tempdir %s", runDir) + if err = os.Mkdir(path.Join(runDir, "work"), os.ModePerm); err != nil { + return err + } + if err = os.Mkdir(path.Join(runDir, "lower"), os.ModePerm); err != nil { + return err + } + if err = os.Mkdir(path.Join(runDir, "nodeoverlay"), os.ModePerm); err != nil { + return err + } // handle all lower object, have some extra logic if the object is a file for _, obj := range lowerObjects { newFile := "" @@ -57,12 +61,12 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { newFile = filepath.Base(obj) obj = filepath.Dir(obj) } - err = os.MkdirAll(filepath.Join(overlayDir, "lower", obj), os.ModePerm) + err = os.Mkdir(filepath.Join(runDir, "lower", obj), os.ModePerm) if err != nil { wwlog.Warn("couldn't create directory for mounts: %s", err) } if newFile != "" { - desc, err := os.Create(filepath.Join(overlayDir, "lower", obj, newFile)) + desc, err := os.Create(filepath.Join(runDir, "lower", obj, newFile)) if err != nil { wwlog.Warn("couldn't create directory for mounts: %s", err) } @@ -75,10 +79,10 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { if err != nil { return errors.Wrap(err, "failed to mount") } - ps1Str := fmt.Sprintf("[%s|%s] Warewulf> ", exitEval, containerName) + ps1Str := fmt.Sprintf("[%s] Warewulf> ", containerName) if len(lowerObjects) != 0 && nodename == "" { options := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", - path.Join(overlayDir, "lower"), containerPath, path.Join(overlayDir, "work")) + path.Join(runDir, "lower"), containerPath, path.Join(runDir, "work")) wwlog.Debug("overlay options: %s", options) err = syscall.Mount("overlay", containerPath, "overlay", 0, options) if err != nil { @@ -103,13 +107,13 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { } overlays := nodes[0].SystemOverlay.GetSlice() overlays = append(overlays, nodes[0].RuntimeOverlay.GetSlice()...) - err = overlay.BuildOverlayIndir(nodes[0], overlays, path.Join(overlayDir, "nodeoverlay")) + err = overlay.BuildOverlayIndir(nodes[0], overlays, path.Join(runDir, "nodeoverlay")) if err != nil { wwlog.Error("Could not build overlay: %s", err) os.Exit(1) } options := fmt.Sprintf("lowerdir=%s:%s:%s", - path.Join(overlayDir, "lower"), containerPath, path.Join(overlayDir, "nodeoverlay")) + path.Join(runDir, "lower"), containerPath, path.Join(runDir, "nodeoverlay")) wwlog.Debug("overlay options: %s", options) err = syscall.Mount("overlay", containerPath, "overlay", 0, options) if err != nil { @@ -171,11 +175,8 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { os.Setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin") os.Setenv("HISTFILE", "/dev/null") - _ = syscall.Exec(args[1], args[1:], os.Environ()) - /* - Exec replaces the actual program, so nothing to do here afterwards - */ - return nil + wwlog.Debug("Exec: %s %s", args[1], args[1:]) + return syscall.Exec(args[1], args[1:], os.Environ()) } /* diff --git a/internal/app/wwctl/container/exec/child/root.go b/internal/app/wwctl/container/exec/child/root.go index ab72086d..ad807a6f 100644 --- a/internal/app/wwctl/container/exec/child/root.go +++ b/internal/app/wwctl/container/exec/child/root.go @@ -13,16 +13,13 @@ var ( Args: cobra.MinimumNArgs(1), FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true}, } - binds []string - nodename string - overlayDir string + binds []string + nodename string ) func init() { baseCmd.Flags().StringVarP(&nodename, "node", "n", "", "create ro overlay for given node") baseCmd.Flags().StringArrayVarP(&binds, "bind", "b", []string{}, "bind points") - baseCmd.Flags().StringVar(&overlayDir, "overlaydir", "", "overlayDir") - } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/container/exec/main.go b/internal/app/wwctl/container/exec/main.go index 8f16120e..4de99940 100644 --- a/internal/app/wwctl/container/exec/main.go +++ b/internal/app/wwctl/container/exec/main.go @@ -9,7 +9,6 @@ import ( "os" "os/exec" "path" - "path/filepath" "syscall" "time" @@ -26,20 +25,23 @@ fork off a process with a new PID space */ func runContainedCmd(args []string) (err error) { conf := warewulfconf.Get() - if matches, _ := filepath.Glob(path.Join(conf.Paths.WWChrootdir, args[0], args[0]) + "-run-*"); len(matches) > 0 { - return fmt.Errorf("found lock directories for container: %v", matches) - } - overlayDir, err = os.MkdirTemp(path.Join(conf.Paths.WWChrootdir, args[0]), args[0]+"-run-") - if err != nil { - wwlog.Warn("couldn't create temp dir for overlay", err) + containerName := args[0] + runDir := container.RunDir(containerName) + if err := os.Mkdir(runDir, 0750); err != nil { + if _, existerr := os.Stat(runDir); !os.IsNotExist(existerr) { + return errors.New("run directory already exists: another container command may already be running") + } else { + return fmt.Errorf("unable to create run directory: %w", err) + } } defer func() { - err = errors.Join(os.RemoveAll(overlayDir), err) + if err := errors.Join(os.RemoveAll(runDir), err); err != nil { + wwlog.Error("error removing run directory: %w", err) + } }() - logStr := fmt.Sprint(wwlog.GetLogLevel()) wwlog.Verbose("Running contained command: %s", args[1:]) - c := exec.Command("/proc/self/exe", append([]string{"--warewulfconf", conf.GetWarewulfConf(), "--loglevel", logStr, "--overlaydir", overlayDir, "container", "exec", "__child"}, args...)...) + c := exec.Command("/proc/self/exe", append([]string{"--warewulfconf", conf.GetWarewulfConf(), "--loglevel", logStr, "container", "exec", "__child"}, args...)...) c.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS, diff --git a/internal/app/wwctl/container/exec/root.go b/internal/app/wwctl/container/exec/root.go index f68fa620..4b74c941 100644 --- a/internal/app/wwctl/container/exec/root.go +++ b/internal/app/wwctl/container/exec/root.go @@ -25,17 +25,15 @@ var ( }, FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true}, } - SyncUser bool - binds []string - overlayDir string - nodeName string + SyncUser bool + binds []string + nodeName string ) func init() { baseCmd.AddCommand(child.GetCommand()) baseCmd.PersistentFlags().StringArrayVarP(&binds, "bind", "b", []string{}, "Bind a local path into the container (must exist)") baseCmd.PersistentFlags().BoolVar(&SyncUser, "syncuser", false, "Synchronize UIDs/GIDs from host to container") - baseCmd.PersistentFlags().StringVar(&overlayDir, "overlaydir", "", "Use tempdir for constructing the overlay fs (only used if mount points don't exist in container)") baseCmd.PersistentFlags().StringVarP(&nodeName, "node", "n", "", "Create a read only view of the container for the given node") } diff --git a/internal/pkg/container/config.go b/internal/pkg/container/config.go index 902827ea..afbd3b40 100644 --- a/internal/pkg/container/config.go +++ b/internal/pkg/container/config.go @@ -33,6 +33,10 @@ func RootFsDir(name string) string { return path.Join(SourceDir(name), "rootfs") } +func RunDir(name string) string { + return path.Join(SourceDir(name), "run") +} + func ImageParentDir() string { conf := warewulfconf.Get() return path.Join(conf.Paths.WWProvisiondir, "container/")