From 4bcf9dea9733d9d4a375865c6e8283cb42b0f447 Mon Sep 17 00:00:00 2001 From: David White Date: Fri, 23 Oct 2026 10:55:55 +0100 Subject: [PATCH 1/2] Create every VM with the VNC clipboard and a serial port The node's console copies its configure link to the viewer through both. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 6 ++++++ src/arcane_mage/provisioner.py | 7 +++++++ tests/test_provisioner.py | 16 ++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ebfb3a..501fc7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Added + +- **Console copy devices**: every VM is created with `vga: std,clipboard=vnc` and `serial0: socket`. The node's console offers its configure link to the viewer's clipboard (the noVNC clipboard panel) and writes it to the serial port (the xterm.js console). VNC clipboard needs PVE 8.2, below the 8.4.1 minimum. + ## 3.0.0 ### Breaking Changes diff --git a/src/arcane_mage/provisioner.py b/src/arcane_mage/provisioner.py index 5ade0dc..40e2f5b 100644 --- a/src/arcane_mage/provisioner.py +++ b/src/arcane_mage/provisioner.py @@ -58,6 +58,8 @@ class VmConfig: ide2: str net0: str scsihw: str + vga: str + serial0: str startup: str | None = None def to_proxmox_dict(self) -> dict: @@ -528,6 +530,11 @@ async def create_vm_config( ide2=f"{storage_iso}:iso/{iso_name},media=cdrom", net0=f"model=virtio,bridge={network_bridge}{network_rate}", scsihw="virtio-scsi-single", + # The node's console offers text to the viewer's clipboard (Proxmox's + # "Clipboard: VNC", PVE 8.2+, below MIN_API_VERSION) and writes it to its + # first serial port (the xterm.js console). + vga="std,clipboard=vnc", + serial0="socket", startup=startup_config, ) diff --git a/tests/test_provisioner.py b/tests/test_provisioner.py index eae0bb4..ee564d9 100644 --- a/tests/test_provisioner.py +++ b/tests/test_provisioner.py @@ -154,6 +154,22 @@ async def test_create_vm_config_cumulus(self, provisioner: Provisioner, mock_api assert config.memory == 8192 assert config.cores == 4 + async def test_a_vm_has_the_clipboard_channel_and_a_serial_port( + self, provisioner: Provisioner, mock_api: AsyncMock + ): + mock_api.get_next_id.return_value = ApiSuccess(payload=100) + + config = await provisioner.create_vm_config( + vm_name="test-vm", + tier="cumulus", + network_bridge="vmbr0", + ) + + assert config is not None + api = config.to_proxmox_dict() + assert api["vga"] == "std,clipboard=vnc" + assert api["serial0"] == "socket" + async def test_create_vm_config_invalid_tier(self, provisioner: Provisioner, mock_api: AsyncMock): config = await provisioner.create_vm_config( vm_name="test-vm", From 191f7e4e0c27df51e371d3211dfaf468f9f9953d Mon Sep 17 00:00:00 2001 From: David White Date: Fri, 23 Oct 2026 10:56:39 +0100 Subject: [PATCH 2/2] Release 3.1.0 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 501fc7e..4eb9f80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 3.1.0 ### Added diff --git a/pyproject.toml b/pyproject.toml index 75b576a..c019306 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "arcane-mage" -version = "3.0.0" +version = "3.1.0" description = "Automation helper for Fluxnodes" readme = "README.md" authors = [ diff --git a/uv.lock b/uv.lock index 237ae1f..03fdcf7 100644 --- a/uv.lock +++ b/uv.lock @@ -204,7 +204,7 @@ wheels = [ [[package]] name = "arcane-mage" -version = "3.0.0" +version = "3.1.0" source = { editable = "." } default-groups = ["ansible", "dev"] dependencies = [