Repository: threefoldtech/zos (go)

Issue:
provisiond: failed to mount volume in container when using coreX
Problem seems to come from the fact that coreX does a chroot after it stars which somehow mask the bind mount  in the container.

This chroot approach was taken cause we needed to have all the libraries and binaries of coreX in the container, so when using coreX, the container is started with `/var/lib/corex` as root filesystem, the flist mounted at `/sandbox` and the a chroot was done into `/sandbox` to have the root of the flist as root of the container.

This all hack seems to have reached his limit. 
The proposed solution for this is to have a static build if coreX that we could easily insert into the container when needed. That would remove the need of starting the container with `/user/lib/corex` as root and avoid the chroot too.

CoreX status build issue: https://github.com/threefoldtech/corex/issues/13

Pull request description:
contd: remove coreX chroot hack
fixes #381
Now that we have coreX build staticly, we can just mount the binary into
the container. We don't need to do the chroot hack

Let's wait we have a new base image with static coreX binary before merging this.

Patch:
diff --git a/pkg/container.go b/pkg/container.go
index a76801cf..ceca914b 100644
--- a/pkg/container.go
+++ b/pkg/container.go
@@ -20,10 +20,8 @@ type NetworkInfo struct {
 
 // MountInfo defines a mount point
 type MountInfo struct {
-	Source  string   // source of the mount point on the host
-	Target  string   // target of mount inside the container
-	Type    string   // mount type
-	Options []string // mount options
+	Source string // source of the mount point on the host
+	Target string // target of mount inside the container
 }
 
 //Container creation info
diff --git a/pkg/container/container.go b/pkg/container/container.go
index 33b1b21a..4531826f 100644
--- a/pkg/container/container.go
+++ b/pkg/container/container.go
@@ -81,22 +81,13 @@ func (c *containerModule) Run(ns string, data pkg.Container) (id pkg.ContainerID
 		return id, ErrEmptyRootFS
 	}
 
-	if err := applyStartup(&data, filepath.Join(data.RootFS, ".startup.toml")); err != nil {
-		errors.Wrap(err, "error updating environment variable from startup file")
+	// we never allow any container to boot without a network namespace
+	if data.Network.Namespace == "" {
+		return "", fmt.Errorf("cannot create container without network namespace")
 	}
 
-	if data.Interactive {
-		if err := os.MkdirAll(filepath.Join(data.RootFS, "sandbox"), 0770); err != nil {
-			return id, err
-		}
-		data.Mounts = append(data.Mounts, pkg.MountInfo{
-			Source:  data.RootFS,
-			Target:  "/sandbox",
-			Type:    "bind",
-			Options: []string{"rbind"}, // mount options
-		})
-		data.RootFS = "/usr/lib/corex"
-		data.Entrypoint = "/bin/corex --ipv6 --chroot /sandbox -d 7"
+	if err := applyStartup(&data, filepath.Join(data.RootFS, ".startup.toml")); err != nil {
+		errors.Wrap(err, "error updating environment variable from startup file")
 	}
 
 	args, err := shlex.Split(data.Entrypoint)
@@ -111,6 +102,8 @@ func (c *containerModule) Run(ns string, data pkg.Container) (id pkg.ContainerID
 		oci.WithEnv(data.Env),
 		oci.WithHostResolvconf,
 		removeRunMount(),
+		withNetworkNamespace(data.Network.Namespace),
+		withMounts(data.Mounts),
 	}
 
 	if data.WorkingDir != "" {
@@ -118,40 +111,7 @@ func (c *containerModule) Run(ns string, data pkg.Container) (id pkg.ContainerID
 	}
 
 	if data.Interactive {
-		opts = append(
-			opts,
-			withAddedCapabilities([]string{
-				"CAP_SYS_ADMIN",
-			}),
-			// in interactive mode, since we start the container
-			// from /usr/lib/corex
-			// we make it read-only
-			oci.WithReadonlyPaths([]string{"/"}),
-		)
-	}
-
-	// we never allow any container to boot without a network namespace
-	if data.Network.Namespace == "" {
-		return "", fmt.Errorf("cannot create container without network namespace")
-	}
-
-	opts = append(
-		opts,
-		withNetworkNamespace(data.Network.Namespace),
-	)
-
-	for _, mount := range data.Mounts {
-		opts = append(
-			opts,
-			oci.WithMounts([]specs.Mount{
-				{
-					Destination: mount.Target,
-					Type:        mount.Type,
-					Source:      mount.Source,
-					Options:     mount.Options,
-				},
-			}),
-		)
+		opts = append(opts, withCoreX())
 	}
 
 	log.Info().
@@ -178,6 +138,7 @@ func (c *containerModule) Run(ns string, data pkg.Container) (id pkg.ContainerID
 	for _, linxNS := range spec.Linux.Namespaces {
 		log.Info().Msgf("namespace %+v", linxNS.Type)
 	}
+	log.Info().Msgf("mounts %+v", spec.Mounts)
 
 	defer func() {
 		// if any of the next steps below fails, make sure
@@ -244,10 +205,8 @@ func (c *containerModule) Inspect(ns string, id pkg.ContainerID) (result pkg.Con
 		}
 		result.Mounts = append(result.Mounts,
 			pkg.MountInfo{
-				Source:  mount.Source,
-				Target:  mount.Destination,
-				Type:    mount.Type,
-				Options: mount.Options,
+				Source: mount.Source,
+				Target: mount.Destination,
 			},
 		)
 	}
diff --git a/pkg/container/opts.go b/pkg/container/opts.go
index f0ceb3ce..c05c4123 100644
--- a/pkg/container/opts.go
+++ b/pkg/container/opts.go
@@ -6,6 +6,7 @@ import (
 	"path"
 
 	"github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/threefoldtech/zos/pkg"
 
 	"github.com/containerd/containerd/containers"
 	"github.com/containerd/containerd/oci"
@@ -67,3 +68,33 @@ func removeRunMount() oci.SpecOpts {
 		return nil
 	}
 }
+
+// withCoreX enable corex in a container
+// to do so, it mounts the corex binary into the container and set the entrypoint
+func withCoreX() oci.SpecOpts {
+
+	withMount := func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
+		s.Mounts = append(s.Mounts, specs.Mount{
+			Destination: "/corex",
+			Type:        "bind",
+			Source:      "/usr/bin/corex",
+			Options:     []string{"rbind", "ro"},
+		})
+		return nil
+	}
+
+	return oci.Compose(withMount, oci.WithProcessArgs("/corex", "--ipv6", "-d", "7"))
+}
+
+func withMounts(mounts []pkg.MountInfo) oci.SpecOpts {
+	mnts := make([]specs.Mount, len(mounts))
+	for i, mount := range mounts {
+		mnts[i] = specs.Mount{
+			Destination: mount.Target,
+			Type:        "bind",
+			Source:      mount.Source,
+			Options:     []string{"rbind"},
+		}
+	}
+	return oci.Compose(oci.WithMounts(mnts))
+}
diff --git a/pkg/provision/container.go b/pkg/provision/container.go
index 91c7785b..aff02e1c 100644
--- a/pkg/provision/container.go
+++ b/pkg/provision/container.go
@@ -153,10 +153,8 @@ func containerProvisionImpl(ctx context.Context, reservation *Reservation) (Cont
 		mounts = append(
 			mounts,
 			pkg.MountInfo{
-				Source:  source,
-				Target:  mountpoint,
-				Type:    "none",
-				Options: []string{"bind"},
+				Source: source,
+				Target: mountpoint,
 			},
 		)
 	}
diff --git a/pkg/provision/zdb.go b/pkg/provision/zdb.go
index ba8a6022..58c267a3 100644
--- a/pkg/provision/zdb.go
+++ b/pkg/provision/zdb.go
@@ -261,16 +261,12 @@ func createZdbContainer(ctx context.Context, name string, mode pkg.ZDBMode, volu
 			Network:     pkg.NetworkInfo{Namespace: netNsName},
 			Mounts: []pkg.MountInfo{
 				{
-					Source:  volumePath,
-					Target:  "/data",
-					Type:    "none",
-					Options: []string{"bind"},
+					Source: volumePath,
+					Target: "/data",
 				},
 				{
-					Source:  socketDir,
-					Target:  "/socket",
-					Type:    "none",
-					Options: []string{"bind"},
+					Source: socketDir,
+					Target: "/socket",
 				},
 			},
 		})


Test patch:
diff --git a/pkg/provision/container_test.go b/pkg/provision/container_test.go
index ccdb463f..5c864da4 100644
--- a/pkg/provision/container_test.go
+++ b/pkg/provision/container_test.go
@@ -221,10 +221,8 @@ func TestContainerProvisionWithMounts(t *testing.T) {
 			},
 			Mounts: []pkg.MountInfo{
 				{
-					Source:  "/some/path/to/vol1",
-					Target:  "/opt",
-					Type:    "none",
-					Options: []string{"bind"},
+					Source: "/some/path/to/vol1",
+					Target: "/opt",
 				},
 			},
 		}).
diff --git a/pkg/provision/zdb_test.go b/pkg/provision/zdb_test.go
index 51ec1a38..7401ef1e 100644
--- a/pkg/provision/zdb_test.go
+++ b/pkg/provision/zdb_test.go
@@ -180,16 +180,12 @@ func TestZDBProvisionNoMappingContainerDoesNotExists(t *testing.T) {
 			Network: pkg.NetworkInfo{Namespace: "net-ns"},
 			Mounts: []pkg.MountInfo{
 				pkg.MountInfo{
-					Source:  "/path/to/volume",
-					Target:  "/data",
-					Type:    "none",
-					Options: []string{"bind"},
+					Source: "/path/to/volume",
+					Target: "/data",
 				},
 				pkg.MountInfo{
-					Source:  "/var/run/zdb_container-id",
-					Target:  "/socket",
-					Type:    "none",
-					Options: []string{"bind"},
+					Source: "/var/run/zdb_container-id",
+					Target: "/socket",
 				},
 			},
 			Entrypoint:  "/bin/zdb --data /data --index /data --mode seq  --listen :: --port 9900 --socket /socket/zdb.sock --dualnet",