summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_api.go4
-rw-r--r--libpod/container_internal.go17
-rw-r--r--libpod/container_internal_linux.go48
-rw-r--r--libpod/oci.go13
-rw-r--r--libpod/runtime.go25
5 files changed, 92 insertions, 15 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 6bef3c47d..4a76e1434 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -204,7 +204,7 @@ func (c *Container) Kill(signal uint) error {
// Exec starts a new process inside the container
// TODO investigate allowing exec without attaching
-func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams) error {
+func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams, preserveFDs int) error {
var capList []string
locked := false
@@ -266,7 +266,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir
logrus.Debugf("Creating new exec session in container %s with session id %s", c.ID(), sessionID)
- execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams)
+ execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams, preserveFDs)
if err != nil {
return errors.Wrapf(err, "error exec %s", c.ID())
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index e3753d825..08945c410 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1231,6 +1231,23 @@ func (c *Container) writeStringToRundir(destFile, output string) (string, error)
return filepath.Join(c.state.DestinationRunDir, destFile), nil
}
+// appendStringToRundir appends the provided string to the runtimedir file
+func (c *Container) appendStringToRundir(destFile, output string) (string, error) {
+ destFileName := filepath.Join(c.state.RunDir, destFile)
+
+ f, err := os.OpenFile(destFileName, os.O_APPEND|os.O_WRONLY, 0600)
+ if err != nil {
+ return "", errors.Wrapf(err, "unable to open %s", destFileName)
+ }
+ defer f.Close()
+
+ if _, err := f.WriteString(output); err != nil {
+ return "", errors.Wrapf(err, "unable to write %s", destFileName)
+ }
+
+ return filepath.Join(c.state.DestinationRunDir, destFile), nil
+}
+
// Save OCI spec to disk, replacing any existing specs for the container
func (c *Container) saveSpec(spec *spec.Spec) error {
// If the OCI spec already exists, we need to replace it
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 0e9a5124e..5f9e5a20c 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -698,13 +698,29 @@ func (c *Container) makeBindMounts() error {
// If it doesn't, don't copy them
resolvPath, exists := bindMounts["/etc/resolv.conf"]
if exists {
-
c.state.BindMounts["/etc/resolv.conf"] = resolvPath
}
+
+ // check if dependency container has an /etc/hosts file
hostsPath, exists := bindMounts["/etc/hosts"]
- if exists {
- c.state.BindMounts["/etc/hosts"] = hostsPath
+ if !exists {
+ return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
+ }
+
+ depCtr.lock.Lock()
+ // generate a hosts file for the dependency container,
+ // based on either its old hosts file, or the default,
+ // and add the relevant information from the new container (hosts and IP)
+ hostsPath, err = depCtr.appendHosts(hostsPath, c)
+
+ if err != nil {
+ depCtr.lock.Unlock()
+ return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID())
}
+ depCtr.lock.Unlock()
+
+ // finally, save it in the new container
+ c.state.BindMounts["/etc/hosts"] = hostsPath
} else {
newResolv, err := c.generateResolvConf()
if err != nil {
@@ -712,7 +728,7 @@ func (c *Container) makeBindMounts() error {
}
c.state.BindMounts["/etc/resolv.conf"] = newResolv
- newHosts, err := c.generateHosts()
+ newHosts, err := c.generateHosts("/etc/hosts")
if err != nil {
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
}
@@ -854,12 +870,28 @@ func (c *Container) generateResolvConf() (string, error) {
}
// generateHosts creates a containers hosts file
-func (c *Container) generateHosts() (string, error) {
- orig, err := ioutil.ReadFile("/etc/hosts")
+func (c *Container) generateHosts(path string) (string, error) {
+ orig, err := ioutil.ReadFile(path)
if err != nil {
- return "", errors.Wrapf(err, "unable to read /etc/hosts")
+ return "", errors.Wrapf(err, "unable to read %s", path)
}
hosts := string(orig)
+ hosts += c.getHosts()
+ return c.writeStringToRundir("hosts", hosts)
+}
+
+// appendHosts appends a container's config and state pertaining to hosts to a container's
+// local hosts file. netCtr is the container from which the netNS information is
+// taken.
+// path is the basis of the hosts file, into which netCtr's netNS information will be appended.
+func (c *Container) appendHosts(path string, netCtr *Container) (string, error) {
+ return c.appendStringToRundir("hosts", netCtr.getHosts())
+}
+
+// getHosts finds the pertinent information for a container's host file in its config and state
+// and returns a string in a format that can be written to the host file
+func (c *Container) getHosts() string {
+ var hosts string
if len(c.config.HostAdd) > 0 {
for _, host := range c.config.HostAdd {
// the host format has already been verified at this point
@@ -871,7 +903,7 @@ func (c *Container) generateHosts() (string, error) {
ipAddress := strings.Split(c.state.NetworkStatus[0].IPs[0].Address.String(), "/")[0]
hosts += fmt.Sprintf("%s\t%s\n", ipAddress, c.Hostname())
}
- return c.writeStringToRundir("hosts", hosts)
+ return hosts
}
// generatePasswd generates a container specific passwd file,
diff --git a/libpod/oci.go b/libpod/oci.go
index 2b3cc5db5..2cbf25699 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -733,7 +733,7 @@ func (r *OCIRuntime) unpauseContainer(ctr *Container) error {
// TODO: Add --detach support
// TODO: Convert to use conmon
// TODO: add --pid-file and use that to generate exec session tracking
-func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams) (*exec.Cmd, error) {
+func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams, preserveFDs int) (*exec.Cmd, error) {
if len(cmd) == 0 {
return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute")
}
@@ -770,6 +770,9 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
args = append(args, "--user", user)
}
+ if preserveFDs > 0 {
+ args = append(args, fmt.Sprintf("--preserve-fds=%d", preserveFDs))
+ }
if c.config.Spec.Process.NoNewPrivileges {
args = append(args, "--no-new-privs")
}
@@ -806,6 +809,14 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
return nil, errors.Wrapf(err, "cannot start container %s", c.ID())
}
+ if preserveFDs > 0 {
+ for fd := 3; fd < 3+preserveFDs; fd++ {
+ // These fds were passed down to the runtime. Close them
+ // and not interfere
+ os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)).Close()
+ }
+ }
+
return execCmd, nil
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 112b6820a..482cd9d73 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -333,7 +333,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
storageConf, err := util.GetDefaultStoreOptions()
if err != nil {
- return nil, errors.Wrapf(err, "error retrieving rootless storage config")
+ return nil, errors.Wrapf(err, "error retrieving storage config")
}
runtime.config.StorageConfig = storageConf
runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod")
@@ -365,8 +365,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
// containers/image uses XDG_RUNTIME_DIR to locate the auth file.
// So make sure the env variable is set.
- err = SetXdgRuntimeDir(runtimeDir)
- if err != nil {
+ if err := SetXdgRuntimeDir(runtimeDir); err != nil {
return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
}
@@ -475,13 +474,31 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime
// Set three fields not in the TOML config
runtime.config.StateType = defaultRuntimeConfig.StateType
runtime.config.OCIRuntime = defaultRuntimeConfig.OCIRuntime
- runtime.config.StorageConfig = storage.StoreOptions{}
+
+ storageConf, err := util.GetDefaultStoreOptions()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error retrieving storage config")
+ }
+ runtime.config.StorageConfig = storageConf
+ runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod")
+ runtime.config.VolumePath = filepath.Join(storageConf.GraphRoot, "volumes")
tmpDir, err := getDefaultTmpDir()
if err != nil {
return nil, err
}
runtime.config.TmpDir = tmpDir
+ if rootless.IsRootless() {
+ runtimeDir, err := util.GetRootlessRuntimeDir()
+ if err != nil {
+ return nil, err
+ }
+ // containers/image uses XDG_RUNTIME_DIR to locate the auth file.
+ // So make sure the env variable is set.
+ if err := SetXdgRuntimeDir(runtimeDir); err != nil {
+ return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
+ }
+ }
// Check to see if the given configuration file exists
if _, err := os.Stat(configPath); err != nil {