podman

Форк
0
/
oci_util.go 
170 строк · 4.7 Кб
1
//go:build !remote
2

3
package libpod
4

5
import (
6
	"fmt"
7
	"net"
8
	"os"
9
	"regexp"
10
	"strings"
11
	"time"
12

13
	"github.com/containers/common/libnetwork/types"
14
	"github.com/containers/podman/v5/libpod/define"
15
	"github.com/sirupsen/logrus"
16
)
17

18
// Timeout before declaring that runtime has failed to kill a given
19
// container
20
const killContainerTimeout = 5 * time.Second
21

22
// ociError is used to parse the OCI runtime JSON log.  It is not part of the
23
// OCI runtime specifications, it follows what runc does
24
type ociError struct {
25
	Level string `json:"level,omitempty"`
26
	Time  string `json:"time,omitempty"`
27
	Msg   string `json:"msg,omitempty"`
28
}
29

30
// Create systemd unit name for cgroup scopes
31
func createUnitName(prefix string, name string) string {
32
	return fmt.Sprintf("%s-%s.scope", prefix, name)
33
}
34

35
// Bind ports to keep them closed on the host
36
func bindPorts(ports []types.PortMapping) ([]*os.File, error) {
37
	var files []*os.File
38
	sctpWarning := true
39
	for _, port := range ports {
40
		isV6 := net.ParseIP(port.HostIP).To4() == nil
41
		if port.HostIP == "" {
42
			isV6 = false
43
		}
44
		protocols := strings.Split(port.Protocol, ",")
45
		for _, protocol := range protocols {
46
			for i := uint16(0); i < port.Range; i++ {
47
				f, err := bindPort(protocol, port.HostIP, port.HostPort+i, isV6, &sctpWarning)
48
				if err != nil {
49
					return files, err
50
				}
51
				if f != nil {
52
					files = append(files, f)
53
				}
54
			}
55
		}
56
	}
57
	return files, nil
58
}
59

60
func bindPort(protocol, hostIP string, port uint16, isV6 bool, sctpWarning *bool) (*os.File, error) {
61
	var file *os.File
62
	switch protocol {
63
	case "udp":
64
		var (
65
			addr *net.UDPAddr
66
			err  error
67
		)
68
		if isV6 {
69
			addr, err = net.ResolveUDPAddr("udp6", fmt.Sprintf("[%s]:%d", hostIP, port))
70
		} else {
71
			addr, err = net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", hostIP, port))
72
		}
73
		if err != nil {
74
			return nil, fmt.Errorf("cannot resolve the UDP address: %w", err)
75
		}
76

77
		proto := "udp4"
78
		if isV6 {
79
			proto = "udp6"
80
		}
81
		server, err := net.ListenUDP(proto, addr)
82
		if err != nil {
83
			return nil, fmt.Errorf("cannot listen on the UDP port: %w", err)
84
		}
85
		file, err = server.File()
86
		if err != nil {
87
			return nil, fmt.Errorf("cannot get file for UDP socket: %w", err)
88
		}
89
		// close the listener
90
		// note that this does not affect the fd, see the godoc for server.File()
91
		err = server.Close()
92
		if err != nil {
93
			logrus.Warnf("Failed to close connection: %v", err)
94
		}
95

96
	case "tcp":
97
		var (
98
			addr *net.TCPAddr
99
			err  error
100
		)
101
		if isV6 {
102
			addr, err = net.ResolveTCPAddr("tcp6", fmt.Sprintf("[%s]:%d", hostIP, port))
103
		} else {
104
			addr, err = net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", hostIP, port))
105
		}
106
		if err != nil {
107
			return nil, fmt.Errorf("cannot resolve the TCP address: %w", err)
108
		}
109

110
		proto := "tcp4"
111
		if isV6 {
112
			proto = "tcp6"
113
		}
114
		server, err := net.ListenTCP(proto, addr)
115
		if err != nil {
116
			return nil, fmt.Errorf("cannot listen on the TCP port: %w", err)
117
		}
118
		file, err = server.File()
119
		if err != nil {
120
			return nil, fmt.Errorf("cannot get file for TCP socket: %w", err)
121
		}
122
		// close the listener
123
		// note that this does not affect the fd, see the godoc for server.File()
124
		err = server.Close()
125
		if err != nil {
126
			logrus.Warnf("Failed to close connection: %v", err)
127
		}
128

129
	case "sctp":
130
		if *sctpWarning {
131
			logrus.Info("Port reservation for SCTP is not supported")
132
			*sctpWarning = false
133
		}
134
	default:
135
		return nil, fmt.Errorf("unknown protocol %s", protocol)
136
	}
137
	return file, nil
138
}
139

140
func getOCIRuntimeError(name, runtimeMsg string) error {
141
	includeFullOutput := logrus.GetLevel() == logrus.DebugLevel
142

143
	if match := regexp.MustCompile("(?i).*permission denied.*|.*operation not permitted.*").FindString(runtimeMsg); match != "" {
144
		errStr := match
145
		if includeFullOutput {
146
			errStr = runtimeMsg
147
		}
148
		return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrOCIRuntimePermissionDenied)
149
	}
150
	if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*").FindString(runtimeMsg); match != "" {
151
		errStr := match
152
		if includeFullOutput {
153
			errStr = runtimeMsg
154
		}
155
		return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrOCIRuntimeNotFound)
156
	}
157
	if match := regexp.MustCompile("`/proc/[a-z0-9-].+/attr.*`").FindString(runtimeMsg); match != "" {
158
		errStr := match
159
		if includeFullOutput {
160
			errStr = runtimeMsg
161
		}
162
		if strings.HasSuffix(match, "/exec`") {
163
			return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrSetSecurityAttribute)
164
		} else if strings.HasSuffix(match, "/current`") {
165
			return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrGetSecurityAttribute)
166
		}
167
		return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrSecurityAttribute)
168
	}
169
	return fmt.Errorf("%s: %s: %w", name, strings.Trim(runtimeMsg, "\n"), define.ErrOCIRuntime)
170
}
171

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.