diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_api.go | 12 | ||||
-rw-r--r-- | libpod/container_attach_linux.go | 17 | ||||
-rw-r--r-- | libpod/container_attach_unsupported.go | 4 | ||||
-rw-r--r-- | libpod/events/events.go | 4 | ||||
-rw-r--r-- | libpod/events/events_linux.go | 8 | ||||
-rw-r--r-- | libpod/events/journal_linux.go | 10 | ||||
-rw-r--r-- | libpod/events/journal_unsupported.go | 11 | ||||
-rw-r--r-- | libpod/healthcheck_linux.go | 11 | ||||
-rw-r--r-- | libpod/networking_linux.go | 4 | ||||
-rw-r--r-- | libpod/runtime.go | 2 | ||||
-rw-r--r-- | libpod/runtime_pod_linux.go | 10 |
11 files changed, 80 insertions, 13 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go index 5bb610aab..06a31da11 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "strconv" + "sync" "time" "github.com/containers/libpod/libpod/driver" @@ -119,13 +120,20 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *AttachStreams, attachChan := make(chan error) + // We need to ensure that we don't return until start() fired in attach. + // Use a WaitGroup to sync this. + wg := new(sync.WaitGroup) + wg.Add(1) + // Attach to the container before starting it go func() { - if err := c.attach(streams, keys, resize, true); err != nil { + if err := c.attach(streams, keys, resize, true, wg); err != nil { attachChan <- err } close(attachChan) }() + + wg.Wait() c.newContainerEvent(events.Attach) return attachChan, nil } @@ -398,7 +406,7 @@ func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan re return errors.Wrapf(ErrCtrStateInvalid, "can only attach to created or running containers") } defer c.newContainerEvent(events.Attach) - return c.attach(streams, keys, resize, false) + return c.attach(streams, keys, resize, false, nil) } // Mount mounts a container's filesystem on the host diff --git a/libpod/container_attach_linux.go b/libpod/container_attach_linux.go index 3ff6ddc76..7e9b7697b 100644 --- a/libpod/container_attach_linux.go +++ b/libpod/container_attach_linux.go @@ -8,6 +8,7 @@ import ( "net" "os" "path/filepath" + "sync" "github.com/containers/libpod/pkg/kubeutils" "github.com/containers/libpod/utils" @@ -31,7 +32,7 @@ const ( // Attach to the given container // Does not check if state is appropriate -func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { +func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, wg *sync.WaitGroup) error { if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput { return errors.Wrapf(ErrInvalidArg, "must provide at least one stream to attach to") } @@ -48,12 +49,17 @@ func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan re logrus.Debugf("Attaching to container %s", c.ID()) - return c.attachContainerSocket(resize, detachKeys, streams, startContainer) + return c.attachContainerSocket(resize, detachKeys, streams, startContainer, wg) } -// attachContainerSocket connects to the container's attach socket and deals with the IO +// attachContainerSocket connects to the container's attach socket and deals with the IO. +// wg is only required if startContainer is true // TODO add a channel to allow interrupting -func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool) error { +func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool, wg *sync.WaitGroup) error { + if startContainer && wg == nil { + return errors.Wrapf(ErrInternal, "wait group not passed when startContainer set") + } + kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) { controlPath := filepath.Join(c.bundlePath(), "ctl") controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0) @@ -84,10 +90,13 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi } defer conn.Close() + // If starting was requested, start the container and notify when that's + // done. if startContainer { if err := c.start(); err != nil { return err } + wg.Done() } receiveStdoutError := make(chan error) diff --git a/libpod/container_attach_unsupported.go b/libpod/container_attach_unsupported.go index 068652b29..9e8badeaf 100644 --- a/libpod/container_attach_unsupported.go +++ b/libpod/container_attach_unsupported.go @@ -3,9 +3,11 @@ package libpod import ( + "sync" + "k8s.io/client-go/tools/remotecommand" ) -func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { +func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, wg *sync.WaitGroup) error { return ErrNotImplemented } diff --git a/libpod/events/events.go b/libpod/events/events.go index 650a47bfb..1ec79bcd7 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -10,6 +10,10 @@ import ( "github.com/pkg/errors" ) +// ErrNoJournaldLogging indicates that there is no journald logging +// supported (requires libsystemd) +var ErrNoJournaldLogging = errors.New("No support for journald logging") + // String returns a string representation of EventerType func (et EventerType) String() string { if et == LogFile { diff --git a/libpod/events/events_linux.go b/libpod/events/events_linux.go index da5d7965e..11f309574 100644 --- a/libpod/events/events_linux.go +++ b/libpod/events/events_linux.go @@ -8,12 +8,14 @@ import ( ) // NewEventer creates an eventer based on the eventer type -func NewEventer(options EventerOptions) (Eventer, error) { - var eventer Eventer +func NewEventer(options EventerOptions) (eventer Eventer, err error) { logrus.Debugf("Initializing event backend %s", options.EventerType) switch strings.ToUpper(options.EventerType) { case strings.ToUpper(Journald.String()): - eventer = EventJournalD{options} + eventer, err = newEventJournalD(options) + if err != nil { + return nil, errors.Wrapf(err, "eventer creation") + } case strings.ToUpper(LogFile.String()): eventer = EventLogFile{options} default: diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go index 8ba5bc2c7..78a630e9a 100644 --- a/libpod/events/journal_linux.go +++ b/libpod/events/journal_linux.go @@ -1,3 +1,5 @@ +// +build systemd + package events import ( @@ -10,11 +12,19 @@ import ( "github.com/sirupsen/logrus" ) +// DefaultEventerType is journald when systemd is available +const DefaultEventerType = Journald + // EventJournalD is the journald implementation of an eventer type EventJournalD struct { options EventerOptions } +// newEventJournalD creates a new journald Eventer +func newEventJournalD(options EventerOptions) (Eventer, error) { + return EventJournalD{options}, nil +} + // Write to journald func (e EventJournalD) Write(ee Event) error { m := make(map[string]string) diff --git a/libpod/events/journal_unsupported.go b/libpod/events/journal_unsupported.go new file mode 100644 index 000000000..004efdab2 --- /dev/null +++ b/libpod/events/journal_unsupported.go @@ -0,0 +1,11 @@ +// +build !systemd + +package events + +// DefaultEventerType is logfile when systemd is not present +const DefaultEventerType = LogFile + +// newEventJournalD always returns an error if libsystemd not found +func newEventJournalD(options EventerOptions) (Eventer, error) { + return nil, ErrNoJournaldLogging +} diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go index 869605ea8..d47a3b7cd 100644 --- a/libpod/healthcheck_linux.go +++ b/libpod/healthcheck_linux.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/exec" + "strings" "github.com/coreos/go-systemd/dbus" "github.com/pkg/errors" @@ -61,7 +62,13 @@ func (c *Container) removeTimer() error { return errors.Wrapf(err, "unable to get systemd connection to remove healthchecks") } defer conn.Close() - serviceFile := fmt.Sprintf("%s.timer", c.ID()) - _, err = conn.StopUnit(serviceFile, "fail", nil) + timerFile := fmt.Sprintf("%s.timer", c.ID()) + _, err = conn.StopUnit(timerFile, "fail", nil) + + // We want to ignore errors where the timer unit has already been removed. The error + // return is generic so we have to check against the string in the error + if err != nil && strings.HasSuffix(err.Error(), ".timer not loaded.") { + return nil + } return err } diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 2450bd6b1..b8a916de3 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -19,6 +19,7 @@ import ( "github.com/containers/libpod/pkg/firewall" "github.com/containers/libpod/pkg/inspect" "github.com/containers/libpod/pkg/netns" + "github.com/containers/libpod/pkg/rootless" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -100,6 +101,9 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re // Create and configure a new network namespace for a container func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q []*cnitypes.Result, err error) { + if rootless.IsRootless() { + return nil, nil, errors.New("cannot configure a new network namespace in rootless mode, only --network=slirp4netns is supported") + } ctrNS, err := netns.NewNS() if err != nil { return nil, nil, errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID()) diff --git a/libpod/runtime.go b/libpod/runtime.go index e6b84014e..18e9dfeb3 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -304,7 +304,7 @@ func defaultRuntimeConfig() (RuntimeConfig, error) { EnablePortReservation: true, EnableLabeling: true, NumLocks: 2048, - EventsLogger: "journald", + EventsLogger: events.DefaultEventerType.String(), }, nil } diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 456ad365f..124d0daf8 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -308,5 +308,15 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) // Mark pod invalid p.valid = false p.newPodEvent(events.Remove) + + // Deallocate the pod lock + if err := p.lock.Free(); err != nil { + if removalErr == nil { + removalErr = errors.Wrapf(err, "error freeing pod %s lock", p.ID()) + } else { + logrus.Errorf("Error freeing pod %s lock: %v", p.ID(), err) + } + } + return removalErr } |