Browse Source

devices: adjust XML serialization of device options

Use '<option name="option_name">option_value</option>' instead of
'<options option_name="option_value"/>'. It's more consistent with the
rest of qubes.xml - have one thing per element.

Also, add options deserialization test.
Marek Marczykowski-Górecki 6 years ago
parent
commit
f93583e2be
4 changed files with 31 additions and 13 deletions
  1. 3 1
      doc/example.xml
  2. 8 1
      qubes/tests/vm/init.py
  3. 7 6
      qubes/vm/__init__.py
  4. 13 5
      relaxng/qubes.rng

+ 3 - 1
doc/example.xml

@@ -22,7 +22,9 @@
             </features>
 
             <devices class="pci">
-                <device backend-domain="dom0" id="01_23.45"/>
+                <device backend-domain="dom0" id="01_23.45">
+                  <option name="no-strict-reset">True</option>
+                </device>
             </devices>
         </domain>
 

+ 8 - 1
qubes/tests/vm/init.py

@@ -76,7 +76,9 @@ class TC_10_BaseVM(qubes.tests.QubesTestCase):
             </features>
 
             <devices class="pci">
-                <device backend-domain="domain1" id="00_11.22"/>
+                <device backend-domain="domain1" id="00_11.22">
+                  <option name="no-strict-reset">True</option>
+                </device>
             </devices>
 
             <devices class="usb" />
@@ -111,6 +113,11 @@ class TC_10_BaseVM(qubes.tests.QubesTestCase):
         self.assertCountEqual(list(vm.devices['pci'].persistent()),
             [qubes.ext.pci.PCIDevice(vm, '00_11.22')])
 
+        assignments = list(vm.devices['pci'].assignments())
+        self.assertEqual(len(assignments), 1)
+        self.assertEqual(assignments[0].options, {'no-strict-reset': 'True'})
+        self.assertEqual(assignments[0].persistent, True)
+
         self.assertXMLIsValid(vm.__xml__(), 'domain.rng')
 
     def test_001_nxproperty(self):

+ 7 - 6
qubes/vm/__init__.py

@@ -289,8 +289,8 @@ class BaseVM(qubes.PropertyHolder):
             devclass = parent.get('class')
             for node in parent.xpath('./device'):
                 options = {}
-                if node.get('options'):
-                    options = node.get('options').attribs(),
+                for option in node.xpath('./option'):
+                    options[option.get('name')] = option.text
 
                 device_assignment = qubes.devices.DeviceAssignment(
                     self.app.domains[node.get('backend-domain')],
@@ -331,10 +331,11 @@ class BaseVM(qubes.PropertyHolder):
                 node = lxml.etree.Element('device')
                 node.set('backend-domain', device.backend_domain.name)
                 node.set('id', device.ident)
-                options_node = lxml.etree.Element('options')
-                for key, val in device.options:
-                    options_node.set(key, val)
-                node.append(options_node)
+                for key, val in device.options.items():
+                    option_node = lxml.etree.Element('option')
+                    option_node.set('name', key)
+                    option_node.text = val
+                    node.append(option_node)
                 devices.append(node)
             element.append(devices)
 

+ 13 - 5
relaxng/qubes.rng

@@ -224,15 +224,23 @@ the parser will complain about missing combine= attribute on the second <start>.
                                     <param name="pattern">[0-9a-f]{2}_[0-9a-f]{2}.[0-9a-f]{2}</param>
                                 </data>
                             </attribute>
-                              <optional>
-                                <element name="options">
-                                    <doc:description>
-                                      Options
+                            <zeroOrMore>
+                              <element name="option">
+                                <doc:description>
+                                    Options
+                                </doc:description>
+                                <attribute name="name">
+                                  <doc:description>
+                                    Option name.
                                   </doc:description>
+                                  <data type="string">
+                                    <param name="pattern">[a-z0-9_-]+</param>
+                                  </data>
+                                </attribute>
                                 <data type="string">
                                 </data>
                               </element>
-                            </optional>
+                            </zeroOrMore>
                         </element>
                     </oneOrMore>
                 </element>