com.yahoo.vespa.hosted.provision.node.Status Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of node-repository Show documentation
Show all versions of node-repository Show documentation
Keeps track of node assignment in a multi-application setup.
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.node;
import com.yahoo.component.Version;
import com.yahoo.config.provision.DockerImage;
import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
/**
* Information about current status of a node. This is immutable.
*
* @author bratseth
*/
public class Status {
private final Generation reboot;
private final Optional vespaVersion;
private final Optional containerImage;
private final int failCount;
private final boolean wantToRetire;
private final boolean wantToDeprovision;
private final boolean wantToRebuild;
private final boolean preferToRetire;
private final boolean wantToFail;
private final boolean wantToUpgradeFlavor;
private final OsVersion osVersion;
private final Optional firmwareVerifiedAt;
public Status(Generation generation,
Optional vespaVersion,
Optional containerImage,
int failCount,
boolean wantToRetire,
boolean wantToDeprovision,
boolean wantToRebuild,
boolean preferToRetire,
boolean wantToFail,
boolean wantToUpgradeFlavor,
OsVersion osVersion,
Optional firmwareVerifiedAt) {
this.reboot = Objects.requireNonNull(generation, "Generation must be non-null");
this.vespaVersion = Objects.requireNonNull(vespaVersion, "Vespa version must be non-null").filter(v -> !Version.emptyVersion.equals(v));
this.containerImage = Objects.requireNonNull(containerImage, "Container image must be non-null").filter(d -> !DockerImage.EMPTY.equals(d));
this.failCount = failCount;
this.wantToUpgradeFlavor = wantToUpgradeFlavor;
if (wantToDeprovision && wantToRebuild) {
throw new IllegalArgumentException("Node cannot be marked both wantToDeprovision and wantToRebuild");
}
if (wantToDeprovision && !wantToRetire) {
throw new IllegalArgumentException("Node cannot be marked wantToDeprovision unless it's also marked wantToRetire");
}
if (wantToUpgradeFlavor && !wantToRetire) {
throw new IllegalArgumentException("Node cannot be marked wantToUpgradeFlavor unless it's also marked wantToRetire");
}
this.wantToRetire = wantToRetire;
this.wantToDeprovision = wantToDeprovision;
this.wantToRebuild = wantToRebuild;
this.preferToRetire = preferToRetire;
this.wantToFail = wantToFail;
this.osVersion = Objects.requireNonNull(osVersion, "OS version must be non-null");
this.firmwareVerifiedAt = Objects.requireNonNull(firmwareVerifiedAt, "Firmware check instant must be non-null");
}
/** Returns a copy of this with the reboot generation changed */
public Status withReboot(Generation reboot) { return new Status(reboot, vespaVersion, containerImage, failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt); }
/** 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), containerImage, failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt); }
/** Returns the Vespa version installed on the node, if known */
public Optional vespaVersion() { return vespaVersion; }
/** Returns a copy of this with the container image changed */
public Status withContainerImage(DockerImage containerImage) { return new Status(reboot, vespaVersion, Optional.of(containerImage), failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt); }
/** Returns the container image the node is running, if any */
public Optional containerImage() { return containerImage; }
public Status withIncreasedFailCount() { return new Status(reboot, vespaVersion, containerImage, failCount + 1, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt); }
public Status withDecreasedFailCount() { return new Status(reboot, vespaVersion, containerImage, failCount - 1, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt); }
public Status withFailCount(int value) { return new Status(reboot, vespaVersion, containerImage, value, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt); }
/** Returns how many times this node has been moved to the failed state. */
public int failCount() { return failCount; }
/** Returns a copy of this with the want to retire/deprovision/rebuild flags changed */
public Status withWantToRetire(boolean wantToRetire, boolean wantToDeprovision, boolean wantToRebuild, boolean wantToUpgradeFlavor) {
return new Status(reboot, vespaVersion, containerImage, failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt);
}
/**
* Returns whether this node is requested to retire. This is a hard request to retire, which allows any replacement
* to increase node skew in the cluster.
*/
public boolean wantToRetire() { return wantToRetire; }
/**
* Returns whether this node should be de-provisioned when possible.
*/
public boolean wantToDeprovision() { return wantToDeprovision; }
/** Returns whether this node should be rebuilt when possible. */
public boolean wantToRebuild() { return wantToRebuild; }
/**
* Returns whether this node is requested to retire. Unlike {@link Status#wantToRetire()}, this is a soft
* request to retire, which will not allow any replacement to increase node skew in the cluster.
*/
public boolean preferToRetire() { return preferToRetire; }
/** Returns whether the flavor of is node is required to be of the latest generation */
public boolean wantToUpgradeFlavor() {
return wantToUpgradeFlavor;
}
/** Returns a copy of this with want to fail set to the given value */
public Status withWantToFail(boolean wantToFail) {
return new Status(reboot, vespaVersion, containerImage, failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt);
}
/** Returns whether this node should be failed */
public boolean wantToFail() { return wantToFail; }
/** Returns a copy of this with prefer-to-retire set to given value */
public Status withPreferToRetire(boolean preferToRetire) {
return new Status(reboot, vespaVersion, containerImage, failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, firmwareVerifiedAt);
}
/** Returns a copy of this with the OS version set to given version */
public Status withOsVersion(OsVersion version) {
return new Status(reboot, vespaVersion, containerImage, failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, version, firmwareVerifiedAt);
}
/** Returns the OS version of this node */
public OsVersion osVersion() {
return osVersion;
}
/** Returns a copy of this with the firmwareVerifiedAt set to the given instant. */
public Status withFirmwareVerifiedAt(Instant instant) {
return new Status(reboot, vespaVersion, containerImage, failCount, wantToRetire, wantToDeprovision, wantToRebuild, preferToRetire, wantToFail, wantToUpgradeFlavor, osVersion, Optional.of(instant));
}
/** Returns the last time this node had firmware that was verified to be up to date. */
public Optional firmwareVerifiedAt() {
return firmwareVerifiedAt;
}
/** Returns the initial status of a newly provisioned node */
public static Status initial() {
return new Status(Generation.initial(), Optional.empty(), Optional.empty(), 0, false,
false, false, false, false, false, OsVersion.EMPTY, Optional.empty());
}
}