virt-manager/virtManager/lib/testmock.py

263 lines
9.5 KiB
Python

# Copyright (C) 2020 Red Hat, Inc.
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
# This file is a collection of code used for testing
# code paths primarily via our uitests/
import os
def fake_job_info():
import random
total = 1024 * 1024 * 1024
fakepcent = random.choice(range(1, 100))
remaining = ((total / 100) * fakepcent)
return [None, None, None, total, None, remaining]
def fake_interface_addresses(iface, source):
import libvirt
mac = iface.macaddr
if source == libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT:
ret = {
'enp1s0': {'hwaddr': mac, 'addrs': [
{'addr': '10.0.0.1', 'prefix': 24, 'type': 0},
{'addr': 'fd00:beef::1', 'prefix': 128, 'type': 1},
{'addr': 'fe80::1', 'prefix': 64, 'type': 1}],
},
'lo': {'hwaddr': '00:00:00:00:00:00', 'addrs': [
{'addr': '127.0.0.1', 'prefix': 8, 'type': 0},
{'addr': '::1', 'prefix': 128, 'type': 1}],
},
}
else:
ret = {'vnet0': {'hwaddr': mac, 'addrs': [
{'addr': '10.0.0.3', 'prefix': 0, 'type': 0}],
}}
return ret
def fake_dhcp_leases():
ret = [{
'clientid': 'XXX',
'expirytime': 1598570993,
'hostname': None,
'iaid': '1448103320',
'iface': 'virbr1',
'ipaddr': 'fd00:beef::2',
'mac': 'BAD',
'prefix': 64,
'type': 1}, {
'clientid': 'YYY',
'expirytime': 1598570993,
'hostname': None,
'iaid': None,
'iface': 'virbr1',
'ipaddr': '10.0.0.2',
'mac': 'NOPE',
'prefix': 24,
'type': 0}]
return ret
def schedule_fake_agent_event(conn, cb):
import libvirt
vmname = conn.config.CLITestOptions.fake_agent_event
backend = conn.get_backend()
state = libvirt.VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_CONNECTED
reason = libvirt.VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL
def time_cb():
dom = backend.lookupByName(vmname)
cb(backend, dom, state, reason, None)
conn.timeout_add(500, time_cb)
def schedule_fake_nodedev_event(conn, lifecycle_cb, update_cb):
import libvirt
nodename = conn.config.CLITestOptions.fake_nodedev_event
backend = conn.get_backend()
def lifecycle_cb_wrapper():
nodedev = backend.nodeDeviceLookupByName(nodename)
state = libvirt.VIR_NODE_DEVICE_EVENT_CREATED
reason = 0
lifecycle_cb(backend, nodedev, state, reason, None)
def update_cb_wrapper():
nodedev = backend.nodeDeviceLookupByName(nodename)
update_cb(backend, nodedev, None)
conn.timeout_add(500, lifecycle_cb_wrapper)
conn.timeout_add(1000, update_cb_wrapper)
def fake_openauth(conn, cb, data):
ignore = conn
import libvirt
creds = [
[libvirt.VIR_CRED_USERNAME, "Username", None, None, None],
[libvirt.VIR_CRED_PASSPHRASE, "Password", None, None, None],
]
cb(creds, data)
assert all([bool(cred[4]) for cred in creds])
class fakeVirtBootstrap:
@staticmethod
def bootstrap(**kwargs):
import time
import logging
log = logging.getLogger("virtBootstrap")
log.info("mock virtBootstrap msg1")
kwargs["progress_cb"]({"status": "msg1"})
time.sleep(.5)
log.info("mock virtBootstrap msg2")
kwargs["progress_cb"]({"status": "msg2"})
time.sleep(.5)
log.info("mock virtBootstrap msg3")
kwargs["progress_cb"]({"status": "msg3"})
if "username" in kwargs:
raise RuntimeError("fakeVirtBootstrap mock auth failure!")
class CLITestOptionsClass:
"""
Helper class for parsing and tracking --test-* options.
The suboptions are:
* first-run: Run the app with fresh gsettings values saved to
a keyfile, mimicking a first app run. Also sets
GSETTINGS to use memory backend, in case any other app
preferences would be affected. The ui testsuite sets this
for most tests.
* xmleditor-enabled: Force the xmleditor gsettings preference on.
* gsettings-keyfile: Override the gsettings values with those
from the passed in keyfile, to test with different default
settings.
* leak-debug: Enabling this will tell us, at app exit time,
which vmmGObjects were not garbage collected. This is caused
by circular references to other objects, like a signal that
wasn't disconnected. It's not a big deal, but if we have objects
that can be created and destroyed a lot over the course of
the app lifecycle, every non-garbage collected class is a
memory leak. So it's nice to poke at this every now and then
and try to track down what we need to add to class _cleanup handling.
* no-events: Force disable libvirt event APIs for testing fallback
* break_setfacl: For setfacl calls to fail, for test scenarios.
This is hit via the directory search permissions checking
for disk image usage for qemu
* enable-libguestfs: Force enable the libguestfs gsetting
* disable-libguestfs: Force disable the libguestfs gsetting
* test-managed-save: Triggers a couple conditions for testing
managed save issues
* test-vm-run-fail: Make VM run fail, so we can test the error path
* spice-agent: Make spice-agent detection return true in viewer.py
* firstrun-uri: If set, use this as the initial connection URI
if we are doing firstrun testing
* fake-no-libvirtd: If doing firstrun testing, fake that
libvirtd is not installed
* fake-vnc-username: Fake VNC username auth request
* fake-console-resolution: Fake viewer console resolution response.
Spice doesn't return values here when we are just testing
against seabios in uitests, this fakes it to hit more code paths
* fake-systray: Enable the fake systray window
* fake-virtbootstrap: Mock the virtBootstrap module, since getting
it to actually work across fedora versions is hard
* object-denylist=NAME: Make object initialize for that name
fail to test some connection code paths
* conn-crash: Test connection abruptly closing like when
libvirtd is restarted.
* fake-agent-event: Fake a qemu guest agent API event
* fake-nodedev-event: Fake nodedev API events
* fake-openauth: Fake user+pass response from libvirt openauth,
for testing the TCP URI auth dialog
* fake-session-error: Fake a connection open error that
triggers logind session lookup
* short-poll: Use a polling interval of only .1 seconds to speed
up the uitests a bit
"""
def __init__(self, test_options_str):
optset = set()
for optstr in test_options_str:
optset.update(set(optstr.split(",")))
first_run = self._parse(optset)
self._process(first_run)
def _parse(self, optset):
def _get(optname):
if optname not in optset:
return False
optset.remove(optname)
return True
def _get_value(optname):
for opt in optset:
if opt.startswith(optname + "="):
optset.remove(opt)
return opt.split("=", 1)[1]
first_run = _get("first-run")
self.leak_debug = _get("leak-debug")
self.no_events = _get("no-events")
self.xmleditor_enabled = _get("xmleditor-enabled")
self.gsettings_keyfile = _get_value("gsettings-keyfile")
self.break_setfacl = _get("break-setfacl")
self.disable_libguestfs = _get("disable-libguestfs")
self.enable_libguestfs = _get("enable-libguestfs")
self.test_managed_save = _get("test-managed-save")
self.test_vm_run_fail = _get("test-vm-run-fail")
self.spice_agent = _get("spice-agent")
self.firstrun_uri = _get_value("firstrun-uri")
self.fake_no_libvirtd = _get("fake-no-libvirtd")
self.fake_vnc_username = _get("fake-vnc-username")
self.fake_console_resolution = _get("fake-console-resolution")
self.fake_systray = _get("fake-systray")
self.object_denylist = _get_value("object-denylist")
self.conn_crash = _get("conn-crash")
self.fake_agent_event = _get_value("fake-agent-event")
self.fake_nodedev_event = _get_value("fake-nodedev-event")
self.fake_openauth = _get("fake-openauth")
self.fake_session_error = _get("fake-session-error")
self.short_poll = _get("short-poll")
self.fake_virtbootstrap = _get("fake-virtbootstrap")
if optset: # pragma: no cover
raise RuntimeError("Unknown --test-options keys: %s" % optset)
return first_run
def _process(self, first_run):
if first_run:
# So other settings like gtk are reset and not affected
os.environ["GSETTINGS_BACKEND"] = "memory"
if first_run and not self.gsettings_keyfile:
import atexit
import tempfile
filename = tempfile.mktemp(prefix="virtmanager-firstrun-keyfile")
self.gsettings_keyfile = filename
atexit.register(lambda: os.unlink(filename))
if self.break_setfacl:
import virtinst.diskbackend
def fake_search(*args, **kwargs):
raise RuntimeError("Fake search fix fail from test suite")
virtinst.diskbackend.SETFACL = "getfacl"
# pylint: disable=protected-access
virtinst.diskbackend._fix_perms_chmod = fake_search