Skip to content
Snippets Groups Projects
Commit 449eeef7 authored by František Dvořák's avatar František Dvořák
Browse files

Implement changes in ownCloud integration

parent 1ad6234d
No related branches found
No related tags found
No related merge requests found
...@@ -29,9 +29,11 @@ singleuser: ...@@ -29,9 +29,11 @@ singleuser:
# sizeLimit problematic in this environment, # sizeLimit problematic in this environment,
# not needed for remote mounts # not needed for remote mounts
empty_dir: empty_dir:
- name: owncloud - name: owncloud-home
# sizeLimit problematic in this environment, empty_dir:
# not needed for remote mounts - name: owncloud-shared
empty_dir:
- name: owncloud-spaces
empty_dir: empty_dir:
# - name: scratch # - name: scratch
# ephemeral: # ephemeral:
...@@ -47,8 +49,12 @@ singleuser: ...@@ -47,8 +49,12 @@ singleuser:
mountPath: "/cvmfs:shared" mountPath: "/cvmfs:shared"
- name: b2drop - name: b2drop
mountPath: '/home/jovyan/b2drop:shared' mountPath: '/home/jovyan/b2drop:shared'
- name: owncloud - name: owncloud-home
mountPath: '/home/jovyan:shared' mountPath: '/home/jovyan:shared'
- name: owncloud-shared
mountPath: '/home/jovyan/Shared:shared'
- name: owncloud-spaces
mountPath: '/home/jovyan/Spaces:shared'
# - name: scratch # - name: scratch
# mountPath: '/scratch' # mountPath: '/scratch'
memory: memory:
...@@ -154,6 +160,8 @@ hub: ...@@ -154,6 +160,8 @@ hub:
from jinja2 import Environment from jinja2 import Environment
from egi_notebooks_hub.onedata import OnedataSpawner from egi_notebooks_hub.onedata import OnedataSpawner
from kubernetes_asyncio.client.rest import ApiException from kubernetes_asyncio.client.rest import ApiException
from tornado.httpclient import AsyncHTTPClient, HTTPClientError, HTTPRequest
class B2DropSpawner(OnedataSpawner): class B2DropSpawner(OnedataSpawner):
async def auth_state_hook(self, spawner, auth_state): async def auth_state_hook(self, spawner, auth_state):
...@@ -230,26 +238,50 @@ hub: ...@@ -230,26 +238,50 @@ hub:
'b2drop-pwd': formdata.get('b2drop-pwd', [None])[0]}) 'b2drop-pwd': formdata.get('b2drop-pwd', [None])[0]})
return data return data
class WebDavOIDCSpawner(B2DropSpawner): class WebDavOIDCSpawner(B2DropSpawner):
async def pre_spawn_hook(self, spawner): # ownCloud Infinite Scale parameters
await super(WebDavOIDCSpawner, self).pre_spawn_hook(spawner) # (https://owncloud.dev/apis/http/graph/spaces/#list-my-spaces-get-medrives)
auth_state = await self.user.get_auth_state() OCIS_URL = "https://ocis.aaitest.owncloud.works"
# volume name as in EGI spawner # personal space
token_secret_volume_name = self._expand_user_properties( OCIS_PERSONAL_SPACE = "/graph/v1.0/me/drives?%24filter=driveType+eq+personal"
self.token_secret_volume_name_template # shared space
OCIS_SHARED_WITH_ME = "/graph/v1.0/me/drives?%24filter=driveType+eq+virtual"
# otter spaces
OCIS_SPACES = "/graph/v1.0/me/drives?%24filter=driveType+eq+project"
async def append_owncloud_sidecar(self, spawner, type, query, fallback_url=None, headers={}):
owncloud_url = fallback_url
http_client = AsyncHTTPClient()
req = HTTPRequest(
self.OCIS_URL + query,
headers=headers,
method="GET",
) )
token_path = os.path.join(self.token_mount_path, "access_token") try:
resp = await http_client.fetch(req)
ocis_infos = json.loads(resp.body.decode("utf8", "replace"))
self.log.info("OCIS response: %s", ocis_infos)
if len(ocis_infos) >= 1 and "root" in ocis_infos[0]:
owncloud_url = get(ocis_infos[0]["root"], "webDavUrl", None)
except HTTPClientError as e:
self.log.error("can't query ownCloud: %s", e)
self.log.info("ownCloud %s URL: %s", type, owncloud_url)
if owncloud_url is None:
return
volume_mounts = [ volume_mounts = [
{"mountPath": "/owncloud:shared", "name": "owncloud"}, {"mountPath": "/owncloud:shared", "name": "owncloud-" + type},
{"mountPath": self.token_mount_path, "name": token_secret_volume_name, "readOnly": True}, {"mountPath": self.token_mount_path, "name": self.token_secret_volume_name, "readOnly": True},
] ]
spawner.extra_containers.append( spawner.extra_containers.append(
{ {
"name": "owncloud", "name": "owncloud-" + type,
"image": "eginotebooks/webdav-rclone-sidecar:sha-95b4f95", "image": "eginotebooks/webdav-rclone-sidecar:sha-95b4f95",
"args": ["bearer_token_command=cat " + token_path], "args": ["bearer_token_command=cat " + self.token_path],
"env": [ "env": [
{"name": "WEBDAV_URL", "value": "https://ocis.aaitest.owncloud.works/remote.php/webdav/"}, {"name": "WEBDAV_URL", "value": owncloud_url},
{"name": "WEBDAV_VENDOR", "value": "owncloud"}, {"name": "WEBDAV_VENDOR", "value": "owncloud"},
# XXX: strict permissions needed for .local/share/jupyter/runtime/jupyter_cookie_secret # XXX: strict permissions needed for .local/share/jupyter/runtime/jupyter_cookie_secret
# quicker directory cache and polling # quicker directory cache and polling
...@@ -270,6 +302,27 @@ hub: ...@@ -270,6 +302,27 @@ hub:
} }
) )
async def pre_spawn_hook(self, spawner):
await super(WebDavOIDCSpawner, self).pre_spawn_hook(spawner)
auth_state = await self.user.get_auth_state()
# volume name as in EGI spawner
self.token_secret_volume_name = self._expand_user_properties(
self.token_secret_volume_name_template
)
self.token_path = os.path.join(self.token_mount_path, "access_token")
access_token = auth_state.get("access_token", None)
headers = {
"Accept": "application/json",
"User-Agent": "JupyterHub",
"Authorization": "Bearer %s" % access_token,
}
# ownCloud user home
await self.append_owncloud_sidecar(spawner, "home", self.OCIS_PERSONAL_SPACE, fallback_url=self.OCIS_URL + "/remote.php/webdav/", headers=headers)
await self.append_owncloud_sidecar(spawner, "shared", self.OCIS_SHARED_WITH_ME, headers=headers)
await self.append_owncloud_sidecar(spawner, "spaces", self.OCIS_SPACES, headers=headers)
c.JupyterHub.spawner_class = WebDavOIDCSpawner c.JupyterHub.spawner_class = WebDavOIDCSpawner
c.B2DropSpawner.http_timeout = 90 c.B2DropSpawner.http_timeout = 90
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment