Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-glanceclient for
openSUSE:Factory checked in at 2026-08-09 21:35:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-glanceclient (Old)
and /work/SRC/openSUSE:Factory/.python-glanceclient.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-glanceclient"
Sun Aug 9 21:35:10 2026 rev:45 rq:1370119 version:4.12.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-glanceclient/python-glanceclient.changes
2026-05-18 17:50:39.510854271 +0200
+++
/work/SRC/openSUSE:Factory/.python-glanceclient.new.16738/python-glanceclient.changes
2026-08-09 21:37:35.974859754 +0200
@@ -1,0 +2,11 @@
+Thu Aug 6 20:40:24 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 4.12.0:
+ * Remove useless glanceclient/common/https.py
+ * Support for downloading image from preferred stores
+ * Fix unit tests with urllib3 2.x
+ * Update master for stable/2026.1
+- drop 0001-Fix-bytes-related-test-failures-with-urllib-3.patch
+ (upstream)
+
+-------------------------------------------------------------------
Old:
----
0001-Fix-bytes-related-test-failures-with-urllib-3.patch
python_glanceclient-4.11.0.tar.gz
New:
----
python_glanceclient-4.12.0.tar.gz
----------(Old B)----------
Old: * Update master for stable/2026.1
- drop 0001-Fix-bytes-related-test-failures-with-urllib-3.patch
(upstream)
----------(Old E)----------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-glanceclient.spec ++++++
--- /var/tmp/diff_new_pack.FICTEz/_old 2026-08-09 21:37:36.494877461 +0200
+++ /var/tmp/diff_new_pack.FICTEz/_new 2026-08-09 21:37:36.498877598 +0200
@@ -18,14 +18,13 @@
%global pythons %{primary_python}
Name: python-glanceclient
-Version: 4.11.0
+Version: 4.12.0
Release: 0
Summary: Python API and CLI for OpenStack Glance
License: Apache-2.0
Group: Development/Languages/Python
URL: https://docs.openstack.org/python-glanceclient
Source0:
https://files.pythonhosted.org/packages/source/p/python_glanceclient/python_glanceclient-%{version}.tar.gz
-Patch: 0001-Fix-bytes-related-test-failures-with-urllib-3.patch
BuildRequires: %{python_module PrettyTable >= 0.7.1}
BuildRequires: %{python_module ddt}
BuildRequires: %{python_module fixtures}
++++++ python_glanceclient-4.11.0.tar.gz -> python_glanceclient-4.12.0.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_glanceclient-4.11.0/ChangeLog
new/python_glanceclient-4.12.0/ChangeLog
--- old/python_glanceclient-4.11.0/ChangeLog 2026-02-27 16:44:21.000000000
+0100
+++ new/python_glanceclient-4.12.0/ChangeLog 2026-05-19 11:26:32.000000000
+0200
@@ -1,6 +1,14 @@
CHANGES
=======
+4.12.0
+------
+
+* Remove useless glanceclient/common/https.py
+* Support for downloading image from preferred stores
+* Fix unit tests with urllib3 2.x
+* Update master for stable/2026.1
+
4.11.0
------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_glanceclient-4.11.0/PKG-INFO
new/python_glanceclient-4.12.0/PKG-INFO
--- old/python_glanceclient-4.11.0/PKG-INFO 2026-02-27 16:44:21.827034500
+0100
+++ new/python_glanceclient-4.12.0/PKG-INFO 2026-05-19 11:26:32.340457000
+0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: python-glanceclient
-Version: 4.11.0
+Version: 4.12.0
Summary: OpenStack Image API Client Library
Home-page: https://docs.openstack.org/python-glanceclient/latest/
Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/common/https.py
new/python_glanceclient-4.12.0/glanceclient/common/https.py
--- old/python_glanceclient-4.11.0/glanceclient/common/https.py 2026-02-27
16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/common/https.py 1970-01-01
01:00:00.000000000 +0100
@@ -1,250 +0,0 @@
-# Copyright 2014 Red Hat, Inc
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import socket
-import ssl
-import struct
-
-import OpenSSL
-
-
-try:
- from eventlet import patcher
- # Handle case where we are running in a monkey patched environment
- if patcher.is_monkey_patched('socket'):
- from eventlet.green.httplib import HTTPSConnection
- from eventlet.green.OpenSSL.SSL import GreenConnection as Connection
- else:
- raise ImportError
-except ImportError:
- import http.client
- from OpenSSL import SSL
- HTTPSConnection = http.client.HTTPSConnection
- Connection = SSL.Connection
-
-
-from glanceclient import exc
-
-
-def verify_callback(host=None):
- """Provide wrapper for do_verify_callback.
-
- We use a partial around the 'real' verify_callback function
- so that we can stash the host value without holding a
- reference on the VerifiedHTTPSConnection.
- """
- def wrapper(connection, x509, errnum,
- depth, preverify_ok, host=host):
- return do_verify_callback(connection, x509, errnum,
- depth, preverify_ok, host=host)
- return wrapper
-
-
-def do_verify_callback(connection, x509, errnum,
- depth, preverify_ok, host=None):
- """Verify the server's SSL certificate.
-
- This is a standalone function rather than a method to avoid
- issues around closing sockets if a reference is held on
- a VerifiedHTTPSConnection by the callback function.
- """
- if x509.has_expired():
- msg = "SSL Certificate expired on '%s'" % x509.get_notAfter()
- raise exc.SSLCertificateError(msg)
-
- if depth == 0 and preverify_ok:
- # We verify that the host matches against the last
- # certificate in the chain
- return host_matches_cert(host, x509)
- else:
- # Pass through OpenSSL's default result
- return preverify_ok
-
-
-def host_matches_cert(host, x509):
- """Verify the certificate identifies the host.
-
- Verify that the x509 certificate we have received
- from 'host' correctly identifies the server we are
- connecting to, ie that the certificate's Common Name
- or a Subject Alternative Name matches 'host'.
- """
- def check_match(name):
- # Directly match the name
- if name == host:
- return True
-
- # Support single wildcard matching
- if name.startswith('*.') and host.find('.') > 0:
- if name[2:] == host.split('.', 1)[1]:
- return True
-
- common_name = x509.get_subject().commonName
-
- # First see if we can match the CN
- if check_match(common_name):
- return True
- # Also try Subject Alternative Names for a match
- san_list = None
- for i in range(x509.get_extension_count()):
- ext = x509.get_extension(i)
- if ext.get_short_name() == b'subjectAltName':
- san_list = str(ext)
- for san in ''.join(san_list.split()).split(','):
- if san.startswith('DNS:'):
- if check_match(san.split(':', 1)[1]):
- return True
-
- # Server certificate does not match host
- msg = ('Host "%s" does not match x509 certificate contents: '
- 'CommonName "%s"' % (host, common_name))
- if san_list is not None:
- msg = msg + ', subjectAltName "%s"' % san_list
- raise exc.SSLCertificateError(msg)
-
-
-def to_bytes(s):
- if isinstance(s, str):
- return bytes(s, 'latin-1')
- else:
- return s
-
-
-class OpenSSLConnectionDelegator(object):
- """An OpenSSL.SSL.Connection delegator.
-
- Supplies an additional 'makefile' method which httplib requires
- and is not present in OpenSSL.SSL.Connection.
-
- Note: Since it is not possible to inherit from OpenSSL.SSL.Connection
- a delegator must be used.
- """
- def __init__(self, *args, **kwargs):
- self.connection = Connection(*args, **kwargs)
-
- def __getattr__(self, name):
- return getattr(self.connection, name)
-
- def makefile(self, *args, **kwargs):
- return socket._fileobject(self.connection, *args, **kwargs)
-
-
-class VerifiedHTTPSConnection(HTTPSConnection):
- """Extended OpenSSL HTTPSConnection for enhanced SSL support.
-
- Note: Much of this functionality can eventually be replaced
- with native Python 3.3 code.
- """
- # Restrict the set of client supported cipher suites
- CIPHERS = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:'\
- 'eCDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:'\
- 'RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
-
- def __init__(self, host, port=None, key_file=None, cert_file=None,
- cacert=None, timeout=None, insecure=False,
- ssl_compression=True):
- # List of exceptions reported by Python3 instead of
- # SSLConfigurationError
- excp_lst = (TypeError, FileNotFoundError, ssl.SSLError)
- try:
- HTTPSConnection.__init__(self, host, port,
- key_file=key_file,
- cert_file=cert_file)
- self.key_file = key_file
- self.cert_file = cert_file
- self.timeout = timeout
- self.insecure = insecure
- # NOTE(flaper87): `is_verified` is needed for
- # requests' urllib3. If insecure is True then
- # the request is not `verified`, hence `not insecure`
- self.is_verified = not insecure
- self.ssl_compression = ssl_compression
- self.cacert = None if cacert is None else str(cacert)
- self.set_context()
- # ssl exceptions are reported in various form in Python 3
- # so to be compatible, we report the same kind as under
- # Python2
- except excp_lst as e:
- raise exc.SSLConfigurationError(str(e))
-
- def set_context(self):
- """Set up the OpenSSL context."""
- self.context = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
- self.context.set_cipher_list(self.CIPHERS)
-
- if self.ssl_compression is False:
- self.context.set_options(0x20000) # SSL_OP_NO_COMPRESSION
-
- if self.insecure is not True:
- self.context.set_verify(OpenSSL.SSL.VERIFY_PEER,
- verify_callback(host=self.host))
- else:
- self.context.set_verify(OpenSSL.SSL.VERIFY_NONE,
- lambda *args: True)
-
- if self.cert_file:
- try:
- self.context.use_certificate_file(self.cert_file)
- except Exception as e:
- msg = 'Unable to load cert from "%s" %s' % (self.cert_file, e)
- raise exc.SSLConfigurationError(msg)
- if self.key_file is None:
- # We support having key and cert in same file
- try:
- self.context.use_privatekey_file(self.cert_file)
- except Exception as e:
- msg = ('No key file specified and unable to load key '
- 'from "%s" %s' % (self.cert_file, e))
- raise exc.SSLConfigurationError(msg)
-
- if self.key_file:
- try:
- self.context.use_privatekey_file(self.key_file)
- except Exception as e:
- msg = 'Unable to load key from "%s" %s' % (self.key_file, e)
- raise exc.SSLConfigurationError(msg)
-
- if self.cacert:
- try:
- self.context.load_verify_locations(to_bytes(self.cacert))
- except Exception as e:
- msg = 'Unable to load CA from "%s" %s' % (self.cacert, e)
- raise exc.SSLConfigurationError(msg)
- else:
- self.context.set_default_verify_paths()
-
- def connect(self):
- """Connect to an SSL port using the OpenSSL library.
-
- This method also applies per-connection parameters to the connection.
- """
- result = socket.getaddrinfo(self.host, self.port, 0,
- socket.SOCK_STREAM)
- if result:
- socket_family = result[0][0]
- if socket_family == socket.AF_INET6:
- sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
- else:
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- else:
- # If due to some reason the address lookup fails - we still connect
- # to IPv4 socket. This retains the older behavior.
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- if self.timeout is not None:
- # '0' microseconds
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO,
- struct.pack('LL', self.timeout, 0))
- self.sock = OpenSSLConnectionDelegator(self.context, sock)
- self.sock.connect((self.host, self.port))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/test_http.py
new/python_glanceclient-4.12.0/glanceclient/tests/unit/test_http.py
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/test_http.py
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/test_http.py
2026-05-19 11:25:56.000000000 +0200
@@ -318,7 +318,7 @@
def test_http_chunked_request(self):
text = "Ok"
- data = io.StringIO(text)
+ data = io.BytesIO(text.encode())
path = '/v1/images/'
self.mock.post(self.endpoint + path, text=text)
@@ -341,9 +341,9 @@
self.assertEqual(data, json.loads(self.mock.last_request.body))
def test_http_chunked_response(self):
- data = "TEST"
+ data = b"TEST"
path = '/v1/images/'
- self.mock.get(self.endpoint + path, body=io.StringIO(data),
+ self.mock.get(self.endpoint + path, body=io.BytesIO(data),
headers={"Content-Type": "application/octet-stream"})
resp, body = self.client.get(path)
@@ -353,10 +353,10 @@
@original_only
def test_log_http_response_with_non_ascii_char(self):
try:
- response = 'Ok'
+ response = b'Ok'
headers = {"Content-Type": "text/plain",
"test": "value1\xa5\xa6"}
- fake = utils.FakeResponse(headers, io.StringIO(response))
+ fake = utils.FakeResponse(headers, io.BytesIO(response))
self.client.log_http_response(fake)
except UnicodeDecodeError as e:
self.fail("Unexpected UnicodeDecodeError exception '%s'" % e)
@@ -457,9 +457,9 @@
def test_log_request_id_once(self):
logger = self.useFixture(fixtures.FakeLogger(level=logging.DEBUG))
- data = "TEST"
+ data = b"TEST"
path = '/v1/images/'
- self.mock.get(self.endpoint + path, body=io.StringIO(data),
+ self.mock.get(self.endpoint + path, body=io.BytesIO(data),
headers={"Content-Type": "application/octet-stream",
'x-openstack-request-id': "1234"})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/test_ssl.py
new/python_glanceclient-4.12.0/glanceclient/tests/unit/test_ssl.py
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/test_ssl.py
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/test_ssl.py
2026-05-19 11:25:56.000000000 +0200
@@ -77,7 +77,7 @@
def test_v1_requests_cert_verification(self, __):
"""v1 regression test for bug 115260."""
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
try:
client = v1.Client(url,
@@ -94,7 +94,7 @@
"""v1 regression test for bug 115260."""
# Legacy test. Verify 'no compression' has no effect
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
try:
client = v1.Client(url,
@@ -110,7 +110,7 @@
def test_v2_requests_cert_verification(self, __):
"""v2 regression test for bug 115260."""
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
try:
gc = v2.Client(url,
@@ -127,7 +127,7 @@
"""v2 regression test for bug 115260."""
# Legacy test. Verify 'no compression' has no effect
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
try:
gc = v2.Client(url,
@@ -143,7 +143,7 @@
def test_v2_requests_valid_cert_verification(self, __):
"""Test absence of SSL key file."""
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
try:
@@ -158,9 +158,9 @@
@mock.patch('sys.stderr')
def test_v2_requests_valid_cert_verification_no_compression(self, __):
- """Test VerifiedHTTPSConnection: absence of SSL key file."""
+ """Test SSL certificate verification with valid CA certificate."""
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
try:
@@ -175,9 +175,9 @@
@mock.patch('sys.stderr')
def test_v2_requests_valid_cert_no_key(self, __):
- """Test VerifiedHTTPSConnection: absence of SSL key file."""
+ """Test client cert authentication fails without private key."""
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
@@ -194,9 +194,9 @@
@mock.patch('sys.stderr')
def test_v2_requests_bad_cert(self, __):
- """Test VerifiedHTTPSConnection: absence of SSL key file."""
+ """Test client cert authentication fails with bad certificate."""
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
cert_file = os.path.join(TEST_VAR_DIR, 'badcert.crt')
cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
@@ -217,9 +217,9 @@
@mock.patch('sys.stderr')
def test_v2_requests_bad_ca(self, __):
- """Test VerifiedHTTPSConnection: absence of SSL key file."""
+ """Test SSL verification fails with invalid CA certificate path."""
port = self.port
- url = 'https://0.0.0.0:%d' % port
+ url = 'https://127.0.0.1:%d' % port
cacert = os.path.join(TEST_VAR_DIR, 'badca.crt')
try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/v2/test_images.py
new/python_glanceclient-4.12.0/glanceclient/tests/unit/v2/test_images.py
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/v2/test_images.py
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/v2/test_images.py
2026-05-19 11:25:56.000000000 +0200
@@ -1323,6 +1323,36 @@
except exc.HTTPForbidden:
pass
+ def test_data_with_prefer(self):
+ image_id = '606b0e88-7c5a-4d54-b5bb-046105d4de6f'
+ prefer = ['store1', 'store2']
+ resp = utils.FakeResponse(headers={'content-length': '3'},
+ status_code=200)
+ self.controller.controller.http_client.get = mock.Mock(
+ return_value=(resp, 'CCC'))
+ self.controller.data(image_id, do_checksum=False,
+ prefer=prefer)
+ # Check that the prefer parameter was passed as query parameters
+ calls = self.controller.controller.http_client.get.call_args_list
+ self.assertEqual(1, len(calls))
+ expected_call = calls[0]
+ self.assertIn('prefer=store1%2Cstore2', expected_call[0][0])
+ self.assertNotIn('stores', expected_call[0][0])
+
+ def test_data_without_stores(self):
+ image_id = '606b0e88-7c5a-4d54-b5bb-046105d4de6f'
+ resp = utils.FakeResponse(headers={'content-length': '3'},
+ status_code=200)
+ self.controller.controller.http_client.get = mock.Mock(
+ return_value=(resp, 'CCC'))
+ self.controller.data(image_id, do_checksum=False)
+ # Check that no query parameters were added
+ calls = self.controller.controller.http_client.get.call_args_list
+ self.assertEqual(1, len(calls))
+ expected_call = calls[0]
+ self.assertEqual('/v2/images/%s/file' % image_id, expected_call[0][0])
+ self.assertNotIn('?', expected_call[0][0])
+
def test_update_replace_prop(self):
image_id = '3a4560a1-e585-443e-9b39-553b46ec92d1'
params = {'name': 'pong'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/v2/test_shell_v2.py
new/python_glanceclient-4.12.0/glanceclient/tests/unit/v2/test_shell_v2.py
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/v2/test_shell_v2.py
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/v2/test_shell_v2.py
2026-05-19 11:25:56.000000000 +0200
@@ -2774,7 +2774,7 @@
def test_image_download(self):
args = self._make_args(
{'id': 'IMG-01', 'file': 'test', 'progress': True,
- 'allow_md5_fallback': False})
+ 'allow_md5_fallback': False, 'prefer': None})
with mock.patch.object(self.gc.images, 'data') as mocked_data, \
mock.patch.object(utils, '_extract_request_id'):
@@ -2783,7 +2783,8 @@
test_shell.do_image_download(self.gc, args)
mocked_data.assert_called_once_with('IMG-01',
- allow_md5_fallback=False)
+ allow_md5_fallback=False,
+ prefer=None)
# check that non-default value is being passed correctly
args.allow_md5_fallback = True
@@ -2794,7 +2795,8 @@
test_shell.do_image_download(self.gc, args)
mocked_data.assert_called_once_with('IMG-01',
- allow_md5_fallback=True)
+ allow_md5_fallback=True,
+ prefer=None)
@mock.patch.object(utils, 'exit')
@mock.patch('sys.stdout', autospec=True)
@@ -2802,7 +2804,7 @@
mocked_utils_exit):
# Indicate that no file name was given as command line argument
args = self._make_args({'id': '1234', 'file': None, 'progress': False,
- 'allow_md5_fallback': False})
+ 'allow_md5_fallback': False, 'prefer': None})
# Indicate that no file is specified for output redirection
mocked_stdout.isatty = lambda: True
test_shell.do_image_download(self.gc, args)
@@ -2917,7 +2919,8 @@
mocked_stdout):
args = self._make_args({'id': 'IMG-01', 'file': None,
'progress': False,
- 'allow_md5_fallback': False})
+ 'allow_md5_fallback': False,
+ 'prefer': None})
mocked_stdout.isatty = lambda: False
with mock.patch.object(self.gc.images, 'data') as mocked_data:
mocked_data.side_effect = exc.HTTPForbidden
@@ -2935,7 +2938,8 @@
def test_do_image_download_with_500(self, mocked_print_err, mocked_stdout):
args = self._make_args({'id': 'IMG-01', 'file': None,
'progress': False,
- 'allow_md5_fallback': False})
+ 'allow_md5_fallback': False,
+ 'prefer': None})
mocked_stdout.isatty = lambda: False
with mock.patch.object(self.gc.images, 'data') as mocked_data:
mocked_data.side_effect = exc.HTTPInternalServerError
@@ -2948,6 +2952,51 @@
self.assertEqual(1, mocked_data.call_count)
self.assertEqual(1, mocked_print_err.call_count)
+ def test_image_download_with_prefer(self):
+ args = self._make_args(
+ {'id': 'IMG-01', 'file': 'test', 'progress': False,
+ 'allow_md5_fallback': False, 'prefer': 'store1,store2'})
+
+ with mock.patch.object(self.gc.images, 'data') as mocked_data, \
+ mock.patch.object(utils, '_extract_request_id'):
+ mocked_data.return_value = utils.RequestIdProxy(
+ [c for c in 'abcdef'])
+
+ test_shell.do_image_download(self.gc, args)
+ mocked_data.assert_called_once_with('IMG-01',
+ allow_md5_fallback=False,
+ prefer=['store1', 'store2'])
+
+ def test_image_download_with_prefer_empty_string(self):
+ args = self._make_args(
+ {'id': 'IMG-01', 'file': 'test', 'progress': False,
+ 'allow_md5_fallback': False, 'prefer': ''})
+
+ with mock.patch.object(self.gc.images, 'data') as mocked_data, \
+ mock.patch.object(utils, '_extract_request_id'):
+ mocked_data.return_value = utils.RequestIdProxy(
+ [c for c in 'abcdef'])
+
+ test_shell.do_image_download(self.gc, args)
+ mocked_data.assert_called_once_with('IMG-01',
+ allow_md5_fallback=False,
+ prefer=None)
+
+ def test_image_download_without_prefer(self):
+ args = self._make_args(
+ {'id': 'IMG-01', 'file': 'test', 'progress': False,
+ 'allow_md5_fallback': False, 'prefer': None})
+
+ with mock.patch.object(self.gc.images, 'data') as mocked_data, \
+ mock.patch.object(utils, '_extract_request_id'):
+ mocked_data.return_value = utils.RequestIdProxy(
+ [c for c in 'abcdef'])
+
+ test_shell.do_image_download(self.gc, args)
+ mocked_data.assert_called_once_with('IMG-01',
+ allow_md5_fallback=False,
+ prefer=None)
+
def test_do_member_list(self):
args = self._make_args({'image_id': 'IMG-01'})
with mock.patch.object(self.gc.image_members, 'list') as mocked_list:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/ca.crt
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/ca.crt
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/ca.crt
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/ca.crt
2026-05-19 11:25:56.000000000 +0200
@@ -1,36 +1,38 @@
+# DO NOT EDIT. This file is generated by tools/generate_test_certs.sh
-----BEGIN CERTIFICATE-----
-MIIGVTCCBD2gAwIBAgIUEstxpjoCFDZo8K1Mmz7QIpYwSXIwDQYJKoZIhvcNAQEL
+MIIGYzCCBEugAwIBAgIUVH2HK/6/Au6Gf7JYvFM+Rps4J94wDQYJKoZIhvcNAQEL
BQAwgbgxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhTdGF0ZSBDQTELMAkGA1UEBwwC
Q0ExGTAXBgNVBAoMEE9wZW5TdGFjayBDQSBPcmcxGjAYBgNVBAsMEU9wZW5TdGFj
ayBUZXN0IENBMS0wKwYDVQQDDCRPcGVuc3RhY2sgVGVzdCBDZXJ0aWZpY2F0ZSBB
-dXRob3JpdHkxIzAhBgkqhkiG9w0BCQEWFGFkbWluQGNhLmV4YW1wbGUuY29tMCAX
-DTIwMDQwNzEyMjYwMVoYDzI5OTkwMTAxMTIyNjAxWjCBuDELMAkGA1UEBhMCQVUx
-ETAPBgNVBAgMCFN0YXRlIENBMQswCQYDVQQHDAJDQTEZMBcGA1UECgwQT3BlblN0
-YWNrIENBIE9yZzEaMBgGA1UECwwRT3BlblN0YWNrIFRlc3QgQ0ExLTArBgNVBAMM
-JE9wZW5zdGFjayBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTEjMCEGCSqGSIb3
-DQEJARYUYWRtaW5AY2EuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4IC
-DwAwggIKAoICAQD6KfGpVSJsmhTgdbdovaaa3Qe4PeP+Dg9Y7muSggVQVlqUp3YB
-xUSo1RDoLyu1ci+KrNODr+kkD/Cbo8yJQCxqTzUpCw3tadFhUJOWvPaqdcYTA8R9
-p7Xjvw3Me7Q7xr4l0pCUIiz/kwxYxk+GCQyXzpXZm14zz+Qm8gz37eoW2jJfoyzA
-dB9Tp609Id7C6VHFCWZ2Zsa4+Ua/q+Pn7vLNJ61C2H5sfus8dtcGDzViDWwnWyHw
-spyR79rciV2yA3xeq09RvIx2SB1tc3S2Rxw7SmKeYcnkv6YplvhIG5QpErvp+URh
-De2wbbxzjFzJqFQO0Yh8IgTBIvQI02++lA8ZX84UDaxmrT92m8GfqQvb96em/H1k
-RKJTq0QqSC+BbGDeFxHkuOTJiOZm5Bnivpo0TAPwX6YqpadXARAFWw+fJiHCuFGr
-6ltD7zgRnx6SR5WNRNWmTZQNx7wC2Bm0cJ2ec0Asn+bl93RVloaNtbFJhkaN555G
-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
+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
+VAPX6MRWpQ==
-----END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/certificate.crt
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/certificate.crt
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/certificate.crt
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/certificate.crt
2026-05-19 11:25:56.000000000 +0200
@@ -1,34 +1,36 @@
+# DO NOT EDIT. This file is generated by tools/generate_test_certs.sh
-----BEGIN CERTIFICATE-----
-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
-9l4gwJ1ojNB2abF4LOEf5bU=
+MIIGIjCCBAqgAwIBAgIUa8IbpYTnevi57LCXS/7RHHMAhEQwDQYJKoZIhvcNAQEL
+BQAwgbgxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhTdGF0ZSBDQTELMAkGA1UEBwwC
+Q0ExGTAXBgNVBAoMEE9wZW5TdGFjayBDQSBPcmcxGjAYBgNVBAsMEU9wZW5TdGFj
+ayBUZXN0IENBMS0wKwYDVQQDDCRPcGVuc3RhY2sgVGVzdCBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkxIzAhBgkqhkiG9w0BCQEWFGFkbWluQGNhLmV4YW1wbGUuY29tMB4X
+DTI2MDMwOTE1MjYyMloXDTM2MDMwNjE1MjYyMlowgYcxCzAJBgNVBAYTAkFVMREw
+DwYDVQQIDAhTdGF0ZSBDQTEPMA0GA1UEBwwGU3RhdGUxMRswGQYDVQQKDBJPcGVu
+U3RhY2sgVGVzdCBPcmcxHDAaBgNVBAsME09wZW5TdGFjayBUZXN0IFVuaXQxGTAX
+BgNVBAMMEHRlc3QuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQCcc5oW+VurGaz9KFHaO1DmQm2I7jUsYNsZK9+FnPJMxg836Zk3N1e9
+NDZiwQwXxgcU8yPEFdToqEJEedxi827iQW+yOvZKwCewhyTosqWblxhOUEHPmCRB
+6gJlMzxUj3JKoBbZyoBp1bjpMq8262fNVCxmwR7lMW6Fcmv1hrrtZY/BFA8h2j1R
+H8wIsSN+cQXyresXaP1hff67S/MKJWrQCcLL1MmBzD7ukbUaCaOmcCfhU10/2L99
+EtbZhc12DWxfWPdTs/wPwxPfWfuebv3T153B9sWSiIR2gClIFhm/moslbsDrlAmf
+hcPxLz6cUpWtqyk2kOXeoNiOgPD+om98Q9SunokPFI9uLjSy/wkbXbW6/C14ay8c
++044foTs6u2ACnKne9FricVB3p8zLhn5vtVAAE0koH8/aVUWkOD13lNLxIyz4kc2
+4qwIUOjc/YLcYoCZw91A7TRFQuHgm0A1GtBDIUg393fGsXMR8jXz6YOcI4tYobDK
+FXX3m8K79h3LgdKQismD/+hjZNOqgzYR7WH+6LMZw8ueXnBZzK0716iRC603dswU
+mUF5Ajz9YRWdGHn+MRdk3L4/p3YZzLkpLf1itgMxoyYsdyPyYktr+n7cmf8mqCBi
+5P+qhdGZqFh+1haZX/f8ugqN5Ev0LNUFQHBxGcPn4ascBXXW0N9gHwIDAQABo1Mw
+UTAPBgNVHREECDAGhwR/AAABMB0GA1UdDgQWBBS7bt0vNE5i4KM+nLEo+ZgdhHwN
+bTAfBgNVHSMEGDAWgBSdjBWCNzn38PrEmKGB2t7KLGKxHjANBgkqhkiG9w0BAQsF
+AAOCAgEAKJu6m7MhTUZx7g9jXltZJ/oI+EWDPAKocp5Z38ipfSa1pkmYc3wIWU1h
+FxBleFjbWFCHL6l3vHSjbm7ExfB9w+J9SA/7ZmztC2NiS7DimwPexlIAStESQhPp
+wBSSQWD3b/N+JYDmLykyDkNcgq+eNSs9Fn50mqnsgm1Q+UiFX13l97MnlH5S83RB
+KnsnR1PwL3a1XaiGPu8TlKabm40AGwBVVX2Y85jU/WMYTkZZJf/LtxNh6CLqcnQ2
+WPOyArKgXQVDhO9oeHfwK3K8FBzFtDHC+1TY962mC2yzqCv2eBbDeyk9hPhQQqUT
+VXUo49lW+ZryTRXVlHZYVFuMxedjDr6AMPf1y8m228p7H2rIiB+FWYPIv7xJ08T0
+hGT4NMMv+yrk3ZgabCmtPAqCVcmRTiPmygFu7QsantwI8o19/BFlE7xgOKNvIc7J
+ozNdBpcjXIYjtBi79dVSgqL3kzMJERUqu+uykLqruysGLMPcPtmAQxLOU/YuKray
+0j0QIiKN4XcArTR55L3hrREJKGw3wCgvYSahVoj04timrsIUnUl+YymjKAwykMP0
+/wZxdtLFpYOueAYrMgbOQOVfVxA4tfFD7hQuWr8VIRahDyjhb+rsH533xllDkDLB
+zHpRA3zDHjJXn8kP9DaNYo3tSBJQ9FzR6uQFexjqiTVwe4BBXi0=
-----END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/expired-cert.crt
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/expired-cert.crt
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/expired-cert.crt
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/expired-cert.crt
2026-05-19 11:25:56.000000000 +0200
@@ -1,35 +1,36 @@
+# DO NOT EDIT. This file is generated by tools/generate_test_certs.sh
-----BEGIN CERTIFICATE-----
-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
-l3+dFHnWayuCdqcFwIl3m8i8FupFihz9+A==
+MIIGIjCCBAqgAwIBAgIUa8IbpYTnevi57LCXS/7RHHMAhEUwDQYJKoZIhvcNAQEL
+BQAwgbgxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhTdGF0ZSBDQTELMAkGA1UEBwwC
+Q0ExGTAXBgNVBAoMEE9wZW5TdGFjayBDQSBPcmcxGjAYBgNVBAsMEU9wZW5TdGFj
+ayBUZXN0IENBMS0wKwYDVQQDDCRPcGVuc3RhY2sgVGVzdCBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkxIzAhBgkqhkiG9w0BCQEWFGFkbWluQGNhLmV4YW1wbGUuY29tMB4X
+DTI2MDMwOTE1MjYyMloXDTI2MDMwOTE1MjYyMlowgYcxCzAJBgNVBAYTAkFVMREw
+DwYDVQQIDAhTdGF0ZSBDQTEPMA0GA1UEBwwGU3RhdGUxMRswGQYDVQQKDBJPcGVu
+U3RhY2sgVGVzdCBPcmcxHDAaBgNVBAsME09wZW5TdGFjayBUZXN0IFVuaXQxGTAX
+BgNVBAMMEHRlc3QuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQCcc5oW+VurGaz9KFHaO1DmQm2I7jUsYNsZK9+FnPJMxg836Zk3N1e9
+NDZiwQwXxgcU8yPEFdToqEJEedxi827iQW+yOvZKwCewhyTosqWblxhOUEHPmCRB
+6gJlMzxUj3JKoBbZyoBp1bjpMq8262fNVCxmwR7lMW6Fcmv1hrrtZY/BFA8h2j1R
+H8wIsSN+cQXyresXaP1hff67S/MKJWrQCcLL1MmBzD7ukbUaCaOmcCfhU10/2L99
+EtbZhc12DWxfWPdTs/wPwxPfWfuebv3T153B9sWSiIR2gClIFhm/moslbsDrlAmf
+hcPxLz6cUpWtqyk2kOXeoNiOgPD+om98Q9SunokPFI9uLjSy/wkbXbW6/C14ay8c
++044foTs6u2ACnKne9FricVB3p8zLhn5vtVAAE0koH8/aVUWkOD13lNLxIyz4kc2
+4qwIUOjc/YLcYoCZw91A7TRFQuHgm0A1GtBDIUg393fGsXMR8jXz6YOcI4tYobDK
+FXX3m8K79h3LgdKQismD/+hjZNOqgzYR7WH+6LMZw8ueXnBZzK0716iRC603dswU
+mUF5Ajz9YRWdGHn+MRdk3L4/p3YZzLkpLf1itgMxoyYsdyPyYktr+n7cmf8mqCBi
+5P+qhdGZqFh+1haZX/f8ugqN5Ev0LNUFQHBxGcPn4ascBXXW0N9gHwIDAQABo1Mw
+UTAPBgNVHREECDAGhwR/AAABMB0GA1UdDgQWBBS7bt0vNE5i4KM+nLEo+ZgdhHwN
+bTAfBgNVHSMEGDAWgBSdjBWCNzn38PrEmKGB2t7KLGKxHjANBgkqhkiG9w0BAQsF
+AAOCAgEAMCwZe3uUThBuhcI01Xzr1J08YqHB81WeORqRRmhQoSQZVawuwgMqFKzv
+GOEYGi1cYB1r+877C4vDjYtRQmtaLhVd09sgvNmTpdbPWfHooebSJcJzPhKt0Stb
+5oG5AMaM0GrcDPTXz7b81vGJPwKu0lYg/cDXmXbt176i7DHovEFXjA8COfAluc56
+rStc3wFRJ2mYP2j5iEWa7VjXrJGHSDhJAglTg1tuQkmePbcShThzw8OFpUdCBH3H
+s82Pr1aaH4NkgtG81sq+1EPHDOvBR8bjvuzxCDxIOkMMdDW7xjRwIdnT2uOE5kMj
+WJ1Z+AXZIsGvu8Wx2j4nwutuKc71ejHXUir3vrDmbGs7hqUdibu652bycw7Nc7a6
+D2JNrOWzJH7IuIyvR+NmL4IPcG3je3exfwmfz7612VkFv8Ek4cPWGi00zHwkE/Xz
+DMR/lFBc4R6Tpkj09JRWFGL2VDSzImcmaojIqQAapD40nDpZJ8TqOPwpaXeNcWIr
+xpEnMq4pLI9TUWFteXEMh5ij3CB2U0TAXeeowQ5nX2WNrAjnDov+mrSG79eNOBxl
+UblTCjfeytyciH4WQ2BDXkX06db2udeo7hSTABgnUYk26u7r2qPM4O1Zf/sWiDG4
+8oWEaI5553dfsp+sWW5UsC47N3YMUVCyrWX1/yX7Xc9RuuytF34=
-----END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/privatekey.key
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/privatekey.key
--- old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/privatekey.key
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/privatekey.key
2026-05-19 11:25:56.000000000 +0200
@@ -1,51 +1,53 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
+# DO NOT EDIT. This file is generated by tools/generate_test_certs.sh
+-----BEGIN PRIVATE KEY-----
+MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQCcc5oW+VurGaz9
+KFHaO1DmQm2I7jUsYNsZK9+FnPJMxg836Zk3N1e9NDZiwQwXxgcU8yPEFdToqEJE
+edxi827iQW+yOvZKwCewhyTosqWblxhOUEHPmCRB6gJlMzxUj3JKoBbZyoBp1bjp
+Mq8262fNVCxmwR7lMW6Fcmv1hrrtZY/BFA8h2j1RH8wIsSN+cQXyresXaP1hff67
+S/MKJWrQCcLL1MmBzD7ukbUaCaOmcCfhU10/2L99EtbZhc12DWxfWPdTs/wPwxPf
+Wfuebv3T153B9sWSiIR2gClIFhm/moslbsDrlAmfhcPxLz6cUpWtqyk2kOXeoNiO
+gPD+om98Q9SunokPFI9uLjSy/wkbXbW6/C14ay8c+044foTs6u2ACnKne9FricVB
+3p8zLhn5vtVAAE0koH8/aVUWkOD13lNLxIyz4kc24qwIUOjc/YLcYoCZw91A7TRF
+QuHgm0A1GtBDIUg393fGsXMR8jXz6YOcI4tYobDKFXX3m8K79h3LgdKQismD/+hj
+ZNOqgzYR7WH+6LMZw8ueXnBZzK0716iRC603dswUmUF5Ajz9YRWdGHn+MRdk3L4/
+p3YZzLkpLf1itgMxoyYsdyPyYktr+n7cmf8mqCBi5P+qhdGZqFh+1haZX/f8ugqN
+5Ev0LNUFQHBxGcPn4ascBXXW0N9gHwIDAQABAoICABkFdAi7QKnl+qtSSM+k2j9j
+3a4fSr8aORrsJVzHyQig9HYgv1xRVuWaSshoeiKjN9Fl7BEZh2oziXBM0lkQ+GmU
+cDoKVrGFzH3dtKLH+ix0HHMJ6uc55zKTgRE7rH5poqxvW2LhkWqxFQMBaXxYZyAz
+l2unnzql4+MmdZWtl9+3ynyP/2Dj98KDBK1Z3ISwVsnaftVzo8fKesmW+qZjbZMa
+vIi/iKq1m6r+qql2DoeOkGeSXuuDIrzsx70U5SiS5QOAGwN2ru1maZs4V5bzHAKc
+DU2kGzJgRa8eDXwgl2Wetc+lcufk+Spbc7GduLRk5i4BncnC9WsxlkYpi7bDC8k3
+2fVfnfGmhFM57dlTs7IM3maVr8zXoNgADh5Jub2iJO8DxemrUyvDGWjGCwYIemZy
+MW9mOsZZRfx6rSA6L/Y5hp6GxKDd1bAkMTDhfYWgORS+RmXUHDYSAhCOLcwjfixk
+InsVqb7DeYdliKwqTdi4fAnZLIFGSSEoYHHZY/wqYInfi7tBh1pzyOJr/V4HGL6g
+OaPWHdqMdJdfcqtceJUU4l3JyENSihuPxOyqLnXI4PFhHRJXKAm1ba2Jq+B1feAA
+IZzH+oL96OgEu0/RYJcDt2oaSqAxfXuBW70ikbzFzmehCJQHQC0/2vpLY3C6DzB3
+GFF2ncCjOiZh01Ya2O2BAoIBAQDTLtPuq2yHZAVyzbMnjt7A8xKURM6ORaKrzPza
+xqDCg7cSNcKXabu9+NtGydlqaIrR4AAx/Z0sA92mzSB31F7SuBoZL4pxUPWVqsHx
+eFhp7kGRn0CP4Tlmh6gj+Azu9wo+6sH24GbewxD556e/WgtgzdT6lbRDhI083byP
+btGjkbfhcnCCJjpj1/DfI2/8yF81p3gsqOlEmiXB25rP/USZLEXWFDabxPNct6Gp
+K80t0XsxqjX/D7TNeMCu6/E8Xoe+tUdbyyYQ+z1PX2M/+wJkN3Oi6wYFTvrY5NvH
+GbP6b/GaPo24PLEgT6+DdHQFoS+BxfKevuBQi10AmyBYvFHPAoIBAQC9p1KF+F+F
+C4Rj+CnYqE6j2UWZWcSdCrQ5JT4NpZAoexTtskqQqGJ+lrxBLkDldApZDAGlWtkQ
+VXcKsLpbN+R7rV1OaLtO/55LoyIoxJeFDh3ovUuo2JO7n34Dsi4sq0IvUzzndmVW
+xOwwn2a9NvQiulhoFGwO+qdMr22kqJS/M8CEMwz8CUjAW9k2qAFcWdLNzUAKQRRF
+YJkcg87uyHuF8sz7Btp9Xbx26sdx763KThMyXqELtQO30It1n4COT3081JLUhVlc
+RhRe4rOfnhKH9K5SPsK2nBJlF9DWhNmbyhFNS015lLFNhTZ56F3sIU720qqqdGPu
+pm6ETr8cbDCxAoIBAQC0N1cGauWv2GxJ3z5OuL5hHE2zl9BJWyWJxOHW9QBFXk/B
+S31m5wUfBhpiG2jdRJ+KoMSp5IrW/+mMKarWd7X/zrn+2jIjp3ocId9l6FRS+c6c
+rbFT11i7pXKYV1r6Jnlo3b9upWtEGGUJTmY5hmcFUkG5Ij32DEzXL0Z1hJWEJ5sq
+2hUnC+ZyQ9o7Iau0pW2ShPqp6e8+6ujjuTsw2SpMKJrkKNW9MmKXseFUU5vByO1/
+oYh4xHd/jNeprpFr+iOPXHWr4P34Kd7VOEqjU9pjmWqmEjhOGWs54nunOcj8I8Gi
+5lTcb3acY0QdQyirkTTQYxM74xnbwkI4fSkqcHLDAoIBAQCK7LGXr3wREoG1VUka
+CxgoD/VawxYyT2/7WFufVYNHE/odsHfMhXw47KQUPxSMwDcASbo+7VCKFYDxFMo+
+HbBCJJlv4WosETVchLB2GqQ/dDrWjSuKELQPQWLmxDPsxrrhveCkUOck63V0nJ9+
+xW2KruQpwaPySQwaMXtonZDwirFgZaECUq63MdDop6LvimDQHqTlngyCUaN27tq7
+saJCWbxrufZ81RhEJ/FXddHhmtWXFRh1YfDKSnqN+/wIwxOjZrfz84alADTV2Mzp
+hLpgWw0C9DRf3e3fndV9/q0E4L1R2HJ1OEW02nswS9XZLgEQ7vrTiBTX8ZSNWL3H
+zTzRAoIBAQC+4lRSsNf+mMYGmJHt7C46thXKFfK7vAccbnoamX5TZcaXxSaYfWjX
+Maump1qaObvel1RBzXfDC+MwqSufFVoQWETkNclZa5lJ34XCWCVYyYqN8dAsboLf
+NeHUv1pQn0nYpk9evd4qdVZoZZs/2DU4xVC7npv70q3MtBuYWVjlhC9nXihUfbUn
+5pL+Z2qdwuI88Cryju0aWQdukHF5DHnTJYH1YhCVeBrOGxFleI9+NQ5GzDzM09n7
+2sUaB+BwVWxXtdQH0DzddzDMPMujGhNjPnfWEBe3v4xmqwNHo4MrHw9GLTT4Gm5n
+blfeGXB9HbKj2/tdUT6DnyixuyDmv4DU
+-----END PRIVATE KEY-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/wildcard-certificate.crt
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/wildcard-certificate.crt
---
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/wildcard-certificate.crt
2026-02-27 16:43:53.000000000 +0100
+++
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/wildcard-certificate.crt
1970-01-01 01:00:00.000000000 +0100
@@ -1,61 +0,0 @@
-#Certificate:
-# Data:
-# Version: 1 (0x0)
-# Serial Number: 13493453254446411258 (0xbb42603e589dedfa)
-# Signature Algorithm: sha1WithRSAEncryption
-# Issuer: C=US, ST=CA, L=State1, O=Openstack Test Org, OU=Openstack
Test Unit, CN=*.pong.example.com/[email protected]
-# Validity
-# Not Before: Aug 21 17:29:18 2013 GMT
-# Not After : Jul 28 17:29:18 2113 GMT
-# Subject: C=US, ST=CA, L=State1, O=Openstack Test Org, OU=Openstack
Test Unit, CN=*.pong.example.com/[email protected]
-# Subject Public Key Info:
-# Public Key Algorithm: rsaEncryption
-# Public-Key: (4096 bit)
-# Modulus:
-# 00:d4:bb:3a:c4:a0:06:54:31:23:5d:b0:78:5a:be:
-# 45:44:ae:a1:89:86:11:d8:ca:a8:33:b0:4f:f3:e1:
-# 46:1e:85:a3:2a:9c:a4:e0:c2:14:34:4f:91:df:dc:
-# .
-# .
-# .
-# Exponent: 65537 (0x10001)
-# Signature Algorithm: sha1WithRSAEncryption
-# 9f:cc:08:5d:19:ee:54:31:a3:57:d7:3c:89:89:c0:69:41:dd:
-# 46:f8:73:68:ec:46:b9:fa:f5:df:f6:d9:58:35:d8:53:94:88:
-# bd:36:a6:23:9e:0c:0d:89:62:35:91:49:b6:14:f4:43:69:3c:
-# .
-# .
-# .
------BEGIN CERTIFICATE-----
-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
------END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/wildcard-san-certificate.crt
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/wildcard-san-certificate.crt
---
old/python_glanceclient-4.11.0/glanceclient/tests/unit/var/wildcard-san-certificate.crt
2026-02-27 16:43:53.000000000 +0100
+++
new/python_glanceclient-4.12.0/glanceclient/tests/unit/var/wildcard-san-certificate.crt
1970-01-01 01:00:00.000000000 +0100
@@ -1,54 +0,0 @@
-#Certificate:
-# Data:
-# Version: 3 (0x2)
-# Serial Number: 11990626514780340979 (0xa66743493fdcc2f3)
-# Signature Algorithm: sha1WithRSAEncryption
-# Issuer: C=US, ST=CA, L=State1, O=Openstack Test Org, OU=Openstack
Test Unit, CN=0.0.0.0
-# Validity
-# Not Before: Dec 10 15:31:22 2013 GMT
-# Not After : Nov 16 15:31:22 2113 GMT
-# Subject: C=US, ST=CA, L=State1, O=Openstack Test Org, OU=Openstack
Test Unit, CN=0.0.0.0
-# Subject Public Key Info:
-# Public Key Algorithm: rsaEncryption
-# Public-Key: (2048 bit)
-# Modulus:
-# 00:ca:6b:07:73:53:24:45:74:05:a5:2a:27:bd:3e:
-# .
-# .
-# .
-# Exponent: 65537 (0x10001)
-# X509v3 extensions:
-# X509v3 Key Usage:
-# Key Encipherment, Data Encipherment
-# X509v3 Extended Key Usage:
-# TLS Web Server Authentication
-# X509v3 Subject Alternative Name:
-# DNS:foo.example.net, DNS:*.example.com
-# Signature Algorithm: sha1WithRSAEncryption
-# 7e:41:69:da:f4:3c:06:d6:83:c6:f2:db:df:37:f1:ac:fa:f5:
-# .
-# .
-# .
------BEGIN CERTIFICATE-----
-MIIDxDCCAqygAwIBAgIJAKZnQ0k/3MLzMA0GCSqGSIb3DQEBBQUAMHgxCzAJBgNV
-BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEBxMGU3RhdGUxMRswGQYDVQQKExJP
-cGVuc3RhY2sgVGVzdCBPcmcxHDAaBgNVBAsTE09wZW5zdGFjayBUZXN0IFVuaXQx
-EDAOBgNVBAMTBzAuMC4wLjAwIBcNMTMxMjEwMTUzMTIyWhgPMjExMzExMTYxNTMx
-MjJaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEBxMGU3RhdGUx
-MRswGQYDVQQKExJPcGVuc3RhY2sgVGVzdCBPcmcxHDAaBgNVBAsTE09wZW5zdGFj
-ayBUZXN0IFVuaXQxEDAOBgNVBAMTBzAuMC4wLjAwggEiMA0GCSqGSIb3DQEBAQUA
-A4IBDwAwggEKAoIBAQDKawdzUyRFdAWlKie9Pn10j7frffN+z1gEMluK2CtDEwv9
-kbD4uS/Kz4dujfTx03mdyNfiMVlOM+YJm/qeLLSdJyFyvZ9Y3WmJ+vT2RGlMMhLd
-/wEnMRrTYLL39pwI6z+gyw+4D78Pyv/OXy02IA6WtVEefYSx1vmVngb3pL+iBzhO
-8CZXNI6lqrFhh+Hr4iMkYMtY1vTnwezAL6p64E/ZAFNPYCEJlacESTLQ4VZYniHc
-QTgnE1czlI1vxlIk1KDXAzUGeeopZecRih9qlTxtOpklqEciQEE+sHtPcvyvdRE9
-Bdyx5rNSALLIcXs0ViJE1RPlw3fjdBoDIOygqvX1AgMBAAGjTzBNMAsGA1UdDwQE
-AwIEMDATBgNVHSUEDDAKBggrBgEFBQcDATApBgNVHREEIjAggg9mb28uZXhhbXBs
-ZS5uZXSCDSouZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEBAH5Badr0PAbW
-g8by29838az69Raul5IkpZQ5V3O1NaNNWxvmF1q8zFFqqGK5ktXJAwGiwnYEBb30
-Zfrr+eFIEERzBthSJkWlP8NG+2ooMyg50femp+asAvW+KYYefJW8KaXTsznMsAFy
-z1agcWVYVZ4H9PwunEYn/rM1krLEe4Cagsw5nmf8VqZg+hHtw930q8cRzgDsZdfA
-jVK6dWdmzmLCUTL1GKCeNriDw1jIeFvNufC+Q3orH7xBx4VL+NV5ORWdNY/B8q1b
-mFHdzbuZX6v39+2ww6aZqG2orfxUocc/5Ox6fXqenKPI3moeHS6Ktesq7sEQSJ6H
-QZFsTuT/124=
------END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_glanceclient-4.11.0/glanceclient/v2/images.py
new/python_glanceclient-4.12.0/glanceclient/v2/images.py
--- old/python_glanceclient-4.11.0/glanceclient/v2/images.py 2026-02-27
16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/v2/images.py 2026-05-19
11:25:56.000000000 +0200
@@ -216,7 +216,8 @@
'This operation is not supported by Glance.')
@utils.add_req_id_to_object()
- def data(self, image_id, do_checksum=True, allow_md5_fallback=False):
+ def data(self, image_id, do_checksum=True, allow_md5_fallback=False,
+ prefer=None):
"""Retrieve data of an image.
When do_checksum is enabled, validation proceeds as follows:
@@ -240,6 +241,8 @@
:param allow_md5_fallback:
Use the MD5 checksum for validation if the algorithm specified by
the image's 'os_hash_algo' property is not available
+ :param prefer: List of store identifiers suggesting the ordering of
+ stores to try when downloading
:returns: An iterable body or ``None``
"""
if do_checksum:
@@ -252,6 +255,13 @@
meta_hash_algo = image_meta.get('os_hash_algo', None)
url = '/v2/images/%s/file' % image_id
+ params = {}
+ if prefer:
+ params['prefer'] = ','.join(prefer)
+
+ if params:
+ url = '%s?%s' % (url, urllib.parse.urlencode(params))
+
resp, body = self.http_client.get(url)
if resp.status_code == codes.no_content:
return None, resp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python_glanceclient-4.11.0/glanceclient/v2/shell.py
new/python_glanceclient-4.12.0/glanceclient/v2/shell.py
--- old/python_glanceclient-4.11.0/glanceclient/v2/shell.py 2026-02-27
16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/glanceclient/v2/shell.py 2026-05-19
11:25:56.000000000 +0200
@@ -678,6 +678,11 @@
@utils.arg('id', metavar='<IMAGE_ID>', help=_('ID of image to download.'))
@utils.arg('--progress', action='store_true', default=False,
help=_('Show download progress bar.'))
[email protected]('--prefer', metavar='<STORES>',
+ help=_('Comma-separated list of store identifiers suggesting the '
+ 'ordering of stores to try when downloading the image. '
+ 'Store identifiers are site-specific and can be discovered '
+ 'using the "stores-info" command.'))
def do_image_download(gc, args):
"""Download a specific image."""
if sys.stdout.isatty() and (args.file is None):
@@ -686,9 +691,14 @@
'downloaded image or redirect output to another source.')
utils.exit(msg)
+ prefer = None
+ if args.prefer:
+ prefer = [s for s in (x.strip() for x in args.prefer.split(',')) if s]
+
try:
body = gc.images.data(args.id,
- allow_md5_fallback=args.allow_md5_fallback)
+ allow_md5_fallback=args.allow_md5_fallback,
+ prefer=prefer)
except (exc.HTTPForbidden, exc.HTTPException) as e:
msg = "Unable to download image '%s'. (%s)" % (args.id, e)
utils.exit(msg)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/python_glanceclient.egg-info/PKG-INFO
new/python_glanceclient-4.12.0/python_glanceclient.egg-info/PKG-INFO
--- old/python_glanceclient-4.11.0/python_glanceclient.egg-info/PKG-INFO
2026-02-27 16:44:21.000000000 +0100
+++ new/python_glanceclient-4.12.0/python_glanceclient.egg-info/PKG-INFO
2026-05-19 11:26:32.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: python-glanceclient
-Version: 4.11.0
+Version: 4.12.0
Summary: OpenStack Image API Client Library
Home-page: https://docs.openstack.org/python-glanceclient/latest/
Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/python_glanceclient.egg-info/SOURCES.txt
new/python_glanceclient-4.12.0/python_glanceclient.egg-info/SOURCES.txt
--- old/python_glanceclient-4.11.0/python_glanceclient.egg-info/SOURCES.txt
2026-02-27 16:44:21.000000000 +0100
+++ new/python_glanceclient-4.12.0/python_glanceclient.egg-info/SOURCES.txt
2026-05-19 11:26:32.000000000 +0200
@@ -31,7 +31,6 @@
glanceclient/common/__init__.py
glanceclient/common/exceptions.py
glanceclient/common/http.py
-glanceclient/common/https.py
glanceclient/common/progressbar.py
glanceclient/common/utils.py
glanceclient/tests/__init__.py
@@ -81,8 +80,6 @@
glanceclient/tests/unit/var/certificate.crt
glanceclient/tests/unit/var/expired-cert.crt
glanceclient/tests/unit/var/privatekey.key
-glanceclient/tests/unit/var/wildcard-certificate.crt
-glanceclient/tests/unit/var/wildcard-san-certificate.crt
glanceclient/v1/__init__.py
glanceclient/v1/client.py
glanceclient/v1/image_members.py
@@ -132,6 +129,7 @@
releasenotes/notes/check-for-md5-59db8fd67870b214.yaml
releasenotes/notes/copy-existing-image-619b7e6bc3394446.yaml
releasenotes/notes/del_from_store-2d807c3038283907.yaml
+releasenotes/notes/download-from-suggested-stores.yaml
releasenotes/notes/drop-py-2-7-f10417b8d1dd38fb.yaml
releasenotes/notes/drop-python-3-6-and-3-7-0b299b4dc9673c6e.yaml
releasenotes/notes/fix-undesirable-raw-python-error-66e3ddaca7b72ae2.yaml
@@ -160,6 +158,7 @@
releasenotes/source/2024.2.rst
releasenotes/source/2025.1.rst
releasenotes/source/2025.2.rst
+releasenotes/source/2026.1.rst
releasenotes/source/conf.py
releasenotes/source/earlier.rst
releasenotes/source/index.rst
@@ -181,5 +180,6 @@
releasenotes/source/_static/.placeholder
releasenotes/source/_templates/.placeholder
tools/fix_ca_bundle.sh
+tools/generate_test_certs.sh
tools/glance.bash_completion
tools/with_venv.sh
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/python_glanceclient.egg-info/pbr.json
new/python_glanceclient-4.12.0/python_glanceclient.egg-info/pbr.json
--- old/python_glanceclient-4.11.0/python_glanceclient.egg-info/pbr.json
2026-02-27 16:44:21.000000000 +0100
+++ new/python_glanceclient-4.12.0/python_glanceclient.egg-info/pbr.json
2026-05-19 11:26:32.000000000 +0200
@@ -1 +1 @@
-{"git_version": "b9e5198", "is_release": true}
\ No newline at end of file
+{"git_version": "0b06bb4", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/releasenotes/notes/download-from-suggested-stores.yaml
new/python_glanceclient-4.12.0/releasenotes/notes/download-from-suggested-stores.yaml
---
old/python_glanceclient-4.11.0/releasenotes/notes/download-from-suggested-stores.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/python_glanceclient-4.12.0/releasenotes/notes/download-from-suggested-stores.yaml
2026-05-19 11:25:56.000000000 +0200
@@ -0,0 +1,19 @@
+---
+features:
+ - |
+ The ``image-download`` command now supports the ``--prefer`` parameter
+ to suggest which stores to try when downloading images. The prefer
+ parameter accepts a comma-separated list of store identifiers.
+
+ If the image is not found in any of the specified stores, Glance will
+ fall back to trying all available stores.
+
+ Example usage:
+
+ .. code-block:: bash
+
+ glance image-download <image-id> --prefer store1,store2 --file
image.qcow2
+
+ Store identifiers are site-specific and can be discovered using the
+ ``stores-info`` command.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/releasenotes/source/2026.1.rst
new/python_glanceclient-4.12.0/releasenotes/source/2026.1.rst
--- old/python_glanceclient-4.11.0/releasenotes/source/2026.1.rst
1970-01-01 01:00:00.000000000 +0100
+++ new/python_glanceclient-4.12.0/releasenotes/source/2026.1.rst
2026-05-19 11:25:56.000000000 +0200
@@ -0,0 +1,6 @@
+===========================
+2026.1 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/2026.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/releasenotes/source/index.rst
new/python_glanceclient-4.12.0/releasenotes/source/index.rst
--- old/python_glanceclient-4.11.0/releasenotes/source/index.rst
2026-02-27 16:43:53.000000000 +0100
+++ new/python_glanceclient-4.12.0/releasenotes/source/index.rst
2026-05-19 11:25:56.000000000 +0200
@@ -6,6 +6,7 @@
:maxdepth: 1
unreleased
+ 2026.1
2025.2
2025.1
2024.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python_glanceclient-4.11.0/tools/generate_test_certs.sh
new/python_glanceclient-4.12.0/tools/generate_test_certs.sh
--- old/python_glanceclient-4.11.0/tools/generate_test_certs.sh 1970-01-01
01:00:00.000000000 +0100
+++ new/python_glanceclient-4.12.0/tools/generate_test_certs.sh 2026-05-19
11:25:56.000000000 +0200
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# The script to generate the key file sand certificates files used in unit
+# tests. These files are saved in glanceclient/tests/unit/var .
+#
+pushd $(dirname -- "$0")/../glanceclient/tests/unit/var
+
+# Remove existing files
+rm *.key *.csr *.crt *.srl
+
+openssl genrsa -out ca.key 4096
+
+openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt \
+ -subj "/C=AU/ST=State CA/L=CA/O=OpenStack CA Org/OU=OpenStack Test
CA/CN=Openstack Test Certificate Authority/[email protected]/" \
+ -addext "keyUsage=critical,digitalSignature,keyCertSign"
+
+openssl genrsa -out privatekey.key 4096
+
+openssl req -new -key privatekey.key -out server.csr \
+ -subj "/C=AU/ST=State CA/L=State1/O=OpenStack Test Org/OU=OpenStack Test
Unit/CN=test.example.com/" \
+ -addext "subjectAltName=IP:127.0.0.1"
+openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
+ -out certificate.crt -days 3650 -sha256 -copy_extensions copyall
+
+openssl req -new -key privatekey.key -out expired-cert.csr \
+ -subj "/C=AU/ST=State CA/L=State1/O=OpenStack Test Org/OU=OpenStack Test
Unit/CN=test.example.com/" \
+ -addext "subjectAltName=IP:127.0.0.1"
+openssl x509 -req -in expired-cert.csr -CA ca.crt -CAkey ca.key
-CAcreateserial \
+ -out expired-cert.crt -days 0 -sha256 -copy_extensions copyall
+
+touch badcert.crt
+
+for f in badcert.crt ca.crt certificate.crt expired-cert.crt privatekey.key; do
+ if [ -f $f ]; then
+ sed -i '1i # DO NOT EDIT. This file is generated by
tools/generate_test_certs.sh' $f
+ fi
+done
+
+# Remove unused files
+rm *.csr
+rm ca.key
+rm ca.srl
+
+popd