From f1a3a131e6901d51c390f187740d752743eb0eb1 Mon Sep 17 00:00:00 2001 From: Ettore Simone Date: Mon, 15 Jun 2026 19:08:20 +0200 Subject: [PATCH 1/2] UnicodeDecodeError in PodmanWorker.compare_config During container config comparison, podman's Docker-compat exec API inconsistently demultiplexes the 8-byte frame headers from the output stream depending on podman version, leaving binary bytes in raw_output. This will raise an "UnicodeDecodeError: 'utf-8' codec can't decode byte 0x?? in position 167: invalid start byte" Closes-Bug: 2153943 Change-Id: Ida1c017f50b9a24b88f8962d304eb015fa357211 Signed-off-by: Ettore Simone (cherry picked from commit c99f521356012d5bc42ab3c41a994b67657e86f0) --- ansible/module_utils/kolla_podman_worker.py | 8 ++++++-- .../test_podman_worker.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/ansible/module_utils/kolla_podman_worker.py b/ansible/module_utils/kolla_podman_worker.py index 66e5bba1b7..0b9e25ef8f 100644 --- a/ansible/module_utils/kolla_podman_worker.py +++ b/ansible/module_utils/kolla_podman_worker.py @@ -538,8 +538,12 @@ def compare_config(self): if rc == 0: return False elif rc == 1: - self._config_diff = (raw_output.decode('utf-8') if - isinstance(raw_output, bytes) else raw_output) + try: + self._config_diff = (raw_output.decode('utf-8') if + isinstance(raw_output, bytes) else + raw_output) + except UnicodeDecodeError: + self._config_diff = 'container changed during config check' return True else: raise Exception('Failed to compare container configuration: ' diff --git a/tests/kolla_container_tests/test_podman_worker.py b/tests/kolla_container_tests/test_podman_worker.py index 55ab5c1657..048a7a797e 100644 --- a/tests/kolla_container_tests/test_podman_worker.py +++ b/tests/kolla_container_tests/test_podman_worker.py @@ -766,6 +766,24 @@ def test_compare_config_changed(self): user='root') self.assertTrue(return_data) + def test_compare_config_chenged_unicode_error(self): + self.fake_data['params']['name'] = 'my_container' + self.pw = get_PodmanWorker(self.fake_data['params']) + my_container = construct_container(self.fake_data['containers'][0]) + invalid_bytes = b'\x8e\xfe\xfd' + my_container.exec_run = mock.Mock(return_value=(1, invalid_bytes)) + self.pw.pc.containers.get.return_value = my_container + + return_data = self.pw.compare_config() + self.pw.pc.containers.get.assert_called_once_with( + self.fake_data['params']['name']) + my_container.exec_run.assert_called_once_with( + pwm.COMPARE_CONFIG_CMD, + user='root') + self.assertTrue(return_data) + self.assertEqual(self.pw._config_diff, + 'container changed during config check') + def test_compare_config_changed_container_exited(self): self.fake_data['params']['name'] = 'my_container' self.pw = get_PodmanWorker(self.fake_data['params']) From b8d02a18fdcf69194cdbb89798ae6081b6ef2366 Mon Sep 17 00:00:00 2001 From: Alex Welsh Date: Fri, 3 Jul 2026 09:30:28 +0100 Subject: [PATCH 2/2] Increase Glance `chunked-input-limit` This change sets the default Glance uWSGI `chunked-input-limit` to 67108864 (64MB). Before this change, Glance would use the uWSGI default 1MB. Snapshotting an instance would hang indefinitely because Nova sends larger chunks. Change-Id: I43f9232efade5e98bcd67b9c94e7161c790995ce Closes-Bug: #2158974 Signed-off-by: Alex Welsh (cherry picked from commit a64dd7075780d6b614aabff7769f4f83a315b680) --- ansible/roles/glance/tasks/config.yml | 1 + ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2 | 3 +++ releasenotes/notes/bug-2158974-8a585c20e4dbff1f.yaml | 5 +++++ 3 files changed, 9 insertions(+) create mode 100644 releasenotes/notes/bug-2158974-8a585c20e4dbff1f.yaml diff --git a/ansible/roles/glance/tasks/config.yml b/ansible/roles/glance/tasks/config.yml index 7fa92b2605..2362c046c5 100644 --- a/ansible/roles/glance/tasks/config.yml +++ b/ansible/roles/glance/tasks/config.yml @@ -53,6 +53,7 @@ project_services: "{{ glance_services }}" service: "{{ glance_services['glance-api'] }}" service_name: "glance-api" + service_uwsgi_config_chunked_input_limit: "{{ '64M' | human_to_bytes }}" service_uwsgi_config_http_port: "{{ glance_api_listen_port }}" service_uwsgi_config_log_file_chmod: "644" service_uwsgi_config_module: "{{ service.wsgi }}" diff --git a/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2 b/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2 index ef0a5d3735..e8873eefca 100644 --- a/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2 +++ b/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2 @@ -1,6 +1,9 @@ [uwsgi] add-header = Connection: close buffer-size = 65535 +{% if service_uwsgi_config_chunked_input_limit is defined %} +chunked-input-limit = {{ service_uwsgi_config_chunked_input_limit }} +{% endif %} die-on-term = true enable-threads = true exit-on-reload = false diff --git a/releasenotes/notes/bug-2158974-8a585c20e4dbff1f.yaml b/releasenotes/notes/bug-2158974-8a585c20e4dbff1f.yaml new file mode 100644 index 0000000000..c3343f565e --- /dev/null +++ b/releasenotes/notes/bug-2158974-8a585c20e4dbff1f.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed instance snapshot hanging indefinitely. + `LP#2158974 `__