diff --git a/docs/schema/flavor.schema.json b/docs/schema/flavor.schema.json new file mode 120000 index 000000000..28bad20bd --- /dev/null +++ b/docs/schema/flavor.schema.json @@ -0,0 +1 @@ +../../schema/flavor.schema.json \ No newline at end of file diff --git a/python/ironic-understack/ironic_understack/flavor_spec.py b/python/ironic-understack/ironic_understack/flavor_spec.py index 8848f80db..30fcd1262 100644 --- a/python/ironic-understack/ironic_understack/flavor_spec.py +++ b/python/ironic-understack/ironic_understack/flavor_spec.py @@ -6,6 +6,14 @@ from ironic_understack.machine import Machine +@dataclass +class PciSpec: + vendor_id: str + device_id: str + sub_vendor_id: str + sub_device_id: str + + @dataclass class FlavorSpec: name: str @@ -13,8 +21,9 @@ class FlavorSpec: model: str memory_gb: int cpu_cores: int - cpu_models: list[str] + cpu_model: str drives: list[int] + pci: list[PciSpec] @staticmethod def from_yaml(yaml_str: str) -> "FlavorSpec": @@ -25,8 +34,9 @@ def from_yaml(yaml_str: str) -> "FlavorSpec": model=data["model"], memory_gb=data["memory_gb"], cpu_cores=data["cpu_cores"], - cpu_models=data["cpu_models"], + cpu_model=data.get("cpu_model", data.get("cpu_models", [""]).pop()), drives=data["drives"], + pci=data.get("pci", []), ) @staticmethod @@ -67,7 +77,7 @@ def score_machine(self, machine: Machine): if ( machine.memory_gb == self.memory_gb and machine.disk_gb in self.drives - and machine.cpu in self.cpu_models + and machine.cpu == self.cpu_model ): return 100 @@ -80,7 +90,7 @@ def score_machine(self, machine: Machine): return 0 # Rule 4: Machine must match the flavor on one of the CPU models exactly - if machine.cpu not in self.cpu_models: + if machine.cpu != self.cpu_model: return 0 # Rule 5 and 6: Rank based on exact matches or excess capacity diff --git a/python/ironic-understack/ironic_understack/tests/test_flavor_spec.py b/python/ironic-understack/ironic_understack/tests/test_flavor_spec.py index 16cdcc8b5..8e06a3bc0 100644 --- a/python/ironic-understack/ironic_understack/tests/test_flavor_spec.py +++ b/python/ironic-understack/ironic_understack/tests/test_flavor_spec.py @@ -14,8 +14,7 @@ def valid_yaml(): model: PowerEdge R7615 memory_gb: 7777 cpu_cores: 245 -cpu_models: - - AMD EPYC 9254 245-Core Processor +cpu_model: AMD EPYC 9254 245-Core Processor drives: - 960 - 960 @@ -50,7 +49,7 @@ def test_from_yaml(valid_yaml): assert spec.model == "PowerEdge R7615" assert spec.memory_gb == 7777 assert spec.cpu_cores == 245 - assert spec.cpu_models == ["AMD EPYC 9254 245-Core Processor"] + assert spec.cpu_model == "AMD EPYC 9254 245-Core Processor" assert spec.drives == [960, 960] @@ -119,8 +118,9 @@ def flavors(): model="Fake Machine", memory_gb=100, cpu_cores=13, - cpu_models=["AMD EPYC 9254 245-Core Processor"], + cpu_model="AMD EPYC 9254 245-Core Processor", drives=[500, 500], + pci=[], ), FlavorSpec( name="medium", @@ -128,8 +128,9 @@ def flavors(): model="Fake Machine", memory_gb=200, cpu_cores=15, - cpu_models=["AMD EPYC 9254 245-Core Processor"], + cpu_model="AMD EPYC 9254 245-Core Processor", drives=[1500, 1500], + pci=[], ), FlavorSpec( name="large", @@ -137,8 +138,9 @@ def flavors(): model="Fake Machine", memory_gb=400, cpu_cores=27, - cpu_models=["AMD EPYC 9254 245-Core Processor"], + cpu_model="AMD EPYC 9254 245-Core Processor", drives=[1800, 1800], + pci=[], ), ] diff --git a/python/ironic-understack/ironic_understack/tests/test_matcher.py b/python/ironic-understack/ironic_understack/tests/test_matcher.py index 89dd22f8d..2e4455fc3 100644 --- a/python/ironic-understack/ironic_understack/tests/test_matcher.py +++ b/python/ironic-understack/ironic_understack/tests/test_matcher.py @@ -13,8 +13,9 @@ def sample_flavors(): model="Fake Machine", memory_gb=4, cpu_cores=2, - cpu_models=["x86"], + cpu_model="x86", drives=[20], + pci=[], ), FlavorSpec( name="medium", @@ -22,8 +23,9 @@ def sample_flavors(): model="Fake Machine", memory_gb=8, cpu_cores=4, - cpu_models=["x86"], + cpu_model="x86", drives=[40], + pci=[], ), FlavorSpec( name="large", @@ -31,8 +33,9 @@ def sample_flavors(): model="Fake Machine", memory_gb=16, cpu_cores=8, - cpu_models=["x86"], + cpu_model="x86", drives=[80], + pci=[], ), ] diff --git a/schema/README.md b/schema/README.md index ff56aec9f..ff0139fb2 100644 --- a/schema/README.md +++ b/schema/README.md @@ -5,3 +5,8 @@ ```bash curl -o argo-workflows.json https://raw.githubusercontent.com/argoproj/argo-workflows/master/api/jsonschema/schema.json ``` + +## flavor.schema + +Used to define hardware identification / mapping for Ironic hardware to Nova flavors. +The flavors hook uses these files to set properties automatically on the nodes. diff --git a/schema/flavor.schema.json b/schema/flavor.schema.json new file mode 100644 index 000000000..397b8c94e --- /dev/null +++ b/schema/flavor.schema.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://rackerlabs.github.io/understack/schema/flavor.schema.json", + "title": "UnderStack Hardware Flavor", + "description": "Server flavor configuration schema", + "type": "object", + "properties": { + "name": { + "description": "Flavor name for specified configuration (ie gp01.s)", + "type": "string" + }, + "manufacturer": { + "description": "Manufacturer of the hardware chassis", + "type": "string" + }, + "model": { + "description": "Model of the hardware chassis", + "type": "string" + }, + "cpu_cores": { + "description": "Total CPU cores.", + "type": "number" + }, + "cpu_model": { + "description": "Processor model", + "type": "string" + }, + "cpu_models": { + "description": "Processor models", + "type": "array", + "items": { + "type": "string", + "description": "Processor model" + }, + "minItems": 1, + "maxItems": 1 + }, + "memory_gb": { + "description": "Total memory in GB", + "type": "number" + }, + "memory_modules": { + "description": "Memory modules", + "type": "array", + "items": { + "type": "number", + "description": "Capacity in GB" + } + }, + "drives": { + "description": "Drives", + "type": "array", + "items": { + "type": "number", + "description": "Capacity in GB" + } + }, + "pci": { + "description": "PCI devices", + "type": "array", + "items": { + "type": "object", + "description": "PCI device", + "properties": { + "vendor_id": { + "type": "string" + }, + "device_id": { + "type": "string" + }, + "sub_vendor_id": { + "type": "string" + }, + "sub_device_id": { + "type": "string" + } + }, + "required": ["vendor_id", "device_id", "sub_vendor_id", "sub_device_id"] + + } + } + }, + "required": [ "name", "manufacturer", "model", "cpu_cores", "cpu_models", "memory_gb", "drives" ] +}