diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal_linux.go | 2 | ||||
-rw-r--r-- | libpod/events.go | 10 | ||||
-rw-r--r-- | libpod/events/config.go | 9 | ||||
-rw-r--r-- | libpod/events/events.go | 15 | ||||
-rw-r--r-- | libpod/events/events_linux.go | 5 | ||||
-rw-r--r-- | libpod/events/journal_linux.go | 7 | ||||
-rw-r--r-- | libpod/events/logfile.go | 8 | ||||
-rw-r--r-- | libpod/options.go | 30 | ||||
-rw-r--r-- | libpod/runtime.go | 49 | ||||
-rw-r--r-- | libpod/runtime_migrate.go | 47 | ||||
-rw-r--r-- | libpod/runtime_renumber.go | 3 |
11 files changed, 167 insertions, 18 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index f352b188e..c5e404155 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -420,7 +420,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // It also expects to be able to write to /sys/fs/cgroup/systemd and /var/log/journal func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) error { options := []string{"rw", "rprivate", "noexec", "nosuid", "nodev"} - for _, dest := range []string{"/run", "/run/lock"} { + for _, dest := range []string{"/run"} { if MountExists(mounts, dest) { continue } diff --git a/libpod/events.go b/libpod/events.go index 1b5c3bd99..13bb5bdde 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -50,6 +50,16 @@ func (p *Pod) newPodEvent(status events.Status) { } } +// newSystemEvent creates a new event for libpod as a whole. +func (r *Runtime) newSystemEvent(status events.Status) { + e := events.NewEvent(status) + e.Type = events.System + + if err := r.eventer.Write(e); err != nil { + logrus.Errorf("unable to write system event: %q", err) + } +} + // newVolumeEvent creates a new event for a libpod volume func (v *Volume) newVolumeEvent(status events.Status) { e := events.NewEvent(status) diff --git a/libpod/events/config.go b/libpod/events/config.go index d3b6d8c50..36387e835 100644 --- a/libpod/events/config.go +++ b/libpod/events/config.go @@ -84,6 +84,9 @@ const ( Image Type = "image" // Pod - event is related to pods Pod Type = "pod" + // System - event is related to Podman whole and not to any specific + // container/pod/image/volume + System Type = "system" // Volume - event is related to volumes Volume Type = "volume" @@ -123,8 +126,14 @@ const ( Pull Status = "pull" // Push ... Push Status = "push" + // Refresh indicates that the system refreshed the state after a + // reboot. + Refresh Status = "refresh" // Remove ... Remove Status = "remove" + // Renumber indicates that lock numbers were reallocated at user + // request. + Renumber Status = "renumber" // Restore ... Restore Status = "restore" // Save ... diff --git a/libpod/events/events.go b/libpod/events/events.go index e8c61faa0..202c9db4e 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -49,6 +49,8 @@ func (e *Event) ToHumanReadable() string { humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s)", e.Time, e.Type, e.Status, e.ID, e.Image, e.Name) case Image: humanFormat = fmt.Sprintf("%s %s %s %s %s", e.Time, e.Type, e.Status, e.ID, e.Name) + case System: + humanFormat = fmt.Sprintf("%s %s %s", e.Time, e.Type, e.Status) case Volume: humanFormat = fmt.Sprintf("%s %s %s %s", e.Time, e.Type, e.Status, e.Name) } @@ -85,10 +87,12 @@ func StringToType(name string) (Type, error) { return Image, nil case Pod.String(): return Pod, nil + case System.String(): + return System, nil case Volume.String(): return Volume, nil } - return "", errors.Errorf("unknown event type %s", name) + return "", errors.Errorf("unknown event type %q", name) } // StringToStatus converts a string to an Event Status @@ -107,7 +111,6 @@ func StringToStatus(name string) (Status, error) { case Commit.String(): return Commit, nil case Create.String(): - return Create, nil case Exec.String(): return Exec, nil @@ -135,8 +138,14 @@ func StringToStatus(name string) (Status, error) { return Pull, nil case Push.String(): return Push, nil + case Refresh.String(): + return Refresh, nil case Remove.String(): return Remove, nil + case Renumber.String(): + return Renumber, nil + case Restore.String(): + return Restore, nil case Save.String(): return Save, nil case Start.String(): @@ -154,7 +163,7 @@ func StringToStatus(name string) (Status, error) { case Untag.String(): return Untag, nil } - return "", errors.Errorf("unknown event status %s", name) + return "", errors.Errorf("unknown event status %q", name) } func (e EventLogFile) getTail(options ReadOptions) (*tail.Tail, error) { diff --git a/libpod/events/events_linux.go b/libpod/events/events_linux.go index d6898145c..da5d7965e 100644 --- a/libpod/events/events_linux.go +++ b/libpod/events/events_linux.go @@ -1,13 +1,16 @@ package events import ( - "github.com/pkg/errors" "strings" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) // NewEventer creates an eventer based on the eventer type func NewEventer(options EventerOptions) (Eventer, error) { var eventer Eventer + logrus.Debugf("Initializing event backend %s", options.EventerType) switch strings.ToUpper(options.EventerType) { case strings.ToUpper(Journald.String()): eventer = EventJournalD{options} diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go index e6b54db1d..8ba5bc2c7 100644 --- a/libpod/events/journal_linux.go +++ b/libpod/events/journal_linux.go @@ -7,6 +7,7 @@ import ( "github.com/coreos/go-systemd/journal" "github.com/coreos/go-systemd/sdjournal" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) // EventJournalD is the journald implementation of an eventer @@ -87,7 +88,11 @@ func (e EventJournalD) Read(options ReadOptions) error { } newEvent, err := newEventFromJournalEntry(entry) if err != nil { - return err + // We can't decode this event. + // Don't fail hard - that would make events unusable. + // Instead, log and continue. + logrus.Errorf("Unable to decode event: %v", err) + continue } include := true for _, filter := range eventOptions { diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go index 3232b86d0..e5efc09bb 100644 --- a/libpod/events/logfile.go +++ b/libpod/events/logfile.go @@ -4,6 +4,7 @@ import ( "fmt" "os" + "github.com/containers/storage" "github.com/pkg/errors" ) @@ -15,6 +16,13 @@ type EventLogFile struct { // Writes to the log file func (e EventLogFile) Write(ee Event) error { + // We need to lock events file + lock, err := storage.GetLockfile(e.options.LogFilePath + ".lock") + if err != nil { + return err + } + lock.Lock() + defer lock.Unlock() f, err := os.OpenFile(e.options.LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0700) if err != nil { return err diff --git a/libpod/options.go b/libpod/options.go index 8038f1935..9932d5453 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1,6 +1,7 @@ package libpod import ( + "context" "net" "os" "path/filepath" @@ -436,6 +437,22 @@ func WithRenumber() RuntimeOption { } } +// WithMigrate instructs libpod to perform a lock migrateing while +// initializing. This will handle migrations from early versions of libpod with +// file locks to newer versions with SHM locking, as well as changes in the +// number of configured locks. +func WithMigrate() RuntimeOption { + return func(rt *Runtime) error { + if rt.valid { + return ErrRuntimeFinalized + } + + rt.doMigrate = true + + return nil + } +} + // Container Creation Options // WithShmDir sets the directory that should be mounted on /dev/shm. @@ -450,6 +467,19 @@ func WithShmDir(dir string) CtrCreateOption { } } +// WithContext sets the context to use. +func WithContext(ctx context.Context) RuntimeOption { + return func(rt *Runtime) error { + if rt.valid { + return ErrRuntimeFinalized + } + + rt.ctx = ctx + + return nil + } +} + // WithSystemd turns on systemd mode in the container func WithSystemd() CtrCreateOption { return func(ctr *Container) error { diff --git a/libpod/runtime.go b/libpod/runtime.go index d03731284..e85242028 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1,8 +1,8 @@ package libpod import ( + "context" "fmt" - "github.com/containers/libpod/libpod/events" "io/ioutil" "os" "path/filepath" @@ -12,6 +12,7 @@ import ( "github.com/BurntSushi/toml" is "github.com/containers/image/storage" "github.com/containers/image/types" + "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/lock" "github.com/containers/libpod/pkg/firewall" @@ -100,6 +101,8 @@ type Runtime struct { // unused. doRenumber bool + doMigrate bool + // valid indicates whether the runtime is ready to use. // valid is set to true when a runtime is returned from GetRuntime(), // and remains true until the runtime is shut down (rendering its @@ -109,6 +112,8 @@ type Runtime struct { // mechanism to read and write even logs eventer events.Eventer + + ctx context.Context } // OCIRuntimePath contains information about an OCI runtime. @@ -754,6 +759,17 @@ func makeRuntime(runtime *Runtime) (err error) { if err != nil { return err } + + defer func() { + if err != nil && store != nil { + // Don't forcibly shut down + // We could be opening a store in use by another libpod + _, err2 := store.Shutdown(false) + if err2 != nil { + logrus.Errorf("Error removing store for partially-created runtime: %s", err2) + } + } + }() } runtime.store = store @@ -780,17 +796,6 @@ func makeRuntime(runtime *Runtime) (err error) { runtime.eventer = eventer ir.Eventer = eventer - defer func() { - if err != nil && store != nil { - // Don't forcibly shut down - // We could be opening a store in use by another libpod - _, err2 := store.Shutdown(false) - if err2 != nil { - logrus.Errorf("Error removing store for partially-created runtime: %s", err2) - } - } - }() - // Set up a storage service for creating container root filesystems from // images storageService, err := getStorageService(runtime.store) @@ -962,6 +967,24 @@ func makeRuntime(runtime *Runtime) (err error) { // further runtime.valid = true + if runtime.doMigrate { + if os.Geteuid() != 0 { + aliveLock.Unlock() + locked = false + + became, ret, err := rootless.BecomeRootInUserNS() + if err != nil { + return err + } + if became { + os.Exit(ret) + } + } + if err := runtime.migrate(); err != nil { + return err + } + } + return nil } @@ -1074,6 +1097,8 @@ func (r *Runtime) refresh(alivePath string) error { } defer file.Close() + r.newSystemEvent(events.Refresh) + return nil } diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go new file mode 100644 index 000000000..a084df289 --- /dev/null +++ b/libpod/runtime_migrate.go @@ -0,0 +1,47 @@ +package libpod + +import ( + "path/filepath" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +func (r *Runtime) migrate() error { + runningContainers, err := r.GetRunningContainers() + if err != nil { + return err + } + + allCtrs, err := r.state.AllContainers() + if err != nil { + return err + } + + logrus.Infof("stopping all containers") + for _, ctr := range runningContainers { + logrus.Infof("stopping %s", ctr.ID()) + if err := ctr.Stop(); err != nil { + return errors.Wrapf(err, "cannot stop container %s", ctr.ID()) + } + } + + for _, ctr := range allCtrs { + oldLocation := filepath.Join(ctr.state.RunDir, "conmon.pid") + if ctr.config.ConmonPidFile == oldLocation { + logrus.Infof("changing conmon PID file for %s", ctr.ID()) + ctr.config.ConmonPidFile = filepath.Join(ctr.config.StaticDir, "conmon.pid") + if err := r.state.RewriteContainerConfig(ctr, ctr.config); err != nil { + return errors.Wrapf(err, "error rewriting config for container %s", ctr.ID()) + } + } + } + + for _, ctr := range runningContainers { + if err := ctr.Start(r.ctx, true); err != nil { + logrus.Errorf("error restarting container %s", ctr.ID()) + } + } + + return nil +} diff --git a/libpod/runtime_renumber.go b/libpod/runtime_renumber.go index 125cf0825..735ffba34 100644 --- a/libpod/runtime_renumber.go +++ b/libpod/runtime_renumber.go @@ -1,6 +1,7 @@ package libpod import ( + "github.com/containers/libpod/libpod/events" "github.com/pkg/errors" ) @@ -53,5 +54,7 @@ func (r *Runtime) renumberLocks() error { } } + r.newSystemEvent(events.Renumber) + return nil } |