From 85c19c14835f990f322f9a2000f5d45d2087dbbb Mon Sep 17 00:00:00 2001 From: Starnop Date: Mon, 21 May 2018 00:34:59 +0800 Subject: [PATCH] container state Signed-off-by: Starnop --- cri/config/config.go | 7 + cri/criservice.go | 15 +- cri/v1alpha1/cri.go | 105 +- cri/v1alpha1/cri_utils.go | 162 +- cri/v1alpha2/cri.go | 102 +- cri/v1alpha2/cri_utils.go | 109 +- ctrd/container.go | 16 + ctrd/interface.go | 8 + ctrd/snapshot.go | 27 + ctrd/utils.go | 5 +- ctrd/wrapper_client.go | 4 +- daemon/daemon.go | 2 +- daemon/mgr/container.go | 25 +- daemon/mgr/snapshot.go | 153 + daemon/mgr/snapshot_test.go | 66 + .../github.com/containerd/cgroups/.gitignore | 1 + .../github.com/containerd/cgroups/.travis.yml | 16 + vendor/github.com/containerd/cgroups/LICENSE | 201 + .../containerd/cgroups/Protobuild.toml | 39 + .../github.com/containerd/cgroups/README.md | 112 + vendor/github.com/containerd/cgroups/blkio.go | 326 ++ .../containerd/cgroups/blkio_test.go | 51 + .../github.com/containerd/cgroups/cgroup.go | 445 ++ .../containerd/cgroups/cgroup_test.go | 354 ++ .../github.com/containerd/cgroups/control.go | 77 + vendor/github.com/containerd/cgroups/cpu.go | 129 + .../github.com/containerd/cgroups/cpuacct.go | 121 + .../github.com/containerd/cgroups/cpuset.go | 159 + .../github.com/containerd/cgroups/devices.go | 90 + .../github.com/containerd/cgroups/errors.go | 47 + .../github.com/containerd/cgroups/freezer.go | 82 + .../containerd/cgroups/hierarchy.go | 20 + .../github.com/containerd/cgroups/hugetlb.go | 109 + .../github.com/containerd/cgroups/memory.go | 325 ++ .../containerd/cgroups/memory_test.go | 106 + .../containerd/cgroups/metrics.pb.go | 4288 +++++++++++++++++ .../containerd/cgroups/metrics.pb.txt | 638 +++ .../containerd/cgroups/metrics.proto | 123 + .../containerd/cgroups/mock_test.go | 78 + vendor/github.com/containerd/cgroups/named.go | 39 + .../containerd/cgroups/named_test.go | 34 + .../github.com/containerd/cgroups/net_cls.go | 58 + .../github.com/containerd/cgroups/net_prio.go | 66 + vendor/github.com/containerd/cgroups/paths.go | 104 + .../containerd/cgroups/paths_test.go | 114 + .../containerd/cgroups/perf_event.go | 37 + vendor/github.com/containerd/cgroups/pids.go | 85 + vendor/github.com/containerd/cgroups/rdma.go | 153 + vendor/github.com/containerd/cgroups/state.go | 28 + .../containerd/cgroups/subsystem.go | 112 + .../github.com/containerd/cgroups/systemd.go | 131 + vendor/github.com/containerd/cgroups/ticks.go | 26 + vendor/github.com/containerd/cgroups/utils.go | 297 ++ vendor/github.com/containerd/cgroups/v1.go | 81 + .../runtime-spec/.gitattributes | 2 + .../opencontainers/runtime-spec/.gitignore | 3 + .../opencontainers/runtime-spec/.mailmap | 21 + .../runtime-spec/.pullapprove.yml | 27 + .../runtime-spec/.tool/version-doc.go | 25 + .../opencontainers/runtime-spec/.travis.yml | 25 + .../opencontainers/runtime-spec/ChangeLog | 684 +++ .../opencontainers/runtime-spec/GOVERNANCE.md | 70 + .../opencontainers/runtime-spec/MAINTAINERS | 8 + .../opencontainers/runtime-spec/Makefile | 94 + .../opencontainers/runtime-spec/README.md | 153 + .../opencontainers/runtime-spec/RELEASES.md | 51 + .../opencontainers/runtime-spec/bundle.md | 22 + .../runtime-spec/config-linux.md | 703 +++ .../runtime-spec/config-solaris.md | 120 + .../opencontainers/runtime-spec/config-vm.md | 68 + .../runtime-spec/config-windows.md | 175 + .../opencontainers/runtime-spec/config.md | 864 ++++ .../opencontainers/runtime-spec/glossary.md | 38 + .../runtime-spec/implementations.md | 35 + .../opencontainers/runtime-spec/meeting.ics | 39 + .../opencontainers/runtime-spec/principles.md | 46 + .../opencontainers/runtime-spec/project.md | 12 + .../runtime-spec/runtime-linux.md | 21 + .../opencontainers/runtime-spec/runtime.md | 140 + .../runtime-spec/schema/Makefile | 50 + .../runtime-spec/schema/README.md | 47 + .../runtime-spec/schema/config-linux.json | 238 + .../runtime-spec/schema/config-schema.json | 174 + .../runtime-spec/schema/config-solaris.json | 65 + .../runtime-spec/schema/config-vm.json | 60 + .../runtime-spec/schema/config-windows.json | 93 + .../runtime-spec/schema/defs-linux.json | 281 ++ .../runtime-spec/schema/defs-vm.json | 14 + .../runtime-spec/schema/defs.json | 155 + .../runtime-spec/schema/state-schema.json | 39 + .../schema/test/config/bad/invalid-json.json | 1 + .../schema/test/config/bad/linux-rdma.json | 15 + .../schema/test/config/good/linux-rdma.json | 22 + .../test/config/good/minimal-for-start.json | 16 + .../schema/test/config/good/minimal.json | 6 + .../schema/test/config/good/spec-example.json | 368 ++ .../schema/test/state/bad/invalid-json.json | 1 + .../schema/test/state/good/spec-example.json | 10 + .../runtime-spec/schema/validate.go | 100 + .../opencontainers/runtime-spec/spec.md | 48 + .../runtime-spec/specs-go/config.go | 56 +- .../runtime-spec/specs-go/version.go | 4 +- .../opencontainers/runtime-spec/style.md | 131 + 103 files changed, 15504 insertions(+), 44 deletions(-) create mode 100644 daemon/mgr/snapshot.go create mode 100644 daemon/mgr/snapshot_test.go create mode 100644 vendor/github.com/containerd/cgroups/.gitignore create mode 100644 vendor/github.com/containerd/cgroups/.travis.yml create mode 100644 vendor/github.com/containerd/cgroups/LICENSE create mode 100644 vendor/github.com/containerd/cgroups/Protobuild.toml create mode 100644 vendor/github.com/containerd/cgroups/README.md create mode 100644 vendor/github.com/containerd/cgroups/blkio.go create mode 100644 vendor/github.com/containerd/cgroups/blkio_test.go create mode 100644 vendor/github.com/containerd/cgroups/cgroup.go create mode 100644 vendor/github.com/containerd/cgroups/cgroup_test.go create mode 100644 vendor/github.com/containerd/cgroups/control.go create mode 100644 vendor/github.com/containerd/cgroups/cpu.go create mode 100644 vendor/github.com/containerd/cgroups/cpuacct.go create mode 100644 vendor/github.com/containerd/cgroups/cpuset.go create mode 100644 vendor/github.com/containerd/cgroups/devices.go create mode 100644 vendor/github.com/containerd/cgroups/errors.go create mode 100644 vendor/github.com/containerd/cgroups/freezer.go create mode 100644 vendor/github.com/containerd/cgroups/hierarchy.go create mode 100644 vendor/github.com/containerd/cgroups/hugetlb.go create mode 100644 vendor/github.com/containerd/cgroups/memory.go create mode 100644 vendor/github.com/containerd/cgroups/memory_test.go create mode 100644 vendor/github.com/containerd/cgroups/metrics.pb.go create mode 100644 vendor/github.com/containerd/cgroups/metrics.pb.txt create mode 100644 vendor/github.com/containerd/cgroups/metrics.proto create mode 100644 vendor/github.com/containerd/cgroups/mock_test.go create mode 100644 vendor/github.com/containerd/cgroups/named.go create mode 100644 vendor/github.com/containerd/cgroups/named_test.go create mode 100644 vendor/github.com/containerd/cgroups/net_cls.go create mode 100644 vendor/github.com/containerd/cgroups/net_prio.go create mode 100644 vendor/github.com/containerd/cgroups/paths.go create mode 100644 vendor/github.com/containerd/cgroups/paths_test.go create mode 100644 vendor/github.com/containerd/cgroups/perf_event.go create mode 100644 vendor/github.com/containerd/cgroups/pids.go create mode 100644 vendor/github.com/containerd/cgroups/rdma.go create mode 100644 vendor/github.com/containerd/cgroups/state.go create mode 100644 vendor/github.com/containerd/cgroups/subsystem.go create mode 100644 vendor/github.com/containerd/cgroups/systemd.go create mode 100644 vendor/github.com/containerd/cgroups/ticks.go create mode 100644 vendor/github.com/containerd/cgroups/utils.go create mode 100644 vendor/github.com/containerd/cgroups/v1.go create mode 100644 vendor/github.com/opencontainers/runtime-spec/.gitattributes create mode 100644 vendor/github.com/opencontainers/runtime-spec/.gitignore create mode 100644 vendor/github.com/opencontainers/runtime-spec/.mailmap create mode 100644 vendor/github.com/opencontainers/runtime-spec/.pullapprove.yml create mode 100644 vendor/github.com/opencontainers/runtime-spec/.tool/version-doc.go create mode 100644 vendor/github.com/opencontainers/runtime-spec/.travis.yml create mode 100644 vendor/github.com/opencontainers/runtime-spec/ChangeLog create mode 100644 vendor/github.com/opencontainers/runtime-spec/GOVERNANCE.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/MAINTAINERS create mode 100644 vendor/github.com/opencontainers/runtime-spec/Makefile create mode 100644 vendor/github.com/opencontainers/runtime-spec/README.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/RELEASES.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/bundle.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/config-linux.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/config-solaris.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/config-vm.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/config-windows.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/config.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/glossary.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/implementations.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/meeting.ics create mode 100644 vendor/github.com/opencontainers/runtime-spec/principles.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/project.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/runtime-linux.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/runtime.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/Makefile create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/README.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/config-linux.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/config-schema.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/config-solaris.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/config-vm.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/config-windows.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/defs-linux.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/defs-vm.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/defs.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/state-schema.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/invalid-json.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/linux-rdma.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/linux-rdma.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal-for-start.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/spec-example.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/state/bad/invalid-json.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/test/state/good/spec-example.json create mode 100644 vendor/github.com/opencontainers/runtime-spec/schema/validate.go create mode 100644 vendor/github.com/opencontainers/runtime-spec/spec.md create mode 100644 vendor/github.com/opencontainers/runtime-spec/style.md diff --git a/cri/config/config.go b/cri/config/config.go index c5e5b231e8..5952ca0705 100644 --- a/cri/config/config.go +++ b/cri/config/config.go @@ -1,5 +1,12 @@ package config +const ( + // DefaultNameSpace the default namespace of containerd + DefaultNameSpace = "default" + // CadvisorNameSpace the default namespace of the cadvisor will collect + CadvisorNameSpace = "k8s.io" +) + // Config defines the CRI configuration. type Config struct { // Listen is the listening address which servers CRI. diff --git a/cri/criservice.go b/cri/criservice.go index d236767c21..ded2770cda 100644 --- a/cri/criservice.go +++ b/cri/criservice.go @@ -7,6 +7,7 @@ import ( servicev1alpha1 "github.com/alibaba/pouch/cri/v1alpha1/service" criv1alpha2 "github.com/alibaba/pouch/cri/v1alpha2" servicev1alpha2 "github.com/alibaba/pouch/cri/v1alpha2/service" + "github.com/alibaba/pouch/ctrd" "github.com/alibaba/pouch/daemon/config" "github.com/alibaba/pouch/daemon/mgr" @@ -14,7 +15,7 @@ import ( ) // RunCriService start cri service if pouchd is specified with --enable-cri. -func RunCriService(daemonconfig *config.Config, containerMgr mgr.ContainerMgr, imageMgr mgr.ImageMgr, stopCh chan error) { +func RunCriService(daemonconfig *config.Config, client ctrd.APIClient, containerMgr mgr.ContainerMgr, imageMgr mgr.ImageMgr, stopCh chan error) { var err error defer func() { @@ -26,9 +27,9 @@ func RunCriService(daemonconfig *config.Config, containerMgr mgr.ContainerMgr, i } switch daemonconfig.CriConfig.CriVersion { case "v1alpha1": - err = runv1alpha1(daemonconfig, containerMgr, imageMgr) + err = runv1alpha1(daemonconfig, client, containerMgr, imageMgr) case "v1alpha2": - err = runv1alpha2(daemonconfig, containerMgr, imageMgr) + err = runv1alpha2(daemonconfig, client, containerMgr, imageMgr) default: err = fmt.Errorf("invalid CRI version,failed to start CRI service") } @@ -36,9 +37,9 @@ func RunCriService(daemonconfig *config.Config, containerMgr mgr.ContainerMgr, i } // Start CRI service with CRI version: v1alpha1 -func runv1alpha1(daemonconfig *config.Config, containerMgr mgr.ContainerMgr, imageMgr mgr.ImageMgr) error { +func runv1alpha1(daemonconfig *config.Config, client ctrd.APIClient, containerMgr mgr.ContainerMgr, imageMgr mgr.ImageMgr) error { logrus.Infof("Start CRI service with CRI version: v1alpha1") - criMgr, err := criv1alpha1.NewCriManager(daemonconfig, containerMgr, imageMgr) + criMgr, err := criv1alpha1.NewCriManager(daemonconfig, client, containerMgr, imageMgr) if err != nil { return fmt.Errorf("failed to get CriManager with error: %v", err) } @@ -76,9 +77,9 @@ func runv1alpha1(daemonconfig *config.Config, containerMgr mgr.ContainerMgr, ima } // Start CRI service with CRI version: v1alpha2 -func runv1alpha2(daemonconfig *config.Config, containerMgr mgr.ContainerMgr, imageMgr mgr.ImageMgr) error { +func runv1alpha2(daemonconfig *config.Config, client ctrd.APIClient, containerMgr mgr.ContainerMgr, imageMgr mgr.ImageMgr) error { logrus.Infof("Start CRI service with CRI version: v1alpha2") - criMgr, err := criv1alpha2.NewCriManager(daemonconfig, containerMgr, imageMgr) + criMgr, err := criv1alpha2.NewCriManager(daemonconfig, client, containerMgr, imageMgr) if err != nil { return fmt.Errorf("failed to get CriManager with error: %v", err) } diff --git a/cri/v1alpha1/cri.go b/cri/v1alpha1/cri.go index 9144595a30..18fb8285f1 100644 --- a/cri/v1alpha1/cri.go +++ b/cri/v1alpha1/cri.go @@ -12,6 +12,7 @@ import ( "time" apitypes "github.com/alibaba/pouch/apis/types" + "github.com/alibaba/pouch/ctrd" "github.com/alibaba/pouch/daemon/config" "github.com/alibaba/pouch/daemon/mgr" "github.com/alibaba/pouch/pkg/errtypes" @@ -60,6 +61,15 @@ const ( // resolvConfPath is the abs path of resolv.conf on host or container. resolvConfPath = "/etc/resolv.conf" + + // statsCollectPeriod is the time duration we sync stats from containerd. + statsCollectPeriod = 10 + + // defaultSnapshotterName is the default Snapshotter name. + defaultSnapshotterName = "overlayfs" + + // snapshotPlugin implements a snapshotter. + snapshotPlugin = "io.containerd.snapshotter.v1" ) var ( @@ -85,6 +95,9 @@ type CriManager struct { ImageMgr mgr.ImageMgr CniMgr CniMgr + // Client is used to interact with containerd. + Client ctrd.APIClient + // StreamServer is the stream server of CRI serves container streaming request. StreamServer Server @@ -95,10 +108,16 @@ type CriManager struct { SandboxImage string // SandboxStore stores the configuration of sandboxes. SandboxStore *meta.Store + + // SnapshotStore stores information of all snapshots. + SnapshotStore *mgr.SnapshotStore + + // ImageFSUUID is the device uuid of image filesystem. + ImageFSUUID string } // NewCriManager creates a brand new cri manager. -func NewCriManager(config *config.Config, ctrMgr mgr.ContainerMgr, imgMgr mgr.ImageMgr) (CriMgr, error) { +func NewCriManager(config *config.Config, cli ctrd.APIClient, ctrMgr mgr.ContainerMgr, imgMgr mgr.ImageMgr) (CriMgr, error) { streamServer, err := newStreamServer(ctrMgr, streamServerAddress, streamServerPort) if err != nil { return nil, fmt.Errorf("failed to create stream server for cri manager: %v", err) @@ -108,9 +127,11 @@ func NewCriManager(config *config.Config, ctrMgr mgr.ContainerMgr, imgMgr mgr.Im ContainerMgr: ctrMgr, ImageMgr: imgMgr, CniMgr: NewCniManager(&config.CriConfig), + Client: cli, StreamServer: streamServer, SandboxBaseDir: path.Join(config.HomeDir, "sandboxes"), SandboxImage: config.CriConfig.SandboxImage, + SnapshotStore: mgr.NewSnapshotStore(), } c.SandboxStore, err = meta.NewStore(meta.Config{ @@ -127,6 +148,19 @@ func NewCriManager(config *config.Config, ctrMgr mgr.ContainerMgr, imgMgr mgr.Im return nil, fmt.Errorf("failed to create sandbox meta store: %v", err) } + imageFSPath := imageFSPath(path.Join(config.HomeDir, "containerd/root"), defaultSnapshotterName) + c.ImageFSUUID, err = getDeviceUUID(imageFSPath) + if err != nil { + return nil, fmt.Errorf("failed to get imagefs uuid of %q: %v", imageFSPath, err) + } + + snapshotsSyncer := mgr.NewSnapshotsSyncer( + c.SnapshotStore, + c.Client, + time.Duration(statsCollectPeriod)*time.Second, + ) + snapshotsSyncer.Start() + return NewCriWrapper(c), nil } @@ -679,12 +713,55 @@ func (c *CriManager) ContainerStatus(ctx context.Context, r *runtime.ContainerSt // ContainerStats returns stats of the container. If the container does not // exist, the call returns an error. func (c *CriManager) ContainerStats(ctx context.Context, r *runtime.ContainerStatsRequest) (*runtime.ContainerStatsResponse, error) { - return nil, fmt.Errorf("ContainerStats Not Implemented Yet") + containerID := r.GetContainerId() + + container, err := c.ContainerMgr.Get(ctx, containerID) + if err != nil { + return nil, fmt.Errorf("failed to get container %q with error: %v", containerID, err) + } + + stats, err := c.ContainerMgr.Stats(ctx, containerID) + if err != nil { + return nil, fmt.Errorf("failed to get stats of container %q with error: %v", containerID, err) + } + + cs, err := c.getContainerMetrics(container, stats) + if err != nil { + return nil, fmt.Errorf("failed to decode container metrics: %v", err) + } + + return &runtime.ContainerStatsResponse{Stats: cs}, nil } // ListContainerStats returns stats of all running containers. func (c *CriManager) ListContainerStats(ctx context.Context, r *runtime.ListContainerStatsRequest) (*runtime.ListContainerStatsResponse, error) { - return nil, fmt.Errorf("ListContainerStats Not Implemented Yet") + opts := &mgr.ContainerListOption{All: true} + filter := func(c *mgr.Container) bool { + return true + } + containers, err := c.ContainerMgr.List(ctx, filter, opts) + if err != nil { + return nil, fmt.Errorf("failed to list containers: %v", err) + } + + result := &runtime.ListContainerStatsResponse{} + for _, container := range containers { + stats, err := c.ContainerMgr.Stats(ctx, container.ID) + if err != nil { + logrus.Errorf("failed to get stats of container %q: %v", container.ID, err) + continue + } + + cs, err := c.getContainerMetrics(container, stats) + if err != nil { + logrus.Errorf("failed to decode metrics of container %q: %v", container.ID, err) + continue + } + + result.Stats = append(result.Stats, cs) + } + + return result, nil } // UpdateContainerResources updates ContainerConfig of the container. @@ -907,5 +984,25 @@ func (c *CriManager) RemoveImage(ctx context.Context, r *runtime.RemoveImageRequ // ImageFsInfo returns information of the filesystem that is used to store images. func (c *CriManager) ImageFsInfo(ctx context.Context, r *runtime.ImageFsInfoRequest) (*runtime.ImageFsInfoResponse, error) { - return nil, fmt.Errorf("ImageFsInfo Not Implemented Yet") + snapshots := c.SnapshotStore.List() + timestamp := time.Now().UnixNano() + var usedBytes, inodesUsed uint64 + for _, sn := range snapshots { + // Use the oldest timestamp as the timestamp of imagefs info. + if sn.Timestamp < timestamp { + timestamp = sn.Timestamp + } + usedBytes += sn.Size + inodesUsed += sn.Inodes + } + return &runtime.ImageFsInfoResponse{ + ImageFilesystems: []*runtime.FilesystemUsage{ + { + Timestamp: timestamp, + StorageId: &runtime.StorageIdentifier{Uuid: c.ImageFSUUID}, + UsedBytes: &runtime.UInt64Value{Value: usedBytes}, + InodesUsed: &runtime.UInt64Value{Value: inodesUsed}, + }, + }, + }, nil } diff --git a/cri/v1alpha1/cri_utils.go b/cri/v1alpha1/cri_utils.go index 1904629950..d81b2b641f 100644 --- a/cri/v1alpha1/cri_utils.go +++ b/cri/v1alpha1/cri_utils.go @@ -7,8 +7,10 @@ import ( "io/ioutil" "os" "path" + "path/filepath" "strconv" "strings" + "syscall" "time" apitypes "github.com/alibaba/pouch/apis/types" @@ -16,7 +18,12 @@ import ( "github.com/alibaba/pouch/pkg/utils" "github.com/go-openapi/strfmt" + "github.com/containerd/cgroups" + containerdtypes "github.com/containerd/containerd/api/types" + containerdmount "github.com/containerd/containerd/mount" + "github.com/containerd/typeurl" "golang.org/x/net/context" + "golang.org/x/sys/unix" "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" ) @@ -258,6 +265,10 @@ func makeSandboxPouchConfig(config *runtime.PodSandboxConfig, image string) (*ap return nil, err } + // Apply resource options. + if lc := config.GetLinux(); lc != nil { + hc.CgroupParent = lc.CgroupParent + } return createConfig, nil } @@ -277,11 +288,17 @@ func toCriSandbox(c *mgr.Container) (*runtime.PodSandbox, error) { return nil, err } labels, annotations := extractLabels(c.Config.Labels) + + createdAt, err := toCriTimestamp(c.Created) + if err != nil { + return nil, fmt.Errorf("failed to parse create timestamp for container %q: %v", c.ID, err) + } + return &runtime.PodSandbox{ - Id: c.ID, - Metadata: metadata, - State: state, - // TODO: fill "CreatedAt" when it is appropriate. + Id: c.ID, + Metadata: metadata, + State: state, + CreatedAt: createdAt, Labels: labels, Annotations: annotations, }, nil @@ -608,7 +625,15 @@ func applyContainerSecurityContext(lc *runtime.LinuxContainerConfig, podSandboxI // Apply Linux-specific options if applicable. func (c *CriManager) updateCreateConfig(createConfig *apitypes.ContainerCreateConfig, config *runtime.ContainerConfig, sandboxConfig *runtime.PodSandboxConfig, podSandboxID string) error { if lc := config.GetLinux(); lc != nil { - // TODO: resource restriction. + resources := lc.GetResources() + if resources != nil { + createConfig.HostConfig.Resources.CPUPeriod = resources.GetCpuPeriod() + createConfig.HostConfig.Resources.CPUQuota = resources.GetCpuQuota() + createConfig.HostConfig.Resources.CPUShares = resources.GetCpuShares() + createConfig.HostConfig.Resources.Memory = resources.GetMemoryLimitInBytes() + createConfig.HostConfig.Resources.CpusetCpus = resources.GetCpusetCpus() + createConfig.HostConfig.Resources.CpusetMems = resources.GetCpusetMems() + } // Apply security context. if err := applyContainerSecurityContext(lc, podSandboxID, &createConfig.ContainerConfig, createConfig.HostConfig); err != nil { @@ -616,7 +641,10 @@ func (c *CriManager) updateCreateConfig(createConfig *apitypes.ContainerCreateCo } } - // TODO: apply cgroupParent derived from the sandbox config. + // Apply cgroupsParent derived from the sandbox config. + if sandboxConfig.GetLinux().GetCgroupParent() != "" { + createConfig.HostConfig.CgroupParent = sandboxConfig.GetLinux().GetCgroupParent() + } return nil } @@ -643,6 +671,10 @@ func toCriContainer(c *mgr.Container) (*runtime.Container, error) { labels, annotations := extractLabels(c.Config.Labels) sandboxID := c.Config.Labels[sandboxIDLabelKey] + createdAt, err := toCriTimestamp(c.Created) + if err != nil { + return nil, fmt.Errorf("failed to parse create timestamp for container %q: %v", c.ID, err) + } return &runtime.Container{ Id: c.ID, PodSandboxId: sandboxID, @@ -650,9 +682,9 @@ func toCriContainer(c *mgr.Container) (*runtime.Container, error) { Image: &runtime.ImageSpec{Image: c.Config.Image}, ImageRef: c.Image, State: state, - // TODO: fill "CreatedAt" when it is appropriate. - Labels: labels, - Annotations: annotations, + CreatedAt: createdAt, + Labels: labels, + Annotations: annotations, }, nil } @@ -770,3 +802,115 @@ func parseUserFromImageUser(id string) string { // no group, just return the id return id } + +func (c *CriManager) getContainerMetrics(meta *mgr.Container, stats *containerdtypes.Metric) (*runtime.ContainerStats, error) { + var usedBytes, inodesUsed uint64 + cs := &runtime.ContainerStats{} + + sn, err := c.SnapshotStore.Get(meta.ID) + if err == nil { + usedBytes = sn.Size + inodesUsed = sn.Inodes + } + cs.WritableLayer = &runtime.FilesystemUsage{ + Timestamp: sn.Timestamp, + StorageId: &runtime.StorageIdentifier{ + Uuid: c.ImageFSUUID, + }, + UsedBytes: &runtime.UInt64Value{usedBytes}, + InodesUsed: &runtime.UInt64Value{inodesUsed}, + } + + metadata, err := parseContainerName(meta.Name) + if err != nil { + return nil, fmt.Errorf("failed to get metadata of container %q: %v", meta.ID, err) + } + + labels, annotations := extractLabels(meta.Config.Labels) + + cs.Attributes = &runtime.ContainerAttributes{ + Id: meta.ID, + Metadata: metadata, + Labels: labels, + Annotations: annotations, + } + + if stats != nil { + s, err := typeurl.UnmarshalAny(stats.Data) + if err != nil { + return nil, fmt.Errorf("failed to extract container metrics: %v", err) + } + metrics := s.(*cgroups.Metrics) + if metrics.CPU != nil && metrics.CPU.Usage != nil { + cs.Cpu = &runtime.CpuUsage{ + Timestamp: stats.Timestamp.UnixNano(), + UsageCoreNanoSeconds: &runtime.UInt64Value{metrics.CPU.Usage.Total}, + } + } + if metrics.Memory != nil && metrics.Memory.Usage != nil { + cs.Memory = &runtime.MemoryUsage{ + Timestamp: stats.Timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{metrics.Memory.Usage.Usage}, + } + } + } + + return cs, nil +} + +// imageFSPath returns containerd image filesystem path. +func imageFSPath(rootDir, snapshotter string) string { + return filepath.Join(rootDir, fmt.Sprintf("%s.%s", snapshotPlugin, snapshotter)) +} + +// getDeviceUUID gets device uuid for a given path. +func getDeviceUUID(path string) (string, error) { + mount, err := lookupMount(path) + if err != nil { + return "", err + } + rdev := unix.Mkdev(uint32(mount.Major), uint32(mount.Minor)) + return deviceUUID(rdev) +} + +// lookupMount gets mount info of a given path. +func lookupMount(path string) (containerdmount.Info, error) { + return containerdmount.Lookup(path) +} + +// deviceUUID gets device uuid of a device. The passed in rdev should +// be linux device number. +func deviceUUID(rdev uint64) (string, error) { + const uuidDir = "/dev/disk/by-uuid" + files, err := ioutil.ReadDir(uuidDir) + if err != nil { + return "", err + } + for _, file := range files { + path := filepath.Join(uuidDir, file.Name()) + + trdev, err := blkrdev(path) + if err != nil { + continue + } + + if rdev == trdev { + return file.Name(), nil + } + } + + return "", fmt.Errorf("device %d not found", rdev) +} + +// blkdev returns the rdev of a block device or an error if not a block device +func blkrdev(device string) (uint64, error) { + info, err := os.Stat(device) + if err != nil { + return 0, err + } + stat := info.Sys().(*syscall.Stat_t) + if (stat.Mode & syscall.S_IFMT) != syscall.S_IFBLK { + return 0, fmt.Errorf("%s is not a block device", device) + } + return stat.Rdev, nil +} diff --git a/cri/v1alpha2/cri.go b/cri/v1alpha2/cri.go index cadb266eda..f54c4c8a0f 100644 --- a/cri/v1alpha2/cri.go +++ b/cri/v1alpha2/cri.go @@ -12,6 +12,7 @@ import ( "time" apitypes "github.com/alibaba/pouch/apis/types" + "github.com/alibaba/pouch/ctrd" "github.com/alibaba/pouch/daemon/config" "github.com/alibaba/pouch/daemon/mgr" "github.com/alibaba/pouch/pkg/errtypes" @@ -60,6 +61,15 @@ const ( // resolvConfPath is the abs path of resolv.conf on host or container. resolvConfPath = "/etc/resolv.conf" + + // statsCollectPeriod is the time duration we sync stats from containerd. + statsCollectPeriod = 10 + + // defaultSnapshotterName is the default Snapshotter name. + defaultSnapshotterName = "overlayfs" + + // snapshotPlugin implements a snapshotter. + snapshotPlugin = "io.containerd.snapshotter.v1" ) var ( @@ -85,6 +95,8 @@ type CriManager struct { ImageMgr mgr.ImageMgr CniMgr CniMgr + // Client is used to interact with containerd. + Client ctrd.APIClient // StreamServer is the stream server of CRI serves container streaming request. StreamServer Server @@ -93,12 +105,19 @@ type CriManager struct { // SandboxImage is the image used by sandbox container. SandboxImage string + // SandboxStore stores the configuration of sandboxes. SandboxStore *meta.Store + + // SnapshotStore stores information of all snapshots. + SnapshotStore *mgr.SnapshotStore + + // imageFSPath is the path to image filesystem. + imageFSPath string } // NewCriManager creates a brand new cri manager. -func NewCriManager(config *config.Config, ctrMgr mgr.ContainerMgr, imgMgr mgr.ImageMgr) (CriMgr, error) { +func NewCriManager(config *config.Config, cli ctrd.APIClient, ctrMgr mgr.ContainerMgr, imgMgr mgr.ImageMgr) (CriMgr, error) { streamServer, err := newStreamServer(ctrMgr, streamServerAddress, streamServerPort) if err != nil { return nil, fmt.Errorf("failed to create stream server for cri manager: %v", err) @@ -108,9 +127,11 @@ func NewCriManager(config *config.Config, ctrMgr mgr.ContainerMgr, imgMgr mgr.Im ContainerMgr: ctrMgr, ImageMgr: imgMgr, CniMgr: NewCniManager(&config.CriConfig), + Client: cli, StreamServer: streamServer, SandboxBaseDir: path.Join(config.HomeDir, "sandboxes"), SandboxImage: config.CriConfig.SandboxImage, + SnapshotStore: mgr.NewSnapshotStore(), } c.SandboxStore, err = meta.NewStore(meta.Config{ @@ -127,6 +148,16 @@ func NewCriManager(config *config.Config, ctrMgr mgr.ContainerMgr, imgMgr mgr.Im return nil, fmt.Errorf("failed to create sandbox meta store: %v", err) } + c.imageFSPath = imageFSPath(path.Join(config.HomeDir, "containerd/root"), defaultSnapshotterName) + logrus.Infof("Get image filesystem path %q", c.imageFSPath) + + snapshotsSyncer := mgr.NewSnapshotsSyncer( + c.SnapshotStore, + c.Client, + time.Duration(statsCollectPeriod)*time.Second, + ) + snapshotsSyncer.Start() + return NewCriWrapper(c), nil } @@ -676,12 +707,55 @@ func (c *CriManager) ContainerStatus(ctx context.Context, r *runtime.ContainerSt // ContainerStats returns stats of the container. If the container does not // exist, the call returns an error. func (c *CriManager) ContainerStats(ctx context.Context, r *runtime.ContainerStatsRequest) (*runtime.ContainerStatsResponse, error) { - return nil, fmt.Errorf("ContainerStats Not Implemented Yet") + containerID := r.GetContainerId() + + container, err := c.ContainerMgr.Get(ctx, containerID) + if err != nil { + return nil, fmt.Errorf("failed to get container %q with error: %v", containerID, err) + } + + stats, err := c.ContainerMgr.Stats(ctx, containerID) + if err != nil { + return nil, fmt.Errorf("failed to get stats of container %q with error: %v", containerID, err) + } + + cs, err := c.getContainerMetrics(container, stats) + if err != nil { + return nil, fmt.Errorf("failed to decode container metrics: %v", err) + } + + return &runtime.ContainerStatsResponse{Stats: cs}, nil } // ListContainerStats returns stats of all running containers. func (c *CriManager) ListContainerStats(ctx context.Context, r *runtime.ListContainerStatsRequest) (*runtime.ListContainerStatsResponse, error) { - return nil, fmt.Errorf("ListContainerStats Not Implemented Yet") + opts := &mgr.ContainerListOption{All: true} + filter := func(c *mgr.Container) bool { + return true + } + containers, err := c.ContainerMgr.List(ctx, filter, opts) + if err != nil { + return nil, fmt.Errorf("failed to list containers: %v", err) + } + + result := &runtime.ListContainerStatsResponse{} + for _, container := range containers { + stats, err := c.ContainerMgr.Stats(ctx, container.ID) + if err != nil { + logrus.Errorf("failed to get stats of container %q: %v", container.ID, err) + continue + } + + cs, err := c.getContainerMetrics(container, stats) + if err != nil { + logrus.Errorf("failed to decode metrics of container %q: %v", container.ID, err) + continue + } + + result.Stats = append(result.Stats, cs) + } + + return result, nil } // UpdateContainerResources updates ContainerConfig of the container. @@ -913,5 +987,25 @@ func (c *CriManager) RemoveImage(ctx context.Context, r *runtime.RemoveImageRequ // ImageFsInfo returns information of the filesystem that is used to store images. func (c *CriManager) ImageFsInfo(ctx context.Context, r *runtime.ImageFsInfoRequest) (*runtime.ImageFsInfoResponse, error) { - return nil, fmt.Errorf("ImageFsInfo Not Implemented Yet") + snapshots := c.SnapshotStore.List() + timestamp := time.Now().UnixNano() + var usedBytes, inodesUsed uint64 + for _, sn := range snapshots { + // Use the oldest timestamp as the timestamp of imagefs info. + if sn.Timestamp < timestamp { + timestamp = sn.Timestamp + } + usedBytes += sn.Size + inodesUsed += sn.Inodes + } + return &runtime.ImageFsInfoResponse{ + ImageFilesystems: []*runtime.FilesystemUsage{ + { + Timestamp: timestamp, + FsId: &runtime.FilesystemIdentifier{Mountpoint: c.imageFSPath}, + UsedBytes: &runtime.UInt64Value{Value: usedBytes}, + InodesUsed: &runtime.UInt64Value{Value: inodesUsed}, + }, + }, + }, nil } diff --git a/cri/v1alpha2/cri_utils.go b/cri/v1alpha2/cri_utils.go index d65b879ad0..b88cde69f5 100644 --- a/cri/v1alpha2/cri_utils.go +++ b/cri/v1alpha2/cri_utils.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path" + "path/filepath" "strconv" "strings" "time" @@ -15,6 +16,9 @@ import ( "github.com/alibaba/pouch/daemon/mgr" "github.com/alibaba/pouch/pkg/utils" + "github.com/containerd/cgroups" + containerdtypes "github.com/containerd/containerd/api/types" + "github.com/containerd/typeurl" "github.com/go-openapi/strfmt" "golang.org/x/net/context" runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" @@ -257,6 +261,10 @@ func makeSandboxPouchConfig(config *runtime.PodSandboxConfig, image string) (*ap if err != nil { return nil, err } + // Apply resource options. + if lc := config.GetLinux(); lc != nil { + hc.CgroupParent = lc.CgroupParent + } return createConfig, nil } @@ -277,11 +285,17 @@ func toCriSandbox(c *mgr.Container) (*runtime.PodSandbox, error) { return nil, err } labels, annotations := extractLabels(c.Config.Labels) + + createdAt, err := toCriTimestamp(c.Created) + if err != nil { + return nil, fmt.Errorf("failed to parse create timestamp for container %q: %v", c.ID, err) + } + return &runtime.PodSandbox{ - Id: c.ID, - Metadata: metadata, - State: state, - // TODO: fill "CreatedAt" when it is appropriate. + Id: c.ID, + Metadata: metadata, + State: state, + CreatedAt: createdAt, Labels: labels, Annotations: annotations, }, nil @@ -611,7 +625,15 @@ func applyContainerSecurityContext(lc *runtime.LinuxContainerConfig, podSandboxI // Apply Linux-specific options if applicable. func (c *CriManager) updateCreateConfig(createConfig *apitypes.ContainerCreateConfig, config *runtime.ContainerConfig, sandboxConfig *runtime.PodSandboxConfig, podSandboxID string) error { if lc := config.GetLinux(); lc != nil { - // TODO: resource restriction. + resources := lc.GetResources() + if resources != nil { + createConfig.HostConfig.Resources.CPUPeriod = resources.GetCpuPeriod() + createConfig.HostConfig.Resources.CPUQuota = resources.GetCpuQuota() + createConfig.HostConfig.Resources.CPUShares = resources.GetCpuShares() + createConfig.HostConfig.Resources.Memory = resources.GetMemoryLimitInBytes() + createConfig.HostConfig.Resources.CpusetCpus = resources.GetCpusetCpus() + createConfig.HostConfig.Resources.CpusetMems = resources.GetCpusetMems() + } // Apply security context. if err := applyContainerSecurityContext(lc, podSandboxID, &createConfig.ContainerConfig, createConfig.HostConfig); err != nil { @@ -619,7 +641,11 @@ func (c *CriManager) updateCreateConfig(createConfig *apitypes.ContainerCreateCo } } - // TODO: apply cgroupParent derived from the sandbox config. + // Apply cgroupsParent derived from the sandbox config. + if lc := sandboxConfig.GetLinux(); lc != nil { + // Apply Cgroup options. + createConfig.HostConfig.CgroupParent = lc.CgroupParent + } return nil } @@ -646,6 +672,11 @@ func toCriContainer(c *mgr.Container) (*runtime.Container, error) { labels, annotations := extractLabels(c.Config.Labels) sandboxID := c.Config.Labels[sandboxIDLabelKey] + createdAt, err := toCriTimestamp(c.Created) + if err != nil { + return nil, fmt.Errorf("failed to parse create timestamp for container %q: %v", c.ID, err) + } + return &runtime.Container{ Id: c.ID, PodSandboxId: sandboxID, @@ -653,9 +684,9 @@ func toCriContainer(c *mgr.Container) (*runtime.Container, error) { Image: &runtime.ImageSpec{Image: c.Config.Image}, ImageRef: c.Image, State: state, - // TODO: fill "CreatedAt" when it is appropriate. - Labels: labels, - Annotations: annotations, + CreatedAt: createdAt, + Labels: labels, + Annotations: annotations, }, nil } @@ -791,3 +822,63 @@ func (c *CriManager) attachLog(logPath string, containerID string) error { } return nil } + +func (c *CriManager) getContainerMetrics(meta *mgr.Container, stats *containerdtypes.Metric) (*runtime.ContainerStats, error) { + var usedBytes, inodesUsed uint64 + cs := &runtime.ContainerStats{} + + sn, err := c.SnapshotStore.Get(meta.ID) + if err == nil { + usedBytes = sn.Size + inodesUsed = sn.Inodes + } + cs.WritableLayer = &runtime.FilesystemUsage{ + Timestamp: sn.Timestamp, + FsId: &runtime.FilesystemIdentifier{ + Mountpoint: c.imageFSPath, + }, + UsedBytes: &runtime.UInt64Value{usedBytes}, + InodesUsed: &runtime.UInt64Value{inodesUsed}, + } + + metadata, err := parseContainerName(meta.Name) + if err != nil { + return nil, fmt.Errorf("failed to get metadata of container %q: %v", meta.ID, err) + } + + labels, annotations := extractLabels(meta.Config.Labels) + + cs.Attributes = &runtime.ContainerAttributes{ + Id: meta.ID, + Metadata: metadata, + Labels: labels, + Annotations: annotations, + } + + if stats != nil { + s, err := typeurl.UnmarshalAny(stats.Data) + if err != nil { + return nil, fmt.Errorf("failed to extract container metrics: %v", err) + } + metrics := s.(*cgroups.Metrics) + if metrics.CPU != nil && metrics.CPU.Usage != nil { + cs.Cpu = &runtime.CpuUsage{ + Timestamp: stats.Timestamp.UnixNano(), + UsageCoreNanoSeconds: &runtime.UInt64Value{metrics.CPU.Usage.Total}, + } + } + if metrics.Memory != nil && metrics.Memory.Usage != nil { + cs.Memory = &runtime.MemoryUsage{ + Timestamp: stats.Timestamp.UnixNano(), + WorkingSetBytes: &runtime.UInt64Value{metrics.Memory.Usage.Usage}, + } + } + } + + return cs, nil +} + +// imageFSPath returns containerd image filesystem path. +func imageFSPath(rootDir, snapshotter string) string { + return filepath.Join(rootDir, fmt.Sprintf("%s.%s", snapshotPlugin, snapshotter)) +} diff --git a/ctrd/container.go b/ctrd/container.go index c0d3a10ea5..79ea5eae7c 100644 --- a/ctrd/container.go +++ b/ctrd/container.go @@ -13,6 +13,7 @@ import ( "github.com/alibaba/pouch/pkg/errtypes" "github.com/containerd/containerd" + containerdtypes "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/leases" "github.com/containerd/containerd/linux/runctypes" @@ -38,6 +39,21 @@ type containerPack struct { skipStopHooks bool } +// ContainerStats returns stats of the container. +func (c *Client) ContainerStats(ctx context.Context, id string) (*containerdtypes.Metric, error) { + if !c.lock.Trylock(id) { + return nil, errtypes.ErrLockfailed + } + defer c.lock.Unlock(id) + + pack, err := c.watch.get(id) + if err != nil { + return nil, err + } + + return pack.task.Metrics(ctx) +} + // ExecContainer executes a process in container. func (c *Client) ExecContainer(ctx context.Context, process *Process) error { pack, err := c.watch.get(process.ContainerID) diff --git a/ctrd/interface.go b/ctrd/interface.go index fc8ba54f66..7dadb5837e 100644 --- a/ctrd/interface.go +++ b/ctrd/interface.go @@ -10,6 +10,7 @@ import ( "github.com/alibaba/pouch/pkg/jsonstream" "github.com/containerd/containerd" + containerdtypes "github.com/containerd/containerd/api/types" ctrdmetaimages "github.com/containerd/containerd/images" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/snapshots" @@ -37,6 +38,8 @@ type ContainerAPIClient interface { ContainerPIDs(ctx context.Context, id string) ([]int, error) // ContainerPID returns the container's init process id. ContainerPID(ctx context.Context, id string) (int, error) + // ContainerStats returns stats of the container. + ContainerStats(ctx context.Context, id string) (*containerdtypes.Metric, error) // ExecContainer executes a process in container. ExecContainer(ctx context.Context, process *Process) error // RecoverContainer reload the container from metadata and watch it, if program be restarted. @@ -85,4 +88,9 @@ type SnapshotAPIClient interface { // GetMounts returns the mounts for the active snapshot transaction identified // by key. GetMounts(ctx context.Context, id string) ([]mount.Mount, error) + // GetSnapshotUsage returns the resource usage of an active or committed snapshot + // excluding the usage of parent snapshots. + GetSnapshotUsage(ctx context.Context, id string) (snapshots.Usage, error) + // WalkSnapshot walk all snapshots. For each snapshot, the function will be called. + WalkSnapshot(ctx context.Context, fn func(context.Context, snapshots.Info) error) error } diff --git a/ctrd/snapshot.go b/ctrd/snapshot.go index 36de1f4af4..53f0fcc34a 100644 --- a/ctrd/snapshot.go +++ b/ctrd/snapshot.go @@ -77,3 +77,30 @@ func (c *Client) GetMounts(ctx context.Context, id string) ([]mount.Mount, error return service.Mounts(ctx, id) } + +// GetSnapshotUsage returns the resource usage of an active or committed snapshot +// excluding the usage of parent snapshots. +func (c *Client) GetSnapshotUsage(ctx context.Context, id string) (snapshots.Usage, error) { + wrapperCli, err := c.Get(ctx) + if err != nil { + return snapshots.Usage{}, fmt.Errorf("failed to get a containerd grpc client: %v", err) + } + + service := wrapperCli.client.SnapshotService(defaultSnapshotterName) + defer service.Close() + + return service.Usage(ctx, id) +} + +// WalkSnapshot walk all snapshots. For each snapshot, the function will be called. +func (c *Client) WalkSnapshot(ctx context.Context, fn func(context.Context, snapshots.Info) error) error { + wrapperCli, err := c.Get(ctx) + if err != nil { + return fmt.Errorf("failed to get a containerd grpc client: %v", err) + } + + service := wrapperCli.client.SnapshotService(defaultSnapshotterName) + defer service.Close() + + return service.Walk(ctx, fn) +} diff --git a/ctrd/utils.go b/ctrd/utils.go index 6c06b4cdaa..b0e85955f9 100644 --- a/ctrd/utils.go +++ b/ctrd/utils.go @@ -9,6 +9,7 @@ import ( "time" "github.com/alibaba/pouch/apis/types" + "github.com/alibaba/pouch/cri/config" "github.com/alibaba/pouch/pkg/utils" "github.com/containerd/containerd/containers" @@ -18,12 +19,12 @@ import ( "github.com/containerd/containerd/remotes/docker" "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/specs-go/v1" - specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/runtime-spec/specs-go" ) // NewDefaultSpec new a template spec with default. func NewDefaultSpec(ctx context.Context, id string) (*specs.Spec, error) { - ctx = namespaces.WithNamespace(ctx, namespaces.Default) + ctx = namespaces.WithNamespace(ctx, config.DefaultNameSpace) return oci.GenerateSpec(ctx, nil, &containers.Container{ID: id}) } diff --git a/ctrd/wrapper_client.go b/ctrd/wrapper_client.go index 88bb221fcb..65f88767dc 100644 --- a/ctrd/wrapper_client.go +++ b/ctrd/wrapper_client.go @@ -5,6 +5,8 @@ import ( "fmt" "sync" + "github.com/alibaba/pouch/cri/config" + "github.com/containerd/containerd" "github.com/pkg/errors" ) @@ -27,7 +29,7 @@ type WrapperClient struct { func newWrapperClient(rpcAddr string, maxStreamsClient int) (*WrapperClient, error) { options := []containerd.ClientOpt{ - containerd.WithDefaultNamespace("default"), + containerd.WithDefaultNamespace(config.DefaultNameSpace), } cli, err := containerd.New(rpcAddr, options...) if err != nil { diff --git a/daemon/daemon.go b/daemon/daemon.go index 36ad2d4b9c..68f9f9c5a0 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -214,7 +214,7 @@ func (d *Daemon) Run() error { }() criStopCh := make(chan error) - go criservice.RunCriService(d.config, d.containerMgr, d.imageMgr, criStopCh) + go criservice.RunCriService(d.config, d.Containerd(), d.containerMgr, d.imageMgr, criStopCh) err = <-criStopCh if err != nil { diff --git a/daemon/mgr/container.go b/daemon/mgr/container.go index 02aa886b63..bbfff5af1e 100644 --- a/daemon/mgr/container.go +++ b/daemon/mgr/container.go @@ -16,6 +16,7 @@ import ( "github.com/alibaba/pouch/apis/opts" "github.com/alibaba/pouch/apis/plugins" "github.com/alibaba/pouch/apis/types" + criconfig "github.com/alibaba/pouch/cri/config" "github.com/alibaba/pouch/ctrd" "github.com/alibaba/pouch/daemon/config" "github.com/alibaba/pouch/daemon/containerio" @@ -30,8 +31,8 @@ import ( "github.com/alibaba/pouch/storage/quota" volumetypes "github.com/alibaba/pouch/storage/volume/types" + containerdtypes "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/namespaces" "github.com/docker/libnetwork" "github.com/go-openapi/strfmt" "github.com/imdario/mergo" @@ -76,6 +77,9 @@ type ContainerMgr interface { // Unpause a container. Unpause(ctx context.Context, name string) error + // Stats of a container. + Stats(ctx context.Context, name string) (*containerdtypes.Metric, error) + // Attach a container. Attach(ctx context.Context, name string, attach *AttachConfig) error @@ -721,6 +725,23 @@ func (mgr *ContainerManager) Unpause(ctx context.Context, name string) error { return nil } +// Stats gets the stat of a container. +func (mgr *ContainerManager) Stats(ctx context.Context, name string) (*containerdtypes.Metric, error) { + var ( + err error + c *Container + ) + + if c, err = mgr.container(name); err != nil { + return nil, err + } + + c.Lock() + defer c.Unlock() + + return mgr.Client.ContainerStats(ctx, c.ID) +} + // Attach attachs a container's io. func (mgr *ContainerManager) Attach(ctx context.Context, name string, attach *AttachConfig) error { c, err := mgr.container(name) @@ -2263,7 +2284,7 @@ func (mgr *ContainerManager) setBaseFS(ctx context.Context, c *Container, id str } // io.containerd.runtime.v1.linux as a const used by runc - c.BaseFS = filepath.Join(mgr.Config.HomeDir, "containerd/state", "io.containerd.runtime.v1.linux", namespaces.Default, info.Name, "rootfs") + c.BaseFS = filepath.Join(mgr.Config.HomeDir, "containerd/state", "io.containerd.runtime.v1.linux", criconfig.DefaultNameSpace, info.Name, "rootfs") } // execProcessGC cleans unused exec processes config every 5 minutes. diff --git a/daemon/mgr/snapshot.go b/daemon/mgr/snapshot.go new file mode 100644 index 0000000000..7b2353a857 --- /dev/null +++ b/daemon/mgr/snapshot.go @@ -0,0 +1,153 @@ +package mgr + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/alibaba/pouch/ctrd" + + "github.com/containerd/containerd/snapshots" + "github.com/sirupsen/logrus" +) + +// Snapshot contains the information about the snapshot. +type Snapshot struct { + // Key is the key of the snapshot + Key string + // Kind is the kind of the snapshot (active, committed, view) + Kind snapshots.Kind + // Size is the size of the snapshot in bytes. + Size uint64 + // Inodes is the number of inodes used by the snapshot + Inodes uint64 + // Timestamp is latest update time (in nanoseconds) of the snapshot + // information. + Timestamp int64 +} + +// SnapshotStore stores all snapshots. +type SnapshotStore struct { + lock sync.RWMutex + snapshots map[string]Snapshot +} + +// NewSnapshotStore create a new snapshot store. +func NewSnapshotStore() *SnapshotStore { + return &SnapshotStore{snapshots: make(map[string]Snapshot)} +} + +// Add a snapshot into the store. +func (s *SnapshotStore) Add(sn Snapshot) { + s.lock.Lock() + defer s.lock.Unlock() + s.snapshots[sn.Key] = sn +} + +// Get returns the snapshot with specified key. Returns error if the +// snapshot doesn't exist. +func (s *SnapshotStore) Get(key string) (Snapshot, error) { + s.lock.RLock() + defer s.lock.RUnlock() + if sn, ok := s.snapshots[key]; ok { + return sn, nil + } + return Snapshot{}, fmt.Errorf("failed to get %q in snapshot store", key) +} + +// List lists all snapshots. +func (s *SnapshotStore) List() []Snapshot { + s.lock.RLock() + defer s.lock.RUnlock() + var snapshots []Snapshot + for _, sn := range s.snapshots { + snapshots = append(snapshots, sn) + } + return snapshots +} + +// Delete deletes the snapshot with specified key. +func (s *SnapshotStore) Delete(key string) { + s.lock.Lock() + defer s.lock.Unlock() + delete(s.snapshots, key) +} + +// SnapshotsSyncer syncs snapshot stats periodically. +type SnapshotsSyncer struct { + store *SnapshotStore + client ctrd.APIClient + syncPeriod time.Duration +} + +// NewSnapshotsSyncer creates a snapshot syncer. +func NewSnapshotsSyncer(store *SnapshotStore, cli ctrd.APIClient, period time.Duration) *SnapshotsSyncer { + return &SnapshotsSyncer{ + store: store, + client: cli, + syncPeriod: period, + } +} + +// Start starts the snapshots syncer. +func (s *SnapshotsSyncer) Start() { + tick := time.NewTicker(s.syncPeriod) + go func() { + defer tick.Stop() + for { + err := s.Sync() + if err != nil { + logrus.Errorf("failed to sync snapshot stats: %v", err) + } + <-tick.C + } + }() +} + +// Sync updates the snapshots in the snapshot store. +func (s *SnapshotsSyncer) Sync() error { + start := time.Now().UnixNano() + var infos []snapshots.Info + err := s.client.WalkSnapshot(context.Background(), func(ctx context.Context, info snapshots.Info) error { + infos = append(infos, info) + return nil + }) + if err != nil { + return fmt.Errorf("failed to walk all snapshots: %v", err) + } + for _, info := range infos { + sn, err := s.store.Get(info.Name) + if err == nil { + // Only update timestamp for non-active snapshot. + if sn.Kind == info.Kind && sn.Kind != snapshots.KindActive { + sn.Timestamp = time.Now().UnixNano() + s.store.Add(sn) + continue + } + } + // Get newest stats if the snapshot is new or active. + sn = Snapshot{ + Key: info.Name, + Kind: info.Kind, + Timestamp: time.Now().UnixNano(), + } + usage, err := s.client.GetSnapshotUsage(context.Background(), info.Name) + if err != nil { + logrus.Errorf("failed to get usage for snapshot %q: %v", info.Name, err) + continue + } + sn.Size = uint64(usage.Size) + sn.Inodes = uint64(usage.Inodes) + s.store.Add(sn) + } + for _, sn := range s.store.List() { + if sn.Timestamp > start { + continue + } + // Delete the snapshot stats if it's not updated this time. + s.store.Delete(sn.Key) + } + + return nil +} diff --git a/daemon/mgr/snapshot_test.go b/daemon/mgr/snapshot_test.go new file mode 100644 index 0000000000..d361c5d4fc --- /dev/null +++ b/daemon/mgr/snapshot_test.go @@ -0,0 +1,66 @@ +package mgr + +import ( + "fmt" + "testing" + "time" + + snapshot "github.com/containerd/containerd/snapshots" + "github.com/stretchr/testify/assert" +) + +func Test_SnapshotStore(t *testing.T) { + snapshots := map[string]Snapshot{ + "key1": { + Key: "key1", + Kind: snapshot.KindActive, + Size: 10, + Inodes: 100, + Timestamp: time.Now().UnixNano(), + }, + "key2": { + Key: "key2", + Kind: snapshot.KindCommitted, + Size: 20, + Inodes: 200, + Timestamp: time.Now().UnixNano(), + }, + "key3": { + Key: "key3", + Kind: snapshot.KindView, + Size: 0, + Inodes: 0, + Timestamp: time.Now().UnixNano(), + }, + } + + s := NewSnapshotStore() + + t.Logf("should be able to add snapshot") + for _, sn := range snapshots { + s.Add(sn) + } + + t.Logf("should be able to get snapshot") + for id, sn := range snapshots { + got, err := s.Get(id) + assert.NoError(t, err) + assert.Equal(t, sn, got) + } + + t.Logf("should be able to list snapshot") + sns := s.List() + assert.Len(t, sns, 3) + + testKey := "key2" + + t.Logf("should be able to delete snapshot") + s.Delete(testKey) + sns = s.List() + assert.Len(t, sns, 2) + + t.Logf("get should return empty struct and ErrNotExist after deletion") + sn, err := s.Get(testKey) + assert.Equal(t, Snapshot{}, sn) + assert.Equal(t, fmt.Errorf("failed to get %q in snapshot store", testKey), err) +} diff --git a/vendor/github.com/containerd/cgroups/.gitignore b/vendor/github.com/containerd/cgroups/.gitignore new file mode 100644 index 0000000000..528cd5b39b --- /dev/null +++ b/vendor/github.com/containerd/cgroups/.gitignore @@ -0,0 +1 @@ +example/example diff --git a/vendor/github.com/containerd/cgroups/.travis.yml b/vendor/github.com/containerd/cgroups/.travis.yml new file mode 100644 index 0000000000..4a5cf74025 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/.travis.yml @@ -0,0 +1,16 @@ +language: go +go: + - 1.10.x + - tip + +install: + - mkdir -p $GOPATH/src/github.com/prometheus $GOPATH/src/github.com/opencontainers + - cd $GOPATH/src/github.com/opencontainers && git clone https://github.com/opencontainers/runtime-spec && cd runtime-spec && git checkout fa4b36aa9c99e00c2ef7b5c0013c84100ede5f4e + - cd $GOPATH/src/github.com/containerd/cgroups + - go get -t ./... + +script: + - go test -race -coverprofile=coverage.txt -covermode=atomic + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/containerd/cgroups/LICENSE b/vendor/github.com/containerd/cgroups/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/github.com/containerd/cgroups/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/containerd/cgroups/Protobuild.toml b/vendor/github.com/containerd/cgroups/Protobuild.toml new file mode 100644 index 0000000000..0d462b5075 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/Protobuild.toml @@ -0,0 +1,39 @@ +version = "unstable" +generator = "gogoctrd" +plugins = ["grpc"] + +# Control protoc include paths. Below are usually some good defaults, but feel +# free to try it without them if it works for your project. +[includes] + # Include paths that will be added before all others. Typically, you want to + # treat the root of the project as an include, but this may not be necessary. + # before = ["."] + + # Paths that should be treated as include roots in relation to the vendor + # directory. These will be calculated with the vendor directory nearest the + # target package. + # vendored = ["github.com/gogo/protobuf"] + packages = ["github.com/gogo/protobuf"] + + # Paths that will be added untouched to the end of the includes. We use + # `/usr/local/include` to pickup the common install location of protobuf. + # This is the default. + after = ["/usr/local/include"] + +# This section maps protobuf imports to Go packages. These will become +# `-M` directives in the call to the go protobuf generator. +[packages] + "gogoproto/gogo.proto" = "github.com/gogo/protobuf/gogoproto" + "google/protobuf/any.proto" = "github.com/gogo/protobuf/types" + "google/protobuf/descriptor.proto" = "github.com/gogo/protobuf/protoc-gen-gogo/descriptor" + "google/protobuf/field_mask.proto" = "github.com/gogo/protobuf/types" + "google/protobuf/timestamp.proto" = "github.com/gogo/protobuf/types" + +# Aggregrate the API descriptors to lock down API changes. +[[descriptors]] +prefix = "github.com/containerd/cgroups" +target = "metrics.pb.txt" +ignore_files = [ + "google/protobuf/descriptor.proto", + "gogoproto/gogo.proto" +] diff --git a/vendor/github.com/containerd/cgroups/README.md b/vendor/github.com/containerd/cgroups/README.md new file mode 100644 index 0000000000..69e932a9f7 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/README.md @@ -0,0 +1,112 @@ +# cgroups + +[![Build Status](https://travis-ci.org/containerd/cgroups.svg?branch=master)](https://travis-ci.org/containerd/cgroups) + +[![codecov](https://codecov.io/gh/containerd/cgroups/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/cgroups) + +Go package for creating, managing, inspecting, and destroying cgroups. +The resources format for settings on the cgroup uses the OCI runtime-spec found +[here](https://github.com/opencontainers/runtime-spec). + +## Examples + +### Create a new cgroup + +This creates a new cgroup using a static path for all subsystems under `/test`. + +* /sys/fs/cgroup/cpu/test +* /sys/fs/cgroup/memory/test +* etc.... + +It uses a single hierarchy and specifies cpu shares as a resource constraint and +uses the v1 implementation of cgroups. + + +```go +shares := uint64(100) +control, err := cgroups.New(cgroups.V1, cgroups.StaticPath("/test"), &specs.LinuxResources{ + CPU: &specs.CPU{ + Shares: &shares, + }, +}) +defer control.Delete() +``` + +### Create with systemd slice support + + +```go +control, err := cgroups.New(cgroups.Systemd, cgroups.Slice("system.slice", "runc-test"), &specs.LinuxResources{ + CPU: &specs.CPU{ + Shares: &shares, + }, +}) + +``` + +### Load an existing cgroup + +```go +control, err = cgroups.Load(cgroups.V1, cgroups.StaticPath("/test")) +``` + +### Add a process to the cgroup + +```go +if err := control.Add(cgroups.Process{Pid:1234}); err != nil { +} +``` + +### Update the cgroup + +To update the resources applied in the cgroup + +```go +shares = uint64(200) +if err := control.Update(&specs.LinuxResources{ + CPU: &specs.CPU{ + Shares: &shares, + }, +}); err != nil { +} +``` + +### Freeze and Thaw the cgroup + +```go +if err := control.Freeze(); err != nil { +} +if err := control.Thaw(); err != nil { +} +``` + +### List all processes in the cgroup or recursively + +```go +processes, err := control.Processes(cgroups.Devices, recursive) +``` + +### Get Stats on the cgroup + +```go +stats, err := control.Stat() +``` + +By adding `cgroups.IgnoreNotExist` all non-existent files will be ignored, e.g. swap memory stats without swap enabled +```go +stats, err := control.Stat(cgroups.IgnoreNotExist) +``` + +### Move process across cgroups + +This allows you to take processes from one cgroup and move them to another. + +```go +err := control.MoveTo(destination) +``` + +### Create subcgroup + +```go +subCgroup, err := control.New("child", resources) +``` diff --git a/vendor/github.com/containerd/cgroups/blkio.go b/vendor/github.com/containerd/cgroups/blkio.go new file mode 100644 index 0000000000..fc1e689cbd --- /dev/null +++ b/vendor/github.com/containerd/cgroups/blkio.go @@ -0,0 +1,326 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewBlkio(root string) *blkioController { + return &blkioController{ + root: filepath.Join(root, string(Blkio)), + } +} + +type blkioController struct { + root string +} + +func (b *blkioController) Name() Name { + return Blkio +} + +func (b *blkioController) Path(path string) string { + return filepath.Join(b.root, path) +} + +func (b *blkioController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(b.Path(path), defaultDirPerm); err != nil { + return err + } + if resources.BlockIO == nil { + return nil + } + for _, t := range createBlkioSettings(resources.BlockIO) { + if t.value != nil { + if err := ioutil.WriteFile( + filepath.Join(b.Path(path), fmt.Sprintf("blkio.%s", t.name)), + t.format(t.value), + defaultFilePerm, + ); err != nil { + return err + } + } + } + return nil +} + +func (b *blkioController) Update(path string, resources *specs.LinuxResources) error { + return b.Create(path, resources) +} + +func (b *blkioController) Stat(path string, stats *Metrics) error { + stats.Blkio = &BlkIOStat{} + settings := []blkioStatSettings{ + { + name: "throttle.io_serviced", + entry: &stats.Blkio.IoServicedRecursive, + }, + { + name: "throttle.io_service_bytes", + entry: &stats.Blkio.IoServiceBytesRecursive, + }, + } + // Try to read CFQ stats available on all CFQ enabled kernels first + if _, err := os.Lstat(filepath.Join(b.Path(path), fmt.Sprintf("blkio.io_serviced_recursive"))); err == nil { + settings = append(settings, + blkioStatSettings{ + name: "sectors_recursive", + entry: &stats.Blkio.SectorsRecursive, + }, + blkioStatSettings{ + name: "io_service_bytes_recursive", + entry: &stats.Blkio.IoServiceBytesRecursive, + }, + blkioStatSettings{ + name: "io_serviced_recursive", + entry: &stats.Blkio.IoServicedRecursive, + }, + blkioStatSettings{ + name: "io_queued_recursive", + entry: &stats.Blkio.IoQueuedRecursive, + }, + blkioStatSettings{ + name: "io_service_time_recursive", + entry: &stats.Blkio.IoServiceTimeRecursive, + }, + blkioStatSettings{ + name: "io_wait_time_recursive", + entry: &stats.Blkio.IoWaitTimeRecursive, + }, + blkioStatSettings{ + name: "io_merged_recursive", + entry: &stats.Blkio.IoMergedRecursive, + }, + blkioStatSettings{ + name: "time_recursive", + entry: &stats.Blkio.IoTimeRecursive, + }, + ) + } + f, err := os.Open("/proc/diskstats") + if err != nil { + return err + } + defer f.Close() + + devices, err := getDevices(f) + if err != nil { + return err + } + + for _, t := range settings { + if err := b.readEntry(devices, path, t.name, t.entry); err != nil { + return err + } + } + return nil +} + +func (b *blkioController) readEntry(devices map[deviceKey]string, path, name string, entry *[]*BlkIOEntry) error { + f, err := os.Open(filepath.Join(b.Path(path), fmt.Sprintf("blkio.%s", name))) + if err != nil { + return err + } + defer f.Close() + sc := bufio.NewScanner(f) + for sc.Scan() { + if err := sc.Err(); err != nil { + return err + } + // format: dev type amount + fields := strings.FieldsFunc(sc.Text(), splitBlkIOStatLine) + if len(fields) < 3 { + if len(fields) == 2 && fields[0] == "Total" { + // skip total line + continue + } else { + return fmt.Errorf("Invalid line found while parsing %s: %s", path, sc.Text()) + } + } + major, err := strconv.ParseUint(fields[0], 10, 64) + if err != nil { + return err + } + minor, err := strconv.ParseUint(fields[1], 10, 64) + if err != nil { + return err + } + op := "" + valueField := 2 + if len(fields) == 4 { + op = fields[2] + valueField = 3 + } + v, err := strconv.ParseUint(fields[valueField], 10, 64) + if err != nil { + return err + } + *entry = append(*entry, &BlkIOEntry{ + Device: devices[deviceKey{major, minor}], + Major: major, + Minor: minor, + Op: op, + Value: v, + }) + } + return nil +} + +func createBlkioSettings(blkio *specs.LinuxBlockIO) []blkioSettings { + settings := []blkioSettings{ + { + name: "weight", + value: blkio.Weight, + format: uintf, + }, + { + name: "leaf_weight", + value: blkio.LeafWeight, + format: uintf, + }, + } + for _, wd := range blkio.WeightDevice { + settings = append(settings, + blkioSettings{ + name: "weight_device", + value: wd, + format: weightdev, + }, + blkioSettings{ + name: "leaf_weight_device", + value: wd, + format: weightleafdev, + }) + } + for _, t := range []struct { + name string + list []specs.LinuxThrottleDevice + }{ + { + name: "throttle.read_bps_device", + list: blkio.ThrottleReadBpsDevice, + }, + { + name: "throttle.read_iops_device", + list: blkio.ThrottleReadIOPSDevice, + }, + { + name: "throttle.write_bps_device", + list: blkio.ThrottleWriteBpsDevice, + }, + { + name: "throttle.write_iops_device", + list: blkio.ThrottleWriteIOPSDevice, + }, + } { + for _, td := range t.list { + settings = append(settings, blkioSettings{ + name: t.name, + value: td, + format: throttleddev, + }) + } + } + return settings +} + +type blkioSettings struct { + name string + value interface{} + format func(v interface{}) []byte +} + +type blkioStatSettings struct { + name string + entry *[]*BlkIOEntry +} + +func uintf(v interface{}) []byte { + return []byte(strconv.FormatUint(uint64(*v.(*uint16)), 10)) +} + +func weightdev(v interface{}) []byte { + wd := v.(specs.LinuxWeightDevice) + return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, wd.Weight)) +} + +func weightleafdev(v interface{}) []byte { + wd := v.(specs.LinuxWeightDevice) + return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, wd.LeafWeight)) +} + +func throttleddev(v interface{}) []byte { + td := v.(specs.LinuxThrottleDevice) + return []byte(fmt.Sprintf("%d:%d %d", td.Major, td.Minor, td.Rate)) +} + +func splitBlkIOStatLine(r rune) bool { + return r == ' ' || r == ':' +} + +type deviceKey struct { + major, minor uint64 +} + +// getDevices makes a best effort attempt to read all the devices into a map +// keyed by major and minor number. Since devices may be mapped multiple times, +// we err on taking the first occurrence. +func getDevices(r io.Reader) (map[deviceKey]string, error) { + + var ( + s = bufio.NewScanner(r) + devices = make(map[deviceKey]string) + ) + for s.Scan() { + fields := strings.Fields(s.Text()) + major, err := strconv.Atoi(fields[0]) + if err != nil { + return nil, err + } + minor, err := strconv.Atoi(fields[1]) + if err != nil { + return nil, err + } + key := deviceKey{ + major: uint64(major), + minor: uint64(minor), + } + if _, ok := devices[key]; ok { + continue + } + devices[key] = filepath.Join("/dev", fields[2]) + } + return devices, s.Err() +} + +func major(devNumber uint64) uint64 { + return (devNumber >> 8) & 0xfff +} + +func minor(devNumber uint64) uint64 { + return (devNumber & 0xff) | ((devNumber >> 12) & 0xfff00) +} diff --git a/vendor/github.com/containerd/cgroups/blkio_test.go b/vendor/github.com/containerd/cgroups/blkio_test.go new file mode 100644 index 0000000000..b63f5c3045 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/blkio_test.go @@ -0,0 +1,51 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "strings" + "testing" +) + +const data = ` 7 0 loop0 0 0 0 0 0 0 0 0 0 0 0 + 7 1 loop1 0 0 0 0 0 0 0 0 0 0 0 + 7 2 loop2 0 0 0 0 0 0 0 0 0 0 0 + 7 3 loop3 0 0 0 0 0 0 0 0 0 0 0 + 7 4 loop4 0 0 0 0 0 0 0 0 0 0 0 + 7 5 loop5 0 0 0 0 0 0 0 0 0 0 0 + 7 6 loop6 0 0 0 0 0 0 0 0 0 0 0 + 7 7 loop7 0 0 0 0 0 0 0 0 0 0 0 + 8 0 sda 1892042 187697 63489222 1246284 1389086 2887005 134903104 11390608 1 1068060 12692228 + 8 1 sda1 1762875 37086 61241570 1200512 1270037 2444415 131214808 11152764 1 882624 12409308 + 8 2 sda2 2 0 4 0 0 0 0 0 0 0 0 + 8 5 sda5 129102 150611 2244440 45716 18447 442590 3688296 67268 0 62584 112984` + +func TestGetDevices(t *testing.T) { + r := strings.NewReader(data) + devices, err := getDevices(r) + if err != nil { + t.Fatal(err) + } + name, ok := devices[deviceKey{8, 0}] + if !ok { + t.Fatal("no device found for 8,0") + } + const expected = "/dev/sda" + if name != expected { + t.Fatalf("expected device name %q but received %q", expected, name) + } +} diff --git a/vendor/github.com/containerd/cgroups/cgroup.go b/vendor/github.com/containerd/cgroups/cgroup.go new file mode 100644 index 0000000000..7959feb490 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/cgroup.go @@ -0,0 +1,445 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "sync" + + specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" +) + +// New returns a new control via the cgroup cgroups interface +func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources) (Cgroup, error) { + subsystems, err := hierarchy() + if err != nil { + return nil, err + } + for _, s := range subsystems { + if err := initializeSubsystem(s, path, resources); err != nil { + return nil, err + } + } + return &cgroup{ + path: path, + subsystems: subsystems, + }, nil +} + +// Load will load an existing cgroup and allow it to be controlled +func Load(hierarchy Hierarchy, path Path) (Cgroup, error) { + subsystems, err := hierarchy() + if err != nil { + return nil, err + } + // check the the subsystems still exist + for _, s := range pathers(subsystems) { + p, err := path(s.Name()) + if err != nil { + if os.IsNotExist(errors.Cause(err)) { + return nil, ErrCgroupDeleted + } + return nil, err + } + if _, err := os.Lstat(s.Path(p)); err != nil { + if os.IsNotExist(err) { + return nil, ErrCgroupDeleted + } + return nil, err + } + } + return &cgroup{ + path: path, + subsystems: subsystems, + }, nil +} + +type cgroup struct { + path Path + + subsystems []Subsystem + mu sync.Mutex + err error +} + +// New returns a new sub cgroup +func (c *cgroup) New(name string, resources *specs.LinuxResources) (Cgroup, error) { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return nil, c.err + } + path := subPath(c.path, name) + for _, s := range c.subsystems { + if err := initializeSubsystem(s, path, resources); err != nil { + return nil, err + } + } + return &cgroup{ + path: path, + subsystems: c.subsystems, + }, nil +} + +// Subsystems returns all the subsystems that are currently being +// consumed by the group +func (c *cgroup) Subsystems() []Subsystem { + return c.subsystems +} + +// Add moves the provided process into the new cgroup +func (c *cgroup) Add(process Process) error { + if process.Pid <= 0 { + return ErrInvalidPid + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + return c.add(process) +} + +func (c *cgroup) add(process Process) error { + for _, s := range pathers(c.subsystems) { + p, err := c.path(s.Name()) + if err != nil { + return err + } + if err := ioutil.WriteFile( + filepath.Join(s.Path(p), cgroupProcs), + []byte(strconv.Itoa(process.Pid)), + defaultFilePerm, + ); err != nil { + return err + } + } + return nil +} + +// AddTask moves the provided tasks (threads) into the new cgroup +func (c *cgroup) AddTask(process Process) error { + if process.Pid <= 0 { + return ErrInvalidPid + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + return c.addTask(process) +} + +func (c *cgroup) addTask(process Process) error { + for _, s := range pathers(c.subsystems) { + p, err := c.path(s.Name()) + if err != nil { + return err + } + if err := ioutil.WriteFile( + filepath.Join(s.Path(p), cgroupTasks), + []byte(strconv.Itoa(process.Pid)), + defaultFilePerm, + ); err != nil { + return err + } + } + return nil +} + +// Delete will remove the control group from each of the subsystems registered +func (c *cgroup) Delete() error { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + var errors []string + for _, s := range c.subsystems { + if d, ok := s.(deleter); ok { + sp, err := c.path(s.Name()) + if err != nil { + return err + } + if err := d.Delete(sp); err != nil { + errors = append(errors, string(s.Name())) + } + continue + } + if p, ok := s.(pather); ok { + sp, err := c.path(s.Name()) + if err != nil { + return err + } + path := p.Path(sp) + if err := remove(path); err != nil { + errors = append(errors, path) + } + } + } + if len(errors) > 0 { + return fmt.Errorf("cgroups: unable to remove paths %s", strings.Join(errors, ", ")) + } + c.err = ErrCgroupDeleted + return nil +} + +// Stat returns the current metrics for the cgroup +func (c *cgroup) Stat(handlers ...ErrorHandler) (*Metrics, error) { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return nil, c.err + } + if len(handlers) == 0 { + handlers = append(handlers, errPassthrough) + } + var ( + stats = &Metrics{ + CPU: &CPUStat{ + Throttling: &Throttle{}, + Usage: &CPUUsage{}, + }, + } + wg = &sync.WaitGroup{} + errs = make(chan error, len(c.subsystems)) + ) + for _, s := range c.subsystems { + if ss, ok := s.(stater); ok { + sp, err := c.path(s.Name()) + if err != nil { + return nil, err + } + wg.Add(1) + go func() { + defer wg.Done() + if err := ss.Stat(sp, stats); err != nil { + for _, eh := range handlers { + if herr := eh(err); herr != nil { + errs <- herr + } + } + } + }() + } + } + wg.Wait() + close(errs) + for err := range errs { + return nil, err + } + return stats, nil +} + +// Update updates the cgroup with the new resource values provided +// +// Be prepared to handle EBUSY when trying to update a cgroup with +// live processes and other operations like Stats being performed at the +// same time +func (c *cgroup) Update(resources *specs.LinuxResources) error { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + for _, s := range c.subsystems { + if u, ok := s.(updater); ok { + sp, err := c.path(s.Name()) + if err != nil { + return err + } + if err := u.Update(sp, resources); err != nil { + return err + } + } + } + return nil +} + +// Processes returns the processes running inside the cgroup along +// with the subsystem used, pid, and path +func (c *cgroup) Processes(subsystem Name, recursive bool) ([]Process, error) { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return nil, c.err + } + return c.processes(subsystem, recursive) +} + +func (c *cgroup) processes(subsystem Name, recursive bool) ([]Process, error) { + s := c.getSubsystem(subsystem) + sp, err := c.path(subsystem) + if err != nil { + return nil, err + } + path := s.(pather).Path(sp) + var processes []Process + err = filepath.Walk(path, func(p string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !recursive && info.IsDir() { + if p == path { + return nil + } + return filepath.SkipDir + } + dir, name := filepath.Split(p) + if name != cgroupProcs { + return nil + } + procs, err := readPids(dir, subsystem) + if err != nil { + return err + } + processes = append(processes, procs...) + return nil + }) + return processes, err +} + +// Freeze freezes the entire cgroup and all the processes inside it +func (c *cgroup) Freeze() error { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + s := c.getSubsystem(Freezer) + if s == nil { + return ErrFreezerNotSupported + } + sp, err := c.path(Freezer) + if err != nil { + return err + } + return s.(*freezerController).Freeze(sp) +} + +// Thaw thaws out the cgroup and all the processes inside it +func (c *cgroup) Thaw() error { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + s := c.getSubsystem(Freezer) + if s == nil { + return ErrFreezerNotSupported + } + sp, err := c.path(Freezer) + if err != nil { + return err + } + return s.(*freezerController).Thaw(sp) +} + +// OOMEventFD returns the memory cgroup's out of memory event fd that triggers +// when processes inside the cgroup receive an oom event. Returns +// ErrMemoryNotSupported if memory cgroups is not supported. +func (c *cgroup) OOMEventFD() (uintptr, error) { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return 0, c.err + } + s := c.getSubsystem(Memory) + if s == nil { + return 0, ErrMemoryNotSupported + } + sp, err := c.path(Memory) + if err != nil { + return 0, err + } + return s.(*memoryController).OOMEventFD(sp) +} + +// State returns the state of the cgroup and its processes +func (c *cgroup) State() State { + c.mu.Lock() + defer c.mu.Unlock() + c.checkExists() + if c.err != nil && c.err == ErrCgroupDeleted { + return Deleted + } + s := c.getSubsystem(Freezer) + if s == nil { + return Thawed + } + sp, err := c.path(Freezer) + if err != nil { + return Unknown + } + state, err := s.(*freezerController).state(sp) + if err != nil { + return Unknown + } + return state +} + +// MoveTo does a recursive move subsystem by subsystem of all the processes +// inside the group +func (c *cgroup) MoveTo(destination Cgroup) error { + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + for _, s := range c.subsystems { + processes, err := c.processes(s.Name(), true) + if err != nil { + return err + } + for _, p := range processes { + if err := destination.Add(p); err != nil { + return err + } + } + } + return nil +} + +func (c *cgroup) getSubsystem(n Name) Subsystem { + for _, s := range c.subsystems { + if s.Name() == n { + return s + } + } + return nil +} + +func (c *cgroup) checkExists() { + for _, s := range pathers(c.subsystems) { + p, err := c.path(s.Name()) + if err != nil { + return + } + if _, err := os.Lstat(s.Path(p)); err != nil { + if os.IsNotExist(err) { + c.err = ErrCgroupDeleted + return + } + } + } +} diff --git a/vendor/github.com/containerd/cgroups/cgroup_test.go b/vendor/github.com/containerd/cgroups/cgroup_test.go new file mode 100644 index 0000000000..84740bd6a7 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/cgroup_test.go @@ -0,0 +1,354 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "testing" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +// using t.Error in test were defers do cleanup on the filesystem + +func TestCreate(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if control == nil { + t.Error("control is nil") + return + } + for _, s := range Subsystems() { + if _, err := os.Stat(filepath.Join(mock.root, string(s), "test")); err != nil { + if os.IsNotExist(err) { + t.Errorf("group %s was not created", s) + return + } + t.Errorf("group %s was not created correctly %s", s, err) + return + } + } +} + +func TestStat(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + s, err := control.Stat(IgnoreNotExist) + if err != nil { + t.Error(err) + return + } + if s == nil { + t.Error("stat result is nil") + return + } +} + +func TestAdd(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if err := control.Add(Process{Pid: 1234}); err != nil { + t.Error(err) + return + } + for _, s := range Subsystems() { + if err := checkPid(mock, filepath.Join(string(s), "test"), 1234); err != nil { + t.Error(err) + return + } + } +} + +func TestAddTask(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if err := control.AddTask(Process{Pid: 1234}); err != nil { + t.Error(err) + return + } + for _, s := range Subsystems() { + if err := checkTaskid(mock, filepath.Join(string(s), "test"), 1234); err != nil { + t.Error(err) + return + } + } +} + +func TestListPids(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if err := control.Add(Process{Pid: 1234}); err != nil { + t.Error(err) + return + } + for _, s := range Subsystems() { + if err := checkPid(mock, filepath.Join(string(s), "test"), 1234); err != nil { + t.Error(err) + return + } + } + procs, err := control.Processes(Freezer, false) + if err != nil { + t.Error(err) + return + } + if l := len(procs); l != 1 { + t.Errorf("should have one process but received %d", l) + return + } + if procs[0].Pid != 1234 { + t.Errorf("expected pid %d but received %d", 1234, procs[0].Pid) + } +} + +func readValue(mock *mockCgroup, path string) (string, error) { + data, err := ioutil.ReadFile(filepath.Join(mock.root, path)) + if err != nil { + return "", err + } + return string(data), nil +} + +func checkPid(mock *mockCgroup, path string, expected int) error { + data, err := readValue(mock, filepath.Join(path, cgroupProcs)) + if err != nil { + return err + } + v, err := strconv.Atoi(string(data)) + if err != nil { + return err + } + if v != expected { + return fmt.Errorf("expectd pid %d but received %d", expected, v) + } + return nil +} + +func checkTaskid(mock *mockCgroup, path string, expected int) error { + data, err := readValue(mock, filepath.Join(path, cgroupTasks)) + if err != nil { + return err + } + v, err := strconv.Atoi(string(data)) + if err != nil { + return err + } + if v != expected { + return fmt.Errorf("expectd task id %d but received %d", expected, v) + } + return nil +} + +func TestLoad(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if control, err = Load(mock.hierarchy, StaticPath("test")); err != nil { + t.Error(err) + return + } + if control == nil { + t.Error("control is nil") + return + } +} + +func TestDelete(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if err := control.Delete(); err != nil { + t.Error(err) + } +} + +func TestCreateSubCgroup(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + sub, err := control.New("child", &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if err := sub.Add(Process{Pid: 1234}); err != nil { + t.Error(err) + return + } + for _, s := range Subsystems() { + if err := checkPid(mock, filepath.Join(string(s), "test", "child"), 1234); err != nil { + t.Error(err) + return + } + } + if err := sub.AddTask(Process{Pid: 5678}); err != nil { + t.Error(err) + return + } + for _, s := range Subsystems() { + if err := checkTaskid(mock, filepath.Join(string(s), "test", "child"), 5678); err != nil { + t.Error(err) + return + } + } +} + +func TestFreezeThaw(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + if err := control.Freeze(); err != nil { + t.Error(err) + return + } + if state := control.State(); state != Frozen { + t.Errorf("expected %q but received %q", Frozen, state) + return + } + if err := control.Thaw(); err != nil { + t.Error(err) + return + } + if state := control.State(); state != Thawed { + t.Errorf("expected %q but received %q", Thawed, state) + return + } +} + +func TestSubsystems(t *testing.T) { + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + cache := make(map[Name]struct{}) + for _, s := range control.Subsystems() { + cache[s.Name()] = struct{}{} + } + for _, s := range Subsystems() { + if _, ok := cache[s]; !ok { + t.Errorf("expected subsystem %q but not found", s) + } + } +} + +func TestCpusetParent(t *testing.T) { + const expected = "0-3" + mock, err := newMock() + if err != nil { + t.Fatal(err) + } + defer mock.delete() + control, err := New(mock.hierarchy, StaticPath("/parent/child"), &specs.LinuxResources{}) + if err != nil { + t.Error(err) + return + } + defer control.Delete() + for _, file := range []string{ + "parent/cpuset.cpus", + "parent/cpuset.mems", + "parent/child/cpuset.cpus", + "parent/child/cpuset.mems", + } { + v, err := readValue(mock, filepath.Join(string(Cpuset), file)) + if err != nil { + t.Error(err) + return + } + if v != expected { + t.Errorf("expected %q for %s but received %q", expected, file, v) + } + } +} diff --git a/vendor/github.com/containerd/cgroups/control.go b/vendor/github.com/containerd/cgroups/control.go new file mode 100644 index 0000000000..63e2df93dd --- /dev/null +++ b/vendor/github.com/containerd/cgroups/control.go @@ -0,0 +1,77 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "os" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +const ( + cgroupProcs = "cgroup.procs" + cgroupTasks = "tasks" + defaultDirPerm = 0755 +) + +// defaultFilePerm is a var so that the test framework can change the filemode +// of all files created when the tests are running. The difference between the +// tests and real world use is that files like "cgroup.procs" will exist when writing +// to a read cgroup filesystem and do not exist prior when running in the tests. +// this is set to a non 0 value in the test code +var defaultFilePerm = os.FileMode(0) + +type Process struct { + // Subsystem is the name of the subsystem that the process is in + Subsystem Name + // Pid is the process id of the process + Pid int + // Path is the full path of the subsystem and location that the process is in + Path string +} + +// Cgroup handles interactions with the individual groups to perform +// actions on them as them main interface to this cgroup package +type Cgroup interface { + // New creates a new cgroup under the calling cgroup + New(string, *specs.LinuxResources) (Cgroup, error) + // Add adds a process to the cgroup (cgroup.procs) + Add(Process) error + // AddTask adds a process to the cgroup (tasks) + AddTask(Process) error + // Delete removes the cgroup as a whole + Delete() error + // MoveTo moves all the processes under the calling cgroup to the provided one + // subsystems are moved one at a time + MoveTo(Cgroup) error + // Stat returns the stats for all subsystems in the cgroup + Stat(...ErrorHandler) (*Metrics, error) + // Update updates all the subsystems with the provided resource changes + Update(resources *specs.LinuxResources) error + // Processes returns all the processes in a select subsystem for the cgroup + Processes(Name, bool) ([]Process, error) + // Freeze freezes or pauses all processes inside the cgroup + Freeze() error + // Thaw thaw or resumes all processes inside the cgroup + Thaw() error + // OOMEventFD returns the memory subsystem's event fd for OOM events + OOMEventFD() (uintptr, error) + // State returns the cgroups current state + State() State + // Subsystems returns all the subsystems in the cgroup + Subsystems() []Subsystem +} diff --git a/vendor/github.com/containerd/cgroups/cpu.go b/vendor/github.com/containerd/cgroups/cpu.go new file mode 100644 index 0000000000..431cd3e51e --- /dev/null +++ b/vendor/github.com/containerd/cgroups/cpu.go @@ -0,0 +1,129 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "bufio" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewCpu(root string) *cpuController { + return &cpuController{ + root: filepath.Join(root, string(Cpu)), + } +} + +type cpuController struct { + root string +} + +func (c *cpuController) Name() Name { + return Cpu +} + +func (c *cpuController) Path(path string) string { + return filepath.Join(c.root, path) +} + +func (c *cpuController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(c.Path(path), defaultDirPerm); err != nil { + return err + } + if cpu := resources.CPU; cpu != nil { + for _, t := range []struct { + name string + ivalue *int64 + uvalue *uint64 + }{ + { + name: "rt_period_us", + uvalue: cpu.RealtimePeriod, + }, + { + name: "rt_runtime_us", + ivalue: cpu.RealtimeRuntime, + }, + { + name: "shares", + uvalue: cpu.Shares, + }, + { + name: "cfs_period_us", + uvalue: cpu.Period, + }, + { + name: "cfs_quota_us", + ivalue: cpu.Quota, + }, + } { + var value []byte + if t.uvalue != nil { + value = []byte(strconv.FormatUint(*t.uvalue, 10)) + } else if t.ivalue != nil { + value = []byte(strconv.FormatInt(*t.ivalue, 10)) + } + if value != nil { + if err := ioutil.WriteFile( + filepath.Join(c.Path(path), fmt.Sprintf("cpu.%s", t.name)), + value, + defaultFilePerm, + ); err != nil { + return err + } + } + } + } + return nil +} + +func (c *cpuController) Update(path string, resources *specs.LinuxResources) error { + return c.Create(path, resources) +} + +func (c *cpuController) Stat(path string, stats *Metrics) error { + f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat")) + if err != nil { + return err + } + defer f.Close() + // get or create the cpu field because cpuacct can also set values on this struct + sc := bufio.NewScanner(f) + for sc.Scan() { + if err := sc.Err(); err != nil { + return err + } + key, v, err := parseKV(sc.Text()) + if err != nil { + return err + } + switch key { + case "nr_periods": + stats.CPU.Throttling.Periods = v + case "nr_throttled": + stats.CPU.Throttling.ThrottledPeriods = v + case "throttled_time": + stats.CPU.Throttling.ThrottledTime = v + } + } + return nil +} diff --git a/vendor/github.com/containerd/cgroups/cpuacct.go b/vendor/github.com/containerd/cgroups/cpuacct.go new file mode 100644 index 0000000000..42a490a87e --- /dev/null +++ b/vendor/github.com/containerd/cgroups/cpuacct.go @@ -0,0 +1,121 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "strconv" + "strings" +) + +const nanosecondsInSecond = 1000000000 + +var clockTicks = getClockTicks() + +func NewCpuacct(root string) *cpuacctController { + return &cpuacctController{ + root: filepath.Join(root, string(Cpuacct)), + } +} + +type cpuacctController struct { + root string +} + +func (c *cpuacctController) Name() Name { + return Cpuacct +} + +func (c *cpuacctController) Path(path string) string { + return filepath.Join(c.root, path) +} + +func (c *cpuacctController) Stat(path string, stats *Metrics) error { + user, kernel, err := c.getUsage(path) + if err != nil { + return err + } + total, err := readUint(filepath.Join(c.Path(path), "cpuacct.usage")) + if err != nil { + return err + } + percpu, err := c.percpuUsage(path) + if err != nil { + return err + } + stats.CPU.Usage.Total = total + stats.CPU.Usage.User = user + stats.CPU.Usage.Kernel = kernel + stats.CPU.Usage.PerCPU = percpu + return nil +} + +func (c *cpuacctController) percpuUsage(path string) ([]uint64, error) { + var usage []uint64 + data, err := ioutil.ReadFile(filepath.Join(c.Path(path), "cpuacct.usage_percpu")) + if err != nil { + return nil, err + } + for _, v := range strings.Fields(string(data)) { + u, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return nil, err + } + usage = append(usage, u) + } + return usage, nil +} + +func (c *cpuacctController) getUsage(path string) (user uint64, kernel uint64, err error) { + statPath := filepath.Join(c.Path(path), "cpuacct.stat") + data, err := ioutil.ReadFile(statPath) + if err != nil { + return 0, 0, err + } + fields := strings.Fields(string(data)) + if len(fields) != 4 { + return 0, 0, fmt.Errorf("%q is expected to have 4 fields", statPath) + } + for _, t := range []struct { + index int + name string + value *uint64 + }{ + { + index: 0, + name: "user", + value: &user, + }, + { + index: 2, + name: "system", + value: &kernel, + }, + } { + if fields[t.index] != t.name { + return 0, 0, fmt.Errorf("expected field %q but found %q in %q", t.name, fields[t.index], statPath) + } + v, err := strconv.ParseUint(fields[t.index+1], 10, 64) + if err != nil { + return 0, 0, err + } + *t.value = v + } + return (user * nanosecondsInSecond) / clockTicks, (kernel * nanosecondsInSecond) / clockTicks, nil +} diff --git a/vendor/github.com/containerd/cgroups/cpuset.go b/vendor/github.com/containerd/cgroups/cpuset.go new file mode 100644 index 0000000000..f182aa68c1 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/cpuset.go @@ -0,0 +1,159 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewCputset(root string) *cpusetController { + return &cpusetController{ + root: filepath.Join(root, string(Cpuset)), + } +} + +type cpusetController struct { + root string +} + +func (c *cpusetController) Name() Name { + return Cpuset +} + +func (c *cpusetController) Path(path string) string { + return filepath.Join(c.root, path) +} + +func (c *cpusetController) Create(path string, resources *specs.LinuxResources) error { + if err := c.ensureParent(c.Path(path), c.root); err != nil { + return err + } + if err := os.MkdirAll(c.Path(path), defaultDirPerm); err != nil { + return err + } + if err := c.copyIfNeeded(c.Path(path), filepath.Dir(c.Path(path))); err != nil { + return err + } + if resources.CPU != nil { + for _, t := range []struct { + name string + value *string + }{ + { + name: "cpus", + value: &resources.CPU.Cpus, + }, + { + name: "mems", + value: &resources.CPU.Mems, + }, + } { + if t.value != nil { + if err := ioutil.WriteFile( + filepath.Join(c.Path(path), fmt.Sprintf("cpuset.%s", t.name)), + []byte(*t.value), + defaultFilePerm, + ); err != nil { + return err + } + } + } + } + return nil +} + +func (c *cpusetController) Update(path string, resources *specs.LinuxResources) error { + return c.Create(path, resources) +} + +func (c *cpusetController) getValues(path string) (cpus []byte, mems []byte, err error) { + if cpus, err = ioutil.ReadFile(filepath.Join(path, "cpuset.cpus")); err != nil && !os.IsNotExist(err) { + return + } + if mems, err = ioutil.ReadFile(filepath.Join(path, "cpuset.mems")); err != nil && !os.IsNotExist(err) { + return + } + return cpus, mems, nil +} + +// ensureParent makes sure that the parent directory of current is created +// and populated with the proper cpus and mems files copied from +// it's parent. +func (c *cpusetController) ensureParent(current, root string) error { + parent := filepath.Dir(current) + if _, err := filepath.Rel(root, parent); err != nil { + return nil + } + // Avoid infinite recursion. + if parent == current { + return fmt.Errorf("cpuset: cgroup parent path outside cgroup root") + } + if cleanPath(parent) != root { + if err := c.ensureParent(parent, root); err != nil { + return err + } + } + if err := os.MkdirAll(current, defaultDirPerm); err != nil { + return err + } + return c.copyIfNeeded(current, parent) +} + +// copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent +// directory to the current directory if the file's contents are 0 +func (c *cpusetController) copyIfNeeded(current, parent string) error { + var ( + err error + currentCpus, currentMems []byte + parentCpus, parentMems []byte + ) + if currentCpus, currentMems, err = c.getValues(current); err != nil { + return err + } + if parentCpus, parentMems, err = c.getValues(parent); err != nil { + return err + } + if isEmpty(currentCpus) { + if err := ioutil.WriteFile( + filepath.Join(current, "cpuset.cpus"), + parentCpus, + defaultFilePerm, + ); err != nil { + return err + } + } + if isEmpty(currentMems) { + if err := ioutil.WriteFile( + filepath.Join(current, "cpuset.mems"), + parentMems, + defaultFilePerm, + ); err != nil { + return err + } + } + return nil +} + +func isEmpty(b []byte) bool { + return len(bytes.Trim(b, "\n")) == 0 +} diff --git a/vendor/github.com/containerd/cgroups/devices.go b/vendor/github.com/containerd/cgroups/devices.go new file mode 100644 index 0000000000..f9a118b227 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/devices.go @@ -0,0 +1,90 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +const ( + allowDeviceFile = "devices.allow" + denyDeviceFile = "devices.deny" + wildcard = -1 +) + +func NewDevices(root string) *devicesController { + return &devicesController{ + root: filepath.Join(root, string(Devices)), + } +} + +type devicesController struct { + root string +} + +func (d *devicesController) Name() Name { + return Devices +} + +func (d *devicesController) Path(path string) string { + return filepath.Join(d.root, path) +} + +func (d *devicesController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(d.Path(path), defaultDirPerm); err != nil { + return err + } + for _, device := range resources.Devices { + file := denyDeviceFile + if device.Allow { + file = allowDeviceFile + } + if err := ioutil.WriteFile( + filepath.Join(d.Path(path), file), + []byte(deviceString(device)), + defaultFilePerm, + ); err != nil { + return err + } + } + return nil +} + +func (d *devicesController) Update(path string, resources *specs.LinuxResources) error { + return d.Create(path, resources) +} + +func deviceString(device specs.LinuxDeviceCgroup) string { + return fmt.Sprintf("%s %s:%s %s", + device.Type, + deviceNumber(device.Major), + deviceNumber(device.Minor), + device.Access, + ) +} + +func deviceNumber(number *int64) string { + if number == nil || *number == wildcard { + return "*" + } + return fmt.Sprint(*number) +} diff --git a/vendor/github.com/containerd/cgroups/errors.go b/vendor/github.com/containerd/cgroups/errors.go new file mode 100644 index 0000000000..f1ad8315c8 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/errors.go @@ -0,0 +1,47 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "errors" + "os" +) + +var ( + ErrInvalidPid = errors.New("cgroups: pid must be greater than 0") + ErrMountPointNotExist = errors.New("cgroups: cgroup mountpoint does not exist") + ErrInvalidFormat = errors.New("cgroups: parsing file with invalid format failed") + ErrFreezerNotSupported = errors.New("cgroups: freezer cgroup not supported on this system") + ErrMemoryNotSupported = errors.New("cgroups: memory cgroup not supported on this system") + ErrCgroupDeleted = errors.New("cgroups: cgroup deleted") + ErrNoCgroupMountDestination = errors.New("cgroups: cannot find cgroup mount destination") +) + +// ErrorHandler is a function that handles and acts on errors +type ErrorHandler func(err error) error + +// IgnoreNotExist ignores any errors that are for not existing files +func IgnoreNotExist(err error) error { + if os.IsNotExist(err) { + return nil + } + return err +} + +func errPassthrough(err error) error { + return err +} diff --git a/vendor/github.com/containerd/cgroups/freezer.go b/vendor/github.com/containerd/cgroups/freezer.go new file mode 100644 index 0000000000..5e668408a2 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/freezer.go @@ -0,0 +1,82 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "io/ioutil" + "path/filepath" + "strings" + "time" +) + +func NewFreezer(root string) *freezerController { + return &freezerController{ + root: filepath.Join(root, string(Freezer)), + } +} + +type freezerController struct { + root string +} + +func (f *freezerController) Name() Name { + return Freezer +} + +func (f *freezerController) Path(path string) string { + return filepath.Join(f.root, path) +} + +func (f *freezerController) Freeze(path string) error { + return f.waitState(path, Frozen) +} + +func (f *freezerController) Thaw(path string) error { + return f.waitState(path, Thawed) +} + +func (f *freezerController) changeState(path string, state State) error { + return ioutil.WriteFile( + filepath.Join(f.root, path, "freezer.state"), + []byte(strings.ToUpper(string(state))), + defaultFilePerm, + ) +} + +func (f *freezerController) state(path string) (State, error) { + current, err := ioutil.ReadFile(filepath.Join(f.root, path, "freezer.state")) + if err != nil { + return "", err + } + return State(strings.ToLower(strings.TrimSpace(string(current)))), nil +} + +func (f *freezerController) waitState(path string, state State) error { + for { + if err := f.changeState(path, state); err != nil { + return err + } + current, err := f.state(path) + if err != nil { + return err + } + if current == state { + return nil + } + time.Sleep(1 * time.Millisecond) + } +} diff --git a/vendor/github.com/containerd/cgroups/hierarchy.go b/vendor/github.com/containerd/cgroups/hierarchy.go new file mode 100644 index 0000000000..9221bf3f15 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/hierarchy.go @@ -0,0 +1,20 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +// Hierarchy enableds both unified and split hierarchy for cgroups +type Hierarchy func() ([]Subsystem, error) diff --git a/vendor/github.com/containerd/cgroups/hugetlb.go b/vendor/github.com/containerd/cgroups/hugetlb.go new file mode 100644 index 0000000000..3718706d7b --- /dev/null +++ b/vendor/github.com/containerd/cgroups/hugetlb.go @@ -0,0 +1,109 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewHugetlb(root string) (*hugetlbController, error) { + sizes, err := hugePageSizes() + if err != nil { + return nil, err + } + + return &hugetlbController{ + root: filepath.Join(root, string(Hugetlb)), + sizes: sizes, + }, nil +} + +type hugetlbController struct { + root string + sizes []string +} + +func (h *hugetlbController) Name() Name { + return Hugetlb +} + +func (h *hugetlbController) Path(path string) string { + return filepath.Join(h.root, path) +} + +func (h *hugetlbController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(h.Path(path), defaultDirPerm); err != nil { + return err + } + for _, limit := range resources.HugepageLimits { + if err := ioutil.WriteFile( + filepath.Join(h.Path(path), strings.Join([]string{"hugetlb", limit.Pagesize, "limit_in_bytes"}, ".")), + []byte(strconv.FormatUint(limit.Limit, 10)), + defaultFilePerm, + ); err != nil { + return err + } + } + return nil +} + +func (h *hugetlbController) Stat(path string, stats *Metrics) error { + for _, size := range h.sizes { + s, err := h.readSizeStat(path, size) + if err != nil { + return err + } + stats.Hugetlb = append(stats.Hugetlb, s) + } + return nil +} + +func (h *hugetlbController) readSizeStat(path, size string) (*HugetlbStat, error) { + s := HugetlbStat{ + Pagesize: size, + } + for _, t := range []struct { + name string + value *uint64 + }{ + { + name: "usage_in_bytes", + value: &s.Usage, + }, + { + name: "max_usage_in_bytes", + value: &s.Max, + }, + { + name: "failcnt", + value: &s.Failcnt, + }, + } { + v, err := readUint(filepath.Join(h.Path(path), strings.Join([]string{"hugetlb", size, t.name}, "."))) + if err != nil { + return nil, err + } + *t.value = v + } + return &s, nil +} diff --git a/vendor/github.com/containerd/cgroups/memory.go b/vendor/github.com/containerd/cgroups/memory.go new file mode 100644 index 0000000000..ce15ca2b9a --- /dev/null +++ b/vendor/github.com/containerd/cgroups/memory.go @@ -0,0 +1,325 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + + "golang.org/x/sys/unix" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewMemory(root string) *memoryController { + return &memoryController{ + root: filepath.Join(root, string(Memory)), + } +} + +type memoryController struct { + root string +} + +func (m *memoryController) Name() Name { + return Memory +} + +func (m *memoryController) Path(path string) string { + return filepath.Join(m.root, path) +} + +func (m *memoryController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(m.Path(path), defaultDirPerm); err != nil { + return err + } + if resources.Memory == nil { + return nil + } + if resources.Memory.Kernel != nil { + // Check if kernel memory is enabled + // We have to limit the kernel memory here as it won't be accounted at all + // until a limit is set on the cgroup and limit cannot be set once the + // cgroup has children, or if there are already tasks in the cgroup. + for _, i := range []int64{1, -1} { + if err := ioutil.WriteFile( + filepath.Join(m.Path(path), "memory.kmem.limit_in_bytes"), + []byte(strconv.FormatInt(i, 10)), + defaultFilePerm, + ); err != nil { + return checkEBUSY(err) + } + } + } + return m.set(path, getMemorySettings(resources)) +} + +func (m *memoryController) Update(path string, resources *specs.LinuxResources) error { + if resources.Memory == nil { + return nil + } + g := func(v *int64) bool { + return v != nil && *v > 0 + } + settings := getMemorySettings(resources) + if g(resources.Memory.Limit) && g(resources.Memory.Swap) { + // if the updated swap value is larger than the current memory limit set the swap changes first + // then set the memory limit as swap must always be larger than the current limit + current, err := readUint(filepath.Join(m.Path(path), "memory.limit_in_bytes")) + if err != nil { + return err + } + if current < uint64(*resources.Memory.Swap) { + settings[0], settings[1] = settings[1], settings[0] + } + } + return m.set(path, settings) +} + +func (m *memoryController) Stat(path string, stats *Metrics) error { + f, err := os.Open(filepath.Join(m.Path(path), "memory.stat")) + if err != nil { + return err + } + defer f.Close() + stats.Memory = &MemoryStat{ + Usage: &MemoryEntry{}, + Swap: &MemoryEntry{}, + Kernel: &MemoryEntry{}, + KernelTCP: &MemoryEntry{}, + } + if err := m.parseStats(f, stats.Memory); err != nil { + return err + } + for _, t := range []struct { + module string + entry *MemoryEntry + }{ + { + module: "", + entry: stats.Memory.Usage, + }, + { + module: "memsw", + entry: stats.Memory.Swap, + }, + { + module: "kmem", + entry: stats.Memory.Kernel, + }, + { + module: "kmem.tcp", + entry: stats.Memory.KernelTCP, + }, + } { + for _, tt := range []struct { + name string + value *uint64 + }{ + { + name: "usage_in_bytes", + value: &t.entry.Usage, + }, + { + name: "max_usage_in_bytes", + value: &t.entry.Max, + }, + { + name: "failcnt", + value: &t.entry.Failcnt, + }, + { + name: "limit_in_bytes", + value: &t.entry.Limit, + }, + } { + parts := []string{"memory"} + if t.module != "" { + parts = append(parts, t.module) + } + parts = append(parts, tt.name) + v, err := readUint(filepath.Join(m.Path(path), strings.Join(parts, "."))) + if err != nil { + return err + } + *tt.value = v + } + } + return nil +} + +func (m *memoryController) OOMEventFD(path string) (uintptr, error) { + root := m.Path(path) + f, err := os.Open(filepath.Join(root, "memory.oom_control")) + if err != nil { + return 0, err + } + defer f.Close() + fd, _, serr := unix.RawSyscall(unix.SYS_EVENTFD2, 0, unix.EFD_CLOEXEC, 0) + if serr != 0 { + return 0, serr + } + if err := writeEventFD(root, f.Fd(), fd); err != nil { + unix.Close(int(fd)) + return 0, err + } + return fd, nil +} + +func writeEventFD(root string, cfd, efd uintptr) error { + f, err := os.OpenFile(filepath.Join(root, "cgroup.event_control"), os.O_WRONLY, 0) + if err != nil { + return err + } + _, err = f.WriteString(fmt.Sprintf("%d %d", efd, cfd)) + f.Close() + return err +} + +func (m *memoryController) parseStats(r io.Reader, stat *MemoryStat) error { + var ( + raw = make(map[string]uint64) + sc = bufio.NewScanner(r) + line int + ) + for sc.Scan() { + if err := sc.Err(); err != nil { + return err + } + key, v, err := parseKV(sc.Text()) + if err != nil { + return fmt.Errorf("%d: %v", line, err) + } + raw[key] = v + line++ + } + stat.Cache = raw["cache"] + stat.RSS = raw["rss"] + stat.RSSHuge = raw["rss_huge"] + stat.MappedFile = raw["mapped_file"] + stat.Dirty = raw["dirty"] + stat.Writeback = raw["writeback"] + stat.PgPgIn = raw["pgpgin"] + stat.PgPgOut = raw["pgpgout"] + stat.PgFault = raw["pgfault"] + stat.PgMajFault = raw["pgmajfault"] + stat.InactiveAnon = raw["inactive_anon"] + stat.ActiveAnon = raw["active_anon"] + stat.InactiveFile = raw["inactive_file"] + stat.ActiveFile = raw["active_file"] + stat.Unevictable = raw["unevictable"] + stat.HierarchicalMemoryLimit = raw["hierarchical_memory_limit"] + stat.HierarchicalSwapLimit = raw["hierarchical_memsw_limit"] + stat.TotalCache = raw["total_cache"] + stat.TotalRSS = raw["total_rss"] + stat.TotalRSSHuge = raw["total_rss_huge"] + stat.TotalMappedFile = raw["total_mapped_file"] + stat.TotalDirty = raw["total_dirty"] + stat.TotalWriteback = raw["total_writeback"] + stat.TotalPgPgIn = raw["total_pgpgin"] + stat.TotalPgPgOut = raw["total_pgpgout"] + stat.TotalPgFault = raw["total_pgfault"] + stat.TotalPgMajFault = raw["total_pgmajfault"] + stat.TotalInactiveAnon = raw["total_inactive_anon"] + stat.TotalActiveAnon = raw["total_active_anon"] + stat.TotalInactiveFile = raw["total_inactive_file"] + stat.TotalActiveFile = raw["total_active_file"] + stat.TotalUnevictable = raw["total_unevictable"] + return nil +} + +func (m *memoryController) set(path string, settings []memorySettings) error { + for _, t := range settings { + if t.value != nil { + if err := ioutil.WriteFile( + filepath.Join(m.Path(path), fmt.Sprintf("memory.%s", t.name)), + []byte(strconv.FormatInt(*t.value, 10)), + defaultFilePerm, + ); err != nil { + return err + } + } + } + return nil +} + +type memorySettings struct { + name string + value *int64 +} + +func getMemorySettings(resources *specs.LinuxResources) []memorySettings { + mem := resources.Memory + var swappiness *int64 + if mem.Swappiness != nil { + v := int64(*mem.Swappiness) + swappiness = &v + } + return []memorySettings{ + { + name: "limit_in_bytes", + value: mem.Limit, + }, + { + name: "memsw.limit_in_bytes", + value: mem.Swap, + }, + { + name: "kmem.limit_in_bytes", + value: mem.Kernel, + }, + { + name: "kmem.tcp.limit_in_bytes", + value: mem.KernelTCP, + }, + { + name: "oom_control", + value: getOomControlValue(mem), + }, + { + name: "swappiness", + value: swappiness, + }, + } +} + +func checkEBUSY(err error) error { + if pathErr, ok := err.(*os.PathError); ok { + if errNo, ok := pathErr.Err.(syscall.Errno); ok { + if errNo == unix.EBUSY { + return fmt.Errorf( + "failed to set memory.kmem.limit_in_bytes, because either tasks have already joined this cgroup or it has children") + } + } + } + return err +} + +func getOomControlValue(mem *specs.LinuxMemory) *int64 { + if mem.DisableOOMKiller != nil && *mem.DisableOOMKiller { + i := int64(1) + return &i + } + return nil +} diff --git a/vendor/github.com/containerd/cgroups/memory_test.go b/vendor/github.com/containerd/cgroups/memory_test.go new file mode 100644 index 0000000000..2c2e756a69 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/memory_test.go @@ -0,0 +1,106 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "strings" + "testing" +) + +const memoryData = `cache 1 +rss 2 +rss_huge 3 +mapped_file 4 +dirty 5 +writeback 6 +pgpgin 7 +pgpgout 8 +pgfault 9 +pgmajfault 10 +inactive_anon 11 +active_anon 12 +inactive_file 13 +active_file 14 +unevictable 15 +hierarchical_memory_limit 16 +hierarchical_memsw_limit 17 +total_cache 18 +total_rss 19 +total_rss_huge 20 +total_mapped_file 21 +total_dirty 22 +total_writeback 23 +total_pgpgin 24 +total_pgpgout 25 +total_pgfault 26 +total_pgmajfault 27 +total_inactive_anon 28 +total_active_anon 29 +total_inactive_file 30 +total_active_file 31 +total_unevictable 32 +` + +func TestParseMemoryStats(t *testing.T) { + var ( + c = &memoryController{} + m = &MemoryStat{} + r = strings.NewReader(memoryData) + ) + if err := c.parseStats(r, m); err != nil { + t.Fatal(err) + } + index := []uint64{ + m.Cache, + m.RSS, + m.RSSHuge, + m.MappedFile, + m.Dirty, + m.Writeback, + m.PgPgIn, + m.PgPgOut, + m.PgFault, + m.PgMajFault, + m.InactiveAnon, + m.ActiveAnon, + m.InactiveFile, + m.ActiveFile, + m.Unevictable, + m.HierarchicalMemoryLimit, + m.HierarchicalSwapLimit, + m.TotalCache, + m.TotalRSS, + m.TotalRSSHuge, + m.TotalMappedFile, + m.TotalDirty, + m.TotalWriteback, + m.TotalPgPgIn, + m.TotalPgPgOut, + m.TotalPgFault, + m.TotalPgMajFault, + m.TotalInactiveAnon, + m.TotalActiveAnon, + m.TotalInactiveFile, + m.TotalActiveFile, + m.TotalUnevictable, + } + for i, v := range index { + if v != uint64(i)+1 { + t.Errorf("expected value at index %d to be %d but received %d", i, i+1, v) + } + } +} diff --git a/vendor/github.com/containerd/cgroups/metrics.pb.go b/vendor/github.com/containerd/cgroups/metrics.pb.go new file mode 100644 index 0000000000..6043a8f7db --- /dev/null +++ b/vendor/github.com/containerd/cgroups/metrics.pb.go @@ -0,0 +1,4288 @@ +// Code generated by protoc-gen-gogo. +// source: github.com/containerd/cgroups/metrics.proto +// DO NOT EDIT! + +/* + Package cgroups is a generated protocol buffer package. + + It is generated from these files: + github.com/containerd/cgroups/metrics.proto + + It has these top-level messages: + Metrics + HugetlbStat + PidsStat + CPUStat + CPUUsage + Throttle + MemoryStat + MemoryEntry + BlkIOStat + BlkIOEntry + RdmaStat + RdmaEntry +*/ +package cgroups + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type Metrics struct { + Hugetlb []*HugetlbStat `protobuf:"bytes,1,rep,name=hugetlb" json:"hugetlb,omitempty"` + Pids *PidsStat `protobuf:"bytes,2,opt,name=pids" json:"pids,omitempty"` + CPU *CPUStat `protobuf:"bytes,3,opt,name=cpu" json:"cpu,omitempty"` + Memory *MemoryStat `protobuf:"bytes,4,opt,name=memory" json:"memory,omitempty"` + Blkio *BlkIOStat `protobuf:"bytes,5,opt,name=blkio" json:"blkio,omitempty"` + Rdma *RdmaStat `protobuf:"bytes,6,opt,name=rdma" json:"rdma,omitempty"` +} + +func (m *Metrics) Reset() { *m = Metrics{} } +func (*Metrics) ProtoMessage() {} +func (*Metrics) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{0} } + +type HugetlbStat struct { + Usage uint64 `protobuf:"varint,1,opt,name=usage,proto3" json:"usage,omitempty"` + Max uint64 `protobuf:"varint,2,opt,name=max,proto3" json:"max,omitempty"` + Failcnt uint64 `protobuf:"varint,3,opt,name=failcnt,proto3" json:"failcnt,omitempty"` + Pagesize string `protobuf:"bytes,4,opt,name=pagesize,proto3" json:"pagesize,omitempty"` +} + +func (m *HugetlbStat) Reset() { *m = HugetlbStat{} } +func (*HugetlbStat) ProtoMessage() {} +func (*HugetlbStat) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{1} } + +type PidsStat struct { + Current uint64 `protobuf:"varint,1,opt,name=current,proto3" json:"current,omitempty"` + Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` +} + +func (m *PidsStat) Reset() { *m = PidsStat{} } +func (*PidsStat) ProtoMessage() {} +func (*PidsStat) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{2} } + +type CPUStat struct { + Usage *CPUUsage `protobuf:"bytes,1,opt,name=usage" json:"usage,omitempty"` + Throttling *Throttle `protobuf:"bytes,2,opt,name=throttling" json:"throttling,omitempty"` +} + +func (m *CPUStat) Reset() { *m = CPUStat{} } +func (*CPUStat) ProtoMessage() {} +func (*CPUStat) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{3} } + +type CPUUsage struct { + // values in nanoseconds + Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Kernel uint64 `protobuf:"varint,2,opt,name=kernel,proto3" json:"kernel,omitempty"` + User uint64 `protobuf:"varint,3,opt,name=user,proto3" json:"user,omitempty"` + PerCPU []uint64 `protobuf:"varint,4,rep,packed,name=per_cpu,json=perCpu" json:"per_cpu,omitempty"` +} + +func (m *CPUUsage) Reset() { *m = CPUUsage{} } +func (*CPUUsage) ProtoMessage() {} +func (*CPUUsage) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{4} } + +type Throttle struct { + Periods uint64 `protobuf:"varint,1,opt,name=periods,proto3" json:"periods,omitempty"` + ThrottledPeriods uint64 `protobuf:"varint,2,opt,name=throttled_periods,json=throttledPeriods,proto3" json:"throttled_periods,omitempty"` + ThrottledTime uint64 `protobuf:"varint,3,opt,name=throttled_time,json=throttledTime,proto3" json:"throttled_time,omitempty"` +} + +func (m *Throttle) Reset() { *m = Throttle{} } +func (*Throttle) ProtoMessage() {} +func (*Throttle) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{5} } + +type MemoryStat struct { + Cache uint64 `protobuf:"varint,1,opt,name=cache,proto3" json:"cache,omitempty"` + RSS uint64 `protobuf:"varint,2,opt,name=rss,proto3" json:"rss,omitempty"` + RSSHuge uint64 `protobuf:"varint,3,opt,name=rss_huge,json=rssHuge,proto3" json:"rss_huge,omitempty"` + MappedFile uint64 `protobuf:"varint,4,opt,name=mapped_file,json=mappedFile,proto3" json:"mapped_file,omitempty"` + Dirty uint64 `protobuf:"varint,5,opt,name=dirty,proto3" json:"dirty,omitempty"` + Writeback uint64 `protobuf:"varint,6,opt,name=writeback,proto3" json:"writeback,omitempty"` + PgPgIn uint64 `protobuf:"varint,7,opt,name=pg_pg_in,json=pgPgIn,proto3" json:"pg_pg_in,omitempty"` + PgPgOut uint64 `protobuf:"varint,8,opt,name=pg_pg_out,json=pgPgOut,proto3" json:"pg_pg_out,omitempty"` + PgFault uint64 `protobuf:"varint,9,opt,name=pg_fault,json=pgFault,proto3" json:"pg_fault,omitempty"` + PgMajFault uint64 `protobuf:"varint,10,opt,name=pg_maj_fault,json=pgMajFault,proto3" json:"pg_maj_fault,omitempty"` + InactiveAnon uint64 `protobuf:"varint,11,opt,name=inactive_anon,json=inactiveAnon,proto3" json:"inactive_anon,omitempty"` + ActiveAnon uint64 `protobuf:"varint,12,opt,name=active_anon,json=activeAnon,proto3" json:"active_anon,omitempty"` + InactiveFile uint64 `protobuf:"varint,13,opt,name=inactive_file,json=inactiveFile,proto3" json:"inactive_file,omitempty"` + ActiveFile uint64 `protobuf:"varint,14,opt,name=active_file,json=activeFile,proto3" json:"active_file,omitempty"` + Unevictable uint64 `protobuf:"varint,15,opt,name=unevictable,proto3" json:"unevictable,omitempty"` + HierarchicalMemoryLimit uint64 `protobuf:"varint,16,opt,name=hierarchical_memory_limit,json=hierarchicalMemoryLimit,proto3" json:"hierarchical_memory_limit,omitempty"` + HierarchicalSwapLimit uint64 `protobuf:"varint,17,opt,name=hierarchical_swap_limit,json=hierarchicalSwapLimit,proto3" json:"hierarchical_swap_limit,omitempty"` + TotalCache uint64 `protobuf:"varint,18,opt,name=total_cache,json=totalCache,proto3" json:"total_cache,omitempty"` + TotalRSS uint64 `protobuf:"varint,19,opt,name=total_rss,json=totalRss,proto3" json:"total_rss,omitempty"` + TotalRSSHuge uint64 `protobuf:"varint,20,opt,name=total_rss_huge,json=totalRssHuge,proto3" json:"total_rss_huge,omitempty"` + TotalMappedFile uint64 `protobuf:"varint,21,opt,name=total_mapped_file,json=totalMappedFile,proto3" json:"total_mapped_file,omitempty"` + TotalDirty uint64 `protobuf:"varint,22,opt,name=total_dirty,json=totalDirty,proto3" json:"total_dirty,omitempty"` + TotalWriteback uint64 `protobuf:"varint,23,opt,name=total_writeback,json=totalWriteback,proto3" json:"total_writeback,omitempty"` + TotalPgPgIn uint64 `protobuf:"varint,24,opt,name=total_pg_pg_in,json=totalPgPgIn,proto3" json:"total_pg_pg_in,omitempty"` + TotalPgPgOut uint64 `protobuf:"varint,25,opt,name=total_pg_pg_out,json=totalPgPgOut,proto3" json:"total_pg_pg_out,omitempty"` + TotalPgFault uint64 `protobuf:"varint,26,opt,name=total_pg_fault,json=totalPgFault,proto3" json:"total_pg_fault,omitempty"` + TotalPgMajFault uint64 `protobuf:"varint,27,opt,name=total_pg_maj_fault,json=totalPgMajFault,proto3" json:"total_pg_maj_fault,omitempty"` + TotalInactiveAnon uint64 `protobuf:"varint,28,opt,name=total_inactive_anon,json=totalInactiveAnon,proto3" json:"total_inactive_anon,omitempty"` + TotalActiveAnon uint64 `protobuf:"varint,29,opt,name=total_active_anon,json=totalActiveAnon,proto3" json:"total_active_anon,omitempty"` + TotalInactiveFile uint64 `protobuf:"varint,30,opt,name=total_inactive_file,json=totalInactiveFile,proto3" json:"total_inactive_file,omitempty"` + TotalActiveFile uint64 `protobuf:"varint,31,opt,name=total_active_file,json=totalActiveFile,proto3" json:"total_active_file,omitempty"` + TotalUnevictable uint64 `protobuf:"varint,32,opt,name=total_unevictable,json=totalUnevictable,proto3" json:"total_unevictable,omitempty"` + Usage *MemoryEntry `protobuf:"bytes,33,opt,name=usage" json:"usage,omitempty"` + Swap *MemoryEntry `protobuf:"bytes,34,opt,name=swap" json:"swap,omitempty"` + Kernel *MemoryEntry `protobuf:"bytes,35,opt,name=kernel" json:"kernel,omitempty"` + KernelTCP *MemoryEntry `protobuf:"bytes,36,opt,name=kernel_tcp,json=kernelTcp" json:"kernel_tcp,omitempty"` +} + +func (m *MemoryStat) Reset() { *m = MemoryStat{} } +func (*MemoryStat) ProtoMessage() {} +func (*MemoryStat) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{6} } + +type MemoryEntry struct { + Limit uint64 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"` + Usage uint64 `protobuf:"varint,2,opt,name=usage,proto3" json:"usage,omitempty"` + Max uint64 `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty"` + Failcnt uint64 `protobuf:"varint,4,opt,name=failcnt,proto3" json:"failcnt,omitempty"` +} + +func (m *MemoryEntry) Reset() { *m = MemoryEntry{} } +func (*MemoryEntry) ProtoMessage() {} +func (*MemoryEntry) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{7} } + +type BlkIOStat struct { + IoServiceBytesRecursive []*BlkIOEntry `protobuf:"bytes,1,rep,name=io_service_bytes_recursive,json=ioServiceBytesRecursive" json:"io_service_bytes_recursive,omitempty"` + IoServicedRecursive []*BlkIOEntry `protobuf:"bytes,2,rep,name=io_serviced_recursive,json=ioServicedRecursive" json:"io_serviced_recursive,omitempty"` + IoQueuedRecursive []*BlkIOEntry `protobuf:"bytes,3,rep,name=io_queued_recursive,json=ioQueuedRecursive" json:"io_queued_recursive,omitempty"` + IoServiceTimeRecursive []*BlkIOEntry `protobuf:"bytes,4,rep,name=io_service_time_recursive,json=ioServiceTimeRecursive" json:"io_service_time_recursive,omitempty"` + IoWaitTimeRecursive []*BlkIOEntry `protobuf:"bytes,5,rep,name=io_wait_time_recursive,json=ioWaitTimeRecursive" json:"io_wait_time_recursive,omitempty"` + IoMergedRecursive []*BlkIOEntry `protobuf:"bytes,6,rep,name=io_merged_recursive,json=ioMergedRecursive" json:"io_merged_recursive,omitempty"` + IoTimeRecursive []*BlkIOEntry `protobuf:"bytes,7,rep,name=io_time_recursive,json=ioTimeRecursive" json:"io_time_recursive,omitempty"` + SectorsRecursive []*BlkIOEntry `protobuf:"bytes,8,rep,name=sectors_recursive,json=sectorsRecursive" json:"sectors_recursive,omitempty"` +} + +func (m *BlkIOStat) Reset() { *m = BlkIOStat{} } +func (*BlkIOStat) ProtoMessage() {} +func (*BlkIOStat) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{8} } + +type BlkIOEntry struct { + Op string `protobuf:"bytes,1,opt,name=op,proto3" json:"op,omitempty"` + Device string `protobuf:"bytes,2,opt,name=device,proto3" json:"device,omitempty"` + Major uint64 `protobuf:"varint,3,opt,name=major,proto3" json:"major,omitempty"` + Minor uint64 `protobuf:"varint,4,opt,name=minor,proto3" json:"minor,omitempty"` + Value uint64 `protobuf:"varint,5,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *BlkIOEntry) Reset() { *m = BlkIOEntry{} } +func (*BlkIOEntry) ProtoMessage() {} +func (*BlkIOEntry) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{9} } + +type RdmaStat struct { + Current []*RdmaEntry `protobuf:"bytes,1,rep,name=current" json:"current,omitempty"` + Limit []*RdmaEntry `protobuf:"bytes,2,rep,name=limit" json:"limit,omitempty"` +} + +func (m *RdmaStat) Reset() { *m = RdmaStat{} } +func (*RdmaStat) ProtoMessage() {} +func (*RdmaStat) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{10} } + +type RdmaEntry struct { + Device string `protobuf:"bytes,1,opt,name=device,proto3" json:"device,omitempty"` + HcaHandles uint32 `protobuf:"varint,2,opt,name=hca_handles,json=hcaHandles,proto3" json:"hca_handles,omitempty"` + HcaObjects uint32 `protobuf:"varint,3,opt,name=hca_objects,json=hcaObjects,proto3" json:"hca_objects,omitempty"` +} + +func (m *RdmaEntry) Reset() { *m = RdmaEntry{} } +func (*RdmaEntry) ProtoMessage() {} +func (*RdmaEntry) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{11} } + +func init() { + proto.RegisterType((*Metrics)(nil), "io.containerd.cgroups.v1.Metrics") + proto.RegisterType((*HugetlbStat)(nil), "io.containerd.cgroups.v1.HugetlbStat") + proto.RegisterType((*PidsStat)(nil), "io.containerd.cgroups.v1.PidsStat") + proto.RegisterType((*CPUStat)(nil), "io.containerd.cgroups.v1.CPUStat") + proto.RegisterType((*CPUUsage)(nil), "io.containerd.cgroups.v1.CPUUsage") + proto.RegisterType((*Throttle)(nil), "io.containerd.cgroups.v1.Throttle") + proto.RegisterType((*MemoryStat)(nil), "io.containerd.cgroups.v1.MemoryStat") + proto.RegisterType((*MemoryEntry)(nil), "io.containerd.cgroups.v1.MemoryEntry") + proto.RegisterType((*BlkIOStat)(nil), "io.containerd.cgroups.v1.BlkIOStat") + proto.RegisterType((*BlkIOEntry)(nil), "io.containerd.cgroups.v1.BlkIOEntry") + proto.RegisterType((*RdmaStat)(nil), "io.containerd.cgroups.v1.RdmaStat") + proto.RegisterType((*RdmaEntry)(nil), "io.containerd.cgroups.v1.RdmaEntry") +} +func (m *Metrics) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Metrics) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Hugetlb) > 0 { + for _, msg := range m.Hugetlb { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if m.Pids != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Pids.Size())) + n1, err := m.Pids.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } + if m.CPU != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.CPU.Size())) + n2, err := m.CPU.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + } + if m.Memory != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Memory.Size())) + n3, err := m.Memory.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n3 + } + if m.Blkio != nil { + dAtA[i] = 0x2a + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Blkio.Size())) + n4, err := m.Blkio.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n4 + } + if m.Rdma != nil { + dAtA[i] = 0x32 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Rdma.Size())) + n5, err := m.Rdma.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n5 + } + return i, nil +} + +func (m *HugetlbStat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *HugetlbStat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Usage != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Usage)) + } + if m.Max != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Max)) + } + if m.Failcnt != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Failcnt)) + } + if len(m.Pagesize) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(len(m.Pagesize))) + i += copy(dAtA[i:], m.Pagesize) + } + return i, nil +} + +func (m *PidsStat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PidsStat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Current != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Current)) + } + if m.Limit != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Limit)) + } + return i, nil +} + +func (m *CPUStat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CPUStat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Usage != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Usage.Size())) + n5, err := m.Usage.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n5 + } + if m.Throttling != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Throttling.Size())) + n6, err := m.Throttling.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n6 + } + return i, nil +} + +func (m *CPUUsage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CPUUsage) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Total != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Total)) + } + if m.Kernel != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Kernel)) + } + if m.User != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.User)) + } + if len(m.PerCPU) > 0 { + dAtA8 := make([]byte, len(m.PerCPU)*10) + var j7 int + for _, num := range m.PerCPU { + for num >= 1<<7 { + dAtA8[j7] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j7++ + } + dAtA8[j7] = uint8(num) + j7++ + } + dAtA[i] = 0x22 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(j7)) + i += copy(dAtA[i:], dAtA8[:j7]) + } + return i, nil +} + +func (m *Throttle) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Throttle) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Periods != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Periods)) + } + if m.ThrottledPeriods != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.ThrottledPeriods)) + } + if m.ThrottledTime != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.ThrottledTime)) + } + return i, nil +} + +func (m *MemoryStat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MemoryStat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Cache != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Cache)) + } + if m.RSS != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.RSS)) + } + if m.RSSHuge != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.RSSHuge)) + } + if m.MappedFile != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.MappedFile)) + } + if m.Dirty != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Dirty)) + } + if m.Writeback != 0 { + dAtA[i] = 0x30 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Writeback)) + } + if m.PgPgIn != 0 { + dAtA[i] = 0x38 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.PgPgIn)) + } + if m.PgPgOut != 0 { + dAtA[i] = 0x40 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.PgPgOut)) + } + if m.PgFault != 0 { + dAtA[i] = 0x48 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.PgFault)) + } + if m.PgMajFault != 0 { + dAtA[i] = 0x50 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.PgMajFault)) + } + if m.InactiveAnon != 0 { + dAtA[i] = 0x58 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.InactiveAnon)) + } + if m.ActiveAnon != 0 { + dAtA[i] = 0x60 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.ActiveAnon)) + } + if m.InactiveFile != 0 { + dAtA[i] = 0x68 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.InactiveFile)) + } + if m.ActiveFile != 0 { + dAtA[i] = 0x70 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.ActiveFile)) + } + if m.Unevictable != 0 { + dAtA[i] = 0x78 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Unevictable)) + } + if m.HierarchicalMemoryLimit != 0 { + dAtA[i] = 0x80 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.HierarchicalMemoryLimit)) + } + if m.HierarchicalSwapLimit != 0 { + dAtA[i] = 0x88 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.HierarchicalSwapLimit)) + } + if m.TotalCache != 0 { + dAtA[i] = 0x90 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalCache)) + } + if m.TotalRSS != 0 { + dAtA[i] = 0x98 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalRSS)) + } + if m.TotalRSSHuge != 0 { + dAtA[i] = 0xa0 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalRSSHuge)) + } + if m.TotalMappedFile != 0 { + dAtA[i] = 0xa8 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalMappedFile)) + } + if m.TotalDirty != 0 { + dAtA[i] = 0xb0 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalDirty)) + } + if m.TotalWriteback != 0 { + dAtA[i] = 0xb8 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalWriteback)) + } + if m.TotalPgPgIn != 0 { + dAtA[i] = 0xc0 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalPgPgIn)) + } + if m.TotalPgPgOut != 0 { + dAtA[i] = 0xc8 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalPgPgOut)) + } + if m.TotalPgFault != 0 { + dAtA[i] = 0xd0 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalPgFault)) + } + if m.TotalPgMajFault != 0 { + dAtA[i] = 0xd8 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalPgMajFault)) + } + if m.TotalInactiveAnon != 0 { + dAtA[i] = 0xe0 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalInactiveAnon)) + } + if m.TotalActiveAnon != 0 { + dAtA[i] = 0xe8 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalActiveAnon)) + } + if m.TotalInactiveFile != 0 { + dAtA[i] = 0xf0 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalInactiveFile)) + } + if m.TotalActiveFile != 0 { + dAtA[i] = 0xf8 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalActiveFile)) + } + if m.TotalUnevictable != 0 { + dAtA[i] = 0x80 + i++ + dAtA[i] = 0x2 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.TotalUnevictable)) + } + if m.Usage != nil { + dAtA[i] = 0x8a + i++ + dAtA[i] = 0x2 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Usage.Size())) + n9, err := m.Usage.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n9 + } + if m.Swap != nil { + dAtA[i] = 0x92 + i++ + dAtA[i] = 0x2 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Swap.Size())) + n10, err := m.Swap.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n10 + } + if m.Kernel != nil { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x2 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Kernel.Size())) + n11, err := m.Kernel.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n11 + } + if m.KernelTCP != nil { + dAtA[i] = 0xa2 + i++ + dAtA[i] = 0x2 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.KernelTCP.Size())) + n12, err := m.KernelTCP.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n12 + } + return i, nil +} + +func (m *MemoryEntry) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MemoryEntry) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + + if m.Limit != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Limit)) + } + if m.Usage != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Usage)) + } + if m.Max != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Max)) + } + if m.Failcnt != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Failcnt)) + } + return i, nil +} + +func (m *BlkIOStat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlkIOStat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.IoServiceBytesRecursive) > 0 { + for _, msg := range m.IoServiceBytesRecursive { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.IoServicedRecursive) > 0 { + for _, msg := range m.IoServicedRecursive { + dAtA[i] = 0x12 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.IoQueuedRecursive) > 0 { + for _, msg := range m.IoQueuedRecursive { + dAtA[i] = 0x1a + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.IoServiceTimeRecursive) > 0 { + for _, msg := range m.IoServiceTimeRecursive { + dAtA[i] = 0x22 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.IoWaitTimeRecursive) > 0 { + for _, msg := range m.IoWaitTimeRecursive { + dAtA[i] = 0x2a + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.IoMergedRecursive) > 0 { + for _, msg := range m.IoMergedRecursive { + dAtA[i] = 0x32 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.IoTimeRecursive) > 0 { + for _, msg := range m.IoTimeRecursive { + dAtA[i] = 0x3a + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.SectorsRecursive) > 0 { + for _, msg := range m.SectorsRecursive { + dAtA[i] = 0x42 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *BlkIOEntry) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlkIOEntry) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Op) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(len(m.Op))) + i += copy(dAtA[i:], m.Op) + } + if len(m.Device) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(len(m.Device))) + i += copy(dAtA[i:], m.Device) + } + if m.Major != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Major)) + } + if m.Minor != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Minor)) + } + if m.Value != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Value)) + } + return i, nil +} + +func (m *RdmaStat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RdmaStat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Current) > 0 { + for _, msg := range m.Current { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.Limit) > 0 { + for _, msg := range m.Limit { + dAtA[i] = 0x12 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *RdmaEntry) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RdmaEntry) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Device) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(len(m.Device))) + i += copy(dAtA[i:], m.Device) + } + if m.HcaHandles != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.HcaHandles)) + } + if m.HcaObjects != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.HcaObjects)) + } + return i, nil +} + +func encodeFixed64Metrics(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Metrics(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintMetrics(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Metrics) Size() (n int) { + var l int + _ = l + if len(m.Hugetlb) > 0 { + for _, e := range m.Hugetlb { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if m.Pids != nil { + l = m.Pids.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + if m.CPU != nil { + l = m.CPU.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + if m.Memory != nil { + l = m.Memory.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + if m.Blkio != nil { + l = m.Blkio.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + if m.Rdma != nil { + l = m.Rdma.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + return n +} + +func (m *HugetlbStat) Size() (n int) { + var l int + _ = l + if m.Usage != 0 { + n += 1 + sovMetrics(uint64(m.Usage)) + } + if m.Max != 0 { + n += 1 + sovMetrics(uint64(m.Max)) + } + if m.Failcnt != 0 { + n += 1 + sovMetrics(uint64(m.Failcnt)) + } + l = len(m.Pagesize) + if l > 0 { + n += 1 + l + sovMetrics(uint64(l)) + } + return n +} + +func (m *PidsStat) Size() (n int) { + var l int + _ = l + if m.Current != 0 { + n += 1 + sovMetrics(uint64(m.Current)) + } + if m.Limit != 0 { + n += 1 + sovMetrics(uint64(m.Limit)) + } + return n +} + +func (m *CPUStat) Size() (n int) { + var l int + _ = l + if m.Usage != nil { + l = m.Usage.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + if m.Throttling != nil { + l = m.Throttling.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + return n +} + +func (m *CPUUsage) Size() (n int) { + var l int + _ = l + if m.Total != 0 { + n += 1 + sovMetrics(uint64(m.Total)) + } + if m.Kernel != 0 { + n += 1 + sovMetrics(uint64(m.Kernel)) + } + if m.User != 0 { + n += 1 + sovMetrics(uint64(m.User)) + } + if len(m.PerCPU) > 0 { + l = 0 + for _, e := range m.PerCPU { + l += sovMetrics(uint64(e)) + } + n += 1 + sovMetrics(uint64(l)) + l + } + return n +} + +func (m *Throttle) Size() (n int) { + var l int + _ = l + if m.Periods != 0 { + n += 1 + sovMetrics(uint64(m.Periods)) + } + if m.ThrottledPeriods != 0 { + n += 1 + sovMetrics(uint64(m.ThrottledPeriods)) + } + if m.ThrottledTime != 0 { + n += 1 + sovMetrics(uint64(m.ThrottledTime)) + } + return n +} + +func (m *MemoryStat) Size() (n int) { + var l int + _ = l + if m.Cache != 0 { + n += 1 + sovMetrics(uint64(m.Cache)) + } + if m.RSS != 0 { + n += 1 + sovMetrics(uint64(m.RSS)) + } + if m.RSSHuge != 0 { + n += 1 + sovMetrics(uint64(m.RSSHuge)) + } + if m.MappedFile != 0 { + n += 1 + sovMetrics(uint64(m.MappedFile)) + } + if m.Dirty != 0 { + n += 1 + sovMetrics(uint64(m.Dirty)) + } + if m.Writeback != 0 { + n += 1 + sovMetrics(uint64(m.Writeback)) + } + if m.PgPgIn != 0 { + n += 1 + sovMetrics(uint64(m.PgPgIn)) + } + if m.PgPgOut != 0 { + n += 1 + sovMetrics(uint64(m.PgPgOut)) + } + if m.PgFault != 0 { + n += 1 + sovMetrics(uint64(m.PgFault)) + } + if m.PgMajFault != 0 { + n += 1 + sovMetrics(uint64(m.PgMajFault)) + } + if m.InactiveAnon != 0 { + n += 1 + sovMetrics(uint64(m.InactiveAnon)) + } + if m.ActiveAnon != 0 { + n += 1 + sovMetrics(uint64(m.ActiveAnon)) + } + if m.InactiveFile != 0 { + n += 1 + sovMetrics(uint64(m.InactiveFile)) + } + if m.ActiveFile != 0 { + n += 1 + sovMetrics(uint64(m.ActiveFile)) + } + if m.Unevictable != 0 { + n += 1 + sovMetrics(uint64(m.Unevictable)) + } + if m.HierarchicalMemoryLimit != 0 { + n += 2 + sovMetrics(uint64(m.HierarchicalMemoryLimit)) + } + if m.HierarchicalSwapLimit != 0 { + n += 2 + sovMetrics(uint64(m.HierarchicalSwapLimit)) + } + if m.TotalCache != 0 { + n += 2 + sovMetrics(uint64(m.TotalCache)) + } + if m.TotalRSS != 0 { + n += 2 + sovMetrics(uint64(m.TotalRSS)) + } + if m.TotalRSSHuge != 0 { + n += 2 + sovMetrics(uint64(m.TotalRSSHuge)) + } + if m.TotalMappedFile != 0 { + n += 2 + sovMetrics(uint64(m.TotalMappedFile)) + } + if m.TotalDirty != 0 { + n += 2 + sovMetrics(uint64(m.TotalDirty)) + } + if m.TotalWriteback != 0 { + n += 2 + sovMetrics(uint64(m.TotalWriteback)) + } + if m.TotalPgPgIn != 0 { + n += 2 + sovMetrics(uint64(m.TotalPgPgIn)) + } + if m.TotalPgPgOut != 0 { + n += 2 + sovMetrics(uint64(m.TotalPgPgOut)) + } + if m.TotalPgFault != 0 { + n += 2 + sovMetrics(uint64(m.TotalPgFault)) + } + if m.TotalPgMajFault != 0 { + n += 2 + sovMetrics(uint64(m.TotalPgMajFault)) + } + if m.TotalInactiveAnon != 0 { + n += 2 + sovMetrics(uint64(m.TotalInactiveAnon)) + } + if m.TotalActiveAnon != 0 { + n += 2 + sovMetrics(uint64(m.TotalActiveAnon)) + } + if m.TotalInactiveFile != 0 { + n += 2 + sovMetrics(uint64(m.TotalInactiveFile)) + } + if m.TotalActiveFile != 0 { + n += 2 + sovMetrics(uint64(m.TotalActiveFile)) + } + if m.TotalUnevictable != 0 { + n += 2 + sovMetrics(uint64(m.TotalUnevictable)) + } + if m.Usage != nil { + l = m.Usage.Size() + n += 2 + l + sovMetrics(uint64(l)) + } + if m.Swap != nil { + l = m.Swap.Size() + n += 2 + l + sovMetrics(uint64(l)) + } + if m.Kernel != nil { + l = m.Kernel.Size() + n += 2 + l + sovMetrics(uint64(l)) + } + if m.KernelTCP != nil { + l = m.KernelTCP.Size() + n += 2 + l + sovMetrics(uint64(l)) + } + return n +} + +func (m *MemoryEntry) Size() (n int) { + var l int + _ = l + if m.Limit != 0 { + n += 1 + sovMetrics(uint64(m.Limit)) + } + if m.Usage != 0 { + n += 1 + sovMetrics(uint64(m.Usage)) + } + if m.Max != 0 { + n += 1 + sovMetrics(uint64(m.Max)) + } + if m.Failcnt != 0 { + n += 1 + sovMetrics(uint64(m.Failcnt)) + } + return n +} + +func (m *BlkIOStat) Size() (n int) { + var l int + _ = l + if len(m.IoServiceBytesRecursive) > 0 { + for _, e := range m.IoServiceBytesRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.IoServicedRecursive) > 0 { + for _, e := range m.IoServicedRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.IoQueuedRecursive) > 0 { + for _, e := range m.IoQueuedRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.IoServiceTimeRecursive) > 0 { + for _, e := range m.IoServiceTimeRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.IoWaitTimeRecursive) > 0 { + for _, e := range m.IoWaitTimeRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.IoMergedRecursive) > 0 { + for _, e := range m.IoMergedRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.IoTimeRecursive) > 0 { + for _, e := range m.IoTimeRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.SectorsRecursive) > 0 { + for _, e := range m.SectorsRecursive { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + return n +} + +func (m *BlkIOEntry) Size() (n int) { + var l int + _ = l + l = len(m.Op) + if l > 0 { + n += 1 + l + sovMetrics(uint64(l)) + } + l = len(m.Device) + if l > 0 { + n += 1 + l + sovMetrics(uint64(l)) + } + if m.Major != 0 { + n += 1 + sovMetrics(uint64(m.Major)) + } + if m.Minor != 0 { + n += 1 + sovMetrics(uint64(m.Minor)) + } + if m.Value != 0 { + n += 1 + sovMetrics(uint64(m.Value)) + } + return n +} + +func (m *RdmaStat) Size() (n int) { + var l int + _ = l + if len(m.Current) > 0 { + for _, e := range m.Current { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.Limit) > 0 { + for _, e := range m.Limit { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + return n +} + +func (m *RdmaEntry) Size() (n int) { + var l int + _ = l + l = len(m.Device) + if l > 0 { + n += 1 + l + sovMetrics(uint64(l)) + } + if m.HcaHandles != 0 { + n += 1 + sovMetrics(uint64(m.HcaHandles)) + } + if m.HcaObjects != 0 { + n += 1 + sovMetrics(uint64(m.HcaObjects)) + } + return n +} + +func sovMetrics(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozMetrics(x uint64) (n int) { + return sovMetrics(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *Metrics) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Metrics{`, + `Hugetlb:` + strings.Replace(fmt.Sprintf("%v", this.Hugetlb), "HugetlbStat", "HugetlbStat", 1) + `,`, + `Pids:` + strings.Replace(fmt.Sprintf("%v", this.Pids), "PidsStat", "PidsStat", 1) + `,`, + `CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`, + `Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`, + `Blkio:` + strings.Replace(fmt.Sprintf("%v", this.Blkio), "BlkIOStat", "BlkIOStat", 1) + `,`, + `Rdma:` + strings.Replace(fmt.Sprintf("%v", this.Rdma), "RdmaStat", "RdmaStat", 1) + `,`, + `}`, + }, "") + return s +} +func (this *HugetlbStat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&HugetlbStat{`, + `Usage:` + fmt.Sprintf("%v", this.Usage) + `,`, + `Max:` + fmt.Sprintf("%v", this.Max) + `,`, + `Failcnt:` + fmt.Sprintf("%v", this.Failcnt) + `,`, + `Pagesize:` + fmt.Sprintf("%v", this.Pagesize) + `,`, + `}`, + }, "") + return s +} +func (this *PidsStat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PidsStat{`, + `Current:` + fmt.Sprintf("%v", this.Current) + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, + `}`, + }, "") + return s +} +func (this *CPUStat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CPUStat{`, + `Usage:` + strings.Replace(fmt.Sprintf("%v", this.Usage), "CPUUsage", "CPUUsage", 1) + `,`, + `Throttling:` + strings.Replace(fmt.Sprintf("%v", this.Throttling), "Throttle", "Throttle", 1) + `,`, + `}`, + }, "") + return s +} +func (this *CPUUsage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CPUUsage{`, + `Total:` + fmt.Sprintf("%v", this.Total) + `,`, + `Kernel:` + fmt.Sprintf("%v", this.Kernel) + `,`, + `User:` + fmt.Sprintf("%v", this.User) + `,`, + `PerCPU:` + fmt.Sprintf("%v", this.PerCPU) + `,`, + `}`, + }, "") + return s +} +func (this *Throttle) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Throttle{`, + `Periods:` + fmt.Sprintf("%v", this.Periods) + `,`, + `ThrottledPeriods:` + fmt.Sprintf("%v", this.ThrottledPeriods) + `,`, + `ThrottledTime:` + fmt.Sprintf("%v", this.ThrottledTime) + `,`, + `}`, + }, "") + return s +} +func (this *MemoryStat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&MemoryStat{`, + `Cache:` + fmt.Sprintf("%v", this.Cache) + `,`, + `RSS:` + fmt.Sprintf("%v", this.RSS) + `,`, + `RSSHuge:` + fmt.Sprintf("%v", this.RSSHuge) + `,`, + `MappedFile:` + fmt.Sprintf("%v", this.MappedFile) + `,`, + `Dirty:` + fmt.Sprintf("%v", this.Dirty) + `,`, + `Writeback:` + fmt.Sprintf("%v", this.Writeback) + `,`, + `PgPgIn:` + fmt.Sprintf("%v", this.PgPgIn) + `,`, + `PgPgOut:` + fmt.Sprintf("%v", this.PgPgOut) + `,`, + `PgFault:` + fmt.Sprintf("%v", this.PgFault) + `,`, + `PgMajFault:` + fmt.Sprintf("%v", this.PgMajFault) + `,`, + `InactiveAnon:` + fmt.Sprintf("%v", this.InactiveAnon) + `,`, + `ActiveAnon:` + fmt.Sprintf("%v", this.ActiveAnon) + `,`, + `InactiveFile:` + fmt.Sprintf("%v", this.InactiveFile) + `,`, + `ActiveFile:` + fmt.Sprintf("%v", this.ActiveFile) + `,`, + `Unevictable:` + fmt.Sprintf("%v", this.Unevictable) + `,`, + `HierarchicalMemoryLimit:` + fmt.Sprintf("%v", this.HierarchicalMemoryLimit) + `,`, + `HierarchicalSwapLimit:` + fmt.Sprintf("%v", this.HierarchicalSwapLimit) + `,`, + `TotalCache:` + fmt.Sprintf("%v", this.TotalCache) + `,`, + `TotalRSS:` + fmt.Sprintf("%v", this.TotalRSS) + `,`, + `TotalRSSHuge:` + fmt.Sprintf("%v", this.TotalRSSHuge) + `,`, + `TotalMappedFile:` + fmt.Sprintf("%v", this.TotalMappedFile) + `,`, + `TotalDirty:` + fmt.Sprintf("%v", this.TotalDirty) + `,`, + `TotalWriteback:` + fmt.Sprintf("%v", this.TotalWriteback) + `,`, + `TotalPgPgIn:` + fmt.Sprintf("%v", this.TotalPgPgIn) + `,`, + `TotalPgPgOut:` + fmt.Sprintf("%v", this.TotalPgPgOut) + `,`, + `TotalPgFault:` + fmt.Sprintf("%v", this.TotalPgFault) + `,`, + `TotalPgMajFault:` + fmt.Sprintf("%v", this.TotalPgMajFault) + `,`, + `TotalInactiveAnon:` + fmt.Sprintf("%v", this.TotalInactiveAnon) + `,`, + `TotalActiveAnon:` + fmt.Sprintf("%v", this.TotalActiveAnon) + `,`, + `TotalInactiveFile:` + fmt.Sprintf("%v", this.TotalInactiveFile) + `,`, + `TotalActiveFile:` + fmt.Sprintf("%v", this.TotalActiveFile) + `,`, + `TotalUnevictable:` + fmt.Sprintf("%v", this.TotalUnevictable) + `,`, + `Usage:` + strings.Replace(fmt.Sprintf("%v", this.Usage), "MemoryEntry", "MemoryEntry", 1) + `,`, + `Swap:` + strings.Replace(fmt.Sprintf("%v", this.Swap), "MemoryEntry", "MemoryEntry", 1) + `,`, + `Kernel:` + strings.Replace(fmt.Sprintf("%v", this.Kernel), "MemoryEntry", "MemoryEntry", 1) + `,`, + `KernelTCP:` + strings.Replace(fmt.Sprintf("%v", this.KernelTCP), "MemoryEntry", "MemoryEntry", 1) + `,`, + `}`, + }, "") + return s +} +func (this *MemoryEntry) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&MemoryEntry{`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, + `Usage:` + fmt.Sprintf("%v", this.Usage) + `,`, + `Max:` + fmt.Sprintf("%v", this.Max) + `,`, + `Failcnt:` + fmt.Sprintf("%v", this.Failcnt) + `,`, + `}`, + }, "") + return s +} +func (this *BlkIOStat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&BlkIOStat{`, + `IoServiceBytesRecursive:` + strings.Replace(fmt.Sprintf("%v", this.IoServiceBytesRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `IoServicedRecursive:` + strings.Replace(fmt.Sprintf("%v", this.IoServicedRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `IoQueuedRecursive:` + strings.Replace(fmt.Sprintf("%v", this.IoQueuedRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `IoServiceTimeRecursive:` + strings.Replace(fmt.Sprintf("%v", this.IoServiceTimeRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `IoWaitTimeRecursive:` + strings.Replace(fmt.Sprintf("%v", this.IoWaitTimeRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `IoMergedRecursive:` + strings.Replace(fmt.Sprintf("%v", this.IoMergedRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `IoTimeRecursive:` + strings.Replace(fmt.Sprintf("%v", this.IoTimeRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `SectorsRecursive:` + strings.Replace(fmt.Sprintf("%v", this.SectorsRecursive), "BlkIOEntry", "BlkIOEntry", 1) + `,`, + `}`, + }, "") + return s +} +func (this *BlkIOEntry) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&BlkIOEntry{`, + `Op:` + fmt.Sprintf("%v", this.Op) + `,`, + `Device:` + fmt.Sprintf("%v", this.Device) + `,`, + `Major:` + fmt.Sprintf("%v", this.Major) + `,`, + `Minor:` + fmt.Sprintf("%v", this.Minor) + `,`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `}`, + }, "") + return s +} +func (this *RdmaStat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RdmaStat{`, + `Current:` + strings.Replace(fmt.Sprintf("%v", this.Current), "RdmaEntry", "RdmaEntry", 1) + `,`, + `Limit:` + strings.Replace(fmt.Sprintf("%v", this.Limit), "RdmaEntry", "RdmaEntry", 1) + `,`, + `}`, + }, "") + return s +} +func (this *RdmaEntry) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RdmaEntry{`, + `Device:` + fmt.Sprintf("%v", this.Device) + `,`, + `HcaHandles:` + fmt.Sprintf("%v", this.HcaHandles) + `,`, + `HcaObjects:` + fmt.Sprintf("%v", this.HcaObjects) + `,`, + `}`, + }, "") + return s +} +func valueToStringMetrics(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *Metrics) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Metrics: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Metrics: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hugetlb", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hugetlb = append(m.Hugetlb, &HugetlbStat{}) + if err := m.Hugetlb[len(m.Hugetlb)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pids", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pids == nil { + m.Pids = &PidsStat{} + } + if err := m.Pids.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CPU", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CPU == nil { + m.CPU = &CPUStat{} + } + if err := m.CPU.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Memory", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Memory == nil { + m.Memory = &MemoryStat{} + } + if err := m.Memory.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blkio", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Blkio == nil { + m.Blkio = &BlkIOStat{} + } + if err := m.Blkio.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rdma", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Rdma == nil { + m.Rdma = &RdmaStat{} + } + if err := m.Rdma.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *HugetlbStat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: HugetlbStat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: HugetlbStat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Usage", wireType) + } + m.Usage = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Usage |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Max", wireType) + } + m.Max = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Max |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Failcnt", wireType) + } + m.Failcnt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Failcnt |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagesize", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pagesize = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PidsStat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PidsStat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PidsStat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Current", wireType) + } + m.Current = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Current |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CPUStat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CPUStat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CPUStat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Usage", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Usage == nil { + m.Usage = &CPUUsage{} + } + if err := m.Usage.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Throttling", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Throttling == nil { + m.Throttling = &Throttle{} + } + if err := m.Throttling.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CPUUsage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CPUUsage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CPUUsage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + m.Total = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Total |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Kernel", wireType) + } + m.Kernel = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Kernel |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + m.User = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.User |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.PerCPU = append(m.PerCPU, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + packedLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.PerCPU = append(m.PerCPU, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field PerCPU", wireType) + } + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Throttle) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Throttle: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Throttle: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Periods", wireType) + } + m.Periods = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Periods |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ThrottledPeriods", wireType) + } + m.ThrottledPeriods = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ThrottledPeriods |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ThrottledTime", wireType) + } + m.ThrottledTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ThrottledTime |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MemoryStat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MemoryStat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MemoryStat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Cache", wireType) + } + m.Cache = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Cache |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RSS", wireType) + } + m.RSS = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RSS |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RSSHuge", wireType) + } + m.RSSHuge = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RSSHuge |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MappedFile", wireType) + } + m.MappedFile = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MappedFile |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Dirty", wireType) + } + m.Dirty = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Dirty |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Writeback", wireType) + } + m.Writeback = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Writeback |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PgPgIn", wireType) + } + m.PgPgIn = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PgPgIn |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PgPgOut", wireType) + } + m.PgPgOut = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PgPgOut |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PgFault", wireType) + } + m.PgFault = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PgFault |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PgMajFault", wireType) + } + m.PgMajFault = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PgMajFault |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InactiveAnon", wireType) + } + m.InactiveAnon = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InactiveAnon |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ActiveAnon", wireType) + } + m.ActiveAnon = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ActiveAnon |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InactiveFile", wireType) + } + m.InactiveFile = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InactiveFile |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ActiveFile", wireType) + } + m.ActiveFile = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ActiveFile |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 15: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Unevictable", wireType) + } + m.Unevictable = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Unevictable |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 16: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HierarchicalMemoryLimit", wireType) + } + m.HierarchicalMemoryLimit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HierarchicalMemoryLimit |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 17: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HierarchicalSwapLimit", wireType) + } + m.HierarchicalSwapLimit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HierarchicalSwapLimit |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 18: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalCache", wireType) + } + m.TotalCache = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalCache |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 19: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalRSS", wireType) + } + m.TotalRSS = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalRSS |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 20: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalRSSHuge", wireType) + } + m.TotalRSSHuge = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalRSSHuge |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 21: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalMappedFile", wireType) + } + m.TotalMappedFile = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalMappedFile |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 22: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalDirty", wireType) + } + m.TotalDirty = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalDirty |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 23: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalWriteback", wireType) + } + m.TotalWriteback = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalWriteback |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 24: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalPgPgIn", wireType) + } + m.TotalPgPgIn = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalPgPgIn |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 25: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalPgPgOut", wireType) + } + m.TotalPgPgOut = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalPgPgOut |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 26: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalPgFault", wireType) + } + m.TotalPgFault = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalPgFault |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 27: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalPgMajFault", wireType) + } + m.TotalPgMajFault = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalPgMajFault |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 28: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalInactiveAnon", wireType) + } + m.TotalInactiveAnon = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalInactiveAnon |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 29: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalActiveAnon", wireType) + } + m.TotalActiveAnon = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalActiveAnon |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 30: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalInactiveFile", wireType) + } + m.TotalInactiveFile = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalInactiveFile |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 31: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalActiveFile", wireType) + } + m.TotalActiveFile = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalActiveFile |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 32: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalUnevictable", wireType) + } + m.TotalUnevictable = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalUnevictable |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 33: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Usage", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Usage == nil { + m.Usage = &MemoryEntry{} + } + if err := m.Usage.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 34: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Swap", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Swap == nil { + m.Swap = &MemoryEntry{} + } + if err := m.Swap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 35: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Kernel", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Kernel == nil { + m.Kernel = &MemoryEntry{} + } + if err := m.Kernel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 36: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field KernelTCP", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.KernelTCP == nil { + m.KernelTCP = &MemoryEntry{} + } + if err := m.KernelTCP.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MemoryEntry) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MemoryEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MemoryEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Usage", wireType) + } + m.Usage = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Usage |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Max", wireType) + } + m.Max = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Max |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Failcnt", wireType) + } + m.Failcnt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Failcnt |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlkIOStat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlkIOStat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlkIOStat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IoServiceBytesRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IoServiceBytesRecursive = append(m.IoServiceBytesRecursive, &BlkIOEntry{}) + if err := m.IoServiceBytesRecursive[len(m.IoServiceBytesRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IoServicedRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IoServicedRecursive = append(m.IoServicedRecursive, &BlkIOEntry{}) + if err := m.IoServicedRecursive[len(m.IoServicedRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IoQueuedRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IoQueuedRecursive = append(m.IoQueuedRecursive, &BlkIOEntry{}) + if err := m.IoQueuedRecursive[len(m.IoQueuedRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IoServiceTimeRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IoServiceTimeRecursive = append(m.IoServiceTimeRecursive, &BlkIOEntry{}) + if err := m.IoServiceTimeRecursive[len(m.IoServiceTimeRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IoWaitTimeRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IoWaitTimeRecursive = append(m.IoWaitTimeRecursive, &BlkIOEntry{}) + if err := m.IoWaitTimeRecursive[len(m.IoWaitTimeRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IoMergedRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IoMergedRecursive = append(m.IoMergedRecursive, &BlkIOEntry{}) + if err := m.IoMergedRecursive[len(m.IoMergedRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IoTimeRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IoTimeRecursive = append(m.IoTimeRecursive, &BlkIOEntry{}) + if err := m.IoTimeRecursive[len(m.IoTimeRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SectorsRecursive", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SectorsRecursive = append(m.SectorsRecursive, &BlkIOEntry{}) + if err := m.SectorsRecursive[len(m.SectorsRecursive)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlkIOEntry) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlkIOEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlkIOEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Op", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Op = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Device", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Device = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Major", wireType) + } + m.Major = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Major |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Minor", wireType) + } + m.Minor = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Minor |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RdmaStat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RdmaStat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RdmaStat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Current", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Current = append(m.Current, &RdmaEntry{}) + if err := m.Current[len(m.Current)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Limit = append(m.Limit, &RdmaEntry{}) + if err := m.Limit[len(m.Limit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RdmaEntry) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RdmaEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RdmaEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Device", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Device = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HcaHandles", wireType) + } + m.HcaHandles = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HcaHandles |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HcaObjects", wireType) + } + m.HcaObjects = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HcaObjects |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + +func skipMetrics(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMetrics + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMetrics + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMetrics + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthMetrics + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMetrics + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipMetrics(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthMetrics = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowMetrics = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("github.com/containerd/cgroups/metrics.proto", fileDescriptorMetrics) } + +var fileDescriptorMetrics = []byte{ + // 1325 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x57, 0x4d, 0x6f, 0x1b, 0xb7, + 0x16, 0x8d, 0xac, 0xb1, 0x3e, 0xae, 0x6c, 0xc7, 0xa6, 0x13, 0x67, 0xec, 0x97, 0x27, 0x29, 0xb2, + 0xfd, 0x9e, 0x5b, 0x03, 0x32, 0x9a, 0x02, 0x41, 0x93, 0xa6, 0x28, 0x22, 0xb7, 0x41, 0x83, 0xd6, + 0x88, 0x32, 0xb2, 0x91, 0x76, 0x35, 0x18, 0x8d, 0x98, 0x31, 0xe3, 0xd1, 0x70, 0xc2, 0xe1, 0xc8, + 0x71, 0x57, 0xdd, 0xf5, 0x37, 0xf5, 0x1f, 0x64, 0xd9, 0x4d, 0x81, 0x76, 0x63, 0x34, 0xfa, 0x25, + 0x05, 0x2f, 0xe7, 0x4b, 0x49, 0xdc, 0x40, 0xbb, 0xb9, 0xbc, 0xe7, 0x1c, 0x5e, 0x5e, 0x1e, 0x8a, + 0x14, 0xec, 0x7b, 0x4c, 0x9e, 0xc6, 0xc3, 0xae, 0xcb, 0xc7, 0x07, 0x2e, 0x0f, 0xa4, 0xc3, 0x02, + 0x2a, 0x46, 0x07, 0xae, 0x27, 0x78, 0x1c, 0x46, 0x07, 0x63, 0x2a, 0x05, 0x73, 0xa3, 0x6e, 0x28, + 0xb8, 0xe4, 0xc4, 0x64, 0xbc, 0x9b, 0x83, 0xba, 0x09, 0xa8, 0x3b, 0xf9, 0x6c, 0xeb, 0x86, 0xc7, + 0x3d, 0x8e, 0xa0, 0x03, 0xf5, 0xa5, 0xf1, 0x9d, 0xdf, 0x16, 0xa0, 0x7a, 0xa4, 0x15, 0xc8, 0xd7, + 0x50, 0x3d, 0x8d, 0x3d, 0x2a, 0xfd, 0xa1, 0x59, 0x6a, 0x97, 0xf7, 0x1a, 0x77, 0x77, 0xbb, 0x57, + 0xa9, 0x75, 0xbf, 0xd3, 0xc0, 0x81, 0x74, 0xa4, 0x95, 0xb2, 0xc8, 0x3d, 0x30, 0x42, 0x36, 0x8a, + 0xcc, 0x85, 0x76, 0x69, 0xaf, 0x71, 0xb7, 0x73, 0x35, 0xbb, 0xcf, 0x46, 0x11, 0x52, 0x11, 0x4f, + 0x1e, 0x42, 0xd9, 0x0d, 0x63, 0xb3, 0x8c, 0xb4, 0x3b, 0x57, 0xd3, 0x0e, 0xfb, 0x27, 0x8a, 0xd5, + 0xab, 0x4e, 0x2f, 0x5b, 0xe5, 0xc3, 0xfe, 0x89, 0xa5, 0x68, 0xe4, 0x21, 0x54, 0xc6, 0x74, 0xcc, + 0xc5, 0x85, 0x69, 0xa0, 0xc0, 0xce, 0xd5, 0x02, 0x47, 0x88, 0xc3, 0x99, 0x13, 0x0e, 0xb9, 0x0f, + 0x8b, 0x43, 0xff, 0x8c, 0x71, 0x73, 0x11, 0xc9, 0xdb, 0x57, 0x93, 0x7b, 0xfe, 0xd9, 0x93, 0xa7, + 0xc8, 0xd5, 0x8c, 0xce, 0x19, 0x34, 0x0a, 0x6d, 0x20, 0x37, 0x60, 0x31, 0x8e, 0x1c, 0x8f, 0x9a, + 0xa5, 0x76, 0x69, 0xcf, 0xb0, 0x74, 0x40, 0x56, 0xa1, 0x3c, 0x76, 0x5e, 0x63, 0x4b, 0x0c, 0x4b, + 0x7d, 0x12, 0x13, 0xaa, 0x2f, 0x1c, 0xe6, 0xbb, 0x81, 0xc4, 0x15, 0x1b, 0x56, 0x1a, 0x92, 0x2d, + 0xa8, 0x85, 0x8e, 0x47, 0x23, 0xf6, 0x33, 0xc5, 0xb5, 0xd4, 0xad, 0x2c, 0xee, 0x3c, 0x80, 0x5a, + 0xda, 0x35, 0xa5, 0xe0, 0xc6, 0x42, 0xd0, 0x40, 0x26, 0x73, 0xa5, 0xa1, 0xaa, 0xc1, 0x67, 0x63, + 0x26, 0x93, 0xf9, 0x74, 0xd0, 0xf9, 0xb5, 0x04, 0xd5, 0xa4, 0x77, 0xe4, 0x8b, 0x62, 0x95, 0xff, + 0xba, 0x49, 0x87, 0xfd, 0x93, 0x13, 0x85, 0x4c, 0x57, 0xd2, 0x03, 0x90, 0xa7, 0x82, 0x4b, 0xe9, + 0xb3, 0xc0, 0xfb, 0xf8, 0x1e, 0x1f, 0x6b, 0x2c, 0xb5, 0x0a, 0xac, 0xce, 0x2b, 0xa8, 0xa5, 0xb2, + 0xaa, 0x56, 0xc9, 0xa5, 0xe3, 0xa7, 0xfd, 0xc2, 0x80, 0x6c, 0x40, 0xe5, 0x8c, 0x8a, 0x80, 0xfa, + 0xc9, 0x12, 0x92, 0x88, 0x10, 0x30, 0xe2, 0x88, 0x8a, 0xa4, 0x65, 0xf8, 0x4d, 0xb6, 0xa1, 0x1a, + 0x52, 0x61, 0x2b, 0xef, 0x18, 0xed, 0xf2, 0x9e, 0xd1, 0x83, 0xe9, 0x65, 0xab, 0xd2, 0xa7, 0x42, + 0x79, 0xa3, 0x12, 0x52, 0x71, 0x18, 0xc6, 0x9d, 0xd7, 0x50, 0x4b, 0x4b, 0x51, 0x8d, 0x0b, 0xa9, + 0x60, 0x7c, 0x14, 0xa5, 0x8d, 0x4b, 0x42, 0xb2, 0x0f, 0x6b, 0x49, 0x99, 0x74, 0x64, 0xa7, 0x18, + 0x5d, 0xc1, 0x6a, 0x96, 0xe8, 0x27, 0xe0, 0x5d, 0x58, 0xc9, 0xc1, 0x92, 0x8d, 0x69, 0x52, 0xd5, + 0x72, 0x36, 0x7a, 0xcc, 0xc6, 0xb4, 0xf3, 0x57, 0x03, 0x20, 0x77, 0x9c, 0x5a, 0xaf, 0xeb, 0xb8, + 0xa7, 0x99, 0x3f, 0x30, 0x20, 0x9b, 0x50, 0x16, 0x51, 0x32, 0x95, 0x36, 0xb6, 0x35, 0x18, 0x58, + 0x6a, 0x8c, 0xfc, 0x0f, 0x6a, 0x22, 0x8a, 0x6c, 0x75, 0xba, 0xf4, 0x04, 0xbd, 0xc6, 0xf4, 0xb2, + 0x55, 0xb5, 0x06, 0x03, 0x65, 0x3b, 0xab, 0x2a, 0xa2, 0x48, 0x7d, 0x90, 0x16, 0x34, 0xc6, 0x4e, + 0x18, 0xd2, 0x91, 0xfd, 0x82, 0xf9, 0xda, 0x39, 0x86, 0x05, 0x7a, 0xe8, 0x31, 0xf3, 0xb1, 0xd3, + 0x23, 0x26, 0xe4, 0x05, 0x7a, 0xdc, 0xb0, 0x74, 0x40, 0x6e, 0x43, 0xfd, 0x5c, 0x30, 0x49, 0x87, + 0x8e, 0x7b, 0x66, 0x56, 0x30, 0x93, 0x0f, 0x10, 0x13, 0x6a, 0xa1, 0x67, 0x87, 0x9e, 0xcd, 0x02, + 0xb3, 0xaa, 0x77, 0x22, 0xf4, 0xfa, 0xde, 0x93, 0x80, 0x6c, 0x41, 0x5d, 0x67, 0x78, 0x2c, 0xcd, + 0x5a, 0xd2, 0x46, 0xaf, 0xef, 0x3d, 0x8d, 0x25, 0xd9, 0x44, 0xd6, 0x0b, 0x27, 0xf6, 0xa5, 0x59, + 0x4f, 0x53, 0x8f, 0x55, 0x48, 0xda, 0xb0, 0x14, 0x7a, 0xf6, 0xd8, 0x79, 0x99, 0xa4, 0x41, 0x97, + 0x19, 0x7a, 0x47, 0xce, 0x4b, 0x8d, 0xd8, 0x86, 0x65, 0x16, 0x38, 0xae, 0x64, 0x13, 0x6a, 0x3b, + 0x01, 0x0f, 0xcc, 0x06, 0x42, 0x96, 0xd2, 0xc1, 0x47, 0x01, 0x0f, 0xd4, 0x62, 0x8b, 0x90, 0x25, + 0xad, 0x52, 0x00, 0x14, 0x55, 0xb0, 0x1f, 0xcb, 0xb3, 0x2a, 0xd8, 0x91, 0x5c, 0x05, 0x21, 0x2b, + 0x45, 0x15, 0x04, 0xb4, 0xa1, 0x11, 0x07, 0x74, 0xc2, 0x5c, 0xe9, 0x0c, 0x7d, 0x6a, 0x5e, 0x47, + 0x40, 0x71, 0x88, 0x3c, 0x80, 0xcd, 0x53, 0x46, 0x85, 0x23, 0xdc, 0x53, 0xe6, 0x3a, 0xbe, 0xad, + 0x7f, 0x4f, 0x6c, 0x7d, 0xfc, 0x56, 0x11, 0x7f, 0xab, 0x08, 0xd0, 0x4e, 0xf8, 0x41, 0xa5, 0xc9, + 0x3d, 0x98, 0x49, 0xd9, 0xd1, 0xb9, 0x13, 0x26, 0xcc, 0x35, 0x64, 0xde, 0x2c, 0xa6, 0x07, 0xe7, + 0x4e, 0xa8, 0x79, 0x2d, 0x68, 0xe0, 0x29, 0xb1, 0xb5, 0x91, 0x88, 0x2e, 0x1b, 0x87, 0x0e, 0xd1, + 0x4d, 0x9f, 0x40, 0x5d, 0x03, 0x94, 0xa7, 0xd6, 0xd1, 0x33, 0x4b, 0xd3, 0xcb, 0x56, 0xed, 0x58, + 0x0d, 0x2a, 0x63, 0xd5, 0x30, 0x6d, 0x45, 0x11, 0xb9, 0x07, 0x2b, 0x19, 0x54, 0x7b, 0xec, 0x06, + 0xe2, 0x57, 0xa7, 0x97, 0xad, 0xa5, 0x14, 0x8f, 0x46, 0x5b, 0x4a, 0x39, 0xe8, 0xb6, 0x4f, 0x61, + 0x4d, 0xf3, 0x8a, 0x9e, 0xbb, 0x89, 0x95, 0x5c, 0xc7, 0xc4, 0x51, 0x6e, 0xbc, 0xac, 0x5e, 0x6d, + 0xbf, 0x8d, 0x42, 0xbd, 0xdf, 0xa0, 0x07, 0xff, 0x0f, 0x9a, 0x63, 0xe7, 0x4e, 0xbc, 0x85, 0x20, + 0x5d, 0xdb, 0xf3, 0xcc, 0x8e, 0xdb, 0x69, 0xb5, 0x99, 0x29, 0x4d, 0xbd, 0x25, 0x38, 0xda, 0xd7, + 0xce, 0xdc, 0x4d, 0xd5, 0x72, 0x7f, 0x6e, 0xea, 0xcd, 0xcf, 0x50, 0xca, 0xa4, 0x3b, 0x05, 0x2d, + 0xed, 0xc5, 0xad, 0x19, 0x94, 0x76, 0xe3, 0x3e, 0x90, 0x0c, 0x95, 0xbb, 0xf6, 0x3f, 0x85, 0x85, + 0xf6, 0x73, 0xeb, 0x76, 0x61, 0x5d, 0x83, 0x67, 0x0d, 0x7c, 0x1b, 0xd1, 0xba, 0x5f, 0x4f, 0x8a, + 0x2e, 0xce, 0x9a, 0x58, 0x44, 0xff, 0xb7, 0xa0, 0xfd, 0x28, 0xc7, 0xbe, 0xaf, 0x8d, 0x2d, 0x6f, + 0x7e, 0x40, 0x1b, 0x9b, 0xfe, 0xae, 0x36, 0xa2, 0x5b, 0xef, 0x69, 0x23, 0x76, 0x3f, 0xc5, 0x16, + 0xcd, 0xde, 0x4e, 0x7e, 0xf6, 0x54, 0xe2, 0xa4, 0xe0, 0xf8, 0x2f, 0xd3, 0xab, 0xe3, 0x0e, 0xfe, + 0xf6, 0xef, 0x7e, 0xec, 0x9e, 0xfd, 0x36, 0x90, 0xe2, 0x22, 0xbd, 0x3d, 0xee, 0x83, 0xa1, 0x5c, + 0x6e, 0x76, 0xe6, 0xe1, 0x22, 0x85, 0x7c, 0x95, 0x5d, 0x09, 0xdb, 0xf3, 0x90, 0xd3, 0x9b, 0x63, + 0x00, 0xa0, 0xbf, 0x6c, 0xe9, 0x86, 0xe6, 0xce, 0x1c, 0x12, 0xbd, 0xe5, 0xe9, 0x65, 0xab, 0xfe, + 0x3d, 0x92, 0x8f, 0x0f, 0xfb, 0x56, 0x5d, 0xeb, 0x1c, 0xbb, 0x61, 0x87, 0x42, 0xa3, 0x00, 0xcc, + 0xef, 0xdd, 0x52, 0xe1, 0xde, 0xcd, 0x5f, 0x04, 0x0b, 0x1f, 0x78, 0x11, 0x94, 0x3f, 0xf8, 0x22, + 0x30, 0x66, 0x5e, 0x04, 0x9d, 0x3f, 0x16, 0xa1, 0x9e, 0xbd, 0x3b, 0x88, 0x03, 0x5b, 0x8c, 0xdb, + 0x11, 0x15, 0x13, 0xe6, 0x52, 0x7b, 0x78, 0x21, 0x69, 0x64, 0x0b, 0xea, 0xc6, 0x22, 0x62, 0x13, + 0x9a, 0xbc, 0xd9, 0x76, 0x3e, 0xf2, 0x80, 0xd1, 0xbd, 0xb9, 0xc5, 0xf8, 0x40, 0xcb, 0xf4, 0x94, + 0x8a, 0x95, 0x8a, 0x90, 0x1f, 0xe1, 0x66, 0x3e, 0xc5, 0xa8, 0xa0, 0xbe, 0x30, 0x87, 0xfa, 0x7a, + 0xa6, 0x3e, 0xca, 0x95, 0x8f, 0x61, 0x9d, 0x71, 0xfb, 0x55, 0x4c, 0xe3, 0x19, 0xdd, 0xf2, 0x1c, + 0xba, 0x6b, 0x8c, 0x3f, 0x43, 0x7e, 0xae, 0x6a, 0xc3, 0x66, 0xa1, 0x25, 0xea, 0x2e, 0x2e, 0x68, + 0x1b, 0x73, 0x68, 0x6f, 0x64, 0x35, 0xab, 0xbb, 0x3b, 0x9f, 0xe0, 0x27, 0xd8, 0x60, 0xdc, 0x3e, + 0x77, 0x98, 0x7c, 0x57, 0x7d, 0x71, 0xbe, 0x8e, 0x3c, 0x77, 0x98, 0x9c, 0x95, 0xd6, 0x1d, 0x19, + 0x53, 0xe1, 0xcd, 0x74, 0xa4, 0x32, 0x5f, 0x47, 0x8e, 0x90, 0x9f, 0xab, 0xf6, 0x61, 0x8d, 0xf1, + 0x77, 0x6b, 0xad, 0xce, 0xa1, 0x79, 0x9d, 0xf1, 0xd9, 0x3a, 0x9f, 0xc1, 0x5a, 0x44, 0x5d, 0xc9, + 0x45, 0xd1, 0x6d, 0xb5, 0x39, 0x14, 0x57, 0x13, 0x7a, 0x26, 0xd9, 0x99, 0x00, 0xe4, 0x79, 0xb2, + 0x02, 0x0b, 0x3c, 0xc4, 0xa3, 0x53, 0xb7, 0x16, 0x78, 0xa8, 0xde, 0x80, 0x23, 0xf5, 0xb3, 0xa3, + 0x0f, 0x4e, 0xdd, 0x4a, 0x22, 0x75, 0x9e, 0xc6, 0xce, 0x4b, 0x9e, 0x3e, 0x02, 0x75, 0x80, 0xa3, + 0x2c, 0xe0, 0x22, 0x39, 0x3b, 0x3a, 0x50, 0xa3, 0x13, 0xc7, 0x8f, 0x69, 0xfa, 0xe6, 0xc1, 0xa0, + 0x67, 0xbe, 0x79, 0xdb, 0xbc, 0xf6, 0xe7, 0xdb, 0xe6, 0xb5, 0x5f, 0xa6, 0xcd, 0xd2, 0x9b, 0x69, + 0xb3, 0xf4, 0xfb, 0xb4, 0x59, 0xfa, 0x7b, 0xda, 0x2c, 0x0d, 0x2b, 0xf8, 0x7f, 0xe8, 0xf3, 0x7f, + 0x02, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x21, 0x0b, 0xcd, 0x6e, 0x0d, 0x00, 0x00, +} diff --git a/vendor/github.com/containerd/cgroups/metrics.pb.txt b/vendor/github.com/containerd/cgroups/metrics.pb.txt new file mode 100644 index 0000000000..86aacd5413 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/metrics.pb.txt @@ -0,0 +1,638 @@ +file { + name: "github.com/containerd/cgroups/metrics.proto" + package: "io.containerd.cgroups.v1" + dependency: "gogoproto/gogo.proto" + message_type { + name: "Metrics" + field { + name: "hugetlb" + number: 1 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.HugetlbStat" + json_name: "hugetlb" + } + field { + name: "pids" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.PidsStat" + json_name: "pids" + } + field { + name: "cpu" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.CPUStat" + options { + 65004: "CPU" + } + json_name: "cpu" + } + field { + name: "memory" + number: 4 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.MemoryStat" + json_name: "memory" + } + field { + name: "blkio" + number: 5 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOStat" + json_name: "blkio" + } + field { + name: "rdma" + number: 6 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.RdmaStat" + json_name: "rdma" + } + } + message_type { + name: "HugetlbStat" + field { + name: "usage" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "usage" + } + field { + name: "max" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "max" + } + field { + name: "failcnt" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "failcnt" + } + field { + name: "pagesize" + number: 4 + label: LABEL_OPTIONAL + type: TYPE_STRING + json_name: "pagesize" + } + } + message_type { + name: "PidsStat" + field { + name: "current" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "current" + } + field { + name: "limit" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "limit" + } + } + message_type { + name: "CPUStat" + field { + name: "usage" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.CPUUsage" + json_name: "usage" + } + field { + name: "throttling" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.Throttle" + json_name: "throttling" + } + } + message_type { + name: "CPUUsage" + field { + name: "total" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "total" + } + field { + name: "kernel" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "kernel" + } + field { + name: "user" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "user" + } + field { + name: "per_cpu" + number: 4 + label: LABEL_REPEATED + type: TYPE_UINT64 + options { + 65004: "PerCPU" + } + json_name: "perCpu" + } + } + message_type { + name: "Throttle" + field { + name: "periods" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "periods" + } + field { + name: "throttled_periods" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "throttledPeriods" + } + field { + name: "throttled_time" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "throttledTime" + } + } + message_type { + name: "MemoryStat" + field { + name: "cache" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "cache" + } + field { + name: "rss" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + options { + 65004: "RSS" + } + json_name: "rss" + } + field { + name: "rss_huge" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + options { + 65004: "RSSHuge" + } + json_name: "rssHuge" + } + field { + name: "mapped_file" + number: 4 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "mappedFile" + } + field { + name: "dirty" + number: 5 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "dirty" + } + field { + name: "writeback" + number: 6 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "writeback" + } + field { + name: "pg_pg_in" + number: 7 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "pgPgIn" + } + field { + name: "pg_pg_out" + number: 8 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "pgPgOut" + } + field { + name: "pg_fault" + number: 9 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "pgFault" + } + field { + name: "pg_maj_fault" + number: 10 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "pgMajFault" + } + field { + name: "inactive_anon" + number: 11 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "inactiveAnon" + } + field { + name: "active_anon" + number: 12 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "activeAnon" + } + field { + name: "inactive_file" + number: 13 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "inactiveFile" + } + field { + name: "active_file" + number: 14 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "activeFile" + } + field { + name: "unevictable" + number: 15 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "unevictable" + } + field { + name: "hierarchical_memory_limit" + number: 16 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "hierarchicalMemoryLimit" + } + field { + name: "hierarchical_swap_limit" + number: 17 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "hierarchicalSwapLimit" + } + field { + name: "total_cache" + number: 18 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalCache" + } + field { + name: "total_rss" + number: 19 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + options { + 65004: "TotalRSS" + } + json_name: "totalRss" + } + field { + name: "total_rss_huge" + number: 20 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + options { + 65004: "TotalRSSHuge" + } + json_name: "totalRssHuge" + } + field { + name: "total_mapped_file" + number: 21 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalMappedFile" + } + field { + name: "total_dirty" + number: 22 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalDirty" + } + field { + name: "total_writeback" + number: 23 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalWriteback" + } + field { + name: "total_pg_pg_in" + number: 24 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalPgPgIn" + } + field { + name: "total_pg_pg_out" + number: 25 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalPgPgOut" + } + field { + name: "total_pg_fault" + number: 26 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalPgFault" + } + field { + name: "total_pg_maj_fault" + number: 27 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalPgMajFault" + } + field { + name: "total_inactive_anon" + number: 28 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalInactiveAnon" + } + field { + name: "total_active_anon" + number: 29 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalActiveAnon" + } + field { + name: "total_inactive_file" + number: 30 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalInactiveFile" + } + field { + name: "total_active_file" + number: 31 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalActiveFile" + } + field { + name: "total_unevictable" + number: 32 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "totalUnevictable" + } + field { + name: "usage" + number: 33 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.MemoryEntry" + json_name: "usage" + } + field { + name: "swap" + number: 34 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.MemoryEntry" + json_name: "swap" + } + field { + name: "kernel" + number: 35 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.MemoryEntry" + json_name: "kernel" + } + field { + name: "kernel_tcp" + number: 36 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.MemoryEntry" + options { + 65004: "KernelTCP" + } + json_name: "kernelTcp" + } + } + message_type { + name: "MemoryEntry" + field { + name: "limit" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "limit" + } + field { + name: "usage" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "usage" + } + field { + name: "max" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "max" + } + field { + name: "failcnt" + number: 4 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "failcnt" + } + } + message_type { + name: "BlkIOStat" + field { + name: "io_service_bytes_recursive" + number: 1 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "ioServiceBytesRecursive" + } + field { + name: "io_serviced_recursive" + number: 2 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "ioServicedRecursive" + } + field { + name: "io_queued_recursive" + number: 3 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "ioQueuedRecursive" + } + field { + name: "io_service_time_recursive" + number: 4 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "ioServiceTimeRecursive" + } + field { + name: "io_wait_time_recursive" + number: 5 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "ioWaitTimeRecursive" + } + field { + name: "io_merged_recursive" + number: 6 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "ioMergedRecursive" + } + field { + name: "io_time_recursive" + number: 7 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "ioTimeRecursive" + } + field { + name: "sectors_recursive" + number: 8 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.BlkIOEntry" + json_name: "sectorsRecursive" + } + } + message_type { + name: "BlkIOEntry" + field { + name: "op" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_STRING + json_name: "op" + } + field { + name: "device" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_STRING + json_name: "device" + } + field { + name: "major" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "major" + } + field { + name: "minor" + number: 4 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "minor" + } + field { + name: "value" + number: 5 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "value" + } + } + message_type { + name: "RdmaStat" + field { + name: "current" + number: 1 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.RdmaEntry" + json_name: "current" + } + field { + name: "limit" + number: 2 + label: LABEL_REPEATED + type: TYPE_MESSAGE + type_name: ".io.containerd.cgroups.v1.RdmaEntry" + json_name: "limit" + } + } + message_type { + name: "RdmaEntry" + field { + name: "device" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_STRING + json_name: "device" + } + field { + name: "hca_handles" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "hca_handles" + } + field { + name: "hca_objects" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_UINT64 + json_name: "hca_objects" + } + } + syntax: "proto3" +} diff --git a/vendor/github.com/containerd/cgroups/metrics.proto b/vendor/github.com/containerd/cgroups/metrics.proto new file mode 100644 index 0000000000..642623fcee --- /dev/null +++ b/vendor/github.com/containerd/cgroups/metrics.proto @@ -0,0 +1,123 @@ +syntax = "proto3"; + +package io.containerd.cgroups.v1; + +import "gogoproto/gogo.proto"; + +message Metrics { + repeated HugetlbStat hugetlb = 1; + PidsStat pids = 2; + CPUStat cpu = 3 [(gogoproto.customname) = "CPU"]; + MemoryStat memory = 4; + BlkIOStat blkio = 5; + RdmaStat rdma = 6; +} + +message HugetlbStat { + uint64 usage = 1; + uint64 max = 2; + uint64 failcnt = 3; + string pagesize = 4; +} + +message PidsStat { + uint64 current = 1; + uint64 limit = 2; +} + +message CPUStat { + CPUUsage usage = 1; + Throttle throttling = 2; +} + +message CPUUsage { + // values in nanoseconds + uint64 total = 1; + uint64 kernel = 2; + uint64 user = 3; + repeated uint64 per_cpu = 4 [(gogoproto.customname) = "PerCPU"]; + +} + +message Throttle { + uint64 periods = 1; + uint64 throttled_periods = 2; + uint64 throttled_time = 3; +} + +message MemoryStat { + uint64 cache = 1; + uint64 rss = 2 [(gogoproto.customname) = "RSS"]; + uint64 rss_huge = 3 [(gogoproto.customname) = "RSSHuge"]; + uint64 mapped_file = 4; + uint64 dirty = 5; + uint64 writeback = 6; + uint64 pg_pg_in = 7; + uint64 pg_pg_out = 8; + uint64 pg_fault = 9; + uint64 pg_maj_fault = 10; + uint64 inactive_anon = 11; + uint64 active_anon = 12; + uint64 inactive_file = 13; + uint64 active_file = 14; + uint64 unevictable = 15; + uint64 hierarchical_memory_limit = 16; + uint64 hierarchical_swap_limit = 17; + uint64 total_cache = 18; + uint64 total_rss = 19 [(gogoproto.customname) = "TotalRSS"]; + uint64 total_rss_huge = 20 [(gogoproto.customname) = "TotalRSSHuge"]; + uint64 total_mapped_file = 21; + uint64 total_dirty = 22; + uint64 total_writeback = 23; + uint64 total_pg_pg_in = 24; + uint64 total_pg_pg_out = 25; + uint64 total_pg_fault = 26; + uint64 total_pg_maj_fault = 27; + uint64 total_inactive_anon = 28; + uint64 total_active_anon = 29; + uint64 total_inactive_file = 30; + uint64 total_active_file = 31; + uint64 total_unevictable = 32; + MemoryEntry usage = 33; + MemoryEntry swap = 34; + MemoryEntry kernel = 35; + MemoryEntry kernel_tcp = 36 [(gogoproto.customname) = "KernelTCP"]; + +} + +message MemoryEntry { + uint64 limit = 1; + uint64 usage = 2; + uint64 max = 3; + uint64 failcnt = 4; +} + +message BlkIOStat { + repeated BlkIOEntry io_service_bytes_recursive = 1; + repeated BlkIOEntry io_serviced_recursive = 2; + repeated BlkIOEntry io_queued_recursive = 3; + repeated BlkIOEntry io_service_time_recursive = 4; + repeated BlkIOEntry io_wait_time_recursive = 5; + repeated BlkIOEntry io_merged_recursive = 6; + repeated BlkIOEntry io_time_recursive = 7; + repeated BlkIOEntry sectors_recursive = 8; +} + +message BlkIOEntry { + string op = 1; + string device = 2; + uint64 major = 3; + uint64 minor = 4; + uint64 value = 5; +} + +message RdmaStat { + repeated RdmaEntry current = 1; + repeated RdmaEntry limit = 2; +} + +message RdmaEntry { + string device = 1; + uint32 hca_handles = 2; + uint32 hca_objects = 3; +} diff --git a/vendor/github.com/containerd/cgroups/mock_test.go b/vendor/github.com/containerd/cgroups/mock_test.go new file mode 100644 index 0000000000..6cc1bfb7e3 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/mock_test.go @@ -0,0 +1,78 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +func init() { + defaultFilePerm = 0666 +} + +func newMock() (*mockCgroup, error) { + root, err := ioutil.TempDir("", "cgroups") + if err != nil { + return nil, err + } + subsystems, err := defaults(root) + if err != nil { + return nil, err + } + for _, s := range subsystems { + if err := os.MkdirAll(filepath.Join(root, string(s.Name())), defaultDirPerm); err != nil { + return nil, err + } + } + // make cpuset root files + for _, v := range []struct { + name string + value []byte + }{ + { + name: "cpuset.cpus", + value: []byte("0-3"), + }, + { + name: "cpuset.mems", + value: []byte("0-3"), + }, + } { + if err := ioutil.WriteFile(filepath.Join(root, "cpuset", v.name), v.value, defaultFilePerm); err != nil { + return nil, err + } + } + return &mockCgroup{ + root: root, + subsystems: subsystems, + }, nil +} + +type mockCgroup struct { + root string + subsystems []Subsystem +} + +func (m *mockCgroup) delete() error { + return os.RemoveAll(m.root) +} + +func (m *mockCgroup) hierarchy() ([]Subsystem, error) { + return m.subsystems, nil +} diff --git a/vendor/github.com/containerd/cgroups/named.go b/vendor/github.com/containerd/cgroups/named.go new file mode 100644 index 0000000000..06b16c3b15 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/named.go @@ -0,0 +1,39 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import "path/filepath" + +func NewNamed(root string, name Name) *namedController { + return &namedController{ + root: root, + name: name, + } +} + +type namedController struct { + root string + name Name +} + +func (n *namedController) Name() Name { + return n.name +} + +func (n *namedController) Path(path string) string { + return filepath.Join(n.root, string(n.name), path) +} diff --git a/vendor/github.com/containerd/cgroups/named_test.go b/vendor/github.com/containerd/cgroups/named_test.go new file mode 100644 index 0000000000..5415d62b10 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/named_test.go @@ -0,0 +1,34 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import "testing" + +func TestNamedNameValue(t *testing.T) { + n := NewNamed("/sys/fs/cgroup", "systemd") + if n.name != "systemd" { + t.Fatalf("expected name %q to be systemd", n.name) + } +} + +func TestNamedPath(t *testing.T) { + n := NewNamed("/sys/fs/cgroup", "systemd") + path := n.Path("/test") + if expected := "/sys/fs/cgroup/systemd/test"; path != expected { + t.Fatalf("expected %q but received %q from named cgroup", expected, path) + } +} diff --git a/vendor/github.com/containerd/cgroups/net_cls.go b/vendor/github.com/containerd/cgroups/net_cls.go new file mode 100644 index 0000000000..8f1a2651f8 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/net_cls.go @@ -0,0 +1,58 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "io/ioutil" + "os" + "path/filepath" + "strconv" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewNetCls(root string) *netclsController { + return &netclsController{ + root: filepath.Join(root, string(NetCLS)), + } +} + +type netclsController struct { + root string +} + +func (n *netclsController) Name() Name { + return NetCLS +} + +func (n *netclsController) Path(path string) string { + return filepath.Join(n.root, path) +} + +func (n *netclsController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(n.Path(path), defaultDirPerm); err != nil { + return err + } + if resources.Network != nil && resources.Network.ClassID != nil && *resources.Network.ClassID > 0 { + return ioutil.WriteFile( + filepath.Join(n.Path(path), "net_cls.classid"), + []byte(strconv.FormatUint(uint64(*resources.Network.ClassID), 10)), + defaultFilePerm, + ) + } + return nil +} diff --git a/vendor/github.com/containerd/cgroups/net_prio.go b/vendor/github.com/containerd/cgroups/net_prio.go new file mode 100644 index 0000000000..c77169215c --- /dev/null +++ b/vendor/github.com/containerd/cgroups/net_prio.go @@ -0,0 +1,66 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewNetPrio(root string) *netprioController { + return &netprioController{ + root: filepath.Join(root, string(NetPrio)), + } +} + +type netprioController struct { + root string +} + +func (n *netprioController) Name() Name { + return NetPrio +} + +func (n *netprioController) Path(path string) string { + return filepath.Join(n.root, path) +} + +func (n *netprioController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(n.Path(path), defaultDirPerm); err != nil { + return err + } + if resources.Network != nil { + for _, prio := range resources.Network.Priorities { + if err := ioutil.WriteFile( + filepath.Join(n.Path(path), "net_prio_ifpriomap"), + formatPrio(prio.Name, prio.Priority), + defaultFilePerm, + ); err != nil { + return err + } + } + } + return nil +} + +func formatPrio(name string, prio uint32) []byte { + return []byte(fmt.Sprintf("%s %d", name, prio)) +} diff --git a/vendor/github.com/containerd/cgroups/paths.go b/vendor/github.com/containerd/cgroups/paths.go new file mode 100644 index 0000000000..455ce857f9 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/paths.go @@ -0,0 +1,104 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + "path/filepath" + + "github.com/pkg/errors" +) + +type Path func(subsystem Name) (string, error) + +func RootPath(subsysem Name) (string, error) { + return "/", nil +} + +// StaticPath returns a static path to use for all cgroups +func StaticPath(path string) Path { + return func(_ Name) (string, error) { + return path, nil + } +} + +// NestedPath will nest the cgroups based on the calling processes cgroup +// placing its child processes inside its own path +func NestedPath(suffix string) Path { + paths, err := parseCgroupFile("/proc/self/cgroup") + if err != nil { + return errorPath(err) + } + return existingPath(paths, suffix) +} + +// PidPath will return the correct cgroup paths for an existing process running inside a cgroup +// This is commonly used for the Load function to restore an existing container +func PidPath(pid int) Path { + p := fmt.Sprintf("/proc/%d/cgroup", pid) + paths, err := parseCgroupFile(p) + if err != nil { + return errorPath(errors.Wrapf(err, "parse cgroup file %s", p)) + } + return existingPath(paths, "") +} + +func existingPath(paths map[string]string, suffix string) Path { + // localize the paths based on the root mount dest for nested cgroups + for n, p := range paths { + dest, err := getCgroupDestination(string(n)) + if err != nil { + return errorPath(err) + } + rel, err := filepath.Rel(dest, p) + if err != nil { + return errorPath(err) + } + if rel == "." { + rel = dest + } + paths[n] = filepath.Join("/", rel) + } + return func(name Name) (string, error) { + root, ok := paths[string(name)] + if !ok { + if root, ok = paths[fmt.Sprintf("name=%s", name)]; !ok { + return "", fmt.Errorf("unable to find %q in controller set", name) + } + } + if suffix != "" { + return filepath.Join(root, suffix), nil + } + return root, nil + } +} + +func subPath(path Path, subName string) Path { + return func(name Name) (string, error) { + p, err := path(name) + if err != nil { + return "", err + } + return filepath.Join(p, subName), nil + } +} + +func errorPath(err error) Path { + return func(_ Name) (string, error) { + return "", err + } +} diff --git a/vendor/github.com/containerd/cgroups/paths_test.go b/vendor/github.com/containerd/cgroups/paths_test.go new file mode 100644 index 0000000000..f708b90667 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/paths_test.go @@ -0,0 +1,114 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func TestStaticPath(t *testing.T) { + path := StaticPath("test") + p, err := path("") + if err != nil { + t.Fatal(err) + } + if p != "test" { + t.Fatalf("expected static path of \"test\" but received %q", p) + } +} + +func TestSelfPath(t *testing.T) { + _, err := v1MountPoint() + if err == ErrMountPointNotExist { + t.Skip("skipping test that requires cgroup hierarchy") + } else if err != nil { + t.Fatal(err) + } + paths, err := parseCgroupFile("/proc/self/cgroup") + if err != nil { + t.Fatal(err) + } + dp := strings.TrimPrefix(paths["devices"], "/") + path := NestedPath("test") + p, err := path("devices") + if err != nil { + t.Fatal(err) + } + if p != filepath.Join("/", dp, "test") { + t.Fatalf("expected self path of %q but received %q", filepath.Join("/", dp, "test"), p) + } +} + +func TestPidPath(t *testing.T) { + _, err := v1MountPoint() + if err == ErrMountPointNotExist { + t.Skip("skipping test that requires cgroup hierarchy") + } else if err != nil { + t.Fatal(err) + } + paths, err := parseCgroupFile("/proc/self/cgroup") + if err != nil { + t.Fatal(err) + } + dp := strings.TrimPrefix(paths["devices"], "/") + path := PidPath(os.Getpid()) + p, err := path("devices") + if err != nil { + t.Fatal(err) + } + if p != filepath.Join("/", dp) { + t.Fatalf("expected self path of %q but received %q", filepath.Join("/", dp), p) + } +} + +func TestRootPath(t *testing.T) { + p, err := RootPath(Cpu) + if err != nil { + t.Error(err) + return + } + if p != "/" { + t.Errorf("expected / but received %q", p) + } +} + +func TestEmptySubsystem(t *testing.T) { + const data = `10:devices:/user.slice + 9:net_cls,net_prio:/ + 8:blkio:/ + 7:freezer:/ + 6:perf_event:/ + 5:cpuset:/ + 4:memory:/ + 3:pids:/user.slice/user-1000.slice/user@1000.service + 2:cpu,cpuacct:/ + 1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service + 0::/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service` + r := strings.NewReader(data) + paths, err := parseCgroupFromReader(r) + if err != nil { + t.Fatal(err) + } + for subsystem, path := range paths { + if subsystem == "" { + t.Fatalf("empty subsystem for %q", path) + } + } +} diff --git a/vendor/github.com/containerd/cgroups/perf_event.go b/vendor/github.com/containerd/cgroups/perf_event.go new file mode 100644 index 0000000000..648786db68 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/perf_event.go @@ -0,0 +1,37 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import "path/filepath" + +func NewPerfEvent(root string) *PerfEventController { + return &PerfEventController{ + root: filepath.Join(root, string(PerfEvent)), + } +} + +type PerfEventController struct { + root string +} + +func (p *PerfEventController) Name() Name { + return PerfEvent +} + +func (p *PerfEventController) Path(path string) string { + return filepath.Join(p.root, path) +} diff --git a/vendor/github.com/containerd/cgroups/pids.go b/vendor/github.com/containerd/cgroups/pids.go new file mode 100644 index 0000000000..a1cfcb88d4 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/pids.go @@ -0,0 +1,85 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func NewPids(root string) *pidsController { + return &pidsController{ + root: filepath.Join(root, string(Pids)), + } +} + +type pidsController struct { + root string +} + +func (p *pidsController) Name() Name { + return Pids +} + +func (p *pidsController) Path(path string) string { + return filepath.Join(p.root, path) +} + +func (p *pidsController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(p.Path(path), defaultDirPerm); err != nil { + return err + } + if resources.Pids != nil && resources.Pids.Limit > 0 { + return ioutil.WriteFile( + filepath.Join(p.Path(path), "pids.max"), + []byte(strconv.FormatInt(resources.Pids.Limit, 10)), + defaultFilePerm, + ) + } + return nil +} + +func (p *pidsController) Update(path string, resources *specs.LinuxResources) error { + return p.Create(path, resources) +} + +func (p *pidsController) Stat(path string, stats *Metrics) error { + current, err := readUint(filepath.Join(p.Path(path), "pids.current")) + if err != nil { + return err + } + var max uint64 + maxData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "pids.max")) + if err != nil { + return err + } + if maxS := strings.TrimSpace(string(maxData)); maxS != "max" { + if max, err = parseUint(maxS, 10, 64); err != nil { + return err + } + } + stats.Pids = &PidsStat{ + Current: current, + Limit: max, + } + return nil +} diff --git a/vendor/github.com/containerd/cgroups/rdma.go b/vendor/github.com/containerd/cgroups/rdma.go new file mode 100644 index 0000000000..4f423d33a0 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/rdma.go @@ -0,0 +1,153 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "io/ioutil" + "math" + "os" + "path/filepath" + "strconv" + "strings" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +type rdmaController struct { + root string +} + +func (p *rdmaController) Name() Name { + return Rdma +} + +func (p *rdmaController) Path(path string) string { + return filepath.Join(p.root, path) +} + +func NewRdma(root string) *rdmaController { + return &rdmaController{ + root: filepath.Join(root, string(Rdma)), + } +} + +func createCmdString(device string, limits *specs.LinuxRdma) string { + var cmdString string + + cmdString = device + if limits.HcaHandles != nil { + cmdString = cmdString + " " + "hca_handle=" + strconv.FormatUint(uint64(*limits.HcaHandles), 10) + } + + if limits.HcaObjects != nil { + cmdString = cmdString + " " + "hca_object=" + strconv.FormatUint(uint64(*limits.HcaObjects), 10) + } + return cmdString +} + +func (p *rdmaController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(p.Path(path), defaultDirPerm); err != nil { + return err + } + + for device, limit := range resources.Rdma { + if device != "" && (limit.HcaHandles != nil || limit.HcaObjects != nil) { + return ioutil.WriteFile( + filepath.Join(p.Path(path), "rdma.max"), + []byte(createCmdString(device, &limit)), + defaultFilePerm, + ) + } + } + return nil +} + +func (p *rdmaController) Update(path string, resources *specs.LinuxResources) error { + return p.Create(path, resources) +} + +func parseRdmaKV(raw string, entry *RdmaEntry) { + var value uint64 + var err error + + parts := strings.Split(raw, "=") + switch len(parts) { + case 2: + if parts[1] == "max" { + value = math.MaxUint32 + } else { + value, err = parseUint(parts[1], 10, 32) + if err != nil { + return + } + } + if parts[0] == "hca_handle" { + entry.HcaHandles = uint32(value) + } else if parts[0] == "hca_object" { + entry.HcaObjects = uint32(value) + } + } +} + +func toRdmaEntry(strEntries []string) []*RdmaEntry { + var rdmaEntries []*RdmaEntry + for i := range strEntries { + parts := strings.Fields(strEntries[i]) + switch len(parts) { + case 3: + entry := new(RdmaEntry) + entry.Device = parts[0] + parseRdmaKV(parts[1], entry) + parseRdmaKV(parts[2], entry) + + rdmaEntries = append(rdmaEntries, entry) + default: + continue + } + } + return rdmaEntries +} + +func (p *rdmaController) Stat(path string, stats *Metrics) error { + + currentData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.current")) + if err != nil { + return err + } + currentPerDevices := strings.Split(string(currentData), "\n") + + maxData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.max")) + if err != nil { + return err + } + maxPerDevices := strings.Split(string(maxData), "\n") + + // If device got removed between reading two files, ignore returning + // stats. + if len(currentPerDevices) != len(maxPerDevices) { + return nil + } + + currentEntries := toRdmaEntry(currentPerDevices) + maxEntries := toRdmaEntry(maxPerDevices) + + stats.Rdma = &RdmaStat{ + Current: currentEntries, + Limit: maxEntries, + } + return nil +} diff --git a/vendor/github.com/containerd/cgroups/state.go b/vendor/github.com/containerd/cgroups/state.go new file mode 100644 index 0000000000..cfeabbbc60 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/state.go @@ -0,0 +1,28 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +// State is a type that represents the state of the current cgroup +type State string + +const ( + Unknown State = "" + Thawed State = "thawed" + Frozen State = "frozen" + Freezing State = "freezing" + Deleted State = "deleted" +) diff --git a/vendor/github.com/containerd/cgroups/subsystem.go b/vendor/github.com/containerd/cgroups/subsystem.go new file mode 100644 index 0000000000..933a6c38d6 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/subsystem.go @@ -0,0 +1,112 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +// Name is a typed name for a cgroup subsystem +type Name string + +const ( + Devices Name = "devices" + Hugetlb Name = "hugetlb" + Freezer Name = "freezer" + Pids Name = "pids" + NetCLS Name = "net_cls" + NetPrio Name = "net_prio" + PerfEvent Name = "perf_event" + Cpuset Name = "cpuset" + Cpu Name = "cpu" + Cpuacct Name = "cpuacct" + Memory Name = "memory" + Blkio Name = "blkio" + Rdma Name = "rdma" +) + +// Subsystems returns a complete list of the default cgroups +// avaliable on most linux systems +func Subsystems() []Name { + n := []Name{ + Hugetlb, + Freezer, + Pids, + NetCLS, + NetPrio, + PerfEvent, + Cpuset, + Cpu, + Cpuacct, + Memory, + Blkio, + Rdma, + } + if !isUserNS { + n = append(n, Devices) + } + return n +} + +type Subsystem interface { + Name() Name +} + +type pather interface { + Subsystem + Path(path string) string +} + +type creator interface { + Subsystem + Create(path string, resources *specs.LinuxResources) error +} + +type deleter interface { + Subsystem + Delete(path string) error +} + +type stater interface { + Subsystem + Stat(path string, stats *Metrics) error +} + +type updater interface { + Subsystem + Update(path string, resources *specs.LinuxResources) error +} + +// SingleSubsystem returns a single cgroup subsystem within the base Hierarchy +func SingleSubsystem(baseHierarchy Hierarchy, subsystem Name) Hierarchy { + return func() ([]Subsystem, error) { + subsystems, err := baseHierarchy() + if err != nil { + return nil, err + } + for _, s := range subsystems { + if s.Name() == subsystem { + return []Subsystem{ + s, + }, nil + } + } + return nil, fmt.Errorf("unable to find subsystem %s", subsystem) + } +} diff --git a/vendor/github.com/containerd/cgroups/systemd.go b/vendor/github.com/containerd/cgroups/systemd.go new file mode 100644 index 0000000000..8153d744ce --- /dev/null +++ b/vendor/github.com/containerd/cgroups/systemd.go @@ -0,0 +1,131 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "fmt" + "path/filepath" + "strings" + "sync" + + systemdDbus "github.com/coreos/go-systemd/dbus" + "github.com/godbus/dbus" + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +const ( + SystemdDbus Name = "systemd" + defaultSlice = "system.slice" +) + +func Systemd() ([]Subsystem, error) { + root, err := v1MountPoint() + if err != nil { + return nil, err + } + defaultSubsystems, err := defaults(root) + if err != nil { + return nil, err + } + s, err := NewSystemd(root) + if err != nil { + return nil, err + } + // make sure the systemd controller is added first + return append([]Subsystem{s}, defaultSubsystems...), nil +} + +func Slice(slice, name string) Path { + if slice == "" { + slice = defaultSlice + } + return func(subsystem Name) (string, error) { + return filepath.Join(slice, unitName(name)), nil + } +} + +func NewSystemd(root string) (*SystemdController, error) { + return &SystemdController{ + root: root, + }, nil +} + +type SystemdController struct { + mu sync.Mutex + root string +} + +func (s *SystemdController) Name() Name { + return SystemdDbus +} + +func (s *SystemdController) Create(path string, resources *specs.LinuxResources) error { + conn, err := systemdDbus.New() + if err != nil { + return err + } + defer conn.Close() + slice, name := splitName(path) + properties := []systemdDbus.Property{ + systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)), + systemdDbus.PropWants(slice), + newProperty("DefaultDependencies", false), + newProperty("Delegate", true), + newProperty("MemoryAccounting", true), + newProperty("CPUAccounting", true), + newProperty("BlockIOAccounting", true), + } + ch := make(chan string) + _, err = conn.StartTransientUnit(name, "replace", properties, ch) + if err != nil { + return err + } + <-ch + return nil +} + +func (s *SystemdController) Delete(path string) error { + conn, err := systemdDbus.New() + if err != nil { + return err + } + defer conn.Close() + _, name := splitName(path) + ch := make(chan string) + _, err = conn.StopUnit(name, "replace", ch) + if err != nil { + return err + } + <-ch + return nil +} + +func newProperty(name string, units interface{}) systemdDbus.Property { + return systemdDbus.Property{ + Name: name, + Value: dbus.MakeVariant(units), + } +} + +func unitName(name string) string { + return fmt.Sprintf("%s.slice", name) +} + +func splitName(path string) (slice string, unit string) { + slice, unit = filepath.Split(path) + return strings.TrimSuffix(slice, "/"), unit +} diff --git a/vendor/github.com/containerd/cgroups/ticks.go b/vendor/github.com/containerd/cgroups/ticks.go new file mode 100644 index 0000000000..84dc38d0cc --- /dev/null +++ b/vendor/github.com/containerd/cgroups/ticks.go @@ -0,0 +1,26 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +func getClockTicks() uint64 { + // The value comes from `C.sysconf(C._SC_CLK_TCK)`, and + // on Linux it's a constant which is safe to be hard coded, + // so we can avoid using cgo here. + // See https://github.com/containerd/cgroups/pull/12 for + // more details. + return 100 +} diff --git a/vendor/github.com/containerd/cgroups/utils.go b/vendor/github.com/containerd/cgroups/utils.go new file mode 100644 index 0000000000..345be4e463 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/utils.go @@ -0,0 +1,297 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + units "github.com/docker/go-units" + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +var isUserNS = runningInUserNS() + +// runningInUserNS detects whether we are currently running in a user namespace. +// Copied from github.com/lxc/lxd/shared/util.go +func runningInUserNS() bool { + file, err := os.Open("/proc/self/uid_map") + if err != nil { + // This kernel-provided file only exists if user namespaces are supported + return false + } + defer file.Close() + + buf := bufio.NewReader(file) + l, _, err := buf.ReadLine() + if err != nil { + return false + } + + line := string(l) + var a, b, c int64 + fmt.Sscanf(line, "%d %d %d", &a, &b, &c) + /* + * We assume we are in the initial user namespace if we have a full + * range - 4294967295 uids starting at uid 0. + */ + if a == 0 && b == 0 && c == 4294967295 { + return false + } + return true +} + +// defaults returns all known groups +func defaults(root string) ([]Subsystem, error) { + h, err := NewHugetlb(root) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + s := []Subsystem{ + NewNamed(root, "systemd"), + NewFreezer(root), + NewPids(root), + NewNetCls(root), + NewNetPrio(root), + NewPerfEvent(root), + NewCputset(root), + NewCpu(root), + NewCpuacct(root), + NewMemory(root), + NewBlkio(root), + NewRdma(root), + } + // only add the devices cgroup if we are not in a user namespace + // because modifications are not allowed + if !isUserNS { + s = append(s, NewDevices(root)) + } + // add the hugetlb cgroup if error wasn't due to missing hugetlb + // cgroup support on the host + if err == nil { + s = append(s, h) + } + return s, nil +} + +// remove will remove a cgroup path handling EAGAIN and EBUSY errors and +// retrying the remove after a exp timeout +func remove(path string) error { + delay := 10 * time.Millisecond + for i := 0; i < 5; i++ { + if i != 0 { + time.Sleep(delay) + delay *= 2 + } + if err := os.RemoveAll(path); err == nil { + return nil + } + } + return fmt.Errorf("cgroups: unable to remove path %q", path) +} + +// readPids will read all the pids in a cgroup by the provided path +func readPids(path string, subsystem Name) ([]Process, error) { + f, err := os.Open(filepath.Join(path, cgroupProcs)) + if err != nil { + return nil, err + } + defer f.Close() + var ( + out []Process + s = bufio.NewScanner(f) + ) + for s.Scan() { + if t := s.Text(); t != "" { + pid, err := strconv.Atoi(t) + if err != nil { + return nil, err + } + out = append(out, Process{ + Pid: pid, + Subsystem: subsystem, + Path: path, + }) + } + } + return out, nil +} + +func hugePageSizes() ([]string, error) { + var ( + pageSizes []string + sizeList = []string{"B", "kB", "MB", "GB", "TB", "PB"} + ) + files, err := ioutil.ReadDir("/sys/kernel/mm/hugepages") + if err != nil { + return nil, err + } + for _, st := range files { + nameArray := strings.Split(st.Name(), "-") + pageSize, err := units.RAMInBytes(nameArray[1]) + if err != nil { + return nil, err + } + pageSizes = append(pageSizes, units.CustomSize("%g%s", float64(pageSize), 1024.0, sizeList)) + } + return pageSizes, nil +} + +func readUint(path string) (uint64, error) { + v, err := ioutil.ReadFile(path) + if err != nil { + return 0, err + } + return parseUint(strings.TrimSpace(string(v)), 10, 64) +} + +func parseUint(s string, base, bitSize int) (uint64, error) { + v, err := strconv.ParseUint(s, base, bitSize) + if err != nil { + intValue, intErr := strconv.ParseInt(s, base, bitSize) + // 1. Handle negative values greater than MinInt64 (and) + // 2. Handle negative values lesser than MinInt64 + if intErr == nil && intValue < 0 { + return 0, nil + } else if intErr != nil && + intErr.(*strconv.NumError).Err == strconv.ErrRange && + intValue < 0 { + return 0, nil + } + return 0, err + } + return v, nil +} + +func parseKV(raw string) (string, uint64, error) { + parts := strings.Fields(raw) + switch len(parts) { + case 2: + v, err := parseUint(parts[1], 10, 64) + if err != nil { + return "", 0, err + } + return parts[0], v, nil + default: + return "", 0, ErrInvalidFormat + } +} + +func parseCgroupFile(path string) (map[string]string, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + return parseCgroupFromReader(f) +} + +func parseCgroupFromReader(r io.Reader) (map[string]string, error) { + var ( + cgroups = make(map[string]string) + s = bufio.NewScanner(r) + ) + for s.Scan() { + if err := s.Err(); err != nil { + return nil, err + } + var ( + text = s.Text() + parts = strings.SplitN(text, ":", 3) + ) + if len(parts) < 3 { + return nil, fmt.Errorf("invalid cgroup entry: %q", text) + } + for _, subs := range strings.Split(parts[1], ",") { + if subs != "" { + cgroups[subs] = parts[2] + } + } + } + return cgroups, nil +} + +func getCgroupDestination(subsystem string) (string, error) { + f, err := os.Open("/proc/self/mountinfo") + if err != nil { + return "", err + } + defer f.Close() + s := bufio.NewScanner(f) + for s.Scan() { + if err := s.Err(); err != nil { + return "", err + } + fields := strings.Fields(s.Text()) + for _, opt := range strings.Split(fields[len(fields)-1], ",") { + if opt == subsystem { + return fields[3], nil + } + } + } + return "", ErrNoCgroupMountDestination +} + +func pathers(subystems []Subsystem) []pather { + var out []pather + for _, s := range subystems { + if p, ok := s.(pather); ok { + out = append(out, p) + } + } + return out +} + +func initializeSubsystem(s Subsystem, path Path, resources *specs.LinuxResources) error { + if c, ok := s.(creator); ok { + p, err := path(s.Name()) + if err != nil { + return err + } + if err := c.Create(p, resources); err != nil { + return err + } + } else if c, ok := s.(pather); ok { + p, err := path(s.Name()) + if err != nil { + return err + } + // do the default create if the group does not have a custom one + if err := os.MkdirAll(c.Path(p), defaultDirPerm); err != nil { + return err + } + } + return nil +} + +func cleanPath(path string) string { + if path == "" { + return "" + } + path = filepath.Clean(path) + if !filepath.IsAbs(path) { + path, _ = filepath.Rel(string(os.PathSeparator), filepath.Clean(string(os.PathSeparator)+path)) + } + return filepath.Clean(path) +} diff --git a/vendor/github.com/containerd/cgroups/v1.go b/vendor/github.com/containerd/cgroups/v1.go new file mode 100644 index 0000000000..a076d4692e --- /dev/null +++ b/vendor/github.com/containerd/cgroups/v1.go @@ -0,0 +1,81 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strings" +) + +// V1 returns all the groups in the default cgroups mountpoint in a single hierarchy +func V1() ([]Subsystem, error) { + root, err := v1MountPoint() + if err != nil { + return nil, err + } + subsystems, err := defaults(root) + if err != nil { + return nil, err + } + var enabled []Subsystem + for _, s := range pathers(subsystems) { + // check and remove the default groups that do not exist + if _, err := os.Lstat(s.Path("/")); err == nil { + enabled = append(enabled, s) + } + } + return enabled, nil +} + +// v1MountPoint returns the mount point where the cgroup +// mountpoints are mounted in a single hiearchy +func v1MountPoint() (string, error) { + f, err := os.Open("/proc/self/mountinfo") + if err != nil { + return "", err + } + defer f.Close() + scanner := bufio.NewScanner(f) + for scanner.Scan() { + if err := scanner.Err(); err != nil { + return "", err + } + var ( + text = scanner.Text() + fields = strings.Split(text, " ") + // safe as mountinfo encodes mountpoints with spaces as \040. + index = strings.Index(text, " - ") + postSeparatorFields = strings.Fields(text[index+3:]) + numPostFields = len(postSeparatorFields) + ) + // this is an error as we can't detect if the mount is for "cgroup" + if numPostFields == 0 { + return "", fmt.Errorf("Found no fields post '-' in %q", text) + } + if postSeparatorFields[0] == "cgroup" { + // check that the mount is properly formated. + if numPostFields < 3 { + return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text) + } + return filepath.Dir(fields[4]), nil + } + } + return "", ErrMountPointNotExist +} diff --git a/vendor/github.com/opencontainers/runtime-spec/.gitattributes b/vendor/github.com/opencontainers/runtime-spec/.gitattributes new file mode 100644 index 0000000000..558b67f89b --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/.gitattributes @@ -0,0 +1,2 @@ +# https://tools.ietf.org/html/rfc5545#section-3.1 +*.ics text eol=crlf diff --git a/vendor/github.com/opencontainers/runtime-spec/.gitignore b/vendor/github.com/opencontainers/runtime-spec/.gitignore new file mode 100644 index 0000000000..f9663c923f --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/.gitignore @@ -0,0 +1,3 @@ +output +schema/validate +version.md diff --git a/vendor/github.com/opencontainers/runtime-spec/.mailmap b/vendor/github.com/opencontainers/runtime-spec/.mailmap new file mode 100644 index 0000000000..346194c50c --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/.mailmap @@ -0,0 +1,21 @@ +Aleksa Sarai +Alexander Morozov +Amit Saha +Antonio Murdaca +Brandon Philips +Brandon Philips +ChengTiesheng +Daniel, Dao Quang Minh +Doug Davis +James O. D. Hunt +John Howard +LinZhinan(Zen Lin) +Mrunal Patel +Mrunal Patel +Mrunal Patel +Vincent Batts +Vincent Batts +Vishnu Kannan +Vishnu Kannan +Zefan Li +梁辰晔 (Liang Chenye) diff --git a/vendor/github.com/opencontainers/runtime-spec/.pullapprove.yml b/vendor/github.com/opencontainers/runtime-spec/.pullapprove.yml new file mode 100644 index 0000000000..a7efacfe70 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/.pullapprove.yml @@ -0,0 +1,27 @@ +version: 2 + +requirements: + signed_off_by: + required: true + +group_defaults: + required: 2 + approve_by_comment: + enabled: true + approve_regex: ^LGTM + reject_regex: ^Rejected + reset_on_push: + enabled: true + author_approval: + ignored: true + always_pending: + title_regex: ^WIP + explanation: 'Work in progress...' + conditions: + branches: + - master + +groups: + runtime-spec: + teams: + - runtime-spec-maintainers diff --git a/vendor/github.com/opencontainers/runtime-spec/.tool/version-doc.go b/vendor/github.com/opencontainers/runtime-spec/.tool/version-doc.go new file mode 100644 index 0000000000..f36bfe4c36 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/.tool/version-doc.go @@ -0,0 +1,25 @@ +// +build ignore + +package main + +import ( + "fmt" + "html/template" + "os" + + "github.com/opencontainers/runtime-spec/specs-go" +) + +var markdownTemplateString = ` + +**Specification Version:** *{{.}}* + +` + +var markdownTemplate = template.Must(template.New("markdown").Parse(markdownTemplateString)) + +func main() { + if err := markdownTemplate.Execute(os.Stdout, specs.Version); err != nil { + fmt.Fprintln(os.Stderr, err) + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/.travis.yml b/vendor/github.com/opencontainers/runtime-spec/.travis.yml new file mode 100644 index 0000000000..cf9e712530 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/.travis.yml @@ -0,0 +1,25 @@ +language: go +go: + - "1.10.x" + - "1.9.x" + +sudo: required + +services: + - docker + +before_install: + - make install.tools + - docker pull vbatts/pandoc + - go get -d ./schema/... + +install: true + +script: + - env | grep TRAVIS_ + - make .govet + - make .golint + - echo "${TRAVIS_COMMIT_RANGE} -> ${TRAVIS_COMMIT_RANGE/.../..} (travis-ci/travis-ci#4596)" + - TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE/.../..}" make .gitvalidation + - make docs + - make -C schema test diff --git a/vendor/github.com/opencontainers/runtime-spec/ChangeLog b/vendor/github.com/opencontainers/runtime-spec/ChangeLog new file mode 100644 index 0000000000..9849dc7153 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/ChangeLog @@ -0,0 +1,684 @@ +OpenContainers Specifications + +Changes with v1.0.1: + + Minor fixes and documentation: + + * spec: Expand "OCI" in spec-title reference and add "Initiative" + (#900) + * config: Simplify title to "Configuration" (#901) + * config: Fix "procfs_2" -> "proc_2" link label (#906) + * config: Fix IEEE Std 1003.1-2008 exec link markup (#913) + * config: Add a trailing period to the "cannot be mapped" rlimits + line (#915) + * config-linux: RFC 2119 MUST for absolute linux.namespaces[].path + (#925). This is technically a breaking change, because a config + with a relative namespace path would have been compliant before, + but will be non compliant with this change. However, the previous + "an absolute path to namespace file" wording was clear enough that + config authors are unlikely to be relying on relative namespace + paths in configs. + * config-linux: More specific documentation for weightDevice and + throttle* (#825) + * config-linux: Modify procfs to proc (#905) + * config-linux: Fix "psuedo" -> "pseudo" typo (#921) + * config-windows: Make maximum a uint16 (was a uint) (#891) + * runtime: Change "process in the container" -> "container + process" (#907) + * schema/config-schema: Use ArrayOfStrings in capabilities + properties. (#886) + * schema/config-linux: + s/throttleWriteIopsDevice/throttleWriteIOPSDevice/ (#899) + * schema/config-linux: add intelRdt field (#889) + * schema/config-solaris: Replaced refs with some fields + (cappedCPU.ncpus, etc.) (#892) + +Changes with v1.0.0: + + Breaking changes: + + * config: Shift disableOOMKiller from linux.resources to + linux.resources.memory (#896) + + Decreased restrictions: + + * runtime: Make the state JSON's pid optional on non-Linux platforms + (#897) + + Minor fixes and documentation: + + * schema/defs-linux: Require Syscall.action (#885) + * specs-go/config: Fix 'omiempty' -> 'omitempty' typo for + LinuxSeccompArg.ValueTwo (#884) + * ROAMAP: remove the pre-v1.0.0 roadmap (#890) + +Changes with v1.0.0-rc6: + + Breaking changes: + + * config: Shift oomScoreAdj to process and add RFC 2119 requirements + for the runtime (#781, #789, #836) + * config: Forbid 'root' on Hyper-V (#820, #838). + * config: process.capabilities and process.noNewPrivileges are + Linux-only again (#880). This partially reverses #673, which had + landed in v1.0.0-rc5. + * config: Remove process.rlimits from Windows (#880). It is now + POSIX-only, while in v1.0.0-rc5 it was cross-platform (because of + #673). Before #673 (in v1.0.0-rc4 and earlier), it was + Linux-only. + * config-linux: Drop redundant 'blkio' prefix from blockIO + properties (#860) + * config-linux: Make memory limits int64 instead of uint64 (#876). + This partially reverses #704, which had landed in v1.0.0-rc5. + * config-windows: Change CPU 'percent' to 'maximum' (#777) + * config-windows: Remove memory 'reservation' (#788) + * config-windows: Remove 'resources.network' and add 'network' (#801) + + Additions: + + * config: Windows runtimes MUST support the 'ro' mount option (#868) + * config-linux: Add Intel RDT/CAT Linux support (#630, #787) + * config-linux: Add Markdown specification for syscalls (#706) + * config-linux: Add 'unbindable' rootfsPropagation value (#770, #775) + * config-windows: Add 'credentialSpec' (#814, #859) + * config-windows: Add 'servicing' (#815) + * config-windows: Add 'ignoreFlushesDuringBoot' (#816, #859) + * config-windows: Add 'hyperv' (#818, #849, #859) + * config-windows: Add 'layerFolders' (#828) + + Removals and increased restrictions: + + * config: Remove 'platform' (#850) + * config: Require strictly-postitive 'timeout' values (#764) + * config: Strengthen punt to kernel for valid capabilities strings + (#766, #790) + * config: Require volume GUID paths for root.path (#849) + * config: Forbid setting 'readonly' true on Windows (#819) + * config: Forbid setting mount 'type' entirely on Windows and forbid + UNC paths and mapped drives in 'source' on Windows (#821) + * config: Remove 'hooks' from Windows spec (#855, #869, #870) + * config-linux: Clearly require absolute path for namespace (#720) + * config-linux: RFC 2119 tightening for namespaces (#767) + * config-linux: Require at least one entry in + linux.seccomp.syscalls[].names (#769) + * config-linux: Remove syscall.comment (#714) + * config-linux: Use MUST and MAY for weight and leafWeight (#751) + * config-linux: Remove explicit 'null' from device cgroup values + (#804) + * runtime: Remove "features the runtime chooses to support" (#732) + * runtime: Drop "not supported by the base OS" loophole (#733) + * runtime-linux: Condition /proc/self/fd symlinks on source + existence (#736) + + Decreased restrictions: + + * config: Make 'process' optional (#701, #805) + * config-linux: Make linux.seccomp.syscalls optional (#768) + * config-linux: valueTwo is now optional in + `linux.seccomp.syscalls[].args` entries (#877) + * config-linux: Remove local range restrictions for blkioWeight, + blkioLeafWeight, weight, leafWeight, and shares (#780) + * config-linux: Explicitly allow symlinks for providing devices (#873) + + Minor fixes and documentation: + + * config: Remove "MAY support any valid values" sentence (#851) + * config: Remove the previously-forbidden mounts[].type from the + Windows spec (#854) + * config: Clarify mounts[].source relative path anchor (#735) + * config: Explicitly make consoleSize ignored if terminal is false or + unset (#863) + * config: Specify height/width units (characters) for consoleSize (#761) + * config: Use "POSIX platforms" instead of "Linux and Solaris" (#838) + * config-linux: Explicit namespace for interface names (#713) + * config-linux: Explicitly list cgroupsPath as optional (#823) + * runtime: Clarify valid container states for 'start', 'kill', and + 'delete' (#875) + * runtime: Explicitly make process.* timing implementation-defined (#700) + * specs-go/config: Remove range restrictions from Windows comments (#783) + * specs-go/config: Add omitempty to LinuxSyscall.Args (#763) + * specs-go/config: Use a pointer for Process.ConsoleSize (#792) + * schema/README: Use v1.0.0 URL in examples to prepare for the 1.0.0 + release (#881) + * schema/Makefile: Make 'validate' the default target (#750) + * schema/Makefile: Add 'clean' target (#774) + * schema: Add 'test' target to the Makefile (#785) + * *: Remove unnecessary .PHONY entries (#750, #778, #802) + * *: Typo fixes and polishing (#681, #708, #702, #703, #709, #711, + #712, #721, #722, #723, #724, #730, #737, #738, #741, #744, #749, + #753, #756, #765, #773, #776, #784, #786, #793, #794, #796, #798, + #799, #800, #803, #807, #809, #811, #812, #822, #824, #826, #827, + #832, #839, #840, #846, #847, #848, #852, #856, #858, #862, #865, + #871, #874) + +Changes with v1.0.0-rc5: + + Breaking changes: + + * config: Explicitly require `platform` (#695). + * config: The platform-specific sections (`linux`, `solaris`, and + `windows`) MUST NOT be set unless they match `platform.os` (#673). + * config: `process.capabilities` is now an object instead of an + array of strings (#675). + * config-linux: No longer allow negative values for some resources, + partially reversing #648 from v1.0.0-rc4 (#704). + * config-linux: `linux.seccomp.syscalls` entries have `names` + instead of `name` (#657). + * runtime: Rename the state `bundlePath` property to `bundle` + (#674). + + Additions: + + * config: `process.capabilities` is no longer Linux-only (#673). + * config-linux: `linux.seccomp.syscalls` entries have a new + `comment` property (#657). + * config-linux: Add new architectures from libseccomp 2.3.2 (#705) + * runtime: Add a `creating` state `status` (#507, #694). + + Removals and increased restrictions: + + * runtime: Document hook timing and exit code handling (#532). + * schema/config-linux: Explicit `null` values are no longer + compliant (#662). + + Decreased restrictions: + + * config: `type` and `source` properties are now optional for + `mounts` entries (#699). + * config: `args` property is now optional for hooks (#685). + * config-linux: Runtimes no longer need to provide `/proc` and + other filesystems unless they are explicitly requested in the + configuration JSON (#666). + + Minor fixes and documentation: + + * spec: Add OCI Runtime Abstract (#691). + * config: Document the Go `platform` tag (#570). + * config-linux: Remove local uid/gid mapping limit and punt to the + kernel (#693). + * schema: Fix broken `string` and similar `$ref`s (#684). + * schema: Remove `mounts` from required properties (#696). + * schema: Remove `major` and `minor` from `linux.devices` entries + (#688). + * schema: Check for the required `type`, `hard`, and `soft` in + `process.rlimits` entries (#696). + * schema/validate: Gained usage documentation and fixed + `schemaPath` logic when the argument did not contain `://` (#552). + * *: Add anchor tags to a number of spec locations (#707). + * *: Consistent link syntax (#687). + * *: Minor cleanup and rewording (#697). + +Changes with v1.0.0-rc4: + Additions: + + * config-linux: Allow negative values for some resources (#648) + * config-linux: Lift no-tweaking namespace restriction (#649) + + Removals and increased restrictions: + + * config: Rlimit types must be unique (#607) + * config: Forbid empty-string keys in 'annotations' (#645, #654) + * config-linux: Require runtime errors for pre-existing devices + (#647) + * runtime: Only require 'pid' in the state for created/running + statuses (#664) + * schema: Add 'consoleSize' and update requirements (#646) + * schema: Remove string pointers (#656) + * schema/config-linux: Remove blockIODeviceThrottle and other + pointers (#545) + + Breaking Go changes: + + * specs-go/config: Remove string pointers (#653) + * specs-go/config: Make Spec.Hooks a pointer (#427) + * specs-go/config: Convert some resources from unsigned integers + to signed integers (#648) + + Minor fixes and documentation: + + * config: Explicitly list 'hooks' as optional and cite POSIX for + 'env' and 'args' (#427) + * runtime: Replace "process is stopped" with "process exits" + (#465) + * schema/config-linux: Add missing kernelTCP (#655) + * schema/validate: Allow schema identifiers to contain a URL + scheme (#490) + * .travis: Fix git-validation commit ranges (#216) + * *: Add anchor tags to a number of spec locations (#612, #636, + #637, #638, #639, #640) + * *: Typo fixes and polishing (#643, #650, #652, #656, #660, #665) + +Changes with v1.0.0-rc3: + Additions: + + * config: Add support for Windows-based containers (#565, #573) + * config: Add process.consoleSize (#563) + * config: Explicitly allow unknown extensions and document + annotations key conventions (#510) + * config: Define mounts entries for Solaris (#588) + + Removals and increased restrictions: + + * config: Require absolute paths for mount destinations (#609) + * config-linux: Require absolute path for maskedPaths and + readonlyPaths (#587) + * config-linux: Only require /dev/console when process.terminal is + true. Also require /dev/console to be provided by a bind mount + (#518) + * runtime: Require runtimes to generate errors when the container + specified in config.json cannot be created (#559) + + Breaking Go changes: + + * specs-go/config: Aggressive namespacing (#567) + * specs-go/config: Remove pointers from LinuxHugepageLimit, + LinuxInterfacePriority, and LinuxPids properties (#586) + * specs-go/state: Rename version to ociVersion (#633) + LinuxInterfacePriority, and LinuxPids properties (#586) + + Minor fixes and documentation: + + * spec: Separate the spec from project scaffolding (#626) + * README: Define "unspecified", "undefined", and + "implementation-defined" (#575) + * config: Clarify absolue and relative values for root.path (#558) + * config: Clarify ociVersion covering the configuration <-> + runtime API (#523) + * config-linux: Forbid duplicated namespaces with same `type` + (#597) + * glossary: Make objects explicitly unordered and forbid duplicate + names (#584) + * specs-go/config: Add platform tags to Rlimits and + NoNewPRivileges (#564) + * schema/defs-linux: Use int64 for major/minor types (#610) + * Makefile: Add support for Go 1.7 (#547) + * Makefile: Require Go >= 1.6 for golint (#589) + * Makefile: Use a POSIX-compatible test ('==' -> '=') (#542) + * implementations: Rename ocitools -> runtime-tools (#585) + * *: Typo fixes and polishing (#556, #566, #568, #569, #571, #572, + #574, #595, #596, #599, #600, #601, #603, #605, #608, #613, #617, + #619, #621, #622, #623, #624, #625, #627, #629) + +Changes with v1.0.0-rc2: + Additions: + + * config-linux: Add new architectures from libseccomp 2.3.0 (#505) + * schema: Add JSON Schema for state JSON and move schema.json to + config-schema.json and similar (#481, #498, #519) + + Minor fixes and documentation: + + * Add compliance language for platforms and architectures (#527) + * Remove "unconditionally compliant" language (#553) + * bundle: Remove distribution references (#487) + * runtime: Fix sub-bullet indentation (#495) + * config: Replace Arch fstab reference with mount(8) (#443) + * config: Synchronize comments between Markdown and Go (#525) + * config: Drop v0.x compatibility statement (#488) + * config-linux: RFC 2119 wording for cgroupsPath (#493) + * config-linux: Make linux.devices and linux.resources.devices + optional (#526) + * config-linux: Extend no-tweak requirement to runtime namespaces (#538) + * schema: Add hook.timeout (#544) + * schema: Add missing '"type": "object"' (#528) + * schema: Run 'make fmt' and remove duplicates (#546, #551) + * schema/config: Make 'hostname' optional (#491) + * schema/config-linux: Add linux.resources.devices (#550) + * specs-go/config: Add Solaris tags to User properties (#496) + * specs-go/config: Make Linux and Solaris omitempty again (#502) + * specs-go/config: Make KernelTCP and ClassID omitempty (#531) + * specs-go/config: Fix "specified" typo for ApparmorProfile (#503) + * Makefile: Remove code-of-conduct.md and version.md when clean (#541) + * implementations: Mention cc-oci-runtime (#539) + * Use filesystem instead of file system (#529) + * .pullapprove: Add DCO check via PullApprove + * GOVERNANCE: Add governance and release process docs (#521) + * README: Change meeting time from 10am to 2pm Pacific (#524) + * README: Update conference-call phone number (#512, #515) + +Changes with v1.0.0-rc1: + Breaking changes: + + * runtime: Split create and start, #384, #450, #463, #464, #467, + #468 + * runtime: Remove exec, #388 + * runtime: Enviroment MUST match the configuration, #397 + * config: Runtime MUST generate errors for unsupported platforms, + #441 + * config: Windows mount destinations MUST NOT be nested, #437 + + Additions: + + * solaris: Added platform-specific configuration, #411, #424, #431, + #436 + * runtime: Add 'annotations' and 'status' to the state structure, + #462, #484, #485 + * runtime: State no longer needs to be serialized as JSON, #446 + * runtime-linux: Add /dev symbolic links, #449 + * config: Allow absolute paths for root.path (which previously + required relative paths), #394 + * config-linux: Add linux.mountLabel, #393 + * config-linux: Add suport for cgroup namespace, #397 + * config-linux: Runtime SHOULD NOT modify ownership of any + referenced filesystem (previously the restriction only applied to + the root filesystem), #452 + * specs-go/seccomp: Add ppc and s390x to specs-go/config.go, #475 + + Minor fixes and documentation: + + * README: Add project.md to the Table of Contents, #376 + * README: Consistenly indent the Table of Contents, #400 + * README: Link to LICENSE, #442 + * README: Weekly call is OCI-wide, #378 + * config: Explicit runtime namespace for hooks, #415 + * config: Explicit container namespace for uid, gid, and + additionalGids, #412 + * config: Fix 'string' -> 'array of strings' typo for process.args, + #416 + * runtime: The runtime MAY validate config.json, #418 + * runtime: Move errors section out of operations, #445 + * runtime: MAY -> SHOULD for post-stop error logging, #410 + * schema/README: Document JSON Schema usage, #360, #385 + * schema: Minor description updates, #456, #461 + * schema/validate: Support reading documents via stdin, #482 + * .pullapprove: Automate review approval, #458, #474 + * .gitignore: Hide more auto-generated files, #386, #392 + * .travis: git-validation detects Travis now, #366 + * .travis: Regress on failure to produce docs, #479 + * Makefile: Filename docs.* -> oci-runtime-spec.*, #478 + * Makefile: Add install.tools target, #349 + * Makefile: Allow native pandoc implementations, #428, #448 + * Makefile: Prefer Bash, #455 + * Makefile: Travis support for .gitvalidation, #422 + * specs-go/config: Add missing omitempties for Process.Terminal, + Root.Readonly, Spec.Linux, and Spec.Mounts, #408, #429, #430, #431 + * specs-go/config: Remove incorrect omitempties for User.UID and + User.GID, #425 + * specs-go/config: Drop platform-independent comment, #451 + * version: Include version in generated documentation, #406 + * *: Anchor examples, #348 + * *: Fix remnants from SelinuxProcessLabel to SelinuxLabel rename, + #396 + * *: Outsource code-of-conduct to TOB repository, #375, #413 + * *: RFC 2119 consistency, #407, #409, #438, #444, #449 + * *: Typo fixes, #390, #401 + * *: Whitespace fixes and validation, #380, #381, #426 + * ROADMAP: Remove stale targets, #435 + +Changes with v0.5.0: + Breaking changes: + + * specs-go: Renamed the repository from opencontainers/specs to + opencontainers/runtime-spec, #365 + + Additions: + + * config: Add 'timeout' for hooks, #346 + * config-linux: Add 'maskedPaths' and 'readonlyPaths', #364 + + Minor fixes and documentation: + + * JSON Schema bug-fixes and improved examples, #370 + * README: Define "unconditionally compliant", #374 + * config: Make Markdown canonical, #342 + * config: Explicitly list mapping from symbolic names to UID/GIDs as + out-of-scope, #347 + * config-linux: Require the runtime mount namespace for namespace + 'path' values, #275 + * config-linux: Reword kernelTCP docs, #377 + * specs-go: Add omitempty to 'Device' and 'Namespace', #340 + * .travis.yml: Use built-in 'go vet' and current 'go lint', dropping + Go < 1.5, #372, #352 + * implementations: Expand ocitools scope to include testing, #328 + * style: Move one-sentence-per-line rule from the README, #369 + * style: Remove dangling parenthesis, #359 + * README: Add a link to the IRC logs, #358 + * Fix "manadate", "exmaple", "paramters", and "preferrably" typos, + #353, #354 + +Changes with v0.4.0: + Breaking changes: + + * config: Move capabilities, selinuxProcessLabel, apparmorProfile, + and noNewPrivileges from the linux setting to the process setting + and make them optional, renaming selinuxProcessLabel to + selinuxLabel, #329, #330, #339 + * runtime: Rename version to ociVerison in the state JSON, #225 + * runtime: Remove the directory requirement for storing state, now + that there is a 'state' operation, #225, #334 + * go: Shift *.go to specs-go/*.go, #276 + * config: Move rlimits to process, #341 + * go: Move config_linux.go content into config.go, removing + LinuxSpec, #310 + + Additions: + + * schema: Add JSON Schema (and validator) for `config.json`, #313 + * config: Add annotations for opaque-to-the-runtime data, #331 + * config-linux: Make seccomp optional, #333 + * runtime: Added additional operations: state, stop, and exec. + #225 + + Minor fixes and documentation: + + * config-linux: Change mount type from *rune to *string and fix + octal fileMode examples, #323 + * runtime: RFC 2119 phrasing for the lifecycle, #225 + * README: Add a full example of config.json, #276 + * README: Replace BlueJeans with UberConference, #326, #338 + * style: Document Go-pointer exceptions, #317 + +Changes with v0.3.0: + Breaking changes: + + * config: Single, unified config file, #284 + * config: cwd is a required default, and must be absolute, #286, + #307, #308, #312 + * config: qualify the name of the version field, #309 + * config-linux: Convert classID from hex to uint32, #296 + * config-linux: Separate mknod from cgroups, #298 + + Additions: + + * config-linux: Add NoNewPrivileges setting for linux, #290 + + Minor fixes and documentation: + + * config-linux: clarify oom_score_adj, #236, #292 + * config-linux: Update links to cgroups documentation, #318 + * config-linux: Remove pointers for slices preferring omitempty + tag instead, #316 + * README: add runtime, bundle, and hook author user, #280 + * ROADMAP: reshuffled and split into GitHub issues, #300, #301, + #304, #306 + * style: Collect established styles in a discoverable location, #287, #311 + +Changes with v0.2.0: + * Add Apparmor, Selinux and Seccomp + * Add Apparmor, Selinux and Seccomp sections + * Add bind mount example + * Add fd section for linux container process + * Add Go types for specification + * *: adding a code of conduct + * Adding cgroups path to the Spec. + * .: Adding listing of implementations + * .: adding travis file for future CI + * Add license and DCO information for contributions + * Add linux spec description + * Add MAINTAINERS file + * Add memory swappiness to linux spec + * Add runtime state configuration and structs + * Adds a section for user namespace mappings + * Adds link to kernel cgroups documentation + * Adds section for Linux Rlimits + * Adds section for Linux Sysctl. + * Adds user namespace to the list of namespaces + * bundle: add initial run use case + * bundle: Fix 'and any number of and other related' typo + * bundle.md: clarify arbitrary/conventional dirnames + * bundle.md: fix link formatting + * bundle.md: fix off-by-one error + * bundle.md: various updates to latest spec + * bundle: Move 'Linux sysctl' header to its own line + * Change commiter to committer + * Change Device field order in spec_linux.go, 'Path' should be top of the 'Type' field, according to the different of the config-linux.md, 'Path' field is the unique key. + * Change layout of mountpoints and mounts + * Change the rlimit type to string instead of int + * Clarify behavior around namespaces paths. + * config: Add example additionalGids + * config: Add example cwd + * config: cleanup language on readonly parameter + * config: fix links to go files + * config-linux: specify the default devices/filesystems available + * config.md: clarify destination for mounts + * config.md: make the version a semver + * config.md: make the version field example a semver + * config.md: minor clean up of process specification + * config.md: reformat into a standard style + * config.md: update links to spec schema code + * config.md: various cleanup/consistency fixes + * config: minor cleanup + * Deduplicate the field of RootfsPropagation + * Define constants for Linux Namespace names + * Fix LinuxRuntime field + * Fix root object keys + * Fix typos in config.md + * Fix typos in the "Namespace types" section + * Fix typos in the rlimits section + * Fix Windows path escaping in example mount JSON + * JSON objects are easier to parse/manipulate + * made repo public. Added warning in README + * Make namespaces match runc + * make rootfs mount propagation mode settable + * Makes namespaces description linux specific + * *.md: markdown formatting + * Modify the capabilities constants to match header files like other constants + * Move linux specific options to linux spec + * README: add a rule for paragraph formatting in markdown + * README: Document BlueJeans and wiki archive for meetings + * README: Document pre-meeting agenda alteration + * README: Document YouTube and IRC backchannel for meetings + * README: Focus on local runtime (create/start/stop) + * README.md: Add a git commit style guide + * README.md: contribution about discussion + * README: releases section + * README: Remove blank line from infrastructure-agnostic paragraph + * removed boilerplate file + * *: remove superfluous comma in code-of-conduct + * Remove trailing whitespace + * Rename SystemProperties to Sysctl + * Rename the header "Access to devices" to "Devices" to fit with the config + * *: re-org the spec + * Replace Linux.Device with more specific config + * restore formatting + * Return golang compliant names for UID and GID in User + * Return golint-compliant naming for mappings + * runtime: Add prestart/poststop hooks + * runtime_config: comments for golint + * runtime-config-linux: Drop 'Linux' from headers + * runtime_config_linux: Fix 'LinuxSpec' -> 'LinuxRuntimeSpec' in comment + * runtime-config-linux: One sentence per line for opening two paragraphs + * runtime-config: Remove blank lines from the end of files + * runtime-config: Remove 'destination' docs from mounts + * runtime.md: convert oc to runc + * runtime: use opencontainer vs oci + * *: small spelling fixes + * Specific platform specific user struct for spec + * spec: linux: add support for the PIDs cgroup + * spec_linux: conform to `golint` + * spec_linux.go: Rename IDMapping fields to follow syscall.SysProcIDMap + * spec_linux: remove ending periods on one-line comments + * spec: rename ocp to oci and add a link + * specs: add json notation + * specs: align the ascii graph + * specs: fix the description for the [ug]idMappings + * specs: introduce the concept of a runtime.json + * .tools: cleanup the commit entry + * .tools: repo validation tool + * travis: fix DCO validation for merges + * typo: containers -> container's + * typo: the -> for + * Update config-linux for better formatting on values + * Update README.md + * Update readme with weekly call and mailing list + * Update runtime.md + * Update runtime.md + * Update runtime.md + * version: more explicit version for comparison + +Changes with v0.1.0: + * Add Architecture field to Seccomp configuration in Linux runtime + * Add @hqhq as maintainer + * Add hyphen for host specific + * Adding Vishnu Kannan as a Maintainer. + * Add initial roadmap + * Add lifecycle for containers + * Add oom_score_adj to the runtime Spec. + * Add post-start hooks + * Add Seccomp constants to description of Linux runtime spec + * Add Seccomp constants to Linux runtime config + * Add some clarity around the state.json file + * adds text describing the upper-case keywords used in the spec + * add testing framework to ROADMAP + * Appropriately mark optional fields as omitempty + * cgroup: Add support for memory.kmem.tcp.limit_in_bytes + * Change HugepageLimit.Limit type to uint64 + * Change the behavior when cgroupsPath is absent + * Change version from 0.1.0 to 0.2.0 + * Clarify the semantics of hook elements + * Cleanup bundle.md + * Cleanup principles + * config: linux: update description of PidsLimit + * config: Require a new UTS namespace for config.json's hostname + * config: Require the runtime to mount Spec.Mounts in order + * convert **name** to **`name`** + * Example lists "root' but text mentions "bundlePath" + * Fix an extra space in VersionMinor + * Fix golint warnings + * Fix typo in BlockIO struct comment + * Fix typo in Filesystem Bundle + * Fix value of swappiness + * glossary: Provide a quick overview of important terms + * glossary: Specify UTF-8 for all our JSON + * hooks: deduplicate the hooks docs + * implementations: Link to kunalkushwaha/octool + * implementations: Link to mrunalp/ocitools + * lifecycle: Don't require /run/opencontainer//containers + * lifecycle: Mention runtime.json + * lifecycle: no hypens + * MAINTAINERS: add tianon per the charter + * MAINTAINERS: correct Vish's github account + * Makefile: Add glossary to DOC_FILES + * Make optional Cgroup related config params pointers along with `omitempty` json tag. + * Mark RootfsPropagation as omitempty + * *.md: update TOC and links + * move the description of Rlimits before example + * move the description of user ns mapping to proper file + * principles: Give principles their own home + * *: printable documents + * Project: document release process + * README: Fix some headers + * README: make header more concise + * remove blank char from blank line + * Remove the unneeded build tag from the config_linux.go + * Remove trailing comma in hooks json example + * Rename State's Root to Bundle + * ROADMAP.md: remove the tail spaces + * roadmap: update links and add wiki reference + * runtime: Add 'version' to the state.json example + * runtime-config: add example label before json example + * runtime-config: add section about Hooks + * runtime: config: linux: add cgroups information + * runtime: config: linux: Edit BlockIO struct + * runtime: config: linux: Fix typo and trailing commas in json example + * runtime_config_linux.go: add missing pointer + * runtime-config-linux.md: fix the type of cpus and mems + * runtime.md: fix spacing + * Talk about host specific/independent instead of mutability + * .tools: commit validator is a separate project + * .tools: make GetFetchHeadCommit do what it says + * .travis.yml: add go 1.5.1, update from 1.4.2 to 1.4.3 + * Update readme with wiki link to minutes + * Update Typo in ROADMAP.md + * Use unsigned for IDs + * version: introduce a string for dev indication diff --git a/vendor/github.com/opencontainers/runtime-spec/GOVERNANCE.md b/vendor/github.com/opencontainers/runtime-spec/GOVERNANCE.md new file mode 100644 index 0000000000..92c8609491 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/GOVERNANCE.md @@ -0,0 +1,70 @@ +# Project governance + +The [OCI charter][charter] §5.b.viii tasks an OCI Project's maintainers (listed in the repository's MAINTAINERS file and sometimes referred to as "the TDC", [§5.e][charter]) with: + +> Creating, maintaining and enforcing governance guidelines for the TDC, approved by the maintainers, and which shall be posted visibly for the TDC. + +This section describes generic rules and procedures for fulfilling that mandate. + +## Proposing a motion + +A maintainer SHOULD propose a motion on the dev@opencontainers.org mailing list (except [security issues](#security-issues)) with another maintainer as a co-sponsor. + +## Voting + +Voting on a proposed motion SHOULD happen on the dev@opencontainers.org mailing list (except [security issues](#security-issues)) with maintainers posting LGTM or REJECT. +Maintainers MAY also explicitly not vote by posting ABSTAIN (which is useful to revert a previous vote). +Maintainers MAY post multiple times (e.g. as they revise their position based on feedback), but only their final post counts in the tally. +A proposed motion is adopted if two-thirds of votes cast, a quorum having voted, are in favor of the release. + +Voting SHOULD remain open for a week to collect feedback from the wider community and allow the maintainers to digest the proposed motion. +Under exceptional conditions (e.g. non-major security fix releases) proposals which reach quorum with unanimous support MAY be adopted earlier. + +A maintainer MAY choose to reply with REJECT. +A maintainer posting a REJECT MUST include a list of concerns or links to written documentation for those concerns (e.g. GitHub issues or mailing-list threads). +The maintainers SHOULD try to resolve the concerns and wait for the rejecting maintainer to change their opinion to LGTM. +However, a motion MAY be adopted with REJECTs, as outlined in the previous paragraphs. + +## Quorum + +A quorum is established when at least two-thirds of maintainers have voted. + +For projects that are not specifications, a [motion to release](#release-approval) MAY be adopted if the tally is at least three LGTMs and no REJECTs, even if three votes does not meet the usual two-thirds quorum. + +## Security issues + +Motions with sensitive security implications MUST be proposed on the security@opencontainers.org mailing list instead of dev@opencontainers.org, but should otherwise follow the standard [proposal](#proposing-a-motion) process. +The security@opencontainers.org mailing list includes all members of the TOB. +The TOB will contact the project maintainers and provide a channel for discussing and voting on the motion, but voting will otherwise follow the standard [voting](#voting) and [quorum](#quorum) rules. +The TOB and project maintainers will work together to notify affected parties before making an adopted motion public. + +## Amendments + +The [project governance](#project-governance) rules and procedures MAY be amended or replaced using the procedures themselves. +The MAINTAINERS of this project governance document is the total set of MAINTAINERS from all Open Containers projects (runC, runtime-spec, and image-spec). + +## Subject templates + +Maintainers are busy and get lots of email. +To make project proposals recognizable, proposed motions SHOULD use the following subject templates. + +### Proposing a motion + +> [{project} VOTE]: {motion description} (closes {end of voting window}) + +For example: + +> [runtime-spec VOTE]: Tag 0647920 as 1.0.0-rc (closes 2016-06-03 20:00 UTC) + +### Tallying results + +After voting closes, a maintainer SHOULD post a tally to the motion thread with a subject template like: + +> [{project} {status}]: {motion description} (+{LGTMs} -{REJECTs} #{ABSTAINs}) + +Where `{status}` is either `adopted` or `rejected`. +For example: + +> [runtime-spec adopted]: Tag 0647920 as 1.0.0-rc (+6 -0 #3) + +[charter]: https://www.opencontainers.org/about/governance diff --git a/vendor/github.com/opencontainers/runtime-spec/MAINTAINERS b/vendor/github.com/opencontainers/runtime-spec/MAINTAINERS new file mode 100644 index 0000000000..d3fe235d9b --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/MAINTAINERS @@ -0,0 +1,8 @@ +Michael Crosby (@crosbymichael) +Vishnu Kannan (@vishh) +Mrunal Patel (@mrunalp) +Vincent Batts (@vbatts) +Daniel, Dao Quang Minh (@dqminh) +Brandon Philips (@philips) +Tianon Gravi (@tianon) +Qiang Huang (@hqhq) diff --git a/vendor/github.com/opencontainers/runtime-spec/Makefile b/vendor/github.com/opencontainers/runtime-spec/Makefile new file mode 100644 index 0000000000..b7624caaca --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/Makefile @@ -0,0 +1,94 @@ + +EPOCH_TEST_COMMIT := 78e6667ae2d67aad100b28ee9580b41b7a24e667 +OUTPUT_DIRNAME ?= output +DOC_FILENAME ?= oci-runtime-spec +DOCKER ?= $(shell command -v docker 2>/dev/null) +PANDOC ?= $(shell command -v pandoc 2>/dev/null) +ifeq "$(strip $(PANDOC))" '' + ifneq "$(strip $(DOCKER))" '' + PANDOC = $(DOCKER) run \ + -it \ + --rm \ + -v $(shell pwd)/:/input/:ro \ + -v $(shell pwd)/$(OUTPUT_DIRNAME)/:/$(OUTPUT_DIRNAME)/ \ + -u $(shell id -u) \ + vbatts/pandoc + PANDOC_SRC := /input/ + PANDOC_DST := / + endif +endif + +# These docs are in an order that determines how they show up in the PDF/HTML docs. +DOC_FILES := \ + version.md \ + spec.md \ + principles.md \ + bundle.md \ + runtime.md \ + runtime-linux.md \ + config.md \ + config-linux.md \ + config-solaris.md \ + glossary.md + +default: docs + +docs: $(OUTPUT_DIRNAME)/$(DOC_FILENAME).pdf $(OUTPUT_DIRNAME)/$(DOC_FILENAME).html + +ifeq "$(strip $(PANDOC))" '' +$(OUTPUT_DIRNAME)/$(DOC_FILENAME).pdf $(OUTPUT_DIRNAME)/$(DOC_FILENAME).html: + $(error cannot build $@ without either pandoc or docker) +else +$(OUTPUT_DIRNAME)/$(DOC_FILENAME).pdf: $(DOC_FILES) + mkdir -p $(OUTPUT_DIRNAME)/ && \ + $(PANDOC) -f markdown_github -t latex -o $(PANDOC_DST)$@ $(patsubst %,$(PANDOC_SRC)%,$(DOC_FILES)) + +$(OUTPUT_DIRNAME)/$(DOC_FILENAME).html: $(DOC_FILES) + mkdir -p $(OUTPUT_DIRNAME)/ && \ + $(PANDOC) -f markdown_github -t html5 -o $(PANDOC_DST)$@ $(patsubst %,$(PANDOC_SRC)%,$(DOC_FILES)) +endif + +version.md: ./specs-go/version.go + go run ./.tool/version-doc.go > $@ + +HOST_GOLANG_VERSION = $(shell go version | cut -d ' ' -f3 | cut -c 3-) +# this variable is used like a function. First arg is the minimum version, Second arg is the version to be checked. +ALLOWED_GO_VERSION = $(shell test '$(shell /bin/echo -e "$(1)\n$(2)" | sort -V | head -n1)' = '$(1)' && echo 'true') + +test: .govet .golint .gitvalidation + +.govet: + go vet -x ./... + +# `go get github.com/golang/lint/golint` +.golint: +ifeq ($(call ALLOWED_GO_VERSION,1.7,$(HOST_GOLANG_VERSION)),true) + @which golint > /dev/null 2>/dev/null || (echo "ERROR: golint not found. Consider 'make install.tools' target" && false) + golint ./... +endif + + +# When this is running in travis, it will only check the travis commit range +.gitvalidation: + @which git-validation > /dev/null 2>/dev/null || (echo "ERROR: git-validation not found. Consider 'make install.tools' target" && false) +ifdef TRAVIS_COMMIT_RANGE + git-validation -q -run DCO,short-subject,dangling-whitespace +else + git-validation -v -run DCO,short-subject,dangling-whitespace -range $(EPOCH_TEST_COMMIT)..HEAD +endif + +install.tools: .install.golint .install.gitvalidation + +# golint does not even build for + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +You can add the sign off when creating the git commit via `git commit -s`. + +#### Commit Style + +Simple house-keeping for clean git history. +Read more on [How to Write a Git Commit Message][how-to-git-commit] or the Discussion section of [git-commit(1)][git-commit.1]. + +1. Separate the subject from body with a blank line +2. Limit the subject line to 50 characters +3. Capitalize the subject line +4. Do not end the subject line with a period +5. Use the imperative mood in the subject line +6. Wrap the body at 72 characters +7. Use the body to explain what and why vs. how + * If there was important/useful/essential conversation or information, copy or include a reference +8. When possible, one keyword to scope the change in the subject (i.e. "README: ...", "runtime: ...") + + +[charter]: https://www.opencontainers.org/about/governance +[code-of-conduct]: https://github.com/opencontainers/tob/blob/master/code-of-conduct.md +[dev-list]: https://groups.google.com/a/opencontainers.org/forum/#!forum/dev +[how-to-git-commit]: http://chris.beams.io/posts/git-commit +[irc-logs]: http://ircbot.wl.linuxfoundation.org/eavesdrop/%23opencontainers/ +[iso-week]: https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_of_a_given_date +[minutes]: http://ircbot.wl.linuxfoundation.org/meetings/opencontainers/ +[oci]: https://www.opencontainers.org +[rfc5545]: https://tools.ietf.org/html/rfc5545 +[runtime-wiki]: https://github.com/opencontainers/runtime-spec/wiki +[uberconference]: https://www.uberconference.com/opencontainers + +[git-commit.1]: http://git-scm.com/docs/git-commit diff --git a/vendor/github.com/opencontainers/runtime-spec/RELEASES.md b/vendor/github.com/opencontainers/runtime-spec/RELEASES.md new file mode 100644 index 0000000000..a28e086a7c --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/RELEASES.md @@ -0,0 +1,51 @@ +# Releases + +The release process hopes to encourage early, consistent consensus-building during project development. +The mechanisms used are regular community communication on the mailing list about progress, scheduled meetings for issue resolution and release triage, and regularly paced and communicated releases. +Releases are proposed and adopted or rejected using the usual [project governance](GOVERNANCE.md) rules and procedures. + +An anti-pattern that we want to avoid is heavy development or discussions "late cycle" around major releases. +We want to build a community that is involved and communicates consistently through all releases instead of relying on "silent periods" as a judge of stability. + +## Parallel releases + +A single project MAY consider several motions to release in parallel. +However each motion to release after the initial 0.1.0 MUST be based on a previous release that has already landed. + +For example, runtime-spec maintainers may propose a v1.0.0-rc2 on the 1st of the month and a v0.9.1 bugfix on the 2nd of the month. +They may not propose a v1.0.0-rc3 until the v1.0.0-rc2 is accepted (on the 7th if the vote initiated on the 1st passes). + +## Specifications + +The OCI maintains three categories of projects: specifications, applications, and conformance-testing tools. +However, specification releases have special restrictions in the [OCI charter][charter]: + +* They are the target of backwards compatibility (§7.g), and +* They are subject to the OFWa patent grant (§8.d and e). + +To avoid unfortunate side effects (onerous backwards compatibity requirements or Member resignations), the following additional procedures apply to specification releases: + +### Planning a release + +Every OCI specification project SHOULD hold meetings that involve maintainers reviewing pull requests, debating outstanding issues, and planning releases. +This meeting MUST be advertised on the project README and MAY happen on a phone call, video conference, or on IRC. +Maintainers MUST send updates to the dev@opencontainers.org with results of these meetings. + +Before the specification reaches v1.0.0, the meetings SHOULD be weekly. +Once a specification has reached v1.0.0, the maintainers may alter the cadence, but a meeting MUST be held within four weeks of the previous meeting. + +The release plans, corresponding milestones and estimated due dates MUST be published on GitHub (e.g. https://github.com/opencontainers/runtime-spec/milestones). +GitHub milestones and issues are only used for community organization and all releases MUST follow the [project governance](GOVERNANCE.md) rules and procedures. + +### Timelines + +Specifications have a variety of different timelines in their lifecycle. + +* Pre-v1.0.0 specifications SHOULD release on a monthly cadence to garner feedback. +* Major specification releases MUST release at least three release candidates spaced a minimum of one week apart. + This means a major release like a v1.0.0 or v2.0.0 release will take 1 month at minimum: one week for rc1, one week for rc2, one week for rc3, and one week for the major release itself. + Maintainers SHOULD strive to make zero breaking changes during this cycle of release candidates and SHOULD restart the three-candidate count when a breaking change is introduced. + For example if a breaking change is introduced in v1.0.0-rc2 then the series would end with v1.0.0-rc4 and v1.0.0. +- Minor and patch releases SHOULD be made on an as-needed basis. + +[charter]: https://www.opencontainers.org/about/governance diff --git a/vendor/github.com/opencontainers/runtime-spec/bundle.md b/vendor/github.com/opencontainers/runtime-spec/bundle.md new file mode 100644 index 0000000000..0924ad9fe7 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/bundle.md @@ -0,0 +1,22 @@ +# Filesystem Bundle + +## Container Format + +This section defines a format for encoding a container as a *filesystem bundle* - a set of files organized in a certain way, and containing all the necessary data and metadata for any compliant runtime to perform all standard operations against it. +See also [MacOS application bundles][macos_bundle] for a similar use of the term *bundle*. + +The definition of a bundle is only concerned with how a container, and its configuration data, are stored on a local filesystem so that it can be consumed by a compliant runtime. + +A Standard Container bundle contains all the information needed to load and run a container. +This includes the following artifacts: + +1. `config.json`: contains configuration data. + This REQUIRED file MUST reside in the root of the bundle directory and MUST be named `config.json`. + See [`config.json`](config.md) for more details. + +2. container's root filesystem: the directory referenced by [`root.path`](config.md#root), if that property is set in `config.json`. + +When supplied, while these artifacts MUST all be present in a single directory on the local filesystem, that directory itself is not part of the bundle. +In other words, a tar archive of a *bundle* will have these artifacts at the root of the archive, not nested within a top-level directory. + +[macos_bundle]: https://en.wikipedia.org/wiki/Bundle_%28macOS%29 diff --git a/vendor/github.com/opencontainers/runtime-spec/config-linux.md b/vendor/github.com/opencontainers/runtime-spec/config-linux.md new file mode 100644 index 0000000000..e3d4100ab2 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/config-linux.md @@ -0,0 +1,703 @@ +# Linux Container Configuration + +This document describes the schema for the [Linux-specific section](config.md#platform-specific-configuration) of the [container configuration](config.md). +The Linux container specification uses various kernel features like namespaces, cgroups, capabilities, LSM, and filesystem jails to fulfill the spec. + +## Default Filesystems + +The Linux ABI includes both syscalls and several special file paths. +Applications expecting a Linux environment will very likely expect these file paths to be set up correctly. + +The following filesystems SHOULD be made available in each container's filesystem: + +| Path | Type | +| -------- | ------ | +| /proc | [proc][] | +| /sys | [sysfs][] | +| /dev/pts | [devpts][] | +| /dev/shm | [tmpfs][] | + +## Namespaces + +A namespace wraps a global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource. +Changes to the global resource are visible to other processes that are members of the namespace, but are invisible to other processes. +For more information, see the [namespaces(7)][namespaces.7_2] man page. + +Namespaces are specified as an array of entries inside the `namespaces` root field. +The following parameters can be specified to set up namespaces: + +* **`type`** *(string, REQUIRED)* - namespace type. The following namespace types are supported: + * **`pid`** processes inside the container will only be able to see other processes inside the same container. + * **`network`** the container will have its own network stack. + * **`mount`** the container will have an isolated mount table. + * **`ipc`** processes inside the container will only be able to communicate to other processes inside the same container via system level IPC. + * **`uts`** the container will be able to have its own hostname and domain name. + * **`user`** the container will be able to remap user and group IDs from the host to local users and groups within the container. + * **`cgroup`** the container will have an isolated view of the cgroup hierarchy. + +* **`path`** *(string, OPTIONAL)* - namespace file. + This value MUST be an absolute path in the [runtime mount namespace](glossary.md#runtime-namespace). + The runtime MUST place the container process in the namespace associated with that `path`. + The runtime MUST [generate an error](runtime.md#errors) if `path` is not associated with a namespace of type `type`. + + If `path` is not specified, the runtime MUST create a new [container namespace](glossary.md#container-namespace) of type `type`. + +If a namespace type is not specified in the `namespaces` array, the container MUST inherit the [runtime namespace](glossary.md#runtime-namespace) of that type. +If a `namespaces` field contains duplicated namespaces with same `type`, the runtime MUST [generate an error](runtime.md#errors). + +### Example + +```json + "namespaces": [ + { + "type": "pid", + "path": "/proc/1234/ns/pid" + }, + { + "type": "network", + "path": "/var/run/netns/neta" + }, + { + "type": "mount" + }, + { + "type": "ipc" + }, + { + "type": "uts" + }, + { + "type": "user" + }, + { + "type": "cgroup" + } + ] +``` + +## User namespace mappings + +**`uidMappings`** (array of objects, OPTIONAL) describes the user namespace uid mappings from the host to the container. +**`gidMappings`** (array of objects, OPTIONAL) describes the user namespace gid mappings from the host to the container. + +Each entry has the following structure: + +* **`containerID`** *(uint32, REQUIRED)* - is the starting uid/gid in the container. +* **`hostID`** *(uint32, REQUIRED)* - is the starting uid/gid on the host to be mapped to *containerID*. +* **`size`** *(uint32, REQUIRED)* - is the number of ids to be mapped. + +The runtime SHOULD NOT modify the ownership of referenced filesystems to realize the mapping. +Note that the number of mapping entries MAY be limited by the [kernel][user-namespaces]. + +### Example + +```json + "uidMappings": [ + { + "containerID": 0, + "hostID": 1000, + "size": 32000 + } + ], + "gidMappings": [ + { + "containerID": 0, + "hostID": 1000, + "size": 32000 + } + ] +``` + +## Devices + +**`devices`** (array of objects, OPTIONAL) lists devices that MUST be available in the container. +The runtime MAY supply them however it likes (with [`mknod`][mknod.2], by bind mounting from the runtime mount namespace, using symlinks, etc.). + +Each entry has the following structure: + +* **`type`** *(string, REQUIRED)* - type of device: `c`, `b`, `u` or `p`. + More info in [mknod(1)][mknod.1]. +* **`path`** *(string, REQUIRED)* - full path to device inside container. + If a [file][] already exists at `path` that does not match the requested device, the runtime MUST generate an error. +* **`major, minor`** *(int64, REQUIRED unless `type` is `p`)* - [major, minor numbers][devices] for the device. +* **`fileMode`** *(uint32, OPTIONAL)* - file mode for the device. + You can also control access to devices [with cgroups](#device-whitelist). +* **`uid`** *(uint32, OPTIONAL)* - id of device owner in the [container namespace](glossary.md#container-namespace). +* **`gid`** *(uint32, OPTIONAL)* - id of device group in the [container namespace](glossary.md#container-namespace). + +The same `type`, `major` and `minor` SHOULD NOT be used for multiple devices. + +### Example + +```json + "devices": [ + { + "path": "/dev/fuse", + "type": "c", + "major": 10, + "minor": 229, + "fileMode": 438, + "uid": 0, + "gid": 0 + }, + { + "path": "/dev/sda", + "type": "b", + "major": 8, + "minor": 0, + "fileMode": 432, + "uid": 0, + "gid": 0 + } + ] +``` + +### Default Devices + +In addition to any devices configured with this setting, the runtime MUST also supply: + +* [`/dev/null`][null.4] +* [`/dev/zero`][zero.4] +* [`/dev/full`][full.4] +* [`/dev/random`][random.4] +* [`/dev/urandom`][random.4] +* [`/dev/tty`][tty.4] +* `/dev/console` is set up if [`terminal`](config.md#process) is enabled in the config by bind mounting the pseudoterminal slave to `/dev/console`. +* [`/dev/ptmx`][pts.4]. + A [bind-mount or symlink of the container's `/dev/pts/ptmx`][devpts]. + +## Control groups + +Also known as cgroups, they are used to restrict resource usage for a container and handle device access. +cgroups provide controls (through controllers) to restrict cpu, memory, IO, pids, network and RDMA resources for the container. +For more information, see the [kernel cgroups documentation][cgroup-v1]. + +### Cgroups Path + +**`cgroupsPath`** (string, OPTIONAL) path to the cgroups. +It can be used to either control the cgroups hierarchy for containers or to run a new process in an existing container. + +The value of `cgroupsPath` MUST be either an absolute path or a relative path. +* In the case of an absolute path (starting with `/`), the runtime MUST take the path to be relative to the cgroups mount point. +* In the case of a relative path (not starting with `/`), the runtime MAY interpret the path relative to a runtime-determined location in the cgroups hierarchy. + +If the value is specified, the runtime MUST consistently attach to the same place in the cgroups hierarchy given the same value of `cgroupsPath`. +If the value is not specified, the runtime MAY define the default cgroups path. +Runtimes MAY consider certain `cgroupsPath` values to be invalid, and MUST generate an error if this is the case. + +Implementations of the Spec can choose to name cgroups in any manner. +The Spec does not include naming schema for cgroups. +The Spec does not support per-controller paths for the reasons discussed in the [cgroupv2 documentation][cgroup-v2]. +The cgroups will be created if they don't exist. + +You can configure a container's cgroups via the `resources` field of the Linux configuration. +Do not specify `resources` unless limits have to be updated. +For example, to run a new process in an existing container without updating limits, `resources` need not be specified. + +Runtimes MAY attach the container process to additional cgroup controllers beyond those necessary to fulfill the `resources` settings. + +### Example + +```json + "cgroupsPath": "/myRuntime/myContainer", + "resources": { + "memory": { + "limit": 100000, + "reservation": 200000 + }, + "devices": [ + { + "allow": false, + "access": "rwm" + } + ] + } +``` + +### Device whitelist + +**`devices`** (array of objects, OPTIONAL) configures the [device whitelist][cgroup-v1-devices]. +The runtime MUST apply entries in the listed order. + +Each entry has the following structure: + +* **`allow`** *(boolean, REQUIRED)* - whether the entry is allowed or denied. +* **`type`** *(string, OPTIONAL)* - type of device: `a` (all), `c` (char), or `b` (block). + Unset values mean "all", mapping to `a`. +* **`major, minor`** *(int64, OPTIONAL)* - [major, minor numbers][devices] for the device. + Unset values mean "all", mapping to [`*` in the filesystem API][cgroup-v1-devices]. +* **`access`** *(string, OPTIONAL)* - cgroup permissions for device. + A composition of `r` (read), `w` (write), and `m` (mknod). + +#### Example + +```json + "devices": [ + { + "allow": false, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 10, + "minor": 229, + "access": "rw" + }, + { + "allow": true, + "type": "b", + "major": 8, + "minor": 0, + "access": "r" + } + ] +``` + +### Memory + +**`memory`** (object, OPTIONAL) represents the cgroup subsystem `memory` and it's used to set limits on the container's memory usage. +For more information, see the kernel cgroups documentation about [memory][cgroup-v1-memory]. + +Values for memory specify the limit in bytes, or `-1` for unlimited memory. + +* **`limit`** *(int64, OPTIONAL)* - sets limit of memory usage +* **`reservation`** *(int64, OPTIONAL)* - sets soft limit of memory usage +* **`swap`** *(int64, OPTIONAL)* - sets limit of memory+Swap usage +* **`kernel`** *(int64, OPTIONAL)* - sets hard limit for kernel memory +* **`kernelTCP`** *(int64, OPTIONAL)* - sets hard limit for kernel TCP buffer memory + +The following properties do not specify memory limits, but are covered by the `memory` controller: + +* **`swappiness`** *(uint64, OPTIONAL)* - sets swappiness parameter of vmscan (See sysctl's vm.swappiness) + The values are from 0 to 100. Higher means more swappy. +* **`disableOOMKiller`** *(bool, OPTIONAL)* - enables or disables the OOM killer. + If enabled (`false`), tasks that attempt to consume more memory than they are allowed are immediately killed by the OOM killer. + The OOM killer is enabled by default in every cgroup using the `memory` subsystem. + To disable it, specify a value of `true`. + +#### Example + +```json + "memory": { + "limit": 536870912, + "reservation": 536870912, + "swap": 536870912, + "kernel": -1, + "kernelTCP": -1, + "swappiness": 0, + "disableOOMKiller": false + } +``` + +### CPU + +**`cpu`** (object, OPTIONAL) represents the cgroup subsystems `cpu` and `cpusets`. +For more information, see the kernel cgroups documentation about [cpusets][cgroup-v1-cpusets]. + +The following parameters can be specified to set up the controller: + +* **`shares`** *(uint64, OPTIONAL)* - specifies a relative share of CPU time available to the tasks in a cgroup +* **`quota`** *(int64, OPTIONAL)* - specifies the total amount of time in microseconds for which all tasks in a cgroup can run during one period (as defined by **`period`** below) +* **`period`** *(uint64, OPTIONAL)* - specifies a period of time in microseconds for how regularly a cgroup's access to CPU resources should be reallocated (CFS scheduler only) +* **`realtimeRuntime`** *(int64, OPTIONAL)* - specifies a period of time in microseconds for the longest continuous period in which the tasks in a cgroup have access to CPU resources +* **`realtimePeriod`** *(uint64, OPTIONAL)* - same as **`period`** but applies to realtime scheduler only +* **`cpus`** *(string, OPTIONAL)* - list of CPUs the container will run in +* **`mems`** *(string, OPTIONAL)* - list of Memory Nodes the container will run in + +#### Example + +```json + "cpu": { + "shares": 1024, + "quota": 1000000, + "period": 500000, + "realtimeRuntime": 950000, + "realtimePeriod": 1000000, + "cpus": "2-3", + "mems": "0-7" + } +``` + +### Block IO + +**`blockIO`** (object, OPTIONAL) represents the cgroup subsystem `blkio` which implements the block IO controller. +For more information, see the kernel cgroups documentation about [blkio][cgroup-v1-blkio]. + +The following parameters can be specified to set up the controller: + +* **`weight`** *(uint16, OPTIONAL)* - specifies per-cgroup weight. This is default weight of the group on all devices until and unless overridden by per-device rules. +* **`leafWeight`** *(uint16, OPTIONAL)* - equivalents of `weight` for the purpose of deciding how much weight tasks in the given cgroup has while competing with the cgroup's child cgroups. +* **`weightDevice`** *(array of objects, OPTIONAL)* - an array of per-device bandwidth weights. + Each entry has the following structure: + * **`major, minor`** *(int64, REQUIRED)* - major, minor numbers for device. + For more information, see the [mknod(1)][mknod.1] man page. + * **`weight`** *(uint16, OPTIONAL)* - bandwidth weight for the device. + * **`leafWeight`** *(uint16, OPTIONAL)* - bandwidth weight for the device while competing with the cgroup's child cgroups, CFQ scheduler only + + You MUST specify at least one of `weight` or `leafWeight` in a given entry, and MAY specify both. + +* **`throttleReadBpsDevice`**, **`throttleWriteBpsDevice`** *(array of objects, OPTIONAL)* - an array of per-device bandwidth rate limits. + Each entry has the following structure: + * **`major, minor`** *(int64, REQUIRED)* - major, minor numbers for device. + For more information, see the [mknod(1)][mknod.1] man page. + * **`rate`** *(uint64, REQUIRED)* - bandwidth rate limit in bytes per second for the device + +* **`throttleReadIOPSDevice`**, **`throttleWriteIOPSDevice`** *(array of objects, OPTIONAL)* - an array of per-device IO rate limits. + Each entry has the following structure: + * **`major, minor`** *(int64, REQUIRED)* - major, minor numbers for device. + For more information, see the [mknod(1)][mknod.1] man page. + * **`rate`** *(uint64, REQUIRED)* - IO rate limit for the device + +#### Example + +```json + "blockIO": { + "weight": 10, + "leafWeight": 10, + "weightDevice": [ + { + "major": 8, + "minor": 0, + "weight": 500, + "leafWeight": 300 + }, + { + "major": 8, + "minor": 16, + "weight": 500 + } + ], + "throttleReadBpsDevice": [ + { + "major": 8, + "minor": 0, + "rate": 600 + } + ], + "throttleWriteIOPSDevice": [ + { + "major": 8, + "minor": 16, + "rate": 300 + } + ] + } +``` + +### Huge page limits + +**`hugepageLimits`** (array of objects, OPTIONAL) represents the `hugetlb` controller which allows to limit the +HugeTLB usage per control group and enforces the controller limit during page fault. +For more information, see the kernel cgroups documentation about [HugeTLB][cgroup-v1-hugetlb]. + +Each entry has the following structure: + +* **`pageSize`** *(string, REQUIRED)* - hugepage size +* **`limit`** *(uint64, REQUIRED)* - limit in bytes of *hugepagesize* HugeTLB usage + +#### Example + +```json + "hugepageLimits": [ + { + "pageSize": "2MB", + "limit": 209715200 + } + ] +``` + +### Network + +**`network`** (object, OPTIONAL) represents the cgroup subsystems `net_cls` and `net_prio`. +For more information, see the kernel cgroups documentations about [net\_cls cgroup][cgroup-v1-net-cls] and [net\_prio cgroup][cgroup-v1-net-prio]. + +The following parameters can be specified to set up the controller: + +* **`classID`** *(uint32, OPTIONAL)* - is the network class identifier the cgroup's network packets will be tagged with +* **`priorities`** *(array of objects, OPTIONAL)* - specifies a list of objects of the priorities assigned to traffic originating from processes in the group and egressing the system on various interfaces. + The following parameters can be specified per-priority: + * **`name`** *(string, REQUIRED)* - interface name in [runtime network namespace](glossary.md#runtime-namespace) + * **`priority`** *(uint32, REQUIRED)* - priority applied to the interface + +#### Example + +```json + "network": { + "classID": 1048577, + "priorities": [ + { + "name": "eth0", + "priority": 500 + }, + { + "name": "eth1", + "priority": 1000 + } + ] + } +``` + +### PIDs + +**`pids`** (object, OPTIONAL) represents the cgroup subsystem `pids`. +For more information, see the kernel cgroups documentation about [pids][cgroup-v1-pids]. + +The following parameters can be specified to set up the controller: + +* **`limit`** *(int64, REQUIRED)* - specifies the maximum number of tasks in the cgroup + +#### Example + +```json + "pids": { + "limit": 32771 + } +``` + +### RDMA + +**`rdma`** (object, OPTIONAL) represents the cgroup subsystem `rdma`. +For more information, see the kernel cgroups documentation about [rdma][cgroup-v1-rdma]. + +The name of the device to limit is the entry key. +Entry values are objects with the following properties: + +* **`hcaHandles`** *(uint32, OPTIONAL)* - specifies the maximum number of hca_handles in the cgroup +* **`hcaObjects`** *(uint32, OPTIONAL)* - specifies the maximum number of hca_objects in the cgroup + +You MUST specify at least one of the `hcaHandles` or `hcaObjects` in a given entry, and MAY specify both. + +#### Example + +```json +"rdma": { + "mlx5_1": { + "hcaHandles": 3, + "hcaObjects": 10000 + }, + "mlx4_0": { + "hcaObjects": 1000 + }, + "rxe3": { + "hcaObjects": 10000 + } +} +``` + +## IntelRdt + +**`intelRdt`** (object, OPTIONAL) represents the [Intel Resource Director Technology][intel-rdt-cat-kernel-interface]. + If `intelRdt` is set, the runtime MUST write the container process ID to the `/tasks` file in a mounted `resctrl` pseudo-filesystem, using the container ID from [`start`](runtime.md#start) and creating the `` directory if necessary. + If no mounted `resctrl` pseudo-filesystem is available in the [runtime mount namespace](glossary.md#runtime-namespace), the runtime MUST [generate an error](runtime.md#errors). + + If `intelRdt` is not set, the runtime MUST NOT manipulate any `resctrl` pseudo-filesystems. + +The following parameters can be specified for the container: + +* **`l3CacheSchema`** *(string, OPTIONAL)* - specifies the schema for L3 cache id and capacity bitmask (CBM). + If `l3CacheSchema` is set, runtimes MUST write the value to the `schemata` file in the `` directory discussed in `intelRdt`. + + If `l3CacheSchema` is not set, runtimes MUST NOT write to `schemata` files in any `resctrl` pseudo-filesystems. + +### Example + +Consider a two-socket machine with two L3 caches where the default CBM is 0xfffff and the max CBM length is 20 bits. +Tasks inside the container only have access to the "upper" 80% of L3 cache id 0 and the "lower" 50% L3 cache id 1: + +```json +"linux": { + "intelRdt": { + "l3CacheSchema": "L3:0=ffff0;1=3ff" + } +} +``` + +## Sysctl + +**`sysctl`** (object, OPTIONAL) allows kernel parameters to be modified at runtime for the container. +For more information, see the [sysctl(8)][sysctl.8] man page. + +### Example + +```json + "sysctl": { + "net.ipv4.ip_forward": "1", + "net.core.somaxconn": "256" + } +``` + +## Seccomp + +Seccomp provides application sandboxing mechanism in the Linux kernel. +Seccomp configuration allows one to configure actions to take for matched syscalls and furthermore also allows matching on values passed as arguments to syscalls. +For more information about Seccomp, see [Seccomp][seccomp] kernel documentation. +The actions, architectures, and operators are strings that match the definitions in seccomp.h from [libseccomp][] and are translated to corresponding values. + +**`seccomp`** (object, OPTIONAL) + +The following parameters can be specified to set up seccomp: + +* **`defaultAction`** *(string, REQUIRED)* - the default action for seccomp. Allowed values are the same as `syscalls[].action`. + +* **`architectures`** *(array of strings, OPTIONAL)* - the architecture used for system calls. + A valid list of constants as of libseccomp v2.3.2 is shown below. + + * `SCMP_ARCH_X86` + * `SCMP_ARCH_X86_64` + * `SCMP_ARCH_X32` + * `SCMP_ARCH_ARM` + * `SCMP_ARCH_AARCH64` + * `SCMP_ARCH_MIPS` + * `SCMP_ARCH_MIPS64` + * `SCMP_ARCH_MIPS64N32` + * `SCMP_ARCH_MIPSEL` + * `SCMP_ARCH_MIPSEL64` + * `SCMP_ARCH_MIPSEL64N32` + * `SCMP_ARCH_PPC` + * `SCMP_ARCH_PPC64` + * `SCMP_ARCH_PPC64LE` + * `SCMP_ARCH_S390` + * `SCMP_ARCH_S390X` + * `SCMP_ARCH_PARISC` + * `SCMP_ARCH_PARISC64` + +* **`syscalls`** *(array of objects, OPTIONAL)* - match a syscall in seccomp. + + While this property is OPTIONAL, some values of `defaultAction` are not useful without `syscalls` entries. + For example, if `defaultAction` is `SCMP_ACT_KILL` and `syscalls` is empty or unset, the kernel will kill the container process on its first syscall. + + Each entry has the following structure: + + * **`names`** *(array of strings, REQUIRED)* - the names of the syscalls. + `names` MUST contain at least one entry. + * **`action`** *(string, REQUIRED)* - the action for seccomp rules. + A valid list of constants as of libseccomp v2.3.2 is shown below. + + * `SCMP_ACT_KILL` + * `SCMP_ACT_TRAP` + * `SCMP_ACT_ERRNO` + * `SCMP_ACT_TRACE` + * `SCMP_ACT_ALLOW` + + * **`args`** *(array of objects, OPTIONAL)* - the specific syscall in seccomp. + + Each entry has the following structure: + + * **`index`** *(uint, REQUIRED)* - the index for syscall arguments in seccomp. + * **`value`** *(uint64, REQUIRED)* - the value for syscall arguments in seccomp. + * **`valueTwo`** *(uint64, OPTIONAL)* - the value for syscall arguments in seccomp. + * **`op`** *(string, REQUIRED)* - the operator for syscall arguments in seccomp. + A valid list of constants as of libseccomp v2.3.2 is shown below. + + * `SCMP_CMP_NE` + * `SCMP_CMP_LT` + * `SCMP_CMP_LE` + * `SCMP_CMP_EQ` + * `SCMP_CMP_GE` + * `SCMP_CMP_GT` + * `SCMP_CMP_MASKED_EQ` + +### Example + +```json + "seccomp": { + "defaultAction": "SCMP_ACT_ALLOW", + "architectures": [ + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ], + "syscalls": [ + { + "names": [ + "getcwd", + "chmod" + ], + "action": "SCMP_ACT_ERRNO" + } + ] + } +``` + +## Rootfs Mount Propagation + +**`rootfsPropagation`** (string, OPTIONAL) sets the rootfs's mount propagation. + Its value is either slave, private, shared or unbindable. + The [Shared Subtrees][sharedsubtree] article in the kernel documentation has more information about mount propagation. + +### Example + +```json + "rootfsPropagation": "slave", +``` + +## Masked Paths + +**`maskedPaths`** (array of strings, OPTIONAL) will mask over the provided paths inside the container so that they cannot be read. + The values MUST be absolute paths in the [container namespace](glossary.md#container_namespace). + +### Example + +```json + "maskedPaths": [ + "/proc/kcore" + ] +``` + +## Readonly Paths + +**`readonlyPaths`** (array of strings, OPTIONAL) will set the provided paths as readonly inside the container. + The values MUST be absolute paths in the [container namespace](glossary.md#container-namespace). + +### Example + +```json + "readonlyPaths": [ + "/proc/sys" + ] +``` + +## Mount Label + +**`mountLabel`** (string, OPTIONAL) will set the Selinux context for the mounts in the container. + +### Example + +```json + "mountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c715,c811" +``` + + +[cgroup-v1]: https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt +[cgroup-v1-blkio]: https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt +[cgroup-v1-cpusets]: https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt +[cgroup-v1-devices]: https://www.kernel.org/doc/Documentation/cgroup-v1/devices.txt +[cgroup-v1-hugetlb]: https://www.kernel.org/doc/Documentation/cgroup-v1/hugetlb.txt +[cgroup-v1-memory]: https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt +[cgroup-v1-net-cls]: https://www.kernel.org/doc/Documentation/cgroup-v1/net_cls.txt +[cgroup-v1-net-prio]: https://www.kernel.org/doc/Documentation/cgroup-v1/net_prio.txt +[cgroup-v1-pids]: https://www.kernel.org/doc/Documentation/cgroup-v1/pids.txt +[cgroup-v1-rdma]: https://www.kernel.org/doc/Documentation/cgroup-v1/rdma.txt +[cgroup-v2]: https://www.kernel.org/doc/Documentation/cgroup-v2.txt +[devices]: https://www.kernel.org/doc/Documentation/admin-guide/devices.txt +[devpts]: https://www.kernel.org/doc/Documentation/filesystems/devpts.txt +[file]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_164 +[libseccomp]: https://github.com/seccomp/libseccomp +[proc]: https://www.kernel.org/doc/Documentation/filesystems/proc.txt +[seccomp]: https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt +[sharedsubtree]: https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt +[sysfs]: https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt +[tmpfs]: https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt + +[full.4]: http://man7.org/linux/man-pages/man4/full.4.html +[mknod.1]: http://man7.org/linux/man-pages/man1/mknod.1.html +[mknod.2]: http://man7.org/linux/man-pages/man2/mknod.2.html +[namespaces.7_2]: http://man7.org/linux/man-pages/man7/namespaces.7.html +[null.4]: http://man7.org/linux/man-pages/man4/null.4.html +[pts.4]: http://man7.org/linux/man-pages/man4/pts.4.html +[random.4]: http://man7.org/linux/man-pages/man4/random.4.html +[sysctl.8]: http://man7.org/linux/man-pages/man8/sysctl.8.html +[tty.4]: http://man7.org/linux/man-pages/man4/tty.4.html +[zero.4]: http://man7.org/linux/man-pages/man4/zero.4.html +[user-namespaces]: http://man7.org/linux/man-pages/man7/user_namespaces.7.html +[intel-rdt-cat-kernel-interface]: https://www.kernel.org/doc/Documentation/x86/intel_rdt_ui.txt diff --git a/vendor/github.com/opencontainers/runtime-spec/config-solaris.md b/vendor/github.com/opencontainers/runtime-spec/config-solaris.md new file mode 100644 index 0000000000..4446a166a0 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/config-solaris.md @@ -0,0 +1,120 @@ +# Solaris Application Container Configuration + +Solaris application containers can be configured using the following properties, all of the below properties have mappings to properties specified under [zonecfg(1M)][zonecfg.1m_2] man page, except milestone. + +## milestone +The SMF(Service Management Facility) FMRI which should go to "online" state before we start the desired process within the container. + +**`milestone`** *(string, OPTIONAL)* + +### Example +```json +"milestone": "svc:/milestone/container:default" +``` + +## limitpriv +The maximum set of privileges any process in this container can obtain. +The property should consist of a comma-separated privilege set specification as described in [priv_str_to_set(3C)][priv-str-to-set.3c] man page for the respective release of Solaris. + +**`limitpriv`** *(string, OPTIONAL)* + +### Example +```json +"limitpriv": "default" +``` + +## maxShmMemory +The maximum amount of shared memory allowed for this application container. +A scale (K, M, G, T) can be applied to the value for each of these numbers (for example, 1M is one megabyte). +Mapped to `max-shm-memory` in [zonecfg(1M)][zonecfg.1m_2] man page. + +**`maxShmMemory`** *(string, OPTIONAL)* + +### Example +```json +"maxShmMemory": "512m" +``` + +## cappedCPU +Sets a limit on the amount of CPU time that can be used by a container. +The unit used translates to the percentage of a single CPU that can be used by all user threads in a container, expressed as a fraction (for example, .75) or a mixed number (whole number and fraction, for example, 1.25). +An ncpu value of 1 means 100% of a CPU, a value of 1.25 means 125%, .75 mean 75%, and so forth. +When projects within a capped container have their own caps, the minimum value takes precedence. +cappedCPU is mapped to `capped-cpu` in [zonecfg(1M)][zonecfg.1m_2] man page. + +* **`ncpus`** *(string, OPTIONAL)* + +### Example +```json +"cappedCPU": { + "ncpus": "8" +} +``` + +## cappedMemory +The physical and swap caps on the memory that can be used by this application container. +A scale (K, M, G, T) can be applied to the value for each of these numbers (for example, 1M is one megabyte). +cappedMemory is mapped to `capped-memory` in [zonecfg(1M)][zonecfg.1m_2] man page. + +* **`physical`** *(string, OPTIONAL)* +* **`swap`** *(string, OPTIONAL)* + +### Example +```json +"cappedMemory": { + "physical": "512m", + "swap": "512m" +} +``` + +## Network + +### Automatic Network (anet) +anet is specified as an array that is used to set up networking for Solaris application containers. +The anet resource represents the automatic creation of a network resource for an application container. +The zones administration daemon, zoneadmd, is the primary process for managing the container's virtual platform. +One of the daemon's responsibilities is creation and teardown of the networks for the container. +For more information on the daemon see the [zoneadmd(1M)][zoneadmd.1m] man page. +When such a container is started, a temporary VNIC(Virtual NIC) is automatically created for the container. +The VNIC is deleted when the container is torn down. +The following properties can be used to set up automatic networks. +For additional information on properties, check the [zonecfg(1M)][zonecfg.1m_2] man page for the respective release of Solaris. + +* **`linkname`** *(string, OPTIONAL)* Specify a name for the automatically created VNIC datalink. +* **`lowerLink`** *(string, OPTIONAL)* Specify the link over which the VNIC will be created. +Mapped to `lower-link` in the [zonecfg(1M)][zonecfg.1m_2] man page. +* **`allowedAddress`** *(string, OPTIONAL)* The set of IP addresses that the container can use might be constrained by specifying the `allowedAddress` property. + If `allowedAddress` has not been specified, then they can use any IP address on the associated physical interface for the network resource. + Otherwise, when `allowedAddress` is specified, the container cannot use IP addresses that are not in the `allowedAddress` list for the physical address. + Mapped to `allowed-address` in the [zonecfg(1M)][zonecfg.1m_2] man page. +* **`configureAllowedAddress`** *(string, OPTIONAL)* If `configureAllowedAddress` is set to true, the addresses specified by `allowedAddress` are automatically configured on the interface each time the container starts. + When it is set to false, the `allowedAddress` will not be configured on container start. + Mapped to `configure-allowed-address` in the [zonecfg(1M)][zonecfg.1m_2] man page. +* **`defrouter`** *(string, OPTIONAL)* The value for the OPTIONAL default router. +* **`macAddress`** *(string, OPTIONAL)* Set the VNIC's MAC addresses based on the specified value or keyword. + If not a keyword, it is interpreted as a unicast MAC address. + For a list of the supported keywords please refer to the [zonecfg(1M)][zonecfg.1m_2] man page of the respective Solaris release. + Mapped to `mac-address` in the [zonecfg(1M)][zonecfg.1m_2] man page. +* **`linkProtection`** *(string, OPTIONAL)* Enables one or more types of link protection using comma-separated values. + See the protection property in dladm(8) for supported values in respective release of Solaris. + Mapped to `link-protection` in the [zonecfg(1M)][zonecfg.1m_2] man page. + +#### Example +```json +"anet": [ + { + "allowedAddress": "172.17.0.2/16", + "configureAllowedAddress": "true", + "defrouter": "172.17.0.1/16", + "linkProtection": "mac-nospoof, ip-nospoof", + "linkname": "net0", + "lowerLink": "net2", + "macAddress": "02:42:f8:52:c7:16" + } +] +``` + + +[priv-str-to-set.3c]: http://docs.oracle.com/cd/E86824_01/html/E54766/priv-str-to-set-3c.html +[zoneadmd.1m]: http://docs.oracle.com/cd/E86824_01/html/E54764/zoneadmd-1m.html +[zonecfg.1m_2]: http://docs.oracle.com/cd/E86824_01/html/E54764/zonecfg-1m.html diff --git a/vendor/github.com/opencontainers/runtime-spec/config-vm.md b/vendor/github.com/opencontainers/runtime-spec/config-vm.md new file mode 100644 index 0000000000..ff551d317c --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/config-vm.md @@ -0,0 +1,68 @@ +# Virtual-machine-specific Container Configuration + +This section describes the schema for the [virtual-machine-specific section](config.md#platform-specific-configuration) of the [container configuration](config.md). +The virtual-machine container specification provides additional configuration for the hypervisor, kernel, and image. + +## Hypervisor Object + +**`hypervisor`** (object, OPTIONAL) specifies details of the hypervisor that manages the container virtual machine. +* **`path`** (string, REQUIRED) path to the hypervisor binary that manages the container virtual machine. + This value MUST be an absolute path in the [runtime mount namespace](glossary.md#runtime-namespace). +* **`parameters`** (array of strings, OPTIONAL) specifies an array of parameters to pass to the hypervisor. + +### Example + +```json + "hypervisor": { + "path": "/path/to/vmm", + "parameters": ["opts1=foo", "opts2=bar"] + } +``` + +## Kernel Object + +**`kernel`** (object, REQUIRED) specifies details of the kernel to boot the container virtual machine with. +* **`path`** (string, REQUIRED) path to the kernel used to boot the container virtual machine. + This value MUST be an absolute path in the [runtime mount namespace](glossary.md#runtime-namespace). +* **`parameters`** (array of strings, OPTIONAL) specifies an array of parameters to pass to the kernel. +* **`initrd`** (string, OPTIONAL) path to an initial ramdisk to be used by the container virtual machine. + This value MUST be an absolute path in the [runtime mount namespace](glossary.md#runtime-namespace). + +### Example + +```json + "kernel": { + "path": "/path/to/vmlinuz", + "parameters": ["foo=bar", "hello world"], + "initrd": "/path/to/initrd.img" + } +``` + +## Image Object + +**`image`** (object, OPTIONAL) specifies details of the image that contains the root filesystem for the container virtual machine. +* **`path`** (string, REQUIRED) path to the container virtual machine root image. + This value MUST be an absolute path in the [runtime mount namespace](glossary.md#runtime-namespace). +* **`format`** (string, REQUIRED) format of the container virtual machine root image. Commonly supported formats are: + * **`raw`** [raw disk image format][raw-image-format]. Unset values for `format` will default to that format. + * **`qcow2`** [QEMU image format][qcow2-image-format]. + * **`vdi`** [VirtualBox 1.1 compatible image format][vdi-image-format]. + * **`vmdk`** [VMware compatible image format][vmdk-image-format]. + * **`vhd`** [Virtual Hard Disk image format][vhd-image-format]. + +This image contains the root filesystem that the virtual machine **`kernel`** will boot into, not to be confused with the container root filesystem itself. The latter, as specified by **`path`** from the [Root Configuration](config.md#Root-Configuration) section, will be mounted inside the virtual machine at a location chosen by the virtual-machine-based runtime. + +### Example + +```json + "image": { + "path": "/path/to/vm/rootfs.img", + "format": "raw" + } +``` + +[raw-image-format]: https://en.wikipedia.org/wiki/IMG_(file_format) +[qcow2-image-format]: https://git.qemu.org/?p=qemu.git;a=blob_plain;f=docs/interop/qcow2.txt;hb=HEAD +[vdi-image-format]: https://forensicswiki.org/wiki/Virtual_Disk_Image_(VDI) +[vmdk-image-format]: http://www.vmware.com/app/vmdk/?src=vmdk +[vhd-image-format]: https://github.com/libyal/libvhdi/blob/master/documentation/Virtual%20Hard%20Disk%20(VHD)%20image%20format.asciidoc diff --git a/vendor/github.com/opencontainers/runtime-spec/config-windows.md b/vendor/github.com/opencontainers/runtime-spec/config-windows.md new file mode 100644 index 0000000000..a2e5e53392 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/config-windows.md @@ -0,0 +1,175 @@ +# Windows-specific Container Configuration + +This document describes the schema for the [Windows-specific section](config.md#platform-specific-configuration) of the [container configuration](config.md). +The Windows container specification uses APIs provided by the Windows Host Compute Service (HCS) to fulfill the spec. + +## LayerFolders + +**`layerFolders`** (array of strings, REQUIRED) specifies a list of layer folders the container image relies on. The list is ordered from topmost layer to base layer. + `layerFolders` MUST contain at least one entry. + +### Example + +```json + "windows": { + "layerFolders": [ + "C:\\Layers\\layer1", + "C:\\Layers\\layer2" + ] + } +``` + +## Resources + +You can configure a container's resource limits via the OPTIONAL `resources` field of the Windows configuration. + +### Memory + +`memory` is an OPTIONAL configuration for the container's memory usage. + +The following parameters can be specified: + +* **`limit`** *(uint64, OPTIONAL)* - sets limit of memory usage in bytes. + +#### Example + +```json + "windows": { + "resources": { + "memory": { + "limit": 2097152 + } + } + } +``` + +### CPU + +`cpu` is an OPTIONAL configuration for the container's CPU usage. + +The following parameters can be specified: + +* **`count`** *(uint64, OPTIONAL)* - specifies the number of CPUs available to the container. +* **`shares`** *(uint16, OPTIONAL)* - specifies the relative weight to other containers with CPU shares. +* **`maximum`** *(uint16, OPTIONAL)* - specifies the portion of processor cycles that this container can use as a percentage times 100. + +#### Example + +```json + "windows": { + "resources": { + "cpu": { + "maximum": 5000 + } + } + } +``` + +### Storage + +`storage` is an OPTIONAL configuration for the container's storage usage. + +The following parameters can be specified: + +* **`iops`** *(uint64, OPTIONAL)* - specifies the maximum IO operations per second for the system drive of the container. +* **`bps`** *(uint64, OPTIONAL)* - specifies the maximum bytes per second for the system drive of the container. +* **`sandboxSize`** *(uint64, OPTIONAL)* - specifies the minimum size of the system drive in bytes. + +#### Example + +```json + "windows": { + "resources": { + "storage": { + "iops": 50 + } + } + } +``` + +## Network + +You can configure a container's networking options via the OPTIONAL `network` field of the Windows configuration. + +The following parameters can be specified: + +* **`endpointList`** *(array of strings, OPTIONAL)* - list of HNS (Host Network Service) endpoints that the container should connect to. +* **`allowUnqualifiedDNSQuery`** *(bool, OPTIONAL)* - specifies if unqualified DNS name resolution is allowed. +* **`DNSSearchList`** *(array of strings, OPTIONAL)* - comma separated list of DNS suffixes to use for name resolution. +* **`networkSharedContainerName`** *(string, OPTIONAL)* - name (ID) of the container that we will share with the network stack. + +### Example + +```json + "windows": { + "network": { + "endpointList": [ + "7a010682-17e0-4455-a838-02e5d9655fe6" + ], + "allowUnqualifiedDNSQuery": true, + "DNSSearchList": [ + "a.com", + "b.com" + ], + "networkSharedContainerName": "containerName" + } + } +``` + +## Credential Spec + +You can configure a container's group Managed Service Account (gMSA) via the OPTIONAL `credentialSpec` field of the Windows configuration. +The `credentialSpec` is a JSON object whose properties are implementation-defined. +For more information about gMSAs, see [Active Directory Service Accounts for Windows Containers][gMSAOverview]. +For more information about tooling to generate a gMSA, see [Deployment Overview][gMSATooling]. + + +[gMSAOverview]: https://aka.ms/windowscontainers/manage-serviceaccounts +[gMSATooling]: https://aka.ms/windowscontainers/credentialspec-tools + +## Servicing + +When a container terminates, the Host Compute Service indicates if a Windows update servicing operation is pending. +You can indicate that a container should be started in a mode to apply pending servicing operations via the OPTIONAL `servicing` field of the Windows configuration. + +### Example + +```json + "windows": { + "servicing": true + } +``` + +## IgnoreFlushesDuringBoot + +You can indicate that a container should be started in an a mode where disk flushes are not performed during container boot via the OPTIONAL `ignoreFlushesDuringBoot` field of the Windows configuration. + +### Example + +```json + "windows": { + "ignoreFlushesDuringBoot": true + } +``` + +## HyperV + +`hyperv` is an OPTIONAL field of the Windows configuration. +If present, the container MUST be run with Hyper-V isolation. +If omitted, the container MUST be run as a Windows Server container. + +The following parameters can be specified: + +* **`utilityVMPath`** *(string, OPTIONAL)* - specifies the path to the image used for the utility VM. + This would be specified if using a base image which does not contain a utility VM image. + If not supplied, the runtime will search the container filesystem layers from the bottom-most layer upwards, until it locates "UtilityVM", and default to that path. + +### Example + +```json + "windows": { + "hyperv": { + "utilityVMPath": "C:\\path\\to\\utilityvm" + } + } +``` diff --git a/vendor/github.com/opencontainers/runtime-spec/config.md b/vendor/github.com/opencontainers/runtime-spec/config.md new file mode 100644 index 0000000000..2d9279fb12 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/config.md @@ -0,0 +1,864 @@ +# Configuration + +This configuration file contains metadata necessary to implement [standard operations](runtime.md#operations) against the container. +This includes the process to run, environment variables to inject, sandboxing features to use, etc. + +The canonical schema is defined in this document, but there is a JSON Schema in [`schema/config-schema.json`](schema/config-schema.json) and Go bindings in [`specs-go/config.go`](specs-go/config.go). +[Platform](spec.md#platforms)-specific configuration schema are defined in the [platform-specific documents](#platform-specific-configuration) linked below. +For properties that are only defined for some [platforms](spec.md#platforms), the Go property has a `platform` tag listing those protocols (e.g. `platform:"linux,solaris"`). + +Below is a detailed description of each field defined in the configuration format and valid values are specified. +Platform-specific fields are identified as such. +For all platform-specific configuration values, the scope defined below in the [Platform-specific configuration](#platform-specific-configuration) section applies. + + +## Specification version + +* **`ociVersion`** (string, REQUIRED) MUST be in [SemVer v2.0.0][semver-v2.0.0] format and specifies the version of the Open Container Initiative Runtime Specification with which the bundle complies. + The Open Container Initiative Runtime Specification follows semantic versioning and retains forward and backward compatibility within major versions. + For example, if a configuration is compliant with version 1.1 of this specification, it is compatible with all runtimes that support any 1.1 or later release of this specification, but is not compatible with a runtime that supports 1.0 and not 1.1. + +### Example + +```json + "ociVersion": "0.1.0" +``` + +## Root + +**`root`** (object, OPTIONAL) specifies the container's root filesystem. +On Windows, for Windows Server Containers, this field is REQUIRED. +For [Hyper-V Containers](config-windows.md#hyperv), this field MUST NOT be set. + +On all other platforms, this field is REQUIRED. + +* **`path`** (string, REQUIRED) Specifies the path to the root filesystem for the container. + + * On Windows, `path` MUST be a [volume GUID path][naming-a-volume]. + + * On POSIX platforms, `path` is either an absolute path or a relative path to the bundle. + For example, with a bundle at `/to/bundle` and a root filesystem at `/to/bundle/rootfs`, the `path` value can be either `/to/bundle/rootfs` or `rootfs`. + The value SHOULD be the conventional `rootfs`. + + A directory MUST exist at the path declared by the field. + +* **`readonly`** (bool, OPTIONAL) If true then the root filesystem MUST be read-only inside the container, defaults to false. + * On Windows, this field MUST be omitted or false. + +### Example (POSIX platforms) + +```json +"root": { + "path": "rootfs", + "readonly": true +} +``` + +### Example (Windows) + +```json +"root": { + "path": "\\\\?\\Volume{ec84d99e-3f02-11e7-ac6c-00155d7682cf}\\" +} +``` + +## Mounts + +**`mounts`** (array of objects, OPTIONAL) specifies additional mounts beyond [`root`](#root). + The runtime MUST mount entries in the listed order. + For Linux, the parameters are as documented in [mount(2)][mount.2] system call man page. + For Solaris, the mount entry corresponds to the 'fs' resource in the [zonecfg(1M)][zonecfg.1m] man page. + +* **`destination`** (string, REQUIRED) Destination of mount point: path inside container. + This value MUST be an absolute path. + * Windows: one mount destination MUST NOT be nested within another mount (e.g., c:\\foo and c:\\foo\\bar). + * Solaris: corresponds to "dir" of the fs resource in [zonecfg(1M)][zonecfg.1m]. +* **`source`** (string, OPTIONAL) A device name, but can also be a directory name or a dummy. + Path values are either absolute or relative to the bundle. + * Windows: a local directory on the filesystem of the container host. UNC paths and mapped drives are not supported. + * Solaris: corresponds to "special" of the fs resource in [zonecfg(1M)][zonecfg.1m]. +* **`options`** (array of strings, OPTIONAL) Mount options of the filesystem to be used. + * Linux: supported options are listed in the [mount(8)][mount.8] man page. + Note both [filesystem-independent][mount.8-filesystem-independent] and [filesystem-specific][mount.8-filesystem-specific] options are listed. + * Solaris: corresponds to "options" of the fs resource in [zonecfg(1M)][zonecfg.1m]. + * Windows: runtimes MUST support `ro`, mounting the filesystem read-only when `ro` is given. + +### Example (Windows) + +```json +"mounts": [ + { + "destination": "C:\\folder-inside-container", + "source": "C:\\folder-on-host", + "options": ["ro"] + } +] +``` + +### POSIX-platform Mounts + +For POSIX platforms the `mounts` structure has the following fields: + +* **`type`** (string, OPTIONAL) The type of the filesystem to be mounted. + * Linux: filesystem types supported by the kernel as listed in */proc/filesystems* (e.g., "minix", "ext2", "ext3", "jfs", "xfs", "reiserfs", "msdos", "proc", "nfs", "iso9660"). + * Solaris: corresponds to "type" of the fs resource in [zonecfg(1M)][zonecfg.1m]. + +### Example (Linux) + +```json +"mounts": [ + { + "destination": "/tmp", + "type": "tmpfs", + "source": "tmpfs", + "options": ["nosuid","strictatime","mode=755","size=65536k"] + }, + { + "destination": "/data", + "type": "bind", + "source": "/volumes/testing", + "options": ["rbind","rw"] + } +] +``` + +### Example (Solaris) + +```json +"mounts": [ + { + "destination": "/opt/local", + "type": "lofs", + "source": "/usr/local", + "options": ["ro","nodevices"] + }, + { + "destination": "/opt/sfw", + "type": "lofs", + "source": "/opt/sfw" + } +] +``` + +## Process + +**`process`** (object, OPTIONAL) specifies the container process. + This property is REQUIRED when [`start`](runtime.md#start) is called. + +* **`terminal`** (bool, OPTIONAL) specifies whether a terminal is attached to the process, defaults to false. + As an example, if set to true on Linux a pseudoterminal pair is allocated for the process and the pseudoterminal slave is duplicated on the process's [standard streams][stdin.3]. +* **`consoleSize`** (object, OPTIONAL) specifies the console size in characters of the terminal. + Runtimes MUST ignore `consoleSize` if `terminal` is `false` or unset. + * **`height`** (uint, REQUIRED) + * **`width`** (uint, REQUIRED) +* **`cwd`** (string, REQUIRED) is the working directory that will be set for the executable. + This value MUST be an absolute path. +* **`env`** (array of strings, OPTIONAL) with the same semantics as [IEEE Std 1003.1-2008's `environ`][ieee-1003.1-2008-xbd-c8.1]. +* **`args`** (array of strings, REQUIRED) with similar semantics to [IEEE Std 1003.1-2008 `execvp`'s *argv*][ieee-1003.1-2008-functions-exec]. + This specification extends the IEEE standard in that at least one entry is REQUIRED, and that entry is used with the same semantics as `execvp`'s *file*. + +### POSIX process + +For systems that support POSIX rlimits (for example Linux and Solaris), the `process` object supports the following process-specific properties: + +* **`rlimits`** (array of objects, OPTIONAL) allows setting resource limits for the process. + Each entry has the following structure: + + * **`type`** (string, REQUIRED) the platform resource being limited. + * Linux: valid values are defined in the [`getrlimit(2)`][getrlimit.2] man page, such as `RLIMIT_MSGQUEUE`. + * Solaris: valid values are defined in the [`getrlimit(3)`][getrlimit.3] man page, such as `RLIMIT_CORE`. + + The runtime MUST [generate an error](runtime.md#errors) for any values which cannot be mapped to a relevant kernel interface. + For each entry in `rlimits`, a [`getrlimit(3)`][getrlimit.3] on `type` MUST succeed. + For the following properties, `rlim` refers to the status returned by the `getrlimit(3)` call. + + * **`soft`** (uint64, REQUIRED) the value of the limit enforced for the corresponding resource. + `rlim.rlim_cur` MUST match the configured value. + * **`hard`** (uint64, REQUIRED) the ceiling for the soft limit that could be set by an unprivileged process. + `rlim.rlim_max` MUST match the configured value. + Only a privileged process (e.g. one with the `CAP_SYS_RESOURCE` capability) can raise a hard limit. + + If `rlimits` contains duplicated entries with same `type`, the runtime MUST [generate an error](runtime.md#errors). + +### Linux Process + +For Linux-based systems, the `process` object supports the following process-specific properties. + +* **`apparmorProfile`** (string, OPTIONAL) specifies the name of the AppArmor profile for the process. + For more information about AppArmor, see [AppArmor documentation][apparmor]. +* **`capabilities`** (object, OPTIONAL) is an object containing arrays that specifies the sets of capabilities for the process. + Valid values are defined in the [capabilities(7)][capabilities.7] man page, such as `CAP_CHOWN`. + Any value which cannot be mapped to a relevant kernel interface MUST cause an error. + `capabilities` contains the following properties: + + * **`effective`** (array of strings, OPTIONAL) the `effective` field is an array of effective capabilities that are kept for the process. + * **`bounding`** (array of strings, OPTIONAL) the `bounding` field is an array of bounding capabilities that are kept for the process. + * **`inheritable`** (array of strings, OPTIONAL) the `inheritable` field is an array of inheritable capabilities that are kept for the process. + * **`permitted`** (array of strings, OPTIONAL) the `permitted` field is an array of permitted capabilities that are kept for the process. + * **`ambient`** (array of strings, OPTIONAL) the `ambient` field is an array of ambient capabilities that are kept for the process. +* **`noNewPrivileges`** (bool, OPTIONAL) setting `noNewPrivileges` to true prevents the process from gaining additional privileges. + As an example, the [`no_new_privs`][no-new-privs] article in the kernel documentation has information on how this is achieved using a `prctl` system call on Linux. +* **`oomScoreAdj`** *(int, OPTIONAL)* adjusts the oom-killer score in `[pid]/oom_score_adj` for the process's `[pid]` in a [proc pseudo-filesystem][proc_2]. + If `oomScoreAdj` is set, the runtime MUST set `oom_score_adj` to the given value. + If `oomScoreAdj` is not set, the runtime MUST NOT change the value of `oom_score_adj`. + + This is a per-process setting, where as [`disableOOMKiller`](config-linux.md#memory) is scoped for a memory cgroup. + For more information on how these two settings work together, see [the memory cgroup documentation section 10. OOM Contol][cgroup-v1-memory_2]. +* **`selinuxLabel`** (string, OPTIONAL) specifies the SELinux label for the process. + For more information about SELinux, see [SELinux documentation][selinux]. + +### User + +The user for the process is a platform-specific structure that allows specific control over which user the process runs as. + +#### POSIX-platform User + +For POSIX platforms the `user` structure has the following fields: + +* **`uid`** (int, REQUIRED) specifies the user ID in the [container namespace](glossary.md#container-namespace). +* **`gid`** (int, REQUIRED) specifies the group ID in the [container namespace](glossary.md#container-namespace). +* **`additionalGids`** (array of ints, OPTIONAL) specifies additional group IDs in the [container namespace](glossary.md#container-namespace) to be added to the process. + +_Note: symbolic name for uid and gid, such as uname and gname respectively, are left to upper levels to derive (i.e. `/etc/passwd` parsing, NSS, etc)_ + +### Example (Linux) + +```json +"process": { + "terminal": true, + "consoleSize": { + "height": 25, + "width": 80 + }, + "user": { + "uid": 1, + "gid": 1, + "additionalGids": [5, 6] + }, + "env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "TERM=xterm" + ], + "cwd": "/root", + "args": [ + "sh" + ], + "apparmorProfile": "acme_secure_profile", + "selinuxLabel": "system_u:system_r:svirt_lxc_net_t:s0:c124,c675", + "noNewPrivileges": true, + "capabilities": { + "bounding": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "permitted": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "inheritable": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "effective": [ + "CAP_AUDIT_WRITE", + "CAP_KILL" + ], + "ambient": [ + "CAP_NET_BIND_SERVICE" + ] + }, + "rlimits": [ + { + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024 + } + ] +} +``` +### Example (Solaris) + +```json +"process": { + "terminal": true, + "consoleSize": { + "height": 25, + "width": 80 + }, + "user": { + "uid": 1, + "gid": 1, + "additionalGids": [2, 8] + }, + "env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "TERM=xterm" + ], + "cwd": "/root", + "args": [ + "/usr/bin/bash" + ] +} +``` + +#### Windows User + +For Windows based systems the user structure has the following fields: + +* **`username`** (string, OPTIONAL) specifies the user name for the process. + +### Example (Windows) + +```json +"process": { + "terminal": true, + "user": { + "username": "containeradministrator" + }, + "env": [ + "VARIABLE=1" + ], + "cwd": "c:\\foo", + "args": [ + "someapp.exe", + ] +} +``` + + +## Hostname + +* **`hostname`** (string, OPTIONAL) specifies the container's hostname as seen by processes running inside the container. + On Linux, for example, this will change the hostname in the [container](glossary.md#container-namespace) [UTS namespace][uts-namespace.7]. + Depending on your [namespace configuration](config-linux.md#namespaces), the container UTS namespace may be the [runtime](glossary.md#runtime-namespace) [UTS namespace][uts-namespace.7]. + +### Example + +```json +"hostname": "mrsdalloway" +``` + +## Platform-specific configuration + +* **`linux`** (object, OPTIONAL) [Linux-specific configuration](config-linux.md). + This MAY be set if the target platform of this spec is `linux`. +* **`windows`** (object, OPTIONAL) [Windows-specific configuration](config-windows.md). + This MUST be set if the target platform of this spec is `windows`. +* **`solaris`** (object, OPTIONAL) [Solaris-specific configuration](config-solaris.md). + This MAY be set if the target platform of this spec is `solaris`. +* **`vm`** (object, OPTIONAL) [Virtual-machine-specific configuration](config-vm.md). + This MAY be set if the target platform and architecture of this spec support hardware virtualization. + +### Example (Linux) + +```json +{ + "linux": { + "namespaces": [ + { + "type": "pid" + } + ] + } +} +``` + +## POSIX-platform Hooks + +For POSIX platforms, the configuration structure supports `hooks` for configuring custom actions related to the [lifecycle](runtime.md#lifecycle) of the container. + +* **`hooks`** (object, OPTIONAL) MAY contain any of the following properties: + * **`prestart`** (array of objects, OPTIONAL) is an array of [pre-start hooks](#prestart). + Entries in the array contain the following properties: + * **`path`** (string, REQUIRED) with similar semantics to [IEEE Std 1003.1-2008 `execv`'s *path*][ieee-1003.1-2008-functions-exec]. + This specification extends the IEEE standard in that **`path`** MUST be absolute. + Runtimes MUST resolve this value in the [runtime namespace](glossary.md#runtime-namespace). + * **`args`** (array of strings, OPTIONAL) with the same semantics as [IEEE Std 1003.1-2008 `execv`'s *argv*][ieee-1003.1-2008-functions-exec]. + * **`env`** (array of strings, OPTIONAL) with the same semantics as [IEEE Std 1003.1-2008's `environ`][ieee-1003.1-2008-xbd-c8.1]. + * **`timeout`** (int, OPTIONAL) is the number of seconds before aborting the hook. + If set, `timeout` MUST be greater than zero. + * **`poststart`** (array of objects, OPTIONAL) is an array of [post-start hooks](#poststart). + Entries in the array have the same schema as pre-start entries. + * **`poststop`** (array of objects, OPTIONAL) is an array of [post-stop hooks](#poststop). + Entries in the array have the same schema as pre-start entries. + +Hooks allow users to specify programs to run before or after various lifecycle events. +Hooks MUST be called in the listed order. +Hooks MUST be executed in the [runtime namespace](glossary.md#runtime-namespace). +The [state](runtime.md#state) of the container MUST be passed to hooks over stdin so that they may do work appropriate to the current state of the container. + +### Prestart + +The pre-start hooks MUST be called after the [`start`](runtime.md#start) operation is called but [before the user-specified program command is executed](runtime.md#lifecycle). +On Linux, for example, they are called after the container namespaces are created, so they provide an opportunity to customize the container (e.g. the network namespace could be specified in this hook). + +### Poststart + +The post-start hooks MUST be called [after the user-specified process is executed](runtime.md#lifecycle) but before the [`start`](runtime.md#start) operation returns. +For example, this hook can notify the user that the container process is spawned. + +### Poststop + +The post-stop hooks MUST be called [after the container is deleted](runtime.md#lifecycle) but before the [`delete`](runtime.md#delete) operation returns. +Cleanup or debugging functions are examples of such a hook. + +### Example + +```json + "hooks": { + "prestart": [ + { + "path": "/usr/bin/fix-mounts", + "args": ["fix-mounts", "arg1", "arg2"], + "env": [ "key1=value1"] + }, + { + "path": "/usr/bin/setup-network" + } + ], + "poststart": [ + { + "path": "/usr/bin/notify-start", + "timeout": 5 + } + ], + "poststop": [ + { + "path": "/usr/sbin/cleanup.sh", + "args": ["cleanup.sh", "-f"] + } + ] + } +``` + +## Annotations + +**`annotations`** (object, OPTIONAL) contains arbitrary metadata for the container. + This information MAY be structured or unstructured. + Annotations MUST be a key-value map. + If there are no annotations then this property MAY either be absent or an empty map. + + Keys MUST be strings. + Keys MUST NOT be an empty string. + Keys SHOULD be named using a reverse domain notation - e.g. `com.example.myKey`. + Keys using the `org.opencontainers` namespace are reserved and MUST NOT be used by subsequent specifications. + Implementations that are reading/processing this configuration file MUST NOT generate an error if they encounter an unknown annotation key. + + Values MUST be strings. + Values MAY be an empty string. + +```json +"annotations": { + "com.example.gpu-cores": "2" +} +``` + +## Extensibility + +Runtimes that are reading or processing this configuration file MUST NOT generate an error if they encounter an unknown property. +Instead they MUST ignore unknown properties. + +## Valid values + +Runtimes that are reading or processing this configuration file MUST generate an error when invalid or unsupported values are encountered. +Unless support for a valid value is explicitly required, runtimes MAY choose which subset of the valid values it will support. + +## Configuration Schema Example + +Here is a full example `config.json` for reference. + +```json +{ + "ociVersion": "0.5.0-dev", + "process": { + "terminal": true, + "user": { + "uid": 1, + "gid": 1, + "additionalGids": [ + 5, + 6 + ] + }, + "args": [ + "sh" + ], + "env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "TERM=xterm" + ], + "cwd": "/", + "capabilities": { + "bounding": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "permitted": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "inheritable": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "effective": [ + "CAP_AUDIT_WRITE", + "CAP_KILL" + ], + "ambient": [ + "CAP_NET_BIND_SERVICE" + ] + }, + "rlimits": [ + { + "type": "RLIMIT_CORE", + "hard": 1024, + "soft": 1024 + }, + { + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024 + } + ], + "apparmorProfile": "acme_secure_profile", + "oomScoreAdj": 100, + "selinuxLabel": "system_u:system_r:svirt_lxc_net_t:s0:c124,c675", + "noNewPrivileges": true + }, + "root": { + "path": "rootfs", + "readonly": true + }, + "hostname": "slartibartfast", + "mounts": [ + { + "destination": "/proc", + "type": "proc", + "source": "proc" + }, + { + "destination": "/dev", + "type": "tmpfs", + "source": "tmpfs", + "options": [ + "nosuid", + "strictatime", + "mode=755", + "size=65536k" + ] + }, + { + "destination": "/dev/pts", + "type": "devpts", + "source": "devpts", + "options": [ + "nosuid", + "noexec", + "newinstance", + "ptmxmode=0666", + "mode=0620", + "gid=5" + ] + }, + { + "destination": "/dev/shm", + "type": "tmpfs", + "source": "shm", + "options": [ + "nosuid", + "noexec", + "nodev", + "mode=1777", + "size=65536k" + ] + }, + { + "destination": "/dev/mqueue", + "type": "mqueue", + "source": "mqueue", + "options": [ + "nosuid", + "noexec", + "nodev" + ] + }, + { + "destination": "/sys", + "type": "sysfs", + "source": "sysfs", + "options": [ + "nosuid", + "noexec", + "nodev" + ] + }, + { + "destination": "/sys/fs/cgroup", + "type": "cgroup", + "source": "cgroup", + "options": [ + "nosuid", + "noexec", + "nodev", + "relatime", + "ro" + ] + } + ], + "hooks": { + "prestart": [ + { + "path": "/usr/bin/fix-mounts", + "args": [ + "fix-mounts", + "arg1", + "arg2" + ], + "env": [ + "key1=value1" + ] + }, + { + "path": "/usr/bin/setup-network" + } + ], + "poststart": [ + { + "path": "/usr/bin/notify-start", + "timeout": 5 + } + ], + "poststop": [ + { + "path": "/usr/sbin/cleanup.sh", + "args": [ + "cleanup.sh", + "-f" + ] + } + ] + }, + "linux": { + "devices": [ + { + "path": "/dev/fuse", + "type": "c", + "major": 10, + "minor": 229, + "fileMode": 438, + "uid": 0, + "gid": 0 + }, + { + "path": "/dev/sda", + "type": "b", + "major": 8, + "minor": 0, + "fileMode": 432, + "uid": 0, + "gid": 0 + } + ], + "uidMappings": [ + { + "containerID": 0, + "hostID": 1000, + "size": 32000 + } + ], + "gidMappings": [ + { + "containerID": 0, + "hostID": 1000, + "size": 32000 + } + ], + "sysctl": { + "net.ipv4.ip_forward": "1", + "net.core.somaxconn": "256" + }, + "cgroupsPath": "/myRuntime/myContainer", + "resources": { + "network": { + "classID": 1048577, + "priorities": [ + { + "name": "eth0", + "priority": 500 + }, + { + "name": "eth1", + "priority": 1000 + } + ] + }, + "pids": { + "limit": 32771 + }, + "hugepageLimits": [ + { + "pageSize": "2MB", + "limit": 9223372036854772000 + } + ], + "memory": { + "limit": 536870912, + "reservation": 536870912, + "swap": 536870912, + "kernel": -1, + "kernelTCP": -1, + "swappiness": 0, + "disableOOMKiller": false + }, + "cpu": { + "shares": 1024, + "quota": 1000000, + "period": 500000, + "realtimeRuntime": 950000, + "realtimePeriod": 1000000, + "cpus": "2-3", + "mems": "0-7" + }, + "devices": [ + { + "allow": false, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 10, + "minor": 229, + "access": "rw" + }, + { + "allow": true, + "type": "b", + "major": 8, + "minor": 0, + "access": "r" + } + ], + "blockIO": { + "weight": 10, + "leafWeight": 10, + "weightDevice": [ + { + "major": 8, + "minor": 0, + "weight": 500, + "leafWeight": 300 + }, + { + "major": 8, + "minor": 16, + "weight": 500 + } + ], + "throttleReadBpsDevice": [ + { + "major": 8, + "minor": 0, + "rate": 600 + } + ], + "throttleWriteIOPSDevice": [ + { + "major": 8, + "minor": 16, + "rate": 300 + } + ] + } + }, + "rootfsPropagation": "slave", + "seccomp": { + "defaultAction": "SCMP_ACT_ALLOW", + "architectures": [ + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ], + "syscalls": [ + { + "names": [ + "getcwd", + "chmod" + ], + "action": "SCMP_ACT_ERRNO" + } + ] + }, + "namespaces": [ + { + "type": "pid" + }, + { + "type": "network" + }, + { + "type": "ipc" + }, + { + "type": "uts" + }, + { + "type": "mount" + }, + { + "type": "user" + }, + { + "type": "cgroup" + } + ], + "maskedPaths": [ + "/proc/kcore", + "/proc/latency_stats", + "/proc/timer_stats", + "/proc/sched_debug" + ], + "readonlyPaths": [ + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ], + "mountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c715,c811" + }, + "annotations": { + "com.example.key1": "value1", + "com.example.key2": "value2" + } +} +``` + + +[apparmor]: https://wiki.ubuntu.com/AppArmor +[cgroup-v1-memory_2]: https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt +[selinux]:http://selinuxproject.org/page/Main_Page +[no-new-privs]: https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt +[proc_2]: https://www.kernel.org/doc/Documentation/filesystems/proc.txt +[semver-v2.0.0]: http://semver.org/spec/v2.0.0.html +[ieee-1003.1-2008-xbd-c8.1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_01 +[ieee-1003.1-2008-functions-exec]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html +[naming-a-volume]: https://aka.ms/nb3hqb + +[capabilities.7]: http://man7.org/linux/man-pages/man7/capabilities.7.html +[mount.2]: http://man7.org/linux/man-pages/man2/mount.2.html +[mount.8]: http://man7.org/linux/man-pages/man8/mount.8.html +[mount.8-filesystem-independent]: http://man7.org/linux/man-pages/man8/mount.8.html#FILESYSTEM-INDEPENDENT_MOUNT_OPTIONS +[mount.8-filesystem-specific]: http://man7.org/linux/man-pages/man8/mount.8.html#FILESYSTEM-SPECIFIC_MOUNT_OPTIONS +[getrlimit.2]: http://man7.org/linux/man-pages/man2/getrlimit.2.html +[getrlimit.3]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html +[stdin.3]: http://man7.org/linux/man-pages/man3/stdin.3.html +[uts-namespace.7]: http://man7.org/linux/man-pages/man7/namespaces.7.html +[zonecfg.1m]: http://docs.oracle.com/cd/E86824_01/html/E54764/zonecfg-1m.html diff --git a/vendor/github.com/opencontainers/runtime-spec/glossary.md b/vendor/github.com/opencontainers/runtime-spec/glossary.md new file mode 100644 index 0000000000..0c81fad8bd --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/glossary.md @@ -0,0 +1,38 @@ +# Glossary + +## Bundle + +A [directory structure](bundle.md) that is written ahead of time, distributed, and used to seed the runtime for creating a [container](#container) and launching a process within it. + +## Configuration + +The [`config.json`](config.md) file in a [bundle](#bundle) which defines the intended [container](#container) and container process. + +## Container + +An environment for executing processes with configurable isolation and resource limitations. +For example, namespaces, resource limits, and mounts are all part of the container environment. + +## Container namespace + +On Linux,the [namespaces][namespaces.7] in which the [configured process](config.md#process) executes. + +## JSON + +All configuration [JSON][] MUST be encoded in [UTF-8][]. +JSON objects MUST NOT include duplicate names. +The order of entries in JSON objects is not significant. + +## Runtime + +An implementation of this specification. +It reads the [configuration files](#configuration) from a [bundle](#bundle), uses that information to create a [container](#container), launches a process inside the container, and performs other [lifecycle actions](runtime.md). + +## Runtime namespace + +On Linux, the namespaces from which new [container namespaces](#container-namespace) are [created](config-linux.md#namespaces) and from which some configured resources are accessed. + +[JSON]: https://tools.ietf.org/html/rfc8259 +[UTF-8]: http://www.unicode.org/versions/Unicode8.0.0/ch03.pdf + +[namespaces.7]: http://man7.org/linux/man-pages/man7/namespaces.7.html diff --git a/vendor/github.com/opencontainers/runtime-spec/implementations.md b/vendor/github.com/opencontainers/runtime-spec/implementations.md new file mode 100644 index 0000000000..e25ca14c13 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/implementations.md @@ -0,0 +1,35 @@ +# Implementations + +The following sections link to associated projects, some of which are maintained by the OCI and some of which are maintained by external organizations. +If you know of any associated projects that are not listed here, please file a pull request adding a link to that project. + +## Runtime (Container) + +* [opencontainers/runc][runc] - Reference implementation of OCI runtime +* [projectatomic/bwrap-oci][bwrap-oci] - Convert the OCI spec file to a command line for [bubblewrap][bubblewrap] +* [giuseppe/crun][crun] - Runtime implementation in C + +## Runtime (Virtual Machine) + +* [hyperhq/runv][runv] - Hypervisor-based runtime for OCI +* [clearcontainers/runtime][cc-runtime] - Hypervisor-based OCI runtime utilising [virtcontainers][virtcontainers] by Intel®. +* [google/gvisor][gvisor] - gVisor is a user-space kernel, contains runsc to run sandboxed containers. + +## Testing & Tools + +* [kunalkushwaha/octool][octool] - A config linter and validator. +* [huawei-openlab/oct][oct] - Open Container Testing framework for OCI configuration and runtime +* [opencontainers/runtime-tools][runtime-tools] - A config generator and runtime/bundle testing framework. + + +[runc]: https://github.com/opencontainers/runc +[runv]: https://github.com/hyperhq/runv +[cc-runtime]: https://github.com/clearcontainers/runtime +[virtcontainers]: https://github.com/containers/virtcontainers +[octool]: https://github.com/kunalkushwaha/octool +[oct]: https://github.com/huawei-openlab/oct +[runtime-tools]: https://github.com/opencontainers/runtime-tools +[bwrap-oci]: https://github.com/projectatomic/bwrap-oci +[bubblewrap]: https://github.com/projectatomic/bubblewrap +[crun]: https://github.com/giuseppe/crun +[gvisor]: https://github.com/google/gvisor diff --git a/vendor/github.com/opencontainers/runtime-spec/meeting.ics b/vendor/github.com/opencontainers/runtime-spec/meeting.ics new file mode 100644 index 0000000000..4a0cc03b57 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/meeting.ics @@ -0,0 +1,39 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Open Containers Initiative//Developer Meeting//EN +BEGIN:VTIMEZONE +TZID:America/Los_Angeles +LAST-MODIFIED:20050809T050000Z +BEGIN:STANDARD +DTSTART:20071104T020000 +RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU +TZOFFSETFROM:-0700 +TZOFFSETTO:-0800 +TZNAME:PST +END:STANDARD +BEGIN:DAYLIGHT +DTSTART:20070311T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU +TZOFFSETFROM:-0800 +TZOFFSETTO:-0700 +TZNAME:PDT +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +UID:tdc-meeting@opencontainers.org +DTSTAMP:20171207T173000Z +DTSTART;TZID=America/Los_Angeles:20170906T140000 +RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1WE +RDATE;TZID=America/Los_Angeles:20180110T140000 +EXDATE;TZIP=America/Los_Angeles:20180103T140000 +DURATION:PT1H +SUMMARY:OCI TDC Meeting +DESCRIPTION;ALTREP="https://github.com/opencontainers/runtime-spec# + meetings":Open Containers Initiative Developer Meeting\n + https://github.com/opencontainers/runtime-spec#meetings\n + Web: https://www.uberconference.com/opencontainers\n + Audio-only: +1 415 968 0849 (no PIN needed) +LOCATION:https://www.uberconference.com/opencontainers +URL:https://github.com/opencontainers/runtime-spec/blob/master/meeting.ics +END:VEVENT +END:VCALENDAR diff --git a/vendor/github.com/opencontainers/runtime-spec/principles.md b/vendor/github.com/opencontainers/runtime-spec/principles.md new file mode 100644 index 0000000000..6c7696302e --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/principles.md @@ -0,0 +1,46 @@ +# The 5 principles of Standard Containers + +Define a unit of software delivery called a Standard Container. +The goal of a Standard Container is to encapsulate a software component and all its dependencies in a format that is self-describing and portable, so that any compliant runtime can run it without extra dependencies, regardless of the underlying machine and the contents of the container. + +The specification for Standard Containers defines: + +1. configuration file formats +2. a set of standard operations +3. an execution environment. + +A great analogy for this is the physical shipping container used by the transportation industry. +Shipping containers are a fundamental unit of delivery, they can be lifted, stacked, locked, loaded, unloaded and labelled. +Irrespective of their contents, by standardizing the container itself it allowed for a consistent, more streamlined and efficient set of processes to be defined. +For software Standard Containers offer similar functionality by being the fundamental, standardized, unit of delivery for a software package. + +## 1. Standard operations + +Standard Containers define a set of STANDARD OPERATIONS. +They can be created, started, and stopped using standard container tools; copied and snapshotted using standard filesystem tools; and downloaded and uploaded using standard network tools. + +## 2. Content-agnostic + +Standard Containers are CONTENT-AGNOSTIC: all standard operations have the same effect regardless of the contents. +They are started in the same way whether they contain a postgres database, a php application with its dependencies and application server, or Java build artifacts. + +## 3. Infrastructure-agnostic + +Standard Containers are INFRASTRUCTURE-AGNOSTIC: they can be run in any OCI supported infrastructure. +For example, a standard container can be bundled on a laptop, uploaded to cloud storage, downloaded, run and snapshotted by a build server at a fiber hotel in Virginia, uploaded to 10 staging servers in a home-made private cloud cluster, then sent to 30 production instances across 3 public cloud regions. + +## 4. Designed for automation + +Standard Containers are DESIGNED FOR AUTOMATION: because they offer the same standard operations regardless of content and infrastructure, Standard Containers, are extremely well-suited for automation. +In fact, you could say automation is their secret weapon. + +Many things that once required time-consuming and error-prone human effort can now be programmed. +Before Standard Containers, by the time a software component ran in production, it had been individually built, configured, bundled, documented, patched, vendored, templated, tweaked and instrumented by 10 different people on 10 different computers. +Builds failed, libraries conflicted, mirrors crashed, post-it notes were lost, logs were misplaced, cluster updates were half-broken. +The process was slow, inefficient and cost a fortune - and was entirely different depending on the language and infrastructure provider. + +## 5. Industrial-grade delivery + +Standard Containers make INDUSTRIAL-GRADE DELIVERY of software a reality. +Leveraging all of the properties listed above, Standard Containers are enabling large and small enterprises to streamline and automate their software delivery pipelines. +Whether it is in-house devOps flows, or external customer-based software delivery mechanisms, Standard Containers are changing the way the community thinks about software packaging and delivery. diff --git a/vendor/github.com/opencontainers/runtime-spec/project.md b/vendor/github.com/opencontainers/runtime-spec/project.md new file mode 100644 index 0000000000..3f8a09b9d4 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/project.md @@ -0,0 +1,12 @@ +# Project docs + +## Release Process + +* Increment version in [`specs-go/version.go`](specs-go/version.go) +* `git commit` version increment +* `git tag` the prior commit (preferably signed tag) +* `make docs` to produce PDF and HTML copies of the spec +* Make a [release][releases] for the version. Attach the produced docs. + + +[releases]: https://github.com/opencontainers/runtime-spec/releases diff --git a/vendor/github.com/opencontainers/runtime-spec/runtime-linux.md b/vendor/github.com/opencontainers/runtime-spec/runtime-linux.md new file mode 100644 index 0000000000..16c6dbebbd --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/runtime-linux.md @@ -0,0 +1,21 @@ +# Linux Runtime + +## File descriptors + +By default, only the `stdin`, `stdout` and `stderr` file descriptors are kept open for the application by the runtime. +The runtime MAY pass additional file descriptors to the application to support features such as [socket activation][socket-activated-containers]. +Some of the file descriptors MAY be redirected to `/dev/null` even though they are open. + +## Dev symbolic links + +While creating the container (step 2 in the [lifecycle](runtime.md#lifecycle)), runtimes MUST create the following symlinks if the source file exists after processing [`mounts`](config.md#mounts): + +| Source | Destination | +| --------------- | ----------- | +| /proc/self/fd | /dev/fd | +| /proc/self/fd/0 | /dev/stdin | +| /proc/self/fd/1 | /dev/stdout | +| /proc/self/fd/2 | /dev/stderr | + + +[socket-activated-containers]: http://0pointer.de/blog/projects/socket-activated-containers.html diff --git a/vendor/github.com/opencontainers/runtime-spec/runtime.md b/vendor/github.com/opencontainers/runtime-spec/runtime.md new file mode 100644 index 0000000000..d92088b069 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/runtime.md @@ -0,0 +1,140 @@ +# Runtime and Lifecycle + +## Scope of a Container + +The entity using a runtime to create a container MUST be able to use the operations defined in this specification against that same container. +Whether other entities using the same, or other, instance of the runtime can see that container is out of scope of this specification. + +## State + +The state of a container includes the following properties: + +* **`ociVersion`** (string, REQUIRED) is the OCI specification version used when creating the container. +* **`id`** (string, REQUIRED) is the container's ID. + This MUST be unique across all containers on this host. + There is no requirement that it be unique across hosts. +* **`status`** (string, REQUIRED) is the runtime state of the container. + The value MAY be one of: + + * `creating`: the container is being created (step 2 in the [lifecycle](#lifecycle)) + * `created`: the runtime has finished the [create operation](#create) (after step 2 in the [lifecycle](#lifecycle)), and the container process has neither exited nor executed the user-specified program + * `running`: the container process has executed the user-specified program but has not exited (after step 5 in the [lifecycle](#lifecycle)) + * `stopped`: the container process has exited (step 7 in the [lifecycle](#lifecycle)) + + Additional values MAY be defined by the runtime, however, they MUST be used to represent new runtime states not defined above. +* **`pid`** (int, REQUIRED when `status` is `created` or `running` on Linux, OPTIONAL on other platforms) is the ID of the container process, as seen by the host. +* **`bundle`** (string, REQUIRED) is the absolute path to the container's bundle directory. + This is provided so that consumers can find the container's configuration and root filesystem on the host. +* **`annotations`** (map, OPTIONAL) contains the list of annotations associated with the container. + If no annotations were provided then this property MAY either be absent or an empty map. + +The state MAY include additional properties. + +When serialized in JSON, the format MUST adhere to the following pattern: + +```json +{ + "ociVersion": "0.2.0", + "id": "oci-container1", + "status": "running", + "pid": 4422, + "bundle": "/containers/redis", + "annotations": { + "myKey": "myValue" + } +} +``` + +See [Query State](#query-state) for information on retrieving the state of a container. + +## Lifecycle +The lifecycle describes the timeline of events that happen from when a container is created to when it ceases to exist. + +1. OCI compliant runtime's [`create`](runtime.md#create) command is invoked with a reference to the location of the bundle and a unique identifier. +2. The container's runtime environment MUST be created according to the configuration in [`config.json`](config.md). + If the runtime is unable to create the environment specified in the [`config.json`](config.md), it MUST [generate an error](#errors). + While the resources requested in the [`config.json`](config.md) MUST be created, the user-specified program (from [`process`](config.md#process)) MUST NOT be run at this time. + Any updates to [`config.json`](config.md) after this step MUST NOT affect the container. +3. Runtime's [`start`](runtime.md#start) command is invoked with the unique identifier of the container. +4. The [prestart hooks](config.md#prestart) MUST be invoked by the runtime. + If any prestart hook fails, the runtime MUST [generate an error](#errors), stop the container, and continue the lifecycle at step 9. +5. The runtime MUST run the user-specified program, as specified by [`process`](config.md#process). +6. The [poststart hooks](config.md#poststart) MUST be invoked by the runtime. + If any poststart hook fails, the runtime MUST [log a warning](#warnings), but the remaining hooks and lifecycle continue as if the hook had succeeded. +7. The container process exits. + This MAY happen due to erroring out, exiting, crashing or the runtime's [`kill`](runtime.md#kill) operation being invoked. +8. Runtime's [`delete`](runtime.md#delete) command is invoked with the unique identifier of the container. +9. The container MUST be destroyed by undoing the steps performed during create phase (step 2). +10. The [poststop hooks](config.md#poststop) MUST be invoked by the runtime. + If any poststop hook fails, the runtime MUST [log a warning](#warnings), but the remaining hooks and lifecycle continue as if the hook had succeeded. + +## Errors + +In cases where the specified operation generates an error, this specification does not mandate how, or even if, that error is returned or exposed to the user of an implementation. +Unless otherwise stated, generating an error MUST leave the state of the environment as if the operation were never attempted - modulo any possible trivial ancillary changes such as logging. + +## Warnings + +In cases where the specified operation logs a warning, this specification does not mandate how, or even if, that warning is returned or exposed to the user of an implementation. +Unless otherwise stated, logging a warning does not change the flow of the operation; it MUST continue as if the warning had not been logged. + +## Operations + +Unless otherwise stated, runtimes MUST support the following operations. + +Note: these operations are not specifying any command-line APIs, and the parameters are inputs for general operations. + +### Query State + +`state ` + +This operation MUST [generate an error](#errors) if it is not provided the ID of a container. +Attempting to query a container that does not exist MUST [generate an error](#errors). +This operation MUST return the state of a container as specified in the [State](#state) section. + +### Create + +`create ` + +This operation MUST [generate an error](#errors) if it is not provided a path to the bundle and the container ID to associate with the container. +If the ID provided is not unique across all containers within the scope of the runtime, or is not valid in any other way, the implementation MUST [generate an error](#errors) and a new container MUST NOT be created. +This operation MUST create a new container. + +All of the properties configured in [`config.json`](config.md) except for [`process`](config.md#process) MUST be applied. +[`process.args`](config.md#process) MUST NOT be applied until triggered by the [`start`](#start) operation. +The remaining `process` properties MAY be applied by this operation. +If the runtime cannot apply a property as specified in the [configuration](config.md), it MUST [generate an error](#errors) and a new container MUST NOT be created. + +The runtime MAY validate `config.json` against this spec, either generically or with respect to the local system capabilities, before creating the container ([step 2](#lifecycle)). +Runtime callers who are interested in pre-create validation can run [bundle-validation tools](implementations.md#testing--tools) before invoking the create operation. + +Any changes made to the [`config.json`](config.md) file after this operation will not have an effect on the container. + +### Start +`start ` + +This operation MUST [generate an error](#errors) if it is not provided the container ID. +Attempting to `start` a container that is not [`created`](#state) MUST have no effect on the container and MUST [generate an error](#errors). +This operation MUST run the user-specified program as specified by [`process`](config.md#process). +This operation MUST generate an error if `process` was not set. + +### Kill +`kill ` + +This operation MUST [generate an error](#errors) if it is not provided the container ID. +Attempting to send a signal to a container that is neither [`created` nor `running`](#state) MUST have no effect on the container and MUST [generate an error](#errors). +This operation MUST send the specified signal to the container process. + +### Delete +`delete ` + +This operation MUST [generate an error](#errors) if it is not provided the container ID. +Attempting to `delete` a container that is not [`stopped`](#state) MUST have no effect on the container and MUST [generate an error](#errors). +Deleting a container MUST delete the resources that were created during the `create` step. +Note that resources associated with the container, but not created by this container, MUST NOT be deleted. +Once a container is deleted its ID MAY be used by a subsequent container. + + +## Hooks +Many of the operations specified in this specification have "hooks" that allow for additional actions to be taken before or after each operation. +See [runtime configuration for hooks](./config.md#posix-platform-hooks) for more information. diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/Makefile b/vendor/github.com/opencontainers/runtime-spec/schema/Makefile new file mode 100644 index 0000000000..ac8c8d2471 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/Makefile @@ -0,0 +1,50 @@ +GOOD_TESTS = $(wildcard test/good/*.json) +BAD_TESTS = $(wildcard test/bad/*.json) + +default: validate + +help: + @echo "Usage: make [target]" + @echo + @echo " * 'fmt' - format the json with indentation" + @echo " * 'help' - show this help information" + @echo " * 'validate' - build the validation tool" + +fmt: + find . -name '*.json' -exec bash -c 'jq --indent 4 -M . {} > xx && mv xx {} || echo "skipping invalid {}"' \; + +.PHONY: validate +validate: validate.go + go get -d ./... + go build ./validate.go + +test: validate $(TESTS) + for TYPE in $$(ls test); \ + do \ + echo "testing $${TYPE}"; \ + for FILE in $$(ls "test/$${TYPE}/good"); \ + do \ + echo " testing test/$${TYPE}/good/$${FILE}"; \ + if ./validate "$${TYPE}-schema.json" "test/$${TYPE}/good/$${FILE}" ; \ + then \ + echo " received expected validation success" ; \ + else \ + echo " received unexpected validation failure" ; \ + exit 1; \ + fi \ + done; \ + for FILE in $$(ls "test/$${TYPE}/bad"); \ + do \ + echo " testing test/$${TYPE}/bad/$${FILE}"; \ + if ./validate "$${TYPE}-schema.json" "test/$${TYPE}/bad/$${FILE}" ; \ + then \ + echo " received unexpected validation success" ; \ + exit 1; \ + else \ + echo " received expected validation failure" ; \ + fi \ + done; \ + done + +clean: + rm -f validate diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/README.md b/vendor/github.com/opencontainers/runtime-spec/schema/README.md new file mode 100644 index 0000000000..95f3c549ef --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/README.md @@ -0,0 +1,47 @@ +# JSON schema + +## Overview + +This directory contains the [JSON Schema](http://json-schema.org/) for validating JSON covered by this specification. + +The layout of the files is as follows: + +* [config-schema.json](config-schema.json) - the primary entrypoint for the [configuration](../config.md) schema +* [config-linux.json](config-linux.json) - the [Linux-specific configuration sub-structure](../config-linux.md) +* [config-solaris.json](config-solaris.json) - the [Solaris-specific configuration sub-structure](../config-solaris.md) +* [config-windows.json](config-windows.json) - the [Windows-specific configuration sub-structure](../config-windows.md) +* [state-schema.json](state-schema.json) - the primary entrypoint for the [state JSON](../runtime.md#state) schema +* [defs.json](defs.json) - definitions for general types +* [defs-linux.json](defs-linux.json) - definitions for Linux-specific types +* [validate.go](validate.go) - validation utility source code + + +## Utility + +There is also included a simple utility for facilitating validation. +To build it: + +```bash +export GOPATH=`mktemp -d` +go get -d ./... +go build ./validate.go +rm -rf $GOPATH +``` + +Or you can just use make command to create the utility: + +```bash +make validate +``` + +Then use it like: + +```bash +./validate config-schema.json /config.json +``` + +Or like: + +```bash +./validate https://raw.githubusercontent.com/opencontainers/runtime-spec/v1.0.0/schema/schema.json /config.json +``` diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/config-linux.json b/vendor/github.com/opencontainers/runtime-spec/schema/config-linux.json new file mode 100644 index 0000000000..5a3fd50e13 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/config-linux.json @@ -0,0 +1,238 @@ +{ + "linux": { + "description": "Linux platform-specific configurations", + "type": "object", + "properties": { + "devices": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/Device" + } + }, + "uidMappings": { + "type": "array", + "items": { + "$ref": "defs.json#/definitions/IDMapping" + } + }, + "gidMappings": { + "type": "array", + "items": { + "$ref": "defs.json#/definitions/IDMapping" + } + }, + "namespaces": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "defs-linux.json#/definitions/NamespaceReference" + } + ] + } + }, + "resources": { + "type": "object", + "properties": { + "devices": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/DeviceCgroup" + } + }, + "pids": { + "type": "object", + "properties": { + "limit": { + "$ref": "defs.json#/definitions/int64" + } + }, + "required": [ + "limit" + ] + }, + "blockIO": { + "type": "object", + "properties": { + "weight": { + "$ref": "defs-linux.json#/definitions/weight" + }, + "leafWeight": { + "$ref": "defs-linux.json#/definitions/weight" + }, + "throttleReadBpsDevice": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" + } + }, + "throttleWriteBpsDevice": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" + } + }, + "throttleReadIOPSDevice": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" + } + }, + "throttleWriteIOPSDevice": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" + } + }, + "weightDevice": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/blockIODeviceWeight" + } + } + } + }, + "cpu": { + "type": "object", + "properties": { + "cpus": { + "type": "string" + }, + "mems": { + "type": "string" + }, + "period": { + "$ref": "defs.json#/definitions/uint64" + }, + "quota": { + "$ref": "defs.json#/definitions/int64" + }, + "realtimePeriod": { + "$ref": "defs.json#/definitions/uint64" + }, + "realtimeRuntime": { + "$ref": "defs.json#/definitions/int64" + }, + "shares": { + "$ref": "defs.json#/definitions/uint64" + } + } + }, + "hugepageLimits": { + "type": "array", + "items": { + "type": "object", + "properties": { + "pageSize": { + "type": "string" + }, + "limit": { + "$ref": "defs.json#/definitions/uint64" + } + }, + "required": [ + "pageSize", + "limit" + ] + } + }, + "memory": { + "type": "object", + "properties": { + "kernel": { + "$ref": "defs.json#/definitions/int64" + }, + "kernelTCP": { + "$ref": "defs.json#/definitions/int64" + }, + "limit": { + "$ref": "defs.json#/definitions/int64" + }, + "reservation": { + "$ref": "defs.json#/definitions/int64" + }, + "swap": { + "$ref": "defs.json#/definitions/int64" + }, + "swappiness": { + "$ref": "defs.json#/definitions/uint64" + }, + "disableOOMKiller": { + "type": "boolean" + } + } + }, + "network": { + "type": "object", + "properties": { + "classID": { + "$ref": "defs.json#/definitions/uint32" + }, + "priorities": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/NetworkInterfacePriority" + } + } + } + }, + "rdma": { + "type": "object", + "additionalProperties": { + "$ref": "defs-linux.json#/definitions/Rdma" + } + } + } + }, + "cgroupsPath": { + "type": "string" + }, + "rootfsPropagation": { + "$ref": "defs-linux.json#/definitions/RootfsPropagation" + }, + "seccomp": { + "type": "object", + "properties": { + "defaultAction": { + "$ref": "defs-linux.json#/definitions/SeccompAction" + }, + "architectures": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/SeccompArch" + } + }, + "syscalls": { + "type": "array", + "items": { + "$ref": "defs-linux.json#/definitions/Syscall" + } + } + }, + "required": [ + "defaultAction" + ] + }, + "sysctl": { + "$ref": "defs.json#/definitions/mapStringString" + }, + "maskedPaths": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "readonlyPaths": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "mountLabel": { + "type": "string" + }, + "intelRdt": { + "type": "object", + "properties": { + "l3CacheSchema": { + "type": "string" + } + } + } + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/config-schema.json b/vendor/github.com/opencontainers/runtime-spec/schema/config-schema.json new file mode 100644 index 0000000000..f90bd4b7d6 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/config-schema.json @@ -0,0 +1,174 @@ +{ + "description": "Open Container Initiative Runtime Specification Container Configuration Schema", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "ociVersion": { + "$ref": "defs.json#/definitions/ociVersion" + }, + "hooks": { + "type": "object", + "properties": { + "prestart": { + "$ref": "defs.json#/definitions/ArrayOfHooks" + }, + "poststart": { + "$ref": "defs.json#/definitions/ArrayOfHooks" + }, + "poststop": { + "$ref": "defs.json#/definitions/ArrayOfHooks" + } + } + }, + "annotations": { + "$ref": "defs.json#/definitions/annotations" + }, + "hostname": { + "type": "string" + }, + "mounts": { + "type": "array", + "items": { + "$ref": "defs.json#/definitions/Mount" + } + }, + "root": { + "description": "Configures the container's root filesystem.", + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "$ref": "defs.json#/definitions/FilePath" + }, + "readonly": { + "type": "boolean" + } + } + }, + "process": { + "type": "object", + "required": [ + "cwd", + "args" + ], + "properties": { + "args": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "consoleSize": { + "type": "object", + "required": [ + "height", + "width" + ], + "properties": { + "height": { + "$ref": "defs.json#/definitions/uint64" + }, + "width": { + "$ref": "defs.json#/definitions/uint64" + } + } + }, + "cwd": { + "type": "string" + }, + "env": { + "$ref": "defs.json#/definitions/Env" + }, + "terminal": { + "type": "boolean" + }, + "user": { + "type": "object", + "properties": { + "uid": { + "$ref": "defs.json#/definitions/UID" + }, + "gid": { + "$ref": "defs.json#/definitions/GID" + }, + "additionalGids": { + "$ref": "defs.json#/definitions/ArrayOfGIDs" + }, + "username": { + "type": "string" + } + } + }, + "capabilities": { + "type": "object", + "properties": { + "bounding": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "permitted": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "effective": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "inheritable": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "ambient": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + } + } + }, + "apparmorProfile": { + "type": "string" + }, + "oomScoreAdj": { + "type": "integer" + }, + "selinuxLabel": { + "type": "string" + }, + "noNewPrivileges": { + "type": "boolean" + }, + "rlimits": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "soft", + "hard" + ], + "properties": { + "hard": { + "$ref": "defs.json#/definitions/uint64" + }, + "soft": { + "$ref": "defs.json#/definitions/uint64" + }, + "type": { + "type": "string", + "pattern": "^RLIMIT_[A-Z]+$" + } + } + } + } + } + }, + "linux": { + "$ref": "config-linux.json#/linux" + }, + "solaris": { + "$ref": "config-solaris.json#/solaris" + }, + "windows": { + "$ref": "config-windows.json#/windows" + }, + "vm": { + "$ref": "config-vm.json#/vm" + } + }, + "required": [ + "ociVersion" + ] +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/config-solaris.json b/vendor/github.com/opencontainers/runtime-spec/schema/config-solaris.json new file mode 100644 index 0000000000..be9f4d22b5 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/config-solaris.json @@ -0,0 +1,65 @@ +{ + "solaris": { + "description": "Solaris platform-specific configurations", + "type": "object", + "properties": { + "milestone": { + "type": "string" + }, + "limitpriv": { + "type": "string" + }, + "maxShmMemory": { + "type": "string" + }, + "cappedCPU": { + "type": "object", + "properties": { + "ncpus": { + "type": "string" + } + } + }, + "cappedMemory": { + "type": "object", + "properties": { + "physical": { + "type": "string" + }, + "swap": { + "type": "string" + } + } + }, + "anet": { + "type": "array", + "items": { + "type": "object", + "properties": { + "linkname": { + "type": "string" + }, + "lowerLink": { + "type": "string" + }, + "allowedAddress": { + "type": "string" + }, + "configureAllowedAddress": { + "type": "string" + }, + "defrouter": { + "type": "string" + }, + "macAddress": { + "type": "string" + }, + "linkProtection": { + "type": "string" + } + } + } + } + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/config-vm.json b/vendor/github.com/opencontainers/runtime-spec/schema/config-vm.json new file mode 100644 index 0000000000..6b1fb4baf1 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/config-vm.json @@ -0,0 +1,60 @@ +{ + "vm": { + "description": "configuration for virtual-machine-based containers", + "type": "object", + "required": [ + "kernel" + ], + "properties": { + "hypervisor": { + "description": "hypervisor config used by VM-based containers", + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "$ref": "defs.json#/definitions/FilePath" + }, + "parameters": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + } + } + }, + "kernel": { + "description": "kernel config used by VM-based containers", + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "$ref": "defs.json#/definitions/FilePath" + }, + "parameters": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "initrd": { + "$ref": "defs.json#/definitions/FilePath" + } + } + }, + "image": { + "description": "root image config used by VM-based containers", + "type": "object", + "required": [ + "path", + "format" + ], + "properties": { + "path": { + "$ref": "defs.json#/definitions/FilePath" + }, + "format": { + "$ref": "defs-vm.json#/definitions/RootImageFormat" + } + } + } + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/config-windows.json b/vendor/github.com/opencontainers/runtime-spec/schema/config-windows.json new file mode 100644 index 0000000000..04d2cfa1a0 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/config-windows.json @@ -0,0 +1,93 @@ +{ + "windows": { + "description": "Windows platform-specific configurations", + "type": "object", + "properties": { + "layerFolders": { + "type": "array", + "items": { + "$ref": "defs.json#/definitions/FilePath" + }, + "minItems": 1 + }, + "resources": { + "type": "object", + "properties": { + "memory": { + "type": "object", + "properties": { + "limit": { + "$ref": "defs.json#/definitions/uint64" + } + } + }, + "cpu": { + "type": "object", + "properties": { + "count": { + "$ref": "defs.json#/definitions/uint64" + }, + "shares": { + "$ref": "defs.json#/definitions/uint16" + }, + "maximum": { + "$ref": "defs.json#/definitions/uint16" + } + } + }, + "storage": { + "type": "object", + "properties": { + "iops": { + "$ref": "defs.json#/definitions/uint64" + }, + "bps": { + "$ref": "defs.json#/definitions/uint64" + }, + "sandboxSize": { + "$ref": "defs.json#/definitions/uint64" + } + } + } + } + }, + "network": { + "type": "object", + "properties": { + "endpointList": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "allowUnqualifiedDNSQuery": { + "type": "boolean" + }, + "DNSSearchList": { + "$ref": "defs.json#/definitions/ArrayOfStrings" + }, + "networkSharedContainerName": { + "type": "string" + } + } + }, + "credentialSpec": { + "type": "object" + }, + "servicing": { + "type": "boolean" + }, + "ignoreFlushesDuringBoot": { + "type": "boolean" + }, + "hyperv": { + "type": "object", + "properties": { + "utilityVMPath": { + "type": "string" + } + } + } + }, + "required": [ + "layerFolders" + ] + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/defs-linux.json b/vendor/github.com/opencontainers/runtime-spec/schema/defs-linux.json new file mode 100644 index 0000000000..0735e6b893 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/defs-linux.json @@ -0,0 +1,281 @@ +{ + "definitions": { + "RootfsPropagation": { + "type": "string", + "enum": [ + "private", + "shared", + "slave", + "unbindable" + ] + }, + "SeccompArch": { + "type": "string", + "enum": [ + "SCMP_ARCH_X86", + "SCMP_ARCH_X86_64", + "SCMP_ARCH_X32", + "SCMP_ARCH_ARM", + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_MIPS", + "SCMP_ARCH_MIPS64", + "SCMP_ARCH_MIPS64N32", + "SCMP_ARCH_MIPSEL", + "SCMP_ARCH_MIPSEL64", + "SCMP_ARCH_MIPSEL64N32", + "SCMP_ARCH_PPC", + "SCMP_ARCH_PPC64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390", + "SCMP_ARCH_S390X", + "SCMP_ARCH_PARISC", + "SCMP_ARCH_PARISC64" + ] + }, + "SeccompAction": { + "type": "string", + "enum": [ + "SCMP_ACT_KILL", + "SCMP_ACT_TRAP", + "SCMP_ACT_ERRNO", + "SCMP_ACT_TRACE", + "SCMP_ACT_ALLOW" + ] + }, + "SeccompOperators": { + "type": "string", + "enum": [ + "SCMP_CMP_NE", + "SCMP_CMP_LT", + "SCMP_CMP_LE", + "SCMP_CMP_EQ", + "SCMP_CMP_GE", + "SCMP_CMP_GT", + "SCMP_CMP_MASKED_EQ" + ] + }, + "SyscallArg": { + "type": "object", + "properties": { + "index": { + "$ref": "defs.json#/definitions/uint32" + }, + "value": { + "$ref": "defs.json#/definitions/uint64" + }, + "valueTwo": { + "$ref": "defs.json#/definitions/uint64" + }, + "op": { + "$ref": "#/definitions/SeccompOperators" + } + }, + "required": [ + "index", + "value", + "op" + ] + }, + "Syscall": { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "action": { + "$ref": "#/definitions/SeccompAction" + }, + "args": { + "type": "array", + "items": { + "$ref": "#/definitions/SyscallArg" + } + } + }, + "required": [ + "names", + "action" + ] + }, + "Major": { + "description": "major device number", + "$ref": "defs.json#/definitions/int64" + }, + "Minor": { + "description": "minor device number", + "$ref": "defs.json#/definitions/int64" + }, + "FileMode": { + "description": "File permissions mode (typically an octal value)", + "type": "integer", + "minimum": 0, + "maximum": 512 + }, + "FileType": { + "description": "Type of a block or special character device", + "type": "string", + "pattern": "^[cbup]$" + }, + "Device": { + "type": "object", + "required": [ + "type", + "path" + ], + "properties": { + "type": { + "$ref": "#/definitions/FileType" + }, + "path": { + "$ref": "defs.json#/definitions/FilePath" + }, + "fileMode": { + "$ref": "#/definitions/FileMode" + }, + "major": { + "$ref": "#/definitions/Major" + }, + "minor": { + "$ref": "#/definitions/Minor" + }, + "uid": { + "$ref": "defs.json#/definitions/UID" + }, + "gid": { + "$ref": "defs.json#/definitions/GID" + } + } + }, + "weight": { + "type": "integer" + }, + "blockIODevice": { + "type": "object", + "properties": { + "major": { + "$ref": "#/definitions/Major" + }, + "minor": { + "$ref": "#/definitions/Minor" + } + }, + "required": [ + "major", + "minor" + ] + }, + "blockIODeviceWeight": { + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/blockIODevice" + }, + { + "type": "object", + "properties": { + "weight": { + "$ref": "#/definitions/weight" + }, + "leafWeight": { + "$ref": "#/definitions/weight" + } + } + } + ] + }, + "blockIODeviceThrottle": { + "allOf": [ + { + "$ref": "#/definitions/blockIODevice" + }, + { + "type": "object", + "properties": { + "rate": { + "$ref": "defs.json#/definitions/uint64" + } + } + } + ] + }, + "DeviceCgroup": { + "type": "object", + "properties": { + "allow": { + "type": "boolean" + }, + "type": { + "type": "string" + }, + "major": { + "$ref": "#/definitions/Major" + }, + "minor": { + "$ref": "#/definitions/Minor" + }, + "access": { + "type": "string" + } + }, + "required": [ + "allow" + ] + }, + "NetworkInterfacePriority": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "priority": { + "$ref": "defs.json#/definitions/uint32" + } + }, + "required": [ + "name", + "priority" + ] + }, + "Rdma": { + "type": "object", + "properties": { + "hcaHandles": { + "$ref": "defs.json#/definitions/uint32" + }, + "hcaObjects": { + "$ref": "defs.json#/definitions/uint32" + } + } + }, + "NamespaceType": { + "type": "string", + "enum": [ + "mount", + "pid", + "network", + "uts", + "ipc", + "user", + "cgroup" + ] + }, + "NamespaceReference": { + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/NamespaceType" + }, + "path": { + "$ref": "defs.json#/definitions/FilePath" + } + }, + "required": [ + "type" + ] + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/defs-vm.json b/vendor/github.com/opencontainers/runtime-spec/schema/defs-vm.json new file mode 100644 index 0000000000..4dae915065 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/defs-vm.json @@ -0,0 +1,14 @@ +{ + "definitions": { + "RootImageFormat": { + "type": "string", + "enum": [ + "raw", + "qcow2", + "vdi", + "vmdk", + "vhd" + ] + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/defs.json b/vendor/github.com/opencontainers/runtime-spec/schema/defs.json new file mode 100644 index 0000000000..c1533aede2 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/defs.json @@ -0,0 +1,155 @@ +{ + "description": "Definitions used throughout the Open Container Initiative Runtime Specification", + "definitions": { + "int8": { + "type": "integer", + "minimum": -128, + "maximum": 127 + }, + "int16": { + "type": "integer", + "minimum": -32768, + "maximum": 32767 + }, + "int32": { + "type": "integer", + "minimum": -2147483648, + "maximum": 2147483647 + }, + "int64": { + "type": "integer", + "minimum": -9223372036854776000, + "maximum": 9223372036854776000 + }, + "uint8": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "uint16": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "uint32": { + "type": "integer", + "minimum": 0, + "maximum": 4294967295 + }, + "uint64": { + "type": "integer", + "minimum": 0, + "maximum": 18446744073709552000 + }, + "percent": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "mapStringString": { + "type": "object", + "patternProperties": { + ".{1,}": { + "type": "string" + } + } + }, + "UID": { + "$ref": "#/definitions/uint32" + }, + "GID": { + "$ref": "#/definitions/uint32" + }, + "ArrayOfGIDs": { + "type": "array", + "items": { + "$ref": "#/definitions/GID" + } + }, + "ArrayOfStrings": { + "type": "array", + "items": { + "type": "string" + } + }, + "FilePath": { + "type": "string" + }, + "Env": { + "$ref": "#/definitions/ArrayOfStrings" + }, + "Hook": { + "type": "object", + "properties": { + "path": { + "$ref": "#/definitions/FilePath" + }, + "args": { + "$ref": "#/definitions/ArrayOfStrings" + }, + "env": { + "$ref": "#/definitions/Env" + }, + "timeout": { + "type": "integer", + "minimum": 1 + } + }, + "required": [ + "path" + ] + }, + "ArrayOfHooks": { + "type": "array", + "items": { + "$ref": "#/definitions/Hook" + } + }, + "IDMapping": { + "type": "object", + "properties": { + "containerID": { + "$ref": "#/definitions/uint32" + }, + "hostID": { + "$ref": "#/definitions/uint32" + }, + "size": { + "$ref": "#/definitions/uint32" + } + }, + "required": [ + "containerID", + "hostID", + "size" + ] + }, + "Mount": { + "type": "object", + "properties": { + "source": { + "$ref": "#/definitions/FilePath" + }, + "destination": { + "$ref": "#/definitions/FilePath" + }, + "options": { + "$ref": "#/definitions/ArrayOfStrings" + }, + "type": { + "type": "string" + } + }, + "required": [ + "destination" + ] + }, + "ociVersion": { + "description": "The version of Open Container Initiative Runtime Specification that the document complies with", + "type": "string" + }, + "annotations": { + "$ref": "#/definitions/mapStringString" + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/state-schema.json b/vendor/github.com/opencontainers/runtime-spec/schema/state-schema.json new file mode 100644 index 0000000000..8f8242950f --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/state-schema.json @@ -0,0 +1,39 @@ +{ + "description": "Open Container Runtime State Schema", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "ociVersion": { + "$ref": "defs.json#/definitions/ociVersion" + }, + "id": { + "description": "the container's ID", + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "creating", + "created", + "running", + "stopped" + ] + }, + "pid": { + "type": "integer", + "minimum": 0 + }, + "bundle": { + "type": "string" + }, + "annotations": { + "$ref": "defs.json#/definitions/annotations" + } + }, + "required": [ + "ociVersion", + "id", + "status", + "bundle" + ] +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/invalid-json.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/invalid-json.json new file mode 100644 index 0000000000..8e93528306 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/invalid-json.json @@ -0,0 +1 @@ +{] diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/linux-rdma.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/linux-rdma.json new file mode 100644 index 0000000000..5a7ac695dd --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/bad/linux-rdma.json @@ -0,0 +1,15 @@ +{ + "ociVersion": "1.0.0", + "root": { + "path": "rootfs" + }, + "linux": { + "resources": { + "rdma": { + "mlx5_1": { + "hcaHandles": "not a uint32" + } + } + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/linux-rdma.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/linux-rdma.json new file mode 100644 index 0000000000..e70ed53203 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/linux-rdma.json @@ -0,0 +1,22 @@ +{ + "ociVersion": "1.0.0", + "root": { + "path": "rootfs" + }, + "linux": { + "resources": { + "rdma": { + "mlx5_1": { + "hcaHandles": 3, + "hcaObjects": 10000 + }, + "mlx4_0": { + "hcaObjects": 1000 + }, + "rxe3": { + "hcaObjects": 10000 + } + } + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal-for-start.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal-for-start.json new file mode 100644 index 0000000000..766d2d3805 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal-for-start.json @@ -0,0 +1,16 @@ +{ + "ociVersion": "1.0.0", + "root": { + "path": "rootfs" + }, + "process": { + "cwd": "/", + "args": [ + "sh" + ], + "user": { + "uid": 0, + "gid": 0 + } + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal.json new file mode 100644 index 0000000000..e26e9d746d --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/minimal.json @@ -0,0 +1,6 @@ +{ + "ociVersion": "1.0.0", + "root": { + "path": "rootfs" + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/spec-example.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/spec-example.json new file mode 100644 index 0000000000..c1390c379b --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/config/good/spec-example.json @@ -0,0 +1,368 @@ +{ + "ociVersion": "0.5.0-dev", + "process": { + "terminal": true, + "user": { + "uid": 1, + "gid": 1, + "additionalGids": [ + 5, + 6 + ] + }, + "args": [ + "sh" + ], + "env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "TERM=xterm" + ], + "cwd": "/", + "capabilities": { + "bounding": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "permitted": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "inheritable": [ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE" + ], + "effective": [ + "CAP_AUDIT_WRITE", + "CAP_KILL" + ], + "ambient": [ + "CAP_NET_BIND_SERVICE" + ] + }, + "rlimits": [ + { + "type": "RLIMIT_CORE", + "hard": 1024, + "soft": 1024 + }, + { + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024 + } + ], + "apparmorProfile": "acme_secure_profile", + "selinuxLabel": "system_u:system_r:svirt_lxc_net_t:s0:c124,c675", + "noNewPrivileges": true + }, + "root": { + "path": "rootfs", + "readonly": true + }, + "hostname": "slartibartfast", + "mounts": [ + { + "destination": "/proc", + "type": "proc", + "source": "proc" + }, + { + "destination": "/dev", + "type": "tmpfs", + "source": "tmpfs", + "options": [ + "nosuid", + "strictatime", + "mode=755", + "size=65536k" + ] + }, + { + "destination": "/dev/pts", + "type": "devpts", + "source": "devpts", + "options": [ + "nosuid", + "noexec", + "newinstance", + "ptmxmode=0666", + "mode=0620", + "gid=5" + ] + }, + { + "destination": "/dev/shm", + "type": "tmpfs", + "source": "shm", + "options": [ + "nosuid", + "noexec", + "nodev", + "mode=1777", + "size=65536k" + ] + }, + { + "destination": "/dev/mqueue", + "type": "mqueue", + "source": "mqueue", + "options": [ + "nosuid", + "noexec", + "nodev" + ] + }, + { + "destination": "/sys", + "type": "sysfs", + "source": "sysfs", + "options": [ + "nosuid", + "noexec", + "nodev" + ] + }, + { + "destination": "/sys/fs/cgroup", + "type": "cgroup", + "source": "cgroup", + "options": [ + "nosuid", + "noexec", + "nodev", + "relatime", + "ro" + ] + } + ], + "hooks": { + "prestart": [ + { + "path": "/usr/bin/fix-mounts", + "args": [ + "fix-mounts", + "arg1", + "arg2" + ], + "env": [ + "key1=value1" + ] + }, + { + "path": "/usr/bin/setup-network" + } + ], + "poststart": [ + { + "path": "/usr/bin/notify-start", + "timeout": 5 + } + ], + "poststop": [ + { + "path": "/usr/sbin/cleanup.sh", + "args": [ + "cleanup.sh", + "-f" + ] + } + ] + }, + "linux": { + "devices": [ + { + "path": "/dev/fuse", + "type": "c", + "major": 10, + "minor": 229, + "fileMode": 438, + "uid": 0, + "gid": 0 + }, + { + "path": "/dev/sda", + "type": "b", + "major": 8, + "minor": 0, + "fileMode": 432, + "uid": 0, + "gid": 0 + } + ], + "uidMappings": [ + { + "containerID": 0, + "hostID": 1000, + "size": 32000 + } + ], + "gidMappings": [ + { + "containerID": 0, + "hostID": 1000, + "size": 32000 + } + ], + "sysctl": { + "net.ipv4.ip_forward": "1", + "net.core.somaxconn": "256" + }, + "cgroupsPath": "/myRuntime/myContainer", + "resources": { + "network": { + "classID": 1048577, + "priorities": [ + { + "name": "eth0", + "priority": 500 + }, + { + "name": "eth1", + "priority": 1000 + } + ] + }, + "pids": { + "limit": 32771 + }, + "hugepageLimits": [ + { + "pageSize": "2MB", + "limit": 9223372036854772000 + } + ], + "oomScoreAdj": 100, + "memory": { + "limit": 536870912, + "reservation": 536870912, + "swap": 536870912, + "kernel": -1, + "kernelTCP": -1, + "swappiness": 0, + "disableOOMKiller": false + }, + "cpu": { + "shares": 1024, + "quota": 1000000, + "period": 500000, + "realtimeRuntime": 950000, + "realtimePeriod": 1000000, + "cpus": "2-3", + "mems": "0-7" + }, + "devices": [ + { + "allow": false, + "access": "rwm" + }, + { + "allow": true, + "type": "c", + "major": 10, + "minor": 229, + "access": "rw" + }, + { + "allow": true, + "type": "b", + "major": 8, + "minor": 0, + "access": "r" + } + ], + "blockIO": { + "weight": 10, + "leafWeight": 10, + "weightDevice": [ + { + "major": 8, + "minor": 0, + "weight": 500, + "leafWeight": 300 + }, + { + "major": 8, + "minor": 16, + "weight": 500 + } + ], + "throttleReadBpsDevice": [ + { + "major": 8, + "minor": 0, + "rate": 600 + } + ], + "throttleWriteIOPSDevice": [ + { + "major": 8, + "minor": 16, + "rate": 300 + } + ] + } + }, + "rootfsPropagation": "slave", + "seccomp": { + "defaultAction": "SCMP_ACT_ALLOW", + "architectures": [ + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ], + "syscalls": [ + { + "names": [ + "getcwd", + "chmod" + ], + "action": "SCMP_ACT_ERRNO" + } + ] + }, + "namespaces": [ + { + "type": "pid" + }, + { + "type": "network" + }, + { + "type": "ipc" + }, + { + "type": "uts" + }, + { + "type": "mount" + }, + { + "type": "user" + }, + { + "type": "cgroup" + } + ], + "maskedPaths": [ + "/proc/kcore", + "/proc/latency_stats", + "/proc/timer_stats", + "/proc/sched_debug" + ], + "readonlyPaths": [ + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ], + "mountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c715,c811" + }, + "annotations": { + "com.example.key1": "value1", + "com.example.key2": "value2" + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/state/bad/invalid-json.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/state/bad/invalid-json.json new file mode 100644 index 0000000000..8e93528306 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/state/bad/invalid-json.json @@ -0,0 +1 @@ +{] diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/test/state/good/spec-example.json b/vendor/github.com/opencontainers/runtime-spec/schema/test/state/good/spec-example.json new file mode 100644 index 0000000000..a49faee566 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/test/state/good/spec-example.json @@ -0,0 +1,10 @@ +{ + "ociVersion": "0.2.0", + "id": "oci-container1", + "status": "running", + "pid": 4422, + "bundle": "/containers/redis", + "annotations": { + "myKey": "myValue" + } +} diff --git a/vendor/github.com/opencontainers/runtime-spec/schema/validate.go b/vendor/github.com/opencontainers/runtime-spec/schema/validate.go new file mode 100644 index 0000000000..847d205408 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/schema/validate.go @@ -0,0 +1,100 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/xeipuuv/gojsonschema" +) + +const usage = `Validate is used to check document with specified schema. +You can use validate in following ways: + + 1.specify document file as an argument + validate + + 2.pass document content through a pipe + cat | validate + + 3.input document content manually, ended with ctrl+d(or your self-defined EOF keys) + validate + [INPUT DOCUMENT CONTENT HERE] +` + +func main() { + nargs := len(os.Args[1:]) + if nargs == 0 || nargs > 2 { + fmt.Printf("ERROR: invalid arguments number\n\n%s\n", usage) + os.Exit(1) + } + + if os.Args[1] == "help" || + os.Args[1] == "--help" || + os.Args[1] == "-h" { + fmt.Printf("%s\n", usage) + os.Exit(1) + } + + schemaPath := os.Args[1] + if !strings.Contains(schemaPath, "://") { + var err error + schemaPath, err = formatFilePath(schemaPath) + if err != nil { + fmt.Printf("ERROR: invalid schema-file path: %s\n", err) + os.Exit(1) + } + schemaPath = "file://" + schemaPath + } + + schemaLoader := gojsonschema.NewReferenceLoader(schemaPath) + + var documentLoader gojsonschema.JSONLoader + + if nargs > 1 { + documentPath, err := formatFilePath(os.Args[2]) + if err != nil { + fmt.Printf("ERROR: invalid document-file path: %s\n", err) + os.Exit(1) + } + documentLoader = gojsonschema.NewReferenceLoader("file://" + documentPath) + } else { + documentBytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + documentString := string(documentBytes) + documentLoader = gojsonschema.NewStringLoader(documentString) + } + + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + if result.Valid() { + fmt.Printf("The document is valid\n") + } else { + fmt.Printf("The document is not valid. see errors :\n") + for _, desc := range result.Errors() { + fmt.Printf("- %s\n", desc) + } + os.Exit(1) + } +} + +func formatFilePath(path string) (string, error) { + if _, err := os.Stat(path); err != nil { + return "", err + } + + absPath, err := filepath.Abs(path) + if err != nil { + return "", err + } + return absPath, nil +} diff --git a/vendor/github.com/opencontainers/runtime-spec/spec.md b/vendor/github.com/opencontainers/runtime-spec/spec.md new file mode 100644 index 0000000000..684713adb1 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/spec.md @@ -0,0 +1,48 @@ +# Open Container Initiative Runtime Specification + +The [Open Container Initiative][oci] develops specifications for standards on Operating System process and application containers. + +# Abstract + +The Open Container Initiative Runtime Specification aims to specify the configuration, execution environment, and lifecycle of a container. + +A container's configuration is specified as the `config.json` for the supported platforms and details the fields that enable the creation of a container. +The execution environment is specified to ensure that applications running inside a container have a consistent environment between runtimes along with common actions defined for the container's lifecycle. + +# Platforms + +Platforms defined by this specification are: + +* `linux`: [runtime.md](runtime.md), [config.md](config.md), [config-linux.md](config-linux.md), and [runtime-linux.md](runtime-linux.md). +* `solaris`: [runtime.md](runtime.md), [config.md](config.md), and [config-solaris.md](config-solaris.md). +* `windows`: [runtime.md](runtime.md), [config.md](config.md), and [config-windows.md](config-windows.md). +* `vm`: [runtime.md](runtime.md), [config.md](config.md), and [config-vm.md](config-vm.md). + +# Table of Contents + +- [Introduction](spec.md) + - [Notational Conventions](#notational-conventions) + - [Container Principles](principles.md) +- [Filesystem Bundle](bundle.md) +- [Runtime and Lifecycle](runtime.md) + - [Linux-specific Runtime and Lifecycle](runtime-linux.md) +- [Configuration](config.md) + - [Linux-specific Configuration](config-linux.md) + - [Solaris-specific Configuration](config-solaris.md) + - [Windows-specific Configuration](config-windows.md) + - [Virtual-Machine-specific Configuration](config-vm.md) +- [Glossary](glossary.md) + +# Notational Conventions + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in [RFC 2119][rfc2119]. + +The key words "unspecified", "undefined", and "implementation-defined" are to be interpreted as described in the [rationale for the C99 standard][c99-unspecified]. + +An implementation is not compliant for a given CPU architecture if it fails to satisfy one or more of the MUST, REQUIRED, or SHALL requirements for the [platforms](#platforms) it implements. +An implementation is compliant for a given CPU architecture if it satisfies all the MUST, REQUIRED, and SHALL requirements for the [platforms](#platforms) it implements. + + +[c99-unspecified]: http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf#page=18 +[oci]: http://www.opencontainers.org +[rfc2119]: http://tools.ietf.org/html/rfc2119 diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go index f3f37d42df..c9e848db62 100644 --- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go @@ -4,7 +4,7 @@ import "os" // Spec is the base configuration for the container. type Spec struct { - // Version of the Open Container Runtime Specification with which the bundle complies. + // Version of the Open Container Initiative Runtime Specification with which the bundle complies. Version string `json:"ociVersion"` // Process configures the container process. Process *Process `json:"process,omitempty"` @@ -25,6 +25,8 @@ type Spec struct { Solaris *Solaris `json:"solaris,omitempty" platform:"solaris"` // Windows is platform-specific configuration for Windows based containers. Windows *Windows `json:"windows,omitempty" platform:"windows"` + // VM specifies configuration for virtual-machine-based containers. + VM *VM `json:"vm,omitempty" platform:"vm"` } // Process contains information to start a specific application inside the container. @@ -194,10 +196,10 @@ const ( // LinuxIDMapping specifies UID/GID mappings type LinuxIDMapping struct { - // HostID is the starting UID/GID on the host to be mapped to 'ContainerID' - HostID uint32 `json:"hostID"` // ContainerID is the starting UID/GID in the container ContainerID uint32 `json:"containerID"` + // HostID is the starting UID/GID on the host to be mapped to 'ContainerID' + HostID uint32 `json:"hostID"` // Size is the number of IDs to be mapped Size uint32 `json:"size"` } @@ -320,6 +322,14 @@ type LinuxNetwork struct { Priorities []LinuxInterfacePriority `json:"priorities,omitempty"` } +// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11) +type LinuxRdma struct { + // Maximum number of HCA handles that can be opened. Default is "no limit". + HcaHandles *uint32 `json:"hcaHandles,omitempty"` + // Maximum number of HCA objects that can be created. Default is "no limit". + HcaObjects *uint32 `json:"hcaObjects,omitempty"` +} + // LinuxResources has container runtime resource constraints type LinuxResources struct { // Devices configures the device whitelist. @@ -336,6 +346,10 @@ type LinuxResources struct { HugepageLimits []LinuxHugepageLimit `json:"hugepageLimits,omitempty"` // Network restriction configuration Network *LinuxNetwork `json:"network,omitempty"` + // Rdma resource restriction configuration. + // Limits are a set of key value pairs that define RDMA resource limits, + // where the key is device name and value is resource limits. + Rdma map[string]LinuxRdma `json:"rdma,omitempty"` } // LinuxDevice represents the mknod information for a Linux special device file @@ -487,6 +501,42 @@ type WindowsHyperV struct { UtilityVMPath string `json:"utilityVMPath,omitempty"` } +// VM contains information for virtual-machine-based containers. +type VM struct { + // Hypervisor specifies hypervisor-related configuration for virtual-machine-based containers. + Hypervisor VMHypervisor `json:"hypervisor,omitempty"` + // Kernel specifies kernel-related configuration for virtual-machine-based containers. + Kernel VMKernel `json:"kernel"` + // Image specifies guest image related configuration for virtual-machine-based containers. + Image VMImage `json:"image,omitempty"` +} + +// VMHypervisor contains information about the hypervisor to use for a virtual machine. +type VMHypervisor struct { + // Path is the host path to the hypervisor used to manage the virtual machine. + Path string `json:"path"` + // Parameters specifies parameters to pass to the hypervisor. + Parameters string `json:"parameters,omitempty"` +} + +// VMKernel contains information about the kernel to use for a virtual machine. +type VMKernel struct { + // Path is the host path to the kernel used to boot the virtual machine. + Path string `json:"path"` + // Parameters specifies parameters to pass to the kernel. + Parameters string `json:"parameters,omitempty"` + // InitRD is the host path to an initial ramdisk to be used by the kernel. + InitRD string `json:"initrd,omitempty"` +} + +// VMImage contains information about the virtual machine root image. +type VMImage struct { + // Path is the host path to the root image that the VM kernel would boot into. + Path string `json:"path"` + // Format is the root image format type (e.g. "qcow2", "raw", "vhd", etc). + Format string `json:"format"` +} + // LinuxSeccomp represents syscall restrictions type LinuxSeccomp struct { DefaultAction LinuxSeccompAction `json:"defaultAction"` diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go index 926ce66503..b920fc1b39 100644 --- a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go +++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go @@ -8,10 +8,10 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 0 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "" + VersionDev = "-dev" ) // Version is the specification version that the package types support. diff --git a/vendor/github.com/opencontainers/runtime-spec/style.md b/vendor/github.com/opencontainers/runtime-spec/style.md new file mode 100644 index 0000000000..1d42043e7c --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-spec/style.md @@ -0,0 +1,131 @@ +# Style and conventions + +## One sentence per line + +To keep consistency throughout the Markdown files in the Open Container spec all files should be formatted one sentence per line. +This fixes two things: it makes diffing easier with git and it resolves fights about line wrapping length. +For example, this paragraph will span three lines in the Markdown source. + +## Traditionally hex settings should use JSON integers, not JSON strings + +For example, [`"classID": 1048577`](config-linux.md#network) instead of `"classID": "0x100001"`. +The config JSON isn't enough of a UI to be worth jumping through string <-> integer hoops to support an 0x… form ([source][integer-over-hex]). + +## Constant names should keep redundant prefixes + +For example, `CAP_KILL` instead of `KILL` in [**`process.capabilities`**](config.md#process). +The redundancy reduction from removing the namespacing prefix is not useful enough to be worth trimming the upstream identifier ([source][keep-prefix]). + +## Optional settings should not have pointer Go types + +Because in many cases the Go default for the type is a no-op in the spec (sources [here][no-pointer-for-strings], [here][no-pointer-for-slices], and [here][no-pointer-for-boolean]). +The exceptions are entries where we need to distinguish between “not set” and “set to the Go default for that type” ([source][pointer-when-updates-require-changes]), and this decision should be made on a per-setting case. + +## Links + +Internal links should be [relative links][markdown-relative-links] when linking to content within the repository. +Internal links should be used inline. + +External links should be collected at the bottom of a markdown file and used as referenced links. +See 'Referenced Links' in this [markdown quick reference][markdown-quick-reference]. +The use of referenced links in the markdown body helps to keep files clean and organized. +This also facilitates updates of external link targets on a per-file basis. + +Referenced links should be kept in two alphabetically sorted sets, a general reference section followed by a man page section. +To keep Pandoc happy, duplicate naming of links within pages listed in the Makefile's `DOC_FILES` variable should be avoided by appending an `_N` to the link tagname, where `N` is some number not currently in use. +The organization and style of an existing reference section should be maintained unless it violates these style guidelines. + +An exception to these rules is when a URL is needed contextually, for example when showing an explicit link to the reader. + +## Examples + +### Anchoring + +For any given section that provides a notable example, it is ideal to have it denoted with [markdown headers][markdown-headers]. +The level of header should be such that it is a subheader of the header it is an example of. + +#### Example + +```markdown +## Some Topic + +### Some Subheader + +#### Further Subheader + +##### Example + +To use Further Subheader, ... + +### Example + +To use Some Topic, ... + +``` + +### Content + +Where necessary, the values in the example can be empty or unset, but accommodate with comments regarding this intention. + +Where feasible, the content and values used in an example should convey the fullest use of the data structures concerned. +Most commonly onlookers will intend to copy-and-paste a "working example". +If the intention of the example is to be a fully utilized example, rather than a copy-and-paste example, perhaps add a comment as such. + +```markdown +### Example +``` +```json +{ + "foo": null, + "bar": "" +} +``` + +**vs.** + +```markdown +### Example + +Following is a fully populated example (not necessarily for copy/paste use) +``` +```json +{ + "foo": [ + 1, + 2, + 3 + ], + "bar": "waffles", + "bif": { + "baz": "potatoes" + } +} +``` + +### Links + +The following is an example of different types of links. +This is shown as a complete markdown file, where the referenced links are at the bottom. + +```markdown +The specification repository's [glossary](glossary.md) is where readers can find definitions of commonly used terms. + +Readers may click through to the [Open Containers namespace][open-containers] on [GitHub][github]. + +The URL for the Open Containers link above is: https://github.com/opencontainers + + +[github]: https://github.com +[open-containers]: https://github.com/opencontainers +``` + + +[integer-over-hex]: https://github.com/opencontainers/runtime-spec/pull/267#r48360013 +[keep-prefix]: https://github.com/opencontainers/runtime-spec/pull/159#issuecomment-138728337 +[no-pointer-for-boolean]: https://github.com/opencontainers/runtime-spec/pull/290#r50296396 +[no-pointer-for-slices]: https://github.com/opencontainers/runtime-spec/pull/316#r50782982 +[no-pointer-for-strings]: https://github.com/opencontainers/runtime-spec/pull/653#issue-200439192 +[pointer-when-updates-require-changes]: https://github.com/opencontainers/runtime-spec/pull/317#r50932706 +[markdown-headers]: https://help.github.com/articles/basic-writing-and-formatting-syntax/#headings +[markdown-quick-reference]: https://en.support.wordpress.com/markdown-quick-reference +[markdown-relative-links]: https://help.github.com/articles/basic-writing-and-formatting-syntax/#relative-links