api/admin: fix admin.vm.volume.Info when is_outdated() isn't supported

is_outdated() may be not supported by given volume pool driver. In that
case skip is_outdated information, instead of crashing the call.

Fixes QubesOS/qubes-issues#3767
This commit is contained in:
Marek Marczykowski-Górecki 2018-04-08 23:25:34 +02:00
parent 93b2424867
commit b168c4a6d7
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 35 additions and 5 deletions

View File

@ -336,7 +336,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
# properties defined in API
volume_properties = [
'pool', 'vid', 'size', 'usage', 'rw', 'source',
'save_on_stop', 'snap_on_start', 'revisions_to_keep', 'is_outdated']
'save_on_stop', 'snap_on_start', 'revisions_to_keep']
def _serialize(value):
if callable(value):
@ -344,8 +344,13 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
if value is None:
value = ''
return str(value)
return ''.join('{}={}\n'.format(key, _serialize(getattr(volume, key)))
info = ''.join('{}={}\n'.format(key, _serialize(getattr(volume, key)))
for key in volume_properties)
try:
info += '\nis_outdated={}'.format(volume.is_outdated())
except NotImplementedError:
pass
return info
@qubes.api.method('admin.vm.volume.ListSnapshots', no_payload=True,
scope='local', read=True)

View File

@ -40,7 +40,7 @@ import qubes.storage
# properties defined in API
volume_properties = [
'pool', 'vid', 'size', 'usage', 'rw', 'source',
'save_on_stop', 'snap_on_start', 'revisions_to_keep', 'is_outdated']
'save_on_stop', 'snap_on_start', 'revisions_to_keep']
class AdminAPITestCase(qubes.tests.QubesTestCase):
@ -355,7 +355,31 @@ class TC_00_VMs(AdminAPITestCase):
}
for prop in volume_properties:
volumes_conf[
'__getitem__.return_value.{}'.format(prop)] = prop +'-value'
'__getitem__.return_value.{}'.format(prop)] = prop + '-value'
volumes_conf[
'__getitem__.return_value.is_outdated.return_value'] = False
self.vm.volumes.configure_mock(**volumes_conf)
value = self.call_mgmt_func(b'admin.vm.volume.Info', b'test-vm1',
b'private')
self.assertEqual(value,
''.join('{p}={p}-value\n'.format(p=p) for p in volume_properties) +
'\nis_outdated=False')
self.assertEqual(self.vm.volumes.mock_calls,
[unittest.mock.call.keys(),
unittest.mock.call.__getattr__('__getitem__')('private'),
unittest.mock.call.__getattr__('__getitem__')().is_outdated()])
def test_081_vm_volume_info_unsupported_is_outdated(self):
self.vm.volumes = unittest.mock.MagicMock()
volumes_conf = {
'keys.return_value': ['root', 'private', 'volatile', 'kernel']
}
for prop in volume_properties:
volumes_conf[
'__getitem__.return_value.{}'.format(prop)] = prop + '-value'
volumes_conf[
'__getitem__.return_value.is_outdated.side_effect'] = \
NotImplementedError
self.vm.volumes.configure_mock(**volumes_conf)
value = self.call_mgmt_func(b'admin.vm.volume.Info', b'test-vm1',
b'private')
@ -363,7 +387,8 @@ class TC_00_VMs(AdminAPITestCase):
''.join('{p}={p}-value\n'.format(p=p) for p in volume_properties))
self.assertEqual(self.vm.volumes.mock_calls,
[unittest.mock.call.keys(),
unittest.mock.call.__getattr__('__getitem__')('private')])
unittest.mock.call.__getattr__('__getitem__')('private'),
unittest.mock.call.__getattr__('__getitem__')().is_outdated()])
def test_080_vm_volume_info_invalid_volume(self):
self.vm.volumes = unittest.mock.MagicMock()