The problem was a mess inside those dictionaries, access_mode
got twice into the spec and caused bad things. I had to ditch dictionaries and use dot notation, also I’ve added check if pv+pvc already exists. I use spawner.api
to call request functions and I somehow like better than spawner._make_create_pvc_request
.
I’m including whole pre-spawn hook for anyone who might need it (or just as an inspiration). For me, it was hard finding any example on how to do it
extraConfig:
pre-spawn-hook: |
from kubernetes.client.models import V1PersistentVolumeClaim
from kubernetes.client.models import V1PersistentVolumeClaimSpec
from kubernetes.client.models import V1ResourceRequirements
from kubernetes.client.models import V1LabelSelector
from kubernetes.client.models import V1PersistentVolume
from kubernetes.client.models import V1ObjectMeta
from kubernetes.client.models import V1CSIPersistentVolumeSource
from kubernetes.client.models import V1PersistentVolumeSpec
from kubernetes.client.api import CoreV1Api
def create_homes(spawner):
username = spawner.user.name
home_pvc_name = username + "-claim"
home_pv_name = username + "-data-sshfs"
share_path = "/nfs4/home/" + username
pk_secret = "jupyterhub-prod-ns/" + username + "-secret"
mount_path = "/home/meta/" + username
v1 = client.CoreV1Api()
pvs = v1.list_persistent_volume(watch=False)
pv = None
for volume in pvs.items:
if volume.metadata.name == home_pv_name:
pv = volume
if not pv:
pv = V1PersistentVolume()
pv.api_version = "v1"
pv.kind = "PersistentVolume"
pv.metadata = V1ObjectMeta()
pv.metadata.name = home_pv_name
pv.metadata.labels = {"name":home_pv_name}
pv.spec = V1PersistentVolumeSpec()
pv.spec.access_modes = ['ReadWriteMany']
pv.spec.capacity = {"storage":"100Gi"}
pv.spec.storage_class_name = "sshfs"
volume_attr = {"server":"server.cz","port":"22",
"share":share_path,"privateKey":pk_secret,
"user":username,"sshOpts":"uid=1000,gid=100,allow_other"}
pv.spec.csi = V1CSIPersistentVolumeSource(driver="csi-sshfs",
volume_attributes=volume_attr,
volume_handle="data-id")
spawner.api.create_persistent_volume(pv)
pvcs = v1.list_persistent_volume_claim_for_all_namespaces(watch=False)
pvc = None
for claim in pvcs.items:
if claim.metadata.name == home_pvc_name:
pvc = claim
if not pvc:
pvc = V1PersistentVolumeClaim()
pvc.api_version = "v1"
pvc.kind = "PersistentVolumeClaim"
pvc.metadata = V1ObjectMeta()
pvc.metadata.name = home_pvc_name
pvc.spec = V1PersistentVolumeClaimSpec()
pvc.spec.access_modes = ['ReadWriteMany']
pvc.spec.resources = V1ResourceRequirements()
pvc.spec.resources.requests = {"storage":"100Gi"}
pvc.spec.storage_class_name = "sshfs"
pvc.spec.selector = V1LabelSelector()
pvc.spec.selector.match_labels = {"name":home_pv_name}
spawner.api.create_namespaced_persistent_volume_claim("jupyterhub-prod-ns", pvc)
c.KubeSpawner.pre_spawn_hook = create_homes