mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
vendor files
This commit is contained in:
77
vendor/github.com/kubernetes-csi/drivers/.gitignore
generated
vendored
Normal file
77
vendor/github.com/kubernetes-csi/drivers/.gitignore
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
# OSX leaves these everywhere on SMB shares
|
||||
._*
|
||||
|
||||
# OSX trash
|
||||
.DS_Store
|
||||
|
||||
# Eclipse files
|
||||
.classpath
|
||||
.project
|
||||
.settings/**
|
||||
|
||||
# Files generated by JetBrains IDEs, e.g. IntelliJ IDEA
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
# Vscode files
|
||||
.vscode
|
||||
|
||||
# This is where the result of the go build goes
|
||||
/output*/
|
||||
/_output*/
|
||||
/_output
|
||||
|
||||
# Emacs save files
|
||||
*~
|
||||
\#*\#
|
||||
.\#*
|
||||
|
||||
# Vim-related files
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
|
||||
# cscope-related files
|
||||
cscope.*
|
||||
|
||||
# Go test binaries
|
||||
*.test
|
||||
|
||||
# JUnit test output from ginkgo e2e tests
|
||||
/junit*.xml
|
||||
|
||||
# Mercurial files
|
||||
**/.hg
|
||||
**/.hg*
|
||||
|
||||
# Vagrant
|
||||
.vagrant
|
||||
|
||||
.tags*
|
||||
|
||||
# Test artifacts produced by Jenkins jobs
|
||||
/_artifacts/
|
||||
|
||||
# Go dependencies installed on Jenkins
|
||||
/_gopath/
|
||||
|
||||
# Config directories created by gcloud and gsutil on Jenkins
|
||||
/.config/gcloud*/
|
||||
/.gsutil/
|
||||
|
||||
# direnv .envrc files
|
||||
.envrc
|
||||
|
||||
# This file used by some vendor repos (e.g. github.com/go-openapi/...) to store secret variables and should not be ignored
|
||||
!\.drone\.sec
|
||||
|
||||
# Godeps or dep workspace
|
||||
/Godeps/_workspace
|
||||
vendor
|
||||
vendor.*
|
||||
|
||||
/bazel-*
|
||||
*.pyc
|
||||
|
19
vendor/github.com/kubernetes-csi/drivers/.travis.yml
generated
vendored
Normal file
19
vendor/github.com/kubernetes-csi/drivers/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
# Setting "sudo" to false forces Travis-CI to use its
|
||||
# container-based build infrastructure, which has shorter
|
||||
# queue times.
|
||||
sudo: false
|
||||
|
||||
# Use the newer Travis-CI build templates based on the
|
||||
# Debian Linux distribution "Trusty" release.
|
||||
dist: trusty
|
||||
|
||||
# Select Go as the language used to run the build.
|
||||
language: go
|
||||
go: 1.9.x
|
||||
go_import_path: github.com/kubernetes-csi/drivers
|
||||
|
||||
install:
|
||||
- make
|
||||
|
||||
script:
|
||||
- go test -v github.com/kubernetes-csi/drivers/... -cover
|
362
vendor/github.com/kubernetes-csi/drivers/Gopkg.lock
generated
vendored
Normal file
362
vendor/github.com/kubernetes-csi/drivers/Gopkg.lock
generated
vendored
Normal file
@ -0,0 +1,362 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/PuerkitoBio/purell"
|
||||
packages = ["."]
|
||||
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/PuerkitoBio/urlesc"
|
||||
packages = ["."]
|
||||
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/beorn7/perks"
|
||||
packages = ["quantile"]
|
||||
revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/container-storage-interface/spec"
|
||||
packages = ["lib/go/csi"]
|
||||
revision = "51e48d38ac8a5b4bdcf41826b77dc016ad83451e"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/dgrijalva/jwt-go"
|
||||
packages = ["."]
|
||||
revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29"
|
||||
version = "v3.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/distribution"
|
||||
packages = ["digestset","reference"]
|
||||
revision = "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/emicklei/go-restful"
|
||||
packages = [".","log"]
|
||||
revision = "5741799b275a3c4a5a9623a993576d7545cf7b5c"
|
||||
version = "v2.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/emicklei/go-restful-swagger12"
|
||||
packages = ["."]
|
||||
revision = "dcef7f55730566d41eae5db10e7d6981829720f6"
|
||||
version = "1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/ghodss/yaml"
|
||||
packages = ["."]
|
||||
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/jsonpointer"
|
||||
packages = ["."]
|
||||
revision = "779f45308c19820f1a69e9a4cd965f496e0da10f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/jsonreference"
|
||||
packages = ["."]
|
||||
revision = "36d33bfe519efae5632669801b180bf1a245da3b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/spec"
|
||||
packages = ["."]
|
||||
revision = "a4fa9574c7aa73b2fc54e251eb9524d0482bb592"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/swag"
|
||||
packages = ["."]
|
||||
revision = "cf0bdb963811675a4d7e74901cefc7411a1df939"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = ["proto","sortkeys"]
|
||||
revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02"
|
||||
version = "v0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
packages = ["."]
|
||||
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/groupcache"
|
||||
packages = ["lru"]
|
||||
revision = "84a468cf14b4376def5d68c722b139b881c450a4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["proto","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp"]
|
||||
revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/btree"
|
||||
packages = ["."]
|
||||
revision = "316fb6d3f031ae8f4d457c6c5186b9e3ded70435"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/gofuzz"
|
||||
packages = ["."]
|
||||
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/googleapis/gnostic"
|
||||
packages = ["OpenAPIv2","compiler","extensions"]
|
||||
revision = "ee43cbb60db7bd22502942cccbc39059117352ab"
|
||||
version = "v0.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gophercloud/gophercloud"
|
||||
packages = [".","openstack","openstack/blockstorage/v3/volumes","openstack/compute/v2/extensions/volumeattach","openstack/identity/v2/tenants","openstack/identity/v2/tokens","openstack/identity/v3/tokens","openstack/utils","pagination"]
|
||||
revision = "4d2733c962898d8cd68456bd275aee64256cd2a1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gregjones/httpcache"
|
||||
packages = [".","diskcache"]
|
||||
revision = "22a0b1feae53974ed4cfe27bcce70dba061cc5fd"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/golang-lru"
|
||||
packages = [".","simplelru"]
|
||||
revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/inconshreveable/mousetrap"
|
||||
packages = ["."]
|
||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/json-iterator/go"
|
||||
packages = ["."]
|
||||
revision = "6240e1e7983a85228f7fd9c3e1b6932d46ec58e2"
|
||||
version = "1.0.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/juju/ratelimit"
|
||||
packages = ["."]
|
||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mailru/easyjson"
|
||||
packages = ["buffer","jlexer","jwriter"]
|
||||
revision = "7578e5f07ef653b5940eff36e0d0d84e4362bea4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
packages = ["pbutil"]
|
||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/opencontainers/go-digest"
|
||||
packages = ["."]
|
||||
revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf"
|
||||
version = "v1.0.0-rc1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pborman/uuid"
|
||||
packages = ["."]
|
||||
revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53"
|
||||
version = "v1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/petar/GoLLRB"
|
||||
packages = ["llrb"]
|
||||
revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/peterbourgon/diskv"
|
||||
packages = ["."]
|
||||
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
|
||||
version = "v2.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
packages = ["prometheus"]
|
||||
revision = "c5b7fccd204277076155f10851dad72b76a49317"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/client_model"
|
||||
packages = ["go"]
|
||||
revision = "6f3806018612930941127f2a7c6c453ba2c527d2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/common"
|
||||
packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"]
|
||||
revision = "e3fb1a1acd7605367a2b378bc2e2f893c05174b7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/procfs"
|
||||
packages = [".","xfs"]
|
||||
revision = "a6e9df898b1336106c743392c48ee0b71f5c4efa"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/cobra"
|
||||
packages = ["."]
|
||||
revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b"
|
||||
version = "v0.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/stretchr/objx"
|
||||
packages = ["."]
|
||||
revision = "1a9d0bb9f541897e62256577b352fdbc1fb4fd94"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = ["assert","mock"]
|
||||
revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0"
|
||||
version = "v1.1.4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"]
|
||||
revision = "a337091b0525af65de94df2eb7e98bd9962dcbe2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "bf42f188b9bc6f2cf5b8ee5a912ef1aedd0eba4c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable","width"]
|
||||
revision = "88f656faf3f37f690df1a32515b479415e1a6769"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "11c7f9e547da6db876260ce49ea7536985904c9b"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [".","balancer","codes","connectivity","credentials","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","resolver","stats","status","tap","transport"]
|
||||
revision = "5ffe3083946d5603a0578721101dc8165b1d5b5f"
|
||||
version = "v1.7.2"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/gcfg.v1"
|
||||
packages = [".","scanner","token","types"]
|
||||
revision = "298b7a6a3838f79debfaee8bd3bfb2b8d779e756"
|
||||
version = "v1.2.1"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/inf.v0"
|
||||
packages = ["."]
|
||||
revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4"
|
||||
version = "v0.9.0"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/warnings.v0"
|
||||
packages = ["."]
|
||||
revision = "ec4a0fea49c7b46c2aeb0b51aac55779c607e52b"
|
||||
version = "v0.1.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apiextensions-apiserver"
|
||||
packages = ["pkg/features"]
|
||||
revision = "099fd227da1f60394aac19c77254374142d01079"
|
||||
|
||||
[[projects]]
|
||||
branch = "release-1.9"
|
||||
name = "k8s.io/apimachinery"
|
||||
packages = ["pkg/api/equality","pkg/api/errors","pkg/api/meta","pkg/api/resource","pkg/api/validation","pkg/apimachinery","pkg/apimachinery/announced","pkg/apimachinery/registered","pkg/apis/meta/internalversion","pkg/apis/meta/v1","pkg/apis/meta/v1/unstructured","pkg/apis/meta/v1/validation","pkg/apis/meta/v1alpha1","pkg/conversion","pkg/conversion/queryparams","pkg/fields","pkg/labels","pkg/runtime","pkg/runtime/schema","pkg/runtime/serializer","pkg/runtime/serializer/json","pkg/runtime/serializer/protobuf","pkg/runtime/serializer/recognizer","pkg/runtime/serializer/streaming","pkg/runtime/serializer/versioning","pkg/selection","pkg/types","pkg/util/cache","pkg/util/clock","pkg/util/diff","pkg/util/errors","pkg/util/framer","pkg/util/intstr","pkg/util/json","pkg/util/mergepatch","pkg/util/net","pkg/util/runtime","pkg/util/sets","pkg/util/strategicpatch","pkg/util/validation","pkg/util/validation/field","pkg/util/wait","pkg/util/yaml","pkg/version","pkg/watch","third_party/forked/golang/json","third_party/forked/golang/reflect"]
|
||||
revision = "180eddb345a5be3a157cea1c624700ad5bd27b8f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apiserver"
|
||||
packages = ["pkg/authentication/authenticator","pkg/authentication/serviceaccount","pkg/authentication/user","pkg/features","pkg/util/feature"]
|
||||
revision = "73f85001b53a0adc72b5d3dc68abbcda0837fe3a"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/client-go"
|
||||
packages = ["discovery","informers","informers/admissionregistration","informers/admissionregistration/v1alpha1","informers/apps","informers/apps/v1beta1","informers/apps/v1beta2","informers/autoscaling","informers/autoscaling/v1","informers/autoscaling/v2beta1","informers/batch","informers/batch/v1","informers/batch/v1beta1","informers/batch/v2alpha1","informers/certificates","informers/certificates/v1beta1","informers/core","informers/core/v1","informers/extensions","informers/extensions/v1beta1","informers/internalinterfaces","informers/networking","informers/networking/v1","informers/policy","informers/policy/v1beta1","informers/rbac","informers/rbac/v1","informers/rbac/v1alpha1","informers/rbac/v1beta1","informers/scheduling","informers/scheduling/v1alpha1","informers/settings","informers/settings/v1alpha1","informers/storage","informers/storage/v1","informers/storage/v1beta1","kubernetes","kubernetes/scheme","kubernetes/typed/admissionregistration/v1alpha1","kubernetes/typed/apps/v1beta1","kubernetes/typed/apps/v1beta2","kubernetes/typed/authentication/v1","kubernetes/typed/authentication/v1beta1","kubernetes/typed/authorization/v1","kubernetes/typed/authorization/v1beta1","kubernetes/typed/autoscaling/v1","kubernetes/typed/autoscaling/v2beta1","kubernetes/typed/batch/v1","kubernetes/typed/batch/v1beta1","kubernetes/typed/batch/v2alpha1","kubernetes/typed/certificates/v1beta1","kubernetes/typed/core/v1","kubernetes/typed/extensions/v1beta1","kubernetes/typed/networking/v1","kubernetes/typed/policy/v1beta1","kubernetes/typed/rbac/v1","kubernetes/typed/rbac/v1alpha1","kubernetes/typed/rbac/v1beta1","kubernetes/typed/scheduling/v1alpha1","kubernetes/typed/settings/v1alpha1","kubernetes/typed/storage/v1","kubernetes/typed/storage/v1beta1","listers/admissionregistration/v1alpha1","listers/apps/v1beta1","listers/apps/v1beta2","listers/autoscaling/v1","listers/autoscaling/v2beta1","listers/batch/v1","listers/batch/v1beta1","listers/batch/v2alpha1","listers/certificates/v1beta1","listers/core/v1","listers/extensions/v1beta1","listers/networking/v1","listers/policy/v1beta1","listers/rbac/v1","listers/rbac/v1alpha1","listers/rbac/v1beta1","listers/scheduling/v1alpha1","listers/settings/v1alpha1","listers/storage/v1","listers/storage/v1beta1","pkg/version","rest","rest/watch","tools/cache","tools/clientcmd/api","tools/metrics","tools/pager","tools/record","tools/reference","transport","util/cert","util/flowcontrol","util/integer","util/retry"]
|
||||
revision = "59ab1a8387ec5d6273ba6d3d400fb522d6e24c8f"
|
||||
branch = "master"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/kube-openapi"
|
||||
packages = ["pkg/common","pkg/util/proto"]
|
||||
revision = "39a7bf85c140f972372c2a0d1ee40adbf0c8bfe1"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/kubernetes"
|
||||
packages = ["pkg/api/legacyscheme","pkg/api/service","pkg/api/v1/pod","pkg/apis/autoscaling","pkg/apis/core","pkg/apis/core/helper","pkg/apis/core/install","pkg/apis/core/pods","pkg/apis/core/v1","pkg/apis/core/v1/helper","pkg/apis/core/validation","pkg/apis/extensions","pkg/apis/networking","pkg/capabilities","pkg/cloudprovider","pkg/controller","pkg/features","pkg/fieldpath","pkg/kubelet/apis","pkg/kubelet/types","pkg/security/apparmor","pkg/serviceaccount","pkg/util/file","pkg/util/hash","pkg/util/io","pkg/util/mount","pkg/util/net/sets","pkg/util/nsenter","pkg/util/parsers","pkg/util/pointer","pkg/util/taints","pkg/volume","pkg/volume/util"]
|
||||
revision = "3ac6d1f5c03bbc550fe197ae58da9d3f6a91a1f0"
|
||||
version = "v1.9.0-beta.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/utils"
|
||||
packages = ["exec"]
|
||||
revision = "bf963466fd3fea33c428098b12a89d8ecd012f25"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/api"
|
||||
packages = ["admissionregistration/v1alpha1","apps/v1beta1","apps/v1beta2","authentication/v1","authentication/v1beta1","authorization/v1","authorization/v1beta1","autoscaling/v1","autoscaling/v2beta1","batch/v1","batch/v1beta1","batch/v2alpha1","certificates/v1beta1","core/v1","extensions/v1beta1","networking/v1","policy/v1beta1","rbac/v1","rbac/v1alpha1","rbac/v1beta1","scheduling/v1alpha1","settings/v1alpha1","storage/v1","storage/v1beta1"]
|
||||
revision = "5cb170de1f060ebf2dde62cc4b8241fdb3c01203"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "77a9f83151caa2ed28dd48707ab7b3122afd4adbf6699b248cbe3a463dfb4127"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
46
vendor/github.com/kubernetes-csi/drivers/Gopkg.toml
generated
vendored
Normal file
46
vendor/github.com/kubernetes-csi/drivers/Gopkg.toml
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/container-storage-interface/spec"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/grpc"
|
||||
version = "1.7.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/docker/distribution"
|
||||
revision = "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/kubernetes"
|
||||
version = "v1.9.0-beta.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/apimachinery"
|
||||
version = "kubernetes-1.9.0-beta.2"
|
41
vendor/github.com/kubernetes-csi/drivers/Makefile
generated
vendored
Normal file
41
vendor/github.com/kubernetes-csi/drivers/Makefile
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# Copyright 2017 The Kubernetes Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.PHONY: all flexadapter nfs hostpath iscsi cinder clean
|
||||
|
||||
all: flexadapter nfs hostpath iscsi cinder
|
||||
|
||||
test:
|
||||
go test github.com/kubernetes-csi/drivers/pkg/... -cover
|
||||
go vet github.com/kubernetes-csi/drivers/pkg/...
|
||||
|
||||
flexadapter:
|
||||
if [ ! -d ./vendor ]; then dep ensure; fi
|
||||
go build -o _output/flexadapter ./app/flexadapter
|
||||
nfs:
|
||||
if [ ! -d ./vendor ]; then dep ensure; fi
|
||||
go build -o _output/nfsplugin ./app/nfsplugin
|
||||
hostpath:
|
||||
if [ ! -d ./vendor ]; then dep ensure; fi
|
||||
go build -i -o _output/hostpathplugin ./app/hostpathplugin
|
||||
iscsi:
|
||||
if [ ! -d ./vendor ]; then dep ensure; fi
|
||||
go build -o _output/iscsiplugin ./app/iscsiplugin
|
||||
cinder:
|
||||
if [ ! -d ./vendor ]; then dep ensure; fi
|
||||
go build -o _output/cinderplugin ./app/cinderplugin
|
||||
|
||||
clean:
|
||||
go clean -r -x
|
||||
-rm -rf _output
|
9
vendor/github.com/kubernetes-csi/drivers/README.md
generated
vendored
Normal file
9
vendor/github.com/kubernetes-csi/drivers/README.md
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# CSI Drivers
|
||||
|
||||
These drivers are provided puerly for illustrative purposes, and should not be used for production workloads.
|
||||
|
||||
## Other sample drivers
|
||||
Please read [Drivers](https://github.com/kubernetes-csi/docs/wiki/Drivers) for more information
|
||||
|
||||
## Adding new sample drivers
|
||||
Please, DO NOT submit PRs to add new drivers here unless they are just examples. Real CSI drivers are to be housed on their own repo separate from this one. You are then welcomed to send a PR to https://github.com/kubernetes-csi/docs to add the [Driver](https://github.com/kubernetes-csi/docs/wiki/Drivers) page.
|
72
vendor/github.com/kubernetes-csi/drivers/app/cinderplugin/main.go
generated
vendored
Normal file
72
vendor/github.com/kubernetes-csi/drivers/app/cinderplugin/main.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/cinder"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
endpoint string
|
||||
nodeID string
|
||||
cloudconfig string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
flag.CommandLine.Parse([]string{})
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "Cinder",
|
||||
Short: "CSI based Cinder driver",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
handle()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||
|
||||
cmd.PersistentFlags().StringVar(&nodeID, "nodeid", "", "node id")
|
||||
cmd.MarkPersistentFlagRequired("nodeid")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "", "CSI endpoint")
|
||||
cmd.MarkPersistentFlagRequired("endpoint")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&cloudconfig, "cloud-config", "", "CSI driver cloud config")
|
||||
cmd.MarkPersistentFlagRequired("cloud-config")
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func handle() {
|
||||
d := cinder.NewDriver(nodeID, endpoint, cloudconfig)
|
||||
d.Run()
|
||||
}
|
77
vendor/github.com/kubernetes-csi/drivers/app/flexadapter/main.go
generated
vendored
Normal file
77
vendor/github.com/kubernetes-csi/drivers/app/flexadapter/main.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/flexadapter"
|
||||
)
|
||||
|
||||
var (
|
||||
endpoint string
|
||||
driverName string
|
||||
driverPath string
|
||||
nodeID string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
flag.CommandLine.Parse([]string{})
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "flexadapter",
|
||||
Short: "Flex volume adapter for CSI",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
handle()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||
|
||||
cmd.PersistentFlags().StringVar(&nodeID, "nodeid", "", "node id")
|
||||
cmd.MarkPersistentFlagRequired("nodeid")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "", "CSI endpoint")
|
||||
cmd.MarkPersistentFlagRequired("endpoint")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&driverPath, "driverpath", "", "path to flexvolume driver path")
|
||||
cmd.MarkPersistentFlagRequired("driverpath")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&driverName, "drivername", "", "name of the driver")
|
||||
cmd.MarkPersistentFlagRequired("drivername")
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func handle() {
|
||||
adapter := flexadapter.GetFlexAdapter()
|
||||
adapter.Run(driverName, driverPath, nodeID, endpoint)
|
||||
}
|
46
vendor/github.com/kubernetes-csi/drivers/app/hostpathplugin/main.go
generated
vendored
Normal file
46
vendor/github.com/kubernetes-csi/drivers/app/hostpathplugin/main.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/hostpath"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
var (
|
||||
endpoint = flag.String("endpoint", "unix://tmp/csi.sock", "CSI endpoint")
|
||||
driverName = flag.String("drivername", "csi-hostpath", "name of the driver")
|
||||
nodeID = flag.String("nodeid", "", "node id")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
handle()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func handle() {
|
||||
driver := hostpath.GetHostPathDriver()
|
||||
driver.Run(*driverName, *nodeID, *endpoint)
|
||||
}
|
69
vendor/github.com/kubernetes-csi/drivers/app/iscsiplugin/main.go
generated
vendored
Normal file
69
vendor/github.com/kubernetes-csi/drivers/app/iscsiplugin/main.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/iscsi"
|
||||
)
|
||||
|
||||
var (
|
||||
endpoint string
|
||||
nodeID string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
flag.CommandLine.Parse([]string{})
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "ISCSI",
|
||||
Short: "CSI based ISCSI driver",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
handle()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||
|
||||
cmd.PersistentFlags().StringVar(&nodeID, "nodeid", "", "node id")
|
||||
cmd.MarkPersistentFlagRequired("nodeid")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "", "CSI endpoint")
|
||||
cmd.MarkPersistentFlagRequired("endpoint")
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func handle() {
|
||||
d := iscsi.NewDriver(nodeID, endpoint)
|
||||
d.Run()
|
||||
}
|
70
vendor/github.com/kubernetes-csi/drivers/app/nfsplugin/main.go
generated
vendored
Normal file
70
vendor/github.com/kubernetes-csi/drivers/app/nfsplugin/main.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/nfs"
|
||||
)
|
||||
|
||||
var (
|
||||
endpoint string
|
||||
nodeID string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
flag.CommandLine.Parse([]string{})
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "NFS",
|
||||
Short: "CSI based NFS driver",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
handle()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().AddGoFlagSet(flag.CommandLine)
|
||||
|
||||
cmd.PersistentFlags().StringVar(&nodeID, "nodeid", "", "node id")
|
||||
cmd.MarkPersistentFlagRequired("nodeid")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "", "CSI endpoint")
|
||||
cmd.MarkPersistentFlagRequired("endpoint")
|
||||
|
||||
cmd.ParseFlags(os.Args[1:])
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func handle() {
|
||||
d := nfs.NewDriver(nodeID, endpoint)
|
||||
d.Run()
|
||||
}
|
3
vendor/github.com/kubernetes-csi/drivers/code-of-conduct.md
generated
vendored
Normal file
3
vendor/github.com/kubernetes-csi/drivers/code-of-conduct.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Kubernetes Community Code of Conduct
|
||||
|
||||
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
97
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/README.md
generated
vendored
Normal file
97
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/README.md
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
# CSI Cinder driver
|
||||
|
||||
## Kubernetes
|
||||
|
||||
### Requirements
|
||||
|
||||
The following feature gates and runtime config have to be enabled to deploy the driver.
|
||||
|
||||
```
|
||||
FEATURE_GATES=CSIPersistentVolume=true,MountPropagation=true
|
||||
RUNTIME_CONFIG="storage.k8s.io/v1alpha1=true"
|
||||
```
|
||||
|
||||
Mountprogpation requires support for privileged containers. So, make sure privileged containers are enabled in the cluster.
|
||||
|
||||
### Example local-up-cluster.sh
|
||||
|
||||
```ALLOW_PRIVILEGED=true FEATURE_GATES=CSIPersistentVolume=true,MountPropagation=true RUNTIME_CONFIG="storage.k8s.io/v1alpha1=true" LOG_LEVEL=5 hack/local-up-cluster.sh```
|
||||
|
||||
### Deploy
|
||||
|
||||
Encode your ```cloud.conf``` file content using base64.
|
||||
|
||||
```base64 -w 0 cloud.conf```
|
||||
|
||||
Update ```cloud.conf``` configuration in ```deploy/kubernetes/csi-secret-cinderplugin.yaml``` file
|
||||
by using the result of the above command.
|
||||
|
||||
```kubectl -f deploy/kubernetes create```
|
||||
|
||||
### Example Nginx application
|
||||
|
||||
```kubectl -f examples/kubernetes/nginx.yaml create```
|
||||
|
||||
## Using CSC tool
|
||||
|
||||
### Start Cinder driver
|
||||
```
|
||||
$ sudo ./_output/cinderplugin --endpoint tcp://127.0.0.1:10000 --cloud-config /etc/cloud.conf --nodeid CSINodeID
|
||||
```
|
||||
|
||||
### Test
|
||||
Get ```csc``` tool from https://github.com/chakri-nelluri/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugin-info --endpoint tcp://127.0.0.1:10000
|
||||
"csi-cinderplugin" "0.1.0"
|
||||
```
|
||||
|
||||
#### Get supported versions
|
||||
```
|
||||
$ csc identity supported-versions --endpoint tcp://127.0.0.1:10000
|
||||
0.1.0
|
||||
```
|
||||
|
||||
#### Create a volume
|
||||
```
|
||||
$ csc controller new --endpoint tcp://127.0.0.1:10000 CSIVolumeName
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### Delete a volume
|
||||
```
|
||||
$ csc controller del --endpoint tcp://127.0.0.1:10000 CSIVolumeID
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### ControllerPublish a volume
|
||||
```
|
||||
$ csc controller publish --endpoint tcp://127.0.0.1:10000 --node-id=CSINodeID CSIVolumeID
|
||||
CSIVolumeID "DevicePath"="/dev/xxx"
|
||||
```
|
||||
|
||||
#### ControllerUnpublish a volume
|
||||
```
|
||||
$ csc controller unpublish --endpoint tcp://127.0.0.1:10000 --node-id=CSINodeID CSIVolumeID
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### NodePublish a volume
|
||||
```
|
||||
$ csc node publish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/cinder --pub-info DevicePath="/dev/xxx" CSIVolumeID
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### NodeUnpublish a volume
|
||||
```
|
||||
$ csc node unpublish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/cinder CSIVolumeID
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### Get NodeID
|
||||
```
|
||||
$ csc node get-id --endpoint tcp://127.0.0.1:10000
|
||||
CSINodeID
|
||||
```
|
172
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/controllerserver.go
generated
vendored
Normal file
172
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/controllerserver.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cinder
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
"github.com/kubernetes-csi/drivers/pkg/cinder/openstack"
|
||||
csicommon "github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
"github.com/pborman/uuid"
|
||||
"golang.org/x/net/context"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
type controllerServer struct {
|
||||
*csicommon.DefaultControllerServer
|
||||
}
|
||||
|
||||
func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
|
||||
|
||||
// Volume Name
|
||||
volName := req.GetName()
|
||||
if len(volName) == 0 {
|
||||
volName = uuid.NewUUID().String()
|
||||
}
|
||||
|
||||
// Volume Size - Default is 1 GiB
|
||||
volSizeBytes := int64(1 * 1024 * 1024 * 1024)
|
||||
if req.GetCapacityRange() != nil {
|
||||
volSizeBytes = int64(req.GetCapacityRange().GetRequiredBytes())
|
||||
}
|
||||
volSizeGB := int(volume.RoundUpSize(volSizeBytes, 1024*1024*1024))
|
||||
|
||||
// Volume Type
|
||||
volType := req.GetParameters()["type"]
|
||||
|
||||
// Volume Availability - Default is nova
|
||||
volAvailability := req.GetParameters()["availability"]
|
||||
|
||||
// Get OpenStack Provider
|
||||
cloud, err := openstack.GetOpenStackProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetOpenStackProvider: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Volume Create
|
||||
resID, resAvailability, err := cloud.CreateVolume(volName, volSizeGB, volType, volAvailability, nil)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to CreateVolume: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Create volume %s in Availability Zone: %s", resID, resAvailability)
|
||||
|
||||
return &csi.CreateVolumeResponse{
|
||||
VolumeInfo: &csi.VolumeInfo{
|
||||
Id: resID,
|
||||
Attributes: map[string]string{
|
||||
"availability": resAvailability,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
|
||||
|
||||
// Get OpenStack Provider
|
||||
cloud, err := openstack.GetOpenStackProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetOpenStackProvider: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Volume Delete
|
||||
volID := req.GetVolumeId()
|
||||
err = cloud.DeleteVolume(volID)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to DeleteVolume: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Delete volume %s", volID)
|
||||
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ControllerPublishVolume(ctx context.Context, req *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) {
|
||||
|
||||
// Get OpenStack Provider
|
||||
cloud, err := openstack.GetOpenStackProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetOpenStackProvider: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Volume Attach
|
||||
instanceID := req.GetNodeId()
|
||||
volumeID := req.GetVolumeId()
|
||||
|
||||
_, err = cloud.AttachVolume(instanceID, volumeID)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to AttachVolume: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cloud.WaitDiskAttached(instanceID, volumeID)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to WaitDiskAttached: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devicePath, err := cloud.GetAttachmentDiskPath(instanceID, volumeID)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetAttachmentDiskPath: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("ControllerPublishVolume %s on %s", volumeID, instanceID)
|
||||
|
||||
// Publish Volume Info
|
||||
pvInfo := map[string]string{}
|
||||
pvInfo["DevicePath"] = devicePath
|
||||
|
||||
return &csi.ControllerPublishVolumeResponse{
|
||||
PublishVolumeInfo: pvInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ControllerUnpublishVolume(ctx context.Context, req *csi.ControllerUnpublishVolumeRequest) (*csi.ControllerUnpublishVolumeResponse, error) {
|
||||
|
||||
// Get OpenStack Provider
|
||||
cloud, err := openstack.GetOpenStackProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetOpenStackProvider: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Volume Detach
|
||||
instanceID := req.GetNodeId()
|
||||
volumeID := req.GetVolumeId()
|
||||
|
||||
err = cloud.DetachVolume(instanceID, volumeID)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to DetachVolume: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cloud.WaitDiskDetached(instanceID, volumeID)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to WaitDiskDetached: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("ControllerUnpublishVolume %s on %s", volumeID, instanceID)
|
||||
|
||||
return &csi.ControllerUnpublishVolumeResponse{}, nil
|
||||
}
|
176
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/controllerserver_test.go
generated
vendored
Normal file
176
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/controllerserver_test.go
generated
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cinder
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/kubernetes-csi/drivers/pkg/cinder/openstack"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
var fakeCs *controllerServer
|
||||
|
||||
// Init Controller Server
|
||||
func init() {
|
||||
if fakeCs == nil {
|
||||
d := NewDriver(fakeNodeID, fakeEndpoint, fakeConfig)
|
||||
fakeCs = NewControllerServer(d)
|
||||
}
|
||||
}
|
||||
|
||||
// Test CreateVolume
|
||||
func TestCreateVolume(t *testing.T) {
|
||||
|
||||
// mock OpenStack
|
||||
osmock := new(openstack.OpenStackMock)
|
||||
// CreateVolume(name string, size int, vtype, availability string, tags *map[string]string) (string, string, error)
|
||||
osmock.On("CreateVolume", fakeVolName, mock.AnythingOfType("int"), fakeVolType, fakeAvailability, (*map[string]string)(nil)).Return(fakeVolID, fakeAvailability, nil)
|
||||
openstack.OsInstance = osmock
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.CreateVolumeRequest{
|
||||
Version: &version,
|
||||
Name: fakeVolName,
|
||||
VolumeCapabilities: nil,
|
||||
}
|
||||
|
||||
// Invoke CreateVolume
|
||||
actualRes, err := fakeCs.CreateVolume(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to CreateVolume: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.NotNil(actualRes.VolumeInfo)
|
||||
|
||||
assert.NotEqual(0, len(actualRes.VolumeInfo.Id), "Volume Id is nil")
|
||||
|
||||
assert.Equal(fakeAvailability, actualRes.VolumeInfo.Attributes["availability"])
|
||||
}
|
||||
|
||||
// Test DeleteVolume
|
||||
func TestDeleteVolume(t *testing.T) {
|
||||
|
||||
// mock OpenStack
|
||||
osmock := new(openstack.OpenStackMock)
|
||||
// DeleteVolume(volumeID string) error
|
||||
osmock.On("DeleteVolume", fakeVolID).Return(nil)
|
||||
openstack.OsInstance = osmock
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.DeleteVolumeRequest{
|
||||
Version: &version,
|
||||
VolumeId: fakeVolID,
|
||||
}
|
||||
|
||||
// Expected Result
|
||||
expectedRes := &csi.DeleteVolumeResponse{}
|
||||
|
||||
// Invoke DeleteVolume
|
||||
actualRes, err := fakeCs.DeleteVolume(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to DeleteVolume: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedRes, actualRes)
|
||||
}
|
||||
|
||||
// Test ControllerPublishVolume
|
||||
func TestControllerPublishVolume(t *testing.T) {
|
||||
|
||||
// mock OpenStack
|
||||
osmock := new(openstack.OpenStackMock)
|
||||
// AttachVolume(instanceID, volumeID string) (string, error)
|
||||
osmock.On("AttachVolume", fakeNodeID, fakeVolID).Return(fakeVolID, nil)
|
||||
// WaitDiskAttached(instanceID string, volumeID string) error
|
||||
osmock.On("WaitDiskAttached", fakeNodeID, fakeVolID).Return(nil)
|
||||
// GetAttachmentDiskPath(instanceID, volumeID string) (string, error)
|
||||
osmock.On("GetAttachmentDiskPath", fakeNodeID, fakeVolID).Return(fakeDevicePath, nil)
|
||||
openstack.OsInstance = osmock
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.ControllerPublishVolumeRequest{
|
||||
Version: &version,
|
||||
VolumeId: fakeVolID,
|
||||
NodeId: fakeNodeID,
|
||||
VolumeCapability: nil,
|
||||
Readonly: false,
|
||||
}
|
||||
|
||||
// Expected Result
|
||||
expectedRes := &csi.ControllerPublishVolumeResponse{
|
||||
PublishVolumeInfo: map[string]string{
|
||||
"DevicePath": fakeDevicePath,
|
||||
},
|
||||
}
|
||||
|
||||
// Invoke ControllerPublishVolume
|
||||
actualRes, err := fakeCs.ControllerPublishVolume(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to ControllerPublishVolume: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedRes, actualRes)
|
||||
}
|
||||
|
||||
// Test ControllerUnpublishVolume
|
||||
func TestControllerUnpublishVolume(t *testing.T) {
|
||||
|
||||
// mock OpenStack
|
||||
osmock := new(openstack.OpenStackMock)
|
||||
// DetachVolume(instanceID, volumeID string) error
|
||||
osmock.On("DetachVolume", fakeNodeID, fakeVolID).Return(nil)
|
||||
// WaitDiskDetached(instanceID string, volumeID string) error
|
||||
osmock.On("WaitDiskDetached", fakeNodeID, fakeVolID).Return(nil)
|
||||
openstack.OsInstance = osmock
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.ControllerUnpublishVolumeRequest{
|
||||
Version: &version,
|
||||
VolumeId: fakeVolID,
|
||||
NodeId: fakeNodeID,
|
||||
}
|
||||
|
||||
// Expected Result
|
||||
expectedRes := &csi.ControllerUnpublishVolumeResponse{}
|
||||
|
||||
// Invoke ControllerUnpublishVolume
|
||||
actualRes, err := fakeCs.ControllerUnpublishVolume(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to ControllerUnpublishVolume: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedRes, actualRes)
|
||||
}
|
71
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-attacher-cinderplugin.yaml
generated
vendored
Normal file
71
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-attacher-cinderplugin.yaml
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
# This YAML file contains attacher & csi driver API objects,
|
||||
# which are necessary to run external csi attacher for cinder.
|
||||
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: csi-attacher-cinderplugin
|
||||
labels:
|
||||
app: csi-attacher-cinderplugin
|
||||
spec:
|
||||
selector:
|
||||
app: csi-attacher-cinderplugin
|
||||
ports:
|
||||
- name: dummy
|
||||
port: 12345
|
||||
|
||||
---
|
||||
kind: StatefulSet
|
||||
apiVersion: apps/v1beta1
|
||||
metadata:
|
||||
name: csi-attacher-cinderplugin
|
||||
spec:
|
||||
serviceName: "csi-attacher-cinderplugin"
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: csi-attacher-cinderplugin
|
||||
spec:
|
||||
serviceAccount: csi-attacher
|
||||
containers:
|
||||
- name: csi-attacher
|
||||
image: docker.io/k8scsi/csi-attacher
|
||||
args:
|
||||
- "--v=5"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /var/lib/csi/sockets/pluginproxy/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /var/lib/csi/sockets/pluginproxy/
|
||||
- name: cinder
|
||||
image: docker.io/k8scsi/cinderplugin
|
||||
args :
|
||||
- "--nodeid=$(NODE_ID)"
|
||||
- "--endpoint=$(CSI_ENDPOINT)"
|
||||
- "--cloud-config=$(CLOUD_CONFIG)"
|
||||
env:
|
||||
- name: NODE_ID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: CSI_ENDPOINT
|
||||
value: unix://plugin/csi.sock
|
||||
- name: CLOUD_CONFIG
|
||||
value: /etc/config/cloud.conf
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /plugin
|
||||
- name: secret-cinderplugin
|
||||
mountPath: /etc/config
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: socket-dir
|
||||
emptyDir:
|
||||
- name: secret-cinderplugin
|
||||
secret:
|
||||
secretName: csi-secret-cinderplugin
|
37
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-attacher-rbac.yaml
generated
vendored
Normal file
37
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-attacher-rbac.yaml
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
# This YAML file contains RBAC API objects,
|
||||
# which are necessary to run external csi attacher for cinder.
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: csi-attacher
|
||||
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: external-attacher-runner
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["volumeattachments"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-attacher-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: csi-attacher
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: external-attacher-runner
|
||||
apiGroup: rbac.authorization.k8s.io
|
90
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-nodeplugin-cinderplugin.yaml
generated
vendored
Normal file
90
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-nodeplugin-cinderplugin.yaml
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
# This YAML file contains driver-registrar & csi driver nodeplugin API objects,
|
||||
# which are necessary to run csi nodeplugin for cinder.
|
||||
|
||||
kind: DaemonSet
|
||||
apiVersion: apps/v1beta2
|
||||
metadata:
|
||||
name: csi-nodeplugin-cinderplugin
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: csi-nodeplugin-cinderplugin
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: csi-nodeplugin-cinderplugin
|
||||
spec:
|
||||
serviceAccount: csi-nodeplugin
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: driver-registrar
|
||||
image: docker.io/k8scsi/driver-registrar
|
||||
args:
|
||||
- "--v=5"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /plugin/csi.sock
|
||||
- name: KUBE_NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
volumeMounts:
|
||||
- name: plugin-dir
|
||||
mountPath: /plugin
|
||||
- name: cinder
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
add: ["SYS_ADMIN"]
|
||||
allowPrivilegeEscalation: true
|
||||
image: docker.io/k8scsi/cinderplugin
|
||||
args :
|
||||
- "--nodeid=$(NODE_ID)"
|
||||
- "--endpoint=$(CSI_ENDPOINT)"
|
||||
- "--cloud-config=$(CLOUD_CONFIG)"
|
||||
env:
|
||||
- name: NODE_ID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: CSI_ENDPOINT
|
||||
value: unix://plugin/csi.sock
|
||||
- name: CLOUD_CONFIG
|
||||
value: /etc/config/cloud.conf
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: plugin-dir
|
||||
mountPath: /plugin
|
||||
- name: pods-mount-dir
|
||||
mountPath: /var/lib/kubelet/pods
|
||||
mountPropagation: "Bidirectional"
|
||||
- name: pods-cloud-data
|
||||
mountPath: /var/lib/cloud/data
|
||||
readOnly: true
|
||||
- name: pods-probe-dir
|
||||
mountPath: /dev
|
||||
mountPropagation: "HostToContainer"
|
||||
- name: secret-cinderplugin
|
||||
mountPath: /etc/config
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: plugin-dir
|
||||
hostPath:
|
||||
path: /var/lib/kubelet/plugins/csi-cinderplugin
|
||||
type: DirectoryOrCreate
|
||||
- name: pods-mount-dir
|
||||
hostPath:
|
||||
path: /var/lib/kubelet/pods
|
||||
type: Directory
|
||||
- name: pods-cloud-data
|
||||
hostPath:
|
||||
path: /var/lib/cloud/data
|
||||
type: Directory
|
||||
- name: pods-probe-dir
|
||||
hostPath:
|
||||
path: /dev
|
||||
type: Directory
|
||||
- name: secret-cinderplugin
|
||||
secret:
|
||||
secretName: csi-secret-cinderplugin
|
35
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-nodeplugin-rbac.yaml
generated
vendored
Normal file
35
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-nodeplugin-rbac.yaml
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
# This YAML defines all API objects to create RBAC roles for csi node plugin.
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["volumeattachments"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: csi-nodeplugin
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: csi-nodeplugin
|
||||
apiGroup: rbac.authorization.k8s.io
|
71
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-provisioner-cinderplugin.yaml
generated
vendored
Normal file
71
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-provisioner-cinderplugin.yaml
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
# This YAML file contains attacher & csi driver API objects,
|
||||
# which are necessary to run external csi provisioner for cinder.
|
||||
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: csi-provisioner-cinderplugin
|
||||
labels:
|
||||
app: csi-provisioner-cinderplugin
|
||||
spec:
|
||||
selector:
|
||||
app: csi-provisioner-cinderplugin
|
||||
ports:
|
||||
- name: dummy
|
||||
port: 12345
|
||||
|
||||
---
|
||||
kind: StatefulSet
|
||||
apiVersion: apps/v1beta1
|
||||
metadata:
|
||||
name: csi-provisioner-cinderplugin
|
||||
spec:
|
||||
serviceName: "csi-provisioner-cinderplugin"
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: csi-provisioner-cinderplugin
|
||||
spec:
|
||||
serviceAccount: csi-provisioner
|
||||
containers:
|
||||
- name: csi-provisioner
|
||||
image: docker.io/k8scsi/csi-provisioner
|
||||
args:
|
||||
- "--provisioner=csi-cinderplugin"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /var/lib/csi/sockets/pluginproxy/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /var/lib/csi/sockets/pluginproxy/
|
||||
- name: cinder
|
||||
image: docker.io/k8scsi/cinderplugin
|
||||
args :
|
||||
- "--nodeid=$(NODE_ID)"
|
||||
- "--endpoint=$(CSI_ENDPOINT)"
|
||||
- "--cloud-config=$(CLOUD_CONFIG)"
|
||||
env:
|
||||
- name: NODE_ID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: CSI_ENDPOINT
|
||||
value: unix://plugin/csi.sock
|
||||
- name: CLOUD_CONFIG
|
||||
value: /etc/config/cloud.conf
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /plugin
|
||||
- name: secret-cinderplugin
|
||||
mountPath: /etc/config
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: socket-dir
|
||||
emptyDir:
|
||||
- name: secret-cinderplugin
|
||||
secret:
|
||||
secretName: csi-secret-cinderplugin
|
41
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-provisioner-rbac.yaml
generated
vendored
Normal file
41
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-provisioner-rbac.yaml
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# This YAML file contains RBAC API objects,
|
||||
# which are necessary to run external csi provisioner for cinder.
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: csi-provisioner
|
||||
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: external-provisioner-runner
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "create", "delete"]
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumeclaims"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["storageclasses"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["events"]
|
||||
verbs: ["list", "watch", "create", "update", "patch"]
|
||||
|
||||
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-provisioner-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: csi-provisioner
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: external-provisioner-runner
|
||||
apiGroup: rbac.authorization.k8s.io
|
9
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-secret-cinderplugin.yaml
generated
vendored
Normal file
9
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/deploy/kubernetes/csi-secret-cinderplugin.yaml
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# This YAML file contains secret objects,
|
||||
# which are necessary to run csi cinder plugin.
|
||||
|
||||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: csi-secret-cinderplugin
|
||||
data:
|
||||
cloud.conf: W0dsb2JhbF0KdXNlcm5hbWU9dXNlcgpwYXNzd29yZD1wYXNzCmF1dGgtdXJsPWh0dHBzOi8vPGtleXN0b25lX2lwPi9pZGVudGl0eS92Mwp0ZW5hbnQtaWQ9Yzg2OTE2OGE4Mjg4NDdmMzlmN2YwNmVkZDczMDU2MzcKZG9tYWluLWlkPTJhNzNiOGY1OTdjMDQ1NTFhMGZkYzhlOTU1NDRiZThhCg==
|
13
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/dockerfile/Dockerfile
generated
vendored
Normal file
13
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/dockerfile/Dockerfile
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Based on centos
|
||||
FROM centos:7.4.1708
|
||||
LABEL maintainers="Kubernetes Authors"
|
||||
LABEL description="Cinder CSI Plugin"
|
||||
|
||||
# Copy cinderplugin from build directory
|
||||
COPY cinderplugin /cinderplugin
|
||||
|
||||
# Install e4fsprogs for format
|
||||
RUN yum -y install e4fsprogs
|
||||
|
||||
# Define default command
|
||||
ENTRYPOINT ["/cinderplugin"]
|
90
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/driver.go
generated
vendored
Normal file
90
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/driver.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cinder
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/cinder/openstack"
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
csiDriver *csicommon.CSIDriver
|
||||
endpoint string
|
||||
cloudconfig string
|
||||
|
||||
ids *csicommon.DefaultIdentityServer
|
||||
cs *controllerServer
|
||||
ns *nodeServer
|
||||
|
||||
cap []*csi.VolumeCapability_AccessMode
|
||||
cscap []*csi.ControllerServiceCapability
|
||||
}
|
||||
|
||||
const (
|
||||
driverName = "csi-cinderplugin"
|
||||
)
|
||||
|
||||
var (
|
||||
version = csi.Version{
|
||||
Minor: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func GetSupportedVersions() []*csi.Version {
|
||||
return []*csi.Version{&version}
|
||||
}
|
||||
|
||||
func NewDriver(nodeID, endpoint string, cloudconfig string) *driver {
|
||||
glog.Infof("Driver: %v version: %v", driverName, csicommon.GetVersionString(&version))
|
||||
|
||||
d := &driver{}
|
||||
|
||||
d.endpoint = endpoint
|
||||
d.cloudconfig = cloudconfig
|
||||
|
||||
csiDriver := csicommon.NewCSIDriver(driverName, &version, GetSupportedVersions(), nodeID)
|
||||
csiDriver.AddControllerServiceCapabilities(
|
||||
[]csi.ControllerServiceCapability_RPC_Type{
|
||||
csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
|
||||
csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
|
||||
})
|
||||
csiDriver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER})
|
||||
|
||||
d.csiDriver = csiDriver
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func NewControllerServer(d *driver) *controllerServer {
|
||||
return &controllerServer{
|
||||
DefaultControllerServer: csicommon.NewDefaultControllerServer(d.csiDriver),
|
||||
}
|
||||
}
|
||||
|
||||
func NewNodeServer(d *driver) *nodeServer {
|
||||
return &nodeServer{
|
||||
DefaultNodeServer: csicommon.NewDefaultNodeServer(d.csiDriver),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) Run() {
|
||||
openstack.InitOpenStackProvider(d.cloudconfig)
|
||||
csicommon.RunControllerandNodePublishServer(d.endpoint, d.csiDriver, NewControllerServer(d), NewNodeServer(d))
|
||||
}
|
6
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/etc/cloud.conf
generated
vendored
Normal file
6
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/etc/cloud.conf
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[Global]
|
||||
username=user
|
||||
password=pass
|
||||
auth-url=https://<keystone_ip>/identity/v3
|
||||
tenant-id=c869168a828847f39f7f06edd7305637
|
||||
domain-id=2a73b8f597c04551a0fdc8e95544be8a
|
44
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/examples/kubernetes/nginx.yaml
generated
vendored
Normal file
44
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/examples/kubernetes/nginx.yaml
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# This YAML file contains nginx & csi cinder driver objects,
|
||||
# which are necessary to run nginx with csi cinder driver.
|
||||
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: csi-sc-cinderplugin
|
||||
provisioner: csi-cinderplugin
|
||||
parameters:
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: csi-pvc-cinderplugin
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
storageClassName: csi-sc-cinderplugin
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/www/html
|
||||
name: csi-data-cinderplugin
|
||||
volumes:
|
||||
- name: csi-data-cinderplugin
|
||||
persistentVolumeClaim:
|
||||
claimName: csi-pvc-cinderplugin
|
||||
readOnly: false
|
32
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/fake.go
generated
vendored
Normal file
32
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/fake.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cinder
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var fakeNodeID = "CSINodeID"
|
||||
var fakeEndpoint = "tcp://127.0.0.1:10000"
|
||||
var fakeConfig = "/etc/cloud.conf"
|
||||
var fakeCtx = context.Background()
|
||||
var fakeVolName = "CSIVolumeName"
|
||||
var fakeVolID = "CSIVolumeID"
|
||||
var fakeVolType = "lvmdriver-1"
|
||||
var fakeAvailability = "nova"
|
||||
var fakeDevicePath = "/dev/xxx"
|
||||
var fakeTargetPath = "/mnt/cinder"
|
161
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/mount/mount.go
generated
vendored
Normal file
161
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/mount/mount.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
probeVolumeDuration = 1 * time.Second
|
||||
probeVolumeTimeout = 60 * time.Second
|
||||
instanceIDFile = "/var/lib/cloud/data/instance-id"
|
||||
)
|
||||
|
||||
type IMount interface {
|
||||
ScanForAttach(devicePath string) error
|
||||
IsLikelyNotMountPointAttach(targetpath string) (bool, error)
|
||||
FormatAndMount(source string, target string, fstype string, options []string) error
|
||||
IsLikelyNotMountPointDetach(targetpath string) (bool, error)
|
||||
UnmountPath(mountPath string) error
|
||||
GetInstanceID() (string, error)
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
}
|
||||
|
||||
var MInstance IMount = nil
|
||||
|
||||
func GetMountProvider() (IMount, error) {
|
||||
|
||||
if MInstance == nil {
|
||||
MInstance = &Mount{}
|
||||
}
|
||||
return MInstance, nil
|
||||
}
|
||||
|
||||
// probeVolume probes volume in compute
|
||||
func probeVolume() error {
|
||||
// rescan scsi bus
|
||||
scsi_path := "/sys/class/scsi_host/"
|
||||
if dirs, err := ioutil.ReadDir(scsi_path); err == nil {
|
||||
for _, f := range dirs {
|
||||
name := scsi_path + f.Name() + "/scan"
|
||||
data := []byte("- - -")
|
||||
ioutil.WriteFile(name, data, 0666)
|
||||
}
|
||||
}
|
||||
|
||||
executor := utilexec.New()
|
||||
args := []string{"trigger"}
|
||||
cmd := executor.Command("udevadm", args...)
|
||||
_, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("error running udevadm trigger %v\n", err)
|
||||
return err
|
||||
}
|
||||
glog.V(4).Infof("Successfully probed all attachments")
|
||||
return nil
|
||||
}
|
||||
|
||||
// ScanForAttach
|
||||
func (m *Mount) ScanForAttach(devicePath string) error {
|
||||
ticker := time.NewTicker(probeVolumeDuration)
|
||||
defer ticker.Stop()
|
||||
timer := time.NewTimer(probeVolumeTimeout)
|
||||
defer timer.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
glog.V(5).Infof("Checking Cinder disk %q is attached.", devicePath)
|
||||
probeVolume()
|
||||
|
||||
exists, err := util.PathExists(devicePath)
|
||||
if exists && err == nil {
|
||||
return nil
|
||||
} else {
|
||||
glog.V(3).Infof("Could not find attached Cinder disk %s", devicePath)
|
||||
}
|
||||
case <-timer.C:
|
||||
return fmt.Errorf("Could not find attached Cinder disk %s. Timeout waiting for mount paths to be created.", devicePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FormatAndMount
|
||||
func (m *Mount) FormatAndMount(source string, target string, fstype string, options []string) error {
|
||||
diskMounter := &mount.SafeFormatAndMount{Interface: mount.New(""), Exec: mount.NewOsExec()}
|
||||
return diskMounter.FormatAndMount(source, target, fstype, options)
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPointAttach
|
||||
func (m *Mount) IsLikelyNotMountPointAttach(targetpath string) (bool, error) {
|
||||
notMnt, err := mount.New("").IsLikelyNotMountPoint(targetpath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(targetpath, 0750)
|
||||
if err == nil {
|
||||
notMnt = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return notMnt, err
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPointDetach
|
||||
func (m *Mount) IsLikelyNotMountPointDetach(targetpath string) (bool, error) {
|
||||
notMnt, err := mount.New("").IsLikelyNotMountPoint(targetpath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return notMnt, fmt.Errorf("targetpath not found")
|
||||
} else {
|
||||
return notMnt, err
|
||||
}
|
||||
}
|
||||
return notMnt, nil
|
||||
}
|
||||
|
||||
// UnmountPath
|
||||
func (m *Mount) UnmountPath(mountPath string) error {
|
||||
return util.UnmountPath(mountPath, mount.New(""))
|
||||
}
|
||||
|
||||
// GetInstanceID from file
|
||||
func (m *Mount) GetInstanceID() (string, error) {
|
||||
// Try to find instance ID on the local filesystem (created by cloud-init)
|
||||
idBytes, err := ioutil.ReadFile(instanceIDFile)
|
||||
if err == nil {
|
||||
instanceID := string(idBytes)
|
||||
instanceID = strings.TrimSpace(instanceID)
|
||||
glog.V(3).Infof("Got instance id from %s: %s", instanceIDFile, instanceID)
|
||||
if instanceID != "" {
|
||||
return instanceID, nil
|
||||
}
|
||||
}
|
||||
return "", err
|
||||
}
|
130
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/mount/mount_mock.go
generated
vendored
Normal file
130
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/mount/mount_mock.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package mount
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
|
||||
// MountMock is an autogenerated mock type for the IMount type
|
||||
// ORIGINALLY GENERATED BY mockery with hand edits
|
||||
type MountMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// FormatAndMount provides a mock function with given fields: source, target, fstype, options
|
||||
func (_m *MountMock) FormatAndMount(source string, target string, fstype string, options []string) error {
|
||||
ret := _m.Called(source, target, fstype, options)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, string, string, []string) error); ok {
|
||||
r0 = rf(source, target, fstype, options)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetInstanceID provides a mock function with given fields:
|
||||
func (_m *MountMock) GetInstanceID() (string, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPointAttach provides a mock function with given fields: targetpath
|
||||
func (_m *MountMock) IsLikelyNotMountPointAttach(targetpath string) (bool, error) {
|
||||
ret := _m.Called(targetpath)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||
r0 = rf(targetpath)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(targetpath)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPointDetach provides a mock function with given fields: targetpath
|
||||
func (_m *MountMock) IsLikelyNotMountPointDetach(targetpath string) (bool, error) {
|
||||
ret := _m.Called(targetpath)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||
r0 = rf(targetpath)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(targetpath)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ScanForAttach provides a mock function with given fields: devicePath
|
||||
func (_m *MountMock) ScanForAttach(devicePath string) error {
|
||||
ret := _m.Called(devicePath)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(devicePath)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UnmountPath provides a mock function with given fields: mountPath
|
||||
func (_m *MountMock) UnmountPath(mountPath string) error {
|
||||
ret := _m.Called(mountPath)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(mountPath)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
132
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver.go
generated
vendored
Normal file
132
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cinder
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/cinder/mount"
|
||||
csicommon "github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type nodeServer struct {
|
||||
*csicommon.DefaultNodeServer
|
||||
}
|
||||
|
||||
func (ns *nodeServer) GetNodeID(ctx context.Context, req *csi.GetNodeIDRequest) (*csi.GetNodeIDResponse, error) {
|
||||
|
||||
// Get Mount Provider
|
||||
m, err := mount.GetMountProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetMountProvider: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeID, err := m.GetInstanceID()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetInstanceID: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(nodeID) > 0 {
|
||||
return &csi.GetNodeIDResponse{
|
||||
NodeId: nodeID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Using default function
|
||||
return ns.DefaultNodeServer.GetNodeID(ctx, req)
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||
|
||||
targetPath := req.GetTargetPath()
|
||||
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
||||
devicePath := req.GetPublishVolumeInfo()["DevicePath"]
|
||||
|
||||
// Get Mount Provider
|
||||
m, err := mount.GetMountProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetMountProvider: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Device Scan
|
||||
err = m.ScanForAttach(devicePath)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to ScanForAttach: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify whether mounted
|
||||
notMnt, err := m.IsLikelyNotMountPointAttach(targetPath)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
// Volume Mount
|
||||
if notMnt {
|
||||
// Get Options
|
||||
var options []string
|
||||
if req.GetReadonly() {
|
||||
options = append(options, "ro")
|
||||
} else {
|
||||
options = append(options, "rw")
|
||||
}
|
||||
mountFlags := req.GetVolumeCapability().GetMount().GetMountFlags()
|
||||
options = append(options, mountFlags...)
|
||||
|
||||
// Mount
|
||||
err = m.FormatAndMount(devicePath, targetPath, fsType, options)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
||||
|
||||
targetPath := req.GetTargetPath()
|
||||
|
||||
// Get Mount Provider
|
||||
m, err := mount.GetMountProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetMountProvider: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notMnt, err := m.IsLikelyNotMountPointDetach(targetPath)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
if notMnt {
|
||||
return nil, status.Error(codes.NotFound, "Volume not mounted")
|
||||
}
|
||||
|
||||
err = m.UnmountPath(req.GetTargetPath())
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
142
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver_test.go
generated
vendored
Normal file
142
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver_test.go
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cinder
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/kubernetes-csi/drivers/pkg/cinder/mount"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
var fakeNs *nodeServer
|
||||
|
||||
// Init Node Server
|
||||
func init() {
|
||||
if fakeNs == nil {
|
||||
d := NewDriver(fakeNodeID, fakeEndpoint, fakeConfig)
|
||||
fakeNs = NewNodeServer(d)
|
||||
}
|
||||
}
|
||||
|
||||
// Test GetNodeID
|
||||
func TestGetNodeID(t *testing.T) {
|
||||
|
||||
// mock MountMock
|
||||
mmock := new(mount.MountMock)
|
||||
// GetInstanceID() (string, error)
|
||||
mmock.On("GetInstanceID").Return(fakeNodeID, nil)
|
||||
mount.MInstance = mmock
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
// Expected Result
|
||||
expectedRes := &csi.GetNodeIDResponse{
|
||||
NodeId: fakeNodeID,
|
||||
}
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.GetNodeIDRequest{
|
||||
Version: &version,
|
||||
}
|
||||
|
||||
// Invoke GetNodeID
|
||||
actualRes, err := fakeNs.GetNodeID(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to GetNodeID: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedRes, actualRes)
|
||||
}
|
||||
|
||||
// Test NodePublishVolume
|
||||
func TestNodePublishVolume(t *testing.T) {
|
||||
|
||||
// mock MountMock
|
||||
mmock := new(mount.MountMock)
|
||||
// ScanForAttach(devicePath string) error
|
||||
mmock.On("ScanForAttach", fakeDevicePath).Return(nil)
|
||||
// IsLikelyNotMountPointAttach(targetpath string) (bool, error)
|
||||
mmock.On("IsLikelyNotMountPointAttach", fakeTargetPath).Return(true, nil)
|
||||
// FormatAndMount(source string, target string, fstype string, options []string) error
|
||||
mmock.On("FormatAndMount", fakeDevicePath, fakeTargetPath, mock.AnythingOfType("string"), []string{"rw"}).Return(nil)
|
||||
mount.MInstance = mmock
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
// Expected Result
|
||||
expectedRes := &csi.NodePublishVolumeResponse{}
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.NodePublishVolumeRequest{
|
||||
Version: &version,
|
||||
VolumeId: fakeVolID,
|
||||
PublishVolumeInfo: map[string]string{"DevicePath": fakeDevicePath},
|
||||
TargetPath: fakeTargetPath,
|
||||
VolumeCapability: nil,
|
||||
Readonly: false,
|
||||
}
|
||||
|
||||
// Invoke NodePublishVolume
|
||||
actualRes, err := fakeNs.NodePublishVolume(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to NodePublishVolume: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedRes, actualRes)
|
||||
}
|
||||
|
||||
// Test NodeUnpublishVolume
|
||||
func TestNodeUnpublishVolume(t *testing.T) {
|
||||
|
||||
// mock MountMock
|
||||
mmock := new(mount.MountMock)
|
||||
|
||||
// IsLikelyNotMountPointDetach(targetpath string) (bool, error)
|
||||
mmock.On("IsLikelyNotMountPointDetach", fakeTargetPath).Return(false, nil)
|
||||
// UnmountPath(mountPath string) error
|
||||
mmock.On("UnmountPath", fakeTargetPath).Return(nil)
|
||||
mount.MInstance = mmock
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
// Expected Result
|
||||
expectedRes := &csi.NodeUnpublishVolumeResponse{}
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.NodeUnpublishVolumeRequest{
|
||||
Version: &version,
|
||||
VolumeId: fakeVolID,
|
||||
TargetPath: fakeTargetPath,
|
||||
}
|
||||
|
||||
// Invoke NodeUnpublishVolume
|
||||
actualRes, err := fakeNs.NodeUnpublishVolume(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to NodeUnpublishVolume: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedRes, actualRes)
|
||||
}
|
163
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack.go
generated
vendored
Normal file
163
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack.go
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack"
|
||||
"gopkg.in/gcfg.v1"
|
||||
)
|
||||
|
||||
type IOpenStack interface {
|
||||
CreateVolume(name string, size int, vtype, availability string, tags *map[string]string) (string, string, error)
|
||||
DeleteVolume(volumeID string) error
|
||||
AttachVolume(instanceID, volumeID string) (string, error)
|
||||
WaitDiskAttached(instanceID string, volumeID string) error
|
||||
DetachVolume(instanceID, volumeID string) error
|
||||
WaitDiskDetached(instanceID string, volumeID string) error
|
||||
GetAttachmentDiskPath(instanceID, volumeID string) (string, error)
|
||||
}
|
||||
|
||||
type OpenStack struct {
|
||||
compute *gophercloud.ServiceClient
|
||||
blockstorage *gophercloud.ServiceClient
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Global struct {
|
||||
AuthUrl string `gcfg:"auth-url"`
|
||||
Username string
|
||||
UserId string `gcfg:"user-id"`
|
||||
Password string
|
||||
TenantId string `gcfg:"tenant-id"`
|
||||
TenantName string `gcfg:"tenant-name"`
|
||||
DomainId string `gcfg:"domain-id"`
|
||||
DomainName string `gcfg:"domain-name"`
|
||||
Region string
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Config) toAuthOptions() gophercloud.AuthOptions {
|
||||
return gophercloud.AuthOptions{
|
||||
IdentityEndpoint: cfg.Global.AuthUrl,
|
||||
Username: cfg.Global.Username,
|
||||
UserID: cfg.Global.UserId,
|
||||
Password: cfg.Global.Password,
|
||||
TenantID: cfg.Global.TenantId,
|
||||
TenantName: cfg.Global.TenantName,
|
||||
DomainID: cfg.Global.DomainId,
|
||||
DomainName: cfg.Global.DomainName,
|
||||
|
||||
// Persistent service, so we need to be able to renew tokens.
|
||||
AllowReauth: true,
|
||||
}
|
||||
}
|
||||
|
||||
func GetConfigFromFile(configFilePath string) (gophercloud.AuthOptions, gophercloud.EndpointOpts, error) {
|
||||
// Get config from file
|
||||
var authOpts gophercloud.AuthOptions
|
||||
var epOpts gophercloud.EndpointOpts
|
||||
config, err := os.Open(configFilePath)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to open OpenStack configuration file: %v", err)
|
||||
return authOpts, epOpts, err
|
||||
}
|
||||
defer config.Close()
|
||||
|
||||
// Read configuration
|
||||
var cfg Config
|
||||
err = gcfg.ReadInto(&cfg, config)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to read OpenStack configuration file: %v", err)
|
||||
return authOpts, epOpts, err
|
||||
}
|
||||
|
||||
authOpts = cfg.toAuthOptions()
|
||||
epOpts = gophercloud.EndpointOpts{
|
||||
Region: cfg.Global.Region,
|
||||
}
|
||||
|
||||
return authOpts, epOpts, nil
|
||||
}
|
||||
|
||||
func GetConfigFromEnv() (gophercloud.AuthOptions, gophercloud.EndpointOpts, error) {
|
||||
// Get config from env
|
||||
authOpts, err := openstack.AuthOptionsFromEnv()
|
||||
var epOpts gophercloud.EndpointOpts
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to read OpenStack configuration from env: %v", err)
|
||||
return authOpts, epOpts, err
|
||||
}
|
||||
|
||||
epOpts = gophercloud.EndpointOpts{
|
||||
Region: os.Getenv("OS_REGION_NAME"),
|
||||
}
|
||||
|
||||
return authOpts, epOpts, nil
|
||||
}
|
||||
|
||||
var OsInstance IOpenStack = nil
|
||||
var configFile string = "/etc/cloud.conf"
|
||||
|
||||
func InitOpenStackProvider(cfg string) {
|
||||
configFile = cfg
|
||||
glog.V(2).Infof("InitOpenStackProvider configFile: %s", configFile)
|
||||
}
|
||||
|
||||
func GetOpenStackProvider() (IOpenStack, error) {
|
||||
|
||||
if OsInstance == nil {
|
||||
// Get config from file
|
||||
authOpts, epOpts, err := GetConfigFromFile(configFile)
|
||||
if err != nil {
|
||||
// Get config from env
|
||||
authOpts, epOpts, err = GetConfigFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Authenticate Client
|
||||
provider, err := openstack.AuthenticatedClient(authOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Init Nova ServiceClient
|
||||
computeclient, err := openstack.NewComputeV2(provider, epOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Init Cinder ServiceClient
|
||||
blockstorageclient, err := openstack.NewBlockStorageV3(provider, epOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Init OpenStack
|
||||
OsInstance = &OpenStack{
|
||||
compute: computeclient,
|
||||
blockstorage: blockstorageclient,
|
||||
}
|
||||
}
|
||||
|
||||
return OsInstance, nil
|
||||
}
|
151
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_mock.go
generated
vendored
Normal file
151
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_mock.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package openstack
|
||||
|
||||
import "github.com/stretchr/testify/mock"
|
||||
|
||||
// OpenStackMock is an autogenerated mock type for the IOpenStack type
|
||||
// ORIGINALLY GENERATED BY mockery with hand edits
|
||||
type OpenStackMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// AttachVolume provides a mock function with given fields: instanceID, volumeID
|
||||
func (_m *OpenStackMock) AttachVolume(instanceID string, volumeID string) (string, error) {
|
||||
ret := _m.Called(instanceID, volumeID)
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(string, string) string); ok {
|
||||
r0 = rf(instanceID, volumeID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
||||
r1 = rf(instanceID, volumeID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CreateVolume provides a mock function with given fields: name, size, vtype, availability, tags
|
||||
func (_m *OpenStackMock) CreateVolume(name string, size int, vtype string, availability string, tags *map[string]string) (string, string, error) {
|
||||
ret := _m.Called(name, size, vtype, availability, tags)
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(string, int, string, string, *map[string]string) string); ok {
|
||||
r0 = rf(name, size, vtype, availability, tags)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 string
|
||||
if rf, ok := ret.Get(1).(func(string, int, string, string, *map[string]string) string); ok {
|
||||
r1 = rf(name, size, vtype, availability, tags)
|
||||
} else {
|
||||
r1 = ret.Get(1).(string)
|
||||
}
|
||||
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(2).(func(string, int, string, string, *map[string]string) error); ok {
|
||||
r2 = rf(name, size, vtype, availability, tags)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// DeleteVolume provides a mock function with given fields: volumeID
|
||||
func (_m *OpenStackMock) DeleteVolume(volumeID string) error {
|
||||
ret := _m.Called(volumeID)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(volumeID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// DetachVolume provides a mock function with given fields: instanceID, volumeID
|
||||
func (_m *OpenStackMock) DetachVolume(instanceID string, volumeID string) error {
|
||||
ret := _m.Called(instanceID, volumeID)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||
r0 = rf(instanceID, volumeID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetAttachmentDiskPath provides a mock function with given fields: instanceID, volumeID
|
||||
func (_m *OpenStackMock) GetAttachmentDiskPath(instanceID string, volumeID string) (string, error) {
|
||||
ret := _m.Called(instanceID, volumeID)
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(string, string) string); ok {
|
||||
r0 = rf(instanceID, volumeID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
||||
r1 = rf(instanceID, volumeID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// WaitDiskAttached provides a mock function with given fields: instanceID, volumeID
|
||||
func (_m *OpenStackMock) WaitDiskAttached(instanceID string, volumeID string) error {
|
||||
ret := _m.Called(instanceID, volumeID)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||
r0 = rf(instanceID, volumeID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// WaitDiskDetached provides a mock function with given fields: instanceID, volumeID
|
||||
func (_m *OpenStackMock) WaitDiskDetached(instanceID string, volumeID string) error {
|
||||
ret := _m.Called(instanceID, volumeID)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||
r0 = rf(instanceID, volumeID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
119
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_test.go
generated
vendored
Normal file
119
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_test.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var fakeFileName = "cloud.conf"
|
||||
var fakeUserName = "user"
|
||||
var fakePassword = "pass"
|
||||
var fakeAuthUrl = "https://169.254.169.254/identity/v3"
|
||||
var fakeTenantID = "c869168a828847f39f7f06edd7305637"
|
||||
var fakeDomainID = "2a73b8f597c04551a0fdc8e95544be8a"
|
||||
var fakeRegion = "RegionOne"
|
||||
|
||||
// Test GetConfigFromFile
|
||||
func TestGetConfigFromFile(t *testing.T) {
|
||||
// init file
|
||||
var fakeFileContent = `
|
||||
[Global]
|
||||
username=` + fakeUserName + `
|
||||
password=` + fakePassword + `
|
||||
auth-url=` + fakeAuthUrl + `
|
||||
tenant-id=` + fakeTenantID + `
|
||||
domain-id=` + fakeDomainID + `
|
||||
region=` + fakeRegion + `
|
||||
`
|
||||
|
||||
f, err := os.Create(fakeFileName)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create file: %v", err)
|
||||
}
|
||||
|
||||
_, err = f.WriteString(fakeFileContent)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Errorf("failed to write file: %v", err)
|
||||
}
|
||||
defer os.Remove(fakeFileName)
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
expectedAuthOpts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: fakeAuthUrl,
|
||||
Username: fakeUserName,
|
||||
Password: fakePassword,
|
||||
TenantID: fakeTenantID,
|
||||
DomainID: fakeDomainID,
|
||||
AllowReauth: true,
|
||||
}
|
||||
expectedEpOpts := gophercloud.EndpointOpts{
|
||||
Region: fakeRegion,
|
||||
}
|
||||
|
||||
// Invoke GetConfigFromFile
|
||||
actualAuthOpts, actualEpOpts, err := GetConfigFromFile(fakeFileName)
|
||||
if err != nil {
|
||||
t.Errorf("failed to GetConfigFromFile: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedAuthOpts, actualAuthOpts)
|
||||
assert.Equal(expectedEpOpts, actualEpOpts)
|
||||
}
|
||||
|
||||
// Test GetConfigFromEnv
|
||||
func TestGetConfigFromEnv(t *testing.T) {
|
||||
// init env
|
||||
os.Setenv("OS_AUTH_URL", fakeAuthUrl)
|
||||
os.Setenv("OS_USERNAME", fakeUserName)
|
||||
os.Setenv("OS_PASSWORD", fakePassword)
|
||||
os.Setenv("OS_TENANT_ID", fakeTenantID)
|
||||
os.Setenv("OS_DOMAIN_ID", fakeDomainID)
|
||||
os.Setenv("OS_REGION_NAME", fakeRegion)
|
||||
|
||||
// Init assert
|
||||
assert := assert.New(t)
|
||||
|
||||
expectedAuthOpts := gophercloud.AuthOptions{
|
||||
IdentityEndpoint: fakeAuthUrl,
|
||||
Username: fakeUserName,
|
||||
Password: fakePassword,
|
||||
TenantID: fakeTenantID,
|
||||
DomainID: fakeDomainID,
|
||||
}
|
||||
expectedEpOpts := gophercloud.EndpointOpts{
|
||||
Region: fakeRegion,
|
||||
}
|
||||
|
||||
// Invoke GetConfigFromEnv
|
||||
actualAuthOpts, actualEpOpts, err := GetConfigFromEnv()
|
||||
if err != nil {
|
||||
t.Errorf("failed to GetConfigFromEnv: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedAuthOpts, actualAuthOpts)
|
||||
assert.Equal(expectedEpOpts, actualEpOpts)
|
||||
}
|
253
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_volumes.go
generated
vendored
Normal file
253
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_volumes.go
generated
vendored
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
VolumeAvailableStatus = "available"
|
||||
VolumeInUseStatus = "in-use"
|
||||
VolumeDeletedStatus = "deleted"
|
||||
VolumeErrorStatus = "error"
|
||||
operationFinishInitDelay = 1 * time.Second
|
||||
operationFinishFactor = 1.1
|
||||
operationFinishSteps = 10
|
||||
diskAttachInitDelay = 1 * time.Second
|
||||
diskAttachFactor = 1.2
|
||||
diskAttachSteps = 15
|
||||
diskDetachInitDelay = 1 * time.Second
|
||||
diskDetachFactor = 1.2
|
||||
diskDetachSteps = 13
|
||||
)
|
||||
|
||||
type Volume struct {
|
||||
// ID of the instance, to which this volume is attached. "" if not attached
|
||||
AttachedServerId string
|
||||
// Device file path
|
||||
AttachedDevice string
|
||||
// Unique identifier for the volume.
|
||||
ID string
|
||||
// Human-readable display name for the volume.
|
||||
Name string
|
||||
// Current status of the volume.
|
||||
Status string
|
||||
// Volume size in GB
|
||||
Size int
|
||||
}
|
||||
|
||||
// CreateVolume creates a volume of given size
|
||||
func (os *OpenStack) CreateVolume(name string, size int, vtype, availability string, tags *map[string]string) (string, string, error) {
|
||||
opts := &volumes.CreateOpts{
|
||||
Name: name,
|
||||
Size: size,
|
||||
VolumeType: vtype,
|
||||
AvailabilityZone: availability,
|
||||
}
|
||||
if tags != nil {
|
||||
opts.Metadata = *tags
|
||||
}
|
||||
|
||||
vol, err := volumes.Create(os.blockstorage, opts).Extract()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return vol.ID, vol.AvailabilityZone, nil
|
||||
}
|
||||
|
||||
// DeleteVolume delete a volume
|
||||
func (os *OpenStack) DeleteVolume(volumeID string) error {
|
||||
used, err := os.diskIsUsed(volumeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if used {
|
||||
return fmt.Errorf("Cannot delete the volume %q, it's still attached to a node", volumeID)
|
||||
}
|
||||
|
||||
err = volumes.Delete(os.blockstorage, volumeID).ExtractErr()
|
||||
return err
|
||||
}
|
||||
|
||||
// GetVolume retrieves Volume by its ID.
|
||||
func (os *OpenStack) GetVolume(volumeID string) (Volume, error) {
|
||||
|
||||
vol, err := volumes.Get(os.blockstorage, volumeID).Extract()
|
||||
if err != nil {
|
||||
return Volume{}, err
|
||||
}
|
||||
|
||||
volume := Volume{
|
||||
ID: vol.ID,
|
||||
Name: vol.Name,
|
||||
Status: vol.Status,
|
||||
}
|
||||
|
||||
if len(vol.Attachments) > 0 {
|
||||
volume.AttachedServerId = vol.Attachments[0].ServerID
|
||||
volume.AttachedDevice = vol.Attachments[0].Device
|
||||
}
|
||||
|
||||
return volume, nil
|
||||
}
|
||||
|
||||
// AttachVolume attaches given cinder volume to the compute
|
||||
func (os *OpenStack) AttachVolume(instanceID, volumeID string) (string, error) {
|
||||
volume, err := os.GetVolume(volumeID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if volume.AttachedServerId != "" {
|
||||
if instanceID == volume.AttachedServerId {
|
||||
glog.V(4).Infof("Disk %s is already attached to instance %s", volumeID, instanceID)
|
||||
return volume.ID, nil
|
||||
}
|
||||
return "", fmt.Errorf("disk %s is attached to a different instance (%s)", volumeID, volume.AttachedServerId)
|
||||
}
|
||||
|
||||
_, err = volumeattach.Create(os.compute, instanceID, &volumeattach.CreateOpts{
|
||||
VolumeID: volume.ID,
|
||||
}).Extract()
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to attach %s volume to %s compute: %v", volumeID, instanceID, err)
|
||||
}
|
||||
glog.V(2).Infof("Successfully attached %s volume to %s compute", volumeID, instanceID)
|
||||
return volume.ID, nil
|
||||
}
|
||||
|
||||
// WaitDiskAttached waits for attched
|
||||
func (os *OpenStack) WaitDiskAttached(instanceID string, volumeID string) error {
|
||||
backoff := wait.Backoff{
|
||||
Duration: diskAttachInitDelay,
|
||||
Factor: diskAttachFactor,
|
||||
Steps: diskAttachSteps,
|
||||
}
|
||||
|
||||
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||
attached, err := os.diskIsAttached(instanceID, volumeID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return attached, nil
|
||||
})
|
||||
|
||||
if err == wait.ErrWaitTimeout {
|
||||
err = fmt.Errorf("Volume %q failed to be attached within the alloted time", volumeID)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DetachVolume detaches given cinder volume from the compute
|
||||
func (os *OpenStack) DetachVolume(instanceID, volumeID string) error {
|
||||
volume, err := os.GetVolume(volumeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if volume.Status == VolumeAvailableStatus {
|
||||
glog.V(2).Infof("volume: %s has been detached from compute: %s ", volume.ID, instanceID)
|
||||
return nil
|
||||
}
|
||||
|
||||
if volume.Status != VolumeInUseStatus {
|
||||
return fmt.Errorf("can not detach volume %s, its status is %s", volume.Name, volume.Status)
|
||||
}
|
||||
|
||||
if volume.AttachedServerId != instanceID {
|
||||
return fmt.Errorf("disk: %s has no attachments or is not attached to compute: %s", volume.Name, instanceID)
|
||||
} else {
|
||||
err = volumeattach.Delete(os.compute, instanceID, volume.ID).ExtractErr()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete volume %s from compute %s attached %v", volume.ID, instanceID, err)
|
||||
}
|
||||
glog.V(2).Infof("Successfully detached volume: %s from compute: %s", volume.ID, instanceID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitDiskDetached waits for detached
|
||||
func (os *OpenStack) WaitDiskDetached(instanceID string, volumeID string) error {
|
||||
backoff := wait.Backoff{
|
||||
Duration: diskDetachInitDelay,
|
||||
Factor: diskDetachFactor,
|
||||
Steps: diskDetachSteps,
|
||||
}
|
||||
|
||||
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||
attached, err := os.diskIsAttached(instanceID, volumeID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !attached, nil
|
||||
})
|
||||
|
||||
if err == wait.ErrWaitTimeout {
|
||||
err = fmt.Errorf("Volume %q failed to detach within the alloted time", volumeID)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetAttachmentDiskPath gets device path of attached volume to the compute
|
||||
func (os *OpenStack) GetAttachmentDiskPath(instanceID, volumeID string) (string, error) {
|
||||
volume, err := os.GetVolume(volumeID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if volume.Status != VolumeInUseStatus {
|
||||
return "", fmt.Errorf("can not get device path of volume %s, its status is %s ", volume.Name, volume.Status)
|
||||
}
|
||||
if volume.AttachedServerId != "" {
|
||||
if instanceID == volume.AttachedServerId {
|
||||
return volume.AttachedDevice, nil
|
||||
} else {
|
||||
return "", fmt.Errorf("disk %q is attached to a different compute: %q, should be detached before proceeding", volumeID, volume.AttachedServerId)
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("volume %s has no ServerId", volumeID)
|
||||
}
|
||||
|
||||
// diskIsAttached queries if a volume is attached to a compute instance
|
||||
func (os *OpenStack) diskIsAttached(instanceID, volumeID string) (bool, error) {
|
||||
volume, err := os.GetVolume(volumeID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return instanceID == volume.AttachedServerId, nil
|
||||
}
|
||||
|
||||
// diskIsUsed returns true a disk is attached to any node.
|
||||
func (os *OpenStack) diskIsUsed(volumeID string) (bool, error) {
|
||||
volume, err := os.GetVolume(volumeID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return volume.AttachedServerId != "", nil
|
||||
}
|
96
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/controllerserver-default.go
generated
vendored
Normal file
96
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/controllerserver-default.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type DefaultControllerServer struct {
|
||||
Driver *CSIDriver
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) ControllerPublishVolume(ctx context.Context, req *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) ControllerUnpublishVolume(ctx context.Context, req *csi.ControllerUnpublishVolumeRequest) (*csi.ControllerUnpublishVolumeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) ValidateVolumeCapabilities(ctx context.Context, req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
|
||||
glog.V(5).Infof("Using default ValidateVolumeCapabilities")
|
||||
|
||||
for _, c := range req.GetVolumeCapabilities() {
|
||||
found := false
|
||||
for _, c1 := range cs.Driver.vc {
|
||||
if c1.GetMode() == c.GetAccessMode().GetMode() {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{
|
||||
Supported: false,
|
||||
Message: "Driver doesnot support mode:" + c.GetAccessMode().GetMode().String(),
|
||||
}, status.Error(codes.InvalidArgument, "Driver doesnot support mode:"+c.GetAccessMode().GetMode().String())
|
||||
}
|
||||
// TODO: Ignoring mount & block tyeps for now.
|
||||
}
|
||||
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{
|
||||
Supported: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) ListVolumes(ctx context.Context, req *csi.ListVolumesRequest) (*csi.ListVolumesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) GetCapacity(ctx context.Context, req *csi.GetCapacityRequest) (*csi.GetCapacityResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (cs *DefaultControllerServer) ControllerProbe(ctx context.Context, req *csi.ControllerProbeRequest) (*csi.ControllerProbeResponse, error) {
|
||||
glog.V(5).Infof("Using default ControllerProbe")
|
||||
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(req.Version, csi.ControllerServiceCapability_RPC_UNKNOWN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &csi.ControllerProbeResponse{}, nil
|
||||
}
|
||||
|
||||
// ControllerGetCapabilities implements the default GRPC callout.
|
||||
// Default supports all capabilities
|
||||
func (cs *DefaultControllerServer) ControllerGetCapabilities(ctx context.Context, req *csi.ControllerGetCapabilitiesRequest) (*csi.ControllerGetCapabilitiesResponse, error) {
|
||||
glog.V(5).Infof("Using default ControllerGetCapabilities")
|
||||
|
||||
return &csi.ControllerGetCapabilitiesResponse{
|
||||
Capabilities: cs.Driver.cap,
|
||||
}, nil
|
||||
}
|
137
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/driver.go
generated
vendored
Normal file
137
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/driver.go
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"github.com/golang/glog"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
type CSIDriver struct {
|
||||
name string
|
||||
nodeID string
|
||||
version *csi.Version
|
||||
supVers []*csi.Version
|
||||
cap []*csi.ControllerServiceCapability
|
||||
vc []*csi.VolumeCapability_AccessMode
|
||||
}
|
||||
|
||||
// Creates a NewCSIDriver object. Assumes vendor version is equal to driver version &
|
||||
// does not support optional driver plugin info manifest field. Refer to CSI spec for more details.
|
||||
func NewCSIDriver(name string, v *csi.Version, supVers []*csi.Version, nodeID string) *CSIDriver {
|
||||
if name == "" {
|
||||
glog.Errorf("Driver name missing")
|
||||
return nil
|
||||
}
|
||||
|
||||
if nodeID == "" {
|
||||
glog.Errorf("NodeID missing")
|
||||
return nil
|
||||
}
|
||||
|
||||
if v == nil {
|
||||
glog.Errorf("Version argument missing")
|
||||
return nil
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, sv := range supVers {
|
||||
if sv.GetMajor() == v.GetMajor() && sv.GetMinor() == v.GetMinor() && sv.GetPatch() == v.GetPatch() {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
supVers = append(supVers, v)
|
||||
}
|
||||
|
||||
driver := CSIDriver{
|
||||
name: name,
|
||||
version: v,
|
||||
supVers: supVers,
|
||||
nodeID: nodeID,
|
||||
}
|
||||
|
||||
return &driver
|
||||
}
|
||||
|
||||
func (d *CSIDriver) CheckVersion(v *csi.Version) error {
|
||||
if v == nil {
|
||||
return status.Error(codes.InvalidArgument, "Version missing")
|
||||
}
|
||||
|
||||
// Assumes always backward compatible
|
||||
for _, sv := range d.supVers {
|
||||
if v.Major == sv.Major && v.Minor <= sv.Minor {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return status.Error(codes.InvalidArgument, "Unsupported version: "+GetVersionString(v))
|
||||
}
|
||||
|
||||
func (d *CSIDriver) ValidateControllerServiceRequest(v *csi.Version, c csi.ControllerServiceCapability_RPC_Type) error {
|
||||
if v == nil {
|
||||
return status.Error(codes.InvalidArgument, "Version not specified")
|
||||
}
|
||||
|
||||
if err := d.CheckVersion(v); err != nil {
|
||||
return status.Error(codes.InvalidArgument, "Unsupported version")
|
||||
}
|
||||
|
||||
if c == csi.ControllerServiceCapability_RPC_UNKNOWN {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, cap := range d.cap {
|
||||
if c == cap.GetRpc().GetType() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return status.Error(codes.InvalidArgument, "Unsupported version: "+GetVersionString(v))
|
||||
}
|
||||
|
||||
func (d *CSIDriver) AddControllerServiceCapabilities(cl []csi.ControllerServiceCapability_RPC_Type) {
|
||||
var csc []*csi.ControllerServiceCapability
|
||||
|
||||
for _, c := range cl {
|
||||
glog.Infof("Enabling controller service capability: %v", c.String())
|
||||
csc = append(csc, NewControllerServiceCapability(c))
|
||||
}
|
||||
|
||||
d.cap = csc
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *CSIDriver) AddVolumeCapabilityAccessModes(vc []csi.VolumeCapability_AccessMode_Mode) []*csi.VolumeCapability_AccessMode {
|
||||
var vca []*csi.VolumeCapability_AccessMode
|
||||
for _, c := range vc {
|
||||
glog.Infof("Enabling volume access mode: %v", c.String())
|
||||
vca = append(vca, NewVolumeCapabilityAccessMode(c))
|
||||
}
|
||||
d.vc = vca
|
||||
return vca
|
||||
}
|
||||
|
||||
func (d *CSIDriver) GetVolumeCapabilityAccessModes() []*csi.VolumeCapability_AccessMode {
|
||||
return d.vc
|
||||
}
|
181
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/driver_test.go
generated
vendored
Normal file
181
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/driver_test.go
generated
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
fakeDriverName = "fake"
|
||||
fakeNodeID = "fakeNodeID"
|
||||
)
|
||||
|
||||
var (
|
||||
fakeVersion = csi.Version{Major: 5, Minor: 2, Patch: 0}
|
||||
fakeVersionsSupported = []*csi.Version{
|
||||
&csi.Version{
|
||||
Major: 4, Minor: 0, Patch: 0,
|
||||
},
|
||||
&csi.Version{
|
||||
Major: 4, Minor: 1, Patch: 0,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func NewFakeDriver() *CSIDriver {
|
||||
fakeVersion = csi.Version{Major: 5, Minor: 2, Patch: 0}
|
||||
fakeVersionsSupported = []*csi.Version{
|
||||
&csi.Version{
|
||||
Major: 4, Minor: 0, Patch: 0,
|
||||
},
|
||||
&csi.Version{
|
||||
Major: 4, Minor: 1, Patch: 0,
|
||||
},
|
||||
}
|
||||
|
||||
driver := NewCSIDriver(fakeDriverName, &fakeVersion, fakeVersionsSupported, fakeNodeID)
|
||||
|
||||
return driver
|
||||
}
|
||||
|
||||
func TestNewFakeDriver(t *testing.T) {
|
||||
// Test New fake driver with invalid arguments.
|
||||
d := NewCSIDriver("", &fakeVersion, fakeVersionsSupported, fakeNodeID)
|
||||
assert.Nil(t, d)
|
||||
}
|
||||
|
||||
func TestCheckVersion(t *testing.T) {
|
||||
|
||||
driver := NewFakeDriver()
|
||||
|
||||
// Exact version
|
||||
v := csi.Version{
|
||||
Major: 5,
|
||||
Minor: 1,
|
||||
Patch: 0,
|
||||
}
|
||||
err := driver.CheckVersion(&v)
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Supported version
|
||||
v = csi.Version{
|
||||
Major: 4,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
}
|
||||
err = driver.CheckVersion(&v)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Unsupported version
|
||||
v = csi.Version{
|
||||
Major: 6,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
}
|
||||
err = driver.CheckVersion(&v)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Supported minor version
|
||||
v = csi.Version{
|
||||
Major: 5,
|
||||
Minor: 1,
|
||||
Patch: 0,
|
||||
}
|
||||
err = driver.CheckVersion(&v)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Unsupported minor version
|
||||
v = csi.Version{
|
||||
Major: 5,
|
||||
Minor: 3,
|
||||
Patch: 0,
|
||||
}
|
||||
err = driver.CheckVersion(&v)
|
||||
s, ok = status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
}
|
||||
|
||||
func TestGetVolumeCapabilityAccessModes(t *testing.T) {
|
||||
|
||||
d := NewFakeDriver()
|
||||
|
||||
// Test no volume access modes.
|
||||
// REVISIT: Do we need to support any default access modes.
|
||||
c := d.GetVolumeCapabilityAccessModes()
|
||||
assert.Zero(t, len(c))
|
||||
|
||||
// Test driver with access modes.
|
||||
d.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER})
|
||||
modes := d.GetVolumeCapabilityAccessModes()
|
||||
assert.Equal(t, 1, len(modes))
|
||||
assert.Equal(t, modes[0].GetMode(), csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER)
|
||||
}
|
||||
|
||||
func TestValidateControllerServiceRequest(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
v := csi.Version{
|
||||
Major: 5,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
}
|
||||
|
||||
// Valid requests which require no capabilities
|
||||
err := d.ValidateControllerServiceRequest(&v, csi.ControllerServiceCapability_RPC_UNKNOWN)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service publish/unpublish not supported
|
||||
err = d.ValidateControllerServiceRequest(&v, csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Add controller service publish & unpublish request
|
||||
d.AddControllerServiceCapabilities(
|
||||
[]csi.ControllerServiceCapability_RPC_Type{
|
||||
csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
|
||||
csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
|
||||
csi.ControllerServiceCapability_RPC_GET_CAPACITY,
|
||||
csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
|
||||
})
|
||||
|
||||
// Test controller service publish/unpublish is supported
|
||||
err = d.ValidateControllerServiceRequest(&v, csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service create/delete is supported
|
||||
err = d.ValidateControllerServiceRequest(&v, csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service list volumes is supported
|
||||
err = d.ValidateControllerServiceRequest(&v, csi.ControllerServiceCapability_RPC_LIST_VOLUMES)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service get capacity is supported
|
||||
err = d.ValidateControllerServiceRequest(&v, csi.ControllerServiceCapability_RPC_GET_CAPACITY)
|
||||
assert.NoError(t, err)
|
||||
|
||||
}
|
58
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/identityserver-default.go
generated
vendored
Normal file
58
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/identityserver-default.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type DefaultIdentityServer struct {
|
||||
Driver *CSIDriver
|
||||
}
|
||||
|
||||
//GetSupportedVersions(context.Context, *GetSupportedVersionsRequest) (*GetSupportedVersionsResponse, error)
|
||||
//GetPluginInfo(context.Context, *GetPluginInfoRequest) (*GetPluginInfoResponse, error)
|
||||
func (ids *DefaultIdentityServer) GetSupportedVersions(ctx context.Context, req *csi.GetSupportedVersionsRequest) (*csi.GetSupportedVersionsResponse, error) {
|
||||
glog.V(5).Infof("Using default GetSupportedVersions")
|
||||
return &csi.GetSupportedVersionsResponse{
|
||||
SupportedVersions: ids.Driver.supVers,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ids *DefaultIdentityServer) GetPluginInfo(ctx context.Context, req *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) {
|
||||
glog.V(5).Infof("Using default GetPluginInnfo")
|
||||
|
||||
if ids.Driver.name == "" {
|
||||
return nil, status.Error(codes.Unavailable, "Driver name not configured")
|
||||
}
|
||||
|
||||
err := ids.Driver.CheckVersion(req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
version := GetVersionString(ids.Driver.version)
|
||||
|
||||
return &csi.GetPluginInfoResponse{
|
||||
Name: ids.Driver.name,
|
||||
VendorVersion: version,
|
||||
}, nil
|
||||
}
|
68
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/identityserver-default_test.go
generated
vendored
Normal file
68
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/identityserver-default_test.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func TestGetSupportedVersions(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ids := NewDefaultIdentityServer(d)
|
||||
|
||||
req := csi.GetSupportedVersionsRequest{}
|
||||
|
||||
// Test Get supported versions are valid.
|
||||
resp, err := ids.GetSupportedVersions(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
|
||||
for _, fv := range fakeVersionsSupported {
|
||||
found := false
|
||||
for _, rv := range resp.GetSupportedVersions() {
|
||||
if fv.GetMajor() == rv.GetMajor() && fv.GetMinor() == rv.GetMinor() && fv.GetPatch() == rv.GetPatch() {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
assert.True(t, found)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPluginInfo(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ids := NewDefaultIdentityServer(d)
|
||||
|
||||
// Test invalid request
|
||||
req := csi.GetPluginInfoRequest{}
|
||||
resp, err := ids.GetPluginInfo(context.Background(), &req)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Test valid request
|
||||
req.Version = &fakeVersion
|
||||
resp, err = ids.GetPluginInfo(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, resp.GetName(), fakeDriverName)
|
||||
}
|
80
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/nodeserver-default.go
generated
vendored
Normal file
80
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/nodeserver-default.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type DefaultNodeServer struct {
|
||||
Driver *CSIDriver
|
||||
}
|
||||
|
||||
func (ns *DefaultNodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||
err := ns.Driver.CheckVersion(req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (ns *DefaultNodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
||||
err := ns.Driver.CheckVersion(req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (ns *DefaultNodeServer) GetNodeID(ctx context.Context, req *csi.GetNodeIDRequest) (*csi.GetNodeIDResponse, error) {
|
||||
glog.V(5).Infof("Using default GetNodeID")
|
||||
|
||||
err := ns.Driver.CheckVersion(req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &csi.GetNodeIDResponse{
|
||||
NodeId: ns.Driver.nodeID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ns *DefaultNodeServer) NodeProbe(ctx context.Context, req *csi.NodeProbeRequest) (*csi.NodeProbeResponse, error) {
|
||||
glog.V(5).Infof("Using default NodeProbe")
|
||||
|
||||
err := ns.Driver.CheckVersion(req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &csi.NodeProbeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *DefaultNodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) {
|
||||
glog.V(5).Infof("Using default NodeGetCapabilities")
|
||||
|
||||
err := ns.Driver.CheckVersion(req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &csi.NodeGetCapabilitiesResponse{}, nil
|
||||
}
|
122
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/nodeserver-default_test.go
generated
vendored
Normal file
122
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/nodeserver-default_test.go
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func TestGetNodeID(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test invalid request
|
||||
req := csi.GetNodeIDRequest{}
|
||||
_, err := ns.GetNodeID(context.Background(), &req)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Test valid request
|
||||
req.Version = &fakeVersion
|
||||
resp, err := ns.GetNodeID(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, resp.GetNodeId(), fakeNodeID)
|
||||
}
|
||||
|
||||
func TestNodeGetCapabilities(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test invalid request
|
||||
req := csi.NodeGetCapabilitiesRequest{}
|
||||
_, err := ns.NodeGetCapabilities(context.Background(), &req)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Test valid request
|
||||
req.Version = &fakeVersion
|
||||
_, err = ns.NodeGetCapabilities(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestNodeProbe(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test invalid request
|
||||
req := csi.NodeProbeRequest{}
|
||||
_, err := ns.NodeProbe(context.Background(), &req)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Test valid request
|
||||
req.Version = &fakeVersion
|
||||
_, err = ns.NodeProbe(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestNodePublishVolume(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test invalid request
|
||||
req := csi.NodePublishVolumeRequest{}
|
||||
_, err := ns.NodePublishVolume(context.Background(), &req)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Test valid node publish request
|
||||
req.Version = &fakeVersion
|
||||
_, err = ns.NodePublishVolume(context.Background(), &req)
|
||||
s, ok = status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.Unimplemented)
|
||||
}
|
||||
|
||||
func TestNodeUnpublishVolume(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test invalid request
|
||||
req := csi.NodeUnpublishVolumeRequest{}
|
||||
_, err := ns.NodeUnpublishVolume(context.Background(), &req)
|
||||
s, ok := status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.InvalidArgument)
|
||||
|
||||
// Test valid node publish request
|
||||
req.Version = &fakeVersion
|
||||
_, err = ns.NodeUnpublishVolume(context.Background(), &req)
|
||||
s, ok = status.FromError(err)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, s.Code(), codes.Unimplemented)
|
||||
}
|
112
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/server.go
generated
vendored
Normal file
112
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/server.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
// Defines Non blocking GRPC server interfaces
|
||||
type NonBlockingGRPCServer interface {
|
||||
// Start services at the endpoint
|
||||
Start(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer)
|
||||
// Waits for the service to stop
|
||||
Wait()
|
||||
// Stops the service gracefully
|
||||
Stop()
|
||||
// Stops the service forcefully
|
||||
ForceStop()
|
||||
}
|
||||
|
||||
func NewNonBlockingGRPCServer() NonBlockingGRPCServer {
|
||||
return &nonBlockingGRPCServer{}
|
||||
}
|
||||
|
||||
// NonBlocking server
|
||||
type nonBlockingGRPCServer struct {
|
||||
wg sync.WaitGroup
|
||||
server *grpc.Server
|
||||
}
|
||||
|
||||
func (s *nonBlockingGRPCServer) Start(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) {
|
||||
|
||||
s.wg.Add(1)
|
||||
|
||||
go s.serve(endpoint, ids, cs, ns)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *nonBlockingGRPCServer) Wait() {
|
||||
s.wg.Wait()
|
||||
}
|
||||
|
||||
func (s *nonBlockingGRPCServer) Stop() {
|
||||
s.server.GracefulStop()
|
||||
}
|
||||
|
||||
func (s *nonBlockingGRPCServer) ForceStop() {
|
||||
s.server.Stop()
|
||||
}
|
||||
|
||||
func (s *nonBlockingGRPCServer) serve(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) {
|
||||
|
||||
proto, addr, err := ParseEndpoint(endpoint)
|
||||
if err != nil {
|
||||
glog.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if proto == "unix" {
|
||||
addr = "/" + addr
|
||||
if err := os.Remove(addr); err != nil && !os.IsNotExist(err) {
|
||||
glog.Fatalf("Failed to remove %s, error: %s", addr, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
listener, err := net.Listen(proto, addr)
|
||||
if err != nil {
|
||||
glog.Fatalf("Failed to listen: %v", err)
|
||||
}
|
||||
|
||||
opts := []grpc.ServerOption{
|
||||
grpc.UnaryInterceptor(logGRPC),
|
||||
}
|
||||
server := grpc.NewServer(opts...)
|
||||
s.server = server
|
||||
|
||||
if ids != nil {
|
||||
csi.RegisterIdentityServer(server, ids)
|
||||
}
|
||||
if cs != nil {
|
||||
csi.RegisterControllerServer(server, cs)
|
||||
}
|
||||
if ns != nil {
|
||||
csi.RegisterNodeServer(server, ns)
|
||||
}
|
||||
|
||||
glog.Infof("Listening for connections on address: %#v", listener.Addr())
|
||||
|
||||
server.Serve(listener)
|
||||
|
||||
}
|
127
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/utils.go
generated
vendored
Normal file
127
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/utils.go
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func ParseEndpoint(ep string) (string, string, error) {
|
||||
if strings.HasPrefix(strings.ToLower(ep), "unix://") || strings.HasPrefix(strings.ToLower(ep), "tcp://") {
|
||||
s := strings.SplitN(ep, "://", 2)
|
||||
if s[1] != "" {
|
||||
return s[0], s[1], nil
|
||||
}
|
||||
}
|
||||
return "", "", fmt.Errorf("Invalid endpoint: %v", ep)
|
||||
}
|
||||
|
||||
func GetVersionString(v *csi.Version) string {
|
||||
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||
}
|
||||
|
||||
func GetVersionFromString(v string) (*csi.Version, error) {
|
||||
var major, minor, patch uint32
|
||||
|
||||
n, err := fmt.Sscanf(v, "%d.%d.%d", &major, &minor, &patch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n != 3 {
|
||||
return nil, fmt.Errorf("Invalid format. Specify version in x.y.z format")
|
||||
}
|
||||
|
||||
return &csi.Version{
|
||||
Major: major,
|
||||
Minor: minor,
|
||||
Patch: patch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewVolumeCapabilityAccessMode(mode csi.VolumeCapability_AccessMode_Mode) *csi.VolumeCapability_AccessMode {
|
||||
return &csi.VolumeCapability_AccessMode{Mode: mode}
|
||||
}
|
||||
|
||||
func NewDefaultNodeServer(d *CSIDriver) *DefaultNodeServer {
|
||||
return &DefaultNodeServer{
|
||||
Driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDefaultIdentityServer(d *CSIDriver) *DefaultIdentityServer {
|
||||
return &DefaultIdentityServer{
|
||||
Driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDefaultControllerServer(d *CSIDriver) *DefaultControllerServer {
|
||||
return &DefaultControllerServer{
|
||||
Driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func NewControllerServiceCapability(cap csi.ControllerServiceCapability_RPC_Type) *csi.ControllerServiceCapability {
|
||||
return &csi.ControllerServiceCapability{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: cap,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func RunNodePublishServer(endpoint string, d *CSIDriver, ns csi.NodeServer) {
|
||||
ids := NewDefaultIdentityServer(d)
|
||||
|
||||
s := NewNonBlockingGRPCServer()
|
||||
s.Start(endpoint, ids, nil, ns)
|
||||
s.Wait()
|
||||
}
|
||||
|
||||
func RunControllerPublishServer(endpoint string, d *CSIDriver, cs csi.ControllerServer) {
|
||||
ids := NewDefaultIdentityServer(d)
|
||||
|
||||
s := NewNonBlockingGRPCServer()
|
||||
s.Start(endpoint, ids, cs, nil)
|
||||
s.Wait()
|
||||
}
|
||||
|
||||
func RunControllerandNodePublishServer(endpoint string, d *CSIDriver, cs csi.ControllerServer, ns csi.NodeServer) {
|
||||
ids := NewDefaultIdentityServer(d)
|
||||
|
||||
s := NewNonBlockingGRPCServer()
|
||||
s.Start(endpoint, ids, cs, ns)
|
||||
s.Wait()
|
||||
}
|
||||
|
||||
func logGRPC(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
glog.V(3).Infof("GRPC call: %s", info.FullMethod)
|
||||
glog.V(5).Infof("GRPC request: %+v", req)
|
||||
resp, err := handler(ctx, req)
|
||||
if err != nil {
|
||||
glog.Errorf("GRPC error: %v", err)
|
||||
} else {
|
||||
glog.V(5).Infof("GRPC response: %+v", resp)
|
||||
}
|
||||
return resp, err
|
||||
}
|
106
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/utils_test.go
generated
vendored
Normal file
106
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/utils_test.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csicommon
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetVersionFromString(t *testing.T) {
|
||||
|
||||
//Invalid version
|
||||
_, err := GetVersionFromString("")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
v, err := GetVersionFromString("1.2.3")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, v.GetMajor(), uint32(1))
|
||||
assert.Equal(t, v.GetMinor(), uint32(2))
|
||||
assert.Equal(t, v.GetPatch(), uint32(3))
|
||||
|
||||
// Invalid version
|
||||
_, err = GetVersionFromString("1.2")
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestGetVersionString(t *testing.T) {
|
||||
|
||||
v := &csi.Version{
|
||||
Major: 1,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
}
|
||||
//Invalid version
|
||||
vStr := GetVersionString(v)
|
||||
assert.Equal(t, vStr, "1.0.0")
|
||||
}
|
||||
|
||||
func TestParseEndpoint(t *testing.T) {
|
||||
|
||||
//Valid unix domain socket endpoint
|
||||
sockType, addr, err := ParseEndpoint("unix://fake.sock")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sockType, "unix")
|
||||
assert.Equal(t, addr, "fake.sock")
|
||||
|
||||
sockType, addr, err = ParseEndpoint("unix:///fakedir/fakedir/fake.sock")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sockType, "unix")
|
||||
assert.Equal(t, addr, "/fakedir/fakedir/fake.sock")
|
||||
|
||||
//Valid unix domain socket with uppercase
|
||||
sockType, addr, err = ParseEndpoint("UNIX://fake.sock")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sockType, "UNIX")
|
||||
assert.Equal(t, addr, "fake.sock")
|
||||
|
||||
//Valid TCP endpoint with ip
|
||||
sockType, addr, err = ParseEndpoint("tcp://127.0.0.1:80")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sockType, "tcp")
|
||||
assert.Equal(t, addr, "127.0.0.1:80")
|
||||
|
||||
//Valid TCP endpoint with uppercase
|
||||
sockType, addr, err = ParseEndpoint("TCP://127.0.0.1:80")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sockType, "TCP")
|
||||
assert.Equal(t, addr, "127.0.0.1:80")
|
||||
|
||||
//Valid TCP endpoint with hostname
|
||||
sockType, addr, err = ParseEndpoint("tcp://fakehost:80")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sockType, "tcp")
|
||||
assert.Equal(t, addr, "fakehost:80")
|
||||
|
||||
_, _, err = ParseEndpoint("unix:/fake.sock/")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
_, _, err = ParseEndpoint("fake.sock")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
_, _, err = ParseEndpoint("unix://")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
_, _, err = ParseEndpoint("://")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
_, _, err = ParseEndpoint("")
|
||||
assert.NotNil(t, err)
|
||||
}
|
42
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/README.md
generated
vendored
Normal file
42
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/README.md
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
# CSI to Flexvolume adapter
|
||||
|
||||
## Usage:
|
||||
|
||||
### Start Flexvolume adapter for simple nfs flexvolume driver
|
||||
```
|
||||
$ sudo ../_output/flexadapter --endpoint tcp://127.0.0.1:10000 --drivername simplenfs --driverpath ./examples/simple-nfs-flexdriver/nfs --nodeid CSINode
|
||||
```
|
||||
|
||||
### Test using csc
|
||||
Get ```csc``` tool from https://github.com/chakri-nelluri/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugininfo --endpoint tcp://127.0.0.1:10000
|
||||
"simplenfs" "0.1.0"
|
||||
```
|
||||
|
||||
### Get supported versions
|
||||
```
|
||||
$ csc identity supportedversions --endpoint tcp://127.0.0.1:10000
|
||||
0.1.0
|
||||
```
|
||||
|
||||
#### NodePublish a volume
|
||||
```
|
||||
$ csc node publishvolume --endpoint tcp://127.0.0.1:10000 --target-path /mnt/nfs --attrib server=a.b.c.d --attrib share=nfs_share nfstestvol
|
||||
nfstestvol
|
||||
```
|
||||
|
||||
#### NodeUnpublish a volume
|
||||
```
|
||||
$ csc node unpublishvolume --endpoint tcp://127.0.0.1:10000 --target-path /mnt/nfs nfstestvol
|
||||
nfstestvol
|
||||
```
|
||||
|
||||
#### Get NodeID
|
||||
```
|
||||
$ csc node getid --endpoint tcp://127.0.0.1:10000
|
||||
CSINode
|
||||
```
|
||||
|
95
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/controllerserver.go
generated
vendored
Normal file
95
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/controllerserver.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flexadapter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
const (
|
||||
deviceID = "deviceID"
|
||||
)
|
||||
|
||||
type controllerServer struct {
|
||||
*csicommon.DefaultControllerServer
|
||||
}
|
||||
|
||||
func GetVersionString(ver *csi.Version) string {
|
||||
return fmt.Sprintf("%d.%d.%d", ver.Major, ver.Minor, ver.Patch)
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ControllerPublishVolume(ctx context.Context, req *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) {
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(req.Version, csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
call := GetFlexAdapter().flexDriver.NewDriverCall(attachCmd)
|
||||
|
||||
fsType := req.GetVolumeCapability().GetMount().FsType
|
||||
call.AppendSpec(req.GetVolumeId(), fsType, req.GetReadonly(), req.GetVolumeAttributes())
|
||||
call.Append(req.GetNodeId())
|
||||
|
||||
callStatus, err := call.Run()
|
||||
if isCmdNotSupportedErr(err) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
} else if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
pvInfo := map[string]string{}
|
||||
|
||||
pvInfo[deviceID] = callStatus.DevicePath
|
||||
|
||||
return &csi.ControllerPublishVolumeResponse{
|
||||
PublishVolumeInfo: pvInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ControllerUnpublishVolume(ctx context.Context, req *csi.ControllerUnpublishVolumeRequest) (*csi.ControllerUnpublishVolumeResponse, error) {
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(req.Version, csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
call := GetFlexAdapter().flexDriver.NewDriverCall(detachCmd)
|
||||
call.Append(req.GetVolumeId())
|
||||
call.Append(req.GetNodeId())
|
||||
|
||||
_, err := call.Run()
|
||||
if isCmdNotSupportedErr(err) {
|
||||
return nil, status.Error(codes.Unimplemented, "")
|
||||
} else if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.ControllerUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ValidateVolumeCapabilities(ctx context.Context, req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
|
||||
for _, cap := range req.VolumeCapabilities {
|
||||
if cap.GetAccessMode().GetMode() != csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER {
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{Supported: false, Message: ""}, nil
|
||||
}
|
||||
}
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{Supported: true, Message: ""}, nil
|
||||
}
|
239
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/driver-call.go
generated
vendored
Normal file
239
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/driver-call.go
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flexadapter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
// Driver calls
|
||||
initCmd = "init"
|
||||
getVolumeNameCmd = "getvolumename"
|
||||
|
||||
isAttached = "isattached"
|
||||
|
||||
attachCmd = "attach"
|
||||
waitForAttachCmd = "waitforattach"
|
||||
mountDeviceCmd = "mountdevice"
|
||||
|
||||
detachCmd = "detach"
|
||||
waitForDetachCmd = "waitfordetach"
|
||||
unmountDeviceCmd = "unmountdevice"
|
||||
|
||||
mountCmd = "mount"
|
||||
unmountCmd = "unmount"
|
||||
|
||||
// Option keys
|
||||
optionFSType = "kubernetes.io/fsType"
|
||||
optionReadWrite = "kubernetes.io/readwrite"
|
||||
optionKeySecret = "kubernetes.io/secret"
|
||||
optionFSGroup = "kubernetes.io/fsGroup"
|
||||
optionMountsDir = "kubernetes.io/mountsDir"
|
||||
optionPVorVolumeName = "kubernetes.io/pvOrVolumeName"
|
||||
|
||||
optionKeyPodName = "kubernetes.io/pod.name"
|
||||
optionKeyPodNamespace = "kubernetes.io/pod.namespace"
|
||||
optionKeyPodUID = "kubernetes.io/pod.uid"
|
||||
|
||||
optionKeyServiceAccountName = "kubernetes.io/serviceAccount.name"
|
||||
)
|
||||
|
||||
const (
|
||||
// StatusSuccess represents the successful completion of command.
|
||||
StatusSuccess = "Success"
|
||||
// StatusNotSupported represents that the command is not supported.
|
||||
StatusNotSupported = "Not supported"
|
||||
)
|
||||
|
||||
var (
|
||||
TimeoutError = fmt.Errorf("Timeout")
|
||||
)
|
||||
|
||||
// DriverCall implements the basic contract between FlexVolume and its driver.
|
||||
// The caller is responsible for providing the required args.
|
||||
type DriverCall struct {
|
||||
driver *flexVolumeDriver
|
||||
Command string
|
||||
Timeout time.Duration
|
||||
args []string
|
||||
}
|
||||
|
||||
func (d *flexVolumeDriver) NewDriverCall(command string) *DriverCall {
|
||||
return d.NewDriverCallWithTimeout(command, 0)
|
||||
}
|
||||
|
||||
func (d *flexVolumeDriver) NewDriverCallWithTimeout(command string, timeout time.Duration) *DriverCall {
|
||||
return &DriverCall{
|
||||
driver: d,
|
||||
Command: command,
|
||||
Timeout: timeout,
|
||||
args: []string{command},
|
||||
}
|
||||
}
|
||||
|
||||
func (dc *DriverCall) Append(arg string) {
|
||||
dc.args = append(dc.args, arg)
|
||||
}
|
||||
|
||||
func (dc *DriverCall) AppendSpec(volumeID, fsType string, readOnly bool, volumeAttributes map[string]string) error {
|
||||
optionsForDriver := NewOptionsForDriver(volumeID, fsType, readOnly, volumeAttributes)
|
||||
|
||||
jsonBytes, err := json.Marshal(optionsForDriver)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to marshal spec, error: %s", err.Error())
|
||||
}
|
||||
|
||||
dc.Append(string(jsonBytes))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dc *DriverCall) Run() (*DriverStatus, error) {
|
||||
if dc.driver.isUnsupported(dc.Command) {
|
||||
return nil, errors.New(StatusNotSupported)
|
||||
}
|
||||
execPath := dc.driver.getExecutable()
|
||||
|
||||
cmd := exec.Command(execPath, dc.args...)
|
||||
|
||||
timeout := false
|
||||
if dc.Timeout > 0 {
|
||||
timer := time.AfterFunc(dc.Timeout, func() {
|
||||
timeout = true
|
||||
//TODO: cmd.Stop()
|
||||
})
|
||||
defer timer.Stop()
|
||||
}
|
||||
|
||||
output, execErr := cmd.CombinedOutput()
|
||||
if execErr != nil {
|
||||
if timeout {
|
||||
return nil, TimeoutError
|
||||
}
|
||||
_, err := handleCmdResponse(dc.Command, output)
|
||||
if err == nil {
|
||||
glog.Errorf("FlexVolume: driver bug: %s: exec error (%s) but no error in response.", execPath, execErr)
|
||||
return nil, execErr
|
||||
}
|
||||
if isCmdNotSupportedErr(err) {
|
||||
dc.driver.unsupported(dc.Command)
|
||||
} else {
|
||||
glog.Warningf("FlexVolume: driver call failed: executable: %s, args: %s, error: %s, output: %q", execPath, dc.args, execErr.Error(), output)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
status, err := handleCmdResponse(dc.Command, output)
|
||||
if err != nil {
|
||||
if isCmdNotSupportedErr(err) {
|
||||
dc.driver.unsupported(dc.Command)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// OptionsForDriver represents the spec given to the driver.
|
||||
type OptionsForDriver map[string]string
|
||||
|
||||
func NewOptionsForDriver(volumeID, fsType string, readOnly bool, volumeAttributes map[string]string) OptionsForDriver {
|
||||
options := map[string]string{}
|
||||
|
||||
if readOnly {
|
||||
options[optionReadWrite] = "ro"
|
||||
} else {
|
||||
options[optionReadWrite] = "rw"
|
||||
}
|
||||
|
||||
options[optionFSType] = fsType
|
||||
options[optionPVorVolumeName] = volumeID
|
||||
|
||||
for key, value := range volumeAttributes {
|
||||
options[key] = value
|
||||
}
|
||||
|
||||
return OptionsForDriver(options)
|
||||
}
|
||||
|
||||
// DriverStatus represents the return value of the driver callout.
|
||||
type DriverStatus struct {
|
||||
// Status of the callout. One of "Success", "Failure" or "Not supported".
|
||||
Status string `json:"status"`
|
||||
// Reason for success/failure.
|
||||
Message string `json:"message,omitempty"`
|
||||
// Path to the device attached. This field is valid only for attach calls.
|
||||
// ie: /dev/sdx
|
||||
DevicePath string `json:"device,omitempty"`
|
||||
// Cluster wide unique name of the volume.
|
||||
VolumeName string `json:"volumeName,omitempty"`
|
||||
// Represents volume is attached on the node
|
||||
Attached bool `json:"attached,omitempty"`
|
||||
// Returns capabilities of the driver.
|
||||
// By default we assume all the capabilities are supported.
|
||||
// If the plugin does not support a capability, it can return false for that capability.
|
||||
Capabilities *DriverCapabilities `json:",omitempty"`
|
||||
}
|
||||
|
||||
type DriverCapabilities struct {
|
||||
Attach bool `json:"attach"`
|
||||
SELinuxRelabel bool `json:"selinuxRelabel"`
|
||||
}
|
||||
|
||||
func defaultCapabilities() *DriverCapabilities {
|
||||
return &DriverCapabilities{
|
||||
Attach: true,
|
||||
SELinuxRelabel: true,
|
||||
}
|
||||
}
|
||||
|
||||
// isCmdNotSupportedErr checks if the error corresponds to command not supported by
|
||||
// driver.
|
||||
func isCmdNotSupportedErr(err error) bool {
|
||||
if err != nil && err.Error() == StatusNotSupported {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// handleCmdResponse processes the command output and returns the appropriate
|
||||
// error code or message.
|
||||
func handleCmdResponse(cmd string, output []byte) (*DriverStatus, error) {
|
||||
status := DriverStatus{
|
||||
Capabilities: defaultCapabilities(),
|
||||
}
|
||||
if err := json.Unmarshal(output, &status); err != nil {
|
||||
glog.Errorf("Failed to unmarshal output for command: %s, output: %q, error: %s", cmd, string(output), err.Error())
|
||||
return nil, err
|
||||
} else if status.Status == StatusNotSupported {
|
||||
glog.V(5).Infof("%s command is not supported by the driver", cmd)
|
||||
return nil, errors.New(status.Status)
|
||||
} else if status.Status != StatusSuccess {
|
||||
errMsg := fmt.Sprintf("%s command failed, status: %s, reason: %s", cmd, status.Status, status.Message)
|
||||
glog.Errorf(errMsg)
|
||||
return nil, fmt.Errorf("%s", errMsg)
|
||||
}
|
||||
|
||||
return &status, nil
|
||||
}
|
25
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/README.md
generated
vendored
Normal file
25
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/README.md
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# CSI-Flex NFS driver
|
||||
|
||||
# Requirements
|
||||
|
||||
The folllowing feature gates and runtime config have to be enabled to deploy the driver
|
||||
|
||||
```
|
||||
FEATURE_GATES=CSIPersistentVolume=true,MountPropagation=true
|
||||
RUNTIME_CONFIG="storage.k8s.io/v1alpha1=true"
|
||||
```
|
||||
|
||||
Mountprogpation requries support for privileged containers. So, make sure privileged containers are enabled in the cluster.
|
||||
|
||||
## Example local-up-cluster.sh
|
||||
|
||||
```ALLOW_PRIVILEGED=true FEATURE_GATES=CSIPersistentVolume=true,MountPropagation=true RUNTIME_CONFIG="storage.k8s.io/v1alpha1=true" LOG_LEVEL=5 hack/local-up-cluster.sh```
|
||||
|
||||
|
||||
# Deploy in Kubernetes
|
||||
|
||||
```kubectl -f deploy/kubernetes create```
|
||||
|
||||
# Example Nginx application
|
||||
|
||||
``` kubectl -f examples/kubernetes/nginx.yaml create```
|
@ -0,0 +1,107 @@
|
||||
# This YAML file contains all API objects that are necessary to run external
|
||||
# CSI attacher for nfs flex adapter
|
||||
#
|
||||
# In production, this needs to be in separate files, e.g. service account and
|
||||
# role and role binding needs to be created once, while stateful set may
|
||||
# require some tuning.
|
||||
#
|
||||
# In addition, mock CSI driver is hardcoded as the CSI driver.
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: csi-attacher
|
||||
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: external-attacher-runner
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["volumeattachments"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-attacher-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: csi-attacher
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: external-attacher-runner
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: csi-attacher-simplenfs-flexdriver
|
||||
labels:
|
||||
app: csi-attacher-simplenfs-flexdriver
|
||||
spec:
|
||||
selector:
|
||||
app: csi-attacher-simplenfs-flexdriver
|
||||
ports:
|
||||
- name: dummy
|
||||
port: 12345
|
||||
|
||||
---
|
||||
kind: StatefulSet
|
||||
apiVersion: apps/v1beta1
|
||||
metadata:
|
||||
name: csi-attacher-simplenfs-flexdriver
|
||||
spec:
|
||||
serviceName: "csi-attacher"
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: csi-attacher-simplenfs-flexdriver
|
||||
spec:
|
||||
serviceAccount: csi-attacher
|
||||
containers:
|
||||
- name: csi-attacher
|
||||
image: docker.io/k8scsi/csi-attacher
|
||||
args:
|
||||
- "--v=5"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /var/lib/csi/sockets/pluginproxy/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /var/lib/csi/sockets/pluginproxy/
|
||||
|
||||
- name: simplenfs
|
||||
image: docker.io/k8scsi/csi-simplenfs-flexdriver:v0.1
|
||||
args :
|
||||
- "--nodeid=$(NODE_ID)"
|
||||
- "--drivername=csi-simplenfs-flexdriver"
|
||||
- "--endpoint=$(CSI_ENDPOINT)"
|
||||
env:
|
||||
- name: NODE_ID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: CSI_ENDPOINT
|
||||
value: unix://plugin/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /plugin
|
||||
volumes:
|
||||
- name: socket-dir
|
||||
emptyDir:
|
||||
|
34
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/deploy/kubernetes/csi-nodeplugin-rbac.yaml
generated
vendored
Normal file
34
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/deploy/kubernetes/csi-nodeplugin-rbac.yaml
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# This YAML defines all API objects to create RBAC roles for CSI node plugin
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["volumeattachments"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: csi-nodeplugin
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: csi-nodeplugin
|
||||
apiGroup: rbac.authorization.k8s.io
|
@ -0,0 +1,65 @@
|
||||
kind: DaemonSet
|
||||
apiVersion: apps/v1beta2
|
||||
metadata:
|
||||
name: csi-nodeplugin-simplenfs
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: csi-nodeplugin-simplenfs
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: csi-nodeplugin-simplenfs
|
||||
spec:
|
||||
serviceAccount: csi-nodeplugin
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: driver-registrar
|
||||
image: docker.io/k8scsi/driver-registrar
|
||||
args:
|
||||
- "--v=5"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /plugin/csi.sock
|
||||
- name: KUBE_NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
volumeMounts:
|
||||
- name: plugin-dir
|
||||
mountPath: /plugin
|
||||
- name: simplenfs
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
add: ["SYS_ADMIN"]
|
||||
allowPrivilegeEscalation: true
|
||||
image: docker.io/k8scsi/csi-simplenfs-flexdriver:v0.1
|
||||
args :
|
||||
- "--nodeid=$(NODE_ID)"
|
||||
- "--drivername=csi-simplenfs-flexdriver"
|
||||
- "--endpoint=$(CSI_ENDPOINT)"
|
||||
env:
|
||||
- name: NODE_ID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: CSI_ENDPOINT
|
||||
value: unix://plugin/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: plugin-dir
|
||||
mountPath: /plugin
|
||||
- name: pods-mount-dir
|
||||
mountPath: /var/lib/kubelet/pods
|
||||
mountPropagation: "Bidirectional"
|
||||
volumes:
|
||||
- name: plugin-dir
|
||||
hostPath:
|
||||
path: /var/lib/kubelet/plugins/csi-simplenfs-flexdriver
|
||||
type: Directory
|
||||
- name: pods-mount-dir
|
||||
hostPath:
|
||||
path: /var/lib/kubelet/pods
|
||||
type: Directory
|
10
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/dockerfile/Dockerfile
generated
vendored
Normal file
10
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/dockerfile/Dockerfile
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
FROM centos:7.4.1708
|
||||
|
||||
# Copy flexadapter from build _output directory
|
||||
COPY flexadapter /flexadapter
|
||||
# Copy nfs from driver directory
|
||||
COPY nfs /drivers/nfs
|
||||
|
||||
RUN yum -y install nfs-utils && yum -y install epel-release && yum -y install jq && yum clean all
|
||||
|
||||
ENTRYPOINT ["/flexadapter", "--driverpath=/drivers/nfs"]
|
113
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/driver/nfs
generated
vendored
Executable file
113
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/driver/nfs
generated
vendored
Executable file
@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2015 The Kubernetes Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Notes:
|
||||
# - Please install "jq" package before using this driver.
|
||||
usage() {
|
||||
err "Invalid usage. Usage: "
|
||||
err "\t$0 init"
|
||||
err "\t$0 mount <mount dir> <json params>"
|
||||
err "\t$0 unmount <mount dir>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
err() {
|
||||
echo -ne $* 1>&2
|
||||
}
|
||||
|
||||
log() {
|
||||
echo -ne $* >&1
|
||||
}
|
||||
|
||||
ismounted() {
|
||||
MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1`
|
||||
if [ "${MOUNT}" == "${MNTPATH}" ]; then
|
||||
echo "1"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
domount() {
|
||||
MNTPATH=$1
|
||||
|
||||
NFS_SERVER=$(echo $2 | jq -r '.server')
|
||||
SHARE=$(echo $2 | jq -r '.share')
|
||||
|
||||
if [ $(ismounted) -eq 1 ] ; then
|
||||
log '{"status": "Success"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p ${MNTPATH} &> /dev/null
|
||||
|
||||
mount -t nfs ${NFS_SERVER}:/${SHARE} ${MNTPATH} &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
err "{ \"status\": \"Failure\", \"message\": \"Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}\"}"
|
||||
exit 1
|
||||
fi
|
||||
log '{"status": "Success"}'
|
||||
exit 0
|
||||
}
|
||||
|
||||
unmount() {
|
||||
MNTPATH=$1
|
||||
if [ $(ismounted) -eq 0 ] ; then
|
||||
log '{"status": "Success"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
umount ${MNTPATH} &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
err "{ \"status\": \"Failed\", \"message\": \"Failed to unmount volume at ${MNTPATH}\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log '{"status": "Success"}'
|
||||
exit 0
|
||||
}
|
||||
|
||||
op=$1
|
||||
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
err "{ \"status\": \"Failure\", \"message\": \"'jq' binary not found. Please install jq package before using this driver\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$op" = "init" ]; then
|
||||
log '{"status": "Success", "capabilities": {"attach": false}}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
case "$op" in
|
||||
mount)
|
||||
domount $*
|
||||
;;
|
||||
unmount)
|
||||
unmount $*
|
||||
;;
|
||||
*)
|
||||
log '{"status": "Not supported"}'
|
||||
exit 0
|
||||
esac
|
||||
|
||||
exit 1
|
52
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/examples/kubernetes/nginx.yaml
generated
vendored
Normal file
52
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/examples/simplenfs-flexdriver/examples/kubernetes/nginx.yaml
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: data
|
||||
labels:
|
||||
name: data
|
||||
annotations:
|
||||
csi.volume.kubernetes.io/volume-attributes: '{"server": "10.10.10.10", "share": "my_export"}'
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
capacity:
|
||||
storage: 100Gi
|
||||
csi:
|
||||
driver: csi-simplenfs-flexdriver
|
||||
volumeHandle: data-id
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: name
|
||||
operator: In
|
||||
values: ["data"]
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: data
|
||||
spec:
|
||||
containers:
|
||||
- image: maersk/nginx
|
||||
imagePullPolicy: Always
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /var/www
|
||||
name: data
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: data
|
97
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexadapter.go
generated
vendored
Normal file
97
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexadapter.go
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flexadapter
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type flexAdapter struct {
|
||||
driver *csicommon.CSIDriver
|
||||
|
||||
flexDriver *flexVolumeDriver
|
||||
|
||||
ns *nodeServer
|
||||
cs *controllerServer
|
||||
|
||||
cap []*csi.VolumeCapability_AccessMode
|
||||
cscap []*csi.ControllerServiceCapability
|
||||
}
|
||||
|
||||
var (
|
||||
adapter *flexAdapter
|
||||
runOnce sync.Once
|
||||
version = csi.Version{
|
||||
Minor: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func GetSupportedVersions() []*csi.Version {
|
||||
return []*csi.Version{&version}
|
||||
}
|
||||
|
||||
func GetFlexAdapter() *flexAdapter {
|
||||
runOnce.Do(func() {
|
||||
adapter = &flexAdapter{}
|
||||
})
|
||||
return adapter
|
||||
}
|
||||
|
||||
func NewControllerServer(d *csicommon.CSIDriver) *controllerServer {
|
||||
return &controllerServer{
|
||||
DefaultControllerServer: csicommon.NewDefaultControllerServer(d),
|
||||
}
|
||||
}
|
||||
|
||||
func NewNodeServer(d *csicommon.CSIDriver, f *flexVolumeDriver) *nodeServer {
|
||||
return &nodeServer{
|
||||
flexDriver: f,
|
||||
DefaultNodeServer: csicommon.NewDefaultNodeServer(d),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *flexAdapter) Run(driverName, driverPath, nodeID, endpoint string) {
|
||||
var err error
|
||||
|
||||
glog.Infof("Driver: %v version: %v", driverName, GetVersionString(&version))
|
||||
|
||||
// Create flex volume driver
|
||||
adapter.flexDriver, err = NewFlexVolumeDriver(driverName, driverPath)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to initialize flex volume driver, error: %v", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Initialize default library driver
|
||||
adapter.driver = csicommon.NewCSIDriver(driverName, &version, GetSupportedVersions(), nodeID)
|
||||
if adapter.flexDriver.capabilities.Attach {
|
||||
adapter.driver.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME})
|
||||
}
|
||||
adapter.driver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER})
|
||||
|
||||
// Create GRPC servers
|
||||
f.ns = NewNodeServer(adapter.driver, adapter.flexDriver)
|
||||
f.cs = NewControllerServer(adapter.driver)
|
||||
|
||||
csicommon.RunControllerandNodePublishServer(endpoint, adapter.driver, f.cs, f.ns)
|
||||
}
|
73
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexvolumedriver.go
generated
vendored
Normal file
73
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexvolumedriver.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flexadapter
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type flexVolumeDriver struct {
|
||||
sync.Mutex
|
||||
driverName string
|
||||
execPath string
|
||||
unsupportedCommands []string
|
||||
capabilities DriverCapabilities
|
||||
}
|
||||
|
||||
// Returns true iff the given command is known to be unsupported.
|
||||
func (d *flexVolumeDriver) isUnsupported(command string) bool {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
for _, unsupportedCommand := range d.unsupportedCommands {
|
||||
if command == unsupportedCommand {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *flexVolumeDriver) getExecutable() string {
|
||||
return d.execPath
|
||||
}
|
||||
|
||||
// Mark the given commands as unsupported.
|
||||
func (d *flexVolumeDriver) unsupported(commands ...string) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
d.unsupportedCommands = append(d.unsupportedCommands, commands...)
|
||||
}
|
||||
|
||||
func NewFlexVolumeDriver(driverName, driverPath string) (*flexVolumeDriver, error) {
|
||||
|
||||
flexDriver := &flexVolumeDriver{
|
||||
driverName: driverName,
|
||||
execPath: driverPath,
|
||||
}
|
||||
|
||||
adapter.flexDriver = flexDriver
|
||||
|
||||
// Initialize the plugin and probe the capabilities
|
||||
call := flexDriver.NewDriverCall(initCmd)
|
||||
ds, err := call.Run()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
flexDriver.capabilities = *ds.Capabilities
|
||||
|
||||
return flexDriver, nil
|
||||
}
|
113
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/nodeserver.go
generated
vendored
Normal file
113
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/nodeserver.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package flexadapter
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type nodeServer struct {
|
||||
flexDriver *flexVolumeDriver
|
||||
*csicommon.DefaultNodeServer
|
||||
}
|
||||
|
||||
func mountDevice(devicePath, targetPath, fsType string, readOnly bool, mountOptions []string) error {
|
||||
var options []string
|
||||
|
||||
if readOnly {
|
||||
options = append(options, "ro")
|
||||
} else {
|
||||
options = append(options, "rw")
|
||||
}
|
||||
options = append(options, mountOptions...)
|
||||
|
||||
diskMounter := &mount.SafeFormatAndMount{Interface: mount.New(""), Exec: mount.NewOsExec()}
|
||||
|
||||
return diskMounter.FormatAndMount(deviceID, targetPath, fsType, options)
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||
|
||||
targetPath := req.GetTargetPath()
|
||||
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
||||
|
||||
notMnt, err := mount.New("").IsLikelyNotMountPoint(targetPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(targetPath, 0750); err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
notMnt = true
|
||||
} else {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if !notMnt {
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
call := GetFlexAdapter().flexDriver.NewDriverCall(mountCmd)
|
||||
call.Append(req.GetTargetPath())
|
||||
|
||||
if req.GetPublishVolumeInfo() != nil {
|
||||
call.Append(req.GetPublishVolumeInfo()[deviceID])
|
||||
}
|
||||
|
||||
call.AppendSpec(req.GetVolumeId(), fsType, req.GetReadonly(), req.GetVolumeAttributes())
|
||||
_, err = call.Run()
|
||||
if isCmdNotSupportedErr(err) {
|
||||
mountFlags := req.GetVolumeCapability().GetMount().GetMountFlags()
|
||||
err := mountDevice(req.VolumeAttributes[deviceID], targetPath, fsType, req.GetReadonly(), mountFlags)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
} else if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func unmountDevice(path string) error {
|
||||
return util.UnmountPath(path, mount.New(""))
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
||||
|
||||
call := GetFlexAdapter().flexDriver.NewDriverCall(unmountCmd)
|
||||
call.Append(req.GetTargetPath())
|
||||
|
||||
_, err := call.Run()
|
||||
if isCmdNotSupportedErr(err) {
|
||||
err := unmountDevice(req.GetTargetPath())
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
} else if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
84
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/controllerserver.go
generated
vendored
Normal file
84
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/controllerserver.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package hostpath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pborman/uuid"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
const (
|
||||
deviceID = "deviceID"
|
||||
provisionRoot = "/tmp/"
|
||||
)
|
||||
|
||||
type controllerServer struct {
|
||||
*csicommon.DefaultControllerServer
|
||||
}
|
||||
|
||||
func GetVersionString(ver *csi.Version) string {
|
||||
return fmt.Sprintf("%d.%d.%d", ver.Major, ver.Minor, ver.Patch)
|
||||
}
|
||||
|
||||
func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(req.Version, csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
|
||||
glog.V(3).Infof("invalid create volume req: %v", req)
|
||||
return nil, err
|
||||
}
|
||||
volumeId := uuid.NewUUID().String()
|
||||
path := provisionRoot + volumeId
|
||||
err := os.MkdirAll(path, 0777)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("failed to create volume: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
glog.V(4).Infof("create volume %s", path)
|
||||
return &csi.CreateVolumeResponse{
|
||||
VolumeInfo: &csi.VolumeInfo{
|
||||
Id: volumeId,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(req.Version, csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
|
||||
glog.V(3).Infof("invalid delete volume req: %v", req)
|
||||
return nil, err
|
||||
}
|
||||
volumeId := req.VolumeId
|
||||
glog.V(4).Infof("deleting volume %s", volumeId)
|
||||
path := provisionRoot + volumeId
|
||||
os.RemoveAll(path)
|
||||
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ValidateVolumeCapabilities(ctx context.Context, req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
|
||||
for _, cap := range req.VolumeCapabilities {
|
||||
if cap.GetAccessMode().GetMode() != csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER {
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{Supported: false, Message: ""}, nil
|
||||
}
|
||||
}
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{Supported: true, Message: ""}, nil
|
||||
}
|
6
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/extras/docker/Dockerfile
generated
vendored
Normal file
6
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/extras/docker/Dockerfile
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
FROM alpine
|
||||
LABEL maintainers="Kubernetes Authors"
|
||||
LABEL description="HostPath CSI Plugin"
|
||||
|
||||
COPY hostpathplugin /hostpathplugin
|
||||
ENTRYPOINT ["/hostpathplugin"]
|
13
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/extras/docker/Dockerfile.builder
generated
vendored
Normal file
13
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/extras/docker/Dockerfile.builder
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
FROM golang:alpine
|
||||
LABEL maintainers="Kubernetes Authors"
|
||||
LABEL description="HostPath CSI Plugin"
|
||||
|
||||
RUN apk add --no-cache git make wget
|
||||
RUN wget https://github.com/golang/dep/releases/download/v0.3.2/dep-linux-amd64 && \
|
||||
chmod +x dep-linux-amd64 && \
|
||||
mv dep-linux-amd64 /usr/bin/dep
|
||||
RUN go get -d github.com/kubernetes-csi/drivers/app/hostpathplugin
|
||||
RUN cd /go/src/github.com/kubernetes-csi/drivers && \
|
||||
dep ensure && \
|
||||
make hostpath && \
|
||||
cp _output/hostpathplugin /hostpathplugin
|
10
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/extras/docker/make.sh
generated
vendored
Executable file
10
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/extras/docker/make.sh
generated
vendored
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
PROG=hostpathplugin
|
||||
|
||||
docker build --rm -f Dockerfile.builder -t ${PROG}:builder .
|
||||
docker run --rm --privileged -v $PWD:/host ${PROG}:builder cp /${PROG} /host/${PROG}
|
||||
sudo chown $USER ${PROG}
|
||||
docker build --rm -t docker.io/k8scsi/${PROG} .
|
||||
docker rmi ${PROG}:builder
|
||||
rm -f ${PROG}
|
86
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/hostpath.go
generated
vendored
Normal file
86
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/hostpath.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package hostpath
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type hostPath struct {
|
||||
driver *csicommon.CSIDriver
|
||||
|
||||
ids *identityServer
|
||||
ns *nodeServer
|
||||
cs *controllerServer
|
||||
|
||||
cap []*csi.VolumeCapability_AccessMode
|
||||
cscap []*csi.ControllerServiceCapability
|
||||
}
|
||||
|
||||
var (
|
||||
hostPathDriver *hostPath
|
||||
version = csi.Version{
|
||||
Minor: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func GetSupportedVersions() []*csi.Version {
|
||||
return []*csi.Version{&version}
|
||||
}
|
||||
|
||||
func GetHostPathDriver() *hostPath {
|
||||
return &hostPath{}
|
||||
}
|
||||
|
||||
func NewIdentityServer(d *csicommon.CSIDriver) *identityServer {
|
||||
return &identityServer{
|
||||
DefaultIdentityServer: csicommon.NewDefaultIdentityServer(d),
|
||||
}
|
||||
}
|
||||
|
||||
func NewControllerServer(d *csicommon.CSIDriver) *controllerServer {
|
||||
return &controllerServer{
|
||||
DefaultControllerServer: csicommon.NewDefaultControllerServer(d),
|
||||
}
|
||||
}
|
||||
|
||||
func NewNodeServer(d *csicommon.CSIDriver) *nodeServer {
|
||||
return &nodeServer{
|
||||
DefaultNodeServer: csicommon.NewDefaultNodeServer(d),
|
||||
}
|
||||
}
|
||||
|
||||
func (hp *hostPath) Run(driverName, nodeID, endpoint string) {
|
||||
glog.Infof("Driver: %v version: %v", driverName, GetVersionString(&version))
|
||||
|
||||
// Initialize default library driver
|
||||
hp.driver = csicommon.NewCSIDriver(driverName, &version, GetSupportedVersions(), nodeID)
|
||||
hp.driver.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME})
|
||||
hp.driver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER})
|
||||
|
||||
// Create GRPC servers
|
||||
hp.ids = NewIdentityServer(hp.driver)
|
||||
hp.ns = NewNodeServer(hp.driver)
|
||||
hp.cs = NewControllerServer(hp.driver)
|
||||
|
||||
s := csicommon.NewNonBlockingGRPCServer()
|
||||
s.Start(endpoint, hp.ids, hp.cs, hp.ns)
|
||||
s.Wait()
|
||||
}
|
25
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/identityserver.go
generated
vendored
Normal file
25
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/identityserver.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package hostpath
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type identityServer struct {
|
||||
*csicommon.DefaultIdentityServer
|
||||
}
|
85
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/nodeserver.go
generated
vendored
Normal file
85
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/nodeserver.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package hostpath
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type nodeServer struct {
|
||||
*csicommon.DefaultNodeServer
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||
targetPath := req.GetTargetPath()
|
||||
notMnt, err := mount.New("").IsLikelyNotMountPoint(targetPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetPath, 0750); err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
notMnt = true
|
||||
} else {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if !notMnt {
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
||||
|
||||
deviceId := ""
|
||||
if req.GetPublishVolumeInfo() != nil {
|
||||
deviceId = req.GetPublishVolumeInfo()[deviceID]
|
||||
}
|
||||
|
||||
readOnly := req.GetReadonly()
|
||||
volumeId := req.GetVolumeId()
|
||||
attrib := req.GetVolumeAttributes()
|
||||
mountFlags := req.GetVolumeCapability().GetMount().GetMountFlags()
|
||||
|
||||
glog.V(4).Infof("target %v\nfstype %v\ndevice %v\nreadonly %v\nattributes %v\n mountflags %v\n",
|
||||
targetPath, fsType, deviceId, readOnly, volumeId, attrib, mountFlags)
|
||||
|
||||
options := []string{"bind"}
|
||||
if readOnly {
|
||||
options = append(options, "ro")
|
||||
}
|
||||
mounter := mount.New("")
|
||||
path := provisionRoot + volumeId
|
||||
if err := mounter.Mount(path, targetPath, "", options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
43
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/README.md
generated
vendored
Normal file
43
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/README.md
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# CSI ISCSI driver
|
||||
|
||||
## Usage:
|
||||
|
||||
### Start ISCSI driver
|
||||
```
|
||||
$ sudo ../_output/iscsidriver --endpoint tcp://127.0.0.1:10000 --nodeid CSINode
|
||||
```
|
||||
|
||||
### Test using csc
|
||||
Get ```csc``` tool from https://github.com/chakri-nelluri/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugin-info --endpoint tcp://127.0.0.1:10000
|
||||
"ISCSI" "0.1.0"
|
||||
```
|
||||
|
||||
### Get supported versions
|
||||
```
|
||||
$ csc identity supported-versions --endpoint tcp://127.0.0.1:10000
|
||||
0.1.0
|
||||
```
|
||||
|
||||
#### NodePublish a volume
|
||||
```
|
||||
$ export ISCSI_TARGET="iSCSI Target Server IP (Ex: 10.10.10.10)"
|
||||
$ export IQN="Target IQN"
|
||||
$ csc node publish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/iscsi --attrib targetPortal=$ISCSI_TARGET --attrib iqn=$IQN --attrib lun=<lun-id> iscsitestvol
|
||||
iscsitestvol
|
||||
```
|
||||
|
||||
#### NodeUnpublish a volume
|
||||
```
|
||||
$ csc node unpublish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/iscsi iscsitestvol
|
||||
iscsitestvol
|
||||
```
|
||||
|
||||
#### Get NodeID
|
||||
```
|
||||
$ csc node get-id --endpoint tcp://127.0.0.1:10000
|
||||
CSINode
|
||||
```
|
74
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/driver.go
generated
vendored
Normal file
74
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/driver.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package iscsi
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
csiDriver *csicommon.CSIDriver
|
||||
endpoint string
|
||||
|
||||
ids *csicommon.DefaultIdentityServer
|
||||
ns *nodeServer
|
||||
|
||||
cap []*csi.VolumeCapability_AccessMode
|
||||
cscap []*csi.ControllerServiceCapability
|
||||
}
|
||||
|
||||
const (
|
||||
driverName = "ISCSI"
|
||||
)
|
||||
|
||||
var (
|
||||
version = csi.Version{
|
||||
Minor: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func GetSupportedVersions() []*csi.Version {
|
||||
return []*csi.Version{&version}
|
||||
}
|
||||
|
||||
func NewDriver(nodeID, endpoint string) *driver {
|
||||
glog.Infof("Driver: %v version: %v", driverName, csicommon.GetVersionString(&version))
|
||||
|
||||
d := &driver{}
|
||||
|
||||
d.endpoint = endpoint
|
||||
|
||||
csiDriver := csicommon.NewCSIDriver(driverName, &version, GetSupportedVersions(), nodeID)
|
||||
csiDriver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER})
|
||||
|
||||
d.csiDriver = csiDriver
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func NewNodeServer(d *driver) *nodeServer {
|
||||
return &nodeServer{
|
||||
DefaultNodeServer: csicommon.NewDefaultNodeServer(d.csiDriver),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) Run() {
|
||||
csicommon.RunNodePublishServer(d.endpoint, d.csiDriver, NewNodeServer(d))
|
||||
}
|
148
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/iscsi.go
generated
vendored
Normal file
148
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/iscsi.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package iscsi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
func getISCSIInfo(req *csi.NodePublishVolumeRequest) (*iscsiDisk, error) {
|
||||
volName := req.GetVolumeId()
|
||||
tp := req.GetVolumeAttributes()["targetPortal"]
|
||||
iqn := req.GetVolumeAttributes()["iqn"]
|
||||
lun := req.GetVolumeAttributes()["lun"]
|
||||
if tp == "" || iqn == "" || lun == "" {
|
||||
return nil, fmt.Errorf("iSCSI target information is missing")
|
||||
}
|
||||
|
||||
portalList := req.GetVolumeAttributes()["portals"]
|
||||
secretParams := req.GetVolumeAttributes()["secret"]
|
||||
secret := parseSecret(secretParams)
|
||||
|
||||
portal := portalMounter(tp)
|
||||
var bkportal []string
|
||||
bkportal = append(bkportal, portal)
|
||||
|
||||
portals := []string{}
|
||||
if err := json.Unmarshal([]byte(portalList), &portals); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, portal := range portals {
|
||||
bkportal = append(bkportal, portalMounter(string(portal)))
|
||||
}
|
||||
|
||||
iface := req.GetVolumeAttributes()["iscsiInterface"]
|
||||
initiatorName := req.GetVolumeAttributes()["initiatorName"]
|
||||
chapDiscovery := false
|
||||
if req.GetVolumeAttributes()["discoveryCHAPAuth"] == "true" {
|
||||
chapDiscovery = true
|
||||
}
|
||||
|
||||
chapSession := false
|
||||
if req.GetVolumeAttributes()["sessionCHAPAuth"] == "true" {
|
||||
chapSession = true
|
||||
}
|
||||
|
||||
return &iscsiDisk{
|
||||
VolName: volName,
|
||||
Portals: bkportal,
|
||||
Iqn: iqn,
|
||||
lun: lun,
|
||||
Iface: iface,
|
||||
chap_discovery: chapDiscovery,
|
||||
chap_session: chapSession,
|
||||
secret: secret,
|
||||
InitiatorName: initiatorName}, nil
|
||||
}
|
||||
|
||||
func getISCSIDiskMounter(iscsiInfo *iscsiDisk, req *csi.NodePublishVolumeRequest) *iscsiDiskMounter {
|
||||
readOnly := req.GetReadonly()
|
||||
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
||||
mountOptions := req.GetVolumeCapability().GetMount().GetMountFlags()
|
||||
|
||||
return &iscsiDiskMounter{
|
||||
iscsiDisk: iscsiInfo,
|
||||
fsType: fsType,
|
||||
readOnly: readOnly,
|
||||
mountOptions: mountOptions,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mount.New(""), Exec: mount.NewOsExec()},
|
||||
exec: mount.NewOsExec(),
|
||||
targetPath: req.GetTargetPath(),
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}
|
||||
}
|
||||
|
||||
func getISCSIDiskUnmounter(req *csi.NodeUnpublishVolumeRequest) *iscsiDiskUnmounter {
|
||||
return &iscsiDiskUnmounter{
|
||||
iscsiDisk: &iscsiDisk{
|
||||
VolName: req.GetVolumeId(),
|
||||
},
|
||||
mounter: mount.New(""),
|
||||
exec: mount.NewOsExec(),
|
||||
}
|
||||
}
|
||||
|
||||
func portalMounter(portal string) string {
|
||||
if !strings.Contains(portal, ":") {
|
||||
portal = portal + ":3260"
|
||||
}
|
||||
return portal
|
||||
}
|
||||
|
||||
func parseSecret(secretParams string) map[string]string {
|
||||
var secret map[string]string
|
||||
if err := json.Unmarshal([]byte(secretParams), &secret); err != nil {
|
||||
return nil
|
||||
}
|
||||
return secret
|
||||
}
|
||||
|
||||
type iscsiDisk struct {
|
||||
Portals []string
|
||||
Iqn string
|
||||
lun string
|
||||
Iface string
|
||||
chap_discovery bool
|
||||
chap_session bool
|
||||
secret map[string]string
|
||||
InitiatorName string
|
||||
VolName string
|
||||
}
|
||||
|
||||
type iscsiDiskMounter struct {
|
||||
*iscsiDisk
|
||||
readOnly bool
|
||||
fsType string
|
||||
mountOptions []string
|
||||
mounter *mount.SafeFormatAndMount
|
||||
exec mount.Exec
|
||||
deviceUtil util.DeviceUtil
|
||||
targetPath string
|
||||
}
|
||||
|
||||
type iscsiDiskUnmounter struct {
|
||||
*iscsiDisk
|
||||
mounter mount.Interface
|
||||
exec mount.Exec
|
||||
}
|
478
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/iscsi_util.go
generated
vendored
Normal file
478
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/iscsi_util.go
generated
vendored
Normal file
@ -0,0 +1,478 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package iscsi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
var (
|
||||
chap_st = []string{
|
||||
"discovery.sendtargets.auth.username",
|
||||
"discovery.sendtargets.auth.password",
|
||||
"discovery.sendtargets.auth.username_in",
|
||||
"discovery.sendtargets.auth.password_in"}
|
||||
chap_sess = []string{
|
||||
"node.session.auth.username",
|
||||
"node.session.auth.password",
|
||||
"node.session.auth.username_in",
|
||||
"node.session.auth.password_in"}
|
||||
ifaceTransportNameRe = regexp.MustCompile(`iface.transport_name = (.*)\n`)
|
||||
)
|
||||
|
||||
func updateISCSIDiscoverydb(b iscsiDiskMounter, tp string) error {
|
||||
if !b.chap_discovery {
|
||||
return nil
|
||||
}
|
||||
out, err := b.exec.Run("iscsiadm", "-m", "discoverydb", "-t", "sendtargets", "-p", tp, "-I", b.Iface, "-o", "update", "-n", "discovery.sendtargets.auth.authmethod", "-v", "CHAP")
|
||||
if err != nil {
|
||||
return fmt.Errorf("iscsi: failed to update discoverydb with CHAP, output: %v", string(out))
|
||||
}
|
||||
|
||||
for _, k := range chap_st {
|
||||
v := b.secret[k]
|
||||
if len(v) > 0 {
|
||||
out, err := b.exec.Run("iscsiadm", "-m", "discoverydb", "-t", "sendtargets", "-p", tp, "-I", b.Iface, "-o", "update", "-n", k, "-v", v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("iscsi: failed to update discoverydb key %q with value %q error: %v", k, v, string(out))
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateISCSINode(b iscsiDiskMounter, tp string) error {
|
||||
if !b.chap_session {
|
||||
return nil
|
||||
}
|
||||
|
||||
out, err := b.exec.Run("iscsiadm", "-m", "node", "-p", tp, "-T", b.Iqn, "-I", b.Iface, "-o", "update", "-n", "node.session.auth.authmethod", "-v", "CHAP")
|
||||
if err != nil {
|
||||
return fmt.Errorf("iscsi: failed to update node with CHAP, output: %v", string(out))
|
||||
}
|
||||
|
||||
for _, k := range chap_sess {
|
||||
v := b.secret[k]
|
||||
if len(v) > 0 {
|
||||
out, err := b.exec.Run("iscsiadm", "-m", "node", "-p", tp, "-T", b.Iqn, "-I", b.Iface, "-o", "update", "-n", k, "-v", v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("iscsi: failed to update node session key %q with value %q error: %v", k, v, string(out))
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// stat a path, if not exists, retry maxRetries times
|
||||
// when iscsi transports other than default are used, use glob instead as pci id of device is unknown
|
||||
type StatFunc func(string) (os.FileInfo, error)
|
||||
type GlobFunc func(string) ([]string, error)
|
||||
|
||||
func waitForPathToExist(devicePath *string, maxRetries int, deviceTransport string) bool {
|
||||
// This makes unit testing a lot easier
|
||||
return waitForPathToExistInternal(devicePath, maxRetries, deviceTransport, os.Stat, filepath.Glob)
|
||||
}
|
||||
|
||||
func waitForPathToExistInternal(devicePath *string, maxRetries int, deviceTransport string, osStat StatFunc, filepathGlob GlobFunc) bool {
|
||||
if devicePath == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
var err error
|
||||
if deviceTransport == "tcp" {
|
||||
_, err = osStat(*devicePath)
|
||||
} else {
|
||||
fpath, _ := filepathGlob(*devicePath)
|
||||
if fpath == nil {
|
||||
err = os.ErrNotExist
|
||||
} else {
|
||||
// There might be a case that fpath contains multiple device paths if
|
||||
// multiple PCI devices connect to same iscsi target. We handle this
|
||||
// case at subsequent logic. Pick up only first path here.
|
||||
*devicePath = fpath[0]
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
if i == maxRetries-1 {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ISCSIUtil struct{}
|
||||
|
||||
func (util *ISCSIUtil) persistISCSI(conf iscsiDisk, mnt string) error {
|
||||
file := path.Join(mnt, conf.VolName+".json")
|
||||
fp, err := os.Create(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("iscsi: create %s err %s", file, err)
|
||||
}
|
||||
defer fp.Close()
|
||||
encoder := json.NewEncoder(fp)
|
||||
if err = encoder.Encode(conf); err != nil {
|
||||
return fmt.Errorf("iscsi: encode err: %v.", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (util *ISCSIUtil) loadISCSI(conf *iscsiDisk, mnt string) error {
|
||||
// NOTE: The iscsi config json is not deleted after logging out from target portals.
|
||||
file := path.Join(mnt, conf.VolName+".json")
|
||||
fp, err := os.Open(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("iscsi: open %s err %s", file, err)
|
||||
}
|
||||
defer fp.Close()
|
||||
decoder := json.NewDecoder(fp)
|
||||
if err = decoder.Decode(conf); err != nil {
|
||||
return fmt.Errorf("iscsi: decode err: %v.", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (util *ISCSIUtil) AttachDisk(b iscsiDiskMounter) (string, error) {
|
||||
var devicePath string
|
||||
var devicePaths []string
|
||||
var iscsiTransport string
|
||||
var lastErr error
|
||||
|
||||
out, err := b.exec.Run("iscsiadm", "-m", "iface", "-I", b.Iface, "-o", "show")
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: could not read iface %s error: %s", b.Iface, string(out))
|
||||
return "", err
|
||||
}
|
||||
|
||||
iscsiTransport = extractTransportname(string(out))
|
||||
|
||||
bkpPortal := b.Portals
|
||||
|
||||
// create new iface and copy parameters from pre-configured iface to the created iface
|
||||
if b.InitiatorName != "" {
|
||||
// new iface name is <target portal>:<volume name>
|
||||
newIface := bkpPortal[0] + ":" + b.VolName
|
||||
err = cloneIface(b, newIface)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to clone iface: %s error: %v", b.Iface, err)
|
||||
return "", err
|
||||
}
|
||||
// update iface name
|
||||
b.Iface = newIface
|
||||
}
|
||||
|
||||
for _, tp := range bkpPortal {
|
||||
// Rescan sessions to discover newly mapped LUNs. Do not specify the interface when rescanning
|
||||
// to avoid establishing additional sessions to the same target.
|
||||
out, err := b.exec.Run("iscsiadm", "-m", "node", "-p", tp, "-T", b.Iqn, "-R")
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to rescan session with error: %s (%v)", string(out), err)
|
||||
}
|
||||
|
||||
if iscsiTransport == "" {
|
||||
glog.Errorf("iscsi: could not find transport name in iface %s", b.Iface)
|
||||
return "", fmt.Errorf("Could not parse iface file for %s", b.Iface)
|
||||
}
|
||||
if iscsiTransport == "tcp" {
|
||||
devicePath = strings.Join([]string{"/dev/disk/by-path/ip", tp, "iscsi", b.Iqn, "lun", b.lun}, "-")
|
||||
} else {
|
||||
devicePath = strings.Join([]string{"/dev/disk/by-path/pci", "*", "ip", tp, "iscsi", b.Iqn, "lun", b.lun}, "-")
|
||||
}
|
||||
|
||||
if exist := waitForPathToExist(&devicePath, 1, iscsiTransport); exist {
|
||||
glog.V(4).Infof("iscsi: devicepath (%s) exists", devicePath)
|
||||
devicePaths = append(devicePaths, devicePath)
|
||||
continue
|
||||
}
|
||||
// build discoverydb and discover iscsi target
|
||||
b.exec.Run("iscsiadm", "-m", "discoverydb", "-t", "sendtargets", "-p", tp, "-I", b.Iface, "-o", "new")
|
||||
// update discoverydb with CHAP secret
|
||||
err = updateISCSIDiscoverydb(b, tp)
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("iscsi: failed to update discoverydb to portal %s error: %v", tp, err)
|
||||
continue
|
||||
}
|
||||
out, err = b.exec.Run("iscsiadm", "-m", "discoverydb", "-t", "sendtargets", "-p", tp, "-I", b.Iface, "--discover")
|
||||
if err != nil {
|
||||
// delete discoverydb record
|
||||
b.exec.Run("iscsiadm", "-m", "discoverydb", "-t", "sendtargets", "-p", tp, "-I", b.Iface, "-o", "delete")
|
||||
lastErr = fmt.Errorf("iscsi: failed to sendtargets to portal %s output: %s, err %v", tp, string(out), err)
|
||||
continue
|
||||
}
|
||||
err = updateISCSINode(b, tp)
|
||||
if err != nil {
|
||||
// failure to update node db is rare. But deleting record will likely impact those who already start using it.
|
||||
lastErr = fmt.Errorf("iscsi: failed to update iscsi node to portal %s error: %v", tp, err)
|
||||
continue
|
||||
}
|
||||
// login to iscsi target
|
||||
out, err = b.exec.Run("iscsiadm", "-m", "node", "-p", tp, "-T", b.Iqn, "-I", b.Iface, "--login")
|
||||
if err != nil {
|
||||
// delete the node record from database
|
||||
b.exec.Run("iscsiadm", "-m", "node", "-p", tp, "-I", b.Iface, "-T", b.Iqn, "-o", "delete")
|
||||
lastErr = fmt.Errorf("iscsi: failed to attach disk: Error: %s (%v)", string(out), err)
|
||||
continue
|
||||
}
|
||||
if exist := waitForPathToExist(&devicePath, 10, iscsiTransport); !exist {
|
||||
glog.Errorf("Could not attach disk: Timeout after 10s")
|
||||
// update last error
|
||||
lastErr = fmt.Errorf("Could not attach disk: Timeout after 10s")
|
||||
continue
|
||||
} else {
|
||||
devicePaths = append(devicePaths, devicePath)
|
||||
}
|
||||
}
|
||||
|
||||
if len(devicePaths) == 0 {
|
||||
// delete cloned iface
|
||||
b.exec.Run("iscsiadm", "-m", "iface", "-I", b.Iface, "-o", "delete")
|
||||
glog.Errorf("iscsi: failed to get any path for iscsi disk, last err seen:\n%v", lastErr)
|
||||
return "", fmt.Errorf("failed to get any path for iscsi disk, last err seen:\n%v", lastErr)
|
||||
}
|
||||
if lastErr != nil {
|
||||
glog.Errorf("iscsi: last error occurred during iscsi init:\n%v", lastErr)
|
||||
}
|
||||
|
||||
// Make sure we use a valid devicepath to find mpio device.
|
||||
devicePath = devicePaths[0]
|
||||
|
||||
// Mount device
|
||||
mntPath := path.Join(b.targetPath, b.VolName)
|
||||
notMnt, err := b.mounter.IsLikelyNotMountPoint(mntPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("Heuristic determination of mount point failed:%v", err)
|
||||
}
|
||||
if !notMnt {
|
||||
glog.Infof("iscsi: %s already mounted", mntPath)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(mntPath, 0750); err != nil {
|
||||
glog.Errorf("iscsi: failed to mkdir %s, error", mntPath)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Persist iscsi disk config to json file for DetachDisk path
|
||||
if err := util.persistISCSI(*(b.iscsiDisk), b.targetPath); err != nil {
|
||||
glog.Errorf("iscsi: failed to save iscsi config with error: %v", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, path := range devicePaths {
|
||||
// There shouldnt be any empty device paths. However adding this check
|
||||
// for safer side to avoid the possibility of an empty entry.
|
||||
if path == "" {
|
||||
continue
|
||||
}
|
||||
// check if the dev is using mpio and if so mount it via the dm-XX device
|
||||
if mappedDevicePath := b.deviceUtil.FindMultipathDeviceForDevice(path); mappedDevicePath != "" {
|
||||
devicePath = mappedDevicePath
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var options []string
|
||||
|
||||
if b.readOnly {
|
||||
options = append(options, "ro")
|
||||
} else {
|
||||
options = append(options, "rw")
|
||||
}
|
||||
options = append(options, b.mountOptions...)
|
||||
|
||||
err = b.mounter.FormatAndMount(devicePath, mntPath, b.fsType, options)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to mount iscsi volume %s [%s] to %s, error %v", devicePath, b.fsType, mntPath, err)
|
||||
}
|
||||
|
||||
return devicePath, err
|
||||
}
|
||||
|
||||
func (util *ISCSIUtil) DetachDisk(c iscsiDiskUnmounter, targetPath string) error {
|
||||
mntPath := path.Join(targetPath, c.VolName)
|
||||
_, cnt, err := mount.GetDeviceNameFromMount(c.mounter, mntPath)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi detach disk: failed to get device from mnt: %s\nError: %v", mntPath, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if pathExists, pathErr := volumeutil.PathExists(mntPath); pathErr != nil {
|
||||
return fmt.Errorf("Error checking if path exists: %v", pathErr)
|
||||
} else if !pathExists {
|
||||
glog.Warningf("Warning: Unmount skipped because path does not exist: %v", mntPath)
|
||||
return nil
|
||||
}
|
||||
if err = c.mounter.Unmount(mntPath); err != nil {
|
||||
glog.Errorf("iscsi detach disk: failed to unmount: %s\nError: %v", mntPath, err)
|
||||
return err
|
||||
}
|
||||
cnt--
|
||||
if cnt != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var bkpPortal []string
|
||||
var volName, iqn, iface, initiatorName string
|
||||
found := true
|
||||
|
||||
// load iscsi disk config from json file
|
||||
if err := util.loadISCSI(c.iscsiDisk, targetPath); err == nil {
|
||||
bkpPortal, iqn, iface, volName = c.iscsiDisk.Portals, c.iscsiDisk.Iqn, c.iscsiDisk.Iface, c.iscsiDisk.VolName
|
||||
initiatorName = c.iscsiDisk.InitiatorName
|
||||
} else {
|
||||
glog.Errorf("iscsi detach disk: failed to get iscsi config from path %s Error: %v", targetPath, err)
|
||||
return err
|
||||
}
|
||||
portals := removeDuplicate(bkpPortal)
|
||||
if len(portals) == 0 {
|
||||
return fmt.Errorf("iscsi detach disk: failed to detach iscsi disk. Couldn't get connected portals from configurations.")
|
||||
}
|
||||
|
||||
for _, portal := range portals {
|
||||
logoutArgs := []string{"-m", "node", "-p", portal, "-T", iqn, "--logout"}
|
||||
deleteArgs := []string{"-m", "node", "-p", portal, "-T", iqn, "-o", "delete"}
|
||||
if found {
|
||||
logoutArgs = append(logoutArgs, []string{"-I", iface}...)
|
||||
deleteArgs = append(deleteArgs, []string{"-I", iface}...)
|
||||
}
|
||||
glog.Infof("iscsi: log out target %s iqn %s iface %s", portal, iqn, iface)
|
||||
out, err := c.exec.Run("iscsiadm", logoutArgs...)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to detach disk Error: %s", string(out))
|
||||
}
|
||||
// Delete the node record
|
||||
glog.Infof("iscsi: delete node record target %s iqn %s", portal, iqn)
|
||||
out, err = c.exec.Run("iscsiadm", deleteArgs...)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to delete node record Error: %s", string(out))
|
||||
}
|
||||
}
|
||||
// Delete the iface after all sessions have logged out
|
||||
// If the iface is not created via iscsi plugin, skip to delete
|
||||
if initiatorName != "" && found && iface == (portals[0]+":"+volName) {
|
||||
deleteArgs := []string{"-m", "iface", "-I", iface, "-o", "delete"}
|
||||
out, err := c.exec.Run("iscsiadm", deleteArgs...)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi: failed to delete iface Error: %s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(targetPath); err != nil {
|
||||
glog.Errorf("iscsi: failed to remove mount path Error: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractTransportname(ifaceOutput string) (iscsiTransport string) {
|
||||
rexOutput := ifaceTransportNameRe.FindStringSubmatch(ifaceOutput)
|
||||
if rexOutput == nil {
|
||||
return ""
|
||||
}
|
||||
iscsiTransport = rexOutput[1]
|
||||
|
||||
// While iface.transport_name is a required parameter, handle it being unspecified anyways
|
||||
if iscsiTransport == "<empty>" {
|
||||
iscsiTransport = "tcp"
|
||||
}
|
||||
return iscsiTransport
|
||||
}
|
||||
|
||||
// Remove duplicates or string
|
||||
func removeDuplicate(s []string) []string {
|
||||
m := map[string]bool{}
|
||||
for _, v := range s {
|
||||
if v != "" && !m[v] {
|
||||
s[len(m)] = v
|
||||
m[v] = true
|
||||
}
|
||||
}
|
||||
s = s[:len(m)]
|
||||
return s
|
||||
}
|
||||
|
||||
func parseIscsiadmShow(output string) (map[string]string, error) {
|
||||
params := make(map[string]string)
|
||||
slice := strings.Split(output, "\n")
|
||||
for _, line := range slice {
|
||||
if !strings.HasPrefix(line, "iface.") || strings.Contains(line, "<empty>") {
|
||||
continue
|
||||
}
|
||||
iface := strings.Fields(line)
|
||||
if len(iface) != 3 || iface[1] != "=" {
|
||||
return nil, fmt.Errorf("Error: invalid iface setting: %v", iface)
|
||||
}
|
||||
// iscsi_ifacename is immutable once the iface is created
|
||||
if iface[0] == "iface.iscsi_ifacename" {
|
||||
continue
|
||||
}
|
||||
params[iface[0]] = iface[2]
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func cloneIface(b iscsiDiskMounter, newIface string) error {
|
||||
var lastErr error
|
||||
// get pre-configured iface records
|
||||
out, err := b.exec.Run("iscsiadm", "-m", "iface", "-I", b.Iface, "-o", "show")
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("iscsi: failed to show iface records: %s (%v)", string(out), err)
|
||||
return lastErr
|
||||
}
|
||||
// parse obtained records
|
||||
params, err := parseIscsiadmShow(string(out))
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("iscsi: failed to parse iface records: %s (%v)", string(out), err)
|
||||
return lastErr
|
||||
}
|
||||
// update initiatorname
|
||||
params["iface.initiatorname"] = b.InitiatorName
|
||||
// create new iface
|
||||
out, err = b.exec.Run("iscsiadm", "-m", "iface", "-I", newIface, "-o", "new")
|
||||
if err != nil {
|
||||
lastErr = fmt.Errorf("iscsi: failed to create new iface: %s (%v)", string(out), err)
|
||||
return lastErr
|
||||
}
|
||||
// update new iface records
|
||||
for key, val := range params {
|
||||
_, err = b.exec.Run("iscsiadm", "-m", "iface", "-I", newIface, "-o", "update", "-n", key, "-v", val)
|
||||
if err != nil {
|
||||
b.exec.Run("iscsiadm", "-m", "iface", "-I", newIface, "-o", "delete")
|
||||
lastErr = fmt.Errorf("iscsi: failed to update iface records: %s (%v). iface(%s) will be used", string(out), err, b.Iface)
|
||||
break
|
||||
}
|
||||
}
|
||||
return lastErr
|
||||
}
|
59
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/nodeserver.go
generated
vendored
Normal file
59
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/nodeserver.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package iscsi
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type nodeServer struct {
|
||||
*csicommon.DefaultNodeServer
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||
iscsiInfo, err := getISCSIInfo(req)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
diskMounter := getISCSIDiskMounter(iscsiInfo, req)
|
||||
|
||||
util := &ISCSIUtil{}
|
||||
_, err = util.AttachDisk(*diskMounter)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
||||
diskUnmounter := getISCSIDiskUnmounter(req)
|
||||
targetPath := req.GetTargetPath()
|
||||
|
||||
iscsiutil := &ISCSIUtil{}
|
||||
err := iscsiutil.DetachDisk(*diskUnmounter, targetPath)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
70
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/README.md
generated
vendored
Normal file
70
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/README.md
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
# CSI NFS driver
|
||||
|
||||
|
||||
## Kubernetes
|
||||
### Requirements
|
||||
|
||||
The folllowing feature gates and runtime config have to be enabled to deploy the driver
|
||||
|
||||
```
|
||||
FEATURE_GATES=CSIPersistentVolume=true,MountPropagation=true
|
||||
RUNTIME_CONFIG="storage.k8s.io/v1alpha1=true"
|
||||
```
|
||||
|
||||
Mountprogpation requries support for privileged containers. So, make sure privileged containers are enabled in the cluster.
|
||||
|
||||
### Example local-up-cluster.sh
|
||||
|
||||
```ALLOW_PRIVILEGED=true FEATURE_GATES=CSIPersistentVolume=true,MountPropagation=true RUNTIME_CONFIG="storage.k8s.io/v1alpha1=true" LOG_LEVEL=5 hack/local-up-cluster.sh```
|
||||
|
||||
### Deploy
|
||||
|
||||
```kubectl -f deploy/kubernetes create```
|
||||
|
||||
### Example Nginx application
|
||||
Please update the NFS Server & share information in nginx.yaml file.
|
||||
|
||||
```kubectl -f examples/kubernetes/nginx.yaml create```
|
||||
|
||||
## Using CSC tool
|
||||
|
||||
### Start NFS driver
|
||||
```
|
||||
$ sudo ../../_output/flexadapter --endpoint tcp://127.0.0.1:10000 --drivername simplenfs --driverpath ./examples/simplenfs-flexdriver/driver/nfs --nodeid CSINode -v=3
|
||||
```
|
||||
|
||||
## Test
|
||||
Get ```csc``` tool from https://github.com/thecodeteam/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugininfo --endpoint tcp://127.0.0.1:10000
|
||||
"NFS" "0.1.0"
|
||||
```
|
||||
|
||||
### Get supported versions
|
||||
```
|
||||
$ csc identity supportedversions --endpoint tcp://127.0.0.1:10000
|
||||
0.1.0
|
||||
```
|
||||
|
||||
#### NodePublish a volume
|
||||
```
|
||||
$ export NFS_SERVER="Your Server IP (Ex: 10.10.10.10)"
|
||||
$ export NFS_SHARE="Your NFS share"
|
||||
$ csc node publishvolume --endpoint tcp://127.0.0.1:10000 --target-path /mnt/nfs --attrib server=$NFS_SERVER --attrib share=$NFS_SHARE nfstestvol
|
||||
nfstestvol
|
||||
```
|
||||
|
||||
#### NodeUnpublish a volume
|
||||
```
|
||||
$ csc node unpublishvolume --endpoint tcp://127.0.0.1:10000 --target-path /mnt/nfs nfstestvol
|
||||
nfstestvol
|
||||
```
|
||||
|
||||
#### Get NodeID
|
||||
```
|
||||
$ csc node getid --endpoint tcp://127.0.0.1:10000
|
||||
CSINode
|
||||
```
|
||||
|
64
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-attacher-nfsplugin.yaml
generated
vendored
Normal file
64
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-attacher-nfsplugin.yaml
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
# This YAML file contains attacher & csi driver API objects that are necessary
|
||||
# to run external CSI attacher for nfs
|
||||
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: csi-attacher-nfsplugin
|
||||
labels:
|
||||
app: csi-attacher-nfsplugin
|
||||
spec:
|
||||
selector:
|
||||
app: csi-attacher-nfsplugin
|
||||
ports:
|
||||
- name: dummy
|
||||
port: 12345
|
||||
|
||||
---
|
||||
kind: StatefulSet
|
||||
apiVersion: apps/v1beta1
|
||||
metadata:
|
||||
name: csi-attacher-nfsplugin
|
||||
spec:
|
||||
serviceName: "csi-attacher"
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: csi-attacher-nfsplugin
|
||||
spec:
|
||||
serviceAccount: csi-attacher
|
||||
containers:
|
||||
- name: csi-attacher
|
||||
image: docker.io/k8scsi/csi-attacher
|
||||
args:
|
||||
- "--v=5"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /var/lib/csi/sockets/pluginproxy/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /var/lib/csi/sockets/pluginproxy/
|
||||
|
||||
- name: nfs
|
||||
image: docker.io/k8s/nfsplugin:v0.1
|
||||
args :
|
||||
- "--nodeid=$(NODE_ID)"
|
||||
- "--endpoint=$(CSI_ENDPOINT)"
|
||||
env:
|
||||
- name: NODE_ID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: CSI_ENDPOINT
|
||||
value: unix://plugin/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /plugin
|
||||
volumes:
|
||||
- name: socket-dir
|
||||
emptyDir:
|
||||
|
37
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-attacher-rbac.yaml
generated
vendored
Normal file
37
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-attacher-rbac.yaml
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
# This YAML file contains RBAC API objects that are necessary to run external
|
||||
# CSI attacher for nfs flex adapter
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: csi-attacher
|
||||
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: external-attacher-runner
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["volumeattachments"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-attacher-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: csi-attacher
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: external-attacher-runner
|
||||
apiGroup: rbac.authorization.k8s.io
|
66
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-nodeplugin-nfsplugin.yaml
generated
vendored
Normal file
66
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-nodeplugin-nfsplugin.yaml
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
# This YAML file contains driver-registrar & csi driver nodeplugin API objects
|
||||
# that are necessary to run CSI nodeplugin for nfs
|
||||
kind: DaemonSet
|
||||
apiVersion: apps/v1beta2
|
||||
metadata:
|
||||
name: csi-nodeplugin-nfsplugin
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: csi-nodeplugin-nfsplugin
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: csi-nodeplugin-nfsplugin
|
||||
spec:
|
||||
serviceAccount: csi-nodeplugin
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: driver-registrar
|
||||
image: docker.io/k8scsi/driver-registrar
|
||||
args:
|
||||
- "--v=5"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /plugin/csi.sock
|
||||
- name: KUBE_NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
volumeMounts:
|
||||
- name: plugin-dir
|
||||
mountPath: /plugin
|
||||
- name: nfs
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
add: ["SYS_ADMIN"]
|
||||
allowPrivilegeEscalation: true
|
||||
image: docker.io/k8s/nfsplugin:v0.1
|
||||
args :
|
||||
- "--nodeid=$(NODE_ID)"
|
||||
- "--endpoint=$(CSI_ENDPOINT)"
|
||||
env:
|
||||
- name: NODE_ID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: CSI_ENDPOINT
|
||||
value: unix://plugin/csi.sock
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: plugin-dir
|
||||
mountPath: /plugin
|
||||
- name: pods-mount-dir
|
||||
mountPath: /var/lib/kubelet/pods
|
||||
mountPropagation: "Bidirectional"
|
||||
volumes:
|
||||
- name: plugin-dir
|
||||
hostPath:
|
||||
path: /var/lib/kubelet/plugins/csi-nfsplugin
|
||||
type: DirectoryOrCreate
|
||||
- name: pods-mount-dir
|
||||
hostPath:
|
||||
path: /var/lib/kubelet/pods
|
||||
type: Directory
|
34
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-nodeplugin-rbac.yaml
generated
vendored
Normal file
34
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/deploy/kubernetes/csi-nodeplugin-rbac.yaml
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# This YAML defines all API objects to create RBAC roles for CSI node plugin
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["volumeattachments"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: csi-nodeplugin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: csi-nodeplugin
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: csi-nodeplugin
|
||||
apiGroup: rbac.authorization.k8s.io
|
8
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/dockerfile/Dockerfile
generated
vendored
Normal file
8
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/dockerfile/Dockerfile
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
FROM centos:7.4.1708
|
||||
|
||||
# Copy nfsplugin from build _output directory
|
||||
COPY nfsplugin /nfsplugin
|
||||
|
||||
RUN yum -y install nfs-utils && yum -y install epel-release && yum -y install jq && yum clean all
|
||||
|
||||
ENTRYPOINT ["/nfsplugin"]
|
79
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/driver.go
generated
vendored
Normal file
79
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/driver.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package nfs
|
||||
|
||||
import (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
csiDriver *csicommon.CSIDriver
|
||||
endpoint string
|
||||
|
||||
ids *csicommon.DefaultIdentityServer
|
||||
ns *nodeServer
|
||||
|
||||
cap []*csi.VolumeCapability_AccessMode
|
||||
cscap []*csi.ControllerServiceCapability
|
||||
}
|
||||
|
||||
const (
|
||||
driverName = "csi-nfsplugin"
|
||||
)
|
||||
|
||||
var (
|
||||
version = csi.Version{
|
||||
Minor: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func GetSupportedVersions() []*csi.Version {
|
||||
return []*csi.Version{&version}
|
||||
}
|
||||
|
||||
func NewDriver(nodeID, endpoint string) *driver {
|
||||
glog.Infof("Driver: %v version: %v", driverName, csicommon.GetVersionString(&version))
|
||||
|
||||
d := &driver{}
|
||||
|
||||
d.endpoint = endpoint
|
||||
|
||||
csiDriver := csicommon.NewCSIDriver(driverName, &version, GetSupportedVersions(), nodeID)
|
||||
csiDriver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER})
|
||||
|
||||
d.csiDriver = csiDriver
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func NewNodeServer(d *driver) *nodeServer {
|
||||
return &nodeServer{
|
||||
DefaultNodeServer: csicommon.NewDefaultNodeServer(d.csiDriver),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) Run() {
|
||||
s := csicommon.NewNonBlockingGRPCServer()
|
||||
s.Start(d.endpoint,
|
||||
csicommon.NewDefaultIdentityServer(d.csiDriver),
|
||||
csicommon.NewDefaultControllerServer(d.csiDriver),
|
||||
NewNodeServer(d))
|
||||
s.Wait()
|
||||
}
|
52
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/examples/kubernetes/nginx.yaml
generated
vendored
Normal file
52
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/examples/kubernetes/nginx.yaml
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: data-nfsplugin
|
||||
labels:
|
||||
name: data-nfsplugin
|
||||
annotations:
|
||||
csi.volume.kubernetes.io/volume-attributes: '{"server": "10.10.10.10", "share": "share"}'
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
capacity:
|
||||
storage: 100Gi
|
||||
csi:
|
||||
driver: csi-nfsplugin
|
||||
volumeHandle: data-id
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: data-nfsplugin
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: name
|
||||
operator: In
|
||||
values: ["data-nfsplugin"]
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: maersk/nginx
|
||||
imagePullPolicy: Always
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /var/www
|
||||
name: data-nfsplugin
|
||||
volumes:
|
||||
- name: data-nfsplugin
|
||||
persistentVolumeClaim:
|
||||
claimName: data-nfsplugin
|
101
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/nodeserver.go
generated
vendored
Normal file
101
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/nodeserver.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package nfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
type nodeServer struct {
|
||||
*csicommon.DefaultNodeServer
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||
targetPath := req.GetTargetPath()
|
||||
notMnt, err := mount.New("").IsLikelyNotMountPoint(targetPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(targetPath, 0750); err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
notMnt = true
|
||||
} else {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if !notMnt {
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
mo := req.GetVolumeCapability().GetMount().GetMountFlags()
|
||||
if req.GetReadonly() {
|
||||
mo = append(mo, "ro")
|
||||
}
|
||||
|
||||
s := req.GetVolumeAttributes()["server"]
|
||||
ep := req.GetVolumeAttributes()["exportPath"]
|
||||
source := fmt.Sprintf("%s:%s", s, ep)
|
||||
|
||||
mounter := mount.New("")
|
||||
err = mounter.Mount(source, targetPath, "nfs", mo)
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return nil, status.Error(codes.PermissionDenied, err.Error())
|
||||
}
|
||||
if strings.Contains(err.Error(), "invalid argument") {
|
||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
|
||||
targetPath := req.GetTargetPath()
|
||||
notMnt, err := mount.New("").IsLikelyNotMountPoint(targetPath)
|
||||
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, status.Error(codes.NotFound, "Targetpath not found")
|
||||
} else {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
if notMnt {
|
||||
return nil, status.Error(codes.NotFound, "Volume not mounted")
|
||||
}
|
||||
|
||||
err = util.UnmountPath(req.GetTargetPath(), mount.New(""))
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
Reference in New Issue
Block a user