diff --git a/inventory/sample/group_vars/all/upcloud.yml b/inventory/sample/group_vars/all/upcloud.yml
index 16e6e6fb262ee3b14c4630bc56b4305066a5851e..c2d7f5df8c280d46ec42896cd601b5763b80bc3f 100644
--- a/inventory/sample/group_vars/all/upcloud.yml
+++ b/inventory/sample/group_vars/all/upcloud.yml
@@ -7,13 +7,18 @@
 # upcloud_csi_provisioner_image_tag: "v3.1.0"
 # upcloud_csi_attacher_image_tag: "v3.4.0"
 # upcloud_csi_resizer_image_tag: "v1.4.0"
-# upcloud_csi_plugin_image_tag: "v0.2.1"
+# upcloud_csi_plugin_image_tag: "v0.3.3"
 # upcloud_csi_node_image_tag: "v2.5.0"
 # upcloud_tolerations: []
 ## Storage class options
-# expand_persistent_volumes: true
-# parameters:
-#   tier: maxiops # or hdd
 # storage_classes:
 #   - name: standard
 #     is_default: true
+#     expand_persistent_volumes: true
+#     parameters:
+#       tier: maxiops
+#   - name: hdd
+#     is_default: false
+#     expand_persistent_volumes: true
+#     parameters:
+#       tier: hdd
\ No newline at end of file
diff --git a/roles/kubernetes-apps/csi_driver/upcloud/defaults/main.yml b/roles/kubernetes-apps/csi_driver/upcloud/defaults/main.yml
index 01541ec1d05fbbfb354bd50544bd71cafac0d529..657b3006dfb8cb2bf5a6efad0b2c7eca419bb465 100644
--- a/roles/kubernetes-apps/csi_driver/upcloud/defaults/main.yml
+++ b/roles/kubernetes-apps/csi_driver/upcloud/defaults/main.yml
@@ -3,8 +3,14 @@ upcloud_csi_controller_replicas: 1
 upcloud_csi_provisioner_image_tag: "v3.1.0"
 upcloud_csi_attacher_image_tag: "v3.4.0"
 upcloud_csi_resizer_image_tag: "v1.4.0"
-upcloud_csi_plugin_image_tag: "v0.2.1"
+upcloud_csi_plugin_image_tag: "v0.3.3"
 upcloud_csi_node_image_tag: "v2.5.0"
 upcloud_username: "{{ lookup('env','UPCLOUD_USERNAME')  }}"
 upcloud_password: "{{ lookup('env','UPCLOUD_PASSWORD')  }}"
-upcloud_tolerations: []
\ No newline at end of file
+upcloud_tolerations: []
+upcloud_csi_enable_volume_snapshot: false
+upcloud_csi_snapshot_controller_replicas: 2
+upcloud_csi_snapshotter_image_tag: "v4.2.1"
+upcloud_csi_snapshot_controller_image_tag: "v4.2.1"
+upcloud_csi_snapshot_validation_webhook_image_tag: "v4.2.1"
+upcloud_cacert: "{{ lookup('env','OS_CACERT') }}"
\ No newline at end of file
diff --git a/roles/kubernetes-apps/csi_driver/upcloud/tasks/main.yml b/roles/kubernetes-apps/csi_driver/upcloud/tasks/main.yml
index 63e37bcf5f0cedc24525440310a20fb7a684bce2..f37daba92f3dbc02e33173d835b21b534d840d40 100644
--- a/roles/kubernetes-apps/csi_driver/upcloud/tasks/main.yml
+++ b/roles/kubernetes-apps/csi_driver/upcloud/tasks/main.yml
@@ -37,4 +37,4 @@
     - inventory_hostname == groups['kube_control_plane'][0]
     - not item is skipped
   loop_control:
-    label: "{{ item.item.file }}"
+    label: "{{ item.item.file }}"
\ No newline at end of file
diff --git a/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-controller.yml.j2 b/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-controller.yml.j2
index 8f05f77fb5bc90e950ab9b2902d6215d4b83fb0c..0d52837a968e708b2c7eb39674e28a0737a9b9e3 100644
--- a/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-controller.yml.j2
+++ b/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-controller.yml.j2
@@ -23,7 +23,7 @@ spec:
           args:
             - "--csi-address=$(ADDRESS)"
             - "--v=5"
-            - "--timeout=60s"
+            - "--timeout=600s"
           env:
             - name: ADDRESS
               value: /var/lib/csi/sockets/pluginproxy/csi.sock
@@ -36,7 +36,7 @@ spec:
           args:
             - "--v=5"
             - "--csi-address=$(ADDRESS)"
-            - "--timeout=30s"
+            - "--timeout=120s"
           env:
             - name: ADDRESS
               value: /var/lib/csi/sockets/pluginproxy/csi.sock
@@ -48,7 +48,7 @@ spec:
           image: registry.k8s.io/sig-storage/csi-resizer:{{ upcloud_csi_resizer_image_tag }}
           args:
             - "--v=5"
-            - "--timeout=45s"
+            - "--timeout=120s"
             - "--csi-address=$(ADDRESS)"
             - "--handle-volume-inuse-error=true"
           env:
@@ -68,8 +68,6 @@ spec:
           env:
             - name: CSI_ENDPOINT
               value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock
-            - name: UPCLOUD_API_URL
-              value: https://api.upcloud.com/
             - name: UPCLOUD_USERNAME
               valueFrom:
                 secretKeyRef:
@@ -92,4 +90,4 @@ spec:
         - name: regcred
       volumes:
         - name: socket-dir
-          emptyDir: { }
\ No newline at end of file
+          emptyDir: {}
\ No newline at end of file
diff --git a/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-node.yml.j2 b/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-node.yml.j2
index 269f4cf54f1483021ca78164af39444b27a37712..7173c6baf8eb2a6a4fa557102fe06af8a86a0c4e 100644
--- a/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-node.yml.j2
+++ b/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-node.yml.j2
@@ -23,15 +23,6 @@ spec:
             - "--v=5"
             - "--csi-address=$(ADDRESS)"
             - "--kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)"
-          lifecycle:
-            preStop:
-              exec:
-                command:
-                  [
-                      "/bin/sh",
-                      "-c",
-                      "rm -rf /registration/storage.csi.upcloud.com /registration/storage.csi.upcloud.com-reg.sock",
-                  ]
           env:
             - name: ADDRESS
               value: /csi/csi.sock
@@ -56,8 +47,6 @@ spec:
           env:
             - name: CSI_ENDPOINT
               value: unix:///csi/csi.sock
-            - name: UPCLOUD_API_URL
-              value: https://api.upcloud.com/
             - name: UPCLOUD_USERNAME
               valueFrom:
                 secretKeyRef:
@@ -76,7 +65,7 @@ spec:
           securityContext:
             privileged: true
             capabilities:
-              add: [ "SYS_ADMIN" ]
+              add: ["SYS_ADMIN"]
             allowPrivilegeEscalation: true
           volumeMounts:
             - name: plugin-dir
diff --git a/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-setup.yml.j2 b/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-setup.yml.j2
index 2a9ec08beeae1320c28ec30ada8579560d02d45a..3bc0bd580644ed3fd33704987ad4dce191a9ac9b 100644
--- a/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-setup.yml.j2
+++ b/roles/kubernetes-apps/csi_driver/upcloud/templates/upcloud-csi-setup.yml.j2
@@ -5,6 +5,40 @@ metadata:
   namespace: kube-system
 
 ---
+
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: csi-upcloud-node-sa
+  namespace: kube-system
+
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-upcloud-node-driver-registrar-role
+  namespace: kube-system
+rules:
+  - apiGroups: [ "" ]
+    resources: [ "events" ]
+    verbs: [ "get", "list", "watch", "create", "update", "patch" ]
+
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: csi-upcloud-node-driver-registrar-binding
+subjects:
+  - kind: ServiceAccount
+    name: csi-upcloud-node-sa
+    namespace: kube-system
+roleRef:
+  kind: ClusterRole
+  name: csi-upcloud-node-driver-registrar-role
+  apiGroup: rbac.authorization.k8s.io
+
+---
+
 kind: ClusterRole
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
@@ -28,12 +62,6 @@ rules:
   - 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: [ "" ]
     resources: [ "nodes" ]
     verbs: [ "get", "list", "watch" ]
@@ -90,85 +118,37 @@ roleRef:
   apiGroup: rbac.authorization.k8s.io
 
 ---
-kind: ClusterRole
+# Provisioner must be able to work with endpoints and leases in current namespace
+# if (and only if) leadership election is enabled
+kind: Role
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
-  name: csi-upcloud-snapshotter-role
+  namespace: kube-system
+  name: csi-upcloud-provisioner-cfg-role
 rules:
-  - apiGroups: [ "" ]
-    resources: [ "persistentvolumes" ]
-    verbs: [ "get", "list", "watch" ]
-  - apiGroups: [ "" ]
-    resources: [ "persistentvolumeclaims" ]
-    verbs: [ "get", "list", "watch" ]
-  - apiGroups: [ "storage.k8s.io" ]
-    resources: [ "storageclasses" ]
-    verbs: [ "get", "list", "watch" ]
-  - apiGroups: [ "" ]
-    resources: [ "events" ]
-    verbs: [ "list", "watch", "create", "update", "patch" ]
-  - apiGroups: [ "" ]
-    resources: [ "secrets" ]
-    verbs: [ "get", "list" ]
-  - apiGroups: [ "snapshot.storage.k8s.io" ]
-    resources: [ "volumesnapshotclasses" ]
-    verbs: [ "get", "list", "watch" ]
-  - apiGroups: [ "snapshot.storage.k8s.io" ]
-    resources: [ "volumesnapshotcontents" ]
-    verbs: [ "create", "get", "list", "watch", "update", "delete" ]
-  - apiGroups: [ "snapshot.storage.k8s.io" ]
-    resources: [ "volumesnapshots" ]
-    verbs: [ "get", "list", "watch", "update" ]
-  - apiGroups: [ "apiextensions.k8s.io" ]
-    resources: [ "customresourcedefinitions" ]
-    verbs: [ "create", "list", "watch", "delete" ]
+- apiGroups: [""]
+  resources: ["endpoints"]
+  verbs: ["get", "watch", "list", "delete", "update", "create"]
+- apiGroups: ["coordination.k8s.io"]
+  resources: ["leases"]
+  verbs: ["get", "watch", "list", "delete", "update", "create"]
 
 ---
-kind: ClusterRoleBinding
+kind: RoleBinding
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
-  name: csi-upcloud-snapshotter-binding
+  name: csi-provisioner-role-cfg-binding
+  namespace: kube-system
 subjects:
   - kind: ServiceAccount
     name: csi-upcloud-controller-sa
     namespace: kube-system
 roleRef:
-  kind: ClusterRole
-  name: csi-upcloud-snapshotter-role
+  kind: Role
+  name: csi-upcloud-provisioner-cfg-role
   apiGroup: rbac.authorization.k8s.io
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: csi-upcloud-node-sa
-  namespace: kube-system
-
----
-kind: ClusterRole
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
-  name: csi-upcloud-node-driver-registrar-role
-  namespace: kube-system
-rules:
-  - apiGroups: [ "" ]
-    resources: [ "events" ]
-    verbs: [ "get", "list", "watch", "create", "update", "patch" ]
 
 ---
-kind: ClusterRoleBinding
-apiVersion: rbac.authorization.k8s.io/v1
-metadata:
-  name: csi-upcloud-node-driver-registrar-binding
-subjects:
-  - kind: ServiceAccount
-    name: csi-upcloud-node-sa
-    namespace: kube-system
-roleRef:
-  kind: ClusterRole
-  name: csi-upcloud-node-driver-registrar-role
-  apiGroup: rbac.authorization.k8s.io
----
-# Resizer must be able to work with PVCs, PVs, SCs.
 kind: ClusterRole
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
diff --git a/roles/kubernetes-apps/persistent_volumes/upcloud-csi/defaults/main.yml b/roles/kubernetes-apps/persistent_volumes/upcloud-csi/defaults/main.yml
index 7ca901ee18b0e6663cc27d15c0ba871dc7e94d21..5986e8cb0b7e47541e90330d51aaad1c57496931 100644
--- a/roles/kubernetes-apps/persistent_volumes/upcloud-csi/defaults/main.yml
+++ b/roles/kubernetes-apps/persistent_volumes/upcloud-csi/defaults/main.yml
@@ -1,7 +1,12 @@
 ---
-expand_persistent_volumes: true
-parameters:
-  tier: maxiops
 storage_classes:
   - name: standard
     is_default: true
+    expand_persistent_volumes: true
+    parameters:
+      tier: maxiops
+  - name: hdd
+    is_default: false
+    expand_persistent_volumes: true
+    parameters:
+      tier: hdd
diff --git a/roles/kubernetes-apps/persistent_volumes/upcloud-csi/templates/upcloud-csi-storage-class.yml.j2 b/roles/kubernetes-apps/persistent_volumes/upcloud-csi/templates/upcloud-csi-storage-class.yml.j2
index 058531a30045187b677506355bc197f8806b6fd0..d5c84b544bac99cba59529adb35b9fe2fe3da4ec 100644
--- a/roles/kubernetes-apps/persistent_volumes/upcloud-csi/templates/upcloud-csi-storage-class.yml.j2
+++ b/roles/kubernetes-apps/persistent_volumes/upcloud-csi/templates/upcloud-csi-storage-class.yml.j2
@@ -7,9 +7,10 @@ metadata:
   annotations:
     storageclass.kubernetes.io/is-default-class: "{{ class.is_default | default(false) | ternary("true","false") }}"
 provisioner: storage.csi.upcloud.com
+reclaimPolicy: Retain
 parameters:
 {% for key, value in (class.parameters | default({})).items() %}
   "{{ key }}": "{{ value }}"
 {% endfor %}
-allowVolumeExpansion: {{ expand_persistent_volumes }}
+allowVolumeExpansion: {{ class.expand_persistent_volumes | default(true) | ternary("true","false") }}
 {% endfor %}