diff options
author | Julia Kreger <juliaashleykreger@gmail.com> | 2021-09-15 09:50:34 -0700 |
---|---|---|
committer | Julia Kreger <juliaashleykreger@gmail.com> | 2021-09-15 10:14:51 -0700 |
commit | 0555b6ba728cc6a30f89d252eaf429ce5a0c987e (patch) | |
tree | aada7dfe42cb8d81888887977cbc2309c1b04e44 | |
parent | bc642ccabcad2d01533ec7620de3c5dc22530a96 (diff) | |
download | python-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.py | 34 | ||||
-rw-r--r-- | ironicclient/tests/unit/common/test_utils.py | 43 | ||||
-rw-r--r-- | releasenotes/notes/address-cross-distro-iso-tools-006711c9f150037a.yaml | 7 |
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``. |