Coverage for manila/share/access.py: 92%

219 statements  

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

1# Copyright (c) 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 

16import copy 

17import ipaddress 

18 

19from oslo_log import log 

20 

21from manila.common import constants 

22from manila.i18n import _ 

23from manila import utils 

24 

25LOG = log.getLogger(__name__) 

26 

27 

28def locked_access_rules_operation(operation): 

29 """Lock decorator for access rules operations. 

30 

31 Takes a named lock prior to executing the operation. The lock is 

32 named with the ID of the share instance to which the access rule belongs. 

33 

34 Intended use: 

35 If an database operation to retrieve or update access rules uses this 

36 decorator, it will block actions on all access rules of the share 

37 instance until the named lock is free. This is used to avoid race 

38 conditions while performing access rules updates on a given share instance. 

39 """ 

40 

41 def wrapped(*args, **kwargs): 

42 instance_id = kwargs.get('share_instance_id') 

43 

44 @utils.synchronized( 

45 "locked_access_rules_operation_by_share_instance_%s" % instance_id, 

46 external=True) 

47 def locked_operation(*_args, **_kwargs): 

48 return operation(*_args, **_kwargs) 

49 

50 return locked_operation(*args, **kwargs) 

51 

52 return wrapped 

53 

54 

55class ShareInstanceAccessDatabaseMixin(object): 

56 

57 @locked_access_rules_operation 

58 def get_and_update_share_instance_access_rules_status( 

59 self, context, status=None, conditionally_change=None, 

60 share_instance_id=None): 

61 """Get and update the access_rules_status of a share instance. 

62 

63 :param status: Set this parameter only if you want to 

64 omit the conditionally_change parameter; i.e, if you want to 

65 force a state change on the share instance regardless of the prior 

66 state. 

67 :param conditionally_change: Set this parameter to a dictionary of rule 

68 state transitions to be made. The key is the expected 

69 access_rules_status and the value is the state to transition the 

70 access_rules_status to. If the state is not as expected, 

71 no transition is performed. Default is {}, which means no state 

72 transitions will be made. 

73 :returns share_instance: if an update was made. 

74 """ 

75 if status is not None: 

76 updates = {'access_rules_status': status} 

77 elif conditionally_change: 77 ↛ 89line 77 didn't jump to line 89 because the condition on line 77 was always true

78 share_instance = self.db.share_instance_get( 

79 context, share_instance_id) 

80 access_rules_status = share_instance['access_rules_status'] 

81 try: 

82 updates = { 

83 'access_rules_status': 

84 conditionally_change[access_rules_status], 

85 } 

86 except KeyError: 

87 updates = {} 

88 else: 

89 updates = {} 

90 if updates: 

91 share_instance = self.db.share_instance_update( 

92 context, share_instance_id, updates, with_share_data=True) 

93 return share_instance 

94 

95 def update_share_instances_access_rules_status( 

96 self, context, status, share_instance_ids): 

97 """Update the access_rules_status of all share instances. 

98 

99 .. note:: 

100 Before making this call, make sure that all share instances have 

101 their status set to a value that will block new operations to 

102 happen during this update. 

103 

104 :param status: Force a state change on all share instances regardless 

105 of the prior state. 

106 :param share_instance_ids: List of share instance ids to have their 

107 access rules status updated. 

108 """ 

109 updates = {'access_rules_status': status} 

110 

111 self.db.share_instance_status_update( 

112 context, share_instance_ids, updates) 

113 

114 @locked_access_rules_operation 

115 def get_and_update_share_instance_access_rules(self, context, 

116 filters=None, updates=None, 

117 conditionally_change=None, 

118 share_instance_id=None): 

119 """Get and conditionally update all access rules of a share instance. 

120 

121 :param updates: Set this parameter to a dictionary of key:value 

122 pairs corresponding to the keys in the ShareInstanceAccessMapping 

123 model. Include 'state' in this dictionary only if you want to 

124 omit the conditionally_change parameter; i.e, if you want to 

125 force a state change on all filtered rules regardless of the prior 

126 state. This parameter is always honored, regardless of whether 

127 conditionally_change allows for a state transition as desired. 

128 

129 Example:: 

130 

131 { 

132 'access_key': 'bob007680048318f4239dfc1c192d5', 

133 'access_level': 'ro', 

134 } 

135 

136 :param conditionally_change: Set this parameter to a dictionary of rule 

137 state transitions to be made. The key is the expected state of 

138 the access rule the value is the state to transition the 

139 access rule to. If the state is not as expected, no transition is 

140 performed. Default is {}, which means no state transitions 

141 will be made. 

142 

143 Example:: 

144 

145 { 

146 'queued_to_apply': 'applying', 

147 'queued_to_deny': 'denying', 

148 } 

149 

150 """ 

151 instance_rules = self.db.share_access_get_all_for_instance( 

152 context, share_instance_id, filters=filters) 

153 

154 if instance_rules and (updates or conditionally_change): 

155 if not updates: 

156 updates = {} 

157 if not conditionally_change: 

158 conditionally_change = {} 

159 for rule in instance_rules: 

160 mapping_state = rule['state'] 

161 rule_updates = copy.deepcopy(updates) 

162 try: 

163 rule_updates['state'] = conditionally_change[mapping_state] 

164 except KeyError: 

165 pass 

166 if rule_updates: 

167 self.db.share_instance_access_update( 

168 context, rule['access_id'], share_instance_id, 

169 rule_updates) 

170 

171 # Refresh the rules after the updates 

172 rules_to_get = { 

173 'access_id': tuple([i['access_id'] for i in instance_rules]), 

174 } 

175 instance_rules = self.db.share_access_get_all_for_instance( 

176 context, share_instance_id, filters=rules_to_get) 

177 

178 return instance_rules 

179 

180 def get_share_instance_access_rules(self, context, filters=None, 

181 share_instance_id=None): 

182 return self.get_and_update_share_instance_access_rules( 

183 context, filters, None, None, share_instance_id) 

184 

185 @locked_access_rules_operation 

186 def get_and_update_share_instance_access_rule(self, context, rule_id, 

187 updates=None, 

188 share_instance_id=None, 

189 conditionally_change=None): 

190 """Get and conditionally update a given share instance access rule. 

191 

192 :param updates: Set this parameter to a dictionary of key:value 

193 pairs corresponding to the keys in the ShareInstanceAccessMapping 

194 model. Include 'state' in this dictionary only if you want to 

195 omit the conditionally_change parameter; i.e, if you want to 

196 force a state change regardless of the prior state. 

197 :param conditionally_change: Set this parameter to a dictionary of rule 

198 state transitions to be made. The key is the expected state of 

199 the access rule the value is the state to transition the 

200 access rule to. If the state is not as expected, no transition is 

201 performed. Default is {}, which means no state transitions 

202 will be made. 

203 

204 Example:: 

205 

206 { 

207 'queued_to_apply': 'applying', 

208 'queued_to_deny': 'denying', 

209 } 

210 """ 

211 instance_rule_mapping = self.db.share_instance_access_get( 

212 context, rule_id, share_instance_id) 

213 

214 if not updates: 

215 updates = {} 

216 if conditionally_change: 

217 mapping_state = instance_rule_mapping['state'] 

218 try: 

219 updated_state = conditionally_change[mapping_state] 

220 updates.update({'state': updated_state}) 

221 except KeyError: 

222 msg = ("The state of the access rule %(rule_id)s (allowing " 

223 "access to share instance %(si)s) was not updated " 

224 "because its state was modified by another operation.") 

225 msg_payload = { 

226 'si': share_instance_id, 

227 'rule_id': rule_id, 

228 } 

229 LOG.debug(msg, msg_payload) 

230 if updates: 

231 self.db.share_instance_access_update( 

232 context, rule_id, share_instance_id, updates) 

233 

234 # Refresh the rule after update 

235 instance_rule_mapping = self.db.share_instance_access_get( 

236 context, rule_id, share_instance_id) 

237 

238 return instance_rule_mapping 

239 

240 @locked_access_rules_operation 

241 def delete_share_instance_access_rules(self, context, access_rules, 

242 share_instance_id=None): 

243 for rule in access_rules: 

244 self.db.share_instance_access_delete(context, rule['id']) 

245 

246 

247class ShareInstanceAccess(ShareInstanceAccessDatabaseMixin): 

248 

249 def __init__(self, db, driver): 

250 self.db = db 

251 self.driver = driver 

252 

253 def update_access_rules(self, context, share_instance_id, 

254 delete_all_rules=False, share_server=None): 

255 """Update access rules for a given share instance. 

256 

257 :param context: request context 

258 :param share_instance_id: ID of the share instance 

259 :param delete_all_rules: set this parameter to True if all 

260 existing access rules must be denied for a given share instance 

261 :param share_server: Share server model or None 

262 """ 

263 share_instance = self.db.share_instance_get( 

264 context, share_instance_id, with_share_data=True) 

265 msg_payload = { 

266 'si': share_instance_id, 

267 'shr': share_instance['share_id'], 

268 } 

269 

270 if delete_all_rules: 

271 updates = { 

272 'state': constants.ACCESS_STATE_QUEUED_TO_DENY, 

273 } 

274 self.get_and_update_share_instance_access_rules( 

275 context, updates=updates, share_instance_id=share_instance_id) 

276 

277 # Is there a sync in progress? If yes, ignore the incoming request. 

278 rule_filter = { 

279 'state': (constants.ACCESS_STATE_APPLYING, 

280 constants.ACCESS_STATE_DENYING, 

281 constants.ACCESS_STATE_UPDATING), 

282 } 

283 syncing_rules = self.get_and_update_share_instance_access_rules( 

284 context, filters=rule_filter, share_instance_id=share_instance_id) 

285 

286 if syncing_rules: 

287 msg = ("Access rules are being synced for share instance " 

288 "%(si)s belonging to share %(shr)s, any rule changes will " 

289 "be applied shortly.") 

290 LOG.debug(msg, msg_payload) 

291 else: 

292 rules_to_apply_or_update_or_deny = ( 

293 self._update_and_get_unsynced_access_rules_from_db( 

294 context, share_instance_id) 

295 ) 

296 if rules_to_apply_or_update_or_deny: 

297 msg = ("Updating access rules for share instance %(si)s " 

298 "belonging to share %(shr)s.") 

299 LOG.debug(msg, msg_payload) 

300 self._update_access_rules(context, share_instance_id, 

301 share_server=share_server) 

302 else: 

303 msg = ("All access rules have been synced for share instance " 

304 "%(si)s belonging to share %(shr)s.") 

305 LOG.debug(msg, msg_payload) 

306 

307 def _update_access_rules(self, context, share_instance_id, 

308 share_server=None): 

309 # Refresh the share instance model 

310 share_instance = self.db.share_instance_get( 

311 context, share_instance_id, with_share_data=True) 

312 

313 conditionally_change = { 

314 constants.STATUS_ACTIVE: constants.SHARE_INSTANCE_RULES_SYNCING, 

315 } 

316 share_instance = ( 

317 self.get_and_update_share_instance_access_rules_status( 

318 context, conditionally_change=conditionally_change, 

319 share_instance_id=share_instance_id) or share_instance 

320 ) 

321 

322 rules_to_be_removed_from_db = [] 

323 # Populate rules to send to the driver 

324 (access_rules_on_share, add_rules, delete_rules, update_rules) = ( 

325 self._get_rules_to_send_to_driver(context, share_instance) 

326 ) 

327 

328 if share_instance['cast_rules_to_readonly']: 

329 # Ensure read/only semantics for a migrating instances 

330 access_rules_on_share = self._set_rules_to_readonly( 

331 access_rules_on_share, share_instance) 

332 add_rules = [] 

333 rules_to_be_removed_from_db = delete_rules 

334 delete_rules = [] 

335 update_rules = [] 

336 

337 try: 

338 share_instance = share_instance.to_dict() 

339 metadata = self.db.share_metadata_get( 

340 context, share_instance['share_id']) 

341 if metadata: 341 ↛ 342line 341 didn't jump to line 342 because the condition on line 341 was never true

342 share_instance.update({'metadata': metadata}) 

343 

344 driver_rule_updates = self._update_rules_through_share_driver( 

345 context, share_instance, access_rules_on_share, 

346 add_rules, delete_rules, update_rules, 

347 rules_to_be_removed_from_db, 

348 share_server) 

349 

350 self.process_driver_rule_updates( 

351 context, driver_rule_updates, share_instance_id) 

352 

353 # Update access rules that are still in 'applying/updating' state 

354 conditionally_change = { 

355 constants.ACCESS_STATE_APPLYING: constants.ACCESS_STATE_ACTIVE, 

356 constants.ACCESS_STATE_UPDATING: constants.ACCESS_STATE_ACTIVE, 

357 } 

358 self.get_and_update_share_instance_access_rules( 

359 context, share_instance_id=share_instance_id, 

360 conditionally_change=conditionally_change) 

361 

362 except Exception: 

363 conditionally_change_rule_state = { 

364 constants.ACCESS_STATE_APPLYING: constants.ACCESS_STATE_ERROR, 

365 constants.ACCESS_STATE_DENYING: constants.ACCESS_STATE_ERROR, 

366 constants.ACCESS_STATE_UPDATING: constants.ACCESS_STATE_ERROR, 

367 } 

368 self.get_and_update_share_instance_access_rules( 

369 context, share_instance_id=share_instance_id, 

370 conditionally_change=conditionally_change_rule_state) 

371 

372 conditionally_change_access_rules_status = { 

373 constants.ACCESS_STATE_ACTIVE: constants.STATUS_ERROR, 

374 constants.SHARE_INSTANCE_RULES_SYNCING: constants.STATUS_ERROR, 

375 } 

376 self.get_and_update_share_instance_access_rules_status( 

377 context, share_instance_id=share_instance_id, 

378 conditionally_change=conditionally_change_access_rules_status) 

379 raise 

380 

381 if rules_to_be_removed_from_db: 381 ↛ 382line 381 didn't jump to line 382 because the condition on line 381 was never true

382 delete_rules = rules_to_be_removed_from_db 

383 

384 self.delete_share_instance_access_rules( 

385 context, delete_rules, share_instance_id=share_instance['id']) 

386 

387 self._loop_for_refresh_else_update_access_rules_status( 

388 context, share_instance_id, share_server) 

389 

390 msg = _("Access rules were successfully modified for share instance " 

391 "%(si)s belonging to share %(shr)s.") 

392 msg_payload = { 

393 'si': share_instance['id'], 

394 'shr': share_instance['share_id'], 

395 } 

396 LOG.info(msg, msg_payload) 

397 

398 def _update_rules_through_share_driver(self, context, share_instance, 

399 access_rules_to_be_on_share, 

400 add_rules, delete_rules, 

401 update_rules, 

402 rules_to_be_removed_from_db, 

403 share_server): 

404 driver_rule_updates = {} 

405 share_protocol = share_instance['share_proto'].lower() 

406 if (not self.driver.ipv6_implemented and 

407 share_protocol == 'nfs'): 

408 add_rules = self._filter_ipv6_rules(add_rules) 

409 delete_rules = self._filter_ipv6_rules(delete_rules) 

410 update_rules = self._filter_ipv6_rules(update_rules) 

411 access_rules_to_be_on_share = self._filter_ipv6_rules( 

412 access_rules_to_be_on_share) 

413 try: 

414 driver_rule_updates = self.driver.update_access( 

415 context, 

416 share_instance, 

417 access_rules_to_be_on_share, 

418 add_rules=add_rules, 

419 delete_rules=delete_rules, 

420 update_rules=update_rules, 

421 share_server=share_server 

422 ) or {} 

423 except NotImplementedError: 

424 # NOTE(u_glide): Fallback to legacy allow_access/deny_access 

425 # for drivers without update_access() method support 

426 # It is also possible that updating the access_level is not 

427 # permitted. 

428 self._update_access_fallback(context, add_rules, delete_rules, 

429 rules_to_be_removed_from_db, 

430 share_instance, 

431 share_server) 

432 return driver_rule_updates 

433 

434 def _loop_for_refresh_else_update_access_rules_status(self, context, 

435 share_instance_id, 

436 share_server): 

437 # Do we need to re-sync or apply any new changes? 

438 if self._check_needs_refresh(context, share_instance_id): 

439 self._update_access_rules(context, share_instance_id, 

440 share_server=share_server) 

441 else: 

442 # Switch the share instance's access_rules_status to 'active' 

443 # if there are no more rules in 'error' state, else, ensure 

444 # 'error' state. 

445 rule_filter = {'state': constants.STATUS_ERROR} 

446 rules_in_error_state = ( 

447 self.get_and_update_share_instance_access_rules( 

448 context, filters=rule_filter, 

449 share_instance_id=share_instance_id) 

450 ) 

451 if not rules_in_error_state: 

452 conditionally_change = { 

453 constants.SHARE_INSTANCE_RULES_SYNCING: 

454 constants.STATUS_ACTIVE, 

455 constants.SHARE_INSTANCE_RULES_ERROR: 

456 constants.STATUS_ACTIVE, 

457 } 

458 self.get_and_update_share_instance_access_rules_status( 

459 context, conditionally_change=conditionally_change, 

460 share_instance_id=share_instance_id) 

461 else: 

462 conditionally_change = { 

463 constants.SHARE_INSTANCE_RULES_SYNCING: 

464 constants.SHARE_INSTANCE_RULES_ERROR, 

465 } 

466 self.get_and_update_share_instance_access_rules_status( 

467 context, conditionally_change=conditionally_change, 

468 share_instance_id=share_instance_id) 

469 

470 def process_driver_rule_updates(self, context, driver_rule_updates, 

471 share_instance_id): 

472 for rule_id, rule_updates in driver_rule_updates.items(): 

473 if 'state' in rule_updates: 

474 # We allow updates *only* if the state is unchanged from 

475 # the time this update was initiated. It is possible 

476 # that the access rule was denied at the API prior to 

477 # the driver reporting that the access rule was added 

478 # successfully. 

479 state = rule_updates.pop('state') 

480 conditional_state_updates = { 

481 constants.ACCESS_STATE_APPLYING: state, 

482 constants.ACCESS_STATE_DENYING: state, 

483 constants.ACCESS_STATE_UPDATING: state, 

484 constants.ACCESS_STATE_ACTIVE: state, 

485 } 

486 else: 

487 conditional_state_updates = {} 

488 self.get_and_update_share_instance_access_rule( 

489 context, rule_id, updates=rule_updates, 

490 share_instance_id=share_instance_id, 

491 conditionally_change=conditional_state_updates) 

492 

493 @staticmethod 

494 def _set_rules_to_readonly(access_rules_to_be_on_share, share_instance): 

495 

496 LOG.debug("All access rules of share instance %s are being " 

497 "cast to read-only for a migration or because the " 

498 "instance is a readable replica.", 

499 share_instance['id']) 

500 

501 for rule in access_rules_to_be_on_share: 

502 rule['access_level'] = constants.ACCESS_LEVEL_RO 

503 

504 return access_rules_to_be_on_share 

505 

506 @staticmethod 

507 def _filter_ipv6_rules(rules): 

508 filtered = [] 

509 for rule in rules: 

510 if rule['access_type'] == 'ip': 

511 ip_version = ipaddress.ip_network( 

512 str(rule['access_to'])).version 

513 if 6 == ip_version: 

514 continue 

515 filtered.append(rule) 

516 return filtered 

517 

518 def _get_rules_to_send_to_driver(self, context, share_instance): 

519 add_rules = [] 

520 delete_rules = [] 

521 update_rules = [] 

522 access_filters = { 

523 'state': (constants.ACCESS_STATE_APPLYING, 

524 constants.ACCESS_STATE_ACTIVE, 

525 constants.ACCESS_STATE_DENYING, 

526 constants.ACCESS_STATE_UPDATING), 

527 } 

528 existing_rules_in_db = self.get_and_update_share_instance_access_rules( 

529 context, filters=access_filters, 

530 share_instance_id=share_instance['id']) 

531 # Update queued rules to transitional states 

532 for rule in existing_rules_in_db: 

533 

534 if rule['state'] == constants.ACCESS_STATE_APPLYING: 

535 add_rules.append(rule) 

536 elif rule['state'] == constants.ACCESS_STATE_DENYING: 

537 delete_rules.append(rule) 

538 elif rule['state'] == constants.ACCESS_STATE_UPDATING: 538 ↛ 539line 538 didn't jump to line 539 because the condition on line 538 was never true

539 update_rules.append(rule) 

540 delete_rule_ids = [r['id'] for r in delete_rules] 

541 access_rules_to_be_on_share = [ 

542 r for r in existing_rules_in_db if r['id'] not in delete_rule_ids 

543 ] 

544 return (access_rules_to_be_on_share, add_rules, 

545 delete_rules, update_rules) 

546 

547 def _check_needs_refresh(self, context, share_instance_id): 

548 rules_to_apply_or_deny = ( 

549 self._update_and_get_unsynced_access_rules_from_db( 

550 context, share_instance_id) 

551 ) 

552 return any(rules_to_apply_or_deny) 

553 

554 def _update_access_fallback(self, context, add_rules, delete_rules, 

555 remove_rules, share_instance, share_server): 

556 for rule in add_rules: 

557 LOG.info( 

558 "Applying access rule '%(rule)s' for share " 

559 "instance '%(instance)s'", 

560 {'rule': rule['id'], 'instance': share_instance['id']} 

561 ) 

562 

563 self.driver.allow_access( 

564 context, 

565 share_instance, 

566 rule, 

567 share_server=share_server 

568 ) 

569 

570 # NOTE(ganso): Fallback mode temporary compatibility workaround 

571 if remove_rules: 

572 delete_rules.extend(remove_rules) 

573 

574 for rule in delete_rules: 

575 LOG.info( 

576 "Denying access rule '%(rule)s' from share " 

577 "instance '%(instance)s'", 

578 {'rule': rule['id'], 'instance': share_instance['id']} 

579 ) 

580 

581 self.driver.deny_access( 

582 context, 

583 share_instance, 

584 rule, 

585 share_server=share_server 

586 ) 

587 

588 def _update_and_get_unsynced_access_rules_from_db(self, context, 

589 share_instance_id): 

590 rule_filter = { 

591 'state': (constants.ACCESS_STATE_QUEUED_TO_APPLY, 

592 constants.ACCESS_STATE_QUEUED_TO_DENY, 

593 constants.ACCESS_STATE_QUEUED_TO_UPDATE), 

594 } 

595 conditionally_change = { 

596 constants.ACCESS_STATE_QUEUED_TO_APPLY: 

597 constants.ACCESS_STATE_APPLYING, 

598 constants.ACCESS_STATE_QUEUED_TO_DENY: 

599 constants.ACCESS_STATE_DENYING, 

600 constants.ACCESS_STATE_QUEUED_TO_UPDATE: 

601 constants.ACCESS_STATE_UPDATING, 

602 } 

603 rules_to_apply_or_deny = ( 

604 self.get_and_update_share_instance_access_rules( 

605 context, filters=rule_filter, 

606 share_instance_id=share_instance_id, 

607 conditionally_change=conditionally_change) 

608 ) 

609 return rules_to_apply_or_deny 

610 

611 def reset_rules_to_queueing_states(self, context, share_instance_id, 

612 reset_active=False): 

613 """Reset applying and denying rules to queued states. 

614 

615 This helper is useful when re-applying rule changes. 

616 :param context: the RequestContext object 

617 :param share_instance_id: ID of the share instance 

618 :param reset_active: If True, set "active" rules to "queued_to_apply" 

619 """ 

620 conditional_updates = { 

621 constants.ACCESS_STATE_APPLYING: 

622 constants.ACCESS_STATE_QUEUED_TO_APPLY, 

623 constants.ACCESS_STATE_DENYING: 

624 constants.ACCESS_STATE_QUEUED_TO_DENY, 

625 } 

626 if reset_active: 

627 conditional_updates.update({ 

628 constants.STATUS_ACTIVE: 

629 constants.ACCESS_STATE_QUEUED_TO_APPLY, 

630 }) 

631 self.get_and_update_share_instance_access_rules_status( 

632 context, 

633 share_instance_id=share_instance_id, 

634 conditionally_change={ 

635 constants.SHARE_INSTANCE_RULES_ERROR: 

636 constants.SHARE_INSTANCE_RULES_SYNCING, 

637 constants.ACCESS_STATE_ACTIVE: 

638 constants.SHARE_INSTANCE_RULES_SYNCING, 

639 }, 

640 ) 

641 self.get_and_update_share_instance_access_rules( 

642 context, share_instance_id=share_instance_id, 

643 conditionally_change=conditional_updates)