Accepting request 709997 from systemsmanagement:saltstack
- Fix zypper pkg.list_pkgs test expectation and dpkg mocking - Added: * fix-zypper-pkg.list_pkgs-expectation-and-dpkg-mockin.patch - Set 'salt' group for files and directories created by salt-standalone-formulas-configuration package - Various fixes for virt module - Fix virt.volume_infos raising an exception when there is only virtual machine on the minion. - Fix virt.purge() on all non-KVM hypervisors. For instance on Xen, virt.purge would simply throw an exception about unsupported flag - Building a libvirt pool starts it. When defining a new pool, we need to let build start it or we will get libvirt errors. - Fix handling of Virtual Machines with white space in their name. - Added: * virt.pool_running-fix-pool-start.patch * virt-handle-whitespaces-in-vm-names.patch * virt.volume_infos-fix-for-single-vm.patch * try-except-undefineflags-as-this-operation-is-not-su.patch - avoid batch.py exception when minion does not respond (bsc#1135507) - Added: * batch.py-avoid-exception-when-minion-does-not-respon.patch - Preserve already defined DESTRUCTIVE_TESTS and EXPENSIVE_TESTS env variables - Added: * preserve-already-defined-destructive_tests-and-expen.patch - Do not break repo files with multiple line values on yumpkg (bsc#1135360) - Added: * do-not-break-repo-files-with-multiple-line-values-on.patch OBS-URL: https://build.opensuse.org/request/show/709997 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=87
This commit is contained in:
commit
6c99feee82
@ -1 +1 @@
|
||||
6ea034113af0bc6f97110175d633bdf951af0fcd
|
||||
1d301081a6e8a705499eb861b24c46ab17120691
|
42
batch.py-avoid-exception-when-minion-does-not-respon.patch
Normal file
42
batch.py-avoid-exception-when-minion-does-not-respon.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From 50377852ca989ffa141fcf32d5ca57d120b455b8 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jos=C3=A9=20Guilherme=20Vanz?= <jvanz@jvanz.com>
|
||||
Date: Tue, 21 May 2019 16:13:18 -0300
|
||||
Subject: [PATCH] batch.py: avoid exception when minion does not respond
|
||||
(bsc#1135507)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We have several issues reporting that salt is throwing exception when
|
||||
the minion does not respond. This change avoid the exception adding a
|
||||
default data to the minion when it fails to respond. This patch based
|
||||
on the patch suggested by @roskens.
|
||||
|
||||
Issues #46876 #48509 #50238
|
||||
bsc#1135507
|
||||
|
||||
Signed-off-by: José Guilherme Vanz <jguilhermevanz@suse.com>
|
||||
---
|
||||
salt/cli/batch.py | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/salt/cli/batch.py b/salt/cli/batch.py
|
||||
index ce239215cb..1623fc5be8 100644
|
||||
--- a/salt/cli/batch.py
|
||||
+++ b/salt/cli/batch.py
|
||||
@@ -315,6 +315,11 @@ class Batch(object):
|
||||
if self.opts.get('failhard') and data['ret']['retcode'] > 0:
|
||||
failhard = True
|
||||
|
||||
+ # avoid an exception if the minion does not respond.
|
||||
+ if data.get("failed") is True:
|
||||
+ log.debug('Minion %s failed to respond: data=%s', minion, data)
|
||||
+ data = {'ret': 'Minion did not return. [Failed]', 'retcode': salt.defaults.exitcodes.EX_GENERIC}
|
||||
+
|
||||
if self.opts.get('raw'):
|
||||
ret[minion] = data
|
||||
yield data
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
111
do-not-break-repo-files-with-multiple-line-values-on.patch
Normal file
111
do-not-break-repo-files-with-multiple-line-values-on.patch
Normal file
@ -0,0 +1,111 @@
|
||||
From b99e55aab52d086315d54cf44af68f40dcf79dc9 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||
<psuarezhernandez@suse.com>
|
||||
Date: Wed, 29 May 2019 11:03:16 +0100
|
||||
Subject: [PATCH] Do not break repo files with multiple line values on
|
||||
yumpkg (bsc#1135360)
|
||||
|
||||
---
|
||||
salt/modules/yumpkg.py | 16 ++++++---
|
||||
tests/integration/modules/test_pkg.py | 48 +++++++++++++++++++++++++++
|
||||
2 files changed, 60 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
||||
index 5ec3835574..3a4fe47a45 100644
|
||||
--- a/salt/modules/yumpkg.py
|
||||
+++ b/salt/modules/yumpkg.py
|
||||
@@ -2763,7 +2763,12 @@ def del_repo(repo, basedir=None, **kwargs): # pylint: disable=W0613
|
||||
del filerepos[stanza]['comments']
|
||||
content += '\n[{0}]'.format(stanza)
|
||||
for line in filerepos[stanza]:
|
||||
- content += '\n{0}={1}'.format(line, filerepos[stanza][line])
|
||||
+ # A whitespace is needed at the begining of the new line in order
|
||||
+ # to avoid breaking multiple line values allowed on repo files.
|
||||
+ value = filerepos[stanza][line]
|
||||
+ if isinstance(value, six.string_types) and '\n' in value:
|
||||
+ value = '\n '.join(value.split('\n'))
|
||||
+ content += '\n{0}={1}'.format(line, value)
|
||||
content += '\n{0}\n'.format(comments)
|
||||
|
||||
with salt.utils.files.fopen(repofile, 'w') as fileout:
|
||||
@@ -2898,11 +2903,14 @@ def mod_repo(repo, basedir=None, **kwargs):
|
||||
)
|
||||
content += '[{0}]\n'.format(stanza)
|
||||
for line in six.iterkeys(filerepos[stanza]):
|
||||
+ # A whitespace is needed at the begining of the new line in order
|
||||
+ # to avoid breaking multiple line values allowed on repo files.
|
||||
+ value = filerepos[stanza][line]
|
||||
+ if isinstance(value, six.string_types) and '\n' in value:
|
||||
+ value = '\n '.join(value.split('\n'))
|
||||
content += '{0}={1}\n'.format(
|
||||
line,
|
||||
- filerepos[stanza][line]
|
||||
- if not isinstance(filerepos[stanza][line], bool)
|
||||
- else _bool_to_str(filerepos[stanza][line])
|
||||
+ value if not isinstance(value, bool) else _bool_to_str(value)
|
||||
)
|
||||
content += comments + '\n'
|
||||
|
||||
diff --git a/tests/integration/modules/test_pkg.py b/tests/integration/modules/test_pkg.py
|
||||
index 0271cea81f..a82c9662c7 100644
|
||||
--- a/tests/integration/modules/test_pkg.py
|
||||
+++ b/tests/integration/modules/test_pkg.py
|
||||
@@ -123,6 +123,54 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
if repo is not None:
|
||||
self.run_function('pkg.del_repo', [repo])
|
||||
|
||||
+ def test_mod_del_repo_multiline_values(self):
|
||||
+ '''
|
||||
+ test modifying and deleting a software repository defined with multiline values
|
||||
+ '''
|
||||
+ os_grain = self.run_function('grains.item', ['os'])['os']
|
||||
+ repo = None
|
||||
+ try:
|
||||
+ if os_grain in ['CentOS', 'RedHat', 'SUSE']:
|
||||
+ my_baseurl = 'http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/'
|
||||
+ expected_get_repo_baseurl = 'http://my.fake.repo/foo/bar/\nhttp://my.fake.repo.alt/foo/bar/'
|
||||
+ major_release = int(
|
||||
+ self.run_function(
|
||||
+ 'grains.item',
|
||||
+ ['osmajorrelease']
|
||||
+ )['osmajorrelease']
|
||||
+ )
|
||||
+ repo = 'fakerepo'
|
||||
+ name = 'Fake repo for RHEL/CentOS/SUSE'
|
||||
+ baseurl = my_baseurl
|
||||
+ gpgkey = 'https://my.fake.repo/foo/bar/MY-GPG-KEY.pub'
|
||||
+ failovermethod = 'priority'
|
||||
+ gpgcheck = 1
|
||||
+ enabled = 1
|
||||
+ ret = self.run_function(
|
||||
+ 'pkg.mod_repo',
|
||||
+ [repo],
|
||||
+ name=name,
|
||||
+ baseurl=baseurl,
|
||||
+ gpgkey=gpgkey,
|
||||
+ gpgcheck=gpgcheck,
|
||||
+ enabled=enabled,
|
||||
+ failovermethod=failovermethod,
|
||||
+ )
|
||||
+ # return data from pkg.mod_repo contains the file modified at
|
||||
+ # the top level, so use next(iter(ret)) to get that key
|
||||
+ self.assertNotEqual(ret, {})
|
||||
+ repo_info = ret[next(iter(ret))]
|
||||
+ self.assertIn(repo, repo_info)
|
||||
+ self.assertEqual(repo_info[repo]['baseurl'], my_baseurl)
|
||||
+ ret = self.run_function('pkg.get_repo', [repo])
|
||||
+ self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
|
||||
+ self.run_function('pkg.mod_repo', [repo])
|
||||
+ ret = self.run_function('pkg.get_repo', [repo])
|
||||
+ self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
|
||||
+ finally:
|
||||
+ if repo is not None:
|
||||
+ self.run_function('pkg.del_repo', [repo])
|
||||
+
|
||||
@requires_salt_modules('pkg.owner')
|
||||
def test_owner(self):
|
||||
'''
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
57
fix-zypper-pkg.list_pkgs-expectation-and-dpkg-mockin.patch
Normal file
57
fix-zypper-pkg.list_pkgs-expectation-and-dpkg-mockin.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From 8c4066c668147b1180c56f39722d2ade78ffd41c Mon Sep 17 00:00:00 2001
|
||||
From: Mihai Dinca <mdinca@suse.de>
|
||||
Date: Thu, 13 Jun 2019 17:48:55 +0200
|
||||
Subject: [PATCH] Fix zypper pkg.list_pkgs expectation and dpkg mocking
|
||||
|
||||
---
|
||||
tests/unit/modules/test_dpkg_lowpkg.py | 12 ++++++------
|
||||
tests/unit/modules/test_zypperpkg.py | 2 +-
|
||||
2 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/tests/unit/modules/test_dpkg_lowpkg.py b/tests/unit/modules/test_dpkg_lowpkg.py
|
||||
index d16ce3cc1a..98557a1d10 100644
|
||||
--- a/tests/unit/modules/test_dpkg_lowpkg.py
|
||||
+++ b/tests/unit/modules/test_dpkg_lowpkg.py
|
||||
@@ -127,9 +127,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch.dict(dpkg.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertEqual(dpkg.file_dict('httpd'), 'Error: error')
|
||||
|
||||
- @patch('salt.modules.dpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
||||
- @patch('salt.modules.dpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
||||
- @patch('salt.modules.dpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
||||
def test_info(self):
|
||||
'''
|
||||
Test info
|
||||
@@ -154,9 +154,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
|
||||
assert pkg_data['maintainer'] == 'Simpsons Developers <simpsons-devel-discuss@lists.springfield.org>'
|
||||
assert pkg_data['license'] == 'BSD v3'
|
||||
|
||||
- @patch('salt.modules.dpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
||||
- @patch('salt.modules.dpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
||||
- @patch('salt.modules.dpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
||||
def test_info_attr(self):
|
||||
'''
|
||||
Test info with 'attr' parameter
|
||||
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
||||
index 5c5091a570..a7063e47c6 100644
|
||||
--- a/tests/unit/modules/test_zypperpkg.py
|
||||
+++ b/tests/unit/modules/test_zypperpkg.py
|
||||
@@ -659,7 +659,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
||||
'install_date_time_t': 1503572639,
|
||||
'epoch': None,
|
||||
}],
|
||||
- 'perseus-dummy.i586': [{
|
||||
+ 'perseus-dummy': [{
|
||||
'version': '1.1',
|
||||
'release': '1.1',
|
||||
'arch': 'i586',
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
34
preserve-already-defined-destructive_tests-and-expen.patch
Normal file
34
preserve-already-defined-destructive_tests-and-expen.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 5a1e0b7b8eab900e03fa800cc7a0a2b59bf2ff55 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||
<psuarezhernandez@suse.com>
|
||||
Date: Mon, 3 Jun 2019 11:38:36 +0100
|
||||
Subject: [PATCH] Preserve already defined DESTRUCTIVE_TESTS and
|
||||
EXPENSIVE_TESTS env variables
|
||||
|
||||
---
|
||||
tests/support/parser/__init__.py | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/support/parser/__init__.py b/tests/support/parser/__init__.py
|
||||
index ed262d46c0..f269457670 100644
|
||||
--- a/tests/support/parser/__init__.py
|
||||
+++ b/tests/support/parser/__init__.py
|
||||
@@ -574,12 +574,12 @@ class SaltTestingParser(optparse.OptionParser):
|
||||
|
||||
self.validate_options()
|
||||
|
||||
- if self.support_destructive_tests_selection:
|
||||
+ if self.support_destructive_tests_selection and not os.environ.get('DESTRUCTIVE_TESTS', None):
|
||||
# Set the required environment variable in order to know if
|
||||
# destructive tests should be executed or not.
|
||||
os.environ['DESTRUCTIVE_TESTS'] = str(self.options.run_destructive)
|
||||
|
||||
- if self.support_expensive_tests_selection:
|
||||
+ if self.support_expensive_tests_selection and not os.environ.get('EXPENSIVE_TESTS', None):
|
||||
# Set the required environment variable in order to know if
|
||||
# expensive tests should be executed or not.
|
||||
os.environ['EXPENSIVE_TESTS'] = str(self.options.run_expensive)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
51
salt.changes
51
salt.changes
@ -1,3 +1,54 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Jun 14 14:09:29 UTC 2019 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
||||
- Fix zypper pkg.list_pkgs test expectation and dpkg mocking
|
||||
|
||||
- Added:
|
||||
* fix-zypper-pkg.list_pkgs-expectation-and-dpkg-mockin.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Jun 14 12:15:43 UTC 2019 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
||||
- Set 'salt' group for files and directories created by
|
||||
salt-standalone-formulas-configuration package
|
||||
- Various fixes for virt module
|
||||
- Fix virt.volume_infos raising an exception when there is only virtual machine on the minion.
|
||||
- Fix virt.purge() on all non-KVM hypervisors. For instance on Xen, virt.purge would simply throw an exception about unsupported flag
|
||||
- Building a libvirt pool starts it. When defining a new pool, we need to
|
||||
let build start it or we will get libvirt errors.
|
||||
- Fix handling of Virtual Machines with white space in their name.
|
||||
|
||||
- Added:
|
||||
* virt.pool_running-fix-pool-start.patch
|
||||
* virt-handle-whitespaces-in-vm-names.patch
|
||||
* virt.volume_infos-fix-for-single-vm.patch
|
||||
* try-except-undefineflags-as-this-operation-is-not-su.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Jun 5 14:26:29 UTC 2019 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
||||
- avoid batch.py exception when minion does not respond (bsc#1135507)
|
||||
|
||||
- Added:
|
||||
* batch.py-avoid-exception-when-minion-does-not-respon.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jun 3 11:01:57 UTC 2019 - psuarezhernandez@suse.com
|
||||
|
||||
- Preserve already defined DESTRUCTIVE_TESTS and EXPENSIVE_TESTS
|
||||
env variables
|
||||
|
||||
- Added:
|
||||
* preserve-already-defined-destructive_tests-and-expen.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed May 29 10:54:42 UTC 2019 - psuarezhernandez@suse.com
|
||||
|
||||
- Do not break repo files with multiple line values on yumpkg (bsc#1135360)
|
||||
|
||||
- Added:
|
||||
* do-not-break-repo-files-with-multiple-line-values-on.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri May 24 16:03:09 UTC 2019 - psuarezhernandez@suse.com
|
||||
|
||||
|
32
salt.spec
32
salt.spec
@ -180,6 +180,22 @@ Patch55: switch-firewalld-state-to-use-change_interface.patch
|
||||
Patch56: add-standalone-configuration-file-for-enabling-packa.patch
|
||||
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/53237
|
||||
Patch57: add-ppc64le-as-a-valid-rpm-package-architecture.patch
|
||||
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/53293
|
||||
Patch58: do-not-break-repo-files-with-multiple-line-values-on.patch
|
||||
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/53343
|
||||
Patch59: preserve-already-defined-destructive_tests-and-expen.patch
|
||||
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/53159
|
||||
Patch60: batch.py-avoid-exception-when-minion-does-not-respon.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/53471
|
||||
Patch61: fix-zypper-pkg.list_pkgs-expectation-and-dpkg-mockin.patch
|
||||
# PATCH_FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/142
|
||||
Patch62: try-except-undefineflags-as-this-operation-is-not-su.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/52160
|
||||
Patch63: virt-handle-whitespaces-in-vm-names.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/52341
|
||||
Patch64: virt.pool_running-fix-pool-start.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/52414
|
||||
Patch65: virt.volume_infos-fix-for-single-vm.patch
|
||||
|
||||
# BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
@ -707,6 +723,14 @@ cp %{S:5} ./.travis.yml
|
||||
%patch55 -p1
|
||||
%patch56 -p1
|
||||
%patch57 -p1
|
||||
%patch58 -p1
|
||||
%patch59 -p1
|
||||
%patch60 -p1
|
||||
%patch61 -p1
|
||||
%patch62 -p1
|
||||
%patch63 -p1
|
||||
%patch64 -p1
|
||||
%patch65 -p1
|
||||
|
||||
%build
|
||||
%if 0%{?build_py2}
|
||||
@ -1426,10 +1450,10 @@ rm -f %{_localstatedir}/cache/salt/minion/thin/version
|
||||
|
||||
%files standalone-formulas-configuration
|
||||
%defattr(-,root,root)
|
||||
%config(noreplace) %attr(0640, root, root) %{_sysconfdir}/salt/master.d/standalone-formulas-configuration.conf
|
||||
%dir %attr(0750, root, root) %{_prefix}/share/salt-formulas/
|
||||
%dir %attr(0750, root, root) %{_prefix}/share/salt-formulas/states/
|
||||
%dir %attr(0750, root, root) %{_prefix}/share/salt-formulas/metadata/
|
||||
%config(noreplace) %attr(0640, root, salt) %{_sysconfdir}/salt/master.d/standalone-formulas-configuration.conf
|
||||
%dir %attr(0750, root, salt) %{_prefix}/share/salt-formulas/
|
||||
%dir %attr(0750, root, salt) %{_prefix}/share/salt-formulas/states/
|
||||
%dir %attr(0750, root, salt) %{_prefix}/share/salt-formulas/metadata/
|
||||
|
||||
%changelog
|
||||
|
||||
|
31
try-except-undefineflags-as-this-operation-is-not-su.patch
Normal file
31
try-except-undefineflags-as-this-operation-is-not-su.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From e0bded83fa691c3b972fa4c22b14c5ac0a7a3f13 Mon Sep 17 00:00:00 2001
|
||||
From: Jeroen Schutrup <jeroenschutrup@hotmail.nl>
|
||||
Date: Sun, 12 Aug 2018 19:43:22 +0200
|
||||
Subject: [PATCH] Try/except undefineFlags() as this operation is not
|
||||
supported on bhyve
|
||||
|
||||
(cherry picked from commit 29a44aceb1a73347ac07dd241b4a64a4a38cef6e)
|
||||
---
|
||||
salt/modules/virt.py | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||
index a3f625909d..423016cd90 100644
|
||||
--- a/salt/modules/virt.py
|
||||
+++ b/salt/modules/virt.py
|
||||
@@ -3189,7 +3189,10 @@ def purge(vm_, dirs=False, removables=None, **kwargs):
|
||||
shutil.rmtree(dir_)
|
||||
if getattr(libvirt, 'VIR_DOMAIN_UNDEFINE_NVRAM', False):
|
||||
# This one is only in 1.2.8+
|
||||
- dom.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_NVRAM)
|
||||
+ try:
|
||||
+ dom.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_NVRAM)
|
||||
+ except Exception:
|
||||
+ dom.undefine()
|
||||
else:
|
||||
dom.undefine()
|
||||
conn.close()
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
243
virt-handle-whitespaces-in-vm-names.patch
Normal file
243
virt-handle-whitespaces-in-vm-names.patch
Normal file
@ -0,0 +1,243 @@
|
||||
From fbad82a38b4460260726cb3b9456cad7986eb4cd Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
||||
Date: Wed, 13 Mar 2019 09:43:51 +0100
|
||||
Subject: [PATCH] virt: handle whitespaces in VM names
|
||||
|
||||
The disk creation code is now ready to handle whitespaces in virtual
|
||||
machine name.
|
||||
---
|
||||
salt/modules/virt.py | 8 +++---
|
||||
tests/unit/modules/test_virt.py | 46 ++++++++++++++++-----------------
|
||||
2 files changed, 27 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||
index 423016cd90..d160f0905f 100644
|
||||
--- a/salt/modules/virt.py
|
||||
+++ b/salt/modules/virt.py
|
||||
@@ -760,14 +760,14 @@ def _qemu_image_create(disk, create_overlay=False, saltenv='base'):
|
||||
|
||||
qcow2 = False
|
||||
if salt.utils.path.which('qemu-img'):
|
||||
- res = __salt__['cmd.run']('qemu-img info {}'.format(sfn))
|
||||
+ res = __salt__['cmd.run']('qemu-img info "{}"'.format(sfn))
|
||||
imageinfo = salt.utils.yaml.safe_load(res)
|
||||
qcow2 = imageinfo['file format'] == 'qcow2'
|
||||
try:
|
||||
if create_overlay and qcow2:
|
||||
log.info('Cloning qcow2 image %s using copy on write', sfn)
|
||||
__salt__['cmd.run'](
|
||||
- 'qemu-img create -f qcow2 -o backing_file={0} {1}'
|
||||
+ 'qemu-img create -f qcow2 -o backing_file="{0}" "{1}"'
|
||||
.format(sfn, img_dest).split())
|
||||
else:
|
||||
log.debug('Copying %s to %s', sfn, img_dest)
|
||||
@@ -778,7 +778,7 @@ def _qemu_image_create(disk, create_overlay=False, saltenv='base'):
|
||||
if disk_size and qcow2:
|
||||
log.debug('Resize qcow2 image to %sM', disk_size)
|
||||
__salt__['cmd.run'](
|
||||
- 'qemu-img resize {0} {1}M'
|
||||
+ 'qemu-img resize "{0}" {1}M'
|
||||
.format(img_dest, disk_size)
|
||||
)
|
||||
|
||||
@@ -800,7 +800,7 @@ def _qemu_image_create(disk, create_overlay=False, saltenv='base'):
|
||||
if disk_size:
|
||||
log.debug('Create empty image with size %sM', disk_size)
|
||||
__salt__['cmd.run'](
|
||||
- 'qemu-img create -f {0} {1} {2}M'
|
||||
+ 'qemu-img create -f {0} "{1}" {2}M'
|
||||
.format(disk.get('format', 'qcow2'), img_dest, disk_size)
|
||||
)
|
||||
else:
|
||||
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
||||
index bbe8d813d7..cc62b67918 100644
|
||||
--- a/tests/unit/modules/test_virt.py
|
||||
+++ b/tests/unit/modules/test_virt.py
|
||||
@@ -1106,7 +1106,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch.dict(virt.__salt__, {'cmd.run': mock_run}): # pylint: disable=no-member
|
||||
|
||||
# Ensure the init() function allows creating VM without NIC and disk
|
||||
- virt.init('testvm',
|
||||
+ virt.init('test vm',
|
||||
2,
|
||||
1234,
|
||||
nic=None,
|
||||
@@ -1120,7 +1120,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
# Test case creating disks
|
||||
defineMock.reset_mock()
|
||||
mock_run.reset_mock()
|
||||
- virt.init('testvm',
|
||||
+ virt.init('test vm',
|
||||
2,
|
||||
1234,
|
||||
nic=None,
|
||||
@@ -1134,10 +1134,10 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
definition = ET.fromstring(defineMock.call_args_list[0][0][0])
|
||||
disk_sources = [disk.find('source').get('file') if disk.find('source') is not None else None
|
||||
for disk in definition.findall('./devices/disk')]
|
||||
- expected_disk_path = os.path.join(root_dir, 'testvm_system.qcow2')
|
||||
+ expected_disk_path = os.path.join(root_dir, 'test vm_system.qcow2')
|
||||
self.assertEqual(disk_sources, [expected_disk_path, None])
|
||||
self.assertEqual(mock_run.call_args[0][0],
|
||||
- 'qemu-img create -f qcow2 {0} 10240M'.format(expected_disk_path))
|
||||
+ 'qemu-img create -f qcow2 "{0}" 10240M'.format(expected_disk_path))
|
||||
self.assertEqual(mock_chmod.call_args[0][0], expected_disk_path)
|
||||
|
||||
def test_update(self):
|
||||
@@ -1147,7 +1147,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
root_dir = os.path.join(salt.syspaths.ROOT_DIR, 'srv', 'salt-images')
|
||||
xml = '''
|
||||
<domain type='kvm' id='7'>
|
||||
- <name>myvm</name>
|
||||
+ <name>my vm</name>
|
||||
<memory unit='KiB'>1048576</memory>
|
||||
<currentMemory unit='KiB'>1048576</currentMemory>
|
||||
<vcpu placement='auto'>1</vcpu>
|
||||
@@ -1157,7 +1157,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='qcow2'/>
|
||||
- <source file='{0}{1}myvm_system.qcow2'/>
|
||||
+ <source file='{0}{1}my vm_system.qcow2'/>
|
||||
<backingStore/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
<alias name='virtio-disk0'/>
|
||||
@@ -1165,7 +1165,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
</disk>
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='qcow2'/>
|
||||
- <source file='{0}{1}myvm_data.qcow2'/>
|
||||
+ <source file='{0}{1}my vm_data.qcow2'/>
|
||||
<backingStore/>
|
||||
<target dev='vdb' bus='virtio'/>
|
||||
<alias name='virtio-disk1'/>
|
||||
@@ -1198,7 +1198,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
</devices>
|
||||
</domain>
|
||||
'''.format(root_dir, os.sep)
|
||||
- domain_mock = self.set_mock_vm('myvm', xml)
|
||||
+ domain_mock = self.set_mock_vm('my vm', xml)
|
||||
domain_mock.OSType = MagicMock(return_value='hvm')
|
||||
define_mock = MagicMock(return_value=True)
|
||||
self.mock_conn.defineXML = define_mock
|
||||
@@ -1211,7 +1211,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'cpu': True,
|
||||
'disk': {'attached': [], 'detached': []},
|
||||
'interface': {'attached': [], 'detached': []}
|
||||
- }, virt.update('myvm', cpu=2))
|
||||
+ }, virt.update('my vm', cpu=2))
|
||||
setxml = ET.fromstring(define_mock.call_args[0][0])
|
||||
self.assertEqual(setxml.find('vcpu').text, '2')
|
||||
self.assertEqual(setvcpus_mock.call_args[0][0], 2)
|
||||
@@ -1225,7 +1225,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'mem': True,
|
||||
'disk': {'attached': [], 'detached': []},
|
||||
'interface': {'attached': [], 'detached': []}
|
||||
- }, virt.update('myvm', mem=2048))
|
||||
+ }, virt.update('my vm', mem=2048))
|
||||
setxml = ET.fromstring(define_mock.call_args[0][0])
|
||||
self.assertEqual(setxml.find('memory').text, '2048')
|
||||
self.assertEqual(setxml.find('memory').get('unit'), 'MiB')
|
||||
@@ -1240,21 +1240,21 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock_run = MagicMock()
|
||||
with patch.dict(os.__dict__, {'chmod': mock_chmod, 'makedirs': MagicMock()}): # pylint: disable=no-member
|
||||
with patch.dict(virt.__salt__, {'cmd.run': mock_run}): # pylint: disable=no-member
|
||||
- ret = virt.update('myvm', disk_profile='default', disks=[
|
||||
+ ret = virt.update('my vm', disk_profile='default', disks=[
|
||||
{'name': 'cddrive', 'device': 'cdrom', 'source_file': None, 'model': 'ide'},
|
||||
{'name': 'added', 'size': 2048}])
|
||||
added_disk_path = os.path.join(
|
||||
- virt.__salt__['config.get']('virt:images'), 'myvm_added.qcow2') # pylint: disable=no-member
|
||||
+ virt.__salt__['config.get']('virt:images'), 'my vm_added.qcow2') # pylint: disable=no-member
|
||||
self.assertEqual(mock_run.call_args[0][0],
|
||||
- 'qemu-img create -f qcow2 {0} 2048M'.format(added_disk_path))
|
||||
+ 'qemu-img create -f qcow2 "{0}" 2048M'.format(added_disk_path))
|
||||
self.assertEqual(mock_chmod.call_args[0][0], added_disk_path)
|
||||
self.assertListEqual(
|
||||
- [None, os.path.join(root_dir, 'myvm_added.qcow2')],
|
||||
+ [None, os.path.join(root_dir, 'my vm_added.qcow2')],
|
||||
[ET.fromstring(disk).find('source').get('file') if str(disk).find('<source') > -1 else None
|
||||
for disk in ret['disk']['attached']])
|
||||
|
||||
self.assertListEqual(
|
||||
- [os.path.join(root_dir, 'myvm_data.qcow2')],
|
||||
+ [os.path.join(root_dir, 'my vm_data.qcow2')],
|
||||
[ET.fromstring(disk).find('source').get('file') for disk in ret['disk']['detached']])
|
||||
self.assertEqual(devattach_mock.call_count, 2)
|
||||
devdetach_mock.assert_called_once()
|
||||
@@ -1271,7 +1271,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
devattach_mock.reset_mock()
|
||||
devdetach_mock.reset_mock()
|
||||
with patch.dict(salt.modules.config.__opts__, mock_config): # pylint: disable=no-member
|
||||
- ret = virt.update('myvm', nic_profile='myprofile',
|
||||
+ ret = virt.update('my vm', nic_profile='myprofile',
|
||||
interfaces=[{'name': 'eth0', 'type': 'network', 'source': 'default',
|
||||
'mac': '52:54:00:39:02:b1'},
|
||||
{'name': 'eth1', 'type': 'network', 'source': 'newnet'}])
|
||||
@@ -1285,7 +1285,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
# Remove nics case
|
||||
devattach_mock.reset_mock()
|
||||
devdetach_mock.reset_mock()
|
||||
- ret = virt.update('myvm', nic_profile=None, interfaces=[])
|
||||
+ ret = virt.update('my vm', nic_profile=None, interfaces=[])
|
||||
self.assertEqual([], ret['interface']['attached'])
|
||||
self.assertEqual(2, len(ret['interface']['detached']))
|
||||
devattach_mock.assert_not_called()
|
||||
@@ -1294,7 +1294,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
# Remove disks case (yeah, it surely is silly)
|
||||
devattach_mock.reset_mock()
|
||||
devdetach_mock.reset_mock()
|
||||
- ret = virt.update('myvm', disk_profile=None, disks=[])
|
||||
+ ret = virt.update('my vm', disk_profile=None, disks=[])
|
||||
self.assertEqual([], ret['disk']['attached'])
|
||||
self.assertEqual(2, len(ret['disk']['detached']))
|
||||
devattach_mock.assert_not_called()
|
||||
@@ -1305,7 +1305,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'definition': True,
|
||||
'disk': {'attached': [], 'detached': []},
|
||||
'interface': {'attached': [], 'detached': []}
|
||||
- }, virt.update('myvm', graphics={'type': 'vnc'}))
|
||||
+ }, virt.update('my vm', graphics={'type': 'vnc'}))
|
||||
setxml = ET.fromstring(define_mock.call_args[0][0])
|
||||
self.assertEqual('vnc', setxml.find('devices/graphics').get('type'))
|
||||
|
||||
@@ -1314,7 +1314,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'definition': False,
|
||||
'disk': {'attached': [], 'detached': []},
|
||||
'interface': {'attached': [], 'detached': []}
|
||||
- }, virt.update('myvm', cpu=1, mem=1024,
|
||||
+ }, virt.update('my vm', cpu=1, mem=1024,
|
||||
disk_profile='default', disks=[{'name': 'data', 'size': 2048}],
|
||||
nic_profile='myprofile',
|
||||
interfaces=[{'name': 'eth0', 'type': 'network', 'source': 'default',
|
||||
@@ -1328,7 +1328,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
self.mock_conn.defineXML.side_effect = self.mock_libvirt.libvirtError("Test error")
|
||||
setmem_mock.reset_mock()
|
||||
with self.assertRaises(self.mock_libvirt.libvirtError):
|
||||
- virt.update('myvm', mem=2048)
|
||||
+ virt.update('my vm', mem=2048)
|
||||
|
||||
# Failed single update failure case
|
||||
self.mock_conn.defineXML = MagicMock(return_value=True)
|
||||
@@ -1338,7 +1338,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'errors': ['Failed to live change memory'],
|
||||
'disk': {'attached': [], 'detached': []},
|
||||
'interface': {'attached': [], 'detached': []}
|
||||
- }, virt.update('myvm', mem=2048))
|
||||
+ }, virt.update('my vm', mem=2048))
|
||||
|
||||
# Failed multiple updates failure case
|
||||
self.assertEqual({
|
||||
@@ -1347,7 +1347,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'cpu': True,
|
||||
'disk': {'attached': [], 'detached': []},
|
||||
'interface': {'attached': [], 'detached': []}
|
||||
- }, virt.update('myvm', cpu=4, mem=2048))
|
||||
+ }, virt.update('my vm', cpu=4, mem=2048))
|
||||
|
||||
def test_mixed_dict_and_list_as_profile_objects(self):
|
||||
'''
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
582
virt.pool_running-fix-pool-start.patch
Normal file
582
virt.pool_running-fix-pool-start.patch
Normal file
@ -0,0 +1,582 @@
|
||||
From 946dd98e911e62c7bc3bcdd8adc8a170645c981c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
||||
Date: Wed, 6 Jun 2018 09:49:36 +0200
|
||||
Subject: [PATCH] virt.pool_running: fix pool start
|
||||
|
||||
Building a libvirt pool starts it. When defining a new pool, we need to
|
||||
let build start it or we will get libvirt errors.
|
||||
|
||||
Also backport virt states test to add test for the bug:
|
||||
|
||||
cherry picked from commits:
|
||||
- 451e7da55bd232546c4d30ec36d432de2d5a14ec
|
||||
- 495db345a570cb14cd9b0ae96e1bb0f3fad6aef0
|
||||
- cb00a5f9b4c9a2a863da3c1107ca6458a4092c3d
|
||||
- fc75872fb63e254eecc782168ff8b37157d9e514
|
||||
- 2a5f6ae5d69be71daeab6c9cbe4dd642255ff3c6
|
||||
- 2463ebe5a82b1a017004e8e0e390535485dc703e
|
||||
- c7c5d6ee88fbc74d0ee0aeab41beb421d8625f05
|
||||
---
|
||||
salt/states/virt.py | 7 +-
|
||||
tests/unit/states/test_virt.py | 508 ++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 508 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/salt/states/virt.py b/salt/states/virt.py
|
||||
index 90693880df..d411f864cd 100644
|
||||
--- a/salt/states/virt.py
|
||||
+++ b/salt/states/virt.py
|
||||
@@ -780,7 +780,7 @@ def pool_running(name,
|
||||
source_name=(source or {}).get('name', None),
|
||||
source_format=(source or {}).get('format', None),
|
||||
transient=transient,
|
||||
- start=True,
|
||||
+ start=False,
|
||||
connection=connection,
|
||||
username=username,
|
||||
password=password)
|
||||
@@ -795,11 +795,6 @@ def pool_running(name,
|
||||
connection=connection,
|
||||
username=username,
|
||||
password=password)
|
||||
-
|
||||
- __salt__['virt.pool_start'](name,
|
||||
- connection=connection,
|
||||
- username=username,
|
||||
- password=password)
|
||||
ret['changes'][name] = 'Pool defined and started'
|
||||
ret['comment'] = 'Pool {0} defined and started'.format(name)
|
||||
except libvirt.libvirtError as err:
|
||||
diff --git a/tests/unit/states/test_virt.py b/tests/unit/states/test_virt.py
|
||||
index 2e421319ad..8022989937 100644
|
||||
--- a/tests/unit/states/test_virt.py
|
||||
+++ b/tests/unit/states/test_virt.py
|
||||
@@ -21,6 +21,25 @@ from tests.support.mock import (
|
||||
# Import Salt Libs
|
||||
import salt.states.virt as virt
|
||||
import salt.utils.files
|
||||
+from salt.exceptions import CommandExecutionError
|
||||
+
|
||||
+# Import 3rd-party libs
|
||||
+from salt.ext import six
|
||||
+
|
||||
+
|
||||
+class LibvirtMock(MagicMock): # pylint: disable=too-many-ancestors
|
||||
+ '''
|
||||
+ libvirt library mockup
|
||||
+ '''
|
||||
+ class libvirtError(Exception): # pylint: disable=invalid-name
|
||||
+ '''
|
||||
+ libvirt error mockup
|
||||
+ '''
|
||||
+ def get_error_message(self):
|
||||
+ '''
|
||||
+ Fake function return error message
|
||||
+ '''
|
||||
+ return six.text_type(self)
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
@@ -29,7 +48,12 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
Test cases for salt.states.libvirt
|
||||
'''
|
||||
def setup_loader_modules(self):
|
||||
- return {virt: {}}
|
||||
+ self.mock_libvirt = LibvirtMock() # pylint: disable=attribute-defined-outside-init
|
||||
+ self.addCleanup(delattr, self, 'mock_libvirt')
|
||||
+ loader_globals = {
|
||||
+ 'libvirt': self.mock_libvirt
|
||||
+ }
|
||||
+ return {virt: loader_globals}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -195,3 +219,485 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
locality='Los_Angeles',
|
||||
organization='SaltStack',
|
||||
expiration_days=700), ret)
|
||||
+
|
||||
+ def test_running(self):
|
||||
+ '''
|
||||
+ running state test cases.
|
||||
+ '''
|
||||
+ ret = {'name': 'myvm',
|
||||
+ 'changes': {},
|
||||
+ 'result': True,
|
||||
+ 'comment': 'myvm is running'}
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(return_value='stopped'),
|
||||
+ 'virt.start': MagicMock(return_value=0),
|
||||
+ }):
|
||||
+ ret.update({'changes': {'myvm': 'Domain started'},
|
||||
+ 'comment': 'Domain myvm started'})
|
||||
+ self.assertDictEqual(virt.running('myvm'), ret)
|
||||
+
|
||||
+ init_mock = MagicMock(return_value=True)
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(side_effect=CommandExecutionError('not found')),
|
||||
+ 'virt.init': init_mock,
|
||||
+ 'virt.start': MagicMock(return_value=0)
|
||||
+ }):
|
||||
+ ret.update({'changes': {'myvm': 'Domain defined and started'},
|
||||
+ 'comment': 'Domain myvm defined and started'})
|
||||
+ self.assertDictEqual(virt.running('myvm',
|
||||
+ cpu=2,
|
||||
+ mem=2048,
|
||||
+ image='/path/to/img.qcow2'), ret)
|
||||
+ init_mock.assert_called_with('myvm', cpu=2, mem=2048, image='/path/to/img.qcow2',
|
||||
+ os_type=None, arch=None,
|
||||
+ disk=None, disks=None, nic=None, interfaces=None,
|
||||
+ graphics=None, hypervisor=None,
|
||||
+ seed=True, install=True, pub_key=None, priv_key=None,
|
||||
+ connection=None, username=None, password=None)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(side_effect=CommandExecutionError('not found')),
|
||||
+ 'virt.init': init_mock,
|
||||
+ 'virt.start': MagicMock(return_value=0)
|
||||
+ }):
|
||||
+ ret.update({'changes': {'myvm': 'Domain defined and started'},
|
||||
+ 'comment': 'Domain myvm defined and started'})
|
||||
+ disks = [{
|
||||
+ 'name': 'system',
|
||||
+ 'size': 8192,
|
||||
+ 'overlay_image': True,
|
||||
+ 'pool': 'default',
|
||||
+ 'image': '/path/to/image.qcow2'
|
||||
+ },
|
||||
+ {
|
||||
+ 'name': 'data',
|
||||
+ 'size': 16834
|
||||
+ }]
|
||||
+ ifaces = [{
|
||||
+ 'name': 'eth0',
|
||||
+ 'mac': '01:23:45:67:89:AB'
|
||||
+ },
|
||||
+ {
|
||||
+ 'name': 'eth1',
|
||||
+ 'type': 'network',
|
||||
+ 'source': 'admin'
|
||||
+ }]
|
||||
+ graphics = {'type': 'spice', 'listen': {'type': 'address', 'address': '192.168.0.1'}}
|
||||
+ self.assertDictEqual(virt.running('myvm',
|
||||
+ cpu=2,
|
||||
+ mem=2048,
|
||||
+ os_type='linux',
|
||||
+ arch='i686',
|
||||
+ vm_type='qemu',
|
||||
+ disk_profile='prod',
|
||||
+ disks=disks,
|
||||
+ nic_profile='prod',
|
||||
+ interfaces=ifaces,
|
||||
+ graphics=graphics,
|
||||
+ seed=False,
|
||||
+ install=False,
|
||||
+ pub_key='/path/to/key.pub',
|
||||
+ priv_key='/path/to/key',
|
||||
+ connection='someconnection',
|
||||
+ username='libvirtuser',
|
||||
+ password='supersecret'), ret)
|
||||
+ init_mock.assert_called_with('myvm',
|
||||
+ cpu=2,
|
||||
+ mem=2048,
|
||||
+ os_type='linux',
|
||||
+ arch='i686',
|
||||
+ image=None,
|
||||
+ disk='prod',
|
||||
+ disks=disks,
|
||||
+ nic='prod',
|
||||
+ interfaces=ifaces,
|
||||
+ graphics=graphics,
|
||||
+ hypervisor='qemu',
|
||||
+ seed=False,
|
||||
+ install=False,
|
||||
+ pub_key='/path/to/key.pub',
|
||||
+ priv_key='/path/to/key',
|
||||
+ connection='someconnection',
|
||||
+ username='libvirtuser',
|
||||
+ password='supersecret')
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(return_value='stopped'),
|
||||
+ 'virt.start': MagicMock(side_effect=[self.mock_libvirt.libvirtError('libvirt error msg')])
|
||||
+ }):
|
||||
+ ret.update({'changes': {}, 'result': False, 'comment': 'libvirt error msg'})
|
||||
+ self.assertDictEqual(virt.running('myvm'), ret)
|
||||
+
|
||||
+ # Working update case when running
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(return_value='running'),
|
||||
+ 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True})
|
||||
+ }):
|
||||
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
|
||||
+ 'result': True,
|
||||
+ 'comment': 'Domain myvm updated, restart to fully apply the changes'})
|
||||
+ self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
||||
+
|
||||
+ # Working update case when stopped
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(return_value='stopped'),
|
||||
+ 'virt.start': MagicMock(return_value=0),
|
||||
+ 'virt.update': MagicMock(return_value={'definition': True})
|
||||
+ }):
|
||||
+ ret.update({'changes': {'myvm': 'Domain updated and started'},
|
||||
+ 'result': True,
|
||||
+ 'comment': 'Domain myvm updated and started'})
|
||||
+ self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
||||
+
|
||||
+ # Failed live update case
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(return_value='running'),
|
||||
+ 'virt.update': MagicMock(return_value={'definition': True, 'cpu': False, 'errors': ['some error']})
|
||||
+ }):
|
||||
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': False, 'errors': ['some error']}},
|
||||
+ 'result': True,
|
||||
+ 'comment': 'Domain myvm updated, but some live update(s) failed'})
|
||||
+ self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
||||
+
|
||||
+ # Failed definition update case
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.vm_state': MagicMock(return_value='running'),
|
||||
+ 'virt.update': MagicMock(side_effect=[self.mock_libvirt.libvirtError('error message')])
|
||||
+ }):
|
||||
+ ret.update({'changes': {},
|
||||
+ 'result': False,
|
||||
+ 'comment': 'error message'})
|
||||
+ self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
||||
+
|
||||
+ def test_stopped(self):
|
||||
+ '''
|
||||
+ stopped state test cases.
|
||||
+ '''
|
||||
+ ret = {'name': 'myvm',
|
||||
+ 'changes': {},
|
||||
+ 'result': True}
|
||||
+
|
||||
+ shutdown_mock = MagicMock(return_value=True)
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.shutdown': shutdown_mock
|
||||
+ }):
|
||||
+ ret.update({'changes': {
|
||||
+ 'stopped': [{'domain': 'myvm', 'shutdown': True}]
|
||||
+ },
|
||||
+ 'comment': 'Machine has been shut down'})
|
||||
+ self.assertDictEqual(virt.stopped('myvm'), ret)
|
||||
+ shutdown_mock.assert_called_with('myvm', connection=None, username=None, password=None)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.shutdown': shutdown_mock,
|
||||
+ }):
|
||||
+ self.assertDictEqual(virt.stopped('myvm',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret'), ret)
|
||||
+ shutdown_mock.assert_called_with('myvm', connection='myconnection', username='user', password='secret')
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.shutdown': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
||||
+ }):
|
||||
+ ret.update({'changes': {'ignored': [{'domain': 'myvm', 'issue': 'Some error'}]},
|
||||
+ 'result': False,
|
||||
+ 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.stopped('myvm'), ret)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, {'virt.list_domains': MagicMock(return_value=[])}): # pylint: disable=no-member
|
||||
+ ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.stopped('myvm'), ret)
|
||||
+
|
||||
+ def test_powered_off(self):
|
||||
+ '''
|
||||
+ powered_off state test cases.
|
||||
+ '''
|
||||
+ ret = {'name': 'myvm',
|
||||
+ 'changes': {},
|
||||
+ 'result': True}
|
||||
+
|
||||
+ stop_mock = MagicMock(return_value=True)
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.stop': stop_mock
|
||||
+ }):
|
||||
+ ret.update({'changes': {
|
||||
+ 'unpowered': [{'domain': 'myvm', 'stop': True}]
|
||||
+ },
|
||||
+ 'comment': 'Machine has been powered off'})
|
||||
+ self.assertDictEqual(virt.powered_off('myvm'), ret)
|
||||
+ stop_mock.assert_called_with('myvm', connection=None, username=None, password=None)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.stop': stop_mock,
|
||||
+ }):
|
||||
+ self.assertDictEqual(virt.powered_off('myvm',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret'), ret)
|
||||
+ stop_mock.assert_called_with('myvm', connection='myconnection', username='user', password='secret')
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.stop': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
||||
+ }):
|
||||
+ ret.update({'changes': {'ignored': [{'domain': 'myvm', 'issue': 'Some error'}]},
|
||||
+ 'result': False,
|
||||
+ 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.powered_off('myvm'), ret)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, {'virt.list_domains': MagicMock(return_value=[])}): # pylint: disable=no-member
|
||||
+ ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.powered_off('myvm'), ret)
|
||||
+
|
||||
+ def test_snapshot(self):
|
||||
+ '''
|
||||
+ snapshot state test cases.
|
||||
+ '''
|
||||
+ ret = {'name': 'myvm',
|
||||
+ 'changes': {},
|
||||
+ 'result': True}
|
||||
+
|
||||
+ snapshot_mock = MagicMock(return_value=True)
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.snapshot': snapshot_mock
|
||||
+ }):
|
||||
+ ret.update({'changes': {
|
||||
+ 'saved': [{'domain': 'myvm', 'snapshot': True}]
|
||||
+ },
|
||||
+ 'comment': 'Snapshot has been taken'})
|
||||
+ self.assertDictEqual(virt.snapshot('myvm'), ret)
|
||||
+ snapshot_mock.assert_called_with('myvm', suffix=None, connection=None, username=None, password=None)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.snapshot': snapshot_mock,
|
||||
+ }):
|
||||
+ self.assertDictEqual(virt.snapshot('myvm',
|
||||
+ suffix='snap',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret'), ret)
|
||||
+ snapshot_mock.assert_called_with('myvm',
|
||||
+ suffix='snap',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret')
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.snapshot': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
||||
+ }):
|
||||
+ ret.update({'changes': {'ignored': [{'domain': 'myvm', 'issue': 'Some error'}]},
|
||||
+ 'result': False,
|
||||
+ 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.snapshot('myvm'), ret)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, {'virt.list_domains': MagicMock(return_value=[])}): # pylint: disable=no-member
|
||||
+ ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.snapshot('myvm'), ret)
|
||||
+
|
||||
+ def test_rebooted(self):
|
||||
+ '''
|
||||
+ rebooted state test cases.
|
||||
+ '''
|
||||
+ ret = {'name': 'myvm',
|
||||
+ 'changes': {},
|
||||
+ 'result': True}
|
||||
+
|
||||
+ reboot_mock = MagicMock(return_value=True)
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.reboot': reboot_mock
|
||||
+ }):
|
||||
+ ret.update({'changes': {
|
||||
+ 'rebooted': [{'domain': 'myvm', 'reboot': True}]
|
||||
+ },
|
||||
+ 'comment': 'Machine has been rebooted'})
|
||||
+ self.assertDictEqual(virt.rebooted('myvm'), ret)
|
||||
+ reboot_mock.assert_called_with('myvm', connection=None, username=None, password=None)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.reboot': reboot_mock,
|
||||
+ }):
|
||||
+ self.assertDictEqual(virt.rebooted('myvm',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret'), ret)
|
||||
+ reboot_mock.assert_called_with('myvm',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret')
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
|
||||
+ 'virt.reboot': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
||||
+ }):
|
||||
+ ret.update({'changes': {'ignored': [{'domain': 'myvm', 'issue': 'Some error'}]},
|
||||
+ 'result': False,
|
||||
+ 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.rebooted('myvm'), ret)
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, {'virt.list_domains': MagicMock(return_value=[])}): # pylint: disable=no-member
|
||||
+ ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
|
||||
+ self.assertDictEqual(virt.rebooted('myvm'), ret)
|
||||
+
|
||||
+ def test_network_running(self):
|
||||
+ '''
|
||||
+ network_running state test cases.
|
||||
+ '''
|
||||
+ ret = {'name': 'mynet', 'changes': {}, 'result': True, 'comment': ''}
|
||||
+ define_mock = MagicMock(return_value=True)
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.network_info': MagicMock(return_value={}),
|
||||
+ 'virt.network_define': define_mock
|
||||
+ }):
|
||||
+ ret.update({'changes': {'mynet': 'Network defined and started'},
|
||||
+ 'comment': 'Network mynet defined and started'})
|
||||
+ self.assertDictEqual(virt.network_running('mynet',
|
||||
+ 'br2',
|
||||
+ 'bridge',
|
||||
+ vport='openvswitch',
|
||||
+ tag=180,
|
||||
+ autostart=False,
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret'), ret)
|
||||
+ define_mock.assert_called_with('mynet',
|
||||
+ 'br2',
|
||||
+ 'bridge',
|
||||
+ 'openvswitch',
|
||||
+ tag=180,
|
||||
+ autostart=False,
|
||||
+ start=True,
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret')
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.network_info': MagicMock(return_value={'active': True}),
|
||||
+ 'virt.network_define': define_mock,
|
||||
+ }):
|
||||
+ ret.update({'changes': {}, 'comment': 'Network mynet exists and is running'})
|
||||
+ self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
||||
+
|
||||
+ start_mock = MagicMock(return_value=True)
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.network_info': MagicMock(return_value={'active': False}),
|
||||
+ 'virt.network_start': start_mock,
|
||||
+ 'virt.network_define': define_mock,
|
||||
+ }):
|
||||
+ ret.update({'changes': {'mynet': 'Network started'}, 'comment': 'Network mynet started'})
|
||||
+ self.assertDictEqual(virt.network_running('mynet',
|
||||
+ 'br2',
|
||||
+ 'bridge',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret'), ret)
|
||||
+ start_mock.assert_called_with('mynet', connection='myconnection', username='user', password='secret')
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.network_info': MagicMock(return_value={}),
|
||||
+ 'virt.network_define': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
||||
+ }):
|
||||
+ ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
||||
+ self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
||||
+
|
||||
+ def test_pool_running(self):
|
||||
+ '''
|
||||
+ pool_running state test cases.
|
||||
+ '''
|
||||
+ ret = {'name': 'mypool', 'changes': {}, 'result': True, 'comment': ''}
|
||||
+ mocks = {mock: MagicMock(return_value=True) for mock in ['define', 'autostart', 'build', 'start']}
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.pool_info': MagicMock(return_value={}),
|
||||
+ 'virt.pool_define': mocks['define'],
|
||||
+ 'virt.pool_build': mocks['build'],
|
||||
+ 'virt.pool_start': mocks['start'],
|
||||
+ 'virt.pool_set_autostart': mocks['autostart']
|
||||
+ }):
|
||||
+ ret.update({'changes': {'mypool': 'Pool defined and started'},
|
||||
+ 'comment': 'Pool mypool defined and started'})
|
||||
+ self.assertDictEqual(virt.pool_running('mypool',
|
||||
+ ptype='logical',
|
||||
+ target='/dev/base',
|
||||
+ permissions={'mode': '0770',
|
||||
+ 'owner': 1000,
|
||||
+ 'group': 100,
|
||||
+ 'label': 'seclabel'},
|
||||
+ source={'devices': [{'path': '/dev/sda'}]},
|
||||
+ transient=True,
|
||||
+ autostart=True,
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret'), ret)
|
||||
+ mocks['define'].assert_called_with('mypool',
|
||||
+ ptype='logical',
|
||||
+ target='/dev/base',
|
||||
+ permissions={'mode': '0770',
|
||||
+ 'owner': 1000,
|
||||
+ 'group': 100,
|
||||
+ 'label': 'seclabel'},
|
||||
+ source_devices=[{'path': '/dev/sda'}],
|
||||
+ source_dir=None,
|
||||
+ source_adapter=None,
|
||||
+ source_hosts=None,
|
||||
+ source_auth=None,
|
||||
+ source_name=None,
|
||||
+ source_format=None,
|
||||
+ transient=True,
|
||||
+ start=False,
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret')
|
||||
+ mocks['autostart'].assert_called_with('mypool',
|
||||
+ state='on',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret')
|
||||
+ mocks['build'].assert_called_with('mypool',
|
||||
+ connection='myconnection',
|
||||
+ username='user',
|
||||
+ password='secret')
|
||||
+ mocks['start'].assert_not_called()
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.pool_info': MagicMock(return_value={'state': 'running'}),
|
||||
+ }):
|
||||
+ ret.update({'changes': {}, 'comment': 'Pool mypool exists and is running'})
|
||||
+ self.assertDictEqual(virt.pool_running('mypool',
|
||||
+ ptype='logical',
|
||||
+ target='/dev/base',
|
||||
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
||||
+
|
||||
+ for mock in mocks:
|
||||
+ mocks[mock].reset_mock()
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.pool_info': MagicMock(return_value={'state': 'stopped'}),
|
||||
+ 'virt.pool_build': mocks['build'],
|
||||
+ 'virt.pool_start': mocks['start']
|
||||
+ }):
|
||||
+ ret.update({'changes': {'mypool': 'Pool started'}, 'comment': 'Pool mypool started'})
|
||||
+ self.assertDictEqual(virt.pool_running('mypool',
|
||||
+ ptype='logical',
|
||||
+ target='/dev/base',
|
||||
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
||||
+ mocks['start'].assert_called_with('mypool', connection=None, username=None, password=None)
|
||||
+ mocks['build'].assert_not_called()
|
||||
+
|
||||
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
||||
+ 'virt.pool_info': MagicMock(return_value={}),
|
||||
+ 'virt.pool_define': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
||||
+ }):
|
||||
+ ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
||||
+ self.assertDictEqual(virt.pool_running('mypool',
|
||||
+ ptype='logical',
|
||||
+ target='/dev/base',
|
||||
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
92
virt.volume_infos-fix-for-single-vm.patch
Normal file
92
virt.volume_infos-fix-for-single-vm.patch
Normal file
@ -0,0 +1,92 @@
|
||||
From b0b5a78a463f7587be4f81074b182d1f4b4461be Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
||||
Date: Thu, 4 Apr 2019 16:18:58 +0200
|
||||
Subject: [PATCH] virt.volume_infos fix for single VM
|
||||
|
||||
_get_domain returns a domain object when only one VM has been found.
|
||||
virt.volume_infos needs to take care of it or it will fail to list the
|
||||
volumes informations if the host in such a case.
|
||||
---
|
||||
salt/modules/virt.py | 4 ++-
|
||||
tests/unit/modules/test_virt.py | 46 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 49 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||
index 17039444c4..a3f625909d 100644
|
||||
--- a/salt/modules/virt.py
|
||||
+++ b/salt/modules/virt.py
|
||||
@@ -5047,10 +5047,12 @@ def volume_infos(pool=None, volume=None, **kwargs):
|
||||
conn = __get_conn(**kwargs)
|
||||
try:
|
||||
backing_stores = _get_all_volumes_paths(conn)
|
||||
+ domains = _get_domain(conn)
|
||||
+ domains_list = domains if isinstance(domains, list) else [domains]
|
||||
disks = {domain.name():
|
||||
{node.get('file') for node
|
||||
in ElementTree.fromstring(domain.XMLDesc(0)).findall('.//disk/source/[@file]')}
|
||||
- for domain in _get_domain(conn)}
|
||||
+ for domain in domains_list}
|
||||
|
||||
def _volume_extract_infos(vol):
|
||||
'''
|
||||
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
||||
index 14e51e1e2a..bbe8d813d7 100644
|
||||
--- a/tests/unit/modules/test_virt.py
|
||||
+++ b/tests/unit/modules/test_virt.py
|
||||
@@ -2864,6 +2864,52 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
}
|
||||
})
|
||||
|
||||
+ # Single VM test
|
||||
+ with patch('salt.modules.virt._get_domain', MagicMock(return_value=mock_vms[0])):
|
||||
+ actual = virt.volume_infos('pool0', 'vol0')
|
||||
+ self.assertEqual(1, len(actual.keys()))
|
||||
+ self.assertEqual(1, len(actual['pool0'].keys()))
|
||||
+ self.assertEqual(['vm0'], sorted(actual['pool0']['vol0']['used_by']))
|
||||
+ self.assertEqual('/path/to/vol0.qcow2', actual['pool0']['vol0']['path'])
|
||||
+ self.assertEqual('file', actual['pool0']['vol0']['type'])
|
||||
+ self.assertEqual('/key/of/vol0', actual['pool0']['vol0']['key'])
|
||||
+ self.assertEqual(123456789, actual['pool0']['vol0']['capacity'])
|
||||
+ self.assertEqual(123456, actual['pool0']['vol0']['allocation'])
|
||||
+
|
||||
+ self.assertEqual(virt.volume_infos('pool1', None), {
|
||||
+ 'pool1': {
|
||||
+ 'vol1': {
|
||||
+ 'type': 'file',
|
||||
+ 'key': '/key/of/vol1',
|
||||
+ 'path': '/path/to/vol1.qcow2',
|
||||
+ 'capacity': 12345,
|
||||
+ 'allocation': 1234,
|
||||
+ 'used_by': [],
|
||||
+ },
|
||||
+ 'vol2': {
|
||||
+ 'type': 'file',
|
||||
+ 'key': '/key/of/vol2',
|
||||
+ 'path': '/path/to/vol2.qcow2',
|
||||
+ 'capacity': 12345,
|
||||
+ 'allocation': 1234,
|
||||
+ 'used_by': [],
|
||||
+ }
|
||||
+ }
|
||||
+ })
|
||||
+
|
||||
+ self.assertEqual(virt.volume_infos(None, 'vol2'), {
|
||||
+ 'pool1': {
|
||||
+ 'vol2': {
|
||||
+ 'type': 'file',
|
||||
+ 'key': '/key/of/vol2',
|
||||
+ 'path': '/path/to/vol2.qcow2',
|
||||
+ 'capacity': 12345,
|
||||
+ 'allocation': 1234,
|
||||
+ 'used_by': [],
|
||||
+ }
|
||||
+ }
|
||||
+ })
|
||||
+
|
||||
def test_volume_delete(self):
|
||||
'''
|
||||
Test virt.volume_delete
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user