mirror of
https://github.com/containers/podman
synced 2024-10-21 17:53:44 +00:00
b906b9d858
We do not use the ocicni code anymore so let's get rid of it. Only the port struct is used but we can copy this into libpod network types so we can debloat the binary. The next step is to remove the OCICNI port mapping form the container config and use the better PortMapping struct everywhere. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
155 lines
4.4 KiB
Go
155 lines
4.4 KiB
Go
package libpod
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/containers/podman/v3/libpod/define"
|
|
"github.com/containers/podman/v3/libpod/network/types"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Timeout before declaring that runtime has failed to kill a given
|
|
// container
|
|
const killContainerTimeout = 5 * time.Second
|
|
|
|
// ociError is used to parse the OCI runtime JSON log. It is not part of the
|
|
// OCI runtime specifications, it follows what runc does
|
|
type ociError struct {
|
|
Level string `json:"level,omitempty"`
|
|
Time string `json:"time,omitempty"`
|
|
Msg string `json:"msg,omitempty"`
|
|
}
|
|
|
|
// Create systemd unit name for cgroup scopes
|
|
func createUnitName(prefix string, name string) string {
|
|
return fmt.Sprintf("%s-%s.scope", prefix, name)
|
|
}
|
|
|
|
// Bind ports to keep them closed on the host
|
|
func bindPorts(ports []types.OCICNIPortMapping) ([]*os.File, error) {
|
|
var files []*os.File
|
|
notifySCTP := false
|
|
for _, i := range ports {
|
|
isV6 := net.ParseIP(i.HostIP).To4() == nil
|
|
if i.HostIP == "" {
|
|
isV6 = false
|
|
}
|
|
switch i.Protocol {
|
|
case "udp":
|
|
var (
|
|
addr *net.UDPAddr
|
|
err error
|
|
)
|
|
if isV6 {
|
|
addr, err = net.ResolveUDPAddr("udp6", fmt.Sprintf("[%s]:%d", i.HostIP, i.HostPort))
|
|
} else {
|
|
addr, err = net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", i.HostIP, i.HostPort))
|
|
}
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "cannot resolve the UDP address")
|
|
}
|
|
|
|
proto := "udp4"
|
|
if isV6 {
|
|
proto = "udp6"
|
|
}
|
|
server, err := net.ListenUDP(proto, addr)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "cannot listen on the UDP port")
|
|
}
|
|
f, err := server.File()
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "cannot get file for UDP socket")
|
|
}
|
|
files = append(files, f)
|
|
// close the listener
|
|
// note that this does not affect the fd, see the godoc for server.File()
|
|
err = server.Close()
|
|
if err != nil {
|
|
logrus.Warnf("failed to close connection: %v", err)
|
|
}
|
|
|
|
case "tcp":
|
|
var (
|
|
addr *net.TCPAddr
|
|
err error
|
|
)
|
|
if isV6 {
|
|
addr, err = net.ResolveTCPAddr("tcp6", fmt.Sprintf("[%s]:%d", i.HostIP, i.HostPort))
|
|
} else {
|
|
addr, err = net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", i.HostIP, i.HostPort))
|
|
}
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "cannot resolve the TCP address")
|
|
}
|
|
|
|
proto := "tcp4"
|
|
if isV6 {
|
|
proto = "tcp6"
|
|
}
|
|
server, err := net.ListenTCP(proto, addr)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "cannot listen on the TCP port")
|
|
}
|
|
f, err := server.File()
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "cannot get file for TCP socket")
|
|
}
|
|
files = append(files, f)
|
|
// close the listener
|
|
// note that this does not affect the fd, see the godoc for server.File()
|
|
err = server.Close()
|
|
if err != nil {
|
|
logrus.Warnf("failed to close connection: %v", err)
|
|
}
|
|
|
|
case "sctp":
|
|
if !notifySCTP {
|
|
notifySCTP = true
|
|
logrus.Warnf("port reservation for SCTP is not supported")
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("unknown protocol %s", i.Protocol)
|
|
}
|
|
}
|
|
return files, nil
|
|
}
|
|
|
|
func getOCIRuntimeError(runtimeMsg string) error {
|
|
includeFullOutput := logrus.GetLevel() == logrus.DebugLevel
|
|
|
|
if match := regexp.MustCompile("(?i).*permission denied.*|.*operation not permitted.*").FindString(runtimeMsg); match != "" {
|
|
errStr := match
|
|
if includeFullOutput {
|
|
errStr = runtimeMsg
|
|
}
|
|
return errors.Wrapf(define.ErrOCIRuntimePermissionDenied, "%s", strings.Trim(errStr, "\n"))
|
|
}
|
|
if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*").FindString(runtimeMsg); match != "" {
|
|
errStr := match
|
|
if includeFullOutput {
|
|
errStr = runtimeMsg
|
|
}
|
|
return errors.Wrapf(define.ErrOCIRuntimeNotFound, "%s", strings.Trim(errStr, "\n"))
|
|
}
|
|
if match := regexp.MustCompile("`/proc/[a-z0-9-].+/attr.*`").FindString(runtimeMsg); match != "" {
|
|
errStr := match
|
|
if includeFullOutput {
|
|
errStr = runtimeMsg
|
|
}
|
|
if strings.HasSuffix(match, "/exec`") {
|
|
return errors.Wrapf(define.ErrSetSecurityAttribute, "%s", strings.Trim(errStr, "\n"))
|
|
} else if strings.HasSuffix(match, "/current`") {
|
|
return errors.Wrapf(define.ErrGetSecurityAttribute, "%s", strings.Trim(errStr, "\n"))
|
|
}
|
|
return errors.Wrapf(define.ErrSecurityAttribute, "%s", strings.Trim(errStr, "\n"))
|
|
}
|
|
return errors.Wrapf(define.ErrOCIRuntime, "%s", strings.Trim(runtimeMsg, "\n"))
|
|
}
|