Skip to content

Commit b20fe87

Browse files
authored
IGNITE-27030 Add force flag for enabling rolling upgrade (#12513)
1 parent a1abd2c commit b20fe87

File tree

7 files changed

+120
-21
lines changed

7 files changed

+120
-21
lines changed

modules/control-utility/src/test/java/org/apache/ignite/util/RollingUpgradeCommandTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public class RollingUpgradeCommandTest extends GridCommandHandlerClusterByClassA
3333
/** */
3434
public static final String DISABLE = "disable";
3535

36+
/** */
37+
public static final String FORCE = "--force";
38+
3639
/** */
3740
public static final String ROLLING_UPGRADE = "--rolling-upgrade";
3841

@@ -43,6 +46,14 @@ public class RollingUpgradeCommandTest extends GridCommandHandlerClusterByClassA
4346
autoConfirmation = true;
4447
}
4548

49+
/** {@inheritDoc} */
50+
@Override protected void afterTest() throws Exception {
51+
super.afterTest();
52+
53+
if (crd.context().rollingUpgrade().enabled())
54+
crd.context().rollingUpgrade().disable();
55+
}
56+
4657
/** */
4758
@Test
4859
public void testEnableAndDisable() {
@@ -127,4 +138,43 @@ public void testEnableWithDifferentTargetVersions() {
127138

128139
assertTrue(crd.context().rollingUpgrade().enabled());
129140
}
141+
142+
/** */
143+
@Test
144+
public void testForceEnable() {
145+
IgniteProductVersion curVer = IgniteProductVersion.fromString(crd.localNode().attribute(ATTR_BUILD_VER));
146+
147+
String targetVerStr = curVer.major() + "." + (curVer.minor() + 1) + "." + (curVer.maintenance() + 1);
148+
IgniteProductVersion targetVer = IgniteProductVersion.fromString(targetVerStr);
149+
150+
int res = execute(ROLLING_UPGRADE, ENABLE, targetVerStr);
151+
152+
assertEquals(EXIT_CODE_OK, res);
153+
154+
RollingUpgradeTaskResult taskRes = (RollingUpgradeTaskResult)lastOperationResult;
155+
156+
assertNotNull(taskRes.errorMessage());
157+
assertTrue(taskRes.errorMessage().contains("Minor version can only be incremented by 1"));
158+
assertNull(taskRes.targetVersion());
159+
160+
String anotherTargetVerStr = curVer.major() + "." + curVer.minor() + "." + (curVer.maintenance() + 1);
161+
162+
execute(ROLLING_UPGRADE, ENABLE, targetVerStr, FORCE);
163+
164+
taskRes = (RollingUpgradeTaskResult)lastOperationResult;
165+
assertNull(taskRes.errorMessage());
166+
167+
res = execute(ROLLING_UPGRADE, ENABLE, anotherTargetVerStr, FORCE);
168+
169+
assertEquals(EXIT_CODE_OK, res);
170+
taskRes = (RollingUpgradeTaskResult)lastOperationResult;
171+
172+
assertNotNull(taskRes.errorMessage());
173+
assertTrue(taskRes.errorMessage().contains("Rolling upgrade is already enabled with a different current and target version"));
174+
175+
assertEquals(curVer, taskRes.currentVersion());
176+
assertEquals(targetVer, taskRes.targetVersion());
177+
178+
assertTrue(crd.context().rollingUpgrade().enabled());
179+
}
130180
}

modules/core/src/main/java/org/apache/ignite/internal/management/rollingupgrade/RollingUpgradeEnableCommandArg.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ public class RollingUpgradeEnableCommandArg extends IgniteDataTransferObject {
3636
+ "or one maintenance version higher (e.g. 2.18.0 -> 2.18.1 or 2.18.1 -> 2.19.0)")
3737
private String targetVersion;
3838

39+
/** Force flag. */
40+
@Argument(description = "Enable rolling upgrade without target version checks."
41+
+ " Use only when required, if the upgrade cannot proceed otherwise", optional = true)
42+
private boolean force;
43+
3944
/** */
4045
public String targetVersion() {
4146
return targetVersion;
@@ -46,13 +51,25 @@ public void targetVersion(String targetVersion) {
4651
this.targetVersion = targetVersion;
4752
}
4853

54+
/** */
55+
public boolean force() {
56+
return force;
57+
}
58+
59+
/** */
60+
public void force(boolean force) {
61+
this.force = force;
62+
}
63+
4964
/** {@inheritDoc} */
5065
@Override protected void writeExternalData(ObjectOutput out) throws IOException {
5166
U.writeString(out, targetVersion);
67+
out.writeBoolean(force);
5268
}
5369

5470
/** {@inheritDoc} */
5571
@Override protected void readExternalData(ObjectInput in) throws IOException, ClassNotFoundException {
5672
targetVersion = U.readString(in);
73+
force = in.readBoolean();
5774
}
5875
}

modules/core/src/main/java/org/apache/ignite/internal/management/rollingupgrade/RollingUpgradeEnableTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ protected RollingUpgradeEnableJob(RollingUpgradeEnableCommandArg arg, boolean de
5252
RollingUpgradeProcessor proc = ignite.context().rollingUpgrade();
5353

5454
try {
55-
proc.enable(IgniteProductVersion.fromString(arg.targetVersion()));
55+
proc.enable(IgniteProductVersion.fromString(arg.targetVersion()), arg.force());
5656

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

modules/core/src/main/java/org/apache/ignite/internal/processors/rollingupgrade/RollingUpgradeProcessor.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ public RollingUpgradeProcessor(GridKernalContext ctx) {
155155
* This method can only be called on coordinator node with {@link TcpDiscoverySpi}.
156156
*
157157
* @param target Target version.
158+
* @param force If {@code true}, skips target version compatibility checks and forcibly enables rolling upgrade.
159+
* This flag does not override an already active upgrade configuration.
158160
* @throws IgniteCheckedException If:
159161
* <ul>
160162
* <li>The current and target versions are incompatible;</li>
@@ -163,7 +165,7 @@ public RollingUpgradeProcessor(GridKernalContext ctx) {
163165
* <li>The distributed metastorage is not ready;</li>
164166
* </ul>
165167
*/
166-
public void enable(IgniteProductVersion target) throws IgniteCheckedException {
168+
public void enable(IgniteProductVersion target, boolean force) throws IgniteCheckedException {
167169
if (startLatch.getCount() > 0)
168170
throw new IgniteCheckedException("Cannot enable rolling upgrade: processor has not been started yet");
169171

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

182-
if (!checkVersionsForEnabling(curVer, target))
184+
if (!checkVersionsForEnabling(curVer, target, force))
183185
return;
184186

185187
IgnitePair<IgniteProductVersion> newPair = F.pair(curVer, target);
@@ -278,10 +280,14 @@ public boolean enabled() {
278280
*
279281
* @param cur Current cluster version.
280282
* @param target Target cluster version.
281-
* @return {@code false} if there is no need to update versions {@code true} otherwise.
283+
* @param force Force flag to skip version checks.
282284
* @throws IgniteCheckedException If versions are incorrect.
283285
*/
284-
private boolean checkVersionsForEnabling(IgniteProductVersion cur, IgniteProductVersion target) throws IgniteCheckedException {
286+
private boolean checkVersionsForEnabling(
287+
IgniteProductVersion cur,
288+
IgniteProductVersion target,
289+
boolean force
290+
) throws IgniteCheckedException {
285291
IgnitePair<IgniteProductVersion> oldVerPair = rollUpVers;
286292
if (oldVerPair != null) {
287293
if (oldVerPair.get1().equals(cur) && oldVerPair.get2().equals(target))
@@ -291,6 +297,14 @@ private boolean checkVersionsForEnabling(IgniteProductVersion cur, IgniteProduct
291297
oldVerPair.get1() + " , " + oldVerPair.get2());
292298
}
293299

300+
if (force) {
301+
if (log.isInfoEnabled())
302+
log.info("Skipping version compatibility check for rolling upgrade due to force flag "
303+
+ "[currentVer=" + cur + ", targetVer=" + target + ']');
304+
305+
return true;
306+
}
307+
294308
if (cur.major() != target.major())
295309
throw new IgniteCheckedException("Major versions are different");
296310

modules/core/src/test/java/org/apache/ignite/internal/GridReleaseTypeSelfTest.java

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,26 @@ public void testThreeCompatibleVersions() throws Exception {
145145
/** */
146146
@Test
147147
public void testForwardRollingUpgrade() throws Exception {
148-
cleanPersistenceDir();
149-
IgniteEx ign0 = startGrid(0, "2.18.0", false);
150-
IgniteEx ign1 = startGrid(1, "2.18.0", client);
151-
IgniteEx ign2 = startGrid(2, "2.18.0", client);
148+
doTestRollingUpgrade("2.18.0", "2.18.1", false);
149+
}
150+
151+
/** */
152+
@Test
153+
public void testForceRollingUpgrade() throws Exception {
154+
doTestRollingUpgrade("2.18.0", "2.19.1", true);
155+
}
156+
157+
/** Performs full rolling upgrade scenario. */
158+
private void doTestRollingUpgrade(String curVer, String targetVer, boolean force) throws Exception {
159+
IgniteEx ign0 = startGrid(0, curVer, false);
160+
IgniteEx ign1 = startGrid(1, curVer, client);
161+
IgniteEx ign2 = startGrid(2, curVer, client);
152162

153163
assertClusterSize(3);
154164

155-
assertRemoteRejected(() -> startGrid(3, "2.18.1", client));
165+
assertRemoteRejected(() -> startGrid(3, targetVer, client));
156166

157-
configureRollingUpgradeVersion(ign0, "2.18.1");
167+
configureRollingUpgradeVersion(ign0, targetVer, force);
158168

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

166176
assertClusterSize(2);
167177

168-
startGrid(2, "2.18.1", client);
178+
startGrid(2, targetVer, client);
169179

170180
assertClusterSize(3);
171181

172182
ign1.close();
173183

174184
assertClusterSize(2);
175185

176-
startGrid(1, "2.18.1", client);
186+
startGrid(1, targetVer, client);
177187

178188
assertClusterSize(3);
179189

180190
ign0.close();
181191

182192
assertClusterSize(2);
183193

184-
startGrid(0, "2.18.1", false);
194+
startGrid(0, targetVer, false);
185195

186196
assertClusterSize(3);
187197

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

198-
assertRemoteRejected(() -> startGrid(3, "2.18.0", client));
208+
assertRemoteRejected(() -> startGrid(3, curVer, client));
199209
}
200210

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

318-
grid0.context().rollingUpgrade().enable(newPair.get2());
328+
grid0.context().rollingUpgrade().enable(newPair.get2(), false);
319329

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

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

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

483+
/** */
484+
private void configureRollingUpgradeVersion(IgniteEx grid, String ver) throws IgniteCheckedException {
485+
configureRollingUpgradeVersion(grid, ver, false);
486+
}
487+
473488
/**
474489
* @param ver Version for rolling upgrade support.
490+
* @param force Force rolling upgrade.
475491
*/
476-
private void configureRollingUpgradeVersion(IgniteEx grid, String ver) throws IgniteCheckedException {
492+
private void configureRollingUpgradeVersion(IgniteEx grid, String ver, boolean force) throws IgniteCheckedException {
477493
if (ver == null) {
478494
grid.context().rollingUpgrade().disable();
479495
return;
480496
}
481497

482498
IgniteProductVersion target = IgniteProductVersion.fromString(ver);
483499

484-
grid.context().rollingUpgrade().enable(target);
500+
grid.context().rollingUpgrade().enable(target, force);
485501
}
486502

487503
/**

modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,11 @@ If the file name isn't specified the output file name is: '<typeId>.bin':
373373

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

378378
Parameters:
379379
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).
380+
--force - Enable rolling upgrade without target version checks. Use only when required, if the upgrade cannot proceed otherwise.
380381

381382
[EXPERIMENTAL]
382383
Disable rolling upgrade mode. All nodes in the cluster must be running the same version:

modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,11 @@ If the file name isn't specified the output file name is: '<typeId>.bin':
373373

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

378378
Parameters:
379379
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).
380+
--force - Enable rolling upgrade without target version checks. Use only when required, if the upgrade cannot proceed otherwise.
380381

381382
[EXPERIMENTAL]
382383
Disable rolling upgrade mode. All nodes in the cluster must be running the same version:

0 commit comments

Comments
 (0)