summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_api.go12
-rw-r--r--libpod/container_attach_linux.go17
-rw-r--r--libpod/container_attach_unsupported.go4
-rw-r--r--libpod/events/events.go4
-rw-r--r--libpod/events/events_linux.go8
-rw-r--r--libpod/events/journal_linux.go10
-rw-r--r--libpod/events/journal_unsupported.go11
-rw-r--r--libpod/healthcheck_linux.go11
-rw-r--r--libpod/networking_linux.go4
-rw-r--r--libpod/runtime.go2
-rw-r--r--libpod/runtime_pod_linux.go10
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
}