Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update RMS models and API #262

Merged
merged 3 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ jobs:
with:
report_paths: '**/test*.xml'
check_name: Test Report ${{ matrix.os }}:${{ matrix.cfg.python-version }}
detailed_summary: true
include_passed: true

- name: Stop services
if: always()
Expand Down
2 changes: 0 additions & 2 deletions ansys/hps/client/rms/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
from ansys.hps.client.exceptions import ClientError

from ..models import (
Cluster,
ComputeResourceSet,
EvaluatorConfigurationUpdate,
EvaluatorRegistration,
ScalerRegistration,
)

OBJECT_TYPE_TO_ENDPOINT = {
Cluster: "clusters",
EvaluatorRegistration: "evaluators",
EvaluatorConfigurationUpdate: "configuration_updates",
ScalerRegistration: "scalers",
Expand Down
14 changes: 6 additions & 8 deletions ansys/hps/client/rms/api/rms_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from ansys.hps.client.client import Client
from ansys.hps.client.rms.models import (
Cluster,
ClusterInfo,
ComputeResourceSet,
EvaluatorConfiguration,
EvaluatorConfigurationUpdate,
Expand Down Expand Up @@ -145,14 +145,12 @@ def get_compute_resource_set(self, id, as_object=True) -> ComputeResourceSet:
from_collection=True,
)

def get_compute_resurce_set_cluster_info(self, id, as_object=True) -> Cluster:
def get_cluster_info(self, compute_resource_set_id, as_object=True) -> ClusterInfo:
"""Returns cluster info of a compute resource set."""

clusters = get_objects(
return get_object(
self.client.session,
self.url,
ComputeResourceSet,
as_object,
crs_id=id,
f"{self.url}/compute_resource_sets/{compute_resource_set_id}/cluster_info",
ClusterInfo,
as_object=as_object,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if your change not gives back a list now whereas previous solution was giving back first entry (without checking if the list is not empty!!)

Copy link
Contributor Author

@FedericoNegri FedericoNegri Dec 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No because now I'm using get_object instead of get_objects

)
return clusters[0]
110 changes: 64 additions & 46 deletions ansys/hps/client/rms/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# generated by datamodel-codegen:
# filename: rms_openapi.json
# timestamp: 2023-11-17T08:04:07+00:00
# timestamp: 2023-12-22T09:38:15+00:00

from __future__ import annotations

Expand Down Expand Up @@ -34,17 +34,13 @@ class ApplicationInfo(BaseModel):
)


class ClustersCountResponse(BaseModel):
num_clusters: Optional[int] = Field(0, title='Num Clusters')


class EvaluatorTaskDirectoryCleanup(Enum):
always = 'always'
on_success = 'on_success'
never = 'never'


class Context(BaseModel):
class ContextUpdate(BaseModel):
custom: Optional[Dict[str, Optional[Union[int, bool, str, float]]]] = Field(
{}, description='Custom runtime properties.', title='Custom'
)
Expand Down Expand Up @@ -146,11 +142,6 @@ class KubernetesKedaBackend(BaseModel):
memory_limit: Optional[str] = Field(
'250M', description='Memory limit applied to each evaluator instance', title='Memory Limit'
)
persistent_volume_claim_name: Optional[str] = Field(
'pvc-rep-files',
description='Persistent volume claim name to be mounted as volume for each evaluator instance ',
title='Persistent Volume Claim Name',
)
namespace: Optional[str] = Field(
'default',
description='Kubernetes namespace to be used to scale evaluators',
Expand Down Expand Up @@ -185,6 +176,11 @@ class LocalBackend(BaseModel):
)


class Machine(BaseModel):
name: str = Field(..., description='Name of the machine', title='Name')
num_cores: int = Field(..., description='Number of cores available', title='Num Cores')


class MaxAvailableResourceScaling(BaseModel):
plugin_name: Literal['max_available_resource_scaling'] = Field(..., title='Plugin Name')
match_all_requirements: Optional[bool] = Field(
Expand All @@ -203,13 +199,17 @@ class MockupBackend(BaseModel):

class Node(BaseModel):
name: Optional[str] = Field(None, description='Node name', title='Name')
total_memory_mb: int = Field(..., description='Total memory', title='Total Memory Mb')
used_memory_mb: int = Field(..., description='Memory in use', title='Used Memory Mb')
total_cores: int = Field(..., description='Number of cores', title='Total Cores')
used_cores: int = Field(..., description='Cores in use', title='Used Cores')
total_memory_mb: Optional[int] = Field(..., description='Total memory', title='Total Memory Mb')
total_cores: Optional[int] = Field(..., description='Number of cores', title='Total Cores')
additional_props: Optional[Dict[str, Any]] = Field({}, title='Additional Props')


class NodeGroup(BaseModel):
node_names: List[str] = Field(..., title='Node Names')
total_memory_mb: Optional[int] = Field(..., description='Total memory', title='Total Memory Mb')
total_cores: Optional[int] = Field(..., description='Number of cores', title='Total Cores')


class PlatformEnum(Enum):
windows = 'windows'
linux = 'linux'
Expand Down Expand Up @@ -251,6 +251,11 @@ class ProcessLauncherProcessRunner(BaseModel):

class Queue(BaseModel):
name: Optional[str] = Field(None, description='Queue name', title='Name')
node_groups: Optional[List[NodeGroup]] = Field(
None,
description='List of node groups associated with the queue (If available)',
title='Node Groups',
)
additional_props: Optional[Dict[str, Any]] = Field({}, title='Additional Props')


Expand All @@ -275,17 +280,11 @@ class Resources(BaseModel):

class RestLauncherProcessRunner(BaseModel):
plugin_name: Literal['process_launcher_service'] = Field(..., title='Plugin Name')
default_user: Optional[str] = Field(
None, description='The user to use when none is specified', title='Default User'
)
launcher_url: Optional[str] = Field(
'http://localhost:4911',
description='The url to use when none is specified',
title='Launcher Url',
)
require_auth: Optional[bool] = Field(
False, description='Only make authenticated calls to the launcher', title='Require Auth'
)
verify_ssl: Optional[bool] = Field(
True, description='Check the SSL certificate for HTTPS launchers', title='Verify Ssl'
)
Expand Down Expand Up @@ -395,7 +394,7 @@ class Status(BaseModel):
build: Dict[str, Any] = Field(..., title='Build')


class Cluster(BaseModel):
class ClusterInfo(BaseModel):
id: Optional[str] = Field(None, description='Unique identifier for database', title='Id')
crs_id: Optional[str] = Field(None, description='Compute resource set ID', title='Crs Id')
name: Optional[str] = Field(None, description='Cluster name', title='Name')
Expand All @@ -404,12 +403,15 @@ class Cluster(BaseModel):
additional_props: Optional[Dict[str, Dict[str, Any]]] = Field({}, title='Additional Props')


class ClustersRequest(BaseModel):
clusters: List[Cluster] = Field(..., description='Cluster details', title='Clusters')


class ClustersResponse(BaseModel):
clusters: List[Cluster] = Field(..., description='Cluster details', title='Clusters')
class Context(BaseModel):
custom: Optional[Dict[str, Optional[Union[int, bool, str, float]]]] = Field(
{}, description='Custom runtime properties.', title='Custom'
)
machines_list: Optional[List[Machine]] = Field(
None,
description='List of machines for distributed parallel processing.',
title='Machines List',
)


class EvaluatorResources(BaseModel):
Expand Down Expand Up @@ -512,13 +514,13 @@ class ComputeResourceSet(BaseModel):
discriminator='plugin_name',
title='Backend',
)
scaling_strategy: Optional[
Union[MaxAvailableResourceScaling, KubernetesResourceScaling]
] = Field(
{'match_all_requirements': False, 'plugin_name': 'max_available_resource_scaling'},
description='Scaling strategy to use in this compute resource set',
discriminator='plugin_name',
title='Scaling Strategy',
scaling_strategy: Optional[Union[MaxAvailableResourceScaling, KubernetesResourceScaling]] = (
Field(
{'match_all_requirements': False, 'plugin_name': 'max_available_resource_scaling'},
description='Scaling strategy to use in this compute resource set',
discriminator='plugin_name',
title='Scaling Strategy',
)
)
available_resources: Optional[Resources] = Field(
{'custom': {}}, description='Available resources in the compute resource set'
Expand All @@ -536,6 +538,16 @@ class ComputeResourceSet(BaseModel):
description='Cleanup policy for task directories passed to evaluators',
title='Evaluator Task Directory Cleanup',
)
evaluator_auto_shutdown_time: Optional[int] = Field(
20,
description='Time after which to shutdown the evaluator if not running any jobs.',
title='Evaluator Auto Shutdown Time',
)
evaluator_loop_interval: Optional[int] = Field(
5,
description='The main evaluator loop is repeated every loop_interval seconds',
title='Evaluator Loop Interval',
)


class ComputeResourceSetsRequest(BaseModel):
Expand Down Expand Up @@ -568,13 +580,10 @@ class EvaluatorConfiguration(BaseModel):
task_directory_cleanup: Optional[TaskDirectoryCleanupEnum] = Field(
None, title='Task Directory Cleanup'
)
context: Optional[Context] = Field(
{'custom': {}}, description='Runtime properties to be passed to executed tasks'
)
resources: Optional[EvaluatorResources] = {'custom': {}}
task_manager_type: Optional[str] = Field(None, title='Task Manager Type')
loop_interval: Optional[float] = Field(
5,
5.0,
description='The main evaluator loop is repeated every loop_interval seconds',
title='Loop Interval',
)
Expand All @@ -601,6 +610,9 @@ class EvaluatorConfiguration(BaseModel):
description='Specifies how the evaluator selects projects to work on. One of: disabled, all_active, list',
title='Project Assignment Mode',
)
context: Optional[Context] = Field(
{'custom': {}}, description='Runtime properties to be passed to executed tasks'
)


class EvaluatorConfigurationUpdate(BaseModel):
Expand All @@ -621,9 +633,6 @@ class EvaluatorConfigurationUpdate(BaseModel):
task_directory_cleanup: Optional[TaskDirectoryCleanupEnum] = Field(
None, title='Task Directory Cleanup'
)
context: Optional[Context] = Field(
{'custom': {}}, description='Runtime properties to be passed to executed tasks'
)
resources: Optional[EvaluatorResources] = {'custom': {}}
name: Optional[str] = Field(
None, description='Update the name of Evaluator (updating the registration)', title='Name'
Expand Down Expand Up @@ -651,15 +660,24 @@ class EvaluatorConfigurationUpdate(BaseModel):
description='Specifies how the evaluator selects projects to work on. One of: disabled, all_active, list',
title='Project Assignment Mode',
)
context: Optional[ContextUpdate] = Field(
{'custom': {}}, description='Runtime properties to be passed to executed tasks'
)


class EvaluatorConfigurationUpdatesRequest(BaseModel):
updates: List[EvaluatorConfigurationUpdate] = Field(
..., description='Configuration update details', title='Updates'
configuration_updates: List[EvaluatorConfigurationUpdate] = Field(
..., description='Configuration update details', title='Configuration Updates'
)


class EvaluatorConfigurationUpdatesResponse(BaseModel):
updates: List[EvaluatorConfigurationUpdate] = Field(
..., description='Configuration update details', title='Updates'
configuration_updates: List[EvaluatorConfigurationUpdate] = Field(
..., description='Configuration update details', title='Configuration Updates'
)


class EvaluatorConfigurationsResponse(BaseModel):
configurations: List[EvaluatorConfiguration] = Field(
..., description='Evaluator configurations', title='Configurations'
)
2 changes: 1 addition & 1 deletion requirements/requirements_build.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build==1.0.3
twine==4.0.2
wheel
datamodel-code-generator==0.25.1
datamodel-code-generator==0.24.2
7 changes: 7 additions & 0 deletions tests/rms/test_compute_resource_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ def test_crs_integration(self):
rs = rms_api.get_compute_resource_set(resource_sets[0].id)
assert rs.scaler_id == resource_sets[0].scaler_id

cluster_info = rms_api.get_cluster_info(rs.id)
assert cluster_info.crs_id == rs.id
if cluster_info.queues is not None and len(cluster_info.queues) > 0:
for queue in cluster_info.queues:
assert queue.name is not None
log.info(f"Compure resource set {rs.name} has queue {queue.name}")


if __name__ == "__main__":
unittest.main()
Loading