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
(cherry picked from commit 0555b6ba72
)
This commit is contained in:
parent
3db05b79c5
commit
f6a0c962a9
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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``.
|
Loading…
Reference in New Issue