Skip to content

Commit b9c590c

Browse files
committed
Call qvm_shutdown module from template postprocess
I tried to not require async functions, by passing the loop from template_postprocess to qvm_shutdown.main, but failed with: RuntimeError: This event loop is already running
1 parent 4bc9bcd commit b9c590c

4 files changed

Lines changed: 106 additions & 115 deletions

File tree

qubesadmin/tests/tools/qvm_shutdown.py

Lines changed: 90 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,53 @@
2828

2929

3030
class TC_00_qvm_shutdown(qubesadmin.tests.QubesTestCase):
31+
3132
def test_000_with_vm(self):
33+
loop = asyncio.new_event_loop()
34+
asyncio.set_event_loop(loop)
35+
3236
self.app.expected_calls[
3337
('dom0', 'admin.vm.List', None, None)] = \
3438
b'0\x00some-vm class=AppVM state=Running\n'
3539
self.app.expected_calls[
3640
('some-vm', 'admin.vm.Shutdown', None, None)] = b'0\x00'
37-
qubesadmin.tools.qvm_shutdown.main(['some-vm'], app=self.app)
41+
loop.run_until_complete(
42+
qubesadmin.tools.qvm_shutdown.main(['some-vm'], app=self.app)
43+
)
3844
self.assertAllCalled()
3945

4046
def test_001_missing_vm(self):
47+
loop = asyncio.new_event_loop()
48+
asyncio.set_event_loop(loop)
49+
4150
with self.assertRaises(SystemExit):
4251
with qubesadmin.tests.tools.StderrBuffer() as stderr:
43-
qubesadmin.tools.qvm_shutdown.main([], app=self.app)
52+
loop.run_until_complete(
53+
qubesadmin.tools.qvm_shutdown.main([], app=self.app)
54+
)
4455
self.assertIn('one of the arguments --all VMNAME is required',
4556
stderr.getvalue())
4657
self.assertAllCalled()
4758

4859
def test_002_invalid_vm(self):
60+
loop = asyncio.new_event_loop()
61+
asyncio.set_event_loop(loop)
62+
4963
self.app.expected_calls[
5064
('dom0', 'admin.vm.List', None, None)] = \
5165
b'0\x00some-vm class=AppVM state=Running\n'
5266
with self.assertRaises(SystemExit):
5367
with qubesadmin.tests.tools.StderrBuffer() as stderr:
54-
qubesadmin.tools.qvm_shutdown.main(['no-such-vm'], app=self.app)
68+
loop.run_until_complete(
69+
qubesadmin.tools.qvm_shutdown.main(['no-such-vm'], app=self.app)
70+
)
5571
self.assertIn('no such domain', stderr.getvalue())
5672
self.assertAllCalled()
5773

5874
def test_003_not_running(self):
75+
loop = asyncio.new_event_loop()
76+
asyncio.set_event_loop(loop)
77+
5978
# TODO: some option to ignore this error?
6079
self.app.expected_calls[
6180
('some-vm', 'admin.vm.Shutdown', None, None)] = \
@@ -64,10 +83,15 @@ def test_003_not_running(self):
6483
self.app.expected_calls[
6584
('dom0', 'admin.vm.List', None, None)] = \
6685
b'0\x00some-vm class=AppVM state=Halted\n'
67-
qubesadmin.tools.qvm_shutdown.main(['some-vm'], app=self.app)
86+
loop.run_until_complete(
87+
qubesadmin.tools.qvm_shutdown.main(['some-vm'], app=self.app)
88+
)
6889
self.assertAllCalled()
6990

7091
def test_004_multiple_vms(self):
92+
loop = asyncio.new_event_loop()
93+
asyncio.set_event_loop(loop)
94+
7195
self.app.expected_calls[
7296
('some-vm', 'admin.vm.Shutdown', None, None)] = \
7397
b'0\x00'
@@ -78,29 +102,34 @@ def test_004_multiple_vms(self):
78102
('dom0', 'admin.vm.List', None, None)] = \
79103
b'0\x00some-vm class=AppVM state=Running\n' \
80104
b'other-vm class=AppVM state=Running\n'
81-
qubesadmin.tools.qvm_shutdown.main(['some-vm', 'other-vm'],
105+
loop.run_until_complete(
106+
qubesadmin.tools.qvm_shutdown.main(['some-vm', 'other-vm'],
82107
app=self.app)
108+
)
83109
self.assertAllCalled()
84110

85111
def test_010_wait(self):
86-
'''test --wait option'''
87112
loop = asyncio.new_event_loop()
88113
asyncio.set_event_loop(loop)
89114

115+
'''test --wait option'''
90116
self.app.expected_calls[
91117
('some-vm', 'admin.vm.Shutdown', 'wait', None)] = \
92118
b'0\x00'
93119
self.app.expected_calls[
94120
('dom0', 'admin.vm.List', None, None)] = \
95121
b'0\x00some-vm class=AppVM state=Running\n'
96-
qubesadmin.tools.qvm_shutdown.main(['--wait', 'some-vm'], app=self.app)
122+
loop.run_until_complete(
123+
qubesadmin.tools.qvm_shutdown.main(['--wait', 'some-vm'],
124+
app=self.app)
125+
)
97126
self.assertAllCalled()
98127

99128
def test_012_wait_all(self):
100-
'''test --wait option, with multiple VMs'''
101129
loop = asyncio.new_event_loop()
102130
asyncio.set_event_loop(loop)
103131

132+
'''test --wait option, with multiple VMs'''
104133
self.app.expected_calls[
105134
('some-vm', 'admin.vm.Shutdown', 'force+wait', None)] = \
106135
b'0\x00'
@@ -116,14 +145,16 @@ def test_012_wait_all(self):
116145
b'sys-net class=AppVM state=Running\n' \
117146
b'some-vm class=AppVM state=Running\n' \
118147
b'other-vm class=AppVM state=Running\n'
119-
qubesadmin.tools.qvm_shutdown.main(['--wait', '--all'], app=self.app)
148+
loop.run_until_complete(
149+
qubesadmin.tools.qvm_shutdown.main(['--wait', '--all'], app=self.app)
150+
)
120151
self.assertAllCalled()
121152

122153
def test_015_wait_all_kill_timeout(self):
123-
'''test --wait option, with multiple VMs and killing on timeout'''
124154
loop = asyncio.new_event_loop()
125155
asyncio.set_event_loop(loop)
126156

157+
'''test --wait option, with multiple VMs and killing on timeout'''
127158
self.app.expected_calls[
128159
('some-vm', 'admin.vm.Shutdown', 'force+wait', None)] = \
129160
b'2\x00QubesVMShutdownTimeoutError\x00\x00Shutdown timed out\x00'
@@ -145,11 +176,16 @@ def test_015_wait_all_kill_timeout(self):
145176
b'sys-net class=AppVM state=Running\n' \
146177
b'some-vm class=AppVM state=Running\n' \
147178
b'other-vm class=AppVM state=Running\n'
148-
qubesadmin.tools.qvm_shutdown.main(
149-
['--wait', '--all', '--timeout=1'], app=self.app)
179+
loop.run_until_complete(
180+
qubesadmin.tools.qvm_shutdown.main(
181+
['--wait', '--all', '--timeout=1'], app=self.app)
182+
)
150183
self.assertAllCalled()
151184

152185
def test_016_all_exclude_noforce(self):
186+
loop = asyncio.new_event_loop()
187+
asyncio.set_event_loop(loop)
188+
153189
'''test --all --exclude does NOT imply --force'''
154190
self.app.expected_calls[
155191
('some-vm', 'admin.vm.Shutdown', None, None)] = \
@@ -159,11 +195,16 @@ def test_016_all_exclude_noforce(self):
159195
b'0\x00' \
160196
b'some-vm class=AppVM state=Running\n' \
161197
b'other-vm class=AppVM state=Running\n'
162-
qubesadmin.tools.qvm_shutdown.main(['--all', '--exclude', 'other-vm'],
163-
app=self.app)
198+
loop.run_until_complete(
199+
qubesadmin.tools.qvm_shutdown.main(
200+
['--all', '--exclude', 'other-vm'], app=self.app)
201+
)
164202
self.assertAllCalled()
165203

166204
def test_017_all_exclude_force_explicit(self):
205+
loop = asyncio.new_event_loop()
206+
asyncio.set_event_loop(loop)
207+
167208
'''test --all --exclude --force DOES imply --force'''
168209
self.app.expected_calls[
169210
('some-vm', 'admin.vm.Shutdown', 'force', None)] = \
@@ -173,36 +214,47 @@ def test_017_all_exclude_force_explicit(self):
173214
b'0\x00' \
174215
b'some-vm class=AppVM state=Running\n' \
175216
b'other-vm class=AppVM state=Running\n'
176-
qubesadmin.tools.qvm_shutdown.main(['--all', '--exclude', 'other-vm',
177-
'--force'],
178-
app=self.app)
217+
loop.run_until_complete(
218+
qubesadmin.tools.qvm_shutdown.main(
219+
['--all', '--exclude', 'other-vm', '--force'], app=self.app)
220+
)
179221
self.assertAllCalled()
180222

181223
def test_005_force(self):
224+
loop = asyncio.new_event_loop()
225+
asyncio.set_event_loop(loop)
226+
182227
'''test --force sends force flag to shutdown call'''
183228
self.app.expected_calls[
184229
('dom0', 'admin.vm.List', None, None)] = \
185230
b'0\x00some-vm class=AppVM state=Running\n'
186231
self.app.expected_calls[
187232
('some-vm', 'admin.vm.Shutdown', 'force', None)] = b'0\x00'
188-
qubesadmin.tools.qvm_shutdown.main(
189-
['--force', 'some-vm'], app=self.app)
233+
loop.run_until_complete(
234+
qubesadmin.tools.qvm_shutdown.main(
235+
['--force', 'some-vm'], app=self.app)
236+
)
190237
self.assertAllCalled()
191238

192239
def test_006_dry_run(self):
240+
loop = asyncio.new_event_loop()
241+
asyncio.set_event_loop(loop)
242+
193243
'''test --dry-run skips shutdown calls'''
194244
self.app.expected_calls[
195245
('dom0', 'admin.vm.List', None, None)] = \
196246
b'0\x00some-vm class=AppVM state=Running\n'
197-
qubesadmin.tools.qvm_shutdown.main(
198-
['--dry-run', 'some-vm'], app=self.app)
247+
loop.run_until_complete(
248+
qubesadmin.tools.qvm_shutdown.main(
249+
['--dry-run', 'some-vm'], app=self.app)
250+
)
199251
self.assertAllCalled()
200252

201253
def test_011_wait_retry(self):
202-
'''test --wait retries VMs whose shutdown request failed'''
203254
loop = asyncio.new_event_loop()
204255
asyncio.set_event_loop(loop)
205256

257+
'''test --wait retries VMs whose shutdown request failed'''
206258
self.app.expected_calls[
207259
('dom0', 'admin.vm.List', None, None)] = \
208260
b'0\x00' \
@@ -217,11 +269,16 @@ def test_011_wait_retry(self):
217269
b'2\x00QubesVMShutdownTimeoutError\x00\x00Shutdown timed out\x00',
218270
b'0\x00',
219271
]
220-
qubesadmin.tools.qvm_shutdown.main(
221-
['--wait', 'some-vm', 'other-vm'], app=self.app)
272+
loop.run_until_complete(
273+
qubesadmin.tools.qvm_shutdown.main(
274+
['--wait', 'some-vm', 'other-vm'], app=self.app)
275+
)
222276
self.assertAllCalled()
223277

224278
def test_013_wait_all_shutdown_fail(self):
279+
loop = asyncio.new_event_loop()
280+
asyncio.set_event_loop(loop)
281+
225282
'''test --wait exits with error when all shutdown requests fail'''
226283
self.app.expected_calls[
227284
('dom0', 'admin.vm.List', None, None)] = \
@@ -230,15 +287,17 @@ def test_013_wait_all_shutdown_fail(self):
230287
('some-vm', 'admin.vm.Shutdown', 'wait', None)] = \
231288
b'2\x00QubesException\x00\x00Shutdown refused\x00'
232289
with self.assertRaises(SystemExit):
233-
qubesadmin.tools.qvm_shutdown.main(
234-
['--wait', 'some-vm'], app=self.app)
290+
loop.run_until_complete(
291+
qubesadmin.tools.qvm_shutdown.main(
292+
['--wait', 'some-vm'], app=self.app)
293+
)
235294
self.assertAllCalled()
236295

237296
def test_016_wait_kill_exception(self):
238-
'''test --wait timeout where kill raises QubesException'''
239297
loop = asyncio.new_event_loop()
240298
asyncio.set_event_loop(loop)
241299

300+
'''test --wait timeout where kill raises QubesException'''
242301
self.app.expected_calls[
243302
('dom0', 'admin.vm.List', None, None)] = \
244303
b'0\x00some-vm class=AppVM state=Running\n'
@@ -249,6 +308,8 @@ def test_016_wait_kill_exception(self):
249308
('some-vm', 'admin.vm.Kill', None, None)] = \
250309
b'2\x00QubesException\x00\x00Kill failed\x00'
251310
with self.assertRaises(SystemExit):
252-
qubesadmin.tools.qvm_shutdown.main(
253-
['--wait', '--timeout=1', 'some-vm'], app=self.app)
311+
loop.run_until_complete(
312+
qubesadmin.tools.qvm_shutdown.main(
313+
['--wait', '--timeout=1', 'some-vm'], app=self.app)
314+
)
254315
self.assertAllCalled()

qubesadmin/tests/tools/qvm_template_postprocess.py

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -402,17 +402,6 @@ def test_020_post_install(self, mock_import_root_img,
402402
self.app.expected_calls[
403403
('test-vm', 'admin.vm.Shutdown', None, None)] = b'0\0'
404404

405-
if qubesadmin.tools.qvm_template_postprocess.have_events:
406-
patch_domain_shutdown = mock.patch(
407-
'qubesadmin.events.utils.wait_for_domain_shutdown')
408-
self.addCleanup(patch_domain_shutdown.stop)
409-
mock_domain_shutdown = patch_domain_shutdown.start()
410-
mock_domain_shutdown.side_effect = self.wait_for_shutdown
411-
else:
412-
self.app.expected_calls[
413-
('test-vm', 'admin.vm.List', None, None)] = \
414-
b'0\0test-vm class=TemplateVM state=Halted\n'
415-
416405
asyncio.set_event_loop(asyncio.new_event_loop())
417406
ret = qubesadmin.tools.qvm_template_postprocess.main([
418407
'--really', 'post-install', 'test-vm', self.source_dir.name],
@@ -424,9 +413,6 @@ def test_020_post_install(self, mock_import_root_img,
424413
'test-vm'], self.source_dir.name)
425414
mock_import_appmenus.assert_called_once_with(self.app.domains[
426415
'test-vm'], self.source_dir.name, skip_generate=True)
427-
if qubesadmin.tools.qvm_template_postprocess.have_events:
428-
mock_domain_shutdown.assert_called_once_with([self.app.domains[
429-
'test-vm']])
430416
self.assertEqual(self.app.service_calls, [
431417
('test-vm', 'qubes.PostInstall', {
432418
'stdin': subprocess.PIPE,
@@ -460,17 +446,6 @@ def test_021_post_install_reinstall(self, mock_reset_private_img,
460446
self.app.expected_calls[
461447
('test-vm', 'admin.vm.Shutdown', None, None)] = b'0\0'
462448

463-
if qubesadmin.tools.qvm_template_postprocess.have_events:
464-
patch_domain_shutdown = mock.patch(
465-
'qubesadmin.events.utils.wait_for_domain_shutdown')
466-
self.addCleanup(patch_domain_shutdown.stop)
467-
mock_domain_shutdown = patch_domain_shutdown.start()
468-
mock_domain_shutdown.side_effect = self.wait_for_shutdown
469-
else:
470-
self.app.expected_calls[
471-
('test-vm', 'admin.vm.List', None, None)] = \
472-
b'0\0test-vm class=TemplateVM state=Halted\n'
473-
474449
asyncio.set_event_loop(asyncio.new_event_loop())
475450
ret = qubesadmin.tools.qvm_template_postprocess.main([
476451
'--really', 'post-install', 'test-vm', self.source_dir.name],
@@ -483,9 +458,6 @@ def test_021_post_install_reinstall(self, mock_reset_private_img,
483458
'test-vm'])
484459
mock_import_appmenus.assert_called_once_with(self.app.domains[
485460
'test-vm'], self.source_dir.name, skip_generate=True)
486-
if qubesadmin.tools.qvm_template_postprocess.have_events:
487-
mock_domain_shutdown.assert_called_once_with([self.app.domains[
488-
'test-vm']])
489461
self.assertEqual(self.app.service_calls, [
490462
('test-vm', 'qubes.PostInstall', {
491463
'stdin': subprocess.PIPE,
@@ -508,13 +480,6 @@ def test_022_post_install_skip_start(self, mock_reset_private_img,
508480
= b'0\0'
509481
self.app.add_new_vm = mock.Mock()
510482

511-
if qubesadmin.tools.qvm_template_postprocess.have_events:
512-
patch_domain_shutdown = mock.patch(
513-
'qubesadmin.events.utils.wait_for_domain_shutdown')
514-
self.addCleanup(patch_domain_shutdown.stop)
515-
mock_domain_shutdown = patch_domain_shutdown.start()
516-
mock_domain_shutdown.side_effect = self.wait_for_shutdown
517-
518483
asyncio.set_event_loop(asyncio.new_event_loop())
519484
ret = qubesadmin.tools.qvm_template_postprocess.main([
520485
'--really', '--skip-start', 'post-install', 'test-vm',
@@ -528,8 +493,6 @@ def test_022_post_install_skip_start(self, mock_reset_private_img,
528493
'test-vm'])
529494
mock_import_appmenus.assert_called_once_with(self.app.domains[
530495
'test-vm'], self.source_dir.name, skip_generate=False)
531-
if qubesadmin.tools.qvm_template_postprocess.have_events:
532-
self.assertFalse(mock_domain_shutdown.called)
533496
self.assertEqual(self.app.service_calls, [])
534497
self.assertAllCalled()
535498

0 commit comments

Comments
 (0)