LabManager¶
- class controller.services.lab.LabManager(*, config, image_service, lab_builder, metadata_storage, lab_storage, slack_client, logger)¶
Bases:
object
Manage user labs.
The lab manager is a process singleton that manages user labs. This includes spawning them, deleting them, and tracking their state.
- Parameters:
config (
LabConfig
) – Configuration for user labs.image_service (
ImageService
) – Tracks all available images and resolves the parameters of a request for a new lab to a specific Docker image.lab_builder (
LabBuilder
) – Builder for Kubernetes lab objects.metadata_storage (
MetadataStorage
) – Storage for metadata about the running controller.lab_storage (
LabStorage
) – Kubernetes storage layer for user labs.slack_client (
SlackWebhookClient
|None
) – Optional Slack webhook client for alerts.logger (
BoundLogger
) – Logger to use.
Methods Summary
create_lab
(user, spec)Schedules creation of user lab objects/resources.
delete_lab
(username)Delete the lab environment for the given user.
events_for_user
(username)Construct an iterator over the events for a user.
get_lab_state
(username)Get lab state for a user.
list_lab_users
(*[, only_running])List all users with labs.
Wait for spawner tasks to complete and record their status.
Reconcile user lab state with Kubernetes.
Stop any tasks that are waiting for labs to spawn.
Methods Documentation
- async create_lab(user, spec)¶
Schedules creation of user lab objects/resources.
- Parameters:
user (
GafaelfawrUser
) – User for whom the lab is being created.spec (
LabSpecification
) – Specification for lab to spawn.
- Raises:
InvalidDockerReferenceError – Raised if the Docker image reference in the lab specification is invalid.
InvalidLabSizeError – Raised if the requested lab size is not one of the configured sizes.
LabExistsError – Raised if this user already has a lab.
OperationConflictError – Raised if some other operation (either spawn or delete) is already in progress on this user’s lab.
- Return type:
- async delete_lab(username)¶
Delete the lab environment for the given user.
This may be called multiple times for the same user, and all deletions will wait for the same underlying Kubernetes operation.
- Parameters:
username (
str
) – Username whose environment should be deleted.- Raises:
LabDeletionError – Raised if the lab deletion failed for any other reason.
OperationConflictError – Raised if another operation is already in progress.
UnknownUserError – Raised if no lab currently exists for this user.
- Return type:
- events_for_user(username)¶
Construct an iterator over the events for a user.
- Parameters:
username (
str
) – Username for which to retrieve events.- Yields:
bytes – Next encoded server-sent event.
- Raises:
UnknownUserError – Raised if there is no event stream for this user.
- Return type:
- async get_lab_state(username)¶
Get lab state for a user.
This method underlies the API called by JupyterHub to track whether the user’s lab still exists. We want to update that state after Kubernetes changes faster than our reconciliation cycle, so ask Kubernetes directly for the pod phase each time we’re asked for the lab state.
- Parameters:
username (
str
) – Username to retrieve lab state for.- Returns:
Lab state for that user, or
None
if that user doesn’t have a lab.- Return type:
LabState or None
- Raises:
UnknownUserError – Raised if the given user has no lab.
- async list_lab_users(*, only_running=False)¶
List all users with labs.
- async reap_spawners()¶
Wait for spawner tasks to complete and record their status.
When a user spawns a lab, the lab controller creates a background task to create the Kubernetes objects and then wait for the pod to finish starting. Something needs to await those tasks so that they can be cleanly finalized and to catch any uncaught exceptions. That function is performed by a background task running this method.
This method is also responsible for updating the last modified time in the lab state.
- Return type:
Notes
Doing this properly is a bit tricky, since we have to avoid both busy-waiting when no operations are in progress and not reaping anything if one operation keeps running forever. The approach used here is to have every spawn set the
_spawner_done
asyncio.Event
when it is complete, and use that as a trigger for doing a reaper pass. Deletes do not do this since they’re normally awaited by the caller and thus don’t need to be reaped separately.
- async reconcile()¶
Reconcile user lab state with Kubernetes.
This method is called on startup and then periodically from a background thread to check Kubernetes and ensure the in-memory record of the user’s lab state matches reality. On startup, it also needs to recreate the internal state from the contents of Kubernetes.
- Raises:
KubernetesError – Raised if there is some failure in a Kubernetes API call.
- Return type: