Compare commits

...

5 Commits

Author SHA1 Message Date
4fb6243330 removed deprecated endpoints
- '/client-token' moved to '/-/client-token'
- '/status' moved to '/-/health' and '/-/config'

see README.md for more information
2023-01-02 19:18:32 +01:00
2e950ca6f4 implemented '/-/config' endpoint to list runtime environment variables 2023-01-02 19:14:25 +01:00
34662e6612 implemented 'LEASE_RENEWAL_PERIOD' variable 2023-01-02 18:57:41 +01:00
a3e089a3d5 added some references 2023-01-02 18:10:11 +01:00
ab996bb030 code styling 2023-01-02 18:04:14 +01:00
3 changed files with 53 additions and 42 deletions

View File

@ -19,13 +19,13 @@ Only the clients need a connection to this service on configured port.
Redirect to `/-/readme`. Redirect to `/-/readme`.
### `GET /status` (deprecated: use `/-/health`)
Status endpoint, used for *healthcheck*. Shows also current version and commit hash.
### `GET /-/health` ### `GET /-/health`
Status endpoint, used for *healthcheck*. Shows also current version and commit hash. Status endpoint, used for *healthcheck*.
### `GET /-/config`
Shows current runtime environment variables and their values.
### `GET /-/readme` ### `GET /-/readme`
@ -63,7 +63,7 @@ List current leases.
Deletes an lease. Deletes an lease.
### `GET /client-token` (deprecated: use `/-/client-token`) ### `GET /-/client-token`
Generate client token, (see [installation](#installation)). Generate client token, (see [installation](#installation)).
@ -282,20 +282,25 @@ After first success you have to replace `--issue` with `--renew`.
# Configuration # Configuration
| Variable | Default | Usage | | Variable | Default | Usage |
|---------------------|----------------------------------------|-------------------------------------------------------------------------------------| |------------------------|----------------------------------------|------------------------------------------------------------------------------------------------------|
| `DEBUG` | `false` | Toggles `fastapi` debug mode | | `DEBUG` | `false` | Toggles `fastapi` debug mode |
| `DLS_URL` | `localhost` | Used in client-token to tell guest driver where dls instance is reachable | | `DLS_URL` | `localhost` | Used in client-token to tell guest driver where dls instance is reachable |
| `DLS_PORT` | `443` | Used in client-token to tell guest driver where dls instance is reachable | | `DLS_PORT` | `443` | Used in client-token to tell guest driver where dls instance is reachable |
| `LEASE_EXPIRE_DAYS` | `90` | Lease time in days | | `LEASE_EXPIRE_DAYS` | `90` | Lease time in days |
| `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) | | `LEASE_RENEWAL_PERIOD` | `0.15` | The percentage of the lease period that must elapse before a licensed client can renew a license \*1 |
| `CORS_ORIGINS` | `https://{DLS_URL}` | Sets `Access-Control-Allow-Origin` header (comma separated string) \* | | `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) |
| `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid | | `CORS_ORIGINS` | `https://{DLS_URL}` | Sets `Access-Control-Allow-Origin` header (comma separated string) \*2 |
| `INSTANCE_REF` | `00000000-0000-0000-0000-000000000000` | Instance identification uuid | | `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid |
| `INSTANCE_KEY_RSA` | `<app-dir>/cert/instance.private.pem` | Site-wide private RSA key for singing JWTs | | `INSTANCE_REF` | `00000000-0000-0000-0000-000000000000` | Instance identification uuid |
| `INSTANCE_KEY_PUB` | `<app-dir>/cert/instance.public.pem` | Site-wide public key | | `INSTANCE_KEY_RSA` | `<app-dir>/cert/instance.private.pem` | Site-wide private RSA key for singing JWTs |
| `INSTANCE_KEY_PUB` | `<app-dir>/cert/instance.public.pem` | Site-wide public key |
\* Always use `https`, since guest-drivers only support secure connections! \*1 For example, if the lease period is one day and the renewal period is 20%, the client attempts to renew its license
every 4.8 hours. If network connectivity is lost, the loss of connectivity is detected during license renewal and the
client has 19.2 hours in which to re-establish connectivity before its license expires.
\*2 Always use `https`, since guest-drivers only support secure connections!
# Setup (Client) # Setup (Client)

View File

@ -40,6 +40,7 @@ INSTANCE_KEY_RSA = load_key(str(env('INSTANCE_KEY_RSA', join(dirname(__file__),
INSTANCE_KEY_PUB = load_key(str(env('INSTANCE_KEY_PUB', join(dirname(__file__), 'cert/instance.public.pem')))) INSTANCE_KEY_PUB = load_key(str(env('INSTANCE_KEY_PUB', join(dirname(__file__), 'cert/instance.public.pem'))))
TOKEN_EXPIRE_DELTA = relativedelta(hours=1) # days=1 TOKEN_EXPIRE_DELTA = relativedelta(hours=1) # days=1
LEASE_EXPIRE_DELTA = relativedelta(days=int(env('LEASE_EXPIRE_DAYS', 90))) LEASE_EXPIRE_DELTA = relativedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)))
LEASE_RENEWAL_PERIOD = float(env('LEASE_RENEWAL_PERIOD', 0.15))
CORS_ORIGINS = str(env('CORS_ORIGINS', '')).split(',') if (env('CORS_ORIGINS')) else [f'https://{DLS_URL}'] CORS_ORIGINS = str(env('CORS_ORIGINS', '')).split(',') if (env('CORS_ORIGINS')) else [f'https://{DLS_URL}']
jwt_encode_key = jwk.construct(INSTANCE_KEY_RSA.export_key().decode('utf-8'), algorithm=ALGORITHMS.RS256) jwt_encode_key = jwk.construct(INSTANCE_KEY_RSA.export_key().decode('utf-8'), algorithm=ALGORITHMS.RS256)
@ -68,11 +69,6 @@ async def index():
return RedirectResponse('/-/readme') return RedirectResponse('/-/readme')
@app.get('/status', summary='* Status', description='returns current service status, version (incl. git-commit) and some variables.', deprecated=True)
async def status(request: Request):
return JSONResponse({'status': 'up', 'version': VERSION, 'commit': COMMIT, 'debug': DEBUG})
@app.get('/-/', summary='* Index') @app.get('/-/', summary='* Index')
async def _index(): async def _index():
return RedirectResponse('/-/readme') return RedirectResponse('/-/readme')
@ -80,7 +76,24 @@ async def _index():
@app.get('/-/health', summary='* Health') @app.get('/-/health', summary='* Health')
async def _health(request: Request): async def _health(request: Request):
return JSONResponse({'status': 'up', 'version': VERSION, 'commit': COMMIT, 'debug': DEBUG}) return JSONResponse({'status': 'up'})
@app.get('/-/config', summary='* Config', description='returns environment variables.')
async def _config():
return JSONResponse({
'VERSION': VERSION,
'COMMIT': COMMIT,
'DEBUG': DEBUG,
'DLS_URL': DLS_URL,
'DLS_PORT': DLS_PORT,
'SITE_KEY_XID': SITE_KEY_XID,
'INSTANCE_REF': INSTANCE_REF,
'TOKEN_EXPIRE_DELTA': TOKEN_EXPIRE_DELTA,
'LEASE_EXPIRE_DELTA': LEASE_EXPIRE_DELTA,
'LEASE_RENEWAL_PERIOD': LEASE_RENEWAL_PERIOD,
'CORS_ORIGINS': CORS_ORIGINS,
})
@app.get('/-/readme', summary='* Readme') @app.get('/-/readme', summary='* Readme')
@ -210,11 +223,6 @@ async def _client_token():
return response return response
@app.get('/client-token', summary='* Client-Token', description='creates a new messenger token for this service instance', deprecated=True)
async def client_token():
return RedirectResponse('/-/client-token')
# venv/lib/python3.9/site-packages/nls_services_auth/test/test_origins_controller.py # venv/lib/python3.9/site-packages/nls_services_auth/test/test_origins_controller.py
# {"candidate_origin_ref":"00112233-4455-6677-8899-aabbccddeeff","environment":{"fingerprint":{"mac_address_list":["ff:ff:ff:ff:ff:ff"]},"hostname":"my-hostname","ip_address_list":["192.168.178.123","fe80::","fe80::1%enp6s18"],"guest_driver_version":"510.85.02","os_platform":"Debian GNU/Linux 11 (bullseye) 11","os_version":"11 (bullseye)"},"registration_pending":false,"update_pending":false} # {"candidate_origin_ref":"00112233-4455-6677-8899-aabbccddeeff","environment":{"fingerprint":{"mac_address_list":["ff:ff:ff:ff:ff:ff"]},"hostname":"my-hostname","ip_address_list":["192.168.178.123","fe80::","fe80::1%enp6s18"],"guest_driver_version":"510.85.02","os_platform":"Debian GNU/Linux 11 (bullseye) 11","os_version":"11 (bullseye)"},"registration_pending":false,"update_pending":false}
@app.post('/auth/v1/origin', description='find or create an origin') @app.post('/auth/v1/origin', description='find or create an origin')
@ -345,6 +353,7 @@ async def auth_v1_token(request: Request):
return JSONResponse(response) return JSONResponse(response)
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
# {'fulfillment_context': {'fulfillment_class_ref_list': []}, 'lease_proposal_list': [{'license_type_qualifiers': {'count': 1}, 'product': {'name': 'NVIDIA RTX Virtual Workstation'}}], 'proposal_evaluation_mode': 'ALL_OF', 'scope_ref_list': ['00112233-4455-6677-8899-aabbccddeeff']} # {'fulfillment_context': {'fulfillment_class_ref_list': []}, 'lease_proposal_list': [{'license_type_qualifiers': {'count': 1}, 'product': {'name': 'NVIDIA RTX Virtual Workstation'}}], 'proposal_evaluation_mode': 'ALL_OF', 'scope_ref_list': ['00112233-4455-6677-8899-aabbccddeeff']}
@app.post('/leasing/v1/lessor', description='request multiple leases (borrow) for current origin') @app.post('/leasing/v1/lessor', description='request multiple leases (borrow) for current origin')
async def leasing_v1_lessor(request: Request): async def leasing_v1_lessor(request: Request):
@ -364,8 +373,7 @@ async def leasing_v1_lessor(request: Request):
"ref": scope_ref, "ref": scope_ref,
"created": cur_time.isoformat(), "created": cur_time.isoformat(),
"expires": expires.isoformat(), "expires": expires.isoformat(),
# The percentage of the lease period that must elapse before a licensed client can renew a license "recommended_lease_renewal": LEASE_RENEWAL_PERIOD,
"recommended_lease_renewal": 0.15,
"offline_lease": "true", "offline_lease": "true",
"license_type": "CONCURRENT_COUNTED_SINGLE" "license_type": "CONCURRENT_COUNTED_SINGLE"
} }
@ -404,6 +412,7 @@ async def leasing_v1_lessor_lease(request: Request):
return JSONResponse(response) return JSONResponse(response)
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_single_controller.py
# venv/lib/python3.9/site-packages/nls_core_lease/lease_single.py # venv/lib/python3.9/site-packages/nls_core_lease/lease_single.py
@app.put('/leasing/v1/lease/{lease_ref}', description='renew a lease') @app.put('/leasing/v1/lease/{lease_ref}', description='renew a lease')
async def leasing_v1_lease_renew(request: Request, lease_ref: str): async def leasing_v1_lease_renew(request: Request, lease_ref: str):
@ -431,6 +440,7 @@ async def leasing_v1_lease_renew(request: Request, lease_ref: str):
return JSONResponse(response) return JSONResponse(response)
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_single_controller.py
@app.delete('/leasing/v1/lease/{lease_ref}', description='release (return) a lease') @app.delete('/leasing/v1/lease/{lease_ref}', description='release (return) a lease')
async def leasing_v1_lease_delete(request: Request, lease_ref: str): async def leasing_v1_lease_delete(request: Request, lease_ref: str):
token, cur_time = __get_token(request), datetime.utcnow() token, cur_time = __get_token(request), datetime.utcnow()
@ -456,6 +466,7 @@ async def leasing_v1_lease_delete(request: Request, lease_ref: str):
return JSONResponse(response) return JSONResponse(response)
# venv/lib/python3.9/site-packages/nls_services_lease/test/test_lease_multi_controller.py
@app.delete('/leasing/v1/lessor/leases', description='release all leases') @app.delete('/leasing/v1/lessor/leases', description='release all leases')
async def leasing_v1_lessor_lease_remove(request: Request): async def leasing_v1_lessor_lease_remove(request: Request):
token, cur_time = __get_token(request), datetime.utcnow() token, cur_time = __get_token(request), datetime.utcnow()

View File

@ -44,11 +44,6 @@ def test_index():
assert response.status_code == 200 assert response.status_code == 200
def test_status():
response = client.get('/status')
assert response.status_code == 200
assert response.json()['status'] == 'up'
def test_health(): def test_health():
response = client.get('/-/health') response = client.get('/-/health')
@ -56,6 +51,11 @@ def test_health():
assert response.json()['status'] == 'up' assert response.json()['status'] == 'up'
def test_config():
response = client.get('/-/')
assert response.status_code == 200
def test_readme(): def test_readme():
response = client.get('/-/readme') response = client.get('/-/readme')
assert response.status_code == 200 assert response.status_code == 200
@ -71,11 +71,6 @@ def test_client_token():
assert response.status_code == 200 assert response.status_code == 200
def test_client_token_deprecated():
response = client.get('/client-token')
assert response.status_code == 200
def test_origins(): def test_origins():
pass pass