aboutsummaryrefslogtreecommitdiffstats
path: root/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2019-08-14 20:25:52 +0200
committerGitHub <noreply@github.com>2019-08-14 20:25:52 +0200
commit4e52564e8d01d3af68d611d9bd88e497bbd08e25 (patch)
treeef0e2e43d1189ad03565e9d911a991474c0f9f6e /config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
parentfc6ebf45c0ef126043eb9db4cf613958ce665411 (diff)
Revert "Bratseth/remove allocation by flavor"
Diffstat (limited to 'config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java')
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java89
1 files changed, 69 insertions, 20 deletions
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
index 2bc70efbc15..48c84b8ecb7 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Flavor.java
@@ -3,14 +3,15 @@ package com.yahoo.config.provision;
import com.yahoo.config.provisioning.FlavorsConfig;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* A host or node flavor.
* *Host* flavors come from a configured set which corresponds to the actual flavors available in a zone.
- * *Node* flavors are simply a wrapper of a NodeResources object.
+ * *Node* flavors are simply a wrapper of a NodeResources object (for now (May 2019) with the exception of some
+ * legacy behavior where nodes are allocated by specifying a physical host flavor directly).
*
* @author bratseth
*/
@@ -19,8 +20,11 @@ public class Flavor {
private boolean configured;
private final String name;
private final int cost;
+ private final boolean isStock;
private final Type type;
private final double bandwidth;
+ private final boolean retired;
+ private List<Flavor> replacesFlavors;
/** The hardware resources of this flavor */
private NodeResources resources;
@@ -30,22 +34,31 @@ public class Flavor {
this.configured = true;
this.name = flavorConfig.name();
this.cost = flavorConfig.cost();
+ this.isStock = flavorConfig.stock();
this.type = Type.valueOf(flavorConfig.environment());
this.resources = new NodeResources(flavorConfig.minCpuCores(),
flavorConfig.minMainMemoryAvailableGb(),
flavorConfig.minDiskAvailableGb(),
flavorConfig.fastDisk() ? NodeResources.DiskSpeed.fast : NodeResources.DiskSpeed.slow);
this.bandwidth = flavorConfig.bandwidth();
+ this.retired = flavorConfig.retired();
+ this.replacesFlavors = new ArrayList<>();
}
/** Creates a *node* flavor from a node resources spec */
public Flavor(NodeResources resources) {
Objects.requireNonNull(resources, "Resources cannot be null");
+ if (resources.allocateByLegacyName())
+ throw new IllegalArgumentException("Can not create flavor '" + resources.legacyName() + "' from a flavor: " +
+ "Non-docker flavors must be of a configured flavor");
this.configured = false;
- this.name = resources.toString();
+ this.name = resources.legacyName().orElse(resources.toString());
this.cost = 0;
+ this.isStock = true;
this.type = Type.DOCKER_CONTAINER;
this.bandwidth = 1;
+ this.retired = false;
+ this.replacesFlavors = List.of();
this.resources = resources;
}
@@ -60,6 +73,8 @@ public class Flavor {
*/
public int cost() { return cost; }
+ public boolean isStock() { return isStock; }
+
/**
* True if this is a configured flavor used for hosts,
* false if it is a virtual flavor created on the fly from node resources
@@ -78,31 +93,65 @@ public class Flavor {
public double getMinCpuCores() { return resources.vcpu(); }
+ /** Returns whether the flavor is retired */
+ public boolean isRetired() {
+ return retired;
+ }
+
public Type getType() { return type; }
/** Convenience, returns getType() == Type.DOCKER_CONTAINER */
public boolean isDocker() { return type == Type.DOCKER_CONTAINER; }
- // TODO: Remove after August 2019
- public String canonicalName() { return name; }
-
- // TODO: Remove after August 2019
- public boolean satisfies(Flavor flavor) { return this.equals(flavor); }
-
- // TODO: Remove after August 2019
- public boolean isStock() { return false; }
-
- // TODO: Remove after August 2019
- public boolean isRetired() { return false; }
+ /**
+ * Returns the canonical name of this flavor - which is the name which should be used as an interface to users.
+ * The canonical name of this flavor is:
+ * <ul>
+ * <li>If it replaces one flavor, the canonical name of the flavor it replaces
+ * <li>If it replaces multiple or no flavors - itself
+ * </ul>
+ *
+ * The logic is that we can use this to capture the gritty details of configurations in exact flavor names
+ * but also encourage users to refer to them by a common name by letting such flavor variants declare that they
+ * replace the canonical name we want. However, if a node replaces multiple names, we have no basis for choosing one
+ * of them as the canonical, so we return the current as canonical.
+ */
+ public String canonicalName() {
+ return isCanonical() ? name : replacesFlavors.get(0).canonicalName();
+ }
+
+ /** Returns whether this is a canonical flavor */
+ public boolean isCanonical() {
+ return replacesFlavors.size() != 1;
+ }
- // TODO: Remove after August 2019
- public boolean isCanonical() { return false; }
+ /**
+ * The flavors this (directly) replaces.
+ * This is immutable if this is frozen, and a mutable list otherwise.
+ */
+ public List<Flavor> replaces() { return replacesFlavors; }
- // TODO: Remove after August 2019
- public List<Flavor> replaces() { return Collections.emptyList(); }
+ /**
+ * Returns whether this flavor satisfies the requested flavor, either directly
+ * (by being the same), or by directly or indirectly replacing it
+ */
+ public boolean satisfies(Flavor flavor) {
+ if (this.equals(flavor)) {
+ return true;
+ }
+ if (this.retired) {
+ return false;
+ }
+ for (Flavor replaces : replacesFlavors)
+ if (replaces.satisfies(flavor))
+ return true;
+ return false;
+ }
- // TODO: Remove after August 2019
- public void freeze() {}
+ /** Irreversibly freezes the content of this */
+ public void freeze() {
+ replacesFlavors = List.copyOf(replacesFlavors);
+ }
@Override
public int hashCode() { return name.hashCode(); }