mirror of
https://github.com/dtzp555-max/aci-sim.git
synced 2026-07-21 21:15:12 +00:00
Initial public release — aci-sim v0.16.0
aci-sim is a stateful REST simulator of a 2-site Cisco ACI fabric (per-site APIC + ND/NDO management planes) — for testing ACI automation (Ansible cisco.aci / cisco.mso, aci-py, custom REST clients) and CI gates without real hardware. Highlights: APIC + NDO REST surface served from one in-memory MIT built from a declarative topology.yaml; port mode + sandbox (real per-device IPs on :443) run modes; LLDP/CDP neighbor visibility; NDO->APIC deploy mirror (multi-site templates materialize onto the target sites' APIC stores); real-APIC fvBD default attributes; file-backed state save/restore; an `aci-sim` CLI (validate/show/graph/run/new/init/lldp); and an 888-test suite. History squashed for the public release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
"""build/health_faults.py — healthInst, faultInst, coopPol/coopInst, configExportP.
|
||||
|
||||
healthInst DN (read by topology.py line 160-163):
|
||||
topology/pod-{pod}/node-{id}/sys/health
|
||||
→ connector.query_dn(dn) → item.get("healthInst", {}).get("attributes", {})
|
||||
|
||||
faultInst DNs must:
|
||||
1. Start with topology/pod-{pod}/node-{id}/ (for node-scoped queries)
|
||||
2. Contain /node-{id}/ (for topology.py line 196 grouping regex)
|
||||
Required attrs: severity, code, lc, type, subject, descr, created, lastTransition
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from aci_sim.mit.mo import MO
|
||||
from aci_sim.mit.store import MITStore
|
||||
from aci_sim.topology.schema import Site, Topology
|
||||
|
||||
_CREATED_TS = "2026-01-01T00:00:00.000+00:00"
|
||||
|
||||
|
||||
def build(topo: Topology, site: Site, store: MITStore) -> None:
|
||||
"""Emit health/fault/coop/config MOs for *site*."""
|
||||
pod = site.pod
|
||||
faults_cfg = topo.faults
|
||||
hd = faults_cfg.health_defaults
|
||||
|
||||
# ---- Per-node healthInst --------------------------------------------------
|
||||
for node in site.all_nodes():
|
||||
store.add(MO(
|
||||
"healthInst",
|
||||
dn=f"topology/pod-{pod}/node-{node.id}/sys/health",
|
||||
cur=str(hd.node),
|
||||
min=str(hd.node),
|
||||
max="100",
|
||||
prev=str(hd.node),
|
||||
))
|
||||
|
||||
# ---- Per-controller healthInst --------------------------------------------
|
||||
# Real APIC exposes controller (role=controller, node IDs 1..N) health at
|
||||
# the same .../sys/health DN shape as switch nodes; fabric.py already
|
||||
# builds a topSystem at topology/pod-{pod}/node-{cid}/sys for each
|
||||
# controller, so this just adds the matching healthInst there too.
|
||||
for cid in range(1, site.controllers + 1):
|
||||
store.add(MO(
|
||||
"healthInst",
|
||||
dn=f"topology/pod-{pod}/node-{cid}/sys/health",
|
||||
cur=str(hd.node),
|
||||
min=str(hd.node),
|
||||
max="100",
|
||||
prev=str(hd.node),
|
||||
))
|
||||
|
||||
# ---- Per-tenant healthInst (for tenants deployed in this site) -----------
|
||||
for tenant in topo.tenants:
|
||||
if site.name not in tenant.sites:
|
||||
continue
|
||||
store.add(MO(
|
||||
"healthInst",
|
||||
dn=f"uni/tn-{tenant.name}/health",
|
||||
cur=str(hd.tenant),
|
||||
min=str(hd.tenant),
|
||||
max="100",
|
||||
prev=str(hd.tenant),
|
||||
))
|
||||
|
||||
# ---- Seeded faultInst (node-local DNs for node-scoped query support) -----
|
||||
# Map node_id → pod for this site
|
||||
site_node_pods: dict[int, int] = {n.id: pod for n in site.all_nodes()}
|
||||
|
||||
for seed in faults_cfg.seed:
|
||||
node_pod = site_node_pods.get(seed.node)
|
||||
if node_pod is None:
|
||||
continue # this fault belongs to a different site's node
|
||||
# seed.code already carries the full ACI fault code (e.g. "F0532") —
|
||||
# do NOT prepend another "F" (that produced invalid "FF0532").
|
||||
fault_dn = (
|
||||
f"topology/pod-{node_pod}/node-{seed.node}"
|
||||
f"/local/svc-policyelem-id-0/uni/fault-{seed.code}"
|
||||
)
|
||||
store.add(MO(
|
||||
"faultInst",
|
||||
dn=fault_dn,
|
||||
severity=seed.severity,
|
||||
code=seed.code,
|
||||
descr=seed.descr,
|
||||
created=_CREATED_TS,
|
||||
lastTransition=_CREATED_TS,
|
||||
lc="raised",
|
||||
type="operational",
|
||||
subject="node",
|
||||
))
|
||||
|
||||
# ---- coopPol + coopInst --------------------------------------------------
|
||||
store.add(MO("coopPol", dn="uni/fabric/pol-coop", name="coop"))
|
||||
for node in site.all_nodes():
|
||||
store.add(MO(
|
||||
"coopInst",
|
||||
dn=f"topology/pod-{pod}/node-{node.id}/local/svc-coop-id-0/uni/epp/fv-[coop]/node-{node.id}",
|
||||
operSt="formed",
|
||||
))
|
||||
|
||||
# ---- configExportP + configJob (backup/export stubs) ---------------------
|
||||
store.add(MO(
|
||||
"configExportP",
|
||||
dn="uni/fabric/configexp-defaultOneTime",
|
||||
name="defaultOneTime",
|
||||
))
|
||||
store.add(MO(
|
||||
"configJob",
|
||||
dn="uni/fabric/configexp-defaultOneTime/job-defaultOneTime",
|
||||
operSt="success",
|
||||
executeTime=_CREATED_TS,
|
||||
))
|
||||
Reference in New Issue
Block a user