Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e38e2a2
Improve unit tests in NetApp Driver
rodrigogansobarbieri Oct 9, 2024
82a61bf
Fix access rule visibility locks
silvacarloss Nov 19, 2024
f5b2b2d
fix manila to use device uuid instead of name for mounting
yaguangtang Dec 5, 2024
5352ca3
Drop broken manila-all script
kajinamit Feb 5, 2025
0aaa640
fix volume resize issue when host not recognized
yaguangtang Mar 12, 2025
5b38049
Don't override nfs protocols w/ CephFS
gouthampacha Feb 20, 2025
12793ce
[2024.1]fix manila-tempest-plugin-dummy-dhss job
ricolin Aug 26, 2025
0c757f6
Fix server instance subnet cleanup
ricolin Jul 28, 2025
fdb00bd
Dell Unity: Fix driver startup issue with LACP configured
YianZong Jul 4, 2025
517a040
Pass share metadata updates to backend drivers
kpawar89 Jul 29, 2024
8e60740
API for ensure shares
silvacarloss Jul 16, 2024
2450670
Remove extra policy check
silvacarloss Sep 18, 2024
44828df
[doc] Driver updatable metadata
kpawar89 Sep 25, 2024
27f32ba
Metadata for Share Export Location
emclidon Jul 3, 2023
1c3972b
[NetApp] Custom storage efficiency policy support for Manila share
jayaanan-netapp Jul 29, 2024
068a69c
NetApp: Implement share metadata update method
kpawar89 Jul 29, 2024
bc4533f
[NetApp] SnapLock support for NetApp driver
Aug 9, 2024
4b635d8
Allow to update access level of access rule
kpawar89 Oct 1, 2024
6f27bcf
[cephfs] Fix access rule update
silvacarloss Jan 28, 2025
5bde37d
Add missing API version description
silvacarloss Feb 20, 2025
9c7a362
Fix access rule update
kpawar89 Jan 30, 2025
605d69e
Pass share network subnet metadata updates to backend drivers
kpawar89 Sep 12, 2024
a37dde1
NetApp: Implement share network subnet metadata update method
kpawar89 Feb 27, 2025
4ee61a4
NetApp - Restrict LIF Creation Per HA Pair
Feb 19, 2025
27bd40c
Fix 'server_migrating' status of non-active replica
kpawar89 Mar 27, 2025
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
5 changes: 5 additions & 0 deletions api-ref/source/samples/share-access-rules-update-request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"update_access": {
"access_level": "ro"
}
}
17 changes: 17 additions & 0 deletions api-ref/source/samples/share-access-rules-update-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"access": {
"access_level": "ro",
"state": "error",
"id": "507bf114-36f2-4f56-8cf4-857985ca87c1",
"share_id": "fb213952-2352-41b4-ad7b-2c4c69d13eef",
"access_type": "ip",
"access_to": "0.0.0.0/0",
"access_key": null,
"created_at": "2024-12-17T02:01:04.000000",
"updated_at": "2024-12-17T02:01:04.000000",
"metadata": {
"key1": "value1",
"key2": "value2"
}
}
}
61 changes: 61 additions & 0 deletions api-ref/source/share-access-rules.inc
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,64 @@ Response example

.. literalinclude:: samples/share-access-rules-list-response.json
:language: javascript


Update share access rule
~~~~~~~~~~~~~~~~~~~~~~~~

.. rest_method:: PUT /v2/share-access-rules/{access_id}

.. versionadded:: 2.88

Update ``access_level`` of a specified access rule.

Response codes
--------------

.. rest_status_code:: success status.yaml

- 200

.. rest_status_code:: error status.yaml

- 400
- 401
- 403
- 404

Request
-------

.. rest_parameters:: parameters.yaml

- project_id: project_id_path
- access_id: access_id_path
- access_level: access_level

Request example
---------------

.. literalinclude:: samples/share-access-rules-update-request.json
:language: javascript

Response parameters
-------------------

.. rest_parameters:: parameters.yaml

- share_id: access_share_id
- created_at: created_at
- updated_at: updated_at
- access_type: access_type
- access_to: access_to
- access_key: access_key_share_access_rules
- state: state
- access_level: access_level
- id: access_rule_id
- metadata: access_metadata

Response example
----------------

.. literalinclude:: samples/share-access-rules-update-response.json
:language: javascript
11 changes: 11 additions & 0 deletions doc/source/admin/shared-file-systems-crud-share.rst
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,17 @@ You can update the metadata:
You also can unset the metadata using
**manila metadata <share_name> unset <metadata_key(s)>**.

.. note::
In case you want to prevent certain metadata key-values to be manipulated by
less privileged users, you can provide a list of such keys through the admin
only metadata configuration option listed in the
:ref:`additional configuration options page <manila-common>`.

In case you want to pass certain metadata key-values to be consumed by share
drivers, you can provide a list of such keys through the driver updatable
metadata configuration option listed in the
:ref:`additional configuration options page <manila-common>`.

Reset share state
-----------------

Expand Down
6 changes: 6 additions & 0 deletions doc/source/configuration/tables/manila-common.inc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@
- (Boolean) Treat X-Forwarded-For as the canonical remote address. Only enable this if you have a sanitizing proxy.
* - ``wsgi_keep_alive`` = ``True``
- (Boolean) If False, closes the client socket connection explicitly. Setting it to True to maintain backward compatibility. Recommended setting is set it to False.
* - ``admin_only_metadata`` = ``__affinity_same_host,__affinity_different_host``
- (List) The affinity keys are default to ensure backwards compatibility. Update the list with metadata items that should only be manipulated by people allowed by the "update_admin_only_metadata" policy.
* - ``driver_updatable_metadata`` = ``None``
- (List) Metadata keys that will decide which share metadata can be passed to share drivers as part of metadata create/update operations.
* - ``driver_updatable_subnet_metadata`` = ``None``
- (List) Metadata keys that will decide which share network_subnet_metadata can be passed to share drivers as part of metadata create/update operations.
* - **[coordination]**
-
* - ``backend_url`` = ``file://$state_path``
Expand Down
5 changes: 4 additions & 1 deletion doc/source/user/share-network-subnet-operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ commands. You can create multiple subnets in a share network, and if you do
not specify an availability zone, the subnet you are creating will be
considered default by the Shared File Systems service. The default subnet
spans all availability zones. You cannot have more than one default subnet
per share network.
per share network. During share server migration, metadata belonging to the
old share network subnet is ignored when moving to a new share network. Since
metadata updates are passed to backend driver, with migration of share network
these metadata updates will no longer be available to new share network.


.. important::
Expand Down
7 changes: 6 additions & 1 deletion manila/api/openstack/api_version_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,18 @@
* 2.83 - Added 'disabled_reason' field to services.
* 2.84 - Added mount_point_name to shares.
* 2.85 - Added backup_type field to share backups.
* 2.86 - Add ensure share API.
* 2.87 - Added Share export location metadata API
* 2.88 - Added support for update Share access rule.
* 2.89 - Added support for passing Share network subnet metadata updates
to driver.
"""

# The minimum and maximum versions of the API supported
# The default api version request is defined to be the
# minimum version of the API supported.
_MIN_API_VERSION = "2.0"
_MAX_API_VERSION = "2.85"
_MAX_API_VERSION = "2.89"
DEFAULT_API_VERSION = _MIN_API_VERSION


Expand Down
19 changes: 19 additions & 0 deletions manila/api/openstack/rest_api_version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,22 @@ user documentation.
2.85
----
Added ``backup_type`` field to share backup object.

2.86
----
Added ensure shares API.

2.87
----
Added Metadata API methods (GET, PUT, POST, DELETE)
to Share Export Locations.

2.88
----
Allows updating the access rule's access type.


2.89
----
Added support for passing share network subnet metadata updates to share
backend driver.
10 changes: 7 additions & 3 deletions manila/api/v1/shares.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,12 +589,14 @@ def _check_for_access_rule_locks(self, context, access_data, access_id,
unrestrict = access_data.get('unrestrict', False)
search_opts = {
'resource_id': access_id,
'resource_action': constants.RESOURCE_ACTION_DELETE
'resource_action': constants.RESOURCE_ACTION_DELETE,
'all_projects': True,
}

locks, locks_count = (
self.resource_locks_api.get_all(
context, search_opts=search_opts, show_count=True) or []
context.elevated(), search_opts=search_opts,
show_count=True) or []
)

# no locks placed, nothing to do
Expand All @@ -620,7 +622,9 @@ def raise_rule_is_locked(share_id, unrestrict=False):
try:
self.resource_locks_api.ensure_context_can_delete_lock(
context, lock['id'])
except exception.NotAuthorized:
except (exception.NotAuthorized, exception.ResourceLockNotFound):
# If it is not found, then it means that the context doesn't
# have access to this resource and should be denied.
non_deletable_locks.append(lock)

if non_deletable_locks:
Expand Down
54 changes: 33 additions & 21 deletions manila/api/v2/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,42 @@ class MetadataController(object):
"share": "share_get",
"share_snapshot": "share_snapshot_get",
"share_network_subnet": "share_network_subnet_get",
"share_export_location": "export_location_get_by_uuid",
}

resource_metadata_get = {
"share": "share_metadata_get",
"share_snapshot": "share_snapshot_metadata_get",
"share_network_subnet": "share_network_subnet_metadata_get",
"share_export_location": "export_location_metadata_get",
}

resource_metadata_get_item = {
"share": "share_metadata_get_item",
"share_snapshot": "share_snapshot_metadata_get_item",
"share_network_subnet": "share_network_subnet_metadata_get_item",
"share_export_location": "export_location_metadata_get_item",
}

resource_metadata_update = {
"share": "share_metadata_update",
"share_snapshot": "share_snapshot_metadata_update",
"share_network_subnet": "share_network_subnet_metadata_update",
"share_export_location": "export_location_metadata_update",
}

resource_metadata_update_item = {
"share": "share_metadata_update_item",
"share_snapshot": "share_snapshot_metadata_update_item",
"share_network_subnet": "share_network_subnet_metadata_update_item",
"share_export_location": "export_location_metadata_update_item",
}

resource_metadata_delete = {
"share": "share_metadata_delete",
"share_snapshot": "share_snapshot_metadata_delete",
"share_network_subnet": "share_network_subnet_metadata_delete",
"share_export_location": "export_location_metadata_delete",
}

resource_policy_get = {
Expand All @@ -72,10 +78,13 @@ def __init__(self):

def _get_resource(self, context, resource_id,
for_modification=False, parent_id=None):
if self.resource_name in ['share', 'share_network_subnet']:
# we would allow retrieving some "public" resources
# across project namespaces except share snapshots,
# project_only=True is hard coded
if self.resource_name in ['share', 'share_network_subnet',
'share_export_location']:
# some resources don't have a "project_id" field (like
# share_export_location or share_network_subnet),
# and sometimes we want to retrieve "public" resources
# (like shares), so avoid hard coding project_only=True in the
# lookup where necessary
kwargs = {}
else:
kwargs = {'project_only': True}
Expand All @@ -86,23 +95,25 @@ def _get_resource(self, context, resource_id,
kwargs["parent_id"] = parent_id
res = get_res_method(context, resource_id, **kwargs)

get_policy = self.resource_policy_get[self.resource_name]
if res.get('is_public') is False:
authorized = policy.check_policy(context,
self.resource_name,
get_policy,
res,
do_raise=False)
if not authorized:
# Raising NotFound to prevent existence detection
raise exception.NotFound()
elif for_modification:
# a public resource's metadata can be viewed, but not
# modified by non owners
policy.check_policy(context,
self.resource_name,
get_policy,
res)
if self.resource_name not in ["share_export_location"]:
get_policy = self.resource_policy_get[self.resource_name]
# skip policy check for export locations
if res.get('is_public') is False:
authorized = policy.check_policy(context,
self.resource_name,
get_policy,
res,
do_raise=False)
if not authorized:
# Raising NotFound to prevent existence detection
raise exception.NotFound()
elif for_modification:
# a public resource's metadata can be viewed, but not
# modified by non owners
policy.check_policy(context,
self.resource_name,
get_policy,
res)
except exception.NotFound:
msg = _('%s not found.' % self.resource_name.capitalize())
raise exc.HTTPNotFound(explanation=msg)
Expand All @@ -120,6 +131,7 @@ def _get_metadata(self, context, resource_id, parent_id=None):

@wsgi.response(200)
def _index_metadata(self, req, resource_id, parent_id=None):
"""Lists existing metadata."""
context = req.environ['manila.context']
metadata = self._get_metadata(context, resource_id,
parent_id=parent_id)
Expand Down
46 changes: 46 additions & 0 deletions manila/api/v2/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ def _setup_routes(self, mapper):
mapper.resource("service",
"services",
controller=self.resources["services"])
for path_prefix in ['/{project_id}', '']:
# project_id is optional
mapper.connect("services",
"%s/services/ensure-shares" % path_prefix,
controller=self.resources["services"],
action="ensure_shares",
conditions={"method": ["POST"]})

self.resources["quota_sets_legacy"] = (
quota_sets.create_resource_legacy())
Expand Down Expand Up @@ -252,6 +259,45 @@ def _setup_routes(self, mapper):
controller=self.resources["share_export_locations"],
action="show",
conditions={"method": ["GET"]})
mapper.connect("export_locations_metadata",
"%s/shares/{share_id}/export_locations"
"/{resource_id}/metadata" % path_prefix,
controller=self.resources["share_export_locations"],
action="create_metadata",
conditions={"method": ["POST"]})
mapper.connect("export_locations_metadata",
"%s/shares/{share_id}/export_locations"
"/{resource_id}/metadata" % path_prefix,
controller=self.resources["share_export_locations"],
action="update_all_metadata",
conditions={"method": ["PUT"]})
mapper.connect("export_locations_metadata",
"%s/shares/{share_id}/export_locations/"
"{resource_id}/metadata/{key}"
% path_prefix,
controller=self.resources["share_export_locations"],
action="update_metadata_item",
conditions={"method": ["POST"]})
mapper.connect("export_locations_metadata",
"%s/shares/{share_id}/export_locations/"
"{resource_id}/metadata" % path_prefix,
controller=self.resources["share_export_locations"],
action="index_metadata",
conditions={"method": ["GET"]})
mapper.connect("export_locations_metadata",
"%s/shares/{share_id}/export_locations/"
"{resource_id}/metadata/{key}"
% path_prefix,
controller=self.resources["share_export_locations"],
action="show_metadata",
conditions={"method": ["GET"]})
mapper.connect("export_locations_metadata",
"%s/shares/{share_id}/export_locations/"
"{resource_id}/metadata/{key}"
% path_prefix,
controller=self.resources["share_export_locations"],
action="delete_metadata",
conditions={"method": ["DELETE"]})

self.resources["snapshots"] = share_snapshots.create_resource()
mapper.resource("snapshot", "snapshots",
Expand Down
Loading