Configure VM provisioning with ZFS mirror disks and virtual TPM 2.0 module
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Add app directory to sys.path so we can import from app
|
||||
sys.path.append(str(Path(__file__).parent))
|
||||
|
||||
from app.config import settings
|
||||
from app.proxmox_client import proxmox
|
||||
|
||||
async def main():
|
||||
node = "dl380-0"
|
||||
vmid = 900
|
||||
if len(sys.argv) > 1:
|
||||
vmid = int(sys.argv[1])
|
||||
if len(sys.argv) > 2:
|
||||
node = sys.argv[2]
|
||||
|
||||
print(f"Requesting termproxy ticket for VM {vmid} on node {node}...")
|
||||
try:
|
||||
res = await proxmox._request("POST", f"/nodes/{node}/qemu/{vmid}/termproxy")
|
||||
except Exception as e:
|
||||
print(f"Error requesting termproxy: {e}")
|
||||
return
|
||||
|
||||
port = res["port"]
|
||||
ticket = res["ticket"]
|
||||
user = res["user"]
|
||||
|
||||
import websockets
|
||||
from urllib.parse import quote
|
||||
|
||||
# Construct ws url
|
||||
host_clean = settings.proxmox_host.replace("https://", "").replace("http://", "").split("/")[0]
|
||||
ws_url = f"wss://{host_clean}/api2/json/nodes/{node}/qemu/{vmid}/vncwebsocket?port={port}&vncticket={quote(ticket)}"
|
||||
|
||||
print(f"Connecting to websocket: {ws_url}")
|
||||
|
||||
import ssl
|
||||
ssl_context = ssl._create_unverified_context()
|
||||
|
||||
# Proxmox websocket protocol requires sending the ticket to authenticate
|
||||
try:
|
||||
async with websockets.connect(
|
||||
ws_url,
|
||||
ssl=ssl_context,
|
||||
subprotocols=["binary"]
|
||||
) as ws:
|
||||
# Handshake format: user:ticket\n
|
||||
handshake = f"{user}:{ticket}\n"
|
||||
await ws.send(handshake)
|
||||
print("Handshake sent, reading console stream (Ctrl+C to exit)...")
|
||||
|
||||
# Proxmox termproxy sends data as frame-wrapped or raw binary
|
||||
while True:
|
||||
msg = await ws.recv()
|
||||
if isinstance(msg, bytes):
|
||||
# Proxmox termproxy data format: 1 byte channel, then data
|
||||
# Channel 0 is stdout, channel 1 is stderr
|
||||
if len(msg) > 1:
|
||||
sys.stdout.buffer.write(msg[1:])
|
||||
sys.stdout.buffer.flush()
|
||||
else:
|
||||
sys.stdout.write(msg)
|
||||
sys.stdout.flush()
|
||||
except KeyboardInterrupt:
|
||||
print("\nExiting console reader.")
|
||||
except websockets.exceptions.ConnectionClosed as e:
|
||||
print(f"\nConnection closed: {e}")
|
||||
except Exception as e:
|
||||
print(f"\nError: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user