Files
proxmox-api-simulator/app/simulation/scenarios.py
T
2026-07-13 00:16:57 +03:00

50 lines
1.5 KiB
Python

"""Seeded deterministic fault-rule evaluation."""
from __future__ import annotations
import hashlib
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class FaultContext:
method: str
path: str
principal: str | None = None
node: str | None = None
vmid: str | None = None
call_number: int = 1
@dataclass(frozen=True, slots=True)
class FaultRule:
kind: str
probability: float = 1.0
method: str | None = None
path_prefix: str | None = None
principal: str | None = None
node: str | None = None
vmid: str | None = None
call_number: int | None = None
def __post_init__(self) -> None:
if not 0 <= self.probability <= 1:
raise ValueError("fault probability must be between zero and one")
def matches(rule: FaultRule, context: FaultContext, seed: int) -> bool:
filters = (
(rule.method, context.method),
(rule.principal, context.principal),
(rule.node, context.node),
(rule.vmid, context.vmid),
(rule.call_number, context.call_number),
)
if any(expected is not None and expected != actual for expected, actual in filters):
return False
if rule.path_prefix is not None and not context.path.startswith(rule.path_prefix):
return False
material = f"{seed}:{rule.kind}:{context.method}:{context.path}:{context.call_number}"
sample = int.from_bytes(hashlib.sha256(material.encode()).digest()[:8], "big") / 2**64
return sample < rule.probability