diff --git a/api-ref/source/qos-types.inc b/api-ref/source/qos-types.inc index 52a7e8222d..502600e498 100644 --- a/api-ref/source/qos-types.inc +++ b/api-ref/source/qos-types.inc @@ -48,6 +48,8 @@ Response parameters - name: qos_type_name - description: qos_type_description - specs: qos_type_specs + - created_at: created_at + - updated_at: updated_at Response example ---------------- @@ -93,6 +95,8 @@ Response Parameters - name: qos_type_name - description: qos_type_description - specs: qos_type_specs + - created_at: created_at + - updated_at: updated_at Response Example ---------------- @@ -189,6 +193,8 @@ Response parameters - name: qos_type_name - description: qos_type_description - specs: qos_type_specs + - created_at: created_at + - updated_at: updated_at Response example ---------------- @@ -352,6 +358,8 @@ Response parameters - name: qos_type_name - description: qos_type_description - specs: qos_type_specs + - created_at: created_at + - updated_at: updated_at Response example ---------------- diff --git a/api-ref/source/samples/qos-type-create-response.json b/api-ref/source/samples/qos-type-create-response.json index 9b27fe0e72..1d8c6d9b6b 100644 --- a/api-ref/source/samples/qos-type-create-response.json +++ b/api-ref/source/samples/qos-type-create-response.json @@ -7,6 +7,8 @@ "expected_iops": 2000 }, "name": "testing", - "description": "qos type description" + "description": "qos type description", + "created_at": "2026-02-18T05:09:54.000000", + "updated_at": null } } diff --git a/api-ref/source/samples/qos-type-show-response.json b/api-ref/source/samples/qos-type-show-response.json index 9b27fe0e72..1d8c6d9b6b 100644 --- a/api-ref/source/samples/qos-type-show-response.json +++ b/api-ref/source/samples/qos-type-show-response.json @@ -7,6 +7,8 @@ "expected_iops": 2000 }, "name": "testing", - "description": "qos type description" + "description": "qos type description", + "created_at": "2026-02-18T05:09:54.000000", + "updated_at": null } } diff --git a/api-ref/source/samples/qos-type-update-response.json b/api-ref/source/samples/qos-type-update-response.json index 42a9896129..496f26188c 100644 --- a/api-ref/source/samples/qos-type-update-response.json +++ b/api-ref/source/samples/qos-type-update-response.json @@ -7,6 +7,8 @@ "expected_iops": 2000 }, "name": "testing", - "description": "qos type description2" + "description": "qos type description2", + "created_at": "2026-02-18T05:09:54.000000", + "updated_at": "2026-02-18T06:12:33.000000" } } diff --git a/api-ref/source/samples/qos-types-list-response.json b/api-ref/source/samples/qos-types-list-response.json index 9bebd1c426..b163e00f63 100644 --- a/api-ref/source/samples/qos-types-list-response.json +++ b/api-ref/source/samples/qos-types-list-response.json @@ -8,7 +8,9 @@ "expected_iops": 2000 }, "name": "testing", - "description": "qos type description" + "description": "qos type description", + "created_at": "2026-02-18T05:09:54.000000", + "updated_at": null }, { "id": "2fa1342b-de9d-4d89-bdc8-af67795c0e52", @@ -18,7 +20,9 @@ "expected_iops": 1000 }, "name": "testing2", - "description": "qos type description2" + "description": "qos type description2", + "created_at": "2026-02-18T05:10:12.000000", + "updated_at": null } ] } diff --git a/devstack/upgrade/shutdown.sh b/devstack/upgrade/shutdown.sh index 9549f48911..019b7b661e 100755 --- a/devstack/upgrade/shutdown.sh +++ b/devstack/upgrade/shutdown.sh @@ -12,6 +12,7 @@ source $BASE_DEVSTACK_DIR/stackrc # needed for status directory # Locate the manila plugin and get its functions MANILA_DEVSTACK_DIR=$(dirname $(dirname $0)) +source $MANILA_DEVSTACK_DIR/settings source $MANILA_DEVSTACK_DIR/plugin.sh set -o xtrace diff --git a/manila/context.py b/manila/context.py index b4ad245006..03276ab4ab 100644 --- a/manila/context.py +++ b/manila/context.py @@ -51,9 +51,9 @@ def __init__(self, user_id=None, project_id=None, is_admin=None, kwargs.setdefault('user_id', user_id) kwargs.setdefault('project_id', project_id) - super().__init__(is_admin=is_admin, **kwargs) - - self.project_name = project_name + # _read_deleted must exist before super().__init__() because the + # parent class may access the read_deleted, remote_address, timestamp, + # quota_class, service_catalog property during init. self.read_deleted = read_deleted self.remote_address = remote_address if not timestamp: @@ -68,6 +68,9 @@ def __init__(self, user_id=None, project_id=None, is_admin=None, else: self.service_catalog = [] + super().__init__(is_admin=is_admin, **kwargs) + + self.project_name = project_name if self.is_admin is None: self.is_admin = policy.check_is_admin(self) elif self.is_admin and 'admin' not in self.roles: diff --git a/manila/share/api.py b/manila/share/api.py index 319b2c6adf..ca05f72ee5 100644 --- a/manila/share/api.py +++ b/manila/share/api.py @@ -2051,7 +2051,7 @@ def migration_start( raise exception.InvalidInput(reason=msg) self._modify_quotas_for_share_migration(context, share, new_share_type) - qos_type = share_type.get('extra_specs').get( + qos_type = share_type.get('extra_specs', {}).get( constants.ExtraSpecs.DEFAULT_QOS_TYPE) if qos_type: qos_db = self.db.qos_type_get_by_name_or_id(context, qos_type) diff --git a/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py b/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py index 2edf8896e9..4addbbc5bd 100644 --- a/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py +++ b/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py @@ -238,8 +238,12 @@ def setup_server_with_lock(): raise if metadata.get('encryption_key_ref'): - self._create_barbican_kms_config_for_specified_vserver( - vserver_name, metadata) + try: + self._create_barbican_kms_config_for_specified_vserver( + vserver_name, metadata) + except Exception as e: + e.detail_data = {'server_details': server_details} + raise return server_details return setup_server_with_lock() diff --git a/manila/tests/api/v2/test_qos_types.py b/manila/tests/api/v2/test_qos_types.py index 6f15c00551..5697fb7af5 100644 --- a/manila/tests/api/v2/test_qos_types.py +++ b/manila/tests/api/v2/test_qos_types.py @@ -50,6 +50,8 @@ def stub_qos_type(id): 'name': name, 'description': description, 'specs': specs, + 'created_at': '2026-02-18T05:09:54.000000', + 'updated_at': None, } return qos_type diff --git a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py index 56c3136d47..a4052222a1 100644 --- a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py +++ b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py @@ -622,6 +622,56 @@ def test_setup_server_with_error(self): }}, fake_exception.detail_data) + def test_setup_server_with_barbican_error(self): + self.library.is_nfs_config_supported = False + mock_get_vserver_name = self.mock_object( + self.library, + '_get_vserver_name', + mock.Mock(return_value=fake.VSERVER1)) + + mock_create_vserver = self.mock_object( + self.library, '_create_vserver') + + fake_exception = exception.NetAppException("fake") + self.mock_object( + self.library, + '_create_barbican_kms_config_for_specified_vserver', + mock.Mock(side_effect=fake_exception)) + + mock_validate_network_type = self.mock_object( + self.library, + '_validate_network_type') + + mock_validate_share_network_subnets = self.mock_object( + self.library, + '_validate_share_network_subnets') + self.mock_object(self.library, '_set_network_with_metadata') + self.library.configuration.netapp_restrict_lif_creation_per_ha_pair = ( + False + ) + + self.assertRaises( + exception.ManilaException, + self.library.setup_server, + fake.NETWORK_INFO_LIST, + fake.SERVER_METADATA_WITH_ENCRYPTION) + + ports = {} + for network_allocation in fake.NETWORK_INFO['network_allocations']: + ports[network_allocation['id']] = network_allocation['ip_address'] + + self.assertTrue(mock_validate_network_type.called) + self.assertTrue(mock_validate_share_network_subnets.called) + self.assertTrue(mock_get_vserver_name.called) + self.assertTrue(mock_create_vserver.called) + + self.assertDictEqual( + {'server_details': { + 'vserver_name': fake.VSERVER1, + 'ports': jsonutils.dumps(ports), + }}, + fake_exception.detail_data) + def test_setup_server_invalid_subnet(self): invalid_subnet_exception = exception.NetworkBadConfigurationException( reason='This is a fake message') diff --git a/releasenotes/notes/bug-2163166-netapp-fix-share-server-deletion-failure-after-failed-barbican-creation-abc8bcb14ef41b69.yaml b/releasenotes/notes/bug-2163166-netapp-fix-share-server-deletion-failure-after-failed-barbican-creation-abc8bcb14ef41b69.yaml new file mode 100644 index 0000000000..0e510cb80e --- /dev/null +++ b/releasenotes/notes/bug-2163166-netapp-fix-share-server-deletion-failure-after-failed-barbican-creation-abc8bcb14ef41b69.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + Fixed an issue in the NetApp ONTAP driver where communication failures + with Barbican prevented share servers from saving internal details + upon creation failure, blocking operators from deleting them. Manila + now properly saves these details, allowing share server deletion. + For more details, see + `Launchpad bug `_. diff --git a/releasenotes/notes/fix_read_deleted_error_log-d07b3c6f3682b401.yaml b/releasenotes/notes/fix_read_deleted_error_log-d07b3c6f3682b401.yaml new file mode 100644 index 0000000000..38817b1a10 --- /dev/null +++ b/releasenotes/notes/fix_read_deleted_error_log-d07b3c6f3682b401.yaml @@ -0,0 +1,8 @@ +fixes: + - | + Fixed a race condition in ``manila.context.RequestContext`` where + an ``AttributeError`` occurred during object initialization. + Attributes such as ``read_deleted``, ``remote_address``, ``timestamp``, + ``quota_class`` and ``service_catalog`` are now initialized before calling + the parent class constructor to ensure they are available for any early + calls to ``to_dict()`` made by the ``oslo_context``.