Blame SOURCES/virt-manager-urlfetcher-Add-xorriso-ISOReader-implementation.patch

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