qubes/vm: New XML format loading
This commit is contained in:
parent
f3673dd34c
commit
87ae0112eb
@ -51,6 +51,7 @@ HVMs:
|
|||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import ast
|
||||||
import collections
|
import collections
|
||||||
import functools
|
import functools
|
||||||
import sys
|
import sys
|
||||||
@ -115,6 +116,16 @@ class VMPlugin(qubes.plugins.Plugin):
|
|||||||
cls.__hooks__ = collections.defaultdict(list)
|
cls.__hooks__ = collections.defaultdict(list)
|
||||||
|
|
||||||
class BaseVM(object):
|
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
|
__metaclass__ = VMPlugin
|
||||||
|
|
||||||
def get_props_list(self):
|
def get_props_list(self):
|
||||||
@ -125,10 +136,45 @@ class BaseVM(object):
|
|||||||
if isinstance(prop, property))
|
if isinstance(prop, property))
|
||||||
return sorted(props, key=lambda prop: (prop.order, prop.__name__))
|
return sorted(props, key=lambda prop: (prop.order, prop.__name__))
|
||||||
|
|
||||||
def __init__(self, D):
|
def __init__(self, xml):
|
||||||
for prop in self.get_props_list():
|
self._xml = xml
|
||||||
if prop.__name__ in D:
|
|
||||||
setattr(self, prop.__name__, D[prop.__name__])
|
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):
|
def __repr__(self):
|
||||||
return '<{} object at {:#x} {}>'.format(
|
return '<{} object at {:#x} {}>'.format(
|
||||||
@ -150,7 +196,7 @@ class BaseVM(object):
|
|||||||
cls.__hooks__[event].append(f)
|
cls.__hooks__[event].append(f)
|
||||||
|
|
||||||
def fire_hooks(self, event, *args, **kwargs):
|
def fire_hooks(self, event, *args, **kwargs):
|
||||||
'''Fire hooks associated with an event.
|
'''Fire hooks associated with an event
|
||||||
|
|
||||||
:param str event: event type
|
:param str event: event type
|
||||||
|
|
||||||
|
88
tests/vm.py
Normal file
88
tests/vm.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user