diff options
3 files changed, 48 insertions, 21 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java index 19e34ccb169..feaa4d8241d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Status.java @@ -22,6 +22,7 @@ public class Status { private final boolean wantToRetire; private final boolean wantToDeprovision; private final Optional<String> hardwareDivergence; + private final Optional<Version> osVersion; public Status(Generation generation, Optional<Version> vespaVersion, @@ -29,50 +30,49 @@ public class Status { Optional<String> hardwareFailureDescription, boolean wantToRetire, boolean wantToDeprovision, - Optional<String> hardwareDivergence) { - Objects.requireNonNull(generation, "Generation must be non-null"); - Objects.requireNonNull(vespaVersion, "Vespa version must be non-null"); - Objects.requireNonNull(hardwareFailureDescription, "Hardware failure description must be non-null"); + Optional<String> hardwareDivergence, + Optional<Version> osVersion) { Objects.requireNonNull(hardwareDivergence, "Hardware divergence must be non-null"); hardwareDivergence.ifPresent(s -> requireNonEmptyString(s, "Hardware divergence must be non-empty")); - this.reboot = generation; - this.vespaVersion = vespaVersion; + this.reboot = Objects.requireNonNull(generation, "Generation must be non-null"); + this.vespaVersion = Objects.requireNonNull(vespaVersion, "Vespa version must be non-null"); this.failCount = failCount; - this.hardwareFailureDescription = hardwareFailureDescription; + this.hardwareFailureDescription = Objects.requireNonNull(hardwareFailureDescription, "Hardware failure description must be non-null"); this.wantToRetire = wantToRetire; this.wantToDeprovision = wantToDeprovision; this.hardwareDivergence = hardwareDivergence; + this.osVersion = Objects.requireNonNull(osVersion, "OS version must be non-null"); } /** Returns a copy of this with the reboot generation changed */ - public Status withReboot(Generation reboot) { return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); } + public Status withReboot(Generation reboot) { return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } /** Returns the reboot generation of this node */ public Generation reboot() { return reboot; } /** Returns a copy of this with the vespa version changed */ - public Status withVespaVersion(Version version) { return new Status(reboot, Optional.of(version), failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); } + public Status withVespaVersion(Version version) { return new Status(reboot, Optional.of(version), failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } /** Returns the Vespa version installed on the node, if known */ public Optional<Version> vespaVersion() { return vespaVersion; } - public Status withIncreasedFailCount() { return new Status(reboot, vespaVersion, failCount + 1, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); } + public Status withIncreasedFailCount() { return new Status(reboot, vespaVersion, failCount + 1, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } - public Status withDecreasedFailCount() { return new Status(reboot, vespaVersion, failCount - 1, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); } + public Status withDecreasedFailCount() { return new Status(reboot, vespaVersion, failCount - 1, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } - public Status setFailCount(Integer value) { return new Status(reboot, vespaVersion, value, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); } + public Status setFailCount(Integer value) { return new Status(reboot, vespaVersion, value, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } /** Returns how many times this node has been moved to the failed state. */ public int failCount() { return failCount; } - public Status withHardwareFailureDescription(Optional<String> hardwareFailureDescription) { return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); } + public Status withHardwareFailureDescription(Optional<String> hardwareFailureDescription) { return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } /** Returns the type of the last hardware failure detected on this node, or empty if none */ public Optional<String> hardwareFailureDescription() { return hardwareFailureDescription; } /** Returns a copy of this with the want to retire flag changed */ public Status withWantToRetire(boolean wantToRetire) { - return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); + return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } /** @@ -85,7 +85,7 @@ public class Status { /** Returns a copy of this with the want to de-provision flag changed */ public Status withWantToDeprovision(boolean wantToDeprovision) { - return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); + return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } /** @@ -96,14 +96,27 @@ public class Status { } public Status withHardwareDivergence(Optional<String> hardwareDivergence) { - return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence); + return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, osVersion); } /** Returns hardware divergence report as JSON string, if any */ public Optional<String> hardwareDivergence() { return hardwareDivergence; } + /** Returns a copy of this with the current OS version set to version */ + public Status withOsVersion(Version version) { + return new Status(reboot, vespaVersion, failCount, hardwareFailureDescription, wantToRetire, wantToDeprovision, hardwareDivergence, Optional.of(version)); + } + + /** Returns the current OS version of this node, if any */ + public Optional<Version> osVersion() { + return osVersion; + } + /** Returns the initial status of a newly provisioned node */ - public static Status initial() { return new Status(Generation.inital(), Optional.empty(), 0, Optional.empty(), false, false, Optional.empty()); } + public static Status initial() { + return new Status(Generation.inital(), Optional.empty(), 0, Optional.empty(), false, + false, Optional.empty(), Optional.empty()); + } private void requireNonEmptyString(String value, String message) { Objects.requireNonNull(value, message); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java index 669f2063ee6..dbe6589dd7f 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java @@ -58,6 +58,7 @@ public class NodeSerializer { private static final String wantToRetireKey = "wantToRetire"; private static final String wantToDeprovisionKey = "wantToDeprovision"; private static final String hardwareDivergenceKey = "hardwareDivergence"; + private static final String osVersionKey = "osVersion"; // Configuration fields private static final String flavorKey = "flavor"; @@ -114,6 +115,7 @@ public class NodeSerializer { object.setString(nodeTypeKey, toString(node.type())); node.status().hardwareDivergence().ifPresent(hardwareDivergence -> object.setString(hardwareDivergenceKey, hardwareDivergence)); + node.status().osVersion().ifPresent(version -> object.setString(osVersionKey, version.toString())); } private void toSlime(Allocation allocation, Cursor object) { @@ -169,7 +171,8 @@ public class NodeSerializer { hardwareFailureDescriptionFromSlime(object), object.field(wantToRetireKey).asBool(), object.field(wantToDeprovisionKey).asBool(), - removeQuotedNulls(hardwareDivergenceFromSlime(object))); + removeQuotedNulls(hardwareDivergenceFromSlime(object)), + versionFromSlime(object.field(osVersionKey))); } private Flavor flavorFromSlime(Inspector object) { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java index 0c32c13f387..6c9d0be69b2 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java @@ -21,7 +21,6 @@ import com.yahoo.vespa.hosted.provision.node.History; import com.yahoo.vespa.hosted.provision.provisioning.FlavorConfigBuilder; import org.junit.Test; -import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Arrays; @@ -240,7 +239,7 @@ public class SerializationTest { } @Test - public void serialize_additional_ip_addresses() throws IOException { + public void serialize_additional_ip_addresses() { Node node = createNode(); // Test round-trip with additional addresses @@ -326,7 +325,7 @@ public class SerializationTest { } @Test - public void vespa_version_serialization() throws Exception { + public void vespa_version_serialization() { String nodeWithWantedVespaVersion = "{\n" + " \"type\" : \"tenant\",\n" + @@ -343,6 +342,18 @@ public class SerializationTest { assertEquals("6.42.2", node.allocation().get().membership().cluster().vespaVersion().toString()); } + @Test + public void os_version_serialization() { + Node serialized = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(createNode())); + assertFalse(serialized.status().osVersion().isPresent()); + + // Update OS version + serialized = serialized.with(serialized.status() + .withOsVersion(Version.fromString("7.1"))); + serialized = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(serialized)); + assertEquals(Version.fromString("7.1"), serialized.status().osVersion().get()); + } + private byte[] createNodeJson(String hostname, String... ipAddress) { String ipAddressJsonPart = ""; if (ipAddress.length > 0) { |