diff options
54 files changed, 373 insertions, 165 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationMetaData.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationMetaData.java index a3769299cf8..236a954f483 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationMetaData.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationMetaData.java @@ -171,4 +171,5 @@ public class ApplicationMetaData { throw new RuntimeException("Unable to encode metadata", e); } } + } diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Deployer.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Deployer.java index 111073aca77..2254b6d7747 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/Deployer.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Deployer.java @@ -11,14 +11,13 @@ import java.util.Optional; */ public interface Deployer { - /** * Creates a new deployment from the active application, if available. Will use the default timeout for deployment. * * @param application the active application to be redeployed * @return a new deployment from the local active, or empty if a local active application - * was not present for this id (meaning it either is not active or active on another - * node in the config server cluster) + * was not present for this id (meaning it either is not active or deployed at another + * node in the config server cluster) */ Optional<Deployment> deployFromLocalActive(ApplicationId application); diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ClientUpdater.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ClientUpdater.java index 0ed5d04e36e..8b8f75a3f99 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ClientUpdater.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ClientUpdater.java @@ -15,6 +15,7 @@ import java.util.logging.Logger; * @author hmusum */ class ClientUpdater { + private final static Logger log = Logger.getLogger(ClientUpdater.class.getName()); private final ConfigProxyStatistics statistics; diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigSourceClient.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigSourceClient.java index f636e723828..5bab27c27a5 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigSourceClient.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ConfigSourceClient.java @@ -11,7 +11,6 @@ import java.util.List; * getting config. * * @author hmusum - * @since 5.1.9 */ interface ConfigSourceClient { @@ -24,4 +23,5 @@ interface ConfigSourceClient { String getActiveSourceConnection(); List<String> getSourceConnections(); + } diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponse.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponse.java index 76c5cb424e8..047576ee647 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponse.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponse.java @@ -15,6 +15,7 @@ import java.util.concurrent.TimeUnit; * @see DelayedResponseHandler */ public class DelayedResponse implements Delayed { + private final JRTServerConfigRequest request; private final long returnTime; @@ -58,8 +59,7 @@ public class DelayedResponse implements Delayed { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(request.getShortDescription()).append(", delayLeft=").append(getDelay(TimeUnit.MILLISECONDS)).append(" ms"); - return sb.toString(); + return request.getShortDescription() + ", delayLeft=" + getDelay(TimeUnit.MILLISECONDS) + " ms"; } + } diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponses.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponses.java index 00f948ef690..953aeefbfd1 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponses.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/DelayedResponses.java @@ -7,7 +7,6 @@ import java.util.concurrent.DelayQueue; * Queue for requests that have no corresponding config in cache and which we are awaiting response from server for * * @author hmusum - * @since 5.1.7 */ class DelayedResponses { diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/MemoryCache.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/MemoryCache.java index 7914b7a80b6..0fe7fe01467 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/MemoryCache.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/MemoryCache.java @@ -21,6 +21,7 @@ import java.util.logging.Logger; * @author hmusum */ public class MemoryCache { + private static final Logger log = Logger.getLogger(MemoryCache.class.getName()); // Separator in file names between different fields of config key @@ -35,6 +36,7 @@ public class MemoryCache { /** * Put in cache, except when config has an error + * * @param config config to put in cache */ public void put(RawConfig config) { diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ProxyServer.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ProxyServer.java index 28bcca9db13..6390c9ca165 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ProxyServer.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/ProxyServer.java @@ -132,7 +132,7 @@ public class ProxyServer implements Runnable { } static boolean configOrGenerationHasChanged(RawConfig config, JRTServerConfigRequest request) { - return (config != null && (!config.hasEqualConfig(request) || config.hasNewerGeneration(request))); + return (config != null && ( ! config.hasEqualConfig(request) || config.hasNewerGeneration(request))); } Mode getMode() { diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/RpcConfigSourceClient.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/RpcConfigSourceClient.java index 0f80f228b36..b4eda05fde4 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/RpcConfigSourceClient.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/RpcConfigSourceClient.java @@ -148,7 +148,8 @@ class RpcConfigSourceClient implements ConfigSourceClient { log.log(LogLevel.DEBUG, () -> "Already a subscriber running for: " + configCacheKey); } else { log.log(LogLevel.DEBUG, () -> "Could not find good config in cache, creating subscriber for: " + configCacheKey); - UpstreamConfigSubscriber subscriber = new UpstreamConfigSubscriber(input, clientUpdater, configSourceSet, timingValues, requesterPool, memoryCache); + UpstreamConfigSubscriber subscriber = new UpstreamConfigSubscriber(input, clientUpdater, configSourceSet, + timingValues, requesterPool, memoryCache); try { subscriber.subscribe(); activeSubscribers.put(configCacheKey, subscriber); diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java index 32b1c661a75..74c99b7670b 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/Subscriber.java @@ -5,7 +5,6 @@ package com.yahoo.vespa.config.proxy; * Interface for subscribing to config from upstream config sources. * * @author hmusum - * @since 5.5 */ public interface Subscriber extends Runnable { diff --git a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/UpstreamConfigSubscriber.java b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/UpstreamConfigSubscriber.java index 528c61fe132..ceaf57e9cf1 100644 --- a/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/UpstreamConfigSubscriber.java +++ b/config-proxy/src/main/java/com/yahoo/vespa/config/proxy/UpstreamConfigSubscriber.java @@ -17,9 +17,9 @@ import java.util.logging.Logger; /** * @author hmusum - * @since 5.5 */ public class UpstreamConfigSubscriber implements Subscriber { + private final static Logger log = Logger.getLogger(UpstreamConfigSubscriber.class.getName()); private final RawConfig config; @@ -33,8 +33,7 @@ public class UpstreamConfigSubscriber implements Subscriber { UpstreamConfigSubscriber(RawConfig config, ClientUpdater clientUpdater, ConfigSource configSourceSet, TimingValues timingValues, Map<ConfigSourceSet, JRTConfigRequester> requesterPool, - MemoryCache memoryCache) - { + MemoryCache memoryCache) { this.config = config; this.clientUpdater = clientUpdater; this.configSourceSet = configSourceSet; @@ -46,7 +45,7 @@ public class UpstreamConfigSubscriber implements Subscriber { void subscribe() { subscriber = new GenericConfigSubscriber(requesterPool); ConfigKey<?> key = config.getKey(); - handle = subscriber.subscribe(new ConfigKey<RawConfig>(key.getName(), key.getConfigId(), key.getNamespace()), + handle = subscriber.subscribe(new ConfigKey<>(key.getName(), key.getConfigId(), key.getNamespace()), config.getDefContent(), configSourceSet, timingValues); } @@ -66,7 +65,7 @@ public class UpstreamConfigSubscriber implements Subscriber { } private void updateWithNewConfig(GenericConfigHandle handle) { - final RawConfig newConfig = handle.getRawConfig(); + RawConfig newConfig = handle.getRawConfig(); if (log.isLoggable(LogLevel.DEBUG)) { log.log(LogLevel.DEBUG, "config to be returned for '" + newConfig.getKey() + "', generation=" + newConfig.getGeneration() + @@ -82,4 +81,5 @@ public class UpstreamConfigSubscriber implements Subscriber { subscriber.close(); } } + } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java index 9f277330401..64eee39af1f 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java @@ -324,6 +324,7 @@ public abstract class ConfigSubscription<T extends ConfigInstance> { * True if someone has set the {@link #reloadedGeneration} number by calling {@link #reload(long)} * and hence wants to force a given generation programmatically. If that is the case, * sets the generation and flags it as changed accordingly. + * * @return true if {@link #reload(long)} has been called, false otherwise */ protected boolean checkReloaded() { diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigHandle.java b/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigHandle.java index 916aa6faeff..bf247dffb7c 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigHandle.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigHandle.java @@ -12,14 +12,15 @@ import com.yahoo.vespa.config.RawConfig; @SuppressWarnings({"rawtypes", "unchecked"}) public class GenericConfigHandle extends ConfigHandle { - private final GenericJRTConfigSubscription genSub; + private final GenericJRTConfigSubscription subscription; - public GenericConfigHandle(GenericJRTConfigSubscription sub) { - super(sub); - genSub = sub; + public GenericConfigHandle(GenericJRTConfigSubscription subscription) { + super(subscription); + this.subscription = subscription; } public RawConfig getRawConfig() { - return genSub.getRawConfig(); + return subscription.getRawConfig(); } + } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigSubscriber.java b/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigSubscriber.java index a33c1556dd3..82d4708f53b 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigSubscriber.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/GenericConfigSubscriber.java @@ -19,6 +19,7 @@ import com.yahoo.vespa.config.TimingValues; * @author vegardh */ public class GenericConfigSubscriber extends ConfigSubscriber { + /** * Constructs a new subscriber using the given pool of requesters (JRTConfigRequester holds 1 connection which in * turn is subject to failover across the elems in the source set.) @@ -72,4 +73,5 @@ public class GenericConfigSubscriber extends ConfigSubscriber { */ public void closeRequesters() { } + } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/GenericJRTConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/GenericJRTConfigSubscription.java index e8c7edd3943..c1f9ce02650 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/GenericJRTConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/GenericJRTConfigSubscription.java @@ -50,6 +50,17 @@ public class GenericJRTConfigSubscription extends JRTConfigSubscription<RawConfi } } + // Override to propagate internal redeploy into the config value in addition to the config state + @Override + void setInternalRedeploy(boolean internalRedeploy) { + super.setInternalRedeploy(internalRedeploy); + ConfigState<RawConfig> configState = getConfigState(); + + if (configState.getConfig() != null) { + configState.getConfig().setInternalRedeploy(internalRedeploy); + } + } + public RawConfig getRawConfig() { return getConfigState().getConfig(); } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/JRTConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/JRTConfigSubscription.java index 920c8c264e7..58f720b8cb6 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/JRTConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/JRTConfigSubscription.java @@ -172,6 +172,7 @@ public class JRTConfigSubscription<T extends ConfigInstance> extends ConfigSubsc /** * The timing values of this + * * @return timing values */ public TimingValues timingValues() { diff --git a/config/src/main/java/com/yahoo/vespa/config/ConfigCacheKey.java b/config/src/main/java/com/yahoo/vespa/config/ConfigCacheKey.java index 79edeea99fc..e8e3fe9ed94 100644 --- a/config/src/main/java/com/yahoo/vespa/config/ConfigCacheKey.java +++ b/config/src/main/java/com/yahoo/vespa/config/ConfigCacheKey.java @@ -3,10 +3,11 @@ package com.yahoo.vespa.config; /** * A ConfigKey that also uses the def MD5 sum. Used for caching when def payload is user provided. - * @author vegardh * + * @author Vegard Havdal */ public class ConfigCacheKey { + private final ConfigKey<?> key; private final String defMd5; @@ -45,6 +46,7 @@ public class ConfigCacheKey { /** * The def md5 sum of this key + * * @return md5 sum */ public String getDefMd5() { diff --git a/config/src/main/java/com/yahoo/vespa/config/ConfigKey.java b/config/src/main/java/com/yahoo/vespa/config/ConfigKey.java index 5f068c4708a..930b74ea804 100755 --- a/config/src/main/java/com/yahoo/vespa/config/ConfigKey.java +++ b/config/src/main/java/com/yahoo/vespa/config/ConfigKey.java @@ -135,4 +135,5 @@ public class ConfigKey<CONFIGCLASS extends ConfigInstance> implements Comparable public static ConfigKey<?> createFull(String name, String configId, String namespace, String md5) { return new ConfigKey<>(name, configId, namespace, md5, null); } + } diff --git a/config/src/main/java/com/yahoo/vespa/config/GetConfigRequest.java b/config/src/main/java/com/yahoo/vespa/config/GetConfigRequest.java index 8021fa95514..c5eeab74157 100644 --- a/config/src/main/java/com/yahoo/vespa/config/GetConfigRequest.java +++ b/config/src/main/java/com/yahoo/vespa/config/GetConfigRequest.java @@ -7,10 +7,8 @@ import java.util.Optional; /** * Interface for getConfig requests. - * @author lulf - * @since 5.3 + * @author Ulf Lilleengen */ - public interface GetConfigRequest { /** @@ -22,6 +20,7 @@ public interface GetConfigRequest { /** * The def file contents in the request, or empty array if not sent/not supported + * * @return the contents (payload) of the def schema */ DefContent getDefContent(); @@ -33,7 +32,9 @@ public interface GetConfigRequest { /** * Whether or not the config can be retrieved from or stored in a cache. + * * @return true if content should _not_ be cached, false if it should. */ boolean noCache(); + } diff --git a/config/src/main/java/com/yahoo/vespa/config/RawConfig.java b/config/src/main/java/com/yahoo/vespa/config/RawConfig.java index ae4431e5195..96908f055f1 100755 --- a/config/src/main/java/com/yahoo/vespa/config/RawConfig.java +++ b/config/src/main/java/com/yahoo/vespa/config/RawConfig.java @@ -35,6 +35,7 @@ public class RawConfig extends ConfigInstance { /** * Constructor for an empty config (not yet resolved). + * * @param key The ConfigKey * @param defMd5 The md5 sum of the .def-file. */ @@ -69,6 +70,7 @@ public class RawConfig extends ConfigInstance { /** * Creates a new Config from the given request, with the values in the response parameters. + * * @param req a {@link JRTClientConfigRequest} */ public static RawConfig createFromResponseParameters(JRTClientConfigRequest req) { @@ -85,6 +87,7 @@ public class RawConfig extends ConfigInstance { /** * Creates a new Config from the given request, with the values in the response parameters. + * * @param req a {@link JRTClientConfigRequest} */ public static RawConfig createFromServerRequest(JRTServerConfigRequest req) { @@ -116,6 +119,8 @@ public class RawConfig extends ConfigInstance { public void setGeneration(long generation) { this.generation = generation; } + public void setInternalRedeploy(boolean internalRedeploy) { this.internalRedeploy = internalRedeploy; } + /** * Returns whether this config generation was created by a system internal redeploy, not an * application package change. @@ -133,7 +138,7 @@ public class RawConfig extends ConfigInstance { /** * Returns true if this config is equal to the config (same payload md5) in the given request. * - * @param req The request for which to compare config payload with this config. + * @param req the request for which to compare config payload with this config. * @return true if this config is equal to the config in the given request. */ public boolean hasEqualConfig(JRTServerConfigRequest req) { @@ -143,7 +148,7 @@ public class RawConfig extends ConfigInstance { /** * Returns true if this config has a more recent generation than the config in the given request. * - * @param req The request for which to compare generation with this config. + * @param req the request for which to compare generation with this config. * @return true if this config has a more recent generation than the config in the given request. */ public boolean hasNewerGeneration(JRTServerConfigRequest req) { @@ -158,6 +163,7 @@ public class RawConfig extends ConfigInstance { return (errorCode() != 0); } + @Override public boolean equals(Object o) { if (o == this) { return true; @@ -184,6 +190,7 @@ public class RawConfig extends ConfigInstance { } } + @Override public int hashCode() { int hash = 17; if (key != null) { @@ -203,6 +210,7 @@ public class RawConfig extends ConfigInstance { return hash; } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(key.getNamespace()).append(".").append(key.getName()); @@ -222,4 +230,5 @@ public class RawConfig extends ConfigInstance { public List<String> getDefContent() { return defContent; } + } diff --git a/config/src/main/java/com/yahoo/vespa/config/protocol/JRTConfigRequest.java b/config/src/main/java/com/yahoo/vespa/config/protocol/JRTConfigRequest.java index 46b3651afd7..26fa41c19c7 100644 --- a/config/src/main/java/com/yahoo/vespa/config/protocol/JRTConfigRequest.java +++ b/config/src/main/java/com/yahoo/vespa/config/protocol/JRTConfigRequest.java @@ -8,11 +8,14 @@ import java.util.Optional; /** * Common interface for jrt config requests available both at server and client. + * * @author Ulf Lilleengen */ public interface JRTConfigRequest { + /** * Get the config key of the config request. + * * @return a {@link ConfigKey}. */ ConfigKey<?> getConfigKey(); @@ -20,18 +23,21 @@ public interface JRTConfigRequest { /** * Perform request parameter validation of this config request. This method should be called before fetching * any kind of config protocol-specific parameter. + * * @return true if valid, false if not. */ boolean validateParameters(); /** * Get the config md5 of the config request. Return an empty string if no response has been returned. + * * @return a config md5. */ String getRequestConfigMd5(); /** * Get the generation of the requested config. If none has been given, 0 should be returned. + * * @return the generation in the request. */ long getRequestGeneration(); @@ -39,42 +45,49 @@ public interface JRTConfigRequest { /** * Get the JRT request object for this config request. * TODO: This method leaks the internal jrt stuff :( + * * @return a {@link Request} object. */ Request getRequest(); /** * Get a short hand description of this request. + * * @return a short description */ String getShortDescription(); /** * Get the error code of this request + * * @return the error code as defined in {@link com.yahoo.vespa.config.ErrorCode}. */ int errorCode(); /** * Return the error message of this request, mostly corresponding to the {@link com.yahoo.vespa.config.ErrorCode}. + * * @return the error message. */ String errorMessage(); /** * Get the server timeout of this request. + * * @return the timeout given to the server */ long getTimeout(); /** * Get the config protocol version + * * @return a protocol version number. */ long getProtocolVersion(); /** * Get the wanted generation for this request. + * * @return a generation that client would like. */ long getWantedGeneration(); @@ -87,7 +100,9 @@ public interface JRTConfigRequest { /** * Get the Vespa version of the client that initiated the request + * * @return Vespa version of the client */ Optional<VespaVersion> getVespaVersion(); + } diff --git a/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeRequestData.java b/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeRequestData.java index 65e50acb72d..5e88c4cb146 100644 --- a/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeRequestData.java +++ b/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeRequestData.java @@ -12,11 +12,10 @@ import com.yahoo.vespa.config.ConfigKey; import java.util.Optional; /** - * Contains slime request data objects. Provides methods for reading various fields from slime request data. All - * data is read lazily. + * Contains slime request data objects. Provides methods for reading various fields from slime request data. + * All data is read lazily. * -* @author lulf -* @since 5.18 +* @author Ulf Lilleengen */ class SlimeRequestData { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerDB.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerDB.java index 72a470cf937..152fc47d807 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerDB.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ConfigServerDB.java @@ -20,6 +20,7 @@ import java.util.List; * @author Ulf Lilleengen */ public class ConfigServerDB { + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(ConfigServerDB.class.getName()); private final File serverDB; private final ConfigserverConfig configserverConfig; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java index 9999fb31e77..d5f3a237b9d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/SuperModelRequestHandler.java @@ -23,8 +23,7 @@ import java.util.Set; /** * Handles request for supermodel config. * - * @author lulf - * @since 5.9 + * @author Ulf Lilleengen */ public class SuperModelRequestHandler implements RequestHandler { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigResponse.java index 489424f8791..43fc0a2f418 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/HttpConfigResponse.java @@ -14,9 +14,9 @@ import static com.yahoo.jdisc.http.HttpResponse.Status.OK; * HTTP getConfig response * * @author lulf - * @since 5.1 */ public class HttpConfigResponse extends HttpResponse { + public static final String JSON_CONTENT_TYPE = "application/json"; private final ConfigResponse config; diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java index 5c5d5f55a4d..b0cb287ed0b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java @@ -149,7 +149,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { // TODO: Enable for all zones if (Arrays.asList(Environment.dev, Environment.test, Environment.staging).contains(zone().environment()) - || zone().region().value().equals("corp-us-east-1")) + || Arrays.asList("corp-us-east-1", "ap-southeast-1").contains(zone().region().value())) versions = keepThoseUsedOn(allocatedHosts.get(), versions); // TODO: We use the allocated hosts from the newest version when building older model versions. diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java index 970fe9f169b..55d5321c93f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/GetConfigProcessor.java @@ -42,7 +42,7 @@ class GetConfigProcessor implements Runnable { } private void respond(JRTServerConfigRequest request) { - final Request req = request.getRequest(); + Request req = request.getRequest(); if (req.isError()) { Level logLevel = (req.errorCode() == ErrorCode.APPLICATION_NOT_LOADED) ? LogLevel.DEBUG : LogLevel.INFO; log.log(logLevel, logPre + req.errorMessage()); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java index 10590a26690..6e34511c62d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java @@ -92,14 +92,14 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { File configApplicationDir, String applicationName, long sessionId, - long currentlyActiveSession, + long currentlyActiveSessionId, boolean internalRedeploy) { long deployTimestamp = System.currentTimeMillis(); String user = System.getenv("USER"); if (user == null) { user = "unknown"; } - DeployData deployData = new DeployData(user, userDir.getAbsolutePath(), applicationName, deployTimestamp, internalRedeploy, sessionId, currentlyActiveSession); + DeployData deployData = new DeployData(user, userDir.getAbsolutePath(), applicationName, deployTimestamp, internalRedeploy, sessionId, currentlyActiveSessionId); return FilesApplicationPackage.fromFileWithDeployData(configApplicationDir, deployData); } @@ -128,15 +128,15 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { File existingApp = getSessionAppDir(existingSession.getSessionId()); ApplicationId existingApplicationId = existingSession.getApplicationId(); - long liveApp = getLiveApp(existingApplicationId); - logger.log(LogLevel.DEBUG, "Create from existing application id " + existingApplicationId + ", live app for it is " + liveApp); - LocalSession session = create(existingApp, existingApplicationId, liveApp, internalRedeploy, timeoutBudget); + long activeSessionId = getActiveSessionId(existingApplicationId); + logger.log(LogLevel.DEBUG, "Create from existing application id " + existingApplicationId + ", active session id is " + activeSessionId); + LocalSession session = create(existingApp, existingApplicationId, activeSessionId, internalRedeploy, timeoutBudget); session.setApplicationId(existingApplicationId); session.setVespaVersion(existingSession.getVespaVersion()); return session; } - private LocalSession create(File applicationFile, ApplicationId applicationId, long currentlyActiveSession, + private LocalSession create(File applicationFile, ApplicationId applicationId, long currentlyActiveSessionId, boolean internalRedeploy, TimeoutBudget timeoutBudget) { long sessionId = sessionCounter.nextSessionId(); Path sessionIdPath = sessionsPath.append(String.valueOf(sessionId)); @@ -155,7 +155,7 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { userApplicationDir, applicationId.application().value(), sessionId, - currentlyActiveSession, + currentlyActiveSessionId, internalRedeploy); applicationPackage.writeMetaData(); return createSessionFromApplication(applicationPackage, sessionId, sessionZooKeeperClient, timeoutBudget, clock); @@ -188,7 +188,7 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { return new LocalSession(tenant, sessionId, sessionPreparer, context); } - private long getLiveApp(ApplicationId applicationId) { + private long getActiveSessionId(ApplicationId applicationId) { List<ApplicationId> applicationIds = applicationRepo.listApplications(); if (applicationIds.contains(applicationId)) { return applicationRepo.getSessionIdForApplication(applicationId); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/SessionCounter.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/SessionCounter.java index 2a25553d456..17d0f7e426e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/SessionCounter.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/SessionCounter.java @@ -25,4 +25,5 @@ public class SessionCounter extends InitializedCounter { public long nextSessionId() { return counter.next(); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java index 8084be1cefa..0aa6a6c88dc 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java @@ -14,7 +14,10 @@ import java.util.logging.Logger; /** * Responsible for providing data from the currently live application subtree in zookeeper. - * (i.e. /vespa/config/apps/<id of currently active app>/) + * (i.e. /vespa/config/apps/<id of currently active app>/). + * + * Note: The application revision ("session") stored in this tree is not necessarily live, just complete, + * preparable, prepared or active. * * @author tonytv */ @@ -34,7 +37,8 @@ public class ZKLiveApp { * Returns a list of the files (as readers) in the given path. The readers <b>must</b> * be closed by the caller. * - * @param path a path relative to the currently active application (i.e. /vespa/config/apps/<id of currently active app>/). + * @param path a path relative to the currently active application + * (i.e. /vespa/config/apps/<id of currently active app>/). * @param fileNameSuffix the suffix of files to return, or null to return all * @param recursive if true, all files from all subdirectories of this will also be returned * @return the files in the given path, or an empty list (never null) if the directory does not exist or is empty. diff --git a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java index b1399c6cc8d..0d9534457e9 100644 --- a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java +++ b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java @@ -192,8 +192,7 @@ public class ClusterSearcher extends Searcher { private static ClusterParams makeClusterParams(int searchclusterIndex, LegacyEmulationConfig emulConfig, int dispatchIndex) { - return new ClusterParams(searchclusterIndex, - "sc" + searchclusterIndex + ".num" + dispatchIndex, + return new ClusterParams("sc" + searchclusterIndex + ".num" + dispatchIndex, emulConfig); } diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/ClusterParams.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/ClusterParams.java index f95f303e87c..3dfa506a967 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/ClusterParams.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/ClusterParams.java @@ -11,29 +11,20 @@ import com.yahoo.container.search.LegacyEmulationConfig; */ public class ClusterParams { - public final int clusterNumber; public final String searcherName; public final LegacyEmulationConfig emulation; /** - * For compatibility - */ - public ClusterParams(int number, String name) { - this(number, name, new LegacyEmulationConfig(new LegacyEmulationConfig.Builder())); - } - - /** * For testcases only */ public ClusterParams(String name) { - this(0, name); + this(name, new LegacyEmulationConfig(new LegacyEmulationConfig.Builder())); } /** * Make up full ClusterParams */ - public ClusterParams(int number, String name, LegacyEmulationConfig cfg) { - this.clusterNumber = number; + public ClusterParams(String name, LegacyEmulationConfig cfg) { this.searcherName = name; this.emulation = cfg; } diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java index 3abd97d814e..34e8390892d 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java @@ -75,9 +75,6 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { /** Cache wrapper */ protected CacheControl cacheControl = null; - /** Searchcluster number */ - private int sourceNumber; - protected final String getName() { return name; } protected final String getDefaultDocsumClass() { return defaultDocsumClass; } @@ -168,7 +165,6 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { public final void init(SummaryParameters docSumParams, ClusterParams clusterParams, CacheParams cacheParams, DocumentdbInfoConfig documentdbInfoConfig) { this.name = clusterParams.searcherName; - this.sourceNumber = clusterParams.clusterNumber; Validator.ensureNotNull("Name of Vespa backend integration", getName()); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index d6c0bf23da6..4b09e78ede2 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -688,7 +688,8 @@ public class ApplicationApiHandler extends LoggingRequestHandler { ApplicationId id = ApplicationId.from(tenantName, applicationName, "default"); controller.applications().lockOrThrow(id, application -> { - controller.applications().deploymentTrigger().triggerChange(application.get().id(), Change.of(version)); + controller.applications().deploymentTrigger().triggerChange(application.get().id(), + application.get().change().with(version)); }); return new MessageResponse("Triggered deployment of application '" + id + "' on version " + version); } diff --git a/jdisc_core/src/main/java/com/yahoo/jdisc/TimeBudget.java b/jdisc_core/src/main/java/com/yahoo/jdisc/TimeBudget.java new file mode 100644 index 00000000000..39322b6e83a --- /dev/null +++ b/jdisc_core/src/main/java/com/yahoo/jdisc/TimeBudget.java @@ -0,0 +1,55 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc; + +import javax.annotation.concurrent.Immutable; +import java.time.Duration; +import java.time.Instant; + +/** + * A TimeBudget tracks the current time compared to a start time and deadline. + * + * @author hakon + */ +@Immutable +public class TimeBudget { + private final Timer timer; + private final Instant start; + private final Duration timeout; + + /** Returns a TimeBudget with a start time of now, and with the given timeout. */ + public static TimeBudget fromNow(Timer timer, Duration timeout) { + return new TimeBudget(timer, timer.currentTime(), timeout); + } + + private TimeBudget(Timer timer, Instant start, Duration timeout) { + this.timer = timer; + this.start = start; + this.timeout = timeout; + } + + /** Time until 'headroom' before deadline. Guaranteed to be non-negative. */ + public Duration timeBeforeDeadline(Duration headroom) { + return nonNegativeBetween(now(), deadline().minus(headroom)); + } + + /** Returns the original timeout. */ + public Duration originalTimeout() { + return timeout; + } + + private static Duration nonNegativeBetween(Instant start, Instant end) { + return makeNonNegative(Duration.between(start, end)); + } + + private static Duration makeNonNegative(Duration duration) { + return duration.isNegative() ? Duration.ZERO : duration; + } + + private Instant now() { + return timer.currentTime(); + } + + private Instant deadline() { + return start.plus(timeout); + } +} diff --git a/jdisc_core/src/test/java/com/yahoo/jdisc/TimeBudgetTestCase.java b/jdisc_core/src/test/java/com/yahoo/jdisc/TimeBudgetTestCase.java new file mode 100644 index 00000000000..5afc205beb3 --- /dev/null +++ b/jdisc_core/src/test/java/com/yahoo/jdisc/TimeBudgetTestCase.java @@ -0,0 +1,29 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc; + +import org.junit.Test; + +import java.time.Duration; +import java.time.Instant; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TimeBudgetTestCase { + private final Timer timer = mock(Timer.class); + + @Test + public void testBasics() { + when(timer.currentTime()).thenReturn(Instant.ofEpochSecond(0)); + TimeBudget timeBudget = TimeBudget.fromNow(timer, Duration.ofSeconds(10)); + + when(timer.currentTime()).thenReturn(Instant.ofEpochSecond(7)); + assertEquals(Duration.ofSeconds(3), timeBudget.timeBeforeDeadline(Duration.ofSeconds(0))); + assertEquals(Duration.ofSeconds(1), timeBudget.timeBeforeDeadline(Duration.ofSeconds(2))); + assertEquals(Duration.ofSeconds(0), timeBudget.timeBeforeDeadline(Duration.ofSeconds(5))); + + when(timer.currentTime()).thenReturn(Instant.ofEpochSecond(11)); + assertEquals(Duration.ofSeconds(0), timeBudget.timeBeforeDeadline(Duration.ofSeconds(0))); + } +}
\ No newline at end of file diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java new file mode 100644 index 00000000000..9e605561e7b --- /dev/null +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorContext.java @@ -0,0 +1,44 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.orchestrator; + +import com.yahoo.jdisc.TimeBudget; +import com.yahoo.jdisc.Timer; + +import java.time.Duration; +import java.util.Optional; + +/** + * Context for the Orchestrator, e.g. timeout management. + * + * @author hakon + */ +public class OrchestratorContext { + private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(10); + private static final Duration POST_OPERATION_HEADROOM = Duration.ofMillis(100); + + private TimeBudget timeBudget; + + public OrchestratorContext(Timer timer) { + this.timeBudget = TimeBudget.fromNow(timer, DEFAULT_TIMEOUT); + } + + /** Get the original timeout in seconds. */ + public long getOriginalTimeoutInSeconds() { + return timeBudget.originalTimeout().getSeconds(); + } + + /** + * Get number of seconds until the deadline, or empty if there's no deadline. + * + * <p>The returned timeout is slightly shorter than the actual timeout to ensure there's + * enough time to wrap up and return from the Orchestrator between when the operation + * times out and the actual timeout. + */ + public Optional<Float> getSuboperationTimeoutInSeconds() { + return getSuboperationTimeoutInSeconds(POST_OPERATION_HEADROOM); + } + + private Optional<Float> getSuboperationTimeoutInSeconds(Duration headroom) { + return Optional.of((float) (timeBudget.timeBeforeDeadline(headroom).toMillis() / 1000.0)); + } +} diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java index 095a7da8322..580d34eccf8 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.orchestrator; import com.google.inject.Inject; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.jdisc.Timer; import com.yahoo.log.LogLevel; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; @@ -43,7 +44,6 @@ import java.util.stream.Collectors; * @author smorgrav */ public class OrchestratorImpl implements Orchestrator { - private static final Logger log = Logger.getLogger(OrchestratorImpl.class.getName()); private final Policy policy; @@ -51,32 +51,36 @@ public class OrchestratorImpl implements Orchestrator { private final InstanceLookupService instanceLookupService; private final int serviceMonitorConvergenceLatencySeconds; private final ClusterControllerClientFactory clusterControllerClientFactory; + private final Timer timer; @Inject public OrchestratorImpl(ClusterControllerClientFactory clusterControllerClientFactory, StatusService statusService, OrchestratorConfig orchestratorConfig, - InstanceLookupService instanceLookupService) + InstanceLookupService instanceLookupService, + Timer timer) { this(new HostedVespaPolicy(new HostedVespaClusterPolicy(), clusterControllerClientFactory), clusterControllerClientFactory, statusService, instanceLookupService, - orchestratorConfig.serviceMonitorConvergenceLatencySeconds()); + orchestratorConfig.serviceMonitorConvergenceLatencySeconds(), + timer); } public OrchestratorImpl(Policy policy, ClusterControllerClientFactory clusterControllerClientFactory, StatusService statusService, InstanceLookupService instanceLookupService, - int serviceMonitorConvergenceLatencySeconds) + int serviceMonitorConvergenceLatencySeconds, + Timer timer) { this.policy = policy; this.clusterControllerClientFactory = clusterControllerClientFactory; this.statusService = statusService; this.serviceMonitorConvergenceLatencySeconds = serviceMonitorConvergenceLatencySeconds; this.instanceLookupService = instanceLookupService; - + this.timer = timer; } @Override @@ -123,7 +127,10 @@ public class OrchestratorImpl implements Orchestrator { ApplicationInstance appInstance = getApplicationInstance(hostName); - try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(appInstance.reference())) { + OrchestratorContext context = new OrchestratorContext(timer); + try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly( + appInstance.reference(), + context.getOriginalTimeoutInSeconds())) { final HostStatus currentHostState = statusRegistry.getHostStatus(hostName); if (HostStatus.NO_REMARKS == currentHostState) { @@ -132,7 +139,7 @@ public class OrchestratorImpl implements Orchestrator { ApplicationInstanceStatus appStatus = statusService.forApplicationInstance(appInstance.reference()).getApplicationInstanceStatus(); if (appStatus == ApplicationInstanceStatus.NO_REMARKS) { - policy.releaseSuspensionGrant(appInstance, hostName, statusRegistry); + policy.releaseSuspensionGrant(context, appInstance, hostName, statusRegistry); } } } @@ -149,13 +156,16 @@ public class OrchestratorImpl implements Orchestrator { ApplicationInstance appInstance = getApplicationInstance(hostName); NodeGroup nodeGroup = new NodeGroup(appInstance, hostName); - try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(appInstance.reference())) { + OrchestratorContext context = new OrchestratorContext(timer); + try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly( + appInstance.reference(), + context.getOriginalTimeoutInSeconds())) { ApplicationApi applicationApi = new ApplicationApiImpl( nodeGroup, statusRegistry, clusterControllerClientFactory); - policy.acquirePermissionToRemove(applicationApi); + policy.acquirePermissionToRemove(context, applicationApi); } } @@ -164,7 +174,11 @@ public class OrchestratorImpl implements Orchestrator { public void suspendGroup(NodeGroup nodeGroup) throws HostStateChangeDeniedException, HostNameNotFoundException { ApplicationInstanceReference applicationReference = nodeGroup.getApplicationReference(); - try (MutableStatusRegistry hostStatusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(applicationReference)) { + OrchestratorContext context = new OrchestratorContext(timer); + try (MutableStatusRegistry hostStatusRegistry = + statusService.lockApplicationInstance_forCurrentThreadOnly( + applicationReference, + context.getOriginalTimeoutInSeconds())) { ApplicationInstanceStatus appStatus = statusService.forApplicationInstance(applicationReference).getApplicationInstanceStatus(); if (appStatus == ApplicationInstanceStatus.ALLOWED_TO_BE_DOWN) { return; @@ -174,7 +188,7 @@ public class OrchestratorImpl implements Orchestrator { nodeGroup, hostStatusRegistry, clusterControllerClientFactory); - policy.grantSuspensionRequest(applicationApi); + policy.grantSuspensionRequest(context, applicationApi); } } @@ -287,9 +301,12 @@ public class OrchestratorImpl implements Orchestrator { private void setApplicationStatus(ApplicationId appId, ApplicationInstanceStatus status) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException{ + OrchestratorContext context = new OrchestratorContext(timer); ApplicationInstanceReference appRef = OrchestratorUtil.toApplicationInstanceReference(appId, instanceLookupService); try (MutableStatusRegistry statusRegistry = - statusService.lockApplicationInstance_forCurrentThreadOnly(appRef)) { + statusService.lockApplicationInstance_forCurrentThreadOnly( + appRef, + context.getOriginalTimeoutInSeconds())) { // Short-circuit if already in wanted state if (status == statusRegistry.getApplicationInstanceStatus()) return; @@ -304,14 +321,15 @@ public class OrchestratorImpl implements Orchestrator { // If the clustercontroller throws an error the nodes will be marked as allowed to be down // and be set back up on next resume invocation. - setClusterStateInController(application, ClusterControllerNodeState.MAINTENANCE); + setClusterStateInController(context, application, ClusterControllerNodeState.MAINTENANCE); } statusRegistry.setApplicationInstanceStatus(status); } } - private void setClusterStateInController(ApplicationInstance application, + private void setClusterStateInController(OrchestratorContext context, + ApplicationInstance application, ClusterControllerNodeState state) throws ApplicationStateChangeDeniedException, ApplicationIdNotFoundException { // Get all content clusters for this application @@ -329,7 +347,7 @@ public class OrchestratorImpl implements Orchestrator { clusterControllers, clusterId.s()); try { - ClusterControllerStateResponse response = client.setApplicationState(state); + ClusterControllerStateResponse response = client.setApplicationState(context, state); if (!response.wasModified) { String msg = String.format("Fail to set application %s, cluster name %s to cluster state %s due to: %s", application.applicationInstanceId(), clusterId, state, response.reason); diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClient.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClient.java index 38cabd5d86d..c2559bdd0da 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClient.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClient.java @@ -1,6 +1,8 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.orchestrator.controller; +import com.yahoo.vespa.orchestrator.OrchestratorContext; + import java.io.IOException; /** @@ -13,13 +15,13 @@ public interface ClusterControllerClient { * * @throws IOException if there was a problem communicating with the cluster controller */ - ClusterControllerStateResponse setNodeState(int storageNodeIndex, ClusterControllerNodeState wantedState) throws IOException; + ClusterControllerStateResponse setNodeState(OrchestratorContext context, int storageNodeIndex, ClusterControllerNodeState wantedState) throws IOException; /** * Requests that a cluster controller sets all nodes in the cluster to the requested state. * * @throws IOException if there was a problem communicating with the cluster controller */ - ClusterControllerStateResponse setApplicationState(ClusterControllerNodeState wantedState) throws IOException; + ClusterControllerStateResponse setApplicationState(OrchestratorContext context, ClusterControllerNodeState wantedState) throws IOException; } diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java index b70e1a56aea..7d7a9b36ff9 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientImpl.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.orchestrator.controller; import com.yahoo.vespa.jaxrs.client.JaxRsStrategy; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import java.io.IOException; @@ -29,12 +30,19 @@ public class ClusterControllerClientImpl implements ClusterControllerClient{ * @throws IOException if there was a problem communicating with the cluster controller */ @Override - public ClusterControllerStateResponse setNodeState(int storageNodeIndex, ClusterControllerNodeState wantedState) throws IOException { + public ClusterControllerStateResponse setNodeState(OrchestratorContext context, + int storageNodeIndex, + ClusterControllerNodeState wantedState) throws IOException { ClusterControllerStateRequest.State state = new ClusterControllerStateRequest.State(wantedState, REQUEST_REASON); ClusterControllerStateRequest stateRequest = new ClusterControllerStateRequest(state, ClusterControllerStateRequest.Condition.SAFE); try { - return clusterControllerApi.apply(api -> api.setNodeState(clusterName, storageNodeIndex, stateRequest)); + return clusterControllerApi.apply(api -> api.setNodeState( + clusterName, + storageNodeIndex, + context.getSuboperationTimeoutInSeconds().orElse(null), + stateRequest) + ); } catch (IOException e) { String message = String.format( "Giving up setting %s for storage node with index %d in cluster %s", @@ -52,12 +60,17 @@ public class ClusterControllerClientImpl implements ClusterControllerClient{ * @throws IOException if there was a problem communicating with the cluster controller */ @Override - public ClusterControllerStateResponse setApplicationState(final ClusterControllerNodeState wantedState) throws IOException { + public ClusterControllerStateResponse setApplicationState( + OrchestratorContext context, + final ClusterControllerNodeState wantedState) throws IOException { final ClusterControllerStateRequest.State state = new ClusterControllerStateRequest.State(wantedState, REQUEST_REASON); final ClusterControllerStateRequest stateRequest = new ClusterControllerStateRequest(state, ClusterControllerStateRequest.Condition.FORCE); try { - return clusterControllerApi.apply(api -> api.setClusterState(clusterName, stateRequest)); + return clusterControllerApi.apply(api -> api.setClusterState( + clusterName, + context.getSuboperationTimeoutInSeconds().orElse(null), + stateRequest)); } catch (IOException e) { final String message = String.format( "Giving up setting %s for cluster %s", diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerJaxRsApi.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerJaxRsApi.java index 7059706c569..4831f4c121a 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerJaxRsApi.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerJaxRsApi.java @@ -6,6 +6,7 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; /** @@ -20,6 +21,7 @@ public interface ClusterControllerJaxRsApi { ClusterControllerStateResponse setNodeState( @PathParam("clusterName") String clusterName, @PathParam("storageNodeIndex") int storageNodeIndex, + @QueryParam("timeout") Float timeoutSeconds, ClusterControllerStateRequest request); @POST @@ -28,6 +30,7 @@ public interface ClusterControllerJaxRsApi { @Produces(MediaType.APPLICATION_JSON) ClusterControllerStateResponse setClusterState( @PathParam("clusterName") String clusterName, + @QueryParam("timeout") Float timeoutSeconds, ClusterControllerStateRequest request); } diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNode.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNode.java index 210f68e8fda..a54d829a029 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNode.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNode.java @@ -2,10 +2,11 @@ package com.yahoo.vespa.orchestrator.model; import com.yahoo.vespa.applicationmodel.HostName; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import com.yahoo.vespa.orchestrator.controller.ClusterControllerNodeState; import com.yahoo.vespa.orchestrator.policy.HostStateChangeDeniedException; public interface StorageNode extends Comparable<StorageNode> { HostName hostName(); - void setNodeState(ClusterControllerNodeState wantedState) throws HostStateChangeDeniedException; + void setNodeState(OrchestratorContext context, ClusterControllerNodeState wantedState) throws HostStateChangeDeniedException; } diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNodeImpl.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNodeImpl.java index 109acbc6486..a2732bca88a 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNodeImpl.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/model/StorageNodeImpl.java @@ -7,6 +7,7 @@ import com.yahoo.vespa.applicationmodel.ClusterId; import com.yahoo.vespa.applicationmodel.ConfigId; import com.yahoo.vespa.applicationmodel.HostName; import com.yahoo.vespa.applicationmodel.ServiceInstance; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import com.yahoo.vespa.orchestrator.controller.ClusterControllerClient; import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactory; import com.yahoo.vespa.orchestrator.controller.ClusterControllerNodeState; @@ -43,7 +44,7 @@ public class StorageNodeImpl implements StorageNode { } @Override - public void setNodeState(ClusterControllerNodeState wantedNodeState) + public void setNodeState(OrchestratorContext context, ClusterControllerNodeState wantedNodeState) throws HostStateChangeDeniedException { // The "cluster name" used by the Cluster Controller IS the cluster ID. String clusterId = this.clusterId.s(); @@ -66,7 +67,7 @@ public class StorageNodeImpl implements StorageNode { ClusterControllerStateResponse response; try { - response = client.setNodeState(nodeIndex, wantedNodeState); + response = client.setNodeState(context, nodeIndex, wantedNodeState); } catch (IOException e) { throw new HostStateChangeDeniedException( hostName(), diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicy.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicy.java index 8e02f940127..e1664466283 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicy.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicy.java @@ -1,10 +1,10 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.orchestrator.policy; -import com.yahoo.config.provision.ApplicationId; import com.yahoo.log.LogLevel; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.HostName; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactory; import com.yahoo.vespa.orchestrator.controller.ClusterControllerNodeState; import com.yahoo.vespa.orchestrator.model.ApplicationApi; @@ -40,7 +40,7 @@ public class HostedVespaPolicy implements Policy { } @Override - public void grantSuspensionRequest(ApplicationApi application) + public void grantSuspensionRequest(OrchestratorContext context, ApplicationApi application) throws HostStateChangeDeniedException { // Apply per-cluster policy for (ClusterApi cluster : application.getClusters()) { @@ -50,7 +50,7 @@ public class HostedVespaPolicy implements Policy { // Ask Cluster Controller to set UP storage nodes in maintenance. // These storage nodes are guaranteed to be NO_REMARKS for (StorageNode storageNode : application.getUpStorageNodesInGroupInClusterOrder()) { - storageNode.setNodeState(ClusterControllerNodeState.MAINTENANCE); + storageNode.setNodeState(context, ClusterControllerNodeState.MAINTENANCE); log.log(LogLevel.INFO, "The storage node on " + storageNode.hostName() + " has been set to MAINTENANCE"); } @@ -62,10 +62,11 @@ public class HostedVespaPolicy implements Policy { } @Override - public void releaseSuspensionGrant(ApplicationApi application) throws HostStateChangeDeniedException { + public void releaseSuspensionGrant(OrchestratorContext context, ApplicationApi application) + throws HostStateChangeDeniedException { // Always defer to Cluster Controller whether it's OK to resume storage node for (StorageNode storageNode : application.getStorageNodesAllowedToBeDownInGroupInReverseClusterOrder()) { - storageNode.setNodeState(ClusterControllerNodeState.UP); + storageNode.setNodeState(context, ClusterControllerNodeState.UP); log.log(LogLevel.INFO, "The storage node on " + storageNode.hostName() + " has been set to UP"); } @@ -76,7 +77,8 @@ public class HostedVespaPolicy implements Policy { } @Override - public void acquirePermissionToRemove(ApplicationApi applicationApi) throws HostStateChangeDeniedException { + public void acquirePermissionToRemove(OrchestratorContext context, ApplicationApi applicationApi) + throws HostStateChangeDeniedException { ApplicationInstanceStatus applicationStatus = applicationApi.getApplicationStatus(); if (applicationStatus == ApplicationInstanceStatus.ALLOWED_TO_BE_DOWN) { throw new HostStateChangeDeniedException( @@ -94,7 +96,7 @@ public class HostedVespaPolicy implements Policy { // Ask Cluster Controller to set storage nodes to DOWN. // These storage nodes are guaranteed to be NO_REMARKS for (StorageNode storageNode : applicationApi.getStorageNodesInGroupInClusterOrder()) { - storageNode.setNodeState(ClusterControllerNodeState.DOWN); + storageNode.setNodeState(context, ClusterControllerNodeState.DOWN); log.log(LogLevel.INFO, "The storage node on " + storageNode.hostName() + " has been set DOWN"); } @@ -107,24 +109,14 @@ public class HostedVespaPolicy implements Policy { // TODO: Remove later - currently used for backward compatibility testing @Override - public void grantSuspensionRequest(ApplicationInstance applicationInstance, - HostName hostName, - MutableStatusRegistry hostStatusService) throws HostStateChangeDeniedException { - NodeGroup nodeGroup = new NodeGroup(applicationInstance); - nodeGroup.addNode(hostName); - ApplicationApi applicationApi = new ApplicationApiImpl(nodeGroup, hostStatusService, clusterControllerClientFactory); - grantSuspensionRequest(applicationApi); - } - - // TODO: Remove later - currently used for backward compatibility testing - @Override public void releaseSuspensionGrant( + OrchestratorContext context, ApplicationInstance applicationInstance, HostName hostName, MutableStatusRegistry hostStatusService) throws HostStateChangeDeniedException { NodeGroup nodeGroup = new NodeGroup(applicationInstance, hostName); ApplicationApi applicationApi = new ApplicationApiImpl(nodeGroup, hostStatusService, clusterControllerClientFactory); - releaseSuspensionGrant(applicationApi); + releaseSuspensionGrant(context, applicationApi); } } diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/Policy.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/Policy.java index 4ea4f81182f..9938d244657 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/Policy.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/policy/Policy.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.orchestrator.policy; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.HostName; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import com.yahoo.vespa.orchestrator.model.ApplicationApi; import com.yahoo.vespa.orchestrator.status.MutableStatusRegistry; @@ -10,30 +11,20 @@ import com.yahoo.vespa.orchestrator.status.MutableStatusRegistry; * @author oyving */ public interface Policy { - - /** - * Decide whether to grant a request for temporarily suspending the services on a host. - * - * @throws HostStateChangeDeniedException if the grant was not given. - */ - void grantSuspensionRequest( - ApplicationInstance applicationInstance, - HostName hostName, - MutableStatusRegistry hostStatusService) throws HostStateChangeDeniedException; - /** * Decide whether to grant a request for temporarily suspending the services on all hosts in the group. */ - void grantSuspensionRequest(ApplicationApi applicationApi) throws HostStateChangeDeniedException; + void grantSuspensionRequest(OrchestratorContext context, ApplicationApi applicationApi) throws HostStateChangeDeniedException; - void releaseSuspensionGrant(ApplicationApi application) throws HostStateChangeDeniedException; + void releaseSuspensionGrant(OrchestratorContext context, ApplicationApi application) throws HostStateChangeDeniedException; /** * Give all hosts in a group permission to be removed from the application. * + * @param context * @param applicationApi */ - void acquirePermissionToRemove(ApplicationApi applicationApi) throws HostStateChangeDeniedException; + void acquirePermissionToRemove(OrchestratorContext context, ApplicationApi applicationApi) throws HostStateChangeDeniedException; /** * Release an earlier grant for suspension. @@ -41,7 +32,7 @@ public interface Policy { * @throws HostStateChangeDeniedException if the release failed. */ void releaseSuspensionGrant( - ApplicationInstance applicationInstance, + OrchestratorContext context, ApplicationInstance applicationInstance, HostName hostName, MutableStatusRegistry hostStatusService) throws HostStateChangeDeniedException; } diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/InMemoryStatusService.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/InMemoryStatusService.java index cab14a2e77f..c5ae553a98c 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/InMemoryStatusService.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/InMemoryStatusService.java @@ -44,6 +44,13 @@ public class InMemoryStatusService implements StatusService { @Override public MutableStatusRegistry lockApplicationInstance_forCurrentThreadOnly(ApplicationInstanceReference applicationInstanceReference) { + return lockApplicationInstance_forCurrentThreadOnly(applicationInstanceReference, 10); + } + + @Override + public MutableStatusRegistry lockApplicationInstance_forCurrentThreadOnly( + ApplicationInstanceReference applicationInstanceReference, + long timeoutSeconds) { Lock lock = instanceLockService.get(applicationInstanceReference); return new InMemoryMutableStatusRegistry(lock, applicationInstanceReference); } diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/StatusService.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/StatusService.java index cf7b40ce0ef..db58544df55 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/StatusService.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/StatusService.java @@ -54,6 +54,11 @@ public interface StatusService { */ MutableStatusRegistry lockApplicationInstance_forCurrentThreadOnly(ApplicationInstanceReference applicationInstanceReference); + /** Lock application instance with timeout. */ + MutableStatusRegistry lockApplicationInstance_forCurrentThreadOnly( + ApplicationInstanceReference applicationInstanceReference, + long timeoutSeconds); + /** * Returns all application instances that are allowed to be down. The intention is to use this * for visualization, informational and debugging purposes. diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/ZookeeperStatusService.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/ZookeeperStatusService.java index c84473a5199..18d6ed4b3f2 100644 --- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/ZookeeperStatusService.java +++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/status/ZookeeperStatusService.java @@ -93,7 +93,8 @@ public class ZookeeperStatusService implements StatusService { } } - MutableStatusRegistry lockApplicationInstance_forCurrentThreadOnly( + @Override + public MutableStatusRegistry lockApplicationInstance_forCurrentThreadOnly( ApplicationInstanceReference applicationInstanceReference, long timeoutSeconds) { String lockPath = applicationInstanceLock2Path(applicationInstanceReference); diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java index 76d9398c44e..c3b1ceb66ec 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.orchestrator; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.jdisc.Timer; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.ApplicationInstanceId; import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; @@ -77,7 +78,8 @@ public class OrchestratorImplTest { clustercontroller, new InMemoryStatusService(), new OrchestratorConfig(new OrchestratorConfig.Builder()), - new DummyInstanceLookupService()); + new DummyInstanceLookupService(), + mock(Timer.class)); clustercontroller.setAllDummyNodesAsUp(); } @@ -307,7 +309,8 @@ public class OrchestratorImplTest { clusterControllerClientFactory, statusService, new OrchestratorConfig(new OrchestratorConfig.Builder()), - lookupService); + lookupService, + mock(Timer.class)); HostName hostName = new HostName("host.yahoo.com"); TenantId tenantId = new TenantId("tenant"); diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientFactoryMock.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientFactoryMock.java index 230e36469d3..5c5ee7d2260 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientFactoryMock.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientFactoryMock.java @@ -5,6 +5,7 @@ import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.ClusterId; import com.yahoo.vespa.applicationmodel.HostName; import com.yahoo.vespa.orchestrator.DummyInstanceLookupService; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import com.yahoo.vespa.orchestrator.model.VespaModelUtil; import java.io.IOException; @@ -52,13 +53,13 @@ public class ClusterControllerClientFactoryMock implements ClusterControllerClie return new ClusterControllerClient() { @Override - public ClusterControllerStateResponse setNodeState(int storageNodeIndex, ClusterControllerNodeState wantedState) throws IOException { + public ClusterControllerStateResponse setNodeState(OrchestratorContext context, int storageNodeIndex, ClusterControllerNodeState wantedState) throws IOException { nodes.put(clusterName + storageNodeIndex, wantedState); return new ClusterControllerStateResponse(true, "Yes"); } @Override - public ClusterControllerStateResponse setApplicationState(ClusterControllerNodeState wantedState) throws IOException { + public ClusterControllerStateResponse setApplicationState(OrchestratorContext context, ClusterControllerNodeState wantedState) throws IOException { Set<String> keyCopy = new HashSet<>(nodes.keySet()); for (String s : keyCopy) { if (s.startsWith(clusterName)) { diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java index 09d52326eb8..b3f80b5129f 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/ClusterControllerClientTest.java @@ -3,12 +3,16 @@ package com.yahoo.vespa.orchestrator.controller; import com.yahoo.vespa.jaxrs.client.JaxRsStrategy; import com.yahoo.vespa.jaxrs.client.LocalPassThroughJaxRsStrategy; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import org.junit.Test; +import java.util.Optional; + import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class ClusterControllerClientTest { private static final String CLUSTER_NAME = "clusterName"; @@ -24,7 +28,9 @@ public class ClusterControllerClientTest { final ClusterControllerNodeState wantedState = ClusterControllerNodeState.MAINTENANCE; - clusterControllerClient.setNodeState(STORAGE_NODE_INDEX, wantedState); + OrchestratorContext context = mock(OrchestratorContext.class); + when(context.getSuboperationTimeoutInSeconds()).thenReturn(Optional.of(1.0f)); + clusterControllerClient.setNodeState(context, STORAGE_NODE_INDEX, wantedState); final ClusterControllerStateRequest expectedNodeStateRequest = new ClusterControllerStateRequest( new ClusterControllerStateRequest.State(wantedState, ClusterControllerClientImpl.REQUEST_REASON), @@ -33,6 +39,7 @@ public class ClusterControllerClientTest { .setNodeState( eq(CLUSTER_NAME), eq(STORAGE_NODE_INDEX), + eq(1.0f), eq(expectedNodeStateRequest)); } } diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java index b26d11a113f..c3dbe5c8a92 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/controller/SingleInstanceClusterControllerClientFactoryTest.java @@ -4,11 +4,13 @@ package com.yahoo.vespa.orchestrator.controller; import com.yahoo.vespa.applicationmodel.ConfigId; import com.yahoo.vespa.applicationmodel.HostName; import com.yahoo.vespa.jaxrs.client.JaxRsClientFactory; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import org.junit.Before; import org.junit.Test; import java.util.Arrays; import java.util.List; +import java.util.Optional; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.equalTo; @@ -31,6 +33,7 @@ public class SingleInstanceClusterControllerClientFactoryTest { private static final HostName HOST_NAME_2 = new HostName("host2"); private static final HostName HOST_NAME_3 = new HostName("host3"); + OrchestratorContext context = mock(OrchestratorContext.class); private final ClusterControllerJaxRsApi mockApi = mock(ClusterControllerJaxRsApi.class); private final JaxRsClientFactory jaxRsClientFactory = mock(JaxRsClientFactory.class); private final ClusterControllerClientFactory clientFactory @@ -64,8 +67,9 @@ public class SingleInstanceClusterControllerClientFactoryTest { public void testCreateClientWithSingleClusterControllerInstance() throws Exception { final List<HostName> clusterControllers = Arrays.asList(HOST_NAME_1); + when(context.getSuboperationTimeoutInSeconds()).thenReturn(Optional.of(1.0f)); clientFactory.createClient(clusterControllers, "clusterName") - .setNodeState(0, ClusterControllerNodeState.MAINTENANCE); + .setNodeState(context, 0, ClusterControllerNodeState.MAINTENANCE); verify(jaxRsClientFactory).createClient( ClusterControllerJaxRsApi.class, @@ -91,8 +95,9 @@ public class SingleInstanceClusterControllerClientFactoryTest { public void testCreateClientWithThreeClusterControllerInstances() throws Exception { final List<HostName> clusterControllers = Arrays.asList(HOST_NAME_1, HOST_NAME_2, HOST_NAME_3); + when(context.getSuboperationTimeoutInSeconds()).thenReturn(Optional.of(1.0f)); clientFactory.createClient(clusterControllers, "clusterName") - .setNodeState(0, ClusterControllerNodeState.MAINTENANCE); + .setNodeState(context, 0, ClusterControllerNodeState.MAINTENANCE); verify(jaxRsClientFactory).createClient( eq(ClusterControllerJaxRsApi.class), diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicyTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicyTest.java index 220371c4a17..329c9576f2c 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicyTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/policy/HostedVespaPolicyTest.java @@ -5,6 +5,7 @@ package com.yahoo.vespa.orchestrator.policy; import com.yahoo.config.provision.ApplicationId; import com.yahoo.vespa.applicationmodel.HostName; import com.yahoo.vespa.orchestrator.OrchestrationException; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import com.yahoo.vespa.orchestrator.controller.ClusterControllerClient; import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactory; import com.yahoo.vespa.orchestrator.controller.ClusterControllerNodeState; @@ -70,7 +71,8 @@ public class HostedVespaPolicyTest { InOrder order = inOrder(applicationApi, clusterPolicy, storageNode1, storageNode3); - policy.grantSuspensionRequest(applicationApi); + OrchestratorContext context = mock(OrchestratorContext.class); + policy.grantSuspensionRequest(context, applicationApi); order.verify(applicationApi).getClusters(); order.verify(clusterPolicy).verifyGroupGoingDownIsFine(clusterApi1); @@ -78,8 +80,8 @@ public class HostedVespaPolicyTest { order.verify(clusterPolicy).verifyGroupGoingDownIsFine(clusterApi3); order.verify(applicationApi).getUpStorageNodesInGroupInClusterOrder(); - order.verify(storageNode1).setNodeState(ClusterControllerNodeState.MAINTENANCE); - order.verify(storageNode3).setNodeState(ClusterControllerNodeState.MAINTENANCE); + order.verify(storageNode1).setNodeState(context, ClusterControllerNodeState.MAINTENANCE); + order.verify(storageNode3).setNodeState(context, ClusterControllerNodeState.MAINTENANCE); order.verify(applicationApi).getNodesInGroupWithStatus(HostStatus.NO_REMARKS); order.verify(applicationApi).setHostState(hostName1, HostStatus.ALLOWED_TO_BE_DOWN); @@ -120,7 +122,8 @@ public class HostedVespaPolicyTest { InOrder order = inOrder(applicationApi, clusterPolicy, storageNode1, storageNode3); - policy.acquirePermissionToRemove(applicationApi); + OrchestratorContext context = mock(OrchestratorContext.class); + policy.acquirePermissionToRemove(context, applicationApi); order.verify(applicationApi).getClusters(); order.verify(clusterPolicy).verifyGroupGoingDownPermanentlyIsFine(clusterApi1); @@ -128,8 +131,8 @@ public class HostedVespaPolicyTest { order.verify(clusterPolicy).verifyGroupGoingDownPermanentlyIsFine(clusterApi3); order.verify(applicationApi).getStorageNodesInGroupInClusterOrder(); - order.verify(storageNode1).setNodeState(ClusterControllerNodeState.DOWN); - order.verify(storageNode3).setNodeState(ClusterControllerNodeState.DOWN); + order.verify(storageNode1).setNodeState(context, ClusterControllerNodeState.DOWN); + order.verify(storageNode3).setNodeState(context, ClusterControllerNodeState.DOWN); order.verify(applicationApi).getNodesInGroupWithStatus(HostStatus.NO_REMARKS); order.verify(applicationApi).setHostState(hostName1, HostStatus.ALLOWED_TO_BE_DOWN); diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java index 2c7db25ae30..49f1a33febb 100644 --- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java +++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.orchestrator.resources; +import com.yahoo.jdisc.Timer; import com.yahoo.vespa.applicationmodel.ApplicationInstance; import com.yahoo.vespa.applicationmodel.ApplicationInstanceId; import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference; @@ -16,6 +17,7 @@ import com.yahoo.vespa.orchestrator.Host; import com.yahoo.vespa.orchestrator.InstanceLookupService; import com.yahoo.vespa.orchestrator.OrchestrationException; import com.yahoo.vespa.orchestrator.Orchestrator; +import com.yahoo.vespa.orchestrator.OrchestratorContext; import com.yahoo.vespa.orchestrator.OrchestratorImpl; import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactoryMock; import com.yahoo.vespa.orchestrator.model.ApplicationApi; @@ -59,7 +61,7 @@ import static org.mockito.Mockito.when; * @author hakonhall */ public class HostResourceTest { - + private static final Timer timer = mock(Timer.class); private static final int SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS = 0; private static final TenantId TENANT_ID = new TenantId("tenantId"); private static final ApplicationInstanceId APPLICATION_INSTANCE_ID = new ApplicationInstanceId("applicationId"); @@ -110,28 +112,20 @@ public class HostResourceTest { private static class AlwaysAllowPolicy implements Policy { @Override - public void grantSuspensionRequest( - ApplicationInstance applicationInstance, - HostName hostName, - MutableStatusRegistry hostStatusService) { - - } - - @Override - public void grantSuspensionRequest(ApplicationApi applicationApi) { + public void grantSuspensionRequest(OrchestratorContext context, ApplicationApi applicationApi) { } @Override - public void releaseSuspensionGrant(ApplicationApi application) { + public void releaseSuspensionGrant(OrchestratorContext context, ApplicationApi application) { } @Override - public void acquirePermissionToRemove(ApplicationApi applicationApi) { + public void acquirePermissionToRemove(OrchestratorContext context, ApplicationApi applicationApi) { } @Override public void releaseSuspensionGrant( - ApplicationInstance applicationInstance, + OrchestratorContext context, ApplicationInstance applicationInstance, HostName hostName, MutableStatusRegistry hostStatusRegistry) { } @@ -141,14 +135,16 @@ public class HostResourceTest { new AlwaysAllowPolicy(), new ClusterControllerClientFactoryMock(), EVERY_HOST_IS_UP_HOST_STATUS_SERVICE, mockInstanceLookupService, - SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS + SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS, + timer ); private static final OrchestratorImpl hostNotFoundOrchestrator = new OrchestratorImpl( new AlwaysAllowPolicy(), new ClusterControllerClientFactoryMock(), EVERY_HOST_IS_UP_HOST_STATUS_SERVICE, alwaysEmptyInstanceLookUpService, - SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS + SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS, + timer ); private final UriInfo uriInfo = mock(UriInfo.class); @@ -209,31 +205,23 @@ public class HostResourceTest { private static class AlwaysFailPolicy implements Policy { @Override - public void grantSuspensionRequest( - ApplicationInstance applicationInstance, - HostName hostName, - MutableStatusRegistry hostStatusRegistry) throws HostStateChangeDeniedException { - doThrow(); - } - - @Override - public void grantSuspensionRequest(ApplicationApi applicationApi) throws HostStateChangeDeniedException { + public void grantSuspensionRequest(OrchestratorContext context, ApplicationApi applicationApi) throws HostStateChangeDeniedException { doThrow(); } @Override - public void releaseSuspensionGrant(ApplicationApi application) throws HostStateChangeDeniedException { + public void releaseSuspensionGrant(OrchestratorContext context, ApplicationApi application) throws HostStateChangeDeniedException { doThrow(); } @Override - public void acquirePermissionToRemove(ApplicationApi applicationApi) throws HostStateChangeDeniedException { + public void acquirePermissionToRemove(OrchestratorContext context, ApplicationApi applicationApi) throws HostStateChangeDeniedException { doThrow(); } @Override public void releaseSuspensionGrant( - ApplicationInstance applicationInstance, + OrchestratorContext context, ApplicationInstance applicationInstance, HostName hostName, MutableStatusRegistry hostStatusRegistry) throws HostStateChangeDeniedException { doThrow(); @@ -253,7 +241,8 @@ public class HostResourceTest { new AlwaysFailPolicy(), new ClusterControllerClientFactoryMock(), EVERY_HOST_IS_UP_HOST_STATUS_SERVICE,mockInstanceLookupService, - SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS); + SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS, + timer); try { HostResource hostResource = new HostResource(alwaysRejectResolver, uriInfo); @@ -271,7 +260,8 @@ public class HostResourceTest { new ClusterControllerClientFactoryMock(), EVERY_HOST_IS_UP_HOST_STATUS_SERVICE, mockInstanceLookupService, - SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS); + SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS, + timer); try { HostSuspensionResource hostSuspensionResource = new HostSuspensionResource(alwaysRejectResolver); |