diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_copy_linux.go | 25 | ||||
-rw-r--r-- | libpod/container_inspect.go | 23 | ||||
-rw-r--r-- | libpod/define/errors.go | 2 | ||||
-rw-r--r-- | libpod/define/info.go | 31 | ||||
-rw-r--r-- | libpod/info.go | 44 | ||||
-rw-r--r-- | libpod/runtime.go | 90 |
6 files changed, 162 insertions, 53 deletions
diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go index 5c275c641..0ab322829 100644 --- a/libpod/container_copy_linux.go +++ b/libpod/container_copy_linux.go @@ -237,21 +237,32 @@ func (c *Container) joinMountAndExec(ctx context.Context, f func() error) error } defer mountFD.Close() - pidFD, err := getFD(PIDNS) + inHostPidNS, err := c.inHostPidNS() if err != nil { - errChan <- err + errChan <- errors.Wrap(err, "checking inHostPidNS") return } - defer pidFD.Close() - if err := unix.Unshare(unix.CLONE_NEWNS); err != nil { - errChan <- err - return + var pidFD *os.File + if !inHostPidNS { + pidFD, err = getFD(PIDNS) + if err != nil { + errChan <- err + return + } + defer pidFD.Close() } - if err := unix.Setns(int(pidFD.Fd()), unix.CLONE_NEWPID); err != nil { + + if err := unix.Unshare(unix.CLONE_NEWNS); err != nil { errChan <- err return } + if pidFD != nil { + if err := unix.Setns(int(pidFD.Fd()), unix.CLONE_NEWPID); err != nil { + errChan <- err + return + } + } if err := unix.Setns(int(mountFD.Fd()), unix.CLONE_NEWNS); err != nil { errChan <- err return diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 4210bc581..638e0b756 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -892,3 +892,26 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named return hostConfig, nil } + +// Return true if the container is running in the host's PID NS. +func (c *Container) inHostPidNS() (bool, error) { + if c.config.PIDNsCtr != "" { + return false, nil + } + ctrSpec, err := c.specFromState() + if err != nil { + return false, err + } + if ctrSpec.Linux != nil { + // Locate the spec's PID namespace. + // If there is none, it's pid=host. + // If there is one and it has a path, it's "ns:". + // If there is no path, it's default - the empty string. + for _, ns := range ctrSpec.Linux.Namespaces { + if ns.Type == spec.PIDNamespace { + return false, nil + } + } + } + return true, nil +} diff --git a/libpod/define/errors.go b/libpod/define/errors.go index 81bf5f69c..9fd210eed 100644 --- a/libpod/define/errors.go +++ b/libpod/define/errors.go @@ -152,7 +152,7 @@ var ( // ErrOCIRuntimeNotFound indicates the OCI runtime attempted to invoke a command // that was not found - ErrOCIRuntimeNotFound = errors.New("OCI not found") + ErrOCIRuntimeNotFound = errors.New("OCI runtime attempted to invoke a command that was not found") // ErrOCIRuntimeUnavailable indicates that the OCI runtime associated to a container // could not be found in the configuration diff --git a/libpod/define/info.go b/libpod/define/info.go index c9d6877c0..de709be74 100644 --- a/libpod/define/info.go +++ b/libpod/define/info.go @@ -23,21 +23,22 @@ type SecurityInfo struct { // HostInfo describes the libpod host type HostInfo struct { - Arch string `json:"arch"` - BuildahVersion string `json:"buildahVersion"` - CgroupManager string `json:"cgroupManager"` - CGroupsVersion string `json:"cgroupVersion"` - Conmon *ConmonInfo `json:"conmon"` - CPUs int `json:"cpus"` - Distribution DistributionInfo `json:"distribution"` - EventLogger string `json:"eventLogger"` - Hostname string `json:"hostname"` - IDMappings IDMappings `json:"idMappings,omitempty"` - Kernel string `json:"kernel"` - MemFree int64 `json:"memFree"` - MemTotal int64 `json:"memTotal"` - OCIRuntime *OCIRuntimeInfo `json:"ociRuntime"` - OS string `json:"os"` + Arch string `json:"arch"` + BuildahVersion string `json:"buildahVersion"` + CgroupManager string `json:"cgroupManager"` + CGroupsVersion string `json:"cgroupVersion"` + CgroupControllers []string `json:"cgroupControllers"` + Conmon *ConmonInfo `json:"conmon"` + CPUs int `json:"cpus"` + Distribution DistributionInfo `json:"distribution"` + EventLogger string `json:"eventLogger"` + Hostname string `json:"hostname"` + IDMappings IDMappings `json:"idMappings,omitempty"` + Kernel string `json:"kernel"` + MemFree int64 `json:"memFree"` + MemTotal int64 `json:"memTotal"` + OCIRuntime *OCIRuntimeInfo `json:"ociRuntime"` + OS string `json:"os"` // RemoteSocket returns the UNIX domain socket the Podman service is listening on RemoteSocket *RemoteSocket `json:"remoteSocket,omitempty"` RuntimeInfo map[string]interface{} `json:"runtimeInfo,omitempty"` diff --git a/libpod/info.go b/libpod/info.go index 7a28a4cf7..461e39a48 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -93,20 +93,33 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { return nil, errors.Wrapf(err, "error getting Seccomp profile path") } + // CGroups version + unified, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return nil, errors.Wrapf(err, "error reading cgroups mode") + } + + // Get Map of all available controllers + availableControllers, err := cgroups.GetAvailableControllers(nil, unified) + if err != nil { + return nil, errors.Wrapf(err, "error getting available cgroup controllers") + } + info := define.HostInfo{ - Arch: runtime.GOARCH, - BuildahVersion: buildah.Version, - CgroupManager: r.config.Engine.CgroupManager, - Linkmode: linkmode.Linkmode(), - CPUs: runtime.NumCPU(), - Distribution: hostDistributionInfo, - EventLogger: r.eventer.String(), - Hostname: host, - IDMappings: define.IDMappings{}, - Kernel: kv, - MemFree: mi.MemFree, - MemTotal: mi.MemTotal, - OS: runtime.GOOS, + Arch: runtime.GOARCH, + BuildahVersion: buildah.Version, + CgroupManager: r.config.Engine.CgroupManager, + CgroupControllers: availableControllers, + Linkmode: linkmode.Linkmode(), + CPUs: runtime.NumCPU(), + Distribution: hostDistributionInfo, + EventLogger: r.eventer.String(), + Hostname: host, + IDMappings: define.IDMappings{}, + Kernel: kv, + MemFree: mi.MemFree, + MemTotal: mi.MemTotal, + OS: runtime.GOOS, Security: define.SecurityInfo{ AppArmorEnabled: apparmor.IsEnabled(), DefaultCapabilities: strings.Join(r.config.Containers.DefaultCapabilities, ","), @@ -120,11 +133,6 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { SwapTotal: mi.SwapTotal, } - // CGroups version - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return nil, errors.Wrapf(err, "error reading cgroups mode") - } cgroupVersion := "v1" if unified { cgroupVersion = "v2" diff --git a/libpod/runtime.go b/libpod/runtime.go index d0bdeb574..713026a9e 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -13,6 +13,7 @@ import ( "strings" "sync" "syscall" + "time" "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" @@ -68,17 +69,18 @@ type Runtime struct { storageConfig storage.StoreOptions storageSet storageSet - state State - store storage.Store - storageService *storageService - imageContext *types.SystemContext - defaultOCIRuntime OCIRuntime - ociRuntimes map[string]OCIRuntime - runtimeFlags []string - netPlugin ocicni.CNIPlugin - conmonPath string - libimageRuntime *libimage.Runtime - lockManager lock.Manager + state State + store storage.Store + storageService *storageService + imageContext *types.SystemContext + defaultOCIRuntime OCIRuntime + ociRuntimes map[string]OCIRuntime + runtimeFlags []string + netPlugin ocicni.CNIPlugin + conmonPath string + libimageRuntime *libimage.Runtime + libimageEventsShutdown chan bool + lockManager lock.Manager // doRenumber indicates that the runtime should perform a lock renumber // during initialization. @@ -215,6 +217,8 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R return nil, err } + runtime.libimageEventsShutdown = make(chan bool) + return runtime, nil } @@ -680,6 +684,62 @@ func (r *Runtime) GetConfig() (*config.Config, error) { return config, nil } +// libimageEventsMap translates a libimage event type to a libpod event status. +var libimageEventsMap = map[libimage.EventType]events.Status{ + libimage.EventTypeImagePull: events.Pull, + libimage.EventTypeImagePush: events.Push, + libimage.EventTypeImageRemove: events.Remove, + libimage.EventTypeImageLoad: events.LoadFromArchive, + libimage.EventTypeImageSave: events.Save, + libimage.EventTypeImageTag: events.Tag, + libimage.EventTypeImageUntag: events.Untag, + libimage.EventTypeImageMount: events.Mount, + libimage.EventTypeImageUnmount: events.Unmount, +} + +// libimageEvents spawns a goroutine in the background which is listenting for +// events on the libimage.Runtime. The gourtine will be cleaned up implicitly +// when the main() exists. +func (r *Runtime) libimageEvents() { + toLibpodEventStatus := func(e *libimage.Event) events.Status { + status, found := libimageEventsMap[e.Type] + if !found { + return "Unknown" + } + return status + } + + go func() { + eventChannel := r.libimageRuntime.EventChannel() + + for { + // Make sure to read and write all events before + // checking if we're about to shutdown. + for len(eventChannel) > 0 { + libimageEvent := <-eventChannel + e := events.Event{ + ID: libimageEvent.ID, + Name: libimageEvent.Name, + Status: toLibpodEventStatus(libimageEvent), + Time: libimageEvent.Time, + Type: events.Image, + } + if err := r.eventer.Write(e); err != nil { + logrus.Errorf("unable to write image event: %q", err) + } + } + + select { + case <-r.libimageEventsShutdown: + return + + default: + time.Sleep(100 * time.Millisecond) + } + } + }() +} + // DeferredShutdown shuts down the runtime without exposing any // errors. This is only meant to be used when the runtime is being // shutdown within a defer statement; else use Shutdown @@ -719,7 +779,11 @@ func (r *Runtime) Shutdown(force bool) error { // If no store was requested, it can be nil and there is no need to // attempt to shut it down if r.store != nil { - if _, err := r.store.Shutdown(force); err != nil { + // Wait for the events to be written. + r.libimageEventsShutdown <- true + + // Note that the libimage runtime shuts down the store. + if err := r.libimageRuntime.Shutdown(force); err != nil { lastError = errors.Wrapf(err, "error shutting down container storage") } } @@ -845,6 +909,8 @@ func (r *Runtime) configureStore() error { return err } r.libimageRuntime = libimageRuntime + // Run the libimage events routine. + r.libimageEvents() return nil } |