Reviewed-by: Royce Lv<lvroyce(a)linux.vnet.ibm.com>
On 2014年04月25日 22:14, 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 | 93 ++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 79 insertions(+), 14 deletions(-)
diff --git a/src/kimchi/model/utils.py b/src/kimchi/model/utils.py
index 9b94a06..257b9e7 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.model.config import CapabilitiesModel
import libvirt
-from lxml import etree
+from lxml import etree, objectify
+from lxml.builder import E, ElementMaker
KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi/metadata/"
@@ -36,6 +38,16 @@ def get_vm_name(vm_name, t_name, name_list):
raise OperationFailed("KCHUTILS0003E")
+def create_metadata_node(element):
+ # create the xml using "element"
+ if CapabilitiesModel().metadata_support:
+ return E
+ else:
+ return ElementMaker(namespace=KIMCHI_META_URL + element,
+ nsmap={KIMCHI_NAMESPACE:
+ KIMCHI_META_URL + element})
+
+
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
@@ -49,20 +61,73 @@ def get_vm_config_flag(dom, mode="persistent"):
return flag[mode]
-def set_metadata_node(dom, meta_xml, mode="all"):
+def _kimchi_set_metadata_node(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_NAMESPACE, KIMCHI_META_URL + element.tag,
- flags=get_vm_config_flag(dom, mode))
+ # 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)
+ 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 get_metadata_node(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:
+
+def set_metadata_node(dom, meta_xml, mode="all"):
+ if CapabilitiesModel().metadata_support:
+ 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_NAMESPACE, 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_metadata_node(dom, meta_xml)
+
+
+def _kimchi_get_metadata_node(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)
+ #remove the "kimchi" prifix of xml
+ if elem is not None:
+ for child in elem.getiterator():
+ i = child.tag.find('}')
+ if i >= 0:
+ child.tag = child.tag[i+1:]
+ objectify.deannotate(elem, cleanup_namespaces=True)
+ return etree.tostring(elem)
+
+ return ""
+
+
+def get_metadata_node(dom, element, mode="current"):
+ if CapabilitiesModel().metadata_support:
+ try:
+ return dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT,
+ KIMCHI_META_URL + element,
+ flags=get_vm_config_flag(dom, mode))
+ except libvirt.libvirtError:
+ return ""
+ else:
+ # FIXME remove this code when all distro libvirt supports metadata element
+ return _kimchi_get_metadata_node(dom, element)