|
20 | 20 |
|
21 | 21 | import java.io.InputStream; |
22 | 22 | import java.sql.Connection; |
| 23 | +import java.sql.PreparedStatement; |
| 24 | +import java.sql.ResultSet; |
| 25 | +import java.sql.SQLException; |
| 26 | +import java.util.ArrayList; |
23 | 27 |
|
24 | 28 | public class Upgrade42005to42006 extends DbUpgradeAbstractImpl { |
25 | 29 |
|
| 30 | + private static final String SELECT_OFFERING = "SELECT `id` FROM `cloud`.`backup_offering` WHERE `external_id` IS NULL AND `provider`= \"knib\";"; |
| 31 | + |
| 32 | + private static final String SELECT_NATIVE_OFFERING = "SELECT `uuid` FROM `cloud`.`native_backup_offering` WHERE `name` = 'Standard' AND `removed` IS NULL;"; |
| 33 | + |
| 34 | + private static final String UPDATE_OFFERING = "UPDATE `cloud`.`backup_offering` SET `external_id`=\"%s\" WHERE `id` IN (%s);"; |
| 35 | + |
| 36 | + private static final String INSERT_OFFERING = "INSERT INTO `cloud`.`native_backup_offering` (uuid, name, compress, validate, allow_quick_restore, allow_extract_file, created) " + |
| 37 | + "VALUES (uuid(), 'Standard', false, false, false, false, now());"; |
| 38 | + |
26 | 39 | @Override |
27 | 40 | public String[] getUpgradableVersionRange() { |
28 | 41 | return new String[] {"4.20.0.5", "4.20.0.6"}; |
@@ -51,6 +64,85 @@ public InputStream[] getPrepareScripts() { |
51 | 64 |
|
52 | 65 | @Override |
53 | 66 | public void performDataMigration(Connection conn) { |
| 67 | + normalizeBackupOfferingsIfNeeded(conn); |
| 68 | + } |
| 69 | + |
| 70 | + private void normalizeBackupOfferingsIfNeeded(Connection conn) { |
| 71 | + ArrayList<Long> ids = new ArrayList<>(); |
| 72 | + try (PreparedStatement pstmt = conn.prepareStatement(SELECT_OFFERING)) { |
| 73 | + ResultSet result = pstmt.executeQuery(); |
| 74 | + while (result.next()) { |
| 75 | + Long id = result.getLong("id"); |
| 76 | + logger.info("Got backup offering with ID [{}] that has no external_id. Will configure it with the standard offering.", id); |
| 77 | + ids.add(id); |
| 78 | + } |
| 79 | + if (ids.isEmpty()) { |
| 80 | + logger.debug("Found no backup offerings to normalize."); |
| 81 | + return; |
| 82 | + } |
| 83 | + } catch (SQLException e) { |
| 84 | + String message = String.format("Unable to retrieve backup offerings due to [%s].", e.getMessage()); |
| 85 | + logger.error(message, e); |
| 86 | + throw new CloudRuntimeException(message, e); |
| 87 | + } |
| 88 | + |
| 89 | + String uuid; |
| 90 | + try (PreparedStatement pstmt = conn.prepareStatement(SELECT_NATIVE_OFFERING)) { |
| 91 | + ResultSet result = pstmt.executeQuery(); |
| 92 | + if (!result.next()) { |
| 93 | + result = createStandardOffering(conn); |
| 94 | + } |
| 95 | + uuid = result.getString("uuid"); |
| 96 | + } catch (SQLException e) { |
| 97 | + String message = String.format("Unable to retrieve Standard native backup offering due to [%s].", e.getMessage()); |
| 98 | + logger.error(message, e); |
| 99 | + throw new CloudRuntimeException(message, e); |
| 100 | + } |
| 101 | + |
| 102 | + StringBuilder stringBuilder = new StringBuilder(); |
| 103 | + for (Long id : ids) { |
| 104 | + stringBuilder.append(id); |
| 105 | + stringBuilder.append(","); |
| 106 | + } |
| 107 | + stringBuilder.delete((stringBuilder.length() - 1), stringBuilder.length()); |
| 108 | + String update = String.format(UPDATE_OFFERING, uuid, stringBuilder); |
| 109 | + |
| 110 | + logger.debug("Executing update [{}].", update); |
| 111 | + try (PreparedStatement pstmt = conn.prepareStatement(update)) { |
| 112 | + int rows = pstmt.executeUpdate(); |
| 113 | + if (rows != ids.size()) { |
| 114 | + throw new CloudRuntimeException("We should have updated the same amount of rows as we informed in the id list. Rows:"+rows +"Ids:"+ids.size()); |
| 115 | + } |
| 116 | + } catch (SQLException e) { |
| 117 | + String message = String.format("Unable to update backup offerings due to [%s].", e.getMessage()); |
| 118 | + logger.error(message, e); |
| 119 | + throw new CloudRuntimeException(message, e); |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + private ResultSet createStandardOffering(Connection conn) { |
| 124 | + logger.warn("Found backup offerings that are inconsistent, but the Standard native backup offering does not exist. Will create it again."); |
| 125 | + try (PreparedStatement pstmt = conn.prepareStatement(INSERT_OFFERING)) { |
| 126 | + pstmt.executeUpdate(); |
| 127 | + } catch (SQLException e) { |
| 128 | + String message = String.format("Unable to insert native backup offering due to [%s].", e.getMessage()); |
| 129 | + logger.error(message, e); |
| 130 | + throw new CloudRuntimeException(message, e); |
| 131 | + } |
| 132 | + |
| 133 | + try (PreparedStatement pstmt = conn.prepareStatement(SELECT_NATIVE_OFFERING)) { |
| 134 | + ResultSet resultSet = pstmt.executeQuery(); |
| 135 | + if (!resultSet.next()) { |
| 136 | + String message = "Unable to find native backup offering that was just inserted."; |
| 137 | + logger.error(message); |
| 138 | + throw new CloudRuntimeException(message); |
| 139 | + } |
| 140 | + return resultSet; |
| 141 | + } catch (SQLException e) { |
| 142 | + String message = String.format("Unable to retrieve native backup offering due to [%s].", e.getMessage()); |
| 143 | + logger.error(message, e); |
| 144 | + throw new CloudRuntimeException(message, e); |
| 145 | + } |
54 | 146 | } |
55 | 147 |
|
56 | 148 | @Override |
|
0 commit comments