/* * Copyright (c) 2008-2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.server.upgrade.impl; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.coordinator.common.Configuration; import com.emc.storageos.coordinator.client.model.MigrationStatus; import com.emc.storageos.coordinator.client.model.Constants; import com.emc.storageos.db.common.DbConfigConstants; import com.emc.storageos.db.server.upgrade.DbStepSkipUpgradeTestBase; import com.emc.storageos.db.server.upgrade.util.callbacks2.Resource3NewFlagsInitializer; /** * test migration checkpoint */ public class DbMigrationCheckpointTest extends DbStepSkipUpgradeTestBase { private static final Logger log = LoggerFactory.getLogger(DbMigrationCheckpointTest.class); private String getCheckpoint(String version) { CoordinatorClient coordinator = getCoordinator(); Configuration config = coordinator.queryConfiguration( coordinator.getSiteId(), coordinator.getVersionedDbConfigPath(Constants.DBSVC_NAME, version), Constants.GLOBAL_ID); Assert.assertNotNull(config); return config.getConfig(DbConfigConstants.MIGRATION_CHECKPOINT); } /** * reset migration status * * @param version */ private void resetMigrationStatus(String version) { CoordinatorClient coordinator = getCoordinator(); Configuration config = coordinator.queryConfiguration(coordinator.getSiteId(), coordinator.getVersionedDbConfigPath(Constants.DBSVC_NAME, version), Constants.GLOBAL_ID); Assert.assertNotNull(config); log.info("setMigrationStatus: target version \"{}\" status {}", version, MigrationStatus.RUNNING); config.setConfig(Constants.MIGRATION_STATUS, MigrationStatus.RUNNING.name()); coordinator.persistServiceConfiguration(coordinator.getSiteId(), config); } /** * Verify if migration checkpoint information is saved to ZK * * @param version target schema version for migration */ private void verifyMigrationFailed(String version) { CoordinatorClient coordinator = getCoordinator(); Assert.assertEquals(MigrationStatus.FAILED, coordinator.getMigrationStatus()); String checkpoint = getCheckpoint(version); log.info("Current migration checkpoint: {}", checkpoint); Assert.assertNotNull(checkpoint); String failedCallbackName = com.emc.storageos.db.server.upgrade.util.callbacks2.Resource3NewFlagsInitializer.class.getSimpleName(); Assert.assertNotSame(failedCallbackName, checkpoint); } /** * Verify if migration checkpoint information is saved to ZK * * @param version target schema version for migration */ private void verifyMigrationInterrupted(String version) { CoordinatorClient coordinator = getCoordinator(); Assert.assertEquals(MigrationStatus.RUNNING, coordinator.getMigrationStatus()); String checkpoint = getCheckpoint(version); log.info("Current migration checkpoint: {}", checkpoint); Assert.assertNotNull(checkpoint); String failedCallbackName = com.emc.storageos.db.server.upgrade.util.callbacks2.Resource3NewFlagsInitializer.class.getSimpleName(); Assert.assertNotSame(failedCallbackName, checkpoint); } /** * Verify if migration checkpoint information is cleared after migration done * * @param version target schema version for migration */ private void verifyMigrationDone(String version) { CoordinatorClient coordinator = getCoordinator(); Assert.assertEquals(MigrationStatus.DONE, coordinator.getMigrationStatus()); String checkpoint = getCheckpoint(version); Assert.assertNull(checkpoint); } /** * Simulate migration failure by injecting a fault. Test if migration could restart from checkpoint * * @throws Exception */ @Test public void runMigrationCheckpointTest() throws Exception { final String targetVersion = secondUpgradeVersion; String targetDoPackage = "com.emc.storageos.db.server.upgrade.util.models.updated2"; // prepare data for version 1.2 stopAll(); setupDB(initalVersion, initalVersion, "com.emc.storageos.db.server.upgrade.util.models.old"); prepareData1(); prepareData2(); stopAll(); // fatal exception -- make sure we are moving into failed state Resource3NewFlagsInitializer.injectFatalFault = true; setupDB(initalVersion, targetVersion, targetDoPackage); verifyMigrationFailed(targetVersion); stopAll(); // reset migration state - for next test resetMigrationStatus(targetVersion); // retryable exception -- should get automatically retried Resource3NewFlagsInitializer.injectFault = true; Resource3NewFlagsInitializer.injectFatalFault = false; Resource3NewFlagsInitializer.faultInjected = false; ScheduledExecutorService exe = Executors.newScheduledThreadPool(1); exe.scheduleWithFixedDelay(new Runnable() { @Override public void run() { if (Resource3NewFlagsInitializer.faultInjected) { verifyMigrationInterrupted(targetVersion); log.info("resetting fault injection"); Resource3NewFlagsInitializer.injectFault = false; } } }, 10, 10, TimeUnit.SECONDS); setupDB(initalVersion, targetVersion, targetDoPackage); verifyAll(); verifyMigrationDone(targetVersion); stopAll(); exe.shutdownNow(); } }