summaryrefslogtreecommitdiffstats
path: root/node-repository
diff options
context:
space:
mode:
authortoby <smorgrav@yahoo-inc.com>2017-07-20 11:17:03 +0200
committertoby <smorgrav@yahoo-inc.com>2017-08-14 11:27:08 +0200
commitbe257d41f011bbe6d8bf9838ac4cf01f9dae7b00 (patch)
tree596171b2c18d18ec97bf386fc7d44e5fa9886076 /node-repository
parent9deb2785feb43f76c34eae81a44e63adba8923c8 (diff)
NodePrioritizer
Diffstat (limited to 'node-repository')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerAllocator.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/GroupPreparer.java92
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java13
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java3
5 files changed, 27 insertions, 87 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerAllocator.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerAllocator.java
index fca15283e5d..eaa1663158f 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerAllocator.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/DockerAllocator.java
@@ -133,7 +133,7 @@ public class DockerAllocator {
*
* TODO propagate this information either through the node object or from the configserver deployer
*/
- private static boolean isReplacement(NodeSpec nodeSpec, List<Node> nodesBefore, List<Node> nodesReserved) {
+ public static boolean isReplacement(NodeSpec nodeSpec, List<Node> nodesBefore, List<Node> nodesReserved) {
int wantedCount = 0;
if (nodeSpec instanceof NodeSpec.CountNodeSpec) {
NodeSpec.CountNodeSpec countSpec = (NodeSpec.CountNodeSpec) nodeSpec;
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 caa2de2f973..ab69db260c7 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
@@ -3,23 +3,14 @@ package com.yahoo.vespa.hosted.provision.provisioning;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
-import com.yahoo.config.provision.Flavor;
-import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.OutOfCapacityException;
import com.yahoo.lang.MutableInteger;
import com.yahoo.transaction.Mutex;
import com.yahoo.vespa.hosted.provision.Node;
-import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.NodeRepository;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.time.Clock;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import java.util.Optional;
-import java.util.Set;
import java.util.function.BiConsumer;
/**
@@ -65,24 +56,20 @@ class GroupPreparer {
NodePrioritizer prioritizer = new NodePrioritizer(
nodeRepository.getNodes(),
+ application,
+ cluster,
+ requestedNodes,
nodeRepository.getAvailableFlavors(),
- a -> nodeRepository.getNode(a.parentHostname().orElse(" NOT-A-NODE !"), Node.State.values()),
- getDockerFlavor(requestedNodes),
- requestedNodes.specifiesNonStockFlavor(),
1,
nofSpares);
- prioritizer.addApplicationNodes(nodeRepository.getNodes(application, Node.State.active, Node.State.inactive, Node.State.reserved));
- prioritizer.addSurplusNodes(surplusActiveNodes);
- prioritizer.addReadyNodes(nodeRepository.getNodes(Node.State.ready));
- prioritizer.addNewNodes(createNewNodes(nodeRepository.getNodes(), getDockerFlavor(requestedNodes), cluster));
-
+ prioritizer.initNodes(surplusActiveNodes, nodeRepository.dynamicAllocationEnabled());
NodeAllocation allocation = new NodeAllocation(application, cluster, requestedNodes, highestIndex, clock);
- List<Node> acceptedNodes = allocation.offer(prioritizer.toPrioritizedNodeList(false), false); //TODO replacement
+ prioritizer.offer(allocation);
if (allocation.fullfilled()) {
- nodeRepository.reserve(prioritizer.filterInactiveAndReadyNodes(acceptedNodes));
- nodeRepository.addDockerNodes(prioritizer.filterNewNodes(acceptedNodes));
- surplusActiveNodes.removeAll(prioritizer.filterSurplusNodes(acceptedNodes));
+ nodeRepository.reserve(prioritizer.filterInactiveAndReadyNodes(allocation.getAcceptedNodes()));
+ nodeRepository.addDockerNodes(prioritizer.filterNewNodes(allocation.getAcceptedNodes()));
+ surplusActiveNodes.removeAll(prioritizer.filterSurplusNodes(allocation.getAcceptedNodes()));
return allocation.finalNodes(surplusActiveNodes);
} else {
throw new OutOfCapacityException("Could not satisfy " + requestedNodes + " for " + cluster +
@@ -92,14 +79,6 @@ class GroupPreparer {
}
}
- private Optional<Flavor> getDockerFlavor(NodeSpec nodeSpec) {
- if (nodeSpec instanceof NodeSpec.CountNodeSpec) {
- NodeSpec.CountNodeSpec countSpec = (NodeSpec.CountNodeSpec) nodeSpec;
- return Optional.of(countSpec.getFlavor());
- }
- return Optional.empty();
- }
-
private String outOfCapacityDetails(NodeAllocation allocation) {
if (allocation.wouldBeFulfilledWithClashingParentHost()) {
return ": Not enough nodes available on separate physical hosts.";
@@ -109,59 +88,4 @@ class GroupPreparer {
}
return ".";
}
-
- /**
- * Create new nodes on all hosts that have capacity for the requested flavor
- * (regardless of headroom and spare constraints) and where the parent nodes does not have
- * a conflicting node (a node in the same cluster).
- *
- * @param allNodes The existing nodes in the node-repository (thus no headroom and spares here)
- */
- private List<Node> createNewNodes(List<Node> allNodes, Optional<Flavor> dockerFlavor, ClusterSpec clusterSpec) {
- List<Node> newNodes = new ArrayList<>();
- // Only create nodes if this is docker and the dynamic allocation is enabled
- if (!nodeRepository.dynamicAllocationEnabled() || !dockerFlavor.isPresent()) return newNodes;
-
- Flavor flavor = dockerFlavor.get();
- DockerHostCapacity capacity = new DockerHostCapacity(allNodes);
- for (Node node : allNodes) {
- // For each host
- if (node.type() == NodeType.host) {
- NodeList list = new NodeList(allNodes);
- NodeList childrenWithSameApp = list.childNodes(node).owner(null);
- for (Node child : childrenWithSameApp.asList()) {
- // Look for nodes from the same cluster
- if (child.allocation().get().membership().cluster().id().equals(clusterSpec.id())) {
-
- }
- }
-
- if (capacity.hasCapacity(node, flavor)) {
- Set<String> ipAddresses = DockerHostCapacity.findFreeIps(node, allNodes);
- if (ipAddresses.isEmpty()) continue;
- String ipAddress = ipAddresses.stream().findFirst().get();
- String hostname = lookupHostname(ipAddress);
- if (hostname == null) continue;
- Node newNode = Node.createDockerNode("fake-" + hostname, Collections.singleton(ipAddress),
- Collections.emptySet(), hostname, Optional.of(node.hostname()), flavor, NodeType.tenant);
- newNodes.add(newNode);
- }
- }
- }
- return newNodes;
- }
-
- /**
- * From ipAddress - get hostname
- *
- * @return hostname or null if not able to do the loopup
- */
- private static String lookupHostname(String ipAddress) {
- try {
- return InetAddress.getByName(ipAddress).getHostName();
- } catch (UnknownHostException e) {
- e.printStackTrace();
- }
- return null;
- }
}
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 b8d0495095b..e0d776a223e 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
@@ -236,6 +236,10 @@ public class NodeAllocation {
return new ArrayList<>(nodes);
}
+ public Set<Node> getAcceptedNodes() {
+ return nodes;
+ }
+
private List<Node> byDecreasingIndex(Set<Node> nodes) {
return nodes.stream().sorted(nodeIndexComparator().reversed()).collect(Collectors.toList());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
index ad66f86de69..fb8fdee222c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
@@ -60,6 +60,10 @@ public class MockNodeRepository extends NodeRepository {
Collections.sort(ipAddressesForAllHost);
final HashSet<String> ipAddresses = new HashSet<>(ipAddressesForAllHost);
+ final List<String> additionalIpAddressesForAllHost = Arrays.asList("::2", "::3", "::4");
+ Collections.sort(additionalIpAddressesForAllHost);
+ final HashSet<String> additionalIpAddresses = new HashSet<>(additionalIpAddressesForAllHost);
+
nodes.add(createNode("node1", "host1.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
nodes.add(createNode("node2", "host2.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
nodes.add(createNode("node3", "host3.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("expensive"), NodeType.tenant));
@@ -83,7 +87,8 @@ public class MockNodeRepository extends NodeRepository {
nodes.add(node10);
nodes.add(createNode("node55", "host55.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.tenant));
- nodes.add(createNode("parent1", "parent1.yahoo.com", ipAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.host));
+ nodes.add(createNode("parent1", "parent1.yahoo.com", ipAddresses, additionalIpAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.host));
+ nodes.add(createNode("parent2", "dockerhost4", ipAddresses, additionalIpAddresses, Optional.empty(), flavors.getFlavorOrThrow("default"), NodeType.host));
nodes = addNodes(nodes);
nodes.remove(6);
@@ -93,6 +98,12 @@ public class MockNodeRepository extends NodeRepository {
fail("host5.yahoo.com", Agent.system, "Failing to unit test");
setDirty("host55.yahoo.com");
+ ApplicationId zoneApp = ApplicationId.from(TenantName.from("zoneapp"), ApplicationName.from("zoneapp"), InstanceName.from("zoneapp"));
+ ClusterSpec zoneCluster = ClusterSpec.request(ClusterSpec.Type.container,
+ ClusterSpec.Id.from("node-admin"),
+ Version.fromString("6.42"));
+ activate(provisioner.prepare(zoneApp, zoneCluster, Capacity.fromRequiredNodeType(NodeType.host), 1, null), zoneApp, provisioner);
+
ApplicationId app1 = ApplicationId.from(TenantName.from("tenant1"), ApplicationName.from("application1"), InstanceName.from("instance1"));
ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("id1"), Version.fromString("6.42"));
provisioner.prepare(app1, cluster1, Capacity.fromNodeCount(2), 1, null);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
index dd2b64a7854..aa54eb292a3 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/RestApiTest.java
@@ -506,7 +506,8 @@ public class RestApiTest {
private JDisc container;
@Before
- public void startContainer() { container = JDisc.fromServicesXml(ContainerConfig.servicesXmlV2(0), Networking.disable); }
+ public void startContainer() {
+ container = JDisc.fromServicesXml(ContainerConfig.servicesXmlV2(0), Networking.disable); }
@After
public void stopContainer() { container.close(); }