From 5f94591ca6028e899c39d34c09bde220c7780b6f Mon Sep 17 00:00:00 2001 From: 1yam Date: Thu, 4 Dec 2025 16:38:52 +0100 Subject: [PATCH] Feature: filter crn can with based on vm resources --- src/aleph/sdk/client/services/crn.py | 69 ++++++++++++++++++++++++++++ src/aleph/sdk/types.py | 6 +++ 2 files changed, 75 insertions(+) diff --git a/src/aleph/sdk/client/services/crn.py b/src/aleph/sdk/client/services/crn.py index fe6d538d..177826b8 100644 --- a/src/aleph/sdk/client/services/crn.py +++ b/src/aleph/sdk/client/services/crn.py @@ -1,3 +1,4 @@ +from datetime import datetime from typing import TYPE_CHECKING, Dict, List, Optional, Union import aiohttp @@ -13,6 +14,7 @@ CrnV1List, CrnV2List, DictLikeModel, + VmResources, ) from aleph.sdk.utils import extract_valid_eth_address, sanitize_url @@ -20,6 +22,48 @@ from aleph.sdk.client.http import AlephHttpClient +class CpuLoad(BaseModel): + load1: float + load5: float + load15: float + + +class CoreFrequencies(BaseModel): + min: float + max: float + + +class CpuInfo(BaseModel): + count: int + load_average: CpuLoad + core_frequencies: CoreFrequencies + + +class MemoryInfo(BaseModel): + total_kB: int + available_kB: int + + +class DiskInfo(BaseModel): + total_kB: int + available_kB: int + + +class UsagePeriod(BaseModel): + start_timestamp: datetime + duration_seconds: int + + +class SystemUsage(BaseModel): + cpu: CpuInfo + mem: MemoryInfo + disk: DiskInfo + period: UsagePeriod + properties: dict + gpu: dict + active: bool + + class GPU(BaseModel): vendor: str model: str @@ -47,6 +91,7 @@ class CRN(DictLikeModel): gpu_support: Optional[bool] = False confidential_support: Optional[bool] = False qemu_support: Optional[bool] = False + system_usage: Optional[SystemUsage] = None version: Optional[str] = "0.0.0" payment_receiver_address: Optional[str] # Can be None if not configured @@ -102,6 +147,7 @@ def filter_crn( stream_address: bool = False, confidential: bool = False, gpu: bool = False, + vm_resources: Optional[VmResources] = None, ) -> list[CRN]: """Filter compute resource node list, unfiltered by default. Args: @@ -110,6 +156,7 @@ def filter_crn( stream_address (bool): Filter invalid payment receiver address. confidential (bool): Filter by confidential computing support. gpu (bool): Filter by GPU support. + vm_resources (VmResources): Filter by VM need, vcpus, memory, disk. Returns: list[CRN]: List of compute resource nodes. (if no filter applied, return all) """ @@ -140,6 +187,28 @@ def filter_crn( if gpu and (not crn_.gpu_support or not available_gpu): continue + # Filter VM resources + if vm_resources: + sys = crn_.system_usage + if not sys: + continue + + # Check CPU count + if sys.cpu.count < vm_resources.vcpus: + continue + + # Convert MiB to kB (1 MiB = 1024 kB) for proper comparison + memory_kb_required = vm_resources.memory * 1024 + disk_kb_required = vm_resources.disk_mib * 1024 + + # Check free memory + if sys.mem.available_kB < memory_kb_required: + continue + + # Check free disk + if sys.disk.available_kB < disk_kb_required: + continue + filtered_crn.append(crn_) return filtered_crn diff --git a/src/aleph/sdk/types.py b/src/aleph/sdk/types.py index 8d952b18..12fc78ad 100644 --- a/src/aleph/sdk/types.py +++ b/src/aleph/sdk/types.py @@ -399,3 +399,9 @@ class Voucher(BaseModel): image: str icon: str attributes: list[VoucherAttribute] + + +class VmResources(BaseModel): + vcpus: int + memory: int + disk_mib: int