diff --git a/Makefile b/Makefile index 4b27751db..1d898fcc4 100644 --- a/Makefile +++ b/Makefile @@ -17,15 +17,23 @@ STAGINGIMAGE=${GCE_PD_CSI_STAGING_IMAGE} STAGINGVERSION=${GCE_PD_CSI_STAGING_VERSION} +DRIVERBINARY=gce-pd-csi-driver +DRIVERWINDOWSBINARY=${DRIVERBINARY}.exe all: gce-pd-driver - gce-pd-driver: mkdir -p bin ifndef GCE_PD_CSI_STAGING_VERSION $(error "Must set environment variable GCE_PD_CSI_STAGING_VERSION to staging version") endif - go build -ldflags "-X main.vendorVersion=${STAGINGVERSION}" -o bin/gce-pd-csi-driver ./cmd/ + go build -ldflags "-X main.vendorVersion=${STAGINGVERSION}" -o bin/${DRIVERBINARY} ./cmd/ + +build-windows: + mkdir -p bin +ifndef GCE_PD_CSI_STAGING_VERSION + $(error "Must set environment variable GCE_PD_CSI_STAGING_VERSION to staging version") +endif + GOOS=windows go build -ldflags "-X main.vendorVersion=${STAGINGVERSION}" -o bin/${DRIVERWINDOWSBINARY} ./cmd/ build-container: ifndef GCE_PD_CSI_STAGING_IMAGE diff --git a/cmd/main.go b/cmd/main.go index 1ee0c3c4d..88e640f97 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -90,7 +90,10 @@ func handle() { //Initialize requirements for the node service var nodeServer *driver.GCENodeServer if *runNodeService { - mounter := mountmanager.NewSafeMounter() + mounter, err := mountmanager.NewSafeMounter() + if err != nil { + klog.Fatalf("Failed to get safe mounter: %v", err) + } deviceUtils := mountmanager.NewDeviceUtils() statter := mountmanager.NewStatter() meta, err := metadataservice.NewMetadataService() diff --git a/go.mod b/go.mod index 89355638d..59a6b4060 100644 --- a/go.mod +++ b/go.mod @@ -6,17 +6,19 @@ require ( cloud.google.com/go v0.45.1 github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190612171043-2e19bb35a278 github.com/container-storage-interface/spec v1.2.0 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.3.4 github.com/google/uuid v1.1.1 github.com/hashicorp/go-multierror v1.0.0 // indirect + github.com/kubernetes-csi/csi-proxy/client v0.0.0-20200330215040-9eff16441b2a github.com/kubernetes-csi/csi-test/v3 v3.0.0 github.com/onsi/ginkgo v1.10.3 github.com/onsi/gomega v1.7.1 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 + golang.org/x/tools/gopls v0.3.3 // indirect google.golang.org/api v0.10.0 google.golang.org/genproto v0.0.0-20191114150713-6bbd007550de - google.golang.org/grpc v1.25.1 + google.golang.org/grpc v1.27.1 gopkg.in/gcfg.v1 v1.2.3 gopkg.in/warnings.v0 v0.1.2 // indirect k8s.io/apimachinery v0.17.1 diff --git a/go.sum b/go.sum index 905a8295f..749cc7491 100644 --- a/go.sum +++ b/go.sum @@ -22,11 +22,13 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190612171043-2e19bb35a278 h1:TgNrmegr5ot2LQQLFikl4VFrPvTvlOB2zCShOcpa+t8= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190612171043-2e19bb35a278/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= github.com/GoogleCloudPlatform/testgrid v0.0.1-alpha.3/go.mod h1:f96W2HYy3tiBNV5zbbRc+NczwYHgG1PHXMQfoEWv680= +github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -91,6 +93,7 @@ github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkg github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -166,6 +169,8 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/gomodule/redigo v1.7.0/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -185,6 +190,7 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -232,6 +238,8 @@ github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v0.0.0-20161215172503-049f9b42e9a5/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/jingxu97/csi-proxy v0.0.0-20200207162946-49547a803bbe h1:yedPdgQSgn9n3FVgk6kl9x9nYSJtOq+iVbqArR3G1S0= +github.com/jingxu97/csi-proxy/client v0.0.0-20200207162946-49547a803bbe h1:bvSDrT0jif5vv8RfVTLJyu+UgEkJlhQuSFo9GaCla/I= github.com/jinzhu/gorm v0.0.0-20170316141641-572d0a0ab1eb/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= github.com/jinzhu/inflection v0.0.0-20190603042836-f5c5f50e6090/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= @@ -265,6 +273,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kubernetes-csi/csi-proxy v0.0.0-20200212230835-1a574c1ea917 h1:r41qapWr8GuEXUre1MwgAlIR7umMQOR/Mo8ReipXNxE= +github.com/kubernetes-csi/csi-proxy v0.0.0-20200309211337-cc7cd172e39f h1:wbCtCrOQ9ShYpJT1KRg6CzE+3Y06qIzHGTO/YJMmFDM= +github.com/kubernetes-csi/csi-proxy v0.0.0-20200319061913-d6ab31300107 h1:vnMFC21mkcWa9Yy4fnsZf3Bwlwu5/oH1DSKmensLaeg= +github.com/kubernetes-csi/csi-proxy v0.1.0 h1:1MbEEMR9+5xopVh6WmrI3L7Y9XvhApBm6135tkzAQiM= +github.com/kubernetes-csi/csi-proxy/client v0.0.0-20200212230835-1a574c1ea917 h1:rETfQd+WrKVIdcQapzPeYeJSY43BPyREmLwRZ0lP2/g= +github.com/kubernetes-csi/csi-proxy/client v0.0.0-20200212230835-1a574c1ea917/go.mod h1:N4i68Hv9rB7IeJnBRC5foXDwMMfEjc23RwuMIwCepDY= +github.com/kubernetes-csi/csi-proxy/client v0.0.0-20200319061913-d6ab31300107 h1:6kPT8Aq3BUck9dkMPPJNwpgCQWf5drAhyHAA37mPLuk= +github.com/kubernetes-csi/csi-proxy/client v0.0.0-20200319061913-d6ab31300107/go.mod h1:AEGb6PeX4XUKjEGycToqZQxHQS01Ch3C+C42FgORhOE= +github.com/kubernetes-csi/csi-proxy/client v0.0.0-20200330215040-9eff16441b2a h1:oUzd0gIsXuEaPLqOBc7h7KmoQaCEDrZcgEVFIlKVzsw= +github.com/kubernetes-csi/csi-proxy/client v0.0.0-20200330215040-9eff16441b2a/go.mod h1:AEGb6PeX4XUKjEGycToqZQxHQS01Ch3C+C42FgORhOE= github.com/kubernetes-csi/csi-test/v3 v3.0.0 h1:mVsfA4J67uNm8fdF/Pr84oMqL92qjIhjWbEUH8zv1fU= github.com/kubernetes-csi/csi-test/v3 v3.0.0/go.mod h1:VdIKGnDZHOjg4M5yd0OZICtsoEzdn64d0K33N6dm35Q= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -314,6 +332,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -340,8 +359,11 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/satori/go.uuid v0.0.0-20160713180306-0aa62d5ddceb/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/githubv4 v0.0.0-20180925043049-51d7b505e2e9/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/graphql v0.0.0-20180924043259-e4a3a37e6d42/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg= @@ -408,6 +430,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -420,6 +443,9 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -454,6 +480,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -505,7 +532,15 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200227200655-6862ededa516 h1:OX66ZzpltgCOuBSGdaeT77hS2z3ub2AB+EuGxvGRBLE= +golang.org/x/tools v0.0.0-20200227200655-6862ededa516/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200309202150-20ab64c0d93f h1:NbrfHxef+IfdI86qCgO/1Siq1BuMH2xG0NqgvCguRhQ= +golang.org/x/tools/gopls v0.3.3 h1:mTFqRDJQmpSsgDDWvbtGnSva1z9uX2XcDszSWa6DhBQ= +golang.org/x/tools/gopls v0.3.3/go.mod h1:/+k338+mxNM3GriqmoCmzmIncmolq6cjO2ZobdFJhuM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= @@ -549,8 +584,12 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 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= @@ -558,6 +597,7 @@ gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs= @@ -588,6 +628,8 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/api v0.0.0-20181018013834-843ad2d9b9ae/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/api v0.0.0-20190918195907-bd6ac527cfd2/go.mod h1:AOxZTnaXR/xiarlQL0JUfwQPxjmKDvVYoRp58cA7lUo= @@ -640,6 +682,8 @@ modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= mvdan.cc/xurls/v2 v2.0.0/go.mod h1:2/webFPYOXN9jp/lzuj0zuAVlF+9g4KPFJANH1oJhRU= +mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA= +mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/controller-runtime v0.3.0/go.mod h1:Cw6PkEg0Sa7dAYovGT4R0tRkGhHXpYijwNxYhAnAZZk= sigs.k8s.io/structured-merge-diff v0.0.0-20190302045857-e85c7b244fd2/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= diff --git a/pkg/gce-pd-csi-driver/node.go b/pkg/gce-pd-csi-driver/node.go index 2401e386f..3d0faa2ad 100644 --- a/pkg/gce-pd-csi-driver/node.go +++ b/pkg/gce-pd-csi-driver/node.go @@ -17,6 +17,7 @@ package gceGCEDriver import ( "fmt" "os" + "runtime" "strconv" "strings" @@ -57,10 +58,20 @@ var _ csi.NodeServer = &GCENodeServer{} // node boot disk is considered an attachable disk so effective attach limit is // one less. const ( - volumeLimitSmall int64 = 15 - volumeLimitBig int64 = 127 + volumeLimitSmall int64 = 15 + volumeLimitBig int64 = 127 + defaultLinuxFsType = "ext4" + defaultWindowsFsType = "ntfs" ) +func getDefaultFsType() string { + if runtime.GOOS == "windows" { + return defaultWindowsFsType + } else { + return defaultLinuxFsType + } +} + func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) { // Validate Arguments targetPath := req.GetTargetPath() @@ -129,10 +140,10 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub } sourcePath = stagingTargetPath - - if err := os.MkdirAll(targetPath, 0750); err != nil { + if err := preparePublishPath(targetPath, ns.Mounter); err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("mkdir failed on disk %s (%v)", targetPath, err)) } + } else if blk := volumeCapability.GetBlock(); blk != nil { klog.V(4).Infof("NodePublishVolume with block volume mode") @@ -141,7 +152,7 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub partition = part } - sourcePath, err = ns.getDevicePath(volumeID, partition) + sourcePath, err = getDevicePath(ns, volumeID, partition) if err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("Error when getting device path: %v", err)) } @@ -218,11 +229,9 @@ func (ns *GCENodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeU } defer ns.volumeLocks.Release(volumeID) - err := mount.CleanupMountPoint(targetPath, ns.Mounter.Interface, false /* bind mount */) - if err != nil { + if err := cleanupPublishPath(targetPath, ns.Mounter); err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("Unmount failed: %v\nUnmounting arguments: %s\n", err, targetPath)) } - klog.V(4).Infof("NodeUnpublishVolume succeded on %v from %s", volumeID, targetPath) return &csi.NodeUnpublishVolumeResponse{}, nil } @@ -264,27 +273,19 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage if part, ok := req.GetVolumeContext()[common.VolumeAttributePartition]; ok { partition = part } + devicePath, err := getDevicePath(ns, volumeID, partition) - devicePath, err := ns.getDevicePath(volumeID, partition) if err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("Error when getting device path: %v", err)) } klog.V(4).Infof("Successfully found attached GCE PD %q at device path %s.", volumeKey.Name, devicePath) - // Part 2: Check if mount already exists at targetpath + // Part 2: Check if mount already exists at stagingTargetPath notMnt, err := ns.Mounter.Interface.IsLikelyNotMountPoint(stagingTargetPath) - if err != nil { - if os.IsNotExist(err) { - if err := os.MkdirAll(stagingTargetPath, 0750); err != nil { - return nil, status.Error(codes.Internal, fmt.Sprintf("Failed to create directory (%q): %v", stagingTargetPath, err)) - } - notMnt = true - } else { - return nil, status.Error(codes.Internal, fmt.Sprintf("Unknown error when checking mount point (%q): %v", stagingTargetPath, err)) - } + if err != nil && !os.IsNotExist(err) { + return nil, status.Error(codes.Internal, fmt.Sprintf("cannot validate mount point: %s %v", stagingTargetPath, err)) } - if !notMnt { // TODO(#95): Check who is mounted here. No error if its us /* @@ -293,15 +294,17 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage 3) Readonly MUST match */ - klog.V(4).Infof("NodeStageVolume succeded on %v to %s, mount already exists.", volumeID, stagingTargetPath) return &csi.NodeStageVolumeResponse{}, nil } + if err := prepareStagePath(stagingTargetPath, ns.Mounter); err != nil { + return nil, status.Error(codes.Internal, fmt.Sprintf("mkdir failed on disk %s (%v)", stagingTargetPath, err)) + } // Part 3: Mount device to stagingTargetPath - // Default fstype is ext4 - fstype := "ext4" + fstype := getDefaultFsType() + options := []string{} if mnt := volumeCapability.GetMount(); mnt != nil { if mnt.FsType != "" { @@ -316,7 +319,7 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage return &csi.NodeStageVolumeResponse{}, nil } - err = ns.Mounter.FormatAndMount(devicePath, stagingTargetPath, fstype, options) + err = formatAndMount(devicePath, stagingTargetPath, fstype, options, ns.Mounter) if err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("Failed to format and mount device from (%q) to (%q) with fstype (%q) and options (%q): %v", @@ -343,9 +346,8 @@ func (ns *GCENodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUns } defer ns.volumeLocks.Release(volumeID) - err := mount.CleanupMountPoint(stagingTargetPath, ns.Mounter.Interface, false /* bind mount */) - if err != nil { - return nil, status.Error(codes.Internal, fmt.Sprintf("NodeUnstageVolume failed to unmount at path %s: %v", stagingTargetPath, err)) + if err := cleanupStagePath(stagingTargetPath, ns.Mounter); err != nil { + return nil, status.Error(codes.Internal, fmt.Sprintf("NodeUnstageVolume failed: %v\nUnmounting arguments: %s\n", err, stagingTargetPath)) } klog.V(4).Infof("NodeUnstageVolume succeded on %v from %s", volumeID, stagingTargetPath) @@ -454,7 +456,7 @@ func (ns *GCENodeServer) NodeExpandVolume(ctx context.Context, req *csi.NodeExpa return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("volume ID is invalid: %v", err)) } - devicePath, err := ns.getDevicePath(volumeID, "") + devicePath, err := getDevicePath(ns, volumeID, "") if err != nil { return nil, status.Error(codes.Internal, fmt.Sprintf("error when getting device path for %s: %v", volumeID, err)) } @@ -517,28 +519,6 @@ func (ns *GCENodeServer) GetVolumeLimits() (int64, error) { return volumeLimitBig, nil } -func (ns *GCENodeServer) getDevicePath(volumeID string, partition string) (string, error) { - volumeKey, err := common.VolumeIDToKey(volumeID) - if err != nil { - return "", err - } - deviceName, err := common.GetDeviceName(volumeKey) - if err != nil { - return "", fmt.Errorf("error getting device name: %v", err) - } - - devicePaths := ns.DeviceUtils.GetDiskByIdPaths(deviceName, partition) - devicePath, err := ns.DeviceUtils.VerifyDevicePath(devicePaths, deviceName) - - if err != nil { - return "", fmt.Errorf("error verifying GCE PD (%q) is attached: %v", volumeKey.Name, err) - } - if devicePath == "" { - return "", fmt.Errorf("unable to find device path out of attempted paths: %v", devicePaths) - } - return devicePath, nil -} - func (ns *GCENodeServer) getBlockSizeBytes(devicePath string) (int64, error) { output, err := ns.Mounter.Exec.Command("blockdev", "--getsize64", devicePath).CombinedOutput() if err != nil { diff --git a/pkg/gce-pd-csi-driver/utils_linux.go b/pkg/gce-pd-csi-driver/utils_linux.go new file mode 100644 index 000000000..f4ea59489 --- /dev/null +++ b/pkg/gce-pd-csi-driver/utils_linux.go @@ -0,0 +1,66 @@ +// +build !windows + +/* +Copyright 2020 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 gceGCEDriver + +import ( + "fmt" + "os" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "k8s.io/utils/mount" + "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/common" +) + +func getDevicePath(ns *GCENodeServer, volumeID, partition string) (string, error) { + volumeKey, err := common.VolumeIDToKey(volumeID) + if err != nil { + return "", err + } + deviceName, err := common.GetDeviceName(volumeKey) + if err != nil { + return "", fmt.Errorf("error getting device name: %v", err) + } + devicePaths := ns.DeviceUtils.GetDiskByIdPaths(deviceName, partition) + devicePath, err := ns.DeviceUtils.VerifyDevicePath(devicePaths, deviceName) + if err != nil { + return "", status.Error(codes.Internal, fmt.Sprintf("error verifying GCE PD (%q) is attached: %v", deviceName, err)) + } + if devicePath == "" { + return "", status.Error(codes.Internal, fmt.Sprintf("Unable to find device path out of attempted paths: %v", devicePaths)) + } + return devicePath, nil +} + +func formatAndMount(source, target, fstype string, options []string, m *mount.SafeFormatAndMount) error { + return m.FormatAndMount(source, target, fstype, options) +} + +func preparePublishPath(path string, m *mount.SafeFormatAndMount) error { + return os.MkdirAll(path, 0750) +} + +func prepareStagePath(path string, m *mount.SafeFormatAndMount) error { + return os.MkdirAll(path, 0750) +} + +func cleanupPublishPath(path string, m *mount.SafeFormatAndMount) error { + return mount.CleanupMountPoint(path, m, false /* bind mount */) +} + +func cleanupStagePath(path string, m *mount.SafeFormatAndMount) error { + return cleanupPublishPath(path, m) +} diff --git a/pkg/gce-pd-csi-driver/utils_windows.go b/pkg/gce-pd-csi-driver/utils_windows.go new file mode 100644 index 000000000..961f984bd --- /dev/null +++ b/pkg/gce-pd-csi-driver/utils_windows.go @@ -0,0 +1,88 @@ +// +build windows + +/* +Copyright 2020 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 gceGCEDriver + +import ( + "fmt" + "k8s.io/utils/mount" + "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/common" + mounter "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager" +) + +func formatAndMount(source, target, fstype string, options []string, m *mount.SafeFormatAndMount) error { + proxy, ok := m.Interface.(*mounter.CSIProxyMounter) + if !ok { + return fmt.Errorf("could not cast to csi proxy class") + } + return proxy.FormatAndMount(source, target, fstype, options) +} + +// Before mounting (which means creating symlink) in Windows, the targetPath should +// not exist. Currently kubelet creates the path beforehand, this is a workaround to +// remove the path first. +func preparePublishPath(path string, m *mount.SafeFormatAndMount) error { + proxy, ok := m.Interface.(*mounter.CSIProxyMounter) + if !ok { + return fmt.Errorf("could not cast to csi proxy class") + } + exists, err := proxy.ExistsPath(path) + if err != nil { + return err + } + if exists { + return proxy.RemovePodDir(path) + } + return nil +} + +// Before staging (which means creating symlink) in Windows, the targetPath should +// not exist. +func prepareStagePath(path string, m *mount.SafeFormatAndMount) error { + return nil +} + +func cleanupPublishPath(path string, m *mount.SafeFormatAndMount) error { + proxy, ok := m.Interface.(*mounter.CSIProxyMounter) + if !ok { + return fmt.Errorf("could not cast to csi proxy class") + } + return proxy.RemovePodDir(path) +} + +func cleanupStagePath(path string, m *mount.SafeFormatAndMount) error { + proxy, ok := m.Interface.(*mounter.CSIProxyMounter) + if !ok { + return fmt.Errorf("could not cast to csi proxy class") + } + return proxy.RemovePluginDir(path) +} + +// search Windows disk number by volumeID +func getDevicePath(ns *GCENodeServer, volumeID, partition string) (string, error) { + volumeKey, err := common.VolumeIDToKey(volumeID) + if err != nil { + return "", err + } + deviceName, err := common.GetDeviceName(volumeKey) + if err != nil { + return "", fmt.Errorf("error getting device name: %v", err) + } + proxy, ok := ns.Mounter.Interface.(*mounter.CSIProxyMounter) + if !ok { + return "", fmt.Errorf("could not cast to csi proxy class") + } + return proxy.GetDevicePath(deviceName, partition, volumeKey.Name) +} diff --git a/pkg/mount-manager/safe-mounter.go b/pkg/mount-manager/safe-mounter_linux.go similarity index 90% rename from pkg/mount-manager/safe-mounter.go rename to pkg/mount-manager/safe-mounter_linux.go index 10c286d6b..a3aff81e2 100644 --- a/pkg/mount-manager/safe-mounter.go +++ b/pkg/mount-manager/safe-mounter_linux.go @@ -1,3 +1,5 @@ +// +build linux + /* Copyright 2018 The Kubernetes Authors. @@ -19,12 +21,12 @@ import ( "k8s.io/utils/mount" ) -func NewSafeMounter() *mount.SafeFormatAndMount { +func NewSafeMounter() (*mount.SafeFormatAndMount, error) { realMounter := mount.New("") realExec := exec.New() return &mount.SafeFormatAndMount{ Interface: realMounter, Exec: realExec, - } + }, nil } diff --git a/pkg/mount-manager/safe-mounter_windows.go b/pkg/mount-manager/safe-mounter_windows.go new file mode 100644 index 000000000..9c5de9055 --- /dev/null +++ b/pkg/mount-manager/safe-mounter_windows.go @@ -0,0 +1,229 @@ +// +build windows + +/* +Copyright 2020 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 mountmanager + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + + diskv1alpha1 "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1alpha1" + diskclientv1alpha1 "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1alpha1" + + fsv1alpha1 "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1alpha1" + fsclientv1alpha1 "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v1alpha1" + + volumev1alpha1 "github.com/kubernetes-csi/csi-proxy/client/api/volume/v1alpha1" + volumeclientv1alpha1 "github.com/kubernetes-csi/csi-proxy/client/groups/volume/v1alpha1" + + utilexec "k8s.io/utils/exec" + "k8s.io/utils/mount" +) + +var _ mount.Interface = &CSIProxyMounter{} + +type CSIProxyMounter struct { + FsClient *fsclientv1alpha1.Client + DiskClient *diskclientv1alpha1.Client + VolumeClient *volumeclientv1alpha1.Client +} + +func NewCSIProxyMounter() (*CSIProxyMounter, error) { + fsClient, err := fsclientv1alpha1.NewClient() + if err != nil { + return nil, err + } + diskClient, err := diskclientv1alpha1.NewClient() + if err != nil { + return nil, err + } + volumeClient, err := volumeclientv1alpha1.NewClient() + if err != nil { + return nil, err + } + return &CSIProxyMounter{ + FsClient: fsClient, + DiskClient: diskClient, + VolumeClient: volumeClient, + }, nil +} + +func NewSafeMounter() (*mount.SafeFormatAndMount, error) { + csiProxyMounter, err := NewCSIProxyMounter() + if err != nil { + return nil, err + } + return &mount.SafeFormatAndMount{ + Interface: csiProxyMounter, + Exec: utilexec.New(), + }, nil +} + +// Mount just creates a soft link at target pointing to source. +func (mounter *CSIProxyMounter) Mount(source string, target string, fstype string, options []string) error { + // Mount is called after the format is done. + // TODO: Confirm that fstype is empty. + // Call the LinkPath CSI proxy from the source path to the target path + parentDir := filepath.Dir(target) + if err := os.MkdirAll(parentDir, 0755); err != nil { + return err + } + linkRequest := &fsv1alpha1.LinkPathRequest{ + SourcePath: mount.NormalizeWindowsPath(source), + TargetPath: mount.NormalizeWindowsPath(target), + } + response, err := mounter.FsClient.LinkPath(context.Background(), linkRequest) + if err != nil { + return err + } + if response.Error != "" { + return errors.New(response.Error) + } + return nil +} + +// Delete the given directory with Pod context. CSI proxy does a check for path prefix +// based on context +func (mounter *CSIProxyMounter) RemovePodDir(target string) error { + rmdirRequest := &fsv1alpha1.RmdirRequest{ + Path: mount.NormalizeWindowsPath(target), + Context: fsv1alpha1.PathContext_POD, + Force: true, + } + _, err := mounter.FsClient.Rmdir(context.Background(), rmdirRequest) + if err != nil { + return err + } + return nil +} + +// Delete the given directory with plugin context. CSI proxy does a check for path prefix +// based on context +func (mounter *CSIProxyMounter) RemovePluginDir(target string) error { + rmdirRequest := &fsv1alpha1.RmdirRequest{ + Path: mount.NormalizeWindowsPath(target), + Context: fsv1alpha1.PathContext_PLUGIN, + Force: true, + } + _, err := mounter.FsClient.Rmdir(context.Background(), rmdirRequest) + if err != nil { + return err + } + return nil +} + +func (mounter *CSIProxyMounter) Unmount(target string) error { + return mounter.RemovePodDir(target) +} + +func (mounter *CSIProxyMounter) GetDevicePath(deviceName string, partition string, volumeKey string) (string, error) { + getDiskNumberRequest := &diskv1alpha1.GetDiskNumberByNameRequest{ + DiskName: deviceName, + } + getDiskNumberResponse, err := mounter.DiskClient.GetDiskNumberByName(context.Background(), getDiskNumberRequest) + if err != nil { + return "", err + } + return getDiskNumberResponse.DiskNumber, nil + +} + +// FormatAndMount accepts the source disk number, target path to mount, the fstype to format with and options to be used. +// After formatting, it will mount the disk to target path on the host +func (mounter *CSIProxyMounter) FormatAndMount(source string, target string, fstype string, options []string) error { + // Call PartitionDisk CSI proxy call to partition the disk and return the volume id + partionDiskRequest := &diskv1alpha1.PartitionDiskRequest{ + DiskID: source, + } + + _, err := mounter.DiskClient.PartitionDisk(context.Background(), partionDiskRequest) + if err != nil { + return err + } + volumeIDsRequest := &volumev1alpha1.ListVolumesOnDiskRequest{ + DiskId: source, + } + volumeIdResponse, err := mounter.VolumeClient.ListVolumesOnDisk(context.Background(), volumeIDsRequest) + if err != nil { + return err + } + // TODO: consider partitions and choose the right partition. + volumeID := volumeIdResponse.VolumeIds[0] + isVolumeFormattedRequest := &volumev1alpha1.IsVolumeFormattedRequest{ + VolumeId: volumeID, + } + isVolumeFormattedResponse, err := mounter.VolumeClient.IsVolumeFormatted(context.Background(), isVolumeFormattedRequest) + if err != nil { + return err + } + if !isVolumeFormattedResponse.Formatted { + formatVolumeRequest := &volumev1alpha1.FormatVolumeRequest{ + VolumeId: volumeID, + // TODO (jingxu97): Accept the filesystem and other options + } + _, err = mounter.VolumeClient.FormatVolume(context.Background(), formatVolumeRequest) + if err != nil { + return err + } + } + // Mount the volume by calling the CSI proxy call. + mountVolumeRequest := &volumev1alpha1.MountVolumeRequest{ + VolumeId: volumeID, + Path: target, + } + _, err = mounter.VolumeClient.MountVolume(context.Background(), mountVolumeRequest) + if err != nil { + return err + } + return nil +} + +func (mounter *CSIProxyMounter) GetMountRefs(pathname string) ([]string, error) { + return []string{}, fmt.Errorf("GetMountRefs not implemented for ProxyMounter") +} + +func (mounter *CSIProxyMounter) IsLikelyNotMountPoint(file string) (bool, error) { + isMountRequest := &fsv1alpha1.IsMountPointRequest{ + Path: file, + } + + isMountResponse, err := mounter.FsClient.IsMountPoint(context.Background(), isMountRequest) + if err != nil { + return false, err + } + + return !isMountResponse.IsMountPoint, nil +} + +func (mounter *CSIProxyMounter) List() ([]mount.MountPoint, error) { + return []mount.MountPoint{}, nil +} + +func (mounter *CSIProxyMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool { + return mp.Path == dir +} + +// ExistsPath - Checks if a path exists. Unlike util ExistsPath, this call does not perform follow link. +func (mounter *CSIProxyMounter) ExistsPath(path string) (bool, error) { + isExistsResponse, err := mounter.FsClient.PathExists(context.Background(), + &fsv1alpha1.PathExistsRequest{ + Path: mount.NormalizeWindowsPath(path), + }) + return isExistsResponse.Exists, err +} diff --git a/pkg/mount-manager/statter.go b/pkg/mount-manager/statter.go index b4a4ad900..0b8b1e7b5 100644 --- a/pkg/mount-manager/statter.go +++ b/pkg/mount-manager/statter.go @@ -14,68 +14,7 @@ limitations under the License. package mountmanager -import ( - "fmt" - - "golang.org/x/sys/unix" -) - type Statter interface { StatFS(path string) (int64, int64, int64, int64, int64, int64, error) IsBlockDevice(string) (bool, error) } - -var _ Statter = realStatter{} - -type realStatter struct { -} - -func NewStatter() realStatter { - return realStatter{} -} - -// IsBlock checks if the given path is a block device -func (realStatter) IsBlockDevice(fullPath string) (bool, error) { - var st unix.Stat_t - err := unix.Stat(fullPath, &st) - if err != nil { - return false, err - } - - return (st.Mode & unix.S_IFMT) == unix.S_IFBLK, nil -} - -func (realStatter) StatFS(path string) (available, capacity, used, inodesFree, inodes, inodesUsed int64, err error) { - statfs := &unix.Statfs_t{} - err = unix.Statfs(path, statfs) - if err != nil { - err = fmt.Errorf("failed to get fs info on path %s: %v", path, err) - return - } - - // Available is blocks available * fragment size - available = int64(statfs.Bavail) * int64(statfs.Bsize) - // Capacity is total block count * fragment size - capacity = int64(statfs.Blocks) * int64(statfs.Bsize) - // Usage is block being used * fragment size (aka block size). - used = (int64(statfs.Blocks) - int64(statfs.Bfree)) * int64(statfs.Bsize) - inodes = int64(statfs.Files) - inodesFree = int64(statfs.Ffree) - inodesUsed = inodes - inodesFree - return -} - -type fakeStatter struct{} - -func NewFakeStatter() fakeStatter { - return fakeStatter{} -} - -func (fakeStatter) StatFS(path string) (available, capacity, used, inodesFree, inodes, inodesUsed int64, err error) { - // Assume the file exists and give some dummy values back - return 1, 1, 1, 1, 1, 1, nil -} - -func (fakeStatter) IsBlockDevice(fullPath string) (bool, error) { - return false, nil -} diff --git a/pkg/mount-manager/statter_linux.go b/pkg/mount-manager/statter_linux.go new file mode 100644 index 000000000..1b1d4fe03 --- /dev/null +++ b/pkg/mount-manager/statter_linux.go @@ -0,0 +1,76 @@ +/* +Copyright 2019 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 mountmanager + +import ( + "fmt" + + "golang.org/x/sys/unix" +) + +var _ Statter = realStatter{} + +type realStatter struct { +} + +func NewStatter() realStatter { + return realStatter{} +} + +// IsBlock checks if the given path is a block device +func (realStatter) IsBlockDevice(fullPath string) (bool, error) { + var st unix.Stat_t + err := unix.Stat(fullPath, &st) + if err != nil { + return false, err + } + + return (st.Mode & unix.S_IFMT) == unix.S_IFBLK, nil +} + +func (realStatter) StatFS(path string) (available, capacity, used, inodesFree, inodes, inodesUsed int64, err error) { + statfs := &unix.Statfs_t{} + err = unix.Statfs(path, statfs) + if err != nil { + err = fmt.Errorf("failed to get fs info on path %s: %v", path, err) + return + } + + // Available is blocks available * fragment size + available = int64(statfs.Bavail) * int64(statfs.Bsize) + // Capacity is total block count * fragment size + capacity = int64(statfs.Blocks) * int64(statfs.Bsize) + // Usage is block being used * fragment size (aka block size). + used = (int64(statfs.Blocks) - int64(statfs.Bfree)) * int64(statfs.Bsize) + inodes = int64(statfs.Files) + inodesFree = int64(statfs.Ffree) + inodesUsed = inodes - inodesFree + return +} + +type fakeStatter struct{} + +func NewFakeStatter() fakeStatter { + return fakeStatter{} +} + +func (fakeStatter) StatFS(path string) (available, capacity, used, inodesFree, inodes, inodesUsed int64, err error) { + // Assume the file exists and give some dummy values back + return 1, 1, 1, 1, 1, 1, nil +} + +func (fakeStatter) IsBlockDevice(fullPath string) (bool, error) { + return false, nil +} diff --git a/pkg/mount-manager/statter_windows.go b/pkg/mount-manager/statter_windows.go new file mode 100644 index 000000000..3a8de3013 --- /dev/null +++ b/pkg/mount-manager/statter_windows.go @@ -0,0 +1,55 @@ +// +build windows +/* +Copyright 2019 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 mountmanager + +import ( + "fmt" +) + +var _ Statter = realStatter{} + +type realStatter struct { +} + +func NewStatter() realStatter { + return realStatter{} +} + +// IsBlock checks if the given path is a block device +func (realStatter) IsBlockDevice(fullPath string) (bool, error) { + return false, nil +} + +//TODO (jinxu): implement StatFS to get metrics +func (realStatter) StatFS(path string) (available, capacity, used, inodesFree, inodes, inodesUsed int64, err error) { + zero := int64(0) + return zero, zero, zero, zero, zero, zero, fmt.Errorf("Not implemented") +} + +type fakeStatter struct{} + +func NewFakeStatter() fakeStatter { + return fakeStatter{} +} + +func (fakeStatter) StatFS(path string) (available, capacity, used, inodesFree, inodes, inodesUsed int64, err error) { + // Assume the file exists and give some dummy values back + return 1, 1, 1, 1, 1, 1, nil +} + +func (fakeStatter) IsBlockDevice(fullPath string) (bool, error) { + return false, nil +}