summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2017-11-08 15:38:38 +0100
committerJon Bratseth <bratseth@yahoo-inc.com>2017-11-08 15:38:38 +0100
commitde07a398d52413413ff1688411707cd67de69164 (patch)
tree5f5afd03f4e7de9f0e2c566185cb4eda97b12b51 /node-repository
parentf89408d83451f4c2ab73ae366ce2f7344a1a33e8 (diff)
In-place flavor downsize
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java44
3 files changed, 46 insertions, 12 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
index 0bf48b805aa..fae178adb87 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java
@@ -49,7 +49,7 @@ class GroupPreparer {
List<Node> surplusActiveNodes, MutableInteger highestIndex, int nofSpares, BiConsumer<List<Node>, String> debugRecorder) {
try (Mutex lock = nodeRepository.lock(application)) {
- // Use new, ready nodes. Lock ready pool to ensure that nodes are not grabbed by others.
+ // Lock ready pool to ensure that ready nodes are not simultaneously grabbed by others
try (Mutex readyLock = nodeRepository.lockUnallocated()) {
// Create a prioritized set of nodes
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
index b9f682bc79f..d9d7b4a5d12 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java
@@ -90,15 +90,15 @@ class NodeAllocation {
// conditions on which we want to retire nodes that were allocated previously
if ( offeredNodeHasParentHostnameAlreadyAccepted(this.nodes, offered)) wantToRetireNode = true;
- if ( !hasCompatibleFlavor(offered)) wantToRetireNode = true;
+ if ( ! hasCompatibleFlavor(offered)) wantToRetireNode = true;
if ( offered.flavor().isRetired()) wantToRetireNode = true;
if ( offered.status().wantToRetire()) wantToRetireNode = true;
- if ((!saturated() && hasCompatibleFlavor(offered)) || acceptToRetire(offered) ) {
+ if (( ! saturated() && hasCompatibleFlavor(offered)) || acceptToRetire(offered) ) {
accepted.add(acceptNode(offeredPriority, wantToRetireNode));
}
}
- else if (! saturated() && hasCompatibleFlavor(offered)) {
+ else if ( ! saturated() && hasCompatibleFlavor(offered)) {
if ( offeredNodeHasParentHostnameAlreadyAccepted(this.nodes, offered)) {
++rejectedWithClashingParentHost;
continue;
@@ -233,6 +233,12 @@ class NodeAllocation {
}
}
}
+
+ // Update flavor of allocated docker nodes as we can change it in place
+ for (PrioritizableNode node : nodes) {
+ if (node.node.allocation().isPresent())
+ node.node = requestedNodes.assignRequestedFlavor(node.node);
+ }
return nodes.stream().map(n -> n.node).collect(Collectors.toList());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
index 10d562eff98..dba6c527038 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeSpec.java
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.Flavor;
+import com.yahoo.vespa.hosted.provision.Node;
import java.util.Objects;
@@ -39,6 +40,13 @@ public interface NodeSpec {
/** Returns a specification of a fraction of all the nodes of this. It is assumed the argument is a valid divisor. */
NodeSpec fraction(int divisor);
+ /**
+ * Assigns the flavor requested by this to the given node and returns it,
+ * if one is requested and it is allowed to change.
+ * Otherwise, the node is returned unchanged.
+ */
+ Node assignRequestedFlavor(Node node);
+
static NodeSpec from(int nodeCount, Flavor flavor) {
return new CountNodeSpec(nodeCount, flavor);
}
@@ -51,16 +59,16 @@ public interface NodeSpec {
class CountNodeSpec implements NodeSpec {
private final int count;
- private final Flavor flavor;
+ private final Flavor requestedFlavor;
public CountNodeSpec(int count, Flavor flavor) {
Objects.requireNonNull(flavor, "A flavor must be specified");
this.count = count;
- this.flavor = flavor;
+ this.requestedFlavor = flavor;
}
public Flavor getFlavor() {
- return flavor;
+ return requestedFlavor;
}
public int getCount() { return count; }
@@ -69,13 +77,17 @@ public interface NodeSpec {
public NodeType type() { return NodeType.tenant; }
@Override
- public boolean isCompatible(Flavor flavor) { return flavor.satisfies(this.flavor); }
+ public boolean isCompatible(Flavor flavor) {
+ if (flavor.satisfies(requestedFlavor)) return true;
+
+ return requestedFlavorCanBeAchievedByResizing(flavor);
+ }
@Override
- public boolean matchesExactly(Flavor flavor) { return flavor.equals(this.flavor); }
+ public boolean matchesExactly(Flavor flavor) { return flavor.equals(this.requestedFlavor); }
@Override
- public boolean specifiesNonStockFlavor() { return ! flavor.isStock(); }
+ public boolean specifiesNonStockFlavor() { return ! requestedFlavor.isStock(); }
@Override
public boolean fulfilledBy(int count) { return count >= this.count; }
@@ -87,10 +99,23 @@ public interface NodeSpec {
public int surplusGiven(int count) { return count - this.count; }
@Override
- public NodeSpec fraction(int divisor) { return new CountNodeSpec(count/divisor, flavor); }
+ public NodeSpec fraction(int divisor) { return new CountNodeSpec(count/divisor, requestedFlavor); }
+
+ @Override
+ public Node assignRequestedFlavor(Node node) {
+ // Docker nodes can change flavor in place
+ if (requestedFlavorCanBeAchievedByResizing(node.flavor()))
+ return node.with(requestedFlavor);
+ return node;
+ }
@Override
- public String toString() { return "request for " + count + " nodes of " + flavor; }
+ public String toString() { return "request for " + count + " nodes of " + requestedFlavor; }
+
+ /** Docker nodes can be downsized in place */
+ private boolean requestedFlavorCanBeAchievedByResizing(Flavor flavor) {
+ return flavor.isDocker() && requestedFlavor.isDocker() && flavor.isLargerThan(requestedFlavor);
+ }
}
@@ -128,6 +153,9 @@ public interface NodeSpec {
public NodeSpec fraction(int divisor) { return this; }
@Override
+ public Node assignRequestedFlavor(Node node) { return node; }
+
+ @Override
public String toString() { return "request for all nodes of type '" + type + "'"; }
}