2017-04-19 18:55:17 +00:00
|
|
|
package oci
|
|
|
|
|
|
|
|
import (
|
2017-05-11 10:10:18 +00:00
|
|
|
"encoding/json"
|
2017-04-19 18:55:17 +00:00
|
|
|
"fmt"
|
2017-05-11 10:10:18 +00:00
|
|
|
"os"
|
2017-05-11 10:03:59 +00:00
|
|
|
"path/filepath"
|
2017-05-26 16:31:28 +00:00
|
|
|
"strings"
|
2017-04-19 18:55:17 +00:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2017-09-05 20:10:42 +00:00
|
|
|
"github.com/containernetworking/plugins/pkg/ns"
|
2017-05-26 16:31:28 +00:00
|
|
|
"github.com/docker/docker/pkg/signal"
|
2017-04-19 18:55:17 +00:00
|
|
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
|
|
"k8s.io/apimachinery/pkg/fields"
|
2017-08-04 11:13:19 +00:00
|
|
|
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
2017-04-19 18:55:17 +00:00
|
|
|
)
|
|
|
|
|
2017-05-26 16:31:28 +00:00
|
|
|
const (
|
|
|
|
defaultStopSignal = "TERM"
|
|
|
|
)
|
|
|
|
|
2017-04-19 18:55:17 +00:00
|
|
|
// Container represents a runtime container.
|
|
|
|
type Container struct {
|
2017-09-22 23:44:02 +00:00
|
|
|
id string
|
|
|
|
name string
|
|
|
|
logPath string
|
|
|
|
labels fields.Set
|
|
|
|
annotations fields.Set
|
|
|
|
crioAnnotations fields.Set
|
|
|
|
image string
|
|
|
|
sandbox string
|
|
|
|
netns ns.NetNS
|
|
|
|
terminal bool
|
|
|
|
stdin bool
|
|
|
|
stdinOnce bool
|
|
|
|
privileged bool
|
|
|
|
trusted bool
|
|
|
|
state *ContainerState
|
|
|
|
metadata *pb.ContainerMetadata
|
|
|
|
opLock sync.Locker
|
2017-05-11 09:12:37 +00:00
|
|
|
// this is the /var/run/storage/... directory, erased on reboot
|
|
|
|
bundlePath string
|
|
|
|
// this is the /var/lib/storage/... directory
|
2017-09-27 18:46:31 +00:00
|
|
|
dir string
|
|
|
|
stopSignal string
|
|
|
|
imageName string
|
|
|
|
imageRef string
|
|
|
|
volumes []ContainerVolume
|
|
|
|
mountPoint string
|
|
|
|
seccompProfilePath string
|
|
|
|
spec *specs.Spec
|
2017-08-14 19:43:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ContainerVolume is a bind mount for the container.
|
|
|
|
type ContainerVolume struct {
|
|
|
|
ContainerPath string `json:"container_path"`
|
|
|
|
HostPath string `json:"host_path"`
|
|
|
|
Readonly bool `json:"readonly"`
|
2017-04-19 18:55:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ContainerState represents the status of a container.
|
|
|
|
type ContainerState struct {
|
|
|
|
specs.State
|
2017-05-23 21:04:10 +00:00
|
|
|
Created time.Time `json:"created"`
|
|
|
|
Started time.Time `json:"started,omitempty"`
|
|
|
|
Finished time.Time `json:"finished,omitempty"`
|
|
|
|
ExitCode int32 `json:"exitCode,omitempty"`
|
|
|
|
OOMKilled bool `json:"oomKilled,omitempty"`
|
2017-06-10 16:18:59 +00:00
|
|
|
Error string `json:"error,omitempty"`
|
2017-04-19 18:55:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewContainer creates a container object.
|
2017-09-22 23:44:02 +00:00
|
|
|
func NewContainer(id string, name string, bundlePath string, logPath string, netns ns.NetNS, labels map[string]string, crioAnnotations map[string]string, annotations map[string]string, image string, imageName string, imageRef string, metadata *pb.ContainerMetadata, sandbox string, terminal bool, stdin bool, stdinOnce bool, privileged bool, trusted bool, dir string, created time.Time, stopSignal string) (*Container, error) {
|
2017-05-11 09:22:47 +00:00
|
|
|
state := &ContainerState{}
|
|
|
|
state.Created = created
|
2017-04-19 18:55:17 +00:00
|
|
|
c := &Container{
|
2017-09-22 23:44:02 +00:00
|
|
|
id: id,
|
|
|
|
name: name,
|
|
|
|
bundlePath: bundlePath,
|
|
|
|
logPath: logPath,
|
|
|
|
labels: labels,
|
|
|
|
sandbox: sandbox,
|
|
|
|
netns: netns,
|
|
|
|
terminal: terminal,
|
|
|
|
stdin: stdin,
|
|
|
|
stdinOnce: stdinOnce,
|
|
|
|
privileged: privileged,
|
|
|
|
trusted: trusted,
|
|
|
|
metadata: metadata,
|
|
|
|
annotations: annotations,
|
|
|
|
crioAnnotations: crioAnnotations,
|
|
|
|
image: image,
|
|
|
|
imageName: imageName,
|
|
|
|
imageRef: imageRef,
|
|
|
|
dir: dir,
|
|
|
|
state: state,
|
|
|
|
stopSignal: stopSignal,
|
|
|
|
opLock: new(sync.Mutex),
|
2017-04-19 18:55:17 +00:00
|
|
|
}
|
|
|
|
return c, nil
|
|
|
|
}
|
|
|
|
|
2017-10-19 13:02:56 +00:00
|
|
|
// SetSpec loads the OCI spec in the container struct
|
|
|
|
func (c *Container) SetSpec(s *specs.Spec) {
|
|
|
|
c.spec = s
|
|
|
|
}
|
|
|
|
|
|
|
|
// Spec returns a copy of the spec for the container
|
|
|
|
func (c *Container) Spec() specs.Spec {
|
|
|
|
return *c.spec
|
|
|
|
}
|
|
|
|
|
2017-05-26 16:31:28 +00:00
|
|
|
// GetStopSignal returns the container's own stop signal configured from the
|
|
|
|
// image configuration or the default one.
|
|
|
|
func (c *Container) GetStopSignal() string {
|
|
|
|
if c.stopSignal == "" {
|
|
|
|
return defaultStopSignal
|
|
|
|
}
|
|
|
|
cleanSignal := strings.TrimPrefix(strings.ToUpper(c.stopSignal), "SIG")
|
|
|
|
_, ok := signal.SignalMap[cleanSignal]
|
|
|
|
if !ok {
|
|
|
|
return defaultStopSignal
|
|
|
|
}
|
|
|
|
return cleanSignal
|
|
|
|
}
|
|
|
|
|
2017-05-11 10:10:18 +00:00
|
|
|
// FromDisk restores container's state from disk
|
|
|
|
func (c *Container) FromDisk() error {
|
|
|
|
jsonSource, err := os.Open(c.StatePath())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer jsonSource.Close()
|
|
|
|
|
|
|
|
dec := json.NewDecoder(jsonSource)
|
|
|
|
return dec.Decode(c.state)
|
|
|
|
}
|
|
|
|
|
2017-05-11 10:03:59 +00:00
|
|
|
// StatePath returns the containers state.json path
|
|
|
|
func (c *Container) StatePath() string {
|
|
|
|
return filepath.Join(c.dir, "state.json")
|
|
|
|
}
|
|
|
|
|
2017-05-11 09:22:47 +00:00
|
|
|
// CreatedAt returns the container creation time
|
|
|
|
func (c *Container) CreatedAt() time.Time {
|
|
|
|
return c.state.Created
|
|
|
|
}
|
|
|
|
|
2017-04-19 18:55:17 +00:00
|
|
|
// Name returns the name of the container.
|
|
|
|
func (c *Container) Name() string {
|
|
|
|
return c.name
|
|
|
|
}
|
|
|
|
|
|
|
|
// ID returns the id of the container.
|
|
|
|
func (c *Container) ID() string {
|
|
|
|
return c.id
|
|
|
|
}
|
|
|
|
|
2017-09-27 18:46:31 +00:00
|
|
|
// SetSeccompProfilePath sets the seccomp profile path
|
|
|
|
func (c *Container) SetSeccompProfilePath(pp string) {
|
|
|
|
c.seccompProfilePath = pp
|
|
|
|
}
|
|
|
|
|
|
|
|
// SeccompProfilePath returns the seccomp profile path
|
|
|
|
func (c *Container) SeccompProfilePath() string {
|
|
|
|
return c.seccompProfilePath
|
|
|
|
}
|
|
|
|
|
2017-04-19 18:55:17 +00:00
|
|
|
// BundlePath returns the bundlePath of the container.
|
|
|
|
func (c *Container) BundlePath() string {
|
|
|
|
return c.bundlePath
|
|
|
|
}
|
|
|
|
|
|
|
|
// LogPath returns the log path of the container.
|
|
|
|
func (c *Container) LogPath() string {
|
|
|
|
return c.logPath
|
|
|
|
}
|
|
|
|
|
|
|
|
// Labels returns the labels of the container.
|
|
|
|
func (c *Container) Labels() map[string]string {
|
|
|
|
return c.labels
|
|
|
|
}
|
|
|
|
|
|
|
|
// Annotations returns the annotations of the container.
|
|
|
|
func (c *Container) Annotations() map[string]string {
|
|
|
|
return c.annotations
|
|
|
|
}
|
|
|
|
|
2017-09-22 23:44:02 +00:00
|
|
|
// CrioAnnotations returns the crio annotations of the container.
|
|
|
|
func (c *Container) CrioAnnotations() map[string]string {
|
|
|
|
return c.crioAnnotations
|
|
|
|
}
|
|
|
|
|
2017-04-19 18:55:17 +00:00
|
|
|
// Image returns the image of the container.
|
2017-07-17 19:42:14 +00:00
|
|
|
func (c *Container) Image() string {
|
2017-04-19 18:55:17 +00:00
|
|
|
return c.image
|
|
|
|
}
|
|
|
|
|
2017-08-14 19:29:53 +00:00
|
|
|
// ImageName returns the image name of the container.
|
|
|
|
func (c *Container) ImageName() string {
|
|
|
|
return c.imageName
|
|
|
|
}
|
|
|
|
|
|
|
|
// ImageRef returns the image ref of the container.
|
|
|
|
func (c *Container) ImageRef() string {
|
|
|
|
return c.imageRef
|
|
|
|
}
|
|
|
|
|
2017-04-19 18:55:17 +00:00
|
|
|
// Sandbox returns the sandbox name of the container.
|
|
|
|
func (c *Container) Sandbox() string {
|
|
|
|
return c.sandbox
|
|
|
|
}
|
|
|
|
|
2017-08-14 17:30:24 +00:00
|
|
|
// Dir returns the the dir of the container
|
|
|
|
func (c *Container) Dir() string {
|
|
|
|
return c.dir
|
|
|
|
}
|
|
|
|
|
2017-04-19 18:55:17 +00:00
|
|
|
// NetNsPath returns the path to the network namespace of the container.
|
|
|
|
func (c *Container) NetNsPath() (string, error) {
|
|
|
|
if c.state == nil {
|
|
|
|
return "", fmt.Errorf("container state is not populated")
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.netns == nil {
|
|
|
|
return fmt.Sprintf("/proc/%d/ns/net", c.state.Pid), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.netns.Path(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Metadata returns the metadata of the container.
|
|
|
|
func (c *Container) Metadata() *pb.ContainerMetadata {
|
|
|
|
return c.metadata
|
|
|
|
}
|
2017-06-29 19:16:06 +00:00
|
|
|
|
|
|
|
// State returns the state of the running container
|
|
|
|
func (c *Container) State() *ContainerState {
|
|
|
|
c.opLock.Lock()
|
|
|
|
defer c.opLock.Unlock()
|
|
|
|
return c.state
|
|
|
|
}
|
2017-08-14 19:43:56 +00:00
|
|
|
|
|
|
|
// AddVolume adds a volume to list of container volumes.
|
|
|
|
func (c *Container) AddVolume(v ContainerVolume) {
|
|
|
|
c.volumes = append(c.volumes, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Volumes returns the list of container volumes.
|
|
|
|
func (c *Container) Volumes() []ContainerVolume {
|
|
|
|
return c.volumes
|
|
|
|
|
|
|
|
}
|
2017-08-31 13:16:25 +00:00
|
|
|
|
|
|
|
// SetMountPoint sets the container mount point
|
|
|
|
func (c *Container) SetMountPoint(mp string) {
|
|
|
|
c.mountPoint = mp
|
|
|
|
}
|
|
|
|
|
|
|
|
// MountPoint returns the container mount point
|
|
|
|
func (c *Container) MountPoint() string {
|
|
|
|
return c.mountPoint
|
|
|
|
}
|
2017-09-12 10:17:44 +00:00
|
|
|
|
|
|
|
// SetState sets the conainer state
|
|
|
|
//
|
|
|
|
// XXX: DO NOT EVER USE THIS, THIS IS JUST USEFUL FOR MOCKING!!!
|
|
|
|
func (c *Container) SetState(state *ContainerState) {
|
|
|
|
c.state = state
|
|
|
|
}
|