Coverage for manila/db/migrations/alembic/versions/5077ffcc5f1c_add_share_instances.py: 100%

93 statements  

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

1# Copyright 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 

16"""add_share_instances 

17 

18Revision ID: 5077ffcc5f1c 

19Revises: 3db9992c30f3 

20Create Date: 2015-06-26 12:54:55.630152 

21 

22""" 

23 

24# revision identifiers, used by Alembic. 

25revision = '5077ffcc5f1c' 

26down_revision = '3db9992c30f3' 

27 

28 

29from alembic import op 

30from sqlalchemy import Column, DateTime, ForeignKey, String 

31 

32from manila.db.migrations import utils 

33 

34 

35def create_share_instances_table(connection): 

36 # Create 'share_instances' table 

37 share_instances_table = op.create_table( 

38 'share_instances', 

39 Column('created_at', DateTime), 

40 Column('updated_at', DateTime), 

41 Column('deleted_at', DateTime), 

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

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

44 Column('share_id', String(length=36), 

45 ForeignKey('shares.id', name="si_share_fk")), 

46 Column('host', String(length=255)), 

47 Column('status', String(length=255)), 

48 Column('scheduled_at', DateTime), 

49 Column('launched_at', DateTime), 

50 Column('terminated_at', DateTime), 

51 Column('share_network_id', String(length=36), 

52 ForeignKey('share_networks.id', name="si_share_network_fk"), 

53 nullable=True), 

54 Column('share_server_id', String(length=36), 

55 ForeignKey('share_servers.id', name="si_share_server_fk"), 

56 nullable=True), 

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

58 mysql_engine='InnoDB', 

59 mysql_charset='utf8') 

60 

61 # Migrate data from 'shares' to 'share_instances' 

62 share_instances = [] 

63 shares_table = utils.load_table('shares', connection) 

64 for share in connection.execute(shares_table.select()): 

65 share_instances.append({ 

66 'created_at': share.created_at, 

67 'updated_at': share.updated_at, 

68 'deleted_at': share.deleted_at, 

69 'deleted': share.deleted, 

70 'id': share.id, 

71 'share_id': share.id, 

72 'host': share.host, 

73 'status': share.status, 

74 'scheduled_at': share.scheduled_at, 

75 'launched_at': share.launched_at, 

76 'terminated_at': share.terminated_at, 

77 'share_network_id': share.share_network_id, 

78 'share_server_id': share.share_server_id, 

79 'availability_zone': share.availability_zone, 

80 }) 

81 op.bulk_insert(share_instances_table, share_instances) 

82 

83 # Remove columns moved to 'share_instances' table 

84 with op.batch_alter_table("shares") as batch_op: 

85 for fk in shares_table.foreign_keys: 

86 batch_op.drop_constraint(fk.name, type_='foreignkey') 

87 

88 batch_op.drop_column('host') 

89 batch_op.drop_column('status') 

90 batch_op.drop_column('scheduled_at') 

91 batch_op.drop_column('launched_at') 

92 batch_op.drop_column('terminated_at') 

93 batch_op.drop_column('share_network_id') 

94 batch_op.drop_column('share_server_id') 

95 batch_op.drop_column('availability_zone') 

96 

97 

98def remove_share_instances_table(connection): 

99 with op.batch_alter_table("shares") as batch_op: 

100 batch_op.add_column(Column('host', String(length=255))) 

101 batch_op.add_column(Column('status', String(length=255))) 

102 batch_op.add_column(Column('scheduled_at', DateTime)) 

103 batch_op.add_column(Column('launched_at', DateTime)) 

104 batch_op.add_column(Column('terminated_at', DateTime)) 

105 batch_op.add_column(Column('share_network_id', String(length=36), 

106 ForeignKey('share_networks.id'), 

107 nullable=True)) 

108 batch_op.add_column(Column('share_server_id', String(length=36), 

109 ForeignKey('share_servers.id'), 

110 nullable=True)) 

111 batch_op.add_column(Column('availability_zone', String(length=255))) 

112 

113 shares_table = utils.load_table('shares', connection) 

114 share_inst_table = utils.load_table('share_instances', connection) 

115 

116 for share in connection.execute(shares_table.select()): 

117 instance = connection.execute( 

118 share_inst_table.select().where( 

119 share_inst_table.c.share_id == share.id) 

120 ).first() 

121 

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

123 op.execute( 

124 shares_table.update().where( 

125 shares_table.c.id == share.id 

126 ).values( 

127 { 

128 'host': instance._mapping['host'], 

129 'status': instance._mapping['status'], 

130 'scheduled_at': instance._mapping['scheduled_at'], 

131 'launched_at': instance._mapping['launched_at'], 

132 'terminated_at': instance._mapping['terminated_at'], 

133 'share_network_id': instance._mapping['share_network_id'], 

134 'share_server_id': instance._mapping['share_server_id'], 

135 'availability_zone': 

136 instance._mapping['availability_zone'], 

137 } 

138 ) 

139 ) 

140 

141 op.drop_table('share_instances') 

142 

143 

144def create_snapshot_instances_table(connection): 

145 # Create 'share_snapshot_instances' table 

146 snapshot_instances_table = op.create_table( 

147 'share_snapshot_instances', 

148 Column('created_at', DateTime), 

149 Column('updated_at', DateTime), 

150 Column('deleted_at', DateTime), 

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

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

153 Column('snapshot_id', String(length=36), 

154 ForeignKey('share_snapshots.id', name="ssi_snapshot_fk")), 

155 Column('share_instance_id', String(length=36), 

156 ForeignKey('share_instances.id', name="ssi_share_instance_fk")), 

157 Column('status', String(length=255)), 

158 Column('progress', String(length=255)), 

159 mysql_engine='InnoDB', 

160 mysql_charset='utf8' 

161 ) 

162 

163 # Migrate data from share_snapshots to share_snapshot_instances 

164 snapshot_instances = [] 

165 snapshot_table = utils.load_table('share_snapshots', connection) 

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

167 

168 for snapshot in connection.execute(snapshot_table.select()): 

169 share_instances_rows = connection.execute( 

170 share_instances_table.select().where( 

171 share_instances_table.c.share_id == snapshot.share_id 

172 ) 

173 ) 

174 snapshot_instances.append({ 

175 'created_at': snapshot.created_at, 

176 'updated_at': snapshot.updated_at, 

177 'deleted_at': snapshot.deleted_at, 

178 'deleted': snapshot.deleted, 

179 'id': snapshot.id, 

180 'snapshot_id': snapshot.id, 

181 'status': snapshot.status, 

182 'progress': snapshot.progress, 

183 'share_instance_id': share_instances_rows.first().id, 

184 }) 

185 op.bulk_insert(snapshot_instances_table, snapshot_instances) 

186 

187 # Remove columns moved to 'share_snapshot_instances' table 

188 with op.batch_alter_table("share_snapshots") as batch_op: 

189 batch_op.drop_column('status') 

190 batch_op.drop_column('progress') 

191 

192 

193def remove_snapshot_instances_table(connection): 

194 with op.batch_alter_table("share_snapshots") as batch_op: 

195 batch_op.add_column(Column('status', String(length=255))) 

196 batch_op.add_column(Column('progress', String(length=255))) 

197 

198 snapshots_table = utils.load_table('share_snapshots', connection) 

199 snapshots_inst_table = utils.load_table('share_snapshot_instances', 

200 connection) 

201 

202 for snapshot_instance in connection.execute(snapshots_inst_table.select()): 

203 snapshot = connection.execute( 

204 snapshots_table.select().where( 

205 snapshots_table.c.id == snapshot_instance.snapshot_id) 

206 ).first() 

207 

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

209 op.execute( 

210 snapshots_table.update().where( 

211 snapshots_table.c.id == snapshot.id 

212 ).values( 

213 { 

214 'status': snapshot_instance._mapping['status'], 

215 'progress': snapshot_instance._mapping['progress'], 

216 } 

217 ) 

218 ) 

219 

220 op.drop_table('share_snapshot_instances') 

221 

222 

223def upgrade_export_locations_table(connection): 

224 # Update 'share_export_locations' table 

225 op.add_column( 

226 'share_export_locations', 

227 Column('share_instance_id', String(36), 

228 ForeignKey('share_instances.id', name="sel_instance_id_fk")) 

229 ) 

230 

231 # Convert share_id to share_instance_id 

232 share_el_table = utils.load_table('share_export_locations', connection) 

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

234 for export in connection.execute(share_el_table.select()): 

235 share_instance = connection.execute( 

236 share_instances_table.select().where( 

237 share_instances_table.c.share_id == export.share_id) 

238 ).first() 

239 

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

241 op.execute( 

242 share_el_table.update().where( 

243 share_el_table.c.id == export.id 

244 ).values({'share_instance_id': str(share_instance.id)}) 

245 ) 

246 with op.batch_alter_table("share_export_locations") as batch_op: 

247 batch_op.drop_constraint('sel_id_fk', type_='foreignkey') 

248 batch_op.drop_column('share_id') 

249 

250 op.rename_table( 

251 'share_export_locations', 'share_instance_export_locations') 

252 

253 

254def downgrade_export_locations_table(connection): 

255 op.rename_table('share_instance_export_locations', 

256 'share_export_locations') 

257 op.add_column( 

258 'share_export_locations', 

259 Column('share_id', String(36), 

260 ForeignKey('shares.id', name="sel_id_fk")) 

261 ) 

262 

263 # Convert share_instance_id to share_id 

264 share_el_table = utils.load_table('share_export_locations', connection) 

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

266 for export in connection.execute(share_el_table.select()): 

267 share_instance = connection.execute( 

268 share_instances_table.select().where( 

269 share_instances_table.c.id == export.share_instance_id) 

270 ).first() 

271 

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

273 op.execute( 

274 share_el_table.update().where( 

275 share_el_table.c.id == export.id 

276 ).values({'share_id': str(share_instance.share_id)}) 

277 ) 

278 

279 with op.batch_alter_table("share_export_locations") as batch_op: 

280 batch_op.drop_constraint('sel_instance_id_fk', type_='foreignkey') 

281 batch_op.drop_column('share_instance_id') 

282 

283 

284def upgrade(): 

285 connection = op.get_bind() 

286 

287 create_share_instances_table(connection) 

288 create_snapshot_instances_table(connection) 

289 upgrade_export_locations_table(connection) 

290 

291 

292def downgrade(): 

293 """Remove share_instances and share_snapshot_instance tables. 

294 

295 This method can lead to data loss because only first share/snapshot 

296 instance is saved in shares/snapshot table. 

297 """ 

298 connection = op.get_bind() 

299 

300 downgrade_export_locations_table(connection) 

301 remove_snapshot_instances_table(connection) 

302 remove_share_instances_table(connection)