Coverage for manila/db/migrations/alembic/versions/a87e0fb17dee_multiple_share_server_subnets.py: 73%

92 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"""multiple share server subnets 

14 

15Revision ID: a87e0fb17dee 

16Revises: 1946cb97bb8d 

17Create Date: 2022-01-14 06:12:27.596130 

18 

19""" 

20 

21# revision identifiers, used by Alembic. 

22revision = 'a87e0fb17dee' 

23down_revision = '1946cb97bb8d' 

24 

25 

26from alembic import op 

27from oslo_log import log 

28import sqlalchemy as sa 

29 

30from manila.db.migrations import utils 

31 

32 

33SHARE_SERVERS_TABLE = 'share_servers' 

34SHARE_SERVER_SUBNET_MAP_TABLE = 'share_server_share_network_subnet_mappings' 

35NETWORK_ALLOCATIONS_TABLE = 'network_allocations' 

36LOG = log.getLogger(__name__) 

37 

38 

39def upgrade(): 

40 

41 # Create mappings table. 

42 context = op.get_context() 

43 mysql_dl = context.bind.dialect.name == 'mysql' 

44 datetime_type = (sa.dialects.mysql.DATETIME(fsp=6) 

45 if mysql_dl else sa.DateTime) 

46 try: 

47 share_server_fk_name = "fk_ss_sns_m_share_server_id_share_servers" 

48 share_network_subnet_fk_name = ( 

49 "fk_ss_sns_m_share_network_subnet_id_share_network_subnets") 

50 server_subnet_mappings_table = op.create_table( 

51 SHARE_SERVER_SUBNET_MAP_TABLE, 

52 sa.Column('id', sa.Integer, primary_key=True, nullable=False), 

53 sa.Column('created_at', datetime_type), 

54 sa.Column('updated_at', datetime_type), 

55 sa.Column('deleted_at', datetime_type), 

56 sa.Column('deleted', sa.Integer, default=0), 

57 sa.Column( 

58 'share_server_id', sa.String(length=36), 

59 sa.ForeignKey('share_servers.id', name=share_server_fk_name), 

60 nullable=False), 

61 sa.Column( 

62 'share_network_subnet_id', sa.String(length=36), 

63 sa.ForeignKey('share_network_subnets.id', 

64 name=share_network_subnet_fk_name), 

65 nullable=False), 

66 mysql_engine='InnoDB', 

67 mysql_charset='utf8') 

68 except Exception: 

69 LOG.error('Table %s could not be created.', 

70 SHARE_SERVER_SUBNET_MAP_TABLE) 

71 raise 

72 

73 # Populate the mappings table from the share servers table. 

74 try: 

75 connection = op.get_bind() 

76 share_servers_table = utils.load_table(SHARE_SERVERS_TABLE, connection) 

77 server_subnet_mappings = [] 

78 for server in connection.execute(share_servers_table.select()): 

79 if server.share_network_subnet_id: 

80 server_subnet_mappings.append({ 

81 'created_at': server.created_at, 

82 'updated_at': server.updated_at, 

83 'deleted_at': server.deleted_at, 

84 'deleted': 0 if server.deleted == 'False' else 1, 

85 'share_server_id': server.id, 

86 'share_network_subnet_id': server.share_network_subnet_id, 

87 }) 

88 op.bulk_insert(server_subnet_mappings_table, server_subnet_mappings) 

89 except Exception: 

90 LOG.error('Table %s could not be populated from the %s table.', 

91 SHARE_SERVER_SUBNET_MAP_TABLE, SHARE_SERVERS_TABLE) 

92 raise 

93 

94 # add subnet id column to the allocations table. 

95 try: 

96 network_allocation_fk_name = ( 

97 "fk_network_allocation_subnet_id_share_network_subnets") 

98 op.add_column( 

99 NETWORK_ALLOCATIONS_TABLE, 

100 sa.Column('share_network_subnet_id', sa.String(length=36), 

101 sa.ForeignKey('share_network_subnets.id', 

102 name=network_allocation_fk_name)) 

103 ) 

104 except Exception: 

105 LOG.error("Could not add ForeignKey column 'share_network_subnet_id'" 

106 "to table %s.", NETWORK_ALLOCATIONS_TABLE) 

107 raise 

108 

109 # populate the allocation with its subnet id using the share server. 

110 network_allocation_table = utils.load_table(NETWORK_ALLOCATIONS_TABLE, 

111 connection) 

112 for alloc in connection.execute(network_allocation_table.select()): 

113 # admin allocations should not contain subnet id. 

114 if alloc._mapping['label'] == 'admin': 

115 continue 

116 

117 server = connection.execute( 

118 share_servers_table.select().where( 

119 alloc._mapping['share_server_id'] == ( 

120 share_servers_table.c.id))).first() 

121 

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

123 op.execute(network_allocation_table.update().where( 

124 alloc._mapping['id'] == network_allocation_table.c.id).values( 

125 {'share_network_subnet_id': 

126 server._mapping['share_network_subnet_id']})) 

127 

128 # add a new column to share_servers. 

129 try: 

130 op.add_column( 

131 SHARE_SERVERS_TABLE, 

132 sa.Column('network_allocation_update_support', sa.Boolean, 

133 nullable=False, server_default=sa.sql.false())) 

134 except Exception: 

135 LOG.error("Table %s could not add column " 

136 "'network_allocation_update_support'.", 

137 SHARE_SERVERS_TABLE) 

138 raise 

139 

140 # drop subnet id foreign key from share servers. 

141 try: 

142 share_serves_fk_name = ( 

143 "fk_share_servers_share_network_subnet_id_share_network_subnets") 

144 if connection.engine.name == 'mysql': 

145 op.drop_constraint(share_serves_fk_name, SHARE_SERVERS_TABLE, 

146 type_="foreignkey") 

147 op.drop_column(SHARE_SERVERS_TABLE, 'share_network_subnet_id') 

148 except Exception: 

149 LOG.error("Table %s could not drop column 'share_network_subnet_id'.", 

150 SHARE_SERVERS_TABLE) 

151 raise 

152 

153 

154def downgrade(): 

155 """Remove share_server_share_network_subnet_mapping table and new columns. 

156 

157 This method can lead to data loss because the share server can have 

158 more than one subnet. 

159 """ 

160 try: 

161 share_serves_fk_name = ( 

162 "fk_share_servers_share_network_subnet_id_share_network_subnets") 

163 op.add_column( 

164 SHARE_SERVERS_TABLE, 

165 sa.Column( 

166 'share_network_subnet_id', sa.String(36), 

167 sa.ForeignKey('share_network_subnets.id', 

168 name=share_serves_fk_name), 

169 ) 

170 ) 

171 

172 connection = op.get_bind() 

173 server_subnet_mappings_table = utils.load_table( 

174 SHARE_SERVER_SUBNET_MAP_TABLE, connection) 

175 share_servers_table = utils.load_table(SHARE_SERVERS_TABLE, 

176 connection) 

177 

178 with sa.orm.Session(bind=op.get_bind()) as session: 

179 for server in connection.execute(share_servers_table.select()): 

180 subnets = session.query( 

181 server_subnet_mappings_table).filter( 

182 server._mapping['id'] == ( 

183 server_subnet_mappings_table.c.share_server_id) 

184 ).all() 

185 

186 if server._mapping['deleted'] != 'False' and len(subnets) > 1: 186 ↛ 187line 186 didn't jump to line 187 because the condition on line 186 was never true

187 LOG.warning('Share server %s is not deleted and it ' 

188 'has more than one subnet (%s subnets), ' 

189 'the downgrade may cause an inconsistent ' 

190 'environment.', 

191 server._mapping['id'], len(subnets)) 

192 

193 subnet_id = ( 

194 subnets[0].share_network_subnet_id if subnets else None 

195 ) 

196 

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

198 op.execute(share_servers_table.update().where( 

199 server._mapping['id'] == share_servers_table.c.id).values( 

200 {'share_network_subnet_id': subnet_id})) 

201 

202 except Exception: 

203 LOG.error("'share_network_subnet_id' field in the %s table could not " 

204 "be created and populated from %s table.", 

205 SHARE_SERVERS_TABLE, SHARE_SERVER_SUBNET_MAP_TABLE) 

206 raise 

207 

208 try: 

209 op.drop_table(SHARE_SERVER_SUBNET_MAP_TABLE) 

210 except Exception: 

211 LOG.error("Failed to drop table %s.", SHARE_SERVER_SUBNET_MAP_TABLE) 

212 raise 

213 

214 try: 

215 op.drop_column(SHARE_SERVERS_TABLE, 

216 'network_allocation_update_support') 

217 except Exception: 

218 LOG.error("Table %s failed to drop the column " 

219 "'network_allocation_update_support'.", SHARE_SERVERS_TABLE) 

220 raise 

221 

222 try: 

223 network_allocation_fk_name = ( 

224 "fk_network_allocation_subnet_id_share_network_subnets") 

225 if connection.engine.name == 'mysql': 

226 op.drop_constraint(network_allocation_fk_name, 

227 NETWORK_ALLOCATIONS_TABLE, 

228 type_="foreignkey") 

229 op.drop_column(NETWORK_ALLOCATIONS_TABLE, 'share_network_subnet_id') 

230 except Exception: 

231 LOG.error("Column 'network_allocations.share_network_subnet_id' from " 

232 "table %s failed to drop.", NETWORK_ALLOCATIONS_TABLE) 

233 raise