aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
diff options
context:
space:
mode:
Diffstat (limited to 'node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java146
1 files changed, 21 insertions, 125 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
index 8e14b61db9a..2642983dd2a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java
@@ -20,10 +20,7 @@ import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.flags.FlagSource;
import com.yahoo.vespa.hosted.provision.Node.State;
import com.yahoo.vespa.hosted.provision.applications.Applications;
-import com.yahoo.vespa.hosted.provision.lb.LoadBalancer;
-import com.yahoo.vespa.hosted.provision.lb.LoadBalancerId;
-import com.yahoo.vespa.hosted.provision.lb.LoadBalancerInstance;
-import com.yahoo.vespa.hosted.provision.lb.LoadBalancerList;
+import com.yahoo.vespa.hosted.provision.lb.LoadBalancers;
import com.yahoo.vespa.hosted.provision.maintenance.InfrastructureVersions;
import com.yahoo.vespa.hosted.provision.maintenance.NodeFailer;
import com.yahoo.vespa.hosted.provision.maintenance.PeriodicApplicationMaintainer;
@@ -50,17 +47,13 @@ import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
-import java.util.Comparator;
import java.util.EnumSet;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
-import java.util.TreeSet;
import java.util.function.BiFunction;
-import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -111,6 +104,7 @@ public class NodeRepository extends AbstractComponent {
private final ContainerImages containerImages;
private final JobControl jobControl;
private final Applications applications;
+ private final LoadBalancers loadBalancers;
private final int spareCount;
/**
@@ -171,6 +165,7 @@ public class NodeRepository extends AbstractComponent {
this.containerImages = new ContainerImages(db, containerImage);
this.jobControl = new JobControl(new JobControlFlags(db, flagSource));
this.applications = new Applications(db);
+ this.loadBalancers = new LoadBalancers(db);
this.spareCount = spareCount;
rewriteNodes();
}
@@ -213,15 +208,30 @@ public class NodeRepository extends AbstractComponent {
/** Returns this node repo's view of the applications deployed to it */
public Applications applications() { return applications; }
- public NodeFlavors flavors() {
- return flavors;
- }
+ /** Returns the load balancers available in this node repo */
+ public LoadBalancers loadBalancers() { return loadBalancers; }
+
+ public NodeFlavors flavors() { return flavors; }
public HostResourcesCalculator resourcesCalculator() { return resourcesCalculator; }
/** The number of nodes we should ensure has free capacity for node failures whenever possible */
public int spareCount() { return spareCount; }
+ /**
+ * Returns ACLs for the children of the given host.
+ *
+ * @param host node for which to generate ACLs
+ * @return the list of node ACLs
+ */
+ public List<NodeAcl> getChildAcls(Node host) {
+ if ( ! host.type().isHost()) throw new IllegalArgumentException("Only hosts have children");
+ NodeList allNodes = list();
+ return list().childrenOf(host).asList().stream()
+ .map(childNode -> childNode.acl(allNodes, loadBalancers))
+ .collect(Collectors.toUnmodifiableList());
+ }
+
// ---------------- Query API ----------------------------------------------------------------
/**
@@ -274,125 +284,11 @@ public class NodeRepository extends AbstractComponent {
return new LockedNodeList(getNodes(), lock);
}
- /** Returns a filterable list of all load balancers in this repository */
- public LoadBalancerList loadBalancers() {
- return loadBalancers((ignored) -> true);
- }
-
- /** Returns a filterable list of load balancers belonging to given application */
- public LoadBalancerList loadBalancers(ApplicationId application) {
- return loadBalancers((id) -> id.application().equals(application));
- }
-
- private LoadBalancerList loadBalancers(Predicate<LoadBalancerId> predicate) {
- return LoadBalancerList.copyOf(db.readLoadBalancers(predicate).values());
- }
-
public List<Node> getNodes(ApplicationId id, State ... inState) { return db.readNodes(id, inState); }
public List<Node> getInactive() { return db.readNodes(State.inactive); }
public List<Node> getFailed() { return db.readNodes(State.failed); }
/**
- * Returns the ACL for the node (trusted nodes, networks and ports)
- */
- private NodeAcl getNodeAcl(Node node, NodeList candidates) {
- Set<Node> trustedNodes = new TreeSet<>(Comparator.comparing(Node::hostname));
- Set<Integer> trustedPorts = new LinkedHashSet<>();
- Set<String> trustedNetworks = new LinkedHashSet<>();
-
- // For all cases below, trust:
- // - SSH: If the Docker host has one container, and it is using the Docker host's network namespace,
- // opening up SSH to the Docker host is done here as a trusted port. For simplicity all nodes have
- // SSH opened (which is safe for 2 reasons: SSH daemon is not run inside containers, and NPT networks
- // will (should) not forward port 22 traffic to container).
- // - parent host (for health checks and metrics)
- // - nodes in same application
- // - load balancers allocated to application
- trustedPorts.add(22);
- candidates.parentOf(node).ifPresent(trustedNodes::add);
- node.allocation().ifPresent(allocation -> {
- trustedNodes.addAll(candidates.owner(allocation.owner()).asList());
- loadBalancers(allocation.owner()).asList().stream()
- .map(LoadBalancer::instance)
- .map(LoadBalancerInstance::networks)
- .forEach(trustedNetworks::addAll);
- });
-
- switch (node.type()) {
- case tenant:
- // Tenant nodes in other states than ready, trust:
- // - config servers
- // - proxy nodes
- // - parents of the nodes in the same application: If some of the nodes are on a different IP versions
- // or only a subset of them are dual-stacked, the communication between the nodes may be NATed
- // with via parent's IP address.
- trustedNodes.addAll(candidates.nodeType(NodeType.config).asList());
- trustedNodes.addAll(candidates.nodeType(NodeType.proxy).asList());
- node.allocation().ifPresent(allocation ->
- trustedNodes.addAll(candidates.parentsOf(candidates.owner(allocation.owner())).asList()));
-
- if (node.state() == State.ready) {
- // Tenant nodes in state ready, trust:
- // - All tenant nodes in zone. When a ready node is allocated to a an application there's a brief
- // window where current ACLs have not yet been applied on the node. To avoid service disruption
- // during this window, ready tenant nodes trust all other tenant nodes.
- trustedNodes.addAll(candidates.nodeType(NodeType.tenant).asList());
- }
- break;
-
- case config:
- // Config servers trust:
- // - all nodes
- // - port 4443 from the world
- trustedNodes.addAll(candidates.asList());
- trustedPorts.add(4443);
- break;
-
- case proxy:
- // Proxy nodes trust:
- // - config servers
- // - all connections from the world on 4080 (insecure tb removed), and 4443
- trustedNodes.addAll(candidates.nodeType(NodeType.config).asList());
- trustedPorts.add(443);
- trustedPorts.add(4080);
- trustedPorts.add(4443);
- break;
-
- case controller:
- // Controllers:
- // - port 4443 (HTTPS + Athenz) from the world
- // - port 443 (HTTPS + Okta) from the world
- // - port 80 (HTTP) from the world - for redirect to HTTPS/443 only
- trustedPorts.add(4443);
- trustedPorts.add(443);
- trustedPorts.add(80);
- break;
-
- default:
- illegal("Don't know how to create ACL for " + node + " of type " + node.type());
- }
-
- return new NodeAcl(node, trustedNodes, trustedNetworks, trustedPorts);
- }
-
- /**
- * Creates a list of node ACLs which identify which nodes the given node should trust
- *
- * @param node Node for which to generate ACLs
- * @param children Return ACLs for the children of the given node (e.g. containers on a Docker host)
- * @return List of node ACLs
- */
- public List<NodeAcl> getNodeAcls(Node node, boolean children) {
- NodeList candidates = list();
- if (children) {
- return candidates.childrenOf(node).asList().stream()
- .map(childNode -> getNodeAcl(childNode, candidates))
- .collect(Collectors.toUnmodifiableList());
- }
- return List.of(getNodeAcl(node, candidates));
- }
-
- /**
* Returns whether the zone managed by this node repository seems to be working.
* If too many nodes are not responding, there is probably some zone-wide issue
* and we should probably refrain from making changes to it.