summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorHÃ¥kon Hallingstad <hakon@oath.com>2018-02-28 14:52:56 +0100
committerGitHub <noreply@github.com>2018-02-28 14:52:56 +0100
commit5ce8b9526d3b163a68cf8dd10626227cfac3da5b (patch)
tree514c40bc32b00e97289bbaaf1cdd59bafa72d4d1 /config-model
parent79989edc0e7f21b4ccfab906bae02dee6b02e4e7 (diff)
parent8efe633228dd9071cd2b311657293e50736f0069 (diff)
Merge pull request #5169 from vespa-engine/hakonhall/avoid-slobrok-in-node-admin-cluster
Avoid Slobrok in node-admin cluster
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java41
-rw-r--r--config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java97
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java16
3 files changed, 122 insertions, 32 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
index cc9957144f3..44de53991f4 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
@@ -2,22 +2,23 @@
package com.yahoo.vespa.model.builder.xml.dom;
import com.yahoo.component.Version;
+import com.yahoo.config.model.ConfigModelContext;
import com.yahoo.config.model.api.ConfigServerSpec;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.vespa.model.HostResource;
import com.yahoo.vespa.model.HostSystem;
-import com.yahoo.vespa.model.admin.*;
-import com.yahoo.config.model.ConfigModelContext;
import com.yahoo.vespa.model.admin.Admin;
+import com.yahoo.vespa.model.admin.Logserver;
+import com.yahoo.vespa.model.admin.Slobrok;
import com.yahoo.vespa.model.container.Container;
import com.yahoo.vespa.model.container.ContainerModel;
-
import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -27,6 +28,7 @@ import java.util.stream.Collectors;
* @author bratseth
*/
public class DomAdminV4Builder extends DomAdminBuilderBase {
+ private ApplicationId ZONE_APPLICATION_ID = ApplicationId.from("hosted-vespa", "routing", "default");
private final Collection<ContainerModel> containerModels;
private final ConfigModelContext context;
@@ -63,7 +65,7 @@ public class DomAdminV4Builder extends DomAdminBuilderBase {
createSlobroks(admin, allocateHosts(admin.getHostSystem(), "slobroks", nodesSpecification));
}
else {
- createSlobroks(admin, pickContainerHosts(nodesSpecification.count(), 2));
+ createSlobroks(admin, pickContainerHostsForSlobrok(nodesSpecification.count(), 2));
}
}
@@ -94,17 +96,36 @@ public class DomAdminV4Builder extends DomAdminBuilderBase {
* on topology changes, and less nodes may be returned if fewer are available
* @param minHostsPerContainerCluster the desired number of hosts per cluster
*/
- private List<HostResource> pickContainerHosts(int count, int minHostsPerContainerCluster) {
+ private List<HostResource> pickContainerHostsForSlobrok(int count, int minHostsPerContainerCluster) {
+ Collection<ContainerModel> containerModelsWithSlobrok = containerModels.stream()
+ .filter(this::shouldHaveSlobrok)
+ .collect(Collectors.toList());
+ int hostsPerCluster = (int) Math.max(
+ minHostsPerContainerCluster,
+ Math.ceil((double) count / containerModelsWithSlobrok.size()));
+
// Pick from all container clusters to make sure we don't lose all nodes at once if some clusters are removed.
// This will overshoot the desired size (due to ceil and picking at least one node per cluster).
List<HostResource> picked = new ArrayList<>();
- for (ContainerModel containerModel : containerModels)
- picked.addAll(pickContainerHostsFrom(containerModel,
- (int) Math.max(minHostsPerContainerCluster,
- Math.ceil((double) count / containerModels.size()))));
+ for (ContainerModel containerModel : containerModelsWithSlobrok)
+ picked.addAll(pickContainerHostsFrom(containerModel, hostsPerCluster));
return picked;
}
+ private boolean shouldHaveSlobrok(ContainerModel containerModel) {
+ // Avoid Slobroks on node-admin container cluster, as node-admin is migrating
+ // TODO: Remove this hack once node-admin has migrated out the zone app
+
+ ApplicationId applicationId = context.getDeployState().getProperties().applicationId();
+ if (!applicationId.equals(ZONE_APPLICATION_ID)) {
+ return true;
+ }
+
+ // aka clustername, aka application-model's ClusterId
+ String clustername = containerModel.getCluster().getName();
+ return !Objects.equals(clustername, "node-admin");
+ }
+
private List<HostResource> pickContainerHostsFrom(ContainerModel model, int count) {
boolean retired = true;
List<HostResource> picked = sortedContainerHostsFrom(model, count, !retired);
diff --git a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java
index 91be617d0ea..d4ce445d50c 100644
--- a/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java
+++ b/config-model/src/test/java/com/yahoo/config/model/provision/ModelProvisioningTest.java
@@ -1,46 +1,57 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.model.provision;
-import static com.yahoo.config.model.test.TestUtil.joinLines;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
-
-import java.io.StringReader;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
import com.yahoo.config.application.api.ApplicationPackage;
+import com.yahoo.config.model.api.HostInfo;
import com.yahoo.config.model.deploy.DeployProperties;
+import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provisioning.FlavorsConfig;
import com.yahoo.search.config.QrStartConfig;
+import com.yahoo.searchdefinition.parser.ParseException;
import com.yahoo.vespa.config.search.core.ProtonConfig;
-import static com.yahoo.vespa.defaults.Defaults.getDefaults;
+import com.yahoo.vespa.model.AbstractService;
import com.yahoo.vespa.model.HostResource;
import com.yahoo.vespa.model.HostSystem;
+import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.admin.Admin;
import com.yahoo.vespa.model.admin.Slobrok;
import com.yahoo.vespa.model.container.Container;
import com.yahoo.vespa.model.container.ContainerCluster;
import com.yahoo.vespa.model.content.ContentSearchCluster;
+import com.yahoo.vespa.model.content.StorageNode;
+import com.yahoo.vespa.model.content.cluster.ContentCluster;
import com.yahoo.vespa.model.search.Dispatch;
import com.yahoo.vespa.model.search.SearchNode;
import com.yahoo.vespa.model.test.VespaModelTester;
+import com.yahoo.vespa.model.test.utils.ApplicationPackageUtils;
+import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg;
import org.junit.Ignore;
import org.junit.Test;
-import com.yahoo.config.model.deploy.DeployState;
-import com.yahoo.searchdefinition.parser.ParseException;
-import com.yahoo.vespa.model.VespaModel;
-import com.yahoo.vespa.model.content.StorageNode;
-import com.yahoo.vespa.model.content.cluster.ContentCluster;
-import com.yahoo.vespa.model.test.utils.ApplicationPackageUtils;
-import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.yahoo.config.model.test.TestUtil.joinLines;
+import static com.yahoo.vespa.defaults.Defaults.getDefaults;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.collection.IsIn.isIn;
+import static org.hamcrest.core.Every.everyItem;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Test cases for provisioning nodes to entire vespamodels
@@ -736,6 +747,52 @@ public class ModelProvisioningTest {
}
@Test
+ public void testSlobroksAreSpreadOverAllContainerClustersExceptNodeAdmin() {
+ String services =
+ "<?xml version='1.0' encoding='utf-8' ?>\n" +
+ "<services>" +
+ " <admin version='4.0'/>" +
+ " <container version='1.0' id='routing'>" +
+ " <nodes count='10'/>" +
+ " </container>" +
+ " <container version='1.0' id='node-admin'>" +
+ " <nodes count='3'/>" +
+ " </container>" +
+ "</services>";
+
+ int numberOfHosts = 13;
+ VespaModelTester tester = new VespaModelTester();
+ tester.addHosts(numberOfHosts);
+ tester.setApplicationId("hosted-vespa", "routing", "default");
+ VespaModel model = tester.createModel(services, true);
+ assertThat(model.getRoot().getHostSystem().getHosts().size(), is(numberOfHosts));
+
+ Set<String> routingHosts = getClusterHostnames(model, "routing");
+ assertEquals(10, routingHosts.size());
+
+ Set<String> nodeAdminHosts = getClusterHostnames(model, "node-admin");
+ assertEquals(3, nodeAdminHosts.size());
+
+ Set<String> slobrokHosts = model.getAdmin().getSlobroks().stream()
+ .map(AbstractService::getHostName)
+ .collect(Collectors.toSet());
+ assertEquals(3, slobrokHosts.size());
+
+ assertThat(slobrokHosts, everyItem(isIn(routingHosts)));
+ assertThat(slobrokHosts, everyItem(not(isIn(nodeAdminHosts))));
+ }
+
+ private Set<String> getClusterHostnames(VespaModel model, String clusterId) {
+ return model.getHosts().stream()
+ .filter(host -> host.getServices().stream()
+ .anyMatch(serviceInfo -> Objects.equals(
+ serviceInfo.getProperty("clustername"),
+ Optional.of(clusterId))))
+ .map(HostInfo::getHostname)
+ .collect(Collectors.toSet());
+ }
+
+ @Test
public void test2ContentNodesProduces1ClusterController() {
String services =
"<?xml version='1.0' encoding='utf-8' ?>\n" +
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java
index 37ddf458121..715b84c7093 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTester.java
@@ -12,6 +12,7 @@ import com.yahoo.config.model.provision.Host;
import com.yahoo.config.model.provision.Hosts;
import com.yahoo.config.model.provision.InMemoryProvisioner;
import com.yahoo.config.model.provision.SingleNodeProvisioner;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Flavor;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.test.utils.ApplicationPackageUtils;
@@ -43,6 +44,7 @@ public class VespaModelTester {
private boolean hosted = true;
private Map<String, Collection<Host>> hostsByFlavor = new HashMap<>();
+ private ApplicationId applicationId = ApplicationId.defaultId();
public VespaModelTester() {
this(new NullConfigModelRegistry());
@@ -84,6 +86,11 @@ public class VespaModelTester {
/** Sets whether this sets up a model for a hosted system. Default: true */
public void setHosted(boolean hosted) { this.hosted = hosted; }
+ /** Sets the tenant, application name, and instance name of the model being built. */
+ public void setApplicationId(String tenant, String applicationName, String instanceName) {
+ applicationId = ApplicationId.from(tenant, applicationName, instanceName);
+ }
+
/** Creates a model which uses 0 as start index and fails on out of capacity */
public VespaModel createModel(String services, String ... retiredHostNames) {
return createModel(services, true, retiredHostNames);
@@ -108,11 +115,16 @@ public class VespaModelTester {
new InMemoryProvisioner(hostsByFlavor, failOnOutOfCapacity, startIndexForClusters, retiredHostNames) :
new SingleNodeProvisioner();
+ DeployProperties properties = new DeployProperties.Builder()
+ .hostedVespa(hosted)
+ .applicationId(applicationId)
+ .build();
+
DeployState deployState = new DeployState.Builder()
.applicationPackage(appPkg)
.modelHostProvisioner(provisioner)
- .properties((new DeployProperties.Builder()).hostedVespa(hosted).build()).build(true);
+ .properties(properties)
+ .build(true);
return modelCreatorWithMockPkg.create(false, deployState, configModelRegistry);
}
-
}