cri-o/libkpod/containerData.go

225 lines
7 KiB
Go
Raw Normal View History

package libkpod
import (
"encoding/json"
"time"
"k8s.io/apimachinery/pkg/fields"
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
"github.com/containers/storage"
"github.com/kubernetes-incubator/cri-o/cmd/kpod/docker"
"github.com/kubernetes-incubator/cri-o/libkpod/common"
"github.com/kubernetes-incubator/cri-o/libkpod/driver"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/oci"
"github.com/kubernetes-incubator/cri-o/pkg/annotations"
"github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
// ContainerData handles the data used when inspecting a container
type ContainerData struct {
ID string
Name string
LogPath string
Labels fields.Set
Annotations fields.Set
State *oci.ContainerState
Metadata *pb.ContainerMetadata
BundlePath string
StopSignal string
Type string `json:"type"`
FromImage string `json:"image,omitempty"`
FromImageID string `json:"image-id"`
MountPoint string `json:"mountpoint,omitempty"`
MountLabel string
Mounts []specs.Mount
AppArmorProfile string
ImageAnnotations map[string]string `json:"annotations,omitempty"`
ImageCreatedBy string `json:"created-by,omitempty"`
OCIv1 v1.Image `json:"ociv1,omitempty"`
Docker docker.V2Image `json:"docker,omitempty"`
SizeRw uint `json:"SizeRw,omitempty"`
SizeRootFs uint `json:"SizeRootFs,omitempty"`
Args []string
ResolvConfPath string
HostnamePath string
HostsPath string
GraphDriver driverData
}
type driverData struct {
Name string
Data map[string]string
}
// GetContainerData gets the ContainerData for a container with the given name in the given store.
// If size is set to true, it will also determine the size of the container
func GetContainerData(store storage.Store, name string, size bool) (*ContainerData, error) {
ctr, err := inspectContainer(store, name)
if err != nil {
return nil, errors.Wrapf(err, "error reading build container %q", name)
}
cid, err := libkpodimage.GetContainerCopyData(store, name)
if err != nil {
return nil, errors.Wrapf(err, "error reading container image data")
}
config, err := store.FromContainerDirectory(ctr.ID(), "config.json")
if err != nil {
return nil, err
}
var m specs.Spec
if err = json.Unmarshal(config, &m); err != nil {
return nil, err
}
driverName, err := driver.GetDriverName(store)
if err != nil {
return nil, err
}
topLayer, err := GetContainerTopLayerID(store, ctr.ID())
if err != nil {
return nil, err
}
driverMetadata, err := driver.GetDriverMetadata(store, topLayer)
if err != nil {
return nil, err
}
data := &ContainerData{
ID: ctr.ID(),
Name: ctr.Name(),
LogPath: ctr.LogPath(),
Labels: ctr.Labels(),
Annotations: ctr.Annotations(),
State: ctr.State(),
Metadata: ctr.Metadata(),
BundlePath: ctr.BundlePath(),
StopSignal: ctr.GetStopSignal(),
Args: m.Process.Args,
Type: cid.Type,
FromImage: cid.FromImage,
FromImageID: cid.FromImageID,
MountPoint: cid.MountPoint,
ImageAnnotations: cid.ImageAnnotations,
ImageCreatedBy: cid.ImageCreatedBy,
OCIv1: cid.OCIv1,
Docker: cid.Docker,
GraphDriver: driverData{
Name: driverName,
Data: driverMetadata,
},
MountLabel: m.Linux.MountLabel,
Mounts: m.Mounts,
AppArmorProfile: m.Process.ApparmorProfile,
ResolvConfPath: "",
HostnamePath: "",
HostsPath: "",
}
if size {
sizeRootFs, err := GetContainerRootFsSize(store, data.ID)
if err != nil {
return nil, errors.Wrapf(err, "error reading size for container %q", name)
}
data.SizeRootFs = uint(sizeRootFs)
sizeRw, err := GetContainerRwSize(store, data.ID)
if err != nil {
return nil, errors.Wrapf(err, "error reading RWSize for container %q", name)
}
data.SizeRw = uint(sizeRw)
}
return data, nil
}
// Get an oci.Container and update its status
func inspectContainer(store storage.Store, container string) (*oci.Container, error) {
ociCtr, err := getOCIContainer(store, container)
if err != nil {
return nil, err
}
// call oci.New() to get the runtime
runtime, err := getOCIRuntime(store, container)
if err != nil {
return nil, err
}
// call runtime.UpdateStatus()
err = runtime.UpdateStatus(ociCtr)
if err != nil {
return nil, err
}
return ociCtr, nil
}
// get an oci.Container instance for a given container ID
func getOCIContainer(store storage.Store, container string) (*oci.Container, error) {
ctr, err := FindContainer(store, container)
if err != nil {
return nil, err
}
config, err := store.FromContainerDirectory(ctr.ID, "config.json")
if err != nil {
return nil, err
}
var m specs.Spec
if err = json.Unmarshal(config, &m); err != nil {
return nil, err
}
labels := make(map[string]string)
err = json.Unmarshal([]byte(m.Annotations[annotations.Labels]), &labels)
if len(m.Annotations[annotations.Labels]) > 0 && err != nil {
return nil, err
}
name := ctr.Names[0]
var metadata pb.ContainerMetadata
err = json.Unmarshal([]byte(m.Annotations[annotations.Metadata]), &metadata)
if len(m.Annotations[annotations.Metadata]) > 0 && err != nil {
return nil, err
}
tty := common.IsTrue(m.Annotations[annotations.TTY])
stdin := common.IsTrue(m.Annotations[annotations.Stdin])
stdinOnce := common.IsTrue(m.Annotations[annotations.StdinOnce])
containerPath, err := store.ContainerRunDirectory(ctr.ID)
if err != nil {
return nil, err
}
containerDir, err := store.ContainerDirectory(ctr.ID)
if err != nil {
return nil, err
}
img, _ := m.Annotations[annotations.Image]
kubeAnnotations := make(map[string]string)
err = json.Unmarshal([]byte(m.Annotations[annotations.Annotations]), &kubeAnnotations)
if len(m.Annotations[annotations.Annotations]) > 0 && err != nil {
return nil, err
}
created := time.Time{}
if len(m.Annotations[annotations.Created]) > 0 {
created, err = time.Parse(time.RFC3339Nano, m.Annotations[annotations.Created])
if err != nil {
return nil, err
}
}
// create a new OCI Container. kpod currently doesn't deal with pod sandboxes, so the fields for netns, privileged, and trusted are left empty
return oci.NewContainer(ctr.ID, name, containerPath, m.Annotations[annotations.LogPath], nil, labels, kubeAnnotations, img, &metadata, ctr.ImageID, tty, stdin, stdinOnce, false, false, containerDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
}
func getOCIRuntime(store storage.Store, container string) (*oci.Runtime, error) {
// TODO: Move server default config out of server so that it can be used instead of this
return oci.New("/usr/bin/runc", "", "runtime", "/usr/local/libexec/crio/conmon", []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, "cgroupfs")
}