Skip to content

Commit e7da1b6

Browse files
committed
flatiron hub extraConfig updates
- remove delete_user_pvc, now handled by kubespawner - increase user cull timeout to a month - temporarily disable monitor until tomplus/kubernetes_asyncio#260
1 parent 8493070 commit e7da1b6

File tree

1 file changed

+73
-48
lines changed

1 file changed

+73
-48
lines changed

helm-chart/binderhub/values.yaml

+73-48
Original file line numberDiff line numberDiff line change
@@ -226,51 +226,12 @@ jupyterhub:
226226
'admin': True,
227227
'command': ['python3', '-m', 'jupyterhub_idle_culler',
228228
'--url=http://127.0.0.1:8081/hub/hub/api',
229-
'--timeout=604800',
229+
'--timeout=2500000',
230230
'--cull-every=86400',
231231
'--concurrency=4',
232232
'--cull-users'
233233
]})
234234
235-
delete_user_pvc: |
236-
import string
237-
import escapism
238-
import oauthenticator
239-
import kubernetes.client
240-
import tornado.concurrent
241-
import concurrent.futures
242-
243-
pvc_name_template = get_config('singleuser.storage.dynamic.pvcNameTemplate')
244-
pvc_namespace = os.environ.get('POD_NAMESPACE', 'default')
245-
246-
class BinderAuthenticator(oauthenticator.GoogleOAuthenticator):
247-
executor = concurrent.futures.ThreadPoolExecutor(1)
248-
249-
@tornado.concurrent.run_on_executor
250-
def delete_pvc(self, user):
251-
safe_chars = set(string.ascii_lowercase + string.digits)
252-
legacy_escaped_username = ''.join([s if s in safe_chars else '-' for s in user.name.lower()])
253-
safe_username = escapism.escape(user.name, safe=safe_chars, escape_char='-').lower()
254-
name = pvc_name_template.format(
255-
userid=user.id,
256-
username=safe_username,
257-
unescaped_username=user.name,
258-
legacy_escape_username=legacy_escaped_username,
259-
servername='',
260-
unescaped_servername=''
261-
)
262-
try:
263-
kubernetes.client.CoreV1Api().delete_namespaced_persistent_volume_claim(name, pvc_namespace, body=kubernetes.client.V1DeleteOptions())
264-
except kubernetes.client.rest.ApiException as e:
265-
if e.status != 404:
266-
self.log.warn("Error deleting user PVC %s: %s", name, e)
267-
268-
def delete_user(self, user):
269-
self.delete_pvc(user)
270-
return super().delete_user(user)
271-
272-
c.JupyterHub.authenticator_class = BinderAuthenticator
273-
274235
monitor: |
275236
from jupyterhub.handlers import BaseHandler
276237
import prometheus_client
@@ -279,10 +240,73 @@ jupyterhub:
279240
import datetime
280241
from kubespawner.clients import shared_client
281242
from kubespawner import KubeSpawner
282-
from kubernetes.dynamic import DynamicClient
283-
from kubernetes.dynamic.exceptions import ResourceNotFoundError
284-
from kubernetes.client.exceptions import ApiException
285-
from kubernetes.utils import parse_quantity
243+
#from kubernetes_asyncio.dynamic import DynamicClient
244+
#from kubernetes_asyncio.dynamic.exceptions import ResourceNotFoundError
245+
from kubernetes_asyncio.client.exceptions import ApiException
246+
#from kubernetes_asyncio.utils import parse_quantity
247+
248+
# https://github.com/kubernetes-client/python/blob/master/kubernetes/utils/quantity.py
249+
from decimal import Decimal, InvalidOperation
250+
251+
def parse_quantity(quantity):
252+
"""
253+
Parse kubernetes canonical form quantity like 200Mi to a decimal number.
254+
Supported SI suffixes:
255+
base1024: Ki | Mi | Gi | Ti | Pi | Ei
256+
base1000: n | u | m | "" | k | M | G | T | P | E
257+
258+
See https://github.com/kubernetes/apimachinery/blob/master/pkg/api/resource/quantity.go
259+
260+
Input:
261+
quantity: string. kubernetes canonical form quantity
262+
263+
Returns:
264+
Decimal
265+
266+
Raises:
267+
ValueError on invalid or unknown input
268+
"""
269+
if isinstance(quantity, (int, float, Decimal)):
270+
return Decimal(quantity)
271+
272+
exponents = {"n": -3, "u": -2, "m": -1, "K": 1, "k": 1, "M": 2,
273+
"G": 3, "T": 4, "P": 5, "E": 6}
274+
275+
quantity = str(quantity)
276+
number = quantity
277+
suffix = None
278+
if len(quantity) >= 2 and quantity[-1] == "i":
279+
if quantity[-2] in exponents:
280+
number = quantity[:-2]
281+
suffix = quantity[-2:]
282+
elif len(quantity) >= 1 and quantity[-1] in exponents:
283+
number = quantity[:-1]
284+
suffix = quantity[-1:]
285+
286+
try:
287+
number = Decimal(number)
288+
except InvalidOperation:
289+
raise ValueError("Invalid number format: {}".format(number))
290+
291+
if suffix is None:
292+
return number
293+
294+
if suffix.endswith("i"):
295+
base = 1024
296+
elif len(suffix) == 1:
297+
base = 1000
298+
else:
299+
raise ValueError("{} has unknown suffix".format(quantity))
300+
301+
# handle SI inconsistency
302+
if suffix == "ki":
303+
raise ValueError("{} has unknown suffix".format(quantity))
304+
305+
if suffix[0] not in exponents:
306+
raise ValueError("{} has unknown suffix".format(quantity))
307+
308+
exponent = Decimal(exponents[suffix[0]])
309+
return number * (base ** exponent)
286310
287311
import z2jh
288312
allowed = list(map(ipaddress.ip_network, z2jh.get_config('config.Monitor.allowed_monitor_ips', [])))
@@ -291,10 +315,11 @@ jupyterhub:
291315
def collect(self):
292316
pods = KubeSpawner.reflectors['pods']
293317
if not pods: return []
294-
try:
295-
api = DynamicClient(shared_client('ApiClient')).resources.get(api_version='metrics.k8s.io/v1beta1', kind='PodMetrics')
296-
except ResourceNotFoundError:
297-
api = None
318+
#try:
319+
# api = DynamicClient(shared_client('ApiClient')).resources.get(api_version='metrics.k8s.io/v1beta1', kind='PodMetrics')
320+
#except ResourceNotFoundError:
321+
# api = None
322+
api = None
298323
299324
l = ['user','specuser','specproj']
300325
run = prometheus_client.metrics_core.GaugeMetricFamily('binder_running_servers', 'Running binderhub jupyter servers', labels=l)

0 commit comments

Comments
 (0)