Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public class RollingUpgradeCommandTest extends GridCommandHandlerClusterByClassA
/** */
public static final String DISABLE = "disable";

/** */
public static final String FORCE = "--force";

/** */
public static final String ROLLING_UPGRADE = "--rolling-upgrade";

Expand All @@ -43,6 +46,14 @@ public class RollingUpgradeCommandTest extends GridCommandHandlerClusterByClassA
autoConfirmation = true;
}

/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
super.afterTest();

if (crd.context().rollingUpgrade().enabled())
crd.context().rollingUpgrade().disable();
}

/** */
@Test
public void testEnableAndDisable() {
Expand Down Expand Up @@ -127,4 +138,43 @@ public void testEnableWithDifferentTargetVersions() {

assertTrue(crd.context().rollingUpgrade().enabled());
}

/** */
@Test
public void testForceEnable() {
IgniteProductVersion curVer = IgniteProductVersion.fromString(crd.localNode().attribute(ATTR_BUILD_VER));

String targetVerStr = curVer.major() + "." + (curVer.minor() + 1) + "." + (curVer.maintenance() + 1);
IgniteProductVersion targetVer = IgniteProductVersion.fromString(targetVerStr);

int res = execute(ROLLING_UPGRADE, ENABLE, targetVerStr);

assertEquals(EXIT_CODE_OK, res);

RollingUpgradeTaskResult taskRes = (RollingUpgradeTaskResult)lastOperationResult;

assertNotNull(taskRes.errorMessage());
assertTrue(taskRes.errorMessage().contains("Minor version can only be incremented by 1"));
assertNull(taskRes.targetVersion());

String anotherTargetVerStr = curVer.major() + "." + curVer.minor() + "." + (curVer.maintenance() + 1);

execute(ROLLING_UPGRADE, ENABLE, targetVerStr, FORCE);

taskRes = (RollingUpgradeTaskResult)lastOperationResult;
assertNull(taskRes.errorMessage());

res = execute(ROLLING_UPGRADE, ENABLE, anotherTargetVerStr, FORCE);

assertEquals(EXIT_CODE_OK, res);
taskRes = (RollingUpgradeTaskResult)lastOperationResult;

assertNotNull(taskRes.errorMessage());
assertTrue(taskRes.errorMessage().contains("Rolling upgrade is already enabled with a different current and target version"));

assertEquals(curVer, taskRes.currentVersion());
assertEquals(targetVer, taskRes.targetVersion());

assertTrue(crd.context().rollingUpgrade().enabled());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public class RollingUpgradeEnableCommandArg extends IgniteDataTransferObject {
+ "or one maintenance version higher (e.g. 2.18.0 -> 2.18.1 or 2.18.1 -> 2.19.0)")
private String targetVersion;

/** Force flag. */
@Argument(description = "Enable rolling upgrade without target version checks."
+ " Use only when required, if the upgrade cannot proceed otherwise", optional = true)
private boolean force;

/** */
public String targetVersion() {
return targetVersion;
Expand All @@ -46,13 +51,25 @@ public void targetVersion(String targetVersion) {
this.targetVersion = targetVersion;
}

/** */
public boolean force() {
return force;
}

/** */
public void force(boolean force) {
this.force = force;
}

/** {@inheritDoc} */
@Override protected void writeExternalData(ObjectOutput out) throws IOException {
U.writeString(out, targetVersion);
out.writeBoolean(force);
}

/** {@inheritDoc} */
@Override protected void readExternalData(ObjectInput in) throws IOException, ClassNotFoundException {
targetVersion = U.readString(in);
force = in.readBoolean();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected RollingUpgradeEnableJob(RollingUpgradeEnableCommandArg arg, boolean de
RollingUpgradeProcessor proc = ignite.context().rollingUpgrade();

try {
proc.enable(IgniteProductVersion.fromString(arg.targetVersion()));
proc.enable(IgniteProductVersion.fromString(arg.targetVersion()), arg.force());

IgnitePair<IgniteProductVersion> rollUpVers = proc.versions();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ public RollingUpgradeProcessor(GridKernalContext ctx) {
* This method can only be called on coordinator node with {@link TcpDiscoverySpi}.
*
* @param target Target version.
* @param force If {@code true}, skips target version compatibility checks and forcibly enables rolling upgrade.
* This flag does not override an already active upgrade configuration.
* @throws IgniteCheckedException If:
* <ul>
* <li>The current and target versions are incompatible;</li>
Expand All @@ -163,7 +165,7 @@ public RollingUpgradeProcessor(GridKernalContext ctx) {
* <li>The distributed metastorage is not ready;</li>
* </ul>
*/
public void enable(IgniteProductVersion target) throws IgniteCheckedException {
public void enable(IgniteProductVersion target, boolean force) throws IgniteCheckedException {
if (startLatch.getCount() > 0)
throw new IgniteCheckedException("Cannot enable rolling upgrade: processor has not been started yet");

Expand All @@ -179,7 +181,7 @@ public void enable(IgniteProductVersion target) throws IgniteCheckedException {
String curBuildVer = ctx.discovery().localNode().attribute(ATTR_BUILD_VER);
IgniteProductVersion curVer = IgniteProductVersion.fromString(curBuildVer);

if (!checkVersionsForEnabling(curVer, target))
if (!checkVersionsForEnabling(curVer, target, force))
return;

IgnitePair<IgniteProductVersion> newPair = F.pair(curVer, target);
Expand Down Expand Up @@ -278,10 +280,14 @@ public boolean enabled() {
*
* @param cur Current cluster version.
* @param target Target cluster version.
* @return {@code false} if there is no need to update versions {@code true} otherwise.
* @param force Force flag to skip version checks.
* @throws IgniteCheckedException If versions are incorrect.
*/
private boolean checkVersionsForEnabling(IgniteProductVersion cur, IgniteProductVersion target) throws IgniteCheckedException {
private boolean checkVersionsForEnabling(
IgniteProductVersion cur,
IgniteProductVersion target,
boolean force
) throws IgniteCheckedException {
IgnitePair<IgniteProductVersion> oldVerPair = rollUpVers;
if (oldVerPair != null) {
if (oldVerPair.get1().equals(cur) && oldVerPair.get2().equals(target))
Expand All @@ -291,6 +297,14 @@ private boolean checkVersionsForEnabling(IgniteProductVersion cur, IgniteProduct
oldVerPair.get1() + " , " + oldVerPair.get2());
}

if (force) {
if (log.isInfoEnabled())
log.info("Skipping version compatibility check for rolling upgrade due to force flag "
+ "[currentVer=" + cur + ", targetVer=" + target + ']');

return true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add log here that we skip checking versions due to force flag

}

if (cur.major() != target.major())
throw new IgniteCheckedException("Major versions are different");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,26 @@ public void testThreeCompatibleVersions() throws Exception {
/** */
@Test
public void testForwardRollingUpgrade() throws Exception {
cleanPersistenceDir();
IgniteEx ign0 = startGrid(0, "2.18.0", false);
IgniteEx ign1 = startGrid(1, "2.18.0", client);
IgniteEx ign2 = startGrid(2, "2.18.0", client);
doTestRollingUpgrade("2.18.0", "2.18.1", false);
}

/** */
@Test
public void testForceRollingUpgrade() throws Exception {
doTestRollingUpgrade("2.18.0", "2.19.1", true);
}

/** Performs full rolling upgrade scenario. */
private void doTestRollingUpgrade(String curVer, String targetVer, boolean force) throws Exception {
IgniteEx ign0 = startGrid(0, curVer, false);
IgniteEx ign1 = startGrid(1, curVer, client);
IgniteEx ign2 = startGrid(2, curVer, client);

assertClusterSize(3);

assertRemoteRejected(() -> startGrid(3, "2.18.1", client));
assertRemoteRejected(() -> startGrid(3, targetVer, client));

configureRollingUpgradeVersion(ign0, "2.18.1");
configureRollingUpgradeVersion(ign0, targetVer, force);

for (int i = 0; i < 3; i++) {
int finalI = i;
Expand All @@ -165,23 +175,23 @@ public void testForwardRollingUpgrade() throws Exception {

assertClusterSize(2);

startGrid(2, "2.18.1", client);
startGrid(2, targetVer, client);

assertClusterSize(3);

ign1.close();

assertClusterSize(2);

startGrid(1, "2.18.1", client);
startGrid(1, targetVer, client);

assertClusterSize(3);

ign0.close();

assertClusterSize(2);

startGrid(0, "2.18.1", false);
startGrid(0, targetVer, false);

assertClusterSize(3);

Expand All @@ -195,7 +205,7 @@ public void testForwardRollingUpgrade() throws Exception {
assertFalse(grid(i).context().rollingUpgrade().enabled());
}

assertRemoteRejected(() -> startGrid(3, "2.18.0", client));
assertRemoteRejected(() -> startGrid(3, curVer, client));
}

/** */
Expand Down Expand Up @@ -315,7 +325,7 @@ public void testRollingUpgradeProcessorVersionCheck() throws Exception {
IgnitePair<IgniteProductVersion> newPair = F.pair(IgniteProductVersion.fromString("2.18.0"),
IgniteProductVersion.fromString("2.19.0"));

grid0.context().rollingUpgrade().enable(newPair.get2());
grid0.context().rollingUpgrade().enable(newPair.get2(), false);

assertEnablingFails(grid0, "2.18.1", "Rolling upgrade is already enabled with a different current and target version");

Expand All @@ -335,7 +345,7 @@ public void testRollingUpgradeProcessorVersionCheck() throws Exception {
*/
private void assertEnablingFails(IgniteEx ex, String ver, String errMsg) {
Throwable e = assertThrows(log,
() -> ex.context().rollingUpgrade().enable(IgniteProductVersion.fromString(ver)),
() -> ex.context().rollingUpgrade().enable(IgniteProductVersion.fromString(ver), false),
IgniteException.class,
null);

Expand Down Expand Up @@ -470,18 +480,24 @@ private IgniteEx startGrid(int idx, String ver, boolean isClient, UnaryOperator<
return ign;
}

/** */
private void configureRollingUpgradeVersion(IgniteEx grid, String ver) throws IgniteCheckedException {
configureRollingUpgradeVersion(grid, ver, false);
}

/**
* @param ver Version for rolling upgrade support.
* @param force Force rolling upgrade.
*/
private void configureRollingUpgradeVersion(IgniteEx grid, String ver) throws IgniteCheckedException {
private void configureRollingUpgradeVersion(IgniteEx grid, String ver, boolean force) throws IgniteCheckedException {
if (ver == null) {
grid.context().rollingUpgrade().disable();
return;
}

IgniteProductVersion target = IgniteProductVersion.fromString(ver);

grid.context().rollingUpgrade().enable(target);
grid.context().rollingUpgrade().enable(target, force);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,11 @@ If the file name isn't specified the output file name is: '<typeId>.bin':

[EXPERIMENTAL]
Enable rolling upgrade mode. It allows cluster with mixed-version nodes:
control.(sh|bat) --rolling-upgrade enable target_version
control.(sh|bat) --rolling-upgrade enable target_version [--force]

Parameters:
target_version - Target Ignite version. The target version can be one minor higher if its maintenance version is zero, or one maintenance version higher (e.g. 2.18.0 -> 2.18.1 or 2.18.1 -> 2.19.0).
--force - Enable rolling upgrade without target version checks. Use only when required, if the upgrade cannot proceed otherwise.

[EXPERIMENTAL]
Disable rolling upgrade mode. All nodes in the cluster must be running the same version:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,11 @@ If the file name isn't specified the output file name is: '<typeId>.bin':

[EXPERIMENTAL]
Enable rolling upgrade mode. It allows cluster with mixed-version nodes:
control.(sh|bat) --rolling-upgrade enable target_version
control.(sh|bat) --rolling-upgrade enable target_version [--force]

Parameters:
target_version - Target Ignite version. The target version can be one minor higher if its maintenance version is zero, or one maintenance version higher (e.g. 2.18.0 -> 2.18.1 or 2.18.1 -> 2.19.0).
--force - Enable rolling upgrade without target version checks. Use only when required, if the upgrade cannot proceed otherwise.

[EXPERIMENTAL]
Disable rolling upgrade mode. All nodes in the cluster must be running the same version:
Expand Down
Loading