Tested make install_os on a real Fedora 42 VM (exit 0: gcc 15, psql,
node 22 installed). Two fixes from the run:
- postgresql-setup --initdb failed with "invalid locale settings"
because Fedora cloud images ship no LANG; force a valid locale via
PGSETUP_INITDB_OPTIONS=--locale=C.UTF-8 and wipe a partial data dir
first (a failed init leaves /var/lib/pgsql/data/log behind and blocks
the retry). Verified: cluster PG 16 initialised, service active,
erplibre superuser created.
- the dev-tools group was referenced by display name ("C Development
Tools and Libraries", "No match"); use the group id c-development.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From the QEMU install logs: Debian 12 succeeded, Ubuntu 24.04 and
Fedora 42 failed.
Ubuntu (install_debian_dependency.sh):
- apt failed with "Could not get lock" (cloud-init/unattended-upgrades
hold it on first boot) -> all apt-get calls now use
DPkg::Lock::Timeout=600 so apt waits for the lock.
- "postgis" is not a package on Ubuntu 24.04, so the postgresql line
exited 1 before installing build-essential -> no C compiler -> pyenv
could not build Python 3.12.10. PostGIS is now best-effort (tries
postgis, then postgresql-postgis) and never aborts; postgresql-contrib
is added.
Fedora (new install_fedora_dependency.sh, wired into install_dev.sh):
- install_dev.sh dispatched Fedora to the apt script; it now has a
fedora / ID_LIKE branch calling a dnf-based dependency installer
(dev tools, postgresql-server + initdb, pyenv build deps, node, etc.),
using --refresh --skip-unavailable to tolerate mirror/name issues.
Bootstrap (todo.py): the dnf "curl git make" install hit a GPG/checksum
failure on a fresh image; it now uses --refresh and retries after
"dnf clean all".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After "Opening the interactive monitor..." the install now lists every
VM's log file path, so they can be read or shared even when leaving the
dashboard before the installs finish.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause of "git/make: command not found": the bootstrap ran
"apt-get update -qq && apt-get install -y $PKGS". Inside an && list,
set -e does NOT abort on failure, so when apt-get update failed (flaky
VM network) the install was silently skipped and the script marched on
without git/make. Now: "apt-get update || true; apt-get install -y
$PKGS" (update best-effort, install mandatory), followed by an explicit
"command -v curl git make" check that exits with a clear message
("Outil manquant ... (reseau de la VM ?)") instead of a cryptic failure
later. Shared by the streamed and the monitored install paths.
Dashboard: add "c" to copy the selected VM's full log to the clipboard
(OSC 52, works over SSH) with a notification; the ssh bar documents
Shift+drag for native terminal selection; on close, print a ready-to-
copy "tail -n +1 <logdir>/*.log" to share the logs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deploying ERPLibre (single VM [1] and infra [4]) now asks "Interactive
monitoring dashboard?". When yes, the installs run DETACHED (setsid, one
log file + exit marker per VM) and a Textual dashboard opens:
- left: a table of VMs with live status (⏳ running / ✅ done / ❌ failed
with exit code) and elapsed time;
- right: the selected VM's log, tailed live (f toggles follow);
- footer: the VM's ssh command; s suspends the dashboard and SSHes in;
- q quits back to the menu — the installs keep running detached, so you
can leave before they finish and reopen later on the same log dir.
New module qemu_install_monitor.py holds the detached launcher and the
Textual app. The remote install script is factored into
_qemu_erplibre_remote_cmd. Falls back gracefully if textual is missing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds textual to the ERPLibre tooling requirements (installed into
.venv.erplibre by install_locally.sh) for the upcoming interactive
dashboard that monitors parallel ERPLibre installs across VMs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Right after boot the VM's sshd may not be up yet (notably on Fedora),
so the install failed with "Connection refused". _qemu_install_erplibre_vm
now polls SSH (ssh ... true, BatchMode) for up to 3 minutes and skips
with a clear message if it never answers, instead of failing instantly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The infra distribution prompt now accepts "principal" (alongside
numbers and "all"): it deploys the default version of each distro —
ubuntu 24.04, debian 12, fedora 42 — one VM each. The default version is
also marked with a * in the distro listing so it is visible.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Minimal cloud images ship without make (and often without curl), so the
ERPLibre install cloned the repo then died on "make: command not found".
The remote bootstrap now installs curl, git and make via apt (Debian/
Ubuntu) or dnf/yum (Fedora) — running apt-get update first since
cloud-init did not refresh the lists — before cloning and running
make install_os / make install_odoo_18.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Installation was very noisy: poetry ran "install -vvv" and repo sync /
git daemon ran with -v/--verbose. They are now quiet by default
(poetry -q, repo sync -q, no git daemon --verbose) and the detailed
logs come back only when EL_VERBOSE=1.
Applied to install_locally.sh (poetry) and every manifest script (repo
sync + git daemon). env_var.sh documents EL_VERBOSE and respects a value
already set in the environment, so "EL_VERBOSE=1 make install_odoo_18"
works.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"Deploy a new VM" now asks, after a successful deploy, whether to
install ERPLibre into ~/git/erplibre (pick a branch), just like the
infra command.
Installing ERPLibre no longer only clones the repo: after the clone it
runs "make install_os" then "make install_odoo_18" over SSH (the
erplibre user has passwordless sudo from cloud-init). The Odoo target is
a constant (ERPLIBRE_ODOO_TARGET) and both the single-VM and infra flows
use the same install path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cleanup command now runs, each listed and confirmed independently:
1. orphan files (disks/seeds/.part/nvram) — as before;
2. ghost domains: libvirt domains whose disk no longer exists ->
offer destroy + undefine --nvram;
3. stale codename-named Ubuntu images (noble/resolute/... left by the
move to /releases/ version-named images) -> targeted delete;
4. orphan ~/.ssh/config entries: "Host erplibre-*" blocks with no
matching VM (personal SSH hosts are never touched);
5. stale libvirt DHCP leases whose MAC belongs to no VM (best-effort
rewrite of the dnsmasq status file + SIGHUP; they also self-expire);
6. the full base-image cache remains an explicit opt-out at the end.
Detections verified read-only on the host.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New Manage entry that finds and lists QEMU leftovers with no matching
libvirt domain, then asks before deleting:
- working disks /var/lib/libvirt/images/<name>.qcow2
- cloud-init seeds .../iso/<name>-seed.iso
- interrupted downloads (*.part)
- orphan UEFI nvram files
Sizes are shown human-readable with a total. Cached base cloud images
(reusable) are listed and offered separately, since removing them forces
a re-download; this also cleans the stale codename-named duplicates left
by the switch to /releases/ version-named images.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three papercuts hit when creating a VM from the menu:
1. Disk size "30" was passed verbatim to qemu-img resize, which read it
as 30 BYTES and failed ("use --shrink"). The prompt now shows units
(e.g. 30G, 1T) and a bare number is normalised to GB ("30" -> "30G"),
in the menu and in deploy_qemu.py itself.
2. The VM name is no longer required: leaving it blank uses the default
erplibre-<distro>-<version> (e.g. erplibre-ubuntu-2604). Distro and
version are now asked first so the default can be offered.
3. The menu ignored the deploy exit code and carried on to "wait for the
VM IP" even after a failure, hanging forever with the error scrolled
off. It now checks the return code and stops with a clear message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Debian 13 (trixie) genericcloud dropped the BIOS/GRUB-pc bootloader, so
SeaBIOS looped forever on "Booting Debian GNU/Linux" and the install
never completed. Boot via UEFI (OVMF) by default: trixie boots, and
Ubuntu/Debian 12/Fedora keep working (verified Debian 13 and Ubuntu
24.04 end to end). Add a --bios opt-out for hosts without OVMF, and pull
the UEFI firmware (ovmf / edk2-ovmf) with the libvirt/QEMU stack. VM
deletion already removes the nvram (undefine --nvram).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the exact osinfo id is missing from the local osinfo-db (e.g.
ubuntu26.04, fedora43/44), the fallback was detect=on,require=off, which
made virt-install fall back to "generic" and warn "VM performance may
suffer". Fall back instead to the latest KNOWN osinfo of the same distro
(ubuntu26.04 -> ubuntu25.10, fedora44 -> fedora42): proper virtio/OS
defaults, no warning. detect=on,require=off remains only if nothing of
the family is known.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Debian VMs came up with no configured user, no hostname and no SSH key,
so neither the console (erplibre/erplibre) nor SSH worked. Two causes,
found via the guest cloud-init.log:
1. The NoCloud seed was attached as a CD-ROM. Debian's initramfs does
not load the CD driver (sr_mod) at the init-local stage, so the
"cidata" volume was invisible and cloud-init fell back to an empty
DMI seed (Ubuntu tolerates the CD). Attach the seed as a read-only
virtio disk instead: virtio-blk is in the initramfs, the label is
seen immediately, and the user-data is applied. Works for Ubuntu too.
2. The user was added to group "admin", which does not exist on Debian
(it does on Ubuntu) -> useradd failed and the user was never created.
Use "sudo" (present on both) instead.
Validated end to end: Debian 12 and Ubuntu 24.04 both get the erplibre
user (in sudo), the hostname, console login erplibre/erplibre and SSH by
key.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The infra "Parallel deployments" prompt defaulted to a fixed 4. It now
defaults to the host CPU count (os.cpu_count()), still capped by the
number of selected VMs, with a fallback of 4 when the count is unknown.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_write_ssh_config_entry used a DOTALL (?ms) regex to remove an existing
"Host <name>" block; with DOTALL, ".*" crossed newlines and matched from
the block to the end of the file, so re-adding an already-present host
deleted every entry after it. Dropping DOTALL (keep MULTILINE, match
indented lines with [^\n]*) removes only the target block and preserves
the rest. Not a parallelism issue — the writes are sequential.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Interim Ubuntu releases (24.10, 25.04) were removed from cloud-images
/current/ once EOL, so their image URL 404'd. Switch the Ubuntu image
URL to /releases/<version>/release/ubuntu-<version>-server-cloudimg-
<arch>.img, which stays available for every published release, and drop
the EOL interim versions from the catalogue (keep supported LTS + 25.10
+ 26.04).
Also:
- silence the "crypt is deprecated" DeprecationWarning (openssl fallback
already covers Python 3.13+);
- a 404 during download now reports "image not found (EOL/removed), pick
a supported LTS" instead of blaming connectivity;
- add a NoCloud network-config (DHCP on e*) to the seed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The infra fleet was deployed one VM at a time, each blocking up to 90s
waiting for its DHCP lease. Deploys now run concurrently through a
ThreadPoolExecutor (default min(count, 4), promptable), with each job's
output captured and printed per VM as it finishes (no interleaving). VMs
are created with --no-wait-ip so workers return quickly; IPs are then
collected once for the ~/.ssh/config step. Preferred over shelling out
to GNU parallel: no external dependency, grouped output, and it stays
integrated with the ssh-config and ERPLibre-clone steps.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cloud-init's package_update/package_upgrade forced apt to hit the distro
mirrors on first boot; on a slow or unreachable network that stalls
cloud-init and delays SSH availability. They are now off by default
(SSH is already present in the cloud images and enabled via runcmd);
--apt-update opts back in (and runs upgrade too unless --no-upgrade).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
VMs were created with user "erplibre" but NO password (lock_passwd:
true), so the serial console refused every login and only SSH-by-key
worked — hence "can't connect".
- The todo deploy flow (single VM and infra) now sets a default console
password "erplibre" for the "erplibre" user, in addition to the SSH
key, so virsh console and password SSH both work. It is shown as
"Console/SSH login: erplibre / erplibre" and can be changed at the
single-VM prompt.
- The console entry now prints the default login and the Ctrl+] hint.
- After creating a VM, offer to add it to ~/.ssh/config (Host <name>,
HostName <ip>, User erplibre) so "ssh <name>" just works; the infra
flow asks once and adds every VM. Existing blocks for the same Host
are replaced, the rest of the file is preserved, mode kept 600.
Note: VMs created before this change have no console password — delete
and redeploy them to get the erplibre/erplibre login.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Group the longer menus with section headers (reordering items so the
numbering stays sequential within each section):
- Execute: Development / Data / Sources & documentation / AI &
automation / Deployment, network & security / Preferences.
- QEMU/KVM: Deployment / Manage / Catalog.
- Database: Backup / Restore / Danger zone.
- RTK: Setup / Status / Optimize.
- Config: Generate / Advanced.
The QEMU config-entry lookup now skips section rows so appended
makefile entries still map to the right number.
Also in the QEMU menu:
- new "Open the console on a VM" entry (lists VMs, asks which, reminds
Ctrl+] to quit, runs virsh console);
- "Show a VM IP address" accepts "all" to print every VM's IP.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fill_help_info() now renders {"section": "..."} entries as a header line
without consuming a number, so numbering stays continuous over the real
commands (the hardcoded elif chains keep matching). The Deploy menu is
split into "Local", "SSH (remote host)" and "Virtualization &
notifications", making the long SSH block easy to scan.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New QEMU/KVM menu entry to remove one, several or all VMs. It lists the
defined domains, lets you pick by number or "all", asks whether to also
delete the disk images (the qcow2 working disk + the seed ISO), shows
what will be removed and asks for confirmation. Each VM is powered off
(destroy) then undefined (--nvram, with a fallback for older virsh);
disks are only deleted when explicitly requested.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Debian deploy appeared frozen: cloud.debian.org sent this host to an
unreachable mirror and urlretrieve had no timeout, so it hung forever;
worse, output was block-buffered under the todo pipe so nothing showed.
- Stream downloads via urlopen with a 30s per-operation timeout: a dead
mirror now fails fast instead of hanging.
- Try several Debian mirrors in order (cloud.debian.org, then two
acc.umu.se mirrors) — first responsive one wins.
- Reconfigure stdout to line-buffered in main() so headers and progress
appear live even when captured by the menu.
- Add openssh-server to the cloud-init packages and a runcmd enabling
ssh/sshd, so every VM (Debian genericcloud included) is SSH-reachable.
- Add a timeout to the SHA256SUMS fetch too.
Validated: debian-11 fails over from cloud.debian.org to gemmei and
completes; debian-12 downloads fully.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Generalise the _is_yes() helper (y/yes/o/oui) across the whole file so
French answers work everywhere, and add _is_no() (n/no/non) for the
default-yes prompts. Converted: system-install, Pycharm, SSH-password
(default yes via _is_no), template overwrite, keep-temp-database (was
locale-gated, now accepts both), git-repo fetch and the mobile
personalize/debug/picture prompts. Drop the now-unused get_lang import.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The confirmations only matched "y", but the French prompts show "(o/N)",
so answering "o" (oui) was treated as no — the infra deployment aborted
with "Annulé." right after the user confirmed. Add a _is_yes() helper
(y/yes/o/oui) and use it for the infra deploy confirmation, the ERPLibre
install prompt, the disk-overwrite prompt and the SHA256 verify prompt.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New QEMU/KVM entry that stands up a fleet of minimal VMs, one per
selected cloud image. It:
- lets you pick distros then versions (multi-select, "all" per level, or
the whole catalogue), reading the specs straight from deploy_qemu.py so
there is no duplication;
- prints a plan with each VM's minimum RAM/disk, the total concurrent RAM
and virtual disk, and the host's available RAM, warning when the fleet
cannot all run at once;
- deploys sequentially after confirmation (minimum sizing per version),
skipping VMs that already exist;
- optionally clones ERPLibre into ~/git/erplibre on each VM, asking which
branch (list fetched via git ls-remote) and pulling git in through
cloud-init.
Naming is erplibre-<distro>-<version> (e.g. erplibre-ubuntu-2404).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Every menu now prints a breadcrumb line (e.g. "📍 TODO › Execute ›
Deploy › QEMU/KVM") right above "Command:", so it is always clear where
you are and the path can be copied to describe a menu unambiguously.
The trail is derived from the call stack via a method-name -> label map,
so no menu method had to change: fill_help_info and the three inline
menus just render self._menu_header() instead of t("Command:").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Generalise the deployer beyond Ubuntu with a distro registry and a new
--distro flag (ubuntu default, debian, fedora). Each distro keeps its
own codenames, osinfo ids and per-version minimum RAM/disk. Image URLs
are built per distro (Ubuntu current/, Debian latest/, Fedora resolved
from the release index since it has no "latest" link).
Add --list-images to print the whole catalogue with specs, exposed in
the todo menu ("List available images and specs"); the deploy/download
flows now prompt for the distro first.
Resilient osinfo: when the local osinfo-db does not know an id (e.g.
ubuntu26.04, fedora43+), fall back to virt-install detect=on,require=off
instead of failing. Ubuntu 26.04 (resolute) is now enabled.
Also: throttle the download progress to integer-percent steps (single
updating line on a TTY, at most 101 lines when captured by the menu),
and skip the spurious "network is already active" error by checking the
libvirt network state before net-start.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "Show a VM IP address" entry prompted for a VM name with no visible
list, so the user had to guess the name/ID. It now runs virsh list --all
first and asks for a "VM name or ID", making the expected input obvious.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the fixed 8192 MB / 4 vCPU / 20G defaults with the minimum
resources required by the chosen Ubuntu version (libosinfo/osinfo-db
values): 20.04 -> 2048 MB/5G, 22.04 -> 2048 MB/10G, 24.04+ -> 3072
MB/20G. --vcpus now defaults to 2. This stops a small host from being
starved by an oversized default (an 8 GB VM failed to allocate on a
6.7 GB host) and silences the libvirt "less than recommended" warning.
In the todo menu, leaving the RAM/vCPU/disk fields blank now means
"version minimum" (the flag is simply not passed) instead of forcing
8192/4/20G. Any explicit value still overrides. README regenerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expose the QEMU deploy script from the interactive assistant so users
can create, preview, download and manage Ubuntu VMs without memorising
CLI flags. Adds a QEMU/KVM entry under Deploy, its fr/en translations,
and an extensible qemu_from_makefile section in todo.json.
Generated by Claude Code 2.1.210 claude-opus-4-8
Co-Authored-By: Mathieu Benoit <mathben@technolibre.ca>
The script previously required a manually supplied image path and only
installed the client tools, so a bare host aborted at virt-install with
a missing libvirt-sock. It now derives and downloads the Ubuntu cloud
image from --version, detects and installs the full libvirt+QEMU stack
(daemon and system emulator included) through the host package manager,
then enables libvirtd. Adds a --download-only mode, a hypervisor
preflight check, clean error messages instead of Python tracebacks, and
a bilingual usage guide (README).
Generated by Claude Code 2.1.210 claude-opus-4-8
Co-Authored-By: Mathieu Benoit <mathben@technolibre.ca>