summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/boltdb_state.go1
-rw-r--r--libpod/container.go29
-rw-r--r--libpod/container_api.go17
-rw-r--r--libpod/container_inspect.go25
-rw-r--r--libpod/container_internal.go111
5 files changed, 121 insertions, 62 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 7db02d533..aeda94e50 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -143,6 +143,7 @@ func (s *BoltState) Refresh() error {
state.ExecSessions = make(map[string]*ExecSession)
state.IPs = nil
state.Routes = nil
+ state.BindMounts = make(map[string]string)
newStateBytes, err := json.Marshal(state)
if err != nil {
diff --git a/libpod/container.go b/libpod/container.go
index 95db85b70..648dc821e 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -710,6 +710,35 @@ func (c *Container) Routes() ([]types.Route, error) {
return routes, nil
}
+// BindMounts retrieves bind mounts that were created by libpod and will be
+// added to the container
+// All these mounts except /dev/shm are ignored if a mount in the given spec has
+// the same destination
+// These mounts include /etc/resolv.conf, /etc/hosts, and /etc/hostname
+// The return is formatted as a map from destination (mountpoint in the
+// container) to source (path of the file that will be mounted into the
+// container)
+// If the container has not been started yet, an empty map will be returned, as
+// the files in question are only created when the container is started.
+func (c *Container) BindMounts() (map[string]string, error) {
+ if !c.locked {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if err := c.syncContainer(); err != nil {
+ return nil, err
+ }
+ }
+
+ newMap := make(map[string]string, len(c.state.BindMounts))
+
+ for key, val := range c.state.BindMounts {
+ newMap[key] = val
+ }
+
+ return newMap, nil
+}
+
// Misc Accessors
// Most will require locking
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 161cd938c..0a27da7c9 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -59,25 +59,12 @@ func (c *Container) Init() (err error) {
}
}()
- // Copy /etc/resolv.conf to the container's rundir
- runDirResolv, err := c.generateResolvConf()
- if err != nil {
+ if err := c.makeBindMounts(); err != nil {
return err
}
- // Copy /etc/hosts to the container's rundir
- runDirHosts, err := c.generateHosts()
- if err != nil {
- return errors.Wrapf(err, "unable to copy /etc/hosts to container space")
- }
-
- runDirHostname, err := c.generateEtcHostname(c.Hostname())
- if err != nil {
- return errors.Wrapf(err, "unable to generate hostname file for container")
- }
-
// Generate the OCI spec
- spec, err := c.generateSpec(runDirResolv, runDirHosts, runDirHostname)
+ spec, err := c.generateSpec()
if err != nil {
return err
}
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 3a1728826..bbfcd4446 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -25,6 +25,25 @@ func (c *Container) getContainerInspectData(size bool, driverData *inspect.Data)
execIDs = append(execIDs, id)
}
+ if c.state.BindMounts == nil {
+ c.state.BindMounts = make(map[string]string)
+ }
+
+ resolvPath := ""
+ if path, ok := c.state.BindMounts["/etc/resolv.conf"]; ok {
+ resolvPath = path
+ }
+
+ hostsPath := ""
+ if path, ok := c.state.BindMounts["/etc/hosts"]; ok {
+ hostsPath = path
+ }
+
+ hostnamePath := ""
+ if path, ok := c.state.BindMounts["/etc/hostname"]; ok {
+ hostnamePath = path
+ }
+
data := &inspect.ContainerInspectData{
ID: config.ID,
Created: config.CreatedTime,
@@ -45,9 +64,9 @@ func (c *Container) getContainerInspectData(size bool, driverData *inspect.Data)
},
ImageID: config.RootfsImageID,
ImageName: config.RootfsImageName,
- ResolvConfPath: "", // TODO get from networking path
- HostnamePath: spec.Annotations["io.kubernetes.cri-o.HostnamePath"], // not sure
- HostsPath: "", // can't get yet
+ ResolvConfPath: resolvPath,
+ HostnamePath: hostnamePath,
+ HostsPath: hostsPath,
StaticDir: config.StaticDir,
LogPath: config.LogPath,
Name: config.Name,
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 736655f13..3c7637717 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -162,6 +162,8 @@ func newContainer(rspec *spec.Spec, lockDir string) (*Container, error) {
ctr.config.ShmSize = DefaultShmSize
ctr.config.CgroupParent = DefaultCgroupParent
+ ctr.state.BindMounts = make(map[string]string)
+
// Path our lock file will reside at
lockPath := filepath.Join(lockDir, ctr.config.ID)
// Grab a lockfile at the given path
@@ -444,6 +446,56 @@ func (c *Container) cleanupStorage() error {
return c.save()
}
+// Make standard bind mounts to include in the container
+func (c *Container) makeBindMounts() error {
+ if c.state.BindMounts == nil {
+ c.state.BindMounts = make(map[string]string)
+ }
+
+ // SHM is always added when we mount the container
+ c.state.BindMounts["/dev/shm"] = c.config.ShmDir
+
+ // Make /etc/resolv.conf
+ if path, ok := c.state.BindMounts["/etc/resolv.conf"]; ok {
+ // If it already exists, delete so we can recreate
+ if err := os.Remove(path); err != nil {
+ return errors.Wrapf(err, "error removing resolv.conf for container %s", c.ID())
+ }
+ delete(c.state.BindMounts, "/etc/resolv.conf")
+ }
+ newResolv, err := c.generateResolvConf()
+ if err != nil {
+ return errors.Wrapf(err, "error creating resolv.conf for container %s", c.ID())
+ }
+ c.state.BindMounts["/etc/resolv.conf"] = newResolv
+
+ // Make /etc/hosts
+ if path, ok := c.state.BindMounts["/etc/hosts"]; ok {
+ // If it already exists, delete so we can recreate
+ if err := os.Remove(path); err != nil {
+ return errors.Wrapf(err, "error removing hosts file for container %s", c.ID())
+ }
+ delete(c.state.BindMounts, "/etc/hosts")
+ }
+ newHosts, err := c.generateHosts()
+ if err != nil {
+ return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
+ }
+ c.state.BindMounts["/etc/hosts"] = newHosts
+
+ // Make /etc/hostname
+ // This should never change, so no need to recreate if it exists
+ if _, ok := c.state.BindMounts["/etc/hostname"]; !ok {
+ hostnamePath, err := c.writeStringToRundir("hostname", c.Hostname())
+ if err != nil {
+ return errors.Wrapf(err, "error creating hostname file for container %s", c.ID())
+ }
+ c.state.BindMounts["/etc/hostname"] = hostnamePath
+ }
+
+ return nil
+}
+
// writeStringToRundir copies the provided file to the runtimedir
func (c *Container) writeStringToRundir(destFile, output string) (string, error) {
destFileName := filepath.Join(c.state.RunDir, destFile)
@@ -579,58 +631,29 @@ func (c *Container) generateHosts() (string, error) {
return c.writeStringToRundir("hosts", hosts)
}
-// generateEtcHostname creates a containers /etc/hostname
-func (c *Container) generateEtcHostname(hostname string) (string, error) {
- return c.writeStringToRundir("hostname", hostname)
-}
-
// Generate spec for a container
-func (c *Container) generateSpec(resolvPath, hostsPath, hostnamePath string) (*spec.Spec, error) {
+func (c *Container) generateSpec() (*spec.Spec, error) {
g := generate.NewFromSpec(c.config.Spec)
// If network namespace was requested, add it now
if c.config.CreateNetNS {
g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path())
}
- // Remove default /etc/shm mount
+
+ // Remove the default /dev/shm mount to ensure we overwrite it
g.RemoveMount("/dev/shm")
- // Mount ShmDir from host into container
- shmMnt := spec.Mount{
- Type: "bind",
- Source: c.config.ShmDir,
- Destination: "/dev/shm",
- Options: []string{"rw", "bind"},
- }
- g.AddMount(shmMnt)
- // Bind mount resolv.conf
- resolvMnt := spec.Mount{
- Type: "bind",
- Source: resolvPath,
- Destination: "/etc/resolv.conf",
- Options: []string{"rw", "bind"},
- }
- if !MountExists(g.Mounts(), resolvMnt.Destination) {
- g.AddMount(resolvMnt)
- }
- // Bind mount hosts
- hostsMnt := spec.Mount{
- Type: "bind",
- Source: hostsPath,
- Destination: "/etc/hosts",
- Options: []string{"rw", "bind"},
- }
- if !MountExists(g.Mounts(), hostsMnt.Destination) {
- g.AddMount(hostsMnt)
- }
- // Bind hostname
- hostnameMnt := spec.Mount{
- Type: "bind",
- Source: hostnamePath,
- Destination: "/etc/hostname",
- Options: []string{"rw", "bind"},
- }
- if !MountExists(g.Mounts(), hostnameMnt.Destination) {
- g.AddMount(hostnameMnt)
+
+ // Add bind mounts to container
+ for dstPath, srcPath := range c.state.BindMounts {
+ newMount := spec.Mount{
+ Type: "bind",
+ Source: srcPath,
+ Destination: dstPath,
+ Options: []string{"rw", "bind"},
+ }
+ if !MountExists(g.Mounts(), dstPath) {
+ g.AddMount(newMount)
+ }
}
// Bind builtin image volumes