virt-manager/SOURCES/virt-manager-urlfetcher-Add...

201 lines
8.0 KiB
Diff

From 2bda38a197a780a85e9ce448ea81a81fe866c981 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Wed, 7 Apr 2021 11:45:00 -0400
Subject: [PATCH] urlfetcher: Add xorriso ISOReader implementation
xorisso is the still maintained isoinfo alternative, and may be
the only iso reading tool in RHEL9, so we need to support it.
Make it the default for our spec file and test suite too
Signed-off-by: Cole Robinson <crobinso@redhat.com>
(cherry picked from commit f793986378f84bb409d2451bdb62ca08fd4cb5b4)
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1973236
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
---
man/virt-install.rst | 2 +-
tests/test_cli.py | 12 ++++-----
virt-manager.spec | 4 +--
virtinst/install/urldetect.py | 4 +--
virtinst/install/urlfetcher.py | 48 +++++++++++++++++++++++++---------
5 files changed, 47 insertions(+), 23 deletions(-)
diff --git a/man/virt-install.rst b/man/virt-install.rst
index 963f9564..f75af635 100644
--- a/man/virt-install.rst
+++ b/man/virt-install.rst
@@ -617,7 +617,7 @@ ftp://host/path
An FTP server location containing an installable distribution image.
ISO
- Probe the ISO and extract files using 'isoinfo'
+ Extract files directly from the ISO path
DIRECTORY
Path to a local directory containing an installable distribution image.
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 5e69a135..3534e0e2 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -39,7 +39,7 @@ MEDIA_DIR = os.path.relpath(utils.DATADIR + "/fakemedia", utils.TOPDIR)
UNATTENDED_DIR = XMLDIR + "/unattended"
OLD_OSINFO = utils.has_old_osinfo()
NO_OSINFO_UNATTEND = not unattended.OSInstallScript.have_new_libosinfo()
-HAS_ISOINFO = shutil.which("isoinfo")
+HAS_xorriso = shutil.which("xorriso")
# We use this check as a surrogate for a released libosinfo with a bug
# fix we need to get full test coverage
@@ -100,9 +100,9 @@ def has_old_osinfo():
return "osinfo is too old"
-def missing_isoinfo():
- if not HAS_ISOINFO:
- return "isoinfo not installed"
+def missing_xorriso():
+ if not HAS_xorriso:
+ return "xorriso not installed"
def no_osinfo_unattend_cb():
@@ -995,8 +995,8 @@ c.add_compare("--connect " + utils.URIs.kvm_session + " --disk size=8 --os-varia
c.add_valid("--connect " + utils.URIs.kvm_session + " --install fedora21", prerun_check=has_old_osinfo) # hits some get_search_paths and media_upload code paths
# misc KVM config tests
-c.add_compare("--disk none --location %(ISO-NO-OS)s,kernel=frib.img,initrd=/frob.img", "location-manual-kernel", prerun_check=missing_isoinfo) # --location with an unknown ISO but manually specified kernel paths
-c.add_compare("--disk %(EXISTIMG1)s --location %(ISOTREE)s --nonetworks", "location-iso", prerun_check=missing_isoinfo) # Using --location iso mounting
+c.add_compare("--disk none --location %(ISO-NO-OS)s,kernel=frib.img,initrd=/frob.img", "location-manual-kernel", prerun_check=missing_xorriso) # --location with an unknown ISO but manually specified kernel paths
+c.add_compare("--disk %(EXISTIMG1)s --location %(ISOTREE)s --nonetworks", "location-iso", prerun_check=missing_xorriso) # Using --location iso mounting
c.add_compare("--disk %(EXISTIMG1)s --cdrom %(ISOLABEL)s", "cdrom-centos-label") # Using --cdrom with centos CD label, should use virtio etc.
c.add_compare("--disk %(EXISTIMG1)s --install bootdev=network --os-variant rhel5.4 --cloud-init none", "kvm-rhel5") # RHEL5 defaults
c.add_compare("--disk %(EXISTIMG1)s --install kernel=%(ISO-WIN7)s,initrd=%(ISOLABEL)s,kernel_args='foo bar' --os-variant rhel6.4 --unattended none", "kvm-rhel6") # RHEL6 defaults. ISO paths are just to point at existing files
diff --git a/virt-manager.spec b/virt-manager.spec
index f523551b..3946c300 100644
--- a/virt-manager.spec
+++ b/virt-manager.spec
@@ -71,8 +71,8 @@ Requires: python3-requests
Requires: libosinfo >= 0.2.10
# Required for gobject-introspection infrastructure
Requires: python3-gobject-base
-# Required for pulling files from iso media with isoinfo
-Requires: genisoimage
+# Required for pulling files from iso media
+Requires: xorriso
%description common
Common files used by the different virt-manager interfaces, as well as
diff --git a/virtinst/install/urldetect.py b/virtinst/install/urldetect.py
index a73b0bf1..f5ed0270 100644
--- a/virtinst/install/urldetect.py
+++ b/virtinst/install/urldetect.py
@@ -40,9 +40,9 @@ class _DistroCache(object):
if path not in self._filecache:
try:
content = self._fetcher.acquireFileContent(path)
- except ValueError:
+ except ValueError as e:
content = None
- log.debug("Failed to acquire file=%s", path)
+ log.debug("Failed to acquire file=%s: %s", path, e)
self._filecache[path] = content
return self._filecache[path]
diff --git a/virtinst/install/urlfetcher.py b/virtinst/install/urlfetcher.py
index 3cacab1a..835c9e40 100644
--- a/virtinst/install/urlfetcher.py
+++ b/virtinst/install/urlfetcher.py
@@ -26,7 +26,7 @@ class _ISOReader:
def __init__(self, location):
self._location = location
- def grabFile(self, url):
+ def grabFile(self, url, scratchdir):
raise NotImplementedError()
def hasFile(self, url):
raise NotImplementedError()
@@ -43,20 +43,50 @@ class _ISOinfoReader(_ISOReader):
def _make_file_list(self):
cmd = ["isoinfo", "-J", "-i", self._location, "-f"]
- log.debug("Running isoinfo: %s", cmd)
+ log.debug("Generating iso filelist: %s", cmd)
output = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
return output.splitlines(False)
- def grabFile(self, url):
+ def grabFile(self, url, scratchdir):
+ ignore = scratchdir
cmd = ["isoinfo", "-J", "-i", self._location, "-x", url]
- log.debug("Running isoinfo: %s", cmd)
+ log.debug("Extracting iso file: %s", cmd)
return subprocess.check_output(cmd)
def hasFile(self, url):
return url.encode("ascii") in self._cache_file_list
+class _XorrisoReader(_ISOReader):
+ def __init__(self, location):
+ super().__init__(location)
+ self._cache_file_list = self._make_file_list()
+
+ def _make_file_list(self):
+ delim = "VIRTINST_BEGINLIST"
+ cmd = ["xorriso", "-indev", self._location, "-print", delim, "-find"]
+
+ log.debug("Generating iso filelist: %s", cmd)
+ output = subprocess.check_output(cmd,
+ stderr=subprocess.DEVNULL, text=True)
+ return output.split(delim, 1)[1].strip().splitlines()
+
+ def grabFile(self, url, scratchdir):
+ tmp = tempfile.NamedTemporaryFile(
+ prefix="virtinst-iso", suffix="-" + os.path.basename(url),
+ dir=scratchdir)
+
+ cmd = ["xorriso", "-osirrox", "on", "-indev", self._location,
+ "-extract", url, tmp.name]
+ log.debug("Extracting iso file: %s", cmd)
+ subprocess.check_output(cmd)
+ return open(tmp.name, "rb").read()
+
+ def hasFile(self, url):
+ return ("'.%s'" % url) in self._cache_file_list
+
+
###########################
# Fetcher implementations #
###########################
@@ -349,23 +379,17 @@ class _ISOURLFetcher(_URLFetcher):
def _get_isoreader(self):
if not self._isoreader:
- self._isoreader = _ISOinfoReader(self.location)
+ self._isoreader = _XorrisoReader(self.location)
return self._isoreader
def _grabber(self, url):
- """
- Use isoinfo to grab the file
- """
if not self._hasFile(url):
raise RuntimeError("iso doesn't have file=%s" % url)
- output = self._get_isoreader().grabFile(url)
+ output = self._get_isoreader().grabFile(url, self.scratchdir)
return io.BytesIO(output), len(output)
def _hasFile(self, url):
- """
- Use isoinfo to list and search for the file
- """
return self._get_isoreader().hasFile(url)
--
2.31.1