diff --git a/internal/constants.go b/internal/constants.go index 806e573..915c07f 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -7,13 +7,19 @@ const ( porklockConfigSecretName = "porklock-config" porklockConfigMountPath = "/etc/porklock" - csiDriverName = "irods.csi.cyverse.org" - csiDriverStorageClassName = "irods-sc" - csiDriverDataVolumeNamePrefix = "csi-data-volume" - csiDriverDataVolumeClaimNamePrefix = "csi-data-volume-claim" - csiDriverInputVolumeMountPath = "/input" - csiDriverOutputVolumeMountPath = "/output" - csiDriverLocalMountPath = "/data-store" + csiDriverName = "irods.csi.cyverse.org" + csiDriverStorageClassName = "irods-sc" + csiDriverInputVolumeNamePrefix = "csi-input-volume" + csiDriverInputVolumeClaimNamePrefix = "csi-input-volume-claim" + csiDriverOutputVolumeNamePrefix = "csi-output-volume" + csiDriverOutputVolumeClaimNamePrefix = "csi-output-volume-claim" + csiDriverHomeVolumeNamePrefix = "csi-home-volume" + csiDriverHomeVolumeClaimNamePrefix = "csi-home-volume-claim" + csiDriverSharedVolumeNamePrefix = "csi-shared-volume" + csiDriverSharedVolumeClaimNamePrefix = "csi-shared-volume-claim" + csiDriverDataVolumeNamePrefix = "csi-data-volume" + csiDriverDataVolumeClaimNamePrefix = "csi-data-volume-claim" + csiDriverLocalMountPath = "/data-store" // The file transfers volume serves as the working directory when IRODS CSI Driver integration is disabled. fileTransfersVolumeName = "input-files" diff --git a/internal/volumes.go b/internal/volumes.go index bcb0b16..4a7901a 100644 --- a/internal/volumes.go +++ b/internal/volumes.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "path" "path/filepath" "strings" @@ -31,16 +32,52 @@ func (i *Internal) getZoneMountPath() string { return fmt.Sprintf("%s/%s", csiDriverLocalMountPath, i.IRODSZone) } -func (i *Internal) getCSIDataVolumeHandle(job *model.Job) string { - return fmt.Sprintf("%s-handle-%s", csiDriverDataVolumeNamePrefix, job.InvocationID) +func (i *Internal) getCSIInputVolumeHandle(job *model.Job) string { + return fmt.Sprintf("%s-handle-%s", csiDriverInputVolumeNamePrefix, job.InvocationID) } -func (i *Internal) getCSIDataVolumeName(job *model.Job) string { - return fmt.Sprintf("%s-%s", csiDriverDataVolumeNamePrefix, job.InvocationID) +func (i *Internal) getCSIOutputVolumeHandle(job *model.Job) string { + return fmt.Sprintf("%s-handle-%s", csiDriverOutputVolumeNamePrefix, job.InvocationID) } -func (i *Internal) getCSIDataVolumeClaimName(job *model.Job) string { - return fmt.Sprintf("%s-%s", csiDriverDataVolumeClaimNamePrefix, job.InvocationID) +func (i *Internal) getCSIHomeVolumeHandle(job *model.Job) string { + return fmt.Sprintf("%s-handle-%s", csiDriverHomeVolumeNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSISharedVolumeHandle(job *model.Job) string { + return fmt.Sprintf("%s-handle-%s", csiDriverSharedVolumeNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSIInputVolumeName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverInputVolumeNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSIInputVolumeClaimName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverInputVolumeClaimNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSIOutputVolumeName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverOutputVolumeNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSIOutputVolumeClaimName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverOutputVolumeClaimNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSIHomeVolumeName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverHomeVolumeNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSIHomeVolumeClaimName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverHomeVolumeClaimNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSISharedVolumeName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverSharedVolumeNamePrefix, job.InvocationID) +} + +func (i *Internal) getCSISharedVolumeClaimName(job *model.Job) string { + return fmt.Sprintf("%s-%s", csiDriverSharedVolumeClaimNamePrefix, job.InvocationID) } func (i *Internal) getInputPathMappings(job *model.Job) ([]IRODSFSPathMapping, error) { @@ -49,7 +86,7 @@ func (i *Internal) getInputPathMappings(job *model.Job) ([]IRODSFSPathMapping, e // key = mount path, val = irods path mappingMap := map[string]string{} - // Mount the input and output files. + // Mount the input files. for _, step := range job.Steps { for _, stepInput := range step.Config.Inputs { irodsPath := stepInput.IRODSPath() @@ -66,7 +103,7 @@ func (i *Internal) getInputPathMappings(job *model.Job) ([]IRODSFSPathMapping, e return nil, fmt.Errorf("unknown step input type - %s", stepInput.Type) } - mountPath := fmt.Sprintf("%s/%s", csiDriverInputVolumeMountPath, filepath.Base(irodsPath)) + mountPath := fmt.Sprintf("/%s", filepath.Base(irodsPath)) // check if mountPath is already used by other input if existingIRODSPath, ok := mappingMap[mountPath]; ok { // exists - error @@ -94,11 +131,11 @@ func (i *Internal) getOutputPathMapping(job *model.Job) IRODSFSPathMapping { // mount a single collection for output return IRODSFSPathMapping{ IRODSPath: job.OutputDirectory(), - MappingPath: csiDriverOutputVolumeMountPath, + MappingPath: "/", ResourceType: "dir", ReadOnly: false, CreateDir: true, - IgnoreNotExistError: false, + IgnoreNotExistError: true, } } @@ -106,11 +143,11 @@ func (i *Internal) getHomePathMapping(job *model.Job) IRODSFSPathMapping { // mount a single collection for home return IRODSFSPathMapping{ IRODSPath: job.UserHome, - MappingPath: job.UserHome, + MappingPath: "/", ResourceType: "dir", ReadOnly: false, CreateDir: false, - IgnoreNotExistError: false, + IgnoreNotExistError: true, } } @@ -120,7 +157,7 @@ func (i *Internal) getSharedPathMapping(job *model.Job) IRODSFSPathMapping { return IRODSFSPathMapping{ IRODSPath: sharedHomeFullPath, - MappingPath: sharedHomeFullPath, + MappingPath: "/", ResourceType: "dir", ReadOnly: false, CreateDir: false, @@ -128,90 +165,317 @@ func (i *Internal) getSharedPathMapping(job *model.Job) IRODSFSPathMapping { } } -func (i *Internal) getCSIDataVolumeLabels(ctx context.Context, job *model.Job) (map[string]string, error) { +func (i *Internal) getCSIInputVolumeLabels(ctx context.Context, job *model.Job) (map[string]string, error) { labels, err := i.labelsFromJob(ctx, job) if err != nil { return nil, err } - labels["volume-name"] = i.getCSIDataVolumeName(job) + labels["volume-name"] = i.getCSIInputVolumeName(job) return labels, nil } +func (i *Internal) getCSIOutputVolumeLabels(ctx context.Context, job *model.Job) (map[string]string, error) { + labels, err := i.labelsFromJob(ctx, job) + if err != nil { + return nil, err + } + + labels["volume-name"] = i.getCSIOutputVolumeName(job) + return labels, nil +} + +func (i *Internal) getCSIHomeVolumeLabels(ctx context.Context, job *model.Job) (map[string]string, error) { + labels, err := i.labelsFromJob(ctx, job) + if err != nil { + return nil, err + } + + labels["volume-name"] = i.getCSIHomeVolumeName(job) + return labels, nil +} + +func (i *Internal) getCSISharedVolumeLabels(ctx context.Context, job *model.Job) (map[string]string, error) { + labels, err := i.labelsFromJob(ctx, job) + if err != nil { + return nil, err + } + + labels["volume-name"] = i.getCSISharedVolumeName(job) + return labels, nil +} + +func (i *Internal) getCSIPersistentVolume(volumeName string, volumeHandle string, pathMappings []IRODSFSPathMapping, labels map[string]string, clientUser string, uid int, gid int, overlayfs bool) (*apiv1.PersistentVolume, error) { + // convert path mappings into json + pathMappingsJSONBytes, err := json.Marshal(pathMappings) + if err != nil { + return nil, err + } + + volmode := apiv1.PersistentVolumeFilesystem + + overlayfsString := "false" + if overlayfs { + overlayfsString = "true" + } + + volume := &apiv1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: volumeName, + Labels: labels, + }, + Spec: apiv1.PersistentVolumeSpec{ + Capacity: apiv1.ResourceList{ + apiv1.ResourceStorage: defaultStorageCapacity, + }, + VolumeMode: &volmode, + AccessModes: []apiv1.PersistentVolumeAccessMode{ + apiv1.ReadWriteMany, + }, + PersistentVolumeReclaimPolicy: apiv1.PersistentVolumeReclaimRetain, + StorageClassName: csiDriverStorageClassName, + PersistentVolumeSource: apiv1.PersistentVolumeSource{ + CSI: &apiv1.CSIPersistentVolumeSource{ + Driver: csiDriverName, + VolumeHandle: volumeHandle, + VolumeAttributes: map[string]string{ + "client": "irodsfuse", + "path_mapping_json": string(pathMappingsJSONBytes), + "no_permission_check": "true", + // use proxy access + "clientUser": clientUser, + "uid": fmt.Sprintf("%d", uid), + "gid": fmt.Sprintf("%d", gid), + "overlayfs": overlayfsString, + }, + }, + }, + }, + } + + return volume, nil +} + +func (i *Internal) getCSIPersistentVolumeClaim(volumeName string, volumeClaimName string, labels map[string]string) (*apiv1.PersistentVolumeClaim, error) { + storageclassname := csiDriverStorageClassName + + volumeClaim := &apiv1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: volumeClaimName, + Labels: labels, + }, + Spec: apiv1.PersistentVolumeClaimSpec{ + AccessModes: []apiv1.PersistentVolumeAccessMode{ + apiv1.ReadWriteMany, + }, + StorageClassName: &storageclassname, + VolumeName: volumeName, + Resources: apiv1.ResourceRequirements{ + Requests: apiv1.ResourceList{ + apiv1.ResourceStorage: defaultStorageCapacity, + }, + }, + }, + } + + return volumeClaim, nil +} + +func (i *Internal) getInputPersistentVolume(ctx context.Context, job *model.Job) (*apiv1.PersistentVolume, error) { + volumeName := i.getCSIInputVolumeName(job) + volumeHandle := i.getCSIInputVolumeHandle(job) + + pathMappings, err := i.getInputPathMappings(job) + if err != nil { + return nil, err + } + + labels, err := i.getCSIInputVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + volume, err := i.getCSIPersistentVolume(volumeName, volumeHandle, pathMappings, labels, job.Submitter, job.Steps[0].Component.Container.UID, job.Steps[0].Component.Container.UID, false) + if err != nil { + return nil, err + } + + return volume, nil +} + +func (i *Internal) getInputPersistentVolumeClaim(ctx context.Context, job *model.Job) (*apiv1.PersistentVolumeClaim, error) { + volumeName := i.getCSIInputVolumeName(job) + volumeClaimName := i.getCSIInputVolumeClaimName(job) + + labels, err := i.getCSIInputVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + claim, err := i.getCSIPersistentVolumeClaim(volumeName, volumeClaimName, labels) + if err != nil { + return nil, err + } + + return claim, nil +} + +func (i *Internal) getOutputPersistentVolume(ctx context.Context, job *model.Job) (*apiv1.PersistentVolume, error) { + volumeName := i.getCSIOutputVolumeName(job) + volumeHandle := i.getCSIOutputVolumeHandle(job) + + pathMappings := []IRODSFSPathMapping{} + + pathMapping := i.getOutputPathMapping(job) + pathMappings = append(pathMappings, pathMapping) + + labels, err := i.getCSIOutputVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + volume, err := i.getCSIPersistentVolume(volumeName, volumeHandle, pathMappings, labels, job.Submitter, job.Steps[0].Component.Container.UID, job.Steps[0].Component.Container.UID, true) + if err != nil { + return nil, err + } + + return volume, nil +} + +func (i *Internal) getOutputPersistentVolumeClaim(ctx context.Context, job *model.Job) (*apiv1.PersistentVolumeClaim, error) { + volumeName := i.getCSIOutputVolumeName(job) + volumeClaimName := i.getCSIOutputVolumeClaimName(job) + + labels, err := i.getCSIOutputVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + claim, err := i.getCSIPersistentVolumeClaim(volumeName, volumeClaimName, labels) + if err != nil { + return nil, err + } + + return claim, nil +} + +func (i *Internal) getHomePersistentVolume(ctx context.Context, job *model.Job) (*apiv1.PersistentVolume, error) { + volumeName := i.getCSIHomeVolumeName(job) + volumeHandle := i.getCSIHomeVolumeHandle(job) + + pathMappings := []IRODSFSPathMapping{} + + pathMapping := i.getHomePathMapping(job) + pathMappings = append(pathMappings, pathMapping) + + labels, err := i.getCSIHomeVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + volume, err := i.getCSIPersistentVolume(volumeName, volumeHandle, pathMappings, labels, job.Submitter, job.Steps[0].Component.Container.UID, job.Steps[0].Component.Container.UID, true) + if err != nil { + return nil, err + } + + return volume, nil +} + +func (i *Internal) getHomePersistentVolumeClaim(ctx context.Context, job *model.Job) (*apiv1.PersistentVolumeClaim, error) { + volumeName := i.getCSIHomeVolumeName(job) + volumeClaimName := i.getCSIHomeVolumeClaimName(job) + + labels, err := i.getCSIHomeVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + claim, err := i.getCSIPersistentVolumeClaim(volumeName, volumeClaimName, labels) + if err != nil { + return nil, err + } + + return claim, nil +} + +func (i *Internal) getSharedPersistentVolume(ctx context.Context, job *model.Job) (*apiv1.PersistentVolume, error) { + volumeName := i.getCSISharedVolumeName(job) + volumeHandle := i.getCSISharedVolumeHandle(job) + + pathMappings := []IRODSFSPathMapping{} + + pathMapping := i.getSharedPathMapping(job) + pathMappings = append(pathMappings, pathMapping) + + labels, err := i.getCSISharedVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + volume, err := i.getCSIPersistentVolume(volumeName, volumeHandle, pathMappings, labels, job.Submitter, job.Steps[0].Component.Container.UID, job.Steps[0].Component.Container.UID, false) + if err != nil { + return nil, err + } + + return volume, nil +} + +func (i *Internal) getSharedPersistentVolumeClaim(ctx context.Context, job *model.Job) (*apiv1.PersistentVolumeClaim, error) { + volumeName := i.getCSISharedVolumeName(job) + volumeClaimName := i.getCSISharedVolumeClaimName(job) + + labels, err := i.getCSISharedVolumeLabels(ctx, job) + if err != nil { + return nil, err + } + + claim, err := i.getCSIPersistentVolumeClaim(volumeName, volumeClaimName, labels) + if err != nil { + return nil, err + } + + return claim, nil +} + // getPersistentVolumes returns the PersistentVolumes for the VICE analysis. It does // not call the k8s API. func (i *Internal) getPersistentVolumes(ctx context.Context, job *model.Job) ([]*apiv1.PersistentVolume, error) { if i.UseCSIDriver { - dataPathMappings := []IRODSFSPathMapping{} + persistentVolumes := []*apiv1.PersistentVolume{} - // input output path - inputPathMappings, err := i.getInputPathMappings(job) + // input volume + inputVolume, err := i.getInputPersistentVolume(ctx, job) if err != nil { return nil, err } - dataPathMappings = append(dataPathMappings, inputPathMappings...) - - outputPathMapping := i.getOutputPathMapping(job) - dataPathMappings = append(dataPathMappings, outputPathMapping) - - // home path - if job.UserHome != "" { - homePathMapping := i.getHomePathMapping(job) - dataPathMappings = append(dataPathMappings, homePathMapping) - } - // shared path - sharedPathMapping := i.getSharedPathMapping(job) - dataPathMappings = append(dataPathMappings, sharedPathMapping) + persistentVolumes = append(persistentVolumes, inputVolume) - // convert path mappings into json - dataPathMappingsJSONBytes, err := json.Marshal(dataPathMappings) + // output volume + outputVolume, err := i.getOutputPersistentVolume(ctx, job) if err != nil { return nil, err } - volmode := apiv1.PersistentVolumeFilesystem - persistentVolumes := []*apiv1.PersistentVolume{} + persistentVolumes = append(persistentVolumes, outputVolume) - dataVolumeLabels, err := i.getCSIDataVolumeLabels(ctx, job) - if err != nil { - return nil, err + // home path + if job.UserHome != "" { + homeVolume, err := i.getHomePersistentVolume(ctx, job) + if err != nil { + return nil, err + } + + persistentVolumes = append(persistentVolumes, homeVolume) } - dataVolume := &apiv1.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: i.getCSIDataVolumeName(job), - Labels: dataVolumeLabels, - }, - Spec: apiv1.PersistentVolumeSpec{ - Capacity: apiv1.ResourceList{ - apiv1.ResourceStorage: defaultStorageCapacity, - }, - VolumeMode: &volmode, - AccessModes: []apiv1.PersistentVolumeAccessMode{ - apiv1.ReadWriteMany, - }, - PersistentVolumeReclaimPolicy: apiv1.PersistentVolumeReclaimRetain, - StorageClassName: csiDriverStorageClassName, - PersistentVolumeSource: apiv1.PersistentVolumeSource{ - CSI: &apiv1.CSIPersistentVolumeSource{ - Driver: csiDriverName, - VolumeHandle: i.getCSIDataVolumeHandle(job), - VolumeAttributes: map[string]string{ - "client": "irodsfuse", - "path_mapping_json": string(dataPathMappingsJSONBytes), - "no_permission_check": "true", - // use proxy access - "clientUser": job.Submitter, - "uid": fmt.Sprintf("%d", job.Steps[0].Component.Container.UID), - "gid": fmt.Sprintf("%d", job.Steps[0].Component.Container.UID), - }, - }, - }, - }, + // shared path + sharedVolume, err := i.getSharedPersistentVolume(ctx, job) + if err != nil { + return nil, err } - persistentVolumes = append(persistentVolumes, dataVolume) + persistentVolumes = append(persistentVolumes, sharedVolume) return persistentVolumes, nil } @@ -222,35 +486,43 @@ func (i *Internal) getPersistentVolumes(ctx context.Context, job *model.Job) ([] // not call the k8s API. func (i *Internal) getPersistentVolumeClaims(ctx context.Context, job *model.Job) ([]*apiv1.PersistentVolumeClaim, error) { if i.UseCSIDriver { - labels, err := i.labelsFromJob(ctx, job) + persistentVolumeClaims := []*apiv1.PersistentVolumeClaim{} + + // input volume + inputVolumeClaim, err := i.getInputPersistentVolumeClaim(ctx, job) if err != nil { return nil, err } - storageclassname := csiDriverStorageClassName - volumeClaims := []*apiv1.PersistentVolumeClaim{} + persistentVolumeClaims = append(persistentVolumeClaims, inputVolumeClaim) - dataVolumeClaim := &apiv1.PersistentVolumeClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: i.getCSIDataVolumeClaimName(job), - Labels: labels, - }, - Spec: apiv1.PersistentVolumeClaimSpec{ - AccessModes: []apiv1.PersistentVolumeAccessMode{ - apiv1.ReadWriteMany, - }, - StorageClassName: &storageclassname, - VolumeName: i.getCSIDataVolumeName(job), - Resources: apiv1.ResourceRequirements{ - Requests: apiv1.ResourceList{ - apiv1.ResourceStorage: defaultStorageCapacity, - }, - }, - }, + // output volume + outputVolumeClaim, err := i.getOutputPersistentVolumeClaim(ctx, job) + if err != nil { + return nil, err } - volumeClaims = append(volumeClaims, dataVolumeClaim) - return volumeClaims, nil + persistentVolumeClaims = append(persistentVolumeClaims, outputVolumeClaim) + + // home path + if job.UserHome != "" { + homeVolumeClaim, err := i.getHomePersistentVolumeClaim(ctx, job) + if err != nil { + return nil, err + } + + persistentVolumeClaims = append(persistentVolumeClaims, homeVolumeClaim) + } + + // shared path + sharedVolumeClaim, err := i.getSharedPersistentVolumeClaim(ctx, job) + if err != nil { + return nil, err + } + + persistentVolumeClaims = append(persistentVolumeClaims, sharedVolumeClaim) + + return persistentVolumeClaims, nil } return nil, nil @@ -262,16 +534,48 @@ func (i *Internal) getPersistentVolumeSources(job *model.Job) ([]*apiv1.Volume, if i.UseCSIDriver { volumes := []*apiv1.Volume{} - dataVolume := &apiv1.Volume{ - Name: i.getCSIDataVolumeClaimName(job), + inputVolume := &apiv1.Volume{ + Name: i.getCSIInputVolumeClaimName(job), VolumeSource: apiv1.VolumeSource{ PersistentVolumeClaim: &apiv1.PersistentVolumeClaimVolumeSource{ - ClaimName: i.getCSIDataVolumeClaimName(job), + ClaimName: i.getCSIInputVolumeClaimName(job), }, }, } + volumes = append(volumes, inputVolume) + + outputVolume := &apiv1.Volume{ + Name: i.getCSIOutputVolumeClaimName(job), + VolumeSource: apiv1.VolumeSource{ + PersistentVolumeClaim: &apiv1.PersistentVolumeClaimVolumeSource{ + ClaimName: i.getCSIOutputVolumeClaimName(job), + }, + }, + } + volumes = append(volumes, outputVolume) + + if job.UserHome != "" { + homeVolume := &apiv1.Volume{ + Name: i.getCSIHomeVolumeClaimName(job), + VolumeSource: apiv1.VolumeSource{ + PersistentVolumeClaim: &apiv1.PersistentVolumeClaimVolumeSource{ + ClaimName: i.getCSIHomeVolumeClaimName(job), + }, + }, + } + volumes = append(volumes, homeVolume) + } + + sharedVolume := &apiv1.Volume{ + Name: i.getCSISharedVolumeClaimName(job), + VolumeSource: apiv1.VolumeSource{ + PersistentVolumeClaim: &apiv1.PersistentVolumeClaimVolumeSource{ + ClaimName: i.getCSISharedVolumeClaimName(job), + }, + }, + } + volumes = append(volumes, sharedVolume) - volumes = append(volumes, dataVolume) return volumes, nil } @@ -284,12 +588,31 @@ func (i *Internal) getPersistentVolumeMounts(job *model.Job) []*apiv1.VolumeMoun if i.UseCSIDriver { volumeMounts := []*apiv1.VolumeMount{} - dataVolumeMount := &apiv1.VolumeMount{ - Name: i.getCSIDataVolumeClaimName(job), - MountPath: csiDriverLocalMountPath, + inputVolumeMount := &apiv1.VolumeMount{ + Name: i.getCSIInputVolumeClaimName(job), + MountPath: path.Join(csiDriverLocalMountPath, "input"), } + volumeMounts = append(volumeMounts, inputVolumeMount) - volumeMounts = append(volumeMounts, dataVolumeMount) + outputVolumeMount := &apiv1.VolumeMount{ + Name: i.getCSIOutputVolumeClaimName(job), + MountPath: path.Join(csiDriverLocalMountPath, "output"), + } + volumeMounts = append(volumeMounts, outputVolumeMount) + + if job.UserHome != "" { + homeVolumeMount := &apiv1.VolumeMount{ + Name: i.getCSIHomeVolumeClaimName(job), + MountPath: path.Join(csiDriverLocalMountPath, job.UserHome), + } + volumeMounts = append(volumeMounts, homeVolumeMount) + } + + sharedVolumeMount := &apiv1.VolumeMount{ + Name: i.getCSISharedVolumeClaimName(job), + MountPath: path.Join(csiDriverLocalMountPath, "home", "shared"), + } + volumeMounts = append(volumeMounts, sharedVolumeMount) return volumeMounts }