mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-15 09:21:06 +02:00
Add rolling upgrade test.
Change-Id: Id1b09361aa69f1665f19c312933798b5206d46ac
This commit is contained in:
parent
a84936d87e
commit
ca7660a289
@ -18,6 +18,7 @@ package org.onosproject.distributedprimitives.cli;
|
||||
import org.apache.karaf.shell.commands.Argument;
|
||||
import org.apache.karaf.shell.commands.Command;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.core.Version;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.ConsistentMap;
|
||||
import org.onosproject.store.service.Serializer;
|
||||
@ -64,6 +65,8 @@ public class ConsistentMapTestCommand extends AbstractShellCommand {
|
||||
map = storageService.<String, String>consistentMapBuilder()
|
||||
.withName(name)
|
||||
.withSerializer(Serializer.using(KryoNamespaces.BASIC))
|
||||
.withVersion(Version.version("1.0.0"))
|
||||
.withCompatibilityFunction((value, version) -> version + ":" + value)
|
||||
.build();
|
||||
if ("get".equals(operation)) {
|
||||
print(map.get(arg1));
|
||||
@ -95,6 +98,22 @@ public class ConsistentMapTestCommand extends AbstractShellCommand {
|
||||
} else {
|
||||
print("%b", map.replace(arg1, arg2, arg3));
|
||||
}
|
||||
} else if ("compatiblePut".equals(operation)) {
|
||||
ConsistentMap<String, String> map = storageService.<String, String>consistentMapBuilder()
|
||||
.withName(name)
|
||||
.withSerializer(Serializer.using(KryoNamespaces.BASIC))
|
||||
.withCompatibilityFunction((value, version) -> version + ":" + value)
|
||||
.withVersion(Version.version("2.0.0"))
|
||||
.build();
|
||||
print(map.put(arg1, arg2));
|
||||
} else if ("compatibleGet".equals(operation)) {
|
||||
ConsistentMap<String, String> map = storageService.<String, String>consistentMapBuilder()
|
||||
.withName(name)
|
||||
.withSerializer(Serializer.using(KryoNamespaces.BASIC))
|
||||
.withCompatibilityFunction((value, version) -> version + ":" + value)
|
||||
.withVersion(Version.version("2.0.0"))
|
||||
.build();
|
||||
print(map.get(arg1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,8 +100,9 @@ public final class Version implements Comparable<Version> {
|
||||
public static Version fromInt(int version) {
|
||||
int major = (version >> 24) & 0xff;
|
||||
int minor = (version >> 16) & 0xff;
|
||||
int patch = (version) & 0xffff;
|
||||
return new Version(major, minor, String.valueOf(patch), null);
|
||||
int patch = (version >> 8) & 0xff;
|
||||
int build = version & 0xff;
|
||||
return new Version(major, minor, String.valueOf(patch), String.valueOf(build));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,13 +158,30 @@ public final class Version implements Comparable<Version> {
|
||||
public int toInt() {
|
||||
byte major = (byte) this.major;
|
||||
byte minor = (byte) this.minor;
|
||||
short patch;
|
||||
|
||||
byte patch;
|
||||
if (this.patch != null) {
|
||||
try {
|
||||
patch = (short) Integer.parseInt(this.patch);
|
||||
patch = (byte) Integer.parseInt(this.patch.replaceAll("[^0-9]", ""));
|
||||
} catch (NumberFormatException e) {
|
||||
patch = 0;
|
||||
}
|
||||
return major << 24 | (minor & 0xff) << 16 | (patch & 0xffff);
|
||||
} else {
|
||||
patch = 0;
|
||||
}
|
||||
|
||||
byte build;
|
||||
if (this.build != null) {
|
||||
try {
|
||||
build = (byte) Integer.parseInt(this.build.replaceAll("[^0-9]", ""));
|
||||
} catch (NumberFormatException e) {
|
||||
build = 0;
|
||||
}
|
||||
} else {
|
||||
build = 0;
|
||||
}
|
||||
|
||||
return major << 24 | (minor & 0xff) << 16 | (patch & 0xff) << 8 | (build & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,25 +83,30 @@ public class VersionTest {
|
||||
|
||||
version1 = version("1.2");
|
||||
version2 = Version.fromInt(version1.toInt());
|
||||
assertEquals(version2, version(1, 2, "0", null));
|
||||
assertEquals(version2, version(1, 2, "0", "0"));
|
||||
|
||||
version1 = version("1.2.foo.bar");
|
||||
version2 = Version.fromInt(version1.toInt());
|
||||
assertEquals(version2, version(1, 2, "0", null));
|
||||
assertEquals(version2, version(1, 2, "0", "0"));
|
||||
|
||||
version1 = version("1.2.3");
|
||||
version2 = Version.fromInt(version1.toInt());
|
||||
assertEquals(version2, version(1, 2, "3", null));
|
||||
assertEquals(version2, version(1, 2, "3", "0"));
|
||||
|
||||
version1 = version("255.254.65535.252");
|
||||
version1 = version("1.2.3-SNAPSHOT");
|
||||
version2 = Version.fromInt(version1.toInt());
|
||||
assertEquals(version2, version(255, 254, "65535", null));
|
||||
assertEquals(version2, version(1, 2, "3", "0"));
|
||||
|
||||
version1 = version("255.254.253.252");
|
||||
version2 = Version.fromInt(version1.toInt());
|
||||
assertEquals(version2, version(255, 254, "253", "252"));
|
||||
|
||||
assertTrue(version("0.0.2").toInt() > version("0.0.1").toInt());
|
||||
assertTrue(version("0.1.0").toInt() > version("0.0.1").toInt());
|
||||
assertTrue(version("1.0.0").toInt() > version("0.1.0").toInt());
|
||||
assertTrue(version("1.1.0").toInt() > version("1.0.1").toInt());
|
||||
assertTrue(version("2.1.1").toInt() > version("1.10.10").toInt());
|
||||
assertTrue(version("0.1.0-rc2").toInt() > version("0.1.0-rc1").toInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -105,13 +105,6 @@ public class UpgradeManager
|
||||
|
||||
Upgrade upgrade = getState();
|
||||
|
||||
// If the upgrade state is not initialized, ensure this node matches the version of the cluster.
|
||||
if (!upgrade.status().active() && !Objects.equals(upgrade.source(), localVersion)) {
|
||||
log.error("Node version {} inconsistent with cluster version {}", localVersion, upgrade.source());
|
||||
throw new IllegalStateException("Node version " + localVersion +
|
||||
" inconsistent with cluster version " + upgrade.source());
|
||||
}
|
||||
|
||||
// If the upgrade state is initialized then check the node version.
|
||||
if (upgrade.status() == Upgrade.Status.INITIALIZED) {
|
||||
// If the source version equals the target version, attempt to update the target version.
|
||||
|
@ -19,11 +19,17 @@ import com.google.common.collect.Sets;
|
||||
import io.atomix.protocols.raft.proxy.RaftProxy;
|
||||
import io.atomix.protocols.raft.service.RaftService;
|
||||
import org.junit.Test;
|
||||
import org.onlab.util.HexString;
|
||||
import org.onlab.util.Tools;
|
||||
import org.onosproject.store.primitives.MapUpdate;
|
||||
import org.onosproject.store.primitives.TransactionId;
|
||||
import org.onosproject.store.primitives.impl.CompatibleValue;
|
||||
import org.onosproject.store.primitives.impl.DistributedPrimitives;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.AsyncConsistentMap;
|
||||
import org.onosproject.store.service.MapEvent;
|
||||
import org.onosproject.store.service.MapEventListener;
|
||||
import org.onosproject.store.service.Serializer;
|
||||
import org.onosproject.store.service.TransactionLog;
|
||||
import org.onosproject.store.service.Version;
|
||||
import org.onosproject.store.service.Versioned;
|
||||
@ -584,6 +590,50 @@ public class AtomixConsistentMapTest extends AtomixTestBase<AtomixConsistentMap>
|
||||
assertTrue(Arrays.equals(value2, event.newValue().value()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompatibilityFunction() throws Throwable {
|
||||
AtomixConsistentMap atomixMap = newPrimitive("testCompatibilityFunction");
|
||||
|
||||
Serializer rawSerializer = Serializer.using(KryoNamespaces.API, CompatibleValue.class);
|
||||
Serializer valueSerializer = Serializer.using(KryoNamespaces.BASIC);
|
||||
|
||||
// Convert the byte[] value to CompatibleValue<byte[]>
|
||||
AsyncConsistentMap<String, CompatibleValue<byte[]>> rawMap = DistributedPrimitives.newTranscodingMap(
|
||||
atomixMap,
|
||||
key -> HexString.toHexString(rawSerializer.encode(key)),
|
||||
string -> rawSerializer.decode(HexString.fromHexString(string)),
|
||||
value -> value == null ? null : rawSerializer.encode(value),
|
||||
bytes -> rawSerializer.decode(bytes));
|
||||
|
||||
// Convert the CompatibleValue<byte[]> value to CompatibleValue<V> using the user-provided serializer.
|
||||
AsyncConsistentMap<String, CompatibleValue<String>> compatibleMap =
|
||||
DistributedPrimitives.newTranscodingMap(
|
||||
rawMap,
|
||||
key -> key,
|
||||
key -> key,
|
||||
value -> value == null ? null :
|
||||
new CompatibleValue<byte[]>(valueSerializer.encode(value.value()), value.version()),
|
||||
value -> value == null ? null :
|
||||
new CompatibleValue<String>(valueSerializer.decode(value.value()), value.version()));
|
||||
|
||||
AsyncConsistentMap<String, String> map1 = DistributedPrimitives.newCompatibleMap(
|
||||
compatibleMap,
|
||||
(value, version) -> version + ":" + value,
|
||||
org.onosproject.core.Version.version("1.0.0"));
|
||||
AsyncConsistentMap<String, String> map2 = DistributedPrimitives.newCompatibleMap(
|
||||
compatibleMap,
|
||||
(value, version) -> version + ":" + value,
|
||||
org.onosproject.core.Version.version("1.0.1"));
|
||||
|
||||
map1.put("foo", "Hello world!").join();
|
||||
assertEquals("Hello world!", map1.get("foo").join().value());
|
||||
assertEquals("1.0.0:Hello world!", map2.get("foo").join().value());
|
||||
|
||||
map2.put("bar", "Hello world again!").join();
|
||||
assertEquals("Hello world again!", map2.get("bar").join().value());
|
||||
assertEquals("1.0.1:Hello world again!", map1.get("bar").join().value());
|
||||
}
|
||||
|
||||
private static class TestMapEventListener implements MapEventListener<String, byte[]> {
|
||||
|
||||
private final BlockingQueue<MapEvent<String, byte[]>> queue = new ArrayBlockingQueue<>(1);
|
||||
|
82
tools/test/scenarios/rolling-upgrade.xml
Normal file
82
tools/test/scenarios/rolling-upgrade.xml
Normal file
@ -0,0 +1,82 @@
|
||||
<!--
|
||||
~ Copyright 2018-present Open Networking Foundation
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
<scenario name="rolling-upgrade" description="ONOS cluster rolling upgrade">
|
||||
<import file="${ONOS_SCENARIOS}/dist-setup.xml"/>
|
||||
<dependency name="Distributed-Primitives-Setup"/>
|
||||
|
||||
<group name="Upgrade" requires="Distributed-Primitives-Setup">
|
||||
<step name="Push-Bits" exec="onos-push-bits-through-proxy" if="${OCT}"/>
|
||||
|
||||
<group name="Perform-Upgrade">
|
||||
<sequential var="${OC#}"
|
||||
starts="Stop-Service-${#}"
|
||||
ends="Wait-for-Start-${#-1}">
|
||||
<step name="Stop-Service-${#}"
|
||||
exec="onos-service ${OC#} stop"/>
|
||||
|
||||
<step name="Wait-for-Stop-${#}"
|
||||
exec="onos-wait-for-stop ${OC#}"
|
||||
requires="~Stop-Service-${#}"/>
|
||||
|
||||
<step name="Uninstall-${#}"
|
||||
exec="onos-uninstall ${OC#}"
|
||||
requires="~Wait-for-Stop-${#}"/>
|
||||
|
||||
<step name="Push-Bits-${#}"
|
||||
exec="onos-push-bits ${OC#}"
|
||||
unless="${OCT}"
|
||||
requires="~Stop-Service-${#}"/>
|
||||
|
||||
<step name="Install-Upgrade-${#}"
|
||||
exec="onos-install -v ${OC#}"
|
||||
requires="Push-Bits-${#},Push-Bits,Uninstall-${#}"/>
|
||||
|
||||
<step name="Secure-SSH-${#}"
|
||||
exec="onos-secure-ssh -u ${ONOS_WEB_USER} -p ${ONOS_WEB_PASS} ${OC#}"
|
||||
requires="~Install-Upgrade-${#}"/>
|
||||
|
||||
<step name="Wait-for-Start-${#}"
|
||||
exec="onos-wait-for-start ${OC#}"
|
||||
requires="Secure-SSH-${#}"/>
|
||||
|
||||
<step name="Distributed-Primitives-Check-Apps-${#}"
|
||||
exec="onos-check-apps ${OC#} distributedprimitives includes"
|
||||
requires="Wait-for-Start-${#}"/>
|
||||
</sequential>
|
||||
</group>
|
||||
|
||||
<group name="Verify-Upgrade" requires="Perform-Upgrade">
|
||||
<parallel var="${OC#}">
|
||||
<step name="Check-Nodes-${#}"
|
||||
exec="onos-check-nodes ${OC#}"
|
||||
delay="3"/>
|
||||
|
||||
<step name="Check-Components-${#}"
|
||||
exec="onos-check-components ${OC#}"
|
||||
delay="5"
|
||||
requires="~Check-Nodes-${#}"/>
|
||||
|
||||
<step name="Check-Logs-${#}"
|
||||
exec="onos-check-logs ${OC#}"
|
||||
requires="~Check-Components-${#}"/>
|
||||
|
||||
<step name="Check-Apps-${#}"
|
||||
exec="onos-check-apps ${OC#} ${ONOS_APPS},distributedprimitives includes"
|
||||
requires="~Check-Components-${#}"/>
|
||||
</parallel>
|
||||
</group>
|
||||
</group>
|
||||
</scenario>
|
Loading…
x
Reference in New Issue
Block a user