[stable/zed] Add Storpool CSI support (#1172)

This is an automated cherry-pick of #1153
/assign mnaser
diff --git a/roles/csi/meta/main.yml b/roles/csi/meta/main.yml
index 4fe8bdd..58e6c8b 100644
--- a/roles/csi/meta/main.yml
+++ b/roles/csi/meta/main.yml
@@ -36,3 +36,5 @@
     when: csi_driver == "rbd"
   - role: powerstore_csi
     when: csi_driver == "powerstore"
+  - role: storpool_csi
+    when: csi_driver == "storpool"
diff --git a/roles/storpool_csi/README.md b/roles/storpool_csi/README.md
new file mode 100644
index 0000000..f5c38d5
--- /dev/null
+++ b/roles/storpool_csi/README.md
@@ -0,0 +1 @@
+# `storpool_csi`
diff --git a/roles/storpool_csi/files/storpool-csi-controllerplugin-rbac.yaml b/roles/storpool_csi/files/storpool-csi-controllerplugin-rbac.yaml
new file mode 100644
index 0000000..3238411
--- /dev/null
+++ b/roles/storpool_csi/files/storpool-csi-controllerplugin-rbac.yaml
@@ -0,0 +1,86 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: storpool-csi-controller-sa
+  namespace: kube-system
+
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-attacher-role
+rules:
+  - apiGroups: [""]
+    resources: ["persistentvolumes"]
+    verbs: ["get", "list", "watch", "patch"]
+  - apiGroups: ["storage.k8s.io"]
+    resources: ["csinodes"]
+    verbs: ["get", "list", "watch"]
+  - apiGroups: ["storage.k8s.io"]
+    resources: ["volumeattachments"]
+    verbs: ["get", "list", "watch", "patch"]
+  - apiGroups: ["storage.k8s.io"]
+    resources: ["volumeattachments/status"]
+    verbs: ["patch"]
+
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-attacher-binding
+subjects:
+  - kind: ServiceAccount
+    name: storpool-csi-controller-sa
+    namespace: kube-system
+roleRef:
+  kind: ClusterRole
+  name: csi-attacher-role
+  apiGroup: rbac.authorization.k8s.io
+
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-provisioner-role
+rules:
+  - apiGroups: [""]
+    resources: ["persistentvolumes"]
+    verbs: ["get", "list", "watch", "create", "delete"]
+  - apiGroups: [""]
+    resources: ["persistentvolumeclaims"]
+    verbs: ["get", "list", "watch", "update"]
+  - apiGroups: ["storage.k8s.io"]
+    resources: ["storageclasses"]
+    verbs: ["get", "list", "watch"]
+  - apiGroups: [""]
+    resources: ["nodes"]
+    verbs: ["get", "list", "watch"]
+  - apiGroups: ["storage.k8s.io"]
+    resources: ["csinodes"]
+    verbs: ["get", "list", "watch"]
+  - apiGroups: [""]
+    resources: ["events"]
+    verbs: ["list", "watch", "create", "update", "patch"]
+  - apiGroups: ["snapshot.storage.k8s.io"]
+    resources: ["volumesnapshots"]
+    verbs: ["get", "list"]
+  - apiGroups: ["snapshot.storage.k8s.io"]
+    resources: ["volumesnapshotcontents"]
+    verbs: ["get", "list"]
+  - apiGroups: ["coordination.k8s.io"]
+    resources: ["leases"]
+    verbs: ["get", "list", "watch", "create", "delete", "update"]
+
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-provisioner-binding
+subjects:
+  - kind: ServiceAccount
+    name: storpool-csi-controller-sa
+    namespace: kube-system
+roleRef:
+  kind: ClusterRole
+  name: csi-provisioner-role
+  apiGroup: rbac.authorization.k8s.io
diff --git a/roles/storpool_csi/files/storpool-csi-controllerplugin.yaml b/roles/storpool_csi/files/storpool-csi-controllerplugin.yaml
new file mode 100644
index 0000000..cb9f9fd
--- /dev/null
+++ b/roles/storpool_csi/files/storpool-csi-controllerplugin.yaml
@@ -0,0 +1,150 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: storpool-csi-controllerplugin
+  namespace: kube-system
+spec:
+  selector:
+    matchLabels:
+      name: storpool-csi-controllerplugin
+  template:
+    metadata:
+      labels:
+        name: storpool-csi-controllerplugin
+    spec:
+      serviceAccountName: storpool-csi-controller-sa
+      containers:
+        - name: storpool-csi-plugin
+          image: cts.storpool.com/storpool-csi/release:1.0.0
+          env:
+            - name: CSI_ENDPOINT
+              value: unix:///csi/csi.sock
+            - name: SP_NODE_NAME
+              valueFrom:
+                fieldRef:
+                  fieldPath: spec.nodeName
+          imagePullPolicy: "IfNotPresent"
+          ports:
+            - containerPort: 9808
+              name: healthz
+              protocol: TCP
+          livenessProbe:
+            failureThreshold: 5
+            httpGet:
+              path: /healthz
+              port: healthz
+            initialDelaySeconds: 10
+            timeoutSeconds: 3
+            periodSeconds: 10
+          volumeMounts:
+            - name: storpool-conf
+              mountPath: /etc/storpool.conf
+              readOnly: true
+            - name: storpool-dir
+              mountPath: /usr/lib/storpool
+              readOnly: true
+            - name: socket-dir
+              mountPath: /csi
+        - name: csi-provisioner
+          image: registry.k8s.io/sig-storage/csi-provisioner:v3.6.0
+          args:
+            - "--csi-address=$(ADDRESS)"
+            - "--default-fstype=ext4"
+            - "--extra-create-metadata"
+            - '--leader-election'
+            - '--http-endpoint=:8080'
+          ports:
+            - name: http-endpoint
+              containerPort: 8080
+              protocol: TCP
+          env:
+            - name: ADDRESS
+              value: /var/lib/csi/sockets/pluginproxy/csi.sock
+          imagePullPolicy: "IfNotPresent"
+          volumeMounts:
+            - name: socket-dir
+              mountPath: /var/lib/csi/sockets/pluginproxy/
+          livenessProbe:
+            httpGet:
+              path: /healthz/leader-election
+              port: http-endpoint
+              scheme: HTTP
+            initialDelaySeconds: 10
+            timeoutSeconds: 10
+            periodSeconds: 20
+            successThreshold: 1
+            failureThreshold: 1
+        - name: csi-attacher
+          image: registry.k8s.io/sig-storage/csi-attacher:v4.4.0
+          args:
+            - "--csi-address=$(ADDRESS)"
+            - '--leader-election'
+            - '--http-endpoint=:8081'
+          ports:
+            - name: http-endpoint
+              containerPort: 8081
+              protocol: TCP
+          env:
+            - name: ADDRESS
+              value: /var/lib/csi/sockets/pluginproxy/csi.sock
+          imagePullPolicy: "IfNotPresent"
+          volumeMounts:
+            - name: socket-dir
+              mountPath: /var/lib/csi/sockets/pluginproxy/
+          livenessProbe:
+            httpGet:
+              path: /healthz/leader-election
+              port: http-endpoint
+              scheme: HTTP
+            initialDelaySeconds: 10
+            timeoutSeconds: 10
+            periodSeconds: 20
+            successThreshold: 1
+            failureThreshold: 1
+        - name: csi-resizer
+          image: registry.k8s.io/sig-storage/csi-resizer:v1.8.0
+          args:
+            - '--csi-address=$(ADDRESS)'
+            - '--leader-election'
+            - '--http-endpoint=:8082'
+          ports:
+            - name: http-endpoint
+              containerPort: 8082
+              protocol: TCP
+          env:
+            - name: ADDRESS
+              value: /var/lib/csi/sockets/pluginproxy/csi.sock
+          volumeMounts:
+            - name: socket-dir
+              mountPath: /var/lib/csi/sockets/pluginproxy/
+          livenessProbe:
+            httpGet:
+              path: /healthz/leader-election
+              port: http-endpoint
+              scheme: HTTP
+            initialDelaySeconds: 10
+            timeoutSeconds: 10
+            periodSeconds: 20
+            successThreshold: 1
+            failureThreshold: 1
+        - name: liveness-probe
+          image: registry.k8s.io/sig-storage/livenessprobe:v2.11.0
+          args:
+            - "--csi-address=$(ADDRESS)"
+          env:
+            - name: ADDRESS
+              value: /var/lib/csi/sockets/pluginproxy/csi.sock
+          volumeMounts:
+            - name: socket-dir
+              mountPath: /var/lib/csi/sockets/pluginproxy/
+      volumes:
+        - name: storpool-conf
+          hostPath:
+            path: /etc/storpool.conf
+            type: File
+        - name: storpool-dir
+          hostPath:
+            path: /usr/lib/storpool
+            type: Directory
+        - name: socket-dir
+          emptyDir: {}
diff --git a/roles/storpool_csi/files/storpool-csi-driver.yaml b/roles/storpool_csi/files/storpool-csi-driver.yaml
new file mode 100644
index 0000000..f68b056
--- /dev/null
+++ b/roles/storpool_csi/files/storpool-csi-driver.yaml
@@ -0,0 +1,8 @@
+apiVersion: storage.k8s.io/v1
+kind: CSIDriver
+metadata:
+  name: csi.storpool.com
+spec:
+  attachRequired: true
+  volumeLifecycleModes:
+  - Persistent
diff --git a/roles/storpool_csi/files/storpool-csi-nodeplugin-rbac.yaml b/roles/storpool_csi/files/storpool-csi-nodeplugin-rbac.yaml
new file mode 100644
index 0000000..3ee041c
--- /dev/null
+++ b/roles/storpool_csi/files/storpool-csi-nodeplugin-rbac.yaml
@@ -0,0 +1,28 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: storpool-csi-node-sa
+  namespace: kube-system
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-nodeplugin-role
+rules:
+  - apiGroups: [""]
+    resources: ["events"]
+    verbs: ["get", "list", "watch", "create", "update", "patch"]
+
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-nodeplugin-binding
+subjects:
+  - kind: ServiceAccount
+    name: storpool-csi-node-sa
+    namespace: kube-system
+roleRef:
+  kind: ClusterRole
+  name: csi-nodeplugin-role
+  apiGroup: rbac.authorization.k8s.io
diff --git a/roles/storpool_csi/files/storpool-csi-nodeplugin.yaml b/roles/storpool_csi/files/storpool-csi-nodeplugin.yaml
new file mode 100644
index 0000000..f071927
--- /dev/null
+++ b/roles/storpool_csi/files/storpool-csi-nodeplugin.yaml
@@ -0,0 +1,102 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: storpool-csi-nodeplugin
+  namespace: kube-system
+spec:
+  selector:
+    matchLabels:
+      name: storpool-csi-nodeplugin
+  template:
+    metadata:
+      labels:
+        name: storpool-csi-nodeplugin
+    spec:
+      serviceAccountName: storpool-csi-node-sa
+      nodeSelector:
+        kubernetes.io/os: linux
+      containers:
+        - name: storpool-csi-plugin
+          image: cts.storpool.com/storpool-csi/release:1.0.0
+          env:
+            - name: CSI_ENDPOINT
+              value: unix:///csi/csi.sock
+            - name: SP_NODE_NAME
+              valueFrom:
+                fieldRef:
+                  fieldPath: spec.nodeName
+          imagePullPolicy: "IfNotPresent"
+          ports:
+            - containerPort: 9808
+              name: healthz
+              protocol: TCP
+          livenessProbe:
+            failureThreshold: 5
+            httpGet:
+              path: /healthz
+              port: healthz
+            initialDelaySeconds: 10
+            timeoutSeconds: 3
+            periodSeconds: 10
+          securityContext:
+            privileged: true
+            capabilities:
+              add: [ "SYS_ADMIN" ]
+            allowPrivilegeEscalation: true
+          volumeMounts:
+            - name: storpool-conf
+              mountPath: /etc/storpool.conf
+              readOnly: true
+            - name: dev-dir
+              mountPath: /dev
+              mountPropagation: HostToContainer
+            - name: storpool-dir
+              mountPath: /usr/lib/storpool
+              readOnly: true
+            - name: socket-dir
+              mountPath: /csi
+            - name: mountpoint-dir
+              mountPath: /var/lib/kubelet
+              mountPropagation: Bidirectional
+        - name: node-driver-registrar
+          image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.9.0
+          args:
+            - "--csi-address=/csi/csi.sock"
+            - "--kubelet-registration-path=/var/lib/kubelet/plugins/csi.storpool.com/csi.sock"
+          volumeMounts:
+            - name: socket-dir
+              mountPath: /csi
+            - name: registration-dir
+              mountPath: /registration
+        - name: liveness-probe
+          image: k8s.gcr.io/sig-storage/livenessprobe:v2.11.0
+          args:
+            - --csi-address=/csi/csi.sock
+          volumeMounts:
+            - name: socket-dir
+              mountPath: /csi
+      volumes:
+        - name: storpool-conf
+          hostPath:
+            path: /etc/storpool.conf
+            type: File
+        - name: dev-dir
+          hostPath:
+            path: /dev
+            type: Directory
+        - name: storpool-dir
+          hostPath:
+            path: /usr/lib/storpool
+            type: Directory
+        - name: socket-dir
+          hostPath:
+            path: /var/lib/kubelet/plugins/csi.storpool.com
+            type: DirectoryOrCreate
+        - name: mountpoint-dir
+          hostPath:
+            path: /var/lib/kubelet
+            type: Directory
+        - name: registration-dir
+          hostPath:
+            path: /var/lib/kubelet/plugins_registry
+            type: Directory
diff --git a/roles/storpool_csi/meta/main.yml b/roles/storpool_csi/meta/main.yml
new file mode 100644
index 0000000..ff28cf3
--- /dev/null
+++ b/roles/storpool_csi/meta/main.yml
@@ -0,0 +1,32 @@
+# Copyright (c) 2024 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+galaxy_info:
+  author: VEXXHOST, Inc.
+  description: Ansible role for Storpool CSI
+  license: Apache-2.0
+  min_ansible_version: 5.5.0
+  standalone: false
+  platforms:
+    - name: EL
+      versions:
+        - "8"
+        - "9"
+    - name: Ubuntu
+      versions:
+        - focal
+        - jammy
+
+dependencies:
+  - role: defaults
diff --git a/roles/storpool_csi/tasks/main.yml b/roles/storpool_csi/tasks/main.yml
new file mode 100644
index 0000000..acc3cf9
--- /dev/null
+++ b/roles/storpool_csi/tasks/main.yml
@@ -0,0 +1,33 @@
+---
+- name: Deploy CSI RBAC
+  kubernetes.core.k8s:
+    state: present
+    definition: "{{ lookup('file', 'storpool-csi-' ~ item.name ~ '-rbac.yaml') | from_yaml_all }}"
+  loop:
+    - name: controllerplugin
+    - name: nodeplugin
+
+- name: Deploy CSI
+  kubernetes.core.k8s:
+    state: present
+    definition:
+      - "{{ lookup('file', 'storpool-csi-controllerplugin.yaml') | from_yaml }}"
+      - "{{ lookup('file', 'storpool-csi-driver.yaml') | from_yaml }}"
+      - "{{ lookup('file', 'storpool-csi-nodeplugin.yaml') | from_yaml }}"
+
+- name: Create StorageClass
+  kubernetes.core.k8s:
+    state: present
+    definition:
+      apiVersion: storage.k8s.io/v1
+      kind: StorageClass
+      metadata:
+        name: general
+        annotations:
+          storageclass.kubernetes.io/is-default-class: "true"
+      provisioner: csi.storpool.com
+      allowVolumeExpansion: true
+      volumeBindingMode: WaitForFirstConsumer
+      reclaimPolicy: Delete
+      parameters:
+        template: "{{ storpool_csi_template }}"