Merge branch 'dev' into ui

# Conflicts:
#	app/main.py
This commit is contained in:
Oscar Krause 2023-01-05 07:31:15 +01:00
commit 4699c1770d
5 changed files with 109 additions and 96 deletions

View File

@ -1 +1,2 @@
/etc/fastapi-dls/env /etc/fastapi-dls/env
/etc/systemd/system/fastapi-dls.service

View File

@ -50,7 +50,7 @@ build:apt:
- cp .DEBIAN/env.default build/etc/fastapi-dls/env - cp .DEBIAN/env.default build/etc/fastapi-dls/env
# create service file # create service file
- mkdir -p build/etc/systemd/system - mkdir -p build/etc/systemd/system
- cp .DEBIAN/fastapi-dls.service build/etc/systemd/system - cp .DEBIAN/fastapi-dls.service build/etc/systemd/system/fastapi-dls.service
# cd into "build/" # cd into "build/"
- cd build/ - cd build/
script: script:
@ -280,7 +280,7 @@ release:prepare:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script: script:
- source version.env - source version.env
- echo &VERSION - echo $VERSION
artifacts: artifacts:
reports: reports:
dotenv: version.env dotenv: version.env

152
README.md
View File

@ -9,68 +9,6 @@ Only the clients need a connection to this service on configured port.
[[_TOC_]] [[_TOC_]]
## ToDo's
- check why windows guests display "can't acquire license" although in log there is no message displayed and license is
also acquired successfully
## Endpoints
### `GET /`
Redirect to `/-/readme`.
### `GET /-/health`
Status endpoint, used for *healthcheck*.
### `GET /-/config`
Shows current runtime environment variables and their values.
### `GET /-/readme`
HTML rendered README.md.
### `GET /-/docs`, `GET /-/redoc`
OpenAPI specifications rendered from `GET /-/openapi.json`.
### `GET /-/manage`
Shows a very basic UI to delete origins or leases.
### `GET /-/origins?leases=false`
List registered origins.
| Query Parameter | Default | Usage |
|-----------------|---------|--------------------------------------|
| `leases` | `false` | Include referenced leases per origin |
### `DELETE /-/origins`
Deletes all origins and their leases.
### `GET /-/leases?origin=false`
List current leases.
| Query Parameter | Default | Usage |
|-----------------|---------|-------------------------------------|
| `origin` | `false` | Include referenced origin per lease |
### `DELETE /-/lease/{lease_ref}`
Deletes an lease.
### `GET /-/client-token`
Generate client token, (see [installation](#installation)).
### Others
There are some more internal api endpoints for handling authentication and lease process.
# Setup (Service) # Setup (Service)
@ -96,6 +34,8 @@ openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout $WORKING_DIR/webse
**Start container** **Start container**
To test if everything is set up properly you can start container as following:
```shell ```shell
docker volume create dls-db docker volume create dls-db
docker run -e DLS_URL=`hostname -i` -e DLS_PORT=443 -p 443:443 -v $WORKING_DIR:/app/cert -v dls-db:/app/database collinwebdesigns/fastapi-dls:latest docker run -e DLS_URL=`hostname -i` -e DLS_PORT=443 -p 443:443 -v $WORKING_DIR:/app/cert -v dls-db:/app/database collinwebdesigns/fastapi-dls:latest
@ -103,7 +43,7 @@ docker run -e DLS_URL=`hostname -i` -e DLS_PORT=443 -p 443:443 -v $WORKING_DIR:/
**Docker-Compose / Deploy stack** **Docker-Compose / Deploy stack**
Goto [`docker-compose.yml`](docker-compose.yml) for more advanced example. Goto [`docker-compose.yml`](docker-compose.yml) for more advanced example (with reverse proxy usage).
```yaml ```yaml
version: '3.9' version: '3.9'
@ -298,8 +238,8 @@ After first success you have to replace `--issue` with `--renew`.
| `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid | | `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid |
| `INSTANCE_REF` | `10000000-0000-0000-0000-000000000001` | Instance identification uuid | | `INSTANCE_REF` | `10000000-0000-0000-0000-000000000001` | Instance identification uuid |
| `ALLOTMENT_REF` | `20000000-0000-0000-0000-000000000001` | Allotment identification uuid | | `ALLOTMENT_REF` | `20000000-0000-0000-0000-000000000001` | Allotment 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 \*3 |
| `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 \*3 |
\*1 For example, if the lease period is one day and the renewal period is 20%, the client attempts to renew its license \*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 every 4.8 hours. If network connectivity is lost, the loss of connectivity is detected during license renewal and the
@ -307,6 +247,8 @@ client has 19.2 hours in which to re-establish connectivity before its license e
\*2 Always use `https`, since guest-drivers only support secure connections! \*2 Always use `https`, since guest-drivers only support secure connections!
\*3 If you recreate instance keys you need to **recreate client-token for each guest**!
# Setup (Client) # Setup (Client)
**The token file has to be copied! It's not enough to C&P file contents, because there can be special characters.** **The token file has to be copied! It's not enough to C&P file contents, because there can be special characters.**
@ -338,8 +280,68 @@ Restart-Service NVDisplay.ContainerLocalSystem
'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe' -q | Select-String "License" 'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe' -q | Select-String "License"
``` ```
## Endpoints
### `GET /`
Redirect to `/-/readme`.
### `GET /-/health`
Status endpoint, used for *healthcheck*.
### `GET /-/config`
Shows current runtime environment variables and their values.
### `GET /-/readme`
HTML rendered README.md.
### `GET /-/docs`, `GET /-/redoc`
OpenAPI specifications rendered from `GET /-/openapi.json`.
### `GET /-/manage`
Shows a very basic UI to delete origins or leases.
### `GET /-/origins?leases=false`
List registered origins.
| Query Parameter | Default | Usage |
|-----------------|---------|--------------------------------------|
| `leases` | `false` | Include referenced leases per origin |
### `DELETE /-/origins`
Deletes all origins and their leases.
### `GET /-/leases?origin=false`
List current leases.
| Query Parameter | Default | Usage |
|-----------------|---------|-------------------------------------|
| `origin` | `false` | Include referenced origin per lease |
### `DELETE /-/lease/{lease_ref}`
Deletes an lease.
### `GET /-/client-token`
Generate client token, (see [installation](#installation)).
### Others
There are many other internal api endpoints for handling authentication and lease process.
# Troubleshoot # Troubleshoot
**Please make sure that fastapi-dls and your guests are on the same timezone!**
## Linux ## Linux
Logs are available with `journalctl -u nvidia-gridd -f`. Logs are available with `journalctl -u nvidia-gridd -f`.
@ -358,6 +360,9 @@ This message can be ignored.
- Ref. https://github.com/encode/uvicorn/issues/441 - Ref. https://github.com/encode/uvicorn/issues/441
<details>
<summary>Log example</summary>
``` ```
WARNING:uvicorn.error:Invalid HTTP request received. WARNING:uvicorn.error:Invalid HTTP request received.
Traceback (most recent call last): Traceback (most recent call last):
@ -376,6 +381,8 @@ Traceback (most recent call last):
h11._util.RemoteProtocolError: no request line received h11._util.RemoteProtocolError: no request line received
``` ```
</details>
## Windows ## Windows
### Required cipher on Windows Guests (e.g. managed by domain controller with GPO) ### Required cipher on Windows Guests (e.g. managed by domain controller with GPO)
@ -443,14 +450,13 @@ Dec 20 17:53:34 ubuntu-grid-server nvidia-gridd[10354]: License acquired success
</details> </details>
### Error on releasing leases on shutdown (fixed in 1.3 by using reverse proxy) ### Error on releasing leases on shutdown (can be ignored and/or fixed with reverse proxy)
**UPDATE for version `1.3`**: This issue can be fixed by using a reverse proxy (e.g. `nginx`). Please read section The driver wants to release current leases on shutting down windows. This endpoint needs to be a http endpoint.
below. The error message can safely be ignored (since we have no license limitation :P) and looks like this:
The driver wants to release current leases on shutting down windows. This endpoint needs to be a http endpoint and <details>
is currently not implemented. The error message looks like and safely can be ignored (since we have no license <summary>Log example</summary>
limitation :P):
``` ```
<1>:NLS initialized <1>:NLS initialized
@ -459,7 +465,7 @@ limitation :P):
<0>:End Logging <0>:End Logging
``` ```
#### log with 1.3 and nginx as reverse proxy #### log with nginx as reverse proxy (see [docker-compose.yml](docker-compose.yml))
``` ```
<1>:NLS initialized <1>:NLS initialized
@ -474,6 +480,8 @@ limitation :P):
<0>:End Logging <0>:End Logging
``` ```
</details>
# Credits # Credits
Thanks to vGPU community and all who uses this project and report bugs. Thanks to vGPU community and all who uses this project and report bugs.

View File

@ -2,13 +2,28 @@ version: '3.9'
x-dls-variables: &dls-variables x-dls-variables: &dls-variables
DLS_URL: localhost # REQUIRED, change to your ip or hostname DLS_URL: localhost # REQUIRED, change to your ip or hostname
DLS_PORT: 443 # must match nginx listen port DLS_PORT: 443 # must match nginx listen & exposed port
LEASE_EXPIRE_DAYS: 90 LEASE_EXPIRE_DAYS: 90
DATABASE: sqlite:////app/database/db.sqlite DATABASE: sqlite:////app/database/db.sqlite
DEBUG: false DEBUG: false
services: services:
web: dls:
image: collinwebdesigns/fastapi-dls:latest
restart: always
environment:
<<: *dls-variables
volumes:
- /opt/docker/fastapi-dls/cert:/app/cert # instance.private.pem, instance.public.pem
- db:/app/database
entrypoint: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--app-dir", "/app", "--proxy-headers"]
healthcheck:
test: ["CMD", "curl", "--fail", "http://localhost:8000/-/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
proxy:
image: nginx image: nginx
ports: ports:
# thees are ports where nginx (!) is listen to # thees are ports where nginx (!) is listen to
@ -17,14 +32,14 @@ services:
volumes: volumes:
- /opt/docker/fastapi-dls/cert:/opt/cert - /opt/docker/fastapi-dls/cert:/opt/cert
healthcheck: healthcheck:
test: [ "CMD", "curl", "--insecure", "--fail", "https://localhost/-/health" ] test: ["CMD", "curl", "--insecure", "--fail", "https://localhost/-/health"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 3
start_period: 30s start_period: 30s
command: | command: |
bash -c 'bash -s <<"EOF" bash -c "bash -s <<\"EOF\"
cat > /etc/nginx/nginx.conf <<"EON" cat > /etc/nginx/nginx.conf <<\"EON\"
daemon off; daemon off;
user root; user root;
worker_processes auto; worker_processes auto;
@ -39,7 +54,7 @@ services:
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
upstream dls-backend { upstream dls-backend {
server dls:443; server dls:8000; # must match dls listen port
} }
server { server {
@ -60,18 +75,17 @@ services:
ssl_prefer_server_ciphers on; ssl_prefer_server_ciphers on;
location / { location / {
proxy_ssl_verify off;
proxy_set_header Host $$http_host; proxy_set_header Host $$http_host;
proxy_set_header X-Real-IP $$remote_addr; proxy_set_header X-Real-IP $$remote_addr;
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $$scheme; proxy_set_header X-Forwarded-Proto $$scheme;
proxy_pass https://dls-backend$$request_uri; proxy_pass http://dls-backend$$request_uri;
} }
location = /-/health { location = /-/health {
access_log off; access_log off;
add_header 'Content-Type' 'application/json'; add_header 'Content-Type' 'application/json';
return 200; # '{\"status\":\"up\",\"service\":\"nginx\"}'; return 200 '{\"status\":\"up\",\"service\":\"nginx\"}';
} }
} }
@ -84,12 +98,11 @@ services:
server_name _; server_name _;
location /leasing/v1/lessor/shutdown { location /leasing/v1/lessor/shutdown {
proxy_ssl_verify off;
proxy_set_header Host $$http_host; proxy_set_header Host $$http_host;
proxy_set_header X-Real-IP $$remote_addr; proxy_set_header X-Real-IP $$remote_addr;
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $$scheme; proxy_set_header X-Forwarded-Proto $$scheme;
proxy_pass https://dls-backend/leasing/v1/lessor/shutdown; proxy_pass http://dls-backend/leasing/v1/lessor/shutdown;
} }
location / { location / {
@ -99,16 +112,7 @@ services:
} }
EON EON
nginx nginx
EOF' EOF"
dls:
image: collinwebdesigns/fastapi-dls:latest
restart: always
environment:
<<: *dls-variables
volumes:
- /opt/docker/fastapi-dls/cert:/app/cert
- db:/app/database
volumes: volumes:
db: db:

View File

@ -3,7 +3,7 @@ uvicorn[standard]==0.20.0
python-jose==3.3.0 python-jose==3.3.0
pycryptodome==3.16.0 pycryptodome==3.16.0
python-dateutil==2.8.2 python-dateutil==2.8.2
sqlalchemy==1.4.45 sqlalchemy==1.4.46
markdown==3.4.1 markdown==3.4.1
python-dotenv==0.21.0 python-dotenv==0.21.0
jinja2==3.1.2 jinja2==3.1.2