github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/varlinkapi/pods.go (about) 1 // +build varlink 2 3 package varlinkapi 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "syscall" 9 10 "github.com/containers/libpod/cmd/podman/shared" 11 "github.com/containers/libpod/libpod" 12 "github.com/containers/libpod/pkg/adapter/shortcuts" 13 iopodman "github.com/containers/libpod/pkg/varlink" 14 ) 15 16 // CreatePod ... 17 func (i *VarlinkAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCreate) error { 18 var options []libpod.PodCreateOption 19 if create.Infra { 20 options = append(options, libpod.WithInfraContainer()) 21 nsOptions, err := shared.GetNamespaceOptions(create.Share) 22 if err != nil { 23 return err 24 } 25 options = append(options, nsOptions...) 26 } 27 if create.CgroupParent != "" { 28 options = append(options, libpod.WithPodCgroupParent(create.CgroupParent)) 29 } 30 if len(create.Labels) > 0 { 31 options = append(options, libpod.WithPodLabels(create.Labels)) 32 } 33 if create.Name != "" { 34 options = append(options, libpod.WithPodName(create.Name)) 35 } 36 if len(create.Share) > 0 && !create.Infra { 37 return call.ReplyErrorOccurred("You cannot share kernel namespaces on the pod level without an infra container") 38 } 39 if len(create.Share) == 0 && create.Infra { 40 return call.ReplyErrorOccurred("You must share kernel namespaces to run an infra container") 41 } 42 43 if len(create.Publish) > 0 { 44 if !create.Infra { 45 return call.ReplyErrorOccurred("you must have an infra container to publish port bindings to the host") 46 } 47 portBindings, err := shared.CreatePortBindings(create.Publish) 48 if err != nil { 49 return call.ReplyErrorOccurred(err.Error()) 50 } 51 options = append(options, libpod.WithInfraContainerPorts(portBindings)) 52 53 } 54 options = append(options, libpod.WithPodCgroups()) 55 56 pod, err := i.Runtime.NewPod(getContext(), options...) 57 if err != nil { 58 return call.ReplyErrorOccurred(err.Error()) 59 } 60 return call.ReplyCreatePod(pod.ID()) 61 } 62 63 // ListPods ... 64 func (i *VarlinkAPI) ListPods(call iopodman.VarlinkCall) error { 65 var ( 66 listPods []iopodman.ListPodData 67 ) 68 69 pods, err := i.Runtime.GetAllPods() 70 if err != nil { 71 return call.ReplyErrorOccurred(err.Error()) 72 } 73 opts := shared.PsOptions{} 74 for _, pod := range pods { 75 listPod, err := makeListPod(pod, opts) 76 if err != nil { 77 return call.ReplyErrorOccurred(err.Error()) 78 } 79 listPods = append(listPods, listPod) 80 } 81 return call.ReplyListPods(listPods) 82 } 83 84 // GetPod ... 85 func (i *VarlinkAPI) GetPod(call iopodman.VarlinkCall, name string) error { 86 pod, err := i.Runtime.LookupPod(name) 87 if err != nil { 88 return call.ReplyPodNotFound(name, err.Error()) 89 } 90 opts := shared.PsOptions{} 91 92 listPod, err := makeListPod(pod, opts) 93 if err != nil { 94 return call.ReplyErrorOccurred(err.Error()) 95 } 96 97 return call.ReplyGetPod(listPod) 98 } 99 100 // GetPodsByStatus returns a slice of pods filtered by a libpod status 101 func (i *VarlinkAPI) GetPodsByStatus(call iopodman.VarlinkCall, statuses []string) error { 102 filterFuncs := func(p *libpod.Pod) bool { 103 state, _ := shared.GetPodStatus(p) 104 for _, status := range statuses { 105 if state == status { 106 return true 107 } 108 } 109 return false 110 } 111 filteredPods, err := i.Runtime.Pods(filterFuncs) 112 if err != nil { 113 return call.ReplyErrorOccurred(err.Error()) 114 } 115 podIDs := make([]string, 0, len(filteredPods)) 116 for _, p := range filteredPods { 117 podIDs = append(podIDs, p.ID()) 118 } 119 return call.ReplyGetPodsByStatus(podIDs) 120 } 121 122 // InspectPod ... 123 func (i *VarlinkAPI) InspectPod(call iopodman.VarlinkCall, name string) error { 124 pod, err := i.Runtime.LookupPod(name) 125 if err != nil { 126 return call.ReplyPodNotFound(name, err.Error()) 127 } 128 inspectData, err := pod.Inspect() 129 if err != nil { 130 return call.ReplyErrorOccurred(err.Error()) 131 } 132 b, err := json.Marshal(&inspectData) 133 if err != nil { 134 return call.ReplyErrorOccurred("unable to serialize") 135 } 136 return call.ReplyInspectPod(string(b)) 137 } 138 139 // StartPod ... 140 func (i *VarlinkAPI) StartPod(call iopodman.VarlinkCall, name string) error { 141 pod, err := i.Runtime.LookupPod(name) 142 if err != nil { 143 return call.ReplyPodNotFound(name, err.Error()) 144 } 145 ctnrs, err := pod.AllContainers() 146 if err != nil { 147 return call.ReplyErrorOccurred(err.Error()) 148 } 149 if 0 == len(ctnrs) { 150 return call.ReplyNoContainersInPod(name) 151 } 152 ctrErrs, err := pod.Start(getContext()) 153 callErr := handlePodCall(call, pod, ctrErrs, err) 154 if callErr != nil { 155 return err 156 } 157 return call.ReplyStartPod(pod.ID()) 158 } 159 160 // StopPod ... 161 func (i *VarlinkAPI) StopPod(call iopodman.VarlinkCall, name string, timeout int64) error { 162 pod, err := i.Runtime.LookupPod(name) 163 if err != nil { 164 return call.ReplyPodNotFound(name, err.Error()) 165 } 166 ctrErrs, err := pod.StopWithTimeout(getContext(), true, int(timeout)) 167 callErr := handlePodCall(call, pod, ctrErrs, err) 168 if callErr != nil { 169 return err 170 } 171 return call.ReplyStopPod(pod.ID()) 172 } 173 174 // RestartPod ... 175 func (i *VarlinkAPI) RestartPod(call iopodman.VarlinkCall, name string) error { 176 pod, err := i.Runtime.LookupPod(name) 177 if err != nil { 178 return call.ReplyPodNotFound(name, err.Error()) 179 } 180 ctnrs, err := pod.AllContainers() 181 if err != nil { 182 return call.ReplyErrorOccurred(err.Error()) 183 } 184 if 0 == len(ctnrs) { 185 return call.ReplyNoContainersInPod(name) 186 } 187 ctrErrs, err := pod.Restart(getContext()) 188 callErr := handlePodCall(call, pod, ctrErrs, err) 189 if callErr != nil { 190 return err 191 } 192 return call.ReplyRestartPod(pod.ID()) 193 } 194 195 // KillPod kills the running containers in a pod. If you want to use the default SIGTERM signal, 196 // just send a -1 for the signal arg. 197 func (i *VarlinkAPI) KillPod(call iopodman.VarlinkCall, name string, signal int64) error { 198 killSignal := uint(syscall.SIGTERM) 199 if signal != -1 { 200 killSignal = uint(signal) 201 } 202 203 pod, err := i.Runtime.LookupPod(name) 204 if err != nil { 205 return call.ReplyPodNotFound(name, err.Error()) 206 } 207 ctrErrs, err := pod.Kill(killSignal) 208 callErr := handlePodCall(call, pod, ctrErrs, err) 209 if callErr != nil { 210 return err 211 } 212 return call.ReplyKillPod(pod.ID()) 213 } 214 215 // PausePod ... 216 func (i *VarlinkAPI) PausePod(call iopodman.VarlinkCall, name string) error { 217 pod, err := i.Runtime.LookupPod(name) 218 if err != nil { 219 return call.ReplyPodNotFound(name, err.Error()) 220 } 221 ctrErrs, err := pod.Pause() 222 callErr := handlePodCall(call, pod, ctrErrs, err) 223 if callErr != nil { 224 return err 225 } 226 return call.ReplyPausePod(pod.ID()) 227 } 228 229 // UnpausePod ... 230 func (i *VarlinkAPI) UnpausePod(call iopodman.VarlinkCall, name string) error { 231 pod, err := i.Runtime.LookupPod(name) 232 if err != nil { 233 return call.ReplyPodNotFound(name, err.Error()) 234 } 235 ctrErrs, err := pod.Unpause() 236 callErr := handlePodCall(call, pod, ctrErrs, err) 237 if callErr != nil { 238 return err 239 } 240 return call.ReplyUnpausePod(pod.ID()) 241 } 242 243 // RemovePod ... 244 func (i *VarlinkAPI) RemovePod(call iopodman.VarlinkCall, name string, force bool) error { 245 ctx := getContext() 246 pod, err := i.Runtime.LookupPod(name) 247 if err != nil { 248 return call.ReplyPodNotFound(name, err.Error()) 249 } 250 if err = i.Runtime.RemovePod(ctx, pod, true, force); err != nil { 251 return call.ReplyErrorOccurred(err.Error()) 252 } 253 254 return call.ReplyRemovePod(pod.ID()) 255 } 256 257 // GetPodStats ... 258 func (i *VarlinkAPI) GetPodStats(call iopodman.VarlinkCall, name string) error { 259 pod, err := i.Runtime.LookupPod(name) 260 if err != nil { 261 return call.ReplyPodNotFound(name, err.Error()) 262 } 263 prevStats := make(map[string]*libpod.ContainerStats) 264 podStats, err := pod.GetPodStats(prevStats) 265 if err != nil { 266 return call.ReplyErrorOccurred(err.Error()) 267 } 268 if len(podStats) == 0 { 269 return call.ReplyNoContainerRunning() 270 } 271 containersStats := make([]iopodman.ContainerStats, 0) 272 for ctrID, containerStats := range podStats { 273 cs := iopodman.ContainerStats{ 274 Id: ctrID, 275 Name: containerStats.Name, 276 Cpu: containerStats.CPU, 277 Cpu_nano: int64(containerStats.CPUNano), 278 System_nano: int64(containerStats.SystemNano), 279 Mem_usage: int64(containerStats.MemUsage), 280 Mem_limit: int64(containerStats.MemLimit), 281 Mem_perc: containerStats.MemPerc, 282 Net_input: int64(containerStats.NetInput), 283 Net_output: int64(containerStats.NetOutput), 284 Block_input: int64(containerStats.BlockInput), 285 Block_output: int64(containerStats.BlockOutput), 286 Pids: int64(containerStats.PIDs), 287 } 288 containersStats = append(containersStats, cs) 289 } 290 return call.ReplyGetPodStats(pod.ID(), containersStats) 291 } 292 293 // GetPodsByContext returns a slice of pod ids based on all, latest, or a list 294 func (i *VarlinkAPI) GetPodsByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error { 295 var podids []string 296 297 pods, err := shortcuts.GetPodsByContext(all, latest, input, i.Runtime) 298 if err != nil { 299 return call.ReplyErrorOccurred(err.Error()) 300 } 301 for _, p := range pods { 302 podids = append(podids, p.ID()) 303 } 304 return call.ReplyGetPodsByContext(podids) 305 } 306 307 // PodStateData returns a container's state data in string format 308 func (i *VarlinkAPI) PodStateData(call iopodman.VarlinkCall, name string) error { 309 pod, err := i.Runtime.LookupPod(name) 310 if err != nil { 311 return call.ReplyErrorOccurred(err.Error()) 312 } 313 data, err := pod.Inspect() 314 if err != nil { 315 return call.ReplyErrorOccurred("unable to obtain pod state") 316 } 317 b, err := json.Marshal(data) 318 if err != nil { 319 return call.ReplyErrorOccurred("unable to serialize pod inspect data") 320 } 321 return call.ReplyPodStateData(string(b)) 322 } 323 324 // TopPod provides the top stats for a given or latest pod 325 func (i *VarlinkAPI) TopPod(call iopodman.VarlinkCall, name string, latest bool, descriptors []string) error { 326 var ( 327 pod *libpod.Pod 328 err error 329 ) 330 if latest { 331 name = "latest" 332 pod, err = i.Runtime.GetLatestPod() 333 } else { 334 pod, err = i.Runtime.LookupPod(name) 335 } 336 if err != nil { 337 return call.ReplyPodNotFound(name, err.Error()) 338 } 339 340 podStatus, err := shared.GetPodStatus(pod) 341 if err != nil { 342 return call.ReplyErrorOccurred(fmt.Sprintf("unable to get status for pod %s", pod.ID())) 343 } 344 if podStatus != "Running" { 345 return call.ReplyErrorOccurred("pod top can only be used on pods with at least one running container") 346 } 347 reply, err := pod.GetPodPidInformation(descriptors) 348 if err != nil { 349 return call.ReplyErrorOccurred(err.Error()) 350 } 351 return call.ReplyTopPod(reply) 352 }