Coverage for manila/api/v2/share_network_subnets.py: 95%

167 statements  

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

1# Copyright 2019 NetApp, 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 http import client as http_client 

17 

18from oslo_config import cfg 

19from oslo_db import exception as db_exception 

20from oslo_log import log 

21import webob 

22from webob import exc 

23 

24from manila.api import common as api_common 

25from manila.api.openstack import api_version_request as api_version 

26from manila.api.openstack import wsgi 

27from manila.api.v2 import metadata as metadata_controller 

28from manila.api.views import share_network_subnets as subnet_views 

29from manila.db import api as db_api 

30from manila import exception 

31from manila.i18n import _ 

32from manila.message import api as message_api 

33from manila.message import message_field 

34from manila import share 

35from manila.share import rpcapi as share_rpcapi 

36 

37LOG = log.getLogger(__name__) 

38CONF = cfg.CONF 

39 

40 

41class ShareNetworkSubnetController(wsgi.Controller, 

42 metadata_controller.MetadataController): 

43 """The Share Network Subnet API controller for the OpenStack API.""" 

44 

45 resource_name = 'share_network_subnet' 

46 _view_builder_class = subnet_views.ViewBuilder 

47 

48 def __init__(self): 

49 super(ShareNetworkSubnetController, self).__init__() 

50 self.share_rpcapi = share_rpcapi.ShareAPI() 

51 self.share_api = share.API() 

52 self.message_api = message_api.API() 

53 

54 @wsgi.Controller.api_version("2.51") 

55 @wsgi.Controller.authorize 

56 def index(self, req, share_network_id): 

57 """Returns a list of share network subnets.""" 

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

59 

60 try: 

61 share_network = db_api.share_network_get(context, share_network_id) 

62 except exception.ShareNetworkNotFound as e: 

63 raise exc.HTTPNotFound(explanation=e.msg) 

64 

65 return self._view_builder.build_share_network_subnets( 

66 req, share_network.get('share_network_subnets')) 

67 

68 def _all_share_servers_are_auto_deletable(self, share_network_subnet): 

69 return all([ss['is_auto_deletable'] for ss 

70 in share_network_subnet['share_servers']]) 

71 

72 @wsgi.Controller.api_version('2.51') 

73 @wsgi.Controller.authorize 

74 def delete(self, req, share_network_id, share_network_subnet_id): 

75 """Delete specified share network subnet.""" 

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

77 

78 try: 

79 db_api.share_network_get(context, share_network_id) 

80 except exception.ShareNetworkNotFound as e: 

81 raise exc.HTTPNotFound(explanation=e.msg) 

82 

83 try: 

84 share_network_subnet = db_api.share_network_subnet_get( 

85 context, share_network_subnet_id) 

86 except exception.ShareNetworkSubnetNotFound as e: 

87 raise exc.HTTPNotFound(explanation=e.msg) 

88 

89 for share_server in share_network_subnet['share_servers'] or []: 

90 shares = db_api.share_instance_get_all_by_share_server( 

91 context, share_server['id']) 

92 if shares: 

93 msg = _("Cannot delete share network subnet %(id)s, it has " 

94 "one or more shares.") % { 

95 'id': share_network_subnet_id} 

96 LOG.error(msg) 

97 raise exc.HTTPConflict(explanation=msg) 

98 

99 share_groups = db_api.share_group_get_all_by_share_server( 

100 context, share_server['id']) 

101 if share_groups: 101 ↛ 102line 101 didn't jump to line 102 because the condition on line 101 was never true

102 msg = _("Cannot delete share network subnet %(id)s, it has " 

103 "one or more share groups.") % { 

104 'id': share_network_subnet_id} 

105 LOG.error(msg) 

106 raise exc.HTTPConflict(explanation=msg) 

107 

108 # NOTE(silvacarlose): Do not allow the deletion of any share server 

109 # if any of them has the flag is_auto_deletable = False 

110 if not self._all_share_servers_are_auto_deletable( 

111 share_network_subnet): 

112 msg = _("The service cannot determine if there are any " 

113 "non-managed shares on the share network subnet %(id)s," 

114 "so it cannot be deleted. Please contact the cloud " 

115 "administrator to rectify.") % { 

116 'id': share_network_subnet_id} 

117 LOG.error(msg) 

118 raise exc.HTTPConflict(explanation=msg) 

119 

120 for share_server in share_network_subnet['share_servers']: 

121 self.share_rpcapi.delete_share_server(context, share_server) 

122 

123 db_api.share_network_subnet_delete(context, share_network_subnet_id) 

124 return webob.Response(status_int=http_client.ACCEPTED) 

125 

126 @wsgi.Controller.api_version("2.51") 

127 @wsgi.Controller.authorize 

128 def create(self, req, share_network_id, body): 

129 """Add a new share network subnet into the share network.""" 

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

131 if not self.is_valid_body(body, 'share-network-subnet'): 

132 msg = _("Share Network Subnet is missing from the request body.") 

133 raise exc.HTTPBadRequest(explanation=msg) 

134 data = body['share-network-subnet'] 

135 

136 if req.api_version_request >= api_version.APIVersionRequest("2.78"): 

137 api_common.check_metadata_properties(data.get('metadata')) 

138 else: 

139 data.pop('metadata', None) 

140 

141 data['share_network_id'] = share_network_id 

142 multiple_subnet_support = (req.api_version_request >= 

143 api_version.APIVersionRequest("2.70")) 

144 share_network, existing_subnets = api_common.validate_subnet_create( 

145 context, share_network_id, data, multiple_subnet_support) 

146 

147 # create subnet operation on subnets with share servers means that an 

148 # allocation update is requested. 

149 if existing_subnets and existing_subnets[0]['share_servers']: 

150 

151 # NOTE(felipe_rodrigues): all subnets have the same set of share 

152 # servers, so we can just get the servers from one of them. Not 

153 # necessarily all share servers from the specified AZ will be 

154 # updated, only the ones created with subnets in the AZ. Others 

155 # created with default AZ will only have its allocations updated 

156 # when default subnet set is updated. 

157 data['share_servers'] = existing_subnets[0]['share_servers'] 

158 try: 

159 share_network_subnet = ( 

160 self.share_api.update_share_server_network_allocations( 

161 context, share_network, data)) 

162 except exception.ServiceIsDown as e: 

163 msg = _('Could not add the share network subnet.') 

164 LOG.error(e) 

165 raise exc.HTTPInternalServerError(explanation=msg) 

166 except exception.InvalidShareNetwork as e: 

167 raise exc.HTTPBadRequest(explanation=e.msg) 

168 except db_exception.DBError as e: 

169 msg = _('Could not add the share network subnet.') 

170 LOG.error(e) 

171 raise exc.HTTPInternalServerError(explanation=msg) 

172 else: 

173 try: 

174 share_network_subnet = db_api.share_network_subnet_create( 

175 context, data) 

176 metadata_support = (req.api_version_request >= 

177 api_version.APIVersionRequest("2.89")) 

178 if metadata_support and data.get('metadata'): 178 ↛ 179line 178 didn't jump to line 179 because the condition on line 178 was never true

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

180 self.share_api.update_share_network_subnet_from_metadata( 

181 context, 

182 share_network_id, 

183 share_network_subnet['id'], 

184 data.get('metadata')) 

185 except db_exception.DBError as e: 

186 msg = _('Could not create the share network subnet.') 

187 LOG.error(e) 

188 raise exc.HTTPInternalServerError(explanation=msg) 

189 

190 share_network_subnet = db_api.share_network_subnet_get( 

191 context, share_network_subnet['id']) 

192 return self._view_builder.build_share_network_subnet( 

193 req, share_network_subnet) 

194 

195 @wsgi.Controller.api_version('2.51') 

196 @wsgi.Controller.authorize 

197 def show(self, req, share_network_id, share_network_subnet_id): 

198 """Show share network subnet.""" 

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

200 

201 try: 

202 db_api.share_network_get(context, share_network_id) 

203 except exception.ShareNetworkNotFound as e: 

204 raise exc.HTTPNotFound(explanation=e.msg) 

205 

206 try: 

207 share_network_subnet = db_api.share_network_subnet_get( 

208 context, share_network_subnet_id) 

209 except exception.ShareNetworkSubnetNotFound as e: 

210 raise exc.HTTPNotFound(explanation=e.msg) 

211 

212 return self._view_builder.build_share_network_subnet( 

213 req, share_network_subnet) 

214 

215 @wsgi.Controller.api_version("2.78") 

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

217 def index_metadata(self, req, share_network_id, resource_id): 

218 """Returns the list of metadata for a given share network subnet.""" 

219 return self._index_metadata(req, resource_id, 

220 parent_id=share_network_id) 

221 

222 @wsgi.Controller.api_version("2.78") 

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

224 def create_metadata(self, req, share_network_id, resource_id, body): 

225 """Create metadata for a given share network subnet.""" 

226 metadata = self._create_metadata(req, resource_id, body, 

227 parent_id=share_network_id) 

228 if req.api_version_request >= api_version.APIVersionRequest("2.89"): 

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

230 self.share_api.update_share_network_subnet_from_metadata( 

231 context, 

232 share_network_id, 

233 resource_id, 

234 metadata.get('metadata')) 

235 return metadata 

236 

237 @wsgi.Controller.api_version("2.78") 

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

239 def update_all_metadata(self, req, share_network_id, resource_id, body): 

240 """Update entire metadata for a given share network subnet.""" 

241 metadata = self._update_all_metadata(req, resource_id, body, 

242 parent_id=share_network_id) 

243 if req.api_version_request >= api_version.APIVersionRequest("2.89"): 

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

245 self.share_api.update_share_network_subnet_from_metadata( 

246 context, 

247 share_network_id, 

248 resource_id, 

249 metadata.get('metadata')) 

250 return metadata 

251 

252 @wsgi.Controller.api_version("2.78") 

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

254 def update_metadata_item(self, req, share_network_id, resource_id, body, 

255 key): 

256 """Update metadata item for a given share network subnet.""" 

257 metadata = self._update_metadata_item(req, resource_id, body, key, 

258 parent_id=share_network_id) 

259 if req.api_version_request >= api_version.APIVersionRequest("2.89"): 

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

261 self.share_api.update_share_network_subnet_from_metadata( 

262 context, 

263 share_network_id, 

264 resource_id, 

265 metadata.get('metadata')) 

266 return metadata 

267 

268 @wsgi.Controller.api_version("2.78") 

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

270 def show_metadata(self, req, share_network_id, resource_id, key): 

271 """Show metadata for a given share network subnet.""" 

272 return self._show_metadata(req, resource_id, key, 

273 parent_id=share_network_id) 

274 

275 @wsgi.Controller.api_version("2.78") 

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

277 def delete_metadata(self, req, share_network_id, resource_id, key): 

278 """Delete metadata for a given share network subnet.""" 

279 if req.api_version_request >= api_version.APIVersionRequest("2.89"): 

280 driver_keys = getattr( 

281 CONF, 'driver_updatable_subnet_metadata', []) 

282 if key in driver_keys: 282 ↛ 293line 282 didn't jump to line 293 because the condition on line 282 was always true

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

284 share_network = db_api.share_network_get( 

285 context, share_network_id) 

286 self.message_api.create( 

287 context, 

288 message_field.Action.UPDATE_METADATA, 

289 share_network['project_id'], 

290 resource_type=message_field.Resource.SHARE_NETWORK_SUBNET, 

291 resource_id=resource_id, 

292 detail=message_field.Detail.UPDATE_METADATA_NOT_DELETED) 

293 return self._delete_metadata(req, resource_id, key, 

294 parent_id=share_network_id) 

295 

296 

297def create_resource(): 

298 return wsgi.Resource(ShareNetworkSubnetController())