Skip to content

Commit 021f614

Browse files
feat(kubernetes): propagate remote-accessible LINSTOR StorageClasses to tenant clusters
Tenant Kubernetes clusters previously exposed a single hardcoded "kubevirt" StorageClass mapped to one infra class. Discover all remote-accessible LINSTOR infra StorageClasses (provisioner linstor.csi.linbit.com, allowRemoteVolumeAccess != false) via Helm lookup and propagate each to the tenant under the same name. - csi.yaml builds a storageClasses map filtered to remote LINSTOR classes; node-local classes (e.g. "local") are excluded because the backing volume cannot follow a live-migrated worker VM. - The class named by .Values.storageClass (default "replicated") is marked the tenant default; the legacy "kubevirt" StorageClass is kept as a non-default alias so existing tenant PVCs keep binding. - A non-destructive fallback preserves the legacy mapping when the lookup returns empty (dry-run), so tenant StorageClasses are never wiped on a transient reconcile. - infraStorageClassEnforcement is intentionally left disabled (AllowAll) to avoid breaking tenants that already self-served custom StorageClasses under the current default. Refs: #2094, #1424 Assisted-By: Claude <[email protected]> Co-Authored-By: Claude Opus 4.8 <[email protected]> Signed-off-by: Myasnikov Daniil <[email protected]>
1 parent 4752161 commit 021f614

8 files changed

Lines changed: 48 additions & 13 deletions

File tree

‎api/apps/v1alpha1/kubernetes/types.go‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/apps/kubernetes/README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ See the reference for components utilized in this service:
9999
100100
### Common Parameters
101101
102-
| Name | Description | Type | Value |
103-
| -------------- | ------------------------------------ | -------- | ------------ |
104-
| `storageClass` | StorageClass used to store the data. | `string` | `replicated` |
102+
| Name | Description | Type | Value |
103+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------ |
104+
| `storageClass` | Default StorageClass inside the tenant cluster. Remote-accessible LINSTOR classes are auto-propagated to the tenant under the same name. | `string` | `replicated` |
105105
106106
107107
### Application-specific Parameters

‎packages/apps/kubernetes/templates/helmreleases/csi.yaml‎

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,32 @@ spec:
2828
upgrade:
2929
remediation:
3030
retries: -1
31-
{{- with .Values.storageClass }}
3231
values:
33-
storageClass: "{{ . }}"
34-
{{- end }}
32+
storageClasses:
33+
{{- /* Propagate remote-accessible LINSTOR infra StorageClasses to the tenant under the same name. */}}
34+
{{- $defaultName := .Values.storageClass | default "replicated" }}
35+
{{- $out := dict }}
36+
{{- range $sc := (lookup "storage.k8s.io/v1" "StorageClass" "" "").items }}
37+
{{- $params := $sc.parameters | default dict }}
38+
{{- if and (eq $sc.provisioner "linstor.csi.linbit.com") (ne (index $params "linstor.csi.linbit.com/allowRemoteVolumeAccess" | default "true") "false") }}
39+
{{- $_ := set $out $sc.metadata.name (dict "infraStorageClass" $sc.metadata.name "default" false) }}
40+
{{- end }}
41+
{{- end }}
42+
{{- /* Non-destructive fallback for dry-run/empty lookup: preserve the legacy mapping, never collapse to nothing. */}}
43+
{{- if not $out }}
44+
{{- $_ := set $out "replicated" (dict "infraStorageClass" "replicated" "default" false) }}
45+
{{- end }}
46+
{{- /* Legacy alias so existing tenant PVCs bound to the "kubevirt" StorageClass keep working. */}}
47+
{{- if not (hasKey $out "kubevirt") }}
48+
{{- $_ := set $out "kubevirt" (dict "infraStorageClass" $defaultName "default" false) }}
49+
{{- end }}
50+
{{- /* Mark exactly one default: the configured storageClass if propagated, else replicated, else first by name. */}}
51+
{{- $chosen := "" }}
52+
{{- if hasKey $out $defaultName }}{{ $chosen = $defaultName }}
53+
{{- else if hasKey $out "replicated" }}{{ $chosen = "replicated" }}
54+
{{- else }}{{ $chosen = (keys $out | sortAlpha | first) }}{{ end }}
55+
{{- $_ := set (index $out $chosen) "default" true }}
56+
{{- $out | toYaml | nindent 6 }}
3557
dependsOn:
3658
- name: {{ .Release.Name }}-vsnap-crd
3759
namespace: {{ .Release.Namespace }}

‎packages/apps/kubernetes/values.schema.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"type": "object",
44
"properties": {
55
"storageClass": {
6-
"description": "StorageClass used to store the data.",
6+
"description": "Default StorageClass inside the tenant cluster. Remote-accessible LINSTOR classes are auto-propagated to the tenant under the same name.",
77
"type": "string",
88
"default": "replicated",
99
"x-kubernetes-validations": [

‎packages/apps/kubernetes/values.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## @section Common Parameters
33
##
44

5-
## @param {string} storageClass - StorageClass used to store the data.
5+
## @param {string} storageClass - Default StorageClass inside the tenant cluster. Remote-accessible LINSTOR classes are auto-propagated to the tenant under the same name.
66
## @immutable
77
## @x-cozystack-options {source: storageclass}
88
storageClass: replicated

‎packages/system/kubernetes-rd/cozyrds/kubernetes.yaml‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎packages/system/kubevirt-csi-node/templates/deploy.yaml‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,19 @@ metadata:
266266
data:
267267
infraClusterNamespace:
268268
infraClusterLabels: csi-driver/cluster=tenant
269+
{{- range $name, $m := .Values.storageClasses }}
269270
---
270271
apiVersion: storage.k8s.io/v1
271272
kind: StorageClass
272273
metadata:
273-
name: kubevirt
274+
name: {{ $name }}
275+
{{- if $m.default }}
274276
annotations:
275277
storageclass.kubernetes.io/is-default-class: "true"
278+
{{- end }}
276279
provisioner: csi.kubevirt.io
277280
allowVolumeExpansion: true
278281
parameters:
279-
infraStorageClassName: {{ .Values.storageClass }}
282+
infraStorageClassName: {{ $m.infraStorageClass }}
280283
bus: scsi
284+
{{- end }}
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1-
storageClass: replicated
1+
# Map of tenant StorageClasses to create, keyed by name. Normally populated by
2+
# the parent kubernetes chart from remote-accessible LINSTOR infra classes; the
3+
# default below is the fallback used for `helm template` / unit tests.
4+
storageClasses:
5+
replicated:
6+
infraStorageClass: replicated
7+
default: true
8+
kubevirt:
9+
infraStorageClass: replicated
10+
default: false
211
csiDriver:
312
image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:v1.5.0@sha256:dad088fc04cc54af6d5f487ca9296669331a5345f143ed64cd9027b1bb20b5de

0 commit comments

Comments
 (0)