├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ └── docker-image.yml ├── .gitignore ├── Dockerfile ├── Makefile ├── README.md ├── cmd ├── localstorage-controller │ └── main.go ├── localstorage-job │ └── main.go ├── localstorageplugin │ └── main.go └── scheduler-extender │ └── scheduler-extender.go ├── deploy ├── charts │ ├── README.md │ └── localstorage │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── crds │ │ └── storage.caoyingjunz.io_localstorages.yaml │ │ ├── templates │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── ls-controller.yaml │ │ ├── ls-driverinfo.yaml │ │ ├── ls-node.yaml │ │ ├── ls-rbac.yaml │ │ ├── ls-secret.yaml │ │ ├── ls-service.yaml │ │ └── ls-webhookconfiguration.yaml │ │ └── values.yaml ├── crds │ └── storage.caoyingjunz.io_localstorages.yaml ├── install-driver.sh ├── latest │ ├── ls-controller.yaml │ ├── ls-driverinfo.yaml │ ├── ls-node.yaml │ ├── ls-rbac.yaml │ ├── ls-secret.yaml │ ├── ls-service.yaml │ └── ls-webhookconfiguration.yaml ├── ls-job.yaml ├── ls-scheduler-config.yaml ├── ls-scheduler.yaml ├── ls-storageclass.yaml ├── uninstall-driver.sh ├── v1.0.0 │ ├── ls-driverinfo.yaml │ ├── ls-node.yaml │ └── ls-rbac.yaml ├── v1.0.1 │ ├── ls-controller.yaml │ ├── ls-driverinfo.yaml │ ├── ls-node.yaml │ ├── ls-rbac.yaml │ ├── ls-secret.yaml │ ├── ls-service.yaml │ ├── ls-webhookconfiguration.yaml │ └── storage.caoyingjunz.io_localstorages.yaml ├── v1.0.2 │ ├── ls-controller.yaml │ ├── ls-driverinfo.yaml │ ├── ls-node.yaml │ ├── ls-rbac.yaml │ ├── ls-secret.yaml │ ├── ls-service.yaml │ └── ls-webhookconfiguration.yaml └── v1.0.3 │ ├── ls-controller.yaml │ ├── ls-driverinfo.yaml │ ├── ls-node.yaml │ ├── ls-rbac.yaml │ ├── ls-secret.yaml │ ├── ls-service.yaml │ └── ls-webhookconfiguration.yaml ├── docs └── scheduler-extender.md ├── examples ├── ls.yaml ├── pvc.yaml └── sts.yaml ├── go.mod ├── go.sum ├── hack ├── boilerplate.go.txt ├── build-lsconfig.sh ├── tools.go ├── update-codegen.sh ├── update-gofmt.sh ├── verify-codegen.sh └── verify-gofmt.sh └── pkg ├── apis └── localstorage │ ├── register.go │ └── v1 │ ├── doc.go │ ├── register.go │ ├── types.go │ └── zz_generated.deepcopy.go ├── cache └── store.go ├── client ├── clientset │ └── versioned │ │ ├── clientset.go │ │ ├── doc.go │ │ ├── fake │ │ ├── clientset_generated.go │ │ ├── doc.go │ │ └── register.go │ │ ├── scheme │ │ ├── doc.go │ │ └── register.go │ │ └── typed │ │ └── localstorage │ │ └── v1 │ │ ├── doc.go │ │ ├── fake │ │ ├── doc.go │ │ ├── fake_localstorage.go │ │ └── fake_localstorage_client.go │ │ ├── generated_expansion.go │ │ ├── localstorage.go │ │ └── localstorage_client.go ├── informers │ └── externalversions │ │ ├── factory.go │ │ ├── generic.go │ │ ├── internalinterfaces │ │ └── factory_interfaces.go │ │ └── localstorage │ │ ├── interface.go │ │ └── v1 │ │ ├── interface.go │ │ └── localstorage.go └── listers │ └── localstorage │ └── v1 │ ├── expansion_generated.go │ └── localstorage.go ├── controller └── storage │ └── storage_controller.go ├── localstorage ├── controllerserver.go ├── identityserver.go ├── localstorage.go ├── nodeserver.go ├── server.go └── utils.go ├── runtime └── scheme.go ├── scheduler ├── extender │ ├── bind.go │ ├── predicate.go │ └── prioritie.go └── scheduler.go ├── signals └── signal.go ├── types └── localstorage.go ├── util ├── controller_utils.go ├── finalizer.go ├── logicalvolume │ └── logicalvolume.go ├── storage │ ├── storage.go │ └── storage_test.go └── util.go └── webhook ├── mutating.go └── validating.go /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | labels: ["kind/bug"] 4 | about: Create a report to help us improve 5 | --- 6 | 7 | **Describe the Bug** 8 | A clear and concise description of what the bug is. 9 | 10 | For UI issues please also add a screenshot that shows the issue. 11 | 12 | **Versions Used** 13 | KubeSphere: 14 | Kubernetes: (If KubeSphere installer used, you can skip this) 15 | 16 | 17 | **Environment** 18 | How many nodes and their hardware configuration: 19 | 20 | For example: CentOS 7.5 / 3 masters: 8cpu/8g; 3 nodes: 8cpu/16g 21 | (and other info are welcomed to help us debugging) 22 | 23 | **How To Reproduce** 24 | Steps to reproduce the behavior: 25 | 1. Go to '...' 26 | 2. Click on '....' 27 | 3. Scroll down to '....' 28 | 4. See error 29 | 30 | **Expected behavior** 31 | A clear and concise description of what you expected to happen. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Have a good idea? Please don't hesitate to write it down, describe the new feature. 4 | --- 5 | 6 | **What's it about?** 7 | 10 | 11 | **What's the reason why we need it?** 12 | 17 | 18 | I believe this is an important feature for Pixiu. There're a few use cases: 19 | 20 | * case one 21 | * case two 22 | * ... 23 | 24 | Please leave your comments below if there's anyone agrees with me. Or just give me a thumb up. 25 | 26 | **Area Suggestion** 27 | 57 | 58 | /kind feature-request 59 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #### What type of PR is this? 2 | 3 | 18 | 19 | #### What this PR does / why we need it: 20 | 21 | #### Which issue(s) this PR fixes: 22 | 27 | Fixes # 28 | 29 | #### Special notes for your reviewer: 30 | 31 | #### Does this PR introduce a user-facing change? 32 | 37 | ```release-note 38 | 39 | ``` 40 | 41 | #### Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.: 42 | 43 | 58 | ```docs 59 | 60 | ``` 61 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | env: 12 | GO_VERSION: '1.17.3' 13 | 14 | jobs: 15 | misspell-check: 16 | runs-on: ubuntu-latest 17 | container: pouchcontainer/pouchlinter:v0.1.2 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | 22 | - name: Lint markdown files 23 | run: find ./ -name "*.md" | grep -v '.github' | xargs mdl -r ~MD001,~MD004,~MD005,~MD006,~MD007,~MD010,~MD013,~MD022,~MD023,~MD024,~MD029,~MD031,~MD032,~MD033,~MD034,~MD036 24 | 25 | golang-lint: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v2 30 | with: 31 | submodules: true 32 | 33 | - name: Set up Golang 34 | uses: actions/setup-go@v2 35 | with: 36 | go-version: ${{ env.GO_VERSION }} 37 | 38 | - name: Run go fmt test 39 | run: hack/verify-gofmt.sh 40 | env: 41 | GO111MODULE: auto 42 | 43 | - name: Build the localstorage binariy 44 | run: go build -v ./... 45 | 46 | - name: Run localstorage unit test 47 | run: go test -v ./... 48 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Build localstorage image 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | 7 | env: 8 | # Use docker.io for Docker Hub if empty 9 | REGISTRY: harbor.cloud.pixiuio.com 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v3 18 | 19 | - name: Set up QEMU 20 | uses: docker/setup-qemu-action@v3 21 | 22 | - name: Set up Docker Buildx 23 | uses: docker/setup-buildx-action@v3 24 | 25 | - name: Login in image registry 26 | uses: docker/login-action@v3 27 | with: 28 | registry: ${{ env.REGISTRY }} 29 | username: ${{ secrets.DOCKER_NAME }} 30 | password: ${{ secrets.DOCKER_PASSWORD }} 31 | 32 | - name: Build and push the localstorage images 33 | run: | 34 | buildx=true make image 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | bin 8 | testbin/* 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Kubernetes Generated files - skip generated files, except for vendored files 17 | 18 | !vendor/**/zz_generated.* 19 | 20 | # editor and IDE paraphernalia 21 | .idea 22 | .vscode 23 | *.swp 24 | *.swo 25 | 26 | # output 27 | dist 28 | 29 | github.com 30 | vendor 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17-alpine as builder 2 | ARG APP 3 | WORKDIR /app 4 | ENV GOPROXY=https://goproxy.cn 5 | COPY ./go.mod ./ 6 | COPY ./go.sum ./ 7 | # cache deps before building and copying source so that we don't need to re-download as much 8 | # and so that source changes don't invalidate our downloaded layer 9 | #RUN go mod download 10 | 11 | COPY . . 12 | RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o ${APP} ./cmd/${APP} 13 | 14 | FROM busybox as runner 15 | ARG APP 16 | COPY --from=builder /app/${APP} /app 17 | ENTRYPOINT ["/app"] 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: run build image push vendor client-gen clean 2 | 3 | dockerhubUser = harbor.cloud.pixiuio.com/pixiuio 4 | tag = latest 5 | app ?= 6 | ifeq ($(app),) 7 | apps = $(shell ls cmd) 8 | else 9 | apps = $(app) 10 | endif 11 | targetDir ?= dist 12 | buildx ?= false 13 | dualPlatform ?= linux/amd64,linux/arm64 14 | 15 | # check if app name is valid 16 | check: 17 | @$(foreach app, $(apps), \ 18 | if [ ! -d "cmd/$(app)" ]; then \ 19 | echo "cmd/$(app) does not exist"; \ 20 | echo "Please check your app name"; \ 21 | exit 1; \ 22 | fi;) 23 | 24 | # build all apps 25 | build: check 26 | @$(foreach app, $(apps), \ 27 | echo "Building $(app)"; \ 28 | CGO_ENABLED=0 go build -ldflags "-s -w" -o $(targetDir)/$(app) ./cmd/$(app);) 29 | 30 | # build all images 31 | image: check 32 | ifeq ($(buildx), false) 33 | @$(foreach app, $(apps), \ 34 | echo "Building $(app) image"; \ 35 | docker build -t $(dockerhubUser)/$(app):$(tag) --no-cache --build-arg APP=$(app) \ 36 | .;) 37 | else ifeq ($(buildx), true) 38 | @$(foreach app, $(apps), \ 39 | echo "Building $(app) multi-arch image"; \ 40 | docker buildx build -t $(dockerhubUser)/$(app):$(tag) --no-cache --platform $(dualPlatform) --push --build-arg APP=$(app) \ 41 | .;) 42 | endif 43 | 44 | # push all images 45 | push: image 46 | @$(foreach app, $(apps), \ 47 | echo "Pushing $(app) image"; \ 48 | docker push $(dockerhubUser)/$(app):$(tag);) 49 | 50 | # install vendor 51 | vendor: 52 | go mod vendor 53 | 54 | # generate client 55 | client-gen: vendor 56 | ./hack/update-codegen.sh 57 | 58 | # rm vendor and github.com 59 | clean: 60 | rm -rf vendor && rm -rf github.com 61 | 62 | # show help 63 | help: 64 | @echo '' 65 | @echo 'Usage:' 66 | @echo ' make [target]' 67 | @echo '' 68 | @echo 'Targets:' 69 | @awk '/^[a-zA-Z\-\_0-9]+:/ { \ 70 | helpMessage = match(lastLine, /^# (.*)/); \ 71 | if (helpMessage) { \ 72 | helpCommand = substr($$1, 0, index($$1, ":")-1); \ 73 | helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \ 74 | printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \ 75 | } \ 76 | } \ 77 | { lastLine = $$0 }' $(MAKEFILE_LIST) 78 | 79 | .DEFAULT_GOAL := help 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LocalStorage 2 | 3 | ![Build Status][build-url] 4 | [![Release][release-image]][release-url] 5 | [![License][license-image]][license-url] 6 | 7 | ## Overview 8 | This driver allows Kubernetes to access LocalStorage on Linux node. 9 | 10 | ## Getting Started 11 | 12 | ### Installation 13 | - 选择运行 `localstorage` 的 `kubernetes` 节点 14 | ```shell 15 | kubectl label node storage.caoyingjunz.io/node= 16 | ``` 17 | 18 | - 安装 `localstorage` 组件 19 | ```shell 20 | kubectl apply -f deploy/crds 21 | kubectl apply -f deploy/latest 22 | 23 | # 验证 24 | root@pixiu01:~# kubectl get pod -n kube-system | grep pixiu 25 | pixiu-ls-controller-7997b8c446-8hndc 1/1 Running 0 87s 26 | pixiu-ls-node-gfd78 4/4 Running 0 87s 27 | pixiu-ls-node-mb4x6 4/4 Running 0 87s 28 | ``` 29 | 30 | - 安装 [LocalStorage 调度扩展](./docs/scheduler-extender.md) 31 | 32 | - 创建 `localstorage` 资源 33 | ```shell 34 | # 自动创建 35 | kubectl apply -f deploy/ls-job.yaml 36 | 37 | # 手动创建 38 | # 修改 examples/ls.yaml, 多个 node 节点需要多次创建 39 | kubectl apply -f examples/ls.yaml 40 | 41 | # 验证 42 | kubectl get ls 43 | NAME STATUS KUBENODE ALLOCATABLE CAPACITY AGE 44 | ls-pixiu01 Ready pixiu01 360Gi 360Gi 16d 45 | ``` 46 | 47 | - 安装 `storageclass` 48 | ```shell 49 | kubectl apply -f deploy/ls-storageclass.yaml 50 | 51 | # 验证 52 | kubectl get sc pixiu-localstorage 53 | NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE 54 | pixiu-localstorage localstorage.csi.caoyingjunz.io Delete WaitForFirstConsumer false 2m54s 55 | ``` 56 | 57 | - 创建 `pvc` 验证 58 | ```shell 59 | kubectl apply -f examples/pvc.yaml 60 | 61 | # 验证 62 | kubectl get pvc 63 | NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE 64 | test-pvc Bound pvc-2b2c809f-33b5-437f-a4b8-61906c10a3e1 1Mi RWX pixiu-localstorage 5s 65 | ``` 66 | 67 | ## Feature 68 | - Schedule with volume status 69 | - Volume metrics 70 | 71 | ## 学习分享 72 | - [go-learning](https://github.com/caoyingjunz/go-learning) 73 | 74 | ## 沟通交流 75 | - 搜索微信号 `yingjuncz`, 备注(ls), 验证通过会加入群聊 76 | - [bilibili](https://space.bilibili.com/3493104248162809?spm_id_from=333.1007.0.0) 技术分享 77 | 78 | Copyright 2019 caoyingjun (cao.yingjunz@gmail.com) Apache License 2.0 79 | 80 | [build-url]: https://github.com/caoyingjunz/csi-driver-localstorage/actions/workflows/ci.yml/badge.svg 81 | [release-image]: https://img.shields.io/badge/release-download-orange.svg 82 | [release-url]: https://www.apache.org/licenses/LICENSE-2.0.html 83 | [license-image]: https://img.shields.io/badge/license-Apache%202-4EB1BA.svg 84 | [license-url]: https://www.apache.org/licenses/LICENSE-2.0.html 85 | -------------------------------------------------------------------------------- /cmd/localstorage-job/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "flag" 22 | 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | "k8s.io/klog/v2" 25 | 26 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/util" 27 | storageutil "github.com/caoyingjunz/csi-driver-localstorage/pkg/util/storage" 28 | ) 29 | 30 | var ( 31 | kubeconfig = flag.String("kubeconfig", "", "paths to a kubeconfig. Only required if out-of-cluster.") 32 | createLocalstorage = flag.Bool("create-localstorage", true, "Create localstorage object if not present") 33 | ) 34 | 35 | func main() { 36 | klog.InitFlags(nil) 37 | flag.Parse() 38 | 39 | kubeClient, lsClientSet, err := util.NewClientSetsFromConfig(*kubeconfig) 40 | if err != nil { 41 | klog.Fatalf("Failed to build clientSets: %v", err) 42 | } 43 | 44 | nodes, err := kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{ 45 | LabelSelector: "storage.caoyingjunz.io/node", 46 | }) 47 | if err != nil { 48 | klog.Fatalf("Failed to get localstorage nodes: %v", err) 49 | } 50 | 51 | var nodeNames []string 52 | for _, node := range nodes.Items { 53 | nodeNames = append(nodeNames, node.Name) 54 | } 55 | if err = storageutil.CreateLocalStorages(lsClientSet, nodeNames...); err != nil { 56 | klog.Fatalf("Failed to create localstorage nodes: %v", err) 57 | } 58 | 59 | klog.Infof("localstorage job has been completed") 60 | } 61 | -------------------------------------------------------------------------------- /cmd/localstorageplugin/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "net/http" 22 | "os" 23 | "time" 24 | // import pprof for performance diagnosed 25 | _ "net/http/pprof" 26 | 27 | "k8s.io/klog/v2" 28 | 29 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/informers/externalversions" 30 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/localstorage" 31 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/signals" 32 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/util" 33 | ) 34 | 35 | var ( 36 | endpoint = flag.String("endpoint", "unix://tmp/csi.sock", "CSI endpoint") 37 | driverName = flag.String("drivername", localstorage.DefaultDriverName, "name of the driver") 38 | nodeId = flag.String("nodeid", "", "node id") 39 | volumeDir = flag.String("volume-dir", "/tmp", "directory for storing state information across driver volumes") 40 | 41 | kubeconfig = flag.String("kubeconfig", "", "paths to a kubeconfig. Only required if out-of-cluster.") 42 | kubeAPIQPS = flag.Int("kube-api-qps", 5, "QPS to use while communicating with the kubernetes apiserver. Defaults to 5") 43 | kubeAPIBurst = flag.Int("kube-api-burst", 10, "Burst to use while communicating with the kubernetes apiserver. Defaults to 10.") 44 | 45 | // pprof flags 46 | enablePprof = flag.Bool("enable-pprof", false, "Start pprof and gain leadership before executing the main loop") 47 | pprofPort = flag.String("pprof-port", "6060", "The port of pprof to listen on") 48 | ) 49 | 50 | func init() { 51 | _ = flag.Set("logtostderr", "true") 52 | } 53 | 54 | var ( 55 | version = "v1.0.0" 56 | ) 57 | 58 | func main() { 59 | klog.InitFlags(nil) 60 | flag.Parse() 61 | 62 | cfg := localstorage.Config{ 63 | DriverName: *driverName, 64 | Endpoint: *endpoint, 65 | VendorVersion: version, 66 | NodeId: *nodeId, 67 | VolumeDir: *volumeDir, 68 | } 69 | if len(cfg.NodeId) == 0 { 70 | klog.V(2).Infof("Get node name from env") 71 | cfg.NodeId = os.Getenv("NODE_NAME") 72 | } 73 | 74 | // Start pprof and gain leadership before executing the main loop 75 | if *enablePprof { 76 | go func() { 77 | klog.Infof("Starting the pprof server on: %s", *pprofPort) 78 | if err := http.ListenAndServe(":"+*pprofPort, nil); err != nil { 79 | klog.Fatalf("Failed to start pprof server: %v", err) 80 | } 81 | }() 82 | } 83 | 84 | // set up signals so we handle the shutdown signal gracefully 85 | ctx := signals.SetupSignalHandler() 86 | 87 | kubeConfig, err := util.BuildClientConfig(*kubeconfig) 88 | if err != nil { 89 | klog.Fatalf("Failed to build kube config: %v", err) 90 | } 91 | kubeConfig.QPS = float32(*kubeAPIQPS) 92 | kubeConfig.Burst = *kubeAPIBurst 93 | 94 | kubeClient, lsClientSet, err := util.NewClientSets(kubeConfig) 95 | if err != nil { 96 | klog.Fatal("failed to build clientSets: %v", err) 97 | } 98 | 99 | sharedInformer := externalversions.NewSharedInformerFactory(lsClientSet, 300*time.Second) 100 | driver, err := localstorage.NewLocalStorage(ctx, cfg, 101 | sharedInformer.Storage().V1().LocalStorages(), 102 | lsClientSet, 103 | kubeClient, 104 | ) 105 | if err != nil { 106 | klog.Fatalf("Failed to initialize localstorage driver :%v", err) 107 | } 108 | 109 | go func() { 110 | klog.Infof("Starting localstorage driver") 111 | if err = driver.Run(ctx); err != nil { 112 | klog.Fatalf("Failed to run localstorage driver :%v", err) 113 | } 114 | }() 115 | 116 | sharedInformer.Start(ctx.Done()) 117 | sharedInformer.WaitForCacheSync(ctx.Done()) 118 | 119 | <-ctx.Done() 120 | } 121 | -------------------------------------------------------------------------------- /cmd/scheduler-extender/scheduler-extender.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "strconv" 22 | "time" 23 | 24 | "k8s.io/client-go/informers" 25 | "k8s.io/klog/v2" 26 | 27 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/informers/externalversions" 28 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/scheduler" 29 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/signals" 30 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/util" 31 | ) 32 | 33 | var ( 34 | kubeconfig = flag.String("kubeconfig", "", "paths to a kubeconfig. Only required if out-of-cluster.") 35 | port = flag.Int("port", 8090, "port is the port that the scheduler server serves at") 36 | ) 37 | 38 | func init() { 39 | _ = flag.Set("logtostderr", "true") 40 | } 41 | 42 | func main() { 43 | klog.InitFlags(nil) 44 | flag.Parse() 45 | 46 | kubeConfig, err := util.BuildClientConfig(*kubeconfig) 47 | if err != nil { 48 | klog.Fatalf("Failed to build kube config: %v", err) 49 | } 50 | kubeClient, lsClientSet, err := util.NewClientSets(kubeConfig) 51 | if err != nil { 52 | klog.Fatalf("Failed to build clientSets: %v", err) 53 | } 54 | 55 | kubeInformer := informers.NewSharedInformerFactory(kubeClient, 300*time.Second) 56 | shareInformer := externalversions.NewSharedInformerFactory(lsClientSet, 300*time.Second) 57 | 58 | sched, err := scheduler.NewScheduleExtender( 59 | shareInformer.Storage().V1().LocalStorages(), 60 | kubeInformer.Core().V1().PersistentVolumeClaims(), 61 | kubeInformer.Storage().V1().StorageClasses(), 62 | ) 63 | if err != nil { 64 | klog.Fatalf("Failed to new schedule extender controller: %s", err) 65 | } 66 | 67 | // set up signals so we handle the shutdown signal gracefully 68 | ctx := signals.SetupSignalHandler() 69 | 70 | // Start all informers. 71 | kubeInformer.Start(ctx.Done()) 72 | shareInformer.Start(ctx.Done()) 73 | // Wait for all caches to sync. 74 | shareInformer.WaitForCacheSync(ctx.Done()) 75 | kubeInformer.WaitForCacheSync(ctx.Done()) 76 | 77 | // Start localstorage scheduler extender server 78 | if err = sched.Run(ctx, ":"+strconv.Itoa(*port)); err != nil { 79 | klog.Fatalf("failed to start localstorage scheduler extender server: %v", err) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /deploy/charts/README.md: -------------------------------------------------------------------------------- 1 | # LocalStorage 2 | 3 | ### Prerequisites 4 | - Kubernetes 1.16+ 5 | - helm v3+ 6 | 7 | ### Installing the Chart 8 | ```shell 9 | helm install pixiu-localstorage -n kube-system ./charts/localstorage --create-namespace 10 | ``` 11 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: localstorage 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/crds/storage.caoyingjunz.io_localstorages.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.8.0 7 | creationTimestamp: null 8 | name: localstorages.storage.caoyingjunz.io 9 | spec: 10 | group: storage.caoyingjunz.io 11 | names: 12 | kind: LocalStorage 13 | listKind: LocalStorageList 14 | plural: localstorages 15 | shortNames: 16 | - pls 17 | - ls 18 | singular: localstorage 19 | scope: Cluster 20 | versions: 21 | - additionalPrinterColumns: 22 | - jsonPath: .status.phase 23 | name: Status 24 | type: string 25 | - jsonPath: .spec.node 26 | name: kubeNode 27 | type: string 28 | - jsonPath: .status.allocatable 29 | name: Allocatable 30 | type: string 31 | - jsonPath: .status.capacity 32 | name: Capacity 33 | type: string 34 | - jsonPath: .metadata.creationTimestamp 35 | name: AGE 36 | type: date 37 | - jsonPath: .spec.volumeGroup 38 | name: VolumeGroup 39 | priority: 1 40 | type: string 41 | name: v1 42 | schema: 43 | openAPIV3Schema: 44 | properties: 45 | apiVersion: 46 | description: 'APIVersion defines the versioned schema of this representation 47 | of an object. Servers should convert recognized schemas to the latest 48 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 49 | type: string 50 | kind: 51 | description: 'Kind is a string value representing the REST resource this 52 | object represents. Servers may infer this from the endpoint the client 53 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 54 | type: string 55 | metadata: 56 | type: object 57 | spec: 58 | properties: 59 | disks: 60 | items: 61 | properties: 62 | identifier: 63 | description: disk identifier, plugin will fill it 64 | type: string 65 | name: 66 | type: string 67 | type: object 68 | type: array 69 | node: 70 | description: Node kubernetes node name 71 | minLength: 1 72 | type: string 73 | volumeGroup: 74 | type: string 75 | type: object 76 | status: 77 | properties: 78 | allocatable: 79 | anyOf: 80 | - type: integer 81 | - type: string 82 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 83 | x-kubernetes-int-or-string: true 84 | capacity: 85 | anyOf: 86 | - type: integer 87 | - type: string 88 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 89 | x-kubernetes-int-or-string: true 90 | conditions: 91 | type: string 92 | phase: 93 | type: string 94 | volumes: 95 | description: List of mount volumes on this node 96 | items: 97 | properties: 98 | attached: 99 | type: boolean 100 | nodeId: 101 | type: string 102 | volId: 103 | type: string 104 | volName: 105 | type: string 106 | volPath: 107 | type: string 108 | volSize: 109 | format: int64 110 | type: integer 111 | type: object 112 | type: array 113 | type: object 114 | type: object 115 | served: true 116 | storage: true 117 | subresources: {} 118 | status: 119 | acceptedNames: 120 | kind: "" 121 | plural: "" 122 | conditions: [] 123 | storedVersions: [] 124 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "localstorage.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "localstorage.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "localstorage.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "localstorage.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 20 | echo "Visit http://127.0.0.1:8080 to use your application" 21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "localstorage.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "localstorage.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "localstorage.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "localstorage.labels" -}} 37 | helm.sh/chart: {{ include "localstorage.chart" . }} 38 | {{ include "localstorage.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "localstorage.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "localstorage.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "localstorage.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "localstorage.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/templates/ls-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: pixiu-ls-controller 11 | template: 12 | metadata: 13 | labels: 14 | app: pixiu-ls-controller 15 | spec: 16 | serviceAccountName: csi-ls-node-sa 17 | containers: 18 | - args: 19 | - -v=2 20 | # port's value equals 0 means health check func disabled 21 | - --healthz-port=10258 22 | - --cert-dir=/tmp/cert 23 | - --port=8443 24 | image: harbor.cloud.pixiuio.com/pixiuio/localstorage-controller:latest 25 | imagePullPolicy: Always 26 | name: ls-controller 27 | volumeMounts: 28 | - mountPath: /tmp/cert 29 | name: cert 30 | readOnly: true 31 | livenessProbe: 32 | httpGet: 33 | path: /healthz 34 | port: 10258 35 | failureThreshold: 5 36 | initialDelaySeconds: 30 37 | timeoutSeconds: 5 38 | periodSeconds: 5 39 | dnsPolicy: Default 40 | nodeSelector: 41 | kubernetes.io/os: linux 42 | restartPolicy: Always 43 | volumes: 44 | - name: cert 45 | secret: 46 | defaultMode: 420 47 | secretName: pixiu-localstorage-cert 48 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/templates/ls-driverinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: storage.k8s.io/v1 3 | kind: CSIDriver 4 | metadata: 5 | name: localstorage.caoyingjunz.io 6 | spec: 7 | attachRequired: false 8 | volumeLifecycleModes: 9 | - Persistent 10 | fsGroupPolicy: File 11 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/templates/ls-rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: csi-ls-node-sa 6 | namespace: kube-system 7 | --- 8 | 9 | apiVersion: v1 10 | kind: Secret 11 | metadata: 12 | name: pixiu-ls-token 13 | namespace: kube-system 14 | annotations: 15 | kubernetes.io/service-account.name: "csi-ls-node-sa" 16 | type: kubernetes.io/service-account-token 17 | --- 18 | 19 | kind: ClusterRole 20 | apiVersion: rbac.authorization.k8s.io/v1 21 | metadata: 22 | name: ls-external-provisioner-role 23 | rules: 24 | - apiGroups: [""] 25 | resources: ["persistentvolumes"] 26 | verbs: ["get", "list", "watch", "create", "delete"] 27 | - apiGroups: [""] 28 | resources: ["persistentvolumeclaims"] 29 | verbs: ["get", "list", "watch", "update"] 30 | - apiGroups: ["storage.k8s.io"] 31 | resources: ["volumeattachments"] 32 | verbs: ["get", "list", "watch", "create", "delete"] 33 | - apiGroups: ["storage.k8s.io"] 34 | resources: ["storageclasses"] 35 | verbs: ["get", "list", "watch"] 36 | - apiGroups: [""] 37 | resources: ["events"] 38 | verbs: ["get", "list", "watch", "create", "update", "patch"] 39 | - apiGroups: ["storage.k8s.io"] 40 | resources: ["csinodes"] 41 | verbs: ["get", "list", "watch"] 42 | - apiGroups: [""] 43 | resources: ["nodes"] 44 | verbs: ["get", "list", "watch"] 45 | - apiGroups: ["coordination.k8s.io"] 46 | resources: ["leases"] 47 | verbs: ["get", "list", "watch", "create", "update", "patch"] 48 | - apiGroups: [""] 49 | resources: ["secrets"] 50 | verbs: ["get"] 51 | - apiGroups: [""] 52 | resources: ["endpoints"] 53 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 54 | - apiGroups: ["storage.caoyingjunz.io"] 55 | resources: ["localstorages"] 56 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 57 | --- 58 | 59 | kind: ClusterRoleBinding 60 | apiVersion: rbac.authorization.k8s.io/v1 61 | metadata: 62 | name: ls-csi-provisioner-binding 63 | subjects: 64 | - kind: ServiceAccount 65 | name: csi-ls-node-sa 66 | namespace: kube-system 67 | roleRef: 68 | kind: ClusterRole 69 | name: ls-external-provisioner-role 70 | apiGroup: rbac.authorization.k8s.io 71 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/templates/ls-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | ports: 8 | - name: tcp-8443 9 | port: 443 10 | protocol: TCP 11 | targetPort: 8443 12 | selector: 13 | app: pixiu-ls-controller 14 | type: ClusterIP 15 | --- 16 | apiVersion: v1 17 | kind: Service 18 | metadata: 19 | name: pixiu-ls-scheduler 20 | namespace: kube-system 21 | spec: 22 | ports: 23 | - name: tcp-8090 24 | nodePort: 30666 25 | port: 8090 26 | protocol: TCP 27 | targetPort: 8090 28 | selector: 29 | app: pixiu-ls-scheduler 30 | type: NodePort 31 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/templates/ls-webhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: pixiu-ls-mutating-configuration 6 | webhooks: 7 | - admissionReviewVersions: 8 | - v1 9 | clientConfig: 10 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 11 | service: 12 | name: pixiu-ls-controller 13 | namespace: kube-system 14 | path: /mutate-v1-localstorage 15 | port: 443 16 | failurePolicy: Fail 17 | matchPolicy: Equivalent 18 | name: webhook.pixiu.io 19 | namespaceSelector: {} 20 | objectSelector: {} 21 | reinvocationPolicy: Never 22 | rules: 23 | - apiGroups: 24 | - storage.caoyingjunz.io 25 | apiVersions: 26 | - v1 27 | operations: 28 | - CREATE 29 | - UPDATE 30 | resources: 31 | - localstorages 32 | scope: '*' 33 | sideEffects: None 34 | timeoutSeconds: 10 35 | 36 | --- 37 | apiVersion: admissionregistration.k8s.io/v1 38 | kind: ValidatingWebhookConfiguration 39 | metadata: 40 | name: pixiu-ls-validating-configuration 41 | webhooks: 42 | - admissionReviewVersions: 43 | - v1 44 | clientConfig: 45 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 46 | service: 47 | name: pixiu-ls-controller 48 | namespace: kube-system 49 | path: /validate-v1-localstorage 50 | port: 443 51 | failurePolicy: Fail 52 | matchPolicy: Equivalent 53 | name: webhook.pixiu.io 54 | namespaceSelector: {} 55 | objectSelector: {} 56 | rules: 57 | - apiGroups: 58 | - storage.caoyingjunz.io 59 | apiVersions: 60 | - v1 61 | operations: 62 | - CREATE 63 | - UPDATE 64 | resources: 65 | - localstorages 66 | scope: '*' 67 | sideEffects: None 68 | timeoutSeconds: 10 69 | -------------------------------------------------------------------------------- /deploy/charts/localstorage/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for localstorage. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: nginx 9 | pullPolicy: IfNotPresent 10 | # Overrides the image tag whose default is the chart appVersion. 11 | tag: "" 12 | 13 | imagePullSecrets: [] 14 | nameOverride: "" 15 | fullnameOverride: "" 16 | 17 | serviceAccount: 18 | # Specifies whether a service account should be created 19 | create: true 20 | # Annotations to add to the service account 21 | annotations: {} 22 | # The name of the service account to use. 23 | # If not set and create is true, a name is generated using the fullname template 24 | name: "" 25 | 26 | podAnnotations: {} 27 | 28 | podSecurityContext: {} 29 | # fsGroup: 2000 30 | 31 | securityContext: {} 32 | # capabilities: 33 | # drop: 34 | # - ALL 35 | # readOnlyRootFilesystem: true 36 | # runAsNonRoot: true 37 | # runAsUser: 1000 38 | 39 | service: 40 | type: ClusterIP 41 | port: 80 42 | 43 | ingress: 44 | enabled: false 45 | annotations: {} 46 | # kubernetes.io/ingress.class: nginx 47 | # kubernetes.io/tls-acme: "true" 48 | hosts: 49 | - host: chart-example.local 50 | paths: 51 | - path: / 52 | backend: 53 | serviceName: chart-example.local 54 | servicePort: 80 55 | tls: [] 56 | # - secretName: chart-example-tls 57 | # hosts: 58 | # - chart-example.local 59 | 60 | resources: {} 61 | # We usually recommend not to specify default resources and to leave this as a conscious 62 | # choice for the user. This also increases chances charts run on environments with little 63 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 64 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 65 | # limits: 66 | # cpu: 100m 67 | # memory: 128Mi 68 | # requests: 69 | # cpu: 100m 70 | # memory: 128Mi 71 | 72 | autoscaling: 73 | enabled: false 74 | minReplicas: 1 75 | maxReplicas: 100 76 | targetCPUUtilizationPercentage: 80 77 | # targetMemoryUtilizationPercentage: 80 78 | 79 | nodeSelector: {} 80 | 81 | tolerations: [] 82 | 83 | affinity: {} 84 | -------------------------------------------------------------------------------- /deploy/crds/storage.caoyingjunz.io_localstorages.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.8.0 7 | creationTimestamp: null 8 | name: localstorages.storage.caoyingjunz.io 9 | spec: 10 | group: storage.caoyingjunz.io 11 | names: 12 | kind: LocalStorage 13 | listKind: LocalStorageList 14 | plural: localstorages 15 | shortNames: 16 | - pls 17 | - ls 18 | singular: localstorage 19 | scope: Cluster 20 | versions: 21 | - additionalPrinterColumns: 22 | - jsonPath: .status.phase 23 | name: Status 24 | type: string 25 | - jsonPath: .spec.node 26 | name: kubeNode 27 | type: string 28 | - jsonPath: .status.allocatable 29 | name: Allocatable 30 | type: string 31 | - jsonPath: .status.capacity 32 | name: Capacity 33 | type: string 34 | - jsonPath: .metadata.creationTimestamp 35 | name: AGE 36 | type: date 37 | name: v1 38 | schema: 39 | openAPIV3Schema: 40 | properties: 41 | apiVersion: 42 | description: 'APIVersion defines the versioned schema of this representation 43 | of an object. Servers should convert recognized schemas to the latest 44 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 45 | type: string 46 | kind: 47 | description: 'Kind is a string value representing the REST resource this 48 | object represents. Servers may infer this from the endpoint the client 49 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 50 | type: string 51 | metadata: 52 | type: object 53 | spec: 54 | properties: 55 | lvm: 56 | description: Lvm localstorage Logical Volume Manage spec 57 | properties: 58 | disks: 59 | items: 60 | properties: 61 | identifier: 62 | description: disk identifier, plugin will fill it 63 | type: string 64 | name: 65 | type: string 66 | type: object 67 | type: array 68 | volumeGroup: 69 | type: string 70 | type: object 71 | node: 72 | description: Node kubernetes node name 73 | minLength: 1 74 | type: string 75 | path: 76 | description: Path localstorage hostPath volume spec 77 | properties: 78 | volumeDir: 79 | type: string 80 | type: object 81 | type: object 82 | status: 83 | properties: 84 | allocatable: 85 | anyOf: 86 | - type: integer 87 | - type: string 88 | description: Allocatable and Capacity is the Quantity on this node 89 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 90 | x-kubernetes-int-or-string: true 91 | capacity: 92 | anyOf: 93 | - type: integer 94 | - type: string 95 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 96 | x-kubernetes-int-or-string: true 97 | conditions: 98 | type: string 99 | mode: 100 | type: string 101 | phase: 102 | description: Localstorage phase 103 | type: string 104 | volumes: 105 | description: List of mount volumes on this node 106 | items: 107 | properties: 108 | attached: 109 | type: boolean 110 | nodeId: 111 | type: string 112 | volId: 113 | type: string 114 | volName: 115 | type: string 116 | volPath: 117 | type: string 118 | volSize: 119 | format: int64 120 | type: integer 121 | type: object 122 | type: array 123 | type: object 124 | type: object 125 | served: true 126 | storage: true 127 | subresources: {} 128 | status: 129 | acceptedNames: 130 | kind: "" 131 | plural: "" 132 | conditions: [] 133 | storedVersions: [] 134 | -------------------------------------------------------------------------------- /deploy/install-driver.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | -------------------------------------------------------------------------------- /deploy/latest/ls-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: pixiu-ls-controller 11 | template: 12 | metadata: 13 | labels: 14 | app: pixiu-ls-controller 15 | spec: 16 | serviceAccountName: csi-ls-node-sa 17 | containers: 18 | - args: 19 | - -v=2 20 | # port's value equals 0 means health check func disabled 21 | - --healthz-port=10258 22 | - --cert-dir=/tmp/cert 23 | - --port=8443 24 | image: harbor.cloud.pixiuio.com/pixiuio/localstorage-controller:latest 25 | imagePullPolicy: Always 26 | name: ls-controller 27 | volumeMounts: 28 | - mountPath: /tmp/cert 29 | name: cert 30 | readOnly: true 31 | livenessProbe: 32 | httpGet: 33 | path: /healthz 34 | port: 10258 35 | failureThreshold: 5 36 | initialDelaySeconds: 30 37 | timeoutSeconds: 5 38 | periodSeconds: 5 39 | dnsPolicy: Default 40 | nodeSelector: 41 | kubernetes.io/os: linux 42 | restartPolicy: Always 43 | volumes: 44 | - name: cert 45 | secret: 46 | defaultMode: 420 47 | secretName: pixiu-localstorage-cert 48 | -------------------------------------------------------------------------------- /deploy/latest/ls-driverinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: storage.k8s.io/v1 3 | kind: CSIDriver 4 | metadata: 5 | name: localstorage.caoyingjunz.io 6 | spec: 7 | attachRequired: false 8 | volumeLifecycleModes: 9 | - Persistent 10 | fsGroupPolicy: File 11 | -------------------------------------------------------------------------------- /deploy/latest/ls-node.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: DaemonSet 3 | apiVersion: apps/v1 4 | metadata: 5 | name: pixiu-ls-node 6 | namespace: kube-system 7 | spec: 8 | updateStrategy: 9 | rollingUpdate: 10 | maxUnavailable: 1 11 | type: RollingUpdate 12 | selector: 13 | matchLabels: 14 | app: pixiu-ls-node 15 | template: 16 | metadata: 17 | labels: 18 | app: pixiu-ls-node 19 | spec: 20 | # hostNetwork: true 21 | dnsPolicy: Default # available values: Default, ClusterFirstWithHostNet, ClusterFirst 22 | serviceAccountName: csi-ls-node-sa 23 | affinity: 24 | nodeAffinity: 25 | requiredDuringSchedulingIgnoredDuringExecution: 26 | nodeSelectorTerms: 27 | - matchExpressions: 28 | - key: storage.caoyingjunz.io/node 29 | operator: Exists 30 | tolerations: 31 | - operator: "Exists" 32 | containers: 33 | - name: liveness-probe 34 | image: pixiuio/livenessprobe:v2.8.0 35 | args: 36 | - --csi-address=/csi/csi.sock 37 | - --probe-timeout=3s 38 | - --health-port=29653 39 | - --v=2 40 | volumeMounts: 41 | - name: socket-dir 42 | mountPath: /csi 43 | resources: 44 | limits: 45 | memory: 100Mi 46 | requests: 47 | cpu: 10m 48 | memory: 20Mi 49 | 50 | - name: node-driver-registrar 51 | image: pixiuio/csi-node-driver-registrar:v2.6.2 52 | args: 53 | - --v=2 54 | - --csi-address=/csi/csi.sock 55 | - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 56 | livenessProbe: 57 | exec: 58 | command: 59 | - /csi-node-driver-registrar 60 | - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 61 | - --mode=kubelet-registration-probe 62 | initialDelaySeconds: 30 63 | timeoutSeconds: 15 64 | env: 65 | - name: DRIVER_REG_SOCK_PATH 66 | value: /var/lib/kubelet/plugins/csi-lsplugin/csi.sock 67 | - name: KUBE_NODE_NAME 68 | valueFrom: 69 | fieldRef: 70 | fieldPath: spec.nodeName 71 | volumeMounts: 72 | - name: socket-dir 73 | mountPath: /csi 74 | - name: registration-dir 75 | mountPath: /registration 76 | resources: 77 | limits: 78 | memory: 100Mi 79 | requests: 80 | cpu: 10m 81 | memory: 20Mi 82 | 83 | - name: csi-provisioner 84 | image: jacky06/csi-provisioner:v0.1 85 | args: 86 | - -v=5 87 | - --csi-address=/csi/csi.sock 88 | env: 89 | - name: NODE_NAME 90 | valueFrom: 91 | fieldRef: 92 | fieldPath: spec.nodeName 93 | securityContext: 94 | # This is necessary only for systems with SELinux, where 95 | # non-privileged sidecar containers cannot access unix domain socket 96 | # created by privileged CSI driver container. 97 | privileged: true 98 | volumeMounts: 99 | - mountPath: /csi 100 | name: socket-dir 101 | 102 | - name: ls-plugin 103 | securityContext: 104 | privileged: true 105 | capabilities: 106 | add: ["SYS_ADMIN"] 107 | allowPrivilegeEscalation: true 108 | image: harbor.cloud.pixiuio.com/pixiuio/localstorageplugin:latest 109 | args: 110 | - --endpoint=$(CSI_ENDPOINT) 111 | - --volume-dir=/data 112 | - -v=5 113 | env: 114 | - name: NODE_NAME 115 | valueFrom: 116 | fieldRef: 117 | fieldPath: spec.nodeName 118 | - name: CSI_ENDPOINT 119 | value: unix:///csi/csi.sock 120 | ports: 121 | - containerPort: 29653 122 | name: healthz 123 | protocol: TCP 124 | livenessProbe: 125 | failureThreshold: 5 126 | httpGet: 127 | path: /healthz 128 | port: healthz 129 | initialDelaySeconds: 30 130 | timeoutSeconds: 10 131 | periodSeconds: 30 132 | imagePullPolicy: "Always" 133 | volumeMounts: 134 | - name: socket-dir 135 | mountPath: /csi 136 | - name: pods-mount-dir 137 | mountPath: /var/lib/kubelet/pods 138 | mountPropagation: "Bidirectional" 139 | - mountPath: /data 140 | name: volume-dir 141 | resources: 142 | limits: 143 | memory: 300Mi 144 | requests: 145 | cpu: 10m 146 | memory: 20Mi 147 | volumes: 148 | - name: socket-dir 149 | hostPath: 150 | path: /var/lib/kubelet/plugins/csi-lsplugin 151 | type: DirectoryOrCreate 152 | - name: pods-mount-dir 153 | hostPath: 154 | path: /var/lib/kubelet/pods 155 | type: Directory 156 | - hostPath: 157 | path: /var/lib/kubelet/plugins_registry 158 | type: Directory 159 | name: registration-dir 160 | - hostPath: 161 | path: /data 162 | type: DirectoryOrCreate 163 | name: volume-dir 164 | -------------------------------------------------------------------------------- /deploy/latest/ls-rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: csi-ls-node-sa 6 | namespace: kube-system 7 | --- 8 | 9 | apiVersion: v1 10 | kind: Secret 11 | metadata: 12 | name: pixiu-ls-token 13 | namespace: kube-system 14 | annotations: 15 | kubernetes.io/service-account.name: "csi-ls-node-sa" 16 | type: kubernetes.io/service-account-token 17 | --- 18 | 19 | kind: ClusterRole 20 | apiVersion: rbac.authorization.k8s.io/v1 21 | metadata: 22 | name: ls-external-provisioner-role 23 | rules: 24 | - apiGroups: [""] 25 | resources: ["persistentvolumes"] 26 | verbs: ["get", "list", "watch", "create", "delete"] 27 | - apiGroups: [""] 28 | resources: ["persistentvolumeclaims"] 29 | verbs: ["get", "list", "watch", "update"] 30 | - apiGroups: ["storage.k8s.io"] 31 | resources: ["volumeattachments"] 32 | verbs: ["get", "list", "watch", "create", "delete"] 33 | - apiGroups: ["storage.k8s.io"] 34 | resources: ["storageclasses"] 35 | verbs: ["get", "list", "watch"] 36 | - apiGroups: [""] 37 | resources: ["events"] 38 | verbs: ["get", "list", "watch", "create", "update", "patch"] 39 | - apiGroups: ["storage.k8s.io"] 40 | resources: ["csinodes"] 41 | verbs: ["get", "list", "watch"] 42 | - apiGroups: [""] 43 | resources: ["nodes"] 44 | verbs: ["get", "list", "watch"] 45 | - apiGroups: ["coordination.k8s.io"] 46 | resources: ["leases"] 47 | verbs: ["get", "list", "watch", "create", "update", "patch"] 48 | - apiGroups: [""] 49 | resources: ["secrets"] 50 | verbs: ["get"] 51 | - apiGroups: [""] 52 | resources: ["endpoints"] 53 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 54 | - apiGroups: ["storage.caoyingjunz.io"] 55 | resources: ["localstorages"] 56 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 57 | --- 58 | 59 | kind: ClusterRoleBinding 60 | apiVersion: rbac.authorization.k8s.io/v1 61 | metadata: 62 | name: ls-csi-provisioner-binding 63 | subjects: 64 | - kind: ServiceAccount 65 | name: csi-ls-node-sa 66 | namespace: kube-system 67 | roleRef: 68 | kind: ClusterRole 69 | name: ls-external-provisioner-role 70 | apiGroup: rbac.authorization.k8s.io 71 | -------------------------------------------------------------------------------- /deploy/latest/ls-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | ports: 8 | - name: tcp-8443 9 | port: 443 10 | protocol: TCP 11 | targetPort: 8443 12 | selector: 13 | app: pixiu-ls-controller 14 | type: ClusterIP 15 | --- 16 | apiVersion: v1 17 | kind: Service 18 | metadata: 19 | name: pixiu-ls-scheduler 20 | namespace: kube-system 21 | spec: 22 | ports: 23 | - name: tcp-8090 24 | nodePort: 30666 25 | port: 8090 26 | protocol: TCP 27 | targetPort: 8090 28 | selector: 29 | app: pixiu-ls-scheduler 30 | type: NodePort 31 | -------------------------------------------------------------------------------- /deploy/latest/ls-webhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: pixiu-ls-mutating-configuration 6 | webhooks: 7 | - admissionReviewVersions: 8 | - v1 9 | clientConfig: 10 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 11 | service: 12 | name: pixiu-ls-controller 13 | namespace: kube-system 14 | path: /mutate-v1-localstorage 15 | port: 443 16 | failurePolicy: Fail 17 | matchPolicy: Equivalent 18 | name: webhook.pixiu.io 19 | namespaceSelector: {} 20 | objectSelector: {} 21 | reinvocationPolicy: Never 22 | rules: 23 | - apiGroups: 24 | - storage.caoyingjunz.io 25 | apiVersions: 26 | - v1 27 | operations: 28 | - CREATE 29 | - UPDATE 30 | resources: 31 | - localstorages 32 | scope: '*' 33 | sideEffects: None 34 | timeoutSeconds: 10 35 | 36 | --- 37 | apiVersion: admissionregistration.k8s.io/v1 38 | kind: ValidatingWebhookConfiguration 39 | metadata: 40 | name: pixiu-ls-validating-configuration 41 | webhooks: 42 | - admissionReviewVersions: 43 | - v1 44 | clientConfig: 45 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 46 | service: 47 | name: pixiu-ls-controller 48 | namespace: kube-system 49 | path: /validate-v1-localstorage 50 | port: 443 51 | failurePolicy: Fail 52 | matchPolicy: Equivalent 53 | name: webhook.pixiu.io 54 | namespaceSelector: {} 55 | objectSelector: {} 56 | rules: 57 | - apiGroups: 58 | - storage.caoyingjunz.io 59 | apiVersions: 60 | - v1 61 | operations: 62 | - CREATE 63 | - UPDATE 64 | resources: 65 | - localstorages 66 | scope: '*' 67 | sideEffects: None 68 | timeoutSeconds: 10 69 | -------------------------------------------------------------------------------- /deploy/ls-job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: pixiu-ls-job 5 | namespace: kube-system 6 | spec: 7 | backoffLimit: 6 8 | completions: 1 9 | parallelism: 1 10 | template: 11 | metadata: 12 | labels: 13 | app: pixiu-ls-job 14 | name: pixiu-ls-job 15 | spec: 16 | containers: 17 | - args: 18 | - --create-localstorage 19 | image: harbor.cloud.pixiuio.com/pixiuio/localstorage-job:latest 20 | imagePullPolicy: IfNotPresent 21 | name: pixiu-ls-job 22 | dnsPolicy: ClusterFirst 23 | nodeSelector: 24 | kubernetes.io/os: linux 25 | restartPolicy: OnFailure 26 | serviceAccountName: csi-ls-node-sa 27 | terminationGracePeriodSeconds: 30 28 | -------------------------------------------------------------------------------- /deploy/ls-scheduler-config.yaml: -------------------------------------------------------------------------------- 1 | # Used since Kubernetes v1.23 2 | apiVersion: kubescheduler.config.k8s.io/v1beta3 3 | kind: KubeSchedulerConfiguration 4 | clientConnection: 5 | kubeconfig: /etc/kubernetes/scheduler.conf 6 | extenders: 7 | - urlPrefix: http://pixiu-ls-scheduler.kube-system:8090/localstorage-scheduler 8 | filterVerb: filter 9 | prioritizeVerb: prioritize 10 | enableHTTPS: false 11 | weight: 5 12 | nodeCacheCapable: true 13 | ignorable: false 14 | -------------------------------------------------------------------------------- /deploy/ls-scheduler.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | labels: 5 | app: pixiu-ls-scheduler 6 | name: pixiu-ls-scheduler 7 | namespace: kube-system 8 | spec: 9 | containers: 10 | - args: 11 | - -v=2 12 | - --port=8090 13 | - --kubeconfig=/etc/kubernetes/pixiu-ls-scheduler.conf 14 | image: harbor.cloud.pixiuio.com/pixiuio/scheduler-extender:latest 15 | imagePullPolicy: IfNotPresent 16 | name: pixiu-ls-scheduler 17 | livenessProbe: 18 | httpGet: 19 | path: /version 20 | port: 8090 21 | initialDelaySeconds: 5 22 | timeoutSeconds: 30 23 | volumeMounts: 24 | - mountPath: /etc/kubernetes/pixiu-ls-scheduler.conf 25 | name: ls-scheduler 26 | volumes: 27 | - hostPath: 28 | path: /etc/kubernetes/pixiu-ls-scheduler.conf 29 | type: FileOrCreate 30 | name: ls-scheduler 31 | -------------------------------------------------------------------------------- /deploy/ls-storageclass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: pixiu-localstorage 5 | mountOptions: 6 | - owner=caoyingjunz 7 | parameters: 8 | project: pixiu 9 | provisioner: localstorage.csi.caoyingjunz.io 10 | reclaimPolicy: Delete 11 | volumeBindingMode: WaitForFirstConsumer 12 | -------------------------------------------------------------------------------- /deploy/uninstall-driver.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | -------------------------------------------------------------------------------- /deploy/v1.0.0/ls-driverinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: storage.k8s.io/v1 3 | kind: CSIDriver 4 | metadata: 5 | name: localstorage.caoyingjunz.io 6 | spec: 7 | attachRequired: false 8 | volumeLifecycleModes: 9 | - Persistent 10 | fsGroupPolicy: File 11 | -------------------------------------------------------------------------------- /deploy/v1.0.0/ls-node.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: DaemonSet 3 | apiVersion: apps/v1 4 | metadata: 5 | name: pixiu-localstorage-node 6 | namespace: kube-system 7 | spec: 8 | updateStrategy: 9 | rollingUpdate: 10 | maxUnavailable: 1 11 | type: RollingUpdate 12 | selector: 13 | matchLabels: 14 | app: csi-ls-node 15 | template: 16 | metadata: 17 | labels: 18 | app: csi-ls-node 19 | spec: 20 | # hostNetwork: true 21 | dnsPolicy: Default # available values: Default, ClusterFirstWithHostNet, ClusterFirst 22 | serviceAccountName: csi-ls-node-sa 23 | nodeSelector: 24 | kubernetes.io/os: linux 25 | tolerations: 26 | - operator: "Exists" 27 | containers: 28 | - name: liveness-probe 29 | image: pixiuio/livenessprobe:v2.8.0 30 | args: 31 | - --csi-address=/csi/csi.sock 32 | - --probe-timeout=3s 33 | - --health-port=29653 34 | - --v=2 35 | volumeMounts: 36 | - name: socket-dir 37 | mountPath: /csi 38 | resources: 39 | limits: 40 | memory: 100Mi 41 | requests: 42 | cpu: 10m 43 | memory: 20Mi 44 | 45 | # - name: node-driver-registrar 46 | # image: pixiuio/csi-node-driver-registrar:v2.6.2 47 | # args: 48 | # - --v=2 49 | # - --csi-address=/csi/csi.sock 50 | # - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 51 | # livenessProbe: 52 | # exec: 53 | # command: 54 | # - /csi-node-driver-registrar 55 | # - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 56 | # - --mode=kubelet-registration-probe 57 | # initialDelaySeconds: 30 58 | # timeoutSeconds: 15 59 | # env: 60 | # - name: DRIVER_REG_SOCK_PATH 61 | # value: /var/lib/kubelet/plugins_registry/localstorage.csi.caoyingjunz.io-reg.sock 62 | # - name: KUBE_NODE_NAME 63 | # valueFrom: 64 | # fieldRef: 65 | # fieldPath: spec.nodeName 66 | # volumeMounts: 67 | # - name: socket-dir 68 | # mountPath: /csi 69 | # - name: registration-dir 70 | # mountPath: /registration 71 | # resources: 72 | # limits: 73 | # memory: 100Mi 74 | # requests: 75 | # cpu: 10m 76 | # memory: 20Mi 77 | 78 | - name: csi-provisioner 79 | image: jacky06/csi-provisioner:v0.1 80 | args: 81 | - -v=5 82 | - --csi-address=/csi/csi.sock 83 | env: 84 | - name: NODE_NAME 85 | valueFrom: 86 | fieldRef: 87 | fieldPath: spec.nodeName 88 | securityContext: 89 | # This is necessary only for systems with SELinux, where 90 | # non-privileged sidecar containers cannot access unix domain socket 91 | # created by privileged CSI driver container. 92 | privileged: true 93 | volumeMounts: 94 | - mountPath: /csi 95 | name: socket-dir 96 | 97 | - name: localstorage 98 | securityContext: 99 | privileged: true 100 | capabilities: 101 | add: ["SYS_ADMIN"] 102 | allowPrivilegeEscalation: true 103 | image: pixiuio/lsplugin:v1.0.0 104 | args: 105 | - "-v=5" 106 | - "--endpoint=$(CSI_ENDPOINT)" 107 | - "--nodeid=$(KUBE_NODE_NAME)" 108 | - "--volume-dir=/data" 109 | env: 110 | - name: NODE_ID 111 | valueFrom: 112 | fieldRef: 113 | fieldPath: spec.nodeName 114 | - name: CSI_ENDPOINT 115 | value: unix:///csi/csi.sock 116 | ports: 117 | - containerPort: 29653 118 | name: healthz 119 | protocol: TCP 120 | livenessProbe: 121 | failureThreshold: 5 122 | httpGet: 123 | path: /healthz 124 | port: healthz 125 | initialDelaySeconds: 30 126 | timeoutSeconds: 10 127 | periodSeconds: 30 128 | imagePullPolicy: "IfNotPresent" 129 | volumeMounts: 130 | - name: socket-dir 131 | mountPath: /csi 132 | - name: pods-mount-dir 133 | mountPath: /var/lib/kubelet/pods 134 | mountPropagation: "Bidirectional" 135 | - mountPath: /data 136 | name: volume-dir 137 | resources: 138 | limits: 139 | memory: 300Mi 140 | requests: 141 | cpu: 10m 142 | memory: 20Mi 143 | volumes: 144 | - name: socket-dir 145 | hostPath: 146 | path: /var/lib/kubelet/plugins/csi-lsplugin 147 | type: DirectoryOrCreate 148 | - name: pods-mount-dir 149 | hostPath: 150 | path: /var/lib/kubelet/pods 151 | type: Directory 152 | - hostPath: 153 | path: /var/lib/kubelet/plugins_registry 154 | type: Directory 155 | name: registration-dir 156 | - hostPath: 157 | path: /data 158 | type: DirectoryOrCreate 159 | name: volume-dir 160 | -------------------------------------------------------------------------------- /deploy/v1.0.0/ls-rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: csi-ls-node-sa 6 | namespace: kube-system 7 | --- 8 | 9 | kind: ClusterRole 10 | apiVersion: rbac.authorization.k8s.io/v1 11 | metadata: 12 | name: ls-external-provisioner-role 13 | rules: 14 | - apiGroups: [""] 15 | resources: ["persistentvolumes"] 16 | verbs: ["get", "list", "watch", "create", "delete"] 17 | - apiGroups: [""] 18 | resources: ["persistentvolumeclaims"] 19 | verbs: ["get", "list", "watch", "update"] 20 | - apiGroups: ["storage.k8s.io"] 21 | resources: ["volumeattachments"] 22 | verbs: ["get", "list", "watch", "create", "delete"] 23 | - apiGroups: ["storage.k8s.io"] 24 | resources: ["storageclasses"] 25 | verbs: ["get", "list", "watch"] 26 | - apiGroups: [""] 27 | resources: ["events"] 28 | verbs: ["get", "list", "watch", "create", "update", "patch"] 29 | - apiGroups: ["storage.k8s.io"] 30 | resources: ["csinodes"] 31 | verbs: ["get", "list", "watch"] 32 | - apiGroups: [""] 33 | resources: ["nodes"] 34 | verbs: ["get", "list", "watch"] 35 | - apiGroups: ["coordination.k8s.io"] 36 | resources: ["leases"] 37 | verbs: ["get", "list", "watch", "create", "update", "patch"] 38 | - apiGroups: [""] 39 | resources: ["secrets"] 40 | verbs: ["get"] 41 | --- 42 | 43 | kind: ClusterRoleBinding 44 | apiVersion: rbac.authorization.k8s.io/v1 45 | metadata: 46 | name: ls-csi-provisioner-binding 47 | subjects: 48 | - kind: ServiceAccount 49 | name: csi-ls-node-sa 50 | namespace: kube-system 51 | roleRef: 52 | kind: ClusterRole 53 | name: ls-external-provisioner-role 54 | apiGroup: rbac.authorization.k8s.io 55 | -------------------------------------------------------------------------------- /deploy/v1.0.1/ls-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: pixiu-localstorage-controller 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: pixiu-ls-controller 11 | template: 12 | metadata: 13 | labels: 14 | app: pixiu-ls-controller 15 | spec: 16 | serviceAccountName: csi-ls-node-sa 17 | containers: 18 | - args: 19 | - -v=2 20 | # port's value equals 0 means health check func disabled 21 | - --healthz-port=10258 22 | - --cert-dir=/tmp/cert 23 | - --port=8443 24 | image: pixiuio/localstorage-controller:v1.0.1 25 | imagePullPolicy: IfNotPresent 26 | name: ls-controller 27 | volumeMounts: 28 | - mountPath: /tmp/cert 29 | name: cert 30 | readOnly: true 31 | livenessProbe: 32 | httpGet: 33 | path: /healthz 34 | port: 10258 35 | failureThreshold: 5 36 | initialDelaySeconds: 30 37 | timeoutSeconds: 5 38 | periodSeconds: 5 39 | dnsPolicy: Default 40 | nodeSelector: 41 | kubernetes.io/os: linux 42 | restartPolicy: Always 43 | volumes: 44 | - name: cert 45 | secret: 46 | defaultMode: 420 47 | secretName: pixiu-localstorage-cert 48 | -------------------------------------------------------------------------------- /deploy/v1.0.1/ls-driverinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: storage.k8s.io/v1 3 | kind: CSIDriver 4 | metadata: 5 | name: localstorage.caoyingjunz.io 6 | spec: 7 | attachRequired: false 8 | volumeLifecycleModes: 9 | - Persistent 10 | fsGroupPolicy: File 11 | -------------------------------------------------------------------------------- /deploy/v1.0.1/ls-node.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: DaemonSet 3 | apiVersion: apps/v1 4 | metadata: 5 | name: pixiu-localstorage-node 6 | namespace: kube-system 7 | spec: 8 | updateStrategy: 9 | rollingUpdate: 10 | maxUnavailable: 1 11 | type: RollingUpdate 12 | selector: 13 | matchLabels: 14 | app: csi-ls-node 15 | template: 16 | metadata: 17 | labels: 18 | app: csi-ls-node 19 | spec: 20 | # hostNetwork: true 21 | dnsPolicy: Default # available values: Default, ClusterFirstWithHostNet, ClusterFirst 22 | serviceAccountName: csi-ls-node-sa 23 | affinity: 24 | nodeAffinity: 25 | requiredDuringSchedulingIgnoredDuringExecution: 26 | nodeSelectorTerms: 27 | - matchExpressions: 28 | - key: storage.caoyingjunz.io/node 29 | operator: Exists 30 | tolerations: 31 | - operator: "Exists" 32 | containers: 33 | - name: liveness-probe 34 | image: pixiuio/livenessprobe:v2.8.0 35 | args: 36 | - --csi-address=/csi/csi.sock 37 | - --probe-timeout=3s 38 | - --health-port=29653 39 | - --v=2 40 | volumeMounts: 41 | - name: socket-dir 42 | mountPath: /csi 43 | resources: 44 | limits: 45 | memory: 100Mi 46 | requests: 47 | cpu: 10m 48 | memory: 20Mi 49 | 50 | - name: node-driver-registrar 51 | image: pixiuio/csi-node-driver-registrar:v2.6.2 52 | args: 53 | - --v=2 54 | - --csi-address=/csi/csi.sock 55 | - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 56 | livenessProbe: 57 | exec: 58 | command: 59 | - /csi-node-driver-registrar 60 | - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 61 | - --mode=kubelet-registration-probe 62 | initialDelaySeconds: 30 63 | timeoutSeconds: 15 64 | env: 65 | - name: DRIVER_REG_SOCK_PATH 66 | value: /var/lib/kubelet/plugins/csi-lsplugin/csi.sock 67 | - name: KUBE_NODE_NAME 68 | valueFrom: 69 | fieldRef: 70 | fieldPath: spec.nodeName 71 | volumeMounts: 72 | - name: socket-dir 73 | mountPath: /csi 74 | - name: registration-dir 75 | mountPath: /registration 76 | resources: 77 | limits: 78 | memory: 100Mi 79 | requests: 80 | cpu: 10m 81 | memory: 20Mi 82 | 83 | - name: csi-provisioner 84 | image: jacky06/csi-provisioner:v0.1 85 | args: 86 | - -v=5 87 | - --csi-address=/csi/csi.sock 88 | env: 89 | - name: NODE_NAME 90 | valueFrom: 91 | fieldRef: 92 | fieldPath: spec.nodeName 93 | securityContext: 94 | # This is necessary only for systems with SELinux, where 95 | # non-privileged sidecar containers cannot access unix domain socket 96 | # created by privileged CSI driver container. 97 | privileged: true 98 | volumeMounts: 99 | - mountPath: /csi 100 | name: socket-dir 101 | 102 | - name: ls-plugin 103 | securityContext: 104 | privileged: true 105 | capabilities: 106 | add: ["SYS_ADMIN"] 107 | allowPrivilegeEscalation: true 108 | image: pixiuio/localstorageplugin:v1.0.1 109 | args: 110 | - "-v=5" 111 | - "--endpoint=$(CSI_ENDPOINT)" 112 | - "--volume-dir=/data" 113 | env: 114 | - name: NODE_NAME 115 | valueFrom: 116 | fieldRef: 117 | fieldPath: spec.nodeName 118 | - name: CSI_ENDPOINT 119 | value: unix:///csi/csi.sock 120 | ports: 121 | - containerPort: 29653 122 | name: healthz 123 | protocol: TCP 124 | livenessProbe: 125 | failureThreshold: 5 126 | httpGet: 127 | path: /healthz 128 | port: healthz 129 | initialDelaySeconds: 30 130 | timeoutSeconds: 10 131 | periodSeconds: 30 132 | imagePullPolicy: IfNotPresent 133 | volumeMounts: 134 | - name: socket-dir 135 | mountPath: /csi 136 | - name: pods-mount-dir 137 | mountPath: /var/lib/kubelet/pods 138 | mountPropagation: "Bidirectional" 139 | - mountPath: /data 140 | name: volume-dir 141 | resources: 142 | limits: 143 | memory: 300Mi 144 | requests: 145 | cpu: 10m 146 | memory: 20Mi 147 | volumes: 148 | - name: socket-dir 149 | hostPath: 150 | path: /var/lib/kubelet/plugins/csi-lsplugin 151 | type: DirectoryOrCreate 152 | - name: pods-mount-dir 153 | hostPath: 154 | path: /var/lib/kubelet/pods 155 | type: Directory 156 | - hostPath: 157 | path: /var/lib/kubelet/plugins_registry 158 | type: Directory 159 | name: registration-dir 160 | - hostPath: 161 | path: /data 162 | type: DirectoryOrCreate 163 | name: volume-dir 164 | -------------------------------------------------------------------------------- /deploy/v1.0.1/ls-rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: csi-ls-node-sa 6 | namespace: kube-system 7 | --- 8 | 9 | kind: ClusterRole 10 | apiVersion: rbac.authorization.k8s.io/v1 11 | metadata: 12 | name: ls-external-provisioner-role 13 | rules: 14 | - apiGroups: [""] 15 | resources: ["persistentvolumes"] 16 | verbs: ["get", "list", "watch", "create", "delete"] 17 | - apiGroups: [""] 18 | resources: ["persistentvolumeclaims"] 19 | verbs: ["get", "list", "watch", "update"] 20 | - apiGroups: ["storage.k8s.io"] 21 | resources: ["volumeattachments"] 22 | verbs: ["get", "list", "watch", "create", "delete"] 23 | - apiGroups: ["storage.k8s.io"] 24 | resources: ["storageclasses"] 25 | verbs: ["get", "list", "watch"] 26 | - apiGroups: [""] 27 | resources: ["events"] 28 | verbs: ["get", "list", "watch", "create", "update", "patch"] 29 | - apiGroups: ["storage.k8s.io"] 30 | resources: ["csinodes"] 31 | verbs: ["get", "list", "watch"] 32 | - apiGroups: [""] 33 | resources: ["nodes"] 34 | verbs: ["get", "list", "watch"] 35 | - apiGroups: ["coordination.k8s.io"] 36 | resources: ["leases"] 37 | verbs: ["get", "list", "watch", "create", "update", "patch"] 38 | - apiGroups: [""] 39 | resources: ["secrets"] 40 | verbs: ["get"] 41 | - apiGroups: [""] 42 | resources: ["endpoints"] 43 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 44 | - apiGroups: ["storage.caoyingjunz.io"] 45 | resources: ["localstorages"] 46 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 47 | --- 48 | 49 | kind: ClusterRoleBinding 50 | apiVersion: rbac.authorization.k8s.io/v1 51 | metadata: 52 | name: ls-csi-provisioner-binding 53 | subjects: 54 | - kind: ServiceAccount 55 | name: csi-ls-node-sa 56 | namespace: kube-system 57 | roleRef: 58 | kind: ClusterRole 59 | name: ls-external-provisioner-role 60 | apiGroup: rbac.authorization.k8s.io 61 | -------------------------------------------------------------------------------- /deploy/v1.0.1/ls-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: pixiu-localstorage-service 5 | namespace: kube-system 6 | spec: 7 | ports: 8 | - name: tcp-8443 9 | port: 443 10 | protocol: TCP 11 | targetPort: 8443 12 | selector: 13 | app: pixiu-ls-controller 14 | type: ClusterIP 15 | -------------------------------------------------------------------------------- /deploy/v1.0.1/ls-webhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: pixiu-ls-mutating-configuration 6 | webhooks: 7 | - admissionReviewVersions: 8 | - v1 9 | clientConfig: 10 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR5akNDQXJLZ0F3SUJBZ0lVT3NCMUkxU2RvZExDZlhxcC9SaW9VbnBTQ2Fvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0tERW1NQ1FHQTFVRUF3d2RjR2w0YVhVdGJHOWpZV3h6ZEc5eVlXZGxMWE5sY25acFkyVWdRMEV3SUJjTgpNak13TmpBM01EQXhOakkxV2hnUE1qRXlNekExTVRRd01ERTJNalZhTURVeE16QXhCZ05WQkFNTUtuQnBlR2wxCkxXeHZZMkZzYzNSdmNtRm5aUzF6WlhKMmFXTmxMbXQxWW1VdGMzbHpkR1Z0TG5OMll6Q0NBU0l3RFFZSktvWkkKaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNbXVsVElkSGZndlgrUndJOFUwbE1ZbHYyeDFGeXhoeW4wUgpvODhpZ20zTmdMV2xwWE84TlVpczh3U09FYU1sRDgxa3JCcWZWR2lBc2w1SkhWT0NsZTJNU1E4YW5SSXV3d0R2ClFnWlgwcjl4N3dBaVU4LzROMkJCWFRwSnp5VnJBSHFERE14eUg5Kzh1cG5SN09SVFdEeXUrUXMvUjBsa1hvVjUKZ0tJUTN5aXFDdEJaRUVkbnlhYklZYXUwUW5ZL1YzWS9vaWJsQXRuU3hYUUR5TCthUTVZS015a1c4cE95OW1FQwo0d29IZUZlNjNaY3NRV01RQTVtanBZZ3hRMGVOdUFFZ2IzVmZGcXJrTVFFSytaaFFHWVAwWGlkS1hNZlBJellDCk1wdHExMDBQYWlXTWxkZk8xaWt6aUhDcFJERTVna0hoak53T01hRUhCNFJ0Y1N4LytSRUNBd0VBQWFPQjNEQ0IKMlRBSkJnTlZIUk1FQWpBQU1Bc0dBMVVkRHdRRUF3SUY0REIvQmdOVkhSRUVlREIyZ2hwd2FYaHBkUzFzYjJOaApiSE4wYjNKaFoyVXRjMlZ5ZG1salpZSW1jR2w0YVhVdGJHOWpZV3h6ZEc5eVlXZGxMWE5sY25acFkyVXVhM1ZpClpTMXplWE4wWlcyQ0tuQnBlR2wxTFd4dlkyRnNjM1J2Y21GblpTMXpaWEoyYVdObExtdDFZbVV0YzNsemRHVnQKTG5OMlk0Y0Vmd0FBQVRBZEJnTlZIUTRFRmdRVWVCc1FLK3IwUmRnOHBpVktTOU5RM21TRDE3VXdId1lEVlIwagpCQmd3Rm9BVVh3QjlmMjFyV21XVDY3MzgvL25VZ3BDM0lxQXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSGRWCkdhTnJRaDVkNGFUVE5uWUNxQ3ExS3VDdEFaVFJPSDFVUnVzd0VtREhtYi8xMHdDQ21PWUg3MDJqaUVaUW9RelAKdndVY2ZLUFhOWE5MdTlkaThBbXlEZnIzUkNtalAwRWpVMWR0STFYOTBFTENkYTdOSkJMamJ6QjFWem1HdEJuVApHMERuZ0twTzlraGViaFl3Ykt4dS9zM0JJVUtmTExDL3BBTkh5RnYxcU5aWlJJQUNSdW5nb2pBRzlpVEFjOExHCllmNWwyVFBxaUg5WHZmdDZReUNGZ0t5NnU2YmZobXR4REVxNFM3Qm12OEdYWWxLUnBpcVhXWCtZb1FEcFY5MGEKc1BMQU8rcXBRNlh3L1B5eU1Nd2JRSklKRVVjVjdPeXJmT3pta3RjNGRvSklIN2tVcnREYkxZc29MSkRpVGVZUApwU09uMnJDSHlOa1hiQUUvQW9VPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 11 | service: 12 | name: pixiu-localstorage-service 13 | namespace: kube-system 14 | path: /mutate-v1-localstorage 15 | port: 443 16 | failurePolicy: Fail 17 | matchPolicy: Equivalent 18 | name: webhook.pixiu.io 19 | namespaceSelector: {} 20 | objectSelector: {} 21 | reinvocationPolicy: Never 22 | rules: 23 | - apiGroups: 24 | - storage.caoyingjunz.io 25 | apiVersions: 26 | - v1 27 | operations: 28 | - CREATE 29 | - UPDATE 30 | resources: 31 | - localstorages 32 | scope: '*' 33 | sideEffects: None 34 | timeoutSeconds: 10 35 | 36 | --- 37 | apiVersion: admissionregistration.k8s.io/v1 38 | kind: ValidatingWebhookConfiguration 39 | metadata: 40 | name: pixiu-ls-validating-configuration 41 | webhooks: 42 | - admissionReviewVersions: 43 | - v1 44 | clientConfig: 45 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR5akNDQXJLZ0F3SUJBZ0lVT3NCMUkxU2RvZExDZlhxcC9SaW9VbnBTQ2Fvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0tERW1NQ1FHQTFVRUF3d2RjR2w0YVhVdGJHOWpZV3h6ZEc5eVlXZGxMWE5sY25acFkyVWdRMEV3SUJjTgpNak13TmpBM01EQXhOakkxV2hnUE1qRXlNekExTVRRd01ERTJNalZhTURVeE16QXhCZ05WQkFNTUtuQnBlR2wxCkxXeHZZMkZzYzNSdmNtRm5aUzF6WlhKMmFXTmxMbXQxWW1VdGMzbHpkR1Z0TG5OMll6Q0NBU0l3RFFZSktvWkkKaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNbXVsVElkSGZndlgrUndJOFUwbE1ZbHYyeDFGeXhoeW4wUgpvODhpZ20zTmdMV2xwWE84TlVpczh3U09FYU1sRDgxa3JCcWZWR2lBc2w1SkhWT0NsZTJNU1E4YW5SSXV3d0R2ClFnWlgwcjl4N3dBaVU4LzROMkJCWFRwSnp5VnJBSHFERE14eUg5Kzh1cG5SN09SVFdEeXUrUXMvUjBsa1hvVjUKZ0tJUTN5aXFDdEJaRUVkbnlhYklZYXUwUW5ZL1YzWS9vaWJsQXRuU3hYUUR5TCthUTVZS015a1c4cE95OW1FQwo0d29IZUZlNjNaY3NRV01RQTVtanBZZ3hRMGVOdUFFZ2IzVmZGcXJrTVFFSytaaFFHWVAwWGlkS1hNZlBJellDCk1wdHExMDBQYWlXTWxkZk8xaWt6aUhDcFJERTVna0hoak53T01hRUhCNFJ0Y1N4LytSRUNBd0VBQWFPQjNEQ0IKMlRBSkJnTlZIUk1FQWpBQU1Bc0dBMVVkRHdRRUF3SUY0REIvQmdOVkhSRUVlREIyZ2hwd2FYaHBkUzFzYjJOaApiSE4wYjNKaFoyVXRjMlZ5ZG1salpZSW1jR2w0YVhVdGJHOWpZV3h6ZEc5eVlXZGxMWE5sY25acFkyVXVhM1ZpClpTMXplWE4wWlcyQ0tuQnBlR2wxTFd4dlkyRnNjM1J2Y21GblpTMXpaWEoyYVdObExtdDFZbVV0YzNsemRHVnQKTG5OMlk0Y0Vmd0FBQVRBZEJnTlZIUTRFRmdRVWVCc1FLK3IwUmRnOHBpVktTOU5RM21TRDE3VXdId1lEVlIwagpCQmd3Rm9BVVh3QjlmMjFyV21XVDY3MzgvL25VZ3BDM0lxQXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSGRWCkdhTnJRaDVkNGFUVE5uWUNxQ3ExS3VDdEFaVFJPSDFVUnVzd0VtREhtYi8xMHdDQ21PWUg3MDJqaUVaUW9RelAKdndVY2ZLUFhOWE5MdTlkaThBbXlEZnIzUkNtalAwRWpVMWR0STFYOTBFTENkYTdOSkJMamJ6QjFWem1HdEJuVApHMERuZ0twTzlraGViaFl3Ykt4dS9zM0JJVUtmTExDL3BBTkh5RnYxcU5aWlJJQUNSdW5nb2pBRzlpVEFjOExHCllmNWwyVFBxaUg5WHZmdDZReUNGZ0t5NnU2YmZobXR4REVxNFM3Qm12OEdYWWxLUnBpcVhXWCtZb1FEcFY5MGEKc1BMQU8rcXBRNlh3L1B5eU1Nd2JRSklKRVVjVjdPeXJmT3pta3RjNGRvSklIN2tVcnREYkxZc29MSkRpVGVZUApwU09uMnJDSHlOa1hiQUUvQW9VPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 46 | service: 47 | name: pixiu-localstorage-service 48 | namespace: kube-system 49 | path: /validate-v1-localstorage 50 | port: 443 51 | failurePolicy: Fail 52 | matchPolicy: Equivalent 53 | name: webhook.pixiu.io 54 | namespaceSelector: {} 55 | objectSelector: {} 56 | rules: 57 | - apiGroups: 58 | - storage.caoyingjunz.io 59 | apiVersions: 60 | - v1 61 | operations: 62 | - CREATE 63 | - UPDATE 64 | resources: 65 | - localstorages 66 | scope: '*' 67 | sideEffects: None 68 | timeoutSeconds: 10 69 | -------------------------------------------------------------------------------- /deploy/v1.0.1/storage.caoyingjunz.io_localstorages.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.8.0 7 | creationTimestamp: null 8 | name: localstorages.storage.caoyingjunz.io 9 | spec: 10 | group: storage.caoyingjunz.io 11 | names: 12 | kind: LocalStorage 13 | listKind: LocalStorageList 14 | plural: localstorages 15 | shortNames: 16 | - pls 17 | - ls 18 | singular: localstorage 19 | scope: Cluster 20 | versions: 21 | - additionalPrinterColumns: 22 | - jsonPath: .status.phase 23 | name: Status 24 | type: string 25 | - jsonPath: .spec.node 26 | name: kubeNode 27 | type: string 28 | - jsonPath: .status.allocatable 29 | name: Allocatable 30 | type: string 31 | - jsonPath: .status.capacity 32 | name: Capacity 33 | type: string 34 | - jsonPath: .metadata.creationTimestamp 35 | name: AGE 36 | type: date 37 | - jsonPath: .spec.volumeGroup 38 | name: VolumeGroup 39 | priority: 1 40 | type: string 41 | name: v1 42 | schema: 43 | openAPIV3Schema: 44 | properties: 45 | apiVersion: 46 | description: 'APIVersion defines the versioned schema of this representation 47 | of an object. Servers should convert recognized schemas to the latest 48 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 49 | type: string 50 | kind: 51 | description: 'Kind is a string value representing the REST resource this 52 | object represents. Servers may infer this from the endpoint the client 53 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 54 | type: string 55 | metadata: 56 | type: object 57 | spec: 58 | properties: 59 | disks: 60 | items: 61 | properties: 62 | identifier: 63 | description: disk identifier, plugin will fill it 64 | type: string 65 | name: 66 | type: string 67 | type: object 68 | type: array 69 | node: 70 | description: Node kubernetes node name 71 | minLength: 1 72 | type: string 73 | volumeGroup: 74 | type: string 75 | type: object 76 | status: 77 | properties: 78 | allocatable: 79 | anyOf: 80 | - type: integer 81 | - type: string 82 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 83 | x-kubernetes-int-or-string: true 84 | capacity: 85 | anyOf: 86 | - type: integer 87 | - type: string 88 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 89 | x-kubernetes-int-or-string: true 90 | conditions: 91 | type: string 92 | phase: 93 | type: string 94 | volumes: 95 | description: List of mount volumes on this node 96 | items: 97 | properties: 98 | attached: 99 | type: boolean 100 | nodeId: 101 | type: string 102 | volId: 103 | type: string 104 | volName: 105 | type: string 106 | volPath: 107 | type: string 108 | volSize: 109 | format: int64 110 | type: integer 111 | type: object 112 | type: array 113 | type: object 114 | type: object 115 | served: true 116 | storage: true 117 | subresources: {} 118 | status: 119 | acceptedNames: 120 | kind: "" 121 | plural: "" 122 | conditions: [] 123 | storedVersions: [] 124 | -------------------------------------------------------------------------------- /deploy/v1.0.2/ls-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: pixiu-ls-controller 11 | template: 12 | metadata: 13 | labels: 14 | app: pixiu-ls-controller 15 | spec: 16 | serviceAccountName: csi-ls-node-sa 17 | containers: 18 | - args: 19 | - -v=2 20 | # port's value equals 0 means health check func disabled 21 | - --healthz-port=10258 22 | - --cert-dir=/tmp/cert 23 | - --port=8443 24 | image: harbor.cloud.pixiuio.com/pixiuio/localstorage-controller:v1.0.2 25 | imagePullPolicy: IfNotPresent 26 | name: ls-controller 27 | volumeMounts: 28 | - mountPath: /tmp/cert 29 | name: cert 30 | readOnly: true 31 | livenessProbe: 32 | httpGet: 33 | path: /healthz 34 | port: 10258 35 | failureThreshold: 5 36 | initialDelaySeconds: 30 37 | timeoutSeconds: 5 38 | periodSeconds: 5 39 | dnsPolicy: Default 40 | nodeSelector: 41 | kubernetes.io/os: linux 42 | restartPolicy: Always 43 | volumes: 44 | - name: cert 45 | secret: 46 | defaultMode: 420 47 | secretName: pixiu-localstorage-cert 48 | -------------------------------------------------------------------------------- /deploy/v1.0.2/ls-driverinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: storage.k8s.io/v1 3 | kind: CSIDriver 4 | metadata: 5 | name: localstorage.caoyingjunz.io 6 | spec: 7 | attachRequired: false 8 | volumeLifecycleModes: 9 | - Persistent 10 | fsGroupPolicy: File 11 | -------------------------------------------------------------------------------- /deploy/v1.0.2/ls-node.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: DaemonSet 3 | apiVersion: apps/v1 4 | metadata: 5 | name: pixiu-ls-node 6 | namespace: kube-system 7 | spec: 8 | updateStrategy: 9 | rollingUpdate: 10 | maxUnavailable: 1 11 | type: RollingUpdate 12 | selector: 13 | matchLabels: 14 | app: pixiu-ls-node 15 | template: 16 | metadata: 17 | labels: 18 | app: pixiu-ls-node 19 | spec: 20 | # hostNetwork: true 21 | dnsPolicy: Default # available values: Default, ClusterFirstWithHostNet, ClusterFirst 22 | serviceAccountName: csi-ls-node-sa 23 | affinity: 24 | nodeAffinity: 25 | requiredDuringSchedulingIgnoredDuringExecution: 26 | nodeSelectorTerms: 27 | - matchExpressions: 28 | - key: storage.caoyingjunz.io/node 29 | operator: Exists 30 | tolerations: 31 | - operator: "Exists" 32 | containers: 33 | - name: liveness-probe 34 | image: pixiuio/livenessprobe:v2.8.0 35 | args: 36 | - --csi-address=/csi/csi.sock 37 | - --probe-timeout=3s 38 | - --health-port=29653 39 | - --v=2 40 | volumeMounts: 41 | - name: socket-dir 42 | mountPath: /csi 43 | resources: 44 | limits: 45 | memory: 100Mi 46 | requests: 47 | cpu: 10m 48 | memory: 20Mi 49 | 50 | - name: node-driver-registrar 51 | image: pixiuio/csi-node-driver-registrar:v2.6.2 52 | args: 53 | - --v=2 54 | - --csi-address=/csi/csi.sock 55 | - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 56 | livenessProbe: 57 | exec: 58 | command: 59 | - /csi-node-driver-registrar 60 | - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) 61 | - --mode=kubelet-registration-probe 62 | initialDelaySeconds: 30 63 | timeoutSeconds: 15 64 | env: 65 | - name: DRIVER_REG_SOCK_PATH 66 | value: /var/lib/kubelet/plugins/csi-lsplugin/csi.sock 67 | - name: KUBE_NODE_NAME 68 | valueFrom: 69 | fieldRef: 70 | fieldPath: spec.nodeName 71 | volumeMounts: 72 | - name: socket-dir 73 | mountPath: /csi 74 | - name: registration-dir 75 | mountPath: /registration 76 | resources: 77 | limits: 78 | memory: 100Mi 79 | requests: 80 | cpu: 10m 81 | memory: 20Mi 82 | 83 | - name: csi-provisioner 84 | image: jacky06/csi-provisioner:v0.1 85 | args: 86 | - -v=5 87 | - --csi-address=/csi/csi.sock 88 | env: 89 | - name: NODE_NAME 90 | valueFrom: 91 | fieldRef: 92 | fieldPath: spec.nodeName 93 | securityContext: 94 | # This is necessary only for systems with SELinux, where 95 | # non-privileged sidecar containers cannot access unix domain socket 96 | # created by privileged CSI driver container. 97 | privileged: true 98 | volumeMounts: 99 | - mountPath: /csi 100 | name: socket-dir 101 | 102 | - name: ls-plugin 103 | securityContext: 104 | privileged: true 105 | capabilities: 106 | add: ["SYS_ADMIN"] 107 | allowPrivilegeEscalation: true 108 | image: harbor.cloud.pixiuio.com/pixiuio/localstorageplugin:v1.0.2 109 | args: 110 | - "-v=5" 111 | - "--endpoint=$(CSI_ENDPOINT)" 112 | - "--volume-dir=/data" 113 | env: 114 | - name: NODE_NAME 115 | valueFrom: 116 | fieldRef: 117 | fieldPath: spec.nodeName 118 | - name: CSI_ENDPOINT 119 | value: unix:///csi/csi.sock 120 | ports: 121 | - containerPort: 29653 122 | name: healthz 123 | protocol: TCP 124 | livenessProbe: 125 | failureThreshold: 5 126 | httpGet: 127 | path: /healthz 128 | port: healthz 129 | initialDelaySeconds: 30 130 | timeoutSeconds: 10 131 | periodSeconds: 30 132 | imagePullPolicy: "IfNotPresent" 133 | volumeMounts: 134 | - name: socket-dir 135 | mountPath: /csi 136 | - name: pods-mount-dir 137 | mountPath: /var/lib/kubelet/pods 138 | mountPropagation: "Bidirectional" 139 | - mountPath: /data 140 | name: volume-dir 141 | resources: 142 | limits: 143 | memory: 300Mi 144 | requests: 145 | cpu: 10m 146 | memory: 20Mi 147 | volumes: 148 | - name: socket-dir 149 | hostPath: 150 | path: /var/lib/kubelet/plugins/csi-lsplugin 151 | type: DirectoryOrCreate 152 | - name: pods-mount-dir 153 | hostPath: 154 | path: /var/lib/kubelet/pods 155 | type: Directory 156 | - hostPath: 157 | path: /var/lib/kubelet/plugins_registry 158 | type: Directory 159 | name: registration-dir 160 | - hostPath: 161 | path: /data 162 | type: DirectoryOrCreate 163 | name: volume-dir 164 | -------------------------------------------------------------------------------- /deploy/v1.0.2/ls-rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: csi-ls-node-sa 6 | namespace: kube-system 7 | --- 8 | 9 | apiVersion: v1 10 | kind: Secret 11 | metadata: 12 | name: pixiu-ls-token 13 | namespace: kube-system 14 | annotations: 15 | kubernetes.io/service-account.name: "csi-ls-node-sa" 16 | type: kubernetes.io/service-account-token 17 | --- 18 | 19 | kind: ClusterRole 20 | apiVersion: rbac.authorization.k8s.io/v1 21 | metadata: 22 | name: ls-external-provisioner-role 23 | rules: 24 | - apiGroups: [""] 25 | resources: ["persistentvolumes"] 26 | verbs: ["get", "list", "watch", "create", "delete"] 27 | - apiGroups: [""] 28 | resources: ["persistentvolumeclaims"] 29 | verbs: ["get", "list", "watch", "update"] 30 | - apiGroups: ["storage.k8s.io"] 31 | resources: ["volumeattachments"] 32 | verbs: ["get", "list", "watch", "create", "delete"] 33 | - apiGroups: ["storage.k8s.io"] 34 | resources: ["storageclasses"] 35 | verbs: ["get", "list", "watch"] 36 | - apiGroups: [""] 37 | resources: ["events"] 38 | verbs: ["get", "list", "watch", "create", "update", "patch"] 39 | - apiGroups: ["storage.k8s.io"] 40 | resources: ["csinodes"] 41 | verbs: ["get", "list", "watch"] 42 | - apiGroups: [""] 43 | resources: ["nodes"] 44 | verbs: ["get", "list", "watch"] 45 | - apiGroups: ["coordination.k8s.io"] 46 | resources: ["leases"] 47 | verbs: ["get", "list", "watch", "create", "update", "patch"] 48 | - apiGroups: [""] 49 | resources: ["secrets"] 50 | verbs: ["get"] 51 | - apiGroups: [""] 52 | resources: ["endpoints"] 53 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 54 | - apiGroups: ["storage.caoyingjunz.io"] 55 | resources: ["localstorages"] 56 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 57 | --- 58 | 59 | kind: ClusterRoleBinding 60 | apiVersion: rbac.authorization.k8s.io/v1 61 | metadata: 62 | name: ls-csi-provisioner-binding 63 | subjects: 64 | - kind: ServiceAccount 65 | name: csi-ls-node-sa 66 | namespace: kube-system 67 | roleRef: 68 | kind: ClusterRole 69 | name: ls-external-provisioner-role 70 | apiGroup: rbac.authorization.k8s.io 71 | -------------------------------------------------------------------------------- /deploy/v1.0.2/ls-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | ports: 8 | - name: tcp-8443 9 | port: 443 10 | protocol: TCP 11 | targetPort: 8443 12 | selector: 13 | app: pixiu-ls-controller 14 | type: ClusterIP 15 | --- 16 | apiVersion: v1 17 | kind: Service 18 | metadata: 19 | name: pixiu-ls-scheduler 20 | namespace: kube-system 21 | spec: 22 | ports: 23 | - name: tcp-8090 24 | nodePort: 30666 25 | port: 8090 26 | protocol: TCP 27 | targetPort: 8090 28 | selector: 29 | app: pixiu-ls-scheduler 30 | type: NodePort 31 | -------------------------------------------------------------------------------- /deploy/v1.0.2/ls-webhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: pixiu-ls-mutating-configuration 6 | webhooks: 7 | - admissionReviewVersions: 8 | - v1 9 | clientConfig: 10 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 11 | service: 12 | name: pixiu-ls-controller 13 | namespace: kube-system 14 | path: /mutate-v1-localstorage 15 | port: 443 16 | failurePolicy: Fail 17 | matchPolicy: Equivalent 18 | name: webhook.pixiu.io 19 | namespaceSelector: {} 20 | objectSelector: {} 21 | reinvocationPolicy: Never 22 | rules: 23 | - apiGroups: 24 | - storage.caoyingjunz.io 25 | apiVersions: 26 | - v1 27 | operations: 28 | - CREATE 29 | - UPDATE 30 | resources: 31 | - localstorages 32 | scope: '*' 33 | sideEffects: None 34 | timeoutSeconds: 10 35 | 36 | --- 37 | apiVersion: admissionregistration.k8s.io/v1 38 | kind: ValidatingWebhookConfiguration 39 | metadata: 40 | name: pixiu-ls-validating-configuration 41 | webhooks: 42 | - admissionReviewVersions: 43 | - v1 44 | clientConfig: 45 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 46 | service: 47 | name: pixiu-ls-controller 48 | namespace: kube-system 49 | path: /validate-v1-localstorage 50 | port: 443 51 | failurePolicy: Fail 52 | matchPolicy: Equivalent 53 | name: webhook.pixiu.io 54 | namespaceSelector: {} 55 | objectSelector: {} 56 | rules: 57 | - apiGroups: 58 | - storage.caoyingjunz.io 59 | apiVersions: 60 | - v1 61 | operations: 62 | - CREATE 63 | - UPDATE 64 | resources: 65 | - localstorages 66 | scope: '*' 67 | sideEffects: None 68 | timeoutSeconds: 10 69 | -------------------------------------------------------------------------------- /deploy/v1.0.3/ls-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: pixiu-ls-controller 11 | template: 12 | metadata: 13 | labels: 14 | app: pixiu-ls-controller 15 | spec: 16 | serviceAccountName: csi-ls-node-sa 17 | containers: 18 | - args: 19 | - -v=2 20 | # port's value equals 0 means health check func disabled 21 | - --healthz-port=10258 22 | - --cert-dir=/tmp/cert 23 | - --port=8443 24 | image: pixiuio/localstorage-controller:v1.0.3 25 | imagePullPolicy: Always 26 | name: ls-controller 27 | volumeMounts: 28 | - mountPath: /tmp/cert 29 | name: cert 30 | readOnly: true 31 | livenessProbe: 32 | httpGet: 33 | path: /healthz 34 | port: 10258 35 | failureThreshold: 5 36 | initialDelaySeconds: 30 37 | timeoutSeconds: 5 38 | periodSeconds: 5 39 | dnsPolicy: Default 40 | nodeSelector: 41 | kubernetes.io/os: linux 42 | restartPolicy: Always 43 | volumes: 44 | - name: cert 45 | secret: 46 | defaultMode: 420 47 | secretName: pixiu-localstorage-cert 48 | -------------------------------------------------------------------------------- /deploy/v1.0.3/ls-driverinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: storage.k8s.io/v1 3 | kind: CSIDriver 4 | metadata: 5 | name: localstorage.caoyingjunz.io 6 | spec: 7 | attachRequired: false 8 | volumeLifecycleModes: 9 | - Persistent 10 | fsGroupPolicy: File 11 | -------------------------------------------------------------------------------- /deploy/v1.0.3/ls-rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: csi-ls-node-sa 6 | namespace: kube-system 7 | --- 8 | 9 | apiVersion: v1 10 | kind: Secret 11 | metadata: 12 | name: pixiu-ls-token 13 | namespace: kube-system 14 | annotations: 15 | kubernetes.io/service-account.name: "csi-ls-node-sa" 16 | type: kubernetes.io/service-account-token 17 | --- 18 | 19 | kind: ClusterRole 20 | apiVersion: rbac.authorization.k8s.io/v1 21 | metadata: 22 | name: ls-external-provisioner-role 23 | rules: 24 | - apiGroups: [""] 25 | resources: ["persistentvolumes"] 26 | verbs: ["get", "list", "watch", "create", "delete"] 27 | - apiGroups: [""] 28 | resources: ["persistentvolumeclaims"] 29 | verbs: ["get", "list", "watch", "update"] 30 | - apiGroups: ["storage.k8s.io"] 31 | resources: ["volumeattachments"] 32 | verbs: ["get", "list", "watch", "create", "delete"] 33 | - apiGroups: ["storage.k8s.io"] 34 | resources: ["storageclasses"] 35 | verbs: ["get", "list", "watch"] 36 | - apiGroups: [""] 37 | resources: ["events"] 38 | verbs: ["get", "list", "watch", "create", "update", "patch"] 39 | - apiGroups: ["storage.k8s.io"] 40 | resources: ["csinodes"] 41 | verbs: ["get", "list", "watch"] 42 | - apiGroups: [""] 43 | resources: ["nodes"] 44 | verbs: ["get", "list", "watch"] 45 | - apiGroups: ["coordination.k8s.io"] 46 | resources: ["leases"] 47 | verbs: ["get", "list", "watch", "create", "update", "patch"] 48 | - apiGroups: [""] 49 | resources: ["secrets"] 50 | verbs: ["get"] 51 | - apiGroups: [""] 52 | resources: ["endpoints"] 53 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 54 | - apiGroups: ["storage.caoyingjunz.io"] 55 | resources: ["localstorages"] 56 | verbs: [ "get", "list", "watch", "create", "update", "patch" ] 57 | --- 58 | 59 | kind: ClusterRoleBinding 60 | apiVersion: rbac.authorization.k8s.io/v1 61 | metadata: 62 | name: ls-csi-provisioner-binding 63 | subjects: 64 | - kind: ServiceAccount 65 | name: csi-ls-node-sa 66 | namespace: kube-system 67 | roleRef: 68 | kind: ClusterRole 69 | name: ls-external-provisioner-role 70 | apiGroup: rbac.authorization.k8s.io 71 | -------------------------------------------------------------------------------- /deploy/v1.0.3/ls-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: pixiu-ls-controller 5 | namespace: kube-system 6 | spec: 7 | ports: 8 | - name: tcp-8443 9 | port: 443 10 | protocol: TCP 11 | targetPort: 8443 12 | selector: 13 | app: pixiu-ls-controller 14 | type: ClusterIP 15 | --- 16 | apiVersion: v1 17 | kind: Service 18 | metadata: 19 | name: pixiu-ls-scheduler 20 | namespace: kube-system 21 | spec: 22 | ports: 23 | - name: tcp-8090 24 | nodePort: 30666 25 | port: 8090 26 | protocol: TCP 27 | targetPort: 8090 28 | selector: 29 | app: pixiu-ls-scheduler 30 | type: NodePort 31 | -------------------------------------------------------------------------------- /deploy/v1.0.3/ls-webhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: pixiu-ls-mutating-configuration 6 | webhooks: 7 | - admissionReviewVersions: 8 | - v1 9 | clientConfig: 10 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 11 | service: 12 | name: pixiu-ls-controller 13 | namespace: kube-system 14 | path: /mutate-v1-localstorage 15 | port: 443 16 | failurePolicy: Fail 17 | matchPolicy: Equivalent 18 | name: webhook.pixiu.io 19 | namespaceSelector: {} 20 | objectSelector: {} 21 | reinvocationPolicy: Never 22 | rules: 23 | - apiGroups: 24 | - storage.caoyingjunz.io 25 | apiVersions: 26 | - v1 27 | operations: 28 | - CREATE 29 | - UPDATE 30 | resources: 31 | - localstorages 32 | scope: '*' 33 | sideEffects: None 34 | timeoutSeconds: 10 35 | 36 | --- 37 | apiVersion: admissionregistration.k8s.io/v1 38 | kind: ValidatingWebhookConfiguration 39 | metadata: 40 | name: pixiu-ls-validating-configuration 41 | webhooks: 42 | - admissionReviewVersions: 43 | - v1 44 | clientConfig: 45 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwekNDQW8rZ0F3SUJBZ0lVRURBYzkwa1dVUXN5UmJodThlUitzOFlHR3Y4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0lURWZNQjBHQTFVRUF3d1djR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjaUJEUVRBZ0Z3MHlNekEzTVRNeApNekl5TWpaYUdBOHlNVEl6TURZeE9URXpNakl5Tmxvd0xqRXNNQ29HQTFVRUF3d2pjR2w0YVhVdGJITXRZMjl1CmRISnZiR3hsY2k1cmRXSmxMWE41YzNSbGJTNXpkbU13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcKZ2dFS0FvSUJBUUN5d1dZcHFGekFlaS9oL2pBMjFFOWJIZ1NhcjJBTnJNQlcrRk5vOUJCMG9FLytXZkpRejRlaQowVnNuWGpVdTNHTm5ZR1BVMU81ZTdibmtEYjRhOGRremUyZzc1aEFWZ25ldXJFSERuemVVdkpHdnBOZ3dMSFNHClprbERSQkJoTDJJTEVVZkl5bWNnV21mZGtFL2d2M1dTcFowdWdZSnYrR1F1ZmFiNW5lT3ZZYWpyS3pOZFIzb1MKZ0pyUDNzMkNUdU1lcnNIdGtsVWxhZlZNK3ltNlhWSjZXV25veEE3akhUYjJ5OGNkSFdYTmZYVjFuUlhONENkeApXRWFubk9SS0lIc3l4cXdzUXRGYUx6R0hzekhiVTA5VzJYeTNIZ1gxVDFsQzBCSFNlYUdjNHV6cEpQK3VSRzMwCk1GSXNTclhSY2RRckNSakszM0VJWW1TVWVRdkd0Um03QWdNQkFBR2pnY2N3Z2NRd0NRWURWUjBUQkFJd0FEQUwKQmdOVkhROEVCQU1DQmVBd2FnWURWUjBSQkdNd1lZSVRjR2w0YVhVdGJITXRZMjl1ZEhKdmJHeGxjb0lmY0dsNAphWFV0YkhNdFkyOXVkSEp2Ykd4bGNpNXJkV0psTFhONWMzUmxiWUlqY0dsNGFYVXRiSE10WTI5dWRISnZiR3hsCmNpNXJkV0psTFhONWMzUmxiUzV6ZG1PSEJIOEFBQUV3SFFZRFZSME9CQllFRkwwdFZSOGNiTnBTWnF6K3E5ZjAKdWlERXV3eEhNQjhHQTFVZEl3UVlNQmFBRlB4T1FkcmRuOXJjSkVVa3VLRVprWVFBRElXaE1BMEdDU3FHU0liMwpEUUVCQ3dVQUE0SUJBUUFpeG03cEZvOHU2S2FnL0NoMndjaGtTRHVUZXNqRlNDQVpsc01JTkk3dFptTnFadVliCmVJeEZUSEorKzkrVmlNRXJCQ0xhanU4VVorUExlN2p4Mm01UGYvbEY0NDZRdi9EUkhuYlVlS1d6NkRXamhBTngKMFJjalpRVXNMZE9BaUxtYmZvOTBjZnorcjc3KzduZzN6NitPSlpPSCtYWnVOUFM1Z2lUQTdYMmpLSUFQazJCcwpNcGFscVpETElFczFWM3BTaFdCTFZYa1FZeEFBUGJRaG1VTHJUMDNXdmRUOTZEeURiM0gvcHFhb0ZsK0RPMCt3CktwdFZQNW5vVVg1eVRWSG5pMnRldkttbHZwb0Z4RUVDMmFnd3RNeGpaK0EzUGV6YzAzVnhyZllzb0cyNU4xN3IKaGp4STJBQStCZ2g0dm1GRzkvM2E0VE1nbHVWOGlDa0dqQUp2Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 46 | service: 47 | name: pixiu-ls-controller 48 | namespace: kube-system 49 | path: /validate-v1-localstorage 50 | port: 443 51 | failurePolicy: Fail 52 | matchPolicy: Equivalent 53 | name: webhook.pixiu.io 54 | namespaceSelector: {} 55 | objectSelector: {} 56 | rules: 57 | - apiGroups: 58 | - storage.caoyingjunz.io 59 | apiVersions: 60 | - v1 61 | operations: 62 | - CREATE 63 | - UPDATE 64 | resources: 65 | - localstorages 66 | scope: '*' 67 | sideEffects: None 68 | timeoutSeconds: 10 69 | -------------------------------------------------------------------------------- /docs/scheduler-extender.md: -------------------------------------------------------------------------------- 1 | # 安装 LocalStorage Scheduler 扩展 2 | 3 | ### LocalStorage-scheduler 4 | - 生成 `ls-scheduler.conf`, 并拷贝到 `/etc/kubernetes` 目录 5 | ```shell 6 | # 生成 pixiu-ls-scheduler.conf 7 | 8 | # 修改 hack/build-lsconfig.sh 的 API_SERVER 为实际地址,然后执行 9 | ./hack/build-lsconfig.sh 10 | ``` 11 | 12 | - 拷贝 `deploy/ls-scheduler.yaml` 到 `/etc/kubernetes/manifests` 目录 13 | 14 | - 验证 15 | ```shell 16 | # kubectl get pod -n kube-system pixiu-ls-scheduler-pixiu01 17 | NAME READY STATUS RESTARTS AGE 18 | pixiu-ls-scheduler-pixiu01 1/1 Running 15 (81s ago) 2d1h 19 | 20 | root@pixiu01:~# kubectl get svc -n kube-system pixiu-ls-scheduler 21 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 22 | pixiu-ls-scheduler NodePort 10.254.245.253 8090:30666/TCP 2d1h 23 | 24 | # 服务已启动(建议使用 LB) 25 | curl 10.254.245.253:8090/version 26 | v1.0.1 27 | ``` 28 | 29 | ### Kube-scheduler 30 | - 修改 `deploy/ls-scheduler-config.yaml` 的 `urlPrefix` 为实际 `pixiu-ls-scheduler` 地址, 并拷贝到 `/etc/kubernetes` 目录 31 | 32 | - 修改 `kube-scheduler` 默认调度配置文件,添加 `pixiu-scheduler-extender` 关联配置 33 | ```yaml 34 | - command: 35 | - kube-scheduler 36 | ... 37 | - --config=/etc/kubernetes/ls-scheduler-config.yaml 38 | ... 39 | volumeMounts: 40 | - mountPath: /etc/kubernetes/scheduler.conf 41 | name: kubeconfig 42 | readOnly: true 43 | - mountPath: /etc/kubernetes/ls-scheduler-config.yaml 44 | name: ls-scheduler-config 45 | readOnly: true 46 | ... 47 | volumes: 48 | - hostPath: 49 | path: /etc/kubernetes/scheduler.conf 50 | type: FileOrCreate 51 | name: kubeconfig 52 | - hostPath: 53 | path: /etc/kubernetes/ls-scheduler-config.yaml 54 | type: FileOrCreate 55 | name: ls-scheduler-config 56 | ``` 57 | -------------------------------------------------------------------------------- /examples/ls.yaml: -------------------------------------------------------------------------------- 1 | kind: LocalStorage 2 | apiVersion: storage.caoyingjunz.io/v1 3 | metadata: 4 | annotations: 5 | # 自定义可分配的存储容量, 在 path 模式下生效 6 | volume.caoyingjunz.io/node-size: 360Gi 7 | name: ls-pixiu-node 8 | spec: 9 | node: pixiu-node 10 | # 指定 path 模式时的 volume 文件夹 11 | path: 12 | volumeDir: /data 13 | # 指定 vlm 模式时的磁盘配置 14 | lvm: 15 | volumeGroup: pixiu 16 | disks: 17 | - name: pixiu-disk 18 | -------------------------------------------------------------------------------- /examples/pvc.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: test-pvc 5 | annotations: 6 | volume.beta.kubernetes.io/storage-class: "pixiu-localstorage" 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | resources: 11 | requests: 12 | storage: 1Mi 13 | --- 14 | kind: Pod 15 | apiVersion: v1 16 | metadata: 17 | name: test-pod 18 | spec: 19 | containers: 20 | - name: test-pod 21 | image: busybox:1.24 22 | command: 23 | - "/bin/sh" 24 | args: 25 | - "-c" 26 | - "touch /mnt/SUCCESS && exit 0 || exit 1" 27 | volumeMounts: 28 | - name: ls-pvc 29 | mountPath: "/mnt" 30 | restartPolicy: "Never" 31 | volumes: 32 | - name: ls-pvc 33 | persistentVolumeClaim: 34 | claimName: test-pvc 35 | -------------------------------------------------------------------------------- /examples/sts.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: StatefulSet 4 | metadata: 5 | name: test-sts 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: test-sts 10 | serviceName: test-sts 11 | replicas: 1 12 | template: 13 | metadata: 14 | labels: 15 | app: test-sts 16 | spec: 17 | terminationGracePeriodSeconds: 10 18 | containers: 19 | - name: test-sts 20 | imagePullPolicy: IfNotPresent 21 | image: nginx 22 | ports: 23 | - containerPort: 80 24 | name: web 25 | volumeMounts: 26 | - name: pixiu 27 | mountPath: /usr/share/nginx/html 28 | volumeClaimTemplates: 29 | - metadata: 30 | name: pixiu 31 | spec: 32 | accessModes: [ "ReadWriteOnce" ] 33 | storageClassName: "pixiu-localstorage" 34 | resources: 35 | requests: 36 | storage: 1Gi 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/caoyingjunz/csi-driver-localstorage 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/container-storage-interface/spec v1.6.0 7 | github.com/golang/protobuf v1.5.3 8 | github.com/google/uuid v1.3.0 9 | github.com/imdario/mergo v0.3.15 // indirect 10 | github.com/julienschmidt/httprouter v1.3.0 11 | github.com/stretchr/testify v1.8.3 // indirect 12 | golang.org/x/net v0.10.0 13 | google.golang.org/grpc v1.54.0 14 | google.golang.org/protobuf v1.30.0 // indirect 15 | k8s.io/api v0.24.8 16 | k8s.io/apimachinery v0.24.8 17 | k8s.io/apiserver v0.24.8 18 | k8s.io/client-go v0.24.8 19 | k8s.io/code-generator v0.24.9 20 | k8s.io/klog/v2 v2.90.1 21 | k8s.io/kube-scheduler v0.24.8 22 | sigs.k8s.io/controller-runtime v0.12.3 23 | ) 24 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /hack/build-lsconfig.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Caoyingjunz Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # TODO: 通过变量指定 22 | API_SERVER="https://192.168.16.200:6443" 23 | 24 | NAMESPACE="kube-system" 25 | SECRET="pixiu-ls-token" 26 | KUBECONFIG="pixiu-ls-scheduler.conf" 27 | 28 | kubectl get secret $SECRET -n $NAMESPACE -o jsonpath='{.data.ca\.crt}' | base64 --decode > ca.crt 29 | TOKEN=$(kubectl get secret $SECRET -n $NAMESPACE -o jsonpath='{.data.token}' | base64 --decode) 30 | 31 | kubectl config set-cluster ls-cluster --server=$API_SERVER --certificate-authority=ca.crt --embed-certs=true --kubeconfig=$KUBECONFIG 32 | kubectl config set-credentials csi-ls-node-sa --token=$TOKEN --kubeconfig=$KUBECONFIG 33 | kubectl config set-context ls-context --cluster=ls-cluster --user=csi-ls-node-sa --namespace=$NAMESPACE --kubeconfig=$KUBECONFIG 34 | kubectl config use-context ls-context --kubeconfig=$KUBECONFIG 35 | 36 | echo "completed build" $KUBECONFIG 37 | -------------------------------------------------------------------------------- /hack/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | /* 5 | Copyright 2019 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // This package imports things required by build scripts, to force `go mod` to see them as dependencies 21 | package tools 22 | 23 | import _ "k8s.io/code-generator" 24 | -------------------------------------------------------------------------------- /hack/update-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | CONTROLLER_TOOLS_VERSION=v0.8.0 22 | 23 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 24 | CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null)} 25 | GO_BIN=$(pwd)/vendor/bin 26 | 27 | test -s "${GO_BIN}"/controller-gen && "${GO_BIN}"/controller-gen --version | grep -q ${CONTROLLER_TOOLS_VERSION} || \ 28 | GOBIN=${GO_BIN} go install sigs.k8s.io/controller-tools/cmd/controller-gen@${CONTROLLER_TOOLS_VERSION} 29 | 30 | # generate the code with: 31 | # --output-base because this script should also be able to run inside the vendor dir of 32 | 33 | bash "${CODEGEN_PKG}"/generate-groups.sh "deepcopy,client,informer,lister" \ 34 | github.com/caoyingjunz/csi-driver-localstorage/pkg/client github.com/caoyingjunz/csi-driver-localstorage/pkg/apis localstorage:v1 \ 35 | --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt \ 36 | --output-base ./ 37 | 38 | # 拷贝文件 39 | cp -r "${SCRIPT_ROOT}"/github.com/caoyingjunz/csi-driver-localstorage/pkg/client "${SCRIPT_ROOT}"/pkg 40 | cp -r "${SCRIPT_ROOT}"/github.com/caoyingjunz/csi-driver-localstorage/pkg/apis "${SCRIPT_ROOT}"/pkg 41 | 42 | # 生成 CRDs 43 | echo "Generating localstorage CRDs" 44 | "${GO_BIN}"/controller-gen crd paths=./pkg/apis/... output:crd:dir=./deploy/crds output:stdout 45 | -------------------------------------------------------------------------------- /hack/update-gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2021 The Pixiu Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o nounset 18 | set -o errexit 19 | set -o pipefail 20 | 21 | find . -name "*.go" | grep -v vendor | xargs gofmt -s -w 22 | -------------------------------------------------------------------------------- /hack/verify-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | 23 | DIFFROOT="${SCRIPT_ROOT}/examples" 24 | TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/examples" 25 | _tmp="${SCRIPT_ROOT}/_tmp" 26 | 27 | cleanup() { 28 | rm -rf "${_tmp}" 29 | } 30 | trap "cleanup" EXIT SIGINT 31 | 32 | cleanup 33 | 34 | mkdir -p "${TMP_DIFFROOT}" 35 | cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" 36 | 37 | "${SCRIPT_ROOT}/hack/update-codegen.sh" 38 | echo "diffing ${DIFFROOT} against freshly generated codegen" 39 | ret=0 40 | diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? 41 | cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" 42 | if [[ $ret -eq 0 ]] 43 | then 44 | echo "${DIFFROOT} up to date." 45 | else 46 | echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh" 47 | exit 1 48 | fi 49 | 50 | # smoke test 51 | echo "Smoke testing examples by compiling..." 52 | pushd "./${SCRIPT_ROOT}/examples" 53 | go build "k8s.io/code-generator/examples/crd/..." 54 | go build "k8s.io/code-generator/examples/apiserver/..." 55 | go build "k8s.io/code-generator/examples/MixedCase/..." 56 | go build "k8s.io/code-generator/examples/HyphenGroup/..." 57 | popd 58 | -------------------------------------------------------------------------------- /hack/verify-gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2021 The Pixiu Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | HELM_ROOT=$(dirname "${BASH_SOURCE}")/.. 22 | cd "${HELM_ROOT}" 23 | 24 | find_files() { 25 | find . -not \( \ 26 | \( \ 27 | -wholename './output' \ 28 | -o -wholename '*/vendor/*' \ 29 | \) -prune \ 30 | \) -name '*.go' 31 | } 32 | 33 | GOFMT="gofmt -s" 34 | 35 | bad_files=$(find_files | xargs $GOFMT -l) 36 | if [[ -n "${bad_files}" ]]; then 37 | echo "Please run hack/update-gofmt.sh to fix the following files:" 38 | echo "${bad_files}" 39 | exit 1 40 | fi 41 | -------------------------------------------------------------------------------- /pkg/apis/localstorage/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package localstorage 18 | 19 | // GroupName is the group name used in this package 20 | const ( 21 | GroupName = "storage.caoyingjunz.io" 22 | ) 23 | -------------------------------------------------------------------------------- /pkg/apis/localstorage/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=storage.caoyingjunz.io 19 | 20 | // Package v1alpha1 is the v1alpha1 version of the API. 21 | package v1 22 | -------------------------------------------------------------------------------- /pkg/apis/localstorage/v1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | 24 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage" 25 | ) 26 | 27 | // SchemeGroupVersion is group version used to register these objects 28 | var SchemeGroupVersion = schema.GroupVersion{Group: localstorage.GroupName, Version: "v1"} 29 | 30 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 31 | func Kind(kind string) schema.GroupKind { 32 | return SchemeGroupVersion.WithKind(kind).GroupKind() 33 | } 34 | 35 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 36 | func Resource(resource string) schema.GroupResource { 37 | return SchemeGroupVersion.WithResource(resource).GroupResource() 38 | } 39 | 40 | var ( 41 | // SchemeBuilder initializes a scheme builder 42 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 43 | // AddToScheme is a global function that registers this API group & version to a scheme 44 | AddToScheme = SchemeBuilder.AddToScheme 45 | ) 46 | 47 | // Adds the list of known types to Scheme. 48 | func addKnownTypes(scheme *runtime.Scheme) error { 49 | scheme.AddKnownTypes(SchemeGroupVersion, 50 | &LocalStorage{}, 51 | &LocalStorageList{}, 52 | ) 53 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/apis/localstorage/v1/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/api/resource" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | ) 23 | 24 | // +genclient 25 | // +genclient:nonNamespaced 26 | // +kubebuilder:resource:scope=Cluster,shortName={pls, ls} 27 | // +kubebuilder:printcolumn:JSONPath=".status.phase",name=Status,type=string 28 | // +kubebuilder:printcolumn:JSONPath=".spec.node",name=kubeNode,type=string 29 | // +kubebuilder:printcolumn:JSONPath=".status.allocatable",name=Allocatable,type=string 30 | // +kubebuilder:printcolumn:JSONPath=".status.capacity",name=Capacity,type=string 31 | // +kubebuilder:printcolumn:JSONPath=".metadata.creationTimestamp",name=AGE,type=date 32 | //// +kubebuilder:printcolumn:JSONPath=".spec.volumeGroup",name=VolumeGroup,type=string,priority=1 33 | // +k8s:openapi-gen=true 34 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 35 | 36 | type LocalStorage struct { 37 | metav1.TypeMeta `json:",inline"` 38 | metav1.ObjectMeta `json:"metadata,omitempty"` 39 | 40 | Spec LocalStorageSpec `json:"spec,omitempty"` 41 | Status LocalStorageStatus `json:"status,omitempty"` 42 | } 43 | 44 | type LocalStoragePhase string 45 | 46 | const ( 47 | LocalStoragePending LocalStoragePhase = "Pending" 48 | LocalStorageInitiating LocalStoragePhase = "Initiating" 49 | LocalStorageTerminating LocalStoragePhase = "Terminating" 50 | LocalStorageExtending LocalStoragePhase = "Extending" 51 | LocalStorageMaintaining LocalStoragePhase = "Maintaining" 52 | LocalStorageReady LocalStoragePhase = "Ready" 53 | LocalStorageUnknown LocalStoragePhase = "Unknown" 54 | ) 55 | 56 | type LocalStorageMode string 57 | 58 | const ( 59 | LocalStoragePath LocalStorageMode = "path" 60 | LocalStorageLvm LocalStorageMode = "lvm" 61 | ) 62 | 63 | type LocalStorageSpec struct { 64 | // Node kubernetes node name 65 | // +kubebuilder:validation:MinLength=1 66 | Node string `json:"node,omitempty"` 67 | 68 | // Path localstorage hostPath volume spec 69 | Path *PathSpec `json:"path,omitempty"` 70 | // Lvm localstorage Logical Volume Manage spec 71 | Lvm *LvmSpec `json:"lvm,omitempty"` 72 | } 73 | 74 | type PathSpec struct { 75 | VolumeDir string `json:"volumeDir,omitempty"` 76 | } 77 | 78 | type LvmSpec struct { 79 | VolumeGroup string `json:"volumeGroup,omitempty"` 80 | Disks []DiskSpec `json:"disks,omitempty"` 81 | } 82 | 83 | type DiskSpec struct { 84 | Name string `json:"name,omitempty"` 85 | // disk identifier, plugin will fill it 86 | Identifier string `json:"identifier,omitempty"` 87 | } 88 | 89 | type LocalStorageCondition string 90 | 91 | type LocalStorageStatus struct { 92 | // Localstorage phase 93 | Phase LocalStoragePhase `json:"phase,omitempty"` 94 | 95 | // Allocatable and Capacity is the Quantity on this node 96 | Allocatable *resource.Quantity `json:"allocatable,omitempty"` 97 | Capacity *resource.Quantity `json:"capacity,omitempty"` 98 | 99 | // List of mount volumes on this node 100 | // +optional 101 | Volumes []Volume `json:"volumes,omitempty"` 102 | 103 | Mode LocalStorageMode `json:"mode,omitempty"` 104 | Conditions LocalStorageCondition `json:"conditions,omitempty"` 105 | } 106 | 107 | type Volume struct { 108 | VolName string `json:"volName,omitempty"` 109 | VolID string `json:"volId,omitempty"` 110 | VolPath string `json:"volPath,omitempty"` 111 | VolSize int64 `json:"volSize,omitempty"` 112 | NodeID string `json:"nodeId,omitempty"` 113 | Attached bool `json:"attached,omitempty"` 114 | } 115 | 116 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 117 | 118 | type LocalStorageList struct { 119 | metav1.TypeMeta `json:",inline"` 120 | metav1.ListMeta `json:"metadata"` 121 | 122 | Items []LocalStorage `json:"items"` 123 | } 124 | -------------------------------------------------------------------------------- /pkg/cache/store.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cache 18 | 19 | import ( 20 | "encoding/json" 21 | "errors" 22 | "os" 23 | "sync" 24 | 25 | "google.golang.org/grpc/codes" 26 | "google.golang.org/grpc/status" 27 | ) 28 | 29 | type Volume struct { 30 | VolName string 31 | VolID string 32 | VolPath string 33 | VolSize int64 34 | NodeID string 35 | Attached bool 36 | } 37 | 38 | type Cache interface { 39 | // GetVolumeByID retrieves a volume by its unique ID or returns 40 | // an error including that ID when not found. 41 | GetVolumeByID(volID string) (Volume, error) 42 | 43 | // GetVolumeByName retrieves a volume by its name or returns 44 | // an error including that name when not found. 45 | GetVolumeByName(volName string) (Volume, error) 46 | 47 | // GetVolumes returns all currently existing volumes. 48 | GetVolumes() []Volume 49 | 50 | // SetVolume set the existing volume, 51 | // identified by its volume ID, or adds it if it does 52 | // not exist yet. 53 | SetVolume(volume Volume) error 54 | 55 | // DeleteVolume deletes the volume with the given 56 | // volume ID. It is not an error when such a volume 57 | // does not exist. 58 | DeleteVolume(volID string) error 59 | } 60 | 61 | type cache struct { 62 | Volumes map[string]Volume 63 | 64 | storeFile string 65 | lock sync.Mutex 66 | } 67 | 68 | var _ Cache = &cache{} 69 | 70 | func New(storeFile string) (Cache, error) { 71 | c := &cache{ 72 | storeFile: storeFile, 73 | } 74 | 75 | return c, c.restore() 76 | } 77 | 78 | func (c *cache) dump() error { 79 | data, err := json.Marshal(c.Volumes) 80 | if err != nil { 81 | return status.Errorf(codes.Internal, "error encoding volumes: %v", err) 82 | } 83 | 84 | if err := os.WriteFile(c.storeFile, data, 0660); err != nil { 85 | return status.Errorf(codes.Internal, "error writing store file: %v", err) 86 | } 87 | 88 | return nil 89 | } 90 | 91 | func (c *cache) restore() error { 92 | c.lock.Lock() 93 | defer c.lock.Unlock() 94 | 95 | c.Volumes = nil 96 | 97 | data, err := os.ReadFile(c.storeFile) 98 | if err != nil { 99 | // 首次启动,无数据记录 100 | if errors.Is(err, os.ErrNotExist) { 101 | return nil 102 | } 103 | return status.Errorf(codes.Internal, "error reading state file: %v", err) 104 | } 105 | 106 | if err := json.Unmarshal(data, &c.Volumes); err != nil { 107 | return status.Errorf(codes.Internal, "error encoding volumes and snapshots from store file %q: %v", c.storeFile, err) 108 | } 109 | 110 | return nil 111 | } 112 | 113 | func (c *cache) GetVolumeByID(volID string) (Volume, error) { 114 | c.lock.Lock() 115 | defer c.lock.Unlock() 116 | 117 | vol, exist := c.Volumes[volID] 118 | if !exist { 119 | return Volume{}, status.Errorf(codes.NotFound, "volume id %s does not exist in the volumes list", volID) 120 | } 121 | 122 | return vol, nil 123 | } 124 | 125 | func (c *cache) GetVolumeByName(volName string) (Volume, error) { 126 | c.lock.Lock() 127 | defer c.lock.Unlock() 128 | 129 | for _, vol := range c.Volumes { 130 | if vol.VolName == volName { 131 | return vol, nil 132 | } 133 | } 134 | 135 | return Volume{}, status.Errorf(codes.NotFound, "volume name %s does not exist in the volumes list", volName) 136 | } 137 | 138 | func (c *cache) GetVolumes() []Volume { 139 | c.lock.Lock() 140 | defer c.lock.Unlock() 141 | 142 | var volumes []Volume 143 | for _, vol := range c.Volumes { 144 | volumes = append(volumes, vol) 145 | } 146 | 147 | return volumes 148 | } 149 | 150 | func (c *cache) SetVolume(volume Volume) error { 151 | c.lock.Lock() 152 | defer c.lock.Unlock() 153 | 154 | if c.Volumes == nil { 155 | c.Volumes = make(map[string]Volume) 156 | } 157 | c.Volumes[volume.VolID] = volume 158 | 159 | return c.dump() 160 | } 161 | 162 | func (c *cache) DeleteVolume(volID string) error { 163 | c.lock.Lock() 164 | defer c.lock.Unlock() 165 | 166 | if _, exist := c.Volumes[volID]; !exist { 167 | return nil 168 | } 169 | delete(c.Volumes, volID) 170 | 171 | return c.dump() 172 | } 173 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/clientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package versioned 20 | 21 | import ( 22 | "fmt" 23 | "net/http" 24 | 25 | storagev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned/typed/localstorage/v1" 26 | discovery "k8s.io/client-go/discovery" 27 | rest "k8s.io/client-go/rest" 28 | flowcontrol "k8s.io/client-go/util/flowcontrol" 29 | ) 30 | 31 | type Interface interface { 32 | Discovery() discovery.DiscoveryInterface 33 | StorageV1() storagev1.StorageV1Interface 34 | } 35 | 36 | // Clientset contains the clients for groups. Each group has exactly one 37 | // version included in a Clientset. 38 | type Clientset struct { 39 | *discovery.DiscoveryClient 40 | storageV1 *storagev1.StorageV1Client 41 | } 42 | 43 | // StorageV1 retrieves the StorageV1Client 44 | func (c *Clientset) StorageV1() storagev1.StorageV1Interface { 45 | return c.storageV1 46 | } 47 | 48 | // Discovery retrieves the DiscoveryClient 49 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 50 | if c == nil { 51 | return nil 52 | } 53 | return c.DiscoveryClient 54 | } 55 | 56 | // NewForConfig creates a new Clientset for the given config. 57 | // If config's RateLimiter is not set and QPS and Burst are acceptable, 58 | // NewForConfig will generate a rate-limiter in configShallowCopy. 59 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 60 | // where httpClient was generated with rest.HTTPClientFor(c). 61 | func NewForConfig(c *rest.Config) (*Clientset, error) { 62 | configShallowCopy := *c 63 | 64 | if configShallowCopy.UserAgent == "" { 65 | configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() 66 | } 67 | 68 | // share the transport between all clients 69 | httpClient, err := rest.HTTPClientFor(&configShallowCopy) 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | return NewForConfigAndClient(&configShallowCopy, httpClient) 75 | } 76 | 77 | // NewForConfigAndClient creates a new Clientset for the given config and http client. 78 | // Note the http client provided takes precedence over the configured transport values. 79 | // If config's RateLimiter is not set and QPS and Burst are acceptable, 80 | // NewForConfigAndClient will generate a rate-limiter in configShallowCopy. 81 | func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { 82 | configShallowCopy := *c 83 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 84 | if configShallowCopy.Burst <= 0 { 85 | return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") 86 | } 87 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 88 | } 89 | 90 | var cs Clientset 91 | var err error 92 | cs.storageV1, err = storagev1.NewForConfigAndClient(&configShallowCopy, httpClient) 93 | if err != nil { 94 | return nil, err 95 | } 96 | 97 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) 98 | if err != nil { 99 | return nil, err 100 | } 101 | return &cs, nil 102 | } 103 | 104 | // NewForConfigOrDie creates a new Clientset for the given config and 105 | // panics if there is an error in the config. 106 | func NewForConfigOrDie(c *rest.Config) *Clientset { 107 | cs, err := NewForConfig(c) 108 | if err != nil { 109 | panic(err) 110 | } 111 | return cs 112 | } 113 | 114 | // New creates a new Clientset for the given RESTClient. 115 | func New(c rest.Interface) *Clientset { 116 | var cs Clientset 117 | cs.storageV1 = storagev1.New(c) 118 | 119 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 120 | return &cs 121 | } 122 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated clientset. 20 | package versioned 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | clientset "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned" 23 | storagev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned/typed/localstorage/v1" 24 | fakestoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned/typed/localstorage/v1/fake" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | "k8s.io/apimachinery/pkg/watch" 27 | "k8s.io/client-go/discovery" 28 | fakediscovery "k8s.io/client-go/discovery/fake" 29 | "k8s.io/client-go/testing" 30 | ) 31 | 32 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 33 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 34 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 35 | // for a real clientset and is mostly useful in simple unit tests. 36 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 37 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 38 | for _, obj := range objects { 39 | if err := o.Add(obj); err != nil { 40 | panic(err) 41 | } 42 | } 43 | 44 | cs := &Clientset{tracker: o} 45 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 46 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 47 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 48 | gvr := action.GetResource() 49 | ns := action.GetNamespace() 50 | watch, err := o.Watch(gvr, ns) 51 | if err != nil { 52 | return false, nil, err 53 | } 54 | return true, watch, nil 55 | }) 56 | 57 | return cs 58 | } 59 | 60 | // Clientset implements clientset.Interface. Meant to be embedded into a 61 | // struct to get a default implementation. This makes faking out just the method 62 | // you want to test easier. 63 | type Clientset struct { 64 | testing.Fake 65 | discovery *fakediscovery.FakeDiscovery 66 | tracker testing.ObjectTracker 67 | } 68 | 69 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 70 | return c.discovery 71 | } 72 | 73 | func (c *Clientset) Tracker() testing.ObjectTracker { 74 | return c.tracker 75 | } 76 | 77 | var ( 78 | _ clientset.Interface = &Clientset{} 79 | _ testing.FakeClient = &Clientset{} 80 | ) 81 | 82 | // StorageV1 retrieves the StorageV1Client 83 | func (c *Clientset) StorageV1() storagev1.StorageV1Interface { 84 | return &fakestoragev1.FakeStorageV1{Fake: &c.Fake} 85 | } 86 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated fake clientset. 20 | package fake 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | storagev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var scheme = runtime.NewScheme() 31 | var codecs = serializer.NewCodecFactory(scheme) 32 | 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | storagev1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package contains the scheme of the automatically generated clientset. 20 | package scheme 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package scheme 20 | 21 | import ( 22 | storagev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var Scheme = runtime.NewScheme() 31 | var Codecs = serializer.NewCodecFactory(Scheme) 32 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | storagev1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(Scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/localstorage/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated typed clients. 20 | package v1 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/localstorage/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // Package fake has the automatically generated clients. 20 | package fake 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/localstorage/v1/fake/fake_localstorage_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | v1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned/typed/localstorage/v1" 23 | rest "k8s.io/client-go/rest" 24 | testing "k8s.io/client-go/testing" 25 | ) 26 | 27 | type FakeStorageV1 struct { 28 | *testing.Fake 29 | } 30 | 31 | func (c *FakeStorageV1) LocalStorages() v1.LocalStorageInterface { 32 | return &FakeLocalStorages{c} 33 | } 34 | 35 | // RESTClient returns a RESTClient that is used to communicate 36 | // with API server by this client implementation. 37 | func (c *FakeStorageV1) RESTClient() rest.Interface { 38 | var ret *rest.RESTClient 39 | return ret 40 | } 41 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/localstorage/v1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | type LocalStorageExpansion interface{} 22 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/localstorage/v1/localstorage_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | "net/http" 23 | 24 | v1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 25 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned/scheme" 26 | rest "k8s.io/client-go/rest" 27 | ) 28 | 29 | type StorageV1Interface interface { 30 | RESTClient() rest.Interface 31 | LocalStoragesGetter 32 | } 33 | 34 | // StorageV1Client is used to interact with features provided by the storage.caoyingjunz.io group. 35 | type StorageV1Client struct { 36 | restClient rest.Interface 37 | } 38 | 39 | func (c *StorageV1Client) LocalStorages() LocalStorageInterface { 40 | return newLocalStorages(c) 41 | } 42 | 43 | // NewForConfig creates a new StorageV1Client for the given config. 44 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 45 | // where httpClient was generated with rest.HTTPClientFor(c). 46 | func NewForConfig(c *rest.Config) (*StorageV1Client, error) { 47 | config := *c 48 | if err := setConfigDefaults(&config); err != nil { 49 | return nil, err 50 | } 51 | httpClient, err := rest.HTTPClientFor(&config) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return NewForConfigAndClient(&config, httpClient) 56 | } 57 | 58 | // NewForConfigAndClient creates a new StorageV1Client for the given config and http client. 59 | // Note the http client provided takes precedence over the configured transport values. 60 | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*StorageV1Client, error) { 61 | config := *c 62 | if err := setConfigDefaults(&config); err != nil { 63 | return nil, err 64 | } 65 | client, err := rest.RESTClientForConfigAndClient(&config, h) 66 | if err != nil { 67 | return nil, err 68 | } 69 | return &StorageV1Client{client}, nil 70 | } 71 | 72 | // NewForConfigOrDie creates a new StorageV1Client for the given config and 73 | // panics if there is an error in the config. 74 | func NewForConfigOrDie(c *rest.Config) *StorageV1Client { 75 | client, err := NewForConfig(c) 76 | if err != nil { 77 | panic(err) 78 | } 79 | return client 80 | } 81 | 82 | // New creates a new StorageV1Client for the given RESTClient. 83 | func New(c rest.Interface) *StorageV1Client { 84 | return &StorageV1Client{c} 85 | } 86 | 87 | func setConfigDefaults(config *rest.Config) error { 88 | gv := v1.SchemeGroupVersion 89 | config.GroupVersion = &gv 90 | config.APIPath = "/apis" 91 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 92 | 93 | if config.UserAgent == "" { 94 | config.UserAgent = rest.DefaultKubernetesUserAgent() 95 | } 96 | 97 | return nil 98 | } 99 | 100 | // RESTClient returns a RESTClient that is used to communicate 101 | // with API server by this client implementation. 102 | func (c *StorageV1Client) RESTClient() rest.Interface { 103 | if c == nil { 104 | return nil 105 | } 106 | return c.restClient 107 | } 108 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package externalversions 20 | 21 | import ( 22 | "fmt" 23 | 24 | v1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | cache "k8s.io/client-go/tools/cache" 27 | ) 28 | 29 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 30 | // sharedInformers based on type 31 | type GenericInformer interface { 32 | Informer() cache.SharedIndexInformer 33 | Lister() cache.GenericLister 34 | } 35 | 36 | type genericInformer struct { 37 | informer cache.SharedIndexInformer 38 | resource schema.GroupResource 39 | } 40 | 41 | // Informer returns the SharedIndexInformer. 42 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 43 | return f.informer 44 | } 45 | 46 | // Lister returns the GenericLister. 47 | func (f *genericInformer) Lister() cache.GenericLister { 48 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 49 | } 50 | 51 | // ForResource gives generic access to a shared informer of the matching type 52 | // TODO extend this to unknown resources with a client pool 53 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 54 | switch resource { 55 | // Group=storage.caoyingjunz.io, Version=v1 56 | case v1.SchemeGroupVersion.WithResource("localstorages"): 57 | return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1().LocalStorages().Informer()}, nil 58 | 59 | } 60 | 61 | return nil, fmt.Errorf("no informer found for %v", resource) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package internalinterfaces 20 | 21 | import ( 22 | time "time" 23 | 24 | versioned "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned" 25 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | runtime "k8s.io/apimachinery/pkg/runtime" 27 | cache "k8s.io/client-go/tools/cache" 28 | ) 29 | 30 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 31 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 32 | 33 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 34 | type SharedInformerFactory interface { 35 | Start(stopCh <-chan struct{}) 36 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 37 | } 38 | 39 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 40 | type TweakListOptionsFunc func(*v1.ListOptions) 41 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/localstorage/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package localstorage 20 | 21 | import ( 22 | internalinterfaces "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/informers/externalversions/internalinterfaces" 23 | v1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/informers/externalversions/localstorage/v1" 24 | ) 25 | 26 | // Interface provides access to each of this group's versions. 27 | type Interface interface { 28 | // V1 provides access to shared informers for resources in V1. 29 | V1() v1.Interface 30 | } 31 | 32 | type group struct { 33 | factory internalinterfaces.SharedInformerFactory 34 | namespace string 35 | tweakListOptions internalinterfaces.TweakListOptionsFunc 36 | } 37 | 38 | // New returns a new Interface. 39 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 40 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 41 | } 42 | 43 | // V1 returns a new v1.Interface. 44 | func (g *group) V1() v1.Interface { 45 | return v1.New(g.factory, g.namespace, g.tweakListOptions) 46 | } 47 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/localstorage/v1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | internalinterfaces "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/informers/externalversions/internalinterfaces" 23 | ) 24 | 25 | // Interface provides access to all the informers in this group version. 26 | type Interface interface { 27 | // LocalStorages returns a LocalStorageInformer. 28 | LocalStorages() LocalStorageInformer 29 | } 30 | 31 | type version struct { 32 | factory internalinterfaces.SharedInformerFactory 33 | namespace string 34 | tweakListOptions internalinterfaces.TweakListOptionsFunc 35 | } 36 | 37 | // New returns a new Interface. 38 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 39 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 40 | } 41 | 42 | // LocalStorages returns a LocalStorageInformer. 43 | func (v *version) LocalStorages() LocalStorageInformer { 44 | return &localStorageInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} 45 | } 46 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/localstorage/v1/localstorage.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | "context" 23 | time "time" 24 | 25 | localstoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 26 | versioned "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned" 27 | internalinterfaces "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/informers/externalversions/internalinterfaces" 28 | v1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/listers/localstorage/v1" 29 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 | runtime "k8s.io/apimachinery/pkg/runtime" 31 | watch "k8s.io/apimachinery/pkg/watch" 32 | cache "k8s.io/client-go/tools/cache" 33 | ) 34 | 35 | // LocalStorageInformer provides access to a shared informer and lister for 36 | // LocalStorages. 37 | type LocalStorageInformer interface { 38 | Informer() cache.SharedIndexInformer 39 | Lister() v1.LocalStorageLister 40 | } 41 | 42 | type localStorageInformer struct { 43 | factory internalinterfaces.SharedInformerFactory 44 | tweakListOptions internalinterfaces.TweakListOptionsFunc 45 | } 46 | 47 | // NewLocalStorageInformer constructs a new informer for LocalStorage type. 48 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 49 | // one. This reduces memory footprint and number of connections to the server. 50 | func NewLocalStorageInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 51 | return NewFilteredLocalStorageInformer(client, resyncPeriod, indexers, nil) 52 | } 53 | 54 | // NewFilteredLocalStorageInformer constructs a new informer for LocalStorage type. 55 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 56 | // one. This reduces memory footprint and number of connections to the server. 57 | func NewFilteredLocalStorageInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 58 | return cache.NewSharedIndexInformer( 59 | &cache.ListWatch{ 60 | ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { 61 | if tweakListOptions != nil { 62 | tweakListOptions(&options) 63 | } 64 | return client.StorageV1().LocalStorages().List(context.TODO(), options) 65 | }, 66 | WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { 67 | if tweakListOptions != nil { 68 | tweakListOptions(&options) 69 | } 70 | return client.StorageV1().LocalStorages().Watch(context.TODO(), options) 71 | }, 72 | }, 73 | &localstoragev1.LocalStorage{}, 74 | resyncPeriod, 75 | indexers, 76 | ) 77 | } 78 | 79 | func (f *localStorageInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 80 | return NewFilteredLocalStorageInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 81 | } 82 | 83 | func (f *localStorageInformer) Informer() cache.SharedIndexInformer { 84 | return f.factory.InformerFor(&localstoragev1.LocalStorage{}, f.defaultInformer) 85 | } 86 | 87 | func (f *localStorageInformer) Lister() v1.LocalStorageLister { 88 | return v1.NewLocalStorageLister(f.Informer().GetIndexer()) 89 | } 90 | -------------------------------------------------------------------------------- /pkg/client/listers/localstorage/v1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | // LocalStorageListerExpansion allows custom methods to be added to 22 | // LocalStorageLister. 23 | type LocalStorageListerExpansion interface{} 24 | -------------------------------------------------------------------------------- /pkg/client/listers/localstorage/v1/localstorage.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | v1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 23 | "k8s.io/apimachinery/pkg/api/errors" 24 | "k8s.io/apimachinery/pkg/labels" 25 | "k8s.io/client-go/tools/cache" 26 | ) 27 | 28 | // LocalStorageLister helps list LocalStorages. 29 | // All objects returned here must be treated as read-only. 30 | type LocalStorageLister interface { 31 | // List lists all LocalStorages in the indexer. 32 | // Objects returned here must be treated as read-only. 33 | List(selector labels.Selector) (ret []*v1.LocalStorage, err error) 34 | // Get retrieves the LocalStorage from the index for a given name. 35 | // Objects returned here must be treated as read-only. 36 | Get(name string) (*v1.LocalStorage, error) 37 | LocalStorageListerExpansion 38 | } 39 | 40 | // localStorageLister implements the LocalStorageLister interface. 41 | type localStorageLister struct { 42 | indexer cache.Indexer 43 | } 44 | 45 | // NewLocalStorageLister returns a new LocalStorageLister. 46 | func NewLocalStorageLister(indexer cache.Indexer) LocalStorageLister { 47 | return &localStorageLister{indexer: indexer} 48 | } 49 | 50 | // List lists all LocalStorages in the indexer. 51 | func (s *localStorageLister) List(selector labels.Selector) (ret []*v1.LocalStorage, err error) { 52 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 53 | ret = append(ret, m.(*v1.LocalStorage)) 54 | }) 55 | return ret, err 56 | } 57 | 58 | // Get retrieves the LocalStorage from the index for a given name. 59 | func (s *localStorageLister) Get(name string) (*v1.LocalStorage, error) { 60 | obj, exists, err := s.indexer.GetByKey(name) 61 | if err != nil { 62 | return nil, err 63 | } 64 | if !exists { 65 | return nil, errors.NewNotFound(v1.Resource("localstorage"), name) 66 | } 67 | return obj.(*v1.LocalStorage), nil 68 | } 69 | -------------------------------------------------------------------------------- /pkg/localstorage/identityserver.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package localstorage 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/container-storage-interface/spec/lib/go/csi" 23 | "github.com/golang/protobuf/ptypes/wrappers" 24 | ) 25 | 26 | type IdentityServer struct { 27 | Driver *localStorage 28 | } 29 | 30 | func (ls *localStorage) GetPluginInfo(ctx context.Context, req *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) { 31 | return &csi.GetPluginInfoResponse{ 32 | Name: ls.config.DriverName, 33 | VendorVersion: ls.config.VendorVersion, 34 | }, nil 35 | } 36 | 37 | func (ls *localStorage) Probe(ctx context.Context, req *csi.ProbeRequest) (*csi.ProbeResponse, error) { 38 | return &csi.ProbeResponse{Ready: &wrappers.BoolValue{Value: true}}, nil 39 | } 40 | 41 | func (ls *localStorage) GetPluginCapabilities(ctx context.Context, req *csi.GetPluginCapabilitiesRequest) (*csi.GetPluginCapabilitiesResponse, error) { 42 | return &csi.GetPluginCapabilitiesResponse{ 43 | Capabilities: []*csi.PluginCapability{ 44 | { 45 | Type: &csi.PluginCapability_Service_{ 46 | Service: &csi.PluginCapability_Service{ 47 | Type: csi.PluginCapability_Service_CONTROLLER_SERVICE, 48 | }, 49 | }, 50 | }, 51 | }, 52 | }, nil 53 | } 54 | -------------------------------------------------------------------------------- /pkg/localstorage/nodeserver.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package localstorage 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/container-storage-interface/spec/lib/go/csi" 23 | "google.golang.org/grpc/codes" 24 | "google.golang.org/grpc/status" 25 | ) 26 | 27 | // NodePublishVolume mount the volume 28 | func (ls *localStorage) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) { 29 | return &csi.NodePublishVolumeResponse{}, nil 30 | } 31 | 32 | // NodeUnpublishVolume unmount the volume 33 | func (ls *localStorage) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) { 34 | return &csi.NodeUnpublishVolumeResponse{}, nil 35 | } 36 | 37 | // NodeGetInfo return info of the node on which this plugin is running 38 | func (ls *localStorage) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) { 39 | return &csi.NodeGetInfoResponse{ 40 | NodeId: ls.config.NodeId, 41 | }, nil 42 | } 43 | 44 | // NodeGetCapabilities return the capabilities of the Node plugin 45 | func (ls *localStorage) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) { 46 | return &csi.NodeGetCapabilitiesResponse{}, nil 47 | } 48 | 49 | // NodeGetVolumeStats get volume stats 50 | func (ls *localStorage) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) { 51 | return nil, nil 52 | } 53 | 54 | // NodeUnstageVolume unstage volume 55 | func (ls *localStorage) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) { 56 | return nil, status.Error(codes.Unimplemented, "") 57 | } 58 | 59 | // NodeStageVolume stage volume 60 | func (ls *localStorage) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) { 61 | return nil, status.Error(codes.Unimplemented, "") 62 | } 63 | 64 | // NodeExpandVolume node expand volume 65 | func (ls *localStorage) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { 66 | return nil, status.Error(codes.Unimplemented, "") 67 | } 68 | -------------------------------------------------------------------------------- /pkg/localstorage/server.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package localstorage 18 | 19 | import ( 20 | "net" 21 | "os" 22 | "sync" 23 | 24 | "github.com/container-storage-interface/spec/lib/go/csi" 25 | "google.golang.org/grpc" 26 | "k8s.io/klog/v2" 27 | ) 28 | 29 | // NonBlockingGRPCServer Defines Non blocking GRPC server interfaces 30 | type NonBlockingGRPCServer interface { 31 | // Start services at the endpoint 32 | Start(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) 33 | // Wait for the service to stop 34 | Wait() 35 | // Stop the service gracefully 36 | Stop() 37 | // ForceStop Stops the service forcefully 38 | ForceStop() 39 | } 40 | 41 | func NewNonBlockingGRPCServer() NonBlockingGRPCServer { 42 | return &nonBlockingGRPCServer{} 43 | } 44 | 45 | // NonBlocking server 46 | type nonBlockingGRPCServer struct { 47 | wg sync.WaitGroup 48 | server *grpc.Server 49 | } 50 | 51 | func (s *nonBlockingGRPCServer) Start(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) { 52 | s.wg.Add(1) 53 | 54 | go s.serve(endpoint, ids, cs, ns) 55 | } 56 | 57 | func (s *nonBlockingGRPCServer) Wait() { 58 | s.wg.Wait() 59 | } 60 | 61 | func (s *nonBlockingGRPCServer) Stop() { 62 | s.server.GracefulStop() 63 | } 64 | 65 | func (s *nonBlockingGRPCServer) ForceStop() { 66 | s.server.Stop() 67 | } 68 | 69 | func (s *nonBlockingGRPCServer) serve(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) { 70 | proto, addr, err := parseEndpoint(endpoint) 71 | if err != nil { 72 | klog.Fatalf("Failed to parse unix endpoint: %v", err) 73 | } 74 | 75 | if proto == "unix" { 76 | addr = "/" + addr 77 | if err := os.Remove(addr); err != nil && !os.IsNotExist(err) { 78 | klog.Fatalf("Failed to remove %s, error: %s", addr, err.Error()) 79 | } 80 | } 81 | 82 | listener, err := net.Listen(proto, addr) 83 | if err != nil { 84 | klog.Fatalf("Failed to listen: %v", err) 85 | } 86 | 87 | opts := []grpc.ServerOption{ 88 | grpc.UnaryInterceptor(logGRPC), 89 | } 90 | server := grpc.NewServer(opts...) 91 | s.server = server 92 | 93 | if ids != nil { 94 | csi.RegisterIdentityServer(server, ids) 95 | } 96 | if cs != nil { 97 | csi.RegisterControllerServer(server, cs) 98 | } 99 | if ns != nil { 100 | csi.RegisterNodeServer(server, ns) 101 | } 102 | 103 | klog.Infof("Listening for connections on address: %#v", listener.Addr()) 104 | err = server.Serve(listener) 105 | if err != nil { 106 | klog.Fatalf("Failed to serve grpc server: %v", err) 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/localstorage/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package localstorage 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "os" 23 | "path/filepath" 24 | "strings" 25 | 26 | "google.golang.org/grpc" 27 | "k8s.io/klog/v2" 28 | ) 29 | 30 | func parseEndpoint(ep string) (string, string, error) { 31 | if strings.HasPrefix(strings.ToLower(ep), "unix://") { 32 | s := strings.SplitN(ep, "://", 2) 33 | if s[1] != "" { 34 | return s[0], s[1], nil 35 | } 36 | } 37 | return "", "", fmt.Errorf("invalid endpoint: %v", ep) 38 | } 39 | 40 | func logGRPC(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 41 | klog.V(2).Infof("GRPC call: %s", info.FullMethod) 42 | 43 | resp, err := handler(ctx, req) 44 | if err != nil { 45 | klog.Errorf("GRPC error: %v", err) 46 | } 47 | 48 | return resp, err 49 | } 50 | 51 | func makeVolumeDir(volDir string) error { 52 | _, err := os.Stat(volDir) 53 | if err != nil { 54 | if !os.IsNotExist(err) { 55 | return err 56 | } 57 | if err = os.MkdirAll(volDir, os.ModePerm); err != nil { 58 | return err 59 | } 60 | } 61 | 62 | return nil 63 | } 64 | 65 | // parseVolumePath returns the canonical path for volume 66 | func parseVolumePath(baseDir, volID string) string { 67 | return filepath.Join(baseDir, volID) 68 | } 69 | -------------------------------------------------------------------------------- /pkg/runtime/scheme.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package runtime 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime" 21 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 22 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 23 | 24 | localstoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 25 | ) 26 | 27 | var ( 28 | scheme = runtime.NewScheme() 29 | ) 30 | 31 | func init() { 32 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 33 | utilruntime.Must(localstoragev1.AddToScheme(scheme)) 34 | } 35 | 36 | // NewScheme creates a new Scheme. 37 | func NewScheme() *runtime.Scheme { 38 | return scheme 39 | } 40 | -------------------------------------------------------------------------------- /pkg/scheduler/extender/bind.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package extender 18 | -------------------------------------------------------------------------------- /pkg/scheduler/extender/predicate.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package extender 18 | 19 | import ( 20 | "fmt" 21 | 22 | v1 "k8s.io/api/core/v1" 23 | corelisters "k8s.io/client-go/listers/core/v1" 24 | storagelisters "k8s.io/client-go/listers/storage/v1" 25 | "k8s.io/klog/v2" 26 | extenderv1 "k8s.io/kube-scheduler/extender/v1" 27 | 28 | localstoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 29 | localstorage "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/listers/localstorage/v1" 30 | storageutil "github.com/caoyingjunz/csi-driver-localstorage/pkg/util/storage" 31 | ) 32 | 33 | type Predicate struct { 34 | lsLister localstorage.LocalStorageLister 35 | pvcLister corelisters.PersistentVolumeClaimLister 36 | scLister storagelisters.StorageClassLister 37 | } 38 | 39 | func NewPredicate(lsLister localstorage.LocalStorageLister, pvcLister corelisters.PersistentVolumeClaimLister, scLister storagelisters.StorageClassLister) *Predicate { 40 | return &Predicate{lsLister: lsLister, pvcLister: pvcLister, scLister: scLister} 41 | } 42 | 43 | func (p *Predicate) Filter(args extenderv1.ExtenderArgs) *extenderv1.ExtenderFilterResult { 44 | pod := args.Pod 45 | if pod == nil { 46 | return &extenderv1.ExtenderFilterResult{Error: fmt.Sprintf("pod is nil")} 47 | } 48 | 49 | pvc, err := storageutil.GetLocalStoragePersistentVolumeClaimFromPod(pod, p.pvcLister, p.scLister) 50 | if err != nil { 51 | return &extenderv1.ExtenderFilterResult{Error: err.Error()} 52 | } 53 | if pvc == nil { 54 | klog.Infof("ignore filter namespace(%s) name(%s)", pod.Namespace, pod.Name) 55 | return &extenderv1.ExtenderFilterResult{ 56 | NodeNames: args.NodeNames, 57 | Nodes: args.Nodes, 58 | } 59 | } 60 | request, exists := pvc.Spec.Resources.Requests[v1.ResourceStorage] 61 | if !exists { 62 | return &extenderv1.ExtenderFilterResult{Error: fmt.Sprintf("failed to find pvc %s request quantity", pvc.Name)} 63 | } 64 | 65 | klog.Infof("starting filter namespace(%s) name(%s)", pod.Namespace, pod.Name) 66 | localstorageMap, err := storageutil.GetLocalStorageMap(p.lsLister) 67 | if err != nil { 68 | return &extenderv1.ExtenderFilterResult{Error: err.Error()} 69 | } 70 | 71 | scheduleNodes := make([]string, 0) 72 | failedNodes := make(map[string]string) 73 | for _, nodeName := range *args.NodeNames { 74 | ls, found := localstorageMap[nodeName] 75 | if !found { 76 | failedNodes[nodeName] = fmt.Sprintf("node(%s) has no localstorage", nodeName) 77 | continue 78 | } 79 | if ls.Status.Phase != localstoragev1.LocalStorageReady { 80 | failedNodes[nodeName] = fmt.Sprintf("node(%s) localstorage not ready", nodeName) 81 | continue 82 | } 83 | allocSize := ls.Status.Allocatable 84 | if request.Cmp(*allocSize) > 0 { 85 | failedNodes[nodeName] = fmt.Sprintf("node(%s) localstorage allocatable size too small", nodeName) 86 | continue 87 | } 88 | 89 | scheduleNodes = append(scheduleNodes, nodeName) 90 | } 91 | 92 | klog.Infof("filter localstorage pods on nodes: %v", scheduleNodes) 93 | return &extenderv1.ExtenderFilterResult{ 94 | NodeNames: &scheduleNodes, 95 | Nodes: args.Nodes, 96 | FailedNodes: failedNodes, 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /pkg/scheduler/extender/prioritie.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package extender 18 | 19 | import ( 20 | corelisters "k8s.io/client-go/listers/core/v1" 21 | storagelisters "k8s.io/client-go/listers/storage/v1" 22 | "k8s.io/klog/v2" 23 | extenderv1 "k8s.io/kube-scheduler/extender/v1" 24 | 25 | localstoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 26 | localstorage "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/listers/localstorage/v1" 27 | storageutil "github.com/caoyingjunz/csi-driver-localstorage/pkg/util/storage" 28 | ) 29 | 30 | type Prioritize struct { 31 | lsLister localstorage.LocalStorageLister 32 | pvcLister corelisters.PersistentVolumeClaimLister 33 | scLister storagelisters.StorageClassLister 34 | } 35 | 36 | func NewPrioritize(lsLister localstorage.LocalStorageLister, pvcLister corelisters.PersistentVolumeClaimLister, scLister storagelisters.StorageClassLister) *Prioritize { 37 | return &Prioritize{lsLister: lsLister, pvcLister: pvcLister, scLister: scLister} 38 | } 39 | 40 | func (p *Prioritize) Score(args extenderv1.ExtenderArgs) *extenderv1.HostPriorityList { 41 | pod := args.Pod 42 | if pod == nil { 43 | klog.Errorf("pod is nil") 44 | return nil 45 | } 46 | used, err := storageutil.PodIsUseLocalStorage(pod, p.pvcLister, p.scLister) 47 | if err != nil || !used { 48 | klog.Errorf("pod not use localstorage or err") 49 | return nil 50 | } 51 | 52 | nodeNames := *args.NodeNames 53 | klog.Infof("scoring nodes %v", nodeNames) 54 | 55 | hostPriorityList := make(extenderv1.HostPriorityList, len(nodeNames)) 56 | lsMap, err := storageutil.GetLocalStorageMap(p.lsLister) 57 | if err != nil { 58 | klog.Errorf("failed to get localstorage node map: $v", err) 59 | return nil 60 | } 61 | 62 | for i, nodeName := range nodeNames { 63 | var score int64 64 | ls, found := lsMap[nodeName] 65 | if found { 66 | score = p.score(ls) 67 | klog.Infof("scoring node(%s) with score(%d)", nodeName, score) 68 | } 69 | 70 | hostPriorityList[i] = extenderv1.HostPriority{ 71 | Host: nodeName, 72 | Score: score, 73 | } 74 | } 75 | 76 | klog.Infof("score localstorage pods on nodes: %v", hostPriorityList) 77 | return &hostPriorityList 78 | } 79 | 80 | func (p *Prioritize) score(ls *localstoragev1.LocalStorage) int64 { 81 | localstorage := ls.DeepCopy() 82 | 83 | allocatable := localstorage.Status.Allocatable 84 | capacity := localstorage.Status.Capacity 85 | 86 | // TODO optimise score algorithm 87 | // 临时处理,后续优化 88 | score := 100 * allocatable.AsApproximateFloat64() / capacity.AsApproximateFloat64() 89 | klog.V(2).Infof("ls %s get %v score", ls.Name, score) 90 | return int64(score) 91 | } 92 | -------------------------------------------------------------------------------- /pkg/signals/signal.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "context" 21 | "os" 22 | "os/signal" 23 | "syscall" 24 | ) 25 | 26 | var ( 27 | onlyOneSignalHandler = make(chan struct{}) 28 | shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} 29 | ) 30 | 31 | // SetupSignalHandler registered for SIGTERM and SIGINT. A context is returned 32 | // which is cancelled on one of these signals. If a second signal is caught, 33 | // the program is terminated with exit code 1. 34 | func SetupSignalHandler() context.Context { 35 | close(onlyOneSignalHandler) // panics when called twice 36 | 37 | c := make(chan os.Signal, 2) 38 | ctx, cancel := context.WithCancel(context.Background()) 39 | signal.Notify(c, shutdownSignals...) 40 | go func() { 41 | <-c 42 | cancel() 43 | <-c 44 | os.Exit(1) // second signal. Exit directly. 45 | }() 46 | 47 | return ctx 48 | } 49 | -------------------------------------------------------------------------------- /pkg/types/localstorage.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package types 18 | 19 | const ( 20 | // AnnotationKeyNodeID Name of node annotation that contains localstorage of driver names to node 21 | AnnotationKeyNodeID = "csi.volume.caoyingjunz.io/nodeid" 22 | 23 | AnnotationKeyMaintenance = "storage.caoyingjunz.io/maintenance" 24 | ) 25 | 26 | const ( 27 | LabelStorageNode = "storage.caoyingjunz.io/node" 28 | ) 29 | -------------------------------------------------------------------------------- /pkg/util/controller_utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | localstoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 21 | ) 22 | 23 | // AssignedLocalstorage selects ls that are assigned (scheduled and running). 24 | func AssignedLocalstorage(ls *localstoragev1.LocalStorage, nodeId string) bool { 25 | if ls.Spec.Node != nodeId { 26 | return false 27 | } 28 | return LocalStorageIsInitiating(ls) || LocalStorageIsPending(ls) 29 | } 30 | 31 | func LocalStorageIsPending(ls *localstoragev1.LocalStorage) bool { 32 | return CheckLocalStoragePhase(ls.Status.Phase, localstoragev1.LocalStoragePending) 33 | } 34 | 35 | func LocalStorageIsInitiating(ls *localstoragev1.LocalStorage) bool { 36 | return CheckLocalStoragePhase(ls.Status.Phase, localstoragev1.LocalStorageInitiating) 37 | } 38 | 39 | func LocalStorageIsReady(ls *localstoragev1.LocalStorage) bool { 40 | return CheckLocalStoragePhase(ls.Status.Phase, localstoragev1.LocalStorageReady) 41 | } 42 | 43 | func LocalStorageIsTerminating(ls *localstoragev1.LocalStorage) bool { 44 | return CheckLocalStoragePhase(ls.Status.Phase, localstoragev1.LocalStorageTerminating) 45 | } 46 | 47 | func SetLocalStoragePhase(ls *localstoragev1.LocalStorage, phase localstoragev1.LocalStoragePhase) { 48 | ls.Status.Phase = phase 49 | } 50 | 51 | // CheckLocalStoragePhase 检查两个状态是否相同 52 | func CheckLocalStoragePhase(p1, p2 localstoragev1.LocalStoragePhase) bool { 53 | return p1 == p2 54 | } 55 | 56 | // AddVolume accepts a volume and adds the provided volume if not present. 57 | func AddVolume(ls *localstoragev1.LocalStorage, volume localstoragev1.Volume) { 58 | if ContainsVolume(ls, volume.VolID) { 59 | return 60 | } 61 | 62 | volumes := GetVolumes(ls) 63 | SetVolume(ls, append(volumes, volume)) 64 | } 65 | 66 | // RemoveVolume accepts a volume ID and removes the provided volID if present. 67 | func RemoveVolume(ls *localstoragev1.LocalStorage, volID string) localstoragev1.Volume { 68 | volumes := GetVolumes(ls) 69 | var vol localstoragev1.Volume 70 | for i := 0; i < len(volumes); i++ { 71 | if volumes[i].VolID == volID { 72 | vol = volumes[i] 73 | volumes = append(volumes[:i], volumes[i+1:]...) 74 | } 75 | } 76 | 77 | SetVolume(ls, volumes) 78 | return vol 79 | } 80 | 81 | // ContainsVolume checks a volume that the volumeId is present. 82 | func ContainsVolume(ls *localstoragev1.LocalStorage, volID string) bool { 83 | volumes := GetVolumes(ls) 84 | for _, v := range volumes { 85 | if v.VolID == volID { 86 | return true 87 | } 88 | } 89 | 90 | return false 91 | } 92 | 93 | func SetVolume(ls *localstoragev1.LocalStorage, volumes []localstoragev1.Volume) { 94 | ls.Status.Volumes = volumes 95 | } 96 | 97 | func GetVolumes(ls *localstoragev1.LocalStorage) []localstoragev1.Volume { 98 | return ls.Status.Volumes 99 | } 100 | -------------------------------------------------------------------------------- /pkg/util/finalizer.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | localstoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 21 | ) 22 | 23 | const ( 24 | // LsProtectionFinalizer is the name of finalizer on ls. 25 | LsProtectionFinalizer = "caoyingjunz.io/ls-protection" 26 | ) 27 | 28 | // AddFinalizer accepts an Object and adds the provided finalizer if not present. 29 | // It returns an indication of whether it updated the object's list of finalizers. 30 | func AddFinalizer(o *localstoragev1.LocalStorage, finalizer string) (finalizersUpdated bool) { 31 | f := o.GetFinalizers() 32 | for _, e := range f { 33 | if e == finalizer { 34 | return false 35 | } 36 | } 37 | o.SetFinalizers(append(f, finalizer)) 38 | return true 39 | } 40 | 41 | // RemoveFinalizer accepts an Object and removes the provided finalizer if present. 42 | // It returns an indication of whether it updated the object's list of finalizers. 43 | func RemoveFinalizer(o *localstoragev1.LocalStorage, finalizer string) (finalizersUpdated bool) { 44 | f := o.GetFinalizers() 45 | for i := 0; i < len(f); i++ { 46 | if f[i] == finalizer { 47 | f = append(f[:i], f[i+1:]...) 48 | i-- 49 | finalizersUpdated = true 50 | } 51 | } 52 | o.SetFinalizers(f) 53 | return 54 | } 55 | 56 | // ContainsFinalizer checks an Object that the provided finalizer is present. 57 | func ContainsFinalizer(o *localstoragev1.LocalStorage, finalizer string) bool { 58 | f := o.GetFinalizers() 59 | for _, e := range f { 60 | if e == finalizer { 61 | return true 62 | } 63 | } 64 | return false 65 | } 66 | -------------------------------------------------------------------------------- /pkg/util/logicalvolume/logicalvolume.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package logicalvolume 18 | 19 | type Interface interface{} 20 | 21 | // TODO 22 | -------------------------------------------------------------------------------- /pkg/util/storage/storage_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package storage 18 | -------------------------------------------------------------------------------- /pkg/util/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "fmt" 21 | "path/filepath" 22 | "time" 23 | 24 | "k8s.io/api/core/v1" 25 | "k8s.io/apimachinery/pkg/api/resource" 26 | "k8s.io/client-go/kubernetes" 27 | "k8s.io/client-go/kubernetes/scheme" 28 | v1core "k8s.io/client-go/kubernetes/typed/core/v1" 29 | corelisters "k8s.io/client-go/listers/core/v1" 30 | restclient "k8s.io/client-go/rest" 31 | "k8s.io/client-go/tools/cache" 32 | "k8s.io/client-go/tools/clientcmd" 33 | "k8s.io/client-go/tools/record" 34 | "k8s.io/client-go/util/homedir" 35 | "k8s.io/klog/v2" 36 | 37 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/client/clientset/versioned" 38 | ) 39 | 40 | const ( 41 | LocalstorageManagerUserAgent = "localstorage-manager" 42 | ) 43 | 44 | var ( 45 | KeyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc 46 | ) 47 | 48 | func BuildClientConfig(configFile string) (*restclient.Config, error) { 49 | if len(configFile) != 0 { 50 | klog.Infof("kubeconfig specified. building kube config from that") 51 | return clientcmd.BuildConfigFromFlags("", configFile) 52 | } 53 | 54 | kubeConfig, err := clientcmd.BuildConfigFromFlags("", filepath.Join(homedir.HomeDir(), ".kube", "config")) 55 | if err == nil { 56 | klog.Infof("kubeconfig not specified. try to building kube config from ~/.kube/config") 57 | return kubeConfig, nil 58 | } 59 | 60 | klog.Infof("Building kube configs for running in cluster...") 61 | return restclient.InClusterConfig() 62 | } 63 | 64 | func NewClientSets(kubeConfig *restclient.Config) (kubernetes.Interface, versioned.Interface, error) { 65 | kubeClient, err := kubernetes.NewForConfig(kubeConfig) 66 | if err != nil { 67 | return nil, nil, err 68 | } 69 | lsClientSet, err := versioned.NewForConfig(kubeConfig) 70 | if err != nil { 71 | return nil, nil, err 72 | } 73 | 74 | return kubeClient, lsClientSet, nil 75 | } 76 | 77 | func NewClientSetsFromConfig(configFile string) (kubernetes.Interface, versioned.Interface, error) { 78 | kubeConfig, err := BuildClientConfig(configFile) 79 | if err != nil { 80 | return nil, nil, err 81 | } 82 | 83 | return NewClientSets(kubeConfig) 84 | } 85 | 86 | func CreateRecorder(kubeClient kubernetes.Interface) record.EventRecorder { 87 | eventBroadcaster := record.NewBroadcaster() 88 | eventBroadcaster.StartLogging(klog.Infof) 89 | eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) 90 | return eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: LocalstorageManagerUserAgent}) 91 | } 92 | 93 | func BytesToQuantity(bytes int64) resource.Quantity { 94 | quantity := resource.NewQuantity(bytes, resource.BinarySI) 95 | return *quantity 96 | } 97 | 98 | func WaitUntilPersistentVolumeClaimIsCreated(pvcLister corelisters.PersistentVolumeClaimLister, namespace, name string, timeout time.Duration) (*v1.PersistentVolumeClaim, error) { 99 | // Wait until pvc is created 100 | pvc, err := pvcLister.PersistentVolumeClaims(namespace).Get(name) 101 | if err == nil { 102 | klog.V(2).Infof("waited for pvc %s/%s to be created", namespace, name) 103 | return pvc, nil 104 | } 105 | 106 | pollingPeriod := 200 * time.Millisecond 107 | startTime := time.Now() 108 | for startTime.Add(timeout).After(time.Now()) { 109 | time.Sleep(pollingPeriod) 110 | pvc, err := pvcLister.PersistentVolumeClaims(namespace).Get(name) 111 | if err == nil { 112 | klog.V(2).Infof("waited for pvc %s/%s to be created when retry", namespace, name) 113 | return pvc, nil 114 | } 115 | } 116 | return nil, fmt.Errorf("timed out after %v when waiting for pvc %v/%v to created", timeout, namespace, name) 117 | } 118 | -------------------------------------------------------------------------------- /pkg/webhook/mutating.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Caoyingjunz Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package webhook 18 | 19 | import ( 20 | "context" 21 | "encoding/json" 22 | "net/http" 23 | 24 | admissionv1 "k8s.io/api/admission/v1" 25 | "k8s.io/klog/v2" 26 | "sigs.k8s.io/controller-runtime/pkg/client" 27 | "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 28 | 29 | localstoragev1 "github.com/caoyingjunz/csi-driver-localstorage/pkg/apis/localstorage/v1" 30 | "github.com/caoyingjunz/csi-driver-localstorage/pkg/util" 31 | ) 32 | 33 | type LocalstorageMutate struct { 34 | Client client.Client 35 | decoder *admission.Decoder 36 | } 37 | 38 | var _ admission.Handler = &LocalstorageMutate{} 39 | var _ admission.DecoderInjector = &LocalstorageMutate{} 40 | 41 | type SetFunc func(ls *localstoragev1.LocalStorage, op admissionv1.Operation) 42 | 43 | func (s *LocalstorageMutate) Handle(ctx context.Context, req admission.Request) admission.Response { 44 | ls := &localstoragev1.LocalStorage{} 45 | if err := s.decoder.Decode(req, ls); err != nil { 46 | return admission.Errored(http.StatusBadRequest, err) 47 | } 48 | klog.Infof("Mutating localstorage %s for %s", ls.Name, req.Operation) 49 | 50 | // add finalizer into localstorage if necessary 51 | if ls.DeletionTimestamp.IsZero() { 52 | s.SetFinalizer(ls) 53 | } 54 | 55 | // set localstorage default values 56 | s.Default(ls, req.Operation, s.SetStatus, s.SetDisks, s.SetVolumes) 57 | 58 | // PatchResponseFromRaw 59 | data, err := json.Marshal(ls) 60 | if err != nil { 61 | return admission.Errored(http.StatusInternalServerError, err) 62 | } 63 | 64 | klog.Infof("Mutated localstorage %+v for %s", ls, req.Operation) 65 | return admission.PatchResponseFromRaw(req.Object.Raw, data) 66 | } 67 | 68 | // Default implements webhook.Defaulter so a webhook will be registered for the type 69 | func (s *LocalstorageMutate) Default(ls *localstoragev1.LocalStorage, op admissionv1.Operation, fn ...SetFunc) { 70 | for _, f := range fn { 71 | f(ls, op) 72 | } 73 | } 74 | 75 | func (s *LocalstorageMutate) SetStatus(ls *localstoragev1.LocalStorage, op admissionv1.Operation) { 76 | if op == admissionv1.Create { 77 | if len(ls.Status.Phase) == 0 { 78 | ls.Status.Phase = localstoragev1.LocalStoragePending 79 | } 80 | } 81 | } 82 | 83 | // SetDisks set the identifier to empty if provider when Created 84 | func (s *LocalstorageMutate) SetDisks(ls *localstoragev1.LocalStorage, op admissionv1.Operation) { 85 | // TODO: 86 | } 87 | 88 | func (s *LocalstorageMutate) SetVolumes(ls *localstoragev1.LocalStorage, op admissionv1.Operation) { 89 | if op == admissionv1.Create { 90 | if len(ls.Status.Volumes) != 0 { 91 | ls.Status.Volumes = nil 92 | } 93 | } 94 | } 95 | 96 | // SetFinalizer add finalizer if necessary 97 | func (s *LocalstorageMutate) SetFinalizer(ls *localstoragev1.LocalStorage) { 98 | if !util.ContainsFinalizer(ls, util.LsProtectionFinalizer) { 99 | util.AddFinalizer(ls, util.LsProtectionFinalizer) 100 | } 101 | } 102 | 103 | // InjectDecoder implements admission.DecoderInjector interface. 104 | // A decoder will be automatically injected by InjectDecoderInto. 105 | func (s *LocalstorageMutate) InjectDecoder(d *admission.Decoder) error { 106 | s.decoder = d 107 | return nil 108 | } 109 | --------------------------------------------------------------------------------