diff --git a/CHANGELOG-0.x.md b/CHANGELOG-0.x.md index 0a47da90..4d19f165 100644 --- a/CHANGELOG-0.x.md +++ b/CHANGELOG-0.x.md @@ -1,3 +1,6 @@ +#v0.8.2 +* Add Idempotent check for mounting node volume ([#246](https://github.com/kubernetes-sigs/aws-fsx-csi-driver/pull/246), [@amankhunt](https://github.com/amankhunt)) + # v0.8.1 * Updating to latest AL2 base image. diff --git a/Makefile b/Makefile index 183a35f7..9b141c03 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -VERSION=v0.8.1 +VERSION=v0.8.2 PKG=github.com/kubernetes-sigs/aws-fsx-csi-driver GIT_COMMIT?=$(shell git rev-parse HEAD) diff --git a/docs/README.md b/docs/README.md index bddef6eb..1d23b37b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,19 +8,20 @@ The [Amazon FSx for Lustre](https://aws.amazon.com/fsx/lustre/) Container Storage Interface (CSI) Driver implements [CSI](https://github.com/container-storage-interface/spec/blob/master/spec.md) specification for container orchestrators (CO) to manage lifecycle of Amazon FSx for Lustre filesystems. ### CSI Specification Compability Matrix -| AWS FSx for Lustre CSI Driver \ CSI Version | v0.3.0| v1.x.x | -|---------------------------------------------------|-------|--------| -| master branch | no | yes | -| v0.8.1 | no | yes | -| v0.8.0 | no | yes | -| v0.7.1 | no | yes | -| v0.7.0 | no | yes | -| v0.6.0 | no | yes | -| v0.5.0 | no | yes | -| v0.4.0 | no | yes | -| v0.3.0 | no | yes | -| v0.2.0 | no | yes | -| v0.1.0 | yes | no | +| AWS FSx for Lustre CSI Driver \ CSI Version | v0.3.0 | v1.x.x | +|---------------------------------------------|--------|--------| +| master branch | no | yes | +| v0.8.2 | no | yes | +| v0.8.1 | no | yes | +| v0.8.0 | no | yes | +| v0.7.1 | no | yes | +| v0.7.0 | no | yes | +| v0.6.0 | no | yes | +| v0.5.0 | no | yes | +| v0.4.0 | no | yes | +| v0.3.0 | no | yes | +| v0.2.0 | no | yes | +| v0.1.0 | yes | no | ### Features The following CSI interfaces are implemented: @@ -32,34 +33,36 @@ The following CSI interfaces are implemented: The following sections are Kubernetes-specific. If you are a Kubernetes user, use the following for driver features, installation steps and examples. ### Kubernetes Version Compability Matrix -| AWS FSx for Lustre CSI Driver \ Kubernetes Version| v1.11 | v1.12 | v1.13 | v1.14-16 | v1.17+ | -|---------------------------------------------------|-------|-------|-------|----------|--------| -| master branch | no | no | no | no | yes | -| v0.8.1 | no | no | no | no | yes | -| v0.8.0 | no | no | no | no | yes | -| v0.7.1 | no | no | no | no | yes | -| v0.7.0 | no | no | no | no | yes | -| v0.6.0 | no | no | no | no | yes | -| v0.5.0 | no | no | no | no | yes | -| v0.4.0 | no | no | no | yes | yes | -| v0.3.0 | no | no | no | yes | yes | -| v0.2.0 | no | no | no | yes | yes | -| v0.1.0 | yes | yes | yes | no | no | +| AWS FSx for Lustre CSI Driver \ Kubernetes Version | v1.11 | v1.12 | v1.13 | v1.14-16 | v1.17+ | +|----------------------------------------------------|-------|-------|-------|----------|--------| +| master branch | no | no | no | no | yes | +| v0.8.2 | no | no | no | no | yes | +| v0.8.1 | no | no | no | no | yes | +| v0.8.0 | no | no | no | no | yes | +| v0.7.1 | no | no | no | no | yes | +| v0.7.0 | no | no | no | no | yes | +| v0.6.0 | no | no | no | no | yes | +| v0.5.0 | no | no | no | no | yes | +| v0.4.0 | no | no | no | yes | yes | +| v0.3.0 | no | no | no | yes | yes | +| v0.2.0 | no | no | no | yes | yes | +| v0.1.0 | yes | yes | yes | no | no | ### Container Images -|FSx CSI Driver Version | Image | -|---------------------------|-------------------------------------| -|master branch |amazon/aws-fsx-csi-driver:latest | -|v0.8.1 |amazon/aws-fsx-csi-driver:v0.8.1 | -|v0.8.0 |amazon/aws-fsx-csi-driver:v0.8.0 | -|v0.7.1 |amazon/aws-fsx-csi-driver:v0.7.1 | -|v0.7.0 |amazon/aws-fsx-csi-driver:v0.7.0 | -|v0.6.0 |amazon/aws-fsx-csi-driver:v0.6.0 | -|v0.5.0 |amazon/aws-fsx-csi-driver:v0.5.0 | -|v0.4.0 |amazon/aws-fsx-csi-driver:v0.4.0 | -|v0.3.0 |amazon/aws-fsx-csi-driver:v0.3.0 | -|v0.2.0 |amazon/aws-fsx-csi-driver:v0.2.0 | -|v0.1.0 |amazon/aws-fsx-csi-driver:v0.1.0 | +| FSx CSI Driver Version | Image | +|------------------------|----------------------------------| +| master branch | amazon/aws-fsx-csi-driver:latest | +| v0.8.2 | amazon/aws-fsx-csi-driver:v0.8.2 | +| v0.8.1 | amazon/aws-fsx-csi-driver:v0.8.1 | +| v0.8.0 | amazon/aws-fsx-csi-driver:v0.8.0 | +| v0.7.1 | amazon/aws-fsx-csi-driver:v0.7.1 | +| v0.7.0 | amazon/aws-fsx-csi-driver:v0.7.0 | +| v0.6.0 | amazon/aws-fsx-csi-driver:v0.6.0 | +| v0.5.0 | amazon/aws-fsx-csi-driver:v0.5.0 | +| v0.4.0 | amazon/aws-fsx-csi-driver:v0.4.0 | +| v0.3.0 | amazon/aws-fsx-csi-driver:v0.3.0 | +| v0.2.0 | amazon/aws-fsx-csi-driver:v0.2.0 | +| v0.1.0 | amazon/aws-fsx-csi-driver:v0.1.0 | ### Features * Static provisioning - FSx for Lustre file system needs to be created manually first, then it could be mounted inside container as a volume using the Driver. diff --git a/go.mod b/go.mod index a6658d14..835f4aa2 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,13 @@ module github.com/kubernetes-sigs/aws-fsx-csi-driver require ( github.com/aws/aws-sdk-go v1.40.57 github.com/container-storage-interface/spec v1.2.0 - github.com/golang/mock v1.3.1 + github.com/golang/mock v1.6.0 + github.com/golang/protobuf v1.5.2 // indirect github.com/kubernetes-csi/csi-test v2.0.1+incompatible github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.16.0 google.golang.org/grpc v1.23.1 + google.golang.org/protobuf v1.28.0 // indirect k8s.io/api v0.17.0 k8s.io/apimachinery v0.17.0 k8s.io/client-go v0.17.0 diff --git a/go.sum b/go.sum index b7bb3994..d0d88009 100644 --- a/go.sum +++ b/go.sum @@ -214,6 +214,8 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -533,6 +535,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= @@ -578,6 +581,8 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -604,6 +609,7 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -620,6 +626,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -649,8 +656,11 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -695,6 +705,8 @@ golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -727,6 +739,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/hack/e2e/run.sh b/hack/e2e/run.sh index 6ac608da..0831c157 100755 --- a/hack/e2e/run.sh +++ b/hack/e2e/run.sh @@ -105,7 +105,7 @@ loudecho "Installing ginkgo to ${BIN_DIR}" GINKGO_BIN=${BIN_DIR}/ginkgo if [[ ! -e ${GINKGO_BIN} ]]; then pushd /tmp - GOPATH=${TEST_DIR} GOBIN=${BIN_DIR} GO111MODULE=on go get github.com/onsi/ginkgo/ginkgo@v1.12.0 + GOPATH=${TEST_DIR} GOBIN=${BIN_DIR} GO111MODULE=on go install github.com/onsi/ginkgo/ginkgo@v1.12.0 popd fi diff --git a/hack/update-gomock b/hack/update-gomock index 2c271d21..b2508f4d 100755 --- a/hack/update-gomock +++ b/hack/update-gomock @@ -17,7 +17,7 @@ set -euo pipefail IMPORT_PATH=github.com/kubernetes-sigs/aws-fsx-csi-driver -mockgen -package=mocks -destination=./pkg/driver/mocks/mock_mount.go ${IMPORT_PATH}/pkg/driver Mounter -mockgen -package=mocks -destination=./pkg/cloud/mocks/mock_ec2metadata.go ${IMPORT_PATH}/pkg/cloud EC2Metadata -mockgen -package=mocks -destination=./pkg/cloud/mocks/mock_fsx.go ${IMPORT_PATH}/pkg/cloud FSx -mockgen -package=mocks -destination=./pkg/driver/mocks/mock_cloud.go ${IMPORT_PATH}/pkg/cloud Cloud +mockgen -package=mocks -destination=./pkg/driver/mocks/mock_mount.go --build_flags=--mod=mod ${IMPORT_PATH}/pkg/driver Mounter +mockgen -package=mocks -destination=./pkg/cloud/mocks/mock_ec2metadata.go --build_flags=--mod=mod ${IMPORT_PATH}/pkg/cloud EC2Metadata +mockgen -package=mocks -destination=./pkg/cloud/mocks/mock_fsx.go --build_flags=--mod=mod ${IMPORT_PATH}/pkg/cloud FSx +mockgen -package=mocks -destination=./pkg/driver/mocks/mock_cloud.go --build_flags=--mod=mod ${IMPORT_PATH}/pkg/cloud Cloud diff --git a/pkg/driver/mocks/mock_mount.go b/pkg/driver/mocks/mock_mount.go index c6c958ae..6ddf2f5e 100644 --- a/pkg/driver/mocks/mock_mount.go +++ b/pkg/driver/mocks/mock_mount.go @@ -28,6 +28,35 @@ func NewMockMounter(ctrl *gomock.Controller) *MockMounter { return mock } +// IsCorruptedMnt mocks base method. +func (m *MockMounter) IsCorruptedMnt(err error) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsCorruptedMnt", err) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsCorruptedMnt indicates an expected call of IsCorruptedMnt. +func (mr *MockMounterMockRecorder) IsCorruptedMnt(err interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsCorruptedMnt", reflect.TypeOf((*MockMounter)(nil).IsCorruptedMnt), err) +} + +// PathExists mocks base method. +func (m *MockMounter) PathExists(path string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PathExists", path) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// PathExists indicates an expected call of PathExists. +func (mr *MockMounterMockRecorder) PathExists(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PathExists", reflect.TypeOf((*MockMounter)(nil).PathExists), path) +} + // EXPECT returns an object that allows the caller to indicate expected use func (m *MockMounter) EXPECT() *MockMounterMockRecorder { return m.recorder diff --git a/pkg/driver/mount.go b/pkg/driver/mount.go index 296742c1..77a99773 100644 --- a/pkg/driver/mount.go +++ b/pkg/driver/mount.go @@ -17,14 +17,15 @@ limitations under the License. package driver import ( - "os" - "k8s.io/utils/mount" + "os" ) // Mounter is an interface for mount operations type Mounter interface { mount.Interface + IsCorruptedMnt(err error) bool + PathExists(path string) (bool, error) MakeDir(pathname string) error } @@ -47,3 +48,17 @@ func (m *NodeMounter) MakeDir(pathname string) error { } return nil } + +//IsCorruptedMnt return true if err is about corrupted mount point +func (m *NodeMounter) IsCorruptedMnt(err error) bool { + return mount.IsCorruptedMnt(err) +} + +func (m *NodeMounter) PathExists(path string) (bool, error) { + if _, err := os.Stat(path); os.IsNotExist(err) { + return false, nil + } else if err != nil { + return false, err + } + return true, nil +} diff --git a/pkg/driver/node.go b/pkg/driver/node.go index 4ef07c5e..de6c94b9 100644 --- a/pkg/driver/node.go +++ b/pkg/driver/node.go @@ -100,10 +100,18 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu return nil, status.Errorf(codes.Internal, "Could not create dir %q: %v", target, err) } - klog.V(5).Infof("NodePublishVolume: mounting %s at %s with options %v", source, target, mountOptions) - if err := d.mounter.Mount(source, target, "lustre", mountOptions); err != nil { - os.Remove(target) - return nil, status.Errorf(codes.Internal, "Could not mount %q at %q: %v", source, target, err) + //Checking if the target directory is already mounted with a volume. + mounted, err := d.isMounted(source, target) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not check if %q is mounted: %v", target, err) + } + if !mounted { + klog.V(5).Infof("NodePublishVolume: mounting %s at %s with options %v", source, target, mountOptions) + if err := d.mounter.Mount(source, target, "lustre", mountOptions); err != nil { + os.Remove(target) + return nil, status.Errorf(codes.Internal, "Could not mount %q at %q: %v", source, target, err) + } + klog.V(5).Infof("NodePublishVolume: %s was mounted", target) } return &csi.NodePublishVolumeResponse{}, nil @@ -161,3 +169,46 @@ func (d *Driver) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRequest) ( NodeId: d.nodeID, }, nil } + +// isMounted checks if target is mounted. It does NOT return an error if target +// doesn't exist. +func (d *Driver) isMounted(source string, target string) (bool, error) { + /* + Checking if it's a mount point using IsLikelyNotMountPoint. There are three different return values, + 1. true, err when the directory does not exist or corrupted. + 2. false, nil when the path is already mounted with a device. + 3. true, nil when the path is not mounted with any device. + */ + klog.V(4).Infoln(target) + notMnt, err := d.mounter.IsLikelyNotMountPoint(target) + if err != nil && !os.IsNotExist(err) { + //Checking if the path exists and error is related to Corrupted Mount, in that case, the system could unmount and mount. + _, pathErr := d.mounter.PathExists(target) + if pathErr != nil && d.mounter.IsCorruptedMnt(pathErr) { + klog.V(4).Infof("NodePublishVolume: Target path %q is a corrupted mount. Trying to unmount.", target) + if mntErr := d.mounter.Unmount(target); mntErr != nil { + return false, status.Errorf(codes.Internal, "Unable to unmount the target %q : %v", target, mntErr) + } + //After successful unmount, the device is ready to be mounted. + return false, nil + } + return false, status.Errorf(codes.Internal, "Could not check if %q is a mount point: %v, %v", target, err, pathErr) + } + + // Do not return os.IsNotExist error. Other errors were handled above. The + // Existence of the target should be checked by the caller explicitly and + // independently because sometimes prior to mount it is expected not to exist + // (in Windows, the target must NOT exist before a symlink is created at it) + // and in others it is an error (in Linux, the target mount directory must + // exist before mount is called on it) + if err != nil && os.IsNotExist(err) { + klog.V(5).Infof("[Debug] NodePublishVolume: Target path %q does not exist", target) + return false, nil + } + + if !notMnt { + klog.V(4).Infof("NodePublishVolume: Target path %q is already mounted", target) + } + + return !notMnt, nil +} diff --git a/pkg/driver/node_test.go b/pkg/driver/node_test.go index 91cb866f..89a3c165 100644 --- a/pkg/driver/node_test.go +++ b/pkg/driver/node_test.go @@ -72,6 +72,7 @@ func TestNodePublishVolume(t *testing.T) { } mockMounter.EXPECT().MakeDir(gomock.Eq(targetPath)).Return(nil) + mockMounter.EXPECT().IsLikelyNotMountPoint(gomock.Eq(targetPath)).Return(true, nil) mockMounter.EXPECT().Mount(gomock.Eq(source), gomock.Eq(targetPath), gomock.Eq("lustre"), gomock.Any()).Return(nil) _, err := driver.NodePublishVolume(ctx, req) if err != nil { @@ -104,6 +105,7 @@ func TestNodePublishVolume(t *testing.T) { } mockMounter.EXPECT().MakeDir(gomock.Eq(targetPath)).Return(nil) + mockMounter.EXPECT().IsLikelyNotMountPoint(gomock.Eq(targetPath)).Return(true, nil) mockMounter.EXPECT().Mount(gomock.Eq(source), gomock.Eq(targetPath), gomock.Eq("lustre"), gomock.Any()).Return(nil) _, err := driver.NodePublishVolume(ctx, req) if err != nil { @@ -139,6 +141,7 @@ func TestNodePublishVolume(t *testing.T) { } mockMounter.EXPECT().MakeDir(gomock.Eq(targetPath)).Return(nil) + mockMounter.EXPECT().IsLikelyNotMountPoint(gomock.Eq(targetPath)).Return(true, nil) mockMounter.EXPECT().Mount(gomock.Eq(source), gomock.Eq(targetPath), gomock.Eq("lustre"), gomock.Eq([]string{"ro"})).Return(nil) _, err := driver.NodePublishVolume(ctx, req) if err != nil { @@ -182,6 +185,7 @@ func TestNodePublishVolume(t *testing.T) { } mockMounter.EXPECT().MakeDir(gomock.Eq(targetPath)).Return(nil) + mockMounter.EXPECT().IsLikelyNotMountPoint(gomock.Eq(targetPath)).Return(true, nil) mockMounter.EXPECT().Mount(gomock.Eq(source), gomock.Eq(targetPath), gomock.Eq("lustre"), gomock.Eq([]string{"flock"})).Return(nil) _, err := driver.NodePublishVolume(ctx, req) if err != nil { @@ -371,9 +375,9 @@ func TestNodePublishVolume(t *testing.T) { } source := dnsname + "@tcp:/" + mountname - err := fmt.Errorf("failed to Mount") mockMounter.EXPECT().MakeDir(gomock.Eq(targetPath)).Return(nil) + mockMounter.EXPECT().IsLikelyNotMountPoint(gomock.Eq(targetPath)).Return(true, nil) mockMounter.EXPECT().Mount(gomock.Eq(source), gomock.Eq(targetPath), gomock.Eq("lustre"), gomock.Any()).Return(err) _, err = driver.NodePublishVolume(ctx, req) diff --git a/vendor/modules.txt b/vendor/modules.txt index dd26c842..e127d017 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -82,10 +82,11 @@ github.com/gogo/protobuf/protoc-gen-gogo/descriptor github.com/gogo/protobuf/sortkeys # github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 github.com/golang/groupcache/lru -# github.com/golang/mock v1.3.1 +# github.com/golang/mock v1.6.0 ## explicit github.com/golang/mock/gomock # github.com/golang/protobuf v1.5.2 +## explicit github.com/golang/protobuf/proto github.com/golang/protobuf/protoc-gen-go/descriptor github.com/golang/protobuf/ptypes @@ -248,7 +249,7 @@ golang.org/x/net/websocket # golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sys v0.0.0-20210423082822-04245dca01da +# golang.org/x/sys v0.0.0-20210510120138-977fb7262007 golang.org/x/sys/cpu golang.org/x/sys/internal/unsafeheader golang.org/x/sys/unix @@ -321,7 +322,8 @@ google.golang.org/grpc/serviceconfig google.golang.org/grpc/stats google.golang.org/grpc/status google.golang.org/grpc/tap -# google.golang.org/protobuf v1.26.0 +# google.golang.org/protobuf v1.28.0 +## explicit google.golang.org/protobuf/encoding/prototext google.golang.org/protobuf/encoding/protowire google.golang.org/protobuf/internal/descfmt