forked from pool/warewulf4
without patch
OBS-URL: https://build.opensuse.org/package/show/network:cluster/warewulf4?expand=0&rev=91
This commit is contained in:
parent
894c0e3d18
commit
0dfd125dba
@ -1,254 +0,0 @@
|
|||||||
diff --git a/internal/app/wwctl/container/exec/child/main.go b/internal/app/wwctl/container/exec/child/main.go
|
|
||||||
index 253a6ad2..0785ba74 100644
|
|
||||||
--- a/internal/app/wwctl/container/exec/child/main.go
|
|
||||||
+++ b/internal/app/wwctl/container/exec/child/main.go
|
|
||||||
@@ -92,7 +92,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
|
||||||
wwlog.Debug("overlay options: %s", options)
|
|
||||||
err = syscall.Mount("overlay", containerPath, "overlay", 0, options)
|
|
||||||
if err != nil {
|
|
||||||
- wwlog.Warn(fmt.Sprintf("Couldn't create overlay for ephermal mount points: %s", err))
|
|
||||||
+ wwlog.Warn("Couldn't create overlay for ephermal mount points: %s", err)
|
|
||||||
}
|
|
||||||
} else if nodename != "" {
|
|
||||||
nodeDB, err := node.New()
|
|
||||||
@@ -142,6 +142,10 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mntPnt := range mountPts {
|
|
||||||
+ if mntPnt.Copy {
|
|
||||||
+ continue
|
|
||||||
+ }
|
|
||||||
+ wwlog.Debug("bind mounting: %s -> %s", mntPnt.Source, path.Join(containerPath, mntPnt.Dest))
|
|
||||||
err = syscall.Mount(mntPnt.Source, path.Join(containerPath, mntPnt.Dest), "", syscall.MS_BIND, "")
|
|
||||||
if err != nil {
|
|
||||||
wwlog.Warn("Couldn't mount %s to %s: %s", mntPnt.Source, mntPnt.Dest, err)
|
|
||||||
@@ -195,6 +199,9 @@ the invalid mount points. Directories always have '/' as suffix
|
|
||||||
func checkMountPoints(containerName string, binds []*warewulfconf.MountEntry) (overlayObjects []string) {
|
|
||||||
overlayObjects = []string{}
|
|
||||||
for _, b := range binds {
|
|
||||||
+ if b.Copy {
|
|
||||||
+ continue
|
|
||||||
+ }
|
|
||||||
_, err := os.Stat(b.Source)
|
|
||||||
if err != nil {
|
|
||||||
wwlog.Debug("Couldn't stat %s create no mount point in container", b.Source)
|
|
||||||
diff --git a/internal/app/wwctl/container/exec/main.go b/internal/app/wwctl/container/exec/main.go
|
|
||||||
index 60cf9d48..336218a9 100644
|
|
||||||
--- a/internal/app/wwctl/container/exec/main.go
|
|
||||||
+++ b/internal/app/wwctl/container/exec/main.go
|
|
||||||
@@ -54,7 +54,6 @@ func runContainedCmd(cmd *cobra.Command, containerName string, args []string) (e
|
|
||||||
}()
|
|
||||||
|
|
||||||
logStr := fmt.Sprint(wwlog.GetLogLevel())
|
|
||||||
-
|
|
||||||
childArgs := []string{"--warewulfconf", conf.GetWarewulfConf(), "--loglevel", logStr, "container", "exec", "__child"}
|
|
||||||
childArgs = append(childArgs, containerName)
|
|
||||||
for _, b := range binds {
|
|
||||||
@@ -64,8 +63,32 @@ func runContainedCmd(cmd *cobra.Command, containerName string, args []string) (e
|
|
||||||
childArgs = append(childArgs, "--node", nodeName)
|
|
||||||
}
|
|
||||||
childArgs = append(childArgs, args...)
|
|
||||||
+ // copy the files into the container at this stage, es in __child the
|
|
||||||
+ // command syscall.Exec which replaces the __child process with the
|
|
||||||
+ // exec command in the container. All the mounts, have to be done in
|
|
||||||
+ // __child so that the used mounts don't propagate outside on the host
|
|
||||||
+ // (see the CLONE attributes), but as for the copy option we need
|
|
||||||
+ // to see if a file was modified after it was copied into the container
|
|
||||||
+ // so do this here.
|
|
||||||
+ // At first read out conf, the parse commandline, as copy files has the
|
|
||||||
+ // same synatx as mount points
|
|
||||||
+ mountPts := append(container.InitMountPnts(binds), conf.MountsContainer...)
|
|
||||||
+ filesToCpy := getCopyFiles(mountPts)
|
|
||||||
+ for _, cpyFile := range filesToCpy {
|
|
||||||
+ if err := (cpyFile).copyToContainer(containerName); err != nil {
|
|
||||||
+ wwlog.Warn("couldn't copy file: %s", err)
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
wwlog.Verbose("Running contained command: %s", childArgs)
|
|
||||||
- return childCommandFunc(cmd, childArgs)
|
|
||||||
+ retVal := childCommandFunc(cmd, childArgs)
|
|
||||||
+ for _, cpyFile := range filesToCpy {
|
|
||||||
+ if cpyFile.shouldRemoveFromContainer(containerName) {
|
|
||||||
+ if err := cpyFile.removeFromContainer(containerName); err != nil {
|
|
||||||
+ wwlog.Warn("couldn't remove file: %s", err)
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return retVal
|
|
||||||
}
|
|
||||||
|
|
||||||
func CobraRunE(cmd *cobra.Command, args []string) error {
|
|
||||||
@@ -154,3 +177,68 @@ func SetBinds(myBinds []string) {
|
|
||||||
func SetNode(myNode string) {
|
|
||||||
nodeName = myNode
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+// file name and last modification time so we can remove the file if it wasn't modified
|
|
||||||
+type copyFile struct {
|
|
||||||
+ fileName string
|
|
||||||
+ src string
|
|
||||||
+ modTime time.Time
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func (this *copyFile) containerDest(containerName string) string {
|
|
||||||
+ return path.Join(container.RootFsDir(containerName), this.fileName)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func (this *copyFile) copyToContainer(containerName string) error {
|
|
||||||
+ containerDest := this.containerDest(containerName)
|
|
||||||
+ if _, err := os.Stat(path.Dir(containerDest)); err != nil {
|
|
||||||
+ return err
|
|
||||||
+ } else if _, err := os.Stat(containerDest); err == nil {
|
|
||||||
+ return err
|
|
||||||
+ } else if _, err := os.Stat(this.src); err != nil {
|
|
||||||
+ return err
|
|
||||||
+ } else if err := util.CopyFile(this.src, containerDest); err != nil {
|
|
||||||
+ return err
|
|
||||||
+ } else if stat, err := os.Stat(containerDest); err != nil {
|
|
||||||
+ return err
|
|
||||||
+ } else {
|
|
||||||
+ this.modTime = stat.ModTime()
|
|
||||||
+ return nil
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func (this *copyFile) shouldRemoveFromContainer(containerName string) bool {
|
|
||||||
+ containerDest := this.containerDest(containerName)
|
|
||||||
+ if this.modTime.IsZero() {
|
|
||||||
+ wwlog.Debug("file was not previously copied: %s", this.fileName)
|
|
||||||
+ return false
|
|
||||||
+ } else if destStat, err := os.Stat(containerDest); err != nil {
|
|
||||||
+ wwlog.Verbose("file is no longer present: %s (%s)", this.fileName, err)
|
|
||||||
+ return false
|
|
||||||
+ } else if destStat.ModTime() == this.modTime {
|
|
||||||
+ wwlog.Verbose("don't remove modified file:", this.fileName)
|
|
||||||
+ return false
|
|
||||||
+ } else {
|
|
||||||
+ return true
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func (this *copyFile) removeFromContainer(containerName string) error {
|
|
||||||
+ containerDest := this.containerDest(containerName)
|
|
||||||
+ return os.Remove(containerDest)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+Check the objects we want to copy in, instead of mounting
|
|
||||||
+*/
|
|
||||||
+func getCopyFiles(binds []*warewulfconf.MountEntry) (copyObjects []*copyFile) {
|
|
||||||
+ for _, bind := range binds {
|
|
||||||
+ if bind.Copy {
|
|
||||||
+ copyObjects = append(copyObjects, ©File{
|
|
||||||
+ fileName: bind.Dest,
|
|
||||||
+ src: bind.Source,
|
|
||||||
+ })
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return
|
|
||||||
+}
|
|
||||||
diff --git a/internal/app/wwctl/container/exec/root.go b/internal/app/wwctl/container/exec/root.go
|
|
||||||
index 4b74c941..1152fd8e 100644
|
|
||||||
--- a/internal/app/wwctl/container/exec/root.go
|
|
||||||
+++ b/internal/app/wwctl/container/exec/root.go
|
|
||||||
@@ -32,7 +32,10 @@ var (
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
baseCmd.AddCommand(child.GetCommand())
|
|
||||||
- baseCmd.PersistentFlags().StringArrayVarP(&binds, "bind", "b", []string{}, "Bind a local path into the container (must exist)")
|
|
||||||
+ baseCmd.PersistentFlags().StringArrayVarP(&binds, "bind", "b", []string{}, `source[:destination[:{ro|copy}]]
|
|
||||||
+Bind a local path which must exist into the container. If destination is not
|
|
||||||
+set, uses the same path as source. "ro" binds read-only. "copy" temporarily
|
|
||||||
+copies the file into the container.`)
|
|
||||||
baseCmd.PersistentFlags().BoolVar(&SyncUser, "syncuser", false, "Synchronize UIDs/GIDs from host to container")
|
|
||||||
baseCmd.PersistentFlags().StringVarP(&nodeName, "node", "n", "", "Create a read only view of the container for the given node")
|
|
||||||
}
|
|
||||||
diff --git a/internal/app/wwctl/container/shell/root.go b/internal/app/wwctl/container/shell/root.go
|
|
||||||
index cceb7512..e1ae01d3 100644
|
|
||||||
--- a/internal/app/wwctl/container/shell/root.go
|
|
||||||
+++ b/internal/app/wwctl/container/shell/root.go
|
|
||||||
@@ -28,7 +28,10 @@ var (
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
- baseCmd.PersistentFlags().StringArrayVarP(&binds, "bind", "b", []string{}, "Bind a local path into the container (must exist)")
|
|
||||||
+ baseCmd.PersistentFlags().StringArrayVarP(&binds, "bind", "b", []string{}, `source[:destination[:{ro|copy}]]
|
|
||||||
+Bind a local path which must exist into the container. If destination is not
|
|
||||||
+set, uses the same path as source. "ro" binds read-only. "copy" temporarily
|
|
||||||
+copies the file into the container.`)
|
|
||||||
baseCmd.PersistentFlags().StringVarP(&nodeName, "node", "n", "", "Create a read only view of the container for the given node")
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/internal/pkg/config/mounts.go b/internal/pkg/config/mounts.go
|
|
||||||
index 2eb5060b..305fbad4 100644
|
|
||||||
--- a/internal/pkg/config/mounts.go
|
|
||||||
+++ b/internal/pkg/config/mounts.go
|
|
||||||
@@ -7,4 +7,5 @@ type MountEntry struct {
|
|
||||||
Dest string `yaml:"dest,omitempty"`
|
|
||||||
ReadOnly bool `yaml:"readonly,omitempty"`
|
|
||||||
Options string `yaml:"options,omitempty"` // ignored at the moment
|
|
||||||
+ Copy bool `yaml:"copy,omitempty"` // temporarily copy the file into the container
|
|
||||||
}
|
|
||||||
diff --git a/internal/pkg/container/mountpoints.go b/internal/pkg/container/mountpoints.go
|
|
||||||
index 5de00c75..961513fb 100644
|
|
||||||
--- a/internal/pkg/container/mountpoints.go
|
|
||||||
+++ b/internal/pkg/container/mountpoints.go
|
|
||||||
@@ -21,13 +21,19 @@ func InitMountPnts(binds []string) (mounts []*warewulfconf.MountEntry) {
|
|
||||||
dest = bind[1]
|
|
||||||
}
|
|
||||||
readonly := false
|
|
||||||
- if len(bind) >= 3 && bind[2] == "ro" {
|
|
||||||
- readonly = true
|
|
||||||
+ copy_ := false
|
|
||||||
+ if len(bind) >= 3 {
|
|
||||||
+ if bind[2] == "ro" {
|
|
||||||
+ readonly = true
|
|
||||||
+ } else if bind[2] == "copy" {
|
|
||||||
+ copy_ = true
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
mntPnt := warewulfconf.MountEntry{
|
|
||||||
Source: bind[0],
|
|
||||||
Dest: dest,
|
|
||||||
ReadOnly: readonly,
|
|
||||||
+ Copy: copy_,
|
|
||||||
}
|
|
||||||
mounts = append(mounts, &mntPnt)
|
|
||||||
}
|
|
||||||
diff --git a/internal/pkg/warewulfd/copyshim.go b/internal/pkg/warewulfd/copyshim.go
|
|
||||||
index 4f085017..13a32d64 100644
|
|
||||||
--- a/internal/pkg/warewulfd/copyshim.go
|
|
||||||
+++ b/internal/pkg/warewulfd/copyshim.go
|
|
||||||
@@ -16,7 +16,6 @@ import (
|
|
||||||
Copies the default shim, which is the shim located on host
|
|
||||||
to the tftp directory
|
|
||||||
*/
|
|
||||||
-
|
|
||||||
func CopyShimGrub() (err error) {
|
|
||||||
conf := warewulfconf.Get()
|
|
||||||
wwlog.Debug("copy shim and grub binaries from host")
|
|
||||||
diff --git a/userdocs/contents/containers.rst b/userdocs/contents/containers.rst
|
|
||||||
index 2e84921f..2ee7a236 100644
|
|
||||||
--- a/userdocs/contents/containers.rst
|
|
||||||
+++ b/userdocs/contents/containers.rst
|
|
||||||
@@ -213,6 +213,20 @@ when using the exec command. This works as follows:
|
|
||||||
location, as it is almost always present and empty in every Linux
|
|
||||||
distribution (as prescribed by the LSB file hierarchy standard).
|
|
||||||
|
|
||||||
+Files which should always be present in a container image like ``resolv.conf``
|
|
||||||
+can be specified in ``warewulf.conf``:
|
|
||||||
+
|
|
||||||
+.. code-block:: yaml
|
|
||||||
+ container mounts:
|
|
||||||
+ - source: /etc/resolv.conf
|
|
||||||
+ dest: /etc/resolv.conf
|
|
||||||
+ readonly: true
|
|
||||||
+
|
|
||||||
+.. note::
|
|
||||||
+ Instead of ``readonly: true`` you can set ``copy: true``. This causes the
|
|
||||||
+ source file to be copied to the container and removed if it was not
|
|
||||||
+ modified. This can be useful for files used for registrations.
|
|
||||||
+
|
|
||||||
When the command completes, if anything within the container changed,
|
|
||||||
the container will be rebuilt into a bootable static object
|
|
||||||
automatically.
|
|
Loading…
x
Reference in New Issue
Block a user