d0e1a8d380
OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=190
1603 lines
62 KiB
Diff
1603 lines
62 KiB
Diff
From 340570af70f48b2e97a2e0b863fd819f85e92cb7 Mon Sep 17 00:00:00 2001
|
|
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
|
Date: Mon, 8 Feb 2021 16:42:47 +0100
|
|
Subject: [PATCH] virt enhancements
|
|
|
|
3002.2 Xen spicevmc, DNS SRV records backports (#314)
|
|
|
|
* Fix virtual network generated DNS XML for SRV records
|
|
|
|
libvirt network's srv element doesn't take a `name` property but a
|
|
`service` one.
|
|
|
|
* Add missing property in virt.network_define dns srv doc
|
|
|
|
* virt: convert spice generation tests to pytests
|
|
|
|
* virt: don't add spicevmc channel to Xen VMs
|
|
|
|
Xen fully virtualized VMs with spicevmc channel fail to start, so better
|
|
not write it out in such cases.
|
|
|
|
* virt: inverse the remaining asserts in pytests
|
|
|
|
virt.network_update: handle missing ipv4 netmask attribute (#328)
|
|
|
|
In the libvirt definition, the IPv4 netmask XML attribute may be
|
|
replaced by the prefix one. Handle this situation gracefully rather than
|
|
miserably failing.
|
|
|
|
Handle volumes on stopped pools in virt.vm_info (#373)
|
|
|
|
For VMs having at least a disk on a stopped volume, we don't want the
|
|
user to get an exception when running virt.vm_info. Instead just provide
|
|
less information.
|
|
|
|
virt: use /dev/kvm to detect KVM (#383)
|
|
|
|
checking for kvm_* modules to be loaded is not robust enough since the
|
|
kernel could be compiled with builtin modules. /dev/kvm is much more
|
|
reliable.
|
|
|
|
virt: pass emulator when getting domain capabilities from libvirt (#394)
|
|
|
|
On aarch64, for some emulated architectures like armv6l libvirt needs to
|
|
have the emulator path to properly return the domain capabilities.
|
|
|
|
Passing it will avoid virt.all_capabilities to fail on such
|
|
architectures.
|
|
---
|
|
changelog/59416.fixed | 1 +
|
|
changelog/59692.fixed | 1 +
|
|
changelog/60132.fixed | 1 +
|
|
changelog/60419.fixed | 1 +
|
|
changelog/60491.fixed | 1 +
|
|
salt/modules/virt.py | 92 +++++----
|
|
salt/templates/virt/libvirt_domain.jinja | 2 +-
|
|
.../pytests/unit/modules/virt/test_domain.py | 185 +++++++++++++-----
|
|
.../pytests/unit/modules/virt/test_helpers.py | 6 +-
|
|
tests/pytests/unit/modules/virt/test_host.py | 23 ++-
|
|
.../pytests/unit/modules/virt/test_network.py | 70 ++++---
|
|
tests/pytests/unit/states/virt/test_domain.py | 144 +++++++-------
|
|
.../pytests/unit/states/virt/test_network.py | 88 ++++-----
|
|
tests/unit/modules/test_virt.py | 63 +-----
|
|
14 files changed, 371 insertions(+), 307 deletions(-)
|
|
create mode 100644 changelog/59416.fixed
|
|
create mode 100644 changelog/59692.fixed
|
|
create mode 100644 changelog/60132.fixed
|
|
create mode 100644 changelog/60419.fixed
|
|
create mode 100644 changelog/60491.fixed
|
|
|
|
diff --git a/changelog/59416.fixed b/changelog/59416.fixed
|
|
new file mode 100644
|
|
index 0000000000..820124e99a
|
|
--- /dev/null
|
|
+++ b/changelog/59416.fixed
|
|
@@ -0,0 +1 @@
|
|
+Don't create spicevmc channel for Xen virtual machines
|
|
diff --git a/changelog/59692.fixed b/changelog/59692.fixed
|
|
new file mode 100644
|
|
index 0000000000..b4f4533ccc
|
|
--- /dev/null
|
|
+++ b/changelog/59692.fixed
|
|
@@ -0,0 +1 @@
|
|
+Don't fail updating network without netmask ip attribute
|
|
diff --git a/changelog/60132.fixed b/changelog/60132.fixed
|
|
new file mode 100644
|
|
index 0000000000..1e3bc96b98
|
|
--- /dev/null
|
|
+++ b/changelog/60132.fixed
|
|
@@ -0,0 +1 @@
|
|
+Gracefuly handle errors in virt.vm_info
|
|
diff --git a/changelog/60419.fixed b/changelog/60419.fixed
|
|
new file mode 100644
|
|
index 0000000000..44c782da48
|
|
--- /dev/null
|
|
+++ b/changelog/60419.fixed
|
|
@@ -0,0 +1 @@
|
|
+Check for /dev/kvm to detect KVM hypervisor.
|
|
diff --git a/changelog/60491.fixed b/changelog/60491.fixed
|
|
new file mode 100644
|
|
index 0000000000..256d29b5fb
|
|
--- /dev/null
|
|
+++ b/changelog/60491.fixed
|
|
@@ -0,0 +1 @@
|
|
+Pass emulator path to get guest capabilities from libvirt
|
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
|
index 17e3ba7b9b..8c0d743ba1 100644
|
|
--- a/salt/modules/virt.py
|
|
+++ b/salt/modules/virt.py
|
|
@@ -516,41 +516,50 @@ def _get_disks(conn, dom):
|
|
def _get_disk_volume_data(pool_name, volume_name):
|
|
qemu_target = "{}/{}".format(pool_name, volume_name)
|
|
pool = conn.storagePoolLookupByName(pool_name)
|
|
- vol = pool.storageVolLookupByName(volume_name)
|
|
- vol_info = vol.info()
|
|
- extra_properties = {
|
|
- "virtual size": vol_info[1],
|
|
- "disk size": vol_info[2],
|
|
- }
|
|
-
|
|
- backing_files = [
|
|
- {
|
|
- "file": node.find("source").get("file"),
|
|
- "file format": node.find("format").get("type"),
|
|
+ extra_properties = {}
|
|
+ try:
|
|
+ vol = pool.storageVolLookupByName(volume_name)
|
|
+ vol_info = vol.info()
|
|
+ extra_properties = {
|
|
+ "virtual size": vol_info[1],
|
|
+ "disk size": vol_info[2],
|
|
}
|
|
- for node in elem.findall(".//backingStore[source]")
|
|
- ]
|
|
|
|
- if backing_files:
|
|
- # We had the backing files in a flat list, nest them again.
|
|
- extra_properties["backing file"] = backing_files[0]
|
|
- parent = extra_properties["backing file"]
|
|
- for sub_backing_file in backing_files[1:]:
|
|
- parent["backing file"] = sub_backing_file
|
|
- parent = sub_backing_file
|
|
+ backing_files = [
|
|
+ {
|
|
+ "file": node.find("source").get("file"),
|
|
+ "file format": node.find("format").get("type"),
|
|
+ }
|
|
+ for node in elem.findall(".//backingStore[source]")
|
|
+ ]
|
|
|
|
- else:
|
|
- # In some cases the backing chain is not displayed by the domain definition
|
|
- # Try to see if we have some of it in the volume definition.
|
|
- vol_desc = ElementTree.fromstring(vol.XMLDesc())
|
|
- backing_path = vol_desc.find("./backingStore/path")
|
|
- backing_format = vol_desc.find("./backingStore/format")
|
|
- if backing_path is not None:
|
|
- extra_properties["backing file"] = {"file": backing_path.text}
|
|
- if backing_format is not None:
|
|
- extra_properties["backing file"][
|
|
- "file format"
|
|
- ] = backing_format.get("type")
|
|
+ if backing_files:
|
|
+ # We had the backing files in a flat list, nest them again.
|
|
+ extra_properties["backing file"] = backing_files[0]
|
|
+ parent = extra_properties["backing file"]
|
|
+ for sub_backing_file in backing_files[1:]:
|
|
+ parent["backing file"] = sub_backing_file
|
|
+ parent = sub_backing_file
|
|
+
|
|
+ else:
|
|
+ # In some cases the backing chain is not displayed by the domain definition
|
|
+ # Try to see if we have some of it in the volume definition.
|
|
+ vol_desc = ElementTree.fromstring(vol.XMLDesc())
|
|
+ backing_path = vol_desc.find("./backingStore/path")
|
|
+ backing_format = vol_desc.find("./backingStore/format")
|
|
+ if backing_path is not None:
|
|
+ extra_properties["backing file"] = {
|
|
+ "file": backing_path.text
|
|
+ }
|
|
+ if backing_format is not None:
|
|
+ extra_properties["backing file"][
|
|
+ "file format"
|
|
+ ] = backing_format.get("type")
|
|
+ except libvirt.libvirtError:
|
|
+ # The volume won't be found if the pool is not started, just output less infos
|
|
+ log.info(
|
|
+ "Couldn't extract all volume informations: pool is likely not running or refreshed"
|
|
+ )
|
|
return (qemu_target, extra_properties)
|
|
|
|
if disk_type == "file":
|
|
@@ -5908,12 +5917,7 @@ def _is_kvm_hyper():
|
|
"""
|
|
Returns a bool whether or not this node is a KVM hypervisor
|
|
"""
|
|
- try:
|
|
- with salt.utils.files.fopen("/proc/modules") as fp_:
|
|
- if "kvm_" not in salt.utils.stringutils.to_unicode(fp_.read()):
|
|
- return False
|
|
- except OSError:
|
|
- # No /proc/modules? Are we on Windows? Or Solaris?
|
|
+ if not os.path.exists("/dev/kvm"):
|
|
return False
|
|
return "libvirtd" in __salt__["cmd.run"](__grains__["ps"])
|
|
|
|
@@ -6936,7 +6940,11 @@ def all_capabilities(**kwargs):
|
|
host_caps = ElementTree.fromstring(conn.getCapabilities())
|
|
domains = [
|
|
[
|
|
- (guest.get("arch", {}).get("name", None), key)
|
|
+ (
|
|
+ guest.get("arch", {}).get("name", None),
|
|
+ key,
|
|
+ guest.get("arch", {}).get("emulator", None),
|
|
+ )
|
|
for key in guest.get("arch", {}).get("domains", {}).keys()
|
|
]
|
|
for guest in [
|
|
@@ -6954,10 +6962,10 @@ def all_capabilities(**kwargs):
|
|
"domains": [
|
|
_parse_domain_caps(
|
|
ElementTree.fromstring(
|
|
- conn.getDomainCapabilities(None, arch, None, domain)
|
|
+ conn.getDomainCapabilities(emulator, arch, None, domain)
|
|
)
|
|
)
|
|
- for (arch, domain) in flattened
|
|
+ for (arch, domain, emulator) in flattened
|
|
],
|
|
}
|
|
return result
|
|
@@ -7584,7 +7592,7 @@ def network_update(
|
|
if node.get("family", "ipv4") == "ipv4"
|
|
]
|
|
for ip_node in ipv4_nodes:
|
|
- netmask = ip_node.attrib.pop("netmask")
|
|
+ netmask = ip_node.attrib.pop("netmask", None)
|
|
if netmask:
|
|
address = ipaddress.ip_network(
|
|
"{}/{}".format(ip_node.get("address"), netmask), strict=False
|
|
diff --git a/salt/templates/virt/libvirt_domain.jinja b/salt/templates/virt/libvirt_domain.jinja
|
|
index 4603dfd8de..6772b0db56 100644
|
|
--- a/salt/templates/virt/libvirt_domain.jinja
|
|
+++ b/salt/templates/virt/libvirt_domain.jinja
|
|
@@ -285,7 +285,7 @@
|
|
autoport='{{ yesno(not graphics.port and not graphics.tls_port) }}'>
|
|
<listen type='{{ graphics.listen.type }}'{{ opt_attribute(graphics.listen, "address") }}/>
|
|
</graphics>
|
|
- {%- if graphics.type == "spice" %}
|
|
+ {%- if graphics.type == "spice" and hypervisor in ["qemu", "kvm"] %}
|
|
<channel type='spicevmc'>
|
|
<target type='virtio' name='com.redhat.spice.0'/>
|
|
</channel>
|
|
diff --git a/tests/pytests/unit/modules/virt/test_domain.py b/tests/pytests/unit/modules/virt/test_domain.py
|
|
index 3301b94d6d..9a1b2814f8 100644
|
|
--- a/tests/pytests/unit/modules/virt/test_domain.py
|
|
+++ b/tests/pytests/unit/modules/virt/test_domain.py
|
|
@@ -140,13 +140,14 @@ def test_update_xen_disk_volumes(make_mock_vm, make_mock_storage_pool):
|
|
assert ret["definition"]
|
|
virt.libvirt.openAuth().defineXML = virt.libvirt.openAuth().defineXML
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "block" == setxml.find(".//disk[3]").get("type")
|
|
- assert "/path/to/vdb/vdb1" == setxml.find(".//disk[3]/source").get("dev")
|
|
+ assert setxml.find(".//disk[3]").get("type") == "block"
|
|
+ assert setxml.find(".//disk[3]/source").get("dev") == "/path/to/vdb/vdb1"
|
|
|
|
# Note that my_vm-file-data was not an existing volume before the update
|
|
- assert "file" == setxml.find(".//disk[4]").get("type")
|
|
- assert "/path/to/default/my_vm_file-data" == setxml.find(".//disk[4]/source").get(
|
|
- "file"
|
|
+ assert setxml.find(".//disk[4]").get("type") == "file"
|
|
+ assert (
|
|
+ setxml.find(".//disk[4]/source").get("file")
|
|
+ == "/path/to/default/my_vm_file-data"
|
|
)
|
|
|
|
|
|
@@ -191,6 +192,11 @@ def test_get_disks(make_mock_vm, make_mock_storage_pool):
|
|
<alias name='virtio-disk0'/>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
|
</disk>
|
|
+ <disk type='volume' device='disk'>
|
|
+ <driver name='qemu' type='qcow2' cache='none' io='native'/>
|
|
+ <source pool='stopped' volume='vm05_data'/>
|
|
+ <target dev='vdd' bus='virtio'/>
|
|
+ </disk>
|
|
<disk type='network' device='cdrom'>
|
|
<driver name='qemu' type='raw' cache='none' io='native'/>
|
|
<source protocol='http' name='/pub/iso/myimage.iso' query='foo=bar&baz=flurb' index='1'>
|
|
@@ -204,11 +210,12 @@ def test_get_disks(make_mock_vm, make_mock_storage_pool):
|
|
</devices>
|
|
</domain>
|
|
"""
|
|
- domain_mock = make_mock_vm(vm_def)
|
|
+ make_mock_vm(vm_def)
|
|
|
|
pool_mock = make_mock_storage_pool(
|
|
"default", "dir", ["srv01_system", "srv01_data", "vm05_system"]
|
|
)
|
|
+ make_mock_storage_pool("stopped", "dir", [])
|
|
|
|
# Append backing store to srv01_data volume XML description
|
|
srv1data_mock = pool_mock.storageVolLookupByName("srv01_data")
|
|
@@ -255,6 +262,7 @@ def test_get_disks(make_mock_vm, make_mock_storage_pool):
|
|
},
|
|
},
|
|
},
|
|
+ "vdd": {"type": "disk", "file": "stopped/vm05_data", "file format": "qcow2"},
|
|
"hda": {
|
|
"type": "cdrom",
|
|
"file format": "raw",
|
|
@@ -322,7 +330,7 @@ def test_get_disk_convert_volumes(make_mock_vm, make_mock_storage_pool):
|
|
subprocess_mock.Popen = popen_mock
|
|
|
|
with patch.dict(virt.__dict__, {"subprocess": subprocess_mock}):
|
|
- assert {
|
|
+ assert virt.get_disks("srv01") == {
|
|
"vda": {
|
|
"type": "disk",
|
|
"file": "default/srv01_system",
|
|
@@ -345,7 +353,7 @@ def test_get_disk_convert_volumes(make_mock_vm, make_mock_storage_pool):
|
|
"disk size": 340525056,
|
|
"virtual size": 214748364800,
|
|
},
|
|
- } == virt.get_disks("srv01")
|
|
+ }
|
|
|
|
|
|
def test_update_approx_mem(make_mock_vm):
|
|
@@ -388,7 +396,7 @@ def test_gen_hypervisor_features():
|
|
hypervisor_features={"kvm-hint-dedicated": True},
|
|
)
|
|
root = ET.fromstring(xml_data)
|
|
- assert "on" == root.find("features/kvm/hint-dedicated").attrib["state"]
|
|
+ assert root.find("features/kvm/hint-dedicated").attrib["state"] == "on"
|
|
|
|
|
|
def test_update_hypervisor_features(make_mock_vm):
|
|
@@ -423,7 +431,7 @@ def test_update_hypervisor_features(make_mock_vm):
|
|
ret = virt.update("my_vm", hypervisor_features={"kvm-hint-dedicated": False})
|
|
assert ret["definition"]
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "off" == setxml.find("features/kvm/hint-dedicated").get("state")
|
|
+ assert setxml.find("features/kvm/hint-dedicated").get("state") == "off"
|
|
|
|
# Add the features
|
|
xml_def = """
|
|
@@ -442,7 +450,7 @@ def test_update_hypervisor_features(make_mock_vm):
|
|
ret = virt.update("my_vm", hypervisor_features={"kvm-hint-dedicated": True})
|
|
assert ret["definition"]
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "on" == setxml.find("features/kvm/hint-dedicated").get("state")
|
|
+ assert setxml.find("features/kvm/hint-dedicated").get("state") == "on"
|
|
|
|
|
|
def test_gen_clock():
|
|
@@ -463,8 +471,8 @@ def test_gen_clock():
|
|
clock={"adjustment": 3600, "utc": False},
|
|
)
|
|
root = ET.fromstring(xml_data)
|
|
- assert "localtime" == root.find("clock").get("offset")
|
|
- assert "3600" == root.find("clock").get("adjustment")
|
|
+ assert root.find("clock").get("offset") == "localtime"
|
|
+ assert root.find("clock").get("adjustment") == "3600"
|
|
|
|
# Specific timezone
|
|
xml_data = virt._gen_xml(
|
|
@@ -480,8 +488,8 @@ def test_gen_clock():
|
|
clock={"timezone": "CEST"},
|
|
)
|
|
root = ET.fromstring(xml_data)
|
|
- assert "timezone" == root.find("clock").get("offset")
|
|
- assert "CEST" == root.find("clock").get("timezone")
|
|
+ assert root.find("clock").get("offset") == "timezone"
|
|
+ assert root.find("clock").get("timezone") == "CEST"
|
|
|
|
# UTC
|
|
xml_data = virt._gen_xml(
|
|
@@ -497,7 +505,7 @@ def test_gen_clock():
|
|
clock={"utc": True},
|
|
)
|
|
root = ET.fromstring(xml_data)
|
|
- assert "utc" == root.find("clock").get("offset")
|
|
+ assert root.find("clock").get("offset") == "utc"
|
|
|
|
# Timers
|
|
xml_data = virt._gen_xml(
|
|
@@ -524,14 +532,16 @@ def test_gen_clock():
|
|
},
|
|
)
|
|
root = ET.fromstring(xml_data)
|
|
- assert "utc" == root.find("clock").get("offset")
|
|
- assert "3504000000" == root.find("clock/timer[@name='tsc']").get("frequency")
|
|
- assert "native" == root.find("clock/timer[@name='tsc']").get("mode")
|
|
- assert "catchup" == root.find("clock/timer[@name='rtc']").get("tickpolicy")
|
|
- assert {"slew": "4636", "threshold": "123", "limit": "2342"} == root.find(
|
|
- "clock/timer[@name='rtc']/catchup"
|
|
- ).attrib
|
|
- assert "no" == root.find("clock/timer[@name='hpet']").get("present")
|
|
+ assert root.find("clock").get("offset") == "utc"
|
|
+ assert root.find("clock/timer[@name='tsc']").get("frequency") == "3504000000"
|
|
+ assert root.find("clock/timer[@name='tsc']").get("mode") == "native"
|
|
+ assert root.find("clock/timer[@name='rtc']").get("tickpolicy") == "catchup"
|
|
+ assert root.find("clock/timer[@name='rtc']/catchup").attrib == {
|
|
+ "slew": "4636",
|
|
+ "threshold": "123",
|
|
+ "limit": "2342",
|
|
+ }
|
|
+ assert root.find("clock/timer[@name='hpet']").get("present") == "no"
|
|
|
|
|
|
def test_update_clock(make_mock_vm):
|
|
@@ -590,21 +600,23 @@ def test_update_clock(make_mock_vm):
|
|
)
|
|
assert ret["definition"]
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "timezone" == setxml.find("clock").get("offset")
|
|
- assert "CEST" == setxml.find("clock").get("timezone")
|
|
- assert {"rtc", "hpet"} == {t.get("name") for t in setxml.findall("clock/timer")}
|
|
- assert "catchup" == setxml.find("clock/timer[@name='rtc']").get("tickpolicy")
|
|
- assert "wall" == setxml.find("clock/timer[@name='rtc']").get("track")
|
|
- assert {"slew": "4636", "threshold": "123", "limit": "2342"} == setxml.find(
|
|
- "clock/timer[@name='rtc']/catchup"
|
|
- ).attrib
|
|
- assert "yes" == setxml.find("clock/timer[@name='hpet']").get("present")
|
|
+ assert setxml.find("clock").get("offset") == "timezone"
|
|
+ assert setxml.find("clock").get("timezone") == "CEST"
|
|
+ assert {t.get("name") for t in setxml.findall("clock/timer")} == {"rtc", "hpet"}
|
|
+ assert setxml.find("clock/timer[@name='rtc']").get("tickpolicy") == "catchup"
|
|
+ assert setxml.find("clock/timer[@name='rtc']").get("track") == "wall"
|
|
+ assert setxml.find("clock/timer[@name='rtc']/catchup").attrib == {
|
|
+ "slew": "4636",
|
|
+ "threshold": "123",
|
|
+ "limit": "2342",
|
|
+ }
|
|
+ assert setxml.find("clock/timer[@name='hpet']").get("present") == "yes"
|
|
|
|
# Revert to UTC
|
|
ret = virt.update("my_vm", clock={"utc": True, "adjustment": None, "timers": None})
|
|
assert ret["definition"]
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert {"offset": "utc"} == setxml.find("clock").attrib
|
|
+ assert setxml.find("clock").attrib == {"offset": "utc"}
|
|
assert setxml.find("clock/timer") is None
|
|
|
|
|
|
@@ -630,7 +642,7 @@ def test_update_stop_on_reboot_reset(make_mock_vm):
|
|
assert ret["definition"]
|
|
virt.libvirt.openAuth().defineXML = virt.libvirt.openAuth().defineXML
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "restart" == setxml.find("./on_reboot").text
|
|
+ assert setxml.find("./on_reboot").text == "restart"
|
|
|
|
|
|
def test_update_stop_on_reboot(make_mock_vm):
|
|
@@ -654,7 +666,7 @@ def test_update_stop_on_reboot(make_mock_vm):
|
|
assert ret["definition"]
|
|
virt.libvirt.openAuth().defineXML = virt.libvirt.openAuth().defineXML
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "destroy" == setxml.find("./on_reboot").text
|
|
+ assert setxml.find("./on_reboot").text == "destroy"
|
|
|
|
|
|
def test_init_no_stop_on_reboot(make_capabilities):
|
|
@@ -667,7 +679,7 @@ def test_init_no_stop_on_reboot(make_capabilities):
|
|
virt.init("test_vm", 2, 2048, start=False)
|
|
virt.libvirt.openAuth().defineXML = virt.libvirt.openAuth().defineXML
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "restart" == setxml.find("./on_reboot").text
|
|
+ assert setxml.find("./on_reboot").text == "restart"
|
|
|
|
|
|
def test_init_stop_on_reboot(make_capabilities):
|
|
@@ -680,7 +692,7 @@ def test_init_stop_on_reboot(make_capabilities):
|
|
virt.init("test_vm", 2, 2048, stop_on_reboot=True, start=False)
|
|
virt.libvirt.openAuth().defineXML = virt.libvirt.openAuth().defineXML
|
|
setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0])
|
|
- assert "destroy" == setxml.find("./on_reboot").text
|
|
+ assert setxml.find("./on_reboot").text == "destroy"
|
|
|
|
|
|
def test_init_hostdev_usb(make_capabilities, make_mock_device):
|
|
@@ -722,8 +734,8 @@ def test_init_hostdev_usb(make_capabilities, make_mock_device):
|
|
</hostdev>
|
|
"""
|
|
)
|
|
- assert expected_xml == strip_xml(
|
|
- ET.tostring(setxml.find("./devices/hostdev"))
|
|
+ assert (
|
|
+ strip_xml(ET.tostring(setxml.find("./devices/hostdev"))) == expected_xml
|
|
)
|
|
|
|
|
|
@@ -764,8 +776,8 @@ def test_init_hostdev_pci(make_capabilities, make_mock_device):
|
|
</hostdev>
|
|
"""
|
|
)
|
|
- assert expected_xml == strip_xml(
|
|
- ET.tostring(setxml.find("./devices/hostdev"))
|
|
+ assert (
|
|
+ strip_xml(ET.tostring(setxml.find("./devices/hostdev"))) == expected_xml
|
|
)
|
|
|
|
|
|
@@ -938,11 +950,11 @@ def test_update_hostdev_changes(running, live, make_mock_device, make_mock_vm, t
|
|
ET.tostring(xmlutil.strip_spaces(node))
|
|
for node in set_xml.findall("./devices/hostdev")
|
|
]
|
|
- assert [usb_device_xml] == actual_hostdevs
|
|
+ assert actual_hostdevs == [usb_device_xml]
|
|
|
|
if not test and live:
|
|
attach_xml = strip_xml(domain_mock.attachDevice.call_args[0][0])
|
|
- assert usb_device_xml == attach_xml
|
|
+ assert attach_xml == usb_device_xml
|
|
|
|
pci_device_xml = strip_xml(
|
|
"""
|
|
@@ -955,7 +967,7 @@ def test_update_hostdev_changes(running, live, make_mock_device, make_mock_vm, t
|
|
"""
|
|
)
|
|
detach_xml = strip_xml(domain_mock.detachDevice.call_args[0][0])
|
|
- assert pci_device_xml == detach_xml
|
|
+ assert detach_xml == pci_device_xml
|
|
else:
|
|
domain_mock.attachDevice.assert_not_called()
|
|
domain_mock.detachDevice.assert_not_called()
|
|
@@ -1012,14 +1024,16 @@ def test_diff_nics():
|
|
"""
|
|
).findall("interface")
|
|
ret = virt._diff_interface_lists(old_nics, new_nics)
|
|
- assert ["52:54:00:39:02:b1"] == [
|
|
- nic.find("mac").get("address") for nic in ret["unchanged"]
|
|
+ assert [nic.find("mac").get("address") for nic in ret["unchanged"]] == [
|
|
+ "52:54:00:39:02:b1"
|
|
]
|
|
- assert ["52:54:00:39:02:b2", "52:54:00:39:02:b4"] == [
|
|
- nic.find("mac").get("address") for nic in ret["new"]
|
|
+ assert [nic.find("mac").get("address") for nic in ret["new"]] == [
|
|
+ "52:54:00:39:02:b2",
|
|
+ "52:54:00:39:02:b4",
|
|
]
|
|
- assert ["52:54:00:39:02:b2", "52:54:00:39:02:b3"] == [
|
|
- nic.find("mac").get("address") for nic in ret["deleted"]
|
|
+ assert [nic.find("mac").get("address") for nic in ret["deleted"]] == [
|
|
+ "52:54:00:39:02:b2",
|
|
+ "52:54:00:39:02:b3",
|
|
]
|
|
|
|
|
|
@@ -1066,8 +1080,9 @@ def test_diff_nics_live_nochange():
|
|
"""
|
|
)
|
|
ret = virt._diff_interface_lists(old_nics, new_nics)
|
|
- assert ["52:54:00:03:02:15", "52:54:00:ea:2e:89"] == [
|
|
- nic.find("mac").get("address") for nic in ret["unchanged"]
|
|
+ assert [nic.find("mac").get("address") for nic in ret["unchanged"]] == [
|
|
+ "52:54:00:03:02:15",
|
|
+ "52:54:00:ea:2e:89",
|
|
]
|
|
|
|
|
|
@@ -1350,7 +1365,7 @@ def test_update_bootdev_unchanged(make_mock_vm, boot_dev):
|
|
"""
|
|
)
|
|
ret = virt.update("my_vm", boot_dev=boot_dev)
|
|
- assert (boot_dev != "hd") == ret["definition"]
|
|
+ assert ret["definition"] == (boot_dev != "hd")
|
|
if boot_dev == "hd":
|
|
virt.libvirt.openAuth().defineXML.assert_not_called()
|
|
else:
|
|
@@ -2128,3 +2143,65 @@ def test_update_failure(make_mock_vm):
|
|
"disk": {"attached": [], "detached": [], "updated": []},
|
|
"interface": {"attached": [], "detached": []},
|
|
}
|
|
+
|
|
+@pytest.mark.parametrize("hypervisor", ["kvm", "xen"])
|
|
+def test_gen_xml_spice_default(hypervisor):
|
|
+ """
|
|
+ Test virt._gen_xml() with default spice graphics device
|
|
+ """
|
|
+ xml_data = virt._gen_xml(
|
|
+ virt.libvirt.openAuth.return_value,
|
|
+ "hello",
|
|
+ 1,
|
|
+ 512,
|
|
+ {},
|
|
+ {},
|
|
+ hypervisor,
|
|
+ "hvm",
|
|
+ "x86_64",
|
|
+ graphics={"type": "spice"},
|
|
+ )
|
|
+ root = ET.fromstring(xml_data)
|
|
+ assert root.find("devices/graphics").attrib["type"] == "spice"
|
|
+ assert root.find("devices/graphics").attrib["autoport"] == "yes"
|
|
+ assert root.find("devices/graphics").attrib["listen"] == "0.0.0.0"
|
|
+ assert root.find("devices/graphics/listen").attrib["type"] == "address"
|
|
+ assert root.find("devices/graphics/listen").attrib["address"] == "0.0.0.0"
|
|
+ if hypervisor == "kvm":
|
|
+ assert (
|
|
+ root.find(".//channel[@type='spicevmc']/target").get("name")
|
|
+ == "com.redhat.spice.0"
|
|
+ )
|
|
+ else:
|
|
+ assert root.find(".//channel[@type='spicevmc']") is None
|
|
+
|
|
+
|
|
+def test_gen_xml_spice():
|
|
+ """
|
|
+ Test virt._gen_xml() with spice graphics device
|
|
+ """
|
|
+ xml_data = virt._gen_xml(
|
|
+ virt.libvirt.openAuth.return_value,
|
|
+ "hello",
|
|
+ 1,
|
|
+ 512,
|
|
+ {},
|
|
+ {},
|
|
+ "kvm",
|
|
+ "hvm",
|
|
+ "x86_64",
|
|
+ graphics={
|
|
+ "type": "spice",
|
|
+ "port": 1234,
|
|
+ "tls_port": 5678,
|
|
+ "listen": {"type": "none"},
|
|
+ },
|
|
+ )
|
|
+ root = ET.fromstring(xml_data)
|
|
+ assert root.find("devices/graphics").attrib["type"] == "spice"
|
|
+ assert root.find("devices/graphics").attrib["autoport"] == "no"
|
|
+ assert root.find("devices/graphics").attrib["port"] == "1234"
|
|
+ assert root.find("devices/graphics").attrib["tlsPort"] == "5678"
|
|
+ assert "listen" not in root.find("devices/graphics").attrib
|
|
+ assert root.find("devices/graphics/listen").attrib["type"] == "none"
|
|
+ assert "address" not in root.find("devices/graphics/listen").attrib
|
|
diff --git a/tests/pytests/unit/modules/virt/test_helpers.py b/tests/pytests/unit/modules/virt/test_helpers.py
|
|
index 4932d84ec4..e537b87aab 100644
|
|
--- a/tests/pytests/unit/modules/virt/test_helpers.py
|
|
+++ b/tests/pytests/unit/modules/virt/test_helpers.py
|
|
@@ -13,12 +13,12 @@ def append_to_XMLDesc(mocked, fragment):
|
|
mocked.XMLDesc.return_value = ET.tostring(xml_doc)
|
|
|
|
|
|
-def assert_xml_equals(expected, actual):
|
|
+def assert_xml_equals(actual, expected):
|
|
"""
|
|
Assert that two ElementTree nodes are equal
|
|
"""
|
|
- assert xmlutil.to_dict(xmlutil.strip_spaces(expected), True) == xmlutil.to_dict(
|
|
- xmlutil.strip_spaces(actual), True
|
|
+ assert xmlutil.to_dict(xmlutil.strip_spaces(actual), True) == xmlutil.to_dict(
|
|
+ xmlutil.strip_spaces(expected), True
|
|
)
|
|
|
|
|
|
diff --git a/tests/pytests/unit/modules/virt/test_host.py b/tests/pytests/unit/modules/virt/test_host.py
|
|
index 555deb23bb..c5cadb8aa0 100644
|
|
--- a/tests/pytests/unit/modules/virt/test_host.py
|
|
+++ b/tests/pytests/unit/modules/virt/test_host.py
|
|
@@ -1,5 +1,8 @@
|
|
+import os.path
|
|
+
|
|
import pytest
|
|
import salt.modules.virt as virt
|
|
+from tests.support.mock import MagicMock, patch
|
|
|
|
from .conftest import loader_modules_config
|
|
|
|
@@ -173,7 +176,7 @@ def test_node_devices(make_mock_device):
|
|
]
|
|
virt.libvirt.openAuth().listAllDevices.return_value = mock_devs
|
|
|
|
- assert [
|
|
+ assert virt.node_devices() == [
|
|
{
|
|
"name": "pci_1002_71c4",
|
|
"caps": "pci",
|
|
@@ -216,4 +219,20 @@ def test_node_devices(make_mock_device):
|
|
"state": "down",
|
|
"device name": "pci_0000_02_10_7",
|
|
},
|
|
- ] == virt.node_devices()
|
|
+ ]
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize(
|
|
+ "dev_kvm, libvirtd", [(True, True), (False, False), (True, False)]
|
|
+)
|
|
+def test_is_kvm(dev_kvm, libvirtd):
|
|
+ """
|
|
+ Test the virt._is_kvm_hyper() function
|
|
+ """
|
|
+ with patch.dict(os.path.__dict__, {"exists": MagicMock(return_value=dev_kvm)}):
|
|
+ processes = ["libvirtd"] if libvirtd else []
|
|
+ with patch.dict(virt.__grains__, {"ps": MagicMock(return_value="foo")}):
|
|
+ with patch.dict(
|
|
+ virt.__salt__, {"cmd.run": MagicMock(return_value=processes)}
|
|
+ ):
|
|
+ assert virt._is_kvm_hyper() == (dev_kvm and libvirtd)
|
|
diff --git a/tests/pytests/unit/modules/virt/test_network.py b/tests/pytests/unit/modules/virt/test_network.py
|
|
index ba592694c0..5ab4e0a449 100644
|
|
--- a/tests/pytests/unit/modules/virt/test_network.py
|
|
+++ b/tests/pytests/unit/modules/virt/test_network.py
|
|
@@ -19,10 +19,10 @@ def test_gen_xml():
|
|
"""
|
|
xml_data = virt._gen_net_xml("network", "main", "bridge", "openvswitch")
|
|
root = ET.fromstring(xml_data)
|
|
- assert "network" == root.find("name").text
|
|
- assert "main" == root.find("bridge").attrib["name"]
|
|
- assert "bridge" == root.find("forward").attrib["mode"]
|
|
- assert "openvswitch" == root.find("virtualport").attrib["type"]
|
|
+ assert root.find("name").text == "network"
|
|
+ assert root.find("bridge").attrib["name"] == "main"
|
|
+ assert root.find("forward").attrib["mode"] == "bridge"
|
|
+ assert root.find("virtualport").attrib["type"] == "openvswitch"
|
|
|
|
|
|
def test_gen_xml_nat():
|
|
@@ -69,9 +69,9 @@ def test_gen_xml_nat():
|
|
mtu=9000,
|
|
)
|
|
root = ET.fromstring(xml_data)
|
|
- assert "network" == root.find("name").text
|
|
- assert "main" == root.find("bridge").attrib["name"]
|
|
- assert "nat" == root.find("forward").attrib["mode"]
|
|
+ assert root.find("name").text == "network"
|
|
+ assert root.find("bridge").attrib["name"] == "main"
|
|
+ assert root.find("forward").attrib["mode"] == "nat"
|
|
expected_ipv4 = ET.fromstring(
|
|
"""
|
|
<ip family='ipv4' address='192.168.2.1' prefix='24'>
|
|
@@ -85,7 +85,7 @@ def test_gen_xml_nat():
|
|
</ip>
|
|
"""
|
|
)
|
|
- assert_xml_equals(expected_ipv4, root.find("./ip[@address='192.168.2.1']"))
|
|
+ assert_xml_equals(root.find("./ip[@address='192.168.2.1']"), expected_ipv4)
|
|
|
|
expected_ipv6 = ET.fromstring(
|
|
"""
|
|
@@ -97,7 +97,7 @@ def test_gen_xml_nat():
|
|
</ip>
|
|
"""
|
|
)
|
|
- assert_xml_equals(expected_ipv6, root.find("./ip[@address='2001:db8:ca2:2::1']"))
|
|
+ assert_xml_equals(root.find("./ip[@address='2001:db8:ca2:2::1']"), expected_ipv6)
|
|
|
|
actual_nat = ET.tostring(xmlutil.strip_spaces(root.find("./forward/nat")))
|
|
expected_nat = strip_xml(
|
|
@@ -108,10 +108,10 @@ def test_gen_xml_nat():
|
|
</nat>
|
|
"""
|
|
)
|
|
- assert expected_nat == actual_nat
|
|
+ assert actual_nat == expected_nat
|
|
|
|
- assert {"name": "acme.lab", "localOnly": "yes"} == root.find("./domain").attrib
|
|
- assert "9000" == root.find("mtu").get("size")
|
|
+ assert root.find("./domain").attrib == {"name": "acme.lab", "localOnly": "yes"}
|
|
+ assert root.find("mtu").get("size") == "9000"
|
|
|
|
|
|
def test_gen_xml_dns():
|
|
@@ -172,7 +172,7 @@ def test_gen_xml_dns():
|
|
</dns>
|
|
"""
|
|
)
|
|
- assert_xml_equals(expected_xml, root.find("./dns"))
|
|
+ assert_xml_equals(root.find("./dns"), expected_xml)
|
|
|
|
|
|
def test_gen_xml_isolated():
|
|
@@ -191,9 +191,11 @@ def test_gen_xml_passthrough_interfaces():
|
|
"network", "virbr0", "passthrough", None, interfaces="eth10 eth11 eth12",
|
|
)
|
|
root = ET.fromstring(xml_data)
|
|
- assert "passthrough" == root.find("forward").get("mode")
|
|
- assert ["eth10", "eth11", "eth12"] == [
|
|
- n.get("dev") for n in root.findall("forward/interface")
|
|
+ assert root.find("forward").get("mode") == "passthrough"
|
|
+ assert [n.get("dev") for n in root.findall("forward/interface")] == [
|
|
+ "eth10",
|
|
+ "eth11",
|
|
+ "eth12",
|
|
]
|
|
|
|
|
|
@@ -213,7 +215,7 @@ def test_gen_xml_hostdev_addresses():
|
|
</forward>
|
|
"""
|
|
)
|
|
- assert_xml_equals(expected_forward, root.find("./forward"))
|
|
+ assert_xml_equals(root.find("./forward"), expected_forward)
|
|
|
|
|
|
def test_gen_xml_hostdev_pf():
|
|
@@ -232,7 +234,7 @@ def test_gen_xml_hostdev_pf():
|
|
"""
|
|
)
|
|
actual_forward = ET.tostring(xmlutil.strip_spaces(root.find("./forward")))
|
|
- assert expected_forward == actual_forward
|
|
+ assert actual_forward == expected_forward
|
|
|
|
|
|
def test_gen_xml_openvswitch():
|
|
@@ -268,7 +270,7 @@ def test_gen_xml_openvswitch():
|
|
</network>
|
|
"""
|
|
)
|
|
- assert_xml_equals(expected_xml, ET.fromstring(xml_data))
|
|
+ assert_xml_equals(ET.fromstring(xml_data), expected_xml)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
@@ -308,7 +310,7 @@ def test_define(make_mock_network, autostart, start):
|
|
"""
|
|
)
|
|
define_mock = virt.libvirt.openAuth().networkDefineXML
|
|
- assert expected_xml == strip_xml(define_mock.call_args[0][0])
|
|
+ assert strip_xml(define_mock.call_args[0][0]) == expected_xml
|
|
|
|
if autostart:
|
|
mock_network.setAutostart.assert_called_with(1)
|
|
@@ -364,8 +366,11 @@ def test_update_nat_nochange(make_mock_network):
|
|
define_mock.assert_not_called()
|
|
|
|
|
|
-@pytest.mark.parametrize("test", [True, False])
|
|
-def test_update_nat_change(make_mock_network, test):
|
|
+@pytest.mark.parametrize(
|
|
+ "test, netmask",
|
|
+ [(True, "netmask='255.255.255.0'"), (True, "prefix='24'"), (False, "prefix='24'")],
|
|
+)
|
|
+def test_update_nat_change(make_mock_network, test, netmask):
|
|
"""
|
|
Test updating a NAT network with changes
|
|
"""
|
|
@@ -378,13 +383,15 @@ def test_update_nat_change(make_mock_network, test):
|
|
<bridge name='virbr0' stp='on' delay='0'/>
|
|
<mac address='52:54:00:cd:49:6b'/>
|
|
<domain name='my.lab' localOnly='yes'/>
|
|
- <ip address='192.168.122.1' netmask='255.255.255.0'>
|
|
+ <ip address='192.168.122.1' {}>
|
|
<dhcp>
|
|
<range start='192.168.122.2' end='192.168.122.254'/>
|
|
</dhcp>
|
|
</ip>
|
|
</network>
|
|
- """
|
|
+ """.format(
|
|
+ netmask
|
|
+ )
|
|
)
|
|
assert virt.network_update(
|
|
"default",
|
|
@@ -417,7 +424,7 @@ def test_update_nat_change(make_mock_network, test):
|
|
</network>
|
|
"""
|
|
)
|
|
- assert expected_xml == strip_xml(define_mock.call_args[0][0])
|
|
+ assert strip_xml(define_mock.call_args[0][0]) == expected_xml
|
|
|
|
|
|
@pytest.mark.parametrize("change", [True, False], ids=["changed", "unchanged"])
|
|
@@ -438,11 +445,14 @@ def test_update_hostdev_pf(make_mock_network, change):
|
|
</network>
|
|
"""
|
|
)
|
|
- assert change == virt.network_update(
|
|
- "test-hostdev",
|
|
- None,
|
|
- "hostdev",
|
|
- physical_function="eth0" if not change else "eth1",
|
|
+ assert (
|
|
+ virt.network_update(
|
|
+ "test-hostdev",
|
|
+ None,
|
|
+ "hostdev",
|
|
+ physical_function="eth0" if not change else "eth1",
|
|
+ )
|
|
+ == change
|
|
)
|
|
define_mock = virt.libvirt.openAuth().networkDefineXML
|
|
if change:
|
|
diff --git a/tests/pytests/unit/states/virt/test_domain.py b/tests/pytests/unit/states/virt/test_domain.py
|
|
index a4ae8c0694..c705785bf5 100644
|
|
--- a/tests/pytests/unit/states/virt/test_domain.py
|
|
+++ b/tests/pytests/unit/states/virt/test_domain.py
|
|
@@ -21,14 +21,14 @@ def test_defined_no_change(test):
|
|
"virt.init": init_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.defined("myvm") == {
|
|
"name": "myvm",
|
|
"changes": {"myvm": {"definition": False}},
|
|
"result": True,
|
|
"comment": "Domain myvm unchanged",
|
|
- } == virt.defined("myvm")
|
|
+ }
|
|
init_mock.assert_not_called()
|
|
- assert [domain_update_call("myvm", test=test)] == update_mock.call_args_list
|
|
+ assert update_mock.call_args_list == [domain_update_call("myvm", test=test)]
|
|
|
|
|
|
def test_defined_new_with_connection(test):
|
|
@@ -72,12 +72,7 @@ def test_defined_new_with_connection(test):
|
|
{"type": "tcp", "port": 22223, "protocol": "telnet"},
|
|
{"type": "pty"},
|
|
]
|
|
- assert {
|
|
- "name": "myvm",
|
|
- "result": True if not test else None,
|
|
- "changes": {"myvm": {"definition": True}},
|
|
- "comment": "Domain myvm defined",
|
|
- } == virt.defined(
|
|
+ assert virt.defined(
|
|
"myvm",
|
|
cpu=2,
|
|
mem=2048,
|
|
@@ -103,7 +98,12 @@ def test_defined_new_with_connection(test):
|
|
serials=serials,
|
|
consoles=consoles,
|
|
host_devices=["pci_0000_00_17_0"],
|
|
- )
|
|
+ ) == {
|
|
+ "name": "myvm",
|
|
+ "result": True if not test else None,
|
|
+ "changes": {"myvm": {"definition": True}},
|
|
+ "comment": "Domain myvm defined",
|
|
+ }
|
|
if not test:
|
|
init_mock.assert_called_with(
|
|
"myvm",
|
|
@@ -160,16 +160,16 @@ def test_defined_update(test):
|
|
"initrd": "/root/f8-i386-initrd",
|
|
"cmdline": "console=ttyS0 ks=http://example.com/f8-i386/os/",
|
|
}
|
|
- assert {
|
|
+ assert virt.defined("myvm", cpu=2, boot=boot,) == {
|
|
"name": "myvm",
|
|
"changes": {"myvm": {"definition": True, "cpu": True}},
|
|
"result": True if not test else None,
|
|
"comment": "Domain myvm updated",
|
|
- } == virt.defined("myvm", cpu=2, boot=boot,)
|
|
+ }
|
|
init_mock.assert_not_called()
|
|
- assert [
|
|
+ assert update_mock.call_args_list == [
|
|
domain_update_call("myvm", cpu=2, test=test, boot=boot)
|
|
- ] == update_mock.call_args_list
|
|
+ ]
|
|
|
|
|
|
def test_defined_update_error(test):
|
|
@@ -189,7 +189,7 @@ def test_defined_update_error(test):
|
|
"virt.init": init_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.defined("myvm", cpu=2, boot_dev="cdrom hd") == {
|
|
"name": "myvm",
|
|
"changes": {
|
|
"myvm": {
|
|
@@ -200,7 +200,7 @@ def test_defined_update_error(test):
|
|
},
|
|
"result": True if not test else None,
|
|
"comment": "Domain myvm updated with live update(s) failures",
|
|
- } == virt.defined("myvm", cpu=2, boot_dev="cdrom hd")
|
|
+ }
|
|
init_mock.assert_not_called()
|
|
update_mock.assert_called_with(
|
|
"myvm",
|
|
@@ -245,16 +245,16 @@ def test_defined_update_definition_error(test):
|
|
"virt.init": init_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.defined("myvm", cpu=2) == {
|
|
"name": "myvm",
|
|
"changes": {},
|
|
"result": False,
|
|
"comment": "error message",
|
|
- } == virt.defined("myvm", cpu=2)
|
|
+ }
|
|
init_mock.assert_not_called()
|
|
- assert [
|
|
+ assert update_mock.call_args_list == [
|
|
domain_update_call("myvm", cpu=2, test=test)
|
|
- ] == update_mock.call_args_list
|
|
+ ]
|
|
|
|
|
|
@pytest.mark.parametrize("running", ["running", "shutdown"])
|
|
@@ -279,12 +279,12 @@ def test_running_no_change(test, running):
|
|
if running == "shutdown":
|
|
changes["started"] = True
|
|
comment = "Domain myvm started"
|
|
- assert {
|
|
+ assert virt.running("myvm") == {
|
|
"name": "myvm",
|
|
"result": True,
|
|
"changes": {"myvm": changes},
|
|
"comment": comment,
|
|
- } == virt.running("myvm")
|
|
+ }
|
|
if running == "shutdown" and not test:
|
|
start_mock.assert_called()
|
|
else:
|
|
@@ -326,12 +326,7 @@ def test_running_define(test):
|
|
"listen": {"type": "address", "address": "192.168.0.1"},
|
|
}
|
|
|
|
- assert {
|
|
- "name": "myvm",
|
|
- "result": True if not test else None,
|
|
- "changes": {"myvm": {"definition": True, "started": True}},
|
|
- "comment": "Domain myvm defined and started",
|
|
- } == virt.running(
|
|
+ assert virt.running(
|
|
"myvm",
|
|
cpu=2,
|
|
mem=2048,
|
|
@@ -353,7 +348,12 @@ def test_running_define(test):
|
|
connection="someconnection",
|
|
username="libvirtuser",
|
|
password="supersecret",
|
|
- )
|
|
+ ) == {
|
|
+ "name": "myvm",
|
|
+ "result": True if not test else None,
|
|
+ "changes": {"myvm": {"definition": True, "started": True}},
|
|
+ "comment": "Domain myvm defined and started",
|
|
+ }
|
|
if not test:
|
|
init_mock.assert_called_with(
|
|
"myvm",
|
|
@@ -412,12 +412,12 @@ def test_running_start_error():
|
|
"virt.list_domains": MagicMock(return_value=["myvm"]),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.running("myvm") == {
|
|
"name": "myvm",
|
|
"changes": {"myvm": {"definition": False}},
|
|
"result": False,
|
|
"comment": "libvirt error msg",
|
|
- } == virt.running("myvm")
|
|
+ }
|
|
|
|
|
|
@pytest.mark.parametrize("running", ["running", "shutdown"])
|
|
@@ -441,14 +441,14 @@ def test_running_update(test, running):
|
|
changes = {"myvm": {"definition": True, "cpu": True}}
|
|
if running == "shutdown":
|
|
changes["myvm"]["started"] = True
|
|
- assert {
|
|
+ assert virt.running("myvm", cpu=2) == {
|
|
"name": "myvm",
|
|
"changes": changes,
|
|
"result": True if not test else None,
|
|
"comment": "Domain myvm updated"
|
|
if running == "running"
|
|
else "Domain myvm updated and started",
|
|
- } == virt.running("myvm", cpu=2)
|
|
+ }
|
|
if running == "shutdown" and not test:
|
|
start_mock.assert_called()
|
|
else:
|
|
@@ -470,12 +470,12 @@ def test_running_definition_error():
|
|
"virt.list_domains": MagicMock(return_value=["myvm"]),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.running("myvm", cpu=3) == {
|
|
"name": "myvm",
|
|
"changes": {},
|
|
"result": False,
|
|
"comment": "error message",
|
|
- } == virt.running("myvm", cpu=3)
|
|
+ }
|
|
|
|
|
|
def test_running_update_error():
|
|
@@ -494,7 +494,7 @@ def test_running_update_error():
|
|
"virt.list_domains": MagicMock(return_value=["myvm"]),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.running("myvm", cpu=2) == {
|
|
"name": "myvm",
|
|
"changes": {
|
|
"myvm": {
|
|
@@ -505,7 +505,7 @@ def test_running_update_error():
|
|
},
|
|
"result": True,
|
|
"comment": "Domain myvm updated with live update(s) failures",
|
|
- } == virt.running("myvm", cpu=2)
|
|
+ }
|
|
update_mock.assert_called_with(
|
|
"myvm",
|
|
cpu=2,
|
|
@@ -552,14 +552,14 @@ def test_stopped(test, running):
|
|
if running == "running":
|
|
changes = {"stopped": [{"domain": "myvm", "shutdown": True}]}
|
|
comment = "Machine has been shut down"
|
|
- assert {
|
|
+ assert virt.stopped(
|
|
+ "myvm", connection="myconnection", username="user", password="secret",
|
|
+ ) == {
|
|
"name": "myvm",
|
|
"changes": changes,
|
|
"comment": comment,
|
|
"result": True if not test or running == "shutdown" else None,
|
|
- } == virt.stopped(
|
|
- "myvm", connection="myconnection", username="user", password="secret",
|
|
- )
|
|
+ }
|
|
if not test and running == "running":
|
|
shutdown_mock.assert_called_with(
|
|
"myvm",
|
|
@@ -586,12 +586,12 @@ def test_stopped_error():
|
|
),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.stopped("myvm") == {
|
|
"name": "myvm",
|
|
"changes": {"ignored": [{"domain": "myvm", "issue": "Some error"}]},
|
|
"result": False,
|
|
"comment": "No changes had happened",
|
|
- } == virt.stopped("myvm")
|
|
+ }
|
|
|
|
|
|
def test_stopped_not_existing(test):
|
|
@@ -603,12 +603,12 @@ def test_stopped_not_existing(test):
|
|
with patch.dict(
|
|
virt.__salt__, {"virt.list_domains": MagicMock(return_value=[])},
|
|
):
|
|
- assert {
|
|
+ assert virt.stopped("myvm") == {
|
|
"name": "myvm",
|
|
"changes": {},
|
|
"comment": "No changes had happened",
|
|
"result": False,
|
|
- } == virt.stopped("myvm")
|
|
+ }
|
|
|
|
|
|
@pytest.mark.parametrize("running", ["running", "shutdown"])
|
|
@@ -631,14 +631,14 @@ def test_powered_off(test, running):
|
|
if running == "running":
|
|
changes = {"unpowered": [{"domain": "myvm", "stop": True}]}
|
|
comment = "Machine has been powered off"
|
|
- assert {
|
|
+ assert virt.powered_off(
|
|
+ "myvm", connection="myconnection", username="user", password="secret",
|
|
+ ) == {
|
|
"name": "myvm",
|
|
"result": True if not test or running == "shutdown" else None,
|
|
"changes": changes,
|
|
"comment": comment,
|
|
- } == virt.powered_off(
|
|
- "myvm", connection="myconnection", username="user", password="secret",
|
|
- )
|
|
+ }
|
|
if not test and running == "running":
|
|
stop_mock.assert_called_with(
|
|
"myvm",
|
|
@@ -666,12 +666,12 @@ def test_powered_off_error():
|
|
),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.powered_off("myvm") == {
|
|
"name": "myvm",
|
|
"result": False,
|
|
"changes": {"ignored": [{"domain": "myvm", "issue": "Some error"}]},
|
|
"comment": "No changes had happened",
|
|
- } == virt.powered_off("myvm")
|
|
+ }
|
|
|
|
|
|
def test_powered_off_not_existing():
|
|
@@ -686,12 +686,12 @@ def test_powered_off_not_existing():
|
|
ret.update(
|
|
{"changes": {}, "result": False, "comment": "No changes had happened"}
|
|
)
|
|
- assert {
|
|
+ assert virt.powered_off("myvm") == {
|
|
"name": "myvm",
|
|
"changes": {},
|
|
"result": False,
|
|
"comment": "No changes had happened",
|
|
- } == virt.powered_off("myvm")
|
|
+ }
|
|
|
|
|
|
def test_snapshot(test):
|
|
@@ -707,18 +707,18 @@ def test_snapshot(test):
|
|
"virt.snapshot": snapshot_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
- "name": "myvm",
|
|
- "result": True if not test else None,
|
|
- "changes": {"saved": [{"domain": "myvm", "snapshot": True}]},
|
|
- "comment": "Snapshot has been taken",
|
|
- } == virt.snapshot(
|
|
+ assert virt.snapshot(
|
|
"myvm",
|
|
suffix="snap",
|
|
connection="myconnection",
|
|
username="user",
|
|
password="secret",
|
|
- )
|
|
+ ) == {
|
|
+ "name": "myvm",
|
|
+ "result": True if not test else None,
|
|
+ "changes": {"saved": [{"domain": "myvm", "snapshot": True}]},
|
|
+ "comment": "Snapshot has been taken",
|
|
+ }
|
|
if not test:
|
|
snapshot_mock.assert_called_with(
|
|
"myvm",
|
|
@@ -745,12 +745,12 @@ def test_snapshot_error():
|
|
),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.snapshot("myvm") == {
|
|
"name": "myvm",
|
|
"result": False,
|
|
"changes": {"ignored": [{"domain": "myvm", "issue": "Some error"}]},
|
|
"comment": "No changes had happened",
|
|
- } == virt.snapshot("myvm")
|
|
+ }
|
|
|
|
|
|
def test_snapshot_not_existing(test):
|
|
@@ -761,12 +761,12 @@ def test_snapshot_not_existing(test):
|
|
with patch.dict(
|
|
virt.__salt__, {"virt.list_domains": MagicMock(return_value=[])}
|
|
):
|
|
- assert {
|
|
+ assert virt.snapshot("myvm") == {
|
|
"name": "myvm",
|
|
"changes": {},
|
|
"result": False,
|
|
"comment": "No changes had happened",
|
|
- } == virt.snapshot("myvm")
|
|
+ }
|
|
|
|
|
|
def test_rebooted(test):
|
|
@@ -782,14 +782,14 @@ def test_rebooted(test):
|
|
"virt.reboot": reboot_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.rebooted(
|
|
+ "myvm", connection="myconnection", username="user", password="secret",
|
|
+ ) == {
|
|
"name": "myvm",
|
|
"result": True if not test else None,
|
|
"changes": {"rebooted": [{"domain": "myvm", "reboot": True}]},
|
|
"comment": "Machine has been rebooted",
|
|
- } == virt.rebooted(
|
|
- "myvm", connection="myconnection", username="user", password="secret",
|
|
- )
|
|
+ }
|
|
if not test:
|
|
reboot_mock.assert_called_with(
|
|
"myvm",
|
|
@@ -816,12 +816,12 @@ def test_rebooted_error():
|
|
),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.rebooted("myvm") == {
|
|
"name": "myvm",
|
|
"result": False,
|
|
"changes": {"ignored": [{"domain": "myvm", "issue": "Some error"}]},
|
|
"comment": "No changes had happened",
|
|
- } == virt.rebooted("myvm")
|
|
+ }
|
|
|
|
|
|
def test_rebooted_not_existing(test):
|
|
@@ -832,9 +832,9 @@ def test_rebooted_not_existing(test):
|
|
with patch.dict(
|
|
virt.__salt__, {"virt.list_domains": MagicMock(return_value=[])}
|
|
):
|
|
- assert {
|
|
+ assert virt.rebooted("myvm") == {
|
|
"name": "myvm",
|
|
"changes": {},
|
|
"result": False,
|
|
"comment": "No changes had happened",
|
|
- } == virt.rebooted("myvm")
|
|
+ }
|
|
diff --git a/tests/pytests/unit/states/virt/test_network.py b/tests/pytests/unit/states/virt/test_network.py
|
|
index 668eee0c64..a68acfa236 100644
|
|
--- a/tests/pytests/unit/states/virt/test_network.py
|
|
+++ b/tests/pytests/unit/states/virt/test_network.py
|
|
@@ -19,12 +19,7 @@ def test_network_defined_not_existing(test):
|
|
"virt.network_define": define_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
- "name": "mynet",
|
|
- "changes": {"mynet": "Network defined"},
|
|
- "result": None if test else True,
|
|
- "comment": "Network mynet defined",
|
|
- } == virt.network_defined(
|
|
+ assert virt.network_defined(
|
|
"mynet",
|
|
"br2",
|
|
"bridge",
|
|
@@ -58,7 +53,12 @@ def test_network_defined_not_existing(test):
|
|
connection="myconnection",
|
|
username="user",
|
|
password="secret",
|
|
- )
|
|
+ ) == {
|
|
+ "name": "mynet",
|
|
+ "changes": {"mynet": "Network defined"},
|
|
+ "result": None if test else True,
|
|
+ "comment": "Network mynet defined",
|
|
+ }
|
|
if not test:
|
|
define_mock.assert_called_with(
|
|
"mynet",
|
|
@@ -117,16 +117,16 @@ def test_network_defined_no_change(test):
|
|
"virt.network_update": update_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.network_defined("mynet", "br2", "bridge") == {
|
|
"name": "mynet",
|
|
"changes": {},
|
|
"result": True,
|
|
"comment": "Network mynet unchanged",
|
|
- } == virt.network_defined("mynet", "br2", "bridge")
|
|
+ }
|
|
define_mock.assert_not_called()
|
|
- assert [
|
|
+ assert update_mock.call_args_list == [
|
|
network_update_call("mynet", "br2", "bridge", test=True)
|
|
- ] == update_mock.call_args_list
|
|
+ ]
|
|
|
|
|
|
def test_network_defined_change(test):
|
|
@@ -148,12 +148,7 @@ def test_network_defined_change(test):
|
|
"virt.network_set_autostart": autostart_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
- "name": "mynet",
|
|
- "changes": {"mynet": "Network updated, autostart flag changed"},
|
|
- "result": None if test else True,
|
|
- "comment": "Network mynet updated, autostart flag changed",
|
|
- } == virt.network_defined(
|
|
+ assert virt.network_defined(
|
|
"mynet",
|
|
"br2",
|
|
"bridge",
|
|
@@ -187,7 +182,12 @@ def test_network_defined_change(test):
|
|
connection="myconnection",
|
|
username="user",
|
|
password="secret",
|
|
- )
|
|
+ ) == {
|
|
+ "name": "mynet",
|
|
+ "changes": {"mynet": "Network updated, autostart flag changed"},
|
|
+ "result": None if test else True,
|
|
+ "comment": "Network mynet updated, autostart flag changed",
|
|
+ }
|
|
define_mock.assert_not_called()
|
|
expected_update_kwargs = {
|
|
"vport": "openvswitch",
|
|
@@ -226,7 +226,7 @@ def test_network_defined_change(test):
|
|
)
|
|
]
|
|
if test:
|
|
- assert calls == update_mock.call_args_list
|
|
+ assert update_mock.call_args_list == calls
|
|
autostart_mock.assert_not_called()
|
|
else:
|
|
calls.append(
|
|
@@ -234,7 +234,7 @@ def test_network_defined_change(test):
|
|
"mynet", "br2", "bridge", **expected_update_kwargs, test=False
|
|
)
|
|
)
|
|
- assert calls == update_mock.call_args_list
|
|
+ assert update_mock.call_args_list == calls
|
|
autostart_mock.assert_called_with(
|
|
"mynet",
|
|
state="off",
|
|
@@ -258,12 +258,12 @@ def test_network_defined_error(test):
|
|
)
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.network_defined("mynet", "br2", "bridge") == {
|
|
"name": "mynet",
|
|
"changes": {},
|
|
"result": False,
|
|
"comment": "Some error",
|
|
- } == virt.network_defined("mynet", "br2", "bridge")
|
|
+ }
|
|
define_mock.assert_not_called()
|
|
|
|
|
|
@@ -285,12 +285,7 @@ def test_network_running_not_existing(test):
|
|
"virt.network_start": start_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
- "name": "mynet",
|
|
- "changes": {"mynet": "Network defined and started"},
|
|
- "comment": "Network mynet defined and started",
|
|
- "result": None if test else True,
|
|
- } == virt.network_running(
|
|
+ assert virt.network_running(
|
|
"mynet",
|
|
"br2",
|
|
"bridge",
|
|
@@ -324,7 +319,12 @@ def test_network_running_not_existing(test):
|
|
connection="myconnection",
|
|
username="user",
|
|
password="secret",
|
|
- )
|
|
+ ) == {
|
|
+ "name": "mynet",
|
|
+ "changes": {"mynet": "Network defined and started"},
|
|
+ "comment": "Network mynet defined and started",
|
|
+ "result": None if test else True,
|
|
+ }
|
|
if not test:
|
|
define_mock.assert_called_with(
|
|
"mynet",
|
|
@@ -390,15 +390,15 @@ def test_network_running_nochange(test):
|
|
"virt.network_update": update_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.network_running("mynet", "br2", "bridge") == {
|
|
"name": "mynet",
|
|
"changes": {},
|
|
"comment": "Network mynet unchanged and is running",
|
|
"result": None if test else True,
|
|
- } == virt.network_running("mynet", "br2", "bridge")
|
|
- assert [
|
|
+ }
|
|
+ assert update_mock.call_args_list == [
|
|
network_update_call("mynet", "br2", "bridge", test=True)
|
|
- ] == update_mock.call_args_list
|
|
+ ]
|
|
|
|
|
|
def test_network_running_stopped(test):
|
|
@@ -420,20 +420,20 @@ def test_network_running_stopped(test):
|
|
"virt.network_update": update_mock,
|
|
},
|
|
):
|
|
- assert {
|
|
- "name": "mynet",
|
|
- "changes": {"mynet": "Network started"},
|
|
- "comment": "Network mynet unchanged and started",
|
|
- "result": None if test else True,
|
|
- } == virt.network_running(
|
|
+ assert virt.network_running(
|
|
"mynet",
|
|
"br2",
|
|
"bridge",
|
|
connection="myconnection",
|
|
username="user",
|
|
password="secret",
|
|
- )
|
|
- assert [
|
|
+ ) == {
|
|
+ "name": "mynet",
|
|
+ "changes": {"mynet": "Network started"},
|
|
+ "comment": "Network mynet unchanged and started",
|
|
+ "result": None if test else True,
|
|
+ }
|
|
+ assert update_mock.call_args_list == [
|
|
network_update_call(
|
|
"mynet",
|
|
"br2",
|
|
@@ -443,7 +443,7 @@ def test_network_running_stopped(test):
|
|
password="secret",
|
|
test=True,
|
|
)
|
|
- ] == update_mock.call_args_list
|
|
+ ]
|
|
if not test:
|
|
start_mock.assert_called_with(
|
|
"mynet",
|
|
@@ -468,9 +468,9 @@ def test_network_running_error(test):
|
|
),
|
|
},
|
|
):
|
|
- assert {
|
|
+ assert virt.network_running("mynet", "br2", "bridge") == {
|
|
"name": "mynet",
|
|
"changes": {},
|
|
"comment": "Some error",
|
|
"result": False,
|
|
- } == virt.network_running("mynet", "br2", "bridge")
|
|
+ }
|
|
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
|
index dd42ce4441..ec11b56d98 100644
|
|
--- a/tests/unit/modules/test_virt.py
|
|
+++ b/tests/unit/modules/test_virt.py
|
|
@@ -520,65 +520,6 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
|
root.find("devices/graphics/listen").attrib["address"], "myhost"
|
|
)
|
|
|
|
- def test_gen_xml_spice_default(self):
|
|
- """
|
|
- Test virt._gen_xml() with default spice graphics device
|
|
- """
|
|
- diskp = virt._disk_profile(self.mock_conn, "default", "kvm", [], "hello")
|
|
- nicp = virt._nic_profile("default", "kvm")
|
|
- xml_data = virt._gen_xml(
|
|
- self.mock_conn,
|
|
- "hello",
|
|
- 1,
|
|
- 512,
|
|
- diskp,
|
|
- nicp,
|
|
- "kvm",
|
|
- "hvm",
|
|
- "x86_64",
|
|
- graphics={"type": "spice"},
|
|
- )
|
|
- root = ET.fromstring(xml_data)
|
|
- self.assertEqual(root.find("devices/graphics").attrib["type"], "spice")
|
|
- self.assertEqual(root.find("devices/graphics").attrib["autoport"], "yes")
|
|
- self.assertEqual(root.find("devices/graphics").attrib["listen"], "0.0.0.0")
|
|
- self.assertEqual(root.find("devices/graphics/listen").attrib["type"], "address")
|
|
- self.assertEqual(
|
|
- root.find("devices/graphics/listen").attrib["address"], "0.0.0.0"
|
|
- )
|
|
-
|
|
- def test_gen_xml_spice(self):
|
|
- """
|
|
- Test virt._gen_xml() with spice graphics device
|
|
- """
|
|
- diskp = virt._disk_profile(self.mock_conn, "default", "kvm", [], "hello")
|
|
- nicp = virt._nic_profile("default", "kvm")
|
|
- xml_data = virt._gen_xml(
|
|
- self.mock_conn,
|
|
- "hello",
|
|
- 1,
|
|
- 512,
|
|
- diskp,
|
|
- nicp,
|
|
- "kvm",
|
|
- "hvm",
|
|
- "x86_64",
|
|
- graphics={
|
|
- "type": "spice",
|
|
- "port": 1234,
|
|
- "tls_port": 5678,
|
|
- "listen": {"type": "none"},
|
|
- },
|
|
- )
|
|
- root = ET.fromstring(xml_data)
|
|
- self.assertEqual(root.find("devices/graphics").attrib["type"], "spice")
|
|
- self.assertEqual(root.find("devices/graphics").attrib["autoport"], "no")
|
|
- self.assertEqual(root.find("devices/graphics").attrib["port"], "1234")
|
|
- self.assertEqual(root.find("devices/graphics").attrib["tlsPort"], "5678")
|
|
- self.assertFalse("listen" in root.find("devices/graphics").attrib)
|
|
- self.assertEqual(root.find("devices/graphics/listen").attrib["type"], "none")
|
|
- self.assertFalse("address" in root.find("devices/graphics/listen").attrib)
|
|
-
|
|
def test_gen_xml_memory(self):
|
|
"""
|
|
Test virt._gen_xml() with advanced memory settings
|
|
@@ -5140,6 +5081,10 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
|
{"qemu", "kvm"}, {domainCaps["domain"] for domainCaps in caps["domains"]},
|
|
)
|
|
|
|
+ self.mock_conn.getDomainCapabilities.assert_called_with(
|
|
+ "/usr/bin/qemu-system-x86_64", "x86_64", None, "kvm"
|
|
+ )
|
|
+
|
|
def test_network_tag(self):
|
|
"""
|
|
Test virt._get_net_xml() with VLAN tag
|
|
--
|
|
2.33.0
|
|
|
|
|