[PATCH 0/3] Fixes on featuretests.py

It is needed to make mockmodel uses model with 'test:///default' URI Aline Manera (3): Update FeatureTests to use the same libvirt connection used by Model Set domain type in FeatureTests according libvirt URI Move featuretests.py to /model src/kimchi/featuretests.py | 217 --------------------------------------- src/kimchi/model/config.py | 12 ++- src/kimchi/model/featuretests.py | 210 +++++++++++++++++++++++++++++++++++++ src/kimchi/model/utils.py | 2 +- 4 files changed, 218 insertions(+), 223 deletions(-) delete mode 100644 src/kimchi/featuretests.py create mode 100644 src/kimchi/model/featuretests.py -- 1.9.3

The former code was running the FeatureTests with the system libvirt connection, so if a developer used Model() with a different libvirt URI the feature tests would report a false positive result. To avoid this problem share the libvirt connection used by Model() with FeatureTests. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/featuretests.py | 17 ++++------------- src/kimchi/model/config.py | 10 ++++++---- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/kimchi/featuretests.py b/src/kimchi/featuretests.py index f1eb8ae..a8613aa 100644 --- a/src/kimchi/featuretests.py +++ b/src/kimchi/featuretests.py @@ -100,12 +100,10 @@ class FeatureTests(object): libvirt.registerErrorHandler(f=None, ctx=None) @staticmethod - def libvirt_supports_iso_stream(protocol): + def libvirt_supports_iso_stream(conn, protocol): xml = ISO_STREAM_XML % {'protocol': protocol} - conn = None try: FeatureTests.disable_libvirt_error_logging() - conn = libvirt.open(None) dom = conn.defineXML(xml) dom.undefine() return True @@ -114,16 +112,14 @@ class FeatureTests(object): return False finally: FeatureTests.enable_libvirt_error_logging() - conn is None or conn.close() @staticmethod - def libvirt_support_nfs_probe(): + def libvirt_support_nfs_probe(conn): def _get_xml(): obj = E.source(E.host(name='localhost'), E.format(type='nfs')) xml = ET.tostring(obj) return xml try: - conn = libvirt.open(None) FeatureTests.disable_libvirt_error_logging() conn.findStoragePoolSources('netfs', _get_xml(), 0) except libvirt.libvirtError as e: @@ -134,7 +130,6 @@ class FeatureTests(object): return False finally: FeatureTests.enable_libvirt_error_logging() - conn is None or conn.close() return True @@ -172,10 +167,9 @@ class FeatureTests(object): return True @staticmethod - def libvirt_support_fc_host(): + def libvirt_support_fc_host(conn): try: FeatureTests.disable_libvirt_error_logging() - conn = libvirt.open(None) pool = None pool = conn.storagePoolDefineXML(SCSI_FC_XML, 0) except libvirt.libvirtError as e: @@ -185,18 +179,15 @@ class FeatureTests(object): finally: FeatureTests.enable_libvirt_error_logging() pool is None or pool.undefine() - conn is None or conn.close() return True @staticmethod - def has_metadata_support(): + def has_metadata_support(conn): KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi/" KIMCHI_NAMESPACE = "kimchi" with RollbackContext() as rollback: FeatureTests.disable_libvirt_error_logging() rollback.prependDefer(FeatureTests.enable_libvirt_error_logging) - conn = libvirt.open(None) - rollback.prependDefer(conn.close) dom = conn.defineXML(SIMPLE_VM_XML) rollback.prependDefer(dom.undefine) try: diff --git a/src/kimchi/model/config.py b/src/kimchi/model/config.py index 9ffc53e..73ca9c0 100644 --- a/src/kimchi/model/config.py +++ b/src/kimchi/model/config.py @@ -48,6 +48,7 @@ class CapabilitiesModel(object): __metaclass__ = Singleton def __init__(self, **kargs): + self.conn = kargs['conn'] self.qemu_stream = False self.qemu_stream_dns = False self.libvirt_stream_protocols = [] @@ -62,16 +63,17 @@ class CapabilitiesModel(object): def _set_capabilities(self): kimchi_log.info("*** Running feature tests ***") + conn = self.conn.get() self.qemu_stream = FeatureTests.qemu_supports_iso_stream() self.qemu_stream_dns = FeatureTests.qemu_iso_stream_dns() - self.nfs_target_probe = FeatureTests.libvirt_support_nfs_probe() - self.fc_host_support = FeatureTests.libvirt_support_fc_host() - self.metadata_support = FeatureTests.has_metadata_support() + self.nfs_target_probe = FeatureTests.libvirt_support_nfs_probe(conn) + self.fc_host_support = FeatureTests.libvirt_support_fc_host(conn) + self.metadata_support = FeatureTests.has_metadata_support(conn) self.kernel_vfio = FeatureTests.kernel_support_vfio() self.libvirt_stream_protocols = [] for p in ['http', 'https', 'ftp', 'ftps', 'tftp']: - if FeatureTests.libvirt_supports_iso_stream(p): + if FeatureTests.libvirt_supports_iso_stream(conn, p): self.libvirt_stream_protocols.append(p) kimchi_log.info("*** Feature tests completed ***") -- 1.9.3

When using the libvirt URI 'test:///default' the domain type must be 'test' instead of 'kvm' Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/featuretests.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/kimchi/featuretests.py b/src/kimchi/featuretests.py index a8613aa..c187f86 100644 --- a/src/kimchi/featuretests.py +++ b/src/kimchi/featuretests.py @@ -33,7 +33,7 @@ from kimchi.utils import kimchi_log, run_command ISO_STREAM_XML = """ -<domain type='kvm'> +<domain type='%(domain)s'> <name>ISO_STREAMING</name> <memory unit='KiB'>1048576</memory> <os> @@ -55,7 +55,7 @@ ISO_STREAM_XML = """ </domain>""" SIMPLE_VM_XML = """ -<domain type='kvm'> +<domain type='%(domain)s'> <name>A_SIMPLE_VM</name> <memory unit='KiB'>10240</memory> <os> @@ -101,7 +101,8 @@ class FeatureTests(object): @staticmethod def libvirt_supports_iso_stream(conn, protocol): - xml = ISO_STREAM_XML % {'protocol': protocol} + domain_type = 'test' if conn.getType().lower() == 'test' else 'kvm' + xml = ISO_STREAM_XML % {'domain': domain_type, 'protocol': protocol} try: FeatureTests.disable_libvirt_error_logging() dom = conn.defineXML(xml) @@ -188,7 +189,8 @@ class FeatureTests(object): with RollbackContext() as rollback: FeatureTests.disable_libvirt_error_logging() rollback.prependDefer(FeatureTests.enable_libvirt_error_logging) - dom = conn.defineXML(SIMPLE_VM_XML) + domain_type = 'test' if conn.getType().lower() == 'test' else 'kvm' + dom = conn.defineXML(SIMPLE_VM_XML % {'domain': domain_type}) rollback.prependDefer(dom.undefine) try: dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, -- 1.9.3

FeatureTests is only used by Model() as it tests the libvirt and qemu capabilities. So move it to /model Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/featuretests.py | 210 --------------------------------------- src/kimchi/model/config.py | 2 +- src/kimchi/model/featuretests.py | 210 +++++++++++++++++++++++++++++++++++++++ src/kimchi/model/utils.py | 2 +- 4 files changed, 212 insertions(+), 212 deletions(-) delete mode 100644 src/kimchi/featuretests.py create mode 100644 src/kimchi/model/featuretests.py diff --git a/src/kimchi/featuretests.py b/src/kimchi/featuretests.py deleted file mode 100644 index c187f86..0000000 --- a/src/kimchi/featuretests.py +++ /dev/null @@ -1,210 +0,0 @@ -# -# Project Kimchi -# -# Copyright IBM, Corp. 2013-2014 -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# 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 cherrypy -import libvirt -import lxml.etree as ET -import socket -import subprocess -import threading - - -from lxml.builder import E - - -from kimchi.rollbackcontext import RollbackContext -from kimchi.utils import kimchi_log, run_command - - -ISO_STREAM_XML = """ -<domain type='%(domain)s'> - <name>ISO_STREAMING</name> - <memory unit='KiB'>1048576</memory> - <os> - <type>hvm</type> - <boot dev='cdrom'/> - </os> - <devices> - <disk type='network' device='cdrom'> - <driver name='qemu' type='raw'/> - <source protocol='%(protocol)s' name='/url/path/to/iso/file'> - <host name='host.name' port='1234'/> - </source> - <target dev='hdc' bus='ide'/> - <readonly/> - <alias name='ide0-1-0'/> - <address type='drive' controller='0' bus='1' target='0' unit='0'/> - </disk> - </devices> -</domain>""" - -SIMPLE_VM_XML = """ -<domain type='%(domain)s'> - <name>A_SIMPLE_VM</name> - <memory unit='KiB'>10240</memory> - <os> - <type>hvm</type> - <boot dev='hd'/> - </os> -</domain>""" - -SCSI_FC_XML = """ -<pool type='scsi'> - <name>TEST_SCSI_FC_POOL</name> - <source> - <adapter type='fc_host' wwnn='1234567890abcdef' wwpn='abcdef1234567890'/> - </source> - <target> - <path>/dev/disk/by-path</path> - </target> -</pool> -""" - - -class FeatureTests(object): - - @staticmethod - def disable_libvirt_error_logging(): - def libvirt_errorhandler(userdata, error): - # A libvirt error handler to ignore annoying messages in stderr - pass - - # Filter functions are enable only in production env - if cherrypy.config.get('environment') != 'production': - return - # Register the error handler to hide libvirt error in stderr - libvirt.registerErrorHandler(f=libvirt_errorhandler, ctx=None) - - @staticmethod - def enable_libvirt_error_logging(): - # Filter functions are enable only in production env - if cherrypy.config.get('environment') != 'production': - return - # Unregister the error handler - libvirt.registerErrorHandler(f=None, ctx=None) - - @staticmethod - def libvirt_supports_iso_stream(conn, protocol): - domain_type = 'test' if conn.getType().lower() == 'test' else 'kvm' - xml = ISO_STREAM_XML % {'domain': domain_type, 'protocol': protocol} - try: - FeatureTests.disable_libvirt_error_logging() - dom = conn.defineXML(xml) - dom.undefine() - return True - except libvirt.libvirtError, e: - kimchi_log.error(e.message) - return False - finally: - FeatureTests.enable_libvirt_error_logging() - - @staticmethod - def libvirt_support_nfs_probe(conn): - def _get_xml(): - obj = E.source(E.host(name='localhost'), E.format(type='nfs')) - xml = ET.tostring(obj) - return xml - try: - FeatureTests.disable_libvirt_error_logging() - conn.findStoragePoolSources('netfs', _get_xml(), 0) - except libvirt.libvirtError as e: - kimchi_log.error(e.message) - if e.get_error_code() == 38: - # if libvirt cannot find showmount, - # it returns 38--general system call failure - return False - finally: - FeatureTests.enable_libvirt_error_logging() - - return True - - @staticmethod - def qemu_supports_iso_stream(): - host = cherrypy.server.socket_host - port = cherrypy.server.socket_port - cmd = "qemu-io -r http://%s:%d/images/icon-fedora.png \ - -c 'read -v 0 512'" % (host, port) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, shell=True) - stdout, stderr = proc.communicate() - return len(stderr) == 0 - - @staticmethod - def qemu_iso_stream_dns(): - host = socket.getfqdn(cherrypy.server.socket_host) - port = cherrypy.server.socket_port - cmd = ["qemu-io", "-r", "http://%s:%d/images/icon-fedora.png" % - (host, port), "-c", "'read -v 0 512'"] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - thread = threading.Thread(target=proc.communicate) - thread.start() - thread.join(5) - - if thread.is_alive(): - proc.kill() - thread.join() - return False - - if proc.returncode != 0: - return False - - return True - - @staticmethod - def libvirt_support_fc_host(conn): - try: - FeatureTests.disable_libvirt_error_logging() - pool = None - pool = conn.storagePoolDefineXML(SCSI_FC_XML, 0) - except libvirt.libvirtError as e: - if e.get_error_code() == 27: - # Libvirt requires adapter name, not needed when supports to FC - return False - finally: - FeatureTests.enable_libvirt_error_logging() - pool is None or pool.undefine() - return True - - @staticmethod - def has_metadata_support(conn): - KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi/" - KIMCHI_NAMESPACE = "kimchi" - with RollbackContext() as rollback: - FeatureTests.disable_libvirt_error_logging() - rollback.prependDefer(FeatureTests.enable_libvirt_error_logging) - domain_type = 'test' if conn.getType().lower() == 'test' else 'kvm' - dom = conn.defineXML(SIMPLE_VM_XML % {'domain': domain_type}) - rollback.prependDefer(dom.undefine) - try: - dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, - "<metatest/>", KIMCHI_NAMESPACE, - KIMCHI_META_URL, - flags=libvirt.VIR_DOMAIN_AFFECT_CURRENT) - return True - except libvirt.libvirtError: - return False - - @staticmethod - def kernel_support_vfio(): - out, err, rc = run_command(['modprobe', 'vfio-pci']) - if rc != 0: - kimchi_log.warning("Unable to load Kernal module vfio-pci.") - return False - return True diff --git a/src/kimchi/model/config.py b/src/kimchi/model/config.py index 73ca9c0..7479050 100644 --- a/src/kimchi/model/config.py +++ b/src/kimchi/model/config.py @@ -26,8 +26,8 @@ from kimchi.config import config as kconfig from kimchi.config import find_qemu_binary, get_version from kimchi.distroloader import DistroLoader from kimchi.exception import NotFoundError -from kimchi.featuretests import FeatureTests from kimchi.model.debugreports import DebugReportsModel +from kimchi.model.featuretests import FeatureTests from kimchi.repositories import Repositories from kimchi.screenshot import VMScreenshot from kimchi.swupdate import SoftwareUpdate diff --git a/src/kimchi/model/featuretests.py b/src/kimchi/model/featuretests.py new file mode 100644 index 0000000..c187f86 --- /dev/null +++ b/src/kimchi/model/featuretests.py @@ -0,0 +1,210 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013-2014 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# 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 cherrypy +import libvirt +import lxml.etree as ET +import socket +import subprocess +import threading + + +from lxml.builder import E + + +from kimchi.rollbackcontext import RollbackContext +from kimchi.utils import kimchi_log, run_command + + +ISO_STREAM_XML = """ +<domain type='%(domain)s'> + <name>ISO_STREAMING</name> + <memory unit='KiB'>1048576</memory> + <os> + <type>hvm</type> + <boot dev='cdrom'/> + </os> + <devices> + <disk type='network' device='cdrom'> + <driver name='qemu' type='raw'/> + <source protocol='%(protocol)s' name='/url/path/to/iso/file'> + <host name='host.name' port='1234'/> + </source> + <target dev='hdc' bus='ide'/> + <readonly/> + <alias name='ide0-1-0'/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + </devices> +</domain>""" + +SIMPLE_VM_XML = """ +<domain type='%(domain)s'> + <name>A_SIMPLE_VM</name> + <memory unit='KiB'>10240</memory> + <os> + <type>hvm</type> + <boot dev='hd'/> + </os> +</domain>""" + +SCSI_FC_XML = """ +<pool type='scsi'> + <name>TEST_SCSI_FC_POOL</name> + <source> + <adapter type='fc_host' wwnn='1234567890abcdef' wwpn='abcdef1234567890'/> + </source> + <target> + <path>/dev/disk/by-path</path> + </target> +</pool> +""" + + +class FeatureTests(object): + + @staticmethod + def disable_libvirt_error_logging(): + def libvirt_errorhandler(userdata, error): + # A libvirt error handler to ignore annoying messages in stderr + pass + + # Filter functions are enable only in production env + if cherrypy.config.get('environment') != 'production': + return + # Register the error handler to hide libvirt error in stderr + libvirt.registerErrorHandler(f=libvirt_errorhandler, ctx=None) + + @staticmethod + def enable_libvirt_error_logging(): + # Filter functions are enable only in production env + if cherrypy.config.get('environment') != 'production': + return + # Unregister the error handler + libvirt.registerErrorHandler(f=None, ctx=None) + + @staticmethod + def libvirt_supports_iso_stream(conn, protocol): + domain_type = 'test' if conn.getType().lower() == 'test' else 'kvm' + xml = ISO_STREAM_XML % {'domain': domain_type, 'protocol': protocol} + try: + FeatureTests.disable_libvirt_error_logging() + dom = conn.defineXML(xml) + dom.undefine() + return True + except libvirt.libvirtError, e: + kimchi_log.error(e.message) + return False + finally: + FeatureTests.enable_libvirt_error_logging() + + @staticmethod + def libvirt_support_nfs_probe(conn): + def _get_xml(): + obj = E.source(E.host(name='localhost'), E.format(type='nfs')) + xml = ET.tostring(obj) + return xml + try: + FeatureTests.disable_libvirt_error_logging() + conn.findStoragePoolSources('netfs', _get_xml(), 0) + except libvirt.libvirtError as e: + kimchi_log.error(e.message) + if e.get_error_code() == 38: + # if libvirt cannot find showmount, + # it returns 38--general system call failure + return False + finally: + FeatureTests.enable_libvirt_error_logging() + + return True + + @staticmethod + def qemu_supports_iso_stream(): + host = cherrypy.server.socket_host + port = cherrypy.server.socket_port + cmd = "qemu-io -r http://%s:%d/images/icon-fedora.png \ + -c 'read -v 0 512'" % (host, port) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=True) + stdout, stderr = proc.communicate() + return len(stderr) == 0 + + @staticmethod + def qemu_iso_stream_dns(): + host = socket.getfqdn(cherrypy.server.socket_host) + port = cherrypy.server.socket_port + cmd = ["qemu-io", "-r", "http://%s:%d/images/icon-fedora.png" % + (host, port), "-c", "'read -v 0 512'"] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + thread = threading.Thread(target=proc.communicate) + thread.start() + thread.join(5) + + if thread.is_alive(): + proc.kill() + thread.join() + return False + + if proc.returncode != 0: + return False + + return True + + @staticmethod + def libvirt_support_fc_host(conn): + try: + FeatureTests.disable_libvirt_error_logging() + pool = None + pool = conn.storagePoolDefineXML(SCSI_FC_XML, 0) + except libvirt.libvirtError as e: + if e.get_error_code() == 27: + # Libvirt requires adapter name, not needed when supports to FC + return False + finally: + FeatureTests.enable_libvirt_error_logging() + pool is None or pool.undefine() + return True + + @staticmethod + def has_metadata_support(conn): + KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi/" + KIMCHI_NAMESPACE = "kimchi" + with RollbackContext() as rollback: + FeatureTests.disable_libvirt_error_logging() + rollback.prependDefer(FeatureTests.enable_libvirt_error_logging) + domain_type = 'test' if conn.getType().lower() == 'test' else 'kvm' + dom = conn.defineXML(SIMPLE_VM_XML % {'domain': domain_type}) + rollback.prependDefer(dom.undefine) + try: + dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, + "<metatest/>", KIMCHI_NAMESPACE, + KIMCHI_META_URL, + flags=libvirt.VIR_DOMAIN_AFFECT_CURRENT) + return True + except libvirt.libvirtError: + return False + + @staticmethod + def kernel_support_vfio(): + out, err, rc = run_command(['modprobe', 'vfio-pci']) + if rc != 0: + kimchi_log.warning("Unable to load Kernal module vfio-pci.") + return False + return True diff --git a/src/kimchi/model/utils.py b/src/kimchi/model/utils.py index 5cc5075..7dcabf8 100644 --- a/src/kimchi/model/utils.py +++ b/src/kimchi/model/utils.py @@ -25,8 +25,8 @@ from lxml import etree from lxml.builder import E, ElementMaker from kimchi.exception import OperationFailed -from kimchi.featuretests import FeatureTests from kimchi.model.config import CapabilitiesModel +from kimchi.model.featuretests import FeatureTests KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi" KIMCHI_NAMESPACE = "kimchi" -- 1.9.3

Reviewed-by: Royce Lv<lvroyce@linux.vnet.ibm.com> On 2014年11月05日 07:27, Aline Manera wrote:
It is needed to make mockmodel uses model with 'test:///default' URI
Aline Manera (3): Update FeatureTests to use the same libvirt connection used by Model Set domain type in FeatureTests according libvirt URI Move featuretests.py to /model
src/kimchi/featuretests.py | 217 --------------------------------------- src/kimchi/model/config.py | 12 ++- src/kimchi/model/featuretests.py | 210 +++++++++++++++++++++++++++++++++++++ src/kimchi/model/utils.py | 2 +- 4 files changed, 218 insertions(+), 223 deletions(-) delete mode 100644 src/kimchi/featuretests.py create mode 100644 src/kimchi/model/featuretests.py
participants (2)
-
Aline Manera
-
Royce Lv