Skip to content

Commit

Permalink
Implement set_requirements on HostRequirementsWidget
Browse files Browse the repository at this point in the history
This implements several other "setters" on dependant widgets too

This logic could use some testing to ensure its functionality

Signed-off-by: Alex Hughes <[email protected]>
  • Loading branch information
Ahuge committed Dec 16, 2024
1 parent 12eee1f commit 153e19d
Showing 1 changed file with 147 additions and 2 deletions.
149 changes: 147 additions & 2 deletions src/deadline/client/ui/widgets/host_requirements_tab.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,42 @@ def get_requirements(self) -> Optional[Dict[str, Any]]:

return requirements

def set_requirements(self, requirements: Dict[str, Any]):
custom_requirements = {
"attributes": [],
"amounts": [],
}
removed_requirements = {
"attributes": [],
"amounts": [],
}
os_requirements = self.os_requirements_box.get_requirements()
hardware_requirements = self.hardware_requirements_box.get_requirements()

if requirements.get("attributes"):
for requirement in requirements.get("attributes"):
if requirement not in os_requirements:
custom_requirements.get("attributes").append(requirement)
for existing_requirement in os_requirements:
if existing_requirement not in requirements.get("attributes"):
removed_requirements.get("attributes").append(existing_requirement)
for requirement in removed_requirements.get("attributes"):
os_requirements.remove(requirement)

if requirements.get("amounts"):
for requirement in requirements.get("amounts"):
if requirement not in hardware_requirements:
custom_requirements.get("amounts").append(requirement)
for existing_requirement in hardware_requirements:
if existing_requirement not in requirements.get("amounts"):
removed_requirements.get("amounts").append(existing_requirement)
for requirement in removed_requirements.get("amounts"):
hardware_requirements.remove(requirement)

self.custom_requirements_box.set_requirements(custom_requirements)
self.os_requirements_box.set_requirements(os_requirements)
self.hardware_requirements_box.set_requirements(hardware_requirements)


class OverrideRequirementsWidget(QGroupBox): # pylint: disable=too-few-public-methods
"""
Expand Down Expand Up @@ -198,15 +234,17 @@ class OSRequirementsWidget(QGroupBox):
Args:
parent: The parent Qt Widget.
"""
OS_ROW_OPTIONS = ["linux", "macos", "windows"]
CPU_ROW_OPTIONS = ["x86_64", "arm64"]

def __init__(self, parent=None):
super().__init__("", parent=parent)
self.layout = QVBoxLayout(self)
self._build_ui()

def _build_ui(self):
self.os_row = OSRequirementRowWidget("Operating system", ["linux", "macos", "windows"])
self.cpu_row = OSRequirementRowWidget("CPU architecture", ["x86_64", "arm64"])
self.os_row = OSRequirementRowWidget("Operating system", self.OS_ROW_OPTIONS)
self.cpu_row = OSRequirementRowWidget("CPU architecture", self.CPU_ROW_OPTIONS)

self.layout.addWidget(self.os_row)
self.layout.addWidget(self.cpu_row)
Expand Down Expand Up @@ -239,6 +277,23 @@ def get_requirements(self) -> List[Dict[str, Any]]:
)
return requirements

def set_requirements(self, requirements: List[Dict[str, Any]]):
for requirement in requirements:
if requirement.get("name") == "attr.worker.os.family":
if requirement.get("anyOf") not in self.OS_ROW_OPTIONS:
raise ValueError(
"Invalid value {} for option attr.worker.os.family".format(requirement.get("anyOf"))
)
self.os_row.combo_box.setCurrentText(requirement.get("anyOf"))
if requirement.get("name") == "attr.worker.cpu.arch":
if requirement.get("anyOf") not in self.CPU_ROW_OPTIONS:
raise ValueError(
"Invalid value {} for option attr.worker.cpu.arch".format(requirement.get("anyOf"))
)
self.os_row.combo_box.setCurrentText(requirement.get("anyOf"))
else:
raise ValueError("Unknown OS Requirement option of {}".format(requirement.get("name")))


class HardwareRequirementsWidget(QGroupBox): # pylint: disable=too-few-public-methods
"""
Expand Down Expand Up @@ -291,6 +346,26 @@ def get_requirements(self) -> List[Dict[str, Any]]:
self.scratch_space_row.add_requirement(requirements, "amount.worker.disk.scratch")
return requirements

def set_requirements(self, requirements: List[Dict[str, Any]]):
for requirement in requirements:
if requirement.get("name") == "amount.worker.vcpu":
self.cpu_row.update_requirement(requirement)

elif requirement.get("name") == "amount.worker.memory":
self.memory_row.update_requirement(requirement, scaling_factor=1024)

elif requirement.get("name") == "amount.worker.gpu":
self.gpu_row.update_requirement(requirement)

elif requirement.get("name") == "amount.worker.gpu.memory":
self.gpu_memory_row.update_requirement(requirement, scaling_factor=1024)

elif requirement.get("name") == "amount.worker.disk.scratch":
self.scratch_space_row.update_requirement(requirement)

else:
raise ValueError("Unknown Hardware Requirement option of {}".format(requirement.get("name")))


class CustomRequirementsWidget(QGroupBox):
"""
Expand Down Expand Up @@ -431,6 +506,39 @@ def get_requirements(self) -> Dict[str, List]:

return requirements

def set_requirements(self, requirements: Dict[str, List]):
amount_widgets = {}
attribute_widgets = {}
for i in range(self.list_widget.count()):
widget = self.list_widget.itemWidget(self.list_widget.item(i))
widget_requirement = widget.get_requirement()
if widget_requirement:
if isinstance(widget, CustomAmountWidget):
amount_widgets[widget_requirement.get("name")] = widget
elif isinstance(widget, CustomAttributeWidget):
attribute_widgets[widget_requirement.get("name")] = widget
else:
logger.warning(
f"Widget requirement is not a valid expected type: {type(widget)}"
)

for requirement in requirements.get("amounts"):
if requirement.get("name") not in amount_widgets:
logger.warning(
"Amount requirement is not tied to a widget: {}".format(requirement.get("name"))
)
else:
widget = amount_widgets.get(requirement.get("name"))
widget.set_requirement(requirement)
for requirement in requirements.get("attributes"):
if requirement.get("name") not in attribute_widgets:
logger.warning(
"Attribute requirement is not tied to a widget: {}".format(requirement.get("name"))
)
else:
widget = attribute_widgets.get(requirement.get("name"))
widget.set_requirement(requirement)


class CustomCapabilityWidget(QGroupBox):
"""
Expand Down Expand Up @@ -562,6 +670,12 @@ def get_requirement(self) -> Dict[str, Any]:
)
return requirement

def set_requirement(self, requirement: Dict[str, Any]):
if requirement.get("min"):
self.min_spin_box.setValue(requirement.get("min"))
if requirement.get("max"):
self.max_spin_box.setValue(requirement.get("max"))


class CustomAttributeWidget(CustomCapabilityWidget):
"""
Expand Down Expand Up @@ -726,6 +840,31 @@ def get_requirement(self) -> Dict[str, Any]:
)
return requirement

def set_requirement(self, requirement: Dict[str, Any]):
option = ""
if requirement.get("anyOf") and not self.any_of_button.isChecked():
self.any_of_button.setChecked(True)
option = "anyOf"
elif requirement.get("allOf") and self.any_of_button.isChecked():
self.any_of_button.setChecked(False)
option = "allOf"

values = requirement.get(option)
if len(values) > self.value_list_widget.count():
# Added additional values:
for _ in range(len(values) - self.value_list_widget.count()):
self._add_value()
elif len(values) < self.value_list_widget.count():
# Removed values:
for i in range(self.value_list_widget.count() - len(values)):
value = self.value_list_widget.itemWidget(self.value_list_widget.item(i + len(values)))
self.remove_value_item(value.value_list_item)

# We now have the correct number of value widgets. Let us just go fill all the values in.
for i in range(self.value_list_widget.count()):
value = self.value_list_widget.itemWidget(self.value_list_widget.item(i))
value.line_edit.setText(values[i])


class CustomAttributeValueWidget(QWidget):
"""
Expand Down Expand Up @@ -843,6 +982,12 @@ def add_requirement(self, requirements: List, name: str, scaling_factor: int = 1
requirement["max"] = self.max_spin_box.value() * scaling_factor
requirements.append(requirement)

def update_requirement(self, requirement: Dict[str, Any], scaling_factor: int = 1):
if requirement.get("min"):
self.min_spin_box.setValue(requirement.get("min") / scaling_factor)
if requirement.get("max"):
self.max_spin_box.setValue(requirement.get("max") / scaling_factor)


class OptionalComboBox(QComboBox):
"""
Expand Down

0 comments on commit 153e19d

Please sign in to comment.