File: testmock.py

package info (click to toggle)
virt-manager 1%3A5.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 20,404 kB
  • sloc: python: 45,877; xml: 29,099; makefile: 17; sh: 6
file content (278 lines) | stat: -rw-r--r-- 9,612 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# 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(0.5)
        log.info("mock virtBootstrap msg2")
        kwargs["progress_cb"]({"status": "msg2"})
        time.sleep(0.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
    * test-update-device-fail: Make UpdateDevice API call fail

    * firstrun-uri: If set, use this as the initial connection URI
        if we are doing firstrun testing
    * fake-vnc-username: Fake VNC username auth request
    * 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.test_update_device_fail = _get("test-update-device-fail")
        self.firstrun_uri = _get_value("firstrun-uri")
        self.fake_vnc_username = _get("fake-vnc-username")
        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