On 04/24/2014 02:19 PM, shaohef(a)linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef(a)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(a)linux.vnet.ibm.com>
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
---
src/kimchi/model/utils.py | 92 +++++++++++++++++++++++++++++++++++++----------
1 file changed, 74 insertions(+), 18 deletions(-)
diff --git a/src/kimchi/model/utils.py b/src/kimchi/model/utils.py
index be5e526..6ddef8c 100644
--- a/src/kimchi/model/utils.py
+++ b/src/kimchi/model/utils.py
@@ -18,8 +18,10 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from kimchi.exception import OperationFailed
+from kimchi.config import libvirt_support_apis
import libvirt
-from lxml import etree
+from lxml import etree, objectify
+from lxml.builder import E
KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi/metadata/"
@@ -48,24 +50,78 @@ def get_vm_config_flag(dom, mode="persistent"):
return flag[mode]
-def set_vm_metadata_element(dom, meta_xml, mode="all"):
+def _kimchi_set_vm_metadata_element(dom, meta_xml):
element = etree.fromstring(meta_xml)
- # 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, meta_xml,
- "kimchi", KIMCHI_META_URL + element.tag,
- flags=get_vm_config_flag(dom, mode))
+ # E = ElementMaker(namespace=KIMCHI_META_URL + element.tag,
+ # nsmap={'kimchi': KIMCHI_META_URL + element.tag})
ElementMaker can make this code simpler.
Why didn't you use it?
+ # 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)
+ metadata = root.find("metadata")
+ if metadata is None:
+ metadata = E.metadata()
+ root.append(metadata)
+ element.tag = "{%s%s}%s" % (KIMCHI_META_URL, element.tag, element.tag)
+ old_elem = metadata.find(element.tag)
+ (metadata.replace(old_elem, element) if old_elem is not None
+ else metadata.append(element))
+
+ dom.connect().defineXML(etree.tostring(root))
+
+
+def set_vm_metadata_element(dom, meta_xml, mode="all"):
+ if libvirt_support_apis["meta_element"] is True:
+ element = etree.fromstring(meta_xml)
+ # 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, meta_xml,
+ "kimchi", KIMCHI_META_URL + element.tag,
+ flags=get_vm_config_flag(dom, mode))
+ else:
+ # FIXME remove this code when all distro libvirt supports metadata element
+ _kimchi_set_vm_metadata_element(dom, meta_xml)
+
+
+def _kimchi_get_vm_metadata_element(dom, element):
+ # some other tools will not let libvirt create a persistent
+ # configuration, just return empty
+ if not dom.isPersistent():
+ return ""
+ xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)
+ root = etree.fromstring(xml)
+ metadata = root.find("metadata")
+ if metadata is None:
+ return ""
+ tag = "{%s%s}%s" % (KIMCHI_META_URL, element, element)
+ elem = metadata.find(tag)
+ if elem:
+ for child in elem.getiterator():
+ i = child.tag.find('}')
+ if i >= 0:
+ child.tag = child.tag[i+1:]
+ objectify.deannotate(elem, cleanup_namespaces=True)
I didn't understand that code
+ return etree.tostring(elem)
+ return ""
def get_vm_metadata_element(dom, element, mode="current"):
- try:
- return dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT,
- KIMCHI_META_URL + element,
- flags=get_vm_config_flag(dom, mode))
- except libvirt.libvirtError as e:
- if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN_METADATA:
- return ""
- else:
- raise OperationFailed("KCHVM0030E", {'name': dom.name(),
- 'err': e.message})
+ if libvirt_support_apis["meta_element"] is True:
+ try:
+ return dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT,
+ KIMCHI_META_URL + element,
+ flags=get_vm_config_flag(dom, mode))
+ except libvirt.libvirtError as e:
+ if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN_METADATA:
+ return ""
+ else:
+ raise OperationFailed("KCHVM0030E", {'name':
dom.name(),
+ 'err': e.message})
+ else:
+ # FIXME remove this code when all distro libvirt supports metadata element
+ _kimchi_get_vm_metadata_element(dom, element)