Coverage for manila/db/sqlalchemy/models.py: 95%

771 statements  

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

1# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. 

2# Copyright 2010 United States Government as represented by the 

3# Administrator of the National Aeronautics and Space Administration. 

4# Copyright 2011 Piston Cloud Computing, Inc. 

5# All Rights Reserved. 

6# 

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

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

9# a copy of the License at 

10# 

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

12# 

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

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

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

16# License for the specific language governing permissions and limitations 

17# under the License. 

18""" 

19SQLAlchemy models for Manila data. 

20""" 

21 

22from oslo_config import cfg 

23from oslo_db.sqlalchemy import models 

24from sqlalchemy import Column, Integer, String, schema 

25from sqlalchemy import orm 

26from sqlalchemy import ForeignKey, DateTime, Boolean, Enum 

27from sqlalchemy_utils import generic_repr 

28 

29from manila.common import constants 

30 

31CONF = cfg.CONF 

32BASE = orm.declarative_base() 

33 

34 

35@generic_repr 

36class ManilaBase(models.ModelBase, 

37 models.TimestampMixin, 

38 models.SoftDeleteMixin): 

39 """Base class for Manila Models.""" 

40 __table_args__ = {'mysql_engine': 'InnoDB'} 

41 metadata = None 

42 

43 def to_dict(self): 

44 model_dict = {} 

45 for k, v in self.items(): 

46 if not issubclass(type(v), ManilaBase): 

47 model_dict[k] = v 

48 return model_dict 

49 

50 def soft_delete(self, session, update_status=False, 

51 status_field_name='status'): 

52 """Mark this object as deleted.""" 

53 if update_status: 

54 setattr(self, status_field_name, constants.STATUS_DELETED) 

55 

56 return super(ManilaBase, self).soft_delete(session) 

57 

58 

59class Service(BASE, ManilaBase): 

60 """Represents a running service on a host.""" 

61 

62 __tablename__ = 'services' 

63 id = Column(Integer, primary_key=True) 

64 host = Column(String(255)) # , ForeignKey('hosts.id')) 

65 binary = Column(String(255)) 

66 topic = Column(String(255)) 

67 state = Column(String(36)) 

68 report_count = Column(Integer, nullable=False, default=0) 

69 disabled = Column(Boolean, default=False) 

70 disabled_reason = Column(String(255)) 

71 availability_zone_id = Column(String(36), 

72 ForeignKey('availability_zones.id'), 

73 nullable=True) 

74 ensuring = Column(Boolean, default=False) 

75 

76 availability_zone = orm.relationship( 

77 "AvailabilityZone", 

78 lazy='immediate', 

79 primaryjoin=( 

80 'and_(' 

81 'Service.availability_zone_id == ' 

82 'AvailabilityZone.id, ' 

83 'AvailabilityZone.deleted == \'False\')' 

84 ) 

85 ) 

86 

87 

88class Quota(BASE, ManilaBase): 

89 """Represents a single quota override for a project. 

90 

91 If there is no row for a given project id and resource, then the 

92 default for the quota class is used. If there is no row for a 

93 given quota class and resource, then the default for the 

94 deployment is used. If the row is present but the hard limit is 

95 Null, then the resource is unlimited. 

96 """ 

97 

98 __tablename__ = 'quotas' 

99 id = Column(Integer, primary_key=True) 

100 

101 project_id = Column(String(255), index=True) 

102 

103 resource = Column(String(255)) 

104 

105 hard_limit = Column(Integer, nullable=True) 

106 

107 

108class ProjectUserQuota(BASE, ManilaBase): 

109 """Represents a single quota override for a user with in a project.""" 

110 

111 __tablename__ = 'project_user_quotas' 

112 id = Column(Integer, primary_key=True, nullable=False) 

113 

114 project_id = Column(String(255), nullable=False) 

115 user_id = Column(String(255), nullable=False) 

116 

117 resource = Column(String(255), nullable=False) 

118 

119 hard_limit = Column(Integer) 

120 

121 

122class ProjectShareTypeQuota(BASE, ManilaBase): 

123 """Represents a single quota override for a share type within a project.""" 

124 

125 __tablename__ = 'project_share_type_quotas' 

126 id = Column(Integer, primary_key=True, nullable=False) 

127 project_id = Column(String(255), nullable=False) 

128 share_type_id = Column( 

129 String(36), ForeignKey('share_types.id'), nullable=False) 

130 resource = Column(String(255), nullable=False) 

131 hard_limit = Column(Integer) 

132 

133 

134class QuotaClass(BASE, ManilaBase): 

135 """Represents a single quota override for a quota class. 

136 

137 If there is no row for a given quota class and resource, then the 

138 default for the deployment is used. If the row is present but the 

139 hard limit is Null, then the resource is unlimited. 

140 """ 

141 

142 __tablename__ = 'quota_classes' 

143 id = Column(Integer, primary_key=True) 

144 

145 class_name = Column(String(255), index=True) 

146 

147 resource = Column(String(255)) 

148 hard_limit = Column(Integer, nullable=True) 

149 

150 

151class QuotaUsage(BASE, ManilaBase): 

152 """Represents the current usage for a given resource.""" 

153 

154 __tablename__ = 'quota_usages' 

155 id = Column(Integer, primary_key=True) 

156 

157 project_id = Column(String(255), index=True) 

158 user_id = Column(String(255)) 

159 share_type_id = Column(String(36)) 

160 resource = Column(String(255)) 

161 

162 in_use = Column(Integer) 

163 reserved = Column(Integer) 

164 

165 @property 

166 def total(self): 

167 return self.in_use + self.reserved 

168 

169 until_refresh = Column(Integer, nullable=True) 

170 

171 

172class Reservation(BASE, ManilaBase): 

173 """Represents a resource reservation for quotas.""" 

174 

175 __tablename__ = 'reservations' 

176 id = Column(Integer, primary_key=True) 

177 uuid = Column(String(36), nullable=False) 

178 

179 usage_id = Column(Integer, ForeignKey('quota_usages.id'), nullable=False) 

180 

181 project_id = Column(String(255), index=True) 

182 user_id = Column(String(255)) 

183 share_type_id = Column(String(36)) 

184 resource = Column(String(255)) 

185 

186 delta = Column(Integer) 

187 expire = Column(DateTime, nullable=False) 

188 

189 

190class Share(BASE, ManilaBase): 

191 """Represents an NFS and CIFS shares.""" 

192 __tablename__ = 'shares' 

193 _extra_keys = ['name', 'export_location', 'export_locations', 'status', 

194 'host', 'share_server_id', 'share_network_id', 

195 'availability_zone', 'access_rules_status', 'share_type_id'] 

196 

197 @property 

198 def name(self): 

199 return CONF.share_name_template % self.id 

200 

201 @property 

202 def export_location(self): 

203 if len(self.instances) > 0: 203 ↛ exitline 203 didn't return from function 'export_location' because the condition on line 203 was always true

204 return self.instance.export_location 

205 

206 @property 

207 def encryption_key_ref(self): 

208 if len(self.instances) > 0: 

209 return self.instance.encryption_key_ref 

210 

211 @property 

212 def is_busy(self): 

213 # Make sure share is not busy, i.e., not part of a migration 

214 if self.task_state in constants.BUSY_TASK_STATES: 

215 return True 

216 return False 

217 

218 @property 

219 def export_locations(self): 

220 # TODO(gouthamr): Return AZ specific export locations for replicated 

221 # shares. 

222 # NOTE(gouthamr): For a replicated share, export locations of the 

223 # 'active' instances are chosen, if 'available'. 

224 all_export_locations = [] 

225 select_instances = list(filter( 

226 lambda x: x['replica_state'] == constants.REPLICA_STATE_ACTIVE, 

227 self.instances)) or self.instances 

228 

229 for instance in select_instances: 

230 if instance['status'] == constants.STATUS_AVAILABLE: 

231 for export_location in instance.export_locations: 

232 all_export_locations.append(export_location['path']) 

233 

234 return all_export_locations 

235 

236 def __getattr__(self, item): 

237 proxified_properties = ('status', 'host', 'share_server_id', 

238 'share_network_id', 'availability_zone', 

239 'share_type_id', 'share_type') 

240 

241 if item in proxified_properties: 

242 return getattr(self.instance, item, None) 

243 

244 raise AttributeError(item) 

245 

246 @property 

247 def share_server_id(self): 

248 return self.__getattr__('share_server_id') 

249 

250 @property 

251 def has_replicas(self): 

252 if len(self.instances) > 1: 

253 # NOTE(gouthamr): The 'primary' instance of a replicated share 

254 # has a 'replica_state' set to 'active'. Only the secondary replica 

255 # instances need to be regarded as true 'replicas' by users. 

256 replicas = (list(filter(lambda x: x['replica_state'] is not None, 

257 self.instances))) 

258 return len(replicas) > 1 

259 return False 

260 

261 @property 

262 def progress(self): 

263 if len(self.instances) > 0: 

264 return self.instance.progress 

265 

266 @property 

267 def instance(self): 

268 # NOTE(gouthamr): The order of preference: status 'replication_change', 

269 # followed by 'available' and 'error'. If replicated share and 

270 # not undergoing a 'replication_change', only 'active' instances are 

271 # preferred. 

272 result = None 

273 if len(self.instances) > 0: 

274 order = (constants.STATUS_REVERTING, 

275 constants.STATUS_REPLICATION_CHANGE, 

276 constants.STATUS_MIGRATING, 

277 constants.STATUS_SERVER_MIGRATING, 

278 constants.STATUS_AVAILABLE, 

279 constants.STATUS_ERROR, ) 

280 other_statuses = ( 

281 [x['status'] for x in self.instances if 

282 x['status'] not in order and 

283 x['status'] not in constants.TRANSITIONAL_STATUSES] 

284 ) 

285 order = (order + tuple(other_statuses) + 

286 constants.TRANSITIONAL_STATUSES) 

287 sorted_instances = sorted( 

288 self.instances, key=lambda x: order.index(x['status'])) 

289 

290 select_instances = sorted_instances 

291 if (select_instances[0]['status'] != 

292 constants.STATUS_REPLICATION_CHANGE): 

293 select_instances = ( 

294 list(filter(lambda x: x['replica_state'] == 

295 constants.REPLICA_STATE_ACTIVE, 

296 sorted_instances)) or sorted_instances 

297 ) 

298 result = select_instances[0] 

299 return result 

300 

301 @property 

302 def access_rules_status(self): 

303 return get_access_rules_status(self.instances) 

304 

305 id = Column(String(36), primary_key=True) 

306 deleted = Column(String(36), default='False') 

307 user_id = Column(String(255)) 

308 project_id = Column(String(255)) 

309 size = Column(Integer) 

310 

311 display_name = Column(String(255)) 

312 display_description = Column(String(255)) 

313 snapshot_id = Column(String(36)) 

314 source_backup_id = Column(String(36)) 

315 snapshot_support = Column(Boolean, default=True) 

316 create_share_from_snapshot_support = Column(Boolean, default=True) 

317 revert_to_snapshot_support = Column(Boolean, default=False) 

318 replication_type = Column(String(255), nullable=True) 

319 mount_snapshot_support = Column(Boolean, default=False) 

320 share_proto = Column(String(255)) 

321 is_public = Column(Boolean, default=False) 

322 share_group_id = Column(String(36), 

323 ForeignKey('share_groups.id'), 

324 nullable=True) 

325 

326 source_share_group_snapshot_member_id = Column(String(36), nullable=True) 

327 task_state = Column(String(255)) 

328 is_soft_deleted = Column(Boolean, default=False) 

329 scheduled_to_be_deleted_at = Column(DateTime) 

330 instances = orm.relationship( 

331 "ShareInstance", 

332 lazy='subquery', 

333 primaryjoin=( 

334 'and_(' 

335 'Share.id == ShareInstance.share_id, ' 

336 'ShareInstance.deleted == "False")' 

337 ), 

338 viewonly=True, 

339 join_depth=2, 

340 ) 

341 

342 

343class ShareInstance(BASE, ManilaBase): 

344 __tablename__ = 'share_instances' 

345 

346 _extra_keys = ['name', 'export_location', 'availability_zone', 

347 'replica_state'] 

348 _proxified_properties = ('user_id', 'project_id', 'size', 

349 'display_name', 'display_description', 

350 'snapshot_id', 'share_proto', 'is_public', 

351 'share_group_id', 'replication_type', 

352 'source_share_group_snapshot_member_id', 

353 'mount_snapshot_support') 

354 

355 def set_share_data(self, share): 

356 for share_property in self._proxified_properties: 

357 setattr(self, share_property, share[share_property]) 

358 

359 @property 

360 def name(self): 

361 return CONF.share_name_template % self.id 

362 

363 @property 

364 def export_location(self): 

365 if len(self.export_locations) > 0: 

366 return self.export_locations[0]['path'] 

367 

368 @property 

369 def availability_zone(self): 

370 if self._availability_zone: 

371 return self._availability_zone['name'] 

372 

373 id = Column(String(36), primary_key=True) 

374 share_id = Column(String(36), ForeignKey('shares.id')) 

375 deleted = Column(String(36), default='False') 

376 host = Column(String(255)) 

377 status = Column(String(255)) 

378 progress = Column(String(32)) 

379 mount_point_name = Column(String(255)) 

380 ACCESS_STATUS_PRIORITIES = { 

381 constants.STATUS_ACTIVE: 0, 

382 constants.SHARE_INSTANCE_RULES_SYNCING: 1, 

383 constants.SHARE_INSTANCE_RULES_ERROR: 2, 

384 } 

385 

386 access_rules_status = Column(Enum(constants.STATUS_ACTIVE, 

387 constants.SHARE_INSTANCE_RULES_SYNCING, 

388 constants.SHARE_INSTANCE_RULES_ERROR), 

389 default=constants.STATUS_ACTIVE) 

390 

391 scheduled_at = Column(DateTime) 

392 launched_at = Column(DateTime) 

393 terminated_at = Column(DateTime) 

394 encryption_key_ref = Column(String(36), nullable=True) 

395 replica_state = Column(String(255), nullable=True) 

396 cast_rules_to_readonly = Column(Boolean, default=False, nullable=False) 

397 share_type_id = Column(String(36), ForeignKey('share_types.id'), 

398 nullable=True) 

399 availability_zone_id = Column(String(36), 

400 ForeignKey('availability_zones.id'), 

401 nullable=True) 

402 _availability_zone = orm.relationship( 

403 "AvailabilityZone", 

404 lazy='subquery', 

405 foreign_keys=availability_zone_id, 

406 primaryjoin=( 

407 'and_(' 

408 'ShareInstance.availability_zone_id == ' 

409 'AvailabilityZone.id, ' 

410 'AvailabilityZone.deleted == \'False\')' 

411 ) 

412 ) 

413 

414 export_locations = orm.relationship( 

415 "ShareInstanceExportLocations", 

416 lazy='joined', 

417 backref=orm.backref('share_instance', lazy='joined'), 

418 primaryjoin=( 

419 'and_(' 

420 'ShareInstance.id == ' 

421 'ShareInstanceExportLocations.share_instance_id, ' 

422 'ShareInstanceExportLocations.deleted == 0)' 

423 ) 

424 ) 

425 share_network_id = Column(String(36), ForeignKey('share_networks.id'), 

426 nullable=True) 

427 share_server_id = Column(String(36), ForeignKey('share_servers.id'), 

428 nullable=True) 

429 share_type = orm.relationship( 

430 "ShareTypes", 

431 lazy='subquery', 

432 foreign_keys=share_type_id, 

433 primaryjoin='and_(' 

434 'ShareInstance.share_type_id == ShareTypes.id, ' 

435 'ShareTypes.deleted == "False")') 

436 share = orm.relationship( 

437 'Share', 

438 foreign_keys=share_id, 

439 primaryjoin='ShareInstance.share_id == Share.id' 

440 ) 

441 

442 

443class ShareInstanceExportLocations(BASE, ManilaBase): 

444 """Represents export locations of share instances.""" 

445 __tablename__ = 'share_instance_export_locations' 

446 

447 _extra_keys = ['el_metadata', ] 

448 

449 @property 

450 def el_metadata(self): 

451 el_metadata = {} 

452 for meta in self._el_metadata_bare: # pylint: disable=no-member 

453 el_metadata[meta['key']] = meta['value'] 

454 return el_metadata 

455 

456 @property 

457 def replica_state(self): 

458 return self.share_instance['replica_state'] 

459 

460 id = Column(Integer, primary_key=True) 

461 uuid = Column(String(36), nullable=False, unique=True) 

462 share_instance_id = Column( 

463 String(36), ForeignKey('share_instances.id'), nullable=False) 

464 path = Column(String(2000)) 

465 is_admin_only = Column(Boolean, default=False, nullable=False) 

466 

467 

468class ShareInstanceExportLocationsMetadata(BASE, ManilaBase): 

469 """Represents export location metadata of share instances.""" 

470 __tablename__ = "share_instance_export_locations_metadata" 

471 

472 _extra_keys = ['export_location_uuid', ] 

473 

474 id = Column(Integer, primary_key=True) 

475 export_location_id = Column( 

476 Integer, 

477 ForeignKey("share_instance_export_locations.id"), nullable=False) 

478 key = Column(String(255), nullable=False) 

479 value = Column(String(1023), nullable=False) 

480 export_location = orm.relationship( 

481 ShareInstanceExportLocations, 

482 backref="_el_metadata_bare", 

483 foreign_keys=export_location_id, 

484 lazy='immediate', 

485 primaryjoin="and_(" 

486 "%(cls_name)s.export_location_id == " 

487 "ShareInstanceExportLocations.id," 

488 "%(cls_name)s.deleted == 0)" % { 

489 "cls_name": "ShareInstanceExportLocationsMetadata"}) 

490 

491 @property 

492 def export_location_uuid(self): 

493 return self.export_location.uuid # pylint: disable=no-member 

494 

495 

496class ShareTypes(BASE, ManilaBase): 

497 """Represent possible share_types of volumes offered.""" 

498 __tablename__ = "share_types" 

499 id = Column(String(36), primary_key=True) 

500 deleted = Column(String(36), default='False') 

501 name = Column(String(255)) 

502 description = Column(String(255)) 

503 is_public = Column(Boolean, default=True) 

504 

505 

506class ShareTypeProjects(BASE, ManilaBase): 

507 """Represent projects associated share_types.""" 

508 __tablename__ = "share_type_projects" 

509 __table_args__ = (schema.UniqueConstraint( 

510 "share_type_id", "project_id", "deleted", 

511 name="uniq_share_type_projects0share_type_id0project_id0deleted"), 

512 ) 

513 id = Column(Integer, primary_key=True) 

514 share_type_id = Column(Integer, ForeignKey('share_types.id'), 

515 nullable=False) 

516 project_id = Column(String(255)) 

517 

518 share_type = orm.relationship( 

519 ShareTypes, 

520 backref="projects", 

521 foreign_keys=share_type_id, 

522 primaryjoin='and_(' 

523 'ShareTypeProjects.share_type_id == ShareTypes.id,' 

524 'ShareTypeProjects.deleted == 0)') 

525 

526 

527class ShareTypeExtraSpecs(BASE, ManilaBase): 

528 """Represents additional specs as key/value pairs for a share_type.""" 

529 __tablename__ = 'share_type_extra_specs' 

530 id = Column(Integer, primary_key=True) 

531 key = Column("spec_key", String(255)) 

532 value = Column("spec_value", String(255)) 

533 share_type_id = Column(String(36), ForeignKey('share_types.id'), 

534 nullable=False) 

535 share_type = orm.relationship( 

536 ShareTypes, 

537 backref="extra_specs", 

538 foreign_keys=share_type_id, 

539 primaryjoin='and_(' 

540 'ShareTypeExtraSpecs.share_type_id == ShareTypes.id,' 

541 'ShareTypeExtraSpecs.deleted == 0)' 

542 ) 

543 

544 

545class ShareMetadata(BASE, ManilaBase): 

546 """Represents a metadata key/value pair for a share.""" 

547 __tablename__ = 'share_metadata' 

548 id = Column(Integer, primary_key=True) 

549 key = Column(String(255), nullable=False) 

550 value = Column(String(1023), nullable=False) 

551 share_id = Column(String(36), ForeignKey('shares.id'), nullable=False) 

552 share = orm.relationship(Share, backref="share_metadata", 

553 foreign_keys=share_id, 

554 primaryjoin='and_(' 

555 'ShareMetadata.share_id == Share.id,' 

556 'ShareMetadata.deleted == 0)') 

557 

558 

559class ShareAccessMapping(BASE, ManilaBase): 

560 """Represents access to share.""" 

561 __tablename__ = 'share_access_map' 

562 

563 id = Column(String(36), primary_key=True) 

564 deleted = Column(String(36), default='False') 

565 share_id = Column(String(36), ForeignKey('shares.id')) 

566 access_type = Column(String(255)) 

567 access_to = Column(String(255)) 

568 access_key = Column(String(255), nullable=True) 

569 

570 access_level = Column(Enum(*constants.ACCESS_LEVELS), 

571 default=constants.ACCESS_LEVEL_RW) 

572 

573 @property 

574 def state(self): 

575 """Get the aggregated 'state' from all the instance mapping states. 

576 

577 An access rule is supposed to be truly 'active' when it has been 

578 applied across all of the share instances of the parent share object. 

579 """ 

580 return get_aggregated_access_rules_state(self.instance_mappings) 

581 

582 instance_mappings = orm.relationship( 

583 "ShareInstanceAccessMapping", 

584 lazy='immediate', 

585 primaryjoin=( 

586 'and_(' 

587 'ShareAccessMapping.id == ' 

588 'ShareInstanceAccessMapping.access_id, ' 

589 'ShareInstanceAccessMapping.deleted == "False")' 

590 ) 

591 ) 

592 share = orm.relationship( 

593 "Share", 

594 primaryjoin=( 

595 'and_(' 

596 'ShareAccessMapping.share_id == ' 

597 'Share.id, ' 

598 'Share.deleted == "False")' 

599 ) 

600 ) 

601 

602 

603class ShareAccessRulesMetadata(BASE, ManilaBase): 

604 """Represents a metadata key/value pair for a share access rule.""" 

605 __tablename__ = 'share_access_rules_metadata' 

606 id = Column(Integer, primary_key=True) 

607 deleted = Column(String(36), default='False') 

608 key = Column(String(255), nullable=False) 

609 value = Column(String(1023), nullable=False) 

610 access_id = Column(String(36), ForeignKey('share_access_map.id'), 

611 nullable=False) 

612 access = orm.relationship( 

613 ShareAccessMapping, backref="share_access_rules_metadata", 

614 foreign_keys=access_id, 

615 lazy='immediate', 

616 primaryjoin='and_(' 

617 'ShareAccessRulesMetadata.access_id == ShareAccessMapping.id,' 

618 'ShareAccessRulesMetadata.deleted == "False")') 

619 

620 

621class ShareInstanceAccessMapping(BASE, ManilaBase): 

622 """Represents access to individual share instances.""" 

623 

624 __tablename__ = 'share_instance_access_map' 

625 _proxified_properties = ('share_id', 'access_type', 'access_key', 

626 'access_to', 'access_level') 

627 

628 def set_share_access_data(self, share_access): 

629 for share_access_attr in self._proxified_properties: 

630 setattr(self, share_access_attr, share_access[share_access_attr]) 

631 

632 id = Column(String(36), primary_key=True) 

633 deleted = Column(String(36), default='False') 

634 share_instance_id = Column(String(36), ForeignKey('share_instances.id')) 

635 access_id = Column(String(36), ForeignKey('share_access_map.id')) 

636 state = Column(String(255), default=constants.ACCESS_STATE_QUEUED_TO_APPLY) 

637 

638 instance = orm.relationship( 

639 "ShareInstance", 

640 lazy='immediate', 

641 primaryjoin=( 

642 'and_(' 

643 'ShareInstanceAccessMapping.share_instance_id == ' 

644 'ShareInstance.id, ' 

645 'ShareInstanceAccessMapping.deleted == "False")' 

646 ) 

647 ) 

648 

649 

650class ShareSnapshot(BASE, ManilaBase): 

651 """Represents a snapshot of a share.""" 

652 __tablename__ = 'share_snapshots' 

653 _extra_keys = ['name', 'share_name', 'status', 'progress', 

654 'provider_location', 'aggregate_status'] 

655 

656 def __getattr__(self, item): 

657 proxified_properties = ('status', 'progress', 'provider_location') 

658 

659 if item in proxified_properties: 

660 return getattr(self.instance, item, None) 

661 

662 raise AttributeError(item) 

663 

664 @property 

665 def export_locations(self): 

666 # TODO(gouthamr): Return AZ specific export locations for replicated 

667 # snapshots. 

668 # NOTE(gouthamr): For a replicated snapshot, export locations of the 

669 # 'active' instances are chosen, if 'available'. 

670 all_export_locations = [] 

671 select_instances = list(filter( 

672 lambda x: (x['share_instance']['replica_state'] == 

673 constants.REPLICA_STATE_ACTIVE), 

674 self.instances)) or self.instances 

675 

676 for instance in select_instances: 

677 if instance['status'] == constants.STATUS_AVAILABLE: 677 ↛ 676line 677 didn't jump to line 676 because the condition on line 677 was always true

678 for export_location in instance.export_locations: 

679 all_export_locations.append(export_location) 

680 

681 return all_export_locations 

682 

683 @property 

684 def name(self): 

685 return CONF.share_snapshot_name_template % self.id 

686 

687 @property 

688 def share_name(self): 

689 return CONF.share_name_template % self.share_id 

690 

691 @property 

692 def instance(self): 

693 result = None 

694 if len(self.instances) > 0: 694 ↛ 715line 694 didn't jump to line 715 because the condition on line 694 was always true

695 def qualified_replica(x): 

696 if x is None: 696 ↛ 697line 696 didn't jump to line 697 because the condition on line 696 was never true

697 return False 

698 else: 

699 preferred_statuses = (constants.REPLICA_STATE_ACTIVE,) 

700 return x['replica_state'] in preferred_statuses 

701 

702 replica_snapshots = list(filter( 

703 lambda x: qualified_replica(x.share_instance), self.instances)) 

704 

705 migrating_snapshots = list(filter( 

706 lambda x: x.share_instance['status'] in ( 

707 constants.STATUS_MIGRATING, 

708 constants.STATUS_SERVER_MIGRATING), self.instances)) 

709 

710 snapshot_instances = (replica_snapshots or migrating_snapshots 

711 or self.instances) 

712 

713 result = snapshot_instances[0] 

714 

715 return result 

716 

717 @property 

718 def aggregate_status(self): 

719 """Get the aggregated 'status' of all instances. 

720 

721 A snapshot is supposed to be truly 'available' when it is available 

722 across all of the share instances of the parent share object. In 

723 case of replication, we only consider replicas (share instances) 

724 that are in 'in_sync' replica_state. 

725 """ 

726 

727 def qualified_replica(x): 

728 if x is None: 728 ↛ 729line 728 didn't jump to line 729 because the condition on line 728 was never true

729 return False 

730 else: 

731 preferred_statuses = (constants.REPLICA_STATE_ACTIVE, 

732 constants.REPLICA_STATE_IN_SYNC) 

733 return x['replica_state'] in preferred_statuses 

734 

735 replica_snapshots = list(filter( 

736 lambda x: qualified_replica(x['share_instance']), self.instances)) 

737 

738 if not replica_snapshots: 

739 return self.status 

740 

741 order = (constants.STATUS_DELETING, constants.STATUS_CREATING, 

742 constants.STATUS_ERROR, constants.STATUS_MIGRATING, 

743 constants.STATUS_SERVER_MIGRATING, 

744 constants.STATUS_AVAILABLE) 

745 other_statuses = [x['status'] for x in self.instances if 

746 x['status'] not in order] 

747 order = (order + tuple(other_statuses)) 

748 

749 sorted_instances = sorted( 

750 replica_snapshots, key=lambda x: order.index(x['status'])) 

751 return sorted_instances[0].status 

752 

753 id = Column(String(36), primary_key=True) 

754 deleted = Column(String(36), default='False') 

755 user_id = Column(String(255)) 

756 project_id = Column(String(255)) 

757 share_id = Column(String(36)) 

758 size = Column(Integer) 

759 display_name = Column(String(255)) 

760 display_description = Column(String(255)) 

761 share_size = Column(Integer) 

762 share_proto = Column(String(255)) 

763 share = orm.relationship(Share, backref="snapshots", 

764 foreign_keys=share_id, 

765 primaryjoin='and_(' 

766 'ShareSnapshot.share_id == Share.id,' 

767 'ShareSnapshot.deleted == "False")') 

768 

769 

770class ShareSnapshotMetadata(BASE, ManilaBase): 

771 """Represents a metadata key/value pair for a snapshot.""" 

772 __tablename__ = 'share_snapshot_metadata' 

773 id = Column(Integer, primary_key=True) 

774 key = Column(String(255), nullable=False) 

775 value = Column(String(1023), nullable=False) 

776 deleted = Column(String(36), default='False') 

777 share_snapshot_id = Column(String(36), ForeignKey( 

778 'share_snapshots.id'), nullable=False) 

779 

780 share_snapshot = orm.relationship( 

781 ShareSnapshot, backref="share_snapshot_metadata", 

782 foreign_keys=share_snapshot_id, 

783 primaryjoin='and_(' 

784 'ShareSnapshotMetadata.share_snapshot_id == ShareSnapshot.id,' 

785 'ShareSnapshotMetadata.deleted == "False")') 

786 

787 

788class ShareSnapshotInstance(BASE, ManilaBase): 

789 """Represents a snapshot of a share.""" 

790 __tablename__ = 'share_snapshot_instances' 

791 _extra_keys = ['name', 'share_id', 'share_name'] 

792 

793 @property 

794 def name(self): 

795 return CONF.share_snapshot_name_template % self.id 

796 

797 @property 

798 def share_name(self): 

799 return CONF.share_name_template % self.share_instance_id 

800 

801 @property 

802 def share_id(self): 

803 # NOTE(u_glide): This property required for compatibility 

804 # with share drivers 

805 return self.share_instance_id 

806 

807 @property 

808 def size(self): 

809 # NOTE(silvacarlose) for backwards compatibility 

810 if self.instance_size is None: 810 ↛ 813line 810 didn't jump to line 813 because the condition on line 810 was always true

811 return self.snapshot.size 

812 else: 

813 return self.instance_size 

814 

815 id = Column(String(36), primary_key=True) 

816 deleted = Column(String(36), default='False') 

817 snapshot_id = Column(String(36), nullable=True) 

818 share_instance_id = Column( 

819 String(36), ForeignKey('share_instances.id'), nullable=False) 

820 status = Column(String(255)) 

821 progress = Column(String(255)) 

822 provider_location = Column(String(255)) 

823 share_proto = Column(String(255)) 

824 instance_size = Column('size', Integer) 

825 share_group_snapshot_id = Column(String(36), nullable=True) 

826 user_id = Column(String(255)) 

827 project_id = Column(String(255)) 

828 

829 export_locations = orm.relationship( 

830 "ShareSnapshotInstanceExportLocation", 

831 lazy='immediate', 

832 primaryjoin=( 

833 'and_(' 

834 'ShareSnapshotInstance.id == ' 

835 'ShareSnapshotInstanceExportLocation.share_snapshot_instance_id, ' 

836 'ShareSnapshotInstanceExportLocation.deleted == "False")' 

837 ) 

838 ) 

839 share_instance = orm.relationship( 

840 ShareInstance, backref="snapshot_instances", 

841 lazy='immediate', 

842 primaryjoin=( 

843 'and_(' 

844 'ShareSnapshotInstance.share_instance_id == ShareInstance.id,' 

845 'ShareSnapshotInstance.deleted == "False")') 

846 ) 

847 snapshot = orm.relationship( 

848 "ShareSnapshot", 

849 lazy="immediate", 

850 foreign_keys=snapshot_id, 

851 backref="instances", 

852 primaryjoin=( 

853 'and_(' 

854 'ShareSnapshot.id == ShareSnapshotInstance.snapshot_id, ' 

855 'ShareSnapshotInstance.deleted == "False")' 

856 ), 

857 viewonly=True, 

858 join_depth=2, 

859 sync_backref=False, 

860 ) 

861 share_group_snapshot = orm.relationship( 

862 "ShareGroupSnapshot", 

863 lazy="immediate", 

864 foreign_keys=share_group_snapshot_id, 

865 backref="share_group_snapshot_members", 

866 primaryjoin=('ShareGroupSnapshot.id == ' 

867 'ShareSnapshotInstance.share_group_snapshot_id'), 

868 viewonly=True, 

869 join_depth=2, 

870 sync_backref=False, 

871 ) 

872 

873 

874class ShareSnapshotAccessMapping(BASE, ManilaBase): 

875 """Represents access to share snapshot.""" 

876 __tablename__ = 'share_snapshot_access_map' 

877 

878 @property 

879 def state(self): 

880 """Get the aggregated 'state' from all the instance mapping states. 

881 

882 An access rule is supposed to be truly 'active' when it has been 

883 applied across all of the share snapshot instances of the parent 

884 share snapshot object. 

885 """ 

886 return get_aggregated_access_rules_state(self.instance_mappings) 

887 

888 id = Column(String(36), primary_key=True) 

889 deleted = Column(String(36), default='False') 

890 share_snapshot_id = Column(String(36), ForeignKey('share_snapshots.id')) 

891 access_type = Column(String(255)) 

892 access_to = Column(String(255)) 

893 

894 instance_mappings = orm.relationship( 

895 "ShareSnapshotInstanceAccessMapping", 

896 lazy='immediate', 

897 primaryjoin=( 

898 'and_(' 

899 'ShareSnapshotAccessMapping.id == ' 

900 'ShareSnapshotInstanceAccessMapping.access_id, ' 

901 'ShareSnapshotInstanceAccessMapping.deleted == "False")' 

902 ) 

903 ) 

904 

905 

906class ShareSnapshotInstanceAccessMapping(BASE, ManilaBase): 

907 """Represents access to individual share snapshot instances.""" 

908 

909 __tablename__ = 'share_snapshot_instance_access_map' 

910 _proxified_properties = ('share_snapshot_id', 'access_type', 'access_to') 

911 

912 def set_snapshot_access_data(self, snapshot_access): 

913 for snapshot_access_attr in self._proxified_properties: 

914 setattr(self, snapshot_access_attr, 

915 snapshot_access[snapshot_access_attr]) 

916 

917 id = Column(String(36), primary_key=True) 

918 deleted = Column(String(36), default='False') 

919 share_snapshot_instance_id = Column(String(36), ForeignKey( 

920 'share_snapshot_instances.id')) 

921 access_id = Column(String(36), ForeignKey('share_snapshot_access_map.id')) 

922 state = Column(Enum(*constants.ACCESS_RULES_STATES), 

923 default=constants.ACCESS_STATE_QUEUED_TO_APPLY) 

924 

925 instance = orm.relationship( 

926 "ShareSnapshotInstance", 

927 lazy='immediate', 

928 primaryjoin=( 

929 'and_(' 

930 'ShareSnapshotInstanceAccessMapping.share_snapshot_instance_id == ' 

931 'ShareSnapshotInstance.id, ' 

932 'ShareSnapshotInstanceAccessMapping.deleted == "False")' 

933 ) 

934 ) 

935 

936 

937class ShareSnapshotInstanceExportLocation(BASE, ManilaBase): 

938 """Represents export locations of share snapshot instances.""" 

939 __tablename__ = 'share_snapshot_instance_export_locations' 

940 

941 id = Column(String(36), primary_key=True) 

942 share_snapshot_instance_id = Column( 

943 String(36), ForeignKey('share_snapshot_instances.id'), nullable=False) 

944 path = Column(String(2000)) 

945 is_admin_only = Column(Boolean, default=False, nullable=False) 

946 deleted = Column(String(36), default='False') 

947 

948 

949class SecurityService(BASE, ManilaBase): 

950 """Security service information for manila shares.""" 

951 

952 __tablename__ = 'security_services' 

953 id = Column(String(36), primary_key=True) 

954 deleted = Column(String(36), default='False') 

955 project_id = Column(String(255), nullable=False) 

956 type = Column(String(32), nullable=False) 

957 dns_ip = Column(String(64), nullable=True) 

958 server = Column(String(255), nullable=True) 

959 domain = Column(String(255), nullable=True) 

960 user = Column(String(255), nullable=True) 

961 password = Column(String(255), nullable=True) 

962 name = Column(String(255), nullable=True) 

963 description = Column(String(255), nullable=True) 

964 ou = Column(String(255), nullable=True) 

965 default_ad_site = Column(String(255), nullable=True) 

966 

967 

968class ShareNetwork(BASE, ManilaBase): 

969 """Represents network data used by share.""" 

970 __tablename__ = 'share_networks' 

971 id = Column(String(36), primary_key=True, nullable=False) 

972 deleted = Column(String(36), default='False') 

973 project_id = Column(String(255), nullable=False) 

974 user_id = Column(String(255), nullable=False) 

975 name = Column(String(255), nullable=True) 

976 description = Column(String(255), nullable=True) 

977 status = Column(Enum( 

978 constants.STATUS_NETWORK_ACTIVE, constants.STATUS_NETWORK_ERROR, 

979 constants.STATUS_NETWORK_CHANGE), 

980 default=constants.STATUS_NETWORK_ACTIVE) 

981 security_services = orm.relationship( 

982 "SecurityService", 

983 secondary="share_network_security_service_association", 

984 backref="share_networks", 

985 primaryjoin='and_(' 

986 'ShareNetwork.id == ' 

987 'ShareNetworkSecurityServiceAssociation.share_network_id,' 

988 'ShareNetworkSecurityServiceAssociation.deleted == 0,' 

989 'ShareNetwork.deleted == "False")', 

990 secondaryjoin='and_(' 

991 'SecurityService.id == ' 

992 'ShareNetworkSecurityServiceAssociation.security_service_id,' 

993 'SecurityService.deleted == "False")') 

994 share_instances = orm.relationship( 

995 "ShareInstance", 

996 backref=orm.backref('share_network'), 

997 primaryjoin='and_(' 

998 'ShareNetwork.id == ShareInstance.share_network_id,' 

999 'ShareInstance.deleted == "False")') 

1000 share_network_subnets = orm.relationship( 

1001 "ShareNetworkSubnet", 

1002 lazy='joined', 

1003 backref=orm.backref('share_network', lazy='joined'), 

1004 primaryjoin='and_' 

1005 '(ShareNetwork.id == ShareNetworkSubnet.share_network_id,' 

1006 'ShareNetworkSubnet.deleted == "False")') 

1007 

1008 @property 

1009 def security_service_update_support(self): 

1010 share_servers_support_updating = [] 

1011 for network_subnet in self.share_network_subnets: 

1012 for server in network_subnet['share_servers']: 

1013 share_servers_support_updating.append( 

1014 server['security_service_update_support']) 

1015 # NOTE(carloss): all share servers within this share network must 

1016 # support updating security services in order to have this property 

1017 # set to True. 

1018 return all(share_servers_support_updating) 

1019 

1020 @property 

1021 def network_allocation_update_support(self): 

1022 share_servers_support_updating = [] 

1023 for network_subnet in self.share_network_subnets: 1023 ↛ 1024line 1023 didn't jump to line 1024 because the loop on line 1023 never started

1024 for server in network_subnet['share_servers']: 

1025 share_servers_support_updating.append( 

1026 server['network_allocation_update_support']) 

1027 # NOTE(felipe_rodrigues): all share servers within this share network 

1028 # must support updating in order to have this property set to True. 

1029 return all(share_servers_support_updating) 

1030 

1031 

1032class ShareNetworkSubnet(BASE, ManilaBase): 

1033 """Represents a share network subnet used by some resources.""" 

1034 

1035 _extra_keys = ['availability_zone', 'subnet_metadata'] 

1036 

1037 __tablename__ = 'share_network_subnets' 

1038 id = Column(String(36), primary_key=True, nullable=False) 

1039 neutron_net_id = Column(String(36), nullable=True) 

1040 neutron_subnet_id = Column(String(36), nullable=True) 

1041 network_type = Column(String(32), nullable=True) 

1042 cidr = Column(String(64), nullable=True) 

1043 segmentation_id = Column(Integer, nullable=True) 

1044 gateway = Column(String(64), nullable=True) 

1045 mtu = Column(Integer, nullable=True) 

1046 deleted = Column(String(36), default='False') 

1047 share_network_id = Column(String(36), ForeignKey('share_networks.id'), 

1048 nullable=False) 

1049 ip_version = Column(Integer, nullable=True) 

1050 availability_zone_id = Column( 

1051 String(36), ForeignKey('availability_zones.id'), nullable=True) 

1052 

1053 share_servers = orm.relationship( 

1054 "ShareServer", 

1055 secondary="share_server_share_network_subnet_mappings", 

1056 backref="share_network_subnets", 

1057 lazy='immediate', 

1058 primaryjoin="and_(ShareNetworkSubnet.id == " 

1059 "%(cls_name)s.share_network_subnet_id, " 

1060 "%(cls_name)s.deleted == 0)" % { 

1061 "cls_name": "ShareServerShareNetworkSubnetMapping"}, 

1062 secondaryjoin='and_(' 

1063 'ShareServer.id == ' 

1064 'ShareServerShareNetworkSubnetMapping.share_server_id,' 

1065 'ShareServerShareNetworkSubnetMapping.deleted == 0)' 

1066 ) 

1067 

1068 _availability_zone = orm.relationship( 

1069 "AvailabilityZone", 

1070 lazy='immediate', 

1071 foreign_keys=availability_zone_id, 

1072 primaryjoin=( 

1073 "and_(" 

1074 "ShareNetworkSubnet.availability_zone_id == AvailabilityZone.id, " 

1075 "AvailabilityZone.deleted == 'False')")) 

1076 

1077 @property 

1078 def availability_zone(self): 

1079 if self._availability_zone: 1079 ↛ 1080line 1079 didn't jump to line 1080 because the condition on line 1079 was never true

1080 return self._availability_zone['name'] 

1081 

1082 @property 

1083 def is_default(self): 

1084 return self.availability_zone_id is None 

1085 

1086 @property 

1087 def share_network_name(self): 

1088 return self.share_network['name'] 

1089 

1090 @property 

1091 def subnet_metadata(self): 

1092 metadata_dict = {} 

1093 metadata_list = ( 

1094 self.share_network_subnet_metadata) # pylint: disable=no-member 

1095 for meta in metadata_list: 

1096 metadata_dict[meta['key']] = meta['value'] 

1097 return metadata_dict 

1098 

1099 @property 

1100 def project_id(self): 

1101 return self.share_network['project_id'] 

1102 

1103 

1104class ShareNetworkSubnetMetadata(BASE, ManilaBase): 

1105 """Represents a metadata key/value pair for a subnet.""" 

1106 __tablename__ = 'share_network_subnet_metadata' 

1107 id = Column(Integer, primary_key=True) 

1108 key = Column(String(255), nullable=False) 

1109 value = Column(String(1023), nullable=False) 

1110 deleted = Column(String(36), default='False') 

1111 share_network_subnet_id = Column(String(36), ForeignKey( 

1112 'share_network_subnets.id'), nullable=False) 

1113 

1114 share_network_subnet = orm.relationship( 

1115 ShareNetworkSubnet, 

1116 backref=orm.backref('share_network_subnet_metadata', lazy='immediate'), 

1117 foreign_keys=share_network_subnet_id, 

1118 primaryjoin='and_(' 

1119 'ShareNetworkSubnetMetadata.share_network_subnet_id == ' 

1120 'ShareNetworkSubnet.id,' 

1121 'ShareNetworkSubnetMetadata.deleted == "False")') 

1122 

1123 

1124class ShareServer(BASE, ManilaBase): 

1125 """Represents share server used by share.""" 

1126 __tablename__ = 'share_servers' 

1127 id = Column(String(36), primary_key=True, nullable=False) 

1128 deleted = Column(String(36), default='False') 

1129 host = Column(String(255), nullable=False) 

1130 is_auto_deletable = Column(Boolean, default=True) 

1131 identifier = Column(String(255), nullable=True) 

1132 task_state = Column(String(255), nullable=True) 

1133 source_share_server_id = Column(String(36), ForeignKey('share_servers.id'), 

1134 nullable=True) 

1135 security_service_update_support = Column( 

1136 Boolean, nullable=False, default=False) 

1137 network_allocation_update_support = Column( 

1138 Boolean, nullable=False, default=False) 

1139 share_replicas_migration_support = Column( 

1140 Boolean, nullable=False, default=False) 

1141 encryption_key_ref = Column(String(36), nullable=True) 

1142 application_credential_id = Column(String(36), nullable=True) 

1143 status = Column(Enum( 

1144 constants.STATUS_INACTIVE, constants.STATUS_ACTIVE, 

1145 constants.STATUS_ERROR, constants.STATUS_DELETING, 

1146 constants.STATUS_CREATING, constants.STATUS_DELETED, 

1147 constants.STATUS_MANAGING, constants.STATUS_UNMANAGING, 

1148 constants.STATUS_UNMANAGE_ERROR, constants.STATUS_MANAGE_ERROR, 

1149 constants.STATUS_SERVER_MIGRATING, 

1150 constants.STATUS_SERVER_MIGRATING_TO, 

1151 constants.STATUS_SERVER_NETWORK_CHANGE), 

1152 default=constants.STATUS_INACTIVE) 

1153 network_allocations = orm.relationship( 

1154 "NetworkAllocation", 

1155 primaryjoin='and_(' 

1156 'ShareServer.id == NetworkAllocation.share_server_id,' 

1157 'NetworkAllocation.deleted == "False")') 

1158 share_instances = orm.relationship( 

1159 "ShareInstance", 

1160 backref='share_server', 

1161 primaryjoin='and_(' 

1162 'ShareServer.id == ShareInstance.share_server_id,' 

1163 'ShareInstance.deleted == "False")') 

1164 

1165 share_groups = orm.relationship( 

1166 "ShareGroup", 

1167 backref='share_server', 

1168 primaryjoin='and_(' 

1169 'ShareServer.id == ShareGroup.share_server_id,' 

1170 'ShareGroup.deleted == "False")') 

1171 

1172 _backend_details = orm.relationship( 

1173 "ShareServerBackendDetails", 

1174 lazy='immediate', 

1175 viewonly=True, 

1176 primaryjoin='and_(' 

1177 'ShareServer.id == ' 

1178 'ShareServerBackendDetails.share_server_id, ' 

1179 'ShareServerBackendDetails.deleted == "False")') 

1180 

1181 _share_network_subnet_ids = orm.relationship( 

1182 "ShareServerShareNetworkSubnetMapping", 

1183 lazy='immediate', 

1184 viewonly=True, 

1185 primaryjoin='and_(' 

1186 'ShareServer.id == ' 

1187 'ShareServerShareNetworkSubnetMapping.share_server_id,' 

1188 'ShareServerShareNetworkSubnetMapping.deleted == 0)') 

1189 

1190 @property 

1191 def backend_details(self): 

1192 return {model['key']: model['value'] 

1193 for model in self._backend_details} 

1194 

1195 @property 

1196 def share_network_subnet_ids(self): 

1197 return [model['share_network_subnet_id'] 

1198 for model in self._share_network_subnet_ids] 

1199 

1200 @property 

1201 def share_network_id(self): 

1202 return (self.share_network_subnets[0]['share_network_id'] 

1203 if self.share_network_subnets else None) 

1204 

1205 _extra_keys = ['backend_details', 'share_network_subnet_ids'] 

1206 

1207 

1208class EncryptionRef(BASE, ManilaBase): 

1209 """Represents a share server with encryption keys.""" 

1210 __tablename__ = 'encryption_refs' 

1211 id = Column(String(36), primary_key=True, nullable=False) 

1212 share_server_id = Column( 

1213 String(36), ForeignKey('share_servers.id'), unique=True) 

1214 share_instance_id = Column( 

1215 String(36), ForeignKey('share_instances.id'), unique=True) 

1216 encryption_key_ref = Column(String(36), nullable=True) 

1217 project_id = Column(String(255), nullable=True) 

1218 deleted = Column(String(36), default='False') 

1219 

1220 share_server = orm.relationship( 

1221 ShareServer, 

1222 backref=orm.backref( 

1223 'server_encryption_ref_entry', lazy='joined', uselist=False), 

1224 foreign_keys=share_server_id, 

1225 primaryjoin='and_(' 

1226 'EncryptionRef.share_server_id == ShareServer.id,' 

1227 'EncryptionRef.deleted == "False")' 

1228 ) 

1229 

1230 share_instance = orm.relationship( 

1231 ShareInstance, 

1232 backref=orm.backref( 

1233 'instance_encryption_ref_entry', lazy='joined', uselist=False), 

1234 foreign_keys=share_instance_id, 

1235 primaryjoin='and_(' 

1236 'EncryptionRef.share_instance_id == ShareInstance.id,' 

1237 'EncryptionRef.deleted == "False")' 

1238 ) 

1239 

1240 

1241class ShareServerBackendDetails(BASE, ManilaBase): 

1242 """Represents a metadata key/value pair for a share server.""" 

1243 __tablename__ = 'share_server_backend_details' 

1244 deleted = Column(String(36), default='False') 

1245 id = Column(Integer, primary_key=True) 

1246 key = Column(String(255), nullable=False) 

1247 value = Column(String(1023), nullable=False) 

1248 share_server_id = Column(String(36), ForeignKey('share_servers.id'), 

1249 nullable=False) 

1250 

1251 

1252class ShareServerShareNetworkSubnetMapping(BASE, ManilaBase): 

1253 """Represents the Share Server and Share Network Subnet mapping.""" 

1254 __tablename__ = 'share_server_share_network_subnet_mappings' 

1255 id = Column(Integer, primary_key=True) 

1256 share_server_id = Column( 

1257 String(36), ForeignKey('share_servers.id'), nullable=False) 

1258 share_network_subnet_id = Column( 

1259 String(36), ForeignKey('share_network_subnets.id'), nullable=False) 

1260 

1261 

1262class ShareNetworkSecurityServiceAssociation(BASE, ManilaBase): 

1263 """Association table between compute_zones and compute_nodes tables.""" 

1264 

1265 __tablename__ = 'share_network_security_service_association' 

1266 

1267 id = Column(Integer, primary_key=True) 

1268 share_network_id = Column(String(36), 

1269 ForeignKey('share_networks.id'), 

1270 nullable=False) 

1271 security_service_id = Column(String(36), 

1272 ForeignKey('security_services.id'), 

1273 nullable=False) 

1274 

1275 

1276class Transfer(BASE, ManilaBase): 

1277 """Represents a share transfer request.""" 

1278 

1279 __tablename__ = 'transfers' 

1280 

1281 id = Column(String(36), primary_key=True, nullable=False) 

1282 deleted = Column(String(36), default='False') 

1283 # resource type can be "share" or "share_network" 

1284 resource_type = Column(String(36), nullable=False) 

1285 # The uuid of the related resource. 

1286 resource_id = Column(String(36), nullable=False) 

1287 display_name = Column(String(255)) 

1288 salt = Column(String(255)) 

1289 crypt_hash = Column(String(255)) 

1290 expires_at = Column(DateTime) 

1291 source_project_id = Column(String(255), nullable=True) 

1292 destination_project_id = Column(String(255), nullable=True) 

1293 accepted = Column(Boolean, default=False) 

1294 

1295 

1296class NetworkAllocation(BASE, ManilaBase): 

1297 """Represents network allocation data.""" 

1298 __tablename__ = 'network_allocations' 

1299 id = Column(String(36), primary_key=True, nullable=False) 

1300 deleted = Column(String(36), default='False') 

1301 label = Column(String(255), nullable=True) 

1302 ip_address = Column(String(64), nullable=True) 

1303 ip_version = Column(Integer, nullable=True) 

1304 cidr = Column(String(64), nullable=True) 

1305 gateway = Column(String(64), nullable=True) 

1306 mtu = Column(Integer, nullable=True) 

1307 network_type = Column(String(32), nullable=True) 

1308 segmentation_id = Column(Integer, nullable=True) 

1309 mac_address = Column(String(32), nullable=True) 

1310 share_server_id = Column(String(36), ForeignKey('share_servers.id'), 

1311 nullable=False) 

1312 

1313 # NOTE(felipe_rodrigues): admin allocation does not have subnet. 

1314 share_network_subnet_id = Column( 

1315 String(36), ForeignKey('share_network_subnets.id'), nullable=True) 

1316 

1317 

1318class DriverPrivateData(BASE, ManilaBase): 

1319 """Represents a private data as key-value pairs for a driver.""" 

1320 __tablename__ = 'drivers_private_data' 

1321 entity_uuid = Column(String(36), nullable=False, primary_key=True) 

1322 key = Column(String(255), nullable=False, primary_key=True) 

1323 value = Column(String(1023), nullable=False) 

1324 

1325 

1326class AvailabilityZone(BASE, ManilaBase): 

1327 """Represents a private data as key-value pairs for a driver.""" 

1328 __tablename__ = 'availability_zones' 

1329 __table_args__ = ( 

1330 schema.UniqueConstraint('name', 'deleted', name='az_name_uc'), 

1331 ) 

1332 id = Column(String(36), primary_key=True, nullable=False) 

1333 deleted = Column(String(36), default='False') 

1334 name = Column(String(255), nullable=False) 

1335 

1336 

1337class ShareGroupTypes(BASE, ManilaBase): 

1338 """Represent possible share group types of shares offered.""" 

1339 __tablename__ = "share_group_types" 

1340 __table_args__ = ( 

1341 schema.UniqueConstraint( 

1342 "name", "deleted", name="uniq_share_group_type_name"), 

1343 ) 

1344 id = Column(String(36), primary_key=True) 

1345 deleted = Column(String(36), default='False') 

1346 name = Column(String(255)) 

1347 is_public = Column(Boolean, default=True) 

1348 

1349 

1350class ShareGroup(BASE, ManilaBase): 

1351 """Represents a share group.""" 

1352 __tablename__ = 'share_groups' 

1353 _extra_keys = [ 

1354 'availability_zone', 

1355 ] 

1356 id = Column(String(36), primary_key=True) 

1357 user_id = Column(String(255), nullable=False) 

1358 project_id = Column(String(255), nullable=False) 

1359 deleted = Column(String(36), default='False') 

1360 host = Column(String(255)) 

1361 name = Column(String(255)) 

1362 description = Column(String(255)) 

1363 status = Column(String(255)) 

1364 source_share_group_snapshot_id = Column(String(36)) 

1365 share_network_id = Column( 

1366 String(36), ForeignKey('share_networks.id'), nullable=True) 

1367 share_server_id = Column( 

1368 String(36), ForeignKey('share_servers.id'), nullable=True) 

1369 share_group_type_id = Column( 

1370 String(36), ForeignKey('share_group_types.id'), nullable=True) 

1371 availability_zone_id = Column( 

1372 String(36), ForeignKey('availability_zones.id'), nullable=True) 

1373 consistent_snapshot_support = Column(Enum('pool', 'host'), default=None) 

1374 

1375 share_group_type = orm.relationship( 

1376 ShareGroupTypes, 

1377 backref="share_groups", 

1378 foreign_keys=share_group_type_id, 

1379 primaryjoin="and_(" 

1380 "ShareGroup.share_group_type_id ==" 

1381 "ShareGroupTypes.id," 

1382 "ShareGroup.deleted == 'False')") 

1383 _availability_zone = orm.relationship( 

1384 "AvailabilityZone", 

1385 lazy='immediate', 

1386 foreign_keys=availability_zone_id, 

1387 primaryjoin=( 

1388 "and_(" 

1389 "ShareGroup.availability_zone_id == AvailabilityZone.id, " 

1390 "AvailabilityZone.deleted == 'False')")) 

1391 

1392 @property 

1393 def availability_zone(self): 

1394 if self._availability_zone: 1394 ↛ 1395line 1394 didn't jump to line 1395 because the condition on line 1394 was never true

1395 return self._availability_zone['name'] 

1396 

1397 

1398class ShareGroupTypeProjects(BASE, ManilaBase): 

1399 """Represent projects associated share group types.""" 

1400 __tablename__ = "share_group_type_projects" 

1401 __table_args__ = (schema.UniqueConstraint( 

1402 "share_group_type_id", "project_id", "deleted", 

1403 name=("uniq_share_group_type_projects0share_group_type_id" 

1404 "0project_id0deleted")), 

1405 ) 

1406 id = Column(Integer, primary_key=True) 

1407 share_group_type_id = Column( 

1408 String, ForeignKey('share_group_types.id'), nullable=False) 

1409 project_id = Column(String(255)) 

1410 share_group_type = orm.relationship( 

1411 ShareGroupTypes, 

1412 backref="projects", 

1413 foreign_keys=share_group_type_id, 

1414 primaryjoin='and_(' 

1415 'ShareGroupTypeProjects.share_group_type_id == ' 

1416 'ShareGroupTypes.id,' 

1417 'ShareGroupTypeProjects.deleted == 0)') 

1418 

1419 

1420class ShareGroupTypeSpecs(BASE, ManilaBase): 

1421 """Represents additional specs for a share group type.""" 

1422 __tablename__ = 'share_group_type_specs' 

1423 id = Column(Integer, primary_key=True) 

1424 key = Column("spec_key", String(255)) 

1425 value = Column("spec_value", String(255)) 

1426 share_group_type_id = Column( 

1427 String(36), ForeignKey('share_group_types.id'), nullable=False) 

1428 share_group_type = orm.relationship( 

1429 ShareGroupTypes, 

1430 backref="group_specs", 

1431 foreign_keys=share_group_type_id, 

1432 primaryjoin='and_(' 

1433 'ShareGroupTypeSpecs.share_group_type_id == ShareGroupTypes.id,' 

1434 'ShareGroupTypeSpecs.deleted == 0)' 

1435 ) 

1436 

1437 

1438class ShareGroupSnapshot(BASE, ManilaBase): 

1439 """Represents a share group snapshot.""" 

1440 __tablename__ = 'share_group_snapshots' 

1441 id = Column(String(36), primary_key=True) 

1442 share_group_id = Column(String(36), ForeignKey('share_groups.id')) 

1443 user_id = Column(String(255), nullable=False) 

1444 project_id = Column(String(255), nullable=False) 

1445 deleted = Column(String(36), default='False') 

1446 name = Column(String(255)) 

1447 description = Column(String(255)) 

1448 status = Column(String(255)) 

1449 share_group = orm.relationship( 

1450 ShareGroup, 

1451 backref=orm.backref("snapshots", lazy='joined'), 

1452 foreign_keys=share_group_id, 

1453 primaryjoin=('and_(' 

1454 'ShareGroupSnapshot.share_group_id == ShareGroup.id,' 

1455 'ShareGroupSnapshot.deleted == "False")') 

1456 ) 

1457 

1458 

1459class ShareGroupTypeShareTypeMapping(BASE, ManilaBase): 

1460 """Represents the share types supported by a share group type.""" 

1461 __tablename__ = 'share_group_type_share_type_mappings' 

1462 id = Column(String(36), primary_key=True) 

1463 deleted = Column(String(36), default='False') 

1464 share_group_type_id = Column( 

1465 String(36), ForeignKey('share_group_types.id'), nullable=False) 

1466 share_type_id = Column( 

1467 String(36), ForeignKey('share_types.id'), nullable=False) 

1468 share_group_type = orm.relationship( 

1469 ShareGroupTypes, 

1470 backref="share_types", 

1471 foreign_keys=share_group_type_id, 

1472 primaryjoin=('and_(' 

1473 'ShareGroupTypeShareTypeMapping.share_group_type_id ' 

1474 '== ShareGroupTypes.id,' 

1475 'ShareGroupTypeShareTypeMapping.deleted == "False")') 

1476 ) 

1477 

1478 

1479class ShareGroupShareTypeMapping(BASE, ManilaBase): 

1480 """Represents the share types in a share group.""" 

1481 __tablename__ = 'share_group_share_type_mappings' 

1482 id = Column(String(36), primary_key=True) 

1483 deleted = Column(String(36), default='False') 

1484 share_group_id = Column( 

1485 String(36), ForeignKey('share_groups.id'), nullable=False) 

1486 share_type_id = Column( 

1487 String(36), ForeignKey('share_types.id'), nullable=False) 

1488 share_group = orm.relationship( 

1489 ShareGroup, 

1490 backref="share_types", 

1491 foreign_keys=share_group_id, 

1492 primaryjoin=('and_(' 

1493 'ShareGroupShareTypeMapping.share_group_id ' 

1494 '== ShareGroup.id,' 

1495 'ShareGroupShareTypeMapping.deleted == "False")') 

1496 ) 

1497 

1498 

1499class Message(BASE, ManilaBase): 

1500 """Represents a user message. 

1501 

1502 User messages show information about API operations to the API end-user. 

1503 """ 

1504 __tablename__ = 'messages' 

1505 id = Column(String(36), primary_key=True, nullable=False) 

1506 project_id = Column(String(255), nullable=False) 

1507 # Info/Error/Warning. 

1508 message_level = Column(String(255), nullable=False) 

1509 request_id = Column(String(255), nullable=True) 

1510 resource_type = Column(String(255)) 

1511 # The uuid of the related resource. 

1512 resource_id = Column(String(36), nullable=True) 

1513 # Operation specific action ID, this ID is mapped 

1514 # to a message in manila/message/message_field.py 

1515 action_id = Column(String(10), nullable=False) 

1516 # After this time the message may no longer exist. 

1517 expires_at = Column(DateTime, nullable=True) 

1518 # Message detail ID, this ID is mapped 

1519 # to a message in manila/message/message_field.py 

1520 detail_id = Column(String(10), nullable=True) 

1521 deleted = Column(String(36), default='False') 

1522 

1523 

1524class ResourceLock(BASE, ManilaBase): 

1525 """Represents a resource lock. 

1526 

1527 Resource locks are held by users (or on behalf of users) and prevent 

1528 actions to be performed on resources while the lock is present. 

1529 """ 

1530 __tablename__ = 'resource_locks' 

1531 id = Column(String(36), primary_key=True, nullable=False) 

1532 user_id = Column(String(255), nullable=False) 

1533 project_id = Column(String(255), nullable=False) 

1534 # If the lock is held on behalf of the user, but created by 'service' or 

1535 # 'admin' users, as opposed to the user themselves ('project') 

1536 lock_context = Column(String(10), nullable=False) 

1537 # The uuid of the resource being locked. 

1538 resource_id = Column(String(36), nullable=False) 

1539 # The resource type, a constant dict will hold possible values 

1540 resource_type = Column(Enum(*constants.RESOURCE_LOCK_RESOURCE_TYPES), 

1541 default=constants.SHARE_RESOURCE_TYPE) 

1542 # Action that lock prevents, a constant dict will hold possible values 

1543 resource_action = Column(Enum(*constants.RESOURCE_LOCK_RESOURCE_ACTIONS), 

1544 default=constants.RESOURCE_ACTION_DELETE) 

1545 lock_reason = Column(String(1023), nullable=True) 

1546 deleted = Column(String(36), default='False') 

1547 

1548 

1549class BackendInfo(BASE, ManilaBase): 

1550 """Represent Backend Info.""" 

1551 __tablename__ = "backend_info" 

1552 host = Column(String(255), primary_key=True) 

1553 info_hash = Column(String(255)) 

1554 

1555 

1556class AsynchronousOperationData(BASE, ManilaBase): 

1557 """Represents data as key-value pairs for asynchronous operations.""" 

1558 __tablename__ = 'async_operation_data' 

1559 entity_uuid = Column(String(36), nullable=False, primary_key=True) 

1560 key = Column(String(255), nullable=False, primary_key=True) 

1561 value = Column(String(1023), nullable=False) 

1562 

1563 

1564class ShareBackup(BASE, ManilaBase): 

1565 """Represents a backup of a share.""" 

1566 __tablename__ = 'share_backups' 

1567 id = Column(String(36), primary_key=True) 

1568 

1569 @property 

1570 def name(self): 

1571 return CONF.share_backup_name_template % self.id 

1572 

1573 @property 

1574 def availability_zone(self): 

1575 if self._availability_zone: 

1576 return self._availability_zone['name'] 

1577 

1578 deleted = Column(String(36), default='False') 

1579 user_id = Column(String(255), nullable=False) 

1580 project_id = Column(String(255), nullable=False) 

1581 

1582 share_id = Column(String(36), ForeignKey('shares.id')) 

1583 size = Column(Integer) 

1584 host = Column(String(255)) 

1585 topic = Column(String(255)) 

1586 display_name = Column(String(255)) 

1587 display_description = Column(String(255)) 

1588 progress = Column(String(32)) 

1589 restore_progress = Column(String(32)) 

1590 status = Column(String(255)) 

1591 fail_reason = Column(String(1023)) 

1592 backup_type = Column(String(32)) 

1593 availability_zone_id = Column(String(36), 

1594 ForeignKey('availability_zones.id'), 

1595 nullable=True) 

1596 

1597 _availability_zone = orm.relationship( 

1598 "AvailabilityZone", 

1599 lazy='immediate', 

1600 primaryjoin=( 

1601 'and_(' 

1602 'ShareBackup.availability_zone_id == ' 

1603 'AvailabilityZone.id, ' 

1604 'AvailabilityZone.deleted == \'False\')' 

1605 ) 

1606 ) 

1607 

1608 

1609def register_models(): 

1610 """Register Models and create metadata. 

1611 

1612 Called from manila.db.sqlalchemy.__init__ as part of loading the driver, 

1613 it will never need to be called explicitly elsewhere unless the 

1614 connection is lost and needs to be reestablished. 

1615 """ 

1616 from sqlalchemy import create_engine 

1617 models = (Service, 

1618 Share, 

1619 ShareAccessMapping, 

1620 ShareSnapshot 

1621 ) 

1622 engine = create_engine(CONF.database.connection, echo=False) 

1623 for model in models: 

1624 model.metadata.create_all(engine) 

1625 

1626 

1627def get_access_rules_status(instances): 

1628 share_access_status = constants.STATUS_ACTIVE 

1629 

1630 if len(instances) == 0: 

1631 return share_access_status 

1632 

1633 priorities = ShareInstance.ACCESS_STATUS_PRIORITIES 

1634 

1635 for instance in instances: 

1636 if instance['status'] != constants.STATUS_AVAILABLE: 

1637 continue 

1638 

1639 instance_access_status = instance['access_rules_status'] 

1640 

1641 if priorities.get(instance_access_status) > priorities.get( 

1642 share_access_status): 

1643 share_access_status = instance_access_status 

1644 

1645 if share_access_status == constants.SHARE_INSTANCE_RULES_ERROR: 

1646 break 

1647 

1648 return share_access_status 

1649 

1650 

1651def get_aggregated_access_rules_state(instance_mappings): 

1652 state = None 

1653 if len(instance_mappings) > 0: 1653 ↛ 1667line 1653 didn't jump to line 1667 because the condition on line 1653 was always true

1654 order = (constants.ACCESS_STATE_ERROR, 

1655 constants.ACCESS_STATE_DENYING, 

1656 constants.ACCESS_STATE_QUEUED_TO_DENY, 

1657 constants.ACCESS_STATE_QUEUED_TO_UPDATE, 

1658 constants.ACCESS_STATE_QUEUED_TO_APPLY, 

1659 constants.ACCESS_STATE_UPDATING, 

1660 constants.ACCESS_STATE_APPLYING, 

1661 constants.ACCESS_STATE_ACTIVE) 

1662 

1663 sorted_instance_mappings = sorted( 

1664 instance_mappings, key=lambda x: order.index(x['state'])) 

1665 

1666 state = sorted_instance_mappings[0].state 

1667 return state