| // 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; | |
| import static org.junit.Assert.assertFalse; | |
| import static org.junit.Assert.assertTrue; | |
| import com.cloud.upgrade.dao.VersionDao; | |
| import com.cloud.upgrade.dao.VersionDaoImpl; | |
| import com.cloud.upgrade.dao.VersionVO; | |
| import com.cloud.utils.db.GlobalLock; | |
| import org.junit.Test; | |
| public class DatabaseUpgradeCheckerDoUpgradesTest { | |
| static class StubVersionDao extends VersionDaoImpl implements VersionDao { | |
| private final String currentVersion; | |
| StubVersionDao(String currentVersion) { | |
| this.currentVersion = currentVersion; | |
| } | |
| @Override | |
| public VersionVO findByVersion(String version, VersionVO.Step step) { | |
| return null; | |
| } | |
| @Override | |
| public String getCurrentVersion() { | |
| return currentVersion; | |
| } | |
| } | |
| private static class TestableChecker extends DatabaseUpgradeChecker { | |
| boolean initializeCalled = false; | |
| boolean upgradeCalled = false; | |
| boolean clusterHandlerCalled = false; | |
| String implVersionOverride = null; | |
| String sysVmMetadataOverride = "4.8.0"; | |
| boolean standaloneOverride = true; | |
| TestableChecker(String daoVersion) { | |
| // set a stub DAO | |
| this._dao = new StubVersionDao(daoVersion); | |
| } | |
| @Override | |
| protected void initializeDatabaseEncryptors() { | |
| initializeCalled = true; | |
| // noop instead of doing DB work | |
| } | |
| @Override | |
| protected String getImplementationVersion() { | |
| return implVersionOverride; | |
| } | |
| @Override | |
| protected String parseSystemVmMetadata() { | |
| return sysVmMetadataOverride; | |
| } | |
| @Override | |
| boolean isStandalone() { | |
| return standaloneOverride; | |
| } | |
| @Override | |
| protected void upgrade(org.apache.cloudstack.utils.CloudStackVersion dbVersion, org.apache.cloudstack.utils.CloudStackVersion currentVersion) { | |
| upgradeCalled = true; | |
| } | |
| @Override | |
| protected void handleClusteredUpgradeRequired() { | |
| clusterHandlerCalled = true; | |
| } | |
| } | |
| @Test | |
| public void testDoUpgrades_noImplementationVersion_returnsEarly() { | |
| TestableChecker checker = new TestableChecker("4.8.0"); | |
| checker.implVersionOverride = ""; // blank -> should return early | |
| GlobalLock lock = GlobalLock.getInternLock("test-noimpl"); | |
| try { | |
| // acquire lock so doUpgrades can safely call unlock in finally | |
| lock.lock(1); | |
| checker.doUpgrades(lock); | |
| } finally { | |
| // ensure lock released if still held | |
| lock.releaseRef(); | |
| } | |
| assertTrue("initializeDatabaseEncryptors should be called before returning", checker.initializeCalled); | |
| assertFalse("upgrade should not be called when implementation version is blank", checker.upgradeCalled); | |
| assertFalse("cluster handler should not be called", checker.clusterHandlerCalled); | |
| } | |
| @Test | |
| public void testDoUpgrades_dbUpToDate_noUpgrade() { | |
| // DB version = code version -> no upgrade | |
| TestableChecker checker = new TestableChecker("4.8.1"); | |
| checker.implVersionOverride = "4.8.1"; | |
| checker.sysVmMetadataOverride = "4.8.1"; | |
| GlobalLock lock = GlobalLock.getInternLock("test-uptodate"); | |
| try { | |
| lock.lock(1); | |
| checker.doUpgrades(lock); | |
| } finally { | |
| lock.releaseRef(); | |
| } | |
| assertTrue(checker.initializeCalled); | |
| assertFalse(checker.upgradeCalled); | |
| assertFalse(checker.clusterHandlerCalled); | |
| } | |
| @Test | |
| public void testDoUpgrades_requiresUpgrade_standalone_invokesUpgrade() { | |
| TestableChecker checker = new TestableChecker("4.8.0"); | |
| checker.implVersionOverride = "4.8.2"; // code is newer than DB | |
| checker.sysVmMetadataOverride = "4.8.2"; | |
| checker.standaloneOverride = true; | |
| GlobalLock lock = GlobalLock.getInternLock("test-upgrade-standalone"); | |
| try { | |
| lock.lock(1); | |
| checker.doUpgrades(lock); | |
| } finally { | |
| lock.releaseRef(); | |
| } | |
| assertTrue(checker.initializeCalled); | |
| assertTrue("upgrade should be invoked in standalone mode", checker.upgradeCalled); | |
| assertFalse(checker.clusterHandlerCalled); | |
| } | |
| @Test | |
| public void testDoUpgrades_requiresUpgrade_clustered_invokesHandler() { | |
| TestableChecker checker = new TestableChecker("4.8.0"); | |
| checker.implVersionOverride = "4.8.2"; // code is newer than DB | |
| checker.sysVmMetadataOverride = "4.8.2"; | |
| checker.standaloneOverride = false; | |
| GlobalLock lock = GlobalLock.getInternLock("test-upgrade-clustered"); | |
| try { | |
| lock.lock(1); | |
| checker.doUpgrades(lock); | |
| } finally { | |
| lock.releaseRef(); | |
| } | |
| assertTrue(checker.initializeCalled); | |
| assertFalse("upgrade should not be invoked in clustered mode", checker.upgradeCalled); | |
| assertTrue("cluster handler should be invoked in clustered mode", checker.clusterHandlerCalled); | |
| } | |
| } |