qubes/vm: New XML format loading

This commit is contained in:
Wojtek Porczyk 2014-11-18 17:35:05 +01:00
parent f3673dd34c
commit 87ae0112eb
2 changed files with 139 additions and 5 deletions

View File

@ -51,6 +51,7 @@ HVMs:
'''
import ast
import collections
import functools
import sys
@ -115,6 +116,16 @@ class VMPlugin(qubes.plugins.Plugin):
cls.__hooks__ = collections.defaultdict(list)
class BaseVM(object):
'''Base class for all VMs
:param xml: xml node from which to deserialise
:type xml: :py:class:`lxml.etree._Element` or :py:obj:`None`
This class is responsible for serialising and deserialising machines and
provides basic framework. It contains no management logic. For that, see
:py:class:`qubes.vm.qubesvm.QubesVM`.
'''
__metaclass__ = VMPlugin
def get_props_list(self):
@ -125,10 +136,45 @@ class BaseVM(object):
if isinstance(prop, property))
return sorted(props, key=lambda prop: (prop.order, prop.__name__))
def __init__(self, D):
for prop in self.get_props_list():
if prop.__name__ in D:
setattr(self, prop.__name__, D[prop.__name__])
def __init__(self, xml):
self._xml = xml
self.services = {}
self.devices = collections.defaultdict(list)
self.tags = {}
if self._xml is None:
return
# properties
all_names = set(prop.__name__ for prop in self.get_props_list())
for node in self._xml.xpath('.//property'):
name = node.get('name')
value = node.get('ref') or node.text
if not name in all_names:
raise AttributeError(
'No property {!r} found in {!r}'.format(
name, self.__class__))
setattr(self, name, value)
# tags
for node in self._xml.xpath('.//tag'):
self.tags[node.get('name')] = node.text
# services
for node in self._xml.xpath('.//service'):
self.services[node.text] = bool(ast.literal_eval(node.get('enabled', 'True')))
# devices (pci, usb, ...)
for parent in self._xml.xpath('.//devices'):
devclass = parent.get('class')
for node in parent.xpath('./device'):
self.devices[devclass].append(node.text)
# firewall
#TODO
def __repr__(self):
return '<{} object at {:#x} {}>'.format(
@ -150,7 +196,7 @@ class BaseVM(object):
cls.__hooks__[event].append(f)
def fire_hooks(self, event, *args, **kwargs):
'''Fire hooks associated with an event.
'''Fire hooks associated with an event
:param str event: event type

88
tests/vm.py Normal file
View File

@ -0,0 +1,88 @@
#!/usr/bin/python2 -O
import sys
import unittest
import lxml.etree
sys.path.insert(0, '../')
import qubes.vm
class TestVM(qubes.vm.BaseVM):
testprop = qubes.vm.property('testprop')
testlabel = qubes.vm.property('testlabel')
defaultprop = qubes.vm.property('defaultprop', default='defaultvalue')
class TC_BaseVM(unittest.TestCase):
def setUp(self):
self.xml = lxml.etree.XML('''
<qubes version="3"> <!-- xmlns="https://qubes-os.org/QubesXML/1" -->
<labels>
<label id="label-1" color="#cc0000">red</label>
</labels>
<domains>
<domain id="domain-1" class="TestVM">
<properties>
<property name="testprop">testvalue</property>
<property name="testlabel" ref="label-1" />
</properties>
<tags>
<tag name="testtag">tagvalue</tag>
</tags>
<services>
<service>testservice</service>
<service enabled="True">enabledservice</service>
<service enabled="False">disabledservice</service>
</services>
<devices class="pci">
<device>00:11.22</device>
</devices>
<devices class="usb" />
<devices class="audio-in" />
<devices class="firewire" />
<devices class="i2c" />
<devices class="isa" />
</domain>
</domains>
</qubes>
''')
def test_000_BaseVM_load(self):
node = self.xml.xpath('//domain')[0]
vm = TestVM(node)
self.assertEqual(vm.testprop, 'testvalue')
self.assertEqual(vm.testlabel, 'label-1')
self.assertEqual(vm.defaultprop, 'defaultvalue')
self.assertEqual(vm.tags, {'testtag': 'tagvalue'})
self.assertEqual(vm.devices, {'pci': ['00:11.22']})
self.assertEqual(vm.services, {
'testservice': True,
'enabledservice': True,
'disabledservice': False,
})
def test_001_BaseVM_nxproperty(self):
xml = lxml.etree.XML('''
<qubes version="3">
<domains>
<domain id="domain-1" class="TestVM">
<properties>
<property name="nxproperty">nxvalue</property>
</properties>
</domain>
</domains>
</qubes>
''')
node = xml.xpath('//domain')[0]
def f():
vm = TestVM(node)
self.assertRaises(AttributeError, f)