feat!: declare the guest agent per guest OS, and share what provisioning needs
CI / test (3.10) (push) Successful in 39s
CI / test (3.11) (push) Successful in 36s
CI / test (3.12) (push) Successful in 39s
CI / test (3.10) (pull_request) Successful in 32s
CI / test (3.11) (pull_request) Successful in 23s
CI / test (3.12) (pull_request) Successful in 24s
CI / test (3.10) (push) Successful in 39s
CI / test (3.11) (push) Successful in 36s
CI / test (3.12) (push) Successful in 39s
CI / test (3.10) (pull_request) Successful in 32s
CI / test (3.11) (pull_request) Successful in 23s
CI / test (3.12) (pull_request) Successful in 24s
GUEST_AGENT_PACKAGES / GUEST_AGENT_RUNCMD described one agent per hypervisor. A hypervisor that provisions FreeBSD and OpenBSD guests needs a different agent per guest, and netOrk has to know which guests a driver can provision at all (NetOrk/netork#794). Both now come from one class-level mapping netOrk reads off the driver class: GUEST_AGENTS = {guest_os: (packages, runcmd)} Its keys are the guests the driver provisions, and create_vm_from_cloud_init(guest_os=...) refuses any other. The base keeps Linux with qemu-guest-agent. New module `provisioning`, generic for every hypervisor: - QEMU_GUEST_AGENTS: the QEMU agent for Linux, FreeBSD and OpenBSD, with package names and service commands verified on FreeBSD 15.1 and OpenBSD 7.9 cloud images (NetOrk/netork#793). - network_config(): cloud-init's network-config v2 with MAC matching, moved here from napalm-vmware. FreeBSD's nuageinit reads no other version. - split_compression(): how a packed image (.xz, .gz, .bz2, .zst) is unpacked. BREAKING CHANGE: GUEST_AGENT_PACKAGES and GUEST_AGENT_RUNCMD are gone; drivers declare GUEST_AGENTS instead.
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
"""What provisioning a VM from a cloud image needs to know about the guest,
|
||||
the same for every hypervisor (NetOrk/netork#794)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from napalm_device_types import HypervisorDriver
|
||||
from napalm_device_types.provisioning import (
|
||||
QEMU_GUEST_AGENTS,
|
||||
network_config,
|
||||
split_compression,
|
||||
)
|
||||
|
||||
|
||||
class TestGuestAgentDeclaration:
|
||||
"""netOrk's cloud-init installs the agent through which the hypervisor
|
||||
reads the new VM's IP. Which agent depends on the hypervisor and on the
|
||||
guest; the guests a driver lists are the ones it can provision."""
|
||||
|
||||
def test_the_base_provisions_linux_with_qemu_guest_agent(self):
|
||||
assert HypervisorDriver.GUEST_AGENTS == {
|
||||
"linux": (("qemu-guest-agent",), ("systemctl enable --now qemu-guest-agent",)),
|
||||
}
|
||||
|
||||
def test_the_declaration_is_data_netork_reads_off_the_class(self):
|
||||
assert not callable(vars(HypervisorDriver)["GUEST_AGENTS"])
|
||||
|
||||
def test_the_per_hypervisor_attributes_are_gone(self):
|
||||
assert not hasattr(HypervisorDriver, "GUEST_AGENT_PACKAGES")
|
||||
assert not hasattr(HypervisorDriver, "GUEST_AGENT_RUNCMD")
|
||||
|
||||
|
||||
class TestQemuGuestAgents:
|
||||
"""Verified on FreeBSD 15.1 and OpenBSD 7.9 cloud images (#793)."""
|
||||
|
||||
def test_linux_is_the_base_default(self):
|
||||
assert QEMU_GUEST_AGENTS["linux"] == HypervisorDriver.GUEST_AGENTS["linux"]
|
||||
|
||||
def test_freebsd(self):
|
||||
assert QEMU_GUEST_AGENTS["freebsd"] == (
|
||||
("qemu-guest-agent",),
|
||||
("sysrc qemu_guest_agent_enable=YES", "service qemu-guest-agent start"),
|
||||
)
|
||||
|
||||
def test_openbsd(self):
|
||||
assert QEMU_GUEST_AGENTS["openbsd"] == (
|
||||
("qemu-ga",),
|
||||
("rcctl enable qemu_ga", "rcctl start qemu_ga"),
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("guest_os", ["freebsd", "openbsd"])
|
||||
def test_no_bsd_guest_is_told_to_use_systemd(self, guest_os):
|
||||
_, runcmd = QEMU_GUEST_AGENTS[guest_os]
|
||||
assert not any("systemctl" in command for command in runcmd)
|
||||
|
||||
|
||||
class TestNetworkConfig:
|
||||
"""cloud-init's network-config v2. FreeBSD's nuageinit reads only this
|
||||
version; the v1 Proxmox generates makes it skip runcmd (#793)."""
|
||||
|
||||
def test_dhcp_nics_matched_by_mac(self):
|
||||
cfg = network_config([("00:50:56:aa:bb:cc", True), ("00:50:56:aa:bb:dd", False)])
|
||||
assert cfg == {
|
||||
"version": 2,
|
||||
"ethernets": {
|
||||
"nic0": {"match": {"macaddress": "00:50:56:aa:bb:cc"}, "dhcp4": True},
|
||||
},
|
||||
}
|
||||
|
||||
def test_no_dhcp_nic_means_no_network_config(self):
|
||||
assert network_config([("00:50:56:aa:bb:cc", False)]) is None
|
||||
|
||||
def test_macs_are_written_in_lower_case(self):
|
||||
"""Proxmox reports them upper-case; nuageinit compares them as given."""
|
||||
cfg = network_config([("BC:24:11:AA:BB:02", True)])
|
||||
assert cfg["ethernets"]["nic0"]["match"]["macaddress"] == "bc:24:11:aa:bb:02"
|
||||
|
||||
|
||||
class TestSplitCompression:
|
||||
"""Official FreeBSD images come packed; hypervisors import unpacked ones."""
|
||||
|
||||
def test_xz(self):
|
||||
assert split_compression("FreeBSD-15.1-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2.xz") == (
|
||||
"FreeBSD-15.1-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2",
|
||||
"xz -dc",
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("name", "command"),
|
||||
[("a.raw.gz", "gzip -dc"), ("a.raw.bz2", "bzip2 -dc"), ("a.qcow2.zst", "zstd -dc")],
|
||||
)
|
||||
def test_other_packers(self, name, command):
|
||||
assert split_compression(name) == (name.rsplit(".", 1)[0], command)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"name", ["debian-13-genericcloud-amd64.qcow2", "ubuntu-24.04-server-cloudimg-amd64.img"]
|
||||
)
|
||||
def test_an_unpacked_image_is_left_as_it_is(self, name):
|
||||
assert split_compression(name) == (name, None)
|
||||
|
||||
def test_the_suffix_is_matched_case_insensitively(self):
|
||||
assert split_compression("IMAGE.QCOW2.XZ") == ("IMAGE.QCOW2", "xz -dc")
|
||||
Reference in New Issue
Block a user