diff options
111 files changed, 75 insertions, 7257 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc549116d..c121ac416 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to CRI-O +# Contributing to Libpod We'd love to have you join the community! Below summarizes the processes that we follow. @@ -13,7 +13,7 @@ that we follow. ## Reporting Issues Before reporting an issue, check our backlog of -[open issues](https://github.com/kubernetes-incubator/cri-o/issues) +[open issues](https://github.com/projectatomic/libpod/issues) to see if someone else has already reported it. If so, feel free to add your scenario, or additional information, to the discussion. Or simply "subscribe" to it to be notified when it is updated. @@ -120,9 +120,9 @@ IRC group on `irc.freenode.net` called `cri-o` that has been setup. For discussions around issues/bugs and features, you can use the github -[issues](https://github.com/kubernetes-incubator/cri-o/issues) +[issues](https://github.com/projectatomic/libpod/issues) and -[PRs](https://github.com/kubernetes-incubator/cri-o/pulls) +[PRs](https://github.com/projectatomic/libpod/pulls) tracking system. <!-- diff --git a/Dockerfile b/Dockerfile index 607d5a860..548da0a1f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -112,6 +112,6 @@ RUN mkdir -p /etc/containers COPY test/policy.json /etc/containers/policy.json COPY test/redhat_sigstore.yaml /etc/containers/registries.d/registry.access.redhat.com.yaml -WORKDIR /go/src/github.com/kubernetes-incubator/cri-o +WORKDIR /go/src/github.com/projectatomic/libpod -ADD . /go/src/github.com/kubernetes-incubator/cri-o +ADD . /go/src/github.com/projectatomic/libpod @@ -1,6 +1,6 @@ GO ?= go EPOCH_TEST_COMMIT ?= 1cc5a27 -PROJECT := github.com/kubernetes-incubator/cri-o +PROJECT := github.com/projectatomic/libpod GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null) GIT_BRANCH_CLEAN := $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g") CRIO_IMAGE := crio_dev$(if $(GIT_BRANCH_CLEAN),:$(GIT_BRANCH_CLEAN)) @@ -17,7 +17,7 @@ BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions OCIUMOUNTINSTALLDIR=$(PREFIX)/share/oci-umount/oci-umount.d SELINUXOPT ?= $(shell test -x /usr/sbin/selinuxenabled && selinuxenabled && echo -Z) -PACKAGES ?= $(shell go list -tags "${BUILDTAGS}" ./... | grep -v github.com/kubernetes-incubator/cri-o/vendor) +PACKAGES ?= $(shell go list -tags "${BUILDTAGS}" ./... | grep -v github.com/projectatomic/libpod/vendor) COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true) GIT_COMMIT := $(if $(shell git status --porcelain --untracked-files=no),"${COMMIT_NO}-dirty","${COMMIT_NO}") diff --git a/cmd/kpod/common.go b/cmd/kpod/common.go index f77b3fd1e..338aee8ea 100644 --- a/cmd/kpod/common.go +++ b/cmd/kpod/common.go @@ -9,9 +9,8 @@ import ( is "github.com/containers/image/storage" "github.com/containers/storage" "github.com/fatih/camelcase" - "github.com/kubernetes-incubator/cri-o/libkpod" - "github.com/kubernetes-incubator/cri-o/libpod" - "github.com/kubernetes-incubator/cri-o/server" + "github.com/projectatomic/libpod/libkpod" + "github.com/projectatomic/libpod/libpod" "github.com/pkg/errors" "github.com/urfave/cli" ) @@ -20,6 +19,8 @@ var ( stores = make(map[storage.Store]struct{}) ) +const CrioConfigPath = "/etc/crio/crio.conf" + func getStore(c *libkpod.Config) (storage.Store, error) { options := storage.DefaultStoreOptions options.GraphRoot = c.Root @@ -65,8 +66,8 @@ func getConfig(c *cli.Context) (*libkpod.Config, error) { var configFile string if c.GlobalIsSet("config") { configFile = c.GlobalString("config") - } else if _, err := os.Stat(server.CrioConfigPath); err == nil { - configFile = server.CrioConfigPath + } else if _, err := os.Stat(CrioConfigPath); err == nil { + configFile = CrioConfigPath } // load and merge the configfile from the commandline or use // the default crio config file diff --git a/cmd/kpod/diff.go b/cmd/kpod/diff.go index c28bdfce6..fc2dc8ef8 100644 --- a/cmd/kpod/diff.go +++ b/cmd/kpod/diff.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/containers/storage/pkg/archive" - "github.com/kubernetes-incubator/cri-o/cmd/kpod/formats" + "github.com/projectatomic/libpod/cmd/kpod/formats" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/history.go b/cmd/kpod/history.go index dd0da38a6..ea91904ad 100644 --- a/cmd/kpod/history.go +++ b/cmd/kpod/history.go @@ -8,7 +8,7 @@ import ( "github.com/containers/image/types" units "github.com/docker/go-units" - "github.com/kubernetes-incubator/cri-o/cmd/kpod/formats" + "github.com/projectatomic/libpod/cmd/kpod/formats" "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/urfave/cli" diff --git a/cmd/kpod/images.go b/cmd/kpod/images.go index d7824ba3f..36727a897 100644 --- a/cmd/kpod/images.go +++ b/cmd/kpod/images.go @@ -9,9 +9,9 @@ import ( "github.com/containers/image/types" "github.com/containers/storage" "github.com/docker/go-units" - "github.com/kubernetes-incubator/cri-o/cmd/kpod/formats" - "github.com/kubernetes-incubator/cri-o/libpod" - "github.com/kubernetes-incubator/cri-o/libpod/common" + "github.com/projectatomic/libpod/cmd/kpod/formats" + "github.com/projectatomic/libpod/libpod" + "github.com/projectatomic/libpod/libpod/common" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/urfave/cli" diff --git a/cmd/kpod/info.go b/cmd/kpod/info.go index 22ca74c73..3c634ac9c 100644 --- a/cmd/kpod/info.go +++ b/cmd/kpod/info.go @@ -8,7 +8,7 @@ import ( "runtime" "github.com/docker/docker/pkg/system" - "github.com/kubernetes-incubator/cri-o/cmd/kpod/formats" + "github.com/projectatomic/libpod/cmd/kpod/formats" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/inspect.go b/cmd/kpod/inspect.go index 45e9d7e18..78439ed89 100644 --- a/cmd/kpod/inspect.go +++ b/cmd/kpod/inspect.go @@ -1,9 +1,9 @@ package main import ( - "github.com/kubernetes-incubator/cri-o/cmd/kpod/formats" - "github.com/kubernetes-incubator/cri-o/libkpod" - "github.com/kubernetes-incubator/cri-o/libpod/images" + "github.com/projectatomic/libpod/cmd/kpod/formats" + "github.com/projectatomic/libpod/libkpod" + "github.com/projectatomic/libpod/libpod/images" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/kill.go b/cmd/kpod/kill.go index 8a5500031..686305781 100644 --- a/cmd/kpod/kill.go +++ b/cmd/kpod/kill.go @@ -5,7 +5,7 @@ import ( "os" "github.com/docker/docker/pkg/signal" - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/load.go b/cmd/kpod/load.go index b1cff1e88..392ce08ac 100644 --- a/cmd/kpod/load.go +++ b/cmd/kpod/load.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "os" - "github.com/kubernetes-incubator/cri-o/libpod" + "github.com/projectatomic/libpod/libpod" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/login.go b/cmd/kpod/login.go index 17880f7a7..956de6d14 100644 --- a/cmd/kpod/login.go +++ b/cmd/kpod/login.go @@ -9,7 +9,7 @@ import ( "github.com/containers/image/docker" "github.com/containers/image/pkg/docker/config" - "github.com/kubernetes-incubator/cri-o/libpod/common" + "github.com/projectatomic/libpod/libpod/common" "github.com/pkg/errors" "github.com/urfave/cli" "golang.org/x/crypto/ssh/terminal" diff --git a/cmd/kpod/logout.go b/cmd/kpod/logout.go index 587346151..0b07f1a63 100644 --- a/cmd/kpod/logout.go +++ b/cmd/kpod/logout.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/containers/image/pkg/docker/config" - "github.com/kubernetes-incubator/cri-o/libpod/common" + "github.com/projectatomic/libpod/libpod/common" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/logs.go b/cmd/kpod/logs.go index 60be4792e..23c78688d 100644 --- a/cmd/kpod/logs.go +++ b/cmd/kpod/logs.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/mount.go b/cmd/kpod/mount.go index a711bedea..4a68621ac 100644 --- a/cmd/kpod/mount.go +++ b/cmd/kpod/mount.go @@ -4,7 +4,7 @@ import ( js "encoding/json" "fmt" - of "github.com/kubernetes-incubator/cri-o/cmd/kpod/formats" + of "github.com/projectatomic/libpod/cmd/kpod/formats" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/pause.go b/cmd/kpod/pause.go index 5a8229ebe..510aba424 100644 --- a/cmd/kpod/pause.go +++ b/cmd/kpod/pause.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" "os" diff --git a/cmd/kpod/ps.go b/cmd/kpod/ps.go index 76bc8b8b4..2e981bfaa 100644 --- a/cmd/kpod/ps.go +++ b/cmd/kpod/ps.go @@ -15,9 +15,9 @@ import ( "k8s.io/apimachinery/pkg/fields" - "github.com/kubernetes-incubator/cri-o/cmd/kpod/formats" - "github.com/kubernetes-incubator/cri-o/libkpod" - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/cmd/kpod/formats" + "github.com/projectatomic/libpod/libkpod" + "github.com/projectatomic/libpod/oci" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/pull.go b/cmd/kpod/pull.go index 738221279..662bb2faa 100644 --- a/cmd/kpod/pull.go +++ b/cmd/kpod/pull.go @@ -8,8 +8,8 @@ import ( "golang.org/x/crypto/ssh/terminal" "github.com/containers/image/types" - "github.com/kubernetes-incubator/cri-o/libpod" - "github.com/kubernetes-incubator/cri-o/libpod/common" + "github.com/projectatomic/libpod/libpod" + "github.com/projectatomic/libpod/libpod/common" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli" diff --git a/cmd/kpod/push.go b/cmd/kpod/push.go index 506d97f4a..518c1d8dc 100644 --- a/cmd/kpod/push.go +++ b/cmd/kpod/push.go @@ -7,8 +7,8 @@ import ( "github.com/containers/image/types" "github.com/containers/storage/pkg/archive" - "github.com/kubernetes-incubator/cri-o/libpod" - "github.com/kubernetes-incubator/cri-o/libpod/common" + "github.com/projectatomic/libpod/libpod" + "github.com/projectatomic/libpod/libpod/common" "github.com/pkg/errors" "github.com/urfave/cli" "golang.org/x/crypto/ssh/terminal" diff --git a/cmd/kpod/rename.go b/cmd/kpod/rename.go index b638856ed..68b9a6108 100644 --- a/cmd/kpod/rename.go +++ b/cmd/kpod/rename.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/rm.go b/cmd/kpod/rm.go index c40fa41c8..8f51befc9 100644 --- a/cmd/kpod/rm.go +++ b/cmd/kpod/rm.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" "golang.org/x/net/context" diff --git a/cmd/kpod/save.go b/cmd/kpod/save.go index cfe90a95e..55998fe4d 100644 --- a/cmd/kpod/save.go +++ b/cmd/kpod/save.go @@ -4,7 +4,7 @@ import ( "io" "os" - "github.com/kubernetes-incubator/cri-o/libpod" + "github.com/projectatomic/libpod/libpod" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli" diff --git a/cmd/kpod/stats.go b/cmd/kpod/stats.go index ac81212a1..8548354a9 100644 --- a/cmd/kpod/stats.go +++ b/cmd/kpod/stats.go @@ -11,8 +11,8 @@ import ( "github.com/docker/go-units" tm "github.com/buger/goterm" - "github.com/kubernetes-incubator/cri-o/libkpod" - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/libkpod" + "github.com/projectatomic/libpod/oci" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/stop.go b/cmd/kpod/stop.go index 279f7b762..68e4be472 100644 --- a/cmd/kpod/stop.go +++ b/cmd/kpod/stop.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" "golang.org/x/net/context" diff --git a/cmd/kpod/tag.go b/cmd/kpod/tag.go index b9c380607..b5853ec14 100644 --- a/cmd/kpod/tag.go +++ b/cmd/kpod/tag.go @@ -3,7 +3,7 @@ package main import ( "github.com/containers/image/docker/reference" "github.com/containers/storage" - "github.com/kubernetes-incubator/cri-o/libpod" + "github.com/projectatomic/libpod/libpod" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/cmd/kpod/unpause.go b/cmd/kpod/unpause.go index a7b7db20f..a17e70753 100644 --- a/cmd/kpod/unpause.go +++ b/cmd/kpod/unpause.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" "os" diff --git a/cmd/kpod/wait.go b/cmd/kpod/wait.go index b166e3306..7557bea49 100644 --- a/cmd/kpod/wait.go +++ b/cmd/kpod/wait.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/projectatomic/libpod/libkpod" "github.com/pkg/errors" "github.com/urfave/cli" ) diff --git a/contrib/rpm/Makefile b/contrib/rpm/Makefile deleted file mode 100644 index 24bbca28c..000000000 --- a/contrib/rpm/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -.PHONY: dist -dist: crio.spec - spectool -g crio.spec - -.PHONY: rpm -rpm: dist - rpmbuild --define "_sourcedir `pwd`" --define "_specdir `pwd`" \ - --define "_rpmdir `pwd`" --define "_srcrpmdir `pwd`" -ba crio.spec - -all: rpm - -clean: - rm -f *rpm *gz - rm -rf x86_64 diff --git a/contrib/rpm/crio.spec b/contrib/rpm/crio.spec deleted file mode 100644 index 3485fe371..000000000 --- a/contrib/rpm/crio.spec +++ /dev/null @@ -1,76 +0,0 @@ -%define debug_package %{nil} -%global provider github -%global provider_tld com -%global project kubernetes-incubator -%global repo cri-o -%global Name crio -# https://github.com/kubernetes-incubator/cri-o -%global provider_prefix %{provider}.%{provider_tld}/%{project}/%{repo} -%global import_path %{provider_prefix} -%global commit 8ba639952a95f2e24cc98987689138b67545576c -%global shortcommit %(c=%{commit}; echo ${c:0:7}) - -Name: %{Name} -Version: 0.0.1 -Release: 1.git%{shortcommit}%{?dist} -Summary: Kubelet Container Runtime Interface (CRI) for OCI runtimes. -Group: Applications/Text -License: Apache 2.0 -URL: https://%{provider_prefix} -Source0: https://%{provider_prefix}/archive/%{commit}/%{repo}-%{shortcommit}.tar.gz -Provides: %{repo} - -BuildRequires: golang-github-cpuguy83-go-md2man - -%description -The crio package provides an implementation of the -Kubelet Container Runtime Interface (CRI) using OCI conformant runtimes. - -crio provides following functionalities: - - Support multiple image formats including the existing Docker image format - Support for multiple means to download images including trust & image verification - Container image management (managing image layers, overlay filesystems, etc) - Container process lifecycle management - Monitoring and logging required to satisfy the CRI - Resource isolation as required by the CRI - -%prep -%setup -q -n %{repo}-%{commit} - -%build -make all - -%install -%make_install -%make_install install.systemd - -#define license tag if not already defined -%{!?_licensedir:%global license %doc} -%files -%{_bindir}/crio -%{_bindir}/crioctl -%{_mandir}/man5/crio.conf.5* -%{_mandir}/man8/crio.8* -%{_sysconfdir}/crio.conf -%{_sysconfdir}/seccomp.json -%dir /%{_libexecdir}/crio -/%{_libexecdir}/crio/conmon -/%{_libexecdir}/crio/pause -%{_unitdir}/crio.service -%doc README.md -%license LICENSE -%dir /usr/share/oci-umount/oci-umount.d -/usr/share/oci-umount/oci-umount.d/cri-umount.conf - - -%preun -%systemd_preun %{Name} - -%postun -%systemd_postun_with_restart %{Name} - -%changelog -* Mon Oct 31 2016 Dan Walsh <dwalsh@redhat.com> - 0.0.1 -- Initial RPM release - diff --git a/contrib/systemd/crio-shutdown.service b/contrib/systemd/crio-shutdown.service deleted file mode 100644 index 5651dd980..000000000 --- a/contrib/systemd/crio-shutdown.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Shutdown CRIO containers before shutting down the system -Wants=crio.service -After=crio.service -Documentation=man:crio(8) - -[Service] -Type=oneshot -ExecStart=/usr/bin/true -ExecStop=mkdir -p /var/lib/crio; touch /var/lib/crio/crio.shutdown -RemainAfterExit=yes - -[Install] -WantedBy=multi-user.target diff --git a/contrib/systemd/crio.service b/contrib/systemd/crio.service deleted file mode 100644 index 35d6d4273..000000000 --- a/contrib/systemd/crio.service +++ /dev/null @@ -1,24 +0,0 @@ -[Unit] -Description=Open Container Initiative Daemon -Documentation=https://github.com/kubernetes-incubator/cri-o -After=network-online.target - -[Service] -Type=notify -EnvironmentFile=-/etc/sysconfig/crio-storage -EnvironmentFile=-/etc/sysconfig/crio-network -Environment=GOTRACEBACK=crash -ExecStart=/usr/local/bin/crio \ - $CRIO_STORAGE_OPTIONS \ - $CRIO_NETWORK_OPTIONS -ExecReload=/bin/kill -s HUP $MAINPID -TasksMax=infinity -LimitNOFILE=1048576 -LimitNPROC=1048576 -LimitCORE=infinity -OOMScoreAdjust=-999 -TimeoutStartSec=0 -Restart=on-abnormal - -[Install] -WantedBy=multi-user.target diff --git a/contrib/test/integration/README.md b/contrib/test/integration/README.md deleted file mode 100644 index f13b8b925..000000000 --- a/contrib/test/integration/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Fedora and RHEL Integration and End-to-End Tests - -This directory contains playbooks to set up for and run the integration and -end-to-end tests for CRI-O on RHEL and Fedora hosts. Two entrypoints exist: - - - `main.yml`: sets up the machine and runs tests - - `results.yml`: gathers test output to `/tmp/artifacts` - -When running `main.yml`, three tags are present: - - - `setup`: run all tasks to set up the system for testing - - `e2e`: build CRI-O from source and run Kubernetes node E2Es - - `integration`: build CRI-O from source and run the local integration suite - -The playbooks assume the following things about your system: - - - on RHEL, the server and extras repos are configured and certs are present - - `ansible` is installed and the host is boot-strapped to allow `ansible` to run against it - - the `$GOPATH` is set and present for all shells (*e.g.* written in `/etc/environment`) - - CRI-O is checked out to the correct state at `${GOPATH}/src/github.com/kubernetes-incubator/cri-o` - - the user running the playbook has access to passwordless `sudo`
\ No newline at end of file diff --git a/contrib/test/integration/ansible.cfg b/contrib/test/integration/ansible.cfg deleted file mode 100644 index 92a13a5fb..000000000 --- a/contrib/test/integration/ansible.cfg +++ /dev/null @@ -1,359 +0,0 @@ -# config file for ansible -- http://ansible.com/ -# ============================================== - -# nearly all parameters can be overridden in ansible-playbook -# or with command line flags. ansible will read ANSIBLE_CONFIG, -# ansible.cfg in the current working directory, .ansible.cfg in -# the home directory or /etc/ansible/ansible.cfg, whichever it -# finds first - -[defaults] - -# some basic default values... - -#inventory = inventory -#library = /usr/share/my_modules/ -#remote_tmp = $HOME/.ansible/tmp -#local_tmp = .ansible/tmp -#forks = 5 -forks = 10 -#poll_interval = 15 -#sudo_user = root -#ask_sudo_pass = True -ask_sudo_pass = False -#ask_pass = True -ask_pass = False -#transport = smart -#remote_port = 22 -#module_lang = C -#module_set_locale = True - -# plays will gather facts by default, which contain information about -# the remote system. -# -# smart - gather by default, but don't regather if already gathered -# implicit - gather by default, turn off with gather_facts: False -# explicit - do not gather by default, must say gather_facts: True -#gathering = implicit -gathering = smart - -# by default retrieve all facts subsets -# all - gather all subsets -# network - gather min and network facts -# hardware - gather hardware facts (longest facts to retrieve) -# virtual - gather min and virtual facts -# facter - import facts from facter -# ohai - import facts from ohai -# You can combine them using comma (ex: network,virtual) -# You can negate them using ! (ex: !hardware,!facter,!ohai) -# A minimal set of facts is always gathered. -gather_subset = network - -# additional paths to search for roles in, colon separated -# N/B: This depends on how ansible is called -#roles_path = $WORKSPACE/kommandir_workspace/roles - -# uncomment this to disable SSH key host checking -#host_key_checking = False -host_key_checking = False - -# change the default callback -#stdout_callback = skippy -# enable additional callbacks -#callback_whitelist = timer, mail - -# Determine whether includes in tasks and handlers are "static" by -# default. As of 2.0, includes are dynamic by default. Setting these -# values to True will make includes behave more like they did in the -# 1.x versions. -task_includes_static = True -handler_includes_static = True - -# change this for alternative sudo implementations -#sudo_exe = sudo - -# What flags to pass to sudo -# WARNING: leaving out the defaults might create unexpected behaviours -#sudo_flags = -H -S -n - -# SSH timeout -#timeout = 10 - -# default user to use for playbooks if user is not specified -# (/usr/bin/ansible will use current user as default) -#remote_user = root -remote_user = root - -# logging is off by default unless this path is defined -# if so defined, consider logrotate -log_path = $ARTIFACTS/main.log - -# default module name for /usr/bin/ansible -#module_name = command - -# use this shell for commands executed under sudo -# you may need to change this to bin/bash in rare instances -# if sudo is constrained -# executable = /bin/sh - -# if inventory variables overlap, does the higher precedence one win -# or are hash values merged together? The default is 'replace' but -# this can also be set to 'merge'. -hash_behaviour = replace - -# by default, variables from roles will be visible in the global variable -# scope. To prevent this, the following option can be enabled, and only -# tasks and handlers within the role will see the variables there -private_role_vars = False - -# list any Jinja2 extensions to enable here: -#jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n - -# if set, always use this private key file for authentication, same as -# if passing --private-key to ansible or ansible-playbook -#private_key_file = /path/to/file - -# If set, configures the path to the Vault password file as an alternative to -# specifying --vault-password-file on the command line. -#vault_password_file = /path/to/vault_password_file - -# format of string {{ ansible_managed }} available within Jinja2 -# templates indicates to users editing templates files will be replaced. -# replacing {file}, {host} and {uid} and strftime codes with proper values. -#ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host} -# This short version is better used in templates as it won't flag the file as changed every run. -#ansible_managed = Ansible managed: {file} on {host} - -# by default, ansible-playbook will display "Skipping [host]" if it determines a task -# should not be run on a host. Set this to "False" if you don't want to see these "Skipping" -# messages. NOTE: the task header will still be shown regardless of whether or not the -# task is skipped. -#display_skipped_hosts = True -display_skipped_hosts = False - -# by default, if a task in a playbook does not include a name: field then -# ansible-playbook will construct a header that includes the task's action but -# not the task's args. This is a security feature because ansible cannot know -# if the *module* considers an argument to be no_log at the time that the -# header is printed. If your environment doesn't have a problem securing -# stdout from ansible-playbook (or you have manually specified no_log in your -# playbook on all of the tasks where you have secret information) then you can -# safely set this to True to get more informative messages. -display_args_to_stdout = False - -# by default (as of 1.3), Ansible will raise errors when attempting to dereference -# Jinja2 variables that are not set in templates or action lines. Uncomment this line -# to revert the behavior to pre-1.3. -#error_on_undefined_vars = False - -# by default (as of 1.6), Ansible may display warnings based on the configuration of the -# system running ansible itself. This may include warnings about 3rd party packages or -# other conditions that should be resolved if possible. -# to disable these warnings, set the following value to False: -system_warnings = False - -# by default (as of 1.4), Ansible may display deprecation warnings for language -# features that should no longer be used and will be removed in future versions. -# to disable these warnings, set the following value to False: -deprecation_warnings = False - -# (as of 1.8), Ansible can optionally warn when usage of the shell and -# command module appear to be simplified by using a default Ansible module -# instead. These warnings can be silenced by adjusting the following -# setting or adding warn=yes or warn=no to the end of the command line -# parameter string. This will for example suggest using the git module -# instead of shelling out to the git command. -command_warnings = False - - -# set plugin path directories here, separate with colons -#action_plugins = /usr/share/ansible/plugins/action -#callback_plugins = /usr/share/ansible/plugins/callback -#connection_plugins = /usr/share/ansible/plugins/connection -#lookup_plugins = /usr/share/ansible/plugins/lookup -#vars_plugins = /usr/share/ansible/plugins/vars -#filter_plugins = /usr/share/ansible/plugins/filter -#test_plugins = /usr/share/ansible/plugins/test -#strategy_plugins = /usr/share/ansible/plugins/strategy - -# Most callbacks shipped with Ansible are disabled by default -# and need to be whitelisted in your ansible.cfg file in order to function. -callback_whitelist = default - -# by default callbacks are not loaded for /bin/ansible, enable this if you -# want, for example, a notification or logging callback to also apply to -# /bin/ansible runs -#bin_ansible_callbacks = False - - -# don't like cows? that's unfortunate. -# set to 1 if you don't want cowsay support or export ANSIBLE_NOCOWS=1 -#nocows = 1 - -# set which cowsay stencil you'd like to use by default. When set to 'random', -# a random stencil will be selected for each task. The selection will be filtered -# against the `cow_whitelist` option below. -#cow_selection = default -#cow_selection = random - -# when using the 'random' option for cowsay, stencils will be restricted to this list. -# it should be formatted as a comma-separated list with no spaces between names. -# NOTE: line continuations here are for formatting purposes only, as the INI parser -# in python does not support them. -#cow_whitelist=bud-frogs,bunny,cheese,daemon,default,dragon,elephant-in-snake,elephant,eyes,\ -# hellokitty,kitty,luke-koala,meow,milk,moofasa,moose,ren,sheep,small,stegosaurus,\ -# stimpy,supermilker,three-eyes,turkey,turtle,tux,udder,vader-koala,vader,www - -# don't like colors either? -# set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1 -nocolor = 0 - -# if set to a persistent type (not 'memory', for example 'redis') fact values -# from previous runs in Ansible will be stored. This may be useful when -# wanting to use, for example, IP information from one group of servers -# without having to talk to them in the same playbook run to get their -# current IP information. -#fact_caching = memory - -# retry files -# When a playbook fails by default a .retry file will be created in ~/ -# You can disable this feature by setting retry_files_enabled to False -# and you can change the location of the files by setting retry_files_save_path - -#retry_files_enabled = False -retry_files_enabled = False - -# squash actions -# Ansible can optimise actions that call modules with list parameters -# when looping. Instead of calling the module once per with_ item, the -# module is called once with all items at once. Currently this only works -# under limited circumstances, and only with parameters named 'name'. -squash_actions = apk,apt,dnf,package,pacman,pkgng,yum,zypper - -# prevents logging of task data, off by default -#no_log = False - -# prevents logging of tasks, but only on the targets, data is still logged on the master/controller -no_target_syslog = True - -# controls whether Ansible will raise an error or warning if a task has no -# choice but to create world readable temporary files to execute a module on -# the remote machine. This option is False by default for security. Users may -# turn this on to have behaviour more like Ansible prior to 2.1.x. See -# https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user -# for more secure ways to fix this than enabling this option. -#allow_world_readable_tmpfiles = False - -# controls the compression level of variables sent to -# worker processes. At the default of 0, no compression -# is used. This value must be an integer from 0 to 9. -#var_compression_level = 9 - -# controls what compression method is used for new-style ansible modules when -# they are sent to the remote system. The compression types depend on having -# support compiled into both the controller's python and the client's python. -# The names should match with the python Zipfile compression types: -# * ZIP_STORED (no compression. available everywhere) -# * ZIP_DEFLATED (uses zlib, the default) -# These values may be set per host via the ansible_module_compression inventory -# variable -#module_compression = 'ZIP_DEFLATED' - -# This controls the cutoff point (in bytes) on --diff for files -# set to 0 for unlimited (RAM may suffer!). -#max_diff_size = 1048576 - -[privilege_escalation] -#become=True -#become_method=sudo -#become_user=root -become_user=root -#become_ask_pass=False - -[paramiko_connection] - -# uncomment this line to cause the paramiko connection plugin to not record new host -# keys encountered. Increases performance on new host additions. Setting works independently of the -# host key checking setting above. -#record_host_keys=False - -# by default, Ansible requests a pseudo-terminal for commands executed under sudo. Uncomment this -# line to disable this behaviour. -#pty=False - -[ssh_connection] - -# ssh arguments to use -# Leaving off ControlPersist will result in poor performance, so use -# paramiko on older platforms rather than removing it -ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o PreferredAuthentications=publickey -o ConnectTimeout=13 - -# The path to use for the ControlPath sockets. This defaults to -# "%(directory)s/ansible-ssh-%%h-%%p-%%r", however on some systems with -# very long hostnames or very long path names (caused by long user names or -# deeply nested home directories) this can exceed the character limit on -# file socket names (108 characters for most platforms). In that case, you -# may wish to shorten the string below. -# -# Example: -# control_path = %(directory)s/%%h-%%r -#control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r - -# Enabling pipelining reduces the number of SSH operations required to -# execute a module on the remote server. This can result in a significant -# performance improvement when enabled, however when using "sudo:" you must -# first disable 'requiretty' in /etc/sudoers -# -# By default, this option is disabled to preserve compatibility with -# sudoers configurations that have requiretty (the default on many distros). -# -#pipelining = False -pipelining=True - -# if True, make ansible use scp if the connection type is ssh -# (default is sftp) -#scp_if_ssh = True - -# if False, sftp will not use batch mode to transfer files. This may cause some -# types of file transfer failures impossible to catch however, and should -# only be disabled if your sftp version has problems with batch mode -#sftp_batch_mode = False - -[accelerate] -#accelerate_port = 5099 -#accelerate_timeout = 30 -#accelerate_connect_timeout = 5.0 - -# The daemon timeout is measured in minutes. This time is measured -# from the last activity to the accelerate daemon. -#accelerate_daemon_timeout = 30 - -# If set to yes, accelerate_multi_key will allow multiple -# private keys to be uploaded to it, though each user must -# have access to the system via SSH to add a new key. The default -# is "no". -#accelerate_multi_key = yes - -[selinux] -# file systems that require special treatment when dealing with security context -# the default behaviour that copies the existing context or uses the user default -# needs to be changed to use the file system dependent context. -#special_context_filesystems=nfs,vboxsf,fuse,ramfs - -# Set this to yes to allow libvirt_lxc connections to work without SELinux. -#libvirt_lxc_noseclabel = yes - -[colors] -#highlight = white -#verbose = blue -#warn = bright purple -#error = red -#debug = dark gray -#deprecate = purple -#skip = cyan -#unreachable = red -#ok = green -#changed = yellow -#diff_add = green -#diff_remove = red -#diff_lines = cyan diff --git a/contrib/test/integration/build/bats.yml b/contrib/test/integration/build/bats.yml deleted file mode 100644 index d4ea19c65..000000000 --- a/contrib/test/integration/build/bats.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- - -- name: clone bats source repo - git: - repo: "https://github.com/sstephenson/bats.git" - dest: "{{ ansible_env.GOPATH }}/src/github.com/sstephenson/bats" - -- name: install bats - command: "./install.sh /usr/local" - args: - chdir: "{{ ansible_env.GOPATH }}/src/github.com/sstephenson/bats" - -- name: link bats - file: - src: /usr/local/bin/bats - dest: /usr/bin/bats - state: link diff --git a/contrib/test/integration/build/cri-o.yml b/contrib/test/integration/build/cri-o.yml deleted file mode 100644 index fa025035c..000000000 --- a/contrib/test/integration/build/cri-o.yml +++ /dev/null @@ -1,79 +0,0 @@ ---- - -- name: stat the expected cri-o directory - stat: - path: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o" - register: dir_stat - -- name: expect cri-o to be cloned already - fail: - msg: "Expected cri-o to be cloned at {{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o but it wasn't!" - when: not dir_stat.stat.exists - -- name: install cri-o tools - make: - target: install.tools - chdir: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o" - -- name: build cri-o - make: - chdir: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o" - -- name: install cri-o - make: - target: install - chdir: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o" - -- name: install cri-o systemd files - make: - target: install.systemd - chdir: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o" - -- name: install cri-o config - make: - target: install.config - chdir: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o" - -- name: install configs - copy: - src: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o/{{ item.src }}" - dest: "{{ item.dest }}" - remote_src: yes - with_items: - - src: contrib/cni/10-crio-bridge.conf - dest: /etc/cni/net.d/10-crio-bridge.conf - - src: contrib/cni/99-loopback.conf - dest: /etc/cni/net.d/99-loopback.conf - - src: test/redhat_sigstore.yaml - dest: /etc/containers/registries.d/registry.access.redhat.com.yaml - -- name: run with overlay - replace: - regexp: 'storage_driver = ""' - replace: 'storage_driver = "overlay"' - name: /etc/crio/crio.conf - backup: yes - -- name: run with systemd cgroup manager - replace: - regexp: 'cgroup_manager = "cgroupfs"' - replace: 'cgroup_manager = "systemd"' - name: /etc/crio/crio.conf - backup: yes - -- name: add docker.io default registry - lineinfile: - dest: /etc/crio/crio.conf - line: '"docker.io"' - insertafter: 'registries = \[' - regexp: 'docker\.io' - state: present - -- name: add overlay storage opts on RHEL/CentOS - lineinfile: - dest: /etc/crio/crio.conf - line: '"overlay.override_kernel_check=1"' - insertafter: 'storage_option = \[' - regexp: 'overlay\.override_kernel_check=1' - state: present - when: ansible_distribution == 'RedHat' or ansible_distribution == 'CentOS' diff --git a/contrib/test/integration/build/cri-tools.yml b/contrib/test/integration/build/cri-tools.yml deleted file mode 100644 index e314225ef..000000000 --- a/contrib/test/integration/build/cri-tools.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- - -- name: clone cri-tools source repo - git: - repo: "https://github.com/kubernetes-incubator/cri-tools.git" - dest: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-tools" - version: "16e6fe4d7199c5689db4630a9330e6a8a12cecd1" - -- name: install crictl - command: "/usr/bin/go install github.com/kubernetes-incubator/cri-tools/cmd/crictl" - -- name: link crictl - file: - src: "{{ ansible_env.GOPATH }}/bin/crictl" - dest: /usr/bin/crictl - state: link diff --git a/contrib/test/integration/build/kubernetes.yml b/contrib/test/integration/build/kubernetes.yml deleted file mode 100644 index 206cba448..000000000 --- a/contrib/test/integration/build/kubernetes.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- - -- name: clone kubernetes source repo - git: - repo: "https://github.com/runcom/kubernetes.git" - dest: "{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes" - version: "cri-o-node-e2e-patched" - -- name: install etcd - command: "hack/install-etcd.sh" - args: - chdir: "{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes" - -- name: build kubernetes - make: - chdir: "{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes" - -- name: Add custom cluster service file for the e2e testing - copy: - dest: /etc/systemd/system/customcluster.service - content: | - [Unit] - After=network-online.target - Wants=network-online.target - [Service] - WorkingDirectory={{ ansible_env.GOPATH }}/src/k8s.io/kubernetes - ExecStart=/usr/local/bin/createcluster.sh - User=root - [Install] - WantedBy=multi-user.target - -- name: Add create cluster background script for e2e testing - copy: - dest: /usr/local/bin/createcluster.sh - content: | - #!/bin/bash - - export PATH=/usr/local/go/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/root/bin:{{ ansible_env.GOPATH }}/bin:{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes/third_party/etcd:{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes/_output/local/bin/linux/amd64/ - export CONTAINER_RUNTIME=remote - export CGROUP_DRIVER=systemd - export CONTAINER_RUNTIME_ENDPOINT='/var/run/crio.sock --runtime-request-timeout=5m' - export ALLOW_SECURITY_CONTEXT="," - export ALLOW_PRIVILEGED=1 - export DNS_SERVER_IP={{ ansible_eth0.ipv4.address }} - export API_HOST={{ ansible_eth0.ipv4.address }} - export API_HOST_IP={{ ansible_eth0.ipv4.address }} - export KUBE_ENABLE_CLUSTER_DNS=true - ./hack/local-up-cluster.sh - mode: "u=rwx,g=rwx,o=x" - -- name: Set kubernetes_provider to be local - lineinfile: - dest: /etc/environment - line: 'KUBERNETES_PROVIDER=local' - regexp: 'KUBERNETES_PROVIDER=' - state: present - -- name: Set KUBECONFIG - lineinfile: - dest: /etc/environment - line: 'KUBECONFIG=/var/run/kubernetes/admin.kubeconfig' - regexp: 'KUBECONFIG=' - state: present diff --git a/contrib/test/integration/build/plugins.yml b/contrib/test/integration/build/plugins.yml deleted file mode 100644 index e342a0b91..000000000 --- a/contrib/test/integration/build/plugins.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- - -- name: clone plugins source repo - git: - repo: "https://github.com/containernetworking/plugins.git" - dest: "{{ ansible_env.GOPATH }}/src/github.com/containernetworking/plugins" - version: "dcf7368eeab15e2affc6256f0bb1e84dd46a34de" - -- name: build plugins - command: "./build.sh" - args: - chdir: "{{ ansible_env.GOPATH }}/src/github.com/containernetworking/plugins" - -- name: install plugins - copy: - src: "{{ ansible_env.GOPATH }}/src/github.com/containernetworking/plugins/bin/{{ item }}" - dest: "/opt/cni/bin" - mode: "o=rwx,g=rx,o=rx" - remote_src: yes - with_items: - - bridge - - dhcp - - flannel - - host-local - - ipvlan - - loopback - - macvlan - - ptp - - sample - - tuning - - vlan - -- name: clone runcom plugins source repo - git: - repo: "https://github.com/runcom/plugins.git" - dest: "{{ ansible_env.GOPATH }}/src/github.com/containernetworking/plugins" - version: "custom-bridge" - force: yes - -- name: build plugins - command: "./build.sh" - args: - chdir: "{{ ansible_env.GOPATH }}/src/github.com/containernetworking/plugins" - -- name: install custom bridge - copy: - src: "{{ ansible_env.GOPATH }}/src/github.com/containernetworking/plugins/bin/bridge" - dest: "/opt/cni/bin/bridge-custom" - mode: "o=rwx,g=rx,o=rx" - remote_src: yes diff --git a/contrib/test/integration/build/runc.yml b/contrib/test/integration/build/runc.yml deleted file mode 100644 index 7bb0491d4..000000000 --- a/contrib/test/integration/build/runc.yml +++ /dev/null @@ -1,23 +0,0 @@ ---- - -- name: clone runc source repo - git: - repo: "https://github.com/opencontainers/runc.git" - dest: "{{ ansible_env.GOPATH }}/src/github.com/opencontainers/runc" - version: "84a082bfef6f932de921437815355186db37aeb1" - -- name: build runc - make: - params: BUILDTAGS="seccomp selinux" - chdir: "{{ ansible_env.GOPATH }}/src/github.com/opencontainers/runc" - -- name: install runc - make: - target: "install" - chdir: "{{ ansible_env.GOPATH }}/src/github.com/opencontainers/runc" - -- name: link runc - file: - src: /usr/local/sbin/runc - dest: /usr/bin/runc - state: link diff --git a/contrib/test/integration/callback_plugins/default.py b/contrib/test/integration/callback_plugins/default.py deleted file mode 100644 index 99821f660..000000000 --- a/contrib/test/integration/callback_plugins/default.py +++ /dev/null @@ -1,156 +0,0 @@ -'''Plugin to override the default output logic.''' - -# upstream: https://gist.github.com/cliffano/9868180 - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - - -# For some reason this has to be done -import imp -import os - -ANSIBLE_PATH = imp.find_module('ansible')[1] -DEFAULT_PATH = os.path.join(ANSIBLE_PATH, 'plugins/callback/default.py') -DEFAULT_MODULE = imp.load_source( - 'ansible.plugins.callback.default', - DEFAULT_PATH -) - -try: - from ansible.plugins.callback import CallbackBase - BASECLASS = CallbackBase -except ImportError: # < ansible 2.1 - BASECLASS = DEFAULT_MODULE.CallbackModule - - -class CallbackModule(DEFAULT_MODULE.CallbackModule): # pylint: disable=too-few-public-methods,no-init - ''' - Override for the default callback module. - - Render std err/out outside of the rest of the result which it prints with - indentation. - ''' - CALLBACK_VERSION = 2.0 - CALLBACK_TYPE = 'stdout' - CALLBACK_NAME = 'default' - - def __init__(self, *args, **kwargs): - # pylint: disable=non-parent-init-called - BASECLASS.__init__(self, *args, **kwargs) - self.failed_task = [] - self.result_file = os.environ.get('AHT_RESULT_FILE') - - def _dump_results(self, result): - '''Return the text to output for a result.''' - result['_ansible_verbose_always'] = True - - save = {} - for key in ['stdout', 'stdout_lines', 'stderr', 'stderr_lines', 'msg']: - if key in result: - save[key] = result.pop(key) - - output = BASECLASS._dump_results(self, result) # pylint: disable=protected-access - - for key in ['stdout', 'stderr', 'msg']: - if key in save and save[key]: - output += '\n\n%s:\n---\n%s\n---' % (key.upper(), save[key]) - - for key, value in save.items(): - result[key] = value - - return output - - def v2_runner_on_unreachable(self, result): - self.failed_task = result - - if self._play.strategy == 'free' and self._last_task_banner != result._task._uuid: - self._print_task_banner(result._task) - - delegated_vars = result._result.get('_ansible_delegated_vars', None) - if delegated_vars: - self._display.display("fatal: [%s -> %s]: UNREACHABLE! => %s" % (result._host.get_name(), delegated_vars['ansible_host'], self._dump_results(result._result)), color=C.COLOR_UNREACHABLE) - else: - self._display.display("fatal: [%s]: UNREACHABLE! => %s" % (result._host.get_name(), self._dump_results(result._result)), color=C.COLOR_UNREACHABLE) - - def v2_runner_on_failed(self,result, ignore_errors=False): - if ignore_errors is not True: - # Sets environment variable for test failures for use in playboks. - # Handlers tasks can conditionalize themselves using this variable - # to run only on failure. - os.environ["AHT_FAILURE"] = "1" - - # Save last failure - self.failed_task = result - - if self._play.strategy == 'free' and self._last_task_banner != result._task._uuid: - self._print_task_banner(result._task) - - delegated_vars = result._result.get('_ansible_delegated_vars', None) - if 'exception' in result._result: - if self._display.verbosity < 3: - # extract just the actual error message from the exception text - error = result._result['exception'].strip().split('\n')[-1] - msg = "An exception occurred during task execution. To see the full traceback, use -vvv. The error was: %s" % error - else: - msg = "An exception occurred during task execution. The full traceback is:\n" + result._result['exception'] - - self._display.display(msg, color=C.COLOR_ERROR) - - if result._task.loop and 'results' in result._result: - self._process_items(result) - - else: - if delegated_vars: - self._display.display("fatal: [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'], self._dump_results(result._result)), color=C.COLOR_ERROR) - else: - self._display.display("fatal: [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)), color=C.COLOR_ERROR) - - if ignore_errors: - self._display.display("...ignoring", color=C.COLOR_SKIP) - - def v2_playbook_on_stats(self, stats): - self._display.banner("PLAY RECAP") - - hosts = sorted(stats.processed.keys()) - for h in hosts: - t = stats.summarize(h) - - self._display.display(u"%s : %s %s %s %s" % ( - hostcolor(h, t), - colorize(u'ok', t['ok'], C.COLOR_OK), - colorize(u'changed', t['changed'], C.COLOR_CHANGED), - colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE), - colorize(u'failed', t['failures'], C.COLOR_ERROR)), - screen_only=True - ) - - self._display.display(u"%s : %s %s %s %s" % ( - hostcolor(h, t, False), - colorize(u'ok', t['ok'], None), - colorize(u'changed', t['changed'], None), - colorize(u'unreachable', t['unreachable'], None), - colorize(u'failed', t['failures'], None)), - log_only=True - ) - - self._display.display("", screen_only=True) - # Save result to file if environment variable exists - if self.result_file is not None: - if self.failed_task: - with open(self.result_file, 'w') as f: - f.write("PLAY: %s\n%s\n%s" % (self._play, \ - self.failed_task._task, \ - self._dump_results(self.failed_task._result))) - else: - open(self.result_file, 'w').close() diff --git a/contrib/test/integration/e2e.yml b/contrib/test/integration/e2e.yml deleted file mode 100644 index 5c4d656ef..000000000 --- a/contrib/test/integration/e2e.yml +++ /dev/null @@ -1,57 +0,0 @@ ---- - -- name: enable and start CRI-O - systemd: - name: crio - state: started - enabled: yes - daemon_reload: yes - -- name: update the server address for the custom cluster - lineinfile: - dest: /usr/local/bin/createcluster.sh - line: "export {{ item }}={{ ansible_eth0.ipv4.address }}" - regexp: "^export {{ item }}=" - state: present - with_items: - - DNS_SERVER_IP - - API_HOST - - API_HOST_IP - -- name: enable and start the custom cluster - systemd: - name: customcluster.service - state: started - enabled: yes - daemon_reload: yes - -- name: wait for the cluster to be running - command: "{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes/_output/bin/kubectl get service kubernetes --namespace default" - register: kube_poll - until: kube_poll | succeeded - retries: 100 - delay: 30 - -- name: ensure directory exists for e2e reports - file: - path: "{{ artifacts }}" - state: directory - -- name: Buffer the e2e testing command to workaround Ansible YAML folding "feature" - set_fact: - e2e_shell_cmd: > - /usr/bin/go run hack/e2e.go - --test - --test_args="-host=https://{{ ansible_default_ipv4.address }}:6443 - --ginkgo.focus=\[Conformance\] - --report-dir={{ artifacts }}" - &> {{ artifacts }}/e2e.log - # Fix vim syntax hilighting: " - -- name: disable SELinux - command: setenforce 0 - -- name: run e2e tests - shell: "{{ e2e_shell_cmd | regex_replace('\\s+', ' ') }}" - args: - chdir: "{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes" diff --git a/contrib/test/integration/golang.yml b/contrib/test/integration/golang.yml deleted file mode 100644 index 63e556977..000000000 --- a/contrib/test/integration/golang.yml +++ /dev/null @@ -1,51 +0,0 @@ ---- - -- name: fetch Golang - unarchive: - remote_src: yes - src: https://storage.googleapis.com/golang/go1.8.4.linux-amd64.tar.gz - dest: /usr/local - -- name: link go toolchain - file: - src: "/usr/local/go/bin/{{ item }}" - dest: "/usr/bin/{{ item }}" - state: link - with_items: - - go - - gofmt - - godoc - -- name: ensure user profile exists - file: - path: "{{ ansible_user_dir }}/.profile" - state: touch - -- name: set up PATH for Go toolchain and built binaries - lineinfile: - dest: "{{ ansible_user_dir }}/.profile" - line: 'PATH={{ ansible_env.PATH }}:{{ ansible_env.GOPATH }}/bin:/usr/local/go/bin' - regexp: '^PATH=' - state: present - -- name: set up directories - file: - path: "{{ item }}" - state: directory - with_items: - - "{{ ansible_env.GOPATH }}/src/github.com/containernetworking" - - "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator" - - "{{ ansible_env.GOPATH }}/src/github.com/k8s.io" - - "{{ ansible_env.GOPATH }}/src/github.com/sstephenson" - - "{{ ansible_env.GOPATH }}/src/github.com/opencontainers" - -- name: install Go tools and dependencies - shell: /usr/bin/go get -u "github.com/{{ item }}" - with_items: - - tools/godep - - onsi/ginkgo/ginkgo - - onsi/gomega - - cloudflare/cfssl/cmd/... - - jteeuwen/go-bindata/go-bindata - - vbatts/git-validation - - cpuguy83/go-md2man diff --git a/contrib/test/integration/main.yml b/contrib/test/integration/main.yml deleted file mode 100644 index ce4a206fb..000000000 --- a/contrib/test/integration/main.yml +++ /dev/null @@ -1,58 +0,0 @@ -- hosts: all - remote_user: root - vars_files: - - "{{ playbook_dir }}/vars.yml" - tags: - - setup - tasks: - - name: set up the system - include: system.yml - - - name: install Golang tools - include: golang.yml - - - name: clone build and install bats - include: "build/bats.yml" - - - name: clone build and install cri-tools - include: "build/cri-tools.yml" - - - name: clone build and install kubernetes - include: "build/kubernetes.yml" - - - name: clone build and install runc - include: "build/runc.yml" - - - name: clone build and install networking plugins - include: "build/plugins.yml" - -- hosts: all - remote_user: root - vars_files: - - "{{ playbook_dir }}/vars.yml" - tags: - - integration - - e2e - tasks: - - name: clone build and install cri-o - include: "build/cri-o.yml" - -- hosts: all - remote_user: root - vars_files: - - "{{ playbook_dir }}/vars.yml" - tags: - - integration - tasks: - - name: run cri-o integration tests - include: test.yml - -- hosts: all - remote_user: root - vars_files: - - "{{ playbook_dir }}/vars.yml" - tags: - - e2e - tasks: - - name: run k8s e2e tests - include: e2e.yml diff --git a/contrib/test/integration/results.yml b/contrib/test/integration/results.yml deleted file mode 100644 index c9a96abb1..000000000 --- a/contrib/test/integration/results.yml +++ /dev/null @@ -1,62 +0,0 @@ ---- -# vim-syntax: ansible - -- hosts: '{{ hosts | default("all") }}' - vars_files: - - "{{ playbook_dir }}/vars.yml" - vars: - _result_filepaths: [] # do not use - _dstfnbuff: [] # do not use - tasks: - - name: The crio_integration_filepath is required - tags: - - integration - set_fact: - _result_filepaths: "{{ _result_filepaths + [crio_integration_filepath] }}" - - - name: The crio_node_e2e_filepath is required - tags: - - e2e - set_fact: - _result_filepaths: "{{ _result_filepaths + [crio_node_e2e_filepath] }}" - - - name: Verify expectations - assert: - that: - - 'result_dest_basedir | default(False, True)' - - '_result_filepaths | default(False, True)' - - '_dstfnbuff == []' - - 'results_fetched is undefined' - - - name: Results directory exists - file: - path: "{{ result_dest_basedir }}" - state: directory - delegate_to: localhost - - - name: destination file paths are buffered for overwrite-checking and jUnit conversion - set_fact: - _dstfnbuff: > - {{ _dstfnbuff | - union( [result_dest_basedir ~ "/" ~ inventory_hostname ~ "/" ~ item | basename] ) }} - with_items: '{{ _result_filepaths }}' - - - name: Overwriting existing results assumed very very bad - fail: - msg: "Cowardly refusing to overwrite {{ item }}" - when: item | exists - delegate_to: localhost - with_items: '{{ _dstfnbuff }}' - - # fetch module doesn't support directories - - name: Retrieve results from all hosts - synchronize: - checksum: True # Don't rely on date/time being in sync - archive: False # Don't bother with permissions or times - copy_links: True # We want files, not links to files - recursive: True - mode: pull - dest: '{{ result_dest_basedir }}/{{ inventory_hostname }}/' # must end in / - src: '{{ item }}' - register: results_fetched - with_items: '{{ _result_filepaths }}' diff --git a/contrib/test/integration/system.yml b/contrib/test/integration/system.yml deleted file mode 100644 index d07ae0c82..000000000 --- a/contrib/test/integration/system.yml +++ /dev/null @@ -1,117 +0,0 @@ ---- - -- name: Make sure we have all required packages - package: - name: "{{ item }}" - state: present - with_items: - - container-selinux - - curl - - device-mapper-devel - - expect - - findutils - - gcc - - git - - glib2-devel - - glibc-devel - - glibc-static - - gpgme-devel - - hostname - - iproute - - iptables - - krb5-workstation - - libassuan-devel - - libffi-devel - - libgpg-error-devel - - libguestfs-tools - - libseccomp-devel - - libvirt-client - - libvirt-python - - libxml2-devel - - libxslt-devel - - make - - mlocate - - nfs-utils - - nmap-ncat - - oci-register-machine - - oci-systemd-hook - - oci-umount - - openssl - - openssl-devel - - ostree-devel - - pkgconfig - - python - - python2-boto - - python2-crypto - - python-devel - - python-virtualenv - - PyYAML - - redhat-rpm-config - - rpcbind - - rsync - - sed - - skopeo-containers - - socat - - tar - - wget - async: 600 - poll: 10 - -- name: Add Btrfs for Fedora - package: - name: "{{ item }}" - state: present - with_items: - - btrfs-progs-devel - when: ansible_distribution in ['Fedora'] - -- name: Update all packages - package: - name: '*' - state: latest - async: 600 - poll: 10 - -- name: Setup swap to prevent kernel firing off the OOM killer - shell: | - truncate -s 8G /root/swap && \ - export SWAPDEV=$(losetup --show -f /root/swap | head -1) && \ - mkswap $SWAPDEV && \ - swapon $SWAPDEV && \ - swapon --show - -- name: ensure directories exist as needed - file: - path: "{{ item }}" - state: directory - with_items: - - /opt/cni/bin - - /etc/cni/net.d - -- name: set sysctl vm.overcommit_memory=1 for CentOS - sysctl: - name: vm.overcommit_memory - state: present - value: 1 - when: ansible_distribution == 'CentOS' - -- name: inject hostname into /etc/hosts - lineinfile: - dest: /etc/hosts - line: '{{ ansible_default_ipv4.address }} {{ ansible_nodename }}' - insertafter: 'EOF' - regexp: '{{ ansible_default_ipv4.address }}\s+{{ ansible_nodename }}' - state: present - -- name: Flush the iptables - command: iptables -F - -- name: Enable localnet routing - command: sysctl -w net.ipv4.conf.all.route_localnet=1 - -- name: Add masquerade for localhost - command: iptables -t nat -I POSTROUTING -s 127.0.0.1 ! -d 127.0.0.1 -j MASQUERADE - -- name: Update the kernel cmdline to include quota support - command: grubby --update-kernel=ALL --args="rootflags=pquota" - when: ansible_distribution in ['RedHat', 'CentOS'] diff --git a/contrib/test/integration/test.yml b/contrib/test/integration/test.yml deleted file mode 100644 index 418ceff78..000000000 --- a/contrib/test/integration/test.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- - -- name: Make testing output verbose so it can be converted to xunit - lineinfile: - dest: "{{ ansible_env.GOPATH }}/src/k8s.io/kubernetes/hack/make-rules/test.sh" - line: ' go test -v "${goflags[@]:+${goflags[@]}}" \' - regexp: ' go test \"\$' - state: present - -- name: set extra storage options - set_fact: - extra_storage_opts: " --storage-opt overlay.override_kernel_check=1" - when: ansible_distribution == 'RedHat' or ansible_distribution == 'CentOS' - -- name: ensure directory exists for e2e reports - file: - path: "{{ artifacts }}" - state: directory - -- name: run integration tests - shell: "CGROUP_MANAGER=cgroupfs STORAGE_OPTIONS='--storage-driver=overlay{{ extra_storage_opts | default('') }}' make localintegration >& {{ artifacts }}/testout.txt" - args: - chdir: "{{ ansible_env.GOPATH }}/src/github.com/kubernetes-incubator/cri-o" - async: 5400 - poll: 30 diff --git a/contrib/test/integration/vars.yml b/contrib/test/integration/vars.yml deleted file mode 100644 index f1e5e2f73..000000000 --- a/contrib/test/integration/vars.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- - -# For results.yml Paths use rsync 'source' conventions -artifacts: "/tmp/artifacts" # Base-directory for collection -crio_integration_filepath: "{{ artifacts }}/testout.txt" -crio_node_e2e_filepath: "{{ artifacts }}/junit_01.xml" -result_dest_basedir: '{{ lookup("env","WORKSPACE") | - default(playbook_dir, True) }}/artifacts' diff --git a/contrib/test/requirements.txt b/contrib/test/requirements.txt deleted file mode 100644 index 4dc4531b0..000000000 --- a/contrib/test/requirements.txt +++ /dev/null @@ -1,54 +0,0 @@ -# Pip requirements file for Ansible-based integration-testing environment. -# Intended to be utilized by venv-ansible-playbook.sh script -# -# N/B: Hashes are required here | versions frozen for stability - -ansible==2.3.1.0 --hash=sha256:cd4b8f53720fcd0c351156b840fdd15ecfbec22c951b5406ec503de49d40b9f5 - -asn1crypto==0.22.0 --hash=sha256:d232509fefcfcdb9a331f37e9c9dc20441019ad927c7d2176cf18ed5da0ba097 \ - --hash=sha256:cbbadd640d3165ab24b06ef25d1dca09a3441611ac15f6a6b452474fdf0aed1a - -bcrypt==3.1.3 --hash=sha256:05b35b9842b009b44496fa5433ce462f69966291e50fbd471dbb427f399f748f \ - --hash=sha256:6645c8d0ad845308de3eb9be98b6fd22a46ec5412bfc664a423e411cdd8f5488 - -cffi==1.10.0 --hash=sha256:c49187260043bd4c1d6a52186f9774f17d9b1da0a406798ebf4bfc12da166ade \ - --hash=sha256:b3b02911eb1f6ada203b0763ba924234629b51586f72a21faacc638269f4ced5 - -cryptography==1.9 --hash=sha256:5518337022718029e367d982642f3e3523541e098ad671672a90b82474c84882 - -enum34==1.1.6 --hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \ - --hash=sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1 - -idna==2.5 --hash=sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70 \ - --hash=sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab - -ipaddress==1.0.18 --hash=sha256:d34cf15d95ce9a734560f7400a8bd2ac2606f378e2a1d0eadbf1c98707e7c74a \ - --hash=sha256:5d8534c8e185f2d8a1fda1ef73f2c8f4b23264e8e30063feeb9511d492a413e1 - -Jinja2==2.9.6 --hash=sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054 \ - --hash=sha256:ddaa01a212cd6d641401cb01b605f4a4d9f37bfc93043d7f760ec70fb99ff9ff - -MarkupSafe==1.0 --hash=sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665 - -paramiko==2.2.1 --hash=sha256:9c9402377ba8594889aab1e44a13b78eda685eb2145dc00b2353b4fbb25088cf \ - --hash=sha256:ff94ae65379914ec3c960de731381f49092057b6dd1d24d18842ead5a2eb2277 - -pyasn1==0.2.3 --hash=sha256:0439b9bd518418260c2641a571f0e07fce4370cab13b68f19b5e023306c03cad \ - --hash=sha256:738c4ebd88a718e700ee35c8d129acce2286542daa80a82823a7073644f706ad - -pycparser==2.17 --hash=sha256:0aac31e917c24cb3357f5a4d5566f2cc91a19ca41862f6c3c22dc60a629673b6 - -pycrypto==2.6.1 --hash=sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c - -PyNaCl==1.1.2 --hash=sha256:57314a7bad4bd39501dc622942f9921923673e52e126b0fc4f0214b5d25d619a \ - --hash=sha256:32f52b754abf07c319c04ce16905109cab44b0e7f7c79497431d3b2000f8af8c - -PyYAML==3.12 --hash=sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab - -six==1.10.0 --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \ - --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a - -virtualenv==15.1.0 --hash=sha256:39d88b533b422825d644087a21e78c45cf5af0ef7a99a1fc9fbb7b481e5c85b0 \ - --hash=sha256:02f8102c2436bb03b3ee6dede1919d1dac8a427541652e5ec95171ec8adbc93a - -pip==9.0.1 --hash=sha256:690b762c0a8460c303c089d5d0be034fb15a5ea2b75bdf565f40421f542fefb0 diff --git a/contrib/test/venv-ansible-playbook.sh b/contrib/test/venv-ansible-playbook.sh deleted file mode 100755 index 587042154..000000000 --- a/contrib/test/venv-ansible-playbook.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash - -# example usage -# $ ./venv-ansible-playbook.sh \ -# -i 192.168.169.170 \ -# --private-key=/path/to/key \ -# --extra-vars "pullrequest=42" \ -# --extra-vars "commit=abcd1234" \ -# --user root \ -# --verbose \ -# $PWD/crio-integration-playbook.yaml - -# All errors are fatal -set -e - -SCRIPT_PATH=`realpath $(dirname $0)` -REQUIREMENTS="$SCRIPT_PATH/requirements.txt" - -echo - -if ! type -P virtualenv &> /dev/null -then - echo "Could not find required 'virtualenv' binary installed on system." - exit 1 -fi - -if [ "$#" -lt "1" ] -then - echo "No ansible-playbook command-line options specified." - echo "usage: $0 -i whatever --private-key=something --extra-vars foo=bar playbook.yml" - exit 2 -fi - -# Avoid dirtying up repository, keep execution bits confined to a known location -if [ -z "$WORKSPACE" ] || [ ! -d "$WORKSPACE" ] -then - export WORKSPACE="$(mktemp -d)" - echo "Using temporary \$WORKSPACE=\"$WORKSPACE\" for execution environment." - echo "Directory will be removed upon exit. Export this variable with path" - echo "to an existing directory to preserve contents." - trap 'rm -rf "$WORKSPACE"' EXIT -else - echo "Using existing \$WORKSPACE=\"$WORKSPACE\" for execution environment." - echo "Directory will be left as-is upon exit." - # Don't recycle cache, next job may have different requirements - trap 'rm -rf "$PIPCACHE"' EXIT -fi - -# Create a directory to contain logs and test artifacts -export ARTIFACTS=$(mkdir -pv $WORKSPACE/artifacts | tail -1 | cut -d \' -f 2) -[ -d "$ARTIFACTS" ] || exit 3 - -# All command failures from now on are fatal -set -e -echo -echo "Bootstrapping trusted virtual environment, this may take a few minutes, depending on networking." -echo "(logs: \"$ARTIFACTS/crio_venv_setup_log.txt\")" -echo - - -( - set -x - cd "$WORKSPACE" - # When running more than once, make it fast by skipping the bootstrap - if [ ! -d "./.cri-o_venv" ]; then - # N/B: local system's virtualenv binary - uncontrolled version fixed below - virtualenv --no-site-packages --python=python2.7 ./.venvbootstrap - # Set up paths to install/operate out of $WORKSPACE/.venvbootstrap - source ./.venvbootstrap/bin/activate - # N/B: local system's pip binary - uncontrolled version fixed below - # pip may not support --cache-dir, force it's location into $WORKSPACE the ugly-way - OLD_HOME="$HOME" - export HOME="$WORKSPACE" - export PIPCACHE="$WORKSPACE/.cache/pip" - pip install --force-reinstall --upgrade pip==9.0.1 - # Undo --cache-dir workaround - export HOME="$OLD_HOME" - # Install fixed, trusted, hashed versions of all requirements (including pip and virtualenv) - pip --cache-dir="$PIPCACHE" install --require-hashes \ - --requirement "$SCRIPT_PATH/requirements.txt" - - # Setup trusted virtualenv using hashed binary from requirements.txt - ./.venvbootstrap/bin/virtualenv --no-site-packages --python=python2.7 ./.cri-o_venv - # Exit untrusted virtualenv - deactivate - fi - # Enter trusted virtualenv - source ./.cri-o_venv/bin/activate - # Upgrade stock-pip to support hashes - pip install --force-reinstall --cache-dir="$PIPCACHE" --upgrade pip==9.0.1 - # Re-install from cache but validate all hashes (including on pip itself) - pip --cache-dir="$PIPCACHE" install --require-hashes \ - --requirement "$SCRIPT_PATH/requirements.txt" - # Remove temporary bootstrap virtualenv - rm -rf ./.venvbootstrap - # Exit trusted virtualenv - -) &> $ARTIFACTS/crio_venv_setup_log.txt; - -echo -echo "Executing \"$WORKSPACE/.cri-o_venv/bin/ansible-playbook $@\"" -echo - -# Execute command-line arguments under virtualenv -source ${WORKSPACE}/.cri-o_venv/bin/activate -${WORKSPACE}/.cri-o_venv/bin/ansible-playbook $@ diff --git a/kubernetes.md b/kubernetes.md deleted file mode 100644 index a88a76a38..000000000 --- a/kubernetes.md +++ /dev/null @@ -1,105 +0,0 @@ -# Running CRI-O on kubernetes cluster - -## Switching runtime from docker to CRI-O - -In standard docker kubernetes cluster, kubelet is running on each node as systemd service and is taking care of communication between runtime and api service. -It is reponsible for starting microservices pods (such as `kube-proxy`, `kubedns`, etc. - they can be different for various ways of deploying k8s) and user pods. -Configuration of kubelet determines which runtime is used and in what way. - -Kubelet itself is executed in docker container (as we can see in `kubelet.service`), but, what is important, **it's not** a kubernetes pod (at least for now), -so we can keep kubelet running inside container (as well as directly on the host), and regardless of this, run pods in chosen runtime. - -Below, you can find an instruction how to switch one or more nodes on running kubernetes cluster from docker to CRI-O. - -### Preparing crio - -You must prepare and install `crio` on each node you would like to switch. Here's the list of files that must be provided: - -| File path | Description | Location | -|--------------------------------------------|----------------------------|-----------------------------------------------------| -| `/etc/crio/crio.conf` | crio configuration | Generated on cri-o `make install` | -| `/etc/crio/seccomp.conf` | seccomp config | Example stored in cri-o repository | -| `/etc/containers/policy.json` | containers policy | Example stored in cri-o repository | -| `/bin/{crio, runc}` | `crio` and `runc` binaries | Built from cri-o repository | -| `/usr/local/libexec/crio/conmon` | `conmon` binary | Built from cri-o repository | -| `/opt/cni/bin/{flannel, bridge,...}` | CNI plugins binaries | Can be built from sources `containernetworking/cni` | -| `/etc/cni/net.d/10-mynet.conf` | Network config | Example stored in [README file](README.md) | - -`crio` binary can be executed directly on host, inside the container or in any way. -However, recommended way is to set it as a systemd service. -Here's the example of unit file: - -``` -# cat /etc/systemd/system/crio.service -[Unit] -Description=CRI-O daemon -Documentation=https://github.com/kubernetes-incubator/cri-o - -[Service] -ExecStart=/bin/crio --runtime /bin/runc --log /root/crio.log --log-level debug -Restart=always -RestartSec=10s - -[Install] -WantedBy=multi-user.target -``` - -### Preparing kubelet -At first, you need to stop kubelet service working on the node: -``` -# systemctl stop kubelet -``` -and stop all kubelet docker containers that are still runing. - -``` -# docker stop $(docker ps | grep k8s_ | awk '{print $1}') -``` - -We have to be sure that `kubelet.service` will start after `crio.service`. -It can be done by adding `crio.service` to `Wants=` section in `/etc/systemd/system/kubelet.service`: - -``` -# cat /etc/systemd/system/kubelet.service | grep Wants -Wants=docker.socket crio.service -``` - -If you'd like to change the way of starting kubelet (e.g. directly on host instead of docker container), you can change it here, but, as mentioned, it's not necessary. - - -Kubelet parameters are stored in `/etc/kubernetes/kubelet.env` file. -``` -# cat /etc/kubernetes/kubelet.env | grep KUBELET_ARGS -KUBELET_ARGS="--pod-manifest-path=/etc/kubernetes/manifests ---pod-infra-container-image=gcr.io/google_containers/pause-amd64:3.0 ---cluster_dns=10.233.0.3 --cluster_domain=cluster.local ---resolv-conf=/etc/resolv.conf --kubeconfig=/etc/kubernetes/node-kubeconfig.yaml ---require-kubeconfig" -``` - -You need to add following parameters to `KUBELET_ARGS`: -* `--experimental-cri=true` - Use Container Runtime Interface. Will be true by default from kubernetes 1.6 release. -* `--container-runtime=remote` - Use remote runtime with provided socket. -* `--container-runtime-endpoint=/var/run/crio.sock` - Socket for remote runtime (default `crio` socket localization). -* `--runtime-request-timeout=10m` - Optional but useful. Some requests, especially pulling huge images, may take longer than default (2 minutes) and will cause an error. - -Kubelet is prepared now. - -## Flannel network -If your cluster is using flannel network, your network configuration should be like: -``` -# cat /etc/cni/net.d/10-mynet.conf -{ - "name": "mynet", - "type": "flannel" -} -``` -Then, kubelet will take parameters from `/run/flannel/subnet.env` - file generated by flannel kubelet microservice. - -## Starting kubelet with CRI-O -Start crio first, then kubelet. If you created `crio` service: -``` -# systemctl start crio -# systemctl start kubelet -``` - -You can follow the progress of preparing node using `kubectl get nodes` or `kubectl get pods --all-namespaces` on kubernetes master. diff --git a/libkpod/config.go b/libkpod/config.go index 687b4b380..09bd3f5b9 100644 --- a/libkpod/config.go +++ b/libkpod/config.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "github.com/BurntSushi/toml" - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/oci" "github.com/opencontainers/selinux/go-selinux" ) diff --git a/libkpod/container.go b/libkpod/container.go index 7835952d2..7afcfa009 100644 --- a/libkpod/container.go +++ b/libkpod/container.go @@ -4,9 +4,9 @@ import ( "fmt" cstorage "github.com/containers/storage" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/pkg/registrar" + "github.com/projectatomic/libpod/libkpod/sandbox" + "github.com/projectatomic/libpod/oci" + "github.com/projectatomic/libpod/pkg/registrar" "github.com/pkg/errors" ) diff --git a/libkpod/container_data.go b/libkpod/container_data.go index 2ade63ba0..2c5913589 100644 --- a/libkpod/container_data.go +++ b/libkpod/container_data.go @@ -8,9 +8,9 @@ import ( "k8s.io/apimachinery/pkg/fields" pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - "github.com/kubernetes-incubator/cri-o/libpod/driver" - "github.com/kubernetes-incubator/cri-o/libpod/images" - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/libpod/driver" + "github.com/projectatomic/libpod/libpod/images" + "github.com/projectatomic/libpod/oci" "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" diff --git a/libkpod/container_server.go b/libkpod/container_server.go index 8da465fdf..067b5a906 100644 --- a/libkpod/container_server.go +++ b/libkpod/container_server.go @@ -12,11 +12,11 @@ import ( cstorage "github.com/containers/storage" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/truncindex" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/pkg/annotations" - "github.com/kubernetes-incubator/cri-o/pkg/registrar" - "github.com/kubernetes-incubator/cri-o/pkg/storage" + "github.com/projectatomic/libpod/libkpod/sandbox" + "github.com/projectatomic/libpod/oci" + "github.com/projectatomic/libpod/pkg/annotations" + "github.com/projectatomic/libpod/pkg/registrar" + "github.com/projectatomic/libpod/pkg/storage" "github.com/opencontainers/runc/libcontainer" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux" diff --git a/libkpod/kill.go b/libkpod/kill.go index b2c3219a2..fe7fbc2ba 100644 --- a/libkpod/kill.go +++ b/libkpod/kill.go @@ -2,8 +2,8 @@ package libkpod import ( "github.com/docker/docker/pkg/signal" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/utils" + "github.com/projectatomic/libpod/oci" + "github.com/projectatomic/libpod/utils" "github.com/pkg/errors" "os" "syscall" diff --git a/libkpod/pause.go b/libkpod/pause.go index 29871d32b..221c2591f 100644 --- a/libkpod/pause.go +++ b/libkpod/pause.go @@ -1,7 +1,7 @@ package libkpod import ( - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/oci" "github.com/pkg/errors" ) diff --git a/libkpod/remove.go b/libkpod/remove.go index 5df9e8f74..9f6ba2a49 100644 --- a/libkpod/remove.go +++ b/libkpod/remove.go @@ -4,7 +4,7 @@ import ( "os" "path/filepath" - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/oci" "github.com/pkg/errors" "golang.org/x/net/context" ) diff --git a/libkpod/rename.go b/libkpod/rename.go index 7c0279bfe..49f7f18c4 100644 --- a/libkpod/rename.go +++ b/libkpod/rename.go @@ -7,8 +7,8 @@ import ( "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" "github.com/docker/docker/pkg/ioutils" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/pkg/annotations" + "github.com/projectatomic/libpod/oci" + "github.com/projectatomic/libpod/pkg/annotations" "github.com/opencontainers/runtime-tools/generate" ) diff --git a/libkpod/sandbox/sandbox.go b/libkpod/sandbox/sandbox.go index d7d6569d9..a61c5a4f7 100644 --- a/libkpod/sandbox/sandbox.go +++ b/libkpod/sandbox/sandbox.go @@ -11,7 +11,7 @@ import ( "github.com/containernetworking/plugins/pkg/ns" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/symlink" - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/oci" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" "k8s.io/apimachinery/pkg/fields" diff --git a/libkpod/stats.go b/libkpod/stats.go index f4d645d65..bf49a80ab 100644 --- a/libkpod/stats.go +++ b/libkpod/stats.go @@ -7,7 +7,7 @@ import ( "strings" - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/oci" "github.com/opencontainers/runc/libcontainer" ) diff --git a/libkpod/stop.go b/libkpod/stop.go index 86c9cbec2..5ab974634 100644 --- a/libkpod/stop.go +++ b/libkpod/stop.go @@ -1,7 +1,7 @@ package libkpod import ( - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/oci" "github.com/pkg/errors" "golang.org/x/net/context" ) diff --git a/libkpod/wait.go b/libkpod/wait.go index c7ba57328..a2e3669c7 100644 --- a/libkpod/wait.go +++ b/libkpod/wait.go @@ -1,7 +1,7 @@ package libkpod import ( - "github.com/kubernetes-incubator/cri-o/oci" + "github.com/projectatomic/libpod/oci" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/wait" ) diff --git a/libpod/container.go b/libpod/container.go index 390b20b31..1f5be9477 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -10,7 +10,7 @@ import ( "github.com/containers/storage" "github.com/docker/docker/pkg/stringid" - crioAnnotations "github.com/kubernetes-incubator/cri-o/pkg/annotations" + crioAnnotations "github.com/projectatomic/libpod/pkg/annotations" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" diff --git a/libpod/diff.go b/libpod/diff.go index 055bb7fe8..571c58de8 100644 --- a/libpod/diff.go +++ b/libpod/diff.go @@ -2,7 +2,7 @@ package libpod import ( "github.com/containers/storage/pkg/archive" - "github.com/kubernetes-incubator/cri-o/libpod/layers" + "github.com/projectatomic/libpod/libpod/layers" "github.com/pkg/errors" ) diff --git a/libpod/images/image_data.go b/libpod/images/image_data.go index 12fb1e77a..0295578c5 100644 --- a/libpod/images/image_data.go +++ b/libpod/images/image_data.go @@ -9,7 +9,7 @@ import ( "github.com/containers/image/transports" "github.com/containers/image/types" "github.com/containers/storage" - "github.com/kubernetes-incubator/cri-o/libpod/driver" + "github.com/projectatomic/libpod/libpod/driver" digest "github.com/opencontainers/go-digest" ociv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index b8747d4e7..e815dce3c 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -2,7 +2,7 @@ package libpod import ( "github.com/docker/docker/pkg/truncindex" - "github.com/kubernetes-incubator/cri-o/pkg/registrar" + "github.com/projectatomic/libpod/pkg/registrar" "github.com/pkg/errors" ) diff --git a/libpod/oci.go b/libpod/oci.go index 0ed1c1f66..fd2c3b283 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -18,7 +18,7 @@ import ( // TODO import these functions into libpod and remove the import // Trying to keep libpod from depending on CRI-O code - "github.com/kubernetes-incubator/cri-o/utils" + "github.com/projectatomic/libpod/utils" ) // OCI code is undergoing heavy rewrite diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go index 9e7ad3106..278f0c186 100644 --- a/libpod/runtime_img.go +++ b/libpod/runtime_img.go @@ -22,7 +22,7 @@ import ( "github.com/containers/image/types" "github.com/containers/storage" "github.com/containers/storage/pkg/archive" - "github.com/kubernetes-incubator/cri-o/libpod/common" + "github.com/projectatomic/libpod/libpod/common" digest "github.com/opencontainers/go-digest" ociv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" diff --git a/oci/oci.go b/oci/oci.go index 756be44bf..2ad66f69f 100644 --- a/oci/oci.go +++ b/oci/oci.go @@ -14,7 +14,7 @@ import ( "time" "github.com/containerd/cgroups" - "github.com/kubernetes-incubator/cri-o/utils" + "github.com/projectatomic/libpod/utils" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" "golang.org/x/net/context" diff --git a/server/apparmor/aaparser.go b/server/apparmor/aaparser.go deleted file mode 100644 index 7f0f02ac5..000000000 --- a/server/apparmor/aaparser.go +++ /dev/null @@ -1,89 +0,0 @@ -// +build apparmor - -package apparmor - -import ( - "fmt" - "os/exec" - "strconv" - "strings" -) - -const ( - binary = "apparmor_parser" -) - -// GetVersion returns the major and minor version of apparmor_parser. -func GetVersion() (int, error) { - output, err := cmd("", "--version") - if err != nil { - return -1, err - } - - return parseVersion(output) -} - -// LoadProfile runs `apparmor_parser -r` on a specified apparmor profile to -// replace the profile. -func LoadProfile(profilePath string) error { - _, err := cmd("", "-r", profilePath) - return err -} - -// cmd runs `apparmor_parser` with the passed arguments. -func cmd(dir string, arg ...string) (string, error) { - c := exec.Command(binary, arg...) - c.Dir = dir - - output, err := c.CombinedOutput() - if err != nil { - return "", fmt.Errorf("running `%s %s` failed with output: %s\nerror: %v", c.Path, strings.Join(c.Args, " "), output, err) - } - - return string(output), nil -} - -// parseVersion takes the output from `apparmor_parser --version` and returns -// a representation of the {major, minor, patch} version as a single number of -// the form MMmmPPP {major, minor, patch}. -func parseVersion(output string) (int, error) { - // output is in the form of the following: - // AppArmor parser version 2.9.1 - // Copyright (C) 1999-2008 Novell Inc. - // Copyright 2009-2012 Canonical Ltd. - - lines := strings.SplitN(output, "\n", 2) - words := strings.Split(lines[0], " ") - version := words[len(words)-1] - - // split by major minor version - v := strings.Split(version, ".") - if len(v) == 0 || len(v) > 3 { - return -1, fmt.Errorf("parsing version failed for output: `%s`", output) - } - - // Default the versions to 0. - var majorVersion, minorVersion, patchLevel int - - majorVersion, err := strconv.Atoi(v[0]) - if err != nil { - return -1, err - } - - if len(v) > 1 { - minorVersion, err = strconv.Atoi(v[1]) - if err != nil { - return -1, err - } - } - if len(v) > 2 { - patchLevel, err = strconv.Atoi(v[2]) - if err != nil { - return -1, err - } - } - - // major*10^5 + minor*10^3 + patch*10^0 - numericVersion := majorVersion*1e5 + minorVersion*1e3 + patchLevel - return numericVersion, nil -} diff --git a/server/apparmor/apparmor_common.go b/server/apparmor/apparmor_common.go deleted file mode 100644 index 6366a66e6..000000000 --- a/server/apparmor/apparmor_common.go +++ /dev/null @@ -1,14 +0,0 @@ -package apparmor - -const ( - // DefaultApparmorProfile is the name of default apparmor profile name. - DefaultApparmorProfile = "crio-default" - - // ContainerAnnotationKeyPrefix is the prefix to an annotation key specifying a container profile. - ContainerAnnotationKeyPrefix = "container.apparmor.security.beta.kubernetes.io/" - - // ProfileRuntimeDefault is he profile specifying the runtime default. - ProfileRuntimeDefault = "runtime/default" - // ProfileNamePrefix is the prefix for specifying profiles loaded on the node. - ProfileNamePrefix = "localhost/" -) diff --git a/server/apparmor/apparmor_supported.go b/server/apparmor/apparmor_supported.go deleted file mode 100644 index d765c9de9..000000000 --- a/server/apparmor/apparmor_supported.go +++ /dev/null @@ -1,145 +0,0 @@ -// +build apparmor - -package apparmor - -import ( - "bufio" - "fmt" - "io" - "io/ioutil" - "os" - "path" - "strings" - - "github.com/docker/docker/utils/templates" - "github.com/opencontainers/runc/libcontainer/apparmor" -) - -const ( - // profileDirectory is the file store for apparmor profiles and macros. - profileDirectory = "/etc/apparmor.d" -) - -// profileData holds information about the given profile for generation. -type profileData struct { - // Name is profile name. - Name string - // Imports defines the apparmor functions to import, before defining the profile. - Imports []string - // InnerImports defines the apparmor functions to import in the profile. - InnerImports []string - // Version is the {major, minor, patch} version of apparmor_parser as a single number. - Version int -} - -// EnsureDefaultApparmorProfile loads default apparmor profile, if it is not loaded. -func EnsureDefaultApparmorProfile() error { - if apparmor.IsEnabled() { - loaded, err := IsLoaded(DefaultApparmorProfile) - if err != nil { - return fmt.Errorf("Could not check if %s AppArmor profile was loaded: %s", DefaultApparmorProfile, err) - } - - // Nothing to do. - if loaded { - return nil - } - - // Load the profile. - if err := InstallDefault(DefaultApparmorProfile); err != nil { - return fmt.Errorf("AppArmor enabled on system but the %s profile could not be loaded.", DefaultApparmorProfile) - } - } - - return nil -} - -// IsEnabled returns true if apparmor is enabled for the host. -func IsEnabled() bool { - return apparmor.IsEnabled() -} - -// GetProfileNameFromPodAnnotations gets the name of the profile to use with container from -// pod annotations -func GetProfileNameFromPodAnnotations(annotations map[string]string, containerName string) string { - return annotations[ContainerAnnotationKeyPrefix+containerName] -} - -// InstallDefault generates a default profile in a temp directory determined by -// os.TempDir(), then loads the profile into the kernel using 'apparmor_parser'. -func InstallDefault(name string) error { - p := profileData{ - Name: name, - } - - // Install to a temporary directory. - f, err := ioutil.TempFile("", name) - if err != nil { - return err - } - defer f.Close() - - if err := p.generateDefault(f); err != nil { - return err - } - - return LoadProfile(f.Name()) -} - -// IsLoaded checks if a profile with the given name has been loaded into the -// kernel. -func IsLoaded(name string) (bool, error) { - file, err := os.Open("/sys/kernel/security/apparmor/profiles") - if err != nil { - return false, err - } - defer file.Close() - - r := bufio.NewReader(file) - for { - p, err := r.ReadString('\n') - if err == io.EOF { - break - } - if err != nil { - return false, err - } - if strings.HasPrefix(p, name+" ") { - return true, nil - } - } - - return false, nil -} - -// generateDefault creates an apparmor profile from ProfileData. -func (p *profileData) generateDefault(out io.Writer) error { - compiled, err := templates.NewParse("apparmor_profile", baseTemplate) - if err != nil { - return err - } - - if macroExists("tunables/global") { - p.Imports = append(p.Imports, "#include <tunables/global>") - } else { - p.Imports = append(p.Imports, "@{PROC}=/proc/") - } - - if macroExists("abstractions/base") { - p.InnerImports = append(p.InnerImports, "#include <abstractions/base>") - } - - ver, err := GetVersion() - if err != nil { - return err - } - p.Version = ver - - return compiled.Execute(out, p) -} - -// macrosExists checks if the passed macro exists. -func macroExists(m string) bool { - _, err := os.Stat(path.Join(profileDirectory, m)) - return err == nil -} diff --git a/server/apparmor/apparmor_unsupported.go b/server/apparmor/apparmor_unsupported.go deleted file mode 100644 index fbd1d87a0..000000000 --- a/server/apparmor/apparmor_unsupported.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !apparmor - -package apparmor - -// IsEnabled returns false, when build without apparmor build tag. -func IsEnabled() bool { - return false -} - -// EnsureDefaultApparmorProfile dose nothing, when build without apparmor build tag. -func EnsureDefaultApparmorProfile() error { - return nil -} - -// GetProfileNameFromPodAnnotations dose nothing, when build without apparmor build tag. -func GetProfileNameFromPodAnnotations(annotations map[string]string, containerName string) string { - return "" -} diff --git a/server/apparmor/template.go b/server/apparmor/template.go deleted file mode 100644 index 6656ff61c..000000000 --- a/server/apparmor/template.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build apparmor - -package apparmor - -// baseTemplate defines the default apparmor profile for containers. -const baseTemplate = ` -{{range $value := .Imports}} -{{$value}} -{{end}} - -profile {{.Name}} flags=(attach_disconnected,mediate_deleted) { -{{range $value := .InnerImports}} - {{$value}} -{{end}} - - network, - capability, - file, - umount, - - deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir) - # deny write to files not in /proc/<number>/** or /proc/sys/** - deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w, - deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel) - deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/ - deny @{PROC}/sysrq-trigger rwklx, - deny @{PROC}/mem rwklx, - deny @{PROC}/kmem rwklx, - deny @{PROC}/kcore rwklx, - - deny mount, - - deny /sys/[^f]*/** wklx, - deny /sys/f[^s]*/** wklx, - deny /sys/fs/[^c]*/** wklx, - deny /sys/fs/c[^g]*/** wklx, - deny /sys/fs/cg[^r]*/** wklx, - deny /sys/firmware/** rwklx, - deny /sys/kernel/security/** rwklx, - -{{if ge .Version 208095}} - ptrace (trace,read) peer={{.Name}}, -{{end}} -} -` diff --git a/server/config.go b/server/config.go deleted file mode 100644 index 6c2d26cd0..000000000 --- a/server/config.go +++ /dev/null @@ -1,112 +0,0 @@ -package server - -import ( - "bytes" - "io/ioutil" - - "github.com/BurntSushi/toml" - "github.com/kubernetes-incubator/cri-o/libkpod" -) - -//CrioConfigPath is the default location for the conf file -const CrioConfigPath = "/etc/crio/crio.conf" - -// Config represents the entire set of configuration values that can be set for -// the server. This is intended to be loaded from a toml-encoded config file. -type Config struct { - libkpod.Config - APIConfig -} - -// APIConfig represents the "crio.api" TOML config table. -type APIConfig struct { - // Listen is the path to the AF_LOCAL socket on which cri-o will listen. - // This may support proto://addr formats later, but currently this is just - // a path. - Listen string `toml:"listen"` - - // StreamAddress is the IP address on which the stream server will listen. - StreamAddress string `toml:"stream_address"` - - // StreamPort is the port on which the stream server will listen. - StreamPort string `toml:"stream_port"` -} - -// tomlConfig is another way of looking at a Config, which is -// TOML-friendly (it has all of the explicit tables). It's just used for -// conversions. -type tomlConfig struct { - Crio struct { - libkpod.RootConfig - API struct{ APIConfig } `toml:"api"` - Runtime struct{ libkpod.RuntimeConfig } `toml:"runtime"` - Image struct{ libkpod.ImageConfig } `toml:"image"` - Network struct{ libkpod.NetworkConfig } `toml:"network"` - } `toml:"crio"` -} - -func (t *tomlConfig) toConfig(c *Config) { - c.RootConfig = t.Crio.RootConfig - c.APIConfig = t.Crio.API.APIConfig - c.RuntimeConfig = t.Crio.Runtime.RuntimeConfig - c.ImageConfig = t.Crio.Image.ImageConfig - c.NetworkConfig = t.Crio.Network.NetworkConfig -} - -func (t *tomlConfig) fromConfig(c *Config) { - t.Crio.RootConfig = c.RootConfig - t.Crio.API.APIConfig = c.APIConfig - t.Crio.Runtime.RuntimeConfig = c.RuntimeConfig - t.Crio.Image.ImageConfig = c.ImageConfig - t.Crio.Network.NetworkConfig = c.NetworkConfig -} - -// UpdateFromFile populates the Config from the TOML-encoded file at the given path. -// Returns errors encountered when reading or parsing the files, or nil -// otherwise. -func (c *Config) UpdateFromFile(path string) error { - data, err := ioutil.ReadFile(path) - if err != nil { - return err - } - - t := new(tomlConfig) - t.fromConfig(c) - - _, err = toml.Decode(string(data), t) - if err != nil { - return err - } - - t.toConfig(c) - return nil -} - -// ToFile outputs the given Config as a TOML-encoded file at the given path. -// Returns errors encountered when generating or writing the file, or nil -// otherwise. -func (c *Config) ToFile(path string) error { - var w bytes.Buffer - e := toml.NewEncoder(&w) - - t := new(tomlConfig) - t.fromConfig(c) - - if err := e.Encode(*t); err != nil { - return err - } - - return ioutil.WriteFile(path, w.Bytes(), 0644) -} - -// DefaultConfig returns the default configuration for crio. -func DefaultConfig() *Config { - return &Config{ - Config: *libkpod.DefaultConfig(), - APIConfig: APIConfig{ - Listen: "/var/run/crio.sock", - StreamAddress: "", - StreamPort: "10010", - }, - } -} diff --git a/server/container_attach.go b/server/container_attach.go deleted file mode 100644 index 6a822858d..000000000 --- a/server/container_attach.go +++ /dev/null @@ -1,147 +0,0 @@ -package server - -import ( - "fmt" - "io" - "net" - "os" - "path/filepath" - - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/utils" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "golang.org/x/sys/unix" - "k8s.io/client-go/tools/remotecommand" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" -) - -/* Sync with stdpipe_t in conmon.c */ -const ( - AttachPipeStdin = 1 - AttachPipeStdout = 2 - AttachPipeStderr = 3 -) - -// Attach prepares a streaming endpoint to attach to a running container. -func (s *Server) Attach(ctx context.Context, req *pb.AttachRequest) (*pb.AttachResponse, error) { - logrus.Debugf("AttachRequest %+v", req) - - resp, err := s.GetAttach(req) - if err != nil { - return nil, fmt.Errorf("unable to prepare attach endpoint") - } - - return resp, nil -} - -// Attach endpoint for streaming.Runtime -func (ss streamService) Attach(containerID string, inputStream io.Reader, outputStream, errorStream io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - c := ss.runtimeServer.GetContainer(containerID) - - if c == nil { - return fmt.Errorf("could not find container %q", containerID) - } - - if err := ss.runtimeServer.Runtime().UpdateStatus(c); err != nil { - return err - } - - cState := ss.runtimeServer.Runtime().ContainerStatus(c) - if !(cState.Status == oci.ContainerStateRunning || cState.Status == oci.ContainerStateCreated) { - return fmt.Errorf("container is not created or running") - } - - controlPath := filepath.Join(c.BundlePath(), "ctl") - controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0) - if err != nil { - return fmt.Errorf("failed to open container ctl file: %v", err) - } - - kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) { - logrus.Infof("Got a resize event: %+v", size) - _, err := fmt.Fprintf(controlFile, "%d %d %d\n", 1, size.Height, size.Width) - if err != nil { - logrus.Infof("Failed to write to control file to resize terminal: %v", err) - } - }) - - attachSocketPath := filepath.Join(oci.ContainerAttachSocketDir, c.ID(), "attach") - conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: attachSocketPath, Net: "unixpacket"}) - if err != nil { - return fmt.Errorf("failed to connect to container %s attach socket: %v", c.ID(), err) - } - defer conn.Close() - - receiveStdout := make(chan error) - if outputStream != nil || errorStream != nil { - go func() { - receiveStdout <- redirectResponseToOutputStreams(outputStream, errorStream, conn) - }() - } - - stdinDone := make(chan error) - go func() { - var err error - if inputStream != nil { - _, err = utils.CopyDetachable(conn, inputStream, nil) - conn.CloseWrite() - } - stdinDone <- err - }() - - select { - case err := <-receiveStdout: - return err - case err := <-stdinDone: - if _, ok := err.(utils.DetachError); ok { - return nil - } - if outputStream != nil || errorStream != nil { - return <-receiveStdout - } - } - - return nil -} - -func redirectResponseToOutputStreams(outputStream, errorStream io.Writer, conn io.Reader) error { - var err error - buf := make([]byte, 8192+1) /* Sync with conmon STDIO_BUF_SIZE */ - - for { - nr, er := conn.Read(buf) - if nr > 0 { - var dst io.Writer - if buf[0] == AttachPipeStdout { - dst = outputStream - } else if buf[0] == AttachPipeStderr { - dst = errorStream - } else { - logrus.Infof("Got unexpected attach type %+d", buf[0]) - } - - if dst != nil { - nw, ew := dst.Write(buf[1:nr]) - if ew != nil { - err = ew - break - } - if nr != nw+1 { - err = io.ErrShortWrite - break - } - } - } - if er == io.EOF { - break - } - if er != nil { - err = er - break - } - } - - return err -} diff --git a/server/container_create.go b/server/container_create.go deleted file mode 100644 index b28498c8d..000000000 --- a/server/container_create.go +++ /dev/null @@ -1,1215 +0,0 @@ -package server - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "os" - "path/filepath" - "regexp" - "sort" - "strconv" - "strings" - "time" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/symlink" - "github.com/kubernetes-incubator/cri-o/libkpod" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/pkg/annotations" - "github.com/kubernetes-incubator/cri-o/pkg/storage" - "github.com/kubernetes-incubator/cri-o/server/apparmor" - "github.com/kubernetes-incubator/cri-o/server/seccomp" - "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/devices" - "github.com/opencontainers/runc/libcontainer/user" - rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/runtime-tools/generate" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "golang.org/x/sys/unix" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -const ( - seccompUnconfined = "unconfined" - seccompRuntimeDefault = "runtime/default" - seccompDockerDefault = "docker/default" - seccompLocalhostPrefix = "localhost/" - - scopePrefix = "crio" - defaultCgroupfsParent = "/crio" - defaultSystemdParent = "system.slice" -) - -type orderedMounts []rspec.Mount - -// Len returns the number of mounts. Used in sorting. -func (m orderedMounts) Len() int { - return len(m) -} - -// Less returns true if the number of parts (a/b/c would be 3 parts) in the -// mount indexed by parameter 1 is less than that of the mount indexed by -// parameter 2. Used in sorting. -func (m orderedMounts) Less(i, j int) bool { - return m.parts(i) < m.parts(j) -} - -// Swap swaps two items in an array of mounts. Used in sorting -func (m orderedMounts) Swap(i, j int) { - m[i], m[j] = m[j], m[i] -} - -// parts returns the number of parts in the destination of a mount. Used in sorting. -func (m orderedMounts) parts(i int) int { - return strings.Count(filepath.Clean(m[i].Destination), string(os.PathSeparator)) -} - -func addOCIBindMounts(mountLabel string, containerConfig *pb.ContainerConfig, specgen *generate.Generator) ([]oci.ContainerVolume, []rspec.Mount, error) { - volumes := []oci.ContainerVolume{} - ociMounts := []rspec.Mount{} - mounts := containerConfig.GetMounts() - for _, mount := range mounts { - dest := mount.ContainerPath - if dest == "" { - return nil, nil, fmt.Errorf("Mount.ContainerPath is empty") - } - - src := mount.HostPath - if src == "" { - return nil, nil, fmt.Errorf("Mount.HostPath is empty") - } - - if _, err := os.Stat(src); err != nil && os.IsNotExist(err) { - if err1 := os.MkdirAll(src, 0644); err1 != nil { - return nil, nil, fmt.Errorf("Failed to mkdir %s: %s", src, err) - } - } - - src, err := resolveSymbolicLink(src) - if err != nil { - return nil, nil, fmt.Errorf("failed to resolve symlink %q: %v", src, err) - } - - options := []string{"rw"} - if mount.Readonly { - options = []string{"ro"} - } - options = append(options, []string{"rbind", "rprivate"}...) - - if mount.SelinuxRelabel { - // Need a way in kubernetes to determine if the volume is shared or private - if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP { - return nil, nil, fmt.Errorf("relabel failed %s: %v", src, err) - } - } - - volumes = append(volumes, oci.ContainerVolume{ - ContainerPath: dest, - HostPath: src, - Readonly: mount.Readonly, - }) - - ociMounts = append(ociMounts, rspec.Mount{ - Source: src, - Destination: dest, - Options: options, - }) - } - - return volumes, ociMounts, nil -} - -func addImageVolumes(rootfs string, s *Server, containerInfo *storage.ContainerInfo, specgen *generate.Generator, mountLabel string) ([]rspec.Mount, error) { - mounts := []rspec.Mount{} - for dest := range containerInfo.Config.Config.Volumes { - fp, err := symlink.FollowSymlinkInScope(filepath.Join(rootfs, dest), rootfs) - if err != nil { - return nil, err - } - switch s.config.ImageVolumes { - case libkpod.ImageVolumesMkdir: - if err1 := os.MkdirAll(fp, 0644); err1 != nil { - return nil, err1 - } - case libkpod.ImageVolumesBind: - volumeDirName := stringid.GenerateNonCryptoID() - src := filepath.Join(containerInfo.RunDir, "mounts", volumeDirName) - if err1 := os.MkdirAll(src, 0644); err1 != nil { - return nil, err1 - } - // Label the source with the sandbox selinux mount label - if mountLabel != "" { - if err1 := label.Relabel(src, mountLabel, true); err1 != nil && err1 != unix.ENOTSUP { - return nil, fmt.Errorf("relabel failed %s: %v", src, err1) - } - } - - logrus.Debugf("Adding bind mounted volume: %s to %s", src, dest) - mounts = append(mounts, rspec.Mount{ - Source: src, - Destination: dest, - Options: []string{"rw"}, - }) - - case libkpod.ImageVolumesIgnore: - logrus.Debugf("Ignoring volume %v", dest) - default: - logrus.Fatalf("Unrecognized image volumes setting") - } - } - return mounts, nil -} - -// resolveSymbolicLink resolves a possbile symlink path. If the path is a symlink, returns resolved -// path; if not, returns the original path. -func resolveSymbolicLink(path string) (string, error) { - info, err := os.Lstat(path) - if err != nil { - return "", err - } - if info.Mode()&os.ModeSymlink != os.ModeSymlink { - return path, nil - } - return filepath.EvalSymlinks(path) -} - -func addDevices(sb *sandbox.Sandbox, containerConfig *pb.ContainerConfig, specgen *generate.Generator) error { - sp := specgen.Spec() - if containerConfig.GetLinux().GetSecurityContext().GetPrivileged() { - hostDevices, err := devices.HostDevices() - if err != nil { - return err - } - for _, hostDevice := range hostDevices { - rd := rspec.LinuxDevice{ - Path: hostDevice.Path, - Type: string(hostDevice.Type), - Major: hostDevice.Major, - Minor: hostDevice.Minor, - UID: &hostDevice.Uid, - GID: &hostDevice.Gid, - } - if hostDevice.Major == 0 && hostDevice.Minor == 0 { - // Invalid device, most likely a symbolic link, skip it. - continue - } - specgen.AddDevice(rd) - } - sp.Linux.Resources.Devices = []rspec.LinuxDeviceCgroup{ - { - Allow: true, - Access: "rwm", - }, - } - return nil - } - for _, device := range containerConfig.GetDevices() { - path, err := resolveSymbolicLink(device.HostPath) - if err != nil { - return err - } - dev, err := devices.DeviceFromPath(path, device.Permissions) - // if there was no error, return the device - if err == nil { - rd := rspec.LinuxDevice{ - Path: device.ContainerPath, - Type: string(dev.Type), - Major: dev.Major, - Minor: dev.Minor, - UID: &dev.Uid, - GID: &dev.Gid, - } - specgen.AddDevice(rd) - sp.Linux.Resources.Devices = append(sp.Linux.Resources.Devices, rspec.LinuxDeviceCgroup{ - Allow: true, - Type: string(dev.Type), - Major: &dev.Major, - Minor: &dev.Minor, - Access: dev.Permissions, - }) - continue - } - // if the device is not a device node - // try to see if it's a directory holding many devices - if err == devices.ErrNotADevice { - - // check if it is a directory - if src, e := os.Stat(path); e == nil && src.IsDir() { - - // mount the internal devices recursively - filepath.Walk(path, func(dpath string, f os.FileInfo, e error) error { - childDevice, e := devices.DeviceFromPath(dpath, device.Permissions) - if e != nil { - // ignore the device - return nil - } - cPath := strings.Replace(dpath, path, device.ContainerPath, 1) - rd := rspec.LinuxDevice{ - Path: cPath, - Type: string(childDevice.Type), - Major: childDevice.Major, - Minor: childDevice.Minor, - UID: &childDevice.Uid, - GID: &childDevice.Gid, - } - specgen.AddDevice(rd) - sp.Linux.Resources.Devices = append(sp.Linux.Resources.Devices, rspec.LinuxDeviceCgroup{ - Allow: true, - Type: string(childDevice.Type), - Major: &childDevice.Major, - Minor: &childDevice.Minor, - Access: childDevice.Permissions, - }) - - return nil - }) - } - } - } - return nil -} - -// buildOCIProcessArgs build an OCI compatible process arguments slice. -func buildOCIProcessArgs(containerKubeConfig *pb.ContainerConfig, imageOCIConfig *v1.Image) ([]string, error) { - //# Start the nginx container using the default command, but use custom - //arguments (arg1 .. argN) for that command. - //kubectl run nginx --image=nginx -- <arg1> <arg2> ... <argN> - - //# Start the nginx container using a different command and custom arguments. - //kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN> - - kubeCommands := containerKubeConfig.Command - kubeArgs := containerKubeConfig.Args - - // merge image config and kube config - // same as docker does today... - if imageOCIConfig != nil { - if len(kubeCommands) == 0 { - if len(kubeArgs) == 0 { - kubeArgs = imageOCIConfig.Config.Cmd - } - if kubeCommands == nil { - kubeCommands = imageOCIConfig.Config.Entrypoint - } - } - } - - if len(kubeCommands) == 0 && len(kubeArgs) == 0 { - return nil, fmt.Errorf("no command specified") - } - - // create entrypoint and args - var entrypoint string - var args []string - if len(kubeCommands) != 0 { - entrypoint = kubeCommands[0] - args = append(kubeCommands[1:], kubeArgs...) - } else { - entrypoint = kubeArgs[0] - args = kubeArgs[1:] - } - - processArgs := append([]string{entrypoint}, args...) - - logrus.Debugf("OCI process args %v", processArgs) - - return processArgs, nil -} - -// addOCIHook look for hooks programs installed in hooksDirPath and add them to spec -func addOCIHook(specgen *generate.Generator, hook libkpod.HookParams) error { - logrus.Debugf("AddOCIHook", hook) - for _, stage := range hook.Stage { - switch stage { - case "prestart": - specgen.AddPreStartHook(hook.Hook, []string{hook.Hook, "prestart"}) - - case "poststart": - specgen.AddPostStartHook(hook.Hook, []string{hook.Hook, "poststart"}) - - case "poststop": - specgen.AddPostStopHook(hook.Hook, []string{hook.Hook, "poststop"}) - } - } - return nil -} - -// setupContainerUser sets the UID, GID and supplemental groups in OCI runtime config -func setupContainerUser(specgen *generate.Generator, rootfs string, sc *pb.LinuxContainerSecurityContext, imageConfig *v1.Image) error { - if sc != nil { - containerUser := "" - // Case 1: run as user is set by kubelet - if sc.GetRunAsUser() != nil { - containerUser = strconv.FormatInt(sc.GetRunAsUser().Value, 10) - } else { - // Case 2: run as username is set by kubelet - userName := sc.GetRunAsUsername() - if userName != "" { - containerUser = userName - } else { - // Case 3: get user from image config - if imageConfig != nil { - imageUser := imageConfig.Config.User - if imageUser != "" { - containerUser = imageUser - } - } - } - } - - logrus.Debugf("CONTAINER USER: %+v", containerUser) - - // Add uid, gid and groups from user - uid, gid, addGroups, err1 := getUserInfo(rootfs, containerUser) - if err1 != nil { - return err1 - } - - logrus.Debugf("UID: %v, GID: %v, Groups: %+v", uid, gid, addGroups) - specgen.SetProcessUID(uid) - specgen.SetProcessGID(gid) - for _, group := range addGroups { - specgen.AddProcessAdditionalGid(group) - } - - // Add groups from CRI - groups := sc.GetSupplementalGroups() - for _, group := range groups { - specgen.AddProcessAdditionalGid(uint32(group)) - } - } - return nil -} - -func hostNetwork(containerConfig *pb.ContainerConfig) bool { - securityContext := containerConfig.GetLinux().GetSecurityContext() - if securityContext == nil || securityContext.GetNamespaceOptions() == nil { - return false - } - - return securityContext.GetNamespaceOptions().HostNetwork -} - -// ensureSaneLogPath is a hack to fix https://issues.k8s.io/44043 which causes -// logPath to be a broken symlink to some magical Docker path. Ideally we -// wouldn't have to deal with this, but until that issue is fixed we have to -// remove the path if it's a broken symlink. -func ensureSaneLogPath(logPath string) error { - // If the path exists but the resolved path does not, then we have a broken - // symlink and we need to remove it. - fi, err := os.Lstat(logPath) - if err != nil || fi.Mode()&os.ModeSymlink == 0 { - // Non-existent files and non-symlinks aren't our problem. - return nil - } - - _, err = os.Stat(logPath) - if os.IsNotExist(err) { - err = os.RemoveAll(logPath) - if err != nil { - return fmt.Errorf("ensureSaneLogPath remove bad logPath: %s", err) - } - } - return nil -} - -// addSecretsBindMounts mounts user defined secrets to the container -func addSecretsBindMounts(mountLabel, ctrRunDir string, defaultMounts []string, specgen generate.Generator) ([]rspec.Mount, error) { - containerMounts := specgen.Spec().Mounts - mounts, err := secretMounts(defaultMounts, mountLabel, ctrRunDir, containerMounts) - if err != nil { - return nil, err - } - return mounts, nil -} - -// CreateContainer creates a new container in specified PodSandbox -func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerRequest) (res *pb.CreateContainerResponse, err error) { - logrus.Debugf("CreateContainerRequest %+v", req) - - s.updateLock.RLock() - defer s.updateLock.RUnlock() - - sbID := req.PodSandboxId - if sbID == "" { - return nil, fmt.Errorf("PodSandboxId should not be empty") - } - - sandboxID, err := s.PodIDIndex().Get(sbID) - if err != nil { - return nil, fmt.Errorf("PodSandbox with ID starting with %s not found: %v", sbID, err) - } - - sb := s.getSandbox(sandboxID) - if sb == nil { - return nil, fmt.Errorf("specified sandbox not found: %s", sandboxID) - } - - // The config of the container - containerConfig := req.GetConfig() - if containerConfig == nil { - return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig is nil") - } - - name := containerConfig.GetMetadata().Name - if name == "" { - return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig.Name is empty") - } - - containerID, containerName, err := s.generateContainerIDandName(sb.Metadata(), containerConfig) - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - s.ReleaseContainerName(containerName) - } - }() - - container, err := s.createSandboxContainer(ctx, containerID, containerName, sb, req.GetSandboxConfig(), containerConfig) - if err != nil { - return nil, err - } - defer func() { - if err != nil { - err2 := s.StorageRuntimeServer().DeleteContainer(containerID) - if err2 != nil { - logrus.Warnf("Failed to cleanup container directory: %v", err2) - } - } - }() - - if err = s.Runtime().CreateContainer(container, sb.CgroupParent()); err != nil { - return nil, err - } - - s.addContainer(container) - - if err = s.CtrIDIndex().Add(containerID); err != nil { - s.removeContainer(container) - return nil, err - } - - s.ContainerStateToDisk(container) - - resp := &pb.CreateContainerResponse{ - ContainerId: containerID, - } - - logrus.Debugf("CreateContainerResponse: %+v", resp) - return resp, nil -} - -func (s *Server) setupOCIHooks(specgen *generate.Generator, sb *sandbox.Sandbox, containerConfig *pb.ContainerConfig, command string) error { - mounts := containerConfig.GetMounts() - addedHooks := map[string]struct{}{} - addHook := func(hook libkpod.HookParams) error { - // Only add a hook once - if _, ok := addedHooks[hook.Hook]; !ok { - if err := addOCIHook(specgen, hook); err != nil { - return err - } - addedHooks[hook.Hook] = struct{}{} - } - return nil - } - for _, hook := range s.Hooks() { - logrus.Debugf("SetupOCIHooks", hook) - if hook.HasBindMounts && len(mounts) > 0 { - if err := addHook(hook); err != nil { - return err - } - continue - } - for _, cmd := range hook.Cmds { - match, err := regexp.MatchString(cmd, command) - if err != nil { - logrus.Errorf("Invalid regex %q:%q", cmd, err) - continue - } - if match { - if err := addHook(hook); err != nil { - return err - } - } - } - for _, annotationRegex := range hook.Annotations { - for _, annotation := range sb.Annotations() { - match, err := regexp.MatchString(annotationRegex, annotation) - if err != nil { - logrus.Errorf("Invalid regex %q:%q", annotationRegex, err) - continue - } - if match { - if err := addHook(hook); err != nil { - return err - } - } - } - } - } - return nil -} -func (s *Server) createSandboxContainer(ctx context.Context, containerID string, containerName string, sb *sandbox.Sandbox, SandboxConfig *pb.PodSandboxConfig, containerConfig *pb.ContainerConfig) (*oci.Container, error) { - if sb == nil { - return nil, errors.New("createSandboxContainer needs a sandbox") - } - - // TODO: simplify this function (cyclomatic complexity here is high) - // TODO: factor generating/updating the spec into something other projects can vendor - - // creates a spec Generator with the default spec. - specgen := generate.New() - specgen.HostSpecific = true - specgen.ClearProcessRlimits() - - var readOnlyRootfs bool - var privileged bool - if containerConfig.GetLinux().GetSecurityContext() != nil { - if containerConfig.GetLinux().GetSecurityContext().Privileged { - privileged = true - } - - if containerConfig.GetLinux().GetSecurityContext().ReadonlyRootfs { - readOnlyRootfs = true - specgen.SetRootReadonly(true) - } - } - - mountLabel := sb.MountLabel() - processLabel := sb.ProcessLabel() - selinuxConfig := containerConfig.GetLinux().GetSecurityContext().GetSelinuxOptions() - if selinuxConfig != nil { - var err error - processLabel, mountLabel, err = getSELinuxLabels(selinuxConfig, privileged) - if err != nil { - return nil, err - } - } - - containerVolumes, ociMounts, err := addOCIBindMounts(mountLabel, containerConfig, &specgen) - if err != nil { - return nil, err - } - - volumesJSON, err := json.Marshal(containerVolumes) - if err != nil { - return nil, err - } - specgen.AddAnnotation(annotations.Volumes, string(volumesJSON)) - - // Add cgroup mount so container process can introspect its own limits - specgen.AddCgroupsMount("ro") - - if err := addDevices(sb, containerConfig, &specgen); err != nil { - return nil, err - } - - labels := containerConfig.GetLabels() - - metadata := containerConfig.GetMetadata() - - kubeAnnotations := containerConfig.GetAnnotations() - if kubeAnnotations != nil { - for k, v := range kubeAnnotations { - specgen.AddAnnotation(k, v) - } - } - if labels != nil { - for k, v := range labels { - specgen.AddAnnotation(k, v) - } - } - - // set this container's apparmor profile if it is set by sandbox - if s.appArmorEnabled && !privileged { - appArmorProfileName := s.getAppArmorProfileName(sb.Annotations(), metadata.Name) - if appArmorProfileName != "" { - // reload default apparmor profile if it is unloaded. - if s.appArmorProfile == apparmor.DefaultApparmorProfile { - if err := apparmor.EnsureDefaultApparmorProfile(); err != nil { - return nil, err - } - } - - specgen.SetProcessApparmorProfile(appArmorProfileName) - } - } - - logPath := containerConfig.LogPath - if logPath == "" { - // TODO: Should we use sandboxConfig.GetLogDirectory() here? - logPath = filepath.Join(sb.LogDir(), containerID+".log") - } - if !filepath.IsAbs(logPath) { - // XXX: It's not really clear what this should be versus the sbox logDirectory. - logrus.Warnf("requested logPath for ctr id %s is a relative path: %s", containerID, logPath) - logPath = filepath.Join(sb.LogDir(), logPath) - } - - // Handle https://issues.k8s.io/44043 - if err := ensureSaneLogPath(logPath); err != nil { - return nil, err - } - - logrus.WithFields(logrus.Fields{ - "sbox.logdir": sb.LogDir(), - "ctr.logfile": containerConfig.LogPath, - "log_path": logPath, - }).Debugf("setting container's log_path") - - specgen.SetProcessTerminal(containerConfig.Tty) - if containerConfig.Tty { - specgen.AddProcessEnv("TERM", "xterm") - } - - linux := containerConfig.GetLinux() - if linux != nil { - resources := linux.GetResources() - if resources != nil { - cpuPeriod := resources.CpuPeriod - if cpuPeriod != 0 { - specgen.SetLinuxResourcesCPUPeriod(uint64(cpuPeriod)) - } - - cpuQuota := resources.CpuQuota - if cpuQuota != 0 { - specgen.SetLinuxResourcesCPUQuota(cpuQuota) - } - - cpuShares := resources.CpuShares - if cpuShares != 0 { - specgen.SetLinuxResourcesCPUShares(uint64(cpuShares)) - } - - memoryLimit := resources.MemoryLimitInBytes - if memoryLimit != 0 { - specgen.SetLinuxResourcesMemoryLimit(memoryLimit) - } - - oomScoreAdj := resources.OomScoreAdj - specgen.SetProcessOOMScoreAdj(int(oomScoreAdj)) - } - - var cgPath string - parent := defaultCgroupfsParent - useSystemd := s.config.CgroupManager == oci.SystemdCgroupsManager - if useSystemd { - parent = defaultSystemdParent - } - if sb.CgroupParent() != "" { - parent = sb.CgroupParent() - } - if useSystemd { - cgPath = parent + ":" + scopePrefix + ":" + containerID - } else { - cgPath = filepath.Join(parent, scopePrefix+"-"+containerID) - } - specgen.SetLinuxCgroupsPath(cgPath) - - capabilities := linux.GetSecurityContext().GetCapabilities() - if privileged { - // this is setting correct capabilities as well for privileged mode - specgen.SetupPrivileged(true) - setOCIBindMountsPrivileged(&specgen) - } else { - toCAPPrefixed := func(cap string) string { - if !strings.HasPrefix(strings.ToLower(cap), "cap_") { - return "CAP_" + strings.ToUpper(cap) - } - return cap - } - - // Add/drop all capabilities if "all" is specified, so that - // following individual add/drop could still work. E.g. - // AddCapabilities: []string{"ALL"}, DropCapabilities: []string{"CHOWN"} - // will be all capabilities without `CAP_CHOWN`. - // see https://github.com/kubernetes/kubernetes/issues/51980 - if inStringSlice(capabilities.GetAddCapabilities(), "ALL") { - for _, c := range getOCICapabilitiesList() { - if err := specgen.AddProcessCapability(c); err != nil { - return nil, err - } - } - } - if inStringSlice(capabilities.GetDropCapabilities(), "ALL") { - for _, c := range getOCICapabilitiesList() { - if err := specgen.DropProcessCapability(c); err != nil { - return nil, err - } - } - } - - if capabilities != nil { - for _, cap := range capabilities.GetAddCapabilities() { - if strings.ToUpper(cap) == "ALL" { - continue - } - if err := specgen.AddProcessCapability(toCAPPrefixed(cap)); err != nil { - return nil, err - } - } - - for _, cap := range capabilities.GetDropCapabilities() { - if strings.ToUpper(cap) == "ALL" { - continue - } - if err := specgen.DropProcessCapability(toCAPPrefixed(cap)); err != nil { - return nil, fmt.Errorf("failed to drop cap %s %v", toCAPPrefixed(cap), err) - } - } - } - } - specgen.SetProcessSelinuxLabel(processLabel) - specgen.SetLinuxMountLabel(mountLabel) - - if containerConfig.GetLinux().GetSecurityContext() != nil && - !containerConfig.GetLinux().GetSecurityContext().Privileged { - for _, mp := range []string{ - "/proc/kcore", - "/proc/latency_stats", - "/proc/timer_list", - "/proc/timer_stats", - "/proc/sched_debug", - "/sys/firmware", - } { - specgen.AddLinuxMaskedPaths(mp) - } - - for _, rp := range []string{ - "/proc/asound", - "/proc/bus", - "/proc/fs", - "/proc/irq", - "/proc/sys", - "/proc/sysrq-trigger", - } { - specgen.AddLinuxReadonlyPaths(rp) - } - } - } - // Join the namespace paths for the pod sandbox container. - podInfraState := s.Runtime().ContainerStatus(sb.InfraContainer()) - - logrus.Debugf("pod container state %+v", podInfraState) - - ipcNsPath := fmt.Sprintf("/proc/%d/ns/ipc", podInfraState.Pid) - if err := specgen.AddOrReplaceLinuxNamespace(string(rspec.IPCNamespace), ipcNsPath); err != nil { - return nil, err - } - - utsNsPath := fmt.Sprintf("/proc/%d/ns/uts", podInfraState.Pid) - if err := specgen.AddOrReplaceLinuxNamespace(string(rspec.UTSNamespace), utsNsPath); err != nil { - return nil, err - } - - // Do not share pid ns for now - if containerConfig.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostPid() { - specgen.RemoveLinuxNamespace(string(rspec.PIDNamespace)) - } - - netNsPath := sb.NetNsPath() - if netNsPath == "" { - // The sandbox does not have a permanent namespace, - // it's on the host one. - netNsPath = fmt.Sprintf("/proc/%d/ns/net", podInfraState.Pid) - } - - if err := specgen.AddOrReplaceLinuxNamespace(string(rspec.NetworkNamespace), netNsPath); err != nil { - return nil, err - } - - imageSpec := containerConfig.GetImage() - if imageSpec == nil { - return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig.Image is nil") - } - - image := imageSpec.Image - if image == "" { - return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig.Image.Image is empty") - } - images, err := s.StorageImageServer().ResolveNames(image) - if err != nil { - // This means we got an image ID - if strings.Contains(err.Error(), "cannot specify 64-byte hexadecimal strings") { - images = append(images, image) - } else { - return nil, err - } - } - image = images[0] - - // Get imageName and imageRef that are requested in container status - imageName := image - status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), image) - if err != nil { - return nil, err - } - - imageRef := status.ID - // - // TODO: https://github.com/kubernetes-incubator/cri-o/issues/531 - // - //for _, n := range status.Names { - //r, err := reference.ParseNormalizedNamed(n) - //if err != nil { - //return nil, fmt.Errorf("failed to normalize image name for ImageRef: %v", err) - //} - //if digested, isDigested := r.(reference.Canonical); isDigested { - //imageRef = reference.FamiliarString(digested) - //break - //} - //} - for _, n := range status.Names { - r, err := reference.ParseNormalizedNamed(n) - if err != nil { - return nil, fmt.Errorf("failed to normalize image name for Image: %v", err) - } - if tagged, isTagged := r.(reference.Tagged); isTagged { - imageName = reference.FamiliarString(tagged) - break - } - } - - specgen.AddAnnotation(annotations.ImageName, imageName) - specgen.AddAnnotation(annotations.ImageRef, imageRef) - specgen.AddAnnotation(annotations.IP, sb.IP()) - - // bind mount the pod shm - specgen.AddBindMount(sb.ShmPath(), "/dev/shm", []string{"rw"}) - - options := []string{"rw"} - if readOnlyRootfs { - options = []string{"ro"} - } - if sb.ResolvPath() != "" { - if err := label.Relabel(sb.ResolvPath(), mountLabel, true); err != nil && err != unix.ENOTSUP { - return nil, err - } - - // bind mount the pod resolver file - specgen.AddBindMount(sb.ResolvPath(), "/etc/resolv.conf", options) - } - - if sb.HostnamePath() != "" { - if err := label.Relabel(sb.HostnamePath(), mountLabel, true); err != nil && err != unix.ENOTSUP { - return nil, err - } - - specgen.AddBindMount(sb.HostnamePath(), "/etc/hostname", options) - } - - // Bind mount /etc/hosts for host networking containers - if hostNetwork(containerConfig) { - specgen.AddBindMount("/etc/hosts", "/etc/hosts", options) - } - - specgen.SetHostname(sb.Hostname()) - - specgen.AddAnnotation(annotations.Name, containerName) - specgen.AddAnnotation(annotations.ContainerID, containerID) - specgen.AddAnnotation(annotations.SandboxID, sb.ID()) - specgen.AddAnnotation(annotations.SandboxName, sb.InfraContainer().Name()) - specgen.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer) - specgen.AddAnnotation(annotations.LogPath, logPath) - specgen.AddAnnotation(annotations.TTY, fmt.Sprintf("%v", containerConfig.Tty)) - specgen.AddAnnotation(annotations.Stdin, fmt.Sprintf("%v", containerConfig.Stdin)) - specgen.AddAnnotation(annotations.StdinOnce, fmt.Sprintf("%v", containerConfig.StdinOnce)) - specgen.AddAnnotation(annotations.Image, image) - specgen.AddAnnotation(annotations.ResolvPath, sb.InfraContainer().CrioAnnotations()[annotations.ResolvPath]) - - created := time.Now() - specgen.AddAnnotation(annotations.Created, created.Format(time.RFC3339Nano)) - - metadataJSON, err := json.Marshal(metadata) - if err != nil { - return nil, err - } - specgen.AddAnnotation(annotations.Metadata, string(metadataJSON)) - - labelsJSON, err := json.Marshal(labels) - if err != nil { - return nil, err - } - specgen.AddAnnotation(annotations.Labels, string(labelsJSON)) - - kubeAnnotationsJSON, err := json.Marshal(kubeAnnotations) - if err != nil { - return nil, err - } - specgen.AddAnnotation(annotations.Annotations, string(kubeAnnotationsJSON)) - - metaname := metadata.Name - if !privileged { - if err = s.setupSeccomp(&specgen, metaname, sb.Annotations()); err != nil { - return nil, err - } - } - - attempt := metadata.Attempt - containerInfo, err := s.StorageRuntimeServer().CreateContainer(s.ImageContext(), - sb.Name(), sb.ID(), - image, image, - containerName, containerID, - metaname, - attempt, - mountLabel, - nil) - if err != nil { - return nil, err - } - - mountPoint, err := s.StorageRuntimeServer().StartContainer(containerID) - if err != nil { - return nil, fmt.Errorf("failed to mount container %s(%s): %v", containerName, containerID, err) - } - specgen.AddAnnotation(annotations.MountPoint, mountPoint) - - containerImageConfig := containerInfo.Config - if containerImageConfig == nil { - return nil, fmt.Errorf("empty image config for %s", image) - } - - if containerImageConfig.Config.StopSignal != "" { - // this key is defined in image-spec conversion document at https://github.com/opencontainers/image-spec/pull/492/files#diff-8aafbe2c3690162540381b8cdb157112R57 - specgen.AddAnnotation("org.opencontainers.image.stopSignal", containerImageConfig.Config.StopSignal) - } - - // Add image volumes - volumeMounts, err := addImageVolumes(mountPoint, s, &containerInfo, &specgen, mountLabel) - if err != nil { - return nil, err - } - - processArgs, err := buildOCIProcessArgs(containerConfig, containerImageConfig) - if err != nil { - return nil, err - } - specgen.SetProcessArgs(processArgs) - - // Add environment variables from CRI and image config - envs := containerConfig.GetEnvs() - if envs != nil { - for _, item := range envs { - key := item.Key - value := item.Value - if key == "" { - continue - } - specgen.AddProcessEnv(key, value) - } - } - if containerImageConfig != nil { - for _, item := range containerImageConfig.Config.Env { - parts := strings.SplitN(item, "=", 2) - if len(parts) != 2 { - return nil, fmt.Errorf("invalid env from image: %s", item) - } - - if parts[0] == "" { - continue - } - specgen.AddProcessEnv(parts[0], parts[1]) - } - } - - // Set working directory - // Pick it up from image config first and override if specified in CRI - containerCwd := "/" - if containerImageConfig != nil { - imageCwd := containerImageConfig.Config.WorkingDir - if imageCwd != "" { - containerCwd = imageCwd - } - } - runtimeCwd := containerConfig.WorkingDir - if runtimeCwd != "" { - containerCwd = runtimeCwd - } - specgen.SetProcessCwd(containerCwd) - - var secretMounts []rspec.Mount - if len(s.config.DefaultMounts) > 0 { - var err error - secretMounts, err = addSecretsBindMounts(mountLabel, containerInfo.RunDir, s.config.DefaultMounts, specgen) - if err != nil { - return nil, fmt.Errorf("failed to mount secrets: %v", err) - } - } - - mounts := []rspec.Mount{} - mounts = append(mounts, ociMounts...) - mounts = append(mounts, volumeMounts...) - mounts = append(mounts, secretMounts...) - - sort.Sort(orderedMounts(mounts)) - - for _, m := range mounts { - specgen.AddBindMount(m.Source, m.Destination, m.Options) - } - - if err := s.setupOCIHooks(&specgen, sb, containerConfig, processArgs[0]); err != nil { - return nil, err - } - - // Setup user and groups - if linux != nil { - if err = setupContainerUser(&specgen, mountPoint, linux.GetSecurityContext(), containerImageConfig); err != nil { - return nil, err - } - } - - // Set up pids limit if pids cgroup is mounted - _, err = cgroups.FindCgroupMountpoint("pids") - if err == nil { - specgen.SetLinuxResourcesPidsLimit(s.config.PidsLimit) - } - - // by default, the root path is an empty string. set it now. - specgen.SetRootPath(mountPoint) - - saveOptions := generate.ExportOptions{} - if err = specgen.SaveToFile(filepath.Join(containerInfo.Dir, "config.json"), saveOptions); err != nil { - return nil, err - } - if err = specgen.SaveToFile(filepath.Join(containerInfo.RunDir, "config.json"), saveOptions); err != nil { - return nil, err - } - - crioAnnotations := specgen.Spec().Annotations - - container, err := oci.NewContainer(containerID, containerName, containerInfo.RunDir, logPath, sb.NetNs(), labels, crioAnnotations, kubeAnnotations, image, imageName, imageRef, metadata, sb.ID(), containerConfig.Tty, containerConfig.Stdin, containerConfig.StdinOnce, sb.Privileged(), sb.Trusted(), containerInfo.Dir, created, containerImageConfig.Config.StopSignal) - if err != nil { - return nil, err - } - container.SetSpec(specgen.Spec()) - container.SetMountPoint(mountPoint) - - for _, cv := range containerVolumes { - container.AddVolume(cv) - } - - return container, nil -} - -func (s *Server) setupSeccomp(specgen *generate.Generator, cname string, sbAnnotations map[string]string) error { - profile, ok := sbAnnotations["container.seccomp.security.alpha.kubernetes.io/"+cname] - if !ok { - profile, ok = sbAnnotations["seccomp.security.alpha.kubernetes.io/pod"] - if !ok { - // running w/o seccomp, aka unconfined - profile = seccompUnconfined - } - } - if !s.seccompEnabled { - if profile != seccompUnconfined { - return fmt.Errorf("seccomp is not enabled in your kernel, cannot run with a profile") - } - logrus.Warn("seccomp is not enabled in your kernel, running container without profile") - } - if profile == seccompUnconfined { - // running w/o seccomp, aka unconfined - specgen.Spec().Linux.Seccomp = nil - return nil - } - if profile == seccompRuntimeDefault || profile == seccompDockerDefault { - return seccomp.LoadProfileFromStruct(s.seccompProfile, specgen) - } - if !strings.HasPrefix(profile, seccompLocalhostPrefix) { - return fmt.Errorf("unknown seccomp profile option: %q", profile) - } - // FIXME: https://github.com/kubernetes/kubernetes/issues/39128 - return nil -} - -// getAppArmorProfileName gets the profile name for the given container. -func (s *Server) getAppArmorProfileName(annotations map[string]string, ctrName string) string { - profile := apparmor.GetProfileNameFromPodAnnotations(annotations, ctrName) - - if profile == "" { - return "" - } - - if profile == apparmor.ProfileRuntimeDefault { - // If the value is runtime/default, then return default profile. - return s.appArmorProfile - } - - return strings.TrimPrefix(profile, apparmor.ProfileNamePrefix) -} - -// openContainerFile opens a file inside a container rootfs safely -func openContainerFile(rootfs string, path string) (io.ReadCloser, error) { - fp, err := symlink.FollowSymlinkInScope(filepath.Join(rootfs, path), rootfs) - if err != nil { - return nil, err - } - return os.Open(fp) -} - -// getUserInfo returns UID, GID and additional groups for specified user -// by looking them up in /etc/passwd and /etc/group -func getUserInfo(rootfs string, userName string) (uint32, uint32, []uint32, error) { - // We don't care if we can't open the file because - // not all images will have these files - passwdFile, err := openContainerFile(rootfs, "/etc/passwd") - if err != nil { - logrus.Warnf("Failed to open /etc/passwd: %v", err) - } else { - defer passwdFile.Close() - } - - groupFile, err := openContainerFile(rootfs, "/etc/group") - if err != nil { - logrus.Warnf("Failed to open /etc/group: %v", err) - } else { - defer groupFile.Close() - } - - execUser, err := user.GetExecUser(userName, nil, passwdFile, groupFile) - if err != nil { - return 0, 0, nil, err - } - - uid := uint32(execUser.Uid) - gid := uint32(execUser.Gid) - var additionalGids []uint32 - for _, g := range execUser.Sgids { - additionalGids = append(additionalGids, uint32(g)) - } - - return uid, gid, additionalGids, nil -} - -func setOCIBindMountsPrivileged(g *generate.Generator) { - spec := g.Spec() - // clear readonly for /sys and cgroup - for i, m := range spec.Mounts { - if spec.Mounts[i].Destination == "/sys" && !spec.Root.Readonly { - clearReadOnly(&spec.Mounts[i]) - } - if m.Type == "cgroup" { - clearReadOnly(&spec.Mounts[i]) - } - } - spec.Linux.ReadonlyPaths = nil - spec.Linux.MaskedPaths = nil -} - -func clearReadOnly(m *rspec.Mount) { - var opt []string - for _, o := range m.Options { - if o != "ro" { - opt = append(opt, o) - } - } - m.Options = opt -} diff --git a/server/container_exec.go b/server/container_exec.go deleted file mode 100644 index 0cdb9579e..000000000 --- a/server/container_exec.go +++ /dev/null @@ -1,108 +0,0 @@ -package server - -import ( - "fmt" - "io" - "os" - "os/exec" - - "github.com/docker/docker/pkg/pools" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "k8s.io/client-go/tools/remotecommand" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" - utilexec "k8s.io/kubernetes/pkg/util/exec" - "k8s.io/kubernetes/pkg/util/term" -) - -// Exec prepares a streaming endpoint to execute a command in the container. -func (s *Server) Exec(ctx context.Context, req *pb.ExecRequest) (*pb.ExecResponse, error) { - logrus.Debugf("ExecRequest %+v", req) - - resp, err := s.GetExec(req) - if err != nil { - return nil, fmt.Errorf("unable to prepare exec endpoint") - } - - return resp, nil -} - -// Exec endpoint for streaming.Runtime -func (ss streamService) Exec(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error { - c := ss.runtimeServer.GetContainer(containerID) - - if c == nil { - return fmt.Errorf("could not find container %q", containerID) - } - - if err := ss.runtimeServer.Runtime().UpdateStatus(c); err != nil { - return err - } - - cState := ss.runtimeServer.Runtime().ContainerStatus(c) - if !(cState.Status == oci.ContainerStateRunning || cState.Status == oci.ContainerStateCreated) { - return fmt.Errorf("container is not created or running") - } - - args := []string{"exec"} - if tty { - args = append(args, "-t") - } - args = append(args, c.ID()) - args = append(args, cmd...) - execCmd := exec.Command(ss.runtimeServer.Runtime().Path(c), args...) - var cmdErr error - if tty { - p, err := kubecontainer.StartPty(execCmd) - if err != nil { - return err - } - defer p.Close() - - // make sure to close the stdout stream - defer stdout.Close() - - kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) { - term.SetSize(p.Fd(), size) - }) - - if stdin != nil { - go pools.Copy(p, stdin) - } - - if stdout != nil { - go pools.Copy(stdout, p) - } - - cmdErr = execCmd.Wait() - } else { - if stdin != nil { - // Use an os.Pipe here as it returns true *os.File objects. - // This way, if you run 'kubectl exec <pod> -i bash' (no tty) and type 'exit', - // the call below to execCmd.Run() can unblock because its Stdin is the read half - // of the pipe. - r, w, err := os.Pipe() - if err != nil { - return err - } - go pools.Copy(w, stdin) - - execCmd.Stdin = r - } - if stdout != nil { - execCmd.Stdout = stdout - } - if stderr != nil { - execCmd.Stderr = stderr - } - - cmdErr = execCmd.Run() - } - - if exitErr, ok := cmdErr.(*exec.ExitError); ok { - return &utilexec.ExitErrorWrapper{ExitError: exitErr} - } - return cmdErr -} diff --git a/server/container_execsync.go b/server/container_execsync.go deleted file mode 100644 index 35f7896c5..000000000 --- a/server/container_execsync.go +++ /dev/null @@ -1,46 +0,0 @@ -package server - -import ( - "fmt" - - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// ExecSync runs a command in a container synchronously. -func (s *Server) ExecSync(ctx context.Context, req *pb.ExecSyncRequest) (*pb.ExecSyncResponse, error) { - logrus.Debugf("ExecSyncRequest %+v", req) - c, err := s.GetContainerFromRequest(req.ContainerId) - if err != nil { - return nil, err - } - - if err = s.Runtime().UpdateStatus(c); err != nil { - return nil, err - } - - cState := s.Runtime().ContainerStatus(c) - if !(cState.Status == oci.ContainerStateRunning || cState.Status == oci.ContainerStateCreated) { - return nil, fmt.Errorf("container is not created or running") - } - - cmd := req.Cmd - if cmd == nil { - return nil, fmt.Errorf("exec command cannot be empty") - } - - execResp, err := s.Runtime().ExecSync(c, cmd, req.Timeout) - if err != nil { - return nil, err - } - resp := &pb.ExecSyncResponse{ - Stdout: execResp.Stdout, - Stderr: execResp.Stderr, - ExitCode: execResp.ExitCode, - } - - logrus.Debugf("ExecSyncResponse: %+v", resp) - return resp, nil -} diff --git a/server/container_list.go b/server/container_list.go deleted file mode 100644 index 42204ae1f..000000000 --- a/server/container_list.go +++ /dev/null @@ -1,112 +0,0 @@ -package server - -import ( - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/fields" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// filterContainer returns whether passed container matches filtering criteria -func filterContainer(c *pb.Container, filter *pb.ContainerFilter) bool { - if filter != nil { - if filter.State != nil { - if c.State != filter.State.State { - return false - } - } - if filter.LabelSelector != nil { - sel := fields.SelectorFromSet(filter.LabelSelector) - if !sel.Matches(fields.Set(c.Labels)) { - return false - } - } - } - return true -} - -// ListContainers lists all containers by filters. -func (s *Server) ListContainers(ctx context.Context, req *pb.ListContainersRequest) (*pb.ListContainersResponse, error) { - logrus.Debugf("ListContainersRequest %+v", req) - var ctrs []*pb.Container - filter := req.Filter - ctrList, err := s.ContainerServer.ListContainers() - if err != nil { - return nil, err - } - - // Filter using container id and pod id first. - if filter.Id != "" { - id, err := s.CtrIDIndex().Get(filter.Id) - if err != nil { - // If we don't find a container ID with a filter, it should not - // be considered an error. Log a warning and return an empty struct - logrus.Warn("unable to find container ID %s", filter.Id) - return &pb.ListContainersResponse{}, nil - } - c := s.ContainerServer.GetContainer(id) - if c != nil { - if filter.PodSandboxId != "" { - if c.Sandbox() == filter.PodSandboxId { - ctrList = []*oci.Container{c} - } else { - ctrList = []*oci.Container{} - } - - } else { - ctrList = []*oci.Container{c} - } - } - } else { - if filter.PodSandboxId != "" { - pod := s.ContainerServer.GetSandbox(filter.PodSandboxId) - if pod == nil { - ctrList = []*oci.Container{} - } else { - ctrList = pod.Containers().List() - } - } - } - - for _, ctr := range ctrList { - podSandboxID := ctr.Sandbox() - cState := s.Runtime().ContainerStatus(ctr) - created := cState.Created.UnixNano() - rState := pb.ContainerState_CONTAINER_UNKNOWN - cID := ctr.ID() - img := &pb.ImageSpec{ - Image: ctr.Image(), - } - c := &pb.Container{ - Id: cID, - PodSandboxId: podSandboxID, - CreatedAt: created, - Labels: ctr.Labels(), - Metadata: ctr.Metadata(), - Annotations: ctr.Annotations(), - Image: img, - } - - switch cState.Status { - case oci.ContainerStateCreated: - rState = pb.ContainerState_CONTAINER_CREATED - case oci.ContainerStateRunning: - rState = pb.ContainerState_CONTAINER_RUNNING - case oci.ContainerStateStopped: - rState = pb.ContainerState_CONTAINER_EXITED - } - c.State = rState - - // Filter by other criteria such as state and labels. - if filterContainer(c, req.Filter) { - ctrs = append(ctrs, c) - } - } - - resp := &pb.ListContainersResponse{ - Containers: ctrs, - } - logrus.Debugf("ListContainersResponse: %+v", resp) - return resp, nil -} diff --git a/server/container_portforward.go b/server/container_portforward.go deleted file mode 100644 index 97dd53423..000000000 --- a/server/container_portforward.go +++ /dev/null @@ -1,91 +0,0 @@ -package server - -import ( - "bytes" - "fmt" - "io" - "os/exec" - "strings" - - "github.com/docker/docker/pkg/pools" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// PortForward prepares a streaming endpoint to forward ports from a PodSandbox. -func (s *Server) PortForward(ctx context.Context, req *pb.PortForwardRequest) (*pb.PortForwardResponse, error) { - logrus.Debugf("PortForwardRequest %+v", req) - - resp, err := s.GetPortForward(req) - - if err != nil { - return nil, fmt.Errorf("unable to prepare portforward endpoint") - } - - return resp, nil -} - -func (ss streamService) PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { - c := ss.runtimeServer.GetSandboxContainer(podSandboxID) - - if c == nil { - return fmt.Errorf("could not find container for sandbox %q", podSandboxID) - } - - if err := ss.runtimeServer.Runtime().UpdateStatus(c); err != nil { - return err - } - - cState := ss.runtimeServer.Runtime().ContainerStatus(c) - if !(cState.Status == oci.ContainerStateRunning || cState.Status == oci.ContainerStateCreated) { - return fmt.Errorf("container is not created or running") - } - - containerPid := cState.Pid - socatPath, lookupErr := exec.LookPath("socat") - if lookupErr != nil { - return fmt.Errorf("unable to do port forwarding: socat not found") - } - - args := []string{"-t", fmt.Sprintf("%d", containerPid), "-n", socatPath, "-", fmt.Sprintf("TCP4:localhost:%d", port)} - - nsenterPath, lookupErr := exec.LookPath("nsenter") - if lookupErr != nil { - return fmt.Errorf("unable to do port forwarding: nsenter not found") - } - - commandString := fmt.Sprintf("%s %s", nsenterPath, strings.Join(args, " ")) - logrus.Debugf("executing port forwarding command: %s", commandString) - - command := exec.Command(nsenterPath, args...) - command.Stdout = stream - - stderr := new(bytes.Buffer) - command.Stderr = stderr - - // If we use Stdin, command.Run() won't return until the goroutine that's copying - // from stream finishes. Unfortunately, if you have a client like telnet connected - // via port forwarding, as long as the user's telnet client is connected to the user's - // local listener that port forwarding sets up, the telnet session never exits. This - // means that even if socat has finished running, command.Run() won't ever return - // (because the client still has the connection and stream open). - // - // The work around is to use StdinPipe(), as Wait() (called by Run()) closes the pipe - // when the command (socat) exits. - inPipe, err := command.StdinPipe() - if err != nil { - return fmt.Errorf("unable to do port forwarding: error creating stdin pipe: %v", err) - } - go func() { - pools.Copy(inPipe, stream) - inPipe.Close() - }() - - if err := command.Run(); err != nil { - return fmt.Errorf("%v: %s", err, stderr.String()) - } - - return nil -} diff --git a/server/container_remove.go b/server/container_remove.go deleted file mode 100644 index 871023726..000000000 --- a/server/container_remove.go +++ /dev/null @@ -1,20 +0,0 @@ -package server - -import ( - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// RemoveContainer removes the container. If the container is running, the container -// should be force removed. -func (s *Server) RemoveContainer(ctx context.Context, req *pb.RemoveContainerRequest) (*pb.RemoveContainerResponse, error) { - _, err := s.ContainerServer.Remove(ctx, req.ContainerId, true) - if err != nil { - return nil, err - } - - resp := &pb.RemoveContainerResponse{} - logrus.Debugf("RemoveContainerResponse: %+v", resp) - return resp, nil -} diff --git a/server/container_start.go b/server/container_start.go deleted file mode 100644 index 85be09484..000000000 --- a/server/container_start.go +++ /dev/null @@ -1,43 +0,0 @@ -package server - -import ( - "fmt" - - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// StartContainer starts the container. -func (s *Server) StartContainer(ctx context.Context, req *pb.StartContainerRequest) (*pb.StartContainerResponse, error) { - logrus.Debugf("StartContainerRequest %+v", req) - c, err := s.GetContainerFromRequest(req.ContainerId) - if err != nil { - return nil, err - } - state := s.Runtime().ContainerStatus(c) - if state.Status != oci.ContainerStateCreated { - return nil, fmt.Errorf("container %s is not in created state: %s", c.ID(), state.Status) - } - - defer func() { - // if the call to StartContainer fails below we still want to fill - // some fields of a container status. In particular, we're going to - // adjust container started/finished time and set an error to be - // returned in the Reason field for container status call. - if err != nil { - s.Runtime().SetStartFailed(c, err) - } - s.ContainerStateToDisk(c) - }() - - err = s.Runtime().StartContainer(c) - if err != nil { - return nil, fmt.Errorf("failed to start container %s: %v", c.ID(), err) - } - - resp := &pb.StartContainerResponse{} - logrus.Debugf("StartContainerResponse %+v", resp) - return resp, nil -} diff --git a/server/container_stats.go b/server/container_stats.go deleted file mode 100644 index 22b87c453..000000000 --- a/server/container_stats.go +++ /dev/null @@ -1,14 +0,0 @@ -package server - -import ( - "fmt" - - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// ContainerStats returns stats of the container. If the container does not -// exist, the call returns an error. -func (s *Server) ContainerStats(ctx context.Context, req *pb.ContainerStatsRequest) (*pb.ContainerStatsResponse, error) { - return nil, fmt.Errorf("not implemented") -} diff --git a/server/container_stats_list.go b/server/container_stats_list.go deleted file mode 100644 index 929220994..000000000 --- a/server/container_stats_list.go +++ /dev/null @@ -1,13 +0,0 @@ -package server - -import ( - "fmt" - - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// ListContainerStats returns stats of all running containers. -func (s *Server) ListContainerStats(ctx context.Context, req *pb.ListContainerStatsRequest) (*pb.ListContainerStatsResponse, error) { - return nil, fmt.Errorf("not implemented") -} diff --git a/server/container_status.go b/server/container_status.go deleted file mode 100644 index b1512e0cd..000000000 --- a/server/container_status.go +++ /dev/null @@ -1,102 +0,0 @@ -package server - -import ( - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -const ( - oomKilledReason = "OOMKilled" - completedReason = "Completed" - errorReason = "Error" -) - -// ContainerStatus returns status of the container. -func (s *Server) ContainerStatus(ctx context.Context, req *pb.ContainerStatusRequest) (*pb.ContainerStatusResponse, error) { - logrus.Debugf("ContainerStatusRequest %+v", req) - c, err := s.GetContainerFromRequest(req.ContainerId) - if err != nil { - return nil, err - } - - containerID := c.ID() - resp := &pb.ContainerStatusResponse{ - Status: &pb.ContainerStatus{ - Id: containerID, - Metadata: c.Metadata(), - Labels: c.Labels(), - Annotations: c.Annotations(), - ImageRef: c.ImageRef(), - }, - } - resp.Status.Image = &pb.ImageSpec{Image: c.ImageName()} - - mounts := []*pb.Mount{} - for _, cv := range c.Volumes() { - mounts = append(mounts, &pb.Mount{ - ContainerPath: cv.ContainerPath, - HostPath: cv.HostPath, - Readonly: cv.Readonly, - }) - } - resp.Status.Mounts = mounts - - cState := s.Runtime().ContainerStatus(c) - rStatus := pb.ContainerState_CONTAINER_UNKNOWN - - imageName := c.Image() - status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), imageName) - if err != nil { - return nil, err - } - - resp.Status.ImageRef = status.ImageRef - - // If we defaulted to exit code -1 earlier then we attempt to - // get the exit code from the exit file again. - if cState.ExitCode == -1 { - err := s.Runtime().UpdateStatus(c) - if err != nil { - logrus.Warnf("Failed to UpdateStatus of container %s: %v", c.ID(), err) - } - cState = s.Runtime().ContainerStatus(c) - } - - switch cState.Status { - case oci.ContainerStateCreated: - rStatus = pb.ContainerState_CONTAINER_CREATED - created := cState.Created.UnixNano() - resp.Status.CreatedAt = created - case oci.ContainerStateRunning: - rStatus = pb.ContainerState_CONTAINER_RUNNING - created := cState.Created.UnixNano() - resp.Status.CreatedAt = created - started := cState.Started.UnixNano() - resp.Status.StartedAt = started - case oci.ContainerStateStopped: - rStatus = pb.ContainerState_CONTAINER_EXITED - created := cState.Created.UnixNano() - resp.Status.CreatedAt = created - started := cState.Started.UnixNano() - resp.Status.StartedAt = started - finished := cState.Finished.UnixNano() - resp.Status.FinishedAt = finished - resp.Status.ExitCode = cState.ExitCode - switch { - case cState.OOMKilled: - resp.Status.Reason = oomKilledReason - case cState.ExitCode == 0: - resp.Status.Reason = completedReason - default: - resp.Status.Reason = errorReason - resp.Status.Message = cState.Error - } - } - - resp.Status.State = rStatus - - logrus.Debugf("ContainerStatusResponse: %+v", resp) - return resp, nil -} diff --git a/server/container_stop.go b/server/container_stop.go deleted file mode 100644 index f74ed86e0..000000000 --- a/server/container_stop.go +++ /dev/null @@ -1,19 +0,0 @@ -package server - -import ( - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// StopContainer stops a running container with a grace period (i.e., timeout). -func (s *Server) StopContainer(ctx context.Context, req *pb.StopContainerRequest) (*pb.StopContainerResponse, error) { - _, err := s.ContainerServer.ContainerStop(ctx, req.ContainerId, req.Timeout) - if err != nil { - return nil, err - } - - resp := &pb.StopContainerResponse{} - logrus.Debugf("StopContainerResponse %s: %+v", req.ContainerId, resp) - return resp, nil -} diff --git a/server/container_updateruntimeconfig.go b/server/container_updateruntimeconfig.go deleted file mode 100644 index b900c9b18..000000000 --- a/server/container_updateruntimeconfig.go +++ /dev/null @@ -1,11 +0,0 @@ -package server - -import ( - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// UpdateRuntimeConfig updates the configuration of a running container. -func (s *Server) UpdateRuntimeConfig(ctx context.Context, req *pb.UpdateRuntimeConfigRequest) (*pb.UpdateRuntimeConfigResponse, error) { - return &pb.UpdateRuntimeConfigResponse{}, nil -} diff --git a/server/image_fs_info.go b/server/image_fs_info.go deleted file mode 100644 index 969bdc342..000000000 --- a/server/image_fs_info.go +++ /dev/null @@ -1,13 +0,0 @@ -package server - -import ( - "fmt" - - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// ImageFsInfo returns information of the filesystem that is used to store images. -func (s *Server) ImageFsInfo(ctx context.Context, req *pb.ImageFsInfoRequest) (*pb.ImageFsInfoResponse, error) { - return nil, fmt.Errorf("not implemented") -} diff --git a/server/image_list.go b/server/image_list.go deleted file mode 100644 index ebcc6f6a1..000000000 --- a/server/image_list.go +++ /dev/null @@ -1,41 +0,0 @@ -package server - -import ( - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// ListImages lists existing images. -func (s *Server) ListImages(ctx context.Context, req *pb.ListImagesRequest) (*pb.ListImagesResponse, error) { - logrus.Debugf("ListImagesRequest: %+v", req) - filter := "" - reqFilter := req.GetFilter() - if reqFilter != nil { - filterImage := reqFilter.GetImage() - if filterImage != nil { - filter = filterImage.Image - } - } - results, err := s.StorageImageServer().ListImages(s.ImageContext(), filter) - if err != nil { - return nil, err - } - response := pb.ListImagesResponse{} - for _, result := range results { - if result.Size != nil { - response.Images = append(response.Images, &pb.Image{ - Id: result.ID, - RepoTags: result.Names, - Size_: *result.Size, - }) - } else { - response.Images = append(response.Images, &pb.Image{ - Id: result.ID, - RepoTags: result.Names, - }) - } - } - logrus.Debugf("ListImagesResponse: %+v", response) - return &response, nil -} diff --git a/server/image_pull.go b/server/image_pull.go deleted file mode 100644 index 26d08912f..000000000 --- a/server/image_pull.go +++ /dev/null @@ -1,108 +0,0 @@ -package server - -import ( - "encoding/base64" - "strings" - - "github.com/containers/image/copy" - "github.com/containers/image/types" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// PullImage pulls a image with authentication config. -func (s *Server) PullImage(ctx context.Context, req *pb.PullImageRequest) (*pb.PullImageResponse, error) { - logrus.Debugf("PullImageRequest: %+v", req) - // TODO: what else do we need here? (Signatures when the story isn't just pulling from docker://) - image := "" - img := req.GetImage() - if img != nil { - image = img.Image - } - - var ( - images []string - pulled string - err error - ) - images, err = s.StorageImageServer().ResolveNames(image) - if err != nil { - return nil, err - } - for _, img := range images { - var ( - username string - password string - ) - if req.GetAuth() != nil { - username = req.GetAuth().Username - password = req.GetAuth().Password - if req.GetAuth().Auth != "" { - username, password, err = decodeDockerAuth(req.GetAuth().Auth) - if err != nil { - logrus.Debugf("error decoding authentication for image %s: %v", img, err) - continue - } - } - } - options := ©.Options{ - SourceCtx: &types.SystemContext{}, - } - // Specifying a username indicates the user intends to send authentication to the registry. - if username != "" { - options.SourceCtx = &types.SystemContext{ - DockerAuthConfig: &types.DockerAuthConfig{ - Username: username, - Password: password, - }, - } - } - - var canPull bool - canPull, err = s.StorageImageServer().CanPull(img, options) - if err != nil && !canPull { - logrus.Debugf("error checking image %s: %v", img, err) - continue - } - - // let's be smart, docker doesn't repull if image already exists. - _, err = s.StorageImageServer().ImageStatus(s.ImageContext(), img) - if err == nil { - logrus.Debugf("image %s already in store, skipping pull", img) - pulled = img - break - } - - _, err = s.StorageImageServer().PullImage(s.ImageContext(), img, options) - if err != nil { - logrus.Debugf("error pulling image %s: %v", img, err) - continue - } - pulled = img - break - } - if pulled == "" && err != nil { - return nil, err - } - resp := &pb.PullImageResponse{ - ImageRef: pulled, - } - logrus.Debugf("PullImageResponse: %+v", resp) - return resp, nil -} - -func decodeDockerAuth(s string) (string, string, error) { - decoded, err := base64.StdEncoding.DecodeString(s) - if err != nil { - return "", "", err - } - parts := strings.SplitN(string(decoded), ":", 2) - if len(parts) != 2 { - // if it's invalid just skip, as docker does - return "", "", nil - } - user := parts[0] - password := strings.Trim(parts[1], "\x00") - return user, password, nil -} diff --git a/server/image_remove.go b/server/image_remove.go deleted file mode 100644 index d15296ccc..000000000 --- a/server/image_remove.go +++ /dev/null @@ -1,52 +0,0 @@ -package server - -import ( - "fmt" - "strings" - - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// RemoveImage removes the image. -func (s *Server) RemoveImage(ctx context.Context, req *pb.RemoveImageRequest) (*pb.RemoveImageResponse, error) { - logrus.Debugf("RemoveImageRequest: %+v", req) - image := "" - img := req.GetImage() - if img != nil { - image = img.Image - } - if image == "" { - return nil, fmt.Errorf("no image specified") - } - var ( - images []string - err error - deleted bool - ) - images, err = s.StorageImageServer().ResolveNames(image) - if err != nil { - // This means we got an image ID - if strings.Contains(err.Error(), "cannot specify 64-byte hexadecimal strings") { - images = append(images, image) - } else { - return nil, err - } - } - for _, img := range images { - err = s.StorageImageServer().UntagImage(s.ImageContext(), img) - if err != nil { - logrus.Debugf("error deleting image %s: %v", img, err) - continue - } - deleted = true - break - } - if !deleted && err != nil { - return nil, err - } - resp := &pb.RemoveImageResponse{} - logrus.Debugf("RemoveImageResponse: %+v", resp) - return resp, nil -} diff --git a/server/image_status.go b/server/image_status.go deleted file mode 100644 index 5571c3023..000000000 --- a/server/image_status.go +++ /dev/null @@ -1,53 +0,0 @@ -package server - -import ( - "fmt" - "strings" - - "github.com/containers/storage" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// ImageStatus returns the status of the image. -func (s *Server) ImageStatus(ctx context.Context, req *pb.ImageStatusRequest) (*pb.ImageStatusResponse, error) { - logrus.Debugf("ImageStatusRequest: %+v", req) - image := "" - img := req.GetImage() - if img != nil { - image = img.Image - } - if image == "" { - return nil, fmt.Errorf("no image specified") - } - images, err := s.StorageImageServer().ResolveNames(image) - if err != nil { - // This means we got an image ID - if strings.Contains(err.Error(), "cannot specify 64-byte hexadecimal strings") { - images = append(images, image) - } else { - return nil, err - } - } - // match just the first registry as that's what kube meant - image = images[0] - status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), image) - if err != nil { - if errors.Cause(err) == storage.ErrImageUnknown { - return &pb.ImageStatusResponse{}, nil - } - return nil, err - } - resp := &pb.ImageStatusResponse{ - Image: &pb.Image{ - Id: status.ID, - RepoTags: status.Names, - RepoDigests: status.Digests, - Size_: *status.Size, - }, - } - logrus.Debugf("ImageStatusResponse: %+v", resp) - return resp, nil -} diff --git a/server/inspect.go b/server/inspect.go deleted file mode 100644 index 6e3e813cc..000000000 --- a/server/inspect.go +++ /dev/null @@ -1,105 +0,0 @@ -package server - -import ( - "encoding/json" - "errors" - "fmt" - "net/http" - - "github.com/go-zoo/bone" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/types" - "github.com/sirupsen/logrus" -) - -func (s *Server) getInfo() types.CrioInfo { - return types.CrioInfo{ - StorageDriver: s.config.Config.Storage, - StorageRoot: s.config.Config.Root, - CgroupDriver: s.config.Config.CgroupManager, - } -} - -var ( - errCtrNotFound = errors.New("container not found") - errCtrStateNil = errors.New("container state is nil") - errSandboxNotFound = errors.New("sandbox for container not found") -) - -func (s *Server) getContainerInfo(id string, getContainerFunc func(id string) *oci.Container, getInfraContainerFunc func(id string) *oci.Container, getSandboxFunc func(id string) *sandbox.Sandbox) (types.ContainerInfo, error) { - ctr := getContainerFunc(id) - if ctr == nil { - ctr = getInfraContainerFunc(id) - if ctr == nil { - return types.ContainerInfo{}, errCtrNotFound - } - } - // TODO(mrunalp): should we call UpdateStatus()? - ctrState := ctr.State() - if ctrState == nil { - return types.ContainerInfo{}, errCtrStateNil - } - sb := getSandboxFunc(ctr.Sandbox()) - if sb == nil { - logrus.Debugf("can't find sandbox %s for container %s", ctr.Sandbox(), id) - return types.ContainerInfo{}, errSandboxNotFound - } - return types.ContainerInfo{ - Name: ctr.Name(), - Pid: ctrState.Pid, - Image: ctr.Image(), - CreatedTime: ctrState.Created.UnixNano(), - Labels: ctr.Labels(), - Annotations: ctr.Annotations(), - CrioAnnotations: ctr.CrioAnnotations(), - Root: ctr.MountPoint(), - LogPath: ctr.LogPath(), - Sandbox: ctr.Sandbox(), - IP: sb.IP(), - }, nil - -} - -// GetInfoMux returns the mux used to serve info requests -func (s *Server) GetInfoMux() *bone.Mux { - mux := bone.New() - - mux.Get("/info", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - ci := s.getInfo() - js, err := json.Marshal(ci) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(js) - })) - - mux.Get("/containers/:id", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - containerID := bone.GetValue(req, "id") - ci, err := s.getContainerInfo(containerID, s.GetContainer, s.getInfraContainer, s.getSandbox) - if err != nil { - switch err { - case errCtrNotFound: - http.Error(w, fmt.Sprintf("can't find the container with id %s", containerID), http.StatusNotFound) - case errCtrStateNil: - http.Error(w, fmt.Sprintf("can't find container state for container with id %s", containerID), http.StatusInternalServerError) - case errSandboxNotFound: - http.Error(w, fmt.Sprintf("can't find the sandbox for container id %s", containerID), http.StatusNotFound) - default: - http.Error(w, err.Error(), http.StatusInternalServerError) - } - return - } - js, err := json.Marshal(ci) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(js) - })) - - return mux -} diff --git a/server/inspect_test.go b/server/inspect_test.go deleted file mode 100644 index 7be46c4ed..000000000 --- a/server/inspect_test.go +++ /dev/null @@ -1,235 +0,0 @@ -package server - -import ( - "testing" - "time" - - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - - "github.com/containernetworking/plugins/pkg/ns" - "github.com/kubernetes-incubator/cri-o/libkpod" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - specs "github.com/opencontainers/runtime-spec/specs-go" -) - -func TestGetInfo(t *testing.T) { - c := libkpod.DefaultConfig() - c.RootConfig.Storage = "afoobarstorage" - c.RootConfig.Root = "afoobarroot" - c.RuntimeConfig.CgroupManager = "systemd" - apiConfig := APIConfig{} - s := &Server{ - config: Config{*c, apiConfig}, - } - ci := s.getInfo() - if ci.CgroupDriver != "systemd" { - t.Fatalf("expected 'systemd', got %q", ci.CgroupDriver) - } - if ci.StorageDriver != "afoobarstorage" { - t.Fatalf("expected 'afoobarstorage', got %q", ci.StorageDriver) - } - if ci.StorageRoot != "afoobarroot" { - t.Fatalf("expected 'afoobarroot', got %q", ci.StorageRoot) - } -} - -type mockNetNS struct { -} - -func (ns mockNetNS) Close() error { - return nil -} -func (ns mockNetNS) Fd() uintptr { - ptr := new(uintptr) - return *ptr -} -func (ns mockNetNS) Do(toRun func(ns.NetNS) error) error { - return nil -} -func (ns mockNetNS) Set() error { - return nil -} -func (ns mockNetNS) Path() string { - return "" -} - -func TestGetContainerInfo(t *testing.T) { - s := &Server{} - created := time.Now() - labels := map[string]string{ - "io.kubernetes.container.name": "POD", - "io.kubernetes.test2": "value2", - "io.kubernetes.test3": "value3", - } - annotations := map[string]string{ - "io.kubernetes.test": "value", - "io.kubernetes.test1": "value1", - } - getContainerFunc := func(id string) *oci.Container { - container, err := oci.NewContainer("testid", "testname", "", "/container/logs", mockNetNS{}, labels, annotations, annotations, "imageName", "imageName", "imageRef", &runtime.ContainerMetadata{}, "testsandboxid", false, false, false, false, false, "/root/for/container", created, "SIGKILL") - if err != nil { - t.Fatal(err) - } - container.SetMountPoint("/var/foo/container") - cstate := &oci.ContainerState{} - cstate.State = specs.State{ - Pid: 42, - } - cstate.Created = created - container.SetState(cstate) - return container - } - getInfraContainerFunc := func(id string) *oci.Container { - return nil - } - getSandboxFunc := func(id string) *sandbox.Sandbox { - s := &sandbox.Sandbox{} - s.AddIP("1.1.1.42") - return s - } - ci, err := s.getContainerInfo("", getContainerFunc, getInfraContainerFunc, getSandboxFunc) - if err != nil { - t.Fatal(err) - } - if ci.CreatedTime != created.UnixNano() { - t.Fatalf("expected same created time %d, got %d", created.UnixNano(), ci.CreatedTime) - } - if ci.Pid != 42 { - t.Fatalf("expected pid 42, got %v", ci.Pid) - } - if ci.Name != "testname" { - t.Fatalf("expected name testname, got %s", ci.Name) - } - if ci.Image != "imageName" { - t.Fatalf("expected image name imageName, got %s", ci.Image) - } - if ci.Root != "/var/foo/container" { - t.Fatalf("expected root to be /var/foo/container, got %s", ci.Root) - } - if ci.LogPath != "/container/logs" { - t.Fatalf("expected log path to be /containers/logs, got %s", ci.LogPath) - } - if ci.Sandbox != "testsandboxid" { - t.Fatalf("expected sandbox to be testsandboxid, got %s", ci.Sandbox) - } - if ci.IP != "1.1.1.42" { - t.Fatalf("expected ip 1.1.1.42, got %s", ci.IP) - } - if len(ci.Annotations) == 0 { - t.Fatal("annotations are empty") - } - if len(ci.Labels) == 0 { - t.Fatal("labels are empty") - } - if len(ci.Annotations) != len(annotations) { - t.Fatalf("container info annotations len (%d) isn't the same as original annotations len (%d)", len(ci.Annotations), len(annotations)) - } - if len(ci.Labels) != len(labels) { - t.Fatalf("container info labels len (%d) isn't the same as original labels len (%d)", len(ci.Labels), len(labels)) - } - var found bool - for k, v := range annotations { - found = false - for key, value := range ci.Annotations { - if k == key && v == value { - found = true - break - } - } - if !found { - t.Fatalf("key %s with value %v wasn't in container info annotations", k, v) - } - } - for k, v := range labels { - found = false - for key, value := range ci.Labels { - if k == key && v == value { - found = true - break - } - } - if !found { - t.Fatalf("key %s with value %v wasn't in container info labels", k, v) - } - } -} - -func TestGetContainerInfoCtrNotFound(t *testing.T) { - s := &Server{} - getContainerFunc := func(id string) *oci.Container { - return nil - } - getInfraContainerFunc := func(id string) *oci.Container { - return nil - } - getSandboxFunc := func(id string) *sandbox.Sandbox { - return nil - } - _, err := s.getContainerInfo("", getContainerFunc, getInfraContainerFunc, getSandboxFunc) - if err == nil { - t.Fatal("expected an error but got nothing") - } - if err != errCtrNotFound { - t.Fatalf("expected errCtrNotFound error, got %v", err) - } -} - -func TestGetContainerInfoCtrStateNil(t *testing.T) { - s := &Server{} - created := time.Now() - labels := map[string]string{} - annotations := map[string]string{} - getContainerFunc := func(id string) *oci.Container { - container, err := oci.NewContainer("testid", "testname", "", "/container/logs", mockNetNS{}, labels, annotations, annotations, "imageName", "imageName", "imageRef", &runtime.ContainerMetadata{}, "testsandboxid", false, false, false, false, false, "/root/for/container", created, "SIGKILL") - if err != nil { - t.Fatal(err) - } - container.SetMountPoint("/var/foo/container") - container.SetState(nil) - return container - } - getInfraContainerFunc := func(id string) *oci.Container { - return nil - } - getSandboxFunc := func(id string) *sandbox.Sandbox { - s := &sandbox.Sandbox{} - s.AddIP("1.1.1.42") - return s - } - _, err := s.getContainerInfo("", getContainerFunc, getInfraContainerFunc, getSandboxFunc) - if err == nil { - t.Fatal("expected an error but got nothing") - } - if err != errCtrStateNil { - t.Fatalf("expected errCtrStateNil error, got %v", err) - } -} - -func TestGetContainerInfoSandboxNotFound(t *testing.T) { - s := &Server{} - created := time.Now() - labels := map[string]string{} - annotations := map[string]string{} - getContainerFunc := func(id string) *oci.Container { - container, err := oci.NewContainer("testid", "testname", "", "/container/logs", mockNetNS{}, labels, annotations, annotations, "imageName", "imageName", "imageRef", &runtime.ContainerMetadata{}, "testsandboxid", false, false, false, false, false, "/root/for/container", created, "SIGKILL") - if err != nil { - t.Fatal(err) - } - container.SetMountPoint("/var/foo/container") - return container - } - getInfraContainerFunc := func(id string) *oci.Container { - return nil - } - getSandboxFunc := func(id string) *sandbox.Sandbox { - return nil - } - _, err := s.getContainerInfo("", getContainerFunc, getInfraContainerFunc, getSandboxFunc) - if err == nil { - t.Fatal("expected an error but got nothing") - } - if err != errSandboxNotFound { - t.Fatalf("expected errSandboxNotFound error, got %v", err) - } -} diff --git a/server/naming.go b/server/naming.go deleted file mode 100644 index cc18ba409..000000000 --- a/server/naming.go +++ /dev/null @@ -1,86 +0,0 @@ -package server - -import ( - "fmt" - "strings" - - "github.com/docker/docker/pkg/stringid" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -const ( - kubePrefix = "k8s" - infraName = "POD" - nameDelimiter = "_" -) - -func makeSandboxName(sandboxConfig *pb.PodSandboxConfig) string { - return strings.Join([]string{ - kubePrefix, - sandboxConfig.Metadata.Name, - sandboxConfig.Metadata.Namespace, - sandboxConfig.Metadata.Uid, - fmt.Sprintf("%d", sandboxConfig.Metadata.Attempt), - }, nameDelimiter) -} - -func makeSandboxContainerName(sandboxConfig *pb.PodSandboxConfig) string { - return strings.Join([]string{ - kubePrefix, - infraName, - sandboxConfig.Metadata.Name, - sandboxConfig.Metadata.Namespace, - sandboxConfig.Metadata.Uid, - fmt.Sprintf("%d", sandboxConfig.Metadata.Attempt), - }, nameDelimiter) -} - -func makeContainerName(sandboxMetadata *pb.PodSandboxMetadata, containerConfig *pb.ContainerConfig) string { - return strings.Join([]string{ - kubePrefix, - containerConfig.Metadata.Name, - sandboxMetadata.Name, - sandboxMetadata.Namespace, - sandboxMetadata.Uid, - fmt.Sprintf("%d", containerConfig.Metadata.Attempt), - }, nameDelimiter) -} - -func (s *Server) generatePodIDandName(sandboxConfig *pb.PodSandboxConfig) (string, string, error) { - var ( - err error - id = stringid.GenerateNonCryptoID() - ) - if sandboxConfig.Metadata.Namespace == "" { - return "", "", fmt.Errorf("cannot generate pod ID without namespace") - } - name, err := s.ReservePodName(id, makeSandboxName(sandboxConfig)) - if err != nil { - return "", "", err - } - return id, name, err -} - -func (s *Server) generateContainerIDandNameForSandbox(sandboxConfig *pb.PodSandboxConfig) (string, string, error) { - var ( - err error - id = stringid.GenerateNonCryptoID() - ) - name, err := s.ReserveContainerName(id, makeSandboxContainerName(sandboxConfig)) - if err != nil { - return "", "", err - } - return id, name, err -} - -func (s *Server) generateContainerIDandName(sandboxMetadata *pb.PodSandboxMetadata, containerConfig *pb.ContainerConfig) (string, string, error) { - var ( - err error - id = stringid.GenerateNonCryptoID() - ) - name, err := s.ReserveContainerName(id, makeContainerName(sandboxMetadata, containerConfig)) - if err != nil { - return "", "", err - } - return id, name, err -} diff --git a/server/runtime_status.go b/server/runtime_status.go deleted file mode 100644 index 67fc87b6f..000000000 --- a/server/runtime_status.go +++ /dev/null @@ -1,41 +0,0 @@ -package server - -import ( - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// Status returns the status of the runtime -func (s *Server) Status(ctx context.Context, req *pb.StatusRequest) (*pb.StatusResponse, error) { - - // Deal with Runtime conditions - runtimeReady, err := s.Runtime().RuntimeReady() - if err != nil { - return nil, err - } - networkReady, err := s.Runtime().NetworkReady() - if err != nil { - return nil, err - } - - // Use vendored strings - runtimeReadyConditionString := pb.RuntimeReady - networkReadyConditionString := pb.NetworkReady - - resp := &pb.StatusResponse{ - Status: &pb.RuntimeStatus{ - Conditions: []*pb.RuntimeCondition{ - { - Type: runtimeReadyConditionString, - Status: runtimeReady, - }, - { - Type: networkReadyConditionString, - Status: networkReady, - }, - }, - }, - } - - return resp, nil -} diff --git a/server/sandbox_list.go b/server/sandbox_list.go deleted file mode 100644 index fbc5eafa8..000000000 --- a/server/sandbox_list.go +++ /dev/null @@ -1,94 +0,0 @@ -package server - -import ( - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "k8s.io/apimachinery/pkg/fields" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// filterSandbox returns whether passed container matches filtering criteria -func filterSandbox(p *pb.PodSandbox, filter *pb.PodSandboxFilter) bool { - if filter != nil { - if filter.State != nil { - if p.State != filter.State.State { - return false - } - } - if filter.LabelSelector != nil { - sel := fields.SelectorFromSet(filter.LabelSelector) - if !sel.Matches(fields.Set(p.Labels)) { - return false - } - } - } - return true -} - -// ListPodSandbox returns a list of SandBoxes. -func (s *Server) ListPodSandbox(ctx context.Context, req *pb.ListPodSandboxRequest) (*pb.ListPodSandboxResponse, error) { - logrus.Debugf("ListPodSandboxRequest %+v", req) - var pods []*pb.PodSandbox - var podList []*sandbox.Sandbox - for _, sb := range s.ContainerServer.ListSandboxes() { - podList = append(podList, sb) - } - - filter := req.Filter - // Filter by pod id first. - if filter != nil { - if filter.Id != "" { - id, err := s.PodIDIndex().Get(filter.Id) - if err != nil { - // Not finding an ID in a filtered list should not be considered - // and error; it might have been deleted when stop was done. - // Log and return an empty struct. - logrus.Warn("unable to find pod %s with filter", filter.Id) - return &pb.ListPodSandboxResponse{}, nil - } - sb := s.getSandbox(id) - if sb == nil { - podList = []*sandbox.Sandbox{} - } else { - podList = []*sandbox.Sandbox{sb} - } - } - } - - for _, sb := range podList { - podInfraContainer := sb.InfraContainer() - if podInfraContainer == nil { - // this can't really happen, but if it does because of a bug - // it's better not to panic - continue - } - cState := s.Runtime().ContainerStatus(podInfraContainer) - created := cState.Created.UnixNano() - rStatus := pb.PodSandboxState_SANDBOX_NOTREADY - if cState.Status == oci.ContainerStateRunning { - rStatus = pb.PodSandboxState_SANDBOX_READY - } - - pod := &pb.PodSandbox{ - Id: sb.ID(), - CreatedAt: created, - State: rStatus, - Labels: sb.Labels(), - Annotations: sb.Annotations(), - Metadata: sb.Metadata(), - } - - // Filter by other criteria such as state and labels. - if filterSandbox(pod, req.Filter) { - pods = append(pods, pod) - } - } - - resp := &pb.ListPodSandboxResponse{ - Items: pods, - } - logrus.Debugf("ListPodSandboxResponse %+v", resp) - return resp, nil -} diff --git a/server/sandbox_network.go b/server/sandbox_network.go deleted file mode 100644 index 15cf99c8f..000000000 --- a/server/sandbox_network.go +++ /dev/null @@ -1,70 +0,0 @@ -package server - -import ( - "fmt" - "net" - - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/sirupsen/logrus" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" -) - -// networkStart sets up the sandbox's network and returns the pod IP on success -// or an error -func (s *Server) networkStart(hostNetwork bool, sb *sandbox.Sandbox) (string, error) { - if hostNetwork { - return s.BindAddress(), nil - } - - podNetwork := newPodNetwork(sb) - err := s.netPlugin.SetUpPod(podNetwork) - if err != nil { - return "", fmt.Errorf("failed to create pod network sandbox %s(%s): %v", sb.Name(), sb.ID(), err) - } - - var ip string - if ip, err = s.netPlugin.GetPodNetworkStatus(podNetwork); err != nil { - return "", fmt.Errorf("failed to get network status for pod sandbox %s(%s): %v", sb.Name(), sb.ID(), err) - } - - if len(sb.PortMappings()) > 0 { - ip4 := net.ParseIP(ip).To4() - if ip4 == nil { - return "", fmt.Errorf("failed to get valid ipv4 address for sandbox %s(%s)", sb.Name(), sb.ID()) - } - - if err = s.hostportManager.Add(sb.ID(), &hostport.PodPortMapping{ - Name: sb.Name(), - PortMappings: sb.PortMappings(), - IP: ip4, - HostNetwork: false, - }, "lo"); err != nil { - return "", fmt.Errorf("failed to add hostport mapping for sandbox %s(%s): %v", sb.Name(), sb.ID(), err) - } - - } - return ip, nil -} - -// networkStop cleans up and removes a pod's network. It is best-effort and -// must call the network plugin even if the network namespace is already gone -func (s *Server) networkStop(hostNetwork bool, sb *sandbox.Sandbox) error { - if !hostNetwork { - if err := s.hostportManager.Remove(sb.ID(), &hostport.PodPortMapping{ - Name: sb.Name(), - PortMappings: sb.PortMappings(), - HostNetwork: false, - }); err != nil { - logrus.Warnf("failed to remove hostport for pod sandbox %s(%s): %v", - sb.Name(), sb.ID(), err) - } - - podNetwork := newPodNetwork(sb) - if err := s.netPlugin.TearDownPod(podNetwork); err != nil { - logrus.Warnf("failed to destroy network for pod sandbox %s(%s): %v", - sb.Name(), sb.ID(), err) - } - } - - return nil -} diff --git a/server/sandbox_remove.go b/server/sandbox_remove.go deleted file mode 100644 index b0e073844..000000000 --- a/server/sandbox_remove.go +++ /dev/null @@ -1,98 +0,0 @@ -package server - -import ( - "fmt" - - "github.com/containers/storage" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - pkgstorage "github.com/kubernetes-incubator/cri-o/pkg/storage" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// RemovePodSandbox deletes the sandbox. If there are any running containers in the -// sandbox, they should be force deleted. -func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxRequest) (*pb.RemovePodSandboxResponse, error) { - logrus.Debugf("RemovePodSandboxRequest %+v", req) - sb, err := s.getPodSandboxFromRequest(req.PodSandboxId) - if err != nil { - if err == sandbox.ErrIDEmpty { - return nil, err - } - - // If the sandbox isn't found we just return an empty response to adhere - // the the CRI interface which expects to not error out in not found - // cases. - - resp := &pb.RemovePodSandboxResponse{} - logrus.Warnf("could not get sandbox %s, it's probably been removed already: %v", req.PodSandboxId, err) - return resp, nil - } - - podInfraContainer := sb.InfraContainer() - containers := sb.Containers().List() - containers = append(containers, podInfraContainer) - - // Delete all the containers in the sandbox - for _, c := range containers { - if !sb.Stopped() { - cState := s.Runtime().ContainerStatus(c) - if cState.Status == oci.ContainerStateCreated || cState.Status == oci.ContainerStateRunning { - if err := s.Runtime().StopContainer(ctx, c, 10); err != nil { - // Assume container is already stopped - logrus.Warnf("failed to stop container %s: %v", c.Name(), err) - } - } - } - - if err := s.Runtime().DeleteContainer(c); err != nil { - return nil, fmt.Errorf("failed to delete container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err) - } - - if c.ID() == podInfraContainer.ID() { - continue - } - - if err := s.StorageRuntimeServer().StopContainer(c.ID()); err != nil && err != storage.ErrContainerUnknown { - // assume container already umounted - logrus.Warnf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err) - } - if err := s.StorageRuntimeServer().DeleteContainer(c.ID()); err != nil && err != storage.ErrContainerUnknown { - return nil, fmt.Errorf("failed to delete container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err) - } - - s.ReleaseContainerName(c.Name()) - s.removeContainer(c) - if err := s.CtrIDIndex().Delete(c.ID()); err != nil { - return nil, fmt.Errorf("failed to delete container %s in pod sandbox %s from index: %v", c.Name(), sb.ID(), err) - } - } - - s.removeInfraContainer(podInfraContainer) - - // Remove the files related to the sandbox - if err := s.StorageRuntimeServer().StopContainer(sb.ID()); err != nil && errors.Cause(err) != storage.ErrContainerUnknown { - logrus.Warnf("failed to stop sandbox container in pod sandbox %s: %v", sb.ID(), err) - } - if err := s.StorageRuntimeServer().RemovePodSandbox(sb.ID()); err != nil && err != pkgstorage.ErrInvalidSandboxID { - return nil, fmt.Errorf("failed to remove pod sandbox %s: %v", sb.ID(), err) - } - - s.ReleaseContainerName(podInfraContainer.Name()) - if err := s.CtrIDIndex().Delete(podInfraContainer.ID()); err != nil { - return nil, fmt.Errorf("failed to delete infra container %s in pod sandbox %s from index: %v", podInfraContainer.ID(), sb.ID(), err) - } - - s.ReleasePodName(sb.Name()) - s.removeSandbox(sb.ID()) - if err := s.PodIDIndex().Delete(sb.ID()); err != nil { - return nil, fmt.Errorf("failed to delete pod sandbox %s from index: %v", sb.ID(), err) - } - - resp := &pb.RemovePodSandboxResponse{} - logrus.Debugf("RemovePodSandboxResponse %+v", resp) - return resp, nil -} diff --git a/server/sandbox_run.go b/server/sandbox_run.go deleted file mode 100644 index 72afdb229..000000000 --- a/server/sandbox_run.go +++ /dev/null @@ -1,615 +0,0 @@ -package server - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "regexp" - "strconv" - "strings" - "time" - - "github.com/containers/storage" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/pkg/annotations" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/runtime-tools/generate" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "golang.org/x/sys/unix" - "k8s.io/kubernetes/pkg/api/v1" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - "k8s.io/kubernetes/pkg/kubelet/leaky" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" - "k8s.io/kubernetes/pkg/kubelet/types" -) - -const ( - // PodInfraOOMAdj is the value that we set for oom score adj for - // the pod infra container. - // TODO: Remove this const once this value is provided over CRI - // See https://github.com/kubernetes/kubernetes/issues/47938 - PodInfraOOMAdj int = -998 - // PodInfraCPUshares is default cpu shares for sandbox container. - PodInfraCPUshares = 2 -) - -// privilegedSandbox returns true if the sandbox configuration -// requires additional host privileges for the sandbox. -func (s *Server) privilegedSandbox(req *pb.RunPodSandboxRequest) bool { - securityContext := req.GetConfig().GetLinux().GetSecurityContext() - if securityContext == nil { - return false - } - - if securityContext.Privileged { - return true - } - - namespaceOptions := securityContext.GetNamespaceOptions() - if namespaceOptions == nil { - return false - } - - if namespaceOptions.HostNetwork || - namespaceOptions.HostPid || - namespaceOptions.HostIpc { - return true - } - - return false -} - -// trustedSandbox returns true if the sandbox will run trusted workloads. -func (s *Server) trustedSandbox(req *pb.RunPodSandboxRequest) bool { - kubeAnnotations := req.GetConfig().GetAnnotations() - - trustedAnnotation, ok := kubeAnnotations[annotations.TrustedSandbox] - if !ok { - // A sandbox is trusted by default. - return true - } - - return isTrue(trustedAnnotation) -} - -func (s *Server) runContainer(container *oci.Container, cgroupParent string) error { - if err := s.Runtime().CreateContainer(container, cgroupParent); err != nil { - return err - } - return s.Runtime().StartContainer(container) -} - -var ( - conflictRE = regexp.MustCompile(`already reserved for pod "([0-9a-z]+)"`) -) - -// RunPodSandbox creates and runs a pod-level sandbox. -func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest) (resp *pb.RunPodSandboxResponse, err error) { - s.updateLock.RLock() - defer s.updateLock.RUnlock() - - logrus.Debugf("RunPodSandboxRequest %+v", req) - var processLabel, mountLabel, resolvPath string - // process req.Name - kubeName := req.GetConfig().GetMetadata().Name - if kubeName == "" { - return nil, fmt.Errorf("PodSandboxConfig.Name should not be empty") - } - - namespace := req.GetConfig().GetMetadata().Namespace - attempt := req.GetConfig().GetMetadata().Attempt - - id, name, err := s.generatePodIDandName(req.GetConfig()) - if err != nil { - if strings.Contains(err.Error(), "already reserved for pod") { - matches := conflictRE.FindStringSubmatch(err.Error()) - if len(matches) != 2 { - return nil, err - } - dupID := matches[1] - if _, err := s.StopPodSandbox(ctx, &pb.StopPodSandboxRequest{PodSandboxId: dupID}); err != nil { - return nil, err - } - if _, err := s.RemovePodSandbox(ctx, &pb.RemovePodSandboxRequest{PodSandboxId: dupID}); err != nil { - return nil, err - } - id, name, err = s.generatePodIDandName(req.GetConfig()) - if err != nil { - return nil, err - } - } else { - return nil, err - } - } - - defer func() { - if err != nil { - s.ReleasePodName(name) - } - }() - - _, containerName, err := s.generateContainerIDandNameForSandbox(req.GetConfig()) - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - s.ReleaseContainerName(containerName) - } - }() - - podContainer, err := s.StorageRuntimeServer().CreatePodSandbox(s.ImageContext(), - name, id, - s.config.PauseImage, "", - containerName, - req.GetConfig().GetMetadata().Name, - req.GetConfig().GetMetadata().Uid, - namespace, - attempt, - nil) - if errors.Cause(err) == storage.ErrDuplicateName { - return nil, fmt.Errorf("pod sandbox with name %q already exists", name) - } - if err != nil { - return nil, fmt.Errorf("error creating pod sandbox with name %q: %v", name, err) - } - defer func() { - if err != nil { - if err2 := s.StorageRuntimeServer().RemovePodSandbox(id); err2 != nil { - logrus.Warnf("couldn't cleanup pod sandbox %q: %v", id, err2) - } - } - }() - - // TODO: factor generating/updating the spec into something other projects can vendor - - // creates a spec Generator with the default spec. - g := generate.New() - - // setup defaults for the pod sandbox - g.SetRootReadonly(true) - if s.config.PauseCommand == "" { - if podContainer.Config != nil { - g.SetProcessArgs(podContainer.Config.Config.Cmd) - } else { - g.SetProcessArgs([]string{sandbox.PodInfraCommand}) - } - } else { - g.SetProcessArgs([]string{s.config.PauseCommand}) - } - - // set DNS options - if req.GetConfig().GetDnsConfig() != nil { - dnsServers := req.GetConfig().GetDnsConfig().Servers - dnsSearches := req.GetConfig().GetDnsConfig().Searches - dnsOptions := req.GetConfig().GetDnsConfig().Options - resolvPath = fmt.Sprintf("%s/resolv.conf", podContainer.RunDir) - err = parseDNSOptions(dnsServers, dnsSearches, dnsOptions, resolvPath) - if err != nil { - err1 := removeFile(resolvPath) - if err1 != nil { - err = err1 - return nil, fmt.Errorf("%v; failed to remove %s: %v", err, resolvPath, err1) - } - return nil, err - } - if err := label.Relabel(resolvPath, mountLabel, true); err != nil && err != unix.ENOTSUP { - return nil, err - } - - g.AddBindMount(resolvPath, "/etc/resolv.conf", []string{"ro"}) - } - - // add metadata - metadata := req.GetConfig().GetMetadata() - metadataJSON, err := json.Marshal(metadata) - if err != nil { - return nil, err - } - - // add labels - labels := req.GetConfig().GetLabels() - - // Add special container name label for the infra container - labelsJSON := []byte{} - if labels != nil { - labels[types.KubernetesContainerNameLabel] = leaky.PodInfraContainerName - labelsJSON, err = json.Marshal(labels) - if err != nil { - return nil, err - } - } - - // add annotations - kubeAnnotations := req.GetConfig().GetAnnotations() - kubeAnnotationsJSON, err := json.Marshal(kubeAnnotations) - if err != nil { - return nil, err - } - - // set log directory - logDir := req.GetConfig().LogDirectory - if logDir == "" { - logDir = filepath.Join(s.config.LogDir, id) - } - if err = os.MkdirAll(logDir, 0700); err != nil { - return nil, err - } - // This should always be absolute from k8s. - if !filepath.IsAbs(logDir) { - return nil, fmt.Errorf("requested logDir for sbox id %s is a relative path: %s", id, logDir) - } - - privileged := s.privilegedSandbox(req) - - securityContext := req.GetConfig().GetLinux().GetSecurityContext() - if securityContext == nil { - logrus.Warn("no security context found in config.") - } - - processLabel, mountLabel, err = getSELinuxLabels(securityContext.GetSelinuxOptions(), privileged) - if err != nil { - return nil, err - } - - // Don't use SELinux separation with Host Pid or IPC Namespace or privileged. - if securityContext.GetNamespaceOptions().GetHostPid() || securityContext.GetNamespaceOptions().GetHostIpc() { - processLabel, mountLabel = "", "" - } - g.SetProcessSelinuxLabel(processLabel) - g.SetLinuxMountLabel(mountLabel) - - // create shm mount for the pod containers. - var shmPath string - if securityContext.GetNamespaceOptions().GetHostIpc() { - shmPath = "/dev/shm" - } else { - shmPath, err = setupShm(podContainer.RunDir, mountLabel) - if err != nil { - return nil, err - } - defer func() { - if err != nil { - if err2 := unix.Unmount(shmPath, unix.MNT_DETACH); err2 != nil { - logrus.Warnf("failed to unmount shm for pod: %v", err2) - } - } - }() - } - - err = s.setPodSandboxMountLabel(id, mountLabel) - if err != nil { - return nil, err - } - - if err = s.CtrIDIndex().Add(id); err != nil { - return nil, err - } - - defer func() { - if err != nil { - if err2 := s.CtrIDIndex().Delete(id); err2 != nil { - logrus.Warnf("couldn't delete ctr id %s from idIndex", id) - } - } - }() - - // set log path inside log directory - logPath := filepath.Join(logDir, id+".log") - - // Handle https://issues.k8s.io/44043 - if err := ensureSaneLogPath(logPath); err != nil { - return nil, err - } - - hostNetwork := securityContext.GetNamespaceOptions().GetHostNetwork() - - hostname, err := getHostname(id, req.GetConfig().Hostname, hostNetwork) - if err != nil { - return nil, err - } - g.SetHostname(hostname) - - trusted := s.trustedSandbox(req) - g.AddAnnotation(annotations.Metadata, string(metadataJSON)) - g.AddAnnotation(annotations.Labels, string(labelsJSON)) - g.AddAnnotation(annotations.Annotations, string(kubeAnnotationsJSON)) - g.AddAnnotation(annotations.LogPath, logPath) - g.AddAnnotation(annotations.Name, name) - g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox) - g.AddAnnotation(annotations.SandboxID, id) - g.AddAnnotation(annotations.ContainerName, containerName) - g.AddAnnotation(annotations.ContainerID, id) - g.AddAnnotation(annotations.ShmPath, shmPath) - g.AddAnnotation(annotations.PrivilegedRuntime, fmt.Sprintf("%v", privileged)) - g.AddAnnotation(annotations.TrustedSandbox, fmt.Sprintf("%v", trusted)) - g.AddAnnotation(annotations.ResolvPath, resolvPath) - g.AddAnnotation(annotations.HostName, hostname) - g.AddAnnotation(annotations.KubeName, kubeName) - if podContainer.Config.Config.StopSignal != "" { - // this key is defined in image-spec conversion document at https://github.com/opencontainers/image-spec/pull/492/files#diff-8aafbe2c3690162540381b8cdb157112R57 - g.AddAnnotation("org.opencontainers.image.stopSignal", podContainer.Config.Config.StopSignal) - } - - created := time.Now() - g.AddAnnotation(annotations.Created, created.Format(time.RFC3339Nano)) - - portMappings := convertPortMappings(req.GetConfig().GetPortMappings()) - - // setup cgroup settings - cgroupParent := req.GetConfig().GetLinux().GetCgroupParent() - if cgroupParent != "" { - if s.config.CgroupManager == oci.SystemdCgroupsManager { - if len(cgroupParent) <= 6 || !strings.HasSuffix(path.Base(cgroupParent), ".slice") { - return nil, fmt.Errorf("cri-o configured with systemd cgroup manager, but did not receive slice as parent: %s", cgroupParent) - } - cgPath, err := convertCgroupFsNameToSystemd(cgroupParent) - if err != nil { - return nil, err - } - g.SetLinuxCgroupsPath(cgPath + ":" + "crio" + ":" + id) - cgroupParent = cgPath - } else { - if strings.HasSuffix(path.Base(cgroupParent), ".slice") { - return nil, fmt.Errorf("cri-o configured with cgroupfs cgroup manager, but received systemd slice as parent: %s", cgroupParent) - } - cgPath := filepath.Join(cgroupParent, scopePrefix+"-"+id) - g.SetLinuxCgroupsPath(cgPath) - } - } - - sb, err := sandbox.New(id, namespace, name, kubeName, logDir, labels, kubeAnnotations, processLabel, mountLabel, metadata, shmPath, cgroupParent, privileged, trusted, resolvPath, hostname, portMappings) - if err != nil { - return nil, err - } - - s.addSandbox(sb) - defer func() { - if err != nil { - s.removeSandbox(id) - } - }() - - if err = s.PodIDIndex().Add(id); err != nil { - return nil, err - } - - defer func() { - if err != nil { - if err := s.PodIDIndex().Delete(id); err != nil { - logrus.Warnf("couldn't delete pod id %s from idIndex", id) - } - } - }() - - for k, v := range kubeAnnotations { - g.AddAnnotation(k, v) - } - for k, v := range labels { - g.AddAnnotation(k, v) - } - - // extract linux sysctls from annotations and pass down to oci runtime - safe, unsafe, err := SysctlsFromPodAnnotations(kubeAnnotations) - if err != nil { - return nil, err - } - for _, sysctl := range safe { - g.AddLinuxSysctl(sysctl.Name, sysctl.Value) - } - for _, sysctl := range unsafe { - g.AddLinuxSysctl(sysctl.Name, sysctl.Value) - } - - // Set OOM score adjust of the infra container to be very low - // so it doesn't get killed. - g.SetProcessOOMScoreAdj(PodInfraOOMAdj) - - g.SetLinuxResourcesCPUShares(PodInfraCPUshares) - - // set up namespaces - if hostNetwork { - err = g.RemoveLinuxNamespace(string(runtimespec.NetworkNamespace)) - if err != nil { - return nil, err - } - } else { - // Create the sandbox network namespace - if err = sb.NetNsCreate(); err != nil { - return nil, err - } - - defer func() { - if err == nil { - return - } - - if netnsErr := sb.NetNsRemove(); netnsErr != nil { - logrus.Warnf("Failed to remove networking namespace: %v", netnsErr) - } - }() - - // Pass the created namespace path to the runtime - err = g.AddOrReplaceLinuxNamespace(string(runtimespec.NetworkNamespace), sb.NetNsPath()) - if err != nil { - return nil, err - } - } - - if securityContext.GetNamespaceOptions().GetHostPid() { - err = g.RemoveLinuxNamespace(string(runtimespec.PIDNamespace)) - if err != nil { - return nil, err - } - } - - if securityContext.GetNamespaceOptions().GetHostIpc() { - err = g.RemoveLinuxNamespace(string(runtimespec.IPCNamespace)) - if err != nil { - return nil, err - } - } - - if !s.seccompEnabled { - g.Spec().Linux.Seccomp = nil - } - - saveOptions := generate.ExportOptions{} - mountPoint, err := s.StorageRuntimeServer().StartContainer(id) - if err != nil { - return nil, fmt.Errorf("failed to mount container %s in pod sandbox %s(%s): %v", containerName, sb.Name(), id, err) - } - g.AddAnnotation(annotations.MountPoint, mountPoint) - g.SetRootPath(mountPoint) - - hostnamePath := fmt.Sprintf("%s/hostname", podContainer.RunDir) - if err := ioutil.WriteFile(hostnamePath, []byte(hostname+"\n"), 0644); err != nil { - return nil, err - } - if err := label.Relabel(hostnamePath, mountLabel, true); err != nil && err != unix.ENOTSUP { - return nil, err - } - g.AddBindMount(hostnamePath, "/etc/hostname", []string{"ro"}) - g.AddAnnotation(annotations.HostnamePath, hostnamePath) - sb.AddHostnamePath(hostnamePath) - - container, err := oci.NewContainer(id, containerName, podContainer.RunDir, logPath, sb.NetNs(), labels, g.Spec().Annotations, kubeAnnotations, "", "", "", nil, id, false, false, false, sb.Privileged(), sb.Trusted(), podContainer.Dir, created, podContainer.Config.Config.StopSignal) - if err != nil { - return nil, err - } - container.SetSpec(g.Spec()) - container.SetMountPoint(mountPoint) - - sb.SetInfraContainer(container) - - var ip string - ip, err = s.networkStart(hostNetwork, sb) - if err != nil { - return nil, err - } - defer func() { - if err != nil { - s.networkStop(hostNetwork, sb) - } - }() - - g.AddAnnotation(annotations.IP, ip) - sb.AddIP(ip) - - err = g.SaveToFile(filepath.Join(podContainer.Dir, "config.json"), saveOptions) - if err != nil { - return nil, fmt.Errorf("failed to save template configuration for pod sandbox %s(%s): %v", sb.Name(), id, err) - } - if err = g.SaveToFile(filepath.Join(podContainer.RunDir, "config.json"), saveOptions); err != nil { - return nil, fmt.Errorf("failed to write runtime configuration for pod sandbox %s(%s): %v", sb.Name(), id, err) - } - - if err = s.runContainer(container, sb.CgroupParent()); err != nil { - return nil, err - } - - s.addInfraContainer(container) - - s.ContainerStateToDisk(container) - - resp = &pb.RunPodSandboxResponse{PodSandboxId: id} - logrus.Debugf("RunPodSandboxResponse: %+v", resp) - return resp, nil -} - -func convertPortMappings(in []*pb.PortMapping) []*hostport.PortMapping { - if in == nil { - return nil - } - out := make([]*hostport.PortMapping, len(in)) - for i, v := range in { - out[i] = &hostport.PortMapping{ - HostPort: v.HostPort, - ContainerPort: v.ContainerPort, - Protocol: v1.Protocol(v.Protocol.String()), - HostIP: v.HostIp, - } - } - return out -} - -func getHostname(id, hostname string, hostNetwork bool) (string, error) { - if hostNetwork { - if hostname == "" { - h, err := os.Hostname() - if err != nil { - return "", err - } - hostname = h - } - } else { - if hostname == "" { - hostname = id[:12] - } - } - return hostname, nil -} - -func (s *Server) setPodSandboxMountLabel(id, mountLabel string) error { - storageMetadata, err := s.StorageRuntimeServer().GetContainerMetadata(id) - if err != nil { - return err - } - storageMetadata.SetMountLabel(mountLabel) - return s.StorageRuntimeServer().SetContainerMetadata(id, storageMetadata) -} - -func getSELinuxLabels(selinuxOptions *pb.SELinuxOption, privileged bool) (processLabel string, mountLabel string, err error) { - if privileged { - return "", "", nil - } - labels := []string{} - if selinuxOptions != nil { - if selinuxOptions.User != "" { - labels = append(labels, "user:"+selinuxOptions.User) - } - if selinuxOptions.Role != "" { - labels = append(labels, "role:"+selinuxOptions.Role) - } - if selinuxOptions.Type != "" { - labels = append(labels, "type:"+selinuxOptions.Type) - } - if selinuxOptions.Level != "" { - labels = append(labels, "level:"+selinuxOptions.Level) - } - } - return label.InitLabels(labels) -} - -func setupShm(podSandboxRunDir, mountLabel string) (shmPath string, err error) { - shmPath = filepath.Join(podSandboxRunDir, "shm") - if err = os.Mkdir(shmPath, 0700); err != nil { - return "", err - } - shmOptions := "mode=1777,size=" + strconv.Itoa(sandbox.DefaultShmSize) - if err = unix.Mount("shm", shmPath, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, - label.FormatMountLabel(shmOptions, mountLabel)); err != nil { - return "", fmt.Errorf("failed to mount shm tmpfs for pod: %v", err) - } - return shmPath, nil -} - -// convertCgroupFsNameToSystemd converts an expanded cgroupfs name to its systemd name. -// For example, it will convert test.slice/test-a.slice/test-a-b.slice to become test-a-b.slice -// NOTE: this is public right now to allow its usage in dockermanager and dockershim, ideally both those -// code areas could use something from libcontainer if we get this style function upstream. -func convertCgroupFsNameToSystemd(cgroupfsName string) (string, error) { - // TODO: see if libcontainer systemd implementation could use something similar, and if so, move - // this function up to that library. At that time, it would most likely do validation specific to systemd - // above and beyond the simple assumption here that the base of the path encodes the hierarchy - // per systemd convention. - return path.Base(cgroupfsName), nil -} diff --git a/server/sandbox_status.go b/server/sandbox_status.go deleted file mode 100644 index f5b6dd09a..000000000 --- a/server/sandbox_status.go +++ /dev/null @@ -1,41 +0,0 @@ -package server - -import ( - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// PodSandboxStatus returns the Status of the PodSandbox. -func (s *Server) PodSandboxStatus(ctx context.Context, req *pb.PodSandboxStatusRequest) (*pb.PodSandboxStatusResponse, error) { - logrus.Debugf("PodSandboxStatusRequest %+v", req) - sb, err := s.getPodSandboxFromRequest(req.PodSandboxId) - if err != nil { - return nil, err - } - - podInfraContainer := sb.InfraContainer() - cState := s.Runtime().ContainerStatus(podInfraContainer) - - rStatus := pb.PodSandboxState_SANDBOX_NOTREADY - if cState.Status == oci.ContainerStateRunning { - rStatus = pb.PodSandboxState_SANDBOX_READY - } - - sandboxID := sb.ID() - resp := &pb.PodSandboxStatusResponse{ - Status: &pb.PodSandboxStatus{ - Id: sandboxID, - CreatedAt: podInfraContainer.CreatedAt().UnixNano(), - Network: &pb.PodSandboxNetworkStatus{Ip: sb.IP()}, - State: rStatus, - Labels: sb.Labels(), - Annotations: sb.Annotations(), - Metadata: sb.Metadata(), - }, - } - - logrus.Debugf("PodSandboxStatusResponse: %+v", resp) - return resp, nil -} diff --git a/server/sandbox_stop.go b/server/sandbox_stop.go deleted file mode 100644 index 9d6a5aa3c..000000000 --- a/server/sandbox_stop.go +++ /dev/null @@ -1,114 +0,0 @@ -package server - -import ( - "fmt" - - "github.com/containers/storage" - "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/symlink" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "golang.org/x/sys/unix" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -// StopPodSandbox stops the sandbox. If there are any running containers in the -// sandbox, they should be force terminated. -func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxRequest) (*pb.StopPodSandboxResponse, error) { - logrus.Debugf("StopPodSandboxRequest %+v", req) - sb, err := s.getPodSandboxFromRequest(req.PodSandboxId) - if err != nil { - if err == sandbox.ErrIDEmpty { - return nil, err - } - - // If the sandbox isn't found we just return an empty response to adhere - // the the CRI interface which expects to not error out in not found - // cases. - - resp := &pb.StopPodSandboxResponse{} - logrus.Warnf("could not get sandbox %s, it's probably been stopped already: %v", req.PodSandboxId, err) - logrus.Debugf("StopPodSandboxResponse %s: %+v", req.PodSandboxId, resp) - return resp, nil - } - - if sb.Stopped() { - resp := &pb.StopPodSandboxResponse{} - logrus.Debugf("StopPodSandboxResponse %s: %+v", sb.ID(), resp) - return resp, nil - } - - // Clean up sandbox networking and close its network namespace. - hostNetwork := sb.NetNsPath() == "" - s.networkStop(hostNetwork, sb) - if err := sb.NetNsRemove(); err != nil { - return nil, err - } - - podInfraContainer := sb.InfraContainer() - containers := sb.Containers().List() - containers = append(containers, podInfraContainer) - - for _, c := range containers { - cStatus := s.Runtime().ContainerStatus(c) - if cStatus.Status != oci.ContainerStateStopped { - if err := s.Runtime().StopContainer(ctx, c, 10); err != nil { - return nil, fmt.Errorf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err) - } - if c.ID() == podInfraContainer.ID() { - continue - } - if err := s.StorageRuntimeServer().StopContainer(c.ID()); err != nil && errors.Cause(err) != storage.ErrContainerUnknown { - // assume container already umounted - logrus.Warnf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err) - } - } - s.ContainerStateToDisk(c) - } - - if err := label.ReleaseLabel(sb.ProcessLabel()); err != nil { - return nil, err - } - - // unmount the shm for the pod - if sb.ShmPath() != "/dev/shm" { - // we got namespaces in the form of - // /var/run/containers/storage/overlay-containers/CID/userdata/shm - // but /var/run on most system is symlinked to /run so we first resolve - // the symlink and then try and see if it's mounted - fp, err := symlink.FollowSymlinkInScope(sb.ShmPath(), "/") - if err != nil { - return nil, err - } - if mounted, err := mount.Mounted(fp); err == nil && mounted { - if err := unix.Unmount(fp, unix.MNT_DETACH); err != nil { - return nil, err - } - } - } - if err := s.StorageRuntimeServer().StopContainer(sb.ID()); err != nil && errors.Cause(err) != storage.ErrContainerUnknown { - logrus.Warnf("failed to stop sandbox container in pod sandbox %s: %v", sb.ID(), err) - } - - sb.SetStopped() - resp := &pb.StopPodSandboxResponse{} - logrus.Debugf("StopPodSandboxResponse %s: %+v", sb.ID(), resp) - return resp, nil -} - -// StopAllPodSandboxes removes all pod sandboxes -func (s *Server) StopAllPodSandboxes() { - logrus.Debugf("StopAllPodSandboxes") - for _, sb := range s.ContainerServer.ListSandboxes() { - pod := &pb.StopPodSandboxRequest{ - PodSandboxId: sb.ID(), - } - if _, err := s.StopPodSandbox(nil, pod); err != nil { - logrus.Warnf("could not StopPodSandbox %s: %v", sb.ID(), err) - } - } -} diff --git a/server/seccomp/seccomp.go b/server/seccomp/seccomp.go deleted file mode 100644 index cf77c8274..000000000 --- a/server/seccomp/seccomp.go +++ /dev/null @@ -1,165 +0,0 @@ -// +build seccomp - -package seccomp - -import ( - "encoding/json" - "errors" - "fmt" - - "github.com/docker/docker/pkg/stringutils" - specs "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/runtime-tools/generate" - libseccomp "github.com/seccomp/libseccomp-golang" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" -) - -// IsEnabled returns true if seccomp is enabled for the host. -func IsEnabled() bool { - enabled := false - // Check if Seccomp is supported, via CONFIG_SECCOMP. - if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL { - // Make sure the kernel has CONFIG_SECCOMP_FILTER. - if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL { - enabled = true - } - } - logrus.Debugf("seccomp status: %v", enabled) - return enabled -} - -// LoadProfileFromStruct takes a Seccomp struct and setup seccomp in the spec. -func LoadProfileFromStruct(config Seccomp, specgen *generate.Generator) error { - return setupSeccomp(&config, specgen) -} - -// LoadProfileFromBytes takes a byte slice and decodes the seccomp profile. -func LoadProfileFromBytes(body []byte, specgen *generate.Generator) error { - var config Seccomp - if err := json.Unmarshal(body, &config); err != nil { - return fmt.Errorf("decoding seccomp profile failed: %v", err) - } - return setupSeccomp(&config, specgen) -} - -var nativeToSeccomp = map[string]Arch{ - "amd64": ArchX86_64, - "arm64": ArchAARCH64, - "mips64": ArchMIPS64, - "mips64n32": ArchMIPS64N32, - "mipsel64": ArchMIPSEL64, - "mipsel64n32": ArchMIPSEL64N32, - "s390x": ArchS390X, -} - -func setupSeccomp(config *Seccomp, specgen *generate.Generator) error { - if config == nil { - return nil - } - - // No default action specified, no syscalls listed, assume seccomp disabled - if config.DefaultAction == "" && len(config.Syscalls) == 0 { - return nil - } - - var arch string - var native, err = libseccomp.GetNativeArch() - if err == nil { - arch = native.String() - } - - if len(config.Architectures) != 0 && len(config.ArchMap) != 0 { - return errors.New("'architectures' and 'archMap' were specified in the seccomp profile, use either 'architectures' or 'archMap'") - } - - customspec := specgen.Spec() - customspec.Linux.Seccomp = &specs.LinuxSeccomp{} - - // if config.Architectures == 0 then libseccomp will figure out the architecture to use - if len(config.Architectures) != 0 { - for _, a := range config.Architectures { - customspec.Linux.Seccomp.Architectures = append(customspec.Linux.Seccomp.Architectures, specs.Arch(a)) - } - } - - if len(config.ArchMap) != 0 { - for _, a := range config.ArchMap { - seccompArch, ok := nativeToSeccomp[arch] - if ok { - if a.Arch == seccompArch { - customspec.Linux.Seccomp.Architectures = append(customspec.Linux.Seccomp.Architectures, specs.Arch(a.Arch)) - for _, sa := range a.SubArches { - customspec.Linux.Seccomp.Architectures = append(customspec.Linux.Seccomp.Architectures, specs.Arch(sa)) - } - break - } - } - } - } - - customspec.Linux.Seccomp.DefaultAction = specs.LinuxSeccompAction(config.DefaultAction) - -Loop: - // Loop through all syscall blocks and convert them to libcontainer format after filtering them - for _, call := range config.Syscalls { - if len(call.Excludes.Arches) > 0 { - if stringutils.InSlice(call.Excludes.Arches, arch) { - continue Loop - } - } - if len(call.Excludes.Caps) > 0 { - for _, c := range call.Excludes.Caps { - if stringutils.InSlice(customspec.Process.Capabilities.Permitted, c) { - continue Loop - } - } - } - if len(call.Includes.Arches) > 0 { - if !stringutils.InSlice(call.Includes.Arches, arch) { - continue Loop - } - } - if len(call.Includes.Caps) > 0 { - for _, c := range call.Includes.Caps { - if !stringutils.InSlice(customspec.Process.Capabilities.Permitted, c) { - continue Loop - } - } - } - - if call.Name != "" && len(call.Names) != 0 { - return errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'") - } - - if call.Name != "" { - customspec.Linux.Seccomp.Syscalls = append(customspec.Linux.Seccomp.Syscalls, createSpecsSyscall(call.Name, call.Action, call.Args)) - } - - for _, n := range call.Names { - customspec.Linux.Seccomp.Syscalls = append(customspec.Linux.Seccomp.Syscalls, createSpecsSyscall(n, call.Action, call.Args)) - } - } - - return nil -} - -func createSpecsSyscall(name string, action Action, args []*Arg) specs.LinuxSyscall { - newCall := specs.LinuxSyscall{ - Names: []string{name}, - Action: specs.LinuxSeccompAction(action), - } - - // Loop through all the arguments of the syscall and convert them - for _, arg := range args { - newArg := specs.LinuxSeccompArg{ - Index: arg.Index, - Value: arg.Value, - ValueTwo: arg.ValueTwo, - Op: specs.LinuxSeccompOperator(arg.Op), - } - - newCall.Args = append(newCall.Args, newArg) - } - return newCall -} diff --git a/server/seccomp/seccomp_unsupported.go b/server/seccomp/seccomp_unsupported.go deleted file mode 100644 index efb36bdf9..000000000 --- a/server/seccomp/seccomp_unsupported.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build !seccomp - -package seccomp - -import "github.com/opencontainers/runtime-tools/generate" - -// IsEnabled returns false, when build without seccomp build tag. -func IsEnabled() bool { - return false -} - -// LoadProfileFromStruct takes a Seccomp struct and setup seccomp in the spec. -func LoadProfileFromStruct(config Seccomp, specgen *generate.Generator) error { - return nil -} - -// LoadProfileFromBytes takes a byte slice and decodes the seccomp profile. -func LoadProfileFromBytes(body []byte, specgen *generate.Generator) error { - return nil -} diff --git a/server/seccomp/types.go b/server/seccomp/types.go deleted file mode 100644 index 5b07f8c03..000000000 --- a/server/seccomp/types.go +++ /dev/null @@ -1,93 +0,0 @@ -package seccomp - -// Seccomp represents the config for a seccomp profile for syscall restriction. -type Seccomp struct { - DefaultAction Action `json:"defaultAction"` - // Architectures is kept to maintain backward compatibility with the old - // seccomp profile. - Architectures []Arch `json:"architectures,omitempty"` - ArchMap []Architecture `json:"archMap,omitempty"` - Syscalls []*Syscall `json:"syscalls"` -} - -// Architecture is used to represent an specific architecture -// and its sub-architectures -type Architecture struct { - Arch Arch `json:"architecture"` - SubArches []Arch `json:"subArchitectures"` -} - -// Arch used for architectures -type Arch string - -// Additional architectures permitted to be used for system calls -// By default only the native architecture of the kernel is permitted -const ( - ArchX86 Arch = "SCMP_ARCH_X86" - ArchX86_64 Arch = "SCMP_ARCH_X86_64" - ArchX32 Arch = "SCMP_ARCH_X32" - ArchARM Arch = "SCMP_ARCH_ARM" - ArchAARCH64 Arch = "SCMP_ARCH_AARCH64" - ArchMIPS Arch = "SCMP_ARCH_MIPS" - ArchMIPS64 Arch = "SCMP_ARCH_MIPS64" - ArchMIPS64N32 Arch = "SCMP_ARCH_MIPS64N32" - ArchMIPSEL Arch = "SCMP_ARCH_MIPSEL" - ArchMIPSEL64 Arch = "SCMP_ARCH_MIPSEL64" - ArchMIPSEL64N32 Arch = "SCMP_ARCH_MIPSEL64N32" - ArchPPC Arch = "SCMP_ARCH_PPC" - ArchPPC64 Arch = "SCMP_ARCH_PPC64" - ArchPPC64LE Arch = "SCMP_ARCH_PPC64LE" - ArchS390 Arch = "SCMP_ARCH_S390" - ArchS390X Arch = "SCMP_ARCH_S390X" -) - -// Action taken upon Seccomp rule match -type Action string - -// Define actions for Seccomp rules -const ( - ActKill Action = "SCMP_ACT_KILL" - ActTrap Action = "SCMP_ACT_TRAP" - ActErrno Action = "SCMP_ACT_ERRNO" - ActTrace Action = "SCMP_ACT_TRACE" - ActAllow Action = "SCMP_ACT_ALLOW" -) - -// Operator used to match syscall arguments in Seccomp -type Operator string - -// Define operators for syscall arguments in Seccomp -const ( - OpNotEqual Operator = "SCMP_CMP_NE" - OpLessThan Operator = "SCMP_CMP_LT" - OpLessEqual Operator = "SCMP_CMP_LE" - OpEqualTo Operator = "SCMP_CMP_EQ" - OpGreaterEqual Operator = "SCMP_CMP_GE" - OpGreaterThan Operator = "SCMP_CMP_GT" - OpMaskedEqual Operator = "SCMP_CMP_MASKED_EQ" -) - -// Arg used for matching specific syscall arguments in Seccomp -type Arg struct { - Index uint `json:"index"` - Value uint64 `json:"value"` - ValueTwo uint64 `json:"valueTwo"` - Op Operator `json:"op"` -} - -// Filter is used to conditionally apply Seccomp rules -type Filter struct { - Caps []string `json:"caps,omitempty"` - Arches []string `json:"arches,omitempty"` -} - -// Syscall is used to match a group of syscalls in Seccomp -type Syscall struct { - Name string `json:"name,omitempty"` - Names []string `json:"names,omitempty"` - Action Action `json:"action"` - Args []*Arg `json:"args"` - Comment string `json:"comment"` - Includes Filter `json:"includes"` - Excludes Filter `json:"excludes"` -} diff --git a/server/secrets.go b/server/secrets.go deleted file mode 100644 index 56d3ba81a..000000000 --- a/server/secrets.go +++ /dev/null @@ -1,162 +0,0 @@ -package server - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - - rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// SecretData info -type SecretData struct { - Name string - Data []byte -} - -// SaveTo saves secret data to given directory -func (s SecretData) SaveTo(dir string) error { - path := filepath.Join(dir, s.Name) - if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil && !os.IsExist(err) { - return err - } - return ioutil.WriteFile(path, s.Data, 0700) -} - -func readAll(root, prefix string) ([]SecretData, error) { - path := filepath.Join(root, prefix) - - data := []SecretData{} - - files, err := ioutil.ReadDir(path) - if err != nil { - if os.IsNotExist(err) { - return data, nil - } - - return nil, err - } - - for _, f := range files { - fileData, err := readFile(root, filepath.Join(prefix, f.Name())) - if err != nil { - // If the file did not exist, might be a dangling symlink - // Ignore the error - if os.IsNotExist(err) { - continue - } - return nil, err - } - data = append(data, fileData...) - } - - return data, nil -} - -func readFile(root, name string) ([]SecretData, error) { - path := filepath.Join(root, name) - - s, err := os.Stat(path) - if err != nil { - return nil, err - } - - if s.IsDir() { - dirData, err := readAll(root, name) - if err != nil { - return nil, err - } - return dirData, nil - } - bytes, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - return []SecretData{{Name: name, Data: bytes}}, nil -} - -// getHostAndCtrDir separates the host:container paths -func getMountsMap(path string) (string, string, error) { - arr := strings.SplitN(path, ":", 2) - if len(arr) == 2 { - return arr[0], arr[1], nil - } - return "", "", errors.Errorf("unable to get host and container dir") -} - -func getHostSecretData(hostDir string) ([]SecretData, error) { - var allSecrets []SecretData - hostSecrets, err := readAll(hostDir, "") - if err != nil { - return nil, errors.Wrapf(err, "failed to read secrets from %q", hostDir) - } - return append(allSecrets, hostSecrets...), nil -} - -// secretMount copies the contents of host directory to container directory -// and returns a list of mounts -func secretMounts(defaultMountsPaths []string, mountLabel, containerWorkingDir string, runtimeMounts []rspec.Mount) ([]rspec.Mount, error) { - var mounts []rspec.Mount - for _, path := range defaultMountsPaths { - hostDir, ctrDir, err := getMountsMap(path) - if err != nil { - return nil, err - } - // skip if the hostDir path doesn't exist - if _, err := os.Stat(hostDir); os.IsNotExist(err) { - logrus.Warnf("%q doesn't exist, skipping", hostDir) - continue - } - - ctrDirOnHost := filepath.Join(containerWorkingDir, ctrDir) - // skip if ctrDir has already been mounted by caller - if isAlreadyMounted(runtimeMounts, ctrDir) { - logrus.Warnf("%q has already been mounted; cannot override mount", ctrDir) - continue - } - - if err := os.RemoveAll(ctrDirOnHost); err != nil { - return nil, fmt.Errorf("remove container directory failed: %v", err) - } - - if err := os.MkdirAll(ctrDirOnHost, 0755); err != nil { - return nil, fmt.Errorf("making container directory failed: %v", err) - } - - hostDir, err = resolveSymbolicLink(hostDir) - if err != nil { - return nil, err - } - - data, err := getHostSecretData(hostDir) - if err != nil { - return nil, errors.Wrapf(err, "getting host secret data failed") - } - for _, s := range data { - s.SaveTo(ctrDirOnHost) - } - label.Relabel(ctrDirOnHost, mountLabel, false) - - m := rspec.Mount{ - Source: ctrDirOnHost, - Destination: ctrDir, - } - - mounts = append(mounts, m) - } - return mounts, nil -} - -func isAlreadyMounted(mounts []rspec.Mount, mountPath string) bool { - for _, mount := range mounts { - if mount.Destination == mountPath { - return true - } - } - return false -} diff --git a/server/server.go b/server/server.go deleted file mode 100644 index a308e7d29..000000000 --- a/server/server.go +++ /dev/null @@ -1,423 +0,0 @@ -package server - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net" - "net/http" - "os" - "path/filepath" - "runtime/debug" - "strconv" - "strings" - "sync" - - "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/fsnotify/fsnotify" - "github.com/kubernetes-incubator/cri-o/libkpod" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/kubernetes-incubator/cri-o/oci" - "github.com/kubernetes-incubator/cri-o/pkg/storage" - "github.com/kubernetes-incubator/cri-o/server/apparmor" - "github.com/kubernetes-incubator/cri-o/server/seccomp" - "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" - knet "k8s.io/apimachinery/pkg/util/net" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - "k8s.io/kubernetes/pkg/kubelet/network/hostport" - "k8s.io/kubernetes/pkg/kubelet/server/streaming" - iptablesproxy "k8s.io/kubernetes/pkg/proxy/iptables" - utildbus "k8s.io/kubernetes/pkg/util/dbus" - utilexec "k8s.io/kubernetes/pkg/util/exec" - utiliptables "k8s.io/kubernetes/pkg/util/iptables" -) - -const ( - shutdownFile = "/var/lib/crio/crio.shutdown" -) - -func isTrue(annotaton string) bool { - return annotaton == "true" -} - -// streamService implements streaming.Runtime. -type streamService struct { - runtimeServer *Server // needed by Exec() endpoint - streamServer streaming.Server - streamServerCloseCh chan struct{} - streaming.Runtime -} - -// Server implements the RuntimeService and ImageService -type Server struct { - *libkpod.ContainerServer - config Config - - updateLock sync.RWMutex - netPlugin ocicni.CNIPlugin - hostportManager hostport.HostPortManager - - seccompEnabled bool - seccompProfile seccomp.Seccomp - - appArmorEnabled bool - appArmorProfile string - - bindAddress string - stream streamService - exitMonitorChan chan struct{} -} - -// StopStreamServer stops the stream server -func (s *Server) StopStreamServer() error { - return s.stream.streamServer.Stop() -} - -// StreamingServerCloseChan returns the close channel for the streaming server -func (s *Server) StreamingServerCloseChan() chan struct{} { - return s.stream.streamServerCloseCh -} - -// GetExec returns exec stream request -func (s *Server) GetExec(req *pb.ExecRequest) (*pb.ExecResponse, error) { - return s.stream.streamServer.GetExec(req) -} - -// GetAttach returns attach stream request -func (s *Server) GetAttach(req *pb.AttachRequest) (*pb.AttachResponse, error) { - return s.stream.streamServer.GetAttach(req) -} - -// GetPortForward returns port forward stream request -func (s *Server) GetPortForward(req *pb.PortForwardRequest) (*pb.PortForwardResponse, error) { - return s.stream.streamServer.GetPortForward(req) -} - -func (s *Server) restore() { - containers, err := s.Store().Containers() - if err != nil && !os.IsNotExist(errors.Cause(err)) { - logrus.Warnf("could not read containers and sandboxes: %v", err) - } - pods := map[string]*storage.RuntimeContainerMetadata{} - podContainers := map[string]*storage.RuntimeContainerMetadata{} - for _, container := range containers { - metadata, err2 := s.StorageRuntimeServer().GetContainerMetadata(container.ID) - if err2 != nil { - logrus.Warnf("error parsing metadata for %s: %v, ignoring", container.ID, err2) - continue - } - if metadata.Pod { - pods[container.ID] = &metadata - } else { - podContainers[container.ID] = &metadata - } - } - for containerID, metadata := range pods { - if err = s.LoadSandbox(containerID); err != nil { - logrus.Warnf("could not restore sandbox %s container %s: %v", metadata.PodID, containerID, err) - } - } - for containerID := range podContainers { - if err := s.LoadContainer(containerID); err != nil { - logrus.Warnf("could not restore container %s: %v", containerID, err) - } - } -} - -// Update makes changes to the server's state (lists of pods and containers) to -// reflect the list of pods and containers that are stored on disk, possibly -// having been modified by other parties -func (s *Server) Update() { - logrus.Debugf("updating sandbox and container information") - if err := s.ContainerServer.Update(); err != nil { - logrus.Errorf("error updating sandbox and container information: %v", err) - } -} - -// cleanupSandboxesOnShutdown Remove all running Sandboxes on system shutdown -func (s *Server) cleanupSandboxesOnShutdown() { - _, err := os.Stat(shutdownFile) - if err == nil || !os.IsNotExist(err) { - logrus.Debugf("shutting down all sandboxes, on shutdown") - s.StopAllPodSandboxes() - err = os.Remove(shutdownFile) - if err != nil { - logrus.Warnf("Failed to remove %q", shutdownFile) - } - - } -} - -// Shutdown attempts to shut down the server's storage cleanly -func (s *Server) Shutdown() error { - // why do this on clean shutdown! we want containers left running when crio - // is down for whatever reason no?! - // notice this won't trigger just on system halt but also on normal - // crio.service restart!!! - s.cleanupSandboxesOnShutdown() - return s.ContainerServer.Shutdown() -} - -// configureMaxThreads sets the Go runtime max threads threshold -// which is 90% of the kernel setting from /proc/sys/kernel/threads-max -func configureMaxThreads() error { - mt, err := ioutil.ReadFile("/proc/sys/kernel/threads-max") - if err != nil { - return err - } - mtint, err := strconv.Atoi(strings.TrimSpace(string(mt))) - if err != nil { - return err - } - maxThreads := (mtint / 100) * 90 - debug.SetMaxThreads(maxThreads) - logrus.Debugf("Golang's threads limit set to %d", maxThreads) - return nil -} - -// New creates a new Server with options provided -func New(config *Config) (*Server, error) { - if err := os.MkdirAll("/var/run/crio", 0755); err != nil { - return nil, err - } - - config.ContainerExitsDir = oci.ContainerExitsDir - - // This is used to monitor container exits using inotify - if err := os.MkdirAll(config.ContainerExitsDir, 0755); err != nil { - return nil, err - } - containerServer, err := libkpod.New(&config.Config) - if err != nil { - return nil, err - } - - netPlugin, err := ocicni.InitCNI(config.NetworkDir, config.PluginDir) - if err != nil { - return nil, err - } - iptInterface := utiliptables.New(utilexec.New(), utildbus.New(), utiliptables.ProtocolIpv4) - iptInterface.EnsureChain(utiliptables.TableNAT, iptablesproxy.KubeMarkMasqChain) - hostportManager := hostport.NewHostportManager() - - s := &Server{ - ContainerServer: containerServer, - netPlugin: netPlugin, - hostportManager: hostportManager, - config: *config, - seccompEnabled: seccomp.IsEnabled(), - appArmorEnabled: apparmor.IsEnabled(), - appArmorProfile: config.ApparmorProfile, - exitMonitorChan: make(chan struct{}), - } - - if s.seccompEnabled { - seccompProfile, fileErr := ioutil.ReadFile(config.SeccompProfile) - if fileErr != nil { - return nil, fmt.Errorf("opening seccomp profile (%s) failed: %v", config.SeccompProfile, fileErr) - } - var seccompConfig seccomp.Seccomp - if jsonErr := json.Unmarshal(seccompProfile, &seccompConfig); jsonErr != nil { - return nil, fmt.Errorf("decoding seccomp profile failed: %v", jsonErr) - } - s.seccompProfile = seccompConfig - } - - if s.appArmorEnabled && s.appArmorProfile == apparmor.DefaultApparmorProfile { - if apparmorErr := apparmor.EnsureDefaultApparmorProfile(); apparmorErr != nil { - return nil, fmt.Errorf("ensuring the default apparmor profile is installed failed: %v", apparmorErr) - } - } - - if err := configureMaxThreads(); err != nil { - return nil, err - } - - s.restore() - s.cleanupSandboxesOnShutdown() - - bindAddress := net.ParseIP(config.StreamAddress) - if bindAddress == nil { - bindAddress, err = knet.ChooseBindAddress(net.IP{0, 0, 0, 0}) - if err != nil { - return nil, err - } - } - s.bindAddress = bindAddress.String() - - _, err = net.LookupPort("tcp", config.StreamPort) - if err != nil { - return nil, err - } - - // Prepare streaming server - streamServerConfig := streaming.DefaultConfig - streamServerConfig.Addr = net.JoinHostPort(bindAddress.String(), config.StreamPort) - s.stream.runtimeServer = s - s.stream.streamServer, err = streaming.NewServer(streamServerConfig, s.stream) - if err != nil { - return nil, fmt.Errorf("unable to create streaming server") - } - - s.stream.streamServerCloseCh = make(chan struct{}) - go func() { - defer close(s.stream.streamServerCloseCh) - if err := s.stream.streamServer.Start(true); err != nil { - logrus.Errorf("Failed to start streaming server: %v", err) - } - }() - - logrus.Debugf("sandboxes: %v", s.ContainerServer.ListSandboxes()) - return s, nil -} - -func (s *Server) addSandbox(sb *sandbox.Sandbox) { - s.ContainerServer.AddSandbox(sb) -} - -func (s *Server) getSandbox(id string) *sandbox.Sandbox { - return s.ContainerServer.GetSandbox(id) -} - -func (s *Server) hasSandbox(id string) bool { - return s.ContainerServer.HasSandbox(id) -} - -func (s *Server) removeSandbox(id string) { - s.ContainerServer.RemoveSandbox(id) -} - -func (s *Server) addContainer(c *oci.Container) { - s.ContainerServer.AddContainer(c) -} - -func (s *Server) addInfraContainer(c *oci.Container) { - s.ContainerServer.AddInfraContainer(c) -} - -func (s *Server) getContainer(id string) *oci.Container { - return s.ContainerServer.GetContainer(id) -} - -func (s *Server) getInfraContainer(id string) *oci.Container { - return s.ContainerServer.GetInfraContainer(id) -} - -// BindAddress is used to retrieve host's IP -func (s *Server) BindAddress() string { - return s.bindAddress -} - -// GetSandboxContainer returns the infra container for a given sandbox -func (s *Server) GetSandboxContainer(id string) *oci.Container { - return s.ContainerServer.GetSandboxContainer(id) -} - -// GetContainer returns a container by its ID -func (s *Server) GetContainer(id string) *oci.Container { - return s.getContainer(id) -} - -func (s *Server) removeContainer(c *oci.Container) { - s.ContainerServer.RemoveContainer(c) -} - -func (s *Server) removeInfraContainer(c *oci.Container) { - s.ContainerServer.RemoveInfraContainer(c) -} - -func (s *Server) getPodSandboxFromRequest(podSandboxID string) (*sandbox.Sandbox, error) { - if podSandboxID == "" { - return nil, sandbox.ErrIDEmpty - } - - sandboxID, err := s.PodIDIndex().Get(podSandboxID) - if err != nil { - return nil, fmt.Errorf("PodSandbox with ID starting with %s not found: %v", podSandboxID, err) - } - - sb := s.getSandbox(sandboxID) - if sb == nil { - return nil, fmt.Errorf("specified pod sandbox not found: %s", sandboxID) - } - return sb, nil -} - -// CreateMetricsEndpoint creates a /metrics endpoint -// for prometheus monitoring -func (s *Server) CreateMetricsEndpoint() (*http.ServeMux, error) { - mux := &http.ServeMux{} - mux.Handle("/metrics", prometheus.Handler()) - return mux, nil -} - -// StopExitMonitor stops the exit monitor -func (s *Server) StopExitMonitor() { - close(s.exitMonitorChan) -} - -// ExitMonitorCloseChan returns the close chan for the exit monitor -func (s *Server) ExitMonitorCloseChan() chan struct{} { - return s.exitMonitorChan -} - -// StartExitMonitor start a routine that monitors container exits -// and updates the container status -func (s *Server) StartExitMonitor() { - watcher, err := fsnotify.NewWatcher() - if err != nil { - logrus.Fatalf("Failed to create new watch: %v", err) - } - defer watcher.Close() - - done := make(chan struct{}) - go func() { - for { - select { - case event := <-watcher.Events: - logrus.Debugf("event: %v", event) - if event.Op&fsnotify.Create == fsnotify.Create { - containerID := filepath.Base(event.Name) - logrus.Debugf("container or sandbox exited: %v", containerID) - c := s.GetContainer(containerID) - if c != nil { - logrus.Debugf("container exited and found: %v", containerID) - err := s.Runtime().UpdateStatus(c) - if err != nil { - logrus.Warnf("Failed to update container status %s: %v", c, err) - } else { - s.ContainerStateToDisk(c) - } - } else { - sb := s.GetSandbox(containerID) - if sb != nil { - c := sb.InfraContainer() - logrus.Debugf("sandbox exited and found: %v", containerID) - err := s.Runtime().UpdateStatus(c) - if err != nil { - logrus.Warnf("Failed to update sandbox infra container status %s: %v", c, err) - } else { - s.ContainerStateToDisk(c) - } - } - } - } - case err := <-watcher.Errors: - logrus.Debugf("watch error: %v", err) - close(done) - return - case <-s.exitMonitorChan: - logrus.Debug("closing exit monitor...") - close(done) - return - } - } - }() - if err := watcher.Add(s.config.ContainerExitsDir); err != nil { - logrus.Errorf("watcher.Add(%q) failed: %s", s.config.ContainerExitsDir, err) - close(done) - } - <-done -} diff --git a/server/utils.go b/server/utils.go deleted file mode 100644 index 195942d38..000000000 --- a/server/utils.go +++ /dev/null @@ -1,183 +0,0 @@ -package server - -import ( - "fmt" - "io" - "os" - "strings" - - "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/kubernetes-incubator/cri-o/libkpod/sandbox" - "github.com/opencontainers/runtime-tools/validate" - "github.com/syndtr/gocapability/capability" -) - -const ( - // According to http://man7.org/linux/man-pages/man5/resolv.conf.5.html: - // "The search list is currently limited to six domains with a total of 256 characters." - maxDNSSearches = 6 -) - -func copyFile(src, dest string) error { - in, err := os.Open(src) - if err != nil { - return err - } - defer in.Close() - - out, err := os.Create(dest) - if err != nil { - return err - } - defer out.Close() - - _, err = io.Copy(out, in) - return err -} - -func removeFile(path string) error { - if _, err := os.Stat(path); err == nil { - if err := os.Remove(path); err != nil { - return err - } - } - return nil -} - -func parseDNSOptions(servers, searches, options []string, path string) error { - nServers := len(servers) - nSearches := len(searches) - nOptions := len(options) - if nServers == 0 && nSearches == 0 && nOptions == 0 { - return copyFile("/etc/resolv.conf", path) - } - - if nSearches > maxDNSSearches { - return fmt.Errorf("DNSOption.Searches has more than 6 domains") - } - - f, err := os.Create(path) - if err != nil { - return err - } - defer f.Close() - - if nSearches > 0 { - data := fmt.Sprintf("search %s\n", strings.Join(searches, " ")) - _, err = f.Write([]byte(data)) - if err != nil { - return err - } - } - - if nServers > 0 { - data := fmt.Sprintf("nameserver %s\n", strings.Join(servers, "\nnameserver ")) - _, err = f.Write([]byte(data)) - if err != nil { - return err - } - } - - if nOptions > 0 { - data := fmt.Sprintf("options %s\n", strings.Join(options, " ")) - _, err = f.Write([]byte(data)) - if err != nil { - return err - } - } - - return nil -} - -// TODO: remove sysctl extraction related code here, instead we import from k8s directly. - -const ( - // SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by - // the kubelet. Pods with other sysctls will fail to launch. - SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls" - - // UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure - // container of a pod. The annotation value is a comma separated list of sysctl_name=value - // key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly - // namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use - // is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet - // will fail to launch. - UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls" -) - -// Sysctl defines a kernel parameter to be set -type Sysctl struct { - // Name of a property to set - Name string `json:"name"` - // Value of a property to set - Value string `json:"value"` -} - -// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls -// and a slice of unsafe Sysctls. This is only a convenience wrapper around -// SysctlsFromPodAnnotation. -func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error) { - safe, err := SysctlsFromPodAnnotation(a[SysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - unsafe, err := SysctlsFromPodAnnotation(a[UnsafeSysctlsPodAnnotationKey]) - if err != nil { - return nil, nil, err - } - - return safe, unsafe, nil -} - -// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls. -func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) { - if len(annotation) == 0 { - return nil, nil - } - - kvs := strings.Split(annotation, ",") - sysctls := make([]Sysctl, len(kvs)) - for i, kv := range kvs { - cs := strings.Split(kv, "=") - if len(cs) != 2 || len(cs[0]) == 0 { - return nil, fmt.Errorf("sysctl %q not of the format sysctl_name=value", kv) - } - sysctls[i].Name = cs[0] - sysctls[i].Value = cs[1] - } - return sysctls, nil -} - -func newPodNetwork(sb *sandbox.Sandbox) ocicni.PodNetwork { - return ocicni.PodNetwork{ - Name: sb.KubeName(), - Namespace: sb.Namespace(), - ID: sb.ID(), - NetNS: sb.NetNsPath(), - } -} - -// inStringSlice checks whether a string is inside a string slice. -// Comparison is case insensitive. -func inStringSlice(ss []string, str string) bool { - for _, s := range ss { - if strings.ToLower(s) == strings.ToLower(str) { - return true - } - } - return false -} - -// getOCICapabilitiesList returns a list of all available capabilities. -func getOCICapabilitiesList() []string { - var caps []string - for _, cap := range capability.List() { - if cap > validate.LastCap() { - continue - } - caps = append(caps, "CAP_"+strings.ToUpper(cap.String())) - } - return caps -} diff --git a/server/version.go b/server/version.go deleted file mode 100644 index 5f98e5f0c..000000000 --- a/server/version.go +++ /dev/null @@ -1,27 +0,0 @@ -package server - -import ( - "github.com/kubernetes-incubator/cri-o/version" - "golang.org/x/net/context" - pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" -) - -const ( - // kubeAPIVersion is the api version of kubernetes. - // TODO: Track upstream code. For now it expects 0.1.0 - kubeAPIVersion = "0.1.0" - // containerName is the name prepended in kubectl describe->Container ID: - // cri-o://<CONTAINER_ID> - containerName = "cri-o" - runtimeAPIVersion = "v1alpha1" -) - -// Version returns the runtime name, runtime version and runtime API version -func (s *Server) Version(ctx context.Context, req *pb.VersionRequest) (*pb.VersionResponse, error) { - return &pb.VersionResponse{ - Version: kubeAPIVersion, - RuntimeName: containerName, - RuntimeVersion: version.Version, - RuntimeApiVersion: runtimeAPIVersion, - }, nil -} diff --git a/tutorial.md b/tutorial.md deleted file mode 100644 index 2b48c21ca..000000000 --- a/tutorial.md +++ /dev/null @@ -1,425 +0,0 @@ -# CRI-O Tutorial - -This tutorial will walk you through the installation of [CRI-O](https://github.com/kubernetes-incubator/cri-o), an Open Container Initiative-based implementation of [Kubernetes Container Runtime Interface](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/container-runtime-interface-v1.md), and the creation of [Redis](https://redis.io/) server running in a [Pod](http://kubernetes.io/docs/user-guide/pods/). - -## Prerequisites - -A Linux machine is required to download and build the `CRI-O` components and run the commands in this tutorial. - -Create a machine running Ubuntu 16.10: - -``` -gcloud compute instances create cri-o \ - --machine-type n1-standard-2 \ - --image-family ubuntu-1610 \ - --image-project ubuntu-os-cloud -``` - -SSH into the machine: - -``` -gcloud compute ssh cri-o -``` - -## Installation - -This section will walk you through installing the following components: - -* crio - The implementation of the Kubernetes CRI, which manages Pods. -* crioctl - The crio client for testing. -* cni - The Container Network Interface -* runc - The OCI runtime to launch the container - - -### runc - -Download the `runc` release binary: - -``` -wget https://github.com/opencontainers/runc/releases/download/v1.0.0-rc4/runc.amd64 -``` - -Set the executable bit and copy the `runc` binary into your PATH: - -``` -chmod +x runc.amd64 -``` - -``` -sudo mv runc.amd64 /usr/bin/runc -``` - -Print the `runc` version: - -``` -runc -version -``` -``` -runc version 1.0.0-rc4 -commit: 2e7cfe036e2c6dc51ccca6eb7fa3ee6b63976dcd -spec: 1.0.0 -``` - -### crio - -The `crio` project does not ship binary releases so you'll need to build it from source. - -#### Install the Go runtime and tool chain - -Download the Go 1.7.4 binary release: - -``` -wget https://storage.googleapis.com/golang/go1.7.4.linux-amd64.tar.gz -``` - -Install Go 1.7.4: - -``` -sudo tar -xvf go1.7.4.linux-amd64.tar.gz -C /usr/local/ -``` - -``` -mkdir -p $HOME/go/src -``` - -``` -export GOPATH=$HOME/go -``` - -``` -export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin -``` - -At this point the Go 1.7.4 tool chain should be installed: - -``` -go version -``` - -``` -go version go1.7.4 linux/amd64 -``` - -#### Build crio from source - -``` -sudo apt-get install -y libglib2.0-dev libseccomp-dev libapparmor-dev -``` - -``` -go get -d github.com/kubernetes-incubator/cri-o -``` - -``` -cd $GOPATH/src/github.com/kubernetes-incubator/cri-o -``` - -``` -make install.tools -``` - -``` -make -``` - -``` -sudo make install -``` - -Output: - -``` -install -D -m 755 kpod /usr/local/bin/kpod -install -D -m 755 crio /usr/local/bin/crio -install -D -m 755 crioctl /usr/local/bin/crioctl -install -D -m 755 conmon/conmon /usr/local/libexec/crio/conmon -install -D -m 755 pause/pause /usr/local/libexec/crio/pause -install -d -m 755 /usr/local/share/man/man{1,5,8} -install -m 644 docs/kpod.1 docs/kpod-launch.1 -t /usr/local/share/man/man1 -install -m 644 docs/crio.conf.5 -t /usr/local/share/man/man5 -install -m 644 docs/crio.8 -t /usr/local/share/man/man8 -install -D -m 644 crio.conf /etc/crio/crio.conf -install -D -m 644 seccomp.json /etc/crio/seccomp.json -``` - -If you are installing for the first time, generate config as follows: - -``` -sudo make install.config -``` - -Output: - -``` -install -D -m 644 crio.conf /etc/crio/crio.conf -install -D -m 644 seccomp.json /etc/crio/seccomp.json -``` - -#### Start the crio system daemon - -``` -sudo sh -c 'echo "[Unit] -Description=OCI-based implementation of Kubernetes Container Runtime Interface -Documentation=https://github.com/kubernetes-incubator/cri-o - -[Service] -ExecStart=/usr/local/bin/crio --log-level debug -Restart=on-failure -RestartSec=5 - -[Install] -WantedBy=multi-user.target" > /etc/systemd/system/crio.service' -``` - -``` -sudo systemctl daemon-reload -``` -``` -sudo systemctl enable crio -``` -``` -sudo systemctl start crio -``` - -#### Ensure the crio service is running - -``` -sudo crioctl runtimeversion -``` -``` -VersionResponse: Version: 0.1.0, RuntimeName: runc, RuntimeVersion: 1.0.0-rc4, RuntimeApiVersion: v1alpha1 -``` - -### CNI plugins - -This tutorial will use the latest version of `CNI` plugins from the master branch and build it from source. - -Download the `CNI` plugins source tree: - -``` -go get -d github.com/containernetworking/plugins -``` - -``` -cd $GOPATH/src/github.com/containernetworking/plugins -``` - -Build the `CNI` plugins: - -``` -./build.sh -``` - -Output: - -``` -Building API -Building reference CLI -Building plugins - flannel - tuning - bridge - ipvlan - loopback - macvlan - ptp - dhcp - host-local - noop -``` - -Install the `CNI` plugins: - -``` -sudo mkdir -p /opt/cni/bin -``` - -``` -sudo cp bin/* /opt/cni/bin/ -``` - -#### Configure CNI - -``` -sudo mkdir -p /etc/cni/net.d -``` - -``` -sudo sh -c 'cat >/etc/cni/net.d/10-mynet.conf <<-EOF -{ - "cniVersion": "0.2.0", - "name": "mynet", - "type": "bridge", - "bridge": "cni0", - "isGateway": true, - "ipMasq": true, - "ipam": { - "type": "host-local", - "subnet": "10.88.0.0/16", - "routes": [ - { "dst": "0.0.0.0/0" } - ] - } -} -EOF' -``` - -``` -sudo sh -c 'cat >/etc/cni/net.d/99-loopback.conf <<-EOF -{ - "cniVersion": "0.2.0", - "type": "loopback" -} -EOF' -``` - -At this point `CNI` is installed and configured to allocation IP address to containers from the `10.88.0.0/16` subnet. - -## Pod Tutorial - -Now that the `CRI-O` components have been installed and configured we are ready to create a Pod. This section will walk you through launching a Redis server in a Pod. Once the Redis server is running we'll use telnet to verify it's working, then we'll stop the Redis server and clean up the Pod. - -### Creating a Pod - -First we need to setup a Pod sandbox using a Pod configuration, which can be found in the `cri-o` source tree: - -``` -cd $GOPATH/src/github.com/kubernetes-incubator/cri-o -``` - -Next create the Pod and capture the Pod ID for later use: - -``` -POD_ID=$(sudo crioctl pod run --config test/testdata/sandbox_config.json) -``` - -> sudo crioctl pod run --config test/testdata/sandbox_config.json - -Use the `crioctl` command to get the status of the Pod: - -``` -sudo crioctl pod status --id $POD_ID -``` - -Output: - -``` -ID: cd6c0883663c6f4f99697aaa15af8219e351e03696bd866bc3ac055ef289702a -Name: podsandbox1 -UID: redhat-test-crio -Namespace: redhat.test.crio -Attempt: 1 -Status: SANDBOX_READY -Created: 2016-12-14 15:59:04.373680832 +0000 UTC -Network namespace: /var/run/netns/cni-bc37b858-fb4d-41e6-58b0-9905d0ba23f8 -IP Address: 10.88.0.2 -Labels: - group -> test -Annotations: - owner -> hmeng - security.alpha.kubernetes.io/seccomp/pod -> unconfined - security.alpha.kubernetes.io/sysctls -> kernel.shm_rmid_forced=1,net.ipv4.ip_local_port_range=1024 65000 - security.alpha.kubernetes.io/unsafe-sysctls -> kernel.msgmax=8192 -``` - -### Create a Redis container inside the Pod - -Use the `crioctl` command to pull the redis image, create a redis container from a container configuration and attach it to the Pod created earlier: - -``` -sudo crioctl image pull redis:alpine -CONTAINER_ID=$(sudo crioctl ctr create --pod $POD_ID --config test/testdata/container_redis.json) -``` - -> sudo crioctl ctr create --pod $POD_ID --config test/testdata/container_redis.json - -The `crioctl ctr create` command will take a few seconds to return because the redis container needs to be pulled. - -Start the Redis container: - -``` -sudo crioctl ctr start --id $CONTAINER_ID -``` - -Get the status for the Redis container: - -``` -sudo crioctl ctr status --id $CONTAINER_ID -``` - -Output: - -``` -ID: d0147eb67968d81aaddbccc46cf1030211774b5280fad35bce2fdb0a507a2e7a -Name: podsandbox1-redis -Status: CONTAINER_RUNNING -Created: 2016-12-14 16:00:42.889089352 +0000 UTC -Started: 2016-12-14 16:01:56.733704267 +0000 UTC -``` - -### Test the Redis container - -Connect to the Pod IP on port 6379: - -``` -telnet 10.88.0.2 6379 -``` - -``` -Trying 10.88.0.2... -Connected to 10.88.0.2. -Escape character is '^]'. -``` - -At the prompt type `MONITOR`: - -``` -Trying 10.88.0.2... -Connected to 10.88.0.2. -Escape character is '^]'. -MONITOR -+OK -``` - -Exit the telnet session by typing `ctrl-]` and `quit` at the prompt: - -``` -^] - -telnet> quit -Connection closed. -``` - -#### Viewing the Redis logs - -The Redis logs are logged to the stderr of the crio service, which can be viewed using `journalctl`: - -``` -sudo journalctl -u crio --no-pager -``` - -### Stop the redis container and delete the Pod - -``` -sudo crioctl ctr stop --id $CONTAINER_ID -``` - -``` -sudo crioctl ctr remove --id $CONTAINER_ID -``` - -``` -sudo crioctl pod stop --id $POD_ID -``` - -``` -sudo crioctl pod remove --id $POD_ID -``` - -``` -sudo crioctl pod list -``` - -``` -sudo crioctl ctr list -``` |