Version 2.8.38: eine Rechnung fuer die Resttage, Module benannt
This commit is contained in:
1 parent
970f45cdf7
commit
dce29fbaa4
6 files changed
+39
-5
No files matched your search
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm"
|
name = "tesm"
|
||||||
version = "2.8.37"
|
version = "2.8.38"
|
||||||
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm-core"
|
name = "tesm-core"
|
||||||
version = "2.8.19"
|
version = "2.8.20"
|
||||||
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -193,7 +193,18 @@ def zustand_als_auskunft(state: "LicenseState") -> dict[str, Any]:
|
|||||||
"days_left": (status.days_left if status and not status.lifetime else None),
|
"days_left": (status.days_left if status and not status.lifetime else None),
|
||||||
"expiring_soon": bool(status.expiring_soon) if status else False,
|
"expiring_soon": bool(status.expiring_soon) if status else False,
|
||||||
"grace_active": bool(status.grace_active) if status else False,
|
"grace_active": bool(status.grace_active) if status else False,
|
||||||
"modules": sorted(state.modules_in_use),
|
# Drei Angaben, weil zwei davon verschieden sein koennen und die
|
||||||
|
# Verwechslung teuer ist: "modules" ist, was die **Lizenz** freigibt --
|
||||||
|
# dieselbe Liste, die der Lizenzserver zeigt. Was davon vor Ort
|
||||||
|
# abgeschaltet wurde, steht daneben.
|
||||||
|
#
|
||||||
|
# Vorher stand hier allein das Laufende. Beim Kunden fehlte darin
|
||||||
|
# "dhcp", waehrend die Lizenzseite es auswies -- es war lediglich unter
|
||||||
|
# Verwaltung -> System abgeschaltet. Aus der Antwort ging das nicht
|
||||||
|
# hervor, und damit sah es nach einem Lizenzproblem aus.
|
||||||
|
"modules": sorted(state.modules),
|
||||||
|
"modules_active": sorted(state.modules_in_use),
|
||||||
|
"modules_off": sorted(state.modules_off),
|
||||||
"customer": state.customer_name,
|
"customer": state.customer_name,
|
||||||
"last_heartbeat_at": state.last_heartbeat_at,
|
"last_heartbeat_at": state.last_heartbeat_at,
|
||||||
"error": state.error,
|
"error": state.error,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm-licensing"
|
name = "tesm-licensing"
|
||||||
version = "2.7.7"
|
version = "2.7.8"
|
||||||
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
|
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = ["cryptography>=42"]
|
dependencies = ["cryptography>=42"]
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ from .license import (
|
|||||||
key_id,
|
key_id,
|
||||||
license_status,
|
license_status,
|
||||||
parse_iso,
|
parse_iso,
|
||||||
|
tage_bis,
|
||||||
split_bundle,
|
split_bundle,
|
||||||
utcnow,
|
utcnow,
|
||||||
verify_license,
|
verify_license,
|
||||||
@@ -103,6 +104,7 @@ __all__ = [
|
|||||||
"machine_identity",
|
"machine_identity",
|
||||||
"new_nonce",
|
"new_nonce",
|
||||||
"parse_iso",
|
"parse_iso",
|
||||||
|
"tage_bis",
|
||||||
"sign",
|
"sign",
|
||||||
"split_bundle",
|
"split_bundle",
|
||||||
"system_fingerprint",
|
"system_fingerprint",
|
||||||
|
|||||||
@@ -221,6 +221,27 @@ def verify_license(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def tage_bis(expires_at: datetime, *, now: datetime | None = None) -> int:
|
||||||
|
"""Restlaufzeit in **angefangenen** Tagen.
|
||||||
|
|
||||||
|
Aufgerundet, und das ist eine Entscheidung: eine Lizenz, die in zwei
|
||||||
|
Stunden ablaeuft, hat "1 Tag" und nicht "0". Null bedeutet hier
|
||||||
|
ausschliesslich *abgelaufen* -- eine gueltige Lizenz, die mit "0 Tage"
|
||||||
|
dasteht, liest sich wie eine tote.
|
||||||
|
|
||||||
|
**Es gibt genau diese eine Rechnung.** Der Lizenzserver hatte eine zweite,
|
||||||
|
abgerundete: dieselbe Lizenz zeigte in seiner Oberflaeche "21 Tage" und im
|
||||||
|
Abruf beim Kunden "22". Zwei Zahlen fuer dieselbe Frage sind schlimmer als
|
||||||
|
eine ungenaue -- sie kosten jemanden einen Nachmittag mit der Suche nach
|
||||||
|
einem Fehler, den es nicht gibt.
|
||||||
|
"""
|
||||||
|
moment = now or utcnow()
|
||||||
|
sekunden = int((expires_at - moment).total_seconds())
|
||||||
|
if sekunden <= 0:
|
||||||
|
return 0
|
||||||
|
return -(-sekunden // 86400)
|
||||||
|
|
||||||
|
|
||||||
def license_status(
|
def license_status(
|
||||||
document: Mapping[str, Any],
|
document: Mapping[str, Any],
|
||||||
*,
|
*,
|
||||||
@@ -278,7 +299,7 @@ def license_status(
|
|||||||
days_left = 0
|
days_left = 0
|
||||||
days_since_expiry = int((moment - expires_at).total_seconds() // 86400)
|
days_since_expiry = int((moment - expires_at).total_seconds() // 86400)
|
||||||
else:
|
else:
|
||||||
days_left = -(-int(delta.total_seconds()) // 86400)
|
days_left = tage_bis(expires_at, now=moment)
|
||||||
days_since_expiry = None
|
days_since_expiry = None
|
||||||
|
|
||||||
grace_active = bool(
|
grace_active = bool(
|
||||||
|
|||||||
Reference in new issue
Block a user