Coverage for manila/api/v2/share_accesses.py: 85%

110 statements  

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

1# Copyright 2018 Huawei Corporation. 

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 

16"""The share accesses api.""" 

17 

18import ast 

19 

20import webob 

21 

22from manila.api import common 

23from manila.api.openstack import wsgi 

24from manila.api.views import share_accesses as share_access_views 

25from manila.common import constants 

26from manila import exception 

27from manila.i18n import _ 

28from manila.lock import api as resource_locks 

29from manila import share 

30 

31 

32class ShareAccessesController(wsgi.Controller, wsgi.AdminActionsMixin): 

33 """The Share accesses API V2 controller for the OpenStack API.""" 

34 

35 resource_name = 'share_access_rule' 

36 _view_builder_class = share_access_views.ViewBuilder 

37 

38 def __init__(self): 

39 super(ShareAccessesController, self).__init__() 

40 self.share_api = share.API() 

41 self.resource_locks_api = resource_locks.API() 

42 

43 @wsgi.Controller.api_version('2.45') 

44 @wsgi.Controller.authorize('get') 

45 def show(self, req, id): 

46 """Return data about the given share access rule.""" 

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

48 share_access = self._get_share_access(context, id) 

49 restricted = self._is_rule_restricted(context, id) 

50 if restricted: 

51 share_access['restricted'] = True 

52 return self._view_builder.view(req, share_access) 

53 

54 def _is_rule_restricted(self, context, id): 

55 search_opts = { 

56 'resource_id': id, 

57 'resource_action': constants.RESOURCE_ACTION_SHOW, 

58 'resource_type': 'access_rule', 

59 'all_projects': True, 

60 } 

61 locks, count = self.resource_locks_api.get_all( 

62 context.elevated(), search_opts, show_count=True) 

63 

64 if count: 

65 return self.resource_locks_api.access_is_restricted(context, 

66 locks[0]) 

67 return False 

68 

69 def _get_share_access(self, context, share_access_id): 

70 try: 

71 return self.share_api.access_get(context, share_access_id) 

72 except exception.NotFound: 

73 msg = _("Share access rule %s not found.") % share_access_id 

74 raise webob.exc.HTTPNotFound(explanation=msg) 

75 

76 def _validate_search_opts(self, req, search_opts): 

77 """Check if search opts parameters are valid.""" 

78 access_type = search_opts.get('access_type', None) 

79 access_to = search_opts.get('access_to', None) 

80 

81 if access_type and access_type not in ['ip', 'user', 'cert', 'cephx']: 81 ↛ 82line 81 didn't jump to line 82 because the condition on line 81 was never true

82 raise exception.InvalidShareAccessType(type=access_type) 

83 

84 # If access_to is present but access type is not, it gets tricky to 

85 # validate its content 

86 if access_to and not access_type: 86 ↛ 87line 86 didn't jump to line 87 because the condition on line 86 was never true

87 msg = _("'access_type' parameter must be provided when specifying " 

88 "'access_to'.") 

89 raise exception.InvalidInput(reason=msg) 

90 

91 if access_type and access_to: 91 ↛ 92line 91 didn't jump to line 92 because the condition on line 91 was never true

92 common.validate_access(access_type=access_type, 

93 access_to=access_to, 

94 enable_ceph=True, 

95 enable_ipv6=True) 

96 

97 access_level = search_opts.get('access_level', None) 

98 if access_level and access_level not in constants.ACCESS_LEVELS: 98 ↛ 99line 98 didn't jump to line 99 because the condition on line 98 was never true

99 raise exception.InvalidShareAccessLevel(level=access_level) 

100 

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

102 def _index(self, req, support_for_access_filters=False): 

103 """Returns the list of access rules for a given share.""" 

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

105 search_opts = {} 

106 search_opts.update(req.GET) 

107 if 'share_id' not in search_opts: 

108 msg = _("The field 'share_id' has to be specified.") 

109 raise webob.exc.HTTPBadRequest(explanation=msg) 

110 share_id = search_opts.pop('share_id', None) 

111 

112 if 'metadata' in search_opts: 

113 search_opts['metadata'] = ast.literal_eval( 

114 search_opts['metadata']) 

115 if support_for_access_filters: 

116 try: 

117 self._validate_search_opts(req, search_opts) 

118 except (exception.InvalidShareAccessLevel, 

119 exception.InvalidShareAccessType) as e: 

120 raise webob.exc.HTTPBadRequest(explanation=e.msg) 

121 try: 

122 share = self.share_api.get(context, share_id) 

123 except exception.NotFound: 

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

125 raise webob.exc.HTTPBadRequest(explanation=msg) 

126 access_rules = self.share_api.access_get_all( 

127 context, share, search_opts) 

128 rule_list = [] 

129 for rule in access_rules: 

130 restricted = self._is_rule_restricted(context, rule['id']) 

131 rule['restricted'] = restricted 

132 if (('access_to' in search_opts or 'access_key' in search_opts) 132 ↛ 134line 132 didn't jump to line 134 because the condition on line 132 was never true

133 and restricted): 

134 continue 

135 rule_list.append(rule) 

136 

137 return self._view_builder.list_view(req, rule_list) 

138 

139 @wsgi.Controller.api_version('2.45', '2.81') 

140 def index(self, req): 

141 return self._index(req) 

142 

143 @wsgi.Controller.api_version('2.82') 

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

145 return self._index(req, support_for_access_filters=True) 

146 

147 @wsgi.Controller.api_version('2.88') 

148 @wsgi.Controller.authorize('update') 

149 def update(self, req, id, body): 

150 """Update access_level about the given share access rule.""" 

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

152 if not self.is_valid_body(body, 'update_access'): 

153 raise webob.exc.HTTPBadRequest() 

154 

155 access_data = body['update_access'] 

156 access_level = access_data.get('access_level', None) 

157 if not access_level: 157 ↛ 158line 157 didn't jump to line 158 because the condition on line 157 was never true

158 msg = _("Invalid input. Missing 'access_level' in " 

159 "update request.") 

160 raise webob.exc.HTTPBadRequest(explanation=msg) 

161 

162 if access_level not in constants.ACCESS_LEVELS: 162 ↛ 163line 162 didn't jump to line 163 because the condition on line 162 was never true

163 msg = _("Invalid or unsupported share access " 

164 "level: %s.") % access_level 

165 raise webob.exc.HTTPBadRequest(explanation=msg) 

166 

167 share_access = self._get_share_access(context, id) 

168 if access_level == share_access.access_level: 168 ↛ 169line 168 didn't jump to line 169 because the condition on line 168 was never true

169 return self._view_builder.view(req, share_access) 

170 

171 share = self.share_api.get(context, share_access.share_id) 

172 values = { 

173 'access_level': access_level, 

174 } 

175 access = self.share_api.update_access( 

176 context, share, share_access, values) 

177 return self._view_builder.view(req, access) 

178 

179 

180def create_resource(): 

181 return wsgi.Resource(ShareAccessesController())