diff --git a/nova/conf/glance.py b/nova/conf/glance.py index 46f1ed9b4e..8ecf76d5bf 100644 --- a/nova/conf/glance.py +++ b/nova/conf/glance.py @@ -187,7 +187,15 @@ Related options: is set to ``True``. """), + cfg.BoolOpt('direct_download', + default=False, + help=""" +Try to download image through the /v2/images/{image_id}/direct-download API + route. +Image download will fallback to /v2/images/{image_id}/file route + if direct download is either not implemented or fails +"""), cfg.BoolOpt('debug', default=False, help='Enable or disable debug logging with glanceclient.') diff --git a/nova/image/glance.py b/nova/image/glance.py index e7a117d244..c8ea9dd4fe 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -372,7 +372,12 @@ class GlanceImageServiceV2(object): # to fetch the image and fill image_chunks try: image_chunks = self._client.call( - context, 2, 'data', args=(image_id,)) + context, + 2, + 'data', + args=(image_id,), + kwargs={'direct_download': CONF.glance.direct_download}, + ) except Exception: _reraise_translated_image_exception(image_id) diff --git a/nova/tests/unit/image/test_glance.py b/nova/tests/unit/image/test_glance.py index a155bbe1cc..2160dddc8a 100644 --- a/nova/tests/unit/image/test_glance.py +++ b/nova/tests/unit/image/test_glance.py @@ -570,7 +570,12 @@ class TestDownloadNoDirectUri(test.NoDBTestCase): self.assertFalse(show_mock.called) self.assertFalse(open_mock.called) client.call.assert_called_once_with( - ctx, 2, 'data', args=(mock.sentinel.image_id,)) + ctx, + 2, + 'data', + args=(mock.sentinel.image_id,), + kwargs={'direct_download': CONF.glance.direct_download}, + ) self.assertEqual(mock.sentinel.image_chunks, res) @mock.patch('builtins.open') @@ -605,7 +610,12 @@ class TestDownloadNoDirectUri(test.NoDBTestCase): self.assertFalse(show_mock.called) self.assertFalse(open_mock.called) client.call.assert_called_once_with( - ctx, 2, 'data', args=(mock.sentinel.image_id,)) + ctx, + 2, + 'data', + args=(mock.sentinel.image_id,), + kwargs={'direct_download': CONF.glance.direct_download}, + ) self.assertIsNone(res) data.write.assert_has_calls( [ @@ -632,7 +642,12 @@ class TestDownloadNoDirectUri(test.NoDBTestCase): self.assertFalse(show_mock.called) client.call.assert_called_once_with( - ctx, 2, 'data', args=(mock.sentinel.image_id,)) + ctx, + 2, + 'data', + args=(mock.sentinel.image_id,), + kwargs={'direct_download': CONF.glance.direct_download}, + ) open_mock.assert_called_once_with(mock.sentinel.dst_path, 'wb') fsync_mock.assert_called_once_with(writer) self.assertIsNone(res) @@ -663,7 +678,12 @@ class TestDownloadNoDirectUri(test.NoDBTestCase): self.assertFalse(show_mock.called) self.assertFalse(open_mock.called) client.call.assert_called_once_with( - ctx, 2, 'data', args=(mock.sentinel.image_id,)) + ctx, + 2, + 'data', + args=(mock.sentinel.image_id,), + kwargs={'direct_download': CONF.glance.direct_download}, + ) self.assertIsNone(res) data.write.assert_has_calls( [ @@ -828,7 +848,12 @@ class TestDownloadNoDirectUri(test.NoDBTestCase): mock.sentinel.dst_path, mock.sentinel.loc_meta) client.call.assert_called_once_with( - ctx, 2, 'data', args=(mock.sentinel.image_id,)) + ctx, + 2, + 'data', + args=(mock.sentinel.image_id,), + kwargs={'direct_download': CONF.glance.direct_download}, + ) fsync_mock.assert_called_once_with(writer) # NOTE(jaypipes): log messages call open() in part of the # download path, so here, we just check that the last open() @@ -878,7 +903,12 @@ class TestDownloadNoDirectUri(test.NoDBTestCase): include_locations=True) get_tran_mock.assert_called_once_with('funky') client.call.assert_called_once_with( - ctx, 2, 'data', args=(mock.sentinel.image_id,)) + ctx, + 2, + 'data', + args=(mock.sentinel.image_id,), + kwargs={'direct_download': CONF.glance.direct_download}, + ) fsync_mock.assert_called_once_with(writer) # NOTE(jaypipes): log messages call open() in part of the # download path, so here, we just check that the last open() diff --git a/requirements.txt b/requirements.txt index 0b802bf533..c944f0196e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,7 +23,7 @@ jsonschema>=4.0.0 # MIT python-cinderclient>=4.0.1 # Apache-2.0 keystoneauth1>=3.16.0 # Apache-2.0 python-neutronclient>=7.1.0 # Apache-2.0 -python-glanceclient>=4.7.0 # Apache-2.0 +python-glanceclient @ git+https://git.ruan.fr/womax/python-glanceclient.git@gazpacho_temp_url requests>=2.25.1 # Apache-2.0 stevedore>=1.20.0 # Apache-2.0 websockify>=0.9.0 # LGPLv3 diff --git a/upper-constraints.txt b/upper-constraints.txt new file mode 100644 index 0000000000..9fc1cef202 --- /dev/null +++ b/upper-constraints.txt @@ -0,0 +1,560 @@ +# WARNING: OpenStack makes no security guarantees about third-party +# dependencies listed here, and does not keep track of any +# vulnerabilities they contain. Versions of these dependencies are +# frozen at each coordinated release in order to stabilize upstream +# testing, and can contain known vulnerabilities. Consumers are +# *STRONGLY* encouraged to rely on curated distributions of OpenStack +# or manage security patching of dependencies themselves. +voluptuous===0.16.0 +chardet===5.2.0 +enum-compat===0.0.3 +rsa===4.9.1 +netmiko===4.6.0 +sshtunnel===0.4.0 +PasteDeploy===3.1.0 +Routes===2.5.1 +rtslib-fb===2.2.3 +oslo.limit===2.10.0 +restructuredtext_lint===2.0.2 +tzdata===2025.3 +smmap===5.0.2 +confget===5.1.2 +XStatic-Angular-Bootstrap===2.5.0.1 +WebOb===1.8.9 +sphinxcontrib-actdiag===3.0.0 +pecan===1.7.0 +os-api-ref===3.1.0 +python-ldap===3.4.5 +oslo.concurrency===7.4.0 +websocket-client===1.9.0 +osprofiler===4.3.0 +os-resource-classes===1.1.0 +mypy_extensions===1.1.0 +tabulate===0.9.0 +python-ironic-inspector-client===5.4.0 +lxml===6.0.2 +vintage===0.4.1 +rst2txt===1.1.0 +setproctitle===1.3.7 +pytest===9.0.2 +python-slugify===8.0.4 +cursive===0.2.3 +oslo.service===4.5.1 +django-appconf===1.2.0 +ntc_templates===9.0.0 +sphinxcontrib-nwdiag===2.0.0 +rbd-iscsi-client===0.1.8 +alabaster===1.0.0 +pbr===7.0.3 +munch===4.0.0 +waiting===1.5.0 +attrs===25.4.0 +jwcrypto===1.5.6 +Pint===0.24.4 +oslo.i18n===6.7.2 +jsonpath-rw-ext===1.2.2 +python-mistralclient===6.2.0 +oslo.context===6.3.0 +rcssmin===1.2.2 +pycadf===4.0.1 +grpcio===1.78.1 +fixtures===4.3.1 +neutron-lib===3.24.0 +XStatic-FileSaver===1.3.2.1 +jaraco.functools===4.4.0 +oslo.metrics===0.15.1 +storage-interfaces===1.0.5 +pydantic===2.12.5 +persist-queue===1.1.0 +pystache===0.6.8 +XStatic-Font-Awesome===6.2.1.2 +nose===1.3.7 +waitress===3.0.2 +os-refresh-config===14.0.1 +pysnmp===7.1.22 +Mako===1.3.10 +sphinxcontrib-htmlhelp===2.1.0 +XStatic-jQuery===3.7.1.1 +ddt===1.7.2 +pyserial===3.5 +moto===5.1.21 +infi.dtypes.wwn===0.1.1 +pcre2===0.6.0 +python-freezerclient===6.2.0 +python-vitrageclient===5.4.0 +py-pure-client===1.83.1 +krest===1.3.8 +psycopg2===2.9.11 +networkx===3.4.2 +cheroot===11.1.2 +XStatic-Angular===1.8.2.3 +zuul-sphinx===0.7.0 +ply===3.11 +google-api-core===2.30.0 +requests-toolbelt===1.0.0 +simplejson===3.20.2 +python-swiftclient===4.10.0 +pyOpenSSL===24.2.1 +typing-inspection===0.4.2 +monasca-common===3.8.0 +hyperframe===6.1.0 +zeroconf===0.148.0 +scipy===1.15.3 +opentelemetry-exporter-otlp===1.39.1 +rsd-lib===1.2.0 +XStatic-Jasmine===2.4.1.3 +googleapis-common-protos===1.72.0 +prometheus_client===0.24.1 +jaraco.classes===3.4.0 +debtcollector===3.0.0 +responses===0.26.0 +backports.strenum===1.3.1;python_version=='3.10' +croniter===6.0.0 +horizon===25.7.0 +octavia-lib===3.11.0 +python-watcherclient===4.10.0 +MarkupSafe===3.0.3 +doc8===2.0.0 +pymongo===4.16.0 +python-cloudkittyclient===6.1.0 +soupsieve===2.8.3 +sqlparse===0.5.5 +oslotest===6.0.0 +jsonpointer===3.0.0 +defusedxml===0.7.1 +opentelemetry-sdk===1.39.1 +netaddr===1.3.0 +pyghmi===1.6.13 +sphinxcontrib-blockdiag===3.0.0 +aiosqlite===0.22.1 +gnocchiclient===7.2.0 +wcwidth===0.6.0 +sphinxcontrib.datatemplates===0.11.0 +jsonpath-rw===1.4.0 +prettytable===3.17.0 +vine===5.1.0 +pathspec===1.0.4 +taskflow===6.2.0 +arrow===1.4.0 +semantic-version===2.10.0 +ConfigArgParse===1.7.1 +async-timeout===5.0.1 +virtualbmc===3.3.0 +SQLAlchemy===2.0.46 +pyroute2===0.8.1 +google-auth===2.48.0 +kazoo===2.10.0 +pyspnego===0.12.0 +XStatic-roboto-fontface===0.8.0.1 +pyudev===0.24.4 +eventlet===0.40.4 +openstack-doc-tools===4.0.1 +oslo.messaging===17.3.0 +jira===3.10.5 +PyJWT===2.11.0 +typing_extensions===4.15.0 +zVMCloudConnector===1.6.3 +paramiko===4.0.0 +ifaddr===0.2.0 +reno===4.1.0 +ncclient===0.7.0 +imagesize===1.4.1 +pydot===4.0.1 +urllib3===2.6.3 +graphviz===0.21 +PyKMIP===0.10.0 +python-observabilityclient===1.3.0 +whereto===0.5.0 +networking-generic-switch===9.1.0 +pywbem===1.7.3 +python-subunit===1.4.5 +pycparser===3.0 +mock===5.2.0 +PyYAML===6.0.3 +beautifulsoup4===4.14.3 +ovs===3.7.0 +cryptography===43.0.3 +httpcore===1.0.9 +URLObject===3.0.0 +psycopg2-binary===2.9.11 +glance_store===5.4.0 +openstack-release-test===8.3.0 +requests-mock===1.12.1 +os-apply-config===14.0.1 +gunicorn===25.1.0 +storpool===7.3.0 +textfsm===2.1.0 +python-3parclient===4.2.14 +libvirt-python===12.0.0 +python-zunclient===5.4.0 +tzlocal===5.3.1 +sysv_ipc===1.2.0 +sphinxcontrib-jsmath===1.0.1 +django_compressor===4.6.0 +awscurl===0.36 +python-novaclient===18.12.0 +pact===1.12.0 +bcrypt===5.0.0 +exceptiongroup===1.3.1 +os-client-config===2.3.0 +XStatic-Angular-Gettext===2.4.1.1 +h11===0.16.0 +Pygments===2.19.2 +XStatic-Hogan===2.0.0.5 +XStatic-objectpath===1.2.1.1 +python-manilaclient===6.0.0 +sphinxcontrib-serializinghtml===2.0.0 +requests===2.32.5 +snowballstemmer===3.0.1 +Jinja2===3.1.6 +XStatic-Bootstrap-SCSS===3.4.1.1 +pyzabbix===1.3.1 +ptyprocess===0.7.0 +amqp===5.3.1 +ruamel.yaml===0.19.1 +websockify===0.13.0 +gssapi===1.11.1 +XStatic-JQuery.quicksearch===2.0.3.3 +pyasn1_modules===0.4.1 +mpmath===1.3.0 +python-binary-memcached===0.31.4 +jaraco.context===6.1.0 +django-debreach===2.1.0 +sphinx-feature-classification===2.0.0 +XStatic-JQuery-Migrate===3.3.2.2 +pytest-html===4.2.0 +appdirs===1.4.4 +google-auth-httplib2===0.3.0 +daiquiri===3.4.0 +influxdb===5.3.2 +funcparserlib===2.0.0a0 +passlib===1.7.4 +cliff===4.13.2 +os-brick===7.0.0 +valkey===6.1.1 +scp===0.15.0 +lark===1.3.1 +python-zaqarclient===4.4.0 +ldappool===3.0.0 +hpack===4.1.0 +joblib===1.5.3 +google-api-python-client===2.190.0 +castellan===5.6.0 +oslo.versionedobjects===3.9.0 +enmerkar===0.7.1 +webcolors===25.10.0 +aodhclient===3.10.1 +autobahn===24.4.2 +SQLAlchemy-Utils===0.42.1 +retryz===0.1.9 +pluggy===1.6.0 +coverage===7.13.4 +freezegun===1.5.5 +mdurl===0.1.2 +toml===0.10.2 +pycdlib===1.14.0 +pyperclip===1.11.0 +cassandra-driver===3.29.3 +XStatic-Angular-Schema-Form===0.8.13.1 +opentelemetry-exporter-otlp-proto-http===1.39.1 +gabbi===4.2.0 +nwdiag===3.0.0 +XStatic-bootswatch===3.3.7.1 +annotated-types===0.7.0 +pytest-xdist===3.8.0 +XStatic-JS-Yaml===3.13.1.2 +XStatic-term.js===0.0.7.1 +oslo.log===8.1.0 +nodeenv===1.10.0 +gossip===2.5.0 +suds-community===1.2.0 +os_vif===4.3.0 +qrcode===8.2 +oslo.middleware===8.0.0 +XStatic-mdi===1.6.50.3 +pydantic_core===2.41.5 +uritemplate===4.2.0 +docutils===0.21.2 +threadpoolctl===3.6.0 +os-ken===4.1.1 +ujson===5.11.0 +selenium===4.41.0 +pytest-subtests===0.15.0 +mistral-lib===3.5.1 +dogtag-pki===11.2.1 +XStatic-Angular-UUID===0.0.4.1 +sphinxcontrib-seqdiag===3.0.0 +os-win===5.9.0 +capacity===1.3.14 +markdown-it-py===4.0.0 +retrying===1.4.2 +platformdirs===4.9.2 +pydotplus===2.0.2 +boto3===1.35.99 +jeepney===0.9.0 +stestr===4.2.1 +pillow===12.1.1 +infoblox-client===0.6.2 +pysmi-lextudio===1.4.3 +oslo.serialization===5.9.1 +warlock===2.1.0 +exabgp===5.0.1 +aiomysql===0.3.2 +sphinxcontrib-httpdomain===2.0.0 +metalsmith===2.5.0 +s3transfer===0.10.4 +text-unidecode===1.3 +sphinxcontrib-svg2pdfconverter===2.0.0 +oslo.vmware===4.9.0 +autopage===0.6.0 +gitdb===4.0.12 +python-monascaclient===2.8.0 +opentelemetry-api===1.39.1 +automaton===3.3.0 +os-service-types===1.8.2 +keyring===25.7.0 +elementpath===4.8.0 +wsgi_intercept===1.13.1 +jsonschema-specifications===2025.9.1 +testscenarios===0.5.0 +sphinxcontrib-pecanwsme===0.11.0 +sadisplay===0.4.9 +infinisdk===289.1.0 +rich-argparse===1.7.2 +packaging===26.0 +opentelemetry-exporter-otlp-proto-grpc===1.39.1 +psutil===7.2.2 +txaio===25.9.2 +elasticsearch===9.3.0 +django-nose===1.4.7 +asgiref===3.11.1 +XStatic-JQuery.TableSorter===2.14.5.3 +pifpaf===3.4.0 +blockdiag===3.0.0 +testtools===2.8.5 +infi.dtypes.iqn===0.4.0 +jsonpath-ng===1.7.0 +XStatic-tv4===1.2.7.1 +XStatic-JSEncrypt===2.3.1.2 +python-cinderclient===9.9.0 +keystonemiddleware===12.0.0 +django-formtools===2.5.1 +XStatic-Spin===1.2.5.3 +rich===14.3.3 +os-traits===3.6.0 +typepy===1.3.4 +SecretStorage===3.5.0 +XStatic-Rickshaw===1.5.1.3 +iso8601===2.1.0 +tooz===8.1.0 +idna===3.11 +yamlloader===1.6.0 +protobuf===6.33.5 +sushy===5.10.0 +python-neutronclient===11.8.0 +pika===1.3.2 +oslo.cache===4.1.1 +WebTest===3.0.7 +os-collect-config===14.0.1 +edgegrid-python===2.0.5 +python-octaviaclient===3.13.0 +pysaml2===7.5.4 +requests-oauthlib===2.0.0 +oslo.reports===3.7.0 +pysnmp-lextudio===6.1.2 +bitmath===1.3.3.1 +ceilometermiddleware===3.10.0 +testrepository===0.0.22 +librt===0.8.1 +sympy===1.14.0 +Logbook===1.9.2 +PyNaCl===1.6.2 +osc-lib===4.4.0 +python-consul===1.1.0 +more-itertools===10.8.0 +seqdiag===3.0.0 +numpy===2.2.6 +msgpack===1.1.2 +Sphinx===8.1.3 +oslo.config===10.3.0 +openstackdocstheme===3.5.0 +osc-placement===4.8.0 +rpds-py===0.30.0 +zake===0.2.2 +flux===1.4.0 +pysnmpcrypto===0.0.4 +flexparser===0.4 +krb5===0.9.0 +PyMySQL===1.1.2 +uhashring===2.4 +kubernetes===35.0.0 +httplib2===0.31.2 +betamax===0.9.0 +construct===2.10.70 +pytest-metadata===3.1.1 +pyparsing===3.3.2 +geomet===1.1.0 +opentelemetry-exporter-otlp-proto-common===1.39.1 +distlib===0.4.0 +dogpile.cache===1.5.0 +python-barbicanclient===7.3.0 +salt===3007.13 +opentelemetry-semantic-conventions===0.60b1 +api-object-schema===2.0.0 +blinker===1.9.0 +WSME===0.12.1 +tomli===2.4.0 +oslo.upgradecheck===2.7.1 +sherlock===0.4.1 +stevedore===5.7.0 +botocore===1.35.99 +xmltodict===1.0.3 +pyasn1===0.6.0 +oslo.rootwrap===7.9.0 +Django===4.2.28 +pexpect===4.9.0 +cmd2===3.2.0 +python-json-logger===4.0.0 +redis===7.2.0 +jmespath===1.1.0 +click===8.3.1 +XStatic-smart-table===1.4.13.3 +kuryr-lib===3.4.1 +jsonpatch===1.33 +libsass===0.23.0 +os-testr===3.0.0 +cotyledon===2.2.0 +xattr===1.3.0 +systemd-python===235 +python-memcached===1.62 +openstacksdk===4.10.0 +infi.dtypes.nqn===0.1.0 +six===1.17.0 +h2===4.3.0 +dulwich===0.24.1 +dfs-sdk===1.2.27 +sentinels===1.1.1 +kombu===5.6.2 +distro===1.9.0 +zstd===1.5.7.3 +yaql===3.2.0 +durationpy===0.10 +requestsexceptions===1.4.0 +testresources===2.0.2 +falcon===4.2.0 +tomlkit===0.14.0 +etcd3gw===2.5.0 +Flask-RESTful===0.3.10 +GitPython===3.1.46 +python-ironicclient===6.0.0 +babel===2.18.0 +XStatic===1.0.3 +XStatic-Angular-FileUpload===12.2.13.2 +python-openstackclient===9.0.0 +pyzmq===27.1.0 +oslo.db===18.0.0 +simplegeneric===0.8.1 +yappi===1.7.3 +mbstrdecoder===1.1.4 +pymemcache===4.0.0 +wrapt===2.1.1 +oslo.privsep===3.10.1 +sphinxcontrib-apidoc===0.6.0 +oslo.policy===5.0.0 +hvac===2.4.0 +pyeclib===1.7.0 +repoze.lru===0.7 +rfc3986===2.0.0 +tenacity===9.1.4 +invoke===2.2.1 +python-designateclient===6.4.0 +pytest-cov===4.1.0 +reactivex===4.1.0 +Paste===3.10.1 +pytest-django===4.12.0 +XStatic-Json2yaml===0.1.1.1 +boto===2.49.0 +hyperlink===21.0.0 +mitba===1.1.1 +python-masakariclient===8.8.0 +Werkzeug===3.1.6 +APScheduler===3.11.2 +xmlschema===2.5.1 +python-troveclient===8.10.0 +cachez===0.1.2 +XStatic-Bootstrap-Datepicker===1.4.0.1 +netifaces===0.11.0 +cachetools===7.0.1 +flexcache===0.3 +sphinxcontrib-qthelp===2.0.0 +keystoneauth1===5.13.1 +statsd===4.0.1 +proto-plus===1.27.1 +python-keystoneclient===5.8.0 +diskimage-builder===3.40.2 +heat-translator===3.4.0 +python-magnumclient===4.10.0 +docker===7.1.0 +storops===1.2.11 +anyio===4.12.1 +XStatic-Angular-lrdragndrop===1.0.2.7 +ovsdbapp===2.16.0 +aniso8601===10.0.1 +rjsmin===1.2.5 +icalendar===7.0.1 +configparser===7.2.0 +decorator===5.2.1 +DateTimeRange===2.3.2 +cffi===2.0.0 +python-cyborgclient===2.7.0 +futurist===3.2.1 +jsonschema===4.26.0 +sphinxcontrib-devhelp===2.0.0 +python-blazarclient===4.5.0 +alembic===1.18.4 +execnet===2.1.2 +sphinxcontrib-programoutput===0.19 +storpool.spopenstack===3.2.0 +dnspython===2.8.0 +oauthlib===3.3.1 +zipp===3.23.0 +greenlet===3.3.2 +XStatic-Angular-Vis===4.16.0.1 +iniconfig===2.3.0 +referencing===0.37.0 +confluent-kafka===2.13.0 +backports.tarfile===1.2.0 +xvfbwrapper===0.2.20 +influxdb-client===1.50.0 +tosca-parser===2.14.0 +python-consul2===0.1.5 +charset-normalizer===3.4.4 +Flask===3.1.3 +httpx===0.28.1 +sqlalchemy-filters===0.13.0 +sphinxcontrib-runcmd===0.2.0 +confspirator===0.3.0 +fasteners===0.20 +importlib_metadata===8.7.1 +sortedcontainers===2.4.0 +microversion_parse===2.1.0 +python-linstor===1.27.1 +filelock===3.24.3 +python-tackerclient===2.5.0 +python-heatclient===5.1.0 +oslo.utils===10.0.0 +requests-kerberos===0.15.0 +itsdangerous===2.2.0 +XStatic-jquery-ui===1.13.0.2 +monasca-statsd===2.7.0 +python-dateutil===2.9.0.post0 +virtualenv===20.39.0 +colorama===0.4.6 +confetti===2.5.3 +ironic-lib===7.0.0 +pytz===2025.2 +opentelemetry-proto===1.39.1 +XStatic-D3===3.5.17.1 +actdiag===3.0.0 +sphinxcontrib-applehelp===2.0.0 +scikit-learn===1.7.2