1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
package shared
import (
"strconv"
"github.com/containers/libpod/libpod"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
)
const (
stopped = "Stopped"
running = "Running"
paused = "Paused"
exited = "Exited"
errored = "Error"
created = "Created"
)
// GetPodStatus determines the status of the pod based on the
// statuses of the containers in the pod.
// Returns a string representation of the pod status
func GetPodStatus(pod *libpod.Pod) (string, error) {
ctrStatuses, err := pod.Status()
if err != nil {
return errored, err
}
return CreatePodStatusResults(ctrStatuses)
}
func CreatePodStatusResults(ctrStatuses map[string]libpod.ContainerStatus) (string, error) {
ctrNum := len(ctrStatuses)
if ctrNum == 0 {
return created, nil
}
statuses := map[string]int{
stopped: 0,
running: 0,
paused: 0,
created: 0,
errored: 0,
}
for _, ctrStatus := range ctrStatuses {
switch ctrStatus {
case libpod.ContainerStateExited:
fallthrough
case libpod.ContainerStateStopped:
statuses[stopped]++
case libpod.ContainerStateRunning:
statuses[running]++
case libpod.ContainerStatePaused:
statuses[paused]++
case libpod.ContainerStateCreated, libpod.ContainerStateConfigured:
statuses[created]++
default:
statuses[errored]++
}
}
if statuses[running] > 0 {
return running, nil
} else if statuses[paused] == ctrNum {
return paused, nil
} else if statuses[stopped] == ctrNum {
return exited, nil
} else if statuses[stopped] > 0 {
return stopped, nil
} else if statuses[errored] > 0 {
return errored, nil
}
return created, nil
}
// GetNamespaceOptions transforms a slice of kernel namespaces
// into a slice of pod create options. Currently, not all
// kernel namespaces are supported, and they will be returned in an error
func GetNamespaceOptions(ns []string) ([]libpod.PodCreateOption, error) {
var options []libpod.PodCreateOption
var erroredOptions []libpod.PodCreateOption
for _, toShare := range ns {
switch toShare {
case "cgroup":
options = append(options, libpod.WithPodCgroups())
case "net":
options = append(options, libpod.WithPodNet())
case "mnt":
return erroredOptions, errors.Errorf("Mount sharing functionality not supported on pod level")
case "pid":
options = append(options, libpod.WithPodPID())
case "user":
return erroredOptions, errors.Errorf("User sharing functionality not supported on pod level")
case "ipc":
options = append(options, libpod.WithPodIPC())
case "uts":
options = append(options, libpod.WithPodUTS())
case "":
case "none":
return erroredOptions, nil
default:
return erroredOptions, errors.Errorf("Invalid kernel namespace to share: %s. Options are: net, pid, ipc, uts or none", toShare)
}
}
return options, nil
}
// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
func CreatePortBindings(ports []string) ([]ocicni.PortMapping, error) {
var portBindings []ocicni.PortMapping
// The conversion from []string to natBindings is temporary while mheon reworks the port
// deduplication code. Eventually that step will not be required.
_, natBindings, err := nat.ParsePortSpecs(ports)
if err != nil {
return nil, err
}
for containerPb, hostPb := range natBindings {
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)
pm.Protocol = containerPb.Proto()
portBindings = append(portBindings, pm)
}
}
return portBindings, nil
}
|