FYI - I'm looking at this now. My RHEL 6.2 didn't have lxml and I'm getting
lots
of errors when I try to install via easy_setup. Will send an update once I have
a chance to dig deeper.
On 12/05/2011 11:24 AM, Eduardo Lima (Etrunko) wrote:
From: Eduardo Lima (Etrunko)<eblima(a)br.ibm.com>
PyXML is a legacy python XML library which won't work with recent versions of
python unless you patch the code. The following link describes the problem:
http://stackoverflow.com/questions/4953600/pyxml-on-ubuntu
In summary, when trying to install PyXML with easy_install, you get an error
because it tries to use 'as' which is a reserved keyword introduced in python
2.5.
This patch removes dependency of PyXML in favor of python-lxml, which provides
bindings to the very complete and fast libxml2:
http://lxml.de/intro.html
Signed-off-by: Eduardo Lima (Etrunko)<eblima(a)br.ibm.com>
---
suites/libvirt-cim/cimtest/FilterList/helper.py | 8 +--
.../12_referenced_config.py | 14 +---
.../24_define_sys_features.py | 6 +-
suites/libvirt-cim/lib/XenKvmLib/test_xml.py | 27 +++---
suites/libvirt-cim/lib/XenKvmLib/vxml.py | 95 ++++++++++----------
5 files changed, 69 insertions(+), 81 deletions(-)
diff --git a/suites/libvirt-cim/cimtest/FilterList/helper.py
b/suites/libvirt-cim/cimtest/FilterList/helper.py
index 138f941..9ae2f62 100644
--- a/suites/libvirt-cim/cimtest/FilterList/helper.py
+++ b/suites/libvirt-cim/cimtest/FilterList/helper.py
@@ -35,11 +35,7 @@ from XenKvmLib.vxml import get_class
import VirtLib
from VirtLib.utils import run_remote
-try:
- from xml.etree import cElementTree as ElementTree
-except:
- from xml.etree import ElementTree
-
+from lxml import etree
class BaseTestObject(object):
@@ -247,7 +243,7 @@ class FilterListTest(BaseTestObject):
# Remove all unecessary spaces and new lines
_xml = "".join([a.strip() for a in out.split("\n") if a])
- return ElementTree.fromstring(_xml)
+ return etree.fromstring(_xml)
# libvirt_filter_dumpxml
def libvirt_entries_in_filter_lists(self):
diff --git
a/suites/libvirt-cim/cimtest/VirtualSystemManagementService/12_referenced_config.py
b/suites/libvirt-cim/cimtest/VirtualSystemManagementService/12_referenced_config.py
index 7af65fd..24b47e9 100644
--- a/suites/libvirt-cim/cimtest/VirtualSystemManagementService/12_referenced_config.py
+++ b/suites/libvirt-cim/cimtest/VirtualSystemManagementService/12_referenced_config.py
@@ -102,20 +102,8 @@ def setup_second_guest(ip, virt, cxml2, ref):
return PASS, "define"
def get_dom_disk_src(xml, ip):
- disk_list = []
-
xml.dumpxml(ip)
- myxml = xml.get_formatted_xml()
-
- lines = myxml.splitlines()
- for l in lines:
- if l.find("source file=") != -1:
- disk = l.split('=')[1]
- disk = disk.lstrip('\'')
- disk = disk.rstrip('\'/>')
- disk_list.append(disk)
-
- return disk_list
+ return xml.xdoc.xpath("/domain/devices/disk/source/@file")
@do_main(sup_types)
def main():
diff --git
a/suites/libvirt-cim/cimtest/VirtualSystemManagementService/24_define_sys_features.py
b/suites/libvirt-cim/cimtest/VirtualSystemManagementService/24_define_sys_features.py
index 9716cd1..42c59ec 100644
---
a/suites/libvirt-cim/cimtest/VirtualSystemManagementService/24_define_sys_features.py
+++
b/suites/libvirt-cim/cimtest/VirtualSystemManagementService/24_define_sys_features.py
@@ -48,13 +48,13 @@ def main():
cxml.dumpxml(options.ip)
- if cxml.xml_get_pae() == None:
+ if cxml.xml_get_pae() is None:
raise Exception("Failed to set pae for dom: %s" % default_dom)
- if cxml.xml_get_acpi() == None:
+ if cxml.xml_get_acpi() is None:
raise Exception("Failed to set acpi for dom: %s" % default_dom)
- if cxml.xml_get_apic() == None:
+ if cxml.xml_get_apic() is None:
raise Exception("Failed to set apic for dom: %s" % default_dom)
status = PASS
diff --git a/suites/libvirt-cim/lib/XenKvmLib/test_xml.py
b/suites/libvirt-cim/lib/XenKvmLib/test_xml.py
index 033275b..b32ae4c 100755
--- a/suites/libvirt-cim/lib/XenKvmLib/test_xml.py
+++ b/suites/libvirt-cim/lib/XenKvmLib/test_xml.py
@@ -29,8 +29,7 @@ import os
import sys
import random
from VirtLib import utils
-from xml import xpath
-from xml.dom import minidom, Node
+from lxml import etree
from CimTest.Globals import logger
from XenKvmLib.test_doms import set_uuid, create_vnet
from VirtLib.live import available_bridges
@@ -212,22 +211,26 @@ def dumpxml(name, server, virt="Xen"):
return o
def get_value_xpath(xmlStr, xpathStr):
- xmldoc = minidom.parseString(xmlStr)
- nodes = xpath.Evaluate(xpathStr, xmldoc.documentElement)
+ xmldoc = etree.fromstring(xmlStr)
+ nodes = xmldoc.xpath(xpathStr)
if len(nodes) != 1:
raise LookupError('Zero or multiple xpath results found!')
node = nodes[0]
- if node.nodeType == Node.ATTRIBUTE_NODE:
- return node.value
- if node.nodeType == Node.TEXT_NODE:
- return node.toxml()
- if node.nodeType == Node.ELEMENT_NODE:
+ ret = ''
+
+ if etree.iselement(node):
+ ret = node.text
+ for child in node:
+ ret = ret + child.text
+ elif isinstance(node, str):
+ ret = node
+
+ if ret is None:
ret = ''
- for child in node.childNodes:
- ret = ret + child.toxml()
- return ret
+
+ return ret
def xml_get_dom_name(xmlStr):
return get_value_xpath(xmlStr,
diff --git a/suites/libvirt-cim/lib/XenKvmLib/vxml.py
b/suites/libvirt-cim/lib/XenKvmLib/vxml.py
index 15859c1..51a4166 100644
--- a/suites/libvirt-cim/lib/XenKvmLib/vxml.py
+++ b/suites/libvirt-cim/lib/XenKvmLib/vxml.py
@@ -34,15 +34,10 @@ import sys
import random
import platform
import tempfile
-from time import sleep
import pywbem
-from xml.dom import minidom, Node
-from xml import xpath
-try:
- from xml.etree import cElementTree as ElementTree
-except:
- from xml.etree import ElementTree
+from lxml import etree
+from time import sleep
from VirtLib import utils, live
from XenKvmLib.xm_virt_util import get_bridge_from_network_xml, bootloader, \
@@ -64,35 +59,37 @@ class XMLClass:
xdoc = None
def __init__(self):
- self.xdoc = minidom.Document()
self.refresh()
def __str__(self):
return self.xml_string
def refresh(self):
- self.xml_string = self.xdoc.toxml()
+ if self.xdoc is not None:
+ self.xml_string = etree.tostring(self.xdoc)
def get_node(self, ixpath):
- node_list = xpath.Evaluate(ixpath, self.xdoc.documentElement)
+ if self.xdoc is None:
+ return None
+
+ node_list = self.xdoc.xpath(ixpath)
if len(node_list) != 1:
raise LookupError('Zero or multiple nodes found for XPath' +
ixpath)
return node_list[0]
+
def add_sub_node(self, parent, node_name, text_cdata=None, **attrs):
if isinstance(parent, basestring):
pnode = self.get_node(parent)
else:
pnode = parent
- node = self.xdoc.createElement(node_name)
-
- for key in attrs.keys():
- node.setAttribute(key, str(attrs[key]))
-
- if text_cdata is not None:
- node.appendChild(self.xdoc.createTextNode(str(text_cdata)))
+ if pnode is None:
+ self.xdoc = etree.Element(node_name, **attrs)
+ node = self.xdoc
+ else:
+ node = etree.SubElement(pnode, node_name, **attrs)
- pnode.appendChild(node)
+ node.text = str(text_cdata)
self.refresh()
return node
@@ -103,13 +100,7 @@ class XMLClass:
else:
pnode = parent
- for cnode in pnode.childNodes:
- pnode.removeChild(cnode)
- cnode.unlink()
-
- if text_cdata is not None:
- pnode.appendChild(self.xdoc.createTextNode(str(text_cdata)))
-
+ pnode.text = str(text_cdata)
self.refresh()
def set_attributes(self, node, **attrs):
@@ -118,8 +109,8 @@ class XMLClass:
else:
pnode = node
- for key in attrs.keys():
- pnode.setAttribute(key, str(attrs[key]))
+ for key, val in attrs.items():
+ pnode.set(key, val)
self.refresh()
@@ -127,7 +118,7 @@ class XMLClass:
'''Don't use this to define domain.
Extra newline in the text node fails libvirt
'''
- return self.xdoc.toprettyxml()
+ return etree.tostring(self.xdoc, pretty_print=True)
def get_value_xpath(self, xpathStr):
try:
@@ -136,15 +127,19 @@ class XMLClass:
logger.info('Zero or multiple node found')
return None
- if node.nodeType == Node.ATTRIBUTE_NODE:
- return node.value
- if node.nodeType == Node.TEXT_NODE:
- return node.toxml()
- if node.nodeType == Node.ELEMENT_NODE:
+ ret = ''
+
+ if etree.iselement(node):
+ ret = node.text
+ for child in node:
+ ret = ret + child.text
+ elif isinstance(node, basestring):
+ ret = node
+
+ if ret is None:
ret = ''
- for child in node.childNodes:
- ret = ret + child.toxml()
- return ret
+
+ return ret
class Virsh:
@@ -220,7 +215,7 @@ class NetXML(Virsh, XMLClass):
def _parse_net_dumpxml(_xml):
try:
- root = ElementTree.fromstring(_xml)
+ root = etree.fromstring(_xml)
ip_element = root.find("ip")
return ip_element.get("address")
except:
@@ -247,7 +242,7 @@ class NetXML(Virsh, XMLClass):
return None
else:
self.xml_string = net_xml
- self.xdoc = minidom.parseString(self.xml_string)
+ self.xdoc = etree.fromstring(self.xml_string)
return
network = self.add_sub_node(self.xdoc, 'network')
@@ -337,7 +332,7 @@ class PoolXML(Virsh, XMLClass):
return None
else:
self.xml_string = disk_xml
- self.xdoc = minidom.parseString(self.xml_string)
+ self.xdoc = etree.fromstring(self.xml_string)
return
pool = self.add_sub_node(self.xdoc, 'pool', type='dir')
@@ -547,8 +542,9 @@ class VirtXML(Virsh, XMLClass):
cmd = 'virsh -c %s dumpxml %s 2>/dev/null' % (self.vuri,
self.dname)
s, o = utils.run_remote(ip, cmd)
if s == 0:
- self.xml_string = o
- self.xdoc = minidom.parseString(self.xml_string)
+ o = "".join([i.strip() for i in o.split("\n") if i])
+ self.xdoc = etree.fromstring(o)
+ self.refresh()
def _set_emulator(self, emu):
self.add_sub_node('/domain/devices', 'emulator', emu)
@@ -562,7 +558,7 @@ class VirtXML(Virsh, XMLClass):
# pick the 1st virtual bridge
br = br_list[0]
interface = self.get_node('/domain/devices/interface')
- interface.setAttribute('type', 'bridge')
+ interface.set('type', 'bridge')
self.add_sub_node(interface, 'source', bridge=br)
return br
@@ -570,20 +566,25 @@ class VirtXML(Virsh, XMLClass):
def _set_vbridge(self, ip, virt_type, net_name):
vbr = get_bridge_from_network_xml(net_name, ip, virt=virt_type)
- interface = self.get_node('/domain/devices/interface')
- interface.setAttribute('type', 'bridge')
- self.add_sub_node(interface, 'source', bridge=vbr)
+ if vbr is not None:
+ interface = self.get_node('/domain/devices/interface')
+ interface.set('type', 'bridge')
+ self.add_sub_node(interface, 'source', bridge=vbr)
return vbr
def set_interface_details(self, devices, net_mac, net_type, net_name,
virt_type):
interface = self.add_sub_node(devices, 'interface', type=net_type)
- self.add_sub_node(interface, 'mac', address=net_mac)
+
+ if net_mac:
+ self.add_sub_node(interface, 'mac', address=net_mac)
+
if net_type == 'bridge':
self._set_vbridge(CIM_IP, virt_type, net_name)
elif net_type == 'network':
- self.add_sub_node(interface, 'source', network=net_name)
+ if net_name:
+ self.add_sub_node(interface, 'source', network=net_name)
elif net_type == 'ethernet':
pass
elif net_type == 'user':
--
Chip Vincent
Open Virtualization
IBM Linux Technology Center
cvincent(a)linux.vnet.ibm.com