diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /clustercontroller-apps |
Publish
Diffstat (limited to 'clustercontroller-apps')
14 files changed, 622 insertions, 0 deletions
diff --git a/clustercontroller-apps/.gitignore b/clustercontroller-apps/.gitignore new file mode 100644 index 00000000000..3cc25b51fc4 --- /dev/null +++ b/clustercontroller-apps/.gitignore @@ -0,0 +1,2 @@ +/pom.xml.build +/target diff --git a/clustercontroller-apps/OWNERS b/clustercontroller-apps/OWNERS new file mode 100644 index 00000000000..b3db17e22d8 --- /dev/null +++ b/clustercontroller-apps/OWNERS @@ -0,0 +1,2 @@ +vekterli +hakon diff --git a/clustercontroller-apps/pom.xml b/clustercontroller-apps/pom.xml new file mode 100644 index 00000000000..b8103cd0210 --- /dev/null +++ b/clustercontroller-apps/pom.xml @@ -0,0 +1,83 @@ +<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.yahoo.vespa</groupId> + <artifactId>parent</artifactId> + <version>6-SNAPSHOT</version> + <relativePath>../parent/pom.xml</relativePath> + </parent> + <artifactId>clustercontroller-apps</artifactId> + <version>6-SNAPSHOT</version> + <packaging>container-plugin</packaging> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>container-dev</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + <exclusions> + <exclusion> + <groupId>org.antlr</groupId> + <artifactId>antlr4-runtime</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>clustercontroller-apputil</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>clustercontroller-core</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>clustercontroller-utils</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> + <artifactId>zkfacade</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.codehaus.jettison</groupId> + <artifactId>jettison</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>com.yahoo.vespa</groupId> + <artifactId>bundle-plugin</artifactId> + <extensions>true</extensions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compilerArgs> + <arg>-Xlint:rawtypes</arg> + <arg>-Xlint:unchecked</arg> + <arg>-Xlint:deprecation</arg> + <arg>-Werror</arg> + </compilerArgs> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterController.java b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterController.java new file mode 100644 index 00000000000..2beb248d032 --- /dev/null +++ b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterController.java @@ -0,0 +1,107 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.google.inject.Inject; +import com.yahoo.component.AbstractComponent; +import com.yahoo.jdisc.Metric; +import com.yahoo.vespa.clustercontroller.apputil.communication.http.JDiscMetricWrapper; +import com.yahoo.vespa.clustercontroller.core.FleetController; +import com.yahoo.vespa.clustercontroller.core.FleetControllerOptions; +import com.yahoo.vespa.clustercontroller.core.RemoteClusterControllerTaskScheduler; +import com.yahoo.vespa.clustercontroller.core.restapiv2.ClusterControllerStateRestAPI; +import com.yahoo.vespa.clustercontroller.core.status.StatusHandler; +import com.yahoo.vespa.curator.Curator; +import com.yahoo.vespa.zookeeper.ZooKeeperServer; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; +import java.util.logging.Logger; + +/** + * Wrapper around fleet controller state to be able to use it in container. + */ +public class ClusterController extends AbstractComponent + implements ClusterControllerStateRestAPI.FleetControllerResolver, + StatusHandler.ClusterStatusPageServerSet { + + private static final Logger log = Logger.getLogger(ClusterController.class.getName()); + private final JDiscMetricWrapper metricWrapper; + private final Map<String, FleetController> controllers = new TreeMap<>(); + private final Map<String, StatusHandler.ContainerStatusPageServer> status = new TreeMap<>(); + + /** + * Dependency injection constructor for controller. {@link ZooKeeperProvider} argument given + * to ensure that zookeeper has started before we start polling it. + */ + @Inject + public ClusterController(ZooKeeperProvider zooKeeperProvider) { + this(); + } + + ClusterController() { + metricWrapper = new JDiscMetricWrapper(null); + } + + + public void setOptions(String clusterName, FleetControllerOptions options, Metric metricImpl) throws Exception { + metricWrapper.updateMetricImplementation(metricImpl); + if (options.zooKeeperServerAddress != null && !"".equals(options.zooKeeperServerAddress)) { + // Wipe this path ... it's unclear why + String path = "/" + options.clusterName + options.fleetControllerIndex; + Curator curator = Curator.create(options.zooKeeperServerAddress); + if (curator.framework().checkExists().forPath(path) != null) + curator.framework().delete().deletingChildrenIfNeeded().forPath(path); + curator.framework().create().creatingParentsIfNeeded().forPath(path); + } + synchronized (controllers) { + FleetController controller = controllers.get(clusterName); + + if (controller == null) { + StatusHandler.ContainerStatusPageServer statusPageServer = new StatusHandler.ContainerStatusPageServer(); + controller = FleetController.createForContainer(options, statusPageServer, metricWrapper); + controllers.put(clusterName, controller); + status.put(clusterName, statusPageServer); + } else { + controller.updateOptions(options, 0); + } + } + } + + @Override + public void deconstruct() { + synchronized (controllers) { + for (FleetController controller : controllers.values()) { + try{ + shutdownController(controller); + } catch (Exception e) { + log.warning("Failed to shut down fleet controller: " + e.getMessage()); + } + } + } + super.deconstruct(); + } + + @Override + public Map<String, RemoteClusterControllerTaskScheduler> getFleetControllers() { + Map<String, RemoteClusterControllerTaskScheduler> m = new LinkedHashMap<>(); + synchronized (controllers) { + m.putAll(controllers); + } + return m; + } + + @Override + public StatusHandler.ContainerStatusPageServer get(String cluster) { + return status.get(cluster); + } + + @Override + public Map<String, StatusHandler.ContainerStatusPageServer> getAll() { + return status; + } + + void shutdownController(FleetController controller) throws Exception { + controller.shutdown(); + } +} diff --git a/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerClusterConfigurer.java b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerClusterConfigurer.java new file mode 100644 index 00000000000..07b0a68520b --- /dev/null +++ b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerClusterConfigurer.java @@ -0,0 +1,100 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.yahoo.jdisc.Metric; +import com.yahoo.vdslib.distribution.Distribution; +import com.yahoo.vdslib.state.NodeType; +import com.yahoo.vespa.clustercontroller.core.FleetControllerOptions; +import com.yahoo.vespa.config.content.FleetcontrollerConfig; +import com.yahoo.cloud.config.SlobroksConfig; +import com.yahoo.vespa.config.content.StorDistributionConfig; +import com.yahoo.cloud.config.ZookeepersConfig; + +/** + * When the cluster controller is reconfigured, a new instance of this is created, which will propagate configured + * options to receivers such as the fleet controller. + */ +public class ClusterControllerClusterConfigurer { + + private final FleetControllerOptions options = new FleetControllerOptions(null); + + public ClusterControllerClusterConfigurer(ClusterController controller, + StorDistributionConfig distributionConfig, + FleetcontrollerConfig fleetcontrollerConfig, + SlobroksConfig slobroksConfig, + ZookeepersConfig zookeepersConfig, + Metric metricImpl) throws Exception + { + configure(distributionConfig); + configure(fleetcontrollerConfig); + configure(slobroksConfig); + configure(zookeepersConfig); + checkIfZooKeeperNeeded(); + if (controller != null) { + controller.setOptions(options.clusterName, options, metricImpl); + } + } + + public FleetControllerOptions getOptions() { return options; } + + private void configure(StorDistributionConfig config) { + options.setStorageDistribution(new Distribution(config)); + } + + private void configure(FleetcontrollerConfig config) { + options.clusterName = config.cluster_name(); + options.fleetControllerIndex = config.index(); + options.fleetControllerCount = config.fleet_controller_count(); + options.zooKeeperSessionTimeout = (int) (config.zookeeper_session_timeout() * 1000); + options.masterZooKeeperCooldownPeriod = (int) (config.master_zookeeper_cooldown_period() * 1000); + options.stateGatherCount = config.state_gather_count(); + options.rpcPort = config.rpc_port(); + options.httpPort = config.http_port(); + options.maxTransitionTime.put(NodeType.STORAGE, config.storage_transition_time()); + options.maxTransitionTime.put(NodeType.DISTRIBUTOR, config.distributor_transition_time()); + options.maxInitProgressTime = config.init_progress_time(); + options.statePollingFrequency = config.state_polling_frequency(); + options.maxPrematureCrashes = config.max_premature_crashes(); + options.stableStateTimePeriod = config.stable_state_time_period(); + options.eventLogMaxSize = config.event_log_max_size(); + options.eventNodeLogMaxSize = config.event_node_log_max_size(); + options.minDistributorNodesUp = config.min_distributors_up_count(); + options.minStorageNodesUp = config.min_storage_up_count(); + options.minRatioOfDistributorNodesUp = config.min_distributor_up_ratio(); + options.minRatioOfStorageNodesUp = config.min_storage_up_ratio(); + options.cycleWaitTime = (int) (config.cycle_wait_time() * 1000); + options.minTimeBeforeFirstSystemStateBroadcast = (int) (config.min_time_before_first_system_state_broadcast() * 1000); + options.nodeStateRequestTimeoutMS = (int) (config.get_node_state_request_timeout() * 1000); + options.showLocalSystemStatesInEventLog = config.show_local_systemstates_in_event_log(); + options.minTimeBetweenNewSystemStates = config.min_time_between_new_systemstates(); + options.maxSlobrokDisconnectGracePeriod = (int) (config.max_slobrok_disconnect_grace_period() * 1000); + options.distributionBits = config.ideal_distribution_bits(); + } + + private void configure(SlobroksConfig config) { + String specs[] = new String[config.slobrok().size()]; + for (int i = 0; i < config.slobrok().size(); i++) { + specs[i] = config.slobrok().get(i).connectionspec(); + } + options.slobrokConnectionSpecs = specs; + } + + private void configure(ZookeepersConfig config) { + options.zooKeeperServerAddress = config.zookeeperserverlist(); + } + + private void checkIfZooKeeperNeeded() { + // For legacy (testing, presumably) reasons, support running 1 instance + // without a ZK cluster. This is really a Horrible Thing(tm) since we + // violate cluster state versioning invariants when the controller is + // restarted. + if (options.zooKeeperServerAddress == null || "".equals(options.zooKeeperServerAddress)) { + if (options.fleetControllerCount > 1) { + throw new IllegalArgumentException( + "Must set zookeeper server with multiple fleetcontrollers"); + } else { + options.zooKeeperServerAddress = null; // Force null + } + } + } +} diff --git a/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/DummyZooKeeperProvider.java b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/DummyZooKeeperProvider.java new file mode 100644 index 00000000000..7de4b9c9d99 --- /dev/null +++ b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/DummyZooKeeperProvider.java @@ -0,0 +1,11 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +/** + * A dummy zookeeper provider when we do not run our own zookeeper instance. + * + * @author lulf + * @since 5.26 + */ +public class DummyZooKeeperProvider implements ZooKeeperProvider { +} diff --git a/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StandaloneZooKeeperProvider.java b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StandaloneZooKeeperProvider.java new file mode 100644 index 00000000000..5ef2fb618e8 --- /dev/null +++ b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StandaloneZooKeeperProvider.java @@ -0,0 +1,15 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.yahoo.vespa.zookeeper.ZooKeeperServer; + +/** + * ZooKeeper provider that ensures we are running our own instance of zookeeper. + * + * @author lulf + * @since 5.26 + */ +public class StandaloneZooKeeperProvider implements ZooKeeperProvider { + public StandaloneZooKeeperProvider(ZooKeeperServer server) { + } +} diff --git a/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StateRestApiV2Handler.java b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StateRestApiV2Handler.java new file mode 100644 index 00000000000..ef6202b4d9e --- /dev/null +++ b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StateRestApiV2Handler.java @@ -0,0 +1,65 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.google.inject.Inject; +import com.yahoo.cloud.config.ClusterInfoConfig; +import com.yahoo.cloud.config.ModelConfig; +import com.yahoo.container.jdisc.config.HttpServerConfig; +import com.yahoo.container.logging.AccessLog; +import com.yahoo.log.LogLevel; +import com.yahoo.vespa.clustercontroller.apputil.communication.http.JDiscHttpRequestHandler; +import com.yahoo.vespa.clustercontroller.core.restapiv2.ClusterControllerStateRestAPI; +import com.yahoo.vespa.clustercontroller.utils.staterestapi.server.RestApiHandler; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +public class StateRestApiV2Handler extends JDiscHttpRequestHandler { + private static final Logger log = Logger.getLogger(StateRestApiV2Handler.class.getName()); + + @Inject + public StateRestApiV2Handler(Executor executor, ClusterController cc, ClusterInfoConfig config, AccessLog accessLog) { + this(executor, new ClusterControllerStateRestAPI(cc, getClusterControllerSockets(config)), "/cluster/v2", accessLog); + } + + private StateRestApiV2Handler(Executor executor, ClusterControllerStateRestAPI restApi, String pathPrefix, AccessLog accessLog) { + super(new RestApiHandler(restApi).setDefaultPathPrefix(pathPrefix), executor, accessLog); + } + + // This method is package-private instead of private to be accessible to unit-tests. + static Map<Integer, ClusterControllerStateRestAPI.Socket> getClusterControllerSockets(ClusterInfoConfig config) { + Map<Integer, ClusterControllerStateRestAPI.Socket> result = new TreeMap<>(); + for (ClusterInfoConfig.Services service : config.services()) { + for (ClusterInfoConfig.Services.Ports port : service.ports()) { + Set<String> tags = parseTags(port.tags()); + if (tags.contains("http") && tags.contains("state")) { + result.put(service.index(), new ClusterControllerStateRestAPI.Socket(service.hostname(), port.number())); + break; + } + } + } + if (result.isEmpty()) { + log.warning("Found no cluster controller in model config"); + } else if (log.isLoggable(LogLevel.DEBUG)) { + StringBuilder sb = new StringBuilder(); + sb.append("Found ").append(result.size()).append(" cluster controllers in model config:"); + for (Map.Entry<Integer, ClusterControllerStateRestAPI.Socket> e : result.entrySet()) { + sb.append("\n ").append(e.getKey()).append(" -> ").append(e.getValue()); + } + log.fine(sb.toString()); + } + return result; + } + + private static Set<String> parseTags(String tags) { + Set<String> set = new HashSet<>(); + for(String s : tags.toLowerCase().split(" ")) { + set.add(s.trim()); + } + return set; + } +} diff --git a/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StatusHandler.java b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StatusHandler.java new file mode 100644 index 00000000000..a03042e9675 --- /dev/null +++ b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StatusHandler.java @@ -0,0 +1,22 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.google.inject.Inject; +import com.yahoo.container.logging.AccessLog; +import com.yahoo.vespa.clustercontroller.apputil.communication.http.JDiscHttpRequestHandler; + +import java.util.concurrent.Executor; + +public class StatusHandler extends JDiscHttpRequestHandler { + private final com.yahoo.vespa.clustercontroller.core.status.StatusHandler statusHandler; + + @Inject + public StatusHandler(ClusterController fc, Executor executor, AccessLog accessLog) { + this(new com.yahoo.vespa.clustercontroller.core.status.StatusHandler(fc), executor, accessLog); + } + + private StatusHandler(com.yahoo.vespa.clustercontroller.core.status.StatusHandler handler, Executor executor, AccessLog accessLog) { + super(handler, executor, accessLog); + this.statusHandler = handler; + } +} diff --git a/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ZooKeeperProvider.java b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ZooKeeperProvider.java new file mode 100644 index 00000000000..169ad1a1246 --- /dev/null +++ b/clustercontroller-apps/src/main/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ZooKeeperProvider.java @@ -0,0 +1,11 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +/** + * Abstraction we can depend on providing us with a zookeeper server being up. + * + * @author lulf + * @since 5.25 + */ +public interface ZooKeeperProvider { +} diff --git a/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerClusterConfigurerTest.java b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerClusterConfigurerTest.java new file mode 100644 index 00000000000..6cf4f962c9f --- /dev/null +++ b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerClusterConfigurerTest.java @@ -0,0 +1,77 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.yahoo.cloud.config.SlobroksConfig; +import com.yahoo.cloud.config.ZookeepersConfig; +import com.yahoo.jdisc.Metric; +import com.yahoo.vespa.config.content.FleetcontrollerConfig; +import com.yahoo.vespa.config.content.StorDistributionConfig; +import junit.framework.TestCase; + +import java.util.Map; + +public class ClusterControllerClusterConfigurerTest extends TestCase { + + public void testSimple() throws Exception { + ClusterController controller = new ClusterController(); + StorDistributionConfig.Builder distributionConfig = new StorDistributionConfig.Builder(); + StorDistributionConfig.Group.Builder group = new StorDistributionConfig.Group.Builder(); + group.index("0").name("foo"); + StorDistributionConfig.Group.Nodes.Builder node = new StorDistributionConfig.Group.Nodes.Builder(); + node.index(0); + group.nodes.add(node); + distributionConfig.group.add(group); + FleetcontrollerConfig.Builder fleetcontrollerConfig = new FleetcontrollerConfig.Builder(); + fleetcontrollerConfig.cluster_name("storage").index(0).zookeeper_server("zoo"); + SlobroksConfig.Builder slobroksConfig = new SlobroksConfig.Builder(); + SlobroksConfig.Slobrok.Builder slobrok = new SlobroksConfig.Slobrok.Builder(); + slobrok.connectionspec("foo"); + slobroksConfig.slobrok.add(slobrok); + ZookeepersConfig.Builder zookeepersConfig = new ZookeepersConfig.Builder(); + zookeepersConfig.zookeeperserverlist("foo"); + Metric metric = new Metric() { + @Override + public void set(String s, Number number, Context context) {} + @Override + public void add(String s, Number number, Context context) {} + @Override + public Context createContext(Map<String, ?> stringMap) { return null; } + }; + // Used in standalone modus to get config without a cluster controller instance + ClusterControllerClusterConfigurer configurer = new ClusterControllerClusterConfigurer( + null, + new StorDistributionConfig(distributionConfig), + new FleetcontrollerConfig(fleetcontrollerConfig), + new SlobroksConfig(slobroksConfig), + new ZookeepersConfig(zookeepersConfig), + metric + ); + assertTrue(configurer.getOptions() != null); + + // Oki with no zookeeper if one node + zookeepersConfig.zookeeperserverlist(""); + new ClusterControllerClusterConfigurer( + controller, + new StorDistributionConfig(distributionConfig), + new FleetcontrollerConfig(fleetcontrollerConfig), + new SlobroksConfig(slobroksConfig), + new ZookeepersConfig(zookeepersConfig), + metric + ); + + try{ + fleetcontrollerConfig.fleet_controller_count(5); + new ClusterControllerClusterConfigurer( + controller, + new StorDistributionConfig(distributionConfig), + new FleetcontrollerConfig(fleetcontrollerConfig), + new SlobroksConfig(slobroksConfig), + new ZookeepersConfig(zookeepersConfig), + metric + ); + fail("Should not get here"); + } catch (Exception e) { + assertEquals("Must set zookeeper server with multiple fleetcontrollers", e.getMessage()); + } + } +} diff --git a/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerTest.java b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerTest.java new file mode 100644 index 00000000000..be5c7bf026e --- /dev/null +++ b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/ClusterControllerTest.java @@ -0,0 +1,57 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +/** + * Doesn't really test cluster controller, but runs some lines of code. + * System tests verifies that container can load it.. + */ +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.yahoo.jdisc.Metric; +import com.yahoo.vespa.clustercontroller.core.FleetController; +import com.yahoo.vespa.clustercontroller.core.FleetControllerOptions; +import junit.framework.TestCase; + +import java.util.Map; + +public class ClusterControllerTest extends TestCase { + private FleetControllerOptions options = new FleetControllerOptions("storage"); + private Metric metric = new Metric() { + @Override + public void set(String s, Number number, Context context) {} + @Override + public void add(String s, Number number, Context context) {} + @Override + public Context createContext(Map<String, ?> stringMap) { return null; } + }; + + public void setUp() { + options = new FleetControllerOptions("storage"); + options.zooKeeperServerAddress = null; + options.slobrokConfigId = "raw:"; + options.slobrokConnectionSpecs = null; + } + + public void testSimple() throws Exception { + // Cluster controller object keeps state and should never be remade, so should + // inject nothing + ClusterController cc = new ClusterController(); + cc.setOptions("storage", options, metric); + cc.setOptions("storage", options, metric); + cc.getFleetControllers(); + cc.getAll(); + + assertTrue(cc.get("storage") != null); + assertFalse(cc.get("music") != null); + cc.deconstruct(); + } + + public void testShutdownException() throws Exception { + ClusterController cc = new ClusterController() { + void shutdownController(FleetController controller) throws Exception { + throw new Exception("Foo"); + } + }; + cc.setOptions("storage", options, metric); + cc.deconstruct(); + } + +} diff --git a/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StateRestApiV2HandlerTest.java b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StateRestApiV2HandlerTest.java new file mode 100644 index 00000000000..9230c08f735 --- /dev/null +++ b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StateRestApiV2HandlerTest.java @@ -0,0 +1,51 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.yahoo.cloud.config.ClusterInfoConfig; +import com.yahoo.container.logging.AccessLog; +import com.yahoo.vespa.clustercontroller.core.restapiv2.ClusterControllerStateRestAPI; +import junit.framework.TestCase; + +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class StateRestApiV2HandlerTest extends TestCase { + + public void testNoMatchingSockets() { + ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000)); + ClusterController controller = new ClusterController(); + ClusterInfoConfig config = new ClusterInfoConfig( + new ClusterInfoConfig.Builder().clusterId("cluster-id").nodeCount(1)); + ClusterInfoConfig.Builder clusterConfig = new ClusterInfoConfig.Builder(); + new StateRestApiV2Handler(executor, controller, config, AccessLog.voidAccessLog()); + executor.shutdown(); + } + + public void testMappingOfIndexToClusterControllers() { + ClusterInfoConfig.Builder builder = new ClusterInfoConfig.Builder() + .clusterId("cluster-id") + .nodeCount(1) + .services(new ClusterInfoConfig.Services.Builder() + .index(1) + .hostname("host-1") + .ports(new ClusterInfoConfig.Services.Ports.Builder().number(80).tags("state http")) + .ports(new ClusterInfoConfig.Services.Ports.Builder().number(81).tags("ignored port http"))) + .services(new ClusterInfoConfig.Services.Builder() + .index(3) + .hostname("host-3") + .ports(new ClusterInfoConfig.Services.Ports.Builder().number(85).tags("state http")) + .ports(new ClusterInfoConfig.Services.Ports.Builder().number(86).tags("foo http bar state"))); + + ClusterInfoConfig config = new ClusterInfoConfig(builder); + Map<Integer, ClusterControllerStateRestAPI.Socket> mapping = StateRestApiV2Handler.getClusterControllerSockets(config); + Map<Integer, ClusterControllerStateRestAPI.Socket> expected = new TreeMap<>(); + + expected.put(1, new ClusterControllerStateRestAPI.Socket("host-1", 80)); + expected.put(3, new ClusterControllerStateRestAPI.Socket("host-3", 85)); + + assertEquals(expected, mapping); + } +} diff --git a/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StatusHandlerTest.java b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StatusHandlerTest.java new file mode 100644 index 00000000000..e066e0b367e --- /dev/null +++ b/clustercontroller-apps/src/test/java/com/yahoo/vespa/clustercontroller/apps/clustercontroller/StatusHandlerTest.java @@ -0,0 +1,19 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.clustercontroller.apps.clustercontroller; + +import com.yahoo.container.logging.AccessLog; +import junit.framework.TestCase; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class StatusHandlerTest extends TestCase { + + public void testSimple() { + ClusterController controller = new ClusterController(); + ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000)); + StatusHandler handler = new StatusHandler(controller, executor, AccessLog.voidAccessLog()); + executor.shutdown(); + } +} |