diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index a8a166fbf275..bc2042551987 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -33,6 +33,7 @@ import javax.inject.Inject; +import com.cloud.upgrade.dao.Upgrade42010to42020; import com.cloud.upgrade.dao.Upgrade42020to42030; import com.cloud.utils.FileUtil; import org.apache.cloudstack.utils.CloudStackVersion; @@ -237,6 +238,7 @@ public DatabaseUpgradeChecker() { .next("4.19.0.0", new Upgrade41900to41910()) .next("4.19.1.0", new Upgrade41910to42000()) .next("4.20.0.0", new Upgrade42000to42010()) + .next("4.20.1.0", new Upgrade42010to42020()) .next("4.20.2.0", new Upgrade42020to42030()) .build(); } diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42010to42020.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42010to42020.java new file mode 100644 index 000000000000..664c435de3c3 --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42010to42020.java @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.upgrade.dao; + +import java.io.InputStream; +import java.sql.Connection; + +public class Upgrade42010to42020 extends DbUpgradeAbstractImpl implements DbUpgrade { + + @Override + public String[] getUpgradableVersionRange() { + return new String[]{"4.20.1.0", "4.20.2.0"}; + } + + @Override + public String getUpgradedVersion() { + return "4.20.2.0"; + } + + @Override + public boolean supportsRollingUpgrade() { + return false; + } + + @Override + public InputStream[] getPrepareScripts() { + return new InputStream[0]; + } + + @Override + public void performDataMigration(Connection conn) { + } + + @Override + public InputStream[] getCleanupScripts() { + return new InputStream[0]; + } +} diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql b/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql index 3dd6c18f57c5..4405250f2711 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42000to42010.sql @@ -31,7 +31,7 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.account', 'api_key_access', 'boolean CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" '); -- Create a new group for Usage Server related configurations -INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Usage Server', 'Usage Server related configuration', 9); +INSERT IGNORE INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Usage Server', 'Usage Server related configuration', 9); UPDATE `cloud`.`configuration_subgroup` set `group_id` = (SELECT `id` FROM `cloud`.`configuration_group` WHERE `name` = 'Usage Server'), `precedence` = 1 WHERE `name`='Usage'; UPDATE `cloud`.`configuration` SET `group_id` = (SELECT `id` FROM `cloud`.`configuration_group` WHERE `name` = 'Usage Server') where `subgroup_id` = (SELECT `id` FROM `cloud`.`configuration_subgroup` WHERE `name` = 'Usage'); diff --git a/engine/schema/src/test/java/com/cloud/upgrade/DatabaseUpgradeCheckerTest.java b/engine/schema/src/test/java/com/cloud/upgrade/DatabaseUpgradeCheckerTest.java index 27995eb179af..2fc94d1ff052 100644 --- a/engine/schema/src/test/java/com/cloud/upgrade/DatabaseUpgradeCheckerTest.java +++ b/engine/schema/src/test/java/com/cloud/upgrade/DatabaseUpgradeCheckerTest.java @@ -51,6 +51,8 @@ import com.cloud.upgrade.dao.Upgrade470to471; import com.cloud.upgrade.dao.Upgrade471to480; import com.cloud.upgrade.dao.Upgrade480to481; +import com.cloud.upgrade.dao.Upgrade42010to42020; +import com.cloud.upgrade.dao.Upgrade42020to42030; import com.cloud.upgrade.dao.Upgrade490to4910; import com.cloud.utils.db.TransactionLegacy; @@ -360,6 +362,42 @@ public void testCalculateUpgradePathFromSecurityReleaseToNextSecurityRelease() { assertTrue(upgradesFromSecurityReleaseToNext[upgradesFromSecurityReleaseToNext.length - 1] instanceof NoopDbUpgrade); } + @Test + public void testCalculateUpgradePath42010to42030() { + // Regression test for: missing 4.20.1.0 node in upgrade hierarchy + // caused direct 4.20.1.0 -> 4.20.3.0 upgrade to re-run Upgrade42000to42010 + // and fail with duplicate key on configuration_group.name='Usage Server' + final CloudStackVersion dbVersion = CloudStackVersion.parse("4.20.1.0"); + assertNotNull(dbVersion); + + final CloudStackVersion currentVersion = CloudStackVersion.parse("4.20.3.0"); + assertNotNull(currentVersion); + + final DatabaseUpgradeChecker checker = new DatabaseUpgradeChecker(); + final DbUpgrade[] upgrades = checker.calculateUpgradePath(dbVersion, currentVersion); + + assertNotNull(upgrades); + assertEquals("Direct upgrade from 4.20.1.0 to 4.20.3.0 should have exactly 2 steps", 2, upgrades.length); + assertTrue("First step should be Upgrade42010to42020", upgrades[0] instanceof Upgrade42010to42020); + assertTrue("Second step should be Upgrade42020to42030", upgrades[1] instanceof Upgrade42020to42030); + } + + @Test + public void testCalculateUpgradePath42020to42030() { + final CloudStackVersion dbVersion = CloudStackVersion.parse("4.20.2.0"); + assertNotNull(dbVersion); + + final CloudStackVersion currentVersion = CloudStackVersion.parse("4.20.3.0"); + assertNotNull(currentVersion); + + final DatabaseUpgradeChecker checker = new DatabaseUpgradeChecker(); + final DbUpgrade[] upgrades = checker.calculateUpgradePath(dbVersion, currentVersion); + + assertNotNull(upgrades); + assertEquals("Upgrade from 4.20.2.0 to 4.20.3.0 should have exactly 1 step", 1, upgrades.length); + assertTrue("Only step should be Upgrade42020to42030", upgrades[0] instanceof Upgrade42020to42030); + } + @Test public void isStandalone() throws SQLException { // simulate zero 'UP' hosts -> standalone