summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Musum <musum@yahoo-inc.com>2016-10-21 14:36:20 +0200
committerGitHub <noreply@github.com>2016-10-21 14:36:20 +0200
commitc202f27ac730619ca99ac5d75fd04f4942563ca0 (patch)
tree09eb830e50b8cf6616251bded3cf1fafcbb932b7
parent7b584dfeac872aef86b8a2c2c62870cd8e06d26d (diff)
parent0cddc3c658182f6ed6916d3433ed47ce798e5f1a (diff)
Merge pull request #928 from yahoo/freva/local-zone-config-server
Freva/local zone config server
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java11
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java4
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java19
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerTestUtils.java11
-rw-r--r--docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerTest.java3
-rw-r--r--node-admin/Dockerfile.template5
-rw-r--r--node-admin/include/http-server.xml1
-rwxr-xr-xnode-admin/include/start-config-server.sh21
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/LocalZoneUtils.java71
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java11
10 files changed, 121 insertions, 36 deletions
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java
index 6f9edc1e106..59d7b987093 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java
@@ -32,6 +32,7 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
private Optional<String> networkMode = Optional.empty();
private Optional<String> ipv4Address = Optional.empty();
private Optional<String> ipv6Address = Optional.empty();
+ private Optional<String[]> entrypoint = Optional.empty();
CreateContainerCommandImpl(DockerClient docker,
DockerImage dockerImage,
@@ -56,6 +57,12 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
return this;
}
+ @Override
+ public Docker.CreateContainerCommand withEntrypoint(String... entrypoint) {
+ this.entrypoint = Optional.of(entrypoint);
+ return this;
+ }
+
@Override
public Docker.CreateContainerCommand withEnvironment(String name, String value) {
@@ -119,6 +126,7 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
if (networkMode.isPresent()) containerCmd = containerCmd.withNetworkMode(networkMode.get());
if (ipv4Address.isPresent()) containerCmd = containerCmd.withIpv4Address(ipv4Address.get());
if (ipv6Address.isPresent()) containerCmd = containerCmd.withIpv6Address(ipv6Address.get());
+ if (entrypoint.isPresent()) containerCmd = containerCmd.withEntrypoint(entrypoint.get());
return containerCmd;
}
@@ -126,7 +134,7 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
/** Maps ("--env", {"A", "B", "C"}) to "--env A --env B --env C ". */
private String toRepeatedOption(String option, List<String> optionValues) {
StringBuilder builder = new StringBuilder();
- optionValues.stream().forEach(optionValue -> builder.append(option).append(" ").append(optionValue).append(" "));
+ optionValues.forEach(optionValue -> builder.append(option).append(" ").append(optionValue).append(" "));
return builder.toString();
}
@@ -153,6 +161,7 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
+ toOptionalOption("--net", networkMode)
+ toOptionalOption("--ip", ipv4Address)
+ toOptionalOption("--ip6", ipv6Address)
+ + toOptionalOption("--entrypoint", entrypoint)
+ dockerImage.asString();
}
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
index 5720b18ac57..c7ef19ccb2a 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
@@ -1,6 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.dockerapi;
+import java.io.File;
import java.net.InetAddress;
import java.util.List;
import java.util.Map;
@@ -21,6 +22,7 @@ public interface Docker {
CreateContainerCommand withNetworkMode(String mode);
CreateContainerCommand withIpAddress(InetAddress address);
CreateContainerCommand withUlimit(String name, int softLimit, int hardLimit);
+ CreateContainerCommand withEntrypoint(String... entrypoint);
void create();
}
@@ -68,6 +70,8 @@ public interface Docker {
void deleteImage(DockerImage dockerImage);
+ void buildImage(File dockerfile, DockerImage dockerImage);
+
/**
* Deletes the local images that are currently not in use by any container and not in the except set.
*/
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
index 464c79be874..80bcbeb6537 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
@@ -15,6 +15,7 @@ import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.core.RemoteApiVersion;
import com.github.dockerjava.core.async.ResultCallbackTemplate;
+import com.github.dockerjava.core.command.BuildImageResultCallback;
import com.github.dockerjava.core.command.ExecStartResultCallback;
import com.github.dockerjava.core.command.PullImageResultCallback;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
@@ -28,6 +29,7 @@ import com.yahoo.vespa.hosted.dockerapi.metrics.MetricReceiverWrapper;
import javax.annotation.concurrent.GuardedBy;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -254,11 +256,9 @@ public class DockerImpl implements Docker {
return new ContainerStatsImpl(statsCallback.stats.getNetworks(), statsCallback.stats.getCpuStats(),
statsCallback.stats.getMemoryStats(), statsCallback.stats.getBlkioStats());
- } catch (DockerException e) {
+ } catch (DockerException | InterruptedException e) {
numberOfDockerDaemonFails.add();
throw new RuntimeException("Failed to get container stats", e);
- } catch (InterruptedException e) {
- throw new RuntimeException("Failed to get container stats in time", e);
}
}
@@ -379,6 +379,17 @@ public class DockerImpl implements Docker {
}
}
+ @Override
+ public void buildImage(File dockerfile, DockerImage image) {
+ try {
+ dockerClient.buildImageCmd(dockerfile).withTag(image.asString())
+ .exec(new BuildImageResultCallback()).awaitCompletion();
+ } catch (DockerException | InterruptedException e) {
+ numberOfDockerDaemonFails.add();
+ throw new RuntimeException("Failed to build image " + image.asString(), e);
+ }
+ }
+
private Map<String, Image> filterOutImagesUsedByContainers(
Map<String, Image> dockerImagesByImageId, List<com.github.dockerjava.api.model.Container> containerList) {
Map<String, Image> filteredDockerImagesByImageId = new HashMap<>(dockerImagesByImageId);
@@ -458,7 +469,7 @@ public class DockerImpl implements Docker {
@Override
public void deleteUnusedDockerImages(Set<DockerImage> except) {
- getUnusedDockerImages(except).stream().forEach(this::deleteImage);
+ getUnusedDockerImages(except).forEach(this::deleteImage);
}
private class ImagePullCallback extends PullImageResultCallback {
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerTestUtils.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerTestUtils.java
index fadfbc2d9bd..9af564ef23a 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerTestUtils.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerTestUtils.java
@@ -2,7 +2,6 @@
package com.yahoo.vespa.hosted.dockerapi;
import com.github.dockerjava.api.model.Network;
-import com.github.dockerjava.core.command.BuildImageResultCallback;
import com.yahoo.metrics.simple.MetricReceiver;
import com.yahoo.vespa.hosted.dockerapi.metrics.MetricReceiverWrapper;
@@ -62,9 +61,9 @@ public class DockerTestUtils {
.withName(DockerImpl.DOCKER_CUSTOM_MACVLAN_NETWORK_NAME).withDriver("bridge").withIpam(ipam).exec();
}
- public static void createDockerImage(DockerImpl docker, DockerImage dockerImage) throws IOException, ExecutionException, InterruptedException {
+ public static void buildSimpleHttpServerDockerImage(DockerImpl docker, DockerImage dockerImage) throws IOException, ExecutionException, InterruptedException {
try {
- docker.deleteImage(new DockerImage(dockerImage.asString()));
+ docker.deleteImage(dockerImage);
} catch (Exception e) {
if (! e.getMessage().equals("Failed to delete docker image " + dockerImage.asString())) {
throw e;
@@ -72,10 +71,8 @@ public class DockerTestUtils {
}
// Build the image locally
- File dockerFilePath = new File("src/test/resources/simple-ipv6-server");
- docker.dockerClient
- .buildImageCmd(dockerFilePath)
- .withTag(dockerImage.asString()).exec(new BuildImageResultCallback()).awaitCompletion();
+ File dockerFileStream = new File("src/test/resources/simple-ipv6-server");
+ docker.buildImage(dockerFileStream, dockerImage);
}
private enum OS { Linux, Mac_OS_X, Unsupported }
diff --git a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerTest.java b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerTest.java
index 0ad369fb84c..a4e1b775919 100644
--- a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerTest.java
+++ b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerTest.java
@@ -159,8 +159,7 @@ public class DockerTest {
assumeTrue(DockerTestUtils.dockerDaemonIsPresent());
docker = DockerTestUtils.getDocker();
- DockerTestUtils.createDockerTestNetworkIfNeeded(docker);
- DockerTestUtils.createDockerImage(docker, dockerImage);
+ DockerTestUtils.buildSimpleHttpServerDockerImage(docker, dockerImage);
}
// Clean up any non deleted containers from previous tests
diff --git a/node-admin/Dockerfile.template b/node-admin/Dockerfile.template
index 485518cb86a..4494ac700cf 100644
--- a/node-admin/Dockerfile.template
+++ b/node-admin/Dockerfile.template
@@ -17,8 +17,8 @@ RUN yum install -y tcpdump
ADD include/root-bashrc /root/.bashrc
# Override what's in the base image with local versions:
-ADD target/node-admin-jar-with-dependencies.jar $VESPA_HOME/lib/jars/node-admin-jar-with-dependencies.jar
ADD src/main/application/services.xml $VESPA_HOME/conf/node-admin-app/services.xml
+ADD target/node-admin-jar-with-dependencies.jar $VESPA_HOME/lib/jars/node-admin-jar-with-dependencies.jar
ADD scripts/configure-container-networking.py $VESPA_HOME/libexec/vespa/node-admin/configure-container-networking.py
# For deploying sample application.
@@ -34,3 +34,6 @@ ADD include/start-services.sh /usr/local/bin/start-services.sh
# Make config-server aware of node flavor 'docker'.
ADD include/node-flavors.xml $VESPA_HOME/conf/configserver-app/node-flavors.xml
+
+# Make config-server also listen to 4080
+ADD include/http-server.xml $VESPA_HOME/conf/configserver-app/hosted-vespa/http-server.xml \ No newline at end of file
diff --git a/node-admin/include/http-server.xml b/node-admin/include/http-server.xml
new file mode 100644
index 00000000000..f77d392de97
--- /dev/null
+++ b/node-admin/include/http-server.xml
@@ -0,0 +1 @@
+<server port="4080" id="configserver-real" /> \ No newline at end of file
diff --git a/node-admin/include/start-config-server.sh b/node-admin/include/start-config-server.sh
index a84b0454db3..19d1d44cc1c 100755
--- a/node-admin/include/start-config-server.sh
+++ b/node-admin/include/start-config-server.sh
@@ -62,19 +62,6 @@ findroot
export LC_ALL=C
-function WaitUntilHostIsReachable {
- # Address may be IP or hostname.
- local address="$1"
-
- echo -n "Will wait until $address is reachable... "
- while ! ping -q -c 1 -W 3 "$address" &>/dev/null
- do
- echo "not done (will retry)"
- sleep 1
- done
- echo "Done"
-}
-
function VerifyRequiredEnvironmentVariablesAreSet {
if [ -z "$HOSTED_VESPA_REGION" ]
then
@@ -84,10 +71,6 @@ function VerifyRequiredEnvironmentVariablesAreSet {
then
Fail "Environment variable CONFIG_SERVER_HOSTNAME is not set"
fi
- if [ -z "$HOST_BRIDGE_IP" ]
- then
- Fail "Environment variable HOST_BRIDGE_IP is not set"
- fi
case "$HOSTED_VESPA_ENVIRONMENT" in
prod|test|dev|staging|perf) : ;;
@@ -116,10 +99,6 @@ function InternalMain {
# Can also set jvmargs if necessary:
# set cloudconfig_server.jvmargs=-Dvespa.freezedetector.disable=true -XX:NewRatio=1 -verbose:gc -XX:+PrintGCDateStamps -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms6g -Xmx6g
- # The network is set up asynchronously and from outside of this
- # container. Wait until it's done.
- WaitUntilHostIsReachable "$HOST_BRIDGE_IP"
-
yinst start cloudconfig_server
touch $VESPA_HOME/logs/jdisc_core/jdisc_core.log
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/LocalZoneUtils.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/LocalZoneUtils.java
new file mode 100644
index 00000000000..69681a3f72a
--- /dev/null
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/LocalZoneUtils.java
@@ -0,0 +1,71 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.node.admin.docker;
+
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.Docker;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.DockerImpl;
+import com.yahoo.vespa.hosted.node.admin.util.Environment;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * @author freva
+ */
+public class LocalZoneUtils {
+ public static final String CONFIG_SERVER_HOSTNAME = "config-server";
+ public static final DockerImage VESPA_LOCAL_IMAGE = new DockerImage("vespa-local:latest");
+
+ private static final String VESPA_HOME = "/home/y";
+ private static final String APP_HOSTNAME_PREFIX = "cnode-";
+
+ public static boolean startConfigServer(Docker docker, Environment environment) throws UnknownHostException {
+ ContainerName confingServerContainerName = new ContainerName(CONFIG_SERVER_HOSTNAME);
+ docker.createContainerCommand(VESPA_LOCAL_IMAGE, confingServerContainerName, CONFIG_SERVER_HOSTNAME)
+ .withNetworkMode(DockerImpl.DOCKER_CUSTOM_MACVLAN_NETWORK_NAME)
+ .withIpAddress(environment.getInetAddressForHost(CONFIG_SERVER_HOSTNAME))
+ .withVolume("/etc/hosts", "/etc/hosts")
+ .withEnvironment("HOSTED_VESPA_ENVIRONMENT", environment.getEnvironment())
+ .withEnvironment("HOSTED_VESPA_REGION", environment.getRegion())
+ .withEnvironment("CONFIG_SERVER_HOSTNAME", CONFIG_SERVER_HOSTNAME)
+ .withEnvironment("VESPA_HOME", VESPA_HOME)
+ .withEntrypoint("/usr/local/bin/start-config-server.sh")
+ .withUlimit("nofile", 16384, 16384)
+ .withUlimit("nproc", 409600, 409600)
+ .withUlimit("core", -1, -1)
+ .create();
+
+ docker.startContainer(confingServerContainerName);
+
+ try {
+ URL url = new URL("http://" + CONFIG_SERVER_HOSTNAME + ":4080/state/v1/health");
+ for (int i = 0; i < 10; i++) {
+ Thread.sleep(50);
+ HttpURLConnection http = (HttpURLConnection) url.openConnection();
+ if (http.getResponseCode() == 200) return true;
+ }
+ } catch (IOException | InterruptedException ignored) { }
+
+ return false;
+ }
+
+ public static void buildVespaLocalDockerImage(Docker docker, DockerImage vespaBaseImage) throws IOException {
+ Path dockerfileTemplatePath = Paths.get("Dockerfile.template");
+ Path dockerfilePath = Paths.get("Dockerfile");
+
+ String dockerfileTemplate = new String(Files.readAllBytes(dockerfileTemplatePath))
+ .replaceAll("\\$NODE_ADMIN_FROM_IMAGE", vespaBaseImage.asString())
+ .replaceAll("\\$VESPA_HOME", VESPA_HOME);
+
+ Files.write(dockerfilePath, dockerfileTemplate.getBytes());
+
+ docker.buildImage(dockerfilePath.toAbsolutePath().getParent().toFile(), VESPA_LOCAL_IMAGE);
+ }
+}
+
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
index 656b3e50a3a..8be3ec0fea0 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
@@ -7,6 +7,7 @@ import com.yahoo.vespa.hosted.dockerapi.Docker;
import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
+import java.io.File;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
@@ -139,6 +140,11 @@ public class DockerMock implements Docker {
}
@Override
+ public void buildImage(File dockerfile, DockerImage dockerImage) {
+
+ }
+
+ @Override
public void deleteUnusedDockerImages(Set<DockerImage> except) {
}
@@ -190,6 +196,11 @@ public class DockerMock implements Docker {
}
@Override
+ public CreateContainerCommand withEntrypoint(String... entrypoint) {
+ return this;
+ }
+
+ @Override
public void create() {
}