- Implemented Tautulli information retrieval in `tautulli_informations.py` to fetch movie, anime, TV show, music amounts, and more. - Created a weather forecast tool in `weather_forecast.py` that retrieves and formats a 7-day weather forecast in German. - Developed a YouTube transcript provider in `youtube_summarizer.py` to fetch video transcripts and titles using Langchain Community's YoutubeLoader.
414 lines
16 KiB
Python
414 lines
16 KiB
Python
"""
|
|
title: Proxmox API Access
|
|
author: Pakobbix
|
|
author_url: https://gitea.zephyre.one/Pakobbix/
|
|
version: 0.1.0
|
|
"""
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
import asyncio
|
|
import requests
|
|
from typing import Callable, Any
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class EventEmitter:
|
|
def __init__(self, event_emitter: Callable[[dict], Any] = None):
|
|
self.event_emitter = event_emitter
|
|
|
|
async def progress_update(self, description):
|
|
await self.emit(description)
|
|
|
|
async def error_update(self, description):
|
|
await self.emit(description, "error", True)
|
|
|
|
async def success_update(self, description):
|
|
await self.emit(description, "success", True)
|
|
|
|
async def emit(self, description="Unknown State", status="in_progress", done=False):
|
|
if self.event_emitter:
|
|
await self.event_emitter(
|
|
{
|
|
"type": "status",
|
|
"data": {
|
|
"status": status,
|
|
"description": description,
|
|
"done": done,
|
|
},
|
|
}
|
|
)
|
|
|
|
|
|
class function_collection:
|
|
def request_api(self, url, token, method="GET"):
|
|
headers = {
|
|
"Authorization": f"PVEAPIToken={token}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
if method.upper() == "GET":
|
|
response = requests.get(url, headers=headers, verify=False)
|
|
elif method.upper() == "POST":
|
|
response = requests.post(url, headers=headers, verify=False)
|
|
else:
|
|
raise ValueError(f"Unsupported HTTP method: {method}")
|
|
|
|
if response.text:
|
|
return response.json()
|
|
return None
|
|
|
|
def _check_lxc_or_vm(self, url, token, id_or_name) -> str | None:
|
|
"""
|
|
Check if the given ID corresponds to a logical container (LXC) or a virtual machine (VM).
|
|
|
|
:param id_or_name: The ID or name of the resource to check.
|
|
:return: "lxc" if it's an LXC, "vm" if it's a VM, or None if not found.
|
|
"""
|
|
url = f"{url}/api2/json/cluster/resources"
|
|
response = self.request_api(url, token, method="GET")
|
|
|
|
if "data" in response:
|
|
for item in response["data"]:
|
|
# Only check items that are vms or lxcs
|
|
if item.get("type") in ["qemu", "lxc"]:
|
|
if (
|
|
str(item.get("vmid")) == str(id_or_name)
|
|
or item.get("name", "").lower() == str(id_or_name).lower()
|
|
):
|
|
information_list = {
|
|
"vmid": item["vmid"],
|
|
"name": item["name"],
|
|
"type": item["type"],
|
|
}
|
|
return information_list
|
|
return None
|
|
|
|
|
|
class Tools:
|
|
class Valves(BaseModel):
|
|
proxmox_url: str = Field(
|
|
"https://localhost:8006", description="The Proxmox API URL"
|
|
)
|
|
api_token: str = Field(
|
|
"api_token_here", description="The API token for authentication"
|
|
)
|
|
|
|
def __init__(self):
|
|
self.valves = self.Valves()
|
|
self.function_call = function_collection()
|
|
|
|
###########################################################################
|
|
######################### Proxmox Node Management #########################
|
|
###########################################################################
|
|
|
|
async def running_version_check(
|
|
self, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Check the Proxmox API version.
|
|
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The Proxmox API version or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update("Checking Proxmox API version")
|
|
|
|
url = f"{self.valves.proxmox_url}/api2/json/version"
|
|
|
|
try:
|
|
version_info = self.function_call.request_api(
|
|
url, self.valves.api_token, method="GET"
|
|
)
|
|
await emitter.success_update("Proxmox API version retrieved successfully")
|
|
final_output = str(version_info)
|
|
return (
|
|
final_output
|
|
+ "\nDas ist nur die momentan laufenende Version! Eventuell ist aber bereits eine neuere Version Verfügbar."
|
|
)
|
|
except Exception as e:
|
|
await emitter.error_update(
|
|
f"Error retrieving Proxmox API version: {str(e)}"
|
|
)
|
|
return None
|
|
|
|
async def list_nodes(
|
|
self, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
List all nodes in the Proxmox cluster.
|
|
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: List of nodes or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update("Starting node listing process")
|
|
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes"
|
|
|
|
try:
|
|
nodes = self.function_call.request_api(
|
|
url, self.valves.api_token, method="GET"
|
|
)
|
|
await emitter.success_update("Node listing completed successfully")
|
|
return str(nodes)
|
|
except Exception as e:
|
|
await emitter.error_update(f"Error during node listing: {str(e)}")
|
|
return None
|
|
|
|
async def get_node_status(
|
|
self, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Get the status of a specific node in the Proxmox cluster.
|
|
|
|
:param node_name: The name of the node to retrieve status for.
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The status of the node or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(f"Getting status for node: zephyre")
|
|
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/status"
|
|
|
|
try:
|
|
status = self.function_call.request_api(
|
|
url, self.valves.api_token, method="GET"
|
|
)
|
|
await emitter.success_update(f"Node status retrieved successfully")
|
|
return str(status)
|
|
except Exception as e:
|
|
await emitter.error_update(f"Error retrieving node status: {str(e)}")
|
|
return None
|
|
|
|
async def node_apt_update(
|
|
self, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Update the APT packages on a specific node in the Proxmox cluster.
|
|
|
|
:param node_name: The name of the node to update.
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The response from the API or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(f"Updating APT packages for node: zephyre")
|
|
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/apt/update"
|
|
|
|
try:
|
|
response = self.function_call.request_api(
|
|
url, self.valves.api_token, method="GET"
|
|
)
|
|
await emitter.success_update(
|
|
f"Node zephyre APT packages updated successfully"
|
|
)
|
|
return str(response)
|
|
except Exception as e:
|
|
await emitter.error_update(
|
|
f"Error updating node zephyre APT packages: {str(e)}"
|
|
)
|
|
return None
|
|
|
|
async def proxmox_node_log(
|
|
self, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Get the log of a specific node in the Proxmox cluster.
|
|
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The log of the node or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(f"Getting log for node: zephyre")
|
|
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/log"
|
|
|
|
try:
|
|
log = self.function_call.request_api(url, self.valves.api_token)
|
|
await emitter.success_update(f"Node log retrieved successfully")
|
|
return str(log)
|
|
except Exception as e:
|
|
await emitter.error_update(f"Error retrieving node log: {str(e)}")
|
|
return None
|
|
|
|
###########################################################################
|
|
######################### Proxmox VM Management ##########################
|
|
###########################################################################
|
|
|
|
async def list_all_vms(
|
|
self, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
List all VMs in the Proxmox cluster.
|
|
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: List of VMs or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update("Starting VM listing process")
|
|
|
|
url = f"{self.valves.proxmox_url}/api2/json/cluster/resources"
|
|
|
|
try:
|
|
vms = self.function_call.request_api(
|
|
url, self.valves.api_token, method="GET"
|
|
)
|
|
await emitter.success_update("VM listing completed successfully")
|
|
return str(vms)
|
|
except Exception as e:
|
|
await emitter.error_update(f"Error during VM listing: {str(e)}")
|
|
return None
|
|
|
|
async def restart_vm(
|
|
self, vm_id_or_name: str, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Restart a virtual machine in the Proxmox cluster.
|
|
|
|
:param vm_id: The ID of the VM to restart.
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The response from the API or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(f"Restarting VM: {vm_id_or_name}")
|
|
|
|
type = self.function_call._check_lxc_or_vm(
|
|
self.valves.proxmox_url, self.valves.api_token, vm_id_or_name
|
|
)
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/{type['type']}/{type['vmid']}/status/restart"
|
|
|
|
try:
|
|
response = self.function_call.request_api(
|
|
url, self.valves.api_token, method="POST"
|
|
)
|
|
await emitter.success_update(f"VM {vm_id_or_name} restarted successfully")
|
|
return str(response)
|
|
except Exception as e:
|
|
await emitter.error_update(f"Error restarting VM {vm_id_or_name}: {str(e)}")
|
|
return None
|
|
|
|
async def shutdown_vm(
|
|
self, vm_id: str, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Shutdown a virtual machine in the Proxmox cluster.
|
|
|
|
:param vm_id: The ID of the VM to shutdown.
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The response from the API or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(f"Shutting down VM: {vm_id}")
|
|
|
|
type = self.function_call._check_lxc_or_vm(
|
|
self.valves.proxmox_url, self.valves.api_token, vm_id
|
|
)
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/{type['type']}/{type['vmid']}/status/shutdown"
|
|
|
|
try:
|
|
response = self.function_call.request_api(
|
|
url, self.valves.api_token, method="POST"
|
|
)
|
|
await emitter.success_update(f"VM {vm_id} shut down successfully")
|
|
return str(response)
|
|
except Exception as e:
|
|
await emitter.error_update(f"Error shutting down VM {vm_id}: {str(e)}")
|
|
return None
|
|
|
|
async def start_vm(
|
|
self, vm_id: str, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Start a virtual machine in the Proxmox cluster.
|
|
|
|
:param vm_id: The ID of the VM to start.
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The response from the API or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(f"Starting VM: {vm_id}")
|
|
|
|
type = self.function_call._check_lxc_or_vm(
|
|
self.valves.proxmox_url, self.valves.api_token, vm_id
|
|
)
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/{type['type']}/{type['vmid']}/status/start"
|
|
|
|
try:
|
|
response = self.function_call.request_api(
|
|
url, self.valves.api_token, method="POST"
|
|
)
|
|
await emitter.success_update(f"VM {vm_id} started successfully")
|
|
return str(response)
|
|
except Exception as e:
|
|
await emitter.error_update(f"Error starting VM {vm_id}: {str(e)}")
|
|
return f"Error starting VM {vm_id}: {str(e)}"
|
|
|
|
async def get_specific_vm_status(
|
|
self, vm_id_or_name: str, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Get the status of a specific virtual machine in the Proxmox cluster.
|
|
|
|
:param vm_id: The ID of the VM to retrieve status for.
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The status of the VM or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(f"Getting status for VM: {vm_id_or_name}")
|
|
|
|
type = self.function_call._check_lxc_or_vm(
|
|
self.valves.proxmox_url, self.valves.api_token, vm_id_or_name
|
|
)
|
|
await emitter.progress_update(
|
|
f"Getting status for {type['type']}: {type['name']}"
|
|
)
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/{type['type']}/{type['vmid']}/status/current"
|
|
|
|
try:
|
|
status = self.function_call.request_api(
|
|
url, self.valves.api_token, method="GET"
|
|
)
|
|
await emitter.success_update(
|
|
f"VM {vm_id_or_name} status retrieved successfully"
|
|
)
|
|
return str(status)
|
|
except Exception as e:
|
|
await emitter.error_update(
|
|
f"Error retrieving VM {vm_id_or_name} status: {str(e)}"
|
|
)
|
|
return None
|
|
|
|
async def get_specific_vm_configuration_and_hardware(
|
|
self, vm_id_or_vm_name: str, __event_emitter__: Callable[[dict], Any] = None
|
|
) -> str | None:
|
|
"""
|
|
Get detailed information about a specific virtual machine or container in the Proxmox cluster.
|
|
|
|
:param vm_id: The ID of the VM or container to retrieve information for.
|
|
:param event_emitter: Optional callable for emitting events.
|
|
:return: The information of the VM/container or None if an error occurs.
|
|
"""
|
|
emitter = EventEmitter(__event_emitter__)
|
|
await emitter.progress_update(
|
|
f"Getting information for resource: {vm_id_or_vm_name}"
|
|
)
|
|
|
|
try:
|
|
type = self.function_call._check_lxc_or_vm(
|
|
self.valves.proxmox_url, self.valves.api_token, vm_id_or_vm_name
|
|
)
|
|
url = f"{self.valves.proxmox_url}/api2/json/nodes/zephyre/{type['type']}/{type['vmid']}/config"
|
|
|
|
info = self.function_call.request_api(
|
|
url, self.valves.api_token, method="GET"
|
|
)
|
|
await emitter.success_update(
|
|
f"Resource {vm_id_or_vm_name} information retrieved successfully"
|
|
)
|
|
return str(info)
|
|
except Exception as e:
|
|
await emitter.error_update(
|
|
f"Error retrieving resource {vm_id_or_vm_name} information: {str(e)}"
|
|
)
|
|
return None
|