diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/adapter/client.go | 16 | ||||
-rw-r--r-- | libpod/adapter/info_remote.go | 56 | ||||
-rw-r--r-- | libpod/adapter/runtime.go | 26 | ||||
-rw-r--r-- | libpod/adapter/runtime_remote.go | 28 | ||||
-rw-r--r-- | libpod/boltdb_state.go | 8 | ||||
-rw-r--r-- | libpod/common_test.go | 6 | ||||
-rw-r--r-- | libpod/container.go | 41 | ||||
-rw-r--r-- | libpod/container_api.go | 4 | ||||
-rw-r--r-- | libpod/container_easyjson.go | 14 | ||||
-rw-r--r-- | libpod/container_inspect.go | 5 | ||||
-rw-r--r-- | libpod/container_internal.go | 30 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 28 | ||||
-rw-r--r-- | libpod/container_internal_test.go | 2 | ||||
-rw-r--r-- | libpod/image/image.go | 18 | ||||
-rw-r--r-- | libpod/image/image_test.go | 46 | ||||
-rw-r--r-- | libpod/info.go | 2 | ||||
-rw-r--r-- | libpod/networking_linux.go | 22 | ||||
-rw-r--r-- | libpod/oci.go | 6 | ||||
-rw-r--r-- | libpod/runtime.go | 24 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 2 | ||||
-rw-r--r-- | libpod/state_test.go | 8 |
21 files changed, 321 insertions, 71 deletions
diff --git a/libpod/adapter/client.go b/libpod/adapter/client.go new file mode 100644 index 000000000..383c242c9 --- /dev/null +++ b/libpod/adapter/client.go @@ -0,0 +1,16 @@ +// +build remoteclient + +package adapter + +import ( + "github.com/varlink/go/varlink" +) + +// Connect provides a varlink connection +func (r RemoteRuntime) Connect() (*varlink.Connection, error) { + connection, err := varlink.NewConnection("unix:/run/podman/io.podman") + if err != nil { + return nil, err + } + return connection, nil +} diff --git a/libpod/adapter/info_remote.go b/libpod/adapter/info_remote.go new file mode 100644 index 000000000..3b691ed17 --- /dev/null +++ b/libpod/adapter/info_remote.go @@ -0,0 +1,56 @@ +// +build remoteclient + +package adapter + +import ( + "encoding/json" + + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" +) + +// Info returns information for the host system and its components +func (r RemoteRuntime) Info() ([]libpod.InfoData, error) { + // TODO the varlink implementation for info should be updated to match the output for regular info + var ( + reply []libpod.InfoData + hostInfo map[string]interface{} + store map[string]interface{} + ) + + registries := make(map[string]interface{}) + insecureRegistries := make(map[string]interface{}) + conn, err := r.Connect() + if err != nil { + return nil, err + } + defer conn.Close() + info, err := iopodman.GetInfo().Call(conn) + if err != nil { + return nil, err + } + + // info.host -> map[string]interface{} + h, err := json.Marshal(info.Host) + if err != nil { + return nil, err + } + json.Unmarshal(h, &hostInfo) + + // info.store -> map[string]interface{} + s, err := json.Marshal(info.Store) + if err != nil { + return nil, err + } + json.Unmarshal(s, &store) + + registries["registries"] = info.Registries + insecureRegistries["registries"] = info.Insecure_registries + + // Add everything to the reply + reply = append(reply, libpod.InfoData{Type: "host", Data: hostInfo}) + reply = append(reply, libpod.InfoData{Type: "registries", Data: registries}) + reply = append(reply, libpod.InfoData{Type: "insecure registries", Data: insecureRegistries}) + reply = append(reply, libpod.InfoData{Type: "store", Data: store}) + return reply, nil +} diff --git a/libpod/adapter/runtime.go b/libpod/adapter/runtime.go new file mode 100644 index 000000000..b6db51071 --- /dev/null +++ b/libpod/adapter/runtime.go @@ -0,0 +1,26 @@ +// +build !remoteclient + +package adapter + +import ( + "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/libpod" + "github.com/urfave/cli" +) + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + Runtime *libpod.Runtime + Remote bool +} + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cli.Context) (*LocalRuntime, error) { + runtime, err := libpodruntime.GetRuntime(c) + if err != nil { + return nil, err + } + return &LocalRuntime{ + Runtime: runtime, + }, nil +} diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go new file mode 100644 index 000000000..715728d21 --- /dev/null +++ b/libpod/adapter/runtime_remote.go @@ -0,0 +1,28 @@ +// +build remoteclient + +package adapter + +import "github.com/urfave/cli" + +// RemoteRuntime describes a wrapper runtime struct +type RemoteRuntime struct{} + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + Runtime *RemoteRuntime + Remote bool +} + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cli.Context) (*LocalRuntime, error) { + runtime := RemoteRuntime{} + return &LocalRuntime{ + Runtime: &runtime, + Remote: true, + }, nil +} + +// Shutdown is a bogus wrapper for compat with the libpod runtime +func (r RemoteRuntime) Shutdown(force bool) error { + return nil +} diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index ba8f7375a..b154d8bda 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -322,7 +322,7 @@ func (s *BoltState) Container(id string) (*Container, error) { ctrID := []byte(id) ctr := new(Container) - ctr.config = new(Config) + ctr.config = new(ContainerConfig) ctr.state = new(containerState) db, err := s.getDBCon() @@ -358,7 +358,7 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) { } ctr := new(Container) - ctr.config = new(Config) + ctr.config = new(ContainerConfig) ctr.state = new(containerState) db, err := s.getDBCon() @@ -751,7 +751,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) { } ctr := new(Container) - ctr.config = new(Config) + ctr.config = new(ContainerConfig) ctr.state = new(containerState) if err := s.getContainerFromDB(id, ctr, ctrBucket); err != nil { @@ -1137,7 +1137,7 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) { // Iterate through all containers in the pod err = podCtrs.ForEach(func(id, val []byte) error { newCtr := new(Container) - newCtr.config = new(Config) + newCtr.config = new(ContainerConfig) newCtr.state = new(containerState) ctrs = append(ctrs, newCtr) diff --git a/libpod/common_test.go b/libpod/common_test.go index 882468a3a..efbb5f404 100644 --- a/libpod/common_test.go +++ b/libpod/common_test.go @@ -17,7 +17,7 @@ import ( func getTestContainer(id, name string, manager lock.Manager) (*Container, error) { ctr := &Container{ - config: &Config{ + config: &ContainerConfig{ ID: id, Name: name, RootfsImageID: id, @@ -165,8 +165,8 @@ func testContainersEqual(t *testing.T, a, b *Container, allowedEmpty bool) { require.NotNil(t, a.state) require.NotNil(t, b.state) - aConfig := new(Config) - bConfig := new(Config) + aConfig := new(ContainerConfig) + bConfig := new(ContainerConfig) aState := new(containerState) bState := new(containerState) diff --git a/libpod/container.go b/libpod/container.go index 4e5088b32..026eb1c4f 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -1,7 +1,9 @@ package libpod import ( + "encoding/json" "fmt" + "io/ioutil" "net" "os" "path/filepath" @@ -113,7 +115,7 @@ func (ns LinuxNS) String() string { // syncContainer() immediately after locking. // ffjson: skip type Container struct { - config *Config + config *ContainerConfig state *containerState @@ -128,6 +130,11 @@ type Container struct { rootlessSlirpSyncR *os.File rootlessSlirpSyncW *os.File + + // A restored container should have the same IP address as before + // being checkpointed. If requestedIP is set it will be used instead + // of config.StaticIP. + requestedIP net.IP } // containerState contains the current state of the container @@ -200,11 +207,11 @@ type ExecSession struct { PID int `json:"pid"` } -// Config contains all information that was used to create the +// ContainerConfig contains all information that was used to create the // container. It may not be changed once created. // It is stored, read-only, on disk // easyjson:json -type Config struct { +type ContainerConfig struct { Spec *spec.Spec `json:"spec"` ID string `json:"id"` Name string `json:"name"` @@ -385,8 +392,8 @@ func (t ContainerStatus) String() string { // Unlocked // Config returns the configuration used to create the container -func (c *Container) Config() *Config { - returnConfig := new(Config) +func (c *Container) Config() *ContainerConfig { + returnConfig := new(ContainerConfig) deepcopier.Copy(c.config).To(returnConfig) return returnConfig @@ -402,6 +409,30 @@ func (c *Container) Spec() *spec.Spec { return returnSpec } +// specFromState returns the unmarshalled json config of the container. If the +// config does not exist (e.g., because the container was never started) return +// the spec from the config. +func (c *Container) specFromState() (*spec.Spec, error) { + spec := c.config.Spec + + if f, err := os.Open(c.state.ConfigPath); err == nil { + content, err := ioutil.ReadAll(f) + if err != nil { + return nil, errors.Wrapf(err, "error reading container config") + } + if err := json.Unmarshal([]byte(content), &spec); err != nil { + return nil, errors.Wrapf(err, "error unmarshalling container config") + } + } else { + // ignore when the file does not exist + if !os.IsNotExist(err) { + return nil, errors.Wrapf(err, "error opening container config") + } + } + + return spec, nil +} + // ID returns the container's ID func (c *Container) ID() string { return c.config.ID diff --git a/libpod/container_api.go b/libpod/container_api.go index 09bc46905..4eaf737b0 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -262,7 +262,7 @@ func (c *Container) Kill(signal uint) error { // Exec starts a new process inside the container // TODO allow specifying streams to attach to // TODO investigate allowing exec without attaching -func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) error { +func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string) error { var capList []string locked := false @@ -324,7 +324,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e 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, hostUser, sessionID) + execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID) if err != nil { return errors.Wrapf(err, "error exec %s", c.ID()) } diff --git a/libpod/container_easyjson.go b/libpod/container_easyjson.go index ae0972cf6..f1cb09bcc 100644 --- a/libpod/container_easyjson.go +++ b/libpod/container_easyjson.go @@ -1,6 +1,6 @@ // +build seccomp ostree selinux varlink exclude_graphdriver_devicemapper -// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. +// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT package libpod @@ -1238,7 +1238,7 @@ func (v *ExecSession) UnmarshalJSON(data []byte) error { func (v *ExecSession) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson1dbef17bDecodeGithubComContainersLibpodLibpod1(l, v) } -func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, out *Config) { +func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, out *ContainerConfig) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -1722,7 +1722,7 @@ func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, ou in.Consumed() } } -func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer, in Config) { +func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer, in ContainerConfig) { out.RawByte('{') first := true _ = first @@ -2427,26 +2427,26 @@ func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer, } // MarshalJSON supports json.Marshaler interface -func (v Config) MarshalJSON() ([]byte, error) { +func (v ContainerConfig) MarshalJSON() ([]byte, error) { w := jwriter.Writer{} easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(&w, v) return w.Buffer.BuildBytes(), w.Error } // MarshalEasyJSON supports easyjson.Marshaler interface -func (v Config) MarshalEasyJSON(w *jwriter.Writer) { +func (v ContainerConfig) MarshalEasyJSON(w *jwriter.Writer) { easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(w, v) } // UnmarshalJSON supports json.Unmarshaler interface -func (v *Config) UnmarshalJSON(data []byte) error { +func (v *ContainerConfig) UnmarshalJSON(data []byte) error { r := jlexer.Lexer{Data: data} easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(&r, v) return r.Error() } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *Config) UnmarshalEasyJSON(l *jlexer.Lexer) { +func (v *ContainerConfig) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(l, v) } func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(in *jlexer.Lexer, out *ocicni.PortMapping) { diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 06a0c9f32..e2730c282 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -12,7 +12,10 @@ import ( func (c *Container) getContainerInspectData(size bool, driverData *inspect.Data) (*inspect.ContainerInspectData, error) { config := c.config runtimeInfo := c.state - spec := c.config.Spec + spec, err := c.specFromState() + if err != nil { + return nil, err + } // Process is allowed to be nil in the spec args := []string{} diff --git a/libpod/container_internal.go b/libpod/container_internal.go index cc4c36bc9..69df33bc9 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1181,6 +1181,7 @@ func (c *Container) saveSpec(spec *spec.Spec) error { return nil } +// Warning: precreate hooks may alter 'config' in place. func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (extensionStageHooks map[string][]spec.Hook, err error) { var locale string var ok bool @@ -1209,13 +1210,13 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten } } + allHooks := make(map[string][]spec.Hook) if c.runtime.config.HooksDir == nil { if rootless.IsRootless() { return nil, nil } - allHooks := make(map[string][]spec.Hook) for _, hDir := range []string{hooks.DefaultDir, hooks.OverrideDir} { - manager, err := hooks.New(ctx, []string{hDir}, []string{"poststop"}, lang) + manager, err := hooks.New(ctx, []string{hDir}, []string{"precreate", "poststop"}, lang) if err != nil { if os.IsNotExist(err) { continue @@ -1233,19 +1234,32 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten allHooks[i] = hook } } - return allHooks, nil + } else { + manager, err := hooks.New(ctx, c.runtime.config.HooksDir, []string{"precreate", "poststop"}, lang) + if err != nil { + if os.IsNotExist(err) { + logrus.Warnf("Requested OCI hooks directory %q does not exist", c.runtime.config.HooksDir) + return nil, nil + } + return nil, err + } + + allHooks, err = manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + if err != nil { + return nil, err + } } - manager, err := hooks.New(ctx, c.runtime.config.HooksDir, []string{"poststop"}, lang) + hookErr, err := exec.RuntimeConfigFilter(ctx, allHooks["precreate"], config, exec.DefaultPostKillTimeout) if err != nil { - if os.IsNotExist(err) { - logrus.Warnf("Requested OCI hooks directory %q does not exist", c.runtime.config.HooksDir) - return nil, nil + logrus.Warnf("container %s: precreate hook: %v", c.ID(), err) + if hookErr != nil && hookErr != err { + logrus.Debugf("container %s: precreate hook (hook error): %v", c.ID(), hookErr) } return nil, err } - return manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + return allHooks, nil } // mount mounts the container's root filesystem diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 0745b7732..2f03d45ea 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -20,6 +20,7 @@ import ( cnitypes "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/plugins/pkg/ns" crioAnnotations "github.com/containers/libpod/pkg/annotations" + "github.com/containers/libpod/pkg/apparmor" "github.com/containers/libpod/pkg/criu" "github.com/containers/libpod/pkg/lookup" "github.com/containers/libpod/pkg/resolvconf" @@ -185,6 +186,13 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } + // Apply AppArmor checks and load the default profile if needed. + updatedProfile, err := apparmor.CheckProfileAndLoadDefault(c.config.Spec.Process.ApparmorProfile) + if err != nil { + return nil, err + } + g.SetProcessApparmorProfile(updatedProfile) + if err := c.makeBindMounts(); err != nil { return nil, err } @@ -228,10 +236,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } - if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { - return nil, errors.Wrapf(err, "error setting up OCI Hooks") - } - // Bind builtin image volumes if c.config.Rootfs == "" && c.config.ImageVolumes { if err := c.addLocalVolumes(ctx, &g, execUser); err != nil { @@ -384,6 +388,12 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { logrus.Debugf("set root propagation to %q", rootPropagation) g.SetLinuxRootPropagation(rootPropagation) } + + // Warning: precreate hooks may alter g.Config in place. + if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { + return nil, errors.Wrapf(err, "error setting up OCI Hooks") + } + return g.Config, nil } @@ -547,10 +557,8 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti } } if IP != nil { - env := fmt.Sprintf("IP=%s", IP) // Tell CNI which IP address we want. - os.Setenv("CNI_ARGS", env) - logrus.Debugf("Restoring container with %s", env) + c.requestedIP = IP } } @@ -566,12 +574,6 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti return err } - // TODO: use existing way to request static IPs, once it is merged in ocicni - // https://github.com/cri-o/ocicni/pull/23/ - - // CNI_ARGS was used to request a certain IP address. Unconditionally remove it. - os.Unsetenv("CNI_ARGS") - // Read config jsonPath := filepath.Join(c.bundlePath(), "config.json") logrus.Debugf("generate.NewFromFile at %v", jsonPath) diff --git a/libpod/container_internal_test.go b/libpod/container_internal_test.go index 51fb58713..124f1d20e 100644 --- a/libpod/container_internal_test.go +++ b/libpod/container_internal_test.go @@ -28,7 +28,7 @@ func TestPostDeleteHooks(t *testing.T) { statePath := filepath.Join(dir, "state") copyPath := filepath.Join(dir, "copy") c := Container{ - config: &Config{ + config: &ContainerConfig{ ID: "123abc", Spec: &rspec.Spec{ Annotations: map[string]string{ diff --git a/libpod/image/image.go b/libpod/image/image.go index 3a6d0e305..2e12adb70 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -305,12 +305,24 @@ func (i *Image) Names() []string { } // RepoDigests returns a string array of repodigests associated with the image -func (i *Image) RepoDigests() []string { +func (i *Image) RepoDigests() ([]string, error) { var repoDigests []string + digest := i.Digest() + for _, name := range i.Names() { - repoDigests = append(repoDigests, strings.SplitN(name, ":", 2)[0]+"@"+i.Digest().String()) + named, err := reference.ParseNormalizedNamed(name) + if err != nil { + return nil, err + } + + canonical, err := reference.WithDigest(reference.TrimNamed(named), digest) + if err != nil { + return nil, err + } + + repoDigests = append(repoDigests, canonical.String()) } - return repoDigests + return repoDigests, nil } // Created returns the time the image was created diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go index 91bb2411b..2a68fd273 100644 --- a/libpod/image/image_test.go +++ b/libpod/image/image_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/containers/storage" + "github.com/opencontainers/go-digest" "github.com/stretchr/testify/assert" ) @@ -192,6 +193,51 @@ func TestImage_MatchRepoTag(t *testing.T) { cleanup(workdir, ir) } +// TestImage_RepoDigests tests RepoDigest generation. +func TestImage_RepoDigests(t *testing.T) { + dgst, err := digest.Parse("sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc") + if err != nil { + t.Fatal(err) + } + + for _, test := range []struct { + name string + names []string + expected []string + }{ + { + name: "empty", + names: []string{}, + expected: nil, + }, + { + name: "tagged", + names: []string{"docker.io/library/busybox:latest"}, + expected: []string{"docker.io/library/busybox@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"}, + }, + { + name: "digest", + names: []string{"docker.io/library/busybox@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"}, + expected: []string{"docker.io/library/busybox@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"}, + }, + } { + t.Run(test.name, func(t *testing.T) { + image := &Image{ + image: &storage.Image{ + Names: test.names, + Digest: dgst, + }, + } + actual, err := image.RepoDigests() + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, test.expected, actual) + }) + } +} + // Test_splitString tests the splitString function in image that // takes input and splits on / and returns the last array item func Test_splitString(t *testing.T) { diff --git a/libpod/info.go b/libpod/info.go index 7044eba6a..a98f93897 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -13,6 +13,7 @@ import ( "time" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" "github.com/containers/libpod/utils" "github.com/containers/storage/pkg/system" "github.com/pkg/errors" @@ -115,6 +116,7 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { func (r *Runtime) storeInfo() (map[string]interface{}, error) { // lets say storage driver in use, number of images, number of containers info := map[string]interface{}{} + info["ConfigFile"] = util.StorageConfigFile() info["GraphRoot"] = r.store.GraphRoot() info["RunRoot"] = r.store.RunRoot() info["GraphDriverName"] = r.store.GraphDriverName() diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 43d0a61a4..a343bee6a 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -50,7 +50,16 @@ func (r *Runtime) getPodNetwork(id, name, nsPath string, networks []string, port // Create and configure a new network namespace for a container func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Result, error) { - podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, ctr.config.StaticIP) + var requestedIP net.IP + if ctr.requestedIP != nil { + requestedIP = ctr.requestedIP + // cancel request for a specific IP in case the container is reused later + ctr.requestedIP = nil + } else { + requestedIP = ctr.config.StaticIP + } + + podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP) results, err := r.netPlugin.SetUpPod(podNetwork) if err != nil { @@ -258,7 +267,16 @@ func (r *Runtime) teardownNetNS(ctr *Container) error { logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID()) - podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, ctr.config.StaticIP) + var requestedIP net.IP + if ctr.requestedIP != nil { + requestedIP = ctr.requestedIP + // cancel request for a specific IP in case the container is reused later + ctr.requestedIP = nil + } else { + requestedIP = ctr.config.StaticIP + } + + podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP) // The network may have already been torn down, so don't fail here, just log if err := r.netPlugin.TearDownPod(podNetwork); err != nil { diff --git a/libpod/oci.go b/libpod/oci.go index 093bfdd35..31c1a7e85 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -728,7 +728,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, user, sessionID string) (*exec.Cmd, error) { +func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string) (*exec.Cmd, error) { if len(cmd) == 0 { return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute") } @@ -749,7 +749,9 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty args = append(args, "exec") - args = append(args, "--cwd", c.config.Spec.Process.Cwd) + if cwd != "" { + args = append(args, "--cwd", cwd) + } args = append(args, "--pid-file", c.execPidPath(sessionID)) diff --git a/libpod/runtime.go b/libpod/runtime.go index ab8d02a4f..c9471247c 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -692,25 +692,19 @@ func makeRuntime(runtime *Runtime) (err error) { } } - // Set up the lock manager - var manager lock.Manager lockPath := DefaultSHMLockPath if rootless.IsRootless() { lockPath = fmt.Sprintf("%s_%d", DefaultRootlessSHMLockPath, rootless.GetRootlessUID()) } - if doRefresh { - // If SHM locks already exist, delete them and reinitialize - if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error deleting existing libpod SHM segment %s", lockPath) - } - - manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks) - if err != nil { - return err - } - } else { - manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks) - if err != nil { + // Set up the lock manager + manager, err := lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks) + if err != nil { + if os.IsNotExist(errors.Cause(err)) { + manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks) + if err != nil { + return err + } + } else { return err } } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index e6f2c962f..ab79fe5fb 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -47,7 +47,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. } ctr := new(Container) - ctr.config = new(Config) + ctr.config = new(ContainerConfig) ctr.state = new(containerState) ctr.config.ID = stringid.GenerateNonCryptoID() diff --git a/libpod/state_test.go b/libpod/state_test.go index ee4201b1c..4bd00ab55 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -156,7 +156,7 @@ func TestGetContainerPodSameIDFails(t *testing.T) { func TestAddInvalidContainerFails(t *testing.T) { runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { - err := state.AddContainer(&Container{config: &Config{ID: "1234"}}) + err := state.AddContainer(&Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) }) } @@ -756,7 +756,7 @@ func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) { func TestUpdateInvalidContainerReturnsError(t *testing.T) { runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { - err := state.UpdateContainer(&Container{config: &Config{ID: "1234"}}) + err := state.UpdateContainer(&Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) }) } @@ -780,7 +780,7 @@ func TestUpdateContainerNotInNamespaceReturnsError(t *testing.T) { func TestSaveInvalidContainerReturnsError(t *testing.T) { runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { - err := state.SaveContainer(&Container{config: &Config{ID: "1234"}}) + err := state.SaveContainer(&Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) }) } @@ -2604,7 +2604,7 @@ func TestAddContainerToPodInvalidCtr(t *testing.T) { err = state.AddPod(testPod) assert.NoError(t, err) - err = state.AddContainerToPod(testPod, &Container{config: &Config{ID: "1234"}}) + err = state.AddContainerToPod(testPod, &Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) ctrs, err := state.PodContainersByID(testPod) |