diff options
Diffstat (limited to 'cmd/podman/spec.go')
-rw-r--r-- | cmd/podman/spec.go | 211 |
1 files changed, 143 insertions, 68 deletions
diff --git a/cmd/podman/spec.go b/cmd/podman/spec.go index d630b2f50..cb9efdcb2 100644 --- a/cmd/podman/spec.go +++ b/cmd/podman/spec.go @@ -1,14 +1,14 @@ package main import ( - "encoding/json" - "fmt" "io/ioutil" + "strconv" "strings" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/docker/daemon/caps" "github.com/docker/docker/pkg/mount" + "github.com/docker/docker/profiles/seccomp" "github.com/docker/go-units" "github.com/opencontainers/runc/libcontainer/devices" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -21,6 +21,8 @@ import ( "golang.org/x/sys/unix" ) +const cpuPeriod = 100000 + func blockAccessToKernelFilesystems(config *createConfig, g *generate.Generator) { if !config.Privileged { for _, mp := range []string{ @@ -51,21 +53,10 @@ func blockAccessToKernelFilesystems(config *createConfig, g *generate.Generator) func addPidNS(config *createConfig, g *generate.Generator) error { pidMode := config.PidMode if pidMode.IsHost() { - return g.RemoveLinuxNamespace(libpod.PIDNamespace) + return g.RemoveLinuxNamespace(string(spec.PIDNamespace)) } if pidMode.IsContainer() { - ctr, err := config.Runtime.LookupContainer(pidMode.Container()) - if err != nil { - return errors.Wrapf(err, "container %q not found", pidMode.Container()) - } - pid, err := ctr.PID() - if err != nil { - return errors.Wrapf(err, "Failed to get pid of container %q", pidMode.Container()) - } - pidNsPath := fmt.Sprintf("/proc/%d/ns/pid", pid) - if err := g.AddOrReplaceLinuxNamespace(libpod.PIDNamespace, pidNsPath); err != nil { - return err - } + logrus.Debug("using container pidmode") } return nil } @@ -74,7 +65,7 @@ func addNetNS(config *createConfig, g *generate.Generator) error { netMode := config.NetMode if netMode.IsHost() { logrus.Debug("Using host netmode") - return g.RemoveLinuxNamespace(libpod.NetNamespace) + return g.RemoveLinuxNamespace(spec.NetworkNamespace) } else if netMode.IsNone() { logrus.Debug("Using none netmode") return nil @@ -83,18 +74,6 @@ func addNetNS(config *createConfig, g *generate.Generator) error { return nil } else if netMode.IsContainer() { logrus.Debug("Using container netmode") - ctr, err := config.Runtime.LookupContainer(netMode.ConnectedContainer()) - if err != nil { - return errors.Wrapf(err, "container %q not found", netMode.ConnectedContainer()) - } - pid, err := ctr.PID() - if err != nil { - return errors.Wrapf(err, "Failed to get pid of container %q", netMode.ConnectedContainer()) - } - nsPath := fmt.Sprintf("/proc/%d/ns/net", pid) - if err := g.AddOrReplaceLinuxNamespace(libpod.NetNamespace, nsPath); err != nil { - return err - } } else { return errors.Errorf("unknown network mode") } @@ -104,7 +83,7 @@ func addNetNS(config *createConfig, g *generate.Generator) error { func addUTSNS(config *createConfig, g *generate.Generator) error { utsMode := config.UtsMode if utsMode.IsHost() { - return g.RemoveLinuxNamespace(libpod.UTSNamespace) + return g.RemoveLinuxNamespace(spec.UTSNamespace) } return nil } @@ -112,21 +91,10 @@ func addUTSNS(config *createConfig, g *generate.Generator) error { func addIpcNS(config *createConfig, g *generate.Generator) error { ipcMode := config.IpcMode if ipcMode.IsHost() { - return g.RemoveLinuxNamespace(libpod.IPCNamespace) + return g.RemoveLinuxNamespace(spec.IPCNamespace) } if ipcMode.IsContainer() { - ctr, err := config.Runtime.LookupContainer(ipcMode.Container()) - if err != nil { - return errors.Wrapf(err, "container %q not found", ipcMode.Container()) - } - pid, err := ctr.PID() - if err != nil { - return errors.Wrapf(err, "Failed to get pid of container %q", ipcMode.Container()) - } - nsPath := fmt.Sprintf("/proc/%d/ns/ipc", pid) - if err := g.AddOrReplaceLinuxNamespace(libpod.IPCNamespace, nsPath); err != nil { - return err - } + logrus.Debug("Using container ipcmode") } return nil @@ -143,7 +111,7 @@ func addRlimits(config *createConfig, g *generate.Generator) error { return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u) } - g.AddProcessRlimits("RLIMIT_"+strings.ToUpper(ul.Name), uint64(ul.Soft), uint64(ul.Hard)) + g.AddProcessRlimits("RLIMIT_"+strings.ToUpper(ul.Name), uint64(ul.Hard), uint64(ul.Soft)) } return nil } @@ -210,10 +178,8 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { if config.Hostname != "" { g.AddProcessEnv("HOSTNAME", config.Hostname) } - - for _, sysctl := range config.Sysctl { - s := strings.SplitN(sysctl, "=", 2) - g.AddLinuxSysctl(s[0], s[1]) + for sysctlKey, sysctlVal := range config.Sysctl { + g.AddLinuxSysctl(sysctlKey, sysctlVal) } // RESOURCES - MEMORY @@ -236,7 +202,6 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { g.SetProcessOOMScoreAdj(config.Resources.OomScoreAdj) // RESOURCES - CPU - if config.Resources.CPUShares != 0 { g.SetLinuxResourcesCPUShares(config.Resources.CPUShares) } @@ -246,14 +211,18 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { if config.Resources.CPUPeriod != 0 { g.SetLinuxResourcesCPUPeriod(config.Resources.CPUPeriod) } + if config.Resources.CPUs != 0 { + g.SetLinuxResourcesCPUPeriod(cpuPeriod) + g.SetLinuxResourcesCPUQuota(int64(config.Resources.CPUs * cpuPeriod)) + } if config.Resources.CPURtRuntime != 0 { g.SetLinuxResourcesCPURealtimeRuntime(config.Resources.CPURtRuntime) } if config.Resources.CPURtPeriod != 0 { g.SetLinuxResourcesCPURealtimePeriod(config.Resources.CPURtPeriod) } - if config.Resources.CPUs != "" { - g.SetLinuxResourcesCPUCpus(config.Resources.CPUs) + if config.Resources.CPUsetCPUs != "" { + g.SetLinuxResourcesCPUCpus(config.Resources.CPUsetCPUs) } if config.Resources.CPUsetMems != "" { g.SetLinuxResourcesCPUMems(config.Resources.CPUsetMems) @@ -322,16 +291,31 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { } configSpec := g.Spec() - if config.SeccompProfilePath != "" && config.SeccompProfilePath != "unconfined" { - seccompProfile, err := ioutil.ReadFile(config.SeccompProfilePath) - if err != nil { - return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.SeccompProfilePath) - } - var seccompConfig spec.LinuxSeccomp - if err := json.Unmarshal(seccompProfile, &seccompConfig); err != nil { - return nil, errors.Wrapf(err, "decoding seccomp profile (%s) failed", config.SeccompProfilePath) + // HANDLE CAPABILITIES + // NOTE: Must happen before SECCOMP + if err := setupCapabilities(config, configSpec); err != nil { + return nil, err + } + + // HANDLE SECCOMP + if config.SeccompProfilePath != "unconfined" { + if config.SeccompProfilePath != "" { + seccompProfile, err := ioutil.ReadFile(config.SeccompProfilePath) + if err != nil { + return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.SeccompProfilePath) + } + seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), configSpec) + if err != nil { + return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath) + } + configSpec.Linux.Seccomp = seccompConfig + } else { + seccompConfig, err := seccomp.GetDefaultProfile(configSpec) + if err != nil { + return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath) + } + configSpec.Linux.Seccomp = seccompConfig } - configSpec.Linux.Seccomp = &seccompConfig } // BIND MOUNTS @@ -351,9 +335,13 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { } } - // HANDLE CAPABILITIES - if err := setupCapabilities(config, configSpec); err != nil { - return nil, err + // BLOCK IO + blkio, err := config.CreateBlockIO() + if err != nil { + return nil, errors.Wrapf(err, "error creating block io") + } + if blkio != nil { + configSpec.Linux.Resources.BlockIO = blkio } /* @@ -383,8 +371,8 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { return configSpec, nil } -func (c *createConfig) CreateBlockIO() (spec.LinuxBlockIO, error) { - bio := spec.LinuxBlockIO{} +func (c *createConfig) CreateBlockIO() (*spec.LinuxBlockIO, error) { + bio := &spec.LinuxBlockIO{} bio.Weight = &c.Resources.BlkioWeight if len(c.Resources.BlkioWeightDevice) > 0 { var lwds []spec.LinuxWeightDevice @@ -401,6 +389,7 @@ func (c *createConfig) CreateBlockIO() (spec.LinuxBlockIO, error) { lwd.Minor = int64(unix.Minor(wdStat.Rdev)) lwds = append(lwds, lwd) } + bio.WeightDevice = lwds } if len(c.Resources.DeviceReadBps) > 0 { readBps, err := makeThrottleArray(c.Resources.DeviceReadBps) @@ -430,7 +419,6 @@ func (c *createConfig) CreateBlockIO() (spec.LinuxBlockIO, error) { } bio.ThrottleWriteIOPSDevice = writeIOps } - return bio, nil } @@ -556,6 +544,8 @@ func (c *createConfig) GetTmpfsMounts() []spec.Mount { func (c *createConfig) GetContainerCreateOptions() ([]libpod.CtrCreateOption, error) { var options []libpod.CtrCreateOption + var portBindings []ocicni.PortMapping + var err error // Uncomment after talking to mheon about unimplemented funcs // options = append(options, libpod.WithLabels(c.labels)) @@ -567,12 +557,57 @@ func (c *createConfig) GetContainerCreateOptions() ([]libpod.CtrCreateOption, er logrus.Debugf("appending name %s", c.Name) options = append(options, libpod.WithName(c.Name)) } - // TODO parse ports into libpod format and include - if !c.NetMode.IsHost() { - options = append(options, libpod.WithNetNS([]ocicni.PortMapping{})) + + // TODO deal with ports defined in image metadata + if len(c.PortBindings) > 0 || len(c.ExposedPorts) > 0 { + portBindings, err = c.CreatePortBindings() + if err != nil { + return nil, errors.Wrapf(err, "unable to create port bindings") + } + } + + if c.NetMode.IsContainer() { + connectedCtr, err := c.Runtime.LookupContainer(c.NetMode.ConnectedContainer()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.NetMode.ConnectedContainer()) + } + options = append(options, libpod.WithNetNSFrom(connectedCtr)) + } else if !c.NetMode.IsHost() { + options = append(options, libpod.WithNetNS(portBindings)) + } + + if c.PidMode.IsContainer() { + connectedCtr, err := c.Runtime.LookupContainer(c.PidMode.Container()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.PidMode.Container()) + } + + options = append(options, libpod.WithPIDNSFrom(connectedCtr)) + } + if c.IpcMode.IsContainer() { + connectedCtr, err := c.Runtime.LookupContainer(c.IpcMode.Container()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.IpcMode.Container()) + } + + options = append(options, libpod.WithIPCNSFrom(connectedCtr)) } + options = append(options, libpod.WithStopSignal(c.StopSignal)) options = append(options, libpod.WithStopTimeout(c.StopTimeout)) + if len(c.DNSSearch) > 0 { + options = append(options, libpod.WithDNSSearch(c.DNSSearch)) + } + if len(c.DNSServers) > 0 { + options = append(options, libpod.WithDNS(c.DNSServers)) + } + if len(c.DNSOpt) > 0 { + options = append(options, libpod.WithDNSOption(c.DNSOpt)) + } + if len(c.HostAdd) > 0 { + options = append(options, libpod.WithHosts(c.HostAdd)) + } + return options, nil } @@ -598,3 +633,43 @@ func makeThrottleArray(throttleInput []string) ([]spec.LinuxThrottleDevice, erro } return ltds, nil } + +// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands +func (c *createConfig) CreatePortBindings() ([]ocicni.PortMapping, error) { + var portBindings []ocicni.PortMapping + for containerPb, hostPb := range c.PortBindings { + var pm ocicni.PortMapping + pm.ContainerPort = int32(containerPb.Int()) + for _, i := range hostPb { + var hostPort int + var err error + pm.HostIP = i.HostIP + if i.HostPort == "" { + hostPort = containerPb.Int() + } else { + hostPort, err = strconv.Atoi(i.HostPort) + if err != nil { + return nil, errors.Wrapf(err, "unable to convert host port to integer") + } + } + + pm.HostPort = int32(hostPort) + // CNI requires us to make both udp and tcp structs + pm.Protocol = "udp" + portBindings = append(portBindings, pm) + pm.Protocol = "tcp" + portBindings = append(portBindings, pm) + } + } + for j := range c.ExposedPorts { + var expose ocicni.PortMapping + expose.HostPort = int32(j.Int()) + expose.ContainerPort = int32(j.Int()) + // CNI requires us to make both udp and tcp structs + expose.Protocol = "udp" + portBindings = append(portBindings, expose) + expose.Protocol = "tcp" + portBindings = append(portBindings, expose) + } + return portBindings, nil +} |