Skip to content

Commit

Permalink
feat: use cloud storage from amalthea (#387)
Browse files Browse the repository at this point in the history
Co-authored-by: Samuel Gaist <samuel.gaist@idiap.ch>
  • Loading branch information
olevski and sgaist authored Sep 27, 2024
1 parent a45bec2 commit 689585b
Show file tree
Hide file tree
Showing 19 changed files with 225 additions and 126 deletions.
2 changes: 2 additions & 0 deletions bases/renku_data_services/data_api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def register_all_handlers(app: Sanic, config: Config) -> Sanic:
nb_config=config.nb_config,
internal_gitlab_authenticator=config.gitlab_authenticator,
git_repo=config.git_repositories_repo,
rp_repo=config.rp_repo,
)
notebooks_new = NotebooksNewBP(
name="notebooks",
Expand All @@ -150,6 +151,7 @@ def register_all_handlers(app: Sanic, config: Config) -> Sanic:
nb_config=config.nb_config,
project_repo=config.project_repo,
session_repo=config.session_repo,
storage_repo=config.storage_v2_repo,
rp_repo=config.rp_repo,
internal_gitlab_authenticator=config.gitlab_authenticator,
)
Expand Down
3 changes: 2 additions & 1 deletion components/renku_data_services/notebooks/api.spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1022,11 +1022,12 @@ components:
storage_id:
allOf:
- "$ref": "#/components/schemas/Ulid"
- description: If the storage_id is provided then this config must replace an existing storage config in the session
- description: The storage ID is used to know which storage config from the DB should be overriden
required:
- configuration
- source_path
- target_path
- storage_id
ServerName:
type: string
minLength: 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async def main(server: "UserServer") -> list[dict[str, Any]]:
commit_sha = getattr(server, "commit_sha", None)

volume_mount = {
"mountPath": server.work_dir.absolute().as_posix(),
"mountPath": server.work_dir.as_posix(),
"name": "workspace",
}
if gl_project_path:
Expand Down Expand Up @@ -51,7 +51,7 @@ async def main(server: "UserServer") -> list[dict[str, Any]]:
"env": [
{
"name": "GIT_RPC_MOUNT_PATH",
"value": server.work_dir.absolute().as_posix(),
"value": server.work_dir.as_posix(),
},
{
"name": "GIT_RPC_PORT",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ async def git_clone_container_v2(server: "UserServer") -> dict[str, Any] | None:
env = [
{
"name": f"{prefix}WORKSPACE_MOUNT_PATH",
"value": server.workspace_mount_path.absolute().as_posix(),
"value": server.workspace_mount_path.as_posix(),
},
{
"name": f"{prefix}MOUNT_PATH",
"value": server.work_dir.absolute().as_posix(),
"value": server.work_dir.as_posix(),
},
{
"name": f"{prefix}LFS_AUTO_FETCH",
Expand Down Expand Up @@ -134,7 +134,7 @@ async def git_clone_container_v2(server: "UserServer") -> dict[str, Any] | None:
},
"volumeMounts": [
{
"mountPath": server.workspace_mount_path.absolute().as_posix(),
"mountPath": server.workspace_mount_path.as_posix(),
"name": amalthea_session_work_volume,
},
*etc_cert_volume_mount,
Expand All @@ -161,11 +161,11 @@ async def git_clone_container(server: "UserServer") -> dict[str, Any] | None:
env = [
{
"name": f"{prefix}WORKSPACE_MOUNT_PATH",
"value": server.workspace_mount_path.absolute().as_posix(),
"value": server.workspace_mount_path.as_posix(),
},
{
"name": f"{prefix}MOUNT_PATH",
"value": server.work_dir.absolute().as_posix(),
"value": server.work_dir.as_posix(),
},
{
"name": f"{prefix}LFS_AUTO_FETCH",
Expand Down Expand Up @@ -260,7 +260,7 @@ async def git_clone_container(server: "UserServer") -> dict[str, Any] | None:
},
"volumeMounts": [
{
"mountPath": server.workspace_mount_path.absolute().as_posix(),
"mountPath": server.workspace_mount_path.as_posix(),
"name": "workspace",
},
*etc_cert_volume_mount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def env(server: "UserServer") -> list[dict[str, Any]]:
"path": "/statefulset/spec/template/spec/containers/0/env/-",
"value": {
"name": "NOTEBOOK_DIR",
"value": server.work_dir.absolute().as_posix(),
"value": server.work_dir.as_posix(),
},
},
{
Expand All @@ -53,7 +53,7 @@ def env(server: "UserServer") -> list[dict[str, Any]]:
# relative to $HOME.
"value": {
"name": "MOUNT_PATH",
"value": server.work_dir.absolute().as_posix(),
"value": server.work_dir.as_posix(),
},
},
{
Expand Down Expand Up @@ -223,7 +223,7 @@ def rstudio_env_variables(server: "UserServer") -> list[dict[str, Any]]:
"path": "/statefulset/spec/template/spec/containers/0/volumeMounts/-",
"value": {
"name": secret_name,
"mountPath": mount_location.absolute().as_posix(),
"mountPath": mount_location.as_posix(),
"subPath": mount_location.name,
"readOnly": True,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@
class ICloudStorageRequest(Protocol):
"""The abstract class for cloud storage."""

exists: bool
mount_folder: str
source_folder: str
bucket: str
source_path: str

def get_manifest_patch(
self,
base_name: str,
namespace: str,
labels: dict[str, str] = {},
annotations: dict[str, str] = {},
labels: dict[str, str] | None = None,
annotations: dict[str, str] | None = None,
) -> list[dict[str, Any]]:
"""The patches applied to a jupyter server to insert the storage in the session."""
...
6 changes: 3 additions & 3 deletions components/renku_data_services/notebooks/api/classes/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import re
from dataclasses import dataclass, field
from enum import Enum
from pathlib import Path
from pathlib import PurePosixPath
from typing import Any, Optional, Self, cast

import requests
Expand Down Expand Up @@ -101,7 +101,7 @@ def get_image_config(self, image: "Image") -> Optional[dict[str, Any]]:
return None
return cast(dict[str, Any], res.json())

def image_workdir(self, image: "Image") -> Optional[Path]:
def image_workdir(self, image: "Image") -> Optional[PurePosixPath]:
"""Query the docker API to get the workdir of an image."""
config = self.get_image_config(image)
if config is None:
Expand All @@ -112,7 +112,7 @@ def image_workdir(self, image: "Image") -> Optional[Path]:
workdir = nested_config.get("WorkingDir", "/")
if workdir == "":
workdir = "/"
return Path(workdir)
return PurePosixPath(workdir)

def with_oauth2_token(self, oauth2_token: str) -> "ImageRepoDockerAPI":
"""Return a docker API instance with the token as authentication."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,13 @@ def __init__(self, url: str, server_type: type[_SessionType]):
self.url = url
self.client = httpx.AsyncClient()
self.server_type: type[_SessionType] = server_type
self.url_path_name = "servers"
if server_type == AmaltheaSessionV1Alpha1:
self.url_path_name = "sessions"

async def list_servers(self, safe_username: str) -> list[_SessionType]:
"""List the jupyter servers."""
url = urljoin(self.url, f"/users/{safe_username}/servers")
url = urljoin(self.url, f"/users/{safe_username}/{self.url_path_name}")
try:
res = await self.client.get(url, timeout=10)
except httpx.RequestError as err:
Expand All @@ -374,7 +377,7 @@ async def list_servers(self, safe_username: str) -> list[_SessionType]:

async def get_server(self, name: str) -> _SessionType | None:
"""Get a specific jupyter server."""
url = urljoin(self.url, f"/servers/{name}")
url = urljoin(self.url, f"/{self.url_path_name}/{name}")
try:
res = await self.client.get(url, timeout=10)
except httpx.RequestError as err:
Expand Down Expand Up @@ -487,10 +490,9 @@ async def delete_server(self, server_name: str, safe_username: str) -> None:
"""Delete the server."""
server = await self.get_server(server_name, safe_username)
if not server:
raise MissingResourceError(
f"Cannot find server {server_name} for user " f"{safe_username} in order to delete it."
)
return await self.renku_ns_client.delete_server(server_name)
return None
await self.renku_ns_client.delete_server(server_name)
return None

async def patch_tokens(self, server_name: str, renku_tokens: RenkuTokens, gitlab_token: GitlabToken) -> None:
"""Patch the Renku and Gitlab access tokens used in a session."""
Expand Down
20 changes: 10 additions & 10 deletions components/renku_data_services/notebooks/api/classes/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from abc import ABC
from collections.abc import Sequence
from itertools import chain
from pathlib import Path
from pathlib import PurePosixPath
from typing import Any
from urllib.parse import urljoin, urlparse

Expand Down Expand Up @@ -44,8 +44,8 @@ def __init__(
user_secrets: K8sUserSecrets | None,
cloudstorage: Sequence[ICloudStorageRequest],
k8s_client: K8sClient,
workspace_mount_path: Path,
work_dir: Path,
workspace_mount_path: PurePosixPath,
work_dir: PurePosixPath,
config: _NotebooksConfig,
internal_gitlab_user: APIUser,
using_default_image: bool = False,
Expand Down Expand Up @@ -205,7 +205,7 @@ async def _get_session_manifest(self) -> dict[str, Any]:
"pvc": {
"enabled": True,
"storageClassName": self.config.sessions.storage.pvs_storage_class,
"mountPath": self.workspace_mount_path.absolute().as_posix(),
"mountPath": self.workspace_mount_path.as_posix(),
},
}
else:
Expand All @@ -214,7 +214,7 @@ async def _get_session_manifest(self) -> dict[str, Any]:
"size": storage_size,
"pvc": {
"enabled": False,
"mountPath": self.workspace_mount_path.absolute().as_posix(),
"mountPath": self.workspace_mount_path.as_posix(),
},
}
# Authentication
Expand Down Expand Up @@ -257,7 +257,7 @@ async def _get_session_manifest(self) -> dict[str, Any]:
"jupyterServer": {
"defaultUrl": self.server_options.default_url,
"image": self.image,
"rootDir": self.work_dir.absolute().as_posix(),
"rootDir": self.work_dir.as_posix(),
"resources": self.server_options.to_k8s_resources(
enforce_cpu_limits=self.config.sessions.enforce_cpu_limits
),
Expand Down Expand Up @@ -378,8 +378,8 @@ def __init__(
user_secrets: K8sUserSecrets | None,
cloudstorage: Sequence[ICloudStorageRequest],
k8s_client: K8sClient,
workspace_mount_path: Path,
work_dir: Path,
workspace_mount_path: PurePosixPath,
work_dir: PurePosixPath,
config: _NotebooksConfig,
gitlab_project: Project | None,
internal_gitlab_user: APIUser,
Expand Down Expand Up @@ -503,8 +503,8 @@ def __init__(
user_secrets: K8sUserSecrets | None,
cloudstorage: Sequence[ICloudStorageRequest],
k8s_client: K8sClient,
workspace_mount_path: Path,
work_dir: Path,
workspace_mount_path: PurePosixPath,
work_dir: PurePosixPath,
repositories: list[Repository],
config: _NotebooksConfig,
internal_gitlab_user: APIUser,
Expand Down
Loading

0 comments on commit 689585b

Please sign in to comment.