feat(rack): detect U overlaps within a rack face
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3324c01810
commit
a1b889209a
2 changed files with 55 additions and 0 deletions
|
|
@ -94,3 +94,24 @@ def validate_item(fm: dict) -> None:
|
||||||
raise SchemaError(
|
raise SchemaError(
|
||||||
f"{name}: occupies U{u}..U{u + h - 1}, exceeds {RACK_UNITS}U"
|
f"{name}: occupies U{u}..U{u + h - 1}, exceeds {RACK_UNITS}U"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def check_overlaps(items: list[dict]) -> None:
|
||||||
|
"""Raise if two items share a U on the same face within one rack."""
|
||||||
|
occupied: dict[tuple[str, int], str] = {}
|
||||||
|
for fm in items:
|
||||||
|
face = fm.get("rack_face")
|
||||||
|
if face in ZERO_U_FACES:
|
||||||
|
continue
|
||||||
|
faces = ("front", "rear") if face == "both" else (face,)
|
||||||
|
u = fm["rack_u"]
|
||||||
|
h = fm["u_height"]
|
||||||
|
name = fm.get("hostname", "?")
|
||||||
|
for f in faces:
|
||||||
|
for uu in range(u, u + h):
|
||||||
|
key = (f, uu)
|
||||||
|
if key in occupied:
|
||||||
|
raise SchemaError(
|
||||||
|
f"U{uu} {f}: {name} overlaps {occupied[key]}"
|
||||||
|
)
|
||||||
|
occupied[key] = name
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,37 @@ def test_validate_accepts_zero_u_rail():
|
||||||
def test_validate_rejects_missing_units_on_faced_item():
|
def test_validate_rejects_missing_units_on_faced_item():
|
||||||
with pytest.raises(gen_rack.SchemaError):
|
with pytest.raises(gen_rack.SchemaError):
|
||||||
gen_rack.validate_item(item(rack_face="front"))
|
gen_rack.validate_item(item(rack_face="front"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_overlaps_detects_same_face_overlap():
|
||||||
|
items = [
|
||||||
|
item(hostname="a", rack_u=1, u_height=2, rack_face="front"),
|
||||||
|
item(hostname="b", rack_u=2, u_height=1, rack_face="front"),
|
||||||
|
]
|
||||||
|
with pytest.raises(gen_rack.SchemaError):
|
||||||
|
gen_rack.check_overlaps(items)
|
||||||
|
|
||||||
|
|
||||||
|
def test_overlaps_allows_same_u_different_face():
|
||||||
|
items = [
|
||||||
|
item(hostname="a", rack_u=5, u_height=1, rack_face="front"),
|
||||||
|
item(hostname="b", rack_u=5, u_height=1, rack_face="rear"),
|
||||||
|
]
|
||||||
|
gen_rack.check_overlaps(items) # no raise
|
||||||
|
|
||||||
|
|
||||||
|
def test_overlaps_both_face_conflicts_with_front():
|
||||||
|
items = [
|
||||||
|
item(hostname="a", rack_u=5, u_height=1, rack_face="both"),
|
||||||
|
item(hostname="b", rack_u=5, u_height=1, rack_face="front"),
|
||||||
|
]
|
||||||
|
with pytest.raises(gen_rack.SchemaError):
|
||||||
|
gen_rack.check_overlaps(items)
|
||||||
|
|
||||||
|
|
||||||
|
def test_overlaps_ignores_zero_u_rails():
|
||||||
|
items = [
|
||||||
|
item(hostname="p1", rack_face="left"),
|
||||||
|
item(hostname="p2", rack_face="left"),
|
||||||
|
]
|
||||||
|
gen_rack.check_overlaps(items) # no raise
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue