From 3c19fc9d5b51106d01e047304d028e40c5f06a2e Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 11:49:56 +0100 Subject: [PATCH 01/14] implemented "lease_renewal" attribute as calculated value within what period of time the license must be renewed --- app/main.py | 9 ++++++--- app/orm.py | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/main.py b/app/main.py index 46d8a65..204a55a 100644 --- a/app/main.py +++ b/app/main.py @@ -9,7 +9,7 @@ from dotenv import load_dotenv from fastapi import FastAPI from fastapi.requests import Request from json import loads as json_loads -from datetime import datetime +from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta from calendar import timegm from jose import jws, jwk, jwt, JWTError @@ -43,6 +43,7 @@ INSTANCE_KEY_PUB = load_key(str(env('INSTANCE_KEY_PUB', join(dirname(__file__), TOKEN_EXPIRE_DELTA = relativedelta(days=int(env('TOKEN_EXPIRE_DAYS', 1)), hours=int(env('TOKEN_EXPIRE_HOURS', 0))) LEASE_EXPIRE_DELTA = relativedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)), hours=int(env('LEASE_EXPIRE_HOURS', 0))) 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))) 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) @@ -151,7 +152,8 @@ async def _origins(request: Request, leases: bool = False): for origin in session.query(Origin).all(): x = origin.serialize() if leases: - x['leases'] = list(map(lambda _: _.serialize(), Lease.find_by_origin_ref(db, origin.origin_ref))) + serialize = dict(renewal_period=LEASE_RENEWAL_PERIOD, renewal_delta=LEASE_RENEWAL_DELTA) + x['leases'] = list(map(lambda _: _.serialize(**serialize), Lease.find_by_origin_ref(db, origin.origin_ref))) response.append(x) session.close() return JSONr(response) @@ -168,7 +170,8 @@ async def _leases(request: Request, origin: bool = False): session = sessionmaker(bind=db)() response = [] for lease in session.query(Lease).all(): - x = lease.serialize() + serialize = dict(renewal_period=LEASE_RENEWAL_PERIOD, renewal_delta=LEASE_RENEWAL_DELTA) + x = lease.serialize(**serialize) if origin: lease_origin = session.query(Origin).filter(Origin.origin_ref == lease.origin_ref).first() if lease_origin is not None: diff --git a/app/orm.py b/app/orm.py index aadc0ef..50ff3ce 100644 --- a/app/orm.py +++ b/app/orm.py @@ -81,7 +81,7 @@ class Lease(Base): def __repr__(self): return f'Lease(origin_ref={self.origin_ref}, lease_ref={self.lease_ref}, expires={self.lease_expires})' - def serialize(self) -> dict: + def serialize(self, renewal_period: float, renewal_delta: datetime.timedelta) -> dict: return { 'lease_ref': self.lease_ref, 'origin_ref': self.origin_ref, @@ -89,6 +89,7 @@ class Lease(Base): 'lease_created': self.lease_created.isoformat(), 'lease_expires': self.lease_expires.isoformat(), 'lease_updated': self.lease_updated.isoformat(), + 'lease_renewal': Lease.calculate_renewal(renewal_period, renewal_delta), } @staticmethod @@ -156,6 +157,19 @@ class Lease(Base): session.close() return deletions + @staticmethod + def calculate_renewal(renewal_period: float, delta: datetime.timedelta): + """ + LEASE_RENEWAL_PERIOD=0.2 # 20% + delta = datetime.timedelta(days=1) + renew = delta.total_seconds() * LEASE_RENEWAL_PERIOD + renew = timedelta(seconds=renew) + expires = delta - renew # 19.2 + """ + renew = delta.total_seconds() * renewal_period + renew = datetime.timedelta(seconds=renew) + return delta - renew + def init(engine: Engine): tables = [Origin, Lease] From 7ef071f92b1de522fb5142cd2ceb54ad558175d3 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 14:57:09 +0100 Subject: [PATCH 02/14] removed fastapi-dls.service from conffiles --- .DEBIAN/conffiles | 1 - 1 file changed, 1 deletion(-) diff --git a/.DEBIAN/conffiles b/.DEBIAN/conffiles index cd8fdd7..008d731 100644 --- a/.DEBIAN/conffiles +++ b/.DEBIAN/conffiles @@ -1,2 +1 @@ /etc/fastapi-dls/env -/etc/systemd/system/fastapi-dls.service From d69d83392316cb1286a76bab2aeb96baa473ad77 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 14:57:39 +0100 Subject: [PATCH 03/14] migrated "[[ ]]" if statements to "[ ]" --- .DEBIAN/postinst | 8 ++++---- .DEBIAN/postrm | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.DEBIAN/postinst b/.DEBIAN/postinst index fbf9b82..8213736 100644 --- a/.DEBIAN/postinst +++ b/.DEBIAN/postinst @@ -3,7 +3,7 @@ WORKING_DIR=/usr/share/fastapi-dls CONFIG_DIR=/etc/fastapi-dls -if [[ ! -f $CONFIG_DIR/instance.private.pem ]]; then +if [ ! -f $CONFIG_DIR/instance.private.pem ]; then echo "> Create dls-instance keypair ..." openssl genrsa -out $CONFIG_DIR/instance.private.pem 2048 openssl rsa -in $CONFIG_DIR/instance.private.pem -outform PEM -pubout -out $CONFIG_DIR/instance.public.pem @@ -12,8 +12,8 @@ else fi while true; do - [[ -f $CONFIG_DIR/webserver.key ]] && default_answer="N" || default_answer="Y" - [[ $default_answer == "Y" ]] && V="Y/n" || V="y/N" + [ -f $CONFIG_DIR/webserver.key ] && default_answer="N" || default_answer="Y" + [ $default_answer == "Y" ] && V="Y/n" || V="y/N" read -p "> Do you wish to create self-signed webserver certificate? [${V}]" yn yn=${yn:-$default_answer} # ${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted. case $yn in @@ -27,7 +27,7 @@ while true; do esac done -if [[ -f $CONFIG_DIR/webserver.key ]]; then +if [ -f $CONFIG_DIR/webserver.key ]; then echo "> Starting service ..." systemctl start fastapi-dls.service diff --git a/.DEBIAN/postrm b/.DEBIAN/postrm index b99d0fa..7c21ae7 100755 --- a/.DEBIAN/postrm +++ b/.DEBIAN/postrm @@ -1,6 +1,6 @@ #!/bin/bash -if [[ -f /etc/systemd/system/fastapi-dls.service ]]; then +if [ -f /etc/systemd/system/fastapi-dls.service ]; then echo "> Removing service file." rm /etc/systemd/system/fastapi-dls.service fi From 1e4070a1bacb3e31f75ae94328fb69888dba3309 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 14:57:54 +0100 Subject: [PATCH 04/14] added remove "/usr/share/fastapi-dls" to "postrm" --- .DEBIAN/postrm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.DEBIAN/postrm b/.DEBIAN/postrm index 7c21ae7..63ca44f 100755 --- a/.DEBIAN/postrm +++ b/.DEBIAN/postrm @@ -5,4 +5,9 @@ if [ -f /etc/systemd/system/fastapi-dls.service ]; then rm /etc/systemd/system/fastapi-dls.service fi +if [ -d /usr/share/fastapi-dls ]; then + echo "> Removing app." + rm -r /usr/share/fastapi-dls +fi + # todo From 70f7d3f48336282a4abab8f62b14f332cd53ad4d Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 15:36:38 +0100 Subject: [PATCH 05/14] mark Let's Encrypt section as optional --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 86f27ce..b2ae198 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,7 @@ pacman -U --noconfirm fastapi-dls.pkg.tar.zst Start with `systemctl start fastapi-dls.service` and enable autostart with `systemctl enable fastapi-dls.service`. -## Let's Encrypt Certificate +## Let's Encrypt Certificate (optional) If you're using installation via docker, you can use `traefik`. Please refer to their documentation. From 651af4cc8277a84e30eb12d7567d4ecd628e07ef Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 16:29:21 +0100 Subject: [PATCH 06/14] fixed client-token url and added wget als alternative to curl --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b2ae198..22aed43 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,11 @@ Packages are available here: ```shell pacman -Sy FILENAME=/opt/fastapi-dls.pkg.tar.zst -url -o $FILENAME + +curl -o $FILENAME +# or +wget -O $FILENAME + pacman -U --noconfirm fastapi-dls.pkg.tar.zst ``` @@ -267,7 +271,10 @@ Successfully tested with this package versions: ## Linux ```shell -curl --insecure -L -X GET https:///client-token -o /etc/nvidia/ClientConfigToken/client_configuration_token_$(date '+%d-%m-%Y-%H-%M-%S').tok +curl --insecure -L -X GET https:///-/client-token -o /etc/nvidia/ClientConfigToken/client_configuration_token_$(date '+%d-%m-%Y-%H-%M-%S').tok +# or +wget --no-check-certificate -O /etc/nvidia/ClientConfigToken/client_configuration_token_$(date '+%d-%m-%Y-%H-%M-%S').tok https:///-/client-token + service nvidia-gridd restart nvidia-smi -q | grep "License" ``` @@ -280,7 +287,7 @@ Now restart `NvContainerLocalSystem` service. **Power-Shell** ```Shell -curl.exe --insecure -L -X GET https:///client-token -o "C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken\client_configuration_token_$($(Get-Date).tostring('dd-MM-yy-hh-mm-ss')).tok" +curl.exe --insecure -L -X GET https:///-/client-token -o "C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken\client_configuration_token_$($(Get-Date).tostring('dd-MM-yy-hh-mm-ss')).tok" Restart-Service NVDisplay.ContainerLocalSystem 'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe' -q | Select-String "License" ``` From b09bb091a5e2c306c8abda2866a57cedfc52ad05 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 16:29:32 +0100 Subject: [PATCH 07/14] bump version to 1.3.3 --- version.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.env b/version.env index 0c794cf..93176fc 100644 --- a/version.env +++ b/version.env @@ -1 +1 @@ -VERSION=1.3.2 +VERSION=1.3.3 From b2e6fab294614c3e94b4a2e2929f33f6b1cf9cd2 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 16:37:45 +0100 Subject: [PATCH 08/14] fixes --- app/orm.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/orm.py b/app/orm.py index 50ff3ce..bbabbbc 100644 --- a/app/orm.py +++ b/app/orm.py @@ -1,4 +1,5 @@ -import datetime +from datetime import datetime, timedelta +from dateutil.relativedelta import relativedelta from sqlalchemy import Column, VARCHAR, CHAR, ForeignKey, DATETIME, update, and_, inspect from sqlalchemy.ext.declarative import declarative_base @@ -81,7 +82,10 @@ class Lease(Base): def __repr__(self): return f'Lease(origin_ref={self.origin_ref}, lease_ref={self.lease_ref}, expires={self.lease_expires})' - def serialize(self, renewal_period: float, renewal_delta: datetime.timedelta) -> dict: + def serialize(self, renewal_period: float, renewal_delta: timedelta) -> dict: + lease_renewal = int(Lease.calculate_renewal(renewal_period, renewal_delta).total_seconds()) + lease_renewal = self.lease_created + relativedelta(seconds=lease_renewal) + return { 'lease_ref': self.lease_ref, 'origin_ref': self.origin_ref, @@ -89,7 +93,7 @@ class Lease(Base): 'lease_created': self.lease_created.isoformat(), 'lease_expires': self.lease_expires.isoformat(), 'lease_updated': self.lease_updated.isoformat(), - 'lease_renewal': Lease.calculate_renewal(renewal_period, renewal_delta), + 'lease_renewal': lease_renewal.isoformat(), } @staticmethod @@ -134,7 +138,7 @@ class Lease(Base): return entity @staticmethod - def renew(engine: Engine, lease: "Lease", lease_expires: datetime.datetime, lease_updated: datetime.datetime): + def renew(engine: Engine, lease: "Lease", lease_expires: datetime, lease_updated: datetime): session = sessionmaker(bind=engine)() x = dict(lease_expires=lease_expires, lease_updated=lease_updated) session.execute(update(Lease).where(and_(Lease.origin_ref == lease.origin_ref, Lease.lease_ref == lease.lease_ref)).values(**x)) @@ -158,16 +162,17 @@ class Lease(Base): return deletions @staticmethod - def calculate_renewal(renewal_period: float, delta: datetime.timedelta): + def calculate_renewal(renewal_period: float, delta: timedelta) -> timedelta: """ + import datetime LEASE_RENEWAL_PERIOD=0.2 # 20% delta = datetime.timedelta(days=1) renew = delta.total_seconds() * LEASE_RENEWAL_PERIOD - renew = timedelta(seconds=renew) + renew = datetime.timedelta(seconds=renew) expires = delta - renew # 19.2 """ renew = delta.total_seconds() * renewal_period - renew = datetime.timedelta(seconds=renew) + renew = timedelta(seconds=renew) return delta - renew From f60f08d543e71c8ed0256be567c1f12fd27e79ae Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 16:57:15 +0100 Subject: [PATCH 09/14] run powershell as administrator --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22aed43..ca067ca 100644 --- a/README.md +++ b/README.md @@ -284,7 +284,7 @@ nvidia-smi -q | grep "License" Download file and place it into `C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken`. Now restart `NvContainerLocalSystem` service. -**Power-Shell** +**Power-Shell** (run as administrator!) ```Shell curl.exe --insecure -L -X GET https:///-/client-token -o "C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken\client_configuration_token_$($(Get-Date).tostring('dd-MM-yy-hh-mm-ss')).tok" From bf858b38f4cabca29b63e9aa6b508ecc588aa4aa Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 17:09:13 +0100 Subject: [PATCH 10/14] fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ca067ca..6028bfd 100644 --- a/README.md +++ b/README.md @@ -281,7 +281,7 @@ nvidia-smi -q | grep "License" ## Windows -Download file and place it into `C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken`. +Download *client-token* and place it into `C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken`. Now restart `NvContainerLocalSystem` service. **Power-Shell** (run as administrator!) @@ -292,7 +292,7 @@ Restart-Service NVDisplay.ContainerLocalSystem 'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe' -q | Select-String "License" ``` -## Endpoints +# Endpoints ### `GET /` From 059a51fe74a8017389919f3ada3ddcbbaf74fe61 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 17:25:48 +0100 Subject: [PATCH 11/14] refactored commands --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6028bfd..28a7bdc 100644 --- a/README.md +++ b/README.md @@ -270,28 +270,66 @@ Successfully tested with this package versions: ## Linux +Download *client-token* and place it into `/etc/nvidia/ClientConfigToken`: + ```shell curl --insecure -L -X GET https:///-/client-token -o /etc/nvidia/ClientConfigToken/client_configuration_token_$(date '+%d-%m-%Y-%H-%M-%S').tok # or wget --no-check-certificate -O /etc/nvidia/ClientConfigToken/client_configuration_token_$(date '+%d-%m-%Y-%H-%M-%S').tok https:///-/client-token +``` +Restart `nvidia-gridd` service: + +```shell service nvidia-gridd restart +``` + +Check licensing status: + +```shell nvidia-smi -q | grep "License" ``` -## Windows +Output should be something like: -Download *client-token* and place it into `C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken`. -Now restart `NvContainerLocalSystem` service. +```text +vGPU Software Licensed Product + License Status : Licensed (Expiry: YYYY-M-DD hh:mm:ss GMT) +``` + +Done. For more information check [troubleshoot section](#troubleshoot). + +## Windows **Power-Shell** (run as administrator!) -```Shell +Download *client-token* and place it into `C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken`: + +```shell curl.exe --insecure -L -X GET https:///-/client-token -o "C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken\client_configuration_token_$($(Get-Date).tostring('dd-MM-yy-hh-mm-ss')).tok" -Restart-Service NVDisplay.ContainerLocalSystem -'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe' -q | Select-String "License" ``` +Restart `NvContainerLocalSystem` service: + +```Shell +Restart-Service NVDisplay.ContainerLocalSystem +``` + +Check licensing status: + +```shell +& 'C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe' -q | Select-String "License" +``` + +Output should be something like: + +```text +vGPU Software Licensed Product + License Status : Licensed (Expiry: YYYY-M-DD hh:mm:ss GMT) +``` + +Done. For more information check [troubleshoot section](#troubleshoot). + # Endpoints ### `GET /` From 0ab5969d3a1d5a82bd81109d962a72d55f7af20a Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Tue, 17 Jan 2023 17:27:26 +0100 Subject: [PATCH 12/14] fixes --- app/orm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/orm.py b/app/orm.py index bbabbbc..bfd6557 100644 --- a/app/orm.py +++ b/app/orm.py @@ -84,7 +84,7 @@ class Lease(Base): def serialize(self, renewal_period: float, renewal_delta: timedelta) -> dict: lease_renewal = int(Lease.calculate_renewal(renewal_period, renewal_delta).total_seconds()) - lease_renewal = self.lease_created + relativedelta(seconds=lease_renewal) + lease_renewal = self.lease_updated + relativedelta(seconds=lease_renewal) return { 'lease_ref': self.lease_ref, @@ -173,7 +173,7 @@ class Lease(Base): """ renew = delta.total_seconds() * renewal_period renew = timedelta(seconds=renew) - return delta - renew + return renew def init(engine: Engine): From de17b0f1b5202c76fa1027f03260736474c01c88 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Wed, 18 Jan 2023 07:58:30 +0100 Subject: [PATCH 13/14] fixes --- .DEBIAN/postrm | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.DEBIAN/postrm b/.DEBIAN/postrm index 63ca44f..c3a4023 100755 --- a/.DEBIAN/postrm +++ b/.DEBIAN/postrm @@ -1,13 +1,9 @@ #!/bin/bash -if [ -f /etc/systemd/system/fastapi-dls.service ]; then - echo "> Removing service file." - rm /etc/systemd/system/fastapi-dls.service -fi - -if [ -d /usr/share/fastapi-dls ]; then - echo "> Removing app." - rm -r /usr/share/fastapi-dls -fi +# is removed automatically +#if [ "$1" = purge ] && [ -d /usr/share/fastapi-dls ]; then +# echo "> Removing app." +# rm -r /usr/share/fastapi-dls +#fi # todo From 5bb8f17679e83290bf8591c56beec7a7c1d71a58 Mon Sep 17 00:00:00 2001 From: Oscar Krause Date: Wed, 18 Jan 2023 08:07:55 +0100 Subject: [PATCH 14/14] improvements --- .DEBIAN/postrm | 2 +- .DEBIAN/prerm | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.DEBIAN/postrm b/.DEBIAN/postrm index c3a4023..9c715dd 100755 --- a/.DEBIAN/postrm +++ b/.DEBIAN/postrm @@ -6,4 +6,4 @@ # rm -r /usr/share/fastapi-dls #fi -# todo +echo -e "> Done." diff --git a/.DEBIAN/prerm b/.DEBIAN/prerm index 296c995..3678725 100755 --- a/.DEBIAN/prerm +++ b/.DEBIAN/prerm @@ -1,5 +1,3 @@ #!/bin/bash echo -e "> Starting uninstallation of 'fastapi-dls'!" - -# todo