mirror of
https://github.com/containers/podman.git
synced 2025-06-20 00:51:16 +08:00
Merge pull request #15632 from dfr/freebsd-container
Add support for FreeBSD containers
This commit is contained in:
@ -1133,20 +1133,6 @@ func (c *Container) NetworkDisabled() (bool, error) {
|
|||||||
return networkDisabled(c)
|
return networkDisabled(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func networkDisabled(c *Container) (bool, error) {
|
|
||||||
if c.config.CreateNetNS {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
if !c.config.PostConfigureNetNS {
|
|
||||||
for _, ns := range c.config.Spec.Linux.Namespaces {
|
|
||||||
if ns.Type == spec.NetworkNamespace {
|
|
||||||
return ns.Path == "", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) HostNetwork() bool {
|
func (c *Container) HostNetwork() bool {
|
||||||
if c.config.CreateNetNS || c.config.NetNsCtr != "" {
|
if c.config.CreateNetNS || c.config.NetNsCtr != "" {
|
||||||
return false
|
return false
|
||||||
|
@ -10,3 +10,13 @@ type containerPlatformState struct {
|
|||||||
// namespace.
|
// namespace.
|
||||||
NetworkJail string `json:"-"`
|
NetworkJail string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func networkDisabled(c *Container) (bool, error) {
|
||||||
|
if c.config.CreateNetNS {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if !c.config.PostConfigureNetNS {
|
||||||
|
return c.state.NetworkJail == "", nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
2699
libpod/container_internal_common.go
Normal file
2699
libpod/container_internal_common.go
Normal file
File diff suppressed because it is too large
Load Diff
285
libpod/container_internal_freebsd.go
Normal file
285
libpod/container_internal_freebsd.go
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
//go:build freebsd
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
package libpod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/common/libnetwork/types"
|
||||||
|
"github.com/containers/podman/v4/pkg/rootless"
|
||||||
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
bindOptions = []string{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Network stubs to decouple container_internal_freebsd.go from
|
||||||
|
// networking_freebsd.go so they can be reviewed separately.
|
||||||
|
func (r *Runtime) createNetNS(ctr *Container) (netJail string, q map[string]types.StatusBlock, retErr error) {
|
||||||
|
return "", nil, errors.New("not implemented (*Runtime) createNetNS")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) teardownNetNS(ctr *Container) error {
|
||||||
|
return errors.New("not implemented (*Runtime) teardownNetNS")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.StatusBlock, error) {
|
||||||
|
return nil, errors.New("not implemented (*Runtime) reloadContainerNetwork")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) mountSHM(shmOptions string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) unmountSHM(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare mounts the container and sets up other required resources like net
|
||||||
|
// namespaces
|
||||||
|
func (c *Container) prepare() error {
|
||||||
|
var (
|
||||||
|
wg sync.WaitGroup
|
||||||
|
jailName string
|
||||||
|
networkStatus map[string]types.StatusBlock
|
||||||
|
createNetNSErr, mountStorageErr error
|
||||||
|
mountPoint string
|
||||||
|
tmpStateLock sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
wg.Add(2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
// Set up network namespace if not already set up
|
||||||
|
noNetNS := c.state.NetworkJail == ""
|
||||||
|
if c.config.CreateNetNS && noNetNS && !c.config.PostConfigureNetNS {
|
||||||
|
jailName, networkStatus, createNetNSErr = c.runtime.createNetNS(c)
|
||||||
|
if createNetNSErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpStateLock.Lock()
|
||||||
|
defer tmpStateLock.Unlock()
|
||||||
|
|
||||||
|
// Assign NetNS attributes to container
|
||||||
|
c.state.NetworkJail = jailName
|
||||||
|
c.state.NetworkStatus = networkStatus
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// Mount storage if not mounted
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
mountPoint, mountStorageErr = c.mountStorage()
|
||||||
|
|
||||||
|
if mountStorageErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpStateLock.Lock()
|
||||||
|
defer tmpStateLock.Unlock()
|
||||||
|
|
||||||
|
// Finish up mountStorage
|
||||||
|
c.state.Mounted = true
|
||||||
|
c.state.Mountpoint = mountPoint
|
||||||
|
|
||||||
|
logrus.Debugf("Created root filesystem for container %s at %s", c.ID(), c.state.Mountpoint)
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
var createErr error
|
||||||
|
if mountStorageErr != nil {
|
||||||
|
if createErr != nil {
|
||||||
|
logrus.Errorf("Preparing container %s: %v", c.ID(), createErr)
|
||||||
|
}
|
||||||
|
createErr = mountStorageErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if createErr != nil {
|
||||||
|
return createErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save changes to container state
|
||||||
|
if err := c.save(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanupNetwork unmounts and cleans up the container's network
|
||||||
|
func (c *Container) cleanupNetwork() error {
|
||||||
|
if c.config.NetNsCtr != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
netDisabled, err := c.NetworkDisabled()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if netDisabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the container's network namespace (if it has one)
|
||||||
|
if err := c.runtime.teardownNetNS(c); err != nil {
|
||||||
|
logrus.Errorf("Unable to cleanup network for container %s: %q", c.ID(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.valid {
|
||||||
|
return c.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// reloadNetwork reloads the network for the given container, recreating
|
||||||
|
// firewall rules.
|
||||||
|
func (c *Container) reloadNetwork() error {
|
||||||
|
result, err := c.runtime.reloadContainerNetwork(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.state.NetworkStatus = result
|
||||||
|
|
||||||
|
return c.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an existing container's network jail
|
||||||
|
func (c *Container) addNetworkContainer(g *generate.Generator, ctr string) error {
|
||||||
|
nsCtr, err := c.runtime.state.Container(ctr)
|
||||||
|
c.runtime.state.UpdateContainer(nsCtr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error retrieving dependency %s of container %s from state: %w", ctr, c.ID(), err)
|
||||||
|
}
|
||||||
|
g.AddAnnotation("org.freebsd.parentJail", nsCtr.state.NetworkJail)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRootlessCgroupSet(cgroup string) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) expectPodCgroup() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) getOCICgroupPath() (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func openDirectory(path string) (fd int, err error) {
|
||||||
|
const O_PATH = 0x00400000
|
||||||
|
return unix.Open(path, unix.O_RDONLY|O_PATH, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) addNetworkNamespace(g *generate.Generator) error {
|
||||||
|
if c.config.CreateNetNS {
|
||||||
|
g.AddAnnotation("org.freebsd.parentJail", c.state.NetworkJail)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) addSystemdMounts(g *generate.Generator) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) addSharedNamespaces(g *generate.Generator) error {
|
||||||
|
if c.config.NetNsCtr != "" {
|
||||||
|
if err := c.addNetworkContainer(g, c.config.NetNsCtr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps()
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// The kernel-provided files only exist if user namespaces are supported
|
||||||
|
logrus.Debugf("User or group ID mappings not available: %s", err)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs)
|
||||||
|
g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hostname handling:
|
||||||
|
// If we have a UTS namespace, set Hostname in the OCI spec.
|
||||||
|
// Set the HOSTNAME environment variable unless explicitly overridden by
|
||||||
|
// the user (already present in OCI spec). If we don't have a UTS ns,
|
||||||
|
// set it to the host's hostname instead.
|
||||||
|
hostname := c.Hostname()
|
||||||
|
foundUTS := false
|
||||||
|
|
||||||
|
// TODO: make this optional, needs progress on adding FreeBSD section to the spec
|
||||||
|
foundUTS = true
|
||||||
|
g.SetHostname(hostname)
|
||||||
|
|
||||||
|
if !foundUTS {
|
||||||
|
tmpHostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hostname = tmpHostname
|
||||||
|
}
|
||||||
|
needEnv := true
|
||||||
|
for _, checkEnv := range g.Config.Process.Env {
|
||||||
|
if strings.SplitN(checkEnv, "=", 2)[0] == "HOSTNAME" {
|
||||||
|
needEnv = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if needEnv {
|
||||||
|
g.AddProcessEnv("HOSTNAME", hostname)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) addRootPropagation(g *generate.Generator, mounts []spec.Mount) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) setProcessLabel(g *generate.Generator) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) setMountLabel(g *generate.Generator) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) setCgroupsPath(g *generate.Generator) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) addSlirp4netnsDNS(nameservers []string) []string {
|
||||||
|
return nameservers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) isSlirp4netnsIPv6() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for net=none
|
||||||
|
func (c *Container) hasNetNone() bool {
|
||||||
|
return c.state.NetworkJail == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func setVolumeAtime(mountPoint string, st os.FileInfo) error {
|
||||||
|
stat := st.Sys().(*syscall.Stat_t)
|
||||||
|
atime := time.Unix(int64(stat.Atimespec.Sec), int64(stat.Atimespec.Nsec)) //nolint: unconvert
|
||||||
|
if err := os.Chtimes(mountPoint, atime, st.ModTime()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
//go:build !linux
|
//go:build !linux && !freebsd
|
||||||
// +build !linux
|
// +build !linux,!freebsd
|
||||||
|
|
||||||
package libpod
|
package libpod
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ package libpod
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
type containerPlatformState struct {
|
type containerPlatformState struct {
|
||||||
@ -13,3 +14,17 @@ type containerPlatformState struct {
|
|||||||
// told to join another container's network namespace
|
// told to join another container's network namespace
|
||||||
NetNS ns.NetNS `json:"-"`
|
NetNS ns.NetNS `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func networkDisabled(c *Container) (bool, error) {
|
||||||
|
if c.config.CreateNetNS {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if !c.config.PostConfigureNetNS {
|
||||||
|
for _, ns := range c.config.Spec.Linux.Namespaces {
|
||||||
|
if ns.Type == spec.NetworkNamespace {
|
||||||
|
return ns.Path == "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ package libpod
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"net"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/containers/common/libnetwork/types"
|
"github.com/containers/common/libnetwork/types"
|
||||||
@ -84,3 +85,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
|
|||||||
func (c *Container) convertPortMappings() []types.PortMapping {
|
func (c *Container) convertPortMappings() []types.PortMapping {
|
||||||
return []types.PortMapping{}
|
return []types.PortMapping{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSlirp4netnsIP(subnet *net.IPNet) (*net.IP, error) {
|
||||||
|
return nil, errors.New("not implemented GetSlirp4netnsIP")
|
||||||
|
}
|
||||||
|
@ -171,12 +171,17 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf
|
|||||||
if config == nil {
|
if config == nil {
|
||||||
ctr.config.ID = stringid.GenerateNonCryptoID()
|
ctr.config.ID = stringid.GenerateNonCryptoID()
|
||||||
size, err := units.FromHumanSize(r.config.Containers.ShmSize)
|
size, err := units.FromHumanSize(r.config.Containers.ShmSize)
|
||||||
if err != nil {
|
if useDevShm {
|
||||||
return nil, fmt.Errorf("converting containers.conf ShmSize %s to an int: %w", r.config.Containers.ShmSize, err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("converting containers.conf ShmSize %s to an int: %w", r.config.Containers.ShmSize, err)
|
||||||
|
}
|
||||||
|
ctr.config.ShmSize = size
|
||||||
|
ctr.config.NoShm = false
|
||||||
|
ctr.config.NoShmShare = false
|
||||||
|
} else {
|
||||||
|
ctr.config.NoShm = true
|
||||||
|
ctr.config.NoShmShare = true
|
||||||
}
|
}
|
||||||
ctr.config.ShmSize = size
|
|
||||||
ctr.config.NoShm = false
|
|
||||||
ctr.config.NoShmShare = false
|
|
||||||
ctr.config.StopSignal = 15
|
ctr.config.StopSignal = 15
|
||||||
|
|
||||||
ctr.config.StopTimeout = r.config.Engine.StopTimeout
|
ctr.config.StopTimeout = r.config.Engine.StopTimeout
|
||||||
@ -528,7 +533,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !MountExists(ctr.config.Spec.Mounts, "/dev/shm") && ctr.config.ShmDir == "" && !ctr.config.NoShm {
|
if useDevShm && !MountExists(ctr.config.Spec.Mounts, "/dev/shm") && ctr.config.ShmDir == "" && !ctr.config.NoShm {
|
||||||
ctr.config.ShmDir = filepath.Join(ctr.bundlePath(), "shm")
|
ctr.config.ShmDir = filepath.Join(ctr.bundlePath(), "shm")
|
||||||
if err := os.MkdirAll(ctr.config.ShmDir, 0700); err != nil {
|
if err := os.MkdirAll(ctr.config.ShmDir, 0700); err != nil {
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
|
5
libpod/runtime_ctr_freebsd.go
Normal file
5
libpod/runtime_ctr_freebsd.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package libpod
|
||||||
|
|
||||||
|
const (
|
||||||
|
useDevShm = false
|
||||||
|
)
|
5
libpod/runtime_ctr_linux.go
Normal file
5
libpod/runtime_ctr_linux.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package libpod
|
||||||
|
|
||||||
|
const (
|
||||||
|
useDevShm = true
|
||||||
|
)
|
@ -5,8 +5,14 @@ package util
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetContainerPidInformationDescriptors() ([]string, error) {
|
func GetContainerPidInformationDescriptors() ([]string, error) {
|
||||||
return []string{}, errors.New("this function is not supported on freebsd")
|
return []string{}, errors.New("this function is not supported on freebsd")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddPrivilegedDevices(g *generate.Generator) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user