diff options
Diffstat (limited to 'config-model/src/main/java')
5 files changed, 38 insertions, 125 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index 3722876a53f..59930a77a21 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -37,7 +37,6 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea private Zone zone; private final Set<ContainerEndpoint> endpoints = Collections.emptySet(); private boolean useDedicatedNodeForLogserver = false; - private boolean dedicatedClusterControllerCluster = true; private boolean useThreePhaseUpdates = false; private double defaultTermwiseLimit = 1.0; private String jvmGCOptions = null; @@ -78,7 +77,6 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea @Override public boolean isBootstrap() { return false; } @Override public boolean isFirstTimeDeployment() { return false; } @Override public boolean useDedicatedNodeForLogserver() { return useDedicatedNodeForLogserver; } - @Override public boolean dedicatedClusterControllerCluster() { return hostedVespa && dedicatedClusterControllerCluster; } @Override public Optional<EndpointCertificateSecrets> endpointCertificateSecrets() { return endpointCertificateSecrets; } @Override public double defaultTermwiseLimit() { return defaultTermwiseLimit; } @Override public boolean useThreePhaseUpdates() { return useThreePhaseUpdates; } @@ -170,11 +168,6 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea return this; } - public TestProperties setDedicatedClusterControllerCluster(boolean dedicatedClusterControllerCluster) { - this.dedicatedClusterControllerCluster = dedicatedClusterControllerCluster; - return this; - } - public TestProperties setEndpointCertificateSecrets(Optional<EndpointCertificateSecrets> endpointCertificateSecrets) { this.endpointCertificateSecrets = endpointCertificateSecrets; return this; diff --git a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java index 0f824fcacf9..188504edd18 100644 --- a/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java +++ b/config-model/src/main/java/com/yahoo/config/model/provision/InMemoryProvisioner.java @@ -142,7 +142,6 @@ public class InMemoryProvisioner implements HostProvisioner { public List<HostSpec> prepare(ClusterSpec cluster, ClusterResources requested, boolean required, boolean canFail) { if (cluster.group().isPresent() && requested.groups() > 1) throw new IllegalArgumentException("Cannot both be specifying a group and ask for groups to be created"); - int capacity = failOnOutOfCapacity || required ? requested.nodes() : Math.min(requested.nodes(), freeNodes.get(defaultResources).size() + totalAllocatedTo(cluster)); @@ -200,7 +199,9 @@ public class InMemoryProvisioner implements HostProvisioner { for (int i = allocation.size() - 1; i >= 0; i--) { NodeResources currentResources = allocation.get(0).advertisedResources(); if (currentResources.isUnspecified() || requestedResources.isUnspecified()) continue; - if ( ! currentResources.compatibleWith(requestedResources)) { + if ( (! sharedHosts && ! currentResources.satisfies(requestedResources)) + || + (sharedHosts && ! currentResources.compatibleWith(requestedResources))) { HostSpec removed = allocation.remove(i); freeNodes.put(currentResources, new Host(removed.hostname())); // Return the node back to free pool } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java index 3f346f20144..efae00096df 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/Admin.java @@ -78,7 +78,7 @@ public class Admin extends AbstractConfigProducer<Admin> implements Serializable private final FileDistributionConfigProducer fileDistribution; private final boolean multitenant; - public Admin(AbstractConfigProducer parent, + public Admin(AbstractConfigProducer<?> parent, Monitoring monitoring, Metrics metrics, boolean multitenant, @@ -186,19 +186,6 @@ public class Admin extends AbstractConfigProducer<Admin> implements Serializable return fileDistribution; } - public List<HostResource> getClusterControllerHosts() { - List<HostResource> hosts = new ArrayList<>(); - if (multitenant) { - if (logserver != null) - hosts.add(logserver.getHostResource()); - } else { - for (Configserver configserver : getConfigservers()) { - hosts.add(configserver.getHostResource()); - } - } - return hosts; - } - /** * Adds services to all hosts in the system. */ diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java index 72fb1160f7f..ed1dc80d71d 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/clustercontroller/ClusterControllerContainer.java @@ -61,9 +61,9 @@ public class ClusterControllerContainer extends Container implements "/cluster/v2/*", CLUSTERCONTROLLER_BUNDLE); addComponent(new AccessLogComponent(containerCluster().orElse(null), AccessLogComponent.AccessLogType.jsonAccessLog, - AccessLogComponent.CompressionType.GZIP, - "controller", - deployState.isHosted())); + AccessLogComponent.CompressionType.GZIP, + "controller", + deployState.isHosted())); // TODO: Why are bundles added here instead of in the cluster? addFileBundle("clustercontroller-apps"); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java index 79ce9343560..38eb15819b9 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java @@ -25,6 +25,7 @@ import com.yahoo.vespa.config.content.core.BucketspacesConfig; import com.yahoo.vespa.config.content.core.StorDistributormanagerConfig; import com.yahoo.vespa.model.HostResource; import com.yahoo.vespa.model.admin.Admin; +import com.yahoo.vespa.model.admin.Configserver; import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerCluster; import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerComponent; import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerConfigurer; @@ -170,7 +171,7 @@ public class ContentCluster extends AbstractConfigProducer implements if (context.getParentProducer().getRoot() == null) return c; - addClusterControllers(context, c.rootGroup, contentElement, c.clusterId, c, deployState); + addClusterControllers(context, contentElement, c, deployState); return c; } @@ -284,47 +285,42 @@ public class ContentCluster extends AbstractConfigProducer implements } private void addClusterControllers(ConfigModelContext context, - StorageGroup rootGroup, ModelElement contentElement, - String contentClusterName, ContentCluster contentCluster, DeployState deployState) { if (admin == null) return; // only in tests if (contentCluster.getPersistence() == null) return; - ClusterControllerContainerCluster clusterControllers; - - ContentCluster overlappingCluster = findOverlappingCluster(context.getParentProducer().getRoot(), contentCluster); - - if (overlappingCluster != null && overlappingCluster.getClusterControllers() != null) { - // Borrow the cluster controllers of the other cluster in this case. - // This condition only occurs on non-hosted systems with a shared config server, - // a combination which only exists in system tests. - clusterControllers = overlappingCluster.getClusterControllers(); + if (context.properties().hostedVespa()) { + clusterControllers = getDedicatedSharedControllers(contentElement, admin, context, deployState); } - else if (admin.multitenant()) { - if (context.properties().dedicatedClusterControllerCluster()) - clusterControllers = getDedicatedSharedControllers(contentElement, admin, context, deployState); - else { - clusterControllers = createClusterControllers(new ClusterControllerCluster(contentCluster, "standalone", deployState), - drawControllerHosts(3, rootGroup), - contentClusterName + "-controllers", - true, - context.getDeployState()); - contentCluster.clusterControllers = clusterControllers; + else if (admin.multitenant()) { // system tests: Put on logserver + if (admin.getClusterControllers() == null) { + // TODO: logserver== null only obtains in unit tests, disallow it + List<HostResource> host = admin.getLogserver() == null ? List.of() : List.of(admin.getLogserver().getHostResource()); + admin.setClusterControllers(createClusterControllers(new ClusterControllerCluster(admin, "standalone", deployState), + host, + "cluster-controllers", + true, + deployState)); } - } - else { clusterControllers = admin.getClusterControllers(); - if (clusterControllers == null) { - List<HostResource> hosts = admin.getClusterControllerHosts(); + } + else { // self hosted: Put on config servers or explicit cluster controllers + if (admin.getClusterControllers() == null) { + var hosts = admin.getConfigservers().stream().map(s -> s.getHostResource()).collect(toList()); if (hosts.size() > 1) { - context.getDeployState().getDeployLogger().log(Level.INFO, - "When having content cluster(s) and more than 1 config server it is recommended to configure cluster controllers explicitly."); + var message = "When having content clusters and more than 1 config server " + + "it is recommended to configure cluster controllers explicitly."; + deployState.getDeployLogger().log(Level.INFO, message); } - clusterControllers = createClusterControllers(admin, hosts, "cluster-controllers", false, context.getDeployState()); - admin.setClusterControllers(clusterControllers); + admin.setClusterControllers(createClusterControllers(admin, + hosts, + "cluster-controllers", + false, + deployState)); } + clusterControllers = admin.getClusterControllers(); } addClusterControllerComponentsForThisCluster(clusterControllers, contentCluster); @@ -334,21 +330,6 @@ public class ContentCluster extends AbstractConfigProducer implements } } - /** Returns any other content cluster which shares nodes with this, or null if none are built */ - private ContentCluster findOverlappingCluster(AbstractConfigProducerRoot root, ContentCluster contentCluster) { - for (ContentCluster otherContentCluster : root.getChildrenByTypeRecursive(ContentCluster.class)) { - if (otherContentCluster != contentCluster && overlaps(contentCluster, otherContentCluster)) - return otherContentCluster; - } - return null; - } - - private boolean overlaps(ContentCluster c1, ContentCluster c2) { - Set<HostResource> c1Hosts = c1.getRootGroup().recursiveGetNodes().stream().map(StorageNode::getHostResource).collect(Collectors.toSet()); - Set<HostResource> c2Hosts = c2.getRootGroup().recursiveGetNodes().stream().map(StorageNode::getHostResource).collect(Collectors.toSet()); - return ! Sets.intersection(c1Hosts, c2Hosts).isEmpty(); - } - public static final NodeResources clusterControllerResources = new NodeResources(0.5, 2, 10, 0.3, NodeResources.DiskSpeed.any, NodeResources.StorageType.any); private ClusterControllerContainerCluster getDedicatedSharedControllers(ModelElement contentElement, Admin admin, @@ -375,65 +356,19 @@ public class ContentCluster extends AbstractConfigProducer implements return admin.getClusterControllers(); } - private List<HostResource> drawControllerHosts(int count, StorageGroup rootGroup) { - List<HostResource> hosts = drawControllerHosts(count, false, rootGroup); - List<HostResource> retiredHosts = drawControllerHosts(count, true, rootGroup); - - // preserve the cluster state in case all pre-existing controllers are on retired nodes - List<HostResource> all = new ArrayList<>(hosts); - all.addAll(retiredHosts); - return all; - } - - private List<HostResource> drawControllerHosts(int count, boolean retired, StorageGroup rootGroup) { - List<HostResource> hosts = drawContentHostsRecursively(count, retired, rootGroup); - if (hosts.size() % 2 == 0 && ! hosts.isEmpty()) // ZK clusters of even sizes are less available (even in the size=2 case) - hosts = hosts.subList(0, hosts.size()-1); - return hosts; - } - - /** - * Draw <code>count</code> nodes from as many different content groups below this as possible. - * This will only achieve maximum spread in the case where the groups are balanced and never on the same - * physical node. It will not achieve maximum spread over all levels in a multilevel group hierarchy. - */ - // Note: This method cannot be changed to draw different nodes without ensuring that it will draw nodes - // which overlaps with previously drawn nodes as that will prevent rolling upgrade - private List<HostResource> drawContentHostsRecursively(int count, boolean retired, StorageGroup group) { - Set<HostResource> hosts = new HashSet<>(); - if (group.getNodes().isEmpty()) { - int hostsPerSubgroup = (int)Math.ceil((double)count / group.getSubgroups().size()); - for (StorageGroup subgroup : group.getSubgroups()) - hosts.addAll(drawContentHostsRecursively(hostsPerSubgroup, retired, subgroup)); - } - else { - hosts.addAll(group.getNodes().stream() - .filter(node -> node.isRetired() == retired) - .map(StorageNode::getHostResource).collect(toList())); - } - - List<HostResource> sortedHosts = new ArrayList<>(hosts); - sortedHosts.sort(HostResource::comparePrimarilyByIndexTo); - sortedHosts = sortedHosts.subList(0, Math.min(count, hosts.size())); - return sortedHosts; - } - private ClusterControllerContainerCluster createClusterControllers(AbstractConfigProducer<?> parent, Collection<HostResource> hosts, String name, - boolean multitenant, + boolean runStandaloneZooKeeper, DeployState deployState) { var clusterControllers = new ClusterControllerContainerCluster(parent, name, name, deployState); List<ClusterControllerContainer> containers = new ArrayList<>(); - // Add a cluster controller on each config server (there is always at least one). if (clusterControllers.getContainers().isEmpty()) { int index = 0; for (HostResource host : hosts) { - int ccIndex = deployState.getProperties().dedicatedClusterControllerCluster() - ? host.spec().membership().map(ClusterMembership::index).orElse(index) - : index; + int ccIndex = host.spec().membership().map(ClusterMembership::index).orElse(index); boolean retired = host.spec().membership().map(ClusterMembership::retired).orElse(false); - var clusterControllerContainer = new ClusterControllerContainer(clusterControllers, ccIndex, multitenant, deployState, retired); + var clusterControllerContainer = new ClusterControllerContainer(clusterControllers, ccIndex, runStandaloneZooKeeper, deployState, retired); clusterControllerContainer.setHostResource(host); clusterControllerContainer.initService(deployState.getDeployLogger()); clusterControllerContainer.setProp("clustertype", "admin"); @@ -511,11 +446,7 @@ public class ContentCluster extends AbstractConfigProducer implements public PersistenceEngine.PersistenceFactory getPersistence() { return persistenceFactory; } - /** - * The list of documentdefinitions declared at the cluster level. - * - * @return the set of documenttype names - */ + /** Returns a list of th document types declared at the cluster level. */ public Map<String, NewDocumentType> getDocumentDefinitions() { return documentDefinitions; } public boolean isGloballyDistributed(NewDocumentType docType) { @@ -753,6 +684,7 @@ public class ContentCluster extends AbstractConfigProducer implements * a previous generation of it only by restarting the consuming processes. */ public void setDeferChangesUntilRestart(boolean deferChangesUntilRestart) { + // TODO } } |