Skip to main content
Glama
inventory.py6.21 kB
"""Handler for inventory operations (templates, roles, active ranges).""" from typing import Any from ludus_mcp.core.client import LudusAPIClient from ludus_mcp.scenarios.role_manager import RoleManager from ludus_mcp.utils.logging import get_logger logger = get_logger(__name__) class InventoryHandler: """Handler for inventory and resource listing operations.""" def __init__(self, client: LudusAPIClient) -> None: """Initialize the inventory handler.""" self.client = client self.role_manager = RoleManager(client) async def list_templates(self) -> dict[str, Any]: """List all available templates.""" try: templates = await self.client.list_templates() return { "status": "success", "templates": templates if isinstance(templates, list) else [], "count": len(templates) if isinstance(templates, list) else 0, } except Exception as e: logger.error(f"Error listing templates: {e}") return { "status": "error", "error": str(e), "templates": [], } async def list_roles(self) -> dict[str, Any]: """List all installed Ansible roles.""" try: ansible_resources = await self.client.list_ansible_resources() # Parse roles from response roles = [] if isinstance(ansible_resources, dict): roles = ansible_resources.get("roles", []) elif isinstance(ansible_resources, list): roles = ansible_resources # Normalize role format normalized_roles = [] for role in roles: if isinstance(role, str): normalized_roles.append({"name": role, "installed": True}) elif isinstance(role, dict): normalized_roles.append({ "name": role.get("name") or role.get("role", "unknown"), "installed": True, **{k: v for k, v in role.items() if k not in ["name", "role"]}, }) return { "status": "success", "roles": normalized_roles, "count": len(normalized_roles), } except Exception as e: logger.error(f"Error listing roles: {e}") return { "status": "error", "error": str(e), "roles": [], } async def list_active_ranges(self, user_id: str | None = None) -> dict[str, Any]: """List all actively deployed ranges.""" try: # Get current user's range current_range = await self.client.get_range(user_id) # Get all ranges (admin only) all_ranges = [] try: all_ranges = await self.client.list_ranges() except Exception: # If not admin, just return current range pass # Filter active ranges (not deleted, has VMs or is deploying) active_ranges = [] # Add current range if it exists and is active if current_range and current_range.get("rangeState") not in ["DELETED", None]: active_ranges.append({ "user_id": current_range.get("userID"), "range_number": current_range.get("rangeNumber"), "state": current_range.get("rangeState"), "number_of_vms": current_range.get("numberOfVMs", 0), "last_deployment": current_range.get("lastDeployment"), "testing_enabled": current_range.get("testingEnabled", False), }) # Add other ranges if available if isinstance(all_ranges, list): for range_info in all_ranges: if range_info.get("rangeState") not in ["DELETED", None]: active_ranges.append({ "user_id": range_info.get("userID"), "range_number": range_info.get("rangeNumber"), "state": range_info.get("rangeState"), "number_of_vms": range_info.get("numberOfVMs", 0), "last_deployment": range_info.get("lastDeployment"), "testing_enabled": range_info.get("testingEnabled", False), }) return { "status": "success", "active_ranges": active_ranges, "count": len(active_ranges), } except Exception as e: logger.error(f"Error listing active ranges: {e}") return { "status": "error", "error": str(e), "active_ranges": [], } async def get_inventory_summary(self, user_id: str | None = None) -> dict[str, Any]: """Get complete inventory summary (templates, roles, active ranges).""" try: templates_info = await self.list_templates() roles_info = await self.list_roles() ranges_info = await self.list_active_ranges(user_id) return { "status": "success", "templates": { "count": templates_info.get("count", 0), "list": templates_info.get("templates", []), }, "roles": { "count": roles_info.get("count", 0), "list": roles_info.get("roles", []), }, "active_ranges": { "count": ranges_info.get("count", 0), "list": ranges_info.get("active_ranges", []), }, } except Exception as e: logger.error(f"Error getting inventory summary: {e}") return { "status": "error", "error": str(e), }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tjnull/Ludus-FastMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server