From 792557c604cb2ee7f0b20f0d19e308654a65ab69 Mon Sep 17 00:00:00 2001 From: "Eric D. Helms" Date: Tue, 5 May 2026 12:23:54 -0400 Subject: [PATCH] Scope Vagrant libvirt domains to allow multiple checkouts Use a hash of the absolute working directory path to generate a unique libvirt domain prefix per checkout, preventing collisions when multiple clones or git worktrees deploy Vagrant boxes simultaneously. Both the libvirt domain name prefix and the VM hostnames are scoped using the prefix, ensuring full isolation between deployments. Resolve VM FQDNs dynamically in CI and test fixtures instead of hardcoding the .example.com domain. Co-Authored-By: Claude Opus 4.6 --- DEVELOPMENT.md | 13 +++++++++++++ Vagrantfile | 12 +++++++++--- tests/conftest.py | 4 ++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 21d73de00..68c99100e 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -39,6 +39,19 @@ source .venv/bin/activate ./foremanctl deploy --initial-admin-password=changeme --tuning development --initial-organization "Foreman CI" --initial-location "Internet" ``` +### Running Multiple Checkouts Simultaneously + +If you have multiple clones or git worktrees of this repo and want to run Vagrant VMs for each at the same time, set the `FOREMANCTL_VAGRANT_PREFIX` environment variable before starting VMs: + +``` +export FOREMANCTL_VAGRANT_PREFIX=1 +./forge vms start +``` + +When set, the Vagrantfile generates a unique 8-character prefix from an MD5 hash of the working directory path. This prefix is applied to both the libvirt domain names and VM hostnames, preventing collisions between deployments. + +Without the variable set, behavior is unchanged and VMs use the default hostnames. + ### Deploy hammer (optional) ``` diff --git a/Vagrantfile b/Vagrantfile index 99a51ae70..d2e2b3c56 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,4 +1,7 @@ +require 'digest' + DOMAIN = ENV.fetch('VAGRANT_DOMAIN', 'example.com'.freeze) +prefix = ENV.key?('FOREMANCTL_VAGRANT_PREFIX') ? Digest::MD5.hexdigest(Dir.pwd)[0..7] : nil Vagrant.configure("2") do |config| config.vm.synced_folder ".", "/vagrant" @@ -18,9 +21,10 @@ Vagrant.configure("2") do |config| config.vm.define "quadlet" do |override| override.vm.box = ENV.fetch("FOREMANCTL_BASE_BOX", "centos/stream9") - override.vm.hostname = "quadlet.#{DOMAIN}" + override.vm.hostname = prefix ? "quadlet.#{prefix}.#{DOMAIN}" : "quadlet.#{DOMAIN}" override.vm.provider "libvirt" do |libvirt, provider| + libvirt.default_prefix = prefix if prefix libvirt.memory = 10240 libvirt.cpus = 4 libvirt.machine_virtual_size = 30 @@ -29,18 +33,20 @@ Vagrant.configure("2") do |config| config.vm.define "client" do |override| override.vm.box = "centos/stream9" - override.vm.hostname = "client.#{DOMAIN}" + override.vm.hostname = prefix ? "client.#{prefix}.#{DOMAIN}" : "client.#{DOMAIN}" override.vm.provider "libvirt" do |libvirt, provider| + libvirt.default_prefix = prefix if prefix libvirt.memory = 1024 end end config.vm.define "database" do |override| override.vm.box = "centos/stream9" - override.vm.hostname = "database.#{DOMAIN}" + override.vm.hostname = prefix ? "database.#{prefix}.#{DOMAIN}" : "database.#{DOMAIN}" override.vm.provider "libvirt" do |libvirt, provider| + libvirt.default_prefix = prefix if prefix libvirt.memory = 2048 end end diff --git a/tests/conftest.py b/tests/conftest.py index 9bf66ec3b..54551a352 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -63,7 +63,7 @@ def server_hostname(): @pytest.fixture(scope="module") def server_fqdn(server): - return server.check_output('hostname -f') + return server.backend.hostname @pytest.fixture(scope="module") @@ -73,7 +73,7 @@ def client_hostname(): @pytest.fixture(scope="module") def client_fqdn(client): - return client.check_output('hostname -f') + return client.backend.hostname @pytest.fixture(scope="module")