Coverage for manila/db/migrations/alembic/versions/1f0bd302c1a6_add_availability_zones_table.py: 100%

47 statements  

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

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

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

3# a copy of the License at 

4# 

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

6# 

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

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

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

10# License for the specific language governing permissions and limitations 

11# under the License. 

12 

13"""add_availability_zones_table 

14 

15Revision ID: 1f0bd302c1a6 

16Revises: 579c267fbb4d 

17Create Date: 2015-07-24 12:09:36.008570 

18 

19""" 

20 

21# revision identifiers, used by Alembic. 

22revision = '1f0bd302c1a6' 

23down_revision = '579c267fbb4d' 

24 

25from alembic import op 

26from oslo_utils import timeutils 

27from oslo_utils import uuidutils 

28from sqlalchemy import Column, DateTime, ForeignKey, String, UniqueConstraint 

29 

30from manila.db.migrations import utils 

31 

32 

33def collect_existing_az_from_services_table(connection, services_table, 

34 az_table): 

35 az_name_to_id_mapping = dict() 

36 existing_az = [] 

37 for service in connection.execute(services_table.select()): 

38 if service.availability_zone in az_name_to_id_mapping: 

39 continue 

40 

41 az_id = uuidutils.generate_uuid() 

42 az_name_to_id_mapping[service.availability_zone] = az_id 

43 existing_az.append({ 

44 'created_at': timeutils.utcnow(), 

45 'id': az_id, 

46 'name': service.availability_zone 

47 }) 

48 

49 op.bulk_insert(az_table, existing_az) 

50 

51 return az_name_to_id_mapping 

52 

53 

54def upgrade(): 

55 connection = op.get_bind() 

56 

57 # Create new AZ table and columns 

58 availability_zones_table = op.create_table( 

59 'availability_zones', 

60 Column('created_at', DateTime), 

61 Column('updated_at', DateTime), 

62 Column('deleted_at', DateTime), 

63 Column('deleted', String(length=36), default='False'), 

64 Column('id', String(length=36), primary_key=True, nullable=False), 

65 Column('name', String(length=255)), 

66 UniqueConstraint('name', 'deleted', name='az_name_uc'), 

67 mysql_engine='InnoDB', 

68 mysql_charset='utf8') 

69 

70 for table_name, fk_name in (('services', 'service_az_id_fk'), 

71 ('share_instances', 'si_az_id_fk')): 

72 op.add_column( 

73 table_name, 

74 Column('availability_zone_id', String(36), 

75 ForeignKey('availability_zones.id', name=fk_name)) 

76 ) 

77 

78 # Collect existing AZs from services table 

79 services_table = utils.load_table('services', connection) 

80 az_name_to_id_mapping = collect_existing_az_from_services_table( 

81 connection, services_table, availability_zones_table) 

82 

83 # Map string AZ names to ID's in target tables 

84 # pylint: disable=no-value-for-parameter 

85 set_az_id_in_table = lambda table, id, name: ( # noqa: E731 

86 op.execute( 

87 table.update().where(table.c.availability_zone == name).values( 

88 {'availability_zone_id': id}) 

89 ) 

90 ) 

91 

92 share_instances_table = utils.load_table('share_instances', connection) 

93 for name, id in az_name_to_id_mapping.items(): 

94 for table_name in [services_table, share_instances_table]: 

95 set_az_id_in_table(table_name, id, name) 

96 

97 # Remove old AZ columns from tables 

98 op.drop_column('services', 'availability_zone') 

99 op.drop_column('share_instances', 'availability_zone') 

100 

101 

102def downgrade(): 

103 connection = op.get_bind() 

104 

105 # Create old AZ fields 

106 op.add_column('services', Column('availability_zone', String(length=255))) 

107 op.add_column('share_instances', 

108 Column('availability_zone', String(length=255))) 

109 

110 # Migrate data 

111 az_table = utils.load_table('availability_zones', connection) 

112 share_instances_table = utils.load_table('share_instances', connection) 

113 services_table = utils.load_table('services', connection) 

114 

115 for az in connection.execute(az_table.select()): 

116 # pylint: disable=no-value-for-parameter 

117 op.execute( 

118 share_instances_table.update().where( 

119 share_instances_table.c.availability_zone_id == az.id 

120 ).values({'availability_zone': az.name}) 

121 ) 

122 op.execute( 

123 services_table.update().where( 

124 services_table.c.availability_zone_id == az.id 

125 ).values({'availability_zone': az.name}) 

126 ) 

127 

128 # Remove AZ_id columns and AZ table 

129 op.drop_constraint('service_az_id_fk', 'services', type_='foreignkey') 

130 op.drop_column('services', 'availability_zone_id') 

131 op.drop_constraint('si_az_id_fk', 'share_instances', type_='foreignkey') 

132 op.drop_column('share_instances', 'availability_zone_id') 

133 op.drop_table('availability_zones')