From e8efde98920d18bb4a9ca0c0084b45a2d8c547ab Mon Sep 17 00:00:00 2001 From: "Magel, Denis" Date: Thu, 18 Sep 2025 12:16:30 +0200 Subject: [PATCH] feat: added functionality inside GET/aggregates --- src/aggregate/aggregate_router.py | 8 +------- src/aggregate/aggregate_schema.py | 9 ++++++++- src/aggregate/aggregate_service.py | 32 ++++++++++++++++++++---------- src/utils.py | 23 +++++++++++++++++++++ 4 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 src/utils.py diff --git a/src/aggregate/aggregate_router.py b/src/aggregate/aggregate_router.py index b33556b..fdb87af 100644 --- a/src/aggregate/aggregate_router.py +++ b/src/aggregate/aggregate_router.py @@ -1,16 +1,10 @@ # contains the router for the aggregates endpoint from fastapi import APIRouter, Query -from enum import Enum from typing import List -from .aggregate_schema import AggregateSchema +from .aggregate_schema import AggregateSchema, MetricEnum from .aggregate_service import get_aggregates -class MetricEnum(str, Enum): - relative = "relative" - absolute = "absolute" - - router = APIRouter(tags=["aggregates"]) diff --git a/src/aggregate/aggregate_schema.py b/src/aggregate/aggregate_schema.py index 4edd30a..d197e4f 100644 --- a/src/aggregate/aggregate_schema.py +++ b/src/aggregate/aggregate_schema.py @@ -1,8 +1,15 @@ # contains the schema definitions for aggregates from pydantic import BaseModel +from enum import Enum class AggregateSchema(BaseModel): aggregate: str node: str - available: str + available: int + available_str: str + + +class MetricEnum(str, Enum): + relative = "relative" + absolute = "absolute" diff --git a/src/aggregate/aggregate_service.py b/src/aggregate/aggregate_service.py index 0a40557..8142bae 100644 --- a/src/aggregate/aggregate_service.py +++ b/src/aggregate/aggregate_service.py @@ -1,24 +1,36 @@ # contains the business logic for aggregates + from typing import List -from .aggregate_schema import AggregateSchema +from .aggregate_schema import AggregateSchema, MetricEnum +from logging import getLogger +from ..utils import round_bytes, get_data_from_ontap + +logger = getLogger("uvicorn") +logger.setLevel("DEBUG") async def get_aggregates(metric: str = "relative") -> List[AggregateSchema]: # Dummy data for demonstration # You can use the metric parameter to filter or modify results as needed # For now, just return the same data and show metric usage - print(f"Metric used: {metric}") + logger.debug(f"Metric used: {metric}") + + __aggregates = get_data_from_ontap(logger, "172.16.57.2", "admin", "Netapp12", "storage/aggregates", "fields=name,uuid,space,node,home_node") + logger.debug(__aggregates) + __aggregates = __aggregates.get("records") + if metric == MetricEnum.relative: + __aggregates = sorted(__aggregates, key=lambda r: r["space"]["block_storage"].get("used_percent"), reverse=True) + elif metric == MetricEnum.absolute: + __aggregates = sorted(__aggregates, key=lambda r: r["space"]["block_storage"].get("available"), reverse=False) aggregates: list = [ AggregateSchema( - aggregate="Aggregate A", node="cluster01-01", available="100.0TB" - ), - AggregateSchema( - aggregate="Aggregate B", node="cluster01-01", available="200.5GB" - ), - AggregateSchema( - aggregate="Aggregate C", node="cluster01-02", available="300.75MB" - ), + aggregate=a["name"], + node=a["node"]["name"], + available=a["space"]["block_storage"]["available"], + available_str=round_bytes(a["space"]["block_storage"]["available"]), + ) + for a in __aggregates ] return aggregates diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..09f14e1 --- /dev/null +++ b/src/utils.py @@ -0,0 +1,23 @@ +import httpx + +def round_bytes(size_in_bytes: int) -> str: + # Helper function to convert bytes to a human-readable format + for unit in ["B", "KiB", "MiB", "GiB", "TiB", "PiB"]: + if size_in_bytes < 1024: + return f"{size_in_bytes:.2f}{unit}" + size_in_bytes /= 1024 + return f"{size_in_bytes:.2f}EB" + + +def get_data_from_ontap(logger, hostname: str, username: str, password: str, endpoint: str, query_string: str = ""): + url = f"https://{hostname}/api/{endpoint}" + if query_string: + url += f"?{query_string}" + try: + logger.debug(f"Fetching data from ONTAP: {url}") + response = httpx.get(url, auth=(username, password), verify=False) + response.raise_for_status() + return response.json() + except httpx.HTTPError as e: + logger.error(f"HTTP error occurred: {e}") + return None