<div dir="ltr"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Wed, Mar 15, 2017 at 2:28 PM Francesco Romani &lt;<a href="mailto:fromani@redhat.com" class="gmail_msg" target="_blank">fromani@redhat.com</a>&gt; wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi everyone,<br class="gmail_msg">
<br class="gmail_msg">
This is both a report of the current state of my Vdsm patches for Engine<br class="gmail_msg">
XML support, and a proposal to how move forward and solve<br class="gmail_msg">
the current open issues.<br class="gmail_msg">
<br class="gmail_msg">
TL;DR:<br class="gmail_msg">
1. we can and IMO should reuse the current JSON schema to describe the<br class="gmail_msg">
structure (layout) and the types of the metadata section.<br class="gmail_msg">
2. we don&#39;t need a priori validation of stuff in the metadata section.<br class="gmail_msg">
We will just raise in the creation flow if data is missing, or wrong,<br class="gmail_msg">
according to our schema.<br class="gmail_msg">
2. we will add *few* items to the metadata section, only thing we can&#39;t<br class="gmail_msg">
express clearly-or at all in the libvirt XML. Redundancy and verbosiness<br class="gmail_msg">
will be thus kept at bay<br class="gmail_msg">
3. I believe [3] is the best tool to do (de)serialize data to the<br class="gmail_msg">
metadata section. Existing tools fits poorly in our very specific use case<br class="gmail_msg">
<br class="gmail_msg">
Examples below<br class="gmail_msg">
<br class="gmail_msg">
+++<br class="gmail_msg">
<br class="gmail_msg">
Long(er) discussion:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
I have working code[1][2] to encode any custom, picklable, python<br class="gmail_msg">
object in the metadata section.<br class="gmail_msg">
<br class="gmail_msg">
We should decide which module will do the actual python&lt;=&gt;XML<br class="gmail_msg">
transformation.<br class="gmail_msg">
Please note that this actually also influences how the data in the<br class="gmail_msg">
medata section look like, so the two things are a bit coupled.<br class="gmail_msg">
<br class="gmail_msg">
I&#39;m eager to reinvent another wheel, but after<br class="gmail_msg">
initial evaluation I honestly think that my pyxmlpickle[3] is the best<br class="gmail_msg">
tool for the job over the current alternatives: plistlib[4] and<br class="gmail_msg">
xmltodict[5].<br class="gmail_msg">
<br class="gmail_msg">
I added the initial rationale here:<br class="gmail_msg">
<a href="https://gerrit.ovirt.org/#/c/73790/4//COMMIT_MSG" rel="noreferrer" class="gmail_msg" target="_blank">https://gerrit.ovirt.org/#/c/73790/4//COMMIT_MSG</a><br class="gmail_msg">
<br class="gmail_msg">
I have completed the initial draft of patches to make it possible to<br class="gmail_msg">
initialize devices from their XML representation [6]. This is the bare<br class="gmail_msg">
minimum we need to support the Engine XML, and we *need* this anyway to<br class="gmail_msg">
unlock the cleanup we planned and I outlined in my google doc.<br class="gmail_msg">
<br class="gmail_msg">
So we are progressing, but I&#39;d like to speed up things. Those [6]<br class="gmail_msg">
patches are not yet complete, many flows are not covered or tested;  but<br class="gmail_msg">
they are good enough to demonstrate that there *are* pieces of<br class="gmail_msg">
information wen need to properly initialize the devices, but we can&#39;t<br class="gmail_msg">
easily extract from the XML.<br class="gmail_msg">
<br class="gmail_msg">
First examples that come to my mind are the storage.Drive UUIDs; there<br class="gmail_msg">
could also be some ambiguity I&#39;m investigating right now for<br class="gmail_msg">
displayIp/displayNetwork in Graphics devices. In [6] there are various<br class="gmail_msg">
TODO to mark more of those cases. Most likely, few more cases will pop<br class="gmail_msg">
out as I cover all the flows we support.<br class="gmail_msg">
<br class="gmail_msg">
Long story short: it is hard to correctly rebuild the device conf from<br class="gmail_msg">
the XML. This is why in [6] I added the &#39;meta&#39; argument to from_xml_tree<br class="gmail_msg">
classmethod in [7].<br class="gmail_msg">
<br class="gmail_msg">
&#39;meta&#39; is supposed to be the device metadata: extra data related to a<br class="gmail_msg">
device which doesn&#39;t (yet) fit in the libvirt XML representation.<br class="gmail_msg">
For example, we can store &#39;displayIp&#39; and &#39;displayNetwork&#39; here and be<br class="gmail_msg">
done with that: using both per-device metadata and the XML<br class="gmail_msg">
representation of one graphic device, we will have everything we need to<br class="gmail_msg">
properly build one graphics.Graphics device.<br class="gmail_msg">
This example may (hopefully) be bogus, but I&#39;m keeping it because it is<br class="gmail_msg">
one case easy to follow.<br class="gmail_msg">
<br class="gmail_msg">
The device metadata is going to be stored in the vm metadata for the<br class="gmail_msg">
short/mid term future. Even if the per-device metadata idea/RFE is<br class="gmail_msg">
accepted (no answer yet, but we are working on it), we will not have in<br class="gmail_msg">
7.4, and unlikely in 7.5.<br class="gmail_msg">
<br class="gmail_msg">
As it stands today, I believe there are two open questions:<br class="gmail_msg">
<br class="gmail_msg">
1. do we need a schema for the metadata section?<br class="gmail_msg">
2. how do we bind the metadata to the devices? How do we know which<br class="gmail_msg">
metadata belongs to which metadata, if we don&#39;t have aliases nor<br class="gmail_msg">
addresses to match? (e.g. very first time the VM is created!)<br class="gmail_msg">
<br class="gmail_msg">
My current stance is the following<br class="gmail_msg">
1. In general, one schema gives us two benefits: 1.a. we document how<br class="gmail_msg">
the layout of the data should be, including types; 1.b. we can validate<br class="gmail_msg">
the data we receive.<br class="gmail_msg">
So yes, we need a schema, but we don&#39;t need a *new* schema. I think we<br class="gmail_msg">
are in good enough shape with the current Vdsm schema: we can just<br class="gmail_msg">
translate the python object layout to a XML layout.<br class="gmail_msg">
<br class="gmail_msg">
One example is probably more explicative. Some actual data may look<br class="gmail_msg">
like, using my pyxmlpickle module:<br class="gmail_msg">
<br class="gmail_msg">
&lt;domain type=&#39;kvm&#39; id=&#39;5&#39;&gt;<br class="gmail_msg">
  &lt;name&gt;a0&lt;/name&gt;<br class="gmail_msg">
  &lt;uuid&gt;ccd945c8-8069-4f31-8471-bbb58e9dd6ea&lt;/uuid&gt;<br class="gmail_msg">
  &lt;metadata xmlns:ovirt-tune=&quot;<a href="http://ovirt.org/vm/tune/1.0" rel="noreferrer" class="gmail_msg" target="_blank">http://ovirt.org/vm/tune/1.0</a>&quot;<br class="gmail_msg"></blockquote><div><br></div><div>The url is broken - do we have this?</div><div> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
xmlns:ovirt-vm=&quot;<a href="http://ovirt.org/vm/1.0" rel="noreferrer" class="gmail_msg" target="_blank">http://ovirt.org/vm/1.0</a>&quot;<br class="gmail_msg">
xmlns:ovirt-instance=&quot;<a href="http://ovirt.org/vm/instance/1.0" rel="noreferrer" class="gmail_msg" target="_blank">http://ovirt.org/vm/instance/1.0</a>&quot;&gt;<br class="gmail_msg">
    &lt;ovirt-tune:qos/&gt; </blockquote><div><br></div><div>What do we keep here? why does it need its own namespace?</div><div> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    &lt;ovirt-vm:vm/&gt;<br class="gmail_msg"></blockquote><div><br></div><div><div>What do we keep here? why does it need its own namespace?</div><br class="inbox-inbox-Apple-interchange-newline"></div><div>Can we merge all namespaces into one generic namespace?</div><div> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    &lt;ovirt-instance:instance&gt;<br class="gmail_msg"></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg">What is instance?</div></div></div><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg"> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
      &lt;ovirt-instance:value type=&quot;dict&quot;&gt;  </blockquote><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
        &lt;ovirt-instance:item key=&quot;devices&quot; type=&quot;list&quot;&gt; </blockquote><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
          &lt;ovirt-instance:item index=&quot;0&quot; type=&quot;dict&quot;&gt;</blockquote><div><br></div><div>Isn&#39;t index redundant?</div><div> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
            &lt;ovirt-instance:item key=&quot;device&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;vnc&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;specParams&quot; type=&quot;dict&quot;&gt;<br class="gmail_msg">
              &lt;ovirt-instance:item key=&quot;displayNetwork&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;ovirtmgmt&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
              &lt;ovirt-instance:item key=&quot;displayIp&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;192.168.1.53&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;type&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;graphics&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
          &lt;/ovirt-instance:item&gt;<br class="gmail_msg">
          &lt;ovirt-instance:item index=&quot;1&quot; type=&quot;dict&quot;&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;device&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;spice&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;specParams&quot; type=&quot;dict&quot;&gt;<br class="gmail_msg">
              &lt;ovirt-instance:item key=&quot;displayNetwork&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;ovirtmgmt&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
              &lt;ovirt-instance:item key=&quot;displayIp&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;192.168.1.53&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;type&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;graphics&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
          &lt;/ovirt-instance:item&gt;<br class="gmail_msg">
          &lt;ovirt-instance:item index=&quot;2&quot; type=&quot;dict&quot;&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;poolID&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;5890a292-0390-01d2-01ed-00000000029a&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;imageID&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;66441539-f7ac-4946-8a25-75e422f939d4&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;domainID&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;c578566d-bc61-420c-8f1e-8dfa0a18efd5&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;device&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;disk&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;path&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;/rhev/data-center/5890a292-0390-01d2-01ed-00000000029a/c578566d-bc61-420c-8f1e-8dfa0a18efd5/images/66441539-f7ac-4946-8a25-75e422f939d4/5c4eeed4-f2a7-490a-ab57-a0d6f3a711cc&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
            &lt;ovirt-instance:item key=&quot;volumeID&quot;<br class="gmail_msg">
type=&quot;str&quot;&gt;5c4eeed4-f2a7-490a-ab57-a0d6f3a711cc&lt;/ovirt-instance:item&gt;<br class="gmail_msg">
          &lt;/ovirt-instance:item&gt;<br class="gmail_msg">
        &lt;/ovirt-instance:item&gt;<br class="gmail_msg">
      &lt;/ovirt-instance:value&gt;<br class="gmail_msg">
    &lt;/ovirt-instance:instance&gt;<br class="gmail_msg">
  &lt;/metadata&gt;<br class="gmail_msg">
 &lt;!-- omitted for brevity --&gt;<br class="gmail_msg">
&lt;/domain&gt;<br class="gmail_msg"></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg">How about a generic json namespace?<br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">json:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">{</div><div class="gmail_msg">    &quot;devices&quot;: [</div><div class="gmail_msg">       {</div><div class="gmail_msg">           &quot;foo&quot;: &quot;bar&quot;</div><div class="gmail_msg">       }</div><div class="gmail_msg">   ]</div><div class="gmail_msg">}</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">xml:</div><div class="gmail_msg"><br></div><div class="gmail_msg">&lt;json:object&gt;</div><div class="gmail_msg">    &lt;json:key&gt;devices&lt;/json:key&gt;</div><div class="gmail_msg">    &lt;json:list&gt;</div><div class="gmail_msg">       &lt;json:object&gt;</div><div class="gmail_msg">           &lt;json:key&gt;foo&lt;/json:key&gt;</div><div class="gmail_msg"><div class="gmail_msg">           &lt;json:string&gt;bar&lt;/json:string&gt;</div></div><div class="gmail_msg">       &lt;/json:object&gt;</div><div class="gmail_msg">    &lt;/json:list&gt;<br class="gmail_msg"></div><div class="gmail_msg">&lt;/json:object&gt;</div><div class="gmail_msg"><br></div><div class="gmail_msg">We can query and modify this xml using xpath, like this:</div><div class="gmail_msg"><br></div><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">&gt;&gt;&gt; r.findall(&quot;./metadata/json:object/[json:key=&#39;devices&#39;]/json:list/json:object/&quot;, namespaces={&quot;json&quot;: &quot;<a href="http://ovirt.org/json/1.0">http://ovirt.org/json/1.0</a>&quot;})</div><div class="gmail_msg">[&lt;Element &#39;{<a href="http://ovirt.org/json/1.0}key">http://ovirt.org/json/1.0}key</a>&#39; at 0x7fd3386a69d0&gt;, &lt;Element &#39;{<a href="http://ovirt.org/json/1.0}string">http://ovirt.org/json/1.0}string</a>&#39; at 0x7fd3386a6a50&gt;]</div><div><br></div></div></div><div>Not sure this format will be easy to modify, needs to tinker more</div><div>with this.</div><div><br></div></div></div></div><div class="gmail_quote gmail_msg"><div class="gmail_msg">It will be probably easier to parse the entire metadata, change it,</div><div class="gmail_msg">and serialize it back.</div><div class="gmail_msg"><br></div><div class="gmail_msg">Maybe using key and type attribute as you suggest makes it simpler to use,</div><div class="gmail_msg">and we since we convert from xml to python or python to xml, we can</div><div class="gmail_msg">have a &quot;py&quot; namespace.</div><div class="gmail_msg"><br></div><div class="gmail_msg"><div class="gmail_msg">&lt;py:item&gt;</div><div class="gmail_msg">    &lt;py:item key=&quot;devices&quot; type=&quot;list&quot;&gt;</div><div class="gmail_msg">        &lt;py:item type=&quot;dict&quot;&gt;</div><div class="gmail_msg">            &lt;py:item key=&quot;foo&quot; type=&quot;str&quot;&gt;bar&lt;/py:item&gt;</div><div class="gmail_msg">        &lt;/py:item&gt;<br>    &lt;/py:item&gt;</div><div class="gmail_msg">&lt;/py:item&gt;</div></div><div class="gmail_msg"><br></div><div class="gmail_msg">With this we can have:</div><div class="gmail_msg"><br></div><div class="gmail_msg"><div class="gmail_msg">&gt;&gt;&gt; r.findall(&quot;./metadata/py:item/py:item[@key=&#39;devices&#39;]/py:item[1]/py:item[@key=&#39;foo&#39;]&quot;, namespaces={&quot;py&quot;: &quot;<a href="http://ovirt.org/py/1.0">http://ovirt.org/py/1.0</a>&quot;})[0].text</div><div class="gmail_msg">&#39;bar&#39;</div><div><br></div></div><div class="gmail_msg">Something like this can be useful for others as well.</div><div class="gmail_msg"><br></div></div></div><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Please note that yes, this is still verbose, but we don&#39;t want to add<br class="gmail_msg">
much data here, for most of information the most reliable source will<br class="gmail_msg">
be the domain XML. We will add here only the extra info we can&#39;t really<br class="gmail_msg">
fetch from that.<br class="gmail_msg">
<br class="gmail_msg">
2. I don&#39;t think we need explicit validation: we could just raise along<br class="gmail_msg">
the way in the creation flow if we don&#39;t find some extra metadata we<br class="gmail_msg">
need. This will also solve the issue that if we reuse the current schema<br class="gmail_msg">
and we omit most of data, we will lack quite a lot of elements<br class="gmail_msg">
marked mandatory.<br class="gmail_msg">
<br class="gmail_msg">
Once we reached agreement, I will update my<br class="gmail_msg">
<a href="https://docs.google.com/document/d/1eD8KSLwwyo2Sk64MytbmE0wBxxMlpIyEI1GRcHDkp7Y/edit#heading=h.hqdqzmmm9i77" rel="noreferrer" class="gmail_msg" target="_blank">https://docs.google.com/document/d/1eD8KSLwwyo2Sk64MytbmE0wBxxMlpIyEI1GRcHDkp7Y/edit#heading=h.hqdqzmmm9i77</a><br class="gmail_msg">
accordingly.<br class="gmail_msg">
<br class="gmail_msg">
Final note: while device take the lion&#39;s share, we will likely need help<br class="gmail_msg">
from the metadata section also to store VM extra info, but all the above<br class="gmail_msg">
discussion also applies here.<br class="gmail_msg">
<br class="gmail_msg">
+++<br class="gmail_msg">
<br class="gmail_msg">
[1]<br class="gmail_msg">
<a href="https://gerrit.ovirt.org/#/q/status:open+project:vdsm+branch:master+topic:virt-metadata3" rel="noreferrer" class="gmail_msg" target="_blank">https://gerrit.ovirt.org/#/q/status:open+project:vdsm+branch:master+topic:virt-metadata3</a><br class="gmail_msg">
- uses xmltodict<br class="gmail_msg">
[2]<br class="gmail_msg">
<a href="https://gerrit.ovirt.org/#/q/status:open+project:vdsm+branch:master+topic:virt-metadata-pyxmlpickle" rel="noreferrer" class="gmail_msg" target="_blank">https://gerrit.ovirt.org/#/q/status:open+project:vdsm+branch:master+topic:virt-metadata-pyxmlpickle</a><br class="gmail_msg">
ported the &#39;virt-metadata3&#39; topic to pyxmlpickle<br class="gmail_msg">
[3] <a href="https://github.com/fromanirh/pyxmlpickle" rel="noreferrer" class="gmail_msg" target="_blank">https://github.com/fromanirh/pyxmlpickle</a><br class="gmail_msg">
[4] <a href="https://docs.python.org/2/library/plistlib.html" rel="noreferrer" class="gmail_msg" target="_blank">https://docs.python.org/2/library/plistlib.html</a><br class="gmail_msg">
[5] <a href="https://github.com/martinblech/xmltodict" rel="noreferrer" class="gmail_msg" target="_blank">https://github.com/martinblech/xmltodict</a><br class="gmail_msg">
[6]<br class="gmail_msg">
<a href="https://gerrit.ovirt.org/#/q/status:open+project:vdsm+branch:master+topic:vm-devs-xml" rel="noreferrer" class="gmail_msg" target="_blank">https://gerrit.ovirt.org/#/q/status:open+project:vdsm+branch:master+topic:vm-devs-xml</a><br class="gmail_msg">
[7] <a href="https://gerrit.ovirt.org/#/c/72880/15/lib/vdsm/virt/vmdevices/core.py" rel="noreferrer" class="gmail_msg" target="_blank">https://gerrit.ovirt.org/#/c/72880/15/lib/vdsm/virt/vmdevices/core.py</a><br class="gmail_msg">
<br class="gmail_msg">
--<br class="gmail_msg">
Francesco Romani<br class="gmail_msg">
Red Hat Engineering Virtualization R &amp; D<br class="gmail_msg">
IRC: fromani<br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
Devel mailing list<br class="gmail_msg">
<a href="mailto:Devel@ovirt.org" class="gmail_msg" target="_blank">Devel@ovirt.org</a><br class="gmail_msg">
<a href="http://lists.ovirt.org/mailman/listinfo/devel" rel="noreferrer" class="gmail_msg" target="_blank">http://lists.ovirt.org/mailman/listinfo/devel</a><br class="gmail_msg">
</blockquote></div></div></div>