Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-libvirt-python for
openSUSE:Factory checked in at 2026-09-08 16:53:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-libvirt-python (Old)
and /work/SRC/openSUSE:Factory/.python-libvirt-python.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-libvirt-python"
Tue Sep 8 16:53:02 2026 rev:106 rq:1375859 version:12.7.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-libvirt-python/python-libvirt-python.changes
2026-08-05 17:46:27.565751196 +0200
+++
/work/SRC/openSUSE:Factory/.python-libvirt-python.new.1265/python-libvirt-python.changes
2026-09-08 16:53:33.864573595 +0200
@@ -1,0 +2,6 @@
+Fri Sep 4 21:21:11 UTC 2026 - James Fehlig <[email protected]>
+
+- Update to 12.7.0
+ - Add all new APIs and constants in libvirt 12.7.0
+
+-------------------------------------------------------------------
Old:
----
libvirt-python-12.6.0.tar.gz
New:
----
libvirt-python-12.7.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-libvirt-python.spec ++++++
--- /var/tmp/diff_new_pack.OV0IAQ/_old 2026-09-08 16:53:34.874615970 +0200
+++ /var/tmp/diff_new_pack.OV0IAQ/_new 2026-09-08 16:53:34.877616096 +0200
@@ -23,7 +23,7 @@
%{?sle15_python_module_pythons}
Name: python-libvirt-python
URL: https://libvirt.org/
-Version: 12.6.0
+Version: 12.7.0
Release: 0
Summary: Library providing a virtualization API
License: LGPL-2.1-or-later
++++++ _service ++++++
--- /var/tmp/diff_new_pack.OV0IAQ/_old 2026-09-08 16:53:34.923618025 +0200
+++ /var/tmp/diff_new_pack.OV0IAQ/_new 2026-09-08 16:53:34.930618319 +0200
@@ -1,7 +1,7 @@
<services>
<service name="tar_scm" mode="manual">
<param name="filename">libvirt-python</param>
- <param name="revision">v12.6.0</param>
+ <param name="revision">v12.7.0</param>
<param name="scm">git</param>
<param name="submodules">disable</param>
<param name="url">https://gitlab.com/libvirt/libvirt-python.git</param>
++++++ libvirt-python-12.6.0.tar.gz -> libvirt-python-12.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/.gitignore
new/libvirt-python-12.7.0/.gitignore
--- old/libvirt-python-12.6.0/.gitignore 2026-07-28 17:41:42.000000000
+0200
+++ new/libvirt-python-12.7.0/.gitignore 2026-08-25 14:50:01.000000000
+0200
@@ -13,3 +13,4 @@
sdist/
*.egg-info/
*.egg
+docs/_build/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/.gitlab-ci.yml
new/libvirt-python-12.7.0/.gitlab-ci.yml
--- old/libvirt-python-12.6.0/.gitlab-ci.yml 2026-07-28 17:41:42.000000000
+0200
+++ new/libvirt-python-12.7.0/.gitlab-ci.yml 2026-08-25 14:50:01.000000000
+0200
@@ -3,6 +3,7 @@
- containers
- builds
- sanity_checks
+ - pages
.git_build_vars: &git_build_vars |
export MAKEFLAGS="-j$(getconf _NPROCESSORS_ONLN)"
@@ -57,6 +58,49 @@
include: '/ci/gitlab.yml'
+# Build Sphinx HTML API docs.
+py_api_docs:
+ extends:
+ - .gitlab_native_build_job
+ needs:
+ - job: x86_64-fedora-44-container
+ optional: true
+ script:
+ - export MAKEFLAGS="-j$(getconf _NPROCESSORS_ONLN)"
+ - export CFLAGS="-Werror"
+ - $PYTHON -m build -n -x
+ - $PYTHON -m venv docs-venv --system-site-packages --symlinks
+ - docs-venv/bin/python -m pip install dist/libvirt_python*.whl
+ - docs-venv/bin/python -m pip install -r requirements-docs.txt
+ - docs-venv/bin/sphinx-build -b html docs/ py_api_docs
+ artifacts:
+ expose_as: 'py_api_docs'
+ name: 'py_api_docs'
+ when: on_success
+ expire_in: 30 days
+ paths:
+ - py_api_docs
+ variables:
+ NAME: fedora-44
+ TARGET_BASE_IMAGE: registry.fedoraproject.org/fedora:44
+
+# Publish "py_api_docs" output via GitLab Pages
+pages:
+ stage: pages
+ script:
+ - mv py_api_docs public
+ dependencies:
+ - py_api_docs
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == $RUN_UPSTREAM_NAMESPACE &&
$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+ when: on_success
+ - when: never
+ artifacts:
+ expose_as: 'pages'
+ name: 'pages'
+ paths:
+ - public
+
api_coverage_job:
extends:
- .gitlab_native_build_job
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/HACKING
new/libvirt-python-12.7.0/HACKING
--- old/libvirt-python-12.6.0/HACKING 2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/HACKING 2026-08-25 14:50:01.000000000 +0200
@@ -36,3 +36,23 @@
the virStoragePool class
- libvirt-override-virStream.py - high level overrides in
the virStream class
+
+
+
+ Building API Documentation
+ ==========================
+
+The Python API reference is built with Sphinx using the autodoc
+extension. Since the Python modules are generated at build time
+from XML API descriptions, the package must be compiled before
+Sphinx can import anything.
+
+ $ python -m venv docs-venv --system-site-packages --symlinks
+ $ source docs-venv/bin/activate
+ $ python -m pip install setuptools build
+ $ python -m pip install -r requirements-docs.txt
+ $ python -m build -n -x
+ $ python -m pip install dist/libvirt_python*.whl
+ $ python -m sphinx -b html docs/ py_api_docs
+
+The rendered HTML will be in the py_api_docs/ directory.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/VERSION
new/libvirt-python-12.7.0/VERSION
--- old/libvirt-python-12.6.0/VERSION 2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/VERSION 2026-08-25 14:50:01.000000000 +0200
@@ -1 +1 @@
-12.6.0
+12.7.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libvirt-python-12.6.0/ci/buildenv/centos-stream-10.sh
new/libvirt-python-12.7.0/ci/buildenv/centos-stream-10.sh
--- old/libvirt-python-12.6.0/ci/buildenv/centos-stream-10.sh 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/buildenv/centos-stream-10.sh 2026-08-25
14:50:01.000000000 +0200
@@ -17,6 +17,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/ci/buildenv/centos-stream-9.sh
new/libvirt-python-12.7.0/ci/buildenv/centos-stream-9.sh
--- old/libvirt-python-12.6.0/ci/buildenv/centos-stream-9.sh 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/buildenv/centos-stream-9.sh 2026-08-25
14:50:01.000000000 +0200
@@ -32,6 +32,7 @@
ninja-build \
perl-base \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/ci/buildenv/fedora-43.sh
new/libvirt-python-12.7.0/ci/buildenv/fedora-43.sh
--- old/libvirt-python-12.6.0/ci/buildenv/fedora-43.sh 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/buildenv/fedora-43.sh 2026-08-25
14:50:01.000000000 +0200
@@ -14,6 +14,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/ci/buildenv/fedora-44.sh
new/libvirt-python-12.7.0/ci/buildenv/fedora-44.sh
--- old/libvirt-python-12.6.0/ci/buildenv/fedora-44.sh 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/buildenv/fedora-44.sh 2026-08-25
14:50:01.000000000 +0200
@@ -14,6 +14,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/ci/buildenv/fedora-rawhide.sh
new/libvirt-python-12.7.0/ci/buildenv/fedora-rawhide.sh
--- old/libvirt-python-12.6.0/ci/buildenv/fedora-rawhide.sh 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/buildenv/fedora-rawhide.sh 2026-08-25
14:50:01.000000000 +0200
@@ -15,6 +15,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libvirt-python-12.6.0/ci/containers/centos-stream-10.Dockerfile
new/libvirt-python-12.7.0/ci/containers/centos-stream-10.Dockerfile
--- old/libvirt-python-12.6.0/ci/containers/centos-stream-10.Dockerfile
2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/containers/centos-stream-10.Dockerfile
2026-08-25 14:50:01.000000000 +0200
@@ -18,6 +18,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libvirt-python-12.6.0/ci/containers/centos-stream-9.Dockerfile
new/libvirt-python-12.7.0/ci/containers/centos-stream-9.Dockerfile
--- old/libvirt-python-12.6.0/ci/containers/centos-stream-9.Dockerfile
2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/containers/centos-stream-9.Dockerfile
2026-08-25 14:50:01.000000000 +0200
@@ -33,6 +33,7 @@
ninja-build \
perl-base \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libvirt-python-12.6.0/ci/containers/fedora-43.Dockerfile
new/libvirt-python-12.7.0/ci/containers/fedora-43.Dockerfile
--- old/libvirt-python-12.6.0/ci/containers/fedora-43.Dockerfile
2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/containers/fedora-43.Dockerfile
2026-08-25 14:50:01.000000000 +0200
@@ -25,6 +25,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libvirt-python-12.6.0/ci/containers/fedora-44.Dockerfile
new/libvirt-python-12.7.0/ci/containers/fedora-44.Dockerfile
--- old/libvirt-python-12.6.0/ci/containers/fedora-44.Dockerfile
2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/containers/fedora-44.Dockerfile
2026-08-25 14:50:01.000000000 +0200
@@ -25,6 +25,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libvirt-python-12.6.0/ci/containers/fedora-rawhide.Dockerfile
new/libvirt-python-12.7.0/ci/containers/fedora-rawhide.Dockerfile
--- old/libvirt-python-12.6.0/ci/containers/fedora-rawhide.Dockerfile
2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/containers/fedora-rawhide.Dockerfile
2026-08-25 14:50:01.000000000 +0200
@@ -26,6 +26,7 @@
glibc-langpack-en \
libvirt-devel \
pkgconfig \
+ pyproject-rpm-macros \
python3 \
python3-build \
python3-devel \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/libvirt-python-12.6.0/ci/lcitool/projects/libvirt-python.yml
new/libvirt-python-12.7.0/ci/lcitool/projects/libvirt-python.yml
--- old/libvirt-python-12.6.0/ci/lcitool/projects/libvirt-python.yml
2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/ci/lcitool/projects/libvirt-python.yml
2026-08-25 14:50:01.000000000 +0200
@@ -3,6 +3,7 @@
- ccache
- gcc
- pkg-config
+ - pyproject-rpm-macros
- python3
- python3-build
- python3-devel
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/docs/Makefile
new/libvirt-python-12.7.0/docs/Makefile
--- old/libvirt-python-12.6.0/docs/Makefile 1970-01-01 01:00:00.000000000
+0100
+++ new/libvirt-python-12.7.0/docs/Makefile 2026-08-25 14:50:01.000000000
+0200
@@ -0,0 +1,12 @@
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
+
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/docs/conf.py
new/libvirt-python-12.7.0/docs/conf.py
--- old/libvirt-python-12.6.0/docs/conf.py 1970-01-01 01:00:00.000000000
+0100
+++ new/libvirt-python-12.7.0/docs/conf.py 2026-08-25 14:50:01.000000000
+0200
@@ -0,0 +1,68 @@
+import os
+import sys
+
+sys.path.insert(0, os.path.abspath('../build'))
+sys.path.insert(0, os.path.abspath('..'))
+
+project = 'libvirt-python'
+author = 'Libvirt Maintainers'
+
+with open(os.path.abspath('../VERSION')) as f:
+ version = f.read().strip()
+release = version
+
+# Libvirt major version tracks the year as major + 2014 (e.g. 12 → 2026)
+copyright = '%d, Libvirt Maintainers' % (int(version.split('.')[0]) + 2014)
+
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.viewcode',
+]
+
+autodoc_member_order = 'groupwise'
+autodoc_default_options = {
+ 'members': True,
+ 'undoc-members': True,
+ 'show-inheritance': True,
+}
+
+html_theme = 'alabaster'
+html_theme_options = {
+ 'description': 'Python bindings for the libvirt API',
+ 'github_button': False,
+}
+
+
+def _needs_literal_docstring(lines):
+ """Here comes a little bit of magic.
+ This function returns True if docstring content is unsafe as
reStructuredText,
+ it will tell Sphinx to use the docstring as is, without any formatting.
+
+ Docs from C API descriptions are not always valid reStructuredText,
+ these are valid for Python help() but are not docutils.
+ """
+ in_field = False
+ for line in lines:
+ if line.startswith(':'):
+ in_field = True
+ continue
+ if in_field:
+ stripped = line.lstrip()
+ if stripped.startswith(('-', '*')) and line[:1].isspace():
+ return True
+ if line and not line[0].isspace() and not line.startswith(':'):
+ in_field = False
+ if line.startswith((' ', '\t')):
+ return True
+ return False
+
+
+def process_docstring(app, what, name, obj, options, lines):
+ if not lines or not _needs_literal_docstring(lines):
+ return
+ body = list(lines)
+ lines[:] = ['::', ''] + [(' ' + line if line else '') for line in body]
+
+
+def setup(app):
+ app.connect('autodoc-process-docstring', process_docstring)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/docs/index.rst
new/libvirt-python-12.7.0/docs/index.rst
--- old/libvirt-python-12.6.0/docs/index.rst 1970-01-01 01:00:00.000000000
+0100
+++ new/libvirt-python-12.7.0/docs/index.rst 2026-08-25 14:50:01.000000000
+0200
@@ -0,0 +1,20 @@
+libvirt-python API Documentation
+=================================
+
+Python bindings for the `libvirt <https://libvirt.org/>`_ virtualization API.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: API Reference
+
+ libvirt
+ libvirt_qemu
+ libvirt_lxc
+ libvirtaio
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/docs/libvirt.rst
new/libvirt-python-12.7.0/docs/libvirt.rst
--- old/libvirt-python-12.6.0/docs/libvirt.rst 1970-01-01 01:00:00.000000000
+0100
+++ new/libvirt-python-12.7.0/docs/libvirt.rst 2026-08-25 14:50:01.000000000
+0200
@@ -0,0 +1,7 @@
+libvirt --- Main API
+====================
+
+.. automodule:: libvirt
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/docs/libvirt_lxc.rst
new/libvirt-python-12.7.0/docs/libvirt_lxc.rst
--- old/libvirt-python-12.6.0/docs/libvirt_lxc.rst 1970-01-01
01:00:00.000000000 +0100
+++ new/libvirt-python-12.7.0/docs/libvirt_lxc.rst 2026-08-25
14:50:01.000000000 +0200
@@ -0,0 +1,7 @@
+libvirt_lxc --- LXC Extensions
+===============================
+
+.. automodule:: libvirt_lxc
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/docs/libvirt_qemu.rst
new/libvirt-python-12.7.0/docs/libvirt_qemu.rst
--- old/libvirt-python-12.6.0/docs/libvirt_qemu.rst 1970-01-01
01:00:00.000000000 +0100
+++ new/libvirt-python-12.7.0/docs/libvirt_qemu.rst 2026-08-25
14:50:01.000000000 +0200
@@ -0,0 +1,7 @@
+libvirt_qemu --- QEMU Extensions
+=================================
+
+.. automodule:: libvirt_qemu
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/docs/libvirtaio.rst
new/libvirt-python-12.7.0/docs/libvirtaio.rst
--- old/libvirt-python-12.6.0/docs/libvirtaio.rst 1970-01-01
01:00:00.000000000 +0100
+++ new/libvirt-python-12.7.0/docs/libvirtaio.rst 2026-08-25
14:50:01.000000000 +0200
@@ -0,0 +1,7 @@
+libvirtaio --- Asyncio Integration
+====================================
+
+.. automodule:: libvirtaio
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/libvirt-override.c
new/libvirt-python-12.7.0/libvirt-override.c
--- old/libvirt-python-12.6.0/libvirt-override.c 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/libvirt-override.c 2026-08-25
14:50:01.000000000 +0200
@@ -1696,6 +1696,9 @@
{ VIR_DOMAIN_IOTHREAD_THREAD_POOL_MIN, VIR_TYPED_PARAM_INT },
{ VIR_DOMAIN_IOTHREAD_THREAD_POOL_MAX, VIR_TYPED_PARAM_INT },
# endif /* LIBVIR_CHECK_VERSION(8, 5, 0) */
+# if LIBVIR_CHECK_VERSION(12, 7, 0)
+ { VIR_DOMAIN_IOTHREAD_POLL_WEIGHT, VIR_TYPED_PARAM_UINT },
+# endif /* LIBVIR_CHECK_VERSION(12, 7, 0) */
};
static PyObject *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/libvirt-python.spec.in
new/libvirt-python-12.7.0/libvirt-python.spec.in
--- old/libvirt-python-12.6.0/libvirt-python.spec.in 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/libvirt-python.spec.in 2026-08-25
14:50:01.000000000 +0200
@@ -3,8 +3,8 @@
# This spec file assumes you are building on a Fedora or RHEL version
# that's still supported by the vendor. It may work on other distros
# or versions, but no effort will be made to ensure that going forward
-%define min_rhel 8
-%define min_fedora 33
+%define min_rhel 9
+%define min_fedora 43
%if (0%{?fedora} && 0%{?fedora} >= %{min_fedora}) || (0%{?rhel} && 0%{?rhel}
>= %{min_rhel})
%define supported_platform 1
@@ -25,7 +25,6 @@
BuildRequires: python3-devel
BuildRequires: python3-pytest
BuildRequires: python3-lxml
-BuildRequires: python3-setuptools
BuildRequires: gcc
# Don't want provides for python shared objects
@@ -59,31 +58,26 @@
# for the -python3 package
find examples -type f -exec chmod 0644 \{\} \;
+%generate_buildrequires
+%pyproject_buildrequires
+
%build
%if ! %{supported_platform}
echo "This RPM requires either Fedora >= %{min_fedora} or RHEL >= %{min_rhel}"
exit 1
%endif
-%py3_build
+%pyproject_wheel
%install
-%py3_install
+%pyproject_install
+%pyproject_save_files libvirt libvirt_lxc libvirt_qemu libvirtaio 'libvirtmod*'
%check
+%pyproject_check_import
%pytest
-%files -n python3-libvirt
+%files -n python3-libvirt -f %{pyproject_files}
%doc ChangeLog AUTHORS README COPYING examples/
-%{python3_sitearch}/libvirt.py*
-%{python3_sitearch}/libvirtaio.py*
-%{python3_sitearch}/libvirt_qemu.py*
-%{python3_sitearch}/libvirt_lxc.py*
-%{python3_sitearch}/__pycache__/libvirt.cpython-*.py*
-%{python3_sitearch}/__pycache__/libvirt_qemu.cpython-*.py*
-%{python3_sitearch}/__pycache__/libvirt_lxc.cpython-*.py*
-%{python3_sitearch}/__pycache__/libvirtaio.cpython-*.py*
-%{python3_sitearch}/libvirtmod*
-%{python3_sitearch}/*egg-info
%changelog
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/requirements-docs.txt
new/libvirt-python-12.7.0/requirements-docs.txt
--- old/libvirt-python-12.6.0/requirements-docs.txt 1970-01-01
01:00:00.000000000 +0100
+++ new/libvirt-python-12.7.0/requirements-docs.txt 2026-08-25
14:50:01.000000000 +0200
@@ -0,0 +1 @@
+sphinx
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/setup.cfg
new/libvirt-python-12.7.0/setup.cfg
--- old/libvirt-python-12.6.0/setup.cfg 2026-07-28 17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/setup.cfg 2026-08-25 14:50:01.000000000 +0200
@@ -15,6 +15,6 @@
Programming Language :: Python :: 3 :: Only
[options]
-python_requires = >=3.6
+python_requires = >=3.9
package_dir =
=build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/tests/test_conn.py
new/libvirt-python-12.7.0/tests/test_conn.py
--- old/libvirt-python-12.6.0/tests/test_conn.py 2026-07-28
17:41:42.000000000 +0200
+++ new/libvirt-python-12.7.0/tests/test_conn.py 2026-08-25
14:50:01.000000000 +0200
@@ -18,6 +18,182 @@
self.assertEqual(type(doms[0]), libvirt.virDomain)
self.assertEqual(doms[0].name(), "test")
+
+class TestLibvirtConnMetadata(unittest.TestCase):
+ """Connection metadata and lifecycle tests"""
+
+ def setUp(self):
+ self.conn = libvirt.open("test:///default")
+
+ def tearDown(self):
+ self.conn = None
+
+ def testConnGetURI(self):
+ uri = self.conn.getURI()
+
+ self.assertIsInstance(uri, str)
+ self.assertEqual(uri, "test:///default")
+
+ def testConnGetHostname(self):
+ hostname = self.conn.getHostname()
+
+ self.assertIsInstance(hostname, str)
+ self.assertGreater(len(hostname), 0)
+
+ def testConnGetLibVersion(self):
+ version = self.conn.getLibVersion()
+
+ self.assertIsInstance(version, int)
+ self.assertGreater(version, 0)
+
+ def testConnGetVersion(self):
+ """test driver reports hypervisor version 2"""
+ version = self.conn.getVersion()
+
+ self.assertIsInstance(version, int)
+ self.assertEqual(version, 2)
+
+ def testConnGetType(self):
+ """test driver reports type TEST"""
+ hv_type = self.conn.getType()
+
+ self.assertIsInstance(hv_type, str)
+ self.assertEqual(hv_type, "TEST")
+
+ def testConnIsAlive(self):
+ self.assertTrue(self.conn.isAlive())
+
+ def testConnIsEncrypted(self):
+ result = self.conn.isEncrypted()
+
+ self.assertIsInstance(result, (bool, int))
+ self.assertFalse(result)
+
+ def testConnIsSecure(self):
+ result = self.conn.isSecure()
+
+ self.assertIsInstance(result, (bool, int))
+ self.assertTrue(result)
+
+ def testConnClose(self):
+ self.assertTrue(self.conn.isAlive())
+
+ ret = self.conn.close()
+ self.assertEqual(ret, 0)
+
+ with self.assertRaises(libvirt.libvirtError):
+ self.conn.isAlive()
+
+ def testConnContextManager(self):
+ with libvirt.open("test:///default") as conn:
+ self.assertEqual(conn.getURI(), "test:///default")
+ self.assertTrue(conn.isAlive())
+
+ with self.assertRaises(libvirt.libvirtError):
+ conn.isAlive()
+
+
+class TestLibvirtConnOpenNegative(unittest.TestCase):
+ """Connection open failure for an invalid URI"""
+
+ def testOpenFails(self):
+ with self.assertRaises(libvirt.libvirtError) as ctx:
+ libvirt.open("not-a-valid-libvirt-uri")
+
+ self.assertIsNotNone(ctx.exception.get_error_message())
+
+
+class TestLibvirtConnReadOnly(unittest.TestCase):
+ """Read-only libvirt.openReadOnly() connection tests"""
+
+ DEFINE_XML = """
+ <domain type='test'>
+ <name>test-define-temp</name>
+ <uuid>12345678-1234-1234-1234-123456789abc</uuid>
+ <memory unit='KiB'>524288</memory>
+ <vcpu>1</vcpu>
+ <os>
+ <type>hvm</type>
+ </os>
+ </domain>
+ """
+
+ def setUp(self):
+ self.conn = libvirt.openReadOnly("test:///default")
+
+ def tearDown(self):
+ self.conn = None
+
+ def testOpenReadOnlySucceeds(self):
+ self.assertIsNotNone(self.conn)
+ self.assertTrue(self.conn.isAlive())
+
+ def testReadOnlyGetURI(self):
+ self.assertEqual(self.conn.getURI(), "test:///default")
+
+ def testReadOnlyGetType(self):
+ self.assertEqual(self.conn.getType(), "TEST")
+
+ def testReadOnlyListDomains(self):
+ domains = self.conn.listAllDomains()
+
+ self.assertIsInstance(domains, list)
+ self.assertGreater(len(domains), 0)
+ self.assertIsInstance(domains[0], libvirt.virDomain)
+
+ def testReadOnlyLookupAndInfo(self):
+ dom = self.conn.lookupByName("test")
+
+ self.assertEqual(dom.name(), "test")
+
+ info = dom.info()
+ self.assertIsInstance(info, (tuple, list))
+ self.assertEqual(len(info), 5)
+
+ state, _ = dom.state()
+ self.assertIsInstance(state, int)
+
+ def testReadOnlyXMLDesc(self):
+ dom = self.conn.lookupByName("test")
+ xml = dom.XMLDesc(0)
+
+ self.assertIsInstance(xml, str)
+ self.assertIn("<domain", xml)
+
+ def testReadOnlyDefineXMLDenied(self):
+ with self.assertRaises(libvirt.libvirtError) as ctx:
+ self.conn.defineXML(self.DEFINE_XML)
+
+ self.assertEqual(ctx.exception.get_error_code(),
+ libvirt.VIR_ERR_OPERATION_DENIED)
+
+ def testReadOnlyDestroyDenied(self):
+ dom = self.conn.lookupByName("test")
+
+ with self.assertRaises(libvirt.libvirtError) as ctx:
+ dom.destroy()
+
+ self.assertEqual(ctx.exception.get_error_code(),
+ libvirt.VIR_ERR_OPERATION_DENIED)
+
+ def testReadOnlyXMLDescSecureDenied(self):
+ dom = self.conn.lookupByName("test")
+
+ with self.assertRaises(libvirt.libvirtError) as ctx:
+ dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)
+
+ self.assertEqual(ctx.exception.get_error_code(),
+ libvirt.VIR_ERR_OPERATION_DENIED)
+
+ def testReadOnlyContextManager(self):
+ with libvirt.openReadOnly("test:///default") as conn:
+ self.assertEqual(conn.getURI(), "test:///default")
+ self.assertTrue(conn.isAlive())
+
+ with self.assertRaises(libvirt.libvirtError):
+ conn.isAlive()
+
+
class TestLibvirtConnAuth(unittest.TestCase):
connXML = """
<node>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libvirt-python-12.6.0/tests/test_domain_migration.py
new/libvirt-python-12.7.0/tests/test_domain_migration.py
--- old/libvirt-python-12.6.0/tests/test_domain_migration.py 1970-01-01
01:00:00.000000000 +0100
+++ new/libvirt-python-12.7.0/tests/test_domain_migration.py 2026-08-25
14:50:01.000000000 +0200
@@ -0,0 +1,391 @@
+import libvirt
+import unittest
+
+from unittest.mock import patch, MagicMock
+
+
+class TestLibvirtDomainMigrationMocked(unittest.TestCase):
+ def setUp(self):
+ self.conn = libvirt.open("test:///default")
+ self.dom = self.conn.lookupByName("test")
+
+ def tearDown(self):
+ self.dom = None
+ self.conn = None
+
+ @patch("libvirtmod.virDomainMigrate3")
+ def testMigrate3LiveMigrationSuccess(self, mock_migrate3):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ # A small hack to make virDomainFree work with mocked objects,
+ # the same applies to all tests in this set that return a domain
pointer.
+ # Transfer ownership of the raw C pointer to the mock return value by
+ # setting _o to None so dst_dom.__del__ won't also call virDomainFree
on it.
+ mock_migrate3.return_value = dst_dom._o
+ dst_dom._o = None
+
+ params = {
+ libvirt.VIR_MIGRATE_PARAM_URI: "qemu+ssh://desthost/system",
+ libvirt.VIR_MIGRATE_PARAM_BANDWIDTH: 1024,
+ }
+ flags = libvirt.VIR_MIGRATE_LIVE | libvirt.VIR_MIGRATE_PERSIST_DEST
+
+ result = self.dom.migrate3(dst_conn, params, flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+
+ mock_migrate3.assert_called_once()
+ call_args = mock_migrate3.call_args
+ self.assertEqual(call_args[0][0], self.dom._o)
+ self.assertEqual(call_args[0][1], dst_conn._o)
+ self.assertEqual(call_args[0][3], flags)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrateToURI3")
+ def testMigrateToURI3PeerToPeerSuccess(self, mock_migrateToURI3):
+ mock_migrateToURI3.return_value = 0
+
+ dest_uri = "qemu+ssh://desthost/system"
+ params = {
+ libvirt.VIR_MIGRATE_PARAM_BANDWIDTH: 2048,
+ libvirt.VIR_MIGRATE_PARAM_DEST_NAME: "migrated-vm",
+ }
+ flags = libvirt.VIR_MIGRATE_LIVE | libvirt.VIR_MIGRATE_PEER2PEER
+
+ result = self.dom.migrateToURI3(dest_uri, params, flags)
+
+ self.assertEqual(result, 0)
+
+ mock_migrateToURI3.assert_called_once()
+ call_args = mock_migrateToURI3.call_args
+ self.assertEqual(call_args[0][0], self.dom._o)
+ self.assertEqual(call_args[0][1], dest_uri)
+ self.assertEqual(call_args[0][3], flags)
+
+ @patch("libvirtmod.virDomainMigrate3")
+ def testMigrate3OfflineMigration(self, mock_migrate3):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ # domain must be inactive
+ if self.dom.isActive():
+ self.dom.destroy()
+
+ mock_migrate3.return_value = dst_dom._o
+ dst_dom._o = None
+
+ params = {}
+ flags = libvirt.VIR_MIGRATE_OFFLINE | libvirt.VIR_MIGRATE_PERSIST_DEST
+
+ result = self.dom.migrate3(dst_conn, params, flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ call_args = mock_migrate3.call_args
+ self.assertTrue(call_args[0][3] & libvirt.VIR_MIGRATE_OFFLINE)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate3")
+ def testMigrate3WithCompressionParameters(self, mock_migrate3):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate3.return_value = dst_dom._o
+ dst_dom._o = None
+
+ params = {
+ libvirt.VIR_MIGRATE_PARAM_BANDWIDTH: 1024,
+ libvirt.VIR_MIGRATE_PARAM_COMPRESSION: "mt",
+ libvirt.VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL: 9,
+ libvirt.VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS: 4,
+ libvirt.VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS: 2,
+ }
+ flags = libvirt.VIR_MIGRATE_LIVE | libvirt.VIR_MIGRATE_COMPRESSED
+
+ result = self.dom.migrate3(dst_conn, params, flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ mock_migrate3.assert_called_once()
+ call_args = mock_migrate3.call_args
+ self.assertTrue(call_args[0][3] & libvirt.VIR_MIGRATE_COMPRESSED)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrateToURI3")
+ def testMigrateToURI3WithAutoConverge(self, mock_migrateToURI3):
+ mock_migrateToURI3.return_value = 0
+
+ params = {
+ libvirt.VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL: 20,
+ libvirt.VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT: 10,
+ }
+ flags = (
+ libvirt.VIR_MIGRATE_LIVE
+ | libvirt.VIR_MIGRATE_PEER2PEER
+ | libvirt.VIR_MIGRATE_AUTO_CONVERGE
+ )
+
+ result = self.dom.migrateToURI3("qemu+ssh://dest/system", params,
flags)
+
+ self.assertEqual(result, 0)
+ mock_migrateToURI3.assert_called_once()
+ call_args = mock_migrateToURI3.call_args
+ self.assertTrue(call_args[0][3] & libvirt.VIR_MIGRATE_AUTO_CONVERGE)
+
+ @patch("libvirtmod.virDomainMigrate3")
+ def testMigrate3WithTLSParameters(self, mock_migrate3):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate3.return_value = dst_dom._o
+ dst_dom._o = None
+
+ params = {
+ libvirt.VIR_MIGRATE_PARAM_URI: "qemu+ssh://desthost/system",
+ libvirt.VIR_MIGRATE_PARAM_TLS_DESTINATION: "desthost.example.com",
+ }
+ flags = libvirt.VIR_MIGRATE_LIVE | libvirt.VIR_MIGRATE_TLS
+
+ result = self.dom.migrate3(dst_conn, params, flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ call_args = mock_migrate3.call_args
+ self.assertTrue(call_args[0][3] & libvirt.VIR_MIGRATE_TLS)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrateToURI3")
+ def testMigrateToURI3WithParallelConnections(self, mock_migrateToURI3):
+ mock_migrateToURI3.return_value = 0
+
+ params = {
+ libvirt.VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONS: 4,
+ libvirt.VIR_MIGRATE_PARAM_BANDWIDTH: 4096,
+ }
+ flags = (
+ libvirt.VIR_MIGRATE_LIVE
+ | libvirt.VIR_MIGRATE_PEER2PEER
+ | libvirt.VIR_MIGRATE_PARALLEL
+ )
+
+ result = self.dom.migrateToURI3("qemu+ssh://dest/system", params,
flags)
+
+ self.assertEqual(result, 0)
+
+ call_args = mock_migrateToURI3.call_args
+ self.assertTrue(call_args[0][3] & libvirt.VIR_MIGRATE_PARALLEL)
+
+ @patch("libvirtmod.virDomainMigrate3")
+ def testMigrate3EmptyParameterDict(self, mock_migrate3):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate3.return_value = dst_dom._o
+ dst_dom._o = None
+
+ # Empty params dict
+ params = {}
+ flags = libvirt.VIR_MIGRATE_LIVE
+
+ result = self.dom.migrate3(dst_conn, params, flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ mock_migrate3.assert_called_once()
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate3")
+ def testMigrate3MultipleFlags(self, mock_migrate3):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate3.return_value = dst_dom._o
+ dst_dom._o = None
+
+ params = {
+ libvirt.VIR_MIGRATE_PARAM_BANDWIDTH: 1024,
+ }
+
+ flags = (
+ libvirt.VIR_MIGRATE_LIVE
+ | libvirt.VIR_MIGRATE_PERSIST_DEST
+ | libvirt.VIR_MIGRATE_UNDEFINE_SOURCE
+ | libvirt.VIR_MIGRATE_COMPRESSED
+ | libvirt.VIR_MIGRATE_AUTO_CONVERGE
+ )
+
+ result = self.dom.migrate3(dst_conn, params, flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+
+ call_args = mock_migrate3.call_args
+ passed_flags = call_args[0][3]
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_LIVE)
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_PERSIST_DEST)
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_UNDEFINE_SOURCE)
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_COMPRESSED)
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_AUTO_CONVERGE)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate3")
+ def testMigrate3Failure(self, mock_migrate3):
+ dst_conn = libvirt.open("test:///default")
+
+ mock_migrate3.return_value = None
+
+ params = {}
+ flags = libvirt.VIR_MIGRATE_LIVE
+
+ # raise exception when C layer returns None
+ with self.assertRaises(libvirt.libvirtError) as ctx:
+ self.dom.migrate3(dst_conn, params, flags)
+
+ self.assertIn("virDomainMigrate3() failed", str(ctx.exception))
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrateToURI3")
+ def testMigrateToURI3Failure(self, mock_migrateToURI3):
+ mock_migrateToURI3.return_value = -1
+
+ params = {}
+ flags = libvirt.VIR_MIGRATE_LIVE | libvirt.VIR_MIGRATE_PEER2PEER
+
+ # raise exception on failure
+ with self.assertRaises(libvirt.libvirtError):
+ self.dom.migrateToURI3("qemu+ssh://dest/system", params, flags)
+
+
+class TestLibvirtDomainMigrateLegacyMocked(unittest.TestCase):
+ """Tests for the legacy virDomainMigrate and virDomainMigrate2 APIs.
+
+ Both virDomainMigrate and virDomainMigrate2 call independent C functionas
+ (libvirtmod.virDomainMigrate and libvirtmod.virDomainMigrate2) and have
+ their own wrapping logic, so they are tested separately from migrate3.
+ """
+
+ def setUp(self):
+ self.conn = libvirt.open("test:///default")
+ self.dom = self.conn.lookupByName("test")
+
+ def tearDown(self):
+ self.dom = None
+ self.conn = None
+
+ @patch("libvirtmod.virDomainMigrate")
+ def testMigrateSuccess(self, mock_migrate):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate.return_value = dst_dom._o
+ dst_dom._o = None
+
+ flags = libvirt.VIR_MIGRATE_LIVE | libvirt.VIR_MIGRATE_PERSIST_DEST
+ result = self.dom.migrate(dst_conn, flags, dname="migrated-vm",
+ uri="qemu+ssh://desthost/system",
bandwidth=1024)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ mock_migrate.assert_called_once()
+ call_args = mock_migrate.call_args
+ self.assertEqual(call_args[0][0], self.dom._o)
+ self.assertEqual(call_args[0][1], dst_conn._o)
+ self.assertEqual(call_args[0][2], flags)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate")
+ def testMigrateWithFlags(self, mock_migrate):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate.return_value = dst_dom._o
+ dst_dom._o = None
+
+ flags = (
+ libvirt.VIR_MIGRATE_LIVE
+ | libvirt.VIR_MIGRATE_PERSIST_DEST
+ | libvirt.VIR_MIGRATE_UNDEFINE_SOURCE
+ )
+ result = self.dom.migrate(dst_conn, flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ call_args = mock_migrate.call_args
+ passed_flags = call_args[0][2]
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_LIVE)
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_PERSIST_DEST)
+ self.assertTrue(passed_flags & libvirt.VIR_MIGRATE_UNDEFINE_SOURCE)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate")
+ def testMigrateFailure(self, mock_migrate):
+ dst_conn = libvirt.open("test:///default")
+
+ mock_migrate.return_value = None
+
+ with self.assertRaises(libvirt.libvirtError) as ctx:
+ self.dom.migrate(dst_conn, libvirt.VIR_MIGRATE_LIVE)
+
+ self.assertIn("virDomainMigrate() failed", str(ctx.exception))
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate2")
+ def testMigrate2Success(self, mock_migrate2):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate2.return_value = dst_dom._o
+ dst_dom._o = None
+
+ dxml = "<domain type='test'><name>migrated-vm</name></domain>"
+ flags = libvirt.VIR_MIGRATE_LIVE | libvirt.VIR_MIGRATE_PERSIST_DEST
+ result = self.dom.migrate2(dst_conn, dxml=dxml, flags=flags,
+ dname="migrated-vm")
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ mock_migrate2.assert_called_once()
+ call_args = mock_migrate2.call_args
+ self.assertEqual(call_args[0][0], self.dom._o)
+ self.assertEqual(call_args[0][1], dst_conn._o)
+ self.assertEqual(call_args[0][2], dxml)
+ self.assertEqual(call_args[0][3], flags)
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate2")
+ def testMigrate2WithoutXML(self, mock_migrate2):
+ dst_conn = libvirt.open("test:///default")
+ dst_dom = dst_conn.lookupByName("test")
+
+ mock_migrate2.return_value = dst_dom._o
+ dst_dom._o = None
+
+ flags = libvirt.VIR_MIGRATE_LIVE
+ result = self.dom.migrate2(dst_conn, flags=flags)
+
+ self.assertIsInstance(result, libvirt.virDomain)
+ call_args = mock_migrate2.call_args
+ self.assertIsNone(call_args[0][2])
+
+ dst_conn.close()
+
+ @patch("libvirtmod.virDomainMigrate2")
+ def testMigrate2Failure(self, mock_migrate2):
+ dst_conn = libvirt.open("test:///default")
+
+ mock_migrate2.return_value = None
+
+ with self.assertRaises(libvirt.libvirtError) as ctx:
+ self.dom.migrate2(dst_conn, flags=libvirt.VIR_MIGRATE_LIVE)
+
+ self.assertIn("virDomainMigrate2() failed", str(ctx.exception))
+
+ dst_conn.close()
+
+
+if __name__ == "__main__":
+ unittest.main()