feat: initial commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
Scope: `/home/nikola/codex-cli/projects/incus-topology-map`
|
||||||
|
|
||||||
|
- Keep generated topology snapshots in this project folder.
|
||||||
|
- Prefer read-only discovery commands for infrastructure mapping.
|
||||||
|
- Store human-readable outputs as Markdown.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Incus Topology Corporate Document
|
||||||
|
|
||||||
|
- Diagram file: `incus-topology-corporate.drawio`
|
||||||
|
- Data snapshot: `data/incus-snapshot-20260409-132237.json`
|
||||||
|
- Generated on: 2026-04-09
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
This document maps all reachable Incus remotes configured on the workstation at generation time:
|
||||||
|
- `hetzner-incus2`
|
||||||
|
- `kuber`
|
||||||
|
- `local`
|
||||||
|
- `virgo-incus`
|
||||||
|
|
||||||
|
## Visual Standards Applied
|
||||||
|
- Corporate color coding by environment scope:
|
||||||
|
- Hetzner remote: orange palette
|
||||||
|
- LAN remotes: blue palette
|
||||||
|
- Local remote: neutral gray palette
|
||||||
|
- Status semantics:
|
||||||
|
- Running VM: green card
|
||||||
|
- Stopped VM: red card
|
||||||
|
- Hierarchy:
|
||||||
|
- Remote -> Node -> VM
|
||||||
|
- Per VM metadata:
|
||||||
|
- `project/name`
|
||||||
|
- type
|
||||||
|
- runtime status
|
||||||
|
- primary IPv4
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
- At generation time, all remotes report `clustered=false`.
|
||||||
|
- Primary IP excludes bridge-only `172.16.0.0/12` addresses where possible.
|
||||||
|
|
||||||
|
## Refresh Procedure
|
||||||
|
1. Update snapshot via read-only Incus queries.
|
||||||
|
2. Regenerate `.drawio` using `generate_drawio.py`.
|
||||||
|
3. Re-open the updated diagram in draw.io / diagrams.net.
|
||||||
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,397 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import uuid
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
from pathlib import Path
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from xml.sax.saxutils import escape as xml_escape
|
||||||
|
|
||||||
|
SNAPSHOT = Path('/home/nikola/codex-cli/projects/incus-topology-map/data/incus-snapshot-20260409-132237.json')
|
||||||
|
OUT = Path('/home/nikola/codex-cli/projects/incus-topology-map/incus-topology-corporate.drawio')
|
||||||
|
|
||||||
|
|
||||||
|
def safe_id(prefix: str) -> str:
|
||||||
|
return f"{prefix}_{uuid.uuid4().hex[:8]}"
|
||||||
|
|
||||||
|
|
||||||
|
def is_private_bridge_ip(ip: str) -> bool:
|
||||||
|
if not ip:
|
||||||
|
return False
|
||||||
|
octets = ip.split('.')
|
||||||
|
if len(octets) != 4:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
a, b = int(octets[0]), int(octets[1])
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
return a == 172 and 16 <= b <= 31
|
||||||
|
|
||||||
|
|
||||||
|
def extract_ips(instance: dict) -> list[str]:
|
||||||
|
out = []
|
||||||
|
net = ((instance.get('state') or {}).get('network') or {})
|
||||||
|
for iface in net.values():
|
||||||
|
for addr in iface.get('addresses', []):
|
||||||
|
if addr.get('family') == 'inet' and addr.get('scope') == 'global':
|
||||||
|
ip = addr.get('address')
|
||||||
|
if ip and ip not in out:
|
||||||
|
out.append(ip)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def primary_ip(ips: list[str]) -> str:
|
||||||
|
for ip in ips:
|
||||||
|
if not is_private_bridge_ip(ip):
|
||||||
|
return ip
|
||||||
|
return ips[0] if ips else 'n/a'
|
||||||
|
|
||||||
|
|
||||||
|
def add_vertex(root, _id, value, style, x, y, w, h, parent='1'):
|
||||||
|
cell = ET.SubElement(root, 'mxCell', {
|
||||||
|
'id': _id,
|
||||||
|
'value': value,
|
||||||
|
'style': style,
|
||||||
|
'vertex': '1',
|
||||||
|
'parent': parent,
|
||||||
|
})
|
||||||
|
ET.SubElement(cell, 'mxGeometry', {
|
||||||
|
'x': str(x), 'y': str(y), 'width': str(w), 'height': str(h), 'as': 'geometry'
|
||||||
|
})
|
||||||
|
return cell
|
||||||
|
|
||||||
|
|
||||||
|
def add_edge(root, _id, source, target, style, parent='1'):
|
||||||
|
cell = ET.SubElement(root, 'mxCell', {
|
||||||
|
'id': _id,
|
||||||
|
'edge': '1',
|
||||||
|
'parent': parent,
|
||||||
|
'source': source,
|
||||||
|
'target': target,
|
||||||
|
'style': style,
|
||||||
|
})
|
||||||
|
ET.SubElement(cell, 'mxGeometry', {'relative': '1', 'as': 'geometry'})
|
||||||
|
return cell
|
||||||
|
|
||||||
|
|
||||||
|
def html(text: str) -> str:
|
||||||
|
return xml_escape(str(text))
|
||||||
|
|
||||||
|
|
||||||
|
def compact_endpoint(addr: str) -> str:
|
||||||
|
if not addr or addr == 'n/a':
|
||||||
|
return 'n/a'
|
||||||
|
return addr.replace('https://', '').replace('http://', '')
|
||||||
|
|
||||||
|
|
||||||
|
def remote_palette(name: str) -> tuple[str, str, str]:
|
||||||
|
if name.startswith('hetzner'):
|
||||||
|
return ('#FFF4E8', '#E38B1A', '#7A3E00')
|
||||||
|
if name == 'local':
|
||||||
|
return ('#F5F7FA', '#8B97A8', '#273244')
|
||||||
|
return ('#ECF3FF', '#3E7BDA', '#123765')
|
||||||
|
|
||||||
|
|
||||||
|
def remote_label(name: str, server_name: str, clustered: bool, addr: str, vm_count: int, node_count: int) -> str:
|
||||||
|
endpoint = compact_endpoint(addr)
|
||||||
|
endpoint_line = f'🌍 {html(endpoint)}<br>' if endpoint != 'n/a' else ''
|
||||||
|
return (
|
||||||
|
f'<div style="line-height:1.35;">'
|
||||||
|
f'<span style="font-size:17px;"><b>{html(name)}</b></span><br>'
|
||||||
|
f'🖥 <b>{html(server_name)}</b> | cluster: <b>{str(clustered).lower()}</b><br>'
|
||||||
|
f'{endpoint_line}'
|
||||||
|
f'📦 nodes: <b>{node_count}</b> | vms: <b>{vm_count}</b>'
|
||||||
|
f'</div>'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def classify_vm(vm_name: str) -> tuple[str, str, str, str]:
|
||||||
|
n = (vm_name or '').lower()
|
||||||
|
if any(k in n for k in ('gateway', 'proxy', 'ingress', 'route', 'vpn', 'wacli')):
|
||||||
|
return ('network', 'NET', '🌐', '#1D4ED8')
|
||||||
|
if any(k in n for k in ('postgres', 'mysql', 'mongo', 'redis', 'cassandra', 'supabase', 'db', 'pg-')):
|
||||||
|
return ('database', 'DB', '🗄', '#7C3AED')
|
||||||
|
if any(k in n for k in ('jenkins', 'runner', 'ci', 'build', 'deploy', 'harness')):
|
||||||
|
return ('cicd', 'CI', '⚙', '#B45309')
|
||||||
|
if any(k in n for k in ('grafana', 'prometheus', 'loki', 'elk', 'monitor', 'uptime', 'alert')):
|
||||||
|
return ('observability', 'OBS', '📈', '#0F766E')
|
||||||
|
if any(k in n for k in ('auth', 'vault', 'keycloak', 'infisical', 'secret')):
|
||||||
|
return ('security', 'SEC', '🔐', '#BE123C')
|
||||||
|
if any(k in n for k in ('shell', 'console', 'test', 'ubuntu', 'stage', 'airstrip', 'fileserver')):
|
||||||
|
return ('utility', 'UTIL', '🧰', '#475569')
|
||||||
|
return ('application', 'APP', '🧩', '#166534')
|
||||||
|
|
||||||
|
|
||||||
|
def node_category_summary(vms: list[dict]) -> str:
|
||||||
|
counts: dict[str, int] = {}
|
||||||
|
labels: dict[str, str] = {}
|
||||||
|
for vm in vms:
|
||||||
|
key, short, _, _ = classify_vm(vm.get('name', ''))
|
||||||
|
counts[key] = counts.get(key, 0) + 1
|
||||||
|
labels[key] = short
|
||||||
|
ordered = sorted(counts.items(), key=lambda item: (-item[1], item[0]))
|
||||||
|
parts = [f'{labels[key]} {value}' for key, value in ordered[:4]]
|
||||||
|
return ' | '.join(parts) if parts else 'n/a'
|
||||||
|
|
||||||
|
|
||||||
|
def node_label(node_name: str, vm_count: int, running: int, stopped: int, categories: str) -> str:
|
||||||
|
return (
|
||||||
|
f'<div style="line-height:1.35;">'
|
||||||
|
f'<b>Node: {html(node_name)}</b><br>'
|
||||||
|
f'VMs: <b>{vm_count}</b> | 🟢 {running} | 🔴 {stopped}<br>'
|
||||||
|
f'roles: {html(categories)}'
|
||||||
|
f'</div>'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def vm_label(project: str, vm_name: str, status: str, pip: str) -> str:
|
||||||
|
is_running = str(status).lower() == 'running'
|
||||||
|
state_text = 'RUNNING' if is_running else 'STOPPED'
|
||||||
|
state_dot = '🟢' if is_running else '🔴'
|
||||||
|
display_name = f'{project}/{vm_name}' if project != 'default' else vm_name
|
||||||
|
if len(display_name) > 26:
|
||||||
|
display_name = display_name[:23] + '...'
|
||||||
|
return (
|
||||||
|
f'<div style="line-height:1.3;">'
|
||||||
|
f'<span style="font-size:13px;"><b>{html(display_name)}</b></span><br>'
|
||||||
|
f'{state_dot} <b>{state_text}</b> | {html(pip)}'
|
||||||
|
f'</div>'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data = json.loads(SNAPSHOT.read_text())
|
||||||
|
remotes = [r for r in data['remotes'] if r.get('name') != 'local']
|
||||||
|
try:
|
||||||
|
remotes_meta = json.loads(
|
||||||
|
subprocess.check_output(["incus", "remote", "list", "--format", "json"], text=True)
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
remotes_meta = {}
|
||||||
|
|
||||||
|
mxfile = ET.Element('mxfile', {
|
||||||
|
'host': 'app.diagrams.net',
|
||||||
|
'modified': datetime.now(timezone.utc).isoformat(),
|
||||||
|
'agent': 'codex-gpt-5',
|
||||||
|
'version': '24.7.17',
|
||||||
|
'type': 'device',
|
||||||
|
})
|
||||||
|
diagram = ET.SubElement(mxfile, 'diagram', {'id': uuid.uuid4().hex[:12], 'name': 'Incus Corporate Topology'})
|
||||||
|
model = ET.SubElement(diagram, 'mxGraphModel', {
|
||||||
|
'dx': '2000', 'dy': '1200', 'grid': '1', 'gridSize': '10', 'guides': '1',
|
||||||
|
'tooltips': '1', 'connect': '1', 'arrows': '1', 'fold': '1', 'page': '1',
|
||||||
|
'pageScale': '1', 'pageWidth': '2200', 'pageHeight': '1300', 'math': '0', 'shadow': '0'
|
||||||
|
})
|
||||||
|
root = ET.SubElement(model, 'root')
|
||||||
|
ET.SubElement(root, 'mxCell', {'id': '0'})
|
||||||
|
ET.SubElement(root, 'mxCell', {'id': '1', 'parent': '0'})
|
||||||
|
|
||||||
|
title_style = (
|
||||||
|
'rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;'
|
||||||
|
'fontSize=22;fontStyle=1;fontFamily=Inter;fillColor=#F8FAFC;fontColor=#0F172A;strokeColor=#CBD5E1;'
|
||||||
|
'spacingLeft=20;arcSize=10;'
|
||||||
|
)
|
||||||
|
generated_at = data.get('generated_at', 'n/a')
|
||||||
|
add_vertex(
|
||||||
|
root,
|
||||||
|
safe_id('title'),
|
||||||
|
f'<div><b>Incus Infrastructure Topology</b><br>Generated: {html(generated_at)}</div>',
|
||||||
|
title_style,
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
2160,
|
||||||
|
78,
|
||||||
|
)
|
||||||
|
|
||||||
|
remote_x = 20
|
||||||
|
remote_y = 165
|
||||||
|
remote_w = 525
|
||||||
|
remote_gap = 20
|
||||||
|
max_cols = 4
|
||||||
|
# Keep a fixed generous header area so metadata never gets covered by node cards.
|
||||||
|
remote_header_h = 106
|
||||||
|
|
||||||
|
remote_style_base = (
|
||||||
|
'rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;'
|
||||||
|
'fontSize=13;fontStyle=1;fontFamily=Inter;spacingTop=12;spacingLeft=14;arcSize=10;'
|
||||||
|
)
|
||||||
|
node_style = (
|
||||||
|
'rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;'
|
||||||
|
'fontSize=12;fontStyle=1;fontFamily=Inter;fillColor=#F8FAFC;strokeColor=#CBD5E1;fontColor=#0F172A;'
|
||||||
|
'spacingTop=8;spacingLeft=10;arcSize=8;'
|
||||||
|
)
|
||||||
|
vm_running_style = (
|
||||||
|
'rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;'
|
||||||
|
'fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;'
|
||||||
|
'spacingTop=10;spacingLeft=10;arcSize=6;'
|
||||||
|
)
|
||||||
|
vm_stopped_style = (
|
||||||
|
'rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;'
|
||||||
|
'fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;'
|
||||||
|
'spacingTop=10;spacingLeft=10;arcSize=6;'
|
||||||
|
)
|
||||||
|
vm_badge_style_base = (
|
||||||
|
'shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;'
|
||||||
|
'fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;'
|
||||||
|
)
|
||||||
|
edge_style = (
|
||||||
|
'endArrow=none;rounded=1;strokeColor=#94A3B8;strokeWidth=1;opacity=20;dashed=1;'
|
||||||
|
'orthogonalLoop=1;jettySize=auto;orthogonal=1;'
|
||||||
|
)
|
||||||
|
|
||||||
|
remotes_sorted = sorted(
|
||||||
|
remotes,
|
||||||
|
key=lambda r: (
|
||||||
|
0 if r['name'] == 'local' else 1 if not r['name'].startswith('hetzner') else 2,
|
||||||
|
r['name'],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
total_nodes = 0
|
||||||
|
total_vms = 0
|
||||||
|
total_running = 0
|
||||||
|
total_stopped = 0
|
||||||
|
|
||||||
|
for remote in remotes_sorted:
|
||||||
|
instances = remote.get('instances', [])
|
||||||
|
total_vms += len(instances)
|
||||||
|
total_running += sum(1 for vm in instances if str(vm.get('status', '')).lower() == 'running')
|
||||||
|
total_stopped += sum(1 for vm in instances if str(vm.get('status', '')).lower() != 'running')
|
||||||
|
|
||||||
|
server = remote.get('server', {})
|
||||||
|
env = server.get('environment', {})
|
||||||
|
server_name = env.get('server_name', 'unknown')
|
||||||
|
nodes = {}
|
||||||
|
for inst in instances:
|
||||||
|
loc = inst.get('location') or 'none'
|
||||||
|
node_name = server_name if loc in ('none', '') else loc
|
||||||
|
nodes.setdefault(node_name, []).append(inst)
|
||||||
|
if not nodes:
|
||||||
|
nodes = {server_name: []}
|
||||||
|
total_nodes += len(nodes)
|
||||||
|
|
||||||
|
summary_style = (
|
||||||
|
'rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;'
|
||||||
|
'fontSize=13;fontStyle=1;fontFamily=Inter;fillColor=#FFFFFF;strokeColor=#CBD5E1;arcSize=8;spacingLeft=12;'
|
||||||
|
)
|
||||||
|
chip_w = 210
|
||||||
|
chip_h = 36
|
||||||
|
chip_y = 115
|
||||||
|
add_vertex(root, safe_id('s1'), f'Remotes: <b>{len(remotes_sorted)}</b>', summary_style, 20, chip_y, chip_w, chip_h)
|
||||||
|
add_vertex(root, safe_id('s2'), f'Nodes: <b>{total_nodes}</b>', summary_style, 240, chip_y, chip_w, chip_h)
|
||||||
|
add_vertex(root, safe_id('s3'), f'VMs: <b>{total_vms}</b>', summary_style, 460, chip_y, chip_w, chip_h)
|
||||||
|
add_vertex(root, safe_id('s4'), f'Running: <b>{total_running}</b>', vm_running_style, 680, chip_y, chip_w, chip_h)
|
||||||
|
add_vertex(root, safe_id('s5'), f'Stopped: <b>{total_stopped}</b>', vm_stopped_style, 900, chip_y, chip_w, chip_h)
|
||||||
|
|
||||||
|
max_remote_bottom = 0
|
||||||
|
row_bottom = remote_y
|
||||||
|
|
||||||
|
for idx_remote, remote in enumerate(remotes_sorted):
|
||||||
|
name = remote['name']
|
||||||
|
server = remote.get('server', {})
|
||||||
|
env = server.get('environment', {})
|
||||||
|
server_name = env.get('server_name', 'unknown')
|
||||||
|
clustered = env.get('server_clustered', False)
|
||||||
|
addr = (remotes_meta.get(name) or {}).get('Addr') or 'n/a'
|
||||||
|
|
||||||
|
instances = remote.get('instances', [])
|
||||||
|
nodes = {}
|
||||||
|
for inst in instances:
|
||||||
|
loc = inst.get('location') or 'none'
|
||||||
|
node_name = server_name if loc in ('none', '') else loc
|
||||||
|
nodes.setdefault(node_name, []).append(inst)
|
||||||
|
|
||||||
|
if not nodes:
|
||||||
|
nodes = {server_name: []}
|
||||||
|
|
||||||
|
node_heights = []
|
||||||
|
for node_name, vms in nodes.items():
|
||||||
|
rows = max(1, (len(vms) + 1) // 2)
|
||||||
|
node_h = 50 + rows * 74 + 16
|
||||||
|
node_heights.append(node_h)
|
||||||
|
|
||||||
|
remote_h = remote_header_h + sum(node_heights) + (len(node_heights) - 1) * 16 + 20
|
||||||
|
|
||||||
|
fill, stroke, font = remote_palette(name)
|
||||||
|
remote_style = remote_style_base + f'fillColor={fill};strokeColor={stroke};fontColor={font};'
|
||||||
|
|
||||||
|
remote_id = safe_id('remote')
|
||||||
|
remote_label_value = remote_label(name, server_name, clustered, addr if addr else 'n/a', len(instances), len(nodes))
|
||||||
|
add_vertex(root, remote_id, remote_label_value, remote_style, remote_x, remote_y, remote_w, remote_h)
|
||||||
|
|
||||||
|
current_y = remote_y + remote_header_h
|
||||||
|
for node_name, vms in nodes.items():
|
||||||
|
rows = max(1, (len(vms) + 1) // 2)
|
||||||
|
node_h = 50 + rows * 74 + 16
|
||||||
|
node_id = safe_id('node')
|
||||||
|
running = sum(1 for vm in vms if str(vm.get('status', '')).lower() == 'running')
|
||||||
|
stopped = len(vms) - running
|
||||||
|
categories = node_category_summary(vms)
|
||||||
|
add_vertex(
|
||||||
|
root,
|
||||||
|
node_id,
|
||||||
|
node_label(node_name, len(vms), running, stopped, categories),
|
||||||
|
node_style,
|
||||||
|
remote_x + 12,
|
||||||
|
current_y,
|
||||||
|
remote_w - 24,
|
||||||
|
node_h,
|
||||||
|
)
|
||||||
|
|
||||||
|
vm_w = (remote_w - 24 - 18) / 2
|
||||||
|
for idx, vm in enumerate(vms):
|
||||||
|
col = idx % 2
|
||||||
|
row = idx // 2
|
||||||
|
vm_x = remote_x + 20 + col * (vm_w + 10)
|
||||||
|
vm_y = current_y + 46 + row * 74
|
||||||
|
|
||||||
|
status = vm.get('status', 'Unknown')
|
||||||
|
vm_name = vm.get('name', 'unknown')
|
||||||
|
project = vm.get('project', 'default')
|
||||||
|
ips = extract_ips(vm)
|
||||||
|
pip = primary_ip(ips)
|
||||||
|
_, short_role, role_icon, role_color = classify_vm(vm_name)
|
||||||
|
|
||||||
|
vm_style = vm_running_style if str(status).lower() == 'running' else vm_stopped_style
|
||||||
|
vm_style += 'strokeWidth=1.2;'
|
||||||
|
vm_id = safe_id('vm')
|
||||||
|
add_vertex(root, vm_id, vm_label(project, vm_name, status, pip), vm_style, vm_x, vm_y, vm_w, 66)
|
||||||
|
add_vertex(
|
||||||
|
root,
|
||||||
|
safe_id('role'),
|
||||||
|
role_icon,
|
||||||
|
vm_badge_style_base + f'fillColor={role_color};strokeColor={role_color};fontColor=#FFFFFF;',
|
||||||
|
vm_x + vm_w - 26,
|
||||||
|
vm_y + 5,
|
||||||
|
18,
|
||||||
|
18,
|
||||||
|
)
|
||||||
|
|
||||||
|
current_y += node_h + 16
|
||||||
|
|
||||||
|
max_remote_bottom = max(max_remote_bottom, remote_y + remote_h)
|
||||||
|
row_bottom = max(row_bottom, remote_y + remote_h)
|
||||||
|
if (idx_remote + 1) % max_cols == 0:
|
||||||
|
remote_x = 20
|
||||||
|
remote_y = row_bottom + 20
|
||||||
|
row_bottom = remote_y
|
||||||
|
else:
|
||||||
|
remote_x += remote_w + remote_gap
|
||||||
|
|
||||||
|
legend_y = max_remote_bottom + 20
|
||||||
|
legend_style = (
|
||||||
|
'rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;'
|
||||||
|
'fontSize=12;fontStyle=1;fontFamily=Inter;fillColor=#FFFFFF;strokeColor=#CBD5E1;fontColor=#0F172A;arcSize=8;'
|
||||||
|
)
|
||||||
|
add_vertex(root, safe_id('legend_title'), 'Legend', legend_style, 20, legend_y, 140, 36)
|
||||||
|
add_vertex(root, safe_id('lg1'), 'Running VM', vm_running_style, 170, legend_y, 180, 36)
|
||||||
|
add_vertex(root, safe_id('lg2'), 'Stopped VM', vm_stopped_style, 360, legend_y, 180, 36)
|
||||||
|
add_vertex(root, safe_id('lg5'), 'Role badges: 🌐 🗄 ⚙ 📈 🔐 🧰 🧩', legend_style, 550, legend_y, 340, 36)
|
||||||
|
|
||||||
|
ET.indent(mxfile, space=' ')
|
||||||
|
OUT.write_text(ET.tostring(mxfile, encoding='unicode'))
|
||||||
|
print(str(OUT))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2026-04-09T11:58:51.653223+00:00" agent="codex-gpt-5" version="24.7.17" type="device">
|
||||||
|
<diagram id="70f5a7db7c81" name="Incus Corporate Topology">
|
||||||
|
<mxGraphModel dx="2000" dy="1200" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2200" pageHeight="1300" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0" />
|
||||||
|
<mxCell id="1" parent="0" />
|
||||||
|
<mxCell id="title_74850cde" value="<div><b>Incus Infrastructure Topology</b><br>Generated: 2026-04-09T13:22:37+02:00</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;fontSize=22;fontStyle=1;fontFamily=Inter;fillColor=#F8FAFC;fontColor=#0F172A;strokeColor=#CBD5E1;spacingLeft=20;arcSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="20" y="20" width="2160" height="78" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="s1_ce4710a9" value="Remotes: <b>3</b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;fontSize=13;fontStyle=1;fontFamily=Inter;fillColor=#FFFFFF;strokeColor=#CBD5E1;arcSize=8;spacingLeft=12;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="20" y="115" width="210" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="s2_468d3274" value="Nodes: <b>3</b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;fontSize=13;fontStyle=1;fontFamily=Inter;fillColor=#FFFFFF;strokeColor=#CBD5E1;arcSize=8;spacingLeft=12;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="240" y="115" width="210" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="s3_b52be8f4" value="VMs: <b>22</b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;fontSize=13;fontStyle=1;fontFamily=Inter;fillColor=#FFFFFF;strokeColor=#CBD5E1;arcSize=8;spacingLeft=12;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="460" y="115" width="210" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="s4_29c797ce" value="Running: <b>17</b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="680" y="115" width="210" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="s5_919275f4" value="Stopped: <b>5</b>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;spacingTop=10;spacingLeft=10;arcSize=6;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="900" y="115" width="210" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="remote_94130581" value="<div style="line-height:1.35;"><span style="font-size:17px;"><b>kuber</b></span><br>🖥 <b>kuber</b> | cluster: <b>false</b><br>🌍 10.0.50.79:8443<br>📦 nodes: <b>1</b> | vms: <b>8</b></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=13;fontStyle=1;fontFamily=Inter;spacingTop=12;spacingLeft=14;arcSize=10;fillColor=#ECF3FF;strokeColor=#3E7BDA;fontColor=#123765;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="20" y="165" width="525" height="488" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="node_0fae4ba7" value="<div style="line-height:1.35;"><b>Node: kuber</b><br>VMs: <b>8</b> | 🟢 5 | 🔴 3<br>roles: UTIL 6 | CI 1 | DB 1</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=12;fontStyle=1;fontFamily=Inter;fillColor=#F8FAFC;strokeColor=#CBD5E1;fontColor=#0F172A;spacingTop=8;spacingLeft=10;arcSize=8;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="32" y="271" width="501" height="362" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_1bcbc1bd" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>cassandra</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.164</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="40.0" y="317" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_5350e310" value="🗄" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#7C3AED;strokeColor=#7C3AED;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="255.5" y="322" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_1df3d2f6" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>fileserver</b></span><br>🔴 <b>STOPPED</b> | n/a</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="291.5" y="317" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_c8808ac1" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="507.0" y="322" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_5a665c77" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>harness</b></span><br>🔴 <b>STOPPED</b> | n/a</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="40.0" y="391" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_638a62d1" value="⚙" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#B45309;strokeColor=#B45309;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="255.5" y="396" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_289ebce7" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>lxconsole</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.173</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="291.5" y="391" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_defdb2b5" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="507.0" y="396" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_a95fc429" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>shellhub</b></span><br>🔴 <b>STOPPED</b> | n/a</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="40.0" y="465" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_8a6caa1f" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="255.5" y="470" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_ad398d3b" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>testvm</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.45</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="291.5" y="465" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_fec1eca0" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="507.0" y="470" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_4e7be1a8" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>ubuntu-22-plcnext-conn</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.43</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="40.0" y="539" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_9f2596bb" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="255.5" y="544" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_813c86bb" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>ubuntu20</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.181</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="291.5" y="539" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_e45a2a04" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="507.0" y="544" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="remote_d51f11c7" value="<div style="line-height:1.35;"><span style="font-size:17px;"><b>virgo-incus</b></span><br>🖥 <b>virgo</b> | cluster: <b>false</b><br>🌍 10.0.50.9:8443<br>📦 nodes: <b>1</b> | vms: <b>8</b></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=13;fontStyle=1;fontFamily=Inter;spacingTop=12;spacingLeft=14;arcSize=10;fillColor=#ECF3FF;strokeColor=#3E7BDA;fontColor=#123765;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="565" y="165" width="525" height="488" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="node_1b8d7cdd" value="<div style="line-height:1.35;"><b>Node: virgo</b><br>VMs: <b>8</b> | 🟢 7 | 🔴 1<br>roles: UTIL 3 | DB 2 | APP 1 | NET 1</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=12;fontStyle=1;fontFamily=Inter;fillColor=#F8FAFC;strokeColor=#CBD5E1;fontColor=#0F172A;spacingTop=8;spacingLeft=10;arcSize=8;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="577" y="271" width="501" height="362" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_51e9cf34" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>ai-stage</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.81</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="585.0" y="317" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_db4a2911" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="800.5" y="322" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_0653b7c2" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>airstrip</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.47</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="836.5" y="317" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_2bc5c5d9" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1052.0" y="322" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_c74087e6" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>cassandra-int1</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.225</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="585.0" y="391" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_91237b5f" value="🗄" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#7C3AED;strokeColor=#7C3AED;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="800.5" y="396" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_01514c80" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>homarr</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.41</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="836.5" y="391" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_220837a2" value="🧩" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#166534;strokeColor=#166534;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1052.0" y="396" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_1663767c" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>infisical</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.52</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="585.0" y="465" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_ef5330ae" value="🔐" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#BE123C;strokeColor=#BE123C;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="800.5" y="470" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_63cf2e09" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>pg-backend</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.44</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="836.5" y="465" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_aa82f654" value="🗄" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#7C3AED;strokeColor=#7C3AED;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1052.0" y="470" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_2c43aca5" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>tester</b></span><br>🟢 <b>RUNNING</b> | 10.0.50.46</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="585.0" y="539" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_297a4c04" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="800.5" y="544" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_80fb5b1c" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>wacli</b></span><br>🔴 <b>STOPPED</b> | n/a</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="836.5" y="539" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_533064a1" value="🌐" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#1D4ED8;strokeColor=#1D4ED8;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1052.0" y="544" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="remote_030ae67c" value="<div style="line-height:1.35;"><span style="font-size:17px;"><b>hetzner-incus2</b></span><br>🖥 <b>incus2</b> | cluster: <b>false</b><br>🌍 138.201.135.107:8443<br>📦 nodes: <b>1</b> | vms: <b>6</b></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=13;fontStyle=1;fontFamily=Inter;spacingTop=12;spacingLeft=14;arcSize=10;fillColor=#FFF4E8;strokeColor=#E38B1A;fontColor=#7A3E00;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1110" y="165" width="525" height="414" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="node_d2406a6c" value="<div style="line-height:1.35;"><b>Node: incus2</b><br>VMs: <b>6</b> | 🟢 5 | 🔴 1<br>roles: APP 3 | CI 1 | DB 1 | UTIL 1</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=12;fontStyle=1;fontFamily=Inter;fillColor=#F8FAFC;strokeColor=#CBD5E1;fontColor=#0F172A;spacingTop=8;spacingLeft=10;arcSize=8;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1122" y="271" width="501" height="288" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_f5560c22" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>arizephoenix</b></span><br>🟢 <b>RUNNING</b> | 10.236.251.83</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1130.0" y="317" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_2be5a68b" value="🧩" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#166534;strokeColor=#166534;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1345.5" y="322" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_a7cd2d61" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>customer-portal-new</b></span><br>🟢 <b>RUNNING</b> | 10.236.251.84</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1381.5" y="317" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_c8d1c9c0" value="🧩" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#166534;strokeColor=#166534;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1597.0" y="322" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_a25f64db" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>jenkins</b></span><br>🟢 <b>RUNNING</b> | 10.236.251.80</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1130.0" y="391" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_7ffa29fd" value="⚙" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#B45309;strokeColor=#B45309;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1345.5" y="396" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_65fa0b8d" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>showcase</b></span><br>🟢 <b>RUNNING</b> | 10.236.251.81</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1381.5" y="391" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_30116c77" value="🧩" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#166534;strokeColor=#166534;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1597.0" y="396" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_160b3a58" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>supabase</b></span><br>🟢 <b>RUNNING</b> | 10.236.251.82</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1130.0" y="465" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_e408ef95" value="🗄" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#7C3AED;strokeColor=#7C3AED;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1345.5" y="470" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="vm_d95eb58d" value="<div style="line-height:1.3;"><span style="font-size:13px;"><b>testing-prtiv1</b></span><br>🔴 <b>STOPPED</b> | n/a</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;spacingTop=10;spacingLeft=10;arcSize=6;strokeWidth=1.2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1381.5" y="465" width="241.5" height="66" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="role_4f4cdbce" value="🧰" style="shape=ellipse;whiteSpace=wrap;html=1;align=center;verticalAlign=middle;fontSize=9;fontStyle=1;fontFamily=Inter;strokeWidth=0;fillColor=#475569;strokeColor=#475569;fontColor=#FFFFFF;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="1597.0" y="470" width="18" height="18" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="legend_title_183fc7ff" value="Legend" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;fontSize=12;fontStyle=1;fontFamily=Inter;fillColor=#FFFFFF;strokeColor=#CBD5E1;fontColor=#0F172A;arcSize=8;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="20" y="673" width="140" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="lg1_8ae5f895" value="Running VM" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#0B1F14;fillColor=#ECFDF3;strokeColor=#86EFAC;spacingTop=10;spacingLeft=10;arcSize=6;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="170" y="673" width="180" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="lg2_c3313f36" value="Stopped VM" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fontSize=11;fontFamily=Inter;fontColor=#3A1414;fillColor=#FEF2F2;strokeColor=#FCA5A5;spacingTop=10;spacingLeft=10;arcSize=6;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="360" y="673" width="180" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="lg5_5bb5dd79" value="Role badges: 🌐 🗄 ⚙ 📈 🔐 🧰 🧩" style="rounded=1;whiteSpace=wrap;html=1;align=left;verticalAlign=middle;fontSize=12;fontStyle=1;fontFamily=Inter;fillColor=#FFFFFF;strokeColor=#CBD5E1;fontColor=#0F172A;arcSize=8;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="550" y="673" width="340" height="36" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
@@ -0,0 +1,105 @@
|
|||||||
|
# Incus Topology Map
|
||||||
|
|
||||||
|
Generated: 2026-04-09 11:54:22 CEST
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
- **hetzner-incus2** (https://138.201.135.107:8443) -> server: **incus2**, clustered: **false**, instances: **6**
|
||||||
|
- **kuber** (https://10.0.50.79:8443) -> server: **kuber**, clustered: **false**, instances: **8**
|
||||||
|
- **local** (unix://) -> server: **lenovo**, clustered: **false**, instances: **0**
|
||||||
|
- **virgo-incus** (https://10.0.50.9:8443) -> server: **virgo**, clustered: **false**, instances: **8**
|
||||||
|
|
||||||
|
## Visual Map
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
ROOT[Incus Access]
|
||||||
|
ROOT --> R_hetznerincus2["remote: hetzner-incus2"]
|
||||||
|
R_hetznerincus2 --> N_hetznerincus2_incus2["node: incus2"]
|
||||||
|
N_hetznerincus2_incus2 --> V_hetznerincus2_incus2_defaultarizephoenix["default/arizephoenix (Running)\n10.236.251.83"]
|
||||||
|
N_hetznerincus2_incus2 --> V_hetznerincus2_incus2_defaultcustomerportalnew["default/customer-portal-new (Running)\n10.236.251.84"]
|
||||||
|
N_hetznerincus2_incus2 --> V_hetznerincus2_incus2_defaultjenkins["default/jenkins (Running)\n10.236.251.80"]
|
||||||
|
N_hetznerincus2_incus2 --> V_hetznerincus2_incus2_defaultshowcase["default/showcase (Running)\n10.236.251.81"]
|
||||||
|
N_hetznerincus2_incus2 --> V_hetznerincus2_incus2_defaultsupabase["default/supabase (Running)\n10.236.251.82"]
|
||||||
|
N_hetznerincus2_incus2 --> V_hetznerincus2_incus2_defaulttestingprtiv1["default/testing-prtiv1 (Stopped)\nn/a"]
|
||||||
|
ROOT --> R_kuber["remote: kuber"]
|
||||||
|
R_kuber --> N_kuber_kuber["node: kuber"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaultcassandra["default/cassandra (Running)\n10.0.50.164"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaultfileserver["default/fileserver (Stopped)\nn/a"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaultharness["default/harness (Stopped)\nn/a"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaultlxconsole["default/lxconsole (Running)\n10.0.50.173"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaultshellhub["default/shellhub (Stopped)\nn/a"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaulttestvm["default/testvm (Running)\n10.0.50.45"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaultubuntu22plcnextconn["default/ubuntu-22-plcnext-conn (Running)\n10.0.50.43"]
|
||||||
|
N_kuber_kuber --> V_kuber_kuber_defaultubuntu20["default/ubuntu20 (Running)\n10.0.50.181"]
|
||||||
|
ROOT --> R_local["remote: local"]
|
||||||
|
R_local --> N_local_lenovo["node: lenovo"]
|
||||||
|
N_local_lenovo --> E_local_lenovo["(no VMs)"]
|
||||||
|
ROOT --> R_virgoincus["remote: virgo-incus"]
|
||||||
|
R_virgoincus --> N_virgoincus_virgo["node: virgo"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaultaistage["default/ai-stage (Running)\n10.0.50.81"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaultairstrip["default/airstrip (Running)\n10.0.50.47"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaultcassandraint1["default/cassandra-int1 (Running)\n10.0.50.225"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaulthomarr["default/homarr (Running)\n10.0.50.41"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaultinfisical["default/infisical (Running)\n10.0.50.52"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaultpgbackend["default/pg-backend (Running)\n10.0.50.44"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaulttester["default/tester (Running)\n10.0.50.46"]
|
||||||
|
N_virgoincus_virgo --> V_virgoincus_virgo_defaultwacli["default/wacli (Stopped)\nn/a"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tree View (Remote -> Node -> VM)
|
||||||
|
|
||||||
|
### Remote: hetzner-incus2
|
||||||
|
- Endpoint: https://138.201.135.107:8443
|
||||||
|
- Server name: incus2
|
||||||
|
- Clustered: false
|
||||||
|
- Projects: default
|
||||||
|
- Nodes:
|
||||||
|
- incus2
|
||||||
|
- default/arizephoenix [virtual-machine] status=Running primary_ip=10.236.251.83 all_ipv4=10.236.251.83, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/customer-portal-new [virtual-machine] status=Running primary_ip=10.236.251.84 all_ipv4=10.236.251.84, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/jenkins [virtual-machine] status=Running primary_ip=10.236.251.80 all_ipv4=10.236.251.80
|
||||||
|
- default/showcase [virtual-machine] status=Running primary_ip=10.236.251.81 all_ipv4=10.236.251.81, 172.17.0.1, 172.18.0.1, 172.19.0.1, 172.20.0.1, 172.21.0.1
|
||||||
|
- default/supabase [virtual-machine] status=Running primary_ip=10.236.251.82 all_ipv4=10.236.251.82, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/testing-prtiv1 [virtual-machine] status=Stopped primary_ip=n/a all_ipv4=n/a
|
||||||
|
|
||||||
|
### Remote: kuber
|
||||||
|
- Endpoint: https://10.0.50.79:8443
|
||||||
|
- Server name: kuber
|
||||||
|
- Clustered: false
|
||||||
|
- Projects: default
|
||||||
|
- Nodes:
|
||||||
|
- kuber
|
||||||
|
- default/cassandra [virtual-machine] status=Running primary_ip=10.0.50.164 all_ipv4=10.0.50.164
|
||||||
|
- default/fileserver [virtual-machine] status=Stopped primary_ip=n/a all_ipv4=n/a
|
||||||
|
- default/harness [virtual-machine] status=Stopped primary_ip=n/a all_ipv4=n/a
|
||||||
|
- default/lxconsole [virtual-machine] status=Running primary_ip=10.0.50.173 all_ipv4=10.0.50.173, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/shellhub [virtual-machine] status=Stopped primary_ip=n/a all_ipv4=n/a
|
||||||
|
- default/testvm [virtual-machine] status=Running primary_ip=10.0.50.45 all_ipv4=10.0.50.45, 172.16.0.1, 172.16.0.17, 172.17.0.1
|
||||||
|
- default/ubuntu-22-plcnext-conn [virtual-machine] status=Running primary_ip=10.0.50.43 all_ipv4=10.0.50.43, 172.17.0.1
|
||||||
|
- default/ubuntu20 [virtual-machine] status=Running primary_ip=10.0.50.181 all_ipv4=10.0.50.181, 172.17.0.1
|
||||||
|
|
||||||
|
### Remote: local
|
||||||
|
- Endpoint: unix://
|
||||||
|
- Server name: lenovo
|
||||||
|
- Clustered: false
|
||||||
|
- Projects: default
|
||||||
|
- Nodes:
|
||||||
|
- lenovo
|
||||||
|
- (no instances)
|
||||||
|
|
||||||
|
### Remote: virgo-incus
|
||||||
|
- Endpoint: https://10.0.50.9:8443
|
||||||
|
- Server name: virgo
|
||||||
|
- Clustered: false
|
||||||
|
- Projects: default
|
||||||
|
- Nodes:
|
||||||
|
- virgo
|
||||||
|
- default/ai-stage [virtual-machine] status=Running primary_ip=10.0.50.81 all_ipv4=10.0.50.81, 172.17.0.1, 172.18.0.1, 172.19.0.1, 172.20.0.1, 172.21.0.1
|
||||||
|
- default/airstrip [virtual-machine] status=Running primary_ip=10.0.50.47 all_ipv4=10.0.50.47, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/cassandra-int1 [virtual-machine] status=Running primary_ip=10.0.50.225 all_ipv4=10.0.50.225, 172.17.0.1
|
||||||
|
- default/homarr [virtual-machine] status=Running primary_ip=10.0.50.41 all_ipv4=10.0.50.41, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/infisical [virtual-machine] status=Running primary_ip=10.0.50.52 all_ipv4=10.0.50.52, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/pg-backend [virtual-machine] status=Running primary_ip=10.0.50.44 all_ipv4=10.0.50.44, 172.17.0.1, 172.18.0.1
|
||||||
|
- default/tester [virtual-machine] status=Running primary_ip=10.0.50.46 all_ipv4=10.0.50.46
|
||||||
|
- default/wacli [virtual-machine] status=Stopped primary_ip=n/a all_ipv4=n/a
|
||||||
|
|
||||||
Reference in New Issue
Block a user