summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulia Kreger <juliaashleykreger@gmail.com>2021-09-15 09:50:34 -0700
committerJulia Kreger <juliaashleykreger@gmail.com>2021-09-15 10:14:51 -0700
commit0555b6ba728cc6a30f89d252eaf429ce5a0c987e (patch)
treeaada7dfe42cb8d81888887977cbc2309c1b04e44
parentbc642ccabcad2d01533ec7620de3c5dc22530a96 (diff)
downloadpython-ironicclient-0555b6ba728cc6a30f89d252eaf429ce5a0c987e.tar.gz
Fix distribution compatability for configdrive build
Previously, the configuration drive generation code made use of ``genisoimage``, however ``genisoimage`` is not shipped universally on all linux distributions, and largely has been replaced in distributions with other forks, as the tooling has evolved, forked, and changed over the past quarter century. We now attempt to utilize multiple different commands, including the original ``mkisofs`` command and the newer ``xorrisofs`` command when attempting to generate the ISO image, falling back until one works. Credit goes to I720f25921f8e52f20a631f238a528dedf65a91c6 for the base pattern in OpenstackSDK. Story: 2009230 Task: 43328 Change-Id: Ic732c2e6c77474e0d5b701c47758959c3511743b
-rw-r--r--ironicclient/common/utils.py34
-rw-r--r--ironicclient/tests/unit/common/test_utils.py43
-rw-r--r--releasenotes/notes/address-cross-distro-iso-tools-006711c9f150037a.yaml7
3 files changed, 69 insertions, 15 deletions
diff --git a/ironicclient/common/utils.py b/ironicclient/common/utils.py
index 97f1901..963d2f2 100644
--- a/ironicclient/common/utils.py
+++ b/ironicclient/common/utils.py
@@ -267,20 +267,30 @@ def make_configdrive(path):
with tempfile.NamedTemporaryFile() as tmpfile:
with tempfile.NamedTemporaryFile() as tmpzipfile:
publisher = 'ironicclient-configdrive 0.1'
- try:
- p = subprocess.Popen(['genisoimage', '-o', tmpfile.name,
- '-ldots', '-allow-lowercase',
- '-allow-multidot', '-l',
- '-publisher', publisher,
- '-quiet', '-J',
- '-r', '-V', 'config-2',
- path],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- except OSError as e:
+ # NOTE(toabctl): Luckily, genisoimage, mkisofs and xorrisofs
+ # understand the same parameters which are currently used.
+ cmds = ['genisoimage', 'mkisofs', 'xorrisofs']
+ for c in cmds:
+ try:
+ p = subprocess.Popen([c, '-o', tmpfile.name,
+ '-ldots', '-allow-lowercase',
+ '-allow-multidot', '-l',
+ '-publisher', publisher,
+ '-quiet', '-J',
+ '-r', '-V', 'config-2',
+ path],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ except OSError as e:
+ error = e
+ else:
+ error = None
+ break
+ if error:
raise exc.CommandError(
_('Error generating the config drive. Make sure the '
- '"genisoimage" tool is installed. Error: %s') % e)
+ '"genisoimage", "mkisofs", or "xorriso" tool is '
+ 'installed. Error: %s') % error)
stdout, stderr = p.communicate()
if p.returncode != 0:
diff --git a/ironicclient/tests/unit/common/test_utils.py b/ironicclient/tests/unit/common/test_utils.py
index 3d371a9..8bf06a5 100644
--- a/ironicclient/tests/unit/common/test_utils.py
+++ b/ironicclient/tests/unit/common/test_utils.py
@@ -265,6 +265,20 @@ class MakeConfigDriveTest(test_utils.BaseTestCase):
'-quiet', '-J', '-r', '-V',
'config-2', mock.ANY]
+ self.mkisofs_cmd = ['mkisofs', '-o', mock.ANY,
+ '-ldots', '-allow-lowercase',
+ '-allow-multidot', '-l',
+ '-publisher', 'ironicclient-configdrive 0.1',
+ '-quiet', '-J', '-r', '-V',
+ 'config-2', mock.ANY]
+
+ self.xorrisofs_cmd = ['xorrisofs', '-o', mock.ANY,
+ '-ldots', '-allow-lowercase',
+ '-allow-multidot', '-l',
+ '-publisher', 'ironicclient-configdrive 0.1',
+ '-quiet', '-J', '-r', '-V',
+ 'config-2', mock.ANY]
+
def test_make_configdrive(self, mock_popen):
fake_process = mock.Mock(returncode=0)
fake_process.communicate.return_value = ('', '')
@@ -278,6 +292,24 @@ class MakeConfigDriveTest(test_utils.BaseTestCase):
stdout=subprocess.PIPE)
fake_process.communicate.assert_called_once_with()
+ def test_make_configdrive_fallsback(self, mock_popen):
+ fake_process = mock.Mock(returncode=0)
+ fake_process.communicate.return_value = ('', '')
+ mock_popen.side_effect = iter([OSError('boom'),
+ OSError('boom'),
+ fake_process])
+ with utils.tempdir() as dirname:
+ utils.make_configdrive(dirname)
+ mock_popen.assert_has_calls([
+ mock.call(self.genisoimage_cmd, stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE),
+ mock.call(self.mkisofs_cmd, stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE),
+ mock.call(self.xorrisofs_cmd, stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ ])
+ fake_process.communicate.assert_called_once_with()
+
@mock.patch.object(os, 'access', autospec=True)
def test_make_configdrive_non_readable_dir(self, mock_access, mock_popen):
mock_access.return_value = False
@@ -292,9 +324,14 @@ class MakeConfigDriveTest(test_utils.BaseTestCase):
self.assertRaises(exc.CommandError, utils.make_configdrive, 'fake-dir')
mock_access.assert_called_once_with('fake-dir', os.R_OK)
- mock_popen.assert_called_once_with(self.genisoimage_cmd,
- stderr=subprocess.PIPE,
- stdout=subprocess.PIPE)
+ mock_popen.assert_has_calls([
+ mock.call(self.genisoimage_cmd, stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE),
+ mock.call(self.mkisofs_cmd, stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE),
+ mock.call(self.xorrisofs_cmd, stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ ])
@mock.patch.object(os, 'access', autospec=True)
def test_make_configdrive_non_zero_returncode(self, mock_access,
diff --git a/releasenotes/notes/address-cross-distro-iso-tools-006711c9f150037a.yaml b/releasenotes/notes/address-cross-distro-iso-tools-006711c9f150037a.yaml
new file mode 100644
index 0000000..68ae767
--- /dev/null
+++ b/releasenotes/notes/address-cross-distro-iso-tools-006711c9f150037a.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Embedded configuration drive generation support has been updated to
+ support ``mkisofs`` and ``xorrisofs`` in adition to the previously
+ supported ``genisoimage`` utility. This is as distributions such as
+ Debian and OpenSUSE do not ship ``genisoimage``.