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,45 +238,90 @@ hub: ...@@ -230,45 +238,90 @@ 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):
# ownCloud Infinite Scale parameters
# (https://owncloud.dev/apis/http/graph/spaces/#list-my-spaces-get-medrives)
OCIS_URL = "https://ocis.aaitest.owncloud.works"
# personal space
OCIS_PERSONAL_SPACE = "/graph/v1.0/me/drives?%24filter=driveType+eq+personal"
# 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",
)
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 = [
{"mountPath": "/owncloud:shared", "name": "owncloud-" + type},
{"mountPath": self.token_mount_path, "name": self.token_secret_volume_name, "readOnly": True},
]
spawner.extra_containers.append(
{
"name": "owncloud-" + type,
"image": "eginotebooks/webdav-rclone-sidecar:sha-95b4f95",
"args": ["bearer_token_command=cat " + self.token_path],
"env": [
{"name": "WEBDAV_URL", "value": owncloud_url},
{"name": "WEBDAV_VENDOR", "value": "owncloud"},
# XXX: strict permissions needed for .local/share/jupyter/runtime/jupyter_cookie_secret
# quicker directory cache and polling
{"name": "MOUNT_OPTS", "value": "--file-perms=0600 --dir-perms=0770 --dir-cache-time=1m0s --poll-interval=0m20s"},
{"name": "MOUNT_PATH", "value": "/owncloud"},
# default mode is "full"
{"name": "VFS_CACHE_MODE", "value": "full"},
],
"resources": self.sidecar_resources,
"securityContext": {
"runAsUser": 1000,
"fsUser": 1000,
"fsGroup": 100,
"privileged": True,
"capabilities": {"add": ["SYS_ADMIN"]},
},
"volumeMounts": volume_mounts,
}
)
async def pre_spawn_hook(self, spawner): async def pre_spawn_hook(self, spawner):
await super(WebDavOIDCSpawner, self).pre_spawn_hook(spawner) await super(WebDavOIDCSpawner, self).pre_spawn_hook(spawner)
auth_state = await self.user.get_auth_state() auth_state = await self.user.get_auth_state()
# volume name as in EGI spawner # volume name as in EGI spawner
token_secret_volume_name = self._expand_user_properties( self.token_secret_volume_name = self._expand_user_properties(
self.token_secret_volume_name_template self.token_secret_volume_name_template
) )
token_path = os.path.join(self.token_mount_path, "access_token") self.token_path = os.path.join(self.token_mount_path, "access_token")
volume_mounts = [
{"mountPath": "/owncloud:shared", "name": "owncloud"}, access_token = auth_state.get("access_token", None)
{"mountPath": self.token_mount_path, "name": token_secret_volume_name, "readOnly": True}, headers = {
] "Accept": "application/json",
spawner.extra_containers.append( "User-Agent": "JupyterHub",
{ "Authorization": "Bearer %s" % access_token,
"name": "owncloud", }
"image": "eginotebooks/webdav-rclone-sidecar:sha-95b4f95",
"args": ["bearer_token_command=cat " + token_path], # ownCloud user home
"env": [ await self.append_owncloud_sidecar(spawner, "home", self.OCIS_PERSONAL_SPACE, fallback_url=self.OCIS_URL + "/remote.php/webdav/", headers=headers)
{"name": "WEBDAV_URL", "value": "https://ocis.aaitest.owncloud.works/remote.php/webdav/"}, await self.append_owncloud_sidecar(spawner, "shared", self.OCIS_SHARED_WITH_ME, headers=headers)
{"name": "WEBDAV_VENDOR", "value": "owncloud"}, await self.append_owncloud_sidecar(spawner, "spaces", self.OCIS_SPACES, headers=headers)
# XXX: strict permissions needed for .local/share/jupyter/runtime/jupyter_cookie_secret
# quicker directory cache and polling
{"name": "MOUNT_OPTS", "value": "--file-perms=0600 --dir-perms=0770 --dir-cache-time=1m0s --poll-interval=0m20s"},
{"name": "MOUNT_PATH", "value": "/owncloud"},
# default mode is "full"
{"name": "VFS_CACHE_MODE", "value": "full"},
],
"resources": self.sidecar_resources,
"securityContext": {
"runAsUser": 1000,
"fsUser": 1000,
"fsGroup": 100,
"privileged": True,
"capabilities": {"add": ["SYS_ADMIN"]},
},
"volumeMounts": volume_mounts,
}
)
c.JupyterHub.spawner_class = WebDavOIDCSpawner c.JupyterHub.spawner_class = WebDavOIDCSpawner
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment