[Kimchi-devel] [PATCh V12 4/7] manually manage the metadata element

shaohef at linux.vnet.ibm.com shaohef at linux.vnet.ibm.com
Tue Apr 29 15:45:34 UTC 2014


From: ShaoHe Feng <shaohef at linux.vnet.ibm.com>

virDomain.metadata and virDomain.setMetadata does not work in all livirt
versions used in the supported distros.

So if libvirt do not support these two API.

let kimchi manually manage the metadata element

Signed-off-by: ShaoHe Feng <shaohef at linux.vnet.ibm.com>
Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
---
 src/kimchi/model/utils.py | 88 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 75 insertions(+), 13 deletions(-)

diff --git a/src/kimchi/model/utils.py b/src/kimchi/model/utils.py
index 3aaa956..7845c0d 100644
--- a/src/kimchi/model/utils.py
+++ b/src/kimchi/model/utils.py
@@ -17,10 +17,12 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 
+import re
 from kimchi.exception import OperationFailed
+from kimchi.model.config import CapabilitiesModel
 import libvirt
 from lxml import etree
-from lxml.builder import E
+from lxml.builder import E, ElementMaker
 
 
 KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi"
@@ -37,6 +39,15 @@ def get_vm_name(vm_name, t_name, name_list):
     raise OperationFailed("KCHUTILS0003E")
 
 
+def create_metadata_node(tag):
+    if CapabilitiesModel().metadata_support:
+        return E(tag)
+    else:
+        EM = ElementMaker(namespace=KIMCHI_META_URL,
+                          nsmap={KIMCHI_NAMESPACE: KIMCHI_META_URL})
+        return EM(tag)
+
+
 def get_vm_config_flag(dom, mode="persistent"):
     # libvirt.VIR_DOMAIN_AFFECT_CURRENT is 0
     # VIR_DOMAIN_AFFECT_LIVE is 1, VIR_DOMAIN_AFFECT_CONFIG is 2
@@ -58,6 +69,25 @@ def update_node(root, node):
     return root
 
 
+def _kimchi_set_metadata_node(dom, node):
+    # some other tools will not let libvirt create a persistent
+    # configuration, raise exception.
+    if not dom.isPersistent():
+        msg = 'The VM has not a persistent configuration'
+        raise OperationFailed("KCHVM0030E",
+                              {'name': dom.name(), "err": msg})
+    xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)
+    root = etree.fromstring(xml)
+    kimchi = root.find("metadata/{%s}kimchi" % KIMCHI_META_URL)
+    kimchi = create_metadata_node("kimchi") if kimchi is None else kimchi
+    update_node(kimchi, node)
+    metadata = root.find("metadata")
+    metadata = E.metadata() if metadata is None else metadata
+    update_node(metadata, kimchi)
+    update_node(root, metadata)
+    dom.connect().defineXML(etree.tostring(root))
+
+
 def libvirt_get_kimchi_metadata_node(dom, mode="current"):
     try:
         xml = dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT,
@@ -69,21 +99,53 @@ def libvirt_get_kimchi_metadata_node(dom, mode="current"):
 
 
 def set_metadata_node(dom, node, mode="all"):
-    kimchi = libvirt_get_kimchi_metadata_node(dom, mode)
-    kimchi = E.kimchi() if kimchi is None else kimchi
-
-    update_node(kimchi, node)
-    kimchi_xml = etree.tostring(kimchi)
-    # From libvirt doc, Passing None for @metadata says to remove that
-    # element from the domain XML (passing the empty string leaves the
-    # element present).  Do not support remove the old metadata.
-    dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, kimchi_xml,
-                    KIMCHI_NAMESPACE, KIMCHI_META_URL,
-                    flags=get_vm_config_flag(dom, mode))
+    if CapabilitiesModel().metadata_support:
+        kimchi = libvirt_get_kimchi_metadata_node(dom, mode)
+        kimchi = E.kimchi() if kimchi is None else kimchi
+
+        update_node(kimchi, node)
+        kimchi_xml = etree.tostring(kimchi)
+        # From libvirt doc, Passing None for @metadata says to remove that
+        # element from the domain XML (passing the empty string leaves the
+        # element present).  Do not support remove the old metadata.
+        dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, kimchi_xml,
+                        KIMCHI_NAMESPACE, KIMCHI_META_URL,
+                        flags=get_vm_config_flag(dom, mode))
+    else:
+    # FIXME remove this code when all distro libvirt supports metadata element
+        _kimchi_set_metadata_node(dom, node)
+
+
+def _kimchi_get_metadata_node(dom, tag):
+    # some other tools will not let libvirt create a persistent
+    # configuration, just return empty
+    if not dom.isPersistent():
+        return None
+    xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)
+    root = etree.fromstring(xml)
+    kimchi = root.find("metadata/{%s}kimchi" % KIMCHI_META_URL)
+    #remove the "kimchi" prifix of xml
+    # some developers may do not like to remove prefix by children iteration
+    # so here, use re to remove the "kimchi" prefix of xml
+    # and developers please don not define element like this:
+    #     <foo attr="foo<kimchi:abcd>foo"></foo>
+    if kimchi is not None:
+        kimchi_xml = etree.tostring(kimchi)
+        ns_pattern = re.compile(" xmlns:.*?=((\".*?\")|('.*?'))")
+        kimchi_xml = ns_pattern.sub("", kimchi_xml)
+        prefix_pattern = re.compile("(?<=<)[^/]*?:|(?<=</).*?:")
+        kimchi_xml = prefix_pattern.sub("", kimchi_xml)
+        return etree.fromstring(kimchi_xml)
+    return None
 
 
 def get_metadata_node(dom, tag, mode="current"):
-    kimchi = libvirt_get_kimchi_metadata_node(dom, mode)
+    if CapabilitiesModel().metadata_support:
+        kimchi = libvirt_get_kimchi_metadata_node(dom, mode)
+    else:
+    # FIXME remove this code when all distro libvirt supports metadata element
+        kimchi = _kimchi_get_metadata_node(dom, tag)
+
     if kimchi is not None:
         node = kimchi.find(tag)
         if node is not None:
-- 
1.9.0




More information about the Kimchi-devel mailing list