Vagrant/Libvirt basic test/dev environment
Signed-off-by: Cédric Clerget <cedric.clerget@gmail.com>
This commit is contained in:
committed by
Jonathon Anderson
parent
f2869f4949
commit
0d041cbbbb
42
vagrant/.vagrantplugins
Normal file
42
vagrant/.vagrantplugins
Normal file
@@ -0,0 +1,42 @@
|
||||
class InitWarewulf < Vagrant.plugin(2, :command)
|
||||
def self.synopsis
|
||||
"Initialize Warewulf Dev Environment"
|
||||
end
|
||||
|
||||
def execute
|
||||
ww_version = `git describe --abbrev=0 2>/dev/null`
|
||||
ww_version = ww_version[1..-1]
|
||||
system "WW_VERSION=#{ww_version} vagrant up"
|
||||
system "vagrant provision --provision-with provision-vbmc wwctl"
|
||||
system "vagrant provision --provision-with add-ww-nodes wwctl"
|
||||
end
|
||||
end
|
||||
|
||||
class CleanupWarewulf < Vagrant.plugin(2, :command)
|
||||
def self.synopsis
|
||||
"Cleanup Warewulf Dev Environment"
|
||||
end
|
||||
|
||||
def execute
|
||||
system "vagrant ssh wwctl -c 'sudo wwctl power off n1' || true"
|
||||
system "vagrant ssh wwctl -c 'sudo wwctl power off n2' || true"
|
||||
system "vagrant halt"
|
||||
system "vagrant destroy -f"
|
||||
end
|
||||
end
|
||||
|
||||
class InitWarewulfPlugin < Vagrant.plugin(2)
|
||||
name "InitWarewulf"
|
||||
|
||||
command "init-warewulf" do
|
||||
InitWarewulf
|
||||
end
|
||||
end
|
||||
|
||||
class CleanupWarewulfPlugin < Vagrant.plugin(2)
|
||||
name "CleanupWarewulf"
|
||||
|
||||
command "cleanup-warewulf" do
|
||||
CleanupWarewulf
|
||||
end
|
||||
end
|
||||
55
vagrant/README.md
Normal file
55
vagrant/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
## Dev environment
|
||||
|
||||
For dev and testing purpose, a vagrant environment is provided.
|
||||
|
||||
For now, the only vagrant provider supported is libvirt and only usable on Linux machines.
|
||||
|
||||
### Initialize environment
|
||||
|
||||
To setup the initial environment:
|
||||
|
||||
```shell
|
||||
vagrant init-warewulf
|
||||
```
|
||||
|
||||
This command creates three VM nodes:
|
||||
* wwctl
|
||||
* wwnode1
|
||||
* wwnode2
|
||||
|
||||
On `wwctl` node, the latest stable warewulf release available will be installed and
|
||||
automatically adds `wwnode1`/`wwnode2` respectively as `n1` and `n2` in warewulf.
|
||||
|
||||
Once initialized, you can use `vagrant up` and `vagrant halt` to start/stop VM's as usual.
|
||||
|
||||
### Cleanup environment
|
||||
|
||||
To cleanup the environment:
|
||||
|
||||
```shell
|
||||
vagrant cleanup-warewulf
|
||||
```
|
||||
|
||||
This command stops VM nodes and deletes them
|
||||
|
||||
### Power control
|
||||
|
||||
`wwnode1` and `wwnode2` can be started/stopped from `wwctl` node via commands:
|
||||
|
||||
```shell
|
||||
wwctl power on n1
|
||||
wwctl power on n2
|
||||
```
|
||||
|
||||
```shell
|
||||
wwctl power off n1
|
||||
wwctl power off n2
|
||||
```
|
||||
|
||||
### Alpine boot test
|
||||
|
||||
For a quick test/demo, an alpine boot script is provided, you can run it with:
|
||||
|
||||
```shell
|
||||
vagrant ssh wwctl -c "sudo ./alpine-boot.sh"
|
||||
```
|
||||
55
vagrant/Vagrantfile
vendored
Normal file
55
vagrant/Vagrantfile
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
ENV['VAGRANT_NO_PARALLEL'] = 'yes'
|
||||
ww_version = ENV.fetch('WW_VERSION', "4.6.3")
|
||||
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.define :wwctl do |wwctl|
|
||||
wwctl.vm.box = "rockylinux/9"
|
||||
wwctl.vm.box_version = "6.0.0"
|
||||
wwctl.vm.network :private_network, :ip => "10.100.100.254", :libvirt__dhcp_enabled => false, :libvirt__network_name => 'netboot'
|
||||
wwctl.vm.synced_folder '.', '/vagrant', disabled: true
|
||||
|
||||
wwctl.trigger.after :up, :reload do |trigger|
|
||||
trigger.run = {path: "export-libvirt-sock.sh"}
|
||||
end
|
||||
|
||||
wwctl.vm.provider :libvirt do |domain|
|
||||
domain.memory = 1024
|
||||
domain.cpus = 2
|
||||
domain.machine_virtual_size = 12
|
||||
end
|
||||
|
||||
wwctl.vm.provision "init-wwctl", type: "shell", path: "init-scripts/init-wwctl.sh", args: [ww_version]
|
||||
wwctl.vm.provision "file", source: "alpine-bootable.def", destination: "alpine-bootable.def"
|
||||
wwctl.vm.provision "file", source: "alpine-boot.sh", destination: "alpine-boot.sh"
|
||||
wwctl.vm.provision "provision-vbmc", type: "shell", run: "never", path: "init-scripts/start-vbmcd.sh"
|
||||
wwctl.vm.provision "add-ww-nodes", type: "shell", run: "never", path: "init-scripts/add-ww-nodes.sh"
|
||||
end
|
||||
|
||||
config.vm.define :wwnode1 do |node1|
|
||||
node1.vm.network :private_network, :libvirt__network_name => 'netboot', :libvirt__mac => '006e6f646531'
|
||||
node1.vm.synced_folder '.', '/vagrant', disabled: true
|
||||
node1.vm.provider :libvirt do |domain|
|
||||
domain.memory = 768
|
||||
domain.cpus = 1
|
||||
domain.mgmt_attach = false
|
||||
boot_network = {'network' => 'netboot'}
|
||||
domain.boot boot_network
|
||||
end
|
||||
end
|
||||
|
||||
config.vm.define :wwnode2 do |node2|
|
||||
node2.vm.network :private_network, :libvirt__network_name => 'netboot', :libvirt__mac => '006e6f646532'
|
||||
node2.vm.synced_folder '.', '/vagrant', disabled: true
|
||||
node2.vm.provider :libvirt do |domain|
|
||||
domain.memory = 768
|
||||
domain.cpus = 1
|
||||
domain.mgmt_attach = false
|
||||
boot_network = {'network' => 'netboot'}
|
||||
domain.boot boot_network
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
47
vagrant/alpine-boot.sh
Executable file
47
vagrant/alpine-boot.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -d /tmp/alpine-rootfs ]; then
|
||||
rm -rf /tmp/alpine-rootfs
|
||||
fi
|
||||
|
||||
apptainer build -s /tmp/alpine-rootfs alpine-bootable.def
|
||||
|
||||
wwctl image import --force /tmp/alpine-rootfs alpine
|
||||
wwctl image build alpine
|
||||
|
||||
wwctl power off n1
|
||||
wwctl power off n2
|
||||
|
||||
if ! wwctl overlay list | grep "alpine-net" >/dev/null; then
|
||||
wwctl overlay create alpine-net
|
||||
wwctl overlay mkdir alpine-net /etc/network
|
||||
mkdir -p etc/network
|
||||
cat > etc/network/interfaces.ww <<EOF
|
||||
{{- range \$devname, \$netdev := .ThisNode.NetDevs }}
|
||||
# This file is autogenerated by warewulf
|
||||
{{- if \$netdev.OnBoot.BoolDefaultTrue }}
|
||||
auto {{ \$netdev.Device }}
|
||||
{{- end }}
|
||||
iface {{ \$netdev.Device }} inet static
|
||||
address {{ \$netdev.Ipaddr }}
|
||||
netmask {{ \$netdev.Netmask }}
|
||||
{{ if \$netdev.Gateway }}gateway {{ \$netdev.Gateway }}{{ end }}
|
||||
{{ if \$netdev.MTU }}mtu {{ \$netdev.MTU }}{{ end }}
|
||||
{{ end -}}
|
||||
EOF
|
||||
wwctl overlay import alpine-net etc/network/interfaces.ww
|
||||
fi
|
||||
|
||||
if ! wwctl profile list -j | jq -e 'to_entries[] | select(.key=="alpine")' >/dev/null; then
|
||||
wwctl profile add --profile=default alpine
|
||||
wwctl profile set -y alpine --system-overlays=$(wwctl profile list -j | jq -r 'to_entries[] | select(.key=="default") | .value."system overlay" | join(",")' | sed 's/debian.interfaces/alpine-net/')
|
||||
fi
|
||||
|
||||
wwctl node set -y --image=alpine --profile=alpine n1
|
||||
wwctl node set -y --image=alpine --profile=alpine n2
|
||||
wwctl overlay build n1
|
||||
wwctl overlay build n2
|
||||
|
||||
wwctl power on n1
|
||||
wwctl power on n2
|
||||
|
||||
15
vagrant/alpine-bootable.def
Normal file
15
vagrant/alpine-bootable.def
Normal file
@@ -0,0 +1,15 @@
|
||||
Bootstrap: docker
|
||||
From: alpine:3.22
|
||||
|
||||
%post
|
||||
apk add linux-lts linux-firmware-none openrc mdevd-openrc alpine-conf
|
||||
setup-devd udev || true
|
||||
passwd -d root
|
||||
rc-update add networking boot
|
||||
rc-update add modules
|
||||
setup-sshd openssh
|
||||
ln -s /bin/sh /usr/bin/sh
|
||||
cat > /etc/ssh/sshd_config.d/empty-password.conf <<EOF
|
||||
PermitRootLogin yes
|
||||
PermitEmptyPasswords yes
|
||||
EOF
|
||||
14
vagrant/export-libvirt-sock.sh
Executable file
14
vagrant/export-libvirt-sock.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
pidfile=".export-libvirt-sock.pid"
|
||||
|
||||
pid=$(cat $pidfile 2>/dev/null || true)
|
||||
|
||||
if [ "$pid" != "" ]; then
|
||||
if grep "/var/tmp/libvirt.sock:" /proc/$pid/cmdline >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
nohup vagrant ssh wwctl -- -o ServerAliveInterval=5 -o ServerAliveCountMax=1 -f -R /var/tmp/libvirt.sock:/var/run/libvirt/libvirt-sock -N >/dev/null 2>&1 &
|
||||
echo $! > .export-libvirt-sock.pid
|
||||
4
vagrant/init-scripts/add-ww-nodes.sh
Executable file
4
vagrant/init-scripts/add-ww-nodes.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
wwctl node add -G 10.100.100.1 -H 00:6e:6f:64:65:31 --ipaddr 10.100.100.10 --ipmiaddr 10.100.100.254 --ipmipass password --ipmiport 6231 --ipmiuser admin --ipmiinterface lanplus --netdev eth0 --netmask 255.255.255.0 --nettagadd="DNS1=10.100.100.1" n1
|
||||
wwctl node add -G 10.100.100.1 -H 00:6e:6f:64:65:32 --ipaddr 10.100.100.11 --ipmiaddr 10.100.100.254 --ipmipass password --ipmiport 6232 --ipmiuser admin --ipmiinterface lanplus --netdev eth0 --netmask 255.255.255.0 --nettagadd="DNS1=10.100.100.1" n2
|
||||
125
vagrant/init-scripts/init-wwctl.sh
Executable file
125
vagrant/init-scripts/init-wwctl.sh
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo ", +" | sfdisk --no-reread -N 5 /dev/vda
|
||||
partprobe
|
||||
xfs_growfs /dev/vda5
|
||||
|
||||
echo "StreamLocalBindUnlink yes" > /etc/ssh/sshd_config.d/60-forward-cleanup.conf
|
||||
systemctl reload sshd.service
|
||||
|
||||
dnf install -y libvirt-client python3-pip python3-libvirt ipmitool epel-release
|
||||
pip3 install virtualbmc
|
||||
dnf install -y apptainer
|
||||
|
||||
ww_version=$1
|
||||
|
||||
cat > /usr/local/bin/setup-wwnode <<EOF
|
||||
#!/bin/sh
|
||||
|
||||
node=\$1
|
||||
port=\$2
|
||||
|
||||
if [ ! -e /root/.vbmc/\$node ]; then
|
||||
/usr/local/bin/vbmc add --username admin --password password --port \$port --address 10.100.100.254 --libvirt-uri qemu:///system?socket=/var/tmp/libvirt.sock \$node
|
||||
fi
|
||||
|
||||
/usr/local/bin/vbmc start \$node
|
||||
EOF
|
||||
|
||||
chmod 755 /usr/local/bin/setup-wwnode
|
||||
|
||||
dnf install -y https://github.com/warewulf/warewulf/releases/download/v${ww_version}/warewulf-${ww_version}-1.el9.$(arch).rpm
|
||||
|
||||
cat > /etc/warewulf/warewulf.conf <<EOF
|
||||
ipaddr: 10.100.100.254
|
||||
netmask: 255.255.255.0
|
||||
network: 10.100.100.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: false
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: true
|
||||
grubboot: false
|
||||
api:
|
||||
enabled: false
|
||||
allowed subnets:
|
||||
- 127.0.0.0/8
|
||||
- ::1/128
|
||||
dhcp:
|
||||
enabled: true
|
||||
template: default
|
||||
range start: 10.100.100.2
|
||||
range end: 10.100.100.9
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: /var/lib/tftpboot
|
||||
systemd name: tftp
|
||||
ipxe:
|
||||
00:0B: arm64-efi/snponly.efi
|
||||
"00:00": undionly.kpxe
|
||||
"00:07": ipxe-snponly-x86_64.efi
|
||||
"00:09": ipxe-snponly-x86_64.efi
|
||||
nfs:
|
||||
enabled: true
|
||||
export paths:
|
||||
- path: /home
|
||||
export options: rw,sync
|
||||
- path: /opt
|
||||
export options: ro,sync,no_root_squash
|
||||
systemd name: nfs-server
|
||||
ssh:
|
||||
key types:
|
||||
- ed25519
|
||||
- ecdsa
|
||||
- rsa
|
||||
- dsa
|
||||
image mounts:
|
||||
- source: /etc/resolv.conf
|
||||
dest: /etc/resolv.conf
|
||||
readonly: true
|
||||
paths:
|
||||
bindir: /usr/bin
|
||||
sysconfdir: /etc
|
||||
localstatedir: /var/lib
|
||||
cachedir: /var/cache
|
||||
ipxesource: /usr/share/ipxe
|
||||
srvdir: /var/lib
|
||||
firewallddir: /usr/lib/firewalld/services
|
||||
systemddir: /usr/lib/systemd/system
|
||||
datadir: /usr/share
|
||||
wwoverlaydir: /var/lib/warewulf/overlays
|
||||
wwchrootdir: /var/lib/warewulf/chroots
|
||||
wwprovisiondir: /var/lib/warewulf/provision
|
||||
wwclientdir: /warewulf
|
||||
EOF
|
||||
|
||||
systemctl enable --now warewulfd
|
||||
wwctl configure --all
|
||||
systemctl restart warewulfd
|
||||
|
||||
cat > /etc/systemd/system/vbmcd.service <<EOF
|
||||
[Install]
|
||||
WantedBy = multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecReload = /bin/kill -HUP $MAINPID
|
||||
ExecStart = /usr/local/bin/vbmcd --foreground
|
||||
Group = root
|
||||
Restart = on-failure
|
||||
RestartSec = 2
|
||||
TimeoutSec = 120
|
||||
Type = simple
|
||||
User = root
|
||||
ExecStartPost = /usr/local/bin/setup-wwnode vagrant_wwnode1 6231
|
||||
ExecStartPost = /usr/local/bin/setup-wwnode vagrant_wwnode2 6232
|
||||
|
||||
[Unit]
|
||||
After = syslog.target
|
||||
After = network.target
|
||||
Description = vbmc service
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
3
vagrant/init-scripts/start-vbmcd.sh
Executable file
3
vagrant/init-scripts/start-vbmcd.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
systemctl enable --now vbmcd.service
|
||||
Reference in New Issue
Block a user