Merge ~rodrigo-barbieri2010/ubuntu/+source/cinder:lp1945500_yoga into ~ubuntu-openstack-dev/ubuntu/+source/cinder:stable/yoga

Proposed by Rodrigo Barbieri
Status: Merged
Merged at revision: 1ce0c0275136ab9508611b0f47da09fb399c0c94
Proposed branch: ~rodrigo-barbieri2010/ubuntu/+source/cinder:lp1945500_yoga
Merge into: ~ubuntu-openstack-dev/ubuntu/+source/cinder:stable/yoga
Diff against target: 273 lines (+251/-0)
3 files modified
debian/changelog (+6/-0)
debian/patches/lp1945500.patch (+244/-0)
debian/patches/series (+1/-0)
Reviewer Review Type Date Requested Status
Corey Bryant Pending
Review via email: mp+438903@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index f1ddc2a..94e9654 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,9 @@
6+cinder (2:20.1.0-0ubuntu2) UNRELEASED; urgency=medium
7+
8+ * d/p/lp1945500.patch: Filter reserved image properties (LP: #1945500).
9+
10+ -- Rodrigo Barbieri <rodrigo.barbieri@canonical.com> Tue, 14 Mar 2023 13:21:44 -0300
11+
12 cinder (2:20.1.0-0ubuntu1) jammy; urgency=medium
13
14 * New stable point release for OpenStack Yoga (LP: #2004030).
15diff --git a/debian/patches/lp1945500.patch b/debian/patches/lp1945500.patch
16new file mode 100644
17index 0000000..fbb0f94
18--- /dev/null
19+++ b/debian/patches/lp1945500.patch
20@@ -0,0 +1,244 @@
21+From f2faf7d70f5cd3ace461d9de9fdfe448d78a0107 Mon Sep 17 00:00:00 2001
22+From: =?UTF-8?q?Rafael=20Weing=C3=A4rtner?= <rafael@apache.org>
23+Date: Wed, 6 Oct 2021 10:57:00 -0300
24+Subject: [PATCH] Filter reserved image properties
25+
26+Cinder is currently not able to upload a volume that is based on an
27+image back to glance. This bug is triggered if glance multistore is
28+enabled (devstack in this example).
29+
30+When enabling multistore, the following properties will be stored in Cinder:
31+* os_glance_failed_import=''
32+* os_glance_importing_to_stores=''
33+
34+Those properties will cause problems when Cinder tries to perform some
35+actions with Glance. Error msg:
36+```
37+cinderclient.exceptions.BadRequest: HTTP 403 Forbidden: Access was denied to this resource.: Attribute &#x27;os_glance_failed_import&#x27; is reserved. (HTTP 400)
38+```
39+
40+Nova had the same issue and solved it with:
41+https://github.com/openstack/nova/blob/50fdbc752a9ca9c31488140ef2997ed59d861a41/releasenotes/notes/absolutely-non-inheritable-image-properties-85f7f304fdc20b61.yaml
42+
43+and
44+
45+https://github.com/openstack/nova/commit/dda179d3f901e4f23091f3095f1af58bc26e222e
46+
47+Therefore, this patch is intended to apply a similar solution in Cinder.
48+
49+Change-Id: I79d70543856c01a45e2d8c083ab8df6b9c047ebc
50+Closes-Bug: #1945500
51+(cherry picked from commit c43fb490b204aadf41a32bcb5eb075b1656e2af4)
52+(cherry picked from commit 826b40281123d700b3aeba5dcf076544982973a3)
53+Conflicts: cinder/image/image_utils.py
54+ - Changed syntax from "dict[str, str]" to "Dict[str, str]" for
55+ Python <3.8 compatibility
56+---
57+ cinder/image/image_utils.py | 46 +++++++++++++
58+ cinder/tests/unit/test_image_utils.py | 66 +++++++++++++++++++
59+ cinder/volume/api.py | 4 ++
60+ ...ved-image-properties-9519ddc080e7ed1a.yaml | 28 ++++++++
61+ 4 files changed, 144 insertions(+)
62+ create mode 100644 releasenotes/notes/fix-reserved-image-properties-9519ddc080e7ed1a.yaml
63+
64+diff --git a/cinder/image/image_utils.py b/cinder/image/image_utils.py
65+index 8460ad281..73a95f8f5 100644
66+--- a/cinder/image/image_utils.py
67++++ b/cinder/image/image_utils.py
68+@@ -82,6 +82,24 @@ image_opts = [
69+ 'when an image is converted to raw format as it is written '
70+ 'to a volume. If this list is empty, no VMDK images are '
71+ 'allowed.'),
72++ cfg.ListOpt('reserved_image_namespaces',
73++ help='List of reserved image namespaces that should be '
74++ 'filtered out when uploading a volume as an image back '
75++ 'to Glance. When a volume is created from an image, '
76++ 'Cinder stores the image properties as volume '
77++ 'image metadata, and if the volume is later uploaded as '
78++ 'an image, Cinder will add these properties when it '
79++ 'creates the image in Glance. This can cause problems '
80++ 'for image metadata that are in namespaces that glance '
81++ 'reserves for itself, or when properties (such as an '
82++ 'image signature) cannot apply to the new image, or when '
83++ 'an operator has configured glance property protections '
84++ 'to make some image properties read-only. Cinder will '
85++ '*always* filter out image metadata in the namespaces '
86++ '`os_glance` and `img_signature`; this configuration '
87++ 'option allows operators to specify *additional* '
88++ 'namespaces to be excluded.',
89++ default=[]),
90+ ]
91+
92+ CONF = cfg.CONF
93+@@ -106,6 +124,8 @@ QEMU_IMG_MIN_CONVERT_LUKS_VERSION = '2.10'
94+
95+ COMPRESSIBLE_IMAGE_FORMATS = ('qcow2',)
96+
97++GLANCE_RESERVED_NAMESPACES = ["os_glance", "img_signature"]
98++
99+
100+ def validate_stores_id(context: context.RequestContext,
101+ image_service_store_id: str) -> None:
102+@@ -1248,3 +1268,29 @@ class TemporaryImages(object):
103+ if not self.temporary_images.get(user):
104+ return None
105+ return self.temporary_images[user].get(image_id)
106++
107++
108++def filter_out_reserved_namespaces_metadata(
109++ metadata: Optional[Dict[str, str]]) -> Dict[str, str]:
110++
111++ reserved_name_spaces = GLANCE_RESERVED_NAMESPACES.copy()
112++ if CONF.reserved_image_namespaces:
113++ for image_namespace in CONF.reserved_image_namespaces:
114++ if image_namespace not in reserved_name_spaces:
115++ reserved_name_spaces.append(image_namespace)
116++
117++ if not metadata:
118++ LOG.debug("No metadata to be filtered.")
119++ return {}
120++
121++ new_metadata = {}
122++ for k, v in metadata.items():
123++ if any(k.startswith(reserved_name_space)
124++ for reserved_name_space in reserved_name_spaces):
125++ continue
126++ new_metadata[k] = v
127++
128++ LOG.debug("The metadata set [%s] was filtered using the reserved name "
129++ "spaces [%s], and the result is [%s].", metadata,
130++ reserved_name_spaces, new_metadata)
131++ return new_metadata
132+diff --git a/cinder/tests/unit/test_image_utils.py b/cinder/tests/unit/test_image_utils.py
133+index 37fda1c53..508d8bdeb 100644
134+--- a/cinder/tests/unit/test_image_utils.py
135++++ b/cinder/tests/unit/test_image_utils.py
136+@@ -2504,3 +2504,69 @@ class TestImageFormatCheck(test.TestCase):
137+
138+ image_utils.convert_image(src, dest, out_fmt)
139+ mock_check.assert_called_once_with(src, None, None, None, True)
140++
141++
142++@ddt.ddt
143++class TestFilterReservedNamespaces(test.TestCase):
144++
145++ def setUp(self):
146++ super(TestFilterReservedNamespaces, self).setUp()
147++ self.mock_object(image_utils, 'LOG', side_effect=image_utils.LOG)
148++
149++ def test_filter_out_reserved_namespaces_metadata_with_empty_metadata(self):
150++ metadata_for_test = None
151++ method_return = image_utils.filter_out_reserved_namespaces_metadata(
152++ metadata_for_test)
153++
154++ self.assertEqual({}, method_return)
155++
156++ image_utils.LOG.debug.assert_has_calls(
157++ [mock.call("No metadata to be filtered.")]
158++ )
159++
160++ @ddt.data( # remove default keys
161++ ({"some_key": 13, "other_key": "test",
162++ "os_glance_key": "this should be removed",
163++ "os_glance_key2": "this should also be removed"},
164++ None,
165++ []),
166++ # remove nothing
167++ ({"some_key": 13, "other_key": "test"},
168++ None,
169++ []),
170++ # custom config empty
171++ ({"some_key": 13, "other_key": "test",
172++ "os_glance_key": "this should be removed",
173++ "os_glance_key2": "this should also be removed"},
174++ [],
175++ []),
176++ # custom config
177++ ({"some_key": 13, "other_key": "test",
178++ "os_glance_key": "this should be removed",
179++ "os_glance_key2": "this should also be removed",
180++ "custom_key": "this should be removed",
181++ "another_custom_key": "this should also be removed"},
182++ ['custom_key', 'another_custom_key'],
183++ ['custom_key', 'another_custom_key']))
184++ @ddt.unpack
185++ def test_filter_out_reserved_namespaces_metadata(
186++ self, metadata_for_test, config, keys_to_pop):
187++ hardcoded_keys = ['os_glance', "img_signature"]
188++
189++ keys_to_pop = hardcoded_keys + keys_to_pop
190++
191++ if config:
192++ self.override_config('reserved_image_namespaces', config)
193++
194++ expected_result = {"some_key": 13, "other_key": "test"}
195++
196++ method_return = image_utils.filter_out_reserved_namespaces_metadata(
197++ metadata_for_test)
198++
199++ self.assertEqual(expected_result, method_return)
200++
201++ image_utils.LOG.debug.assert_has_calls([
202++ mock.call("The metadata set [%s] was filtered using the reserved "
203++ "name spaces [%s], and the result is [%s].",
204++ metadata_for_test, keys_to_pop, expected_result)
205++ ])
206+diff --git a/cinder/volume/api.py b/cinder/volume/api.py
207+index 3a9c6377a..394511d6e 100644
208+--- a/cinder/volume/api.py
209++++ b/cinder/volume/api.py
210+@@ -42,6 +42,7 @@ from cinder import flow_utils
211+ from cinder.i18n import _
212+ from cinder.image import cache as image_cache
213+ from cinder.image import glance
214++from cinder.image import image_utils
215+ from cinder.message import api as message_api
216+ from cinder.message import message_field
217+ from cinder import objects
218+@@ -1481,6 +1482,9 @@ class API(base.Base):
219+
220+ try:
221+ self._merge_volume_image_meta(context, volume, metadata)
222++ metadata = image_utils.filter_out_reserved_namespaces_metadata(
223++ metadata)
224++
225+ recv_metadata = self.image_service.create(context, metadata)
226+
227+ # NOTE(ZhengMa): Check if allow image compression before image
228+diff --git a/releasenotes/notes/fix-reserved-image-properties-9519ddc080e7ed1a.yaml b/releasenotes/notes/fix-reserved-image-properties-9519ddc080e7ed1a.yaml
229+new file mode 100644
230+index 000000000..8f3f92eee
231+--- /dev/null
232++++ b/releasenotes/notes/fix-reserved-image-properties-9519ddc080e7ed1a.yaml
233+@@ -0,0 +1,28 @@
234++---
235++upgrade:
236++ - |
237++ We introduced a new config parameter, ``reserved_image_namespaces``,
238++ that allows operators to set the image properties to filter out from
239++ volume image metadata by namespace when uploading a volume to Glance.
240++ These properties, if not filtered out, cause failures when uploading
241++ images back to Glance. The error will happen on Glance side when the
242++ reserved namespaces are used. This option is also useful when an operator
243++ wants to use the Glance property protections feature to make some image
244++ properties read-only.
245++fixes:
246++ - |
247++ `Bug #1945500 <https://bugs.launchpad.net/cinder/+bug/1945500>`_: Fixed
248++ an error when uploading to Glance a previously downloaded glance image
249++ when glance multistore is enabled. Glance reserves image properties
250++ in the namespace 'os_glance' for its own use and will not allow
251++ images to be created with these properties. Additionally, there are image
252++ properties, such as those associated with image signature verification,
253++ that are stored in a volume's image metadata, which should not be added
254++ to a new image when a volume is being uploaded as an image. Thus Cinder
255++ will no longer include any volume image metadata in the namespaces
256++ ``os_glance`` and ``img_signature`` when it creates an image in Glance.
257++ Furthermore, because the Glance property protections feature allows an
258++ operator to configure specific image properties as read-only, this fix
259++ adds a configuration option, ``reserved_image_namespaces``, that allows an
260++ operator to exclude additional image properties by namespace (the
261++ ``os_glance`` and ``img_signature`` namespaces are *always* excluded).
262+--
263+2.34.1
264+
265diff --git a/debian/patches/series b/debian/patches/series
266index 872d7a5..7f59854 100644
267--- a/debian/patches/series
268+++ b/debian/patches/series
269@@ -2,3 +2,4 @@ patch-botocore-exceptions.patch
270 skip-moto-tests.patch
271 skip-victoria-failures.patch
272 fix-qos-computation.patch
273+lp1945500.patch

Subscribers

People subscribed via source and target branches