aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/config/default.go17
-rw-r--r--libpod/container.go8
-rw-r--r--libpod/container_api.go5
-rw-r--r--libpod/container_internal_linux.go50
-rw-r--r--libpod/events/journal_linux.go2
-rw-r--r--libpod/events/logfile.go2
-rw-r--r--libpod/kube.go9
-rw-r--r--libpod/networking_linux.go49
-rw-r--r--libpod/oci_attach_linux.go2
-rw-r--r--libpod/options.go25
10 files changed, 141 insertions, 28 deletions
diff --git a/libpod/config/default.go b/libpod/config/default.go
index 17574c059..5decaeab7 100644
--- a/libpod/config/default.go
+++ b/libpod/config/default.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
+ "github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/containers/storage"
@@ -47,6 +48,12 @@ func defaultConfigFromMemory() (*Config, error) {
c.ImageDefaultTransport = _defaultTransport
c.StateType = define.BoltDBStateStore
c.OCIRuntime = "runc"
+
+ // If we're running on cgroups v2, default to using crun.
+ if onCgroupsv2, _ := cgroups.IsCgroup2UnifiedMode(); onCgroupsv2 {
+ c.OCIRuntime = "crun"
+ }
+
c.OCIRuntimes = map[string][]string{
"runc": {
"/usr/bin/runc",
@@ -58,7 +65,15 @@ func defaultConfigFromMemory() (*Config, error) {
"/usr/lib/cri-o-runc/sbin/runc",
"/run/current-system/sw/bin/runc",
},
- // TODO - should we add "crun" defaults here as well?
+ "crun": {
+ "/usr/bin/crun",
+ "/usr/sbin/crun",
+ "/usr/local/bin/crun",
+ "/usr/local/sbin/crun",
+ "/sbin/crun",
+ "/bin/crun",
+ "/run/current-system/sw/bin/crun",
+ },
}
c.ConmonPath = []string{
"/usr/libexec/podman/conmon",
diff --git a/libpod/container.go b/libpod/container.go
index 8e24391b9..4f7fc067e 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -138,6 +138,10 @@ type Container struct {
// being checkpointed. If requestedIP is set it will be used instead
// of config.StaticIP.
requestedIP net.IP
+ // A restored container should have the same MAC address as before
+ // being checkpointed. If requestedMAC is set it will be used instead
+ // of config.StaticMAC.
+ requestedMAC net.HardwareAddr
// This is true if a container is restored from a checkpoint.
restoreFromCheckpoint bool
@@ -296,6 +300,10 @@ type ContainerConfig struct {
// This cannot be set unless CreateNetNS is set.
// If not set, the container will be dynamically assigned an IP by CNI.
StaticIP net.IP `json:"staticIP"`
+ // StaticMAC is a static MAC to request for the container.
+ // This cannot be set unless CreateNetNS is set.
+ // If not set, the container will be dynamically assigned a MAC by CNI.
+ StaticMAC net.HardwareAddr `json:"staticMAC"`
// PortMappings are the ports forwarded to the container's network
// namespace
// These are not used unless CreateNetNS is true
diff --git a/libpod/container_api.go b/libpod/container_api.go
index a6f5b54d5..b8cfe02f6 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -794,6 +794,11 @@ type ContainerCheckpointOptions struct {
// important to be able to restore a container multiple
// times with '--import --name'.
IgnoreStaticIP bool
+ // IgnoreStaticMAC tells the API to ignore the MAC set
+ // during 'podman run' with '--mac-address'. This is especially
+ // important to be able to restore a container multiple
+ // times with '--import --name'.
+ IgnoreStaticMAC bool
}
// Checkpoint checkpoints a container
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 471648bc8..26d6771b0 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -794,6 +794,15 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
c.config.StaticIP = nil
}
+ // If a container is restored multiple times from an exported checkpoint with
+ // the help of '--import --name', the restore will fail if during 'podman run'
+ // a static container MAC address was set with '--mac-address'. The user
+ // can tell the restore process to ignore the static MAC with
+ // '--ignore-static-mac'
+ if options.IgnoreStaticMAC {
+ c.config.StaticMAC = nil
+ }
+
// Read network configuration from checkpoint
// Currently only one interface with one IP is supported.
networkStatusFile, err := os.Open(filepath.Join(c.bundlePath(), "network.status"))
@@ -803,9 +812,9 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
// TODO: This implicit restoring with or without IP depending on an
// unrelated restore parameter (--name) does not seem like the
// best solution.
- if err == nil && options.Name == "" && !options.IgnoreStaticIP {
+ if err == nil && options.Name == "" && (!options.IgnoreStaticIP || !options.IgnoreStaticMAC) {
// The file with the network.status does exist. Let's restore the
- // container with the same IP address as during checkpointing.
+ // container with the same IP address / MAC address as during checkpointing.
defer networkStatusFile.Close()
var networkStatus []*cnitypes.Result
networkJSON, err := ioutil.ReadAll(networkStatusFile)
@@ -815,16 +824,35 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if err := json.Unmarshal(networkJSON, &networkStatus); err != nil {
return err
}
- // Take the first IP address
- var IP net.IP
- if len(networkStatus) > 0 {
- if len(networkStatus[0].IPs) > 0 {
- IP = networkStatus[0].IPs[0].Address.IP
+ if !options.IgnoreStaticIP {
+ // Take the first IP address
+ var IP net.IP
+ if len(networkStatus) > 0 {
+ if len(networkStatus[0].IPs) > 0 {
+ IP = networkStatus[0].IPs[0].Address.IP
+ }
+ }
+ if IP != nil {
+ // Tell CNI which IP address we want.
+ c.requestedIP = IP
}
}
- if IP != nil {
- // Tell CNI which IP address we want.
- c.requestedIP = IP
+ if !options.IgnoreStaticMAC {
+ // Take the first device with a defined sandbox.
+ var MAC net.HardwareAddr
+ for _, n := range networkStatus[0].Interfaces {
+ if n.Sandbox != "" {
+ MAC, err = net.ParseMAC(n.Mac)
+ if err != nil {
+ return errors.Wrapf(err, "failed to parse MAC %v", n.Mac)
+ }
+ break
+ }
+ }
+ if MAC != nil {
+ // Tell CNI which MAC address we want.
+ c.requestedMAC = MAC
+ }
}
}
@@ -1314,7 +1342,7 @@ func (c *Container) copyOwnerAndPerms(source, dest string) error {
// Teardown CNI config on refresh
func (c *Container) refreshCNI() error {
// Let's try and delete any lingering network config...
- podNetwork := c.runtime.getPodNetwork(c.ID(), c.config.Name, "", c.config.Networks, c.config.PortMappings, c.config.StaticIP)
+ podNetwork := c.runtime.getPodNetwork(c.ID(), c.config.Name, "", c.config.Networks, c.config.PortMappings, c.config.StaticIP, c.config.StaticMAC)
return c.runtime.netPlugin.TearDownPod(podNetwork)
}
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 470c76959..9e6fffc29 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -54,6 +54,7 @@ func (e EventJournalD) Write(ee Event) error {
// Read reads events from the journal and sends qualified events to the event channel
func (e EventJournalD) Read(options ReadOptions) error {
+ defer close(options.EventChannel)
eventOptions, err := generateEventOptions(options.Filters, options.Since, options.Until)
if err != nil {
return errors.Wrapf(err, "failed to generate event options")
@@ -87,7 +88,6 @@ func (e EventJournalD) Read(options ReadOptions) error {
if err != nil {
return err
}
- defer close(options.EventChannel)
for {
if _, err := j.Next(); err != nil {
return err
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index 4b65b0ad0..93e6fa3c9 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -41,6 +41,7 @@ func (e EventLogFile) Write(ee Event) error {
// Reads from the log file
func (e EventLogFile) Read(options ReadOptions) error {
+ defer close(options.EventChannel)
eventOptions, err := generateEventOptions(options.Filters, options.Since, options.Until)
if err != nil {
return errors.Wrapf(err, "unable to generate event options")
@@ -68,7 +69,6 @@ func (e EventLogFile) Read(options ReadOptions) error {
options.EventChannel <- event
}
}
- close(options.EventChannel)
return nil
}
diff --git a/libpod/kube.go b/libpod/kube.go
index d0e7baf95..47a77991e 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -487,13 +487,16 @@ func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) {
if err := c.syncContainer(); err != nil {
return nil, errors.Wrapf(err, "unable to sync container during YAML generation")
}
+
logrus.Debugf("Looking in container for user: %s", c.User())
- u, err := lookup.GetUser(c.state.Mountpoint, c.User())
+ execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.User(), nil)
if err != nil {
return nil, err
}
- user := int64(u.Uid)
- sc.RunAsUser = &user
+ uid := int64(execUser.Uid)
+ gid := int64(execUser.Gid)
+ sc.RunAsUser = &uid
+ sc.RunAsGroup = &gid
}
return &sc, nil
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index ac1144fbe..cba7b636a 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -28,23 +28,34 @@ import (
)
// Get an OCICNI network config
-func (r *Runtime) getPodNetwork(id, name, nsPath string, networks []string, ports []ocicni.PortMapping, staticIP net.IP) ocicni.PodNetwork {
+func (r *Runtime) getPodNetwork(id, name, nsPath string, networks []string, ports []ocicni.PortMapping, staticIP net.IP, staticMAC net.HardwareAddr) ocicni.PodNetwork {
defaultNetwork := r.netPlugin.GetDefaultNetworkName()
network := ocicni.PodNetwork{
Name: name,
Namespace: name, // TODO is there something else we should put here? We don't know about Kube namespaces
ID: id,
NetNS: nsPath,
- Networks: networks,
RuntimeConfig: map[string]ocicni.RuntimeConfig{
defaultNetwork: {PortMappings: ports},
},
}
- if staticIP != nil {
- network.Networks = []string{defaultNetwork}
+ if staticIP != nil || staticMAC != nil {
+ network.Networks = []ocicni.NetAttachment{{Name: defaultNetwork}}
+ var rt ocicni.RuntimeConfig = ocicni.RuntimeConfig{PortMappings: ports}
+ if staticIP != nil {
+ rt.IP = staticIP.String()
+ }
+ if staticMAC != nil {
+ rt.MAC = staticMAC.String()
+ }
network.RuntimeConfig = map[string]ocicni.RuntimeConfig{
- defaultNetwork: {IP: staticIP.String(), PortMappings: ports},
+ defaultNetwork: rt,
+ }
+ } else {
+ network.Networks = make([]ocicni.NetAttachment, len(networks))
+ for i, netName := range networks {
+ network.Networks[i].Name = netName
}
}
@@ -62,7 +73,16 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
requestedIP = ctr.config.StaticIP
}
- podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP)
+ var requestedMAC net.HardwareAddr
+ if ctr.requestedMAC != nil {
+ requestedMAC = ctr.requestedMAC
+ // cancel request for a specific MAC in case the container is reused later
+ ctr.requestedMAC = nil
+ } else {
+ requestedMAC = ctr.config.StaticMAC
+ }
+
+ podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP, requestedMAC)
results, err := r.netPlugin.SetUpPod(podNetwork)
if err != nil {
@@ -78,10 +98,10 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
networkStatus := make([]*cnitypes.Result, 0)
for idx, r := range results {
- logrus.Debugf("[%d] CNI result: %v", idx, r.String())
- resultCurrent, err := cnitypes.GetResult(r)
+ logrus.Debugf("[%d] CNI result: %v", idx, r.Result.String())
+ resultCurrent, err := cnitypes.GetResult(r.Result)
if err != nil {
- return nil, errors.Wrapf(err, "error parsing CNI plugin result %q: %v", r.String(), err)
+ return nil, errors.Wrapf(err, "error parsing CNI plugin result %q: %v", r.Result.String(), err)
}
networkStatus = append(networkStatus, resultCurrent)
}
@@ -443,7 +463,16 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
requestedIP = ctr.config.StaticIP
}
- podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP)
+ var requestedMAC net.HardwareAddr
+ if ctr.requestedMAC != nil {
+ requestedMAC = ctr.requestedMAC
+ // cancel request for a specific MAC in case the container is reused later
+ ctr.requestedMAC = nil
+ } else {
+ requestedMAC = ctr.config.StaticMAC
+ }
+
+ podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP, requestedMAC)
if err := r.netPlugin.TearDownPod(podNetwork); err != nil {
return errors.Wrapf(err, "error tearing down CNI namespace configuration for container %s", ctr.ID())
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index eeaee6d43..46c70e7eb 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -152,7 +152,7 @@ func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-c
func processDetachKeys(keys string) ([]byte, error) {
// Check the validity of the provided keys first
if len(keys) == 0 {
- keys = define.DefaultDetachKeys
+ return []byte{}, nil
}
detachKeys, err := term.ToBytes(keys)
if err != nil {
diff --git a/libpod/options.go b/libpod/options.go
index 66e8ef93c..00b5626b4 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1052,6 +1052,31 @@ func WithStaticIP(ip net.IP) CtrCreateOption {
}
}
+// WithStaticMAC indicates that the container should request a static MAC from
+// the CNI plugins.
+// It cannot be set unless WithNetNS has already been passed.
+// Further, it cannot be set if additional CNI networks to join have been
+// specified.
+func WithStaticMAC(mac net.HardwareAddr) CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+
+ if !ctr.config.CreateNetNS {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set a static MAC if the container is not creating a network namespace")
+ }
+
+ if len(ctr.config.Networks) != 0 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set a static MAC if joining additional CNI networks")
+ }
+
+ ctr.config.StaticMAC = mac
+
+ return nil
+ }
+}
+
// WithLogDriver sets the log driver for the container
func WithLogDriver(driver string) CtrCreateOption {
return func(ctr *Container) error {