diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-11-08 15:38:38 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-11-08 15:38:38 +0100 |
commit | de07a398d52413413ff1688411707cd67de69164 (patch) | |
tree | 5f5afd03f4e7de9f0e2c566185cb4eda97b12b51 /node-repository | |
parent | f89408d83451f4c2ab73ae366ce2f7344a1a33e8 (diff) |
In-place flavor downsize
Diffstat (limited to 'node-repository')
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 + "'"; } } |