Skip to content

Commit

Permalink
Add PVC Provisioning Job
Browse files Browse the repository at this point in the history
  • Loading branch information
AleTopp authored and kingmakerbot committed Feb 12, 2025
1 parent 355149b commit 26f16a3
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
7 changes: 7 additions & 0 deletions operators/pkg/forge/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,17 @@ const (
InstanceSubmissionSelectorLabel = "crownlabs.polito.it/instance-submission-requested"
// InstanceSubmissionCompletedLabel -> label for Instances that have been submitted.
InstanceSubmissionCompletedLabel = "crownlabs.polito.it/instance-submission-completed"
// ProvisionJobLabel -> Key of the label added by the Provision Job to flag the Tenant's MyDrive PVC.
ProvisionJobLabel = "crownlabs.polito.it/mydrive-provisioning"

labelManagedByInstanceValue = "instance"
labelManagedByTenantValue = "tenant"
labelTypeSandboxValue = "sandbox"

// ProvisionJobValueOk -> Value of the label added by the Provision Job to flag the PVC when everything worked fine.
ProvisionJobValueOk = "completed"
// ProvisionJobValuePending -> Value of the label added by the Provision Job to flag the PVC when it hasn't completed yet.
ProvisionJobValuePending = "pending"
)

// InstanceLabels receives in input a set of labels and returns the updated set depending on the specified template,
Expand Down
80 changes: 80 additions & 0 deletions operators/pkg/tenant-controller/tenant_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"strings"
"time"

batchv1 "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
netv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
Expand All @@ -30,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -53,6 +55,12 @@ const (
NFSSecretServerNameKey = "server-name"
// NFSSecretPathKey -> NFS path key in NFS secret.
NFSSecretPathKey = "path"
// ProvisionJobBaseImage -> Base container image for Personal Drive provision job.
ProvisionJobBaseImage = "busybox"
// ProvisionJobMaxRetries -> Maximum number of retries for Provision jobs.
ProvisionJobMaxRetries = 3
// ProvisionJobTTLSeconds -> Seconds for Provision jobs before deletion (either failure or success).
ProvisionJobTTLSeconds = 3600 * 24 * 7
)

// TenantReconciler reconciles a Tenant object.
Expand Down Expand Up @@ -243,6 +251,7 @@ func (r *TenantReconciler) SetupWithManager(mgr ctrl.Manager) error {
Owns(&rbacv1.ClusterRole{}).
Owns(&rbacv1.ClusterRoleBinding{}).
Owns(&netv1.NetworkPolicy{}).
Owns(&batchv1.Job{}).
Watches(&crownlabsv1alpha1.Workspace{},
handler.EnqueueRequestsFromMapFunc(r.workspaceToEnrolledTenants)).
WithOptions(controller.Options{
Expand Down Expand Up @@ -517,6 +526,39 @@ func (r *TenantReconciler) createOrUpdateTnPersonalNFSVolume(ctx context.Context
return err
}
klog.Infof("PVC Secret for tenant %s %s", tn.Name, pvcSecOpRes)

val, found := pvc.Labels[forge.ProvisionJobLabel]
if !found || val != forge.ProvisionJobValueOk {
chownJob := batchv1.Job{ObjectMeta: metav1.ObjectMeta{Name: pvc.Name + "-provision", Namespace: pvc.Namespace}}
labelToSet := forge.ProvisionJobValuePending

chownJobOpRes, err := ctrl.CreateOrUpdate(ctx, r.Client, &chownJob, func() error {
if chownJob.CreationTimestamp.IsZero() {
klog.Infof("PVC Provisioning Job created for tenant %s", tn.Name)
r.updateTnProvisioningJob(&chownJob, &pvc)
} else if found && val == forge.ProvisionJobValuePending {
if chownJob.Status.Succeeded == 1 {
labelToSet = forge.ProvisionJobValueOk
klog.Infof("PVC Provisioning Job completed for tenant %s", tn.Name)
} else if chownJob.Status.Failed == 1 {
klog.Warningf("PVC Provisioning Job failed for tenant %s", tn.Name)
}
}

return ctrl.SetControllerReference(tn, &chownJob, r.Scheme)
})
if err != nil {
klog.Errorf("Unable to create or update PVC Provisioning Job for tenant %s -> %s", tn.Name, err)
return err
}
klog.Infof("PVC Provisioning Job for tenant %s %s", tn.Name, chownJobOpRes)

pvc.Labels[forge.ProvisionJobLabel] = labelToSet
if err := r.Update(ctx, &pvc); err != nil {
klog.Errorf("PVC Provisioning Job failed to update PVC labels for tenant %s", tn.Name)
}
klog.Infof("PVC Provisioning Job updateded PVC label to %s for tenant %s", labelToSet, tn.Name)
}
} else if pvc.Status.Phase == v1.ClaimPending {
klog.Infof("PVC pending for tenant %s", tn.Name)
}
Expand Down Expand Up @@ -576,6 +618,44 @@ func (r *TenantReconciler) updateTnPersistentVolumeClaim(pvc *v1.PersistentVolum
pvc.Spec.StorageClassName = &scName
}

func (r *TenantReconciler) updateTnProvisioningJob(chownJob *batchv1.Job, pvc *v1.PersistentVolumeClaim) {
if chownJob.CreationTimestamp.IsZero() {
chownJob.Spec.BackoffLimit = ptr.To[int32](ProvisionJobMaxRetries)
chownJob.Spec.TTLSecondsAfterFinished = ptr.To[int32](ProvisionJobTTLSeconds)
chownJob.Spec.Template.Spec.RestartPolicy = v1.RestartPolicyOnFailure
chownJob.Spec.Template.Spec.Containers = []v1.Container{{
Name: "chown-container",
Image: ProvisionJobBaseImage,
Command: []string{"chown", "-R", fmt.Sprintf("%d:%d", forge.CrownLabsUserID, forge.CrownLabsUserID), forge.MyDriveVolumeMountPath},
VolumeMounts: []v1.VolumeMount{{
Name: "mydrive",
MountPath: forge.MyDriveVolumeMountPath,
},
},
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
"cpu": resource.MustParse("100m"),
"memory": resource.MustParse("128Mi"),
},
Limits: v1.ResourceList{
"cpu": resource.MustParse("100m"),
"memory": resource.MustParse("128Mi"),
},
},
},
}
chownJob.Spec.Template.Spec.Volumes = []v1.Volume{{
Name: "mydrive",
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: pvc.Name,
},
},
},
}
}
}

func (r *TenantReconciler) handleKeycloakSubscription(ctx context.Context, tn *crownlabsv1alpha2.Tenant, tenantExistingWorkspaces []crownlabsv1alpha2.TenantWorkspaceEntry) error {
// KcA could be nil for local testing skipping the keycloak subscription
if r.KcA == nil {
Expand Down

0 comments on commit 26f16a3

Please sign in to comment.