mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 10:53:34 +00:00
vendor cleanup: remove unused,non-go and test files
This commit is contained in:
77
vendor/github.com/kubernetes-csi/drivers/.gitignore
generated
vendored
77
vendor/github.com/kubernetes-csi/drivers/.gitignore
generated
vendored
@ -1,77 +0,0 @@
|
||||
# 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
|
||||
|
22
vendor/github.com/kubernetes-csi/drivers/.travis.yml
generated
vendored
22
vendor/github.com/kubernetes-csi/drivers/.travis.yml
generated
vendored
@ -1,22 +0,0 @@
|
||||
language: go
|
||||
services:
|
||||
- docker
|
||||
# Needed for e2e tests
|
||||
sudo: true
|
||||
go: 1.10.3
|
||||
go_import_path: github.com/kubernetes-csi/drivers
|
||||
install:
|
||||
- go get -u github.com/golang/dep/cmd/dep
|
||||
- dep ensure -vendor-only
|
||||
- make hostpath
|
||||
script:
|
||||
- go fmt $(go list ./... | grep -v vendor) | wc -l | grep 0
|
||||
- go vet $(go list ./... | grep -v vendor)
|
||||
- go test $(go list ./... | grep -v vendor)
|
||||
- ./hack/e2e-hostpath.sh
|
||||
after_success:
|
||||
- if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then
|
||||
docker login -u "${DOCKER_USERNAME}" -p "${DOCKER_PASSWORD}" quay.io;
|
||||
make hostpath-container;
|
||||
docker push quay.io/k8scsi/hostpathplugin:canary;
|
||||
fi
|
664
vendor/github.com/kubernetes-csi/drivers/Gopkg.lock
generated
vendored
664
vendor/github.com/kubernetes-csi/drivers/Gopkg.lock
generated
vendored
@ -1,664 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/beorn7/perks"
|
||||
packages = ["quantile"]
|
||||
revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/container-storage-interface/spec"
|
||||
packages = ["lib/go/csi/v0"]
|
||||
revision = "2178fdeea87f1150a17a63252eee28d4d8141f72"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/distribution"
|
||||
packages = [
|
||||
"digestset",
|
||||
"reference"
|
||||
]
|
||||
revision = "5db89f0ca68677abc5eefce8f2a0a772c98ba52d"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/ghodss/yaml"
|
||||
packages = ["."]
|
||||
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"sortkeys"
|
||||
]
|
||||
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
packages = ["."]
|
||||
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/groupcache"
|
||||
packages = ["lru"]
|
||||
revision = "66deaeb636dff1ac7d938ce666d090556056a4b0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"ptypes",
|
||||
"ptypes/any",
|
||||
"ptypes/duration",
|
||||
"ptypes/timestamp",
|
||||
"ptypes/wrappers"
|
||||
]
|
||||
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/btree"
|
||||
packages = ["."]
|
||||
revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4"
|
||||
|
||||
[[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 = "afbf0422412f5dc726fa12be280fa0c3cb31fcbd"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gregjones/httpcache"
|
||||
packages = [
|
||||
".",
|
||||
"diskcache"
|
||||
]
|
||||
revision = "2bcd89a1743fd4b373f7370ce8ddc14dfbd18229"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/golang-lru"
|
||||
packages = [
|
||||
".",
|
||||
"simplelru"
|
||||
]
|
||||
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/inconshreveable/mousetrap"
|
||||
packages = ["."]
|
||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/json-iterator/go"
|
||||
packages = ["."]
|
||||
revision = "3353055b2a1a5ae1b6a8dfde887a524e7088f3a2"
|
||||
version = "1.1.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/juju/ratelimit"
|
||||
packages = ["."]
|
||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
||||
version = "1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
packages = ["pbutil"]
|
||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/modern-go/concurrent"
|
||||
packages = ["."]
|
||||
revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a"
|
||||
version = "1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/modern-go/reflect2"
|
||||
packages = ["."]
|
||||
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
|
||||
version = "1.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 = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/common"
|
||||
packages = [
|
||||
"expfmt",
|
||||
"internal/bitbucket.org/ww/goautoneg",
|
||||
"model"
|
||||
]
|
||||
revision = "6fb6fce6f8b75884b92e1889c150403fc0872c5e"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/procfs"
|
||||
packages = [
|
||||
".",
|
||||
"internal/util",
|
||||
"nfs",
|
||||
"xfs"
|
||||
]
|
||||
revision = "d274e363d5759d1c916232217be421f1cc89c5fe"
|
||||
|
||||
[[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]]
|
||||
name = "github.com/stretchr/objx"
|
||||
packages = ["."]
|
||||
revision = "facf9a85c22f48d2f52f2380e4efce1768749a89"
|
||||
version = "v0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = [
|
||||
"assert",
|
||||
"mock"
|
||||
]
|
||||
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
|
||||
version = "v1.2.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = [
|
||||
"ed25519",
|
||||
"ed25519/internal/edwards25519"
|
||||
]
|
||||
revision = "91a49db82a88618983a78a06c1cbd4e00ab749ab"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"http2",
|
||||
"http2/hpack",
|
||||
"idna",
|
||||
"internal/timeseries",
|
||||
"lex/httplex",
|
||||
"trace"
|
||||
]
|
||||
revision = "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "f6cff0780e542efa0c8e864dc8fa522808f6a598"
|
||||
|
||||
[[projects]]
|
||||
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"
|
||||
]
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "2d9486acae19cf9bd0c093d7dc236a323726a9e4"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [
|
||||
".",
|
||||
"balancer",
|
||||
"balancer/base",
|
||||
"balancer/roundrobin",
|
||||
"codes",
|
||||
"connectivity",
|
||||
"credentials",
|
||||
"encoding",
|
||||
"encoding/proto",
|
||||
"grpclb/grpc_lb_v1/messages",
|
||||
"grpclog",
|
||||
"internal",
|
||||
"keepalive",
|
||||
"metadata",
|
||||
"naming",
|
||||
"peer",
|
||||
"resolver",
|
||||
"resolver/dns",
|
||||
"resolver/passthrough",
|
||||
"stats",
|
||||
"status",
|
||||
"tap",
|
||||
"transport"
|
||||
]
|
||||
revision = "8e4536a86ab602859c20df5ebfd0bd4228d08655"
|
||||
version = "v1.10.0"
|
||||
|
||||
[[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/square/go-jose.v2"
|
||||
packages = [
|
||||
".",
|
||||
"cipher",
|
||||
"json",
|
||||
"jwt"
|
||||
]
|
||||
revision = "6ee92191fea850cdcab9a18867abf5f521cdbadb"
|
||||
version = "v2.1.4"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/warnings.v0"
|
||||
packages = ["."]
|
||||
revision = "ec4a0fea49c7b46c2aeb0b51aac55779c607e52b"
|
||||
version = "v0.1.2"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "7f97868eec74b32b0982dd158a51a446d1da7eb5"
|
||||
version = "v2.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/api"
|
||||
packages = [
|
||||
"admissionregistration/v1alpha1",
|
||||
"admissionregistration/v1beta1",
|
||||
"apps/v1",
|
||||
"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",
|
||||
"events/v1beta1",
|
||||
"extensions/v1beta1",
|
||||
"networking/v1",
|
||||
"policy/v1beta1",
|
||||
"rbac/v1",
|
||||
"rbac/v1alpha1",
|
||||
"rbac/v1beta1",
|
||||
"scheduling/v1alpha1",
|
||||
"settings/v1alpha1",
|
||||
"storage/v1",
|
||||
"storage/v1alpha1",
|
||||
"storage/v1beta1"
|
||||
]
|
||||
revision = "7aac3e00a1b32fa476b83078cebaaca606b2fb48"
|
||||
version = "kubernetes-1.10.0-beta.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apiextensions-apiserver"
|
||||
packages = ["pkg/features"]
|
||||
revision = "cfb732a3dd26c3e6349d0954e1209c9d5c093d1f"
|
||||
|
||||
[[projects]]
|
||||
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/v1beta1",
|
||||
"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 = "302974c03f7e50f16561ba237db776ab93594ef6"
|
||||
version = "kubernetes-1.10.0-beta.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apiserver"
|
||||
packages = [
|
||||
"pkg/authentication/authenticator",
|
||||
"pkg/authentication/serviceaccount",
|
||||
"pkg/authentication/user",
|
||||
"pkg/features",
|
||||
"pkg/util/feature"
|
||||
]
|
||||
revision = "74a8a89814a24637e718e271b747a717c24da88f"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/client-go"
|
||||
packages = [
|
||||
"discovery",
|
||||
"informers",
|
||||
"informers/admissionregistration",
|
||||
"informers/admissionregistration/v1alpha1",
|
||||
"informers/admissionregistration/v1beta1",
|
||||
"informers/apps",
|
||||
"informers/apps/v1",
|
||||
"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/events",
|
||||
"informers/events/v1beta1",
|
||||
"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/v1alpha1",
|
||||
"informers/storage/v1beta1",
|
||||
"kubernetes",
|
||||
"kubernetes/scheme",
|
||||
"kubernetes/typed/admissionregistration/v1alpha1",
|
||||
"kubernetes/typed/admissionregistration/v1beta1",
|
||||
"kubernetes/typed/apps/v1",
|
||||
"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/events/v1beta1",
|
||||
"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/v1alpha1",
|
||||
"kubernetes/typed/storage/v1beta1",
|
||||
"listers/admissionregistration/v1alpha1",
|
||||
"listers/admissionregistration/v1beta1",
|
||||
"listers/apps/v1",
|
||||
"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/events/v1beta1",
|
||||
"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/v1alpha1",
|
||||
"listers/storage/v1beta1",
|
||||
"pkg/version",
|
||||
"rest",
|
||||
"rest/watch",
|
||||
"tools/cache",
|
||||
"tools/clientcmd/api",
|
||||
"tools/metrics",
|
||||
"tools/pager",
|
||||
"tools/record",
|
||||
"tools/reference",
|
||||
"transport",
|
||||
"util/buffer",
|
||||
"util/cert",
|
||||
"util/flowcontrol",
|
||||
"util/integer",
|
||||
"util/retry"
|
||||
]
|
||||
revision = "78700dec6369ba22221b72770783300f143df150"
|
||||
version = "v6.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/kube-openapi"
|
||||
packages = ["pkg/util/proto"]
|
||||
revision = "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
|
||||
|
||||
[[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/master/ports",
|
||||
"pkg/scheduler/api",
|
||||
"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",
|
||||
"pkg/volume/util/fs",
|
||||
"pkg/volume/util/recyclerclient",
|
||||
"pkg/volume/util/types"
|
||||
]
|
||||
revision = "37555e6d24c2f951c40660ea59a80fa251982005"
|
||||
version = "v1.10.0-beta.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/utils"
|
||||
packages = ["exec"]
|
||||
revision = "258e2a2fa64568210fbd6267cf1d8fd87c3cb86e"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "8b43ab8306203b049af581d7567bd62d58b438ad31ada07c05ab0398c721a0fd"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
78
vendor/github.com/kubernetes-csi/drivers/Gopkg.toml
generated
vendored
78
vendor/github.com/kubernetes-csi/drivers/Gopkg.toml
generated
vendored
@ -1,78 +0,0 @@
|
||||
|
||||
# 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]]
|
||||
name = "github.com/container-storage-interface/spec"
|
||||
version = "~0.3.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
|
||||
[[override]]
|
||||
revision = "5db89f0ca68677abc5eefce8f2a0a772c98ba52d"
|
||||
name = "github.com/docker/distribution"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/gophercloud/gophercloud"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/pborman/uuid"
|
||||
version = "1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/spf13/cobra"
|
||||
version = "0.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "1.2.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/grpc"
|
||||
version = "1.10.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/gcfg.v1"
|
||||
version = "1.2.1"
|
||||
|
||||
[[constraint]]
|
||||
version = "kubernetes-1.10.0-beta.1"
|
||||
name = "k8s.io/apimachinery"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/kubernetes"
|
||||
version = "v1.10.0-beta.1"
|
||||
|
||||
[[override]]
|
||||
version = "kubernetes-1.10.0-beta.1"
|
||||
name = "k8s.io/api"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/golang/protobuf"
|
||||
version = "v1.1.0"
|
48
vendor/github.com/kubernetes-csi/drivers/Makefile
generated
vendored
48
vendor/github.com/kubernetes-csi/drivers/Makefile
generated
vendored
@ -1,48 +0,0 @@
|
||||
# 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.
|
||||
|
||||
REGISTRY_NAME=quay.io/k8scsi
|
||||
IMAGE_NAME=hostpathplugin
|
||||
IMAGE_VERSION=canary
|
||||
IMAGE_TAG=$(REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_VERSION)
|
||||
|
||||
.PHONY: all flexadapter nfs hostpath iscsi cinder clean hostpath-container
|
||||
|
||||
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 -vendor-only; fi
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o _output/flexadapter ./app/flexadapter
|
||||
nfs:
|
||||
if [ ! -d ./vendor ]; then dep ensure -vendor-only; fi
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o _output/nfsplugin ./app/nfsplugin
|
||||
hostpath:
|
||||
if [ ! -d ./vendor ]; then dep ensure -vendor-only; fi
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o _output/hostpathplugin ./app/hostpathplugin
|
||||
hostpath-container: hostpath
|
||||
docker build -t $(IMAGE_TAG) -f ./app/hostpathplugin/Dockerfile .
|
||||
push: hostpath-container
|
||||
docker push $(IMAGE_TAG)
|
||||
iscsi:
|
||||
if [ ! -d ./vendor ]; then dep ensure -vendor-only; fi
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o _output/iscsiplugin ./app/iscsiplugin
|
||||
cinder:
|
||||
if [ ! -d ./vendor ]; then dep ensure -vendor-only; fi
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o _output/cinderplugin ./app/cinderplugin
|
||||
clean:
|
||||
go clean -r -x
|
||||
-rm -rf _output
|
10
vendor/github.com/kubernetes-csi/drivers/README.md
generated
vendored
10
vendor/github.com/kubernetes-csi/drivers/README.md
generated
vendored
@ -1,10 +0,0 @@
|
||||
[](https://travis-ci.org/kubernetes-csi/drivers)
|
||||
# CSI Drivers
|
||||
|
||||
These drivers are provided purely for illustrative purposes, and should not be used for production workloads.
|
||||
|
||||
## Other sample drivers
|
||||
Please read [Drivers](https://kubernetes-csi.github.io/docs/Drivers.html) 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
72
vendor/github.com/kubernetes-csi/drivers/app/cinderplugin/main.go
generated
vendored
@ -1,72 +0,0 @@
|
||||
/*
|
||||
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
77
vendor/github.com/kubernetes-csi/drivers/app/flexadapter/main.go
generated
vendored
@ -1,77 +0,0 @@
|
||||
/*
|
||||
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.New()
|
||||
adapter.Run(driverName, driverPath, nodeID, endpoint)
|
||||
}
|
6
vendor/github.com/kubernetes-csi/drivers/app/hostpathplugin/Dockerfile
generated
vendored
6
vendor/github.com/kubernetes-csi/drivers/app/hostpathplugin/Dockerfile
generated
vendored
@ -1,6 +0,0 @@
|
||||
FROM alpine
|
||||
LABEL maintainers="Kubernetes Authors"
|
||||
LABEL description="HostPath Driver"
|
||||
|
||||
COPY ./_output/hostpathplugin /hostpathplugin
|
||||
ENTRYPOINT ["/hostpathplugin"]
|
46
vendor/github.com/kubernetes-csi/drivers/app/hostpathplugin/main.go
generated
vendored
46
vendor/github.com/kubernetes-csi/drivers/app/hostpathplugin/main.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
/*
|
||||
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
69
vendor/github.com/kubernetes-csi/drivers/app/iscsiplugin/main.go
generated
vendored
@ -1,69 +0,0 @@
|
||||
/*
|
||||
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
70
vendor/github.com/kubernetes-csi/drivers/app/nfsplugin/main.go
generated
vendored
@ -1,70 +0,0 @@
|
||||
/*
|
||||
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
3
vendor/github.com/kubernetes-csi/drivers/code-of-conduct.md
generated
vendored
@ -1,3 +0,0 @@
|
||||
# Kubernetes Community Code of Conduct
|
||||
|
||||
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
52
vendor/github.com/kubernetes-csi/drivers/hack/e2e-hostpath.sh
generated
vendored
52
vendor/github.com/kubernetes-csi/drivers/hack/e2e-hostpath.sh
generated
vendored
@ -1,52 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
## This file is for app/hostpathplugin
|
||||
## It could be used for other apps in this repo, but
|
||||
## those applications may or may not take the same
|
||||
## arguments
|
||||
|
||||
## Must be run from the root of the repo
|
||||
|
||||
UDS="/tmp/e2e-csi-sanity.sock"
|
||||
CSI_ENDPOINT="unix://${UDS}"
|
||||
CSI_MOUNTPOINT="/mnt"
|
||||
APP=hostpathplugin
|
||||
|
||||
SKIP="WithCapacity"
|
||||
if [ x${TRAVIS} = x"true" ] ; then
|
||||
SKIP="WithCapacity|NodeUnpublishVolume|NodePublishVolume"
|
||||
fi
|
||||
|
||||
# Get csi-sanity
|
||||
if [ ! -x $GOPATH/bin/csi-sanity ] ; then
|
||||
go get -u github.com/kubernetes-csi/csi-test
|
||||
pushd $GOPATH/src/github.com/kubernetes-csi/csi-test/cmd/csi-sanity
|
||||
make all
|
||||
make install
|
||||
popd
|
||||
#./hack/get-sanity.sh
|
||||
fi
|
||||
|
||||
# Build
|
||||
make hostpath
|
||||
|
||||
# Cleanup
|
||||
rm -f $UDS
|
||||
|
||||
# Start the application in the background
|
||||
sudo _output/$APP --endpoint=$CSI_ENDPOINT --nodeid=1 &
|
||||
pid=$!
|
||||
|
||||
# Need to skip Capacity testing since hostpath does not support it
|
||||
sudo $GOPATH/bin/csi-sanity $@ \
|
||||
--ginkgo.skip=${SKIP} \
|
||||
--csi.mountdir=$CSI_MOUNTPOINT \
|
||||
--csi.endpoint=$CSI_ENDPOINT ; ret=$?
|
||||
sudo kill -9 $pid
|
||||
sudo rm -f $UDS
|
||||
|
||||
if [ $ret -ne 0 ] ; then
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
exit 0
|
15
vendor/github.com/kubernetes-csi/drivers/hack/get-sanity.sh
generated
vendored
15
vendor/github.com/kubernetes-csi/drivers/hack/get-sanity.sh
generated
vendored
@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
VERSION="v0.1.0-2"
|
||||
SANITYTGZ="csi-sanity-${VERSION}.linux.amd64.tar.gz"
|
||||
|
||||
if [ ! -x $GOPATH/bin/csi-sanity ] ; then
|
||||
curl -s -L \
|
||||
https://github.com/kubernetes-csi/csi-test/releases/download/${VERSION}/${SANITYTGZ} \
|
||||
-o ${SANITYTGZ} && \
|
||||
tar xzvf ${SANITYTGZ} -C /tmp && \
|
||||
rm -f ${SANITYTGZ} && \
|
||||
cp /tmp/csi-sanity/csi-sanity $GOPATH/bin/csi-sanity && \
|
||||
rm -rf /tmp/csi-sanity
|
||||
fi
|
||||
|
91
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/README.md
generated
vendored
91
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/README.md
generated
vendored
@ -1,91 +0,0 @@
|
||||
# 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 using csc
|
||||
Get ```csc``` tool from https://github.com/rexray/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugin-info --endpoint tcp://127.0.0.1:10000
|
||||
"csi-cinderplugin" "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
172
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/controllerserver.go
generated
vendored
@ -1,172 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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/util"
|
||||
)
|
||||
|
||||
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(util.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{
|
||||
Volume: &csi.Volume{
|
||||
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{
|
||||
PublishInfo: 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
|
||||
}
|
172
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/controllerserver_test.go
generated
vendored
172
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/controllerserver_test.go
generated
vendored
@ -1,172 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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{
|
||||
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.Volume)
|
||||
|
||||
assert.NotEqual(0, len(actualRes.Volume.Id), "Volume Id is nil")
|
||||
|
||||
assert.Equal(fakeAvailability, actualRes.Volume.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{
|
||||
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{
|
||||
VolumeId: fakeVolID,
|
||||
NodeId: fakeNodeID,
|
||||
VolumeCapability: nil,
|
||||
Readonly: false,
|
||||
}
|
||||
|
||||
// Expected Result
|
||||
expectedRes := &csi.ControllerPublishVolumeResponse{
|
||||
PublishInfo: 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{
|
||||
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)
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
# 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: quay.io/k8scsi/csi-attacher:v0.3.0
|
||||
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: quay.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://csi/csi.sock
|
||||
- name: CLOUD_CONFIG
|
||||
value: /etc/config/cloud.conf
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /csi
|
||||
- name: secret-cinderplugin
|
||||
mountPath: /etc/config
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: socket-dir
|
||||
emptyDir:
|
||||
- name: secret-cinderplugin
|
||||
secret:
|
||||
secretName: csi-secret-cinderplugin
|
@ -1,37 +0,0 @@
|
||||
# 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
|
@ -1,90 +0,0 @@
|
||||
# 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: quay.io/k8scsi/driver-registrar:v0.3.0
|
||||
args:
|
||||
- "--v=5"
|
||||
- "--csi-address=$(ADDRESS)"
|
||||
env:
|
||||
- name: ADDRESS
|
||||
value: /csi/csi.sock
|
||||
- name: KUBE_NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /csi
|
||||
- name: cinder
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
add: ["SYS_ADMIN"]
|
||||
allowPrivilegeEscalation: true
|
||||
image: quay.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://csi/csi.sock
|
||||
- name: CLOUD_CONFIG
|
||||
value: /etc/config/cloud.conf
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /csi
|
||||
- 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: socket-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
|
@ -1,35 +0,0 @@
|
||||
# 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
|
@ -1,71 +0,0 @@
|
||||
# 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: quay.io/k8scsi/csi-provisioner:v0.3.0
|
||||
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: quay.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://csi/csi.sock
|
||||
- name: CLOUD_CONFIG
|
||||
value: /etc/config/cloud.conf
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
volumeMounts:
|
||||
- name: socket-dir
|
||||
mountPath: /csi
|
||||
- name: secret-cinderplugin
|
||||
mountPath: /etc/config
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: socket-dir
|
||||
emptyDir:
|
||||
- name: secret-cinderplugin
|
||||
secret:
|
||||
secretName: csi-secret-cinderplugin
|
@ -1,41 +0,0 @@
|
||||
# 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
|
@ -1,9 +0,0 @@
|
||||
# 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
13
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/dockerfile/Dockerfile
generated
vendored
@ -1,13 +0,0 @@
|
||||
# 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"]
|
84
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/driver.go
generated
vendored
84
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/driver.go
generated
vendored
@ -1,84 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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 = "0.3.0"
|
||||
)
|
||||
|
||||
func NewDriver(nodeID, endpoint string, cloudconfig string) *driver {
|
||||
glog.Infof("Driver: %v version: %v", driverName, version)
|
||||
|
||||
d := &driver{}
|
||||
|
||||
d.endpoint = endpoint
|
||||
d.cloudconfig = cloudconfig
|
||||
|
||||
csiDriver := csicommon.NewCSIDriver(driverName, version, 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
6
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/etc/cloud.conf
generated
vendored
@ -1,6 +0,0 @@
|
||||
[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
44
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/examples/kubernetes/nginx.yaml
generated
vendored
@ -1,44 +0,0 @@
|
||||
# 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
32
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/fake.go
generated
vendored
@ -1,32 +0,0 @@
|
||||
/*
|
||||
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 = ""
|
||||
var fakeAvailability = ""
|
||||
var fakeDevicePath = "/dev/xxx"
|
||||
var fakeTargetPath = "/mnt/cinder"
|
161
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/mount/mount.go
generated
vendored
161
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/mount/mount.go
generated
vendored
@ -1,161 +0,0 @@
|
||||
/*
|
||||
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
130
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/mount/mount_mock.go
generated
vendored
@ -1,130 +0,0 @@
|
||||
/*
|
||||
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
|
||||
}
|
167
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver.go
generated
vendored
167
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver.go
generated
vendored
@ -1,167 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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) NodeGetId(ctx context.Context, req *csi.NodeGetIdRequest) (*csi.NodeGetIdResponse, error) {
|
||||
|
||||
nodeID, err := getNodeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(nodeID) > 0 {
|
||||
return &csi.NodeGetIdResponse{
|
||||
NodeId: nodeID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Using default function
|
||||
return ns.DefaultNodeServer.NodeGetId(ctx, req)
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) {
|
||||
|
||||
nodeID, err := getNodeID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(nodeID) > 0 {
|
||||
return &csi.NodeGetInfoResponse{
|
||||
NodeId: nodeID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Using default function
|
||||
return ns.DefaultNodeServer.NodeGetInfo(ctx, req)
|
||||
}
|
||||
|
||||
func getNodeID() (string, error) {
|
||||
|
||||
// Get Mount Provider
|
||||
m, err := mount.GetMountProvider()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetMountProvider: %v", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
nodeID, err := m.GetInstanceID()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to GetInstanceID: %v", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
return nodeID, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
|
||||
|
||||
targetPath := req.GetTargetPath()
|
||||
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
||||
devicePath := req.GetPublishInfo()["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
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
168
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver_test.go
generated
vendored
168
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/nodeserver_test.go
generated
vendored
@ -1,168 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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 NodeGetId
|
||||
func TestNodeGetId(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.NodeGetIdResponse{
|
||||
NodeId: fakeNodeID,
|
||||
}
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.NodeGetIdRequest{}
|
||||
|
||||
// Invoke NodeGetId
|
||||
actualRes, err := fakeNs.NodeGetId(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to NodeGetId: %v", err)
|
||||
}
|
||||
|
||||
// Assert
|
||||
assert.Equal(expectedRes, actualRes)
|
||||
}
|
||||
|
||||
// Test NodeGetInfo
|
||||
func TestNodeGetInfo(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.NodeGetInfoResponse{
|
||||
NodeId: fakeNodeID,
|
||||
}
|
||||
|
||||
// Fake request
|
||||
fakeReq := &csi.NodeGetInfoRequest{}
|
||||
|
||||
// Invoke NodeGetId
|
||||
actualRes, err := fakeNs.NodeGetInfo(fakeCtx, fakeReq)
|
||||
if err != nil {
|
||||
t.Errorf("failed to NodeGetInfo: %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{
|
||||
VolumeId: fakeVolID,
|
||||
PublishInfo: 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{
|
||||
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
163
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack.go
generated
vendored
@ -1,163 +0,0 @@
|
||||
/*
|
||||
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
151
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_mock.go
generated
vendored
@ -1,151 +0,0 @@
|
||||
/*
|
||||
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
119
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_test.go
generated
vendored
@ -1,119 +0,0 @@
|
||||
/*
|
||||
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
253
vendor/github.com/kubernetes-csi/drivers/pkg/cinder/openstack/openstack_volumes.go
generated
vendored
@ -1,253 +0,0 @@
|
||||
/*
|
||||
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
|
||||
}
|
104
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/driver_test.go
generated
vendored
104
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/driver_test.go
generated
vendored
@ -1,104 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
fakeDriverName = "fake"
|
||||
fakeNodeID = "fakeNodeID"
|
||||
)
|
||||
|
||||
var (
|
||||
vendorVersion = "0.3.0"
|
||||
)
|
||||
|
||||
func NewFakeDriver() *CSIDriver {
|
||||
|
||||
driver := NewCSIDriver(fakeDriverName, vendorVersion, fakeNodeID)
|
||||
|
||||
return driver
|
||||
}
|
||||
|
||||
func TestNewFakeDriver(t *testing.T) {
|
||||
// Test New fake driver with invalid arguments.
|
||||
d := NewCSIDriver("", vendorVersion, fakeNodeID)
|
||||
assert.Nil(t, d)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
// Valid requests which require no capabilities
|
||||
err := d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_UNKNOWN)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service publish/unpublish not supported
|
||||
err = d.ValidateControllerServiceRequest(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(csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service create/delete is supported
|
||||
err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service list volumes is supported
|
||||
err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_LIST_VOLUMES)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test controller service get capacity is supported
|
||||
err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_GET_CAPACITY)
|
||||
assert.NoError(t, err)
|
||||
|
||||
}
|
37
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/identityserver-default_test.go
generated
vendored
37
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/identityserver-default_test.go
generated
vendored
@ -1,37 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetPluginInfo(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ids := NewDefaultIdentityServer(d)
|
||||
|
||||
req := csi.GetPluginInfoRequest{}
|
||||
resp, err := ids.GetPluginInfo(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, resp.GetName(), fakeDriverName)
|
||||
assert.Equal(t, resp.GetVendorVersion(), vendorVersion)
|
||||
}
|
88
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/nodeserver-default_test.go
generated
vendored
88
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/nodeserver-default_test.go
generated
vendored
@ -1,88 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func TestNodeGetId(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test valid request
|
||||
req := csi.NodeGetIdRequest{}
|
||||
resp, err := ns.NodeGetId(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, resp.GetNodeId(), fakeNodeID)
|
||||
}
|
||||
|
||||
func TestNodeGetInfo(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test valid request
|
||||
req := csi.NodeGetInfoRequest{}
|
||||
resp, err := ns.NodeGetInfo(context.Background(), &req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, resp.GetNodeId(), fakeNodeID)
|
||||
}
|
||||
|
||||
func TestNodeGetCapabilities(t *testing.T) {
|
||||
d := NewFakeDriver()
|
||||
|
||||
ns := NewDefaultNodeServer(d)
|
||||
|
||||
// Test valid request
|
||||
req := csi.NodeGetCapabilitiesRequest{}
|
||||
_, err := ns.NodeGetCapabilities(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.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.Unimplemented)
|
||||
}
|
76
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/utils_test.go
generated
vendored
76
vendor/github.com/kubernetes-csi/drivers/pkg/csi-common/utils_test.go
generated
vendored
@ -1,76 +0,0 @@
|
||||
/*
|
||||
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/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
36
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/README.md
generated
vendored
36
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/README.md
generated
vendored
@ -1,36 +0,0 @@
|
||||
# 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 ./pkg/flexadapter/examples/simplenfs-flexdriver/driver/nfs --nodeid CSINode -v=5
|
||||
```
|
||||
|
||||
### Test using csc
|
||||
Get ```csc``` tool from https://github.com/rexray/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugin-info --endpoint tcp://127.0.0.1:10000
|
||||
"simplenfs" "0.1.0"
|
||||
```
|
||||
|
||||
#### NodePublish a volume
|
||||
```
|
||||
$ csc node publish --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 unpublish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/nfs nfstestvol
|
||||
nfstestvol
|
||||
```
|
||||
|
||||
#### Get NodeID
|
||||
```
|
||||
$ csc node get-id --endpoint tcp://127.0.0.1:10000
|
||||
CSINode
|
||||
```
|
||||
|
95
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/controllerserver.go
generated
vendored
95
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/controllerserver.go
generated
vendored
@ -1,95 +0,0 @@
|
||||
/*
|
||||
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 (
|
||||
"github.com/container-storage-interface/spec/lib/go/csi/v0"
|
||||
"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 {
|
||||
flexDriver *flexVolumeDriver
|
||||
*csicommon.DefaultControllerServer
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ControllerPublishVolume(ctx context.Context, req *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) {
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cap := req.GetVolumeCapability()
|
||||
fsType := "ext4"
|
||||
if cap != nil {
|
||||
mount := req.GetVolumeCapability().GetMount()
|
||||
fsType = mount.FsType
|
||||
}
|
||||
|
||||
call := cs.flexDriver.NewDriverCall(attachCmd)
|
||||
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{
|
||||
PublishInfo: pvInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ControllerUnpublishVolume(ctx context.Context, req *csi.ControllerUnpublishVolumeRequest) (*csi.ControllerUnpublishVolumeResponse, error) {
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
call := cs.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
239
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/driver-call.go
generated
vendored
@ -1,239 +0,0 @@
|
||||
/*
|
||||
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
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
# 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```
|
@ -1,107 +0,0 @@
|
||||
# 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: quay.io/k8scsi/csi-attacher:v0.3.0
|
||||
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:
|
||||
|
@ -1,34 +0,0 @@
|
||||
# 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
|
@ -1,65 +0,0 @@
|
||||
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: quay.io/k8scsi/driver-registrar:v0.3.0
|
||||
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
|
@ -1,10 +0,0 @@
|
||||
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"]
|
@ -1,113 +0,0 @@
|
||||
#!/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
|
@ -1,52 +0,0 @@
|
||||
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
|
86
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexadapter.go
generated
vendored
86
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexadapter.go
generated
vendored
@ -1,86 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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 (
|
||||
version = "0.3.0"
|
||||
)
|
||||
|
||||
func New() *flexAdapter {
|
||||
return &flexAdapter{}
|
||||
}
|
||||
|
||||
func NewControllerServer(d *csicommon.CSIDriver, f *flexVolumeDriver) *controllerServer {
|
||||
return &controllerServer{
|
||||
flexDriver: f,
|
||||
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, version)
|
||||
|
||||
// Create flex volume driver
|
||||
f.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
|
||||
f.driver = csicommon.NewCSIDriver(driverName, version, nodeID)
|
||||
if f.flexDriver.capabilities.Attach {
|
||||
f.driver.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME})
|
||||
}
|
||||
f.driver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER})
|
||||
|
||||
// Create GRPC servers
|
||||
f.ns = NewNodeServer(f.driver, f.flexDriver)
|
||||
f.cs = NewControllerServer(f.driver, f.flexDriver)
|
||||
|
||||
csicommon.RunControllerandNodePublishServer(endpoint, f.driver, f.cs, f.ns)
|
||||
}
|
71
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexvolumedriver.go
generated
vendored
71
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/flexvolumedriver.go
generated
vendored
@ -1,71 +0,0 @@
|
||||
/*
|
||||
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,
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
170
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/nodeserver.go
generated
vendored
170
vendor/github.com/kubernetes-csi/drivers/pkg/flexadapter/nodeserver.go
generated
vendored
@ -1,170 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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(devicePath, targetPath, fsType, options)
|
||||
}
|
||||
|
||||
func (ns *nodeServer) waitForAttach(req *csi.NodePublishVolumeRequest, fsType string) error {
|
||||
|
||||
var dID string
|
||||
|
||||
if req.GetPublishInfo() != nil {
|
||||
var ok bool
|
||||
dID, ok = req.GetPublishInfo()[deviceID]
|
||||
if !ok {
|
||||
return status.Error(codes.InvalidArgument, "Missing device ID")
|
||||
}
|
||||
} else {
|
||||
return status.Error(codes.InvalidArgument, "Missing publish info and device ID")
|
||||
}
|
||||
|
||||
call := ns.flexDriver.NewDriverCall(waitForAttachCmd)
|
||||
call.Append(dID)
|
||||
call.AppendSpec(req.GetVolumeId(), fsType, req.GetReadonly(), req.GetVolumeAttributes())
|
||||
|
||||
_, err := call.Run()
|
||||
if isCmdNotSupportedErr(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
var call *DriverCall
|
||||
|
||||
// Attachable driver.
|
||||
if ns.flexDriver.capabilities.Attach {
|
||||
err = ns.waitForAttach(req, fsType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
call = ns.flexDriver.NewDriverCall(mountDeviceCmd)
|
||||
} else {
|
||||
call = ns.flexDriver.NewDriverCall(mountCmd)
|
||||
}
|
||||
|
||||
call.Append(req.GetTargetPath())
|
||||
|
||||
if req.GetPublishInfo() != nil {
|
||||
call.Append(req.GetPublishInfo()[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) {
|
||||
|
||||
var call *DriverCall
|
||||
if ns.flexDriver.capabilities.Attach {
|
||||
call = ns.flexDriver.NewDriverCall(unmountDeviceCmd)
|
||||
} else {
|
||||
call = ns.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())
|
||||
}
|
||||
|
||||
// WaitForDetach is ignored in current K8S plugins
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
58
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/README.md
generated
vendored
58
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/README.md
generated
vendored
@ -1,58 +0,0 @@
|
||||
# CSI Hostpath driver
|
||||
|
||||
## Usage:
|
||||
|
||||
### Build hostpathplugin
|
||||
```
|
||||
$ make hostpath
|
||||
```
|
||||
|
||||
### Start Hostpath driver
|
||||
```
|
||||
$ sudo ./_output/hostpathplugin --endpoint tcp://127.0.0.1:10000 --nodeid CSINode -v=5
|
||||
```
|
||||
|
||||
### Test using csc
|
||||
Get ```csc``` tool from https://github.com/rexray/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugin-info --endpoint tcp://127.0.0.1:10000
|
||||
"csi-hostpath" "0.1.0"
|
||||
```
|
||||
|
||||
#### Create a volume
|
||||
```
|
||||
$ csc controller new --endpoint tcp://127.0.0.1:10000 --cap 1,block CSIVolumeName
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### Delete a volume
|
||||
```
|
||||
$ csc controller del --endpoint tcp://127.0.0.1:10000 CSIVolumeID
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### Validate volume capabilities
|
||||
```
|
||||
$ csc controller validate-volume-capabilities --endpoint tcp://127.0.0.1:10000 --cap 1,block CSIVolumeID
|
||||
CSIVolumeID true
|
||||
```
|
||||
|
||||
#### NodePublish a volume
|
||||
```
|
||||
$ csc node publish --endpoint tcp://127.0.0.1:10000 --cap 1,block --target-path /mnt/hostpath CSIVolumeID
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### NodeUnpublish a volume
|
||||
```
|
||||
$ csc node unpublish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/hostpath CSIVolumeID
|
||||
CSIVolumeID
|
||||
```
|
||||
|
||||
#### Get NodeID
|
||||
```
|
||||
$ csc node get-id --endpoint tcp://127.0.0.1:10000
|
||||
CSINode
|
||||
```
|
141
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/controllerserver.go
generated
vendored
141
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/controllerserver.go
generated
vendored
@ -1,141 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi/v0"
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
const (
|
||||
deviceID = "deviceID"
|
||||
provisionRoot = "/tmp/"
|
||||
maxStorageCapacity = tib
|
||||
)
|
||||
|
||||
type controllerServer struct {
|
||||
*csicommon.DefaultControllerServer
|
||||
}
|
||||
|
||||
func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
|
||||
glog.V(3).Infof("invalid create volume req: %v", req)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check arguments
|
||||
if len(req.GetName()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Name missing in request")
|
||||
}
|
||||
if req.GetVolumeCapabilities() == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capabilities missing in request")
|
||||
}
|
||||
// Need to check for already existing volume name, and if found
|
||||
// check for the requested capacity and already allocated capacity
|
||||
if exVol, err := getVolumeByName(req.GetName()); err == nil {
|
||||
// Since err is nil, it means the volume with the same name already exists
|
||||
// need to check if the size of exisiting volume is the same as in new
|
||||
// request
|
||||
if exVol.VolSize >= int64(req.GetCapacityRange().GetRequiredBytes()) {
|
||||
// exisiting volume is compatible with new request and should be reused.
|
||||
// TODO (sbezverk) Do I need to make sure that RBD volume still exists?
|
||||
return &csi.CreateVolumeResponse{
|
||||
Volume: &csi.Volume{
|
||||
Id: exVol.VolID,
|
||||
CapacityBytes: int64(exVol.VolSize),
|
||||
Attributes: req.GetParameters(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("Volume with the same name: %s but with different size already exist", req.GetName()))
|
||||
}
|
||||
// Check for maximum available capacity
|
||||
capacity := int64(req.GetCapacityRange().GetRequiredBytes())
|
||||
if capacity >= maxStorageCapacity {
|
||||
return nil, status.Errorf(codes.OutOfRange, "Requested capacity %d exceeds maximum allowed %d", capacity, maxStorageCapacity)
|
||||
}
|
||||
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)
|
||||
hostPathVol := hostPathVolume{}
|
||||
hostPathVol.VolName = req.GetName()
|
||||
hostPathVol.VolID = volumeID
|
||||
hostPathVol.VolSize = capacity
|
||||
hostPathVol.VolPath = path
|
||||
hostPathVolumes[volumeID] = hostPathVol
|
||||
return &csi.CreateVolumeResponse{
|
||||
Volume: &csi.Volume{
|
||||
Id: volumeID,
|
||||
CapacityBytes: req.GetCapacityRange().GetRequiredBytes(),
|
||||
Attributes: req.GetParameters(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
|
||||
|
||||
// Check arguments
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||
}
|
||||
|
||||
if err := cs.Driver.ValidateControllerServiceRequest(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)
|
||||
delete(hostPathVolumes, volumeID)
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (cs *controllerServer) ValidateVolumeCapabilities(ctx context.Context, req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
|
||||
|
||||
// Check arguments
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||
}
|
||||
if req.GetVolumeCapabilities() == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume capabilities missing in request")
|
||||
}
|
||||
if _, ok := hostPathVolumes[req.GetVolumeId()]; !ok {
|
||||
return nil, status.Error(codes.NotFound, "Volume does not exist")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
123
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/hostpath.go
generated
vendored
123
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/hostpath.go
generated
vendored
@ -1,123 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi/v0"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/kubernetes-csi/drivers/pkg/csi-common"
|
||||
)
|
||||
|
||||
const (
|
||||
kib int64 = 1024
|
||||
mib int64 = kib * 1024
|
||||
gib int64 = mib * 1024
|
||||
gib100 int64 = gib * 100
|
||||
tib int64 = gib * 1024
|
||||
tib100 int64 = tib * 100
|
||||
)
|
||||
|
||||
type hostPath struct {
|
||||
driver *csicommon.CSIDriver
|
||||
|
||||
ids *identityServer
|
||||
ns *nodeServer
|
||||
cs *controllerServer
|
||||
|
||||
cap []*csi.VolumeCapability_AccessMode
|
||||
cscap []*csi.ControllerServiceCapability
|
||||
}
|
||||
|
||||
type hostPathVolume struct {
|
||||
VolName string `json:"volName"`
|
||||
VolID string `json:"volID"`
|
||||
VolSize int64 `json:"volSize"`
|
||||
VolPath string `json:"volPath"`
|
||||
}
|
||||
|
||||
var hostPathVolumes map[string]hostPathVolume
|
||||
|
||||
var (
|
||||
hostPathDriver *hostPath
|
||||
vendorVersion = "0.3.0"
|
||||
)
|
||||
|
||||
func init() {
|
||||
hostPathVolumes = map[string]hostPathVolume{}
|
||||
}
|
||||
|
||||
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 ", driverName)
|
||||
|
||||
// Initialize default library driver
|
||||
hp.driver = csicommon.NewCSIDriver(driverName, vendorVersion, nodeID)
|
||||
if hp.driver == nil {
|
||||
glog.Fatalln("Failed to initialize CSI Driver.")
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
func getVolumeByID(volumeID string) (hostPathVolume, error) {
|
||||
if hostPathVol, ok := hostPathVolumes[volumeID]; ok {
|
||||
return hostPathVol, nil
|
||||
}
|
||||
return hostPathVolume{}, fmt.Errorf("volume id %s does not exit in the volumes list", volumeID)
|
||||
}
|
||||
|
||||
func getVolumeByName(volName string) (hostPathVolume, error) {
|
||||
for _, hostPathVol := range hostPathVolumes {
|
||||
if hostPathVol.VolName == volName {
|
||||
return hostPathVol, nil
|
||||
}
|
||||
}
|
||||
return hostPathVolume{}, fmt.Errorf("volume name %s does not exit in the volumes list", volName)
|
||||
}
|
25
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/identityserver.go
generated
vendored
25
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/identityserver.go
generated
vendored
@ -1,25 +0,0 @@
|
||||
/*
|
||||
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
|
||||
}
|
141
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/nodeserver.go
generated
vendored
141
vendor/github.com/kubernetes-csi/drivers/pkg/hostpath/nodeserver.go
generated
vendored
@ -1,141 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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) {
|
||||
|
||||
// Check arguments
|
||||
if req.GetVolumeCapability() == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume capability missing in request")
|
||||
}
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||
}
|
||||
if len(req.GetTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target path missing in request")
|
||||
}
|
||||
|
||||
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.GetPublishInfo() != nil {
|
||||
deviceId = req.GetPublishInfo()[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\nvolumeId %v\nattributes %v\nmountflags %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) {
|
||||
|
||||
// Check arguments
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||
}
|
||||
if len(req.GetTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target path missing in request")
|
||||
}
|
||||
targetPath := req.GetTargetPath()
|
||||
volumeID := req.GetVolumeId()
|
||||
|
||||
// Unmounting the image
|
||||
err := mount.New("").Unmount(req.GetTargetPath())
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
glog.V(4).Infof("hostpath: volume %s/%s has been unmounted.", targetPath, volumeID)
|
||||
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
|
||||
|
||||
// Check arguments
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||
}
|
||||
if len(req.GetStagingTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target path missing in request")
|
||||
}
|
||||
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
|
||||
|
||||
// Check arguments
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||
}
|
||||
if len(req.GetStagingTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target path missing in request")
|
||||
}
|
||||
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
37
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/README.md
generated
vendored
37
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/README.md
generated
vendored
@ -1,37 +0,0 @@
|
||||
# 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/rexray/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugin-info --endpoint tcp://127.0.0.1:10000
|
||||
"ISCSI" "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
|
||||
```
|
68
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/driver.go
generated
vendored
68
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/driver.go
generated
vendored
@ -1,68 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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 = "0.3.0"
|
||||
)
|
||||
|
||||
func NewDriver(nodeID, endpoint string) *driver {
|
||||
glog.Infof("Driver: %v version: %v", driverName, version)
|
||||
|
||||
d := &driver{}
|
||||
|
||||
d.endpoint = endpoint
|
||||
|
||||
csiDriver := csicommon.NewCSIDriver(driverName, version, 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
148
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/iscsi.go
generated
vendored
@ -1,148 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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
|
||||
}
|
477
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/iscsi_util.go
generated
vendored
477
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/iscsi_util.go
generated
vendored
@ -1,477 +0,0 @@
|
||||
/*
|
||||
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 := b.targetPath
|
||||
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 {
|
||||
_, cnt, err := mount.GetDeviceNameFromMount(c.mounter, targetPath)
|
||||
if err != nil {
|
||||
glog.Errorf("iscsi detach disk: failed to get device from mnt: %s\nError: %v", targetPath, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if pathExists, pathErr := volumeutil.PathExists(targetPath); 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", targetPath)
|
||||
return nil
|
||||
}
|
||||
if err = c.mounter.Unmount(targetPath); err != nil {
|
||||
glog.Errorf("iscsi detach disk: failed to unmount: %s\nError: %v", targetPath, 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
|
||||
}
|
67
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/nodeserver.go
generated
vendored
67
vendor/github.com/kubernetes-csi/drivers/pkg/iscsi/nodeserver.go
generated
vendored
@ -1,67 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
69
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/README.md
generated
vendored
69
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/README.md
generated
vendored
@ -1,69 +0,0 @@
|
||||
# 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
|
||||
|
||||
### Build nfsplugin
|
||||
```
|
||||
$ make nfs
|
||||
```
|
||||
|
||||
### Start NFS driver
|
||||
```
|
||||
$ sudo ./_output/nfsplugin --endpoint tcp://127.0.0.1:10000 --nodeid CSINode -v=5
|
||||
```
|
||||
|
||||
## Test
|
||||
Get ```csc``` tool from https://github.com/rexray/gocsi/tree/master/csc
|
||||
|
||||
#### Get plugin info
|
||||
```
|
||||
$ csc identity plugin-info --endpoint tcp://127.0.0.1:10000
|
||||
"NFS" "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 publish --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 unpublish --endpoint tcp://127.0.0.1:10000 --target-path /mnt/nfs nfstestvol
|
||||
nfstestvol
|
||||
```
|
||||
|
||||
#### Get NodeID
|
||||
```
|
||||
$ csc node get-id --endpoint tcp://127.0.0.1:10000
|
||||
CSINode
|
||||
```
|
||||
|
@ -1,64 +0,0 @@
|
||||
# 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: quay.io/k8scsi/csi-attacher:v0.3.0
|
||||
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: quay.io/k8scsi/nfsplugin:v0.3.0
|
||||
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:
|
||||
|
@ -1,37 +0,0 @@
|
||||
# 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
|
@ -1,66 +0,0 @@
|
||||
# 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: quay.io/k8scsi/driver-registrar:v0.3.0
|
||||
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: quay.io/k8scsi/nfsplugin:v0.3.0
|
||||
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
|
@ -1,34 +0,0 @@
|
||||
# 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
8
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/dockerfile/Dockerfile
generated
vendored
@ -1,8 +0,0 @@
|
||||
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"]
|
78
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/driver.go
generated
vendored
78
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/driver.go
generated
vendored
@ -1,78 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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 = "0.3.0"
|
||||
)
|
||||
|
||||
func NewDriver(nodeID, endpoint string) *driver {
|
||||
glog.Infof("Driver: %v version: %v", driverName, version)
|
||||
|
||||
d := &driver{}
|
||||
|
||||
d.endpoint = endpoint
|
||||
|
||||
csiDriver := csicommon.NewCSIDriver(driverName, version, nodeID)
|
||||
csiDriver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER})
|
||||
// NFS plugin does not support ControllerServiceCapability now.
|
||||
// If support is added, it should set to appropriate
|
||||
// ControllerServiceCapability RPC types.
|
||||
csiDriver.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{csi.ControllerServiceCapability_RPC_UNKNOWN})
|
||||
|
||||
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),
|
||||
// NFS plugin has not implemented ControllerServer.
|
||||
nil,
|
||||
NewNodeServer(d))
|
||||
s.Wait()
|
||||
}
|
53
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/examples/kubernetes/nginx.yaml
generated
vendored
53
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/examples/kubernetes/nginx.yaml
generated
vendored
@ -1,53 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: data-nfsplugin
|
||||
labels:
|
||||
name: data-nfsplugin
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
capacity:
|
||||
storage: 100Gi
|
||||
csi:
|
||||
driver: csi-nfsplugin
|
||||
volumeHandle: data-id
|
||||
volumeAttributes:
|
||||
server: 127.0.0.1
|
||||
share: /export
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: data-nfsplugin
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
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
|
109
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/nodeserver.go
generated
vendored
109
vendor/github.com/kubernetes-csi/drivers/pkg/nfs/nodeserver.go
generated
vendored
@ -1,109 +0,0 @@
|
||||
/*
|
||||
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/v0"
|
||||
"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()["share"]
|
||||
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
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
Reference in New Issue
Block a user