Compare commits

...

15 Commits

Author SHA1 Message Date
Oscar Krause
4133b430ca Merge branch 'v18.x-support' into 'main'
v18.x support / NLS 3.4.x compatibility

See merge request oscar.krause/fastapi-dls!46
2025-04-11 21:23:19 +02:00
Oscar Krause
f20232d425 added EMPTY (!!!) X-NLS-Signature response header 2025-04-11 21:23:15 +02:00
Oscar Krause
b6639f9bfb added debug headers 2025-04-11 21:22:56 +02:00
Oscar Krause
bd02e3d4b8 code styling 2025-04-11 21:22:44 +02:00
Oscar Krause
39bf74fba9 added new "protocol_version" to client-token 2025-04-11 21:01:36 +02:00
Oscar Krause
d46690fd0e fixes 2025-04-11 20:38:58 +02:00
Oscar Krause
7a3c8e2051 also debug response 2025-04-11 20:35:10 +02:00
Oscar Krause
3ed7ae8fdb fixed datetime format 2025-04-11 20:14:17 +02:00
Oscar Krause
3dcfa66d15 added missing lessor attributes 2025-04-11 19:36:25 +02:00
Oscar Krause
6a50bdfb89 fixes 2025-04-11 19:08:41 +02:00
Oscar Krause
d0e64c3e94 added debugging 2025-04-11 18:51:33 +02:00
Oscar Krause
ff4748fef9 updated new responses for 18.x drivers 2025-04-11 18:51:17 +02:00
Oscar Krause
607cca7655 typos 2025-04-10 09:00:58 +02:00
Oscar Krause
6f9b6b9e5c Merge branch 'dev' into 'main'
added NixOS Pull-Request note for official "nixpkgs"

See merge request oscar.krause/fastapi-dls!50
2025-04-10 08:58:36 +02:00
Oscar Krause
d22e93020c added NixOS Pull-Request note for official "nixpkgs" 2025-04-10 07:55:20 +02:00

View File

@ -18,8 +18,7 @@ from jose.constants import ALGORITHMS
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import StreamingResponse, JSONResponse as JSONr, HTMLResponse as HTMLr, Response, \
RedirectResponse
from starlette.responses import StreamingResponse, JSONResponse as JSONr, HTMLResponse as HTMLr, Response, RedirectResponse
from orm import Origin, Lease, init as db_init, migrate
from util import PrivateKey, PublicKey, load_file, Cert
@ -51,6 +50,7 @@ LEASE_RENEWAL_PERIOD = float(env('LEASE_RENEWAL_PERIOD', 0.15))
LEASE_RENEWAL_DELTA = timedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)), hours=int(env('LEASE_EXPIRE_HOURS', 0)))
CLIENT_TOKEN_EXPIRE_DELTA = relativedelta(years=12)
CORS_ORIGINS = str(env('CORS_ORIGINS', '')).split(',') if (env('CORS_ORIGINS')) else [f'https://{DLS_URL}']
DT_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
jwt_encode_key = jwk.construct(INSTANCE_KEY_RSA.pem(), algorithm=ALGORITHMS.RS256)
jwt_decode_key = jwk.construct(INSTANCE_KEY_PUB.pem(), algorithm=ALGORITHMS.RS256)
@ -249,6 +249,7 @@ async def _client_token():
"iat": timegm(cur_time.timetuple()),
"nbf": timegm(cur_time.timetuple()),
"exp": timegm(exp_time.timetuple()),
"protocol_version": "2.0",
"update_mode": "ABSOLUTE",
"scope_ref_list": [ALLOTMENT_REF],
"fulfillment_class_ref_list": [],
@ -299,14 +300,19 @@ async def auth_v1_origin(request: Request):
Origin.create_or_update(db, data)
environment = {
'raw_env': j.get('environment')
}
environment.update(j.get('environment'))
response = {
"origin_ref": origin_ref,
"environment": j.get('environment'),
"environment": environment,
"svc_port_set_list": None,
"node_url_list": None,
"node_query_order": None,
"prompts": None,
"sync_timestamp": cur_time.isoformat()
"sync_timestamp": cur_time.strftime(DT_FORMAT)
}
return JSONr(response)
@ -332,7 +338,7 @@ async def auth_v1_origin_update(request: Request):
response = {
"environment": j.get('environment'),
"prompts": None,
"sync_timestamp": cur_time.isoformat()
"sync_timestamp": cur_time.strftime(DT_FORMAT)
}
return JSONr(response)
@ -363,7 +369,7 @@ async def auth_v1_code(request: Request):
response = {
"auth_code": auth_code,
"sync_timestamp": cur_time.isoformat(),
"sync_timestamp": cur_time.strftime(DT_FORMAT),
"prompts": None
}
@ -405,9 +411,10 @@ async def auth_v1_token(request: Request):
auth_token = jwt.encode(new_payload, key=jwt_encode_key, headers={'kid': payload.get('kid')}, algorithm=ALGORITHMS.RS256)
response = {
"expires": access_expires_on.isoformat(),
"expires": access_expires_on.strftime(DT_FORMAT),
"auth_token": auth_token,
"sync_timestamp": cur_time.isoformat(),
"sync_timestamp": cur_time.strftime(DT_FORMAT),
"prompts": None
}
return JSONr(response)
@ -661,6 +668,9 @@ async def leasing_v1_config_token(request: Request):
async def leasing_v1_lessor(request: Request):
j, token, cur_time = json_loads((await request.body()).decode('utf-8')), __get_token(request), datetime.now(UTC)
logger.debug(j)
logger.debug(request.headers)
try:
token = __get_token(request)
except JWTError:
@ -671,6 +681,7 @@ async def leasing_v1_lessor(request: Request):
logger.info(f'> [ create ]: {origin_ref}: create leases for scope_ref_list {scope_ref_list}')
lease_result_list = []
# todo: for lease_proposal in lease_proposal_list
for scope_ref in scope_ref_list:
# if scope_ref not in [ALLOTMENT_REF]:
# return JSONr(status_code=500, detail=f'no service instances found for scopes: ["{scope_ref}"]')
@ -678,15 +689,20 @@ async def leasing_v1_lessor(request: Request):
lease_ref = str(uuid4())
expires = cur_time + LEASE_EXPIRE_DELTA
lease_result_list.append({
"ordinal": 0,
"ordinal": None,
"error": None,
# https://docs.nvidia.com/license-system/latest/nvidia-license-system-user-guide/index.html
"lease": {
"ref": lease_ref,
"created": cur_time.isoformat(),
"expires": expires.isoformat(),
"created": cur_time.strftime(DT_FORMAT),
"expires": expires.strftime(DT_FORMAT),
"recommended_lease_renewal": LEASE_RENEWAL_PERIOD,
"offline_lease": "true",
"license_type": "CONCURRENT_COUNTED_SINGLE"
"license_type": "CONCURRENT_COUNTED_SINGLE",
"lease_intent_id": None,
"metadata": None,
"feature_name": "GRID-Virtual-WS", # todo
"product_name": "NVIDIA RTX Virtual Workstation", # todo
}
})
@ -694,13 +710,16 @@ async def leasing_v1_lessor(request: Request):
Lease.create_or_update(db, data)
response = {
"client_challenge": None,
"lease_result_list": lease_result_list,
"result_code": "SUCCESS",
"sync_timestamp": cur_time.isoformat(),
"result_code": None,
"sync_timestamp": cur_time.strftime(DT_FORMAT),
"prompts": None
}
return JSONr(response)
logger.debug(response)
return JSONr(response, headers={'X-NLS-Signature': '?'})
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
@ -716,7 +735,7 @@ async def leasing_v1_lessor_lease(request: Request):
response = {
"active_lease_list": active_lease_list,
"sync_timestamp": cur_time.isoformat(),
"sync_timestamp": cur_time.strftime(DT_FORMAT),
"prompts": None
}
@ -739,11 +758,11 @@ async def leasing_v1_lease_renew(request: Request, lease_ref: str):
expires = cur_time + LEASE_EXPIRE_DELTA
response = {
"lease_ref": lease_ref,
"expires": expires.isoformat(),
"expires": expires.strftime(DT_FORMAT),
"recommended_lease_renewal": LEASE_RENEWAL_PERIOD,
"offline_lease": True,
"prompts": None,
"sync_timestamp": cur_time.isoformat(),
"sync_timestamp": cur_time.strftime(DT_FORMAT),
}
Lease.renew(db, entity, expires, cur_time)
@ -771,7 +790,7 @@ async def leasing_v1_lease_delete(request: Request, lease_ref: str):
response = {
"lease_ref": lease_ref,
"prompts": None,
"sync_timestamp": cur_time.isoformat(),
"sync_timestamp": cur_time.strftime(DT_FORMAT),
}
return JSONr(response)
@ -791,7 +810,7 @@ async def leasing_v1_lessor_lease_remove(request: Request):
response = {
"released_lease_list": released_lease_list,
"release_failure_list": None,
"sync_timestamp": cur_time.isoformat(),
"sync_timestamp": cur_time.strftime(DT_FORMAT),
"prompts": None
}
@ -813,7 +832,7 @@ async def leasing_v1_lessor_shutdown(request: Request):
response = {
"released_lease_list": released_lease_list,
"release_failure_list": None,
"sync_timestamp": cur_time.isoformat(),
"sync_timestamp": cur_time.strftime(DT_FORMAT),
"prompts": None
}