Merge remote-tracking branch 'origin/pr/359'

* origin/pr/359:
  Add tests for vm.volume.Clear.
  Use self.dest.storage.import* wrappers instead.
  Add admin.vm.volume.Clear call (QubesOS/qubes-issues#5946)
This commit is contained in:
Marek Marczykowski-Górecki 2020-07-16 03:44:46 +02:00
commit 784878f1f7
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 66 additions and 0 deletions

View File

@ -27,6 +27,7 @@ import itertools
import os
import string
import subprocess
import pathlib
import libvirt
import lxml.etree
@ -486,6 +487,32 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
finally: # even if calling qubes.ResizeDisk inside the VM failed
self.app.save()
@qubes.api.method('admin.vm.volume.Clear', no_payload=True,
scope='local', write=True)
@asyncio.coroutine
def vm_volume_clear(self):
self.enforce(self.arg in self.dest.volumes.keys())
self.fire_event_for_permission()
volume = self.dest.volumes[self.arg]
size = volume.size
# Clear the volume by importing empty data into it
path = yield from self.dest.storage.import_data(self.arg, size)
self.dest.fire_event('domain-volume-import-begin',
volume=self.arg, size=size)
pathlib.Path(path).touch()
try:
yield from self.dest.storage.import_data_end(self.arg, True)
except:
self.dest.fire_event('domain-volume-import-end',
volume=self.arg, success=False)
raise
self.dest.fire_event('domain-volume-import-end',
volume=self.arg, success=True)
self.app.save()
@qubes.api.method('admin.vm.volume.Set.revisions_to_keep',
scope='local', write=True)
@asyncio.coroutine

View File

@ -2757,6 +2757,44 @@ netvm default=True type=vm \n'''
value = self.call_mgmt_func(b'admin.pool.volume.List', b'dom0', b'pool1')
self.assertEqual(value, 'vol1\nvol2\n')
def test_710_vm_volume_clear(self):
with tempfile.TemporaryDirectory() as tmpdir:
tmpfile = os.path.join(tmpdir, 'testfile')
@asyncio.coroutine
def coroutine_mock(*args, **kwargs):
return tmpfile
self.vm.volumes = unittest.mock.MagicMock()
volumes_conf = {
'keys.return_value': ['root', 'private', 'volatile', 'kernel'],
'__getitem__.return_value.size': 0xdeadbeef
}
self.vm.volumes.configure_mock(**volumes_conf)
self.vm.storage = unittest.mock.Mock()
storage_conf = {
'import_data.side_effect': coroutine_mock,
'import_data_end.side_effect': self.dummy_coro
}
self.vm.storage.configure_mock(**storage_conf)
self.app.domains['test-vm1'].fire_event = self.emitter.fire_event
value = self.call_mgmt_func(b'admin.vm.volume.Clear',
b'test-vm1', b'private')
self.assertIsNone(value)
self.assertTrue(os.path.exists(tmpfile))
self.assertEqual(self.vm.volumes.mock_calls, [
unittest.mock.call.keys(),
unittest.mock.call.__getattr__('__getitem__')('private')])
self.assertEqual(self.vm.storage.mock_calls, [
unittest.mock.call.import_data('private', 0xdeadbeef),
unittest.mock.call.import_data_end('private', True)])
self.assertEventFired(
self.emitter, 'admin-permission:admin.vm.volume.Clear')
self.assertEventFired(
self.emitter, 'domain-volume-import-begin')
self.assertEventFired(
self.emitter, 'domain-volume-import-end')
def test_800_current_state_default(self):
value = self.call_mgmt_func(b'admin.vm.CurrentState', b'test-vm1')
self.assertEqual(
@ -3057,6 +3095,7 @@ netvm default=True type=vm \n'''
b'admin.vm.volume.Info',
b'admin.vm.volume.Revert',
b'admin.vm.volume.Resize',
b'admin.vm.volume.Clear',
b'admin.vm.Start',
b'admin.vm.Shutdown',
b'admin.vm.Pause',