Compare commits
5 Commits
0853dd64cb
...
4fb6243330
Author | SHA1 | Date | |
---|---|---|---|
4fb6243330 | |||
2e950ca6f4 | |||
34662e6612 | |||
a3e089a3d5 | |||
ab996bb030 |
23
README.md
23
README.md
@ -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)).
|
||||||
|
|
||||||
@ -283,19 +283,24 @@ 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 |
|
||||||
|
| `LEASE_RENEWAL_PERIOD` | `0.15` | The percentage of the lease period that must elapse before a licensed client can renew a license \*1 |
|
||||||
| `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) |
|
| `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) |
|
||||||
| `CORS_ORIGINS` | `https://{DLS_URL}` | Sets `Access-Control-Allow-Origin` header (comma separated string) \* |
|
| `CORS_ORIGINS` | `https://{DLS_URL}` | Sets `Access-Control-Allow-Origin` header (comma separated string) \*2 |
|
||||||
| `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid |
|
| `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid |
|
||||||
| `INSTANCE_REF` | `00000000-0000-0000-0000-000000000000` | Instance identification uuid |
|
| `INSTANCE_REF` | `00000000-0000-0000-0000-000000000000` | Instance identification uuid |
|
||||||
| `INSTANCE_KEY_RSA` | `<app-dir>/cert/instance.private.pem` | Site-wide private RSA key for singing JWTs |
|
| `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 |
|
| `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)
|
||||||
|
|
||||||
|
37
app/main.py
37
app/main.py
@ -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()
|
||||||
|
15
test/main.py
15
test/main.py
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user