features: add check_with_netvm, similar to check_with_template

Allow using default feature value from netvm, not template. This makes
sense for network-related features like using tor, supporting ipv6 etc.

Similarly to check_with_template, expose it also on Admin API.
This commit is contained in:
Marek Marczykowski-Górecki 2017-12-01 03:19:48 +01:00
parent f223594f92
commit bf59b00f1d
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
4 changed files with 57 additions and 0 deletions

View File

@ -69,6 +69,7 @@ ADMIN_API_METHODS_SIMPLE = \
admin.vm.device.mic.Detach \ admin.vm.device.mic.Detach \
admin.vm.device.mic.List \ admin.vm.device.mic.List \
admin.vm.device.mic.Set.persistent \ admin.vm.device.mic.Set.persistent \
admin.vm.feature.CheckWithNetvm \
admin.vm.feature.CheckWithTemplate \ admin.vm.feature.CheckWithTemplate \
admin.vm.feature.Get \ admin.vm.feature.Get \
admin.vm.feature.List \ admin.vm.feature.List \

View File

@ -883,6 +883,19 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
raise qubes.exc.QubesFeatureNotFoundError(self.dest, self.arg) raise qubes.exc.QubesFeatureNotFoundError(self.dest, self.arg)
return value return value
@qubes.api.method('admin.vm.feature.CheckWithNetvm', no_payload=True,
scope='local', read=True)
@asyncio.coroutine
def vm_feature_checkwithnetvm(self):
# validation of self.arg done by qrexec-policy is enough
self.fire_event_for_permission()
try:
value = self.dest.features.check_with_netvm(self.arg)
except KeyError:
raise qubes.exc.QubesFeatureNotFoundError(self.dest, self.arg)
return value
@qubes.api.method('admin.vm.feature.Remove', no_payload=True, @qubes.api.method('admin.vm.feature.Remove', no_payload=True,
scope='local', write=True) scope='local', write=True)
@asyncio.coroutine @asyncio.coroutine

View File

@ -90,6 +90,10 @@ class AdminAPITestCase(qubes.tests.QubesTestCase):
self.base_dir_patch.stop() self.base_dir_patch.stop()
if os.path.exists(self.test_base_dir): if os.path.exists(self.test_base_dir):
shutil.rmtree(self.test_base_dir) shutil.rmtree(self.test_base_dir)
try:
del self.netvm
except AttributeError:
pass
del self.vm del self.vm
del self.template del self.template
self.app.close() self.app.close()
@ -1047,6 +1051,31 @@ class TC_00_VMs(AdminAPITestCase):
b'test-vm1', b'test-feature') b'test-vm1', b'test-feature')
self.assertFalse(self.app.save.called) self.assertFalse(self.app.save.called)
def test_315_feature_checkwithnetvm(self):
self.vm.features['test-feature'] = 'some-value'
value = self.call_mgmt_func(b'admin.vm.feature.CheckWithNetvm',
b'test-vm1', b'test-feature')
self.assertEqual(value, 'some-value')
self.assertFalse(self.app.save.called)
def test_316_feature_checkwithnetvm_netvm(self):
self.netvm = self.app.add_new_vm('AppVM', label='red',
name='test-netvm1',
template='test-template',
provides_network=True)
self.vm.netvm = self.netvm
self.netvm.features['test-feature'] = 'some-value'
value = self.call_mgmt_func(b'admin.vm.feature.CheckWithNetvm',
b'test-vm1', b'test-feature')
self.assertEqual(value, 'some-value')
self.assertFalse(self.app.save.called)
def test_317_feature_checkwithnetvm_none(self):
with self.assertRaises(qubes.exc.QubesFeatureNotFoundError):
self.call_mgmt_func(b'admin.vm.feature.CheckWithNetvm',
b'test-vm1', b'test-feature')
self.assertFalse(self.app.save.called)
def test_320_feature_set(self): def test_320_feature_set(self):
value = self.call_mgmt_func(b'admin.vm.feature.Set', value = self.call_mgmt_func(b'admin.vm.feature.Set',
b'test-vm1', b'test-feature', b'some-value') b'test-vm1', b'test-feature', b'some-value')

View File

@ -186,6 +186,20 @@ class Features(dict):
return default return default
def check_with_netvm(self, feature, default=_NO_DEFAULT):
''' Check if the vm's netvm has the specified feature. '''
if feature in self:
return self[feature]
if hasattr(self.vm, 'netvm') and self.vm.netvm is not None:
return self.vm.netvm.features.check_with_netvm(feature,
default)
if default is self._NO_DEFAULT:
raise KeyError(feature)
return default
class Tags(set): class Tags(set):
'''Manager of the tags. '''Manager of the tags.