diff --git a/ironic_lib/disk_utils.py b/ironic_lib/disk_utils.py index 46d68658..5a1f2507 100644 --- a/ironic_lib/disk_utils.py +++ b/ironic_lib/disk_utils.py @@ -559,20 +559,34 @@ def _get_configdrive(configdrive, node_uuid, tempdir=None): else: data = configdrive - try: - data = io.BytesIO(base64.decode_as_bytes(data)) - except Exception as exc: - error_msg = (_('Config drive for node %(node)s is not base64 encoded ' - 'or the content is malformed. %(cls)s: %(err)s.') - % {'node': node_uuid, 'err': exc, - 'cls': type(exc).__name__}) - if is_url: - error_msg += _(' Downloaded from "%s".') % configdrive - raise exception.InstanceDeployFailure(error_msg) - configdrive_file = tempfile.NamedTemporaryFile(delete=False, prefix='configdrive', dir=tempdir) + + try: + data = io.BytesIO(base64.decode_as_bytes(data)) + except Exception as exc: + if isinstance(data, bytes): + LOG.debug('Config drive for node %(node)s is not base64 encoded ' + '(%(error)s), assuming binary', + {'node': node_uuid, 'error': exc}) + configdrive_mb = int(math.ceil(len(data) / units.Mi)) + configdrive_file.write(data) + configdrive_file.close() + return (configdrive_mb, configdrive_file.name) + else: + configdrive_file.close() + utils.unlink_without_raise(configdrive_file.name) + + error_msg = (_('Config drive for node %(node)s is not base64 ' + 'encoded or the content is malformed. ' + '%(cls)s: %(err)s.') + % {'node': node_uuid, 'err': exc, + 'cls': type(exc).__name__}) + if is_url: + error_msg += _(' Downloaded from "%s".') % configdrive + raise exception.InstanceDeployFailure(error_msg) + configdrive_mb = 0 with gzip.GzipFile('configdrive', 'rb', fileobj=data) as gunzipped: try: diff --git a/ironic_lib/tests/test_disk_utils.py b/ironic_lib/tests/test_disk_utils.py index a35924e8..11974563 100644 --- a/ironic_lib/tests/test_disk_utils.py +++ b/ironic_lib/tests/test_disk_utils.py @@ -996,6 +996,17 @@ class GetConfigdriveTestCase(base.IronicLibTestCase): fileobj=mock.ANY) mock_copy.assert_called_once_with(mock.ANY, mock.ANY) + def test_get_configdrive_binary(self, mock_requests, mock_copy): + mock_requests.return_value = mock.MagicMock(content=b'content') + tempdir = tempfile.mkdtemp() + (size, path) = disk_utils._get_configdrive('http://1.2.3.4/cd', + 'fake-node-uuid', + tempdir=tempdir) + self.assertTrue(path.startswith(tempdir)) + self.assertEqual(b'content', open(path, 'rb').read()) + mock_requests.assert_called_once_with('http://1.2.3.4/cd') + self.assertFalse(mock_copy.called) + @mock.patch.object(gzip, 'GzipFile', autospec=True) def test_get_configdrive_base64_string(self, mock_gzip, mock_requests, mock_copy):