2014-02-06 15:12:12 +04:00
# Copyright (C) 2013, 2014 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
#
2018-04-04 16:35:41 +03:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 22:00:02 +03:00
# See the COPYING file in the top-level directory.
2013-03-18 01:06:52 +04:00
import difflib
import os
2018-02-22 22:57:10 +03:00
import sys
import unittest
import libvirt
2013-03-18 01:06:52 +04:00
import virtinst
2020-01-27 01:12:09 +03:00
from virtinst import cli
2015-09-22 18:34:15 +03:00
import virtinst . uri
2013-03-18 01:06:52 +04:00
2014-01-31 22:44:50 +04:00
2014-04-03 02:39:43 +04:00
# pylint: disable=protected-access
2013-04-12 00:32:00 +04:00
# Access to protected member, needed to unittest stuff
2020-07-17 23:02:45 +03:00
class _TestConfig ( object ) :
2018-01-09 01:05:55 +03:00
"""
Class containing any bits passed in from setup . py
"""
def __init__ ( self ) :
self . regenerate_output = False
2018-02-22 21:46:24 +03:00
self . debug = False
2020-07-17 22:59:11 +03:00
self . skip_checkprops = False
2019-03-24 18:22:50 +03:00
self . url_only = False
self . url_iso_only = False
self . url_skip_libosinfo = False
self . url_force_libosinfo = False
2020-07-17 23:02:45 +03:00
TESTCONFIG = _TestConfig ( )
2018-01-09 01:05:55 +03:00
2018-10-05 02:18:27 +03:00
def has_old_osinfo ( ) :
# Some tests rely on newer osinfo data. Check for a new condition
# here, and older tests will be skipped
2018-10-13 23:33:37 +03:00
osname = " centos7.0 "
2018-10-05 02:18:27 +03:00
if not virtinst . OSDB . lookup_os ( osname ) :
return True
2018-10-04 21:59:54 +03:00
return not virtinst . OSDB . lookup_os ( osname ) . supports_chipset_q35 ( )
2018-10-05 02:18:27 +03:00
2018-02-22 22:57:10 +03:00
class _URIs ( object ) :
def __init__ ( self ) :
self . _conn_cache = { }
self . _testdriver_cache = None
self . _testdriver_error = None
self . _testdriver_default = None
2020-01-27 02:11:43 +03:00
_capspath = " %s /tests/data/capabilities/ " % os . getcwd ( )
2018-06-12 18:48:11 +03:00
def _domcaps ( path ) :
return " ,domcaps= " + _capspath + path
def _caps ( path ) :
return " ,caps= " + _capspath + path
_testtmpl = " __virtinst_test__test:// %s ,predictable "
self . test_default = _testtmpl % " /default "
2020-08-24 20:34:15 +03:00
_testdriverdir = ( os . path . dirname ( __file__ ) + " /data/testdriver/ " )
self . test_full = _testtmpl % ( _testdriverdir + " testdriver.xml " )
self . test_suite = _testtmpl % ( _testdriverdir + " testsuite.xml " )
self . test_defaultpool_collision = _testtmpl % (
_testdriverdir + " defaultpool-collision.xml " )
2020-08-24 20:35:54 +03:00
self . test_empty = _testtmpl % ( _testdriverdir + " empty.xml " )
2020-08-24 20:34:15 +03:00
2020-02-03 02:16:48 +03:00
def _m ( fakeuri ) :
return self . test_full + " ,fakeuri= %s " % fakeuri
self . test_remote = _m ( " test+tls://fakeuri.example.com/ " )
self . xen = _m ( " xen:/// " ) + _caps ( " xen-rhel5.4.xml " )
self . lxc = _m ( " lxc:/// " ) + _caps ( " lxc.xml " )
self . vz = _m ( " vz:/// " ) + _caps ( " vz.xml " )
_uri_qemu = _m ( " qemu:///system " )
_kvm_x86_caps = _caps ( " kvm-x86_64.xml " ) + _domcaps ( " kvm-x86_64-domcaps.xml " )
self . kvm = _uri_qemu + _kvm_x86_caps
self . kvm_remote = _m ( " qemu+tls://fakeuri.example.com/system " ) + _kvm_x86_caps
self . kvm_session = _m ( " qemu:///session " ) + _kvm_x86_caps
2018-06-12 18:48:11 +03:00
2020-02-03 02:16:48 +03:00
_uri_kvm = _uri_qemu + _kvm_x86_caps
2019-04-11 15:47:00 +03:00
_uri_kvm_rhel7 = _uri_qemu + _domcaps ( " kvm-x86_64-rhel7-domcaps.xml " )
2018-06-12 18:48:11 +03:00
_uri_kvm_q35 = _uri_qemu + _domcaps ( " kvm-x86_64-domcaps-q35.xml " )
2019-06-11 18:41:56 +03:00
_uri_kvm_amd_sev = _uri_qemu + _domcaps ( " kvm-x86_64-domcaps-amd-sev.xml " )
2018-06-12 18:48:11 +03:00
_uri_kvm_aarch64 = _uri_qemu + _domcaps ( " kvm-aarch64-domcaps.xml " )
2019-04-04 13:49:42 +03:00
_uri_qemu_riscv64 = _uri_qemu + _domcaps ( " qemu-riscv64-domcaps.xml " )
2018-06-12 18:48:11 +03:00
self . kvm_nodomcaps = _uri_qemu + _caps ( " kvm-x86_64.xml " )
2019-04-11 15:47:00 +03:00
self . kvm_rhel = _uri_kvm_rhel7 + _caps ( " kvm-x86_64-rhel7.xml " )
2018-06-12 18:48:11 +03:00
self . kvm_q35 = _uri_kvm_q35 + _caps ( " kvm-x86_64.xml " )
2019-06-11 18:41:56 +03:00
self . kvm_amd_sev = _uri_kvm_amd_sev + _caps ( " kvm-x86_64.xml " )
2018-06-12 18:48:11 +03:00
2018-08-31 23:47:10 +03:00
self . kvm_armv7l_nodomcaps = _uri_qemu + _caps ( " kvm-armv7l.xml " )
2020-02-03 13:58:04 +03:00
self . kvm_armv7l = self . kvm_armv7l_nodomcaps + _domcaps ( " kvm-armv7l-domcaps.xml " )
self . kvm_aarch64 = _uri_kvm_aarch64 + _caps ( " kvm-aarch64.xml " ) + _domcaps ( " kvm-aarch64-domcaps.xml " )
2018-06-12 18:48:11 +03:00
self . kvm_ppc64le = _uri_kvm + _caps ( " kvm-ppc64le.xml " )
self . kvm_s390x = _uri_kvm + _caps ( " kvm-s390x.xml " )
self . kvm_s390x_KVMIBM = _uri_kvm + _caps ( " kvm-s390x-KVMIBM.xml " )
2019-04-04 13:49:42 +03:00
self . qemu_riscv64 = _uri_qemu_riscv64 + _caps ( " qemu-riscv64.xml " )
2018-06-12 18:48:11 +03:00
2018-02-22 22:57:10 +03:00
def openconn ( self , uri ) :
"""
Extra super caching to speed up the test suite . We basically
cache the first guest / pool / vol poll attempt for each URI , and save it
across multiple reopenings of that connection . We aren ' t caching
libvirt objects , just parsed XML objects . This works fine since
generally every test uses a fresh virConnect , or undoes the
persistent changes it makes .
"""
is_testdriver_xml = " /testdriver.xml " in uri
if not ( is_testdriver_xml and self . _testdriver_error ) :
try :
2020-01-27 01:12:09 +03:00
conn = cli . getConnection ( uri )
2018-02-22 22:57:10 +03:00
except libvirt . libvirtError as e :
if not is_testdriver_xml :
raise
self . _testdriver_error = (
" error opening testdriver.xml: %s \n "
" libvirt is probably too old " % str ( e ) )
print ( self . _testdriver_error , file = sys . stderr )
if is_testdriver_xml and self . _testdriver_error :
raise unittest . SkipTest ( self . _testdriver_error )
uri = conn . _open_uri
# For the basic test:///default URI, skip this caching, so we have
# an option to test the stock code
2018-06-12 18:48:11 +03:00
if uri == self . test_default :
2018-02-22 22:57:10 +03:00
return conn
if uri not in self . _conn_cache :
2018-08-31 22:20:50 +03:00
conn . fetch_all_domains ( )
2018-02-22 22:57:10 +03:00
conn . fetch_all_pools ( )
conn . fetch_all_vols ( )
conn . fetch_all_nodedevs ( )
self . _conn_cache [ uri ] = { }
for key , value in conn . _fetch_cache . items ( ) :
self . _conn_cache [ uri ] [ key ] = value [ : ]
# Prime the internal connection cache
for key , value in self . _conn_cache [ uri ] . items ( ) :
conn . _fetch_cache [ key ] = value [ : ]
def cb_cache_new_pool ( poolobj ) :
# Used by clonetest.py nvram-newpool test
if poolobj . name ( ) == " nvram-newpool " :
from virtinst import StorageVolume
vol = StorageVolume ( conn )
vol . pool = poolobj
vol . name = " clone-orig-vars.fd "
vol . capacity = 1024 * 1024
vol . install ( )
conn . _cache_new_pool_raw ( poolobj )
conn . cb_cache_new_pool = cb_cache_new_pool
2013-09-29 05:03:03 +04:00
2017-08-30 17:36:37 +03:00
return conn
2018-02-22 22:57:10 +03:00
def open_testdriver_cached ( self ) :
"""
Open plain testdriver . xml and cache the instance . Tests that
use this are expected to clean up after themselves so driver
state doesn ' t become polluted.
"""
if not self . _testdriver_cache :
2018-06-12 18:48:11 +03:00
self . _testdriver_cache = self . openconn ( self . test_full )
2018-02-22 22:57:10 +03:00
return self . _testdriver_cache
def open_testdefault_cached ( self ) :
if not self . _testdriver_default :
2018-06-12 18:48:11 +03:00
self . _testdriver_default = self . openconn ( self . test_default )
2018-02-22 22:57:10 +03:00
return self . _testdriver_default
2019-06-09 23:39:15 +03:00
def open_kvm ( self ) :
return self . openconn ( self . kvm )
2018-02-22 22:57:10 +03:00
def open_test_remote ( self ) :
2018-06-12 18:48:11 +03:00
return self . openconn ( self . test_remote )
2018-02-22 22:57:10 +03:00
URIs = _URIs ( )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2013-09-10 01:14:16 +04:00
def test_create ( testconn , xml , define_func = " defineXML " ) :
2015-09-22 18:34:15 +03:00
xml = virtinst . uri . sanitize_xml_for_test_define ( xml )
2013-03-18 01:06:52 +04:00
2013-06-14 22:58:52 +04:00
try :
2013-09-10 01:14:16 +04:00
func = getattr ( testconn , define_func )
obj = func ( xml )
2017-05-05 19:47:21 +03:00
except Exception as e :
2013-06-14 22:58:52 +04:00
raise RuntimeError ( str ( e ) + " \n " + xml )
2013-03-18 01:06:52 +04:00
try :
2013-09-10 01:14:16 +04:00
obj . create ( )
obj . destroy ( )
obj . undefine ( )
2017-07-24 11:26:48 +03:00
except Exception :
2013-03-18 01:06:52 +04:00
try :
2013-09-10 01:14:16 +04:00
obj . destroy ( )
2017-07-24 11:26:48 +03:00
except Exception :
2013-03-18 01:06:52 +04:00
pass
try :
2013-09-10 01:14:16 +04:00
obj . undefine ( )
2017-07-24 11:26:48 +03:00
except Exception :
2013-03-18 01:06:52 +04:00
pass
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def diff_compare ( actual_out , filename = None , expect_out = None ) :
""" Compare passed string output to contents of filename """
if not expect_out :
2020-07-17 23:02:45 +03:00
if not os . path . exists ( filename ) or TESTCONFIG . regenerate_output :
2017-05-05 21:19:54 +03:00
open ( filename , " w " ) . write ( actual_out )
2018-06-12 18:37:02 +03:00
expect_out = open ( filename ) . read ( )
2013-03-18 01:06:52 +04:00
diff = " " . join ( difflib . unified_diff ( expect_out . splitlines ( 1 ) ,
actual_out . splitlines ( 1 ) ,
2017-10-11 14:35:54 +03:00
fromfile = filename or ' ' ,
2013-03-18 01:06:52 +04:00
tofile = " Generated Output " ) )
if diff :
raise AssertionError ( " Conversion outputs did not match. \n %s " % diff )
2019-06-08 16:11:00 +03:00
def run_without_testsuite_hacks ( cb ) :
"""
Decorator for unsetting the test suite env variable
"""
def wrapper_cb ( * args , * * kwargs ) :
origval = os . environ . pop ( " VIRTINST_TEST_SUITE " , None )
try :
return cb ( * args , * * kwargs )
finally :
if origval :
os . environ [ " VIRTINST_TEST_SUITE " ] = origval
return wrapper_cb