diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_config.go | 2 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 1 | ||||
-rw-r--r-- | libpod/container_path_resolution.go | 2 | ||||
-rw-r--r-- | libpod/network/cni/run.go | 2 | ||||
-rw-r--r-- | libpod/network/cni/run_test.go | 14 | ||||
-rw-r--r-- | libpod/network/types/network.go | 50 | ||||
-rw-r--r-- | libpod/network/types/network_test.go | 82 | ||||
-rw-r--r-- | libpod/networking_linux.go | 249 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 2 | ||||
-rw-r--r-- | libpod/options.go | 2 | ||||
-rw-r--r-- | libpod/runtime.go | 4 |
11 files changed, 273 insertions, 137 deletions
diff --git a/libpod/container_config.go b/libpod/container_config.go index 87d37a9e6..412be835f 100644 --- a/libpod/container_config.go +++ b/libpod/container_config.go @@ -233,7 +233,7 @@ type ContainerNetworkConfig struct { // 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"` + StaticMAC types.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_internal_linux.go b/libpod/container_internal_linux.go index d3151f7e0..2fd519990 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1546,6 +1546,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti logrus.Debugf("Restored container %s", c.ID()) c.state.State = define.ContainerStateRunning + c.state.Checkpointed = false if !options.Keep { // Delete all checkpoint related files. At this point, in theory, all files diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go index bb2ef1a73..7db23b783 100644 --- a/libpod/container_path_resolution.go +++ b/libpod/container_path_resolution.go @@ -161,7 +161,7 @@ func isPathOnBindMount(c *Container, containerPath string) bool { if cleanedContainerPath == filepath.Clean(m.Destination) { return true } - for dest := m.Destination; dest != "/"; dest = filepath.Dir(dest) { + for dest := m.Destination; dest != "/" && dest != "."; dest = filepath.Dir(dest) { if cleanedContainerPath == dest { return true } diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go index 99b2adce5..7795dfeeb 100644 --- a/libpod/network/cni/run.go +++ b/libpod/network/cni/run.go @@ -160,7 +160,7 @@ func CNIResultToStatus(res cnitypes.Result) (types.StatusBlock, error) { return result, err } interfaces[cniInt.Name] = types.NetInterface{ - MacAddress: mac, + MacAddress: types.HardwareAddr(mac), Networks: []types.NetAddress{{ Subnet: types.IPNet{IPNet: ip.Address}, Gateway: ip.Gateway, diff --git a/libpod/network/cni/run_test.go b/libpod/network/cni/run_test.go index 965203c2a..3169cd0eb 100644 --- a/libpod/network/cni/run_test.go +++ b/libpod/network/cni/run_test.go @@ -398,7 +398,7 @@ var _ = Describe("run CNI", func() { i, err := net.InterfaceByName(intName1) Expect(err).To(BeNil()) Expect(i.Name).To(Equal(intName1)) - Expect(i.HardwareAddr).To(Equal(macInt1)) + Expect(i.HardwareAddr).To(Equal((net.HardwareAddr)(macInt1))) addrs, err := i.Addrs() Expect(err).To(BeNil()) subnet := &net.IPNet{ @@ -448,7 +448,7 @@ var _ = Describe("run CNI", func() { i, err := net.InterfaceByName(intName1) Expect(err).To(BeNil()) Expect(i.Name).To(Equal(intName1)) - Expect(i.HardwareAddr).To(Equal(macInt1)) + Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt1))) addrs, err := i.Addrs() Expect(err).To(BeNil()) subnet := &net.IPNet{ @@ -460,7 +460,7 @@ var _ = Describe("run CNI", func() { i, err = net.InterfaceByName(intName2) Expect(err).To(BeNil()) Expect(i.Name).To(Equal(intName2)) - Expect(i.HardwareAddr).To(Equal(macInt2)) + Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt2))) addrs, err = i.Addrs() Expect(err).To(BeNil()) subnet = &net.IPNet{ @@ -600,7 +600,7 @@ var _ = Describe("run CNI", func() { i, err := net.InterfaceByName(intName1) Expect(err).To(BeNil()) Expect(i.Name).To(Equal(intName1)) - Expect(i.HardwareAddr).To(Equal(macInt1)) + Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt1))) addrs, err := i.Addrs() Expect(err).To(BeNil()) subnet := &net.IPNet{ @@ -612,7 +612,7 @@ var _ = Describe("run CNI", func() { i, err = net.InterfaceByName(intName2) Expect(err).To(BeNil()) Expect(i.Name).To(Equal(intName2)) - Expect(i.HardwareAddr).To(Equal(macInt2)) + Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt2))) addrs, err = i.Addrs() Expect(err).To(BeNil()) subnet = &net.IPNet{ @@ -690,7 +690,7 @@ var _ = Describe("run CNI", func() { netName: { InterfaceName: interfaceName, StaticIPs: []net.IP{ip1, ip2}, - StaticMAC: mac, + StaticMAC: types.HardwareAddr(mac), }, }, }, @@ -708,7 +708,7 @@ var _ = Describe("run CNI", func() { Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.IP.String()).To(Equal(ip2.String())) Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.Mask).To(Equal(subnet2.Mask)) Expect(res[netName].Interfaces[interfaceName].Networks[1].Gateway).To(Equal(net.ParseIP("fd41:0a75:2ca0:48a9::1"))) - Expect(res[netName].Interfaces[interfaceName].MacAddress).To(Equal(mac)) + Expect(res[netName].Interfaces[interfaceName].MacAddress).To(Equal(types.HardwareAddr(mac))) // default network has no dns Expect(res[netName].DNSServerIPs).To(BeEmpty()) Expect(res[netName].DNSSearchDomains).To(BeEmpty()) diff --git a/libpod/network/types/network.go b/libpod/network/types/network.go index 657c1ca6a..ba5e018fd 100644 --- a/libpod/network/types/network.go +++ b/libpod/network/types/network.go @@ -1,6 +1,7 @@ package types import ( + "encoding/json" "net" "time" ) @@ -94,6 +95,51 @@ func (n *IPNet) UnmarshalText(text []byte) error { return nil } +// HardwareAddr is the same as net.HardwareAddr except +// that it adds the json marshal/unmarshal methods. +// This allows us to read the mac from a json string +// and a byte array. +// swagger:model MacAddress +type HardwareAddr net.HardwareAddr + +func (h *HardwareAddr) String() string { + return (*net.HardwareAddr)(h).String() +} + +func (h *HardwareAddr) MarshalText() ([]byte, error) { + return []byte((*net.HardwareAddr)(h).String()), nil +} + +func (h *HardwareAddr) UnmarshalJSON(text []byte) error { + if len(text) == 0 { + *h = nil + return nil + } + + // if the json string start with a quote we got a string + // unmarshal the string and parse the mac from this string + if string(text[0]) == `"` { + var macString string + err := json.Unmarshal(text, &macString) + if err == nil { + mac, err := net.ParseMAC(macString) + if err == nil { + *h = HardwareAddr(mac) + return nil + } + } + } + // not a string or got an error fallback to the normal parsing + mac := make(net.HardwareAddr, 0, 6) + // use the standard json unmarshal for backwards compat + err := json.Unmarshal(text, &mac) + if err != nil { + return err + } + *h = HardwareAddr(mac) + return nil +} + type Subnet struct { // Subnet for this Network in CIDR form. // swagger:strfmt string @@ -134,7 +180,7 @@ type NetInterface struct { // Networks list of assigned subnets with their gateway. Networks []NetAddress `json:"networks,omitempty"` // MacAddress for this Interface. - MacAddress net.HardwareAddr `json:"mac_address"` + MacAddress HardwareAddr `json:"mac_address"` } // NetAddress contains the subnet and gateway. @@ -157,7 +203,7 @@ type PerNetworkOptions struct { // Optional. Aliases []string `json:"aliases,omitempty"` // StaticMac for this container. Optional. - StaticMAC net.HardwareAddr `json:"static_mac,omitempty"` + StaticMAC HardwareAddr `json:"static_mac,omitempty"` // InterfaceName for this container. Required. InterfaceName string `json:"interface_name"` } diff --git a/libpod/network/types/network_test.go b/libpod/network/types/network_test.go new file mode 100644 index 000000000..91ee93692 --- /dev/null +++ b/libpod/network/types/network_test.go @@ -0,0 +1,82 @@ +package types_test + +import ( + "encoding/json" + "reflect" + "testing" + + "github.com/containers/podman/v3/libpod/network/types" +) + +func TestUnmarshalMacAddress(t *testing.T) { + tests := []struct { + name string + json string + want types.HardwareAddr + wantErr bool + }{ + { + name: "mac as string with colon", + json: `"52:54:00:1c:2e:46"`, + want: types.HardwareAddr{0x52, 0x54, 0x00, 0x1c, 0x2e, 0x46}, + }, + { + name: "mac as string with dash", + json: `"52-54-00-1c-2e-46"`, + want: types.HardwareAddr{0x52, 0x54, 0x00, 0x1c, 0x2e, 0x46}, + }, + { + name: "mac as byte array", + json: `[82, 84, 0, 28, 46, 70]`, + want: types.HardwareAddr{0x52, 0x54, 0x00, 0x1c, 0x2e, 0x46}, + }, + { + name: "null value", + json: `null`, + want: nil, + }, + { + name: "mac as base64", + json: `"qrvM3e7/"`, + want: types.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, + }, + { + name: "invalid string", + json: `"52:54:00:1c:2e`, + wantErr: true, + }, + { + name: "invalid array", + json: `[82, 84, 0, 28, 46`, + wantErr: true, + }, + + { + name: "invalid value", + json: `ab`, + wantErr: true, + }, + { + name: "invalid object", + json: `{}`, + wantErr: true, + }, + } + for _, tt := range tests { + test := tt + t.Run(test.name, func(t *testing.T) { + mac := types.HardwareAddr{} + err := json.Unmarshal([]byte(test.json), &mac) + if (err != nil) != test.wantErr { + t.Errorf("types.HardwareAddress Unmarshal() error = %v, wantErr %v", err, test.wantErr) + return + } + if test.wantErr { + return + } + if !reflect.DeepEqual(mac, test.want) { + t.Errorf("types.HardwareAddress Unmarshal() got = %v, want %v", mac, test.want) + } + }) + } +} diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index d0f56ce95..ef261a438 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -42,8 +42,11 @@ const ( // default slirp4ns subnet defaultSlirp4netnsSubnet = "10.0.2.0/24" - // rootlessCNINSName is the file name for the rootless network namespace bind mount - rootlessCNINSName = "rootless-cni-ns" + // rootlessNetNsName is the file name for the rootless network namespace bind mount + rootlessNetNsName = "rootless-netns" + + // rootlessNetNsSilrp4netnsPidFile is the name of the rootless netns slirp4netns pid file + rootlessNetNsSilrp4netnsPidFile = "rootless-netns-slirp4netns.pid" // persistentCNIDir is the directory where the CNI files are stored persistentCNIDir = "/var/lib/cni" @@ -134,21 +137,21 @@ func (c *Container) getNetworkOptions() (types.NetworkOptions, error) { return opts, nil } -type RootlessCNI struct { +type RootlessNetNS struct { ns ns.NetNS dir string Lock lockfile.Locker } -// getPath will join the given path to the rootless cni dir -func (r *RootlessCNI) getPath(path string) string { +// getPath will join the given path to the rootless netns dir +func (r *RootlessNetNS) getPath(path string) string { return filepath.Join(r.dir, path) } -// Do - run the given function in the rootless cni ns. +// Do - run the given function in the rootless netns. // It does not lock the rootlessCNI lock, the caller // should only lock when needed, e.g. for cni operations. -func (r *RootlessCNI) Do(toRun func() error) error { +func (r *RootlessNetNS) Do(toRun func() error) error { err := r.ns.Do(func(_ ns.NetNS) error { // Before we can run the given function, // we have to setup all mounts correctly. @@ -159,11 +162,11 @@ func (r *RootlessCNI) Do(toRun func() error) error { // Because the plugins also need access to XDG_RUNTIME_DIR/netns some special setup is needed. // The following bind mounts are needed - // 1. XDG_RUNTIME_DIR/netns -> XDG_RUNTIME_DIR/rootless-cni/XDG_RUNTIME_DIR/netns - // 2. /run/systemd -> XDG_RUNTIME_DIR/rootless-cni/run/systemd (only if it exists) - // 3. XDG_RUNTIME_DIR/rootless-cni/resolv.conf -> /etc/resolv.conf or XDG_RUNTIME_DIR/rootless-cni/run/symlink/target - // 4. XDG_RUNTIME_DIR/rootless-cni/var/lib/cni -> /var/lib/cni (if /var/lib/cni does not exists use the parent dir) - // 5. XDG_RUNTIME_DIR/rootless-cni/run -> /run + // 1. XDG_RUNTIME_DIR -> XDG_RUNTIME_DIR/rootless-netns/XDG_RUNTIME_DIR + // 2. /run/systemd -> XDG_RUNTIME_DIR/rootless-netns/run/systemd (only if it exists) + // 3. XDG_RUNTIME_DIR/rootless-netns/resolv.conf -> /etc/resolv.conf or XDG_RUNTIME_DIR/rootless-netns/run/symlink/target + // 4. XDG_RUNTIME_DIR/rootless-netns/var/lib/cni -> /var/lib/cni (if /var/lib/cni does not exists use the parent dir) + // 5. XDG_RUNTIME_DIR/rootless-netns/run -> /run // Create a new mount namespace, // this must happen inside the netns thread. @@ -172,16 +175,16 @@ func (r *RootlessCNI) Do(toRun func() error) error { return errors.Wrapf(err, "cannot create a new mount namespace") } - netNsDir, err := netns.GetNSRunDir() + xdgRuntimeDir, err := util.GetRuntimeDir() if err != nil { - return errors.Wrap(err, "could not get network namespace directory") + return errors.Wrap(err, "could not get runtime directory") } - newNetNsDir := r.getPath(netNsDir) + newXDGRuntimeDir := r.getPath(xdgRuntimeDir) // 1. Mount the netns into the new run to keep them accessible. // Otherwise cni setup will fail because it cannot access the netns files. - err = unix.Mount(netNsDir, newNetNsDir, "none", unix.MS_BIND|unix.MS_SHARED|unix.MS_REC, "") + err = unix.Mount(xdgRuntimeDir, newXDGRuntimeDir, "none", unix.MS_BIND|unix.MS_SHARED|unix.MS_REC, "") if err != nil { - return errors.Wrap(err, "failed to mount netns directory for rootless cni") + return errors.Wrap(err, "failed to mount runtime directory for rootless netns") } // 2. Also keep /run/systemd if it exists. @@ -192,7 +195,7 @@ func (r *RootlessCNI) Do(toRun func() error) error { newRunSystemd := r.getPath(runSystemd) err = unix.Mount(runSystemd, newRunSystemd, "none", unix.MS_BIND|unix.MS_REC, "") if err != nil { - return errors.Wrap(err, "failed to mount /run/systemd directory for rootless cni") + return errors.Wrap(err, "failed to mount /run/systemd directory for rootless netns") } } @@ -240,25 +243,25 @@ func (r *RootlessCNI) Do(toRun func() error) error { rsr := r.getPath("/run/systemd/resolve") err = unix.Mount("", rsr, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, "") if err != nil { - return errors.Wrapf(err, "failed to mount tmpfs on %q for rootless cni", rsr) + return errors.Wrapf(err, "failed to mount tmpfs on %q for rootless netns", rsr) } } if strings.HasPrefix(resolvePath, "/run/") { resolvePath = r.getPath(resolvePath) err = os.MkdirAll(filepath.Dir(resolvePath), 0700) if err != nil { - return errors.Wrap(err, "failed to create rootless-cni resolv.conf directory") + return errors.Wrap(err, "failed to create rootless-netns resolv.conf directory") } // we want to bind mount on this file so we have to create the file first _, err = os.OpenFile(resolvePath, os.O_CREATE|os.O_RDONLY, 0700) if err != nil { - return errors.Wrap(err, "failed to create rootless-cni resolv.conf file") + return errors.Wrap(err, "failed to create rootless-netns resolv.conf file") } } // mount resolv.conf to make use of the host dns err = unix.Mount(r.getPath("resolv.conf"), resolvePath, "none", unix.MS_BIND, "") if err != nil { - return errors.Wrap(err, "failed to mount resolv.conf for rootless cni") + return errors.Wrap(err, "failed to mount resolv.conf for rootless netns") } // 4. CNI plugins need access to /var/lib/cni and /run @@ -283,14 +286,14 @@ func (r *RootlessCNI) Do(toRun func() error) error { // make sure to mount var first err = unix.Mount(varDir, varTarget, "none", unix.MS_BIND, "") if err != nil { - return errors.Wrapf(err, "failed to mount %s for rootless cni", varTarget) + return errors.Wrapf(err, "failed to mount %s for rootless netns", varTarget) } // 5. Mount the new prepared run dir to /run, it has to be recursive to keep the other bind mounts. runDir := r.getPath("run") err = unix.Mount(runDir, "/run", "none", unix.MS_BIND|unix.MS_REC, "") if err != nil { - return errors.Wrap(err, "failed to mount /run for rootless cni") + return errors.Wrap(err, "failed to mount /run for rootless netns") } // run the given function in the correct namespace @@ -300,10 +303,11 @@ func (r *RootlessCNI) Do(toRun func() error) error { return err } -// Cleanup the rootless cni namespace if needed. +// Cleanup the rootless network namespace if needed. // It checks if we have running containers with the bridge network mode. -// Cleanup() will try to lock RootlessCNI, therefore you have to call it with an unlocked -func (r *RootlessCNI) Cleanup(runtime *Runtime) error { +// Cleanup() will try to lock RootlessNetNS, therefore you have to call +// it with an unlocked lock. +func (r *RootlessNetNS) Cleanup(runtime *Runtime) error { _, err := os.Stat(r.dir) if os.IsNotExist(err) { // the directory does not exists no need for cleanup @@ -312,8 +316,25 @@ func (r *RootlessCNI) Cleanup(runtime *Runtime) error { r.Lock.Lock() defer r.Lock.Unlock() running := func(c *Container) bool { + // no bridge => no need to check + if !c.config.NetMode.IsBridge() { + return false + } + // we cannot use c.state() because it will try to lock the container - // using c.state.State directly should be good enough for this use case + // locking is a problem because cleanup is called after net teardown + // at this stage the container is already locked. + // also do not try to lock only containers which are not currently in net + // teardown because this will result in an ABBA deadlock between the rootless + // cni lock and the container lock + // because we need to get the state we have to sync otherwise this will not + // work because the state is empty by default + // I do not like this but I do not see a better way at moment + err := c.syncContainer() + if err != nil { + return false + } + state := c.state.State return state == define.ContainerStateRunning } @@ -321,101 +342,89 @@ func (r *RootlessCNI) Cleanup(runtime *Runtime) error { if err != nil { return err } - cleanup := true - for _, ctr := range ctrs { - if ctr.config.NetMode.IsBridge() { - cleanup = false - } + // no cleanup if we found containers + if len(ctrs) > 0 { + return nil } - if cleanup { - // make sure the the cni results (cache) dir is empty - // libpod instances with another root dir are not covered by the check above - // this allows several libpod instances to use the same rootless cni ns - contents, err := ioutil.ReadDir(r.getPath("var/lib/cni/results")) - if (err == nil && len(contents) == 0) || os.IsNotExist(err) { - logrus.Debug("Cleaning up rootless cni namespace") - err = netns.UnmountNS(r.ns) - if err != nil { - return err - } - // make the following errors not fatal - err = r.ns.Close() - if err != nil { - logrus.Error(err) - } - b, err := ioutil.ReadFile(r.getPath("rootless-cni-slirp4netns.pid")) - if err == nil { - var i int - i, err = strconv.Atoi(string(b)) - if err == nil { - // kill the slirp process so we do not leak it - err = syscall.Kill(i, syscall.SIGTERM) - } - } - if err != nil { - logrus.Errorf("Failed to kill slirp4netns process: %s", err) - } - err = os.RemoveAll(r.dir) - if err != nil { - logrus.Error(err) - } - } else if err != nil && !os.IsNotExist(err) { - logrus.Errorf("Could not read rootless cni directory, skipping cleanup: %s", err) + logrus.Debug("Cleaning up rootless network namespace") + err = netns.UnmountNS(r.ns) + if err != nil { + return err + } + // make the following errors not fatal + err = r.ns.Close() + if err != nil { + logrus.Error(err) + } + b, err := ioutil.ReadFile(r.getPath(rootlessNetNsSilrp4netnsPidFile)) + if err == nil { + var i int + i, err = strconv.Atoi(string(b)) + if err == nil { + // kill the slirp process so we do not leak it + err = syscall.Kill(i, syscall.SIGTERM) } } + if err != nil { + logrus.Errorf("Failed to kill slirp4netns process: %s", err) + } + err = os.RemoveAll(r.dir) + if err != nil { + logrus.Error(err) + } return nil } -// GetRootlessCNINetNs returns the rootless cni object. If create is set to true -// the rootless cni namespace will be created if it does not exists already. +// GetRootlessNetNs returns the rootless netns object. If create is set to true +// the rootless network namespace will be created if it does not exists already. // If called as root it returns always nil. // On success the returned RootlessCNI lock is locked and must be unlocked by the caller. -func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) { +func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { if !rootless.IsRootless() { return nil, nil } - var rootlessCNINS *RootlessCNI + var rootlessNetNS *RootlessNetNS runDir, err := util.GetRuntimeDir() if err != nil { return nil, err } - lfile := filepath.Join(runDir, "rootless-cni.lock") + lfile := filepath.Join(runDir, "rootless-netns.lock") lock, err := lockfile.GetLockfile(lfile) if err != nil { - return nil, errors.Wrap(err, "failed to get rootless-cni lockfile") + return nil, errors.Wrap(err, "failed to get rootless-netns lockfile") } lock.Lock() defer func() { - // In case of an error (early exit) rootlessCNINS will be nil. + // In case of an error (early exit) rootlessNetNS will be nil. // Make sure to unlock otherwise we could deadlock. - if rootlessCNINS == nil { + if rootlessNetNS == nil { lock.Unlock() } }() - cniDir := filepath.Join(runDir, "rootless-cni") - err = os.MkdirAll(cniDir, 0700) + rootlessNetNsDir := filepath.Join(runDir, rootlessNetNsName) + err = os.MkdirAll(rootlessNetNsDir, 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-cni directory") + return nil, errors.Wrap(err, "could not create rootless-netns directory") } nsDir, err := netns.GetNSRunDir() if err != nil { return nil, err } - path := filepath.Join(nsDir, rootlessCNINSName) + path := filepath.Join(nsDir, rootlessNetNsName) ns, err := ns.GetNS(path) if err != nil { if !new { // return a error if we could not get the namespace and should no create one - return nil, errors.Wrap(err, "error getting rootless cni network namespace") + return nil, errors.Wrap(err, "error getting rootless network namespace") } // create a new namespace - logrus.Debug("creating rootless cni network namespace") - ns, err = netns.NewNSWithName(rootlessCNINSName) + logrus.Debug("creating rootless network namespace") + ns, err = netns.NewNSWithName(rootlessNetNsName) if err != nil { - return nil, errors.Wrap(err, "error creating rootless cni network namespace") + return nil, errors.Wrap(err, "error creating rootless network namespace") } // setup slirp4netns here path := r.config.Engine.NetworkCmdPath @@ -465,7 +474,7 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) { // Leak one end of the pipe in slirp4netns cmd.ExtraFiles = append(cmd.ExtraFiles, syncW) - logPath := filepath.Join(r.config.Engine.TmpDir, "slirp4netns-rootless-cni.log") + logPath := filepath.Join(r.config.Engine.TmpDir, "slirp4netns-rootless-netns.log") logFile, err := os.Create(logPath) if err != nil { return nil, errors.Wrapf(err, "failed to open slirp4netns log file %s", logPath) @@ -484,9 +493,9 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) { // create pid file for the slirp4netns process // this is need to kill the process in the cleanup pid := strconv.Itoa(cmd.Process.Pid) - err = ioutil.WriteFile(filepath.Join(cniDir, "rootless-cni-slirp4netns.pid"), []byte(pid), 0700) + err = ioutil.WriteFile(filepath.Join(rootlessNetNsDir, rootlessNetNsSilrp4netnsPidFile), []byte(pid), 0700) if err != nil { - errors.Wrap(err, "unable to write rootless-cni slirp4netns pid file") + errors.Wrap(err, "unable to write rootless-netns slirp4netns pid file") } defer func() { @@ -527,43 +536,43 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) { dnsOptions := resolvconf.GetOptions(conf.Content) nameServers := resolvconf.GetNameservers(conf.Content) - _, err = resolvconf.Build(filepath.Join(cniDir, "resolv.conf"), append([]string{resolveIP.String()}, nameServers...), searchDomains, dnsOptions) + _, err = resolvconf.Build(filepath.Join(rootlessNetNsDir, "resolv.conf"), append([]string{resolveIP.String()}, nameServers...), searchDomains, dnsOptions) if err != nil { - return nil, errors.Wrap(err, "failed to create rootless cni resolv.conf") + return nil, errors.Wrap(err, "failed to create rootless netns resolv.conf") } // create cni directories to store files // they will be bind mounted to the correct location in a extra mount ns - err = os.MkdirAll(filepath.Join(cniDir, strings.TrimPrefix(persistentCNIDir, "/")), 0700) + err = os.MkdirAll(filepath.Join(rootlessNetNsDir, persistentCNIDir), 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-cni var directory") + return nil, errors.Wrap(err, "could not create rootless-netns var directory") } - runDir := filepath.Join(cniDir, "run") + runDir := filepath.Join(rootlessNetNsDir, "run") err = os.MkdirAll(runDir, 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-cni run directory") + return nil, errors.Wrap(err, "could not create rootless-netns run directory") } // relabel the new run directory to the iptables /run label // this is important, otherwise the iptables command will fail err = label.Relabel(runDir, "system_u:object_r:iptables_var_run_t:s0", false) if err != nil { - return nil, errors.Wrap(err, "could not create relabel rootless-cni run directory") + return nil, errors.Wrap(err, "could not create relabel rootless-netns run directory") } // create systemd run directory err = os.MkdirAll(filepath.Join(runDir, "systemd"), 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-cni systemd directory") + return nil, errors.Wrap(err, "could not create rootless-netns systemd directory") } // create the directory for the netns files at the same location - // relative to the rootless-cni location - err = os.MkdirAll(filepath.Join(cniDir, nsDir), 0700) + // relative to the rootless-netns location + err = os.MkdirAll(filepath.Join(rootlessNetNsDir, nsDir), 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-cni netns directory") + return nil, errors.Wrap(err, "could not create rootless-netns netns directory") } } - // The CNI plugins need access to iptables in $PATH. As it turns out debian doesn't put - // /usr/sbin in $PATH for rootless users. This will break rootless cni completely. + // The CNI plugins and netavark need access to iptables in $PATH. As it turns out debian doesn't put + // /usr/sbin in $PATH for rootless users. This will break rootless networking completely. // We might break existing users and we cannot expect everyone to change their $PATH so // lets add /usr/sbin to $PATH ourselves. path = os.Getenv("PATH") @@ -572,14 +581,14 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) { os.Setenv("PATH", path) } - // Important set rootlessCNINS as last step. + // Important set rootlessNetNS as last step. // Do not return any errors after this. - rootlessCNINS = &RootlessCNI{ + rootlessNetNS = &RootlessNetNS{ ns: ns, - dir: cniDir, + dir: rootlessNetNsDir, Lock: lock, } - return rootlessCNINS, nil + return rootlessNetNS, nil } // setPrimaryMachineIP is used for podman-machine and it sets @@ -601,14 +610,14 @@ func setPrimaryMachineIP() error { } // setUpNetwork will set up the the networks, on error it will also tear down the cni -// networks. If rootless it will join/create the rootless cni namespace. +// networks. If rootless it will join/create the rootless network namespace. func (r *Runtime) setUpNetwork(ns string, opts types.NetworkOptions) (map[string]types.StatusBlock, error) { if r.config.MachineEnabled() { if err := setPrimaryMachineIP(); err != nil { return nil, err } } - rootlessCNINS, err := r.GetRootlessCNINetNs(true) + rootlessNetNS, err := r.GetRootlessNetNs(true) if err != nil { return nil, err } @@ -617,11 +626,11 @@ func (r *Runtime) setUpNetwork(ns string, opts types.NetworkOptions) (map[string results, err = r.network.Setup(ns, types.SetupOptions{NetworkOptions: opts}) return err } - // rootlessCNINS is nil if we are root - if rootlessCNINS != nil { - // execute the cni setup in the rootless net ns - err = rootlessCNINS.Do(setUpPod) - rootlessCNINS.Lock.Unlock() + // rootlessNetNS is nil if we are root + if rootlessNetNS != nil { + // execute the setup in the rootless net ns + err = rootlessNetNS.Do(setUpPod) + rootlessNetNS.Lock.Unlock() } else { err = setUpPod() } @@ -695,10 +704,10 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error { return err } if len(networks) > 0 && len(ctr.config.PortMappings) > 0 { - // set up port forwarder for CNI-in-slirp4netns + // set up port forwarder for rootless netns netnsPath := ctr.state.NetNS.Path() // TODO: support slirp4netns port forwarder as well - // make sure to fix this container.handleRestartPolicy() as well + // make sure to fix this in container.handleRestartPolicy() as well return r.setupRootlessPortMappingViaRLK(ctr, netnsPath) } return nil @@ -717,7 +726,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error { if err != nil { return err } - nsPath = filepath.Join(nsPath, fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])) + nsPath = filepath.Join(nsPath, fmt.Sprintf("netns-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])) if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil { return err @@ -775,10 +784,10 @@ func (r *Runtime) closeNetNS(ctr *Container) error { return nil } -// Tear down a container's CNI network configuration and joins the +// Tear down a container's network configuration and joins the // rootless net ns as rootless user func (r *Runtime) teardownNetwork(ns string, opts types.NetworkOptions) error { - rootlessCNINS, err := r.GetRootlessCNINetNs(false) + rootlessNetNS, err := r.GetRootlessNetNs(false) if err != nil { return err } @@ -787,13 +796,13 @@ func (r *Runtime) teardownNetwork(ns string, opts types.NetworkOptions) error { return errors.Wrapf(err, "error tearing down network namespace configuration for container %s", opts.ContainerID) } - // rootlessCNINS is nil if we are root - if rootlessCNINS != nil { + // rootlessNetNS is nil if we are root + if rootlessNetNS != nil { // execute the cni setup in the rootless net ns - err = rootlessCNINS.Do(tearDownPod) - rootlessCNINS.Lock.Unlock() + err = rootlessNetNS.Do(tearDownPod) + rootlessNetNS.Lock.Unlock() if err == nil { - err = rootlessCNINS.Cleanup(r) + err = rootlessNetNS.Cleanup(r) } } else { err = tearDownPod() diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 1719b2dfa..db906fabb 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -1016,7 +1016,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co } if ctr.config.CgroupsMode == cgroupSplit { - if err := utils.MoveUnderCgroupSubtree("supervisor"); err != nil { + if err := utils.MoveUnderCgroupSubtree("runtime"); err != nil { return err } } diff --git a/libpod/options.go b/libpod/options.go index 59795432f..250b16556 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1104,7 +1104,7 @@ func WithNetworkOptions(options map[string][]string) CtrCreateOption { // 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 { +func WithStaticMAC(mac nettypes.HardwareAddr) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { return define.ErrCtrFinalized diff --git a/libpod/runtime.go b/libpod/runtime.go index 950ac65eb..b01f8dd13 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -545,9 +545,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { if became { // Check if the pause process was created. If it was created, then // move it to its own systemd scope. - if _, err = os.Stat(pausePid); err == nil { - utils.MovePauseProcessToScope(pausePid) - } + utils.MovePauseProcessToScope(pausePid) os.Exit(ret) } } |