6 from unittest
import mock
11 class TestLibvirtAio(unittest
.TestCase
):
12 async def _run(self
, register
):
13 def lifecycleCallback(conn
, dom
, event
, detail
, domainChangedEvent
):
14 if (event
== libvirt
.VIR_DOMAIN_EVENT_STOPPED
or
15 event
== libvirt
.VIR_DOMAIN_EVENT_STARTED
):
16 domainChangedEvent
.set()
19 libvirtEvents
= libvirtaio
.virEventRegisterAsyncIOImpl()
21 libvirtEvents
= libvirtaio
.getCurrentImpl()
23 conn
= libvirt
.open("test:///default")
24 dom
= conn
.lookupByName("test")
26 eventRegistered
= False
29 # Ensure the VM is running.
30 self
.assertEqual([libvirt
.VIR_DOMAIN_RUNNING
, libvirt
.VIR_DOMAIN_RUNNING_UNKNOWN
], dom
.state())
31 self
.assertTrue(libvirtEvents
.is_idle())
33 # Register VM start/stopped event handler.
34 domainChangedEvent
= asyncio
.Event()
35 conn
.domainEventRegisterAny(dom
, libvirt
.VIR_DOMAIN_EVENT_ID_LIFECYCLE
, lifecycleCallback
, domainChangedEvent
)
36 eventRegistered
= True
38 self
.assertFalse(libvirtEvents
.is_idle())
44 # Ensure domain stopped event is received.
45 await asyncio
.wait_for(domainChangedEvent
.wait(), 2)
46 self
.assertEqual([libvirt
.VIR_DOMAIN_SHUTOFF
, libvirt
.VIR_DOMAIN_SHUTOFF_DESTROYED
], dom
.state())
49 domainChangedEvent
.clear()
53 # Ensure domain started event is received.
54 await asyncio
.wait_for(domainChangedEvent
.wait(), 2)
55 self
.assertEqual([libvirt
.VIR_DOMAIN_RUNNING
, libvirt
.VIR_DOMAIN_RUNNING_BOOTED
], dom
.state())
56 self
.assertFalse(libvirtEvents
.is_idle())
58 # Deregister the VM start/stopped event handler.
59 eventRegistered
= False
60 conn
.domainEventDeregisterAny(libvirt
.VIR_DOMAIN_EVENT_ID_LIFECYCLE
)
62 # Wait for event queue to clear.
63 await libvirtEvents
.drain()
65 # Make sure event queue is cleared.
66 self
.assertTrue(libvirtEvents
.is_idle())
70 conn
.domainEventDeregisterAny(libvirt
.VIR_DOMAIN_EVENT_ID_LIFECYCLE
)
75 @mock.patch('libvirt.virEventRegisterImpl',
76 side_effect
=eventmock
.virEventRegisterImplMock
)
77 def testEventsWithManualLoopSetup(self
, mock_event_register
):
78 # Register libvirt events after starting the asyncio loop.
80 # Manually create and set the event loop against this
82 loop
= asyncio
.new_event_loop()
83 asyncio
.set_event_loop(loop
)
85 loop
.run_until_complete(self
._run
(register
=True))
88 asyncio
.set_event_loop(None)
89 mock_event_register
.assert_called_once()
91 @mock.patch('libvirt.virEventRegisterImpl',
92 side_effect
=eventmock
.virEventRegisterImplMock
)
93 @unittest.skipIf(sys
.version_info
< (3,7), "test requires Python 3.7+")
94 def testEventsWithAsyncioRun(self
, mock_event_register
):
95 # Register libvirt events after starting the asyncio loop.
97 # Use asyncio helper to create and set the event loop
98 # against this thread.
99 asyncio
.run(self
._run
(register
=True))
100 mock_event_register
.assert_called_once()
102 @mock.patch('libvirt.virEventRegisterImpl',
103 side_effect
=eventmock
.virEventRegisterImplMock
)
104 def testEventsPreInitExplicit(self
, mock_event_register
):
105 # Register libvirt events before starting the asyncio loop.
107 # Tell virEventRegisterAsyncIOImpl() explicitly what loop
108 # to use before we set a loop for this thread.
109 loop
= asyncio
.new_event_loop()
110 libvirtaio
.virEventRegisterAsyncIOImpl(loop
)
111 asyncio
.set_event_loop(loop
)
113 loop
.run_until_complete(self
._run
(register
=False))
116 asyncio
.set_event_loop(None)
117 mock_event_register
.assert_called_once()
119 @mock.patch('libvirt.virEventRegisterImpl',
120 side_effect
=eventmock
.virEventRegisterImplMock
)
121 @unittest.skipIf(sys
.version_info
>= (3,10), "test incompatible with 3.10+")
122 def testEventsPreInitImplicit(self
, mock_event_register
):
123 # Register libvirt events before starting the asyncio loop.
125 # Allow virEventRegisterAsyncIOImpl() to implicitly find the
126 # loop we set for this thread.
127 loop
= asyncio
.new_event_loop()
128 asyncio
.set_event_loop(loop
)
129 libvirtaio
.virEventRegisterAsyncIOImpl()
131 loop
.run_until_complete(self
._run
(register
=False))
134 asyncio
.set_event_loop(None)
135 mock_event_register
.assert_called_once()
137 @mock.patch('libvirt.virEventRegisterImpl',
138 side_effect
=eventmock
.virEventRegisterImplMock
)
139 @unittest.skipIf(sys
.version_info
>= (3,10), "test incompatible with 3.10+")
140 def testEventsImplicitLoopInit(self
, mock_event_register
):
141 # Register libvirt events before starting the asyncio loop.
143 # Let virEventRegisterAsyncIOImpl() auto-create a default
144 # event loop, which we then register against this thread.
146 # Historically this often worked if called from the main thead,
147 # but since Python 3.10 this triggers a deprecation warning,
148 # which will turn into a RuntimeError in a later release.
149 libvirtaio
.virEventRegisterAsyncIOImpl()
150 loop
= asyncio
.get_event_loop()
152 loop
.run_until_complete(self
._run
(register
=False))
155 asyncio
.set_event_loop(None)
156 mock_event_register
.assert_called_once()