blob: 11bc9b6911476c3bd3a0105dd73d2e2a236fb469 [file] [log] [blame]
package org.apache.helix.integration;
/*
* 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.
*/
import org.apache.helix.HelixDataAccessor;
import org.apache.helix.HelixManager;
import org.apache.helix.controller.rebalancer.strategy.CrushEdRebalanceStrategy;
import org.apache.helix.integration.common.ZkStandAloneCMTestBase;
import org.apache.helix.model.IdealState;
import org.testng.Assert;
import org.testng.annotations.Test;
public class TestSwapInstance extends ZkStandAloneCMTestBase {
@Test
public void testSwapInstance() throws Exception {
HelixManager manager = _controller;
HelixDataAccessor dataAccessor = manager.getHelixDataAccessor();
// Create semi auto resource
_gSetupTool.addResourceToCluster(CLUSTER_NAME, "db-semi", 64, STATE_MODEL,
IdealState.RebalanceMode.SEMI_AUTO.name());
_gSetupTool.rebalanceStorageCluster(CLUSTER_NAME, "db-semi", _replica);
// Create customized resource
_gSetupTool.addResourceToCluster(CLUSTER_NAME, "db-customized", 64, STATE_MODEL,
IdealState.RebalanceMode.CUSTOMIZED.name());
_gSetupTool.rebalanceStorageCluster(CLUSTER_NAME, "db-customized", _replica);
// Create full-auto resource
_gSetupTool.addResourceToCluster(CLUSTER_NAME, "db-fa", 64, STATE_MODEL,
IdealState.RebalanceMode.FULL_AUTO.name(), CrushEdRebalanceStrategy.class.getName());
_gSetupTool.rebalanceStorageCluster(CLUSTER_NAME, "db-fa", _replica);
// Wait for cluster converge
Assert.assertTrue(_clusterVerifier.verifyByPolling());
// Get ideal states before swap
IdealState semiIS = dataAccessor.getProperty(dataAccessor.keyBuilder().idealStates("db-semi"));
IdealState customizedIS =
dataAccessor.getProperty(dataAccessor.keyBuilder().idealStates("db-customized"));
IdealState faIs =
dataAccessor.getProperty(dataAccessor.keyBuilder().idealStates("db-fa"));
String oldInstanceName = String.format("%s_%s", PARTICIPANT_PREFIX, START_PORT);
String newInstanceName = String.format("%s_%s", PARTICIPANT_PREFIX, 66666);
try {
_gSetupTool.swapInstance(CLUSTER_NAME, oldInstanceName, newInstanceName);
Assert.fail("Cannot swap as new instance is not added to cluster yet");
} catch (Exception e) {
// OK - new instance not added to cluster yet
}
// Add new instance to cluster
_gSetupTool.addInstanceToCluster(CLUSTER_NAME, newInstanceName);
try {
_gSetupTool.swapInstance(CLUSTER_NAME, oldInstanceName, newInstanceName);
Assert.fail("Cannot swap as old instance is still alive");
} catch (Exception e) {
// OK - old instance still alive
}
// Stop old instance
_participants[0].syncStop();
Assert.assertTrue(_clusterVerifier.verifyByPolling());
try {
_gSetupTool.swapInstance(CLUSTER_NAME, oldInstanceName, newInstanceName);
Assert.fail("Cannot swap as old instance is still enabled");
} catch (Exception e) {
// OK - old instance still alive
}
// disable old instance
_gSetupTool.getClusterManagementTool().enableInstance(CLUSTER_NAME, oldInstanceName, false);
Assert.assertTrue(_clusterVerifier.verifyByPolling());
// We can swap now
_gSetupTool.swapInstance(CLUSTER_NAME, oldInstanceName, newInstanceName);
// verify cluster
Assert.assertTrue(_clusterVerifier.verifyByPolling());
verifySwapInstance(dataAccessor, "db-semi", semiIS, oldInstanceName, newInstanceName, false);
verifySwapInstance(dataAccessor, "db-customized", customizedIS, oldInstanceName, newInstanceName,
false);
verifySwapInstance(dataAccessor, "db-fa", faIs, oldInstanceName, newInstanceName, true);
// Verify idempotency
_gSetupTool.swapInstance(CLUSTER_NAME, oldInstanceName, newInstanceName);
verifySwapInstance(dataAccessor, "db-semi", semiIS, oldInstanceName, newInstanceName, false);
verifySwapInstance(dataAccessor, "db-customized", customizedIS, oldInstanceName, newInstanceName,
false);
verifySwapInstance(dataAccessor, "db-fa", faIs, oldInstanceName, newInstanceName, true);
}
private void verifySwapInstance(HelixDataAccessor dataAccessor, String resourceName,
IdealState oldIs, String oldInstance, String newInstance, boolean isFullAuto) {
IdealState newIs = dataAccessor.getProperty(dataAccessor.keyBuilder().idealStates(resourceName));
if (isFullAuto) {
// Full auto resource should not contain new instance as it's not live yet
for (String key : newIs.getRecord().getMapFields().keySet()) {
Assert.assertFalse(newIs.getRecord().getMapField(key).keySet().contains(newInstance));
}
for (String key : newIs.getRecord().getListFields().keySet()) {
Assert.assertFalse(newIs.getRecord().getListField(key).contains(newInstance));
}
} else {
verifyIdealStateWithSwappedInstance(oldIs, newIs, oldInstance, newInstance);
}
}
private void verifyIdealStateWithSwappedInstance(IdealState oldIs, IdealState newIs,
String oldInstance, String newInstance) {
// Verify map fields
for (String key : oldIs.getRecord().getMapFields().keySet()) {
for (String host : oldIs.getRecord().getMapField(key).keySet()) {
if (host.equals(oldInstance)) {
Assert.assertTrue(oldIs.getRecord().getMapField(key).get(oldInstance)
.equals(newIs.getRecord().getMapField(key).get(newInstance)));
} else {
Assert.assertTrue(oldIs.getRecord().getMapField(key).get(host)
.equals(newIs.getRecord().getMapField(key).get(host)));
}
}
}
// verify list fields
for (String key : oldIs.getRecord().getListFields().keySet()) {
Assert.assertEquals(oldIs.getRecord().getListField(key).size(), newIs.getRecord()
.getListField(key).size());
for (int i = 0; i < oldIs.getRecord().getListField(key).size(); i++) {
String host = oldIs.getRecord().getListField(key).get(i);
String newHost = newIs.getRecord().getListField(key).get(i);
if (host.equals(oldInstance)) {
Assert.assertTrue(newHost.equals(newInstance));
} else {
Assert.assertTrue(host.equals(newHost));
}
}
}
}
}