Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
aca9788
Pure: Report SAM-2 addressing mode for LUNs
Akrog Feb 21, 2023
b2f20ea
Add fips check jobs
vakwetu Jan 12, 2022
80dc87c
Increase size of volume image metadata values
drencrom Dec 23, 2022
597d320
Hitachi: Fix to use correct pool on secondary storage
atsushikawai Mar 17, 2023
b977f12
HPE XP and NEC V: Host group name is not correct
atsushikawai Apr 7, 2023
7a089fb
Hitachi: Fix exception when deleted volume is busy
atsushikawai Jun 20, 2023
3133cc7
Tests: Save 30s on hbsd FC tests
eharney Aug 30, 2023
0139e9f
Tests: Make NEC tests faster
eharney Oct 9, 2023
2d09548
Hitachi: Stop frequently REST API request in test
atsushikawai Apr 25, 2024
65c7496
Hitachi: Fix to set correct object ID for LDEV nickname
atsushikawai Jul 3, 2024
9a8e5fa
Hitachi: Prevent to delete a LDEV assigned to multi objects
atsushikawai Aug 8, 2024
e5dd20f
Ceph: Catch more failure conditions on volume backup
hrtkpf Jan 16, 2024
85fe94a
Fix broken backup_swift_service_auth=True
kajinamit Apr 16, 2024
47452f9
HPE 3par: getWsApiVersion now requires login
traghavendra Jun 8, 2024
a6a23c9
Merge "Hitachi: Fix to use correct pool on secondary storage" into st…
Sep 17, 2024
329d702
Merge "HPE XP and NEC V: Host group name is not correct" into stable/…
Sep 17, 2024
5f70358
Merge "Hitachi: Fix exception when deleted volume is busy" into stabl…
Sep 17, 2024
c4af21e
Merge "Tests: Save 30s on hbsd FC tests" into stable/2023.1
Sep 17, 2024
be025de
Merge "Tests: Make NEC tests faster" into stable/2023.1
Sep 17, 2024
5870eec
Merge "Hitachi: Stop frequently REST API request in test" into stable…
Sep 17, 2024
8a53812
Merge "Hitachi: Fix to set correct object ID for LDEV nickname" into …
Sep 17, 2024
8d3a8a8
Merge "Hitachi: Prevent to delete a LDEV assigned to multi objects" i…
Sep 17, 2024
86d3ffe
Add cinder-manage command to update service_uuid
rajathere Dec 28, 2021
9d88c88
Merge "HPE 3par: getWsApiVersion now requires login" into stable/2023.1
Sep 25, 2024
48d827b
Make default-types APIs compatible with V3.67
rajathere May 23, 2024
f56f9ed
RBD: Flattening of child volumes during deletion
eharney Apr 20, 2022
95728fe
Merge "Increase size of volume image metadata values" into stable/2023.1
Oct 24, 2024
e6b205b
Merge "Pure: Report SAM-2 addressing mode for LUNs" into stable/2023.1
Oct 24, 2024
01fbaee
Merge "Fix broken backup_swift_service_auth=True" into stable/2023.1
Oct 24, 2024
7e1b1e9
Merge "Add fips check jobs" into stable/2023.1
Oct 31, 2024
022be6c
Merge "Ceph: Catch more failure conditions on volume backup" into sta…
Oct 31, 2024
d74df7e
Update .gitreview for unmaintained/2023.1
openstackadmin Nov 15, 2024
ae2d250
Fix "signature_verified" metadata propagation to images
rodrigogansobarbieri Oct 23, 2024
a3c90fb
[stable-only] Fix online data migrations
andrewbonney Jul 8, 2024
a637c53
Pin flake8-import-order<0.19.0
rajathere Jun 23, 2025
3ad10ba
Merge "Update .gitreview for unmaintained/2023.1" into unmaintained/2…
Jul 24, 2025
1c00d64
Merge "[stable-only] Fix online data migrations" into unmaintained/20…
Aug 13, 2025
c64bd19
Stop testing old release of cinder
arnaudmorin Jul 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitreview
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
host=review.opendev.org
port=29418
project=openstack/cinder.git
defaultbranch=stable/2023.1
defaultbranch=unmaintained/2023.1
17 changes: 17 additions & 0 deletions .zuul.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
irrelevant-files: *gate-irrelevant-files
- cinder-tempest-plugin-lvm-lio-barbican:
irrelevant-files: *gate-irrelevant-files
- cinder-tempest-plugin-lvm-lio-barbican-fips:
voting: false
irrelevant-files: *gate-irrelevant-files
- cinder-grenade-mn-sub-volbak:
irrelevant-files: *gate-irrelevant-files
- cinder-tempest-lvm-multibackend:
Expand All @@ -68,6 +71,9 @@
irrelevant-files: *gate-irrelevant-files
- devstack-plugin-nfs-tempest-full:
irrelevant-files: *gate-irrelevant-files
- devstack-plugin-nfs-tempest-full-fips:
voting: false
irrelevant-files: *gate-irrelevant-files
- tempest-slow-py3:
irrelevant-files: *gate-irrelevant-files
- tempest-integrated-storage:
Expand Down Expand Up @@ -174,6 +180,17 @@
volume_revert: True
volume_image_dep_tests: False

- job:
# this depends on some ceph admin setup which is not yet complete
# TODO(alee) enable this test when ceph admin work is complete.
name: cinder-plugin-ceph-tempest-fips
parent: cinder-plugin-ceph-tempest
nodeset: devstack-single-node-centos-9-stream
pre-run: playbooks/enable-fips.yaml
vars:
configure_swap_size: 4096
nslookup_target: 'opendev.org'

- job:
name: cinder-plugin-ceph-tempest-mn-aa
parent: devstack-plugin-ceph-multinode-tempest-py3
Expand Down
1 change: 1 addition & 0 deletions bindep.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ postgresql
postgresql-client [platform:dpkg]
postgresql-devel [platform:rpm]
postgresql-server [platform:rpm]
python3-devel [platform:rpm test]
libpq-dev [platform:dpkg]
thin-provisioning-tools [platform:debian]
libxml2-dev [platform:dpkg test]
Expand Down
2 changes: 1 addition & 1 deletion cinder/api/schemas/volume_image_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
'os-set_image_metadata': {
'type': 'object',
'properties': {
'metadata': parameter_types.extra_specs,
'metadata': parameter_types.image_metadata,
},
'required': ['metadata'],
'additionalProperties': False,
Expand Down
44 changes: 25 additions & 19 deletions cinder/api/v3/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,22 +210,28 @@ def _setup_routes(self, mapper, ext_mgr):
member={'accept': 'POST'})

self.resources['default_types'] = default_types.create_resource()
mapper.connect("default-types", "/default-types/{id}",
controller=self.resources['default_types'],
action='create_update',
conditions={"method": ['PUT']})

mapper.connect("default-types", "/default-types",
controller=self.resources['default_types'],
action='index',
conditions={"method": ['GET']})

mapper.connect("default-types", "/default-types/{id}",
controller=self.resources['default_types'],
action='detail',
conditions={"method": ['GET']})

mapper.connect("default-types", "/default-types/{id}",
controller=self.resources['default_types'],
action='delete',
conditions={"method": ['DELETE']})
for path_prefix in ['/{project_id}', '']:
# project_id is optional
mapper.connect(
"default-types", "%s/default-types/{id}" % path_prefix,
controller=self.resources['default_types'],
action='create_update',
conditions={"method": ['PUT']})

mapper.connect(
"default-types", "%s/default-types" % path_prefix,
controller=self.resources['default_types'],
action='index',
conditions={"method": ['GET']})

mapper.connect(
"default-types", "%s/default-types/{id}" % path_prefix,
controller=self.resources['default_types'],
action='detail',
conditions={"method": ['GET']})

mapper.connect(
"default-types", "%s/default-types/{id}" % path_prefix,
controller=self.resources['default_types'],
action='delete',
conditions={"method": ['DELETE']})
9 changes: 9 additions & 0 deletions cinder/api/validation/parameter_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ def valid_char(char):
'additionalProperties': False
}

image_metadata = {
'type': 'object',
'patternProperties': {
'^[a-zA-Z0-9-_:. /]{1,255}$': {
'type': 'string', 'format': 'mysql_text'
}
},
'additionalProperties': False
}

extra_specs_with_no_spaces_key = {
'type': 'object',
Expand Down
8 changes: 8 additions & 0 deletions cinder/api/validation/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,14 @@ def _validate_key_size(param_value):
return True


@jsonschema.FormatChecker.cls_checks('mysql_text')
def _validate_mysql_text(param_value):
length = len(param_value.encode('utf8'))
if length > 65535:
return False
return True


class FormatChecker(jsonschema.FormatChecker):
"""A FormatChecker can output the message from cause exception

Expand Down
58 changes: 33 additions & 25 deletions cinder/backup/drivers/ceph.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import os
import re
import subprocess
import tempfile
import time
from typing import Dict, List, Optional, Tuple # noqa: H301

Expand Down Expand Up @@ -618,33 +619,40 @@ def _piped_execute(self, cmd1: list, cmd2: list) -> Tuple[int, bytes]:
LOG.debug("Piping cmd1='%s' into...", ' '.join(cmd1))
LOG.debug("cmd2='%s'", ' '.join(cmd2))

try:
p1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True)
except OSError as e:
LOG.error("Pipe1 failed - %s ", e)
raise
with tempfile.TemporaryFile() as errfile:

# NOTE(dosaboy): ensure that the pipe is blocking. This is to work
# around the case where evenlet.green.subprocess is used which seems to
# use a non-blocking pipe.
assert p1.stdout is not None
flags = fcntl.fcntl(p1.stdout, fcntl.F_GETFL) & (~os.O_NONBLOCK)
fcntl.fcntl(p1.stdout, fcntl.F_SETFL, flags)

try:
p2 = subprocess.Popen(cmd2, stdin=p1.stdout,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True)
except OSError as e:
LOG.error("Pipe2 failed - %s ", e)
raise
try:
p1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE,
stderr=errfile,
close_fds=True)
except OSError as e:
LOG.error("Pipe1 failed - %s ", e)
raise

# NOTE(dosaboy): ensure that the pipe is blocking. This is to work
# around the case where evenlet.green.subprocess is used which
# seems to use a non-blocking pipe.
assert p1.stdout is not None
flags = fcntl.fcntl(p1.stdout, fcntl.F_GETFL) & (~os.O_NONBLOCK)
fcntl.fcntl(p1.stdout, fcntl.F_SETFL, flags)

p1.stdout.close()
stdout, stderr = p2.communicate()
return p2.returncode, stderr
try:
p2 = subprocess.Popen(cmd2, stdin=p1.stdout,
stdout=subprocess.PIPE,
stderr=errfile,
close_fds=True)
except OSError as e:
LOG.error("Pipe2 failed - %s ", e)
raise

p1.stdout.close()
p2.communicate()
p1.wait()

errfile.seek(0)
px_stderr = errfile.read()

return p1.returncode or p2.returncode, px_stderr

def _rbd_diff_transfer(self, src_name: str, src_pool: str,
dest_name: str, dest_pool: str,
Expand Down
3 changes: 2 additions & 1 deletion cinder/backup/drivers/swift.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ def _headers(self, headers=None):

sa_plugin = service_auth.get_service_auth_plugin()
if sa_plugin is not None:
result['X-Service-Token'] = sa_plugin.get_token()
sa_session = service_auth.get_service_session()
result['X-Service-Token'] = sa_plugin.get_token(session=sa_session)

return result

Expand Down
10 changes: 10 additions & 0 deletions cinder/cmd/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,16 @@ def update_host(self, currenthost: str, newhost: str) -> None:
db.volume_update(ctxt, v['id'],
{'host': newhost})

def update_service(self):
"""Modify the service uuid associated with a volume.

In certain upgrade cases, we create new cinder services and delete the
records of old ones, however, the volumes created with old service
still contain the service uuid of the old services.
"""
ctxt = context.get_admin_context()
db.volume_update_all_by_service(ctxt)


class ConfigCommands(object):
"""Class for exposing the flags defined by flag_file(s)."""
Expand Down
5 changes: 5 additions & 0 deletions cinder/db/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ def volume_get_all_by_host(context, host, filters=None):
return IMPL.volume_get_all_by_host(context, host, filters=filters)


def volume_update_all_by_service(context):
"""Update all volumes associated with an old service."""
return IMPL.volume_update_all_by_service(context)


def volume_get_all_by_group(context, group_id, filters=None):
"""Get all volumes belonging to a consistency group."""
return IMPL.volume_get_all_by_group(context, group_id, filters=filters)
Expand Down
31 changes: 28 additions & 3 deletions cinder/db/sqlalchemy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2862,6 +2862,32 @@ def volume_get_all_by_group(context, group_id, filters=None):
return query.all()


@require_admin_context
@main_context_manager.writer
def volume_update_all_by_service(context):
"""Ensure volumes have the correct service_uuid value for their host.

In some deployment tools, when performing an upgrade, all service records
are recreated including c-vol service which gets a new record in the
services table, though its host name is constant. Later we then delete the
old service record.
As a consequence, the volumes have the right host name but the service
UUID needs to be updated to the ID of the new service record.

:param context: context to query under
"""
# Get all cinder-volume services
services = service_get_all(context, binary='cinder-volume')
for service in services:
query = model_query(context, models.Volume)
query = query.filter(
_filter_host(
models.Volume.host, service.host),
models.Volume.service_uuid != service.uuid)
query.update(
{"service_uuid": service.uuid}, synchronize_session=False)


@require_context
@main_context_manager.reader
def volume_get_all_by_generic_group(context, group_id, filters=None):
Expand Down Expand Up @@ -8678,9 +8704,8 @@ def use_quota_online_data_migration(
calculate_use_quota,
):
updated = 0
query = model_query(context, getattr(models, resource_name)).filter_by(
use_quota=None
)
query = model_query(context, getattr(models, resource_name),
read_deleted='yes').filter_by(use_quota=None)
if resource_name == 'Volume':
query = query.options(joinedload(models.Volume.volume_admin_metadata))
total = query.count()
Expand Down
9 changes: 5 additions & 4 deletions cinder/image/image_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@
'an operator has configured glance property protections '
'to make some image properties read-only. Cinder will '
'*always* filter out image metadata in the namespaces '
'`os_glance` and `img_signature`; this configuration '
'option allows operators to specify *additional* '
'namespaces to be excluded.',
'`os_glance`, `img_signature` and `signature_verified`; '
'this configuration option allows operators to specify '
'*additional* namespaces to be excluded.',
default=[]),
]

Expand All @@ -130,7 +130,8 @@

COMPRESSIBLE_IMAGE_FORMATS = ('qcow2',)

GLANCE_RESERVED_NAMESPACES = ["os_glance", "img_signature"]
GLANCE_RESERVED_NAMESPACES = ["os_glance", "img_signature",
"signature_verified"]


def validate_stores_id(context: context.RequestContext,
Expand Down
4 changes: 4 additions & 0 deletions cinder/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from cinder.common import constants
from cinder import context
from cinder import coordination
from cinder import db
from cinder import exception
from cinder.i18n import _
from cinder import objects
Expand Down Expand Up @@ -366,6 +367,9 @@ def _create_service_ref(self,
# If we have updated the service_ref with replication data from
# the cluster it will be saved.
service_ref.save()
# Update all volumes that are associated with an old service with
# the new service uuid
db.volume_update_all_by_service(context)

def __getattr__(self, key: str):
manager = self.__dict__.get('manager', None)
Expand Down
11 changes: 11 additions & 0 deletions cinder/service_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

CONF = cfg.CONF
_SERVICE_AUTH = None
_SERVICE_SESSION = None

SERVICE_USER_GROUP = 'service_user'

Expand Down Expand Up @@ -66,6 +67,16 @@ def get_service_auth_plugin():
return None


def get_service_session():
if CONF.service_user.send_service_user_token:
global _SERVICE_SESSION
if not _SERVICE_SESSION:
_SERVICE_SESSION = ks_loading.load_session_from_conf_options(
CONF, SERVICE_USER_GROUP, auth=get_service_auth_plugin())
return _SERVICE_SESSION
return None


def get_auth_plugin(context, auth=None):
if auth:
user_auth = auth
Expand Down
Loading
Loading