Coverage for manila/api/v2/share_export_locations.py: 84%

150 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright 2015 Mirantis inc. 

2# All Rights Reserved. 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); you may 

5# not use this file except in compliance with the License. You may obtain 

6# a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

13# License for the specific language governing permissions and limitations 

14# under the License. 

15 

16from oslo_config import cfg 

17from oslo_log import log 

18from webob import exc 

19 

20from manila.api.openstack import wsgi 

21from manila.api.schemas import share_export_locations as schema 

22from manila.api.v2 import metadata 

23from manila.api import validation 

24from manila.api.views import export_locations as export_locations_views 

25from manila.db import api as db_api 

26from manila import exception 

27from manila.i18n import _ 

28from manila import policy 

29 

30LOG = log.getLogger(__name__) 

31CONF = cfg.CONF 

32 

33 

34@validation.validated 

35class ShareExportLocationController(wsgi.Controller, 

36 metadata.MetadataController): 

37 """The Share Export Locations API controller.""" 

38 

39 def __init__(self): 

40 self._view_builder_class = export_locations_views.ViewBuilder 

41 self.resource_name = 'share_export_location' 

42 super(ShareExportLocationController, self).__init__() 

43 self._conf_admin_only_metadata_keys = getattr( 

44 CONF, 'admin_only_el_metadata', [] 

45 ) 

46 

47 def _verify_share(self, context, share_id): 

48 try: 

49 share = db_api.share_get(context, share_id) 

50 if not share['is_public']: 50 ↛ exitline 50 didn't return from function '_verify_share' because the condition on line 50 was always true

51 policy.check_policy(context, 'share', 'get', share) 

52 except exception.NotFound: 

53 msg = _("Share '%s' not found.") % share_id 

54 raise exc.HTTPNotFound(explanation=msg) 

55 

56 @wsgi.Controller.authorize('index') 

57 def _index(self, req, share_id, ignore_secondary_replicas=False): 

58 context = req.environ['manila.context'] 

59 self._verify_share(context, share_id) 

60 kwargs = { 

61 'include_admin_only': context.is_admin, 

62 'ignore_migration_destination': True, 

63 'ignore_secondary_replicas': ignore_secondary_replicas, 

64 } 

65 export_locations = db_api.export_location_get_all_by_share_id( 

66 context, share_id, **kwargs) 

67 return self._view_builder.summary_list(req, export_locations) 

68 

69 @wsgi.Controller.authorize('show') 

70 def _show(self, req, share_id, export_location_uuid, 

71 ignore_secondary_replicas=False): 

72 context = req.environ['manila.context'] 

73 self._verify_share(context, share_id) 

74 try: 

75 export_location = db_api.export_location_get_by_uuid( 

76 context, export_location_uuid, 

77 ignore_secondary_replicas=ignore_secondary_replicas) 

78 except exception.ExportLocationNotFound: 

79 msg = _("Export location '%s' not found.") % export_location_uuid 

80 raise exc.HTTPNotFound(explanation=msg) 

81 

82 if export_location.is_admin_only and not context.is_admin: 

83 raise exc.HTTPForbidden() 

84 

85 return self._view_builder.detail(req, export_location) 

86 

87 @wsgi.Controller.api_version('2.9', '2.46') 

88 @validation.request_query_schema(schema.empty_query_schema) 

89 @validation.response_body_schema(schema.index_response_body, '2.9', '2.13') 

90 @validation.response_body_schema(schema.index_response_body_v214, '2.14') 

91 def index(self, req, share_id): 

92 """Return a list of export locations for share.""" 

93 return self._index(req, share_id) 

94 

95 @wsgi.Controller.api_version('2.47') # noqa: F811 

96 # NOTE(jonathon): The new microversion removes secondary replicas from 

97 # the results but doesn't change the schema, so we can re-use the schema 

98 @validation.request_query_schema(schema.empty_query_schema) 

99 @validation.response_body_schema( 

100 schema.index_response_body_v214, '2.14', '2.86') 

101 @validation.response_body_schema(schema.index_response_body_v287, '2.87') 

102 def index(self, req, share_id): # pylint: disable=function-redefined # noqa F811 

103 """Return a list of export locations for share.""" 

104 return self._index(req, share_id, 

105 ignore_secondary_replicas=True) 

106 

107 @wsgi.Controller.api_version('2.9', '2.46') 

108 @validation.request_query_schema(schema.empty_query_schema) 

109 @validation.response_body_schema(schema.show_response_body, '2.9', '2.13') 

110 @validation.response_body_schema(schema.show_response_body_v214, '2.14') 

111 def show(self, req, share_id, export_location_uuid): 

112 """Return data about the requested export location.""" 

113 return self._show(req, share_id, export_location_uuid) 

114 

115 @wsgi.Controller.api_version('2.47') # noqa: F811 

116 # NOTE(jonathon): The new microversion removes secondary replicas from 

117 # the results but doesn't change the schema, so we can re-use the schema 

118 @validation.request_query_schema(schema.empty_query_schema) 

119 @validation.response_body_schema( 

120 schema.show_response_body_v214, '2.14', '2.86') 

121 @validation.response_body_schema(schema.show_response_body_v287, '2.87') 

122 def show(self, req, share_id, # pylint: disable=function-redefined # noqa F811 

123 export_location_uuid): 

124 """Return data about the requested export location.""" 

125 return self._show(req, share_id, export_location_uuid, 

126 ignore_secondary_replicas=True) 

127 

128 def _validate_metadata_for_update(self, req, share_export_location, 

129 metadata, delete=True): 

130 persistent_keys = set(self._conf_admin_only_metadata_keys) 

131 context = req.environ['manila.context'] 

132 if set(metadata).intersection(persistent_keys): 132 ↛ 143line 132 didn't jump to line 143 because the condition on line 132 was always true

133 try: 

134 policy.check_policy( 

135 context, 'share_export_location', 

136 'update_admin_only_metadata') 

137 except exception.PolicyNotAuthorized: 

138 msg = _("Cannot set or update admin only metadata.") 

139 LOG.exception(msg) 

140 raise exc.HTTPForbidden(explanation=msg) 

141 persistent_keys = [] 

142 

143 current_export_metadata = db_api.export_location_metadata_get( 

144 context, share_export_location) 

145 if delete: 145 ↛ 151line 145 didn't jump to line 151 because the condition on line 145 was always true

146 _metadata = metadata 

147 for key in persistent_keys: 147 ↛ 148line 147 didn't jump to line 148 because the loop on line 147 never started

148 if key in current_export_metadata: 

149 _metadata[key] = current_export_metadata[key] 

150 else: 

151 metadata_copy = metadata.copy() 

152 for key in persistent_keys: 

153 metadata_copy.pop(key, None) 

154 _metadata = current_export_metadata.copy() 

155 _metadata.update(metadata_copy) 

156 

157 return _metadata 

158 

159 @wsgi.Controller.api_version("2.87") 

160 @wsgi.Controller.authorize("get_metadata") 

161 @validation.request_query_schema(schema.empty_query_schema) 

162 @validation.response_body_schema(schema.show_metadata_response_body) 

163 def index_metadata(self, req, share_id, resource_id): 

164 """Returns the list of metadata for a given share export location.""" 

165 context = req.environ['manila.context'] 

166 self._verify_share(context, share_id) 

167 return self._index_metadata(req, resource_id) 

168 

169 @wsgi.Controller.api_version("2.87") 

170 @wsgi.Controller.authorize("update_metadata") 

171 @validation.request_body_schema(schema.create_metadata_response_body) 

172 @validation.response_body_schema(schema.create_metadata_response_body) 

173 def create_metadata(self, req, share_id, resource_id, body): 

174 """Create metadata for a given share export location.""" 

175 _metadata = self._validate_metadata_for_update(req, resource_id, 

176 body['metadata'], 

177 delete=False) 

178 body['metadata'] = _metadata 

179 context = req.environ['manila.context'] 

180 self._verify_share(context, share_id) 

181 return self._create_metadata(req, resource_id, body) 

182 

183 @wsgi.Controller.api_version("2.87") 

184 @wsgi.Controller.authorize("update_metadata") 

185 @validation.request_body_schema(schema.update_metadata_request_body) 

186 @validation.response_body_schema(schema.update_metadata_response_body) 

187 def update_all_metadata(self, req, share_id, resource_id, body): 

188 """Update entire metadata for a given share export location.""" 

189 _metadata = self._validate_metadata_for_update(req, resource_id, 

190 body['metadata']) 

191 body['metadata'] = _metadata 

192 context = req.environ['manila.context'] 

193 self._verify_share(context, share_id) 

194 return self._update_all_metadata(req, resource_id, body) 

195 

196 @wsgi.Controller.api_version("2.87") 

197 @wsgi.Controller.authorize("update_metadata") 

198 @validation.request_body_schema(schema.update_metadata_request_body) 

199 @validation.response_body_schema(schema.update_metadata_response_body) 

200 def update_metadata_item(self, req, share_id, resource_id, body, key): 

201 """Update metadata item for a given share export location.""" 

202 _metadata = self._validate_metadata_for_update(req, resource_id, 

203 body['metadata'], 

204 delete=False) 

205 body['metadata'] = _metadata 

206 context = req.environ['manila.context'] 

207 self._verify_share(context, share_id) 

208 return self._update_metadata_item(req, resource_id, body, key) 

209 

210 @wsgi.Controller.api_version("2.87") 

211 @wsgi.Controller.authorize("get_metadata") 

212 @validation.request_query_schema(schema.empty_query_schema) 

213 @validation.response_body_schema(schema.show_metadata_response_body) 

214 def show_metadata(self, req, share_id, resource_id, key): 

215 """Show metadata for a given share export location.""" 

216 context = req.environ['manila.context'] 

217 self._verify_share(context, share_id) 

218 return self._show_metadata(req, resource_id, key) 

219 

220 @wsgi.Controller.api_version("2.87") 

221 @wsgi.Controller.authorize("delete_metadata") 

222 @validation.response_body_schema(schema.delete_metadata_response_body) 

223 def delete_metadata(self, req, share_id, resource_id, key): 

224 """Delete metadata for a given share export location.""" 

225 context = req.environ['manila.context'] 

226 self._verify_share(context, share_id) 

227 return self._delete_metadata(req, resource_id, key) 

228 

229 

230def create_resource(): 

231 return wsgi.Resource(ShareExportLocationController())