diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index c3a982aa70e5..f3ec76a27c7a 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -91,11 +91,12 @@ import com.cloud.upgrade.dao.Upgrade42020to42030; import com.cloud.upgrade.dao.Upgrade42030to42040; import com.cloud.upgrade.dao.Upgrade42040to42100; -import com.cloud.upgrade.dao.Upgrade42100to42200; -import com.cloud.upgrade.dao.Upgrade42200to42210; import com.cloud.upgrade.dao.Upgrade420to421; +import com.cloud.upgrade.dao.Upgrade42100to42200; import com.cloud.upgrade.dao.Upgrade421to430; +import com.cloud.upgrade.dao.Upgrade42200to42210; import com.cloud.upgrade.dao.Upgrade42210to42300; +import com.cloud.upgrade.dao.Upgrade42300to2400; import com.cloud.upgrade.dao.Upgrade430to440; import com.cloud.upgrade.dao.Upgrade431to440; import com.cloud.upgrade.dao.Upgrade432to440; @@ -248,6 +249,7 @@ public DatabaseUpgradeChecker() { .next("4.21.0.0", new Upgrade42100to42200()) .next("4.22.0.0", new Upgrade42200to42210()) .next("4.22.1.0", new Upgrade42210to42300()) + .next("4.23.0.0", new Upgrade42300to2400()) .build(); } @@ -513,8 +515,13 @@ protected void doUpgrades(GlobalLock lock) { String csVersion = parseSystemVmMetadata(); final CloudStackVersion sysVmVersion = CloudStackVersion.parse(csVersion); final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue); - SystemVmTemplateRegistration.CS_MAJOR_VERSION = sysVmVersion.getMajorRelease() + "." + sysVmVersion.getMinorRelease(); - SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getPatchRelease()); + if (sysVmVersion.usesNewVersioning()) { + SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(sysVmVersion.getMajorRelease()); + SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getMajorRelease()); + } else { + SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.format("%d.%d", sysVmVersion.getMajorRelease(), sysVmVersion.getMinorRelease()); + SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getPatchRelease()); + } LOGGER.info("DB version = {} Code Version = {}", dbVersion, currentVersion); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42300to2400.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42300to2400.java new file mode 100644 index 000000000000..ce217cef9e75 --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42300to2400.java @@ -0,0 +1,30 @@ +// 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.dao; + +public class Upgrade42300to2400 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate { + + @Override + public String[] getUpgradableVersionRange() { + return new String[]{"4.23.0.0", "24.0.0"}; + } + + @Override + public String getUpgradedVersion() { + return "24.0.0"; + } +} diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42300to2400-cleanup.sql b/engine/schema/src/main/resources/META-INF/db/schema-42300to2400-cleanup.sql new file mode 100644 index 000000000000..861a038fe7a7 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/schema-42300to2400-cleanup.sql @@ -0,0 +1,20 @@ +-- 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. + +--; +-- Schema upgrade cleanup from 4.23.0.0 to 24.0.0 +--; diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql b/engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql new file mode 100644 index 000000000000..7c11013a17d2 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql @@ -0,0 +1,20 @@ +-- 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. + +--; +-- Schema upgrade from 4.23.0.0 to 24.0.0 +--; diff --git a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Version.java b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Version.java index 7b7d80a0f16c..2d14443e2d58 100644 --- a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Version.java +++ b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Version.java @@ -87,8 +87,12 @@ public static Version fromPackageAndCSVersion(boolean complete) { } version.setMajor(String.valueOf(csVersion.getMajorRelease())); version.setMinor(String.valueOf(csVersion.getMinorRelease())); - version.setBuild(String.valueOf(csVersion.getPatchRelease())); - version.setRevision(String.valueOf(csVersion.getSecurityRelease())); + if (csVersion.usesNewVersioning()) { + version.setBuild(String.valueOf(csVersion.getSecurityRelease())); + } else { + version.setBuild(String.valueOf(csVersion.getPatchRelease())); + version.setRevision(String.valueOf(csVersion.getSecurityRelease())); + } return version; } } diff --git a/utils/src/main/java/org/apache/cloudstack/utils/CloudStackVersion.java b/utils/src/main/java/org/apache/cloudstack/utils/CloudStackVersion.java index e29bd9c4e17b..8eb4c6ab9289 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/CloudStackVersion.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/CloudStackVersion.java @@ -39,22 +39,23 @@ */ public final class CloudStackVersion implements Comparable { - private final static Pattern NUMBER_VERSION_FORMAT = Pattern.compile("(\\d+\\.){2}(\\d+\\.)?\\d+"); - private final static Pattern FULL_VERSION_FORMAT = Pattern.compile("(\\d+\\.){2}(\\d+\\.)?\\d+(-[a-zA-Z]+)?(-\\d+)?(-SNAPSHOT)?"); + private final static Pattern NUMBER_VERSION_FORMAT = Pattern.compile("\\d+\\.\\d+\\.\\d+(?:\\.\\d+)?"); + private final static Pattern FULL_VERSION_FORMAT = Pattern.compile("\\d+\\.\\d+\\.\\d+(?:\\.\\d+)?(?:-[a-zA-Z]+)?(?:-\\d+)?(?:-SNAPSHOT)?"); + private final static int NEW_VERSIONING_CUTOVER_MAJOR_VERSION = 24; private final int majorRelease; private final int minorRelease; - private final int patchRelease; + private final Integer patchRelease; private final Integer securityRelease; - private CloudStackVersion(final int majorRelease, final int minorRelease, final int patchRelease, final Integer securityRelease) { + private CloudStackVersion(final int majorRelease, final int minorRelease, final Integer patchRelease, final Integer securityRelease) { super(); checkArgument(majorRelease >= 0, CloudStackVersion.class.getName() + "(int, int, int, Integer) requires a majorRelease greater than 0."); checkArgument(minorRelease >= 0, CloudStackVersion.class.getName() + "(int, int, int, Integer) requires a minorRelease greater than 0."); - checkArgument(patchRelease >= 0, CloudStackVersion.class.getName() + "(int, int, int, Integer) requires a patchRelease greater than 0."); - checkArgument((securityRelease != null && securityRelease >= 0) || (securityRelease == null), + checkArgument(patchRelease == null || patchRelease >= 0, CloudStackVersion.class.getName() + "(int, int, int, Integer) requires a patchRelease greater than 0."); + checkArgument(securityRelease == null || securityRelease >= 0, CloudStackVersion.class.getName() + "(int, int, int, Integer) requires a null securityRelease or a non-null value greater than 0."); this.majorRelease = majorRelease; @@ -69,11 +70,13 @@ private CloudStackVersion(final int majorRelease, final int minorRelease, final * Parses a String representation of a version that conforms one of the following * formats into a CloudStackVersion instance: * * + * Legacy patch-based formats remain supported for backward compatibility. + * * If the string contains a suffix that begins with a "-" character, then the "-" and all characters following it * will be dropped. * @@ -91,7 +94,7 @@ public static CloudStackVersion parse(final String value) { checkArgument(StringUtils.isNotBlank(trimmedValue), CloudStackVersion.class.getName() + ".parse(String) requires a non-blank value"); checkArgument(NUMBER_VERSION_FORMAT.matcher(trimmedValue).matches(), CloudStackVersion.class.getName() + ".parse(String) passed " + - value + ", but requires a value in the format of int.int.int(.int)(-)"); + value + ", but requires a value in the format of int.int.int(.int)(-)"); final String[] components = trimmedValue.split("\\."); @@ -100,8 +103,26 @@ public static CloudStackVersion parse(final String value) { final int majorRelease = Integer.valueOf(components[0]); final int minorRelease = Integer.valueOf(components[1]); - final int patchRelease = Integer.valueOf(components[2]); - final Integer securityRelease = components.length == 3 ? null : Integer.valueOf(components[3]); + final int thirdComponent = Integer.valueOf(components[2]); + + final int patchRelease; + final Integer securityRelease; + + if (components.length == 4) { + checkArgument(isLegacyVersioning(majorRelease), CloudStackVersion.class.getName() + ".parse(String) passed " + value + + ", but major versions at or above 24 do not support legacy int.int.int.int format"); + // Deprecated legacy format: major.minor.patch.security + patchRelease = thirdComponent; + securityRelease = Integer.valueOf(components[3]); + } else if (isNewVersioning(majorRelease)) { + // New format: major.minor.securityRelease (patch dropped) + patchRelease = 0; + securityRelease = thirdComponent; + } else { + // Deprecated legacy format: major.minor.patch + patchRelease = thirdComponent; + securityRelease = null; + } return new CloudStackVersion(majorRelease, minorRelease, patchRelease, securityRelease); @@ -207,6 +228,14 @@ private static ImmutableList normalizeVersionValues(final ImmutableList } + private static boolean isLegacyVersioning(final int majorRelease) { + return majorRelease < NEW_VERSIONING_CUTOVER_MAJOR_VERSION; + } + + private static boolean isNewVersioning(final int majorRelease) { + return majorRelease >= NEW_VERSIONING_CUTOVER_MAJOR_VERSION; + } + /** * * @return The components of this version as an {@link ImmutableList} in order of major release, minor release, @@ -244,6 +273,10 @@ public Integer getSecurityRelease() { return securityRelease; } + public boolean usesNewVersioning() { + return isNewVersioning(majorRelease); + } + @Override public boolean equals(final Object thatObject) { @@ -270,6 +303,11 @@ public int hashCode() { @Override public String toString() { + // Canonicalize cutover-and-later versions to major.minor.securityRelease. + if (securityRelease != null && patchRelease == 0 && isNewVersioning(majorRelease)) { + return Joiner.on(".").join(ImmutableList.of(majorRelease, minorRelease, securityRelease)); + } + return Joiner.on(".").join(asList()); } diff --git a/utils/src/test/java/org/apache/cloudstack/utils/CloudStackVersionTest.java b/utils/src/test/java/org/apache/cloudstack/utils/CloudStackVersionTest.java index dabaf9bc97d3..4d0b4cb0439b 100644 --- a/utils/src/test/java/org/apache/cloudstack/utils/CloudStackVersionTest.java +++ b/utils/src/test/java/org/apache/cloudstack/utils/CloudStackVersionTest.java @@ -36,7 +36,11 @@ public final class CloudStackVersionTest { "1.2.3, 1.2.3", "1.2.3.4, 1.2.3.4", "1.2.3-12, 1.2.3", - "1.2.3.4-14, 1.2.3.4" + "1.2.3.4-14, 1.2.3.4", + "23.9.5, 23.9.5", + "24.0.0, 24.0.0", + "24.0.1, 24.0.1", + "25.1.1, 25.1.1" }) public void testValidParse(final String inputValue, final String expectedVersion) { final CloudStackVersion version = CloudStackVersion.parse(inputValue); @@ -44,6 +48,28 @@ public void testValidParse(final String inputValue, final String expectedVersion assertEquals(expectedVersion, version.toString()); } + @Test + public void testParseComponentMappingForLegacyAndNewVersioning() { + final CloudStackVersion legacyVersion = CloudStackVersion.parse("23.9.5"); + assertEquals(23, legacyVersion.getMajorRelease()); + assertEquals(9, legacyVersion.getMinorRelease()); + assertEquals(5, legacyVersion.getPatchRelease()); + Assert.assertNull(legacyVersion.getSecurityRelease()); + + final CloudStackVersion newVersion = CloudStackVersion.parse("24.0.1"); + assertEquals(24, newVersion.getMajorRelease()); + assertEquals(0, newVersion.getMinorRelease()); + // Patch is retained as 0 to represent "no patch" in the new major.minor.security scheme. + assertEquals(0, newVersion.getPatchRelease()); + assertEquals(Integer.valueOf(1), newVersion.getSecurityRelease()); + + final CloudStackVersion futureNewVersion = CloudStackVersion.parse("25.1.1"); + assertEquals(25, futureNewVersion.getMajorRelease()); + assertEquals(1, futureNewVersion.getMinorRelease()); + assertEquals(0, futureNewVersion.getPatchRelease()); + assertEquals(Integer.valueOf(1), futureNewVersion.getSecurityRelease()); + } + @Test(expected = IllegalArgumentException.class) @DataProvider({ "1.2", @@ -52,7 +78,10 @@ public void testValidParse(final String inputValue, final String expectedVersion "aaaa", "", " ", - "1.2.3.4.5" + "1.2.3.4.5", + "24.0.0.1", + "25.0.0.1", + "26.2.3.4" }) public void testInvalidParse(final String invalidValue) { CloudStackVersion.parse(invalidValue); @@ -147,7 +176,9 @@ public void testEqualCompareDirect(final String value, final String thatValue) { "1.2.3.4-10, 1.0.0.0-5", "1.2.3-10, 1.0.0-5", "1.2.3.4, 1.0.0.0-5", - "1.2.3.4-10, 1.0.0" + "1.2.3.4-10, 1.0.0", + "24.0.2, 24.0.1", + "24.1.0, 24.0.9" }) public void testGreaterThanAndLessThanCompareTo(final String value, final String thatValue) { @@ -178,7 +209,9 @@ public void testGreaterThanAndLessThanCompareTo(final String value, final String "1.2.3.4-10, 1.0.0.0-5", "1.2.3-10, 1.0.0-5", "1.2.3.4, 1.0.0.0-5", - "1.2.3.4-10, 1.0.0" + "1.2.3.4-10, 1.0.0", + "24.0.2, 24.0.1", + "24.1.0, 24.0.9" }) public void testGreaterThanAndLessThanCompareDirect(final String value, final String thatValue) { @@ -213,6 +246,7 @@ private void verifyGetVMwareParentVersion(String hypervisorVersion, String expec Assert.assertEquals(CloudStackVersion.getVMwareParentVersion(hypervisorVersion), expectedParentVersion); } } + @Test public void testGetParentVersion() { verifyGetVMwareParentVersion(null, null); @@ -223,5 +257,6 @@ public void testGetParentVersion() { verifyGetVMwareParentVersion("8.0.0", "8.0"); verifyGetVMwareParentVersion("8.0.0.2", "8.0"); verifyGetVMwareParentVersion("8.0.1.0", "8.0.1"); + verifyGetVMwareParentVersion("24.1.1", "24.1"); } }