Coverage for manila/api/v2/share_networks.py: 92%

400 statements  

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

1# Copyright 2014 NetApp 

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 shares api.""" 

17 

18import copy 

19from http import client as http_client 

20 

21from oslo_db import exception as db_exception 

22from oslo_log import log 

23from oslo_utils import timeutils 

24import webob 

25from webob import exc 

26 

27from manila.api import common 

28from manila.api.openstack import api_version_request as api_version 

29from manila.api.openstack import wsgi 

30from manila.api.views import share_networks as share_networks_views 

31from manila.common import constants 

32from manila.db import api as db_api 

33from manila import exception 

34from manila.i18n import _ 

35from manila import policy 

36from manila import quota 

37from manila import share 

38from manila.share import rpcapi as share_rpcapi 

39from manila import utils 

40 

41RESOURCE_NAME = 'share_network' 

42RESOURCES_NAME = 'share_networks' 

43LOG = log.getLogger(__name__) 

44QUOTAS = quota.QUOTAS 

45 

46 

47class ShareNetworkController(wsgi.Controller, wsgi.AdminActionsMixin): 

48 """The Share Network API controller for the OpenStack API.""" 

49 

50 resource_name = 'share_network' 

51 _view_builder_class = share_networks_views.ViewBuilder 

52 

53 def __init__(self): 

54 super(ShareNetworkController, self).__init__() 

55 self.share_rpcapi = share_rpcapi.ShareAPI() 

56 self.share_api = share.API() 

57 

58 valid_statuses = { 

59 'status': set(constants.SHARE_NETWORK_STATUSES) 

60 } 

61 

62 def _get(self, *args, **kwargs): 

63 return db_api.share_network_get(*args, **kwargs) 

64 

65 def show(self, req, id): 

66 """Return data about the requested network info.""" 

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

68 policy.check_policy(context, RESOURCE_NAME, 'show') 

69 

70 try: 

71 share_network = db_api.share_network_get(context, id) 

72 except exception.ShareNetworkNotFound as e: 

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

74 

75 return self._view_builder.build_share_network(req, share_network) 

76 

77 def _all_share_servers_are_auto_deletable(self, share_network): 

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

79 in share_network['share_servers']]) 

80 

81 def _share_network_contains_subnets(self, share_network): 

82 return len(share_network['share_network_subnets']) > 1 

83 

84 def _update(self, *args, **kwargs): 

85 db_api.share_network_update(*args, **kwargs) 

86 

87 def delete(self, req, id): 

88 """Delete specified share network.""" 

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

90 policy.check_policy(context, RESOURCE_NAME, 'delete') 

91 

92 try: 

93 share_network = db_api.share_network_get(context, id) 

94 except exception.ShareNetworkNotFound as e: 

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

96 

97 share_instances = db_api.share_instance_get_all_by_share_network( 

98 context, id) 

99 if share_instances: 

100 msg = _("Can not delete share network %(id)s, it has " 

101 "%(len)s share(s).") % {'id': id, 

102 'len': len(share_instances)} 

103 LOG.error(msg) 

104 raise exc.HTTPConflict(explanation=msg) 

105 

106 # NOTE(ameade): Do not allow deletion of share network used by share 

107 # group 

108 sg_count = db_api.count_share_groups_in_share_network(context, id) 

109 if sg_count: 

110 msg = _("Can not delete share network %(id)s, it has %(len)s " 

111 "share group(s).") % {'id': id, 'len': sg_count} 

112 LOG.error(msg) 

113 raise exc.HTTPConflict(explanation=msg) 

114 

115 # NOTE(silvacarlose): Do not allow the deletion of share networks 

116 # if it still contains two or more subnets 

117 if self._share_network_contains_subnets(share_network): 

118 msg = _("The share network %(id)s has more than one subnet " 

119 "attached. Please remove the subnets untill you have one " 

120 "or no subnets remaining.") % {'id': id} 

121 LOG.error(msg) 

122 raise exc.HTTPConflict(explanation=msg) 

123 

124 for subnet in share_network['share_network_subnets']: 

125 if not self._all_share_servers_are_auto_deletable(subnet): 

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

127 "non-managed shares on the share network subnet " 

128 "%(id)s, so it cannot be deleted. Please contact the " 

129 "cloud administrator to rectify.") % { 

130 'id': subnet['id']} 

131 LOG.error(msg) 

132 raise exc.HTTPConflict(explanation=msg) 

133 

134 for subnet in share_network['share_network_subnets']: 

135 for share_server in subnet['share_servers']: 

136 self.share_rpcapi.delete_share_server(context, share_server) 

137 

138 for security_service in share_network['security_services']: 

139 try: 

140 db_api.share_network_remove_security_service( 

141 context, 

142 id, 

143 security_service['id']) 

144 except Exception: 

145 msg = ("Failed to delete security association of network " 

146 "{net_id} and security service " 

147 "{sec_id}".format(net_id=id, 

148 sec_id=security_service['id'])) 

149 LOG.exception(msg) 

150 

151 db_api.share_network_delete(context, id) 

152 

153 try: 

154 reservations = QUOTAS.reserve( 

155 context, project_id=share_network['project_id'], 

156 share_networks=-1, user_id=share_network['user_id']) 

157 except Exception: 

158 LOG.exception("Failed to update usages deleting " 

159 "share-network.") 

160 else: 

161 QUOTAS.commit(context, reservations, 

162 project_id=share_network['project_id'], 

163 user_id=share_network['user_id']) 

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

165 

166 def _subnet_has_search_opt(self, key, value, network, exact_value=False): 

167 for subnet in network.get('share_network_subnets') or []: 

168 if subnet.get(key) == value or ( 168 ↛ 167line 168 didn't jump to line 167 because the condition on line 168 was always true

169 not exact_value and 

170 value in subnet.get(key.rstrip('~')) 

171 if key.endswith('~') and 

172 subnet.get(key.rstrip('~')) else ()): 

173 return True 

174 return False 

175 

176 def _get_share_networks(self, req, is_detail=True): 

177 """Returns a list of share networks.""" 

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

179 search_opts = {} 

180 search_opts.update(req.GET) 

181 filters = {} 

182 

183 # if not context.is_admin, will ignore project_id and all_tenants here, 

184 # in database will auto add context.project_id to search_opts. 

185 if context.is_admin: 

186 if 'project_id' in search_opts: 

187 # if specified project_id, will not use all_tenants 

188 filters['project_id'] = search_opts['project_id'] 

189 elif not utils.is_all_tenants(search_opts): 

190 # if not specified project_id and all_tenants, will get 

191 # share networks in admin project. 

192 filters['project_id'] = context.project_id 

193 

194 date_parsing_error_msg = '''%s is not in yyyy-mm-dd format.''' 

195 for time_comparison_filter in ['created_since', 'created_before']: 

196 if time_comparison_filter in search_opts: 

197 time_str = search_opts.get(time_comparison_filter) 

198 try: 

199 parsed_time = timeutils.parse_strtime(time_str, 

200 fmt="%Y-%m-%d") 

201 except ValueError: 

202 msg = date_parsing_error_msg % time_str 

203 raise exc.HTTPBadRequest(explanation=msg) 

204 

205 filters[time_comparison_filter] = parsed_time 

206 

207 if 'security_service_id' in search_opts: 

208 filters['security_service_id'] = search_opts.get( 

209 'security_service_id') 

210 

211 networks = db_api.share_network_get_all_by_filter(context, 

212 filters=filters) 

213 

214 opts_to_remove = [ 

215 'all_tenants', 

216 'created_since', 

217 'created_before', 

218 'limit', 

219 'offset', 

220 'security_service_id', 

221 'project_id' 

222 ] 

223 for opt in opts_to_remove: 

224 search_opts.pop(opt, None) 

225 if search_opts: 

226 for key, value in search_opts.items(): 

227 if key in ['ip_version', 'segmentation_id']: 227 ↛ 228line 227 didn't jump to line 228 because the condition on line 227 was never true

228 value = int(value) 

229 if (req.api_version_request >= 

230 api_version.APIVersionRequest("2.36")): 

231 networks = [ 

232 network for network in networks 

233 if network.get(key) == value or 

234 self._subnet_has_search_opt(key, value, network) or 

235 (value in network.get(key.rstrip('~')) 

236 if key.endswith('~') and 

237 network.get(key.rstrip('~')) else ())] 

238 else: 

239 networks = [ 

240 network for network in networks 

241 if network.get(key) == value or 

242 self._subnet_has_search_opt(key, value, network, 

243 exact_value=True)] 

244 

245 limited_list = common.limited(networks, req) 

246 return self._view_builder.build_share_networks( 

247 req, limited_list, is_detail) 

248 

249 def _share_network_subnets_contain_share_servers(self, share_network): 

250 for subnet in share_network['share_network_subnets']: 

251 if subnet['share_servers'] and len(subnet['share_servers']) > 0: 

252 return True 

253 return False 

254 

255 def index(self, req): 

256 """Returns a summary list of share networks.""" 

257 policy.check_policy(req.environ['manila.context'], RESOURCE_NAME, 

258 'index') 

259 return self._get_share_networks(req, is_detail=False) 

260 

261 def detail(self, req): 

262 """Returns a detailed list of share networks.""" 

263 policy.check_policy(req.environ['manila.context'], RESOURCE_NAME, 

264 'detail') 

265 return self._get_share_networks(req) 

266 

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

268 """Update specified share network.""" 

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

270 policy.check_policy(context, RESOURCE_NAME, 'update') 

271 

272 if not body or RESOURCE_NAME not in body: 

273 raise exc.HTTPUnprocessableEntity() 

274 

275 try: 

276 share_network = db_api.share_network_get(context, id) 

277 except exception.ShareNetworkNotFound as e: 

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

279 

280 update_values = body[RESOURCE_NAME] 

281 

282 if 'nova_net_id' in update_values: 

283 msg = _("nova networking is not supported starting in Ocata.") 

284 raise exc.HTTPBadRequest(explanation=msg) 

285 

286 if self._share_network_subnets_contain_share_servers(share_network): 

287 for value in update_values: 

288 if value not in ['name', 'description']: 

289 msg = (_("Cannot update share network %s. It is used by " 

290 "share servers. Only 'name' and 'description' " 

291 "fields are available for update") % 

292 share_network['id']) 

293 raise exc.HTTPForbidden(explanation=msg) 

294 try: 

295 if ('neutron_net_id' in update_values or 

296 'neutron_subnet_id' in update_values): 

297 subnets = db_api.share_network_subnet_get_default_subnets( 

298 context, id) 

299 if not subnets: 

300 msg = _("The share network %(id)s does not have a " 

301 "'default' subnet that serves all availability " 

302 "zones, so subnet details " 

303 "('neutron_net_id', 'neutron_subnet_id') cannot " 

304 "be updated.") % {'id': id} 

305 raise exc.HTTPBadRequest(explanation=msg) 

306 if len(subnets) > 1: 

307 msg = _("The share network %(id)s does not have an unique " 

308 "'default' subnet that serves all availability " 

309 "zones, so subnet details " 

310 "('neutron_net_id', 'neutron_subnet_id') cannot " 

311 "be updated.") % {'id': id} 

312 raise exc.HTTPBadRequest(explanation=msg) 

313 subnet = subnets[0] 

314 

315 # NOTE(silvacarlose): If the default share network subnet have 

316 # the fields neutron_net_id and neutron_subnet_id set as None, 

317 # we need to make sure that in the update request the user is 

318 # passing both parameter since a share network subnet must 

319 # have both fields filled or empty. 

320 subnet_neutron_net_and_subnet_id_are_empty = ( 

321 subnet['neutron_net_id'] is None 

322 and subnet['neutron_subnet_id'] is None) 

323 update_values_without_neutron_net_or_subnet = ( 

324 update_values.get('neutron_net_id') is None or 

325 update_values.get('neutron_subnet_id') is None) 

326 if (subnet_neutron_net_and_subnet_id_are_empty 

327 and update_values_without_neutron_net_or_subnet): 

328 msg = _( 

329 "To update the share network %(id)s you need to " 

330 "specify both 'neutron_net_id' and " 

331 "'neutron_subnet_id'.") % {'id': id} 

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

333 db_api.share_network_subnet_update(context, 

334 subnet['id'], 

335 update_values) 

336 share_network = db_api.share_network_update(context, 

337 id, 

338 update_values) 

339 except db_exception.DBError: 

340 msg = "Could not save supplied data due to database error" 

341 raise exc.HTTPBadRequest(explanation=msg) 

342 

343 return self._view_builder.build_share_network(req, share_network) 

344 

345 def create(self, req, body): 

346 """Creates a new share network.""" 

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

348 policy.check_policy(context, RESOURCE_NAME, 'create') 

349 

350 if not body or RESOURCE_NAME not in body: 

351 raise exc.HTTPUnprocessableEntity() 

352 

353 share_network_values = body[RESOURCE_NAME] 

354 share_network_subnet_values = copy.deepcopy(share_network_values) 

355 share_network_values['project_id'] = context.project_id 

356 share_network_values['user_id'] = context.user_id 

357 

358 if 'nova_net_id' in share_network_values: 

359 msg = _("nova networking is not supported starting in Ocata.") 

360 raise exc.HTTPBadRequest(explanation=msg) 

361 

362 share_network_values.pop('availability_zone', None) 

363 share_network_values.pop('neutron_net_id', None) 

364 share_network_values.pop('neutron_subnet_id', None) 

365 

366 if req.api_version_request >= api_version.APIVersionRequest("2.51"): 

367 if 'availability_zone' in share_network_subnet_values: 367 ↛ 381line 367 didn't jump to line 381 because the condition on line 367 was always true

368 try: 

369 az = db_api.availability_zone_get( 

370 context, 

371 share_network_subnet_values['availability_zone']) 

372 share_network_subnet_values['availability_zone_id'] = ( 

373 az['id']) 

374 share_network_subnet_values.pop('availability_zone') 

375 except exception.AvailabilityZoneNotFound: 

376 msg = (_("The provided availability zone %s does not " 

377 "exist.") 

378 % share_network_subnet_values['availability_zone']) 

379 raise exc.HTTPBadRequest(explanation=msg) 

380 

381 common.check_net_id_and_subnet_id(share_network_subnet_values) 

382 

383 try: 

384 reservations = QUOTAS.reserve(context, share_networks=1) 

385 except exception.OverQuota as e: 

386 overs = e.kwargs['overs'] 

387 usages = e.kwargs['usages'] 

388 quotas = e.kwargs['quotas'] 

389 

390 def _consumed(name): 

391 return (usages[name]['reserved'] + usages[name]['in_use']) 

392 

393 if 'share_networks' in overs: 

394 LOG.warning("Quota exceeded for %(s_pid)s, " 

395 "tried to create " 

396 "share-network (%(d_consumed)d of %(d_quota)d " 

397 "already consumed).", { 

398 's_pid': context.project_id, 

399 'd_consumed': _consumed('share_networks'), 

400 'd_quota': quotas['share_networks']}) 

401 raise exception.ShareNetworksLimitExceeded( 

402 allowed=quotas['share_networks']) 

403 else: 

404 # Tries to create the new share network 

405 try: 

406 share_network = db_api.share_network_create( 

407 context, share_network_values) 

408 except db_exception.DBError as e: 

409 QUOTAS.rollback(context, reservations) 

410 LOG.exception(e) 

411 msg = "Could not create share network." 

412 raise exc.HTTPInternalServerError(explanation=msg) 

413 

414 share_network_subnet_values['share_network_id'] = ( 

415 share_network['id']) 

416 share_network_subnet_values.pop('id', None) 

417 

418 # Try to create the share network subnet. If it fails, the service 

419 # must rollback the share network creation. 

420 try: 

421 db_api.share_network_subnet_create( 

422 context, share_network_subnet_values) 

423 except db_exception.DBError: 

424 db_api.share_network_delete(context, share_network['id']) 

425 QUOTAS.rollback(context, reservations) 

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

427 raise exc.HTTPInternalServerError(explanation=msg) 

428 

429 QUOTAS.commit(context, reservations) 

430 share_network = db_api.share_network_get(context, 

431 share_network['id']) 

432 return self._view_builder.build_share_network(req, share_network) 

433 

434 @wsgi.action("add_security_service") 

435 def add_security_service(self, req, id, body): 

436 """Associate share network with a given security service.""" 

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

438 share_network = db_api.share_network_get(context, id) 

439 policy.check_policy(context, RESOURCE_NAME, 'add_security_service', 

440 target_obj=share_network) 

441 try: 

442 data = body['add_security_service'] 

443 

444 security_service = db_api.security_service_get( 

445 context, data['security_service_id']) 

446 except KeyError: 

447 msg = "Malformed request body" 

448 raise exc.HTTPBadRequest(explanation=msg) 

449 

450 contain_share_servers = ( 

451 self._share_network_subnets_contain_share_servers(share_network)) 

452 

453 support_adding_to_in_use_networks = ( 

454 req.api_version_request >= api_version.APIVersionRequest("2.63")) 

455 

456 if contain_share_servers: 

457 if not support_adding_to_in_use_networks: 

458 msg = _("Cannot add security services. Share network is used.") 

459 raise exc.HTTPForbidden(explanation=msg) 

460 try: 

461 self.share_api.update_share_network_security_service( 

462 context, share_network, security_service) 

463 except exception.ServiceIsDown as e: 

464 raise exc.HTTPConflict(explanation=e.msg) 

465 except exception.InvalidShareNetwork as e: 

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

467 except exception.InvalidSecurityService as e: 

468 raise exc.HTTPConflict(explanation=e.msg) 

469 

470 try: 

471 share_network = db_api.share_network_add_security_service( 

472 context, 

473 id, 

474 data['security_service_id']) 

475 except exception.NotFound as e: 

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

477 except exception.ShareNetworkSecurityServiceAssociationError as e: 

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

479 

480 return self._view_builder.build_share_network(req, share_network) 

481 

482 @wsgi.action('remove_security_service') 

483 def remove_security_service(self, req, id, body): 

484 """Dissociate share network from a given security service.""" 

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

486 share_network = db_api.share_network_get(context, id) 

487 policy.check_policy(context, RESOURCE_NAME, 'remove_security_service', 

488 target_obj=share_network) 

489 data = body['remove_security_service'] 

490 

491 if self._share_network_subnets_contain_share_servers(share_network): 

492 msg = _("Cannot remove security services. Share network is used.") 

493 raise exc.HTTPForbidden(explanation=msg) 

494 try: 

495 share_network = db_api.share_network_remove_security_service( 

496 context, 

497 id, 

498 data['security_service_id']) 

499 except KeyError: 

500 msg = "Malformed request body" 

501 raise exc.HTTPBadRequest(explanation=msg) 

502 except exception.NotFound as e: 

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

504 except exception.ShareNetworkSecurityServiceDissociationError as e: 

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

506 

507 return self._view_builder.build_share_network(req, share_network) 

508 

509 @wsgi.Controller.api_version('2.63') 

510 @wsgi.action('update_security_service') 

511 @wsgi.response(202) 

512 def update_security_service(self, req, id, body): 

513 """Update security service parameters from a given share network.""" 

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

515 share_network = db_api.share_network_get(context, id) 

516 policy.check_policy(context, RESOURCE_NAME, 'update_security_service', 

517 target_obj=share_network) 

518 try: 

519 data = body['update_security_service'] 

520 

521 current_security_service = db_api.security_service_get( 

522 context, data['current_service_id'] 

523 ) 

524 new_security_service = db_api.security_service_get( 

525 context, data['new_service_id'] 

526 ) 

527 except KeyError: 

528 msg = "Malformed request body." 

529 raise exc.HTTPBadRequest(explanation=msg) 

530 except exception.NotFound: 

531 msg = ("The current security service or the new security service " 

532 "doesn't exist.") 

533 raise exc.HTTPBadRequest(explanation=msg) 

534 

535 try: 

536 self.share_api.update_share_network_security_service( 

537 context, share_network, new_security_service, 

538 current_security_service=current_security_service) 

539 except exception.ServiceIsDown as e: 

540 raise exc.HTTPConflict(explanation=e.msg) 

541 except exception.InvalidShareNetwork as e: 

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

543 except exception.InvalidSecurityService as e: 

544 raise exc.HTTPConflict(explanation=e.msg) 

545 

546 try: 

547 share_network = db_api.share_network_update_security_service( 

548 context, 

549 id, 

550 data['current_service_id'], 

551 data['new_service_id']) 

552 except exception.NotFound as e: 

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

554 except (exception.ShareNetworkSecurityServiceDissociationError, 

555 exception.ShareNetworkSecurityServiceAssociationError) as e: 

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

557 

558 return self._view_builder.build_share_network(req, share_network) 

559 

560 @wsgi.Controller.api_version('2.63') 

561 @wsgi.action('update_security_service_check') 

562 @wsgi.response(202) 

563 def check_update_security_service(self, req, id, body): 

564 """Check the feasibility of updating a security service.""" 

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

566 share_network = db_api.share_network_get(context, id) 

567 policy.check_policy(context, RESOURCE_NAME, 

568 'update_security_service_check', 

569 target_obj=share_network) 

570 try: 

571 data = body['update_security_service_check'] 

572 

573 current_security_service = db_api.security_service_get( 

574 context, data['current_service_id'] 

575 ) 

576 new_security_service = db_api.security_service_get( 

577 context, data['new_service_id'] 

578 ) 

579 except KeyError: 

580 msg = "Malformed request body." 

581 raise exc.HTTPBadRequest(explanation=msg) 

582 except exception.NotFound: 

583 msg = ("The current security service or the new security service " 

584 "doesn't exist.") 

585 raise exc.HTTPBadRequest(explanation=msg) 

586 

587 reset_check = utils.get_bool_from_api_params('reset_operation', data) 

588 

589 try: 

590 result = ( 

591 self.share_api.check_share_network_security_service_update( 

592 context, share_network, new_security_service, 

593 current_security_service=current_security_service, 

594 reset_operation=reset_check)) 

595 except exception.ServiceIsDown as e: 

596 raise exc.HTTPConflict(explanation=e.msg) 

597 except exception.InvalidShareNetwork as e: 

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

599 except exception.InvalidSecurityService as e: 

600 raise exc.HTTPConflict(explanation=e.msg) 

601 

602 return self._view_builder.build_security_service_update_check( 

603 req, data, result) 

604 

605 @wsgi.Controller.api_version('2.63') 

606 @wsgi.action("add_security_service_check") 

607 @wsgi.response(202) 

608 def check_add_security_service(self, req, id, body): 

609 """Check the feasibility of associate a new security service.""" 

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

611 share_network = db_api.share_network_get(context, id) 

612 policy.check_policy(context, RESOURCE_NAME, 

613 'add_security_service_check', 

614 target_obj=share_network) 

615 data = body['add_security_service_check'] 

616 try: 

617 security_service = db_api.security_service_get( 

618 context, data['security_service_id'], project_only=True) 

619 except KeyError: 

620 msg = "Malformed request body." 

621 raise exc.HTTPBadRequest(explanation=msg) 

622 except exception.NotFound: 

623 msg = ("Security service %s doesn't exist." 

624 ) % data['security_service_id'] 

625 raise exc.HTTPBadRequest(explanation=msg) 

626 

627 reset_check = utils.get_bool_from_api_params('reset_operation', data) 

628 

629 try: 

630 result = ( 

631 self.share_api.check_share_network_security_service_update( 

632 context, share_network, security_service, 

633 reset_operation=reset_check)) 

634 except exception.ServiceIsDown as e: 

635 raise exc.HTTPConflict(explanation=e.msg) 

636 except exception.InvalidShareNetwork as e: 

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

638 except exception.InvalidSecurityService as e: 

639 raise exc.HTTPConflict(explanation=e.msg) 

640 

641 return self._view_builder.build_security_service_update_check( 

642 req, data, result) 

643 

644 @wsgi.Controller.api_version('2.70') 

645 @wsgi.action('share_network_subnet_create_check') 

646 @wsgi.response(202) 

647 def share_network_subnet_create_check(self, req, id, body): 

648 """Check the feasibility of creating a share network subnet.""" 

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

650 if not self.is_valid_body(body, 'share_network_subnet_create_check'): 650 ↛ 651line 650 didn't jump to line 651 because the condition on line 650 was never true

651 msg = _("Share Network Subnet Create Check is missing from " 

652 "the request body.") 

653 raise exc.HTTPBadRequest(explanation=msg) 

654 data = body['share_network_subnet_create_check'] 

655 share_network, existing_subnets = common.validate_subnet_create( 

656 context, id, data, True) 

657 

658 reset_check = utils.get_bool_from_api_params('reset_operation', data) 

659 

660 # create subnet operation alongside subnets with share servers means 

661 # that an allocation update is requested. 

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

663 

664 # NOTE(felipe_rodrigues): all subnets within the same az have the 

665 # same set of share servers, so we can just get the servers from 

666 # one of them. Not necessarily all share servers from the specified 

667 # AZ will be updated, only the ones created with subnets in the AZ. 

668 # Others created with default AZ will only have its allocations 

669 # updated when default subnet set is updated. 

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

671 try: 

672 check_result = ( 

673 self.share_api. 

674 check_update_share_server_network_allocations( 

675 context, share_network, data, reset_check)) 

676 except exception.ServiceIsDown as e: 

677 msg = _("A share network subnet update check cannot be " 

678 "performed at this time.") 

679 LOG.error(e) 

680 raise exc.HTTPInternalServerError(explanation=msg) 

681 except exception.InvalidShareNetwork as e: 

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

683 else: 

684 check_result = { 

685 'compatible': True, 

686 'hosts_check_result': {} 

687 } 

688 

689 return self._view_builder.build_share_network_subnet_create_check( 

690 req, check_result) 

691 

692 @wsgi.Controller.api_version('2.63') 

693 @wsgi.action('reset_status') 

694 def reset_status(self, req, id, body): 

695 return self._reset_status(req, id, body) 

696 

697 

698def create_resource(): 

699 return wsgi.Resource(ShareNetworkController())