summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java6
-rw-r--r--config-proxy/pom.xml5
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java20
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/BuildService.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java19
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java37
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/concurrent/Once.java46
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java1
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgrader.java8
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java13
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/LogSerializer.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/concurrent/OnceTest.java25
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/logs.json8
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerStatsImpl.java7
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/Environment.java70
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerNetworking.java15
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java14
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java1
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/logging/FilebeatConfigProviderTest.java2
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainerTest.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/util/EnvironmentTest.java4
-rw-r--r--vespalib/src/tests/alloc/alloc_test.cpp2
24 files changed, 222 insertions, 103 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
index 095b27a0904..291a2824e46 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
@@ -6,6 +6,7 @@ import com.yahoo.config.model.api.ConfigServerSpec;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.SystemName;
+import com.yahoo.container.handler.LogHandler;
import com.yahoo.log.LogLevel;
import com.yahoo.searchdefinition.derived.RankProfileList;
import com.yahoo.vespa.model.HostResource;
@@ -110,10 +111,9 @@ public class DomAdminV4Builder extends DomAdminBuilderBase {
admin.addAndInitializeService(hostResource, container);
}
- // TODO: Wire in handler for getting logs
private void addLogHandler(ContainerCluster cluster) {
- Handler<?> logHandler = Handler.fromClassName("TODO");
- //logHandler.addServerBindings("http://*/logs/", "https://*/logs/");
+ Handler<?> logHandler = Handler.fromClassName("com.yahoo.container.handler.LogHandler");
+ logHandler.addServerBindings("http://*/logs/", "https://*/logs/");
cluster.addComponent(logHandler);
}
diff --git a/config-proxy/pom.xml b/config-proxy/pom.xml
index a266f68efe2..0985eeca6cf 100644
--- a/config-proxy/pom.xml
+++ b/config-proxy/pom.xml
@@ -63,6 +63,11 @@
<artifactId>filedistribution</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index bcb51f335a3..6a55fb77933 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -53,7 +53,6 @@ import com.yahoo.vespa.config.server.session.SilentDeployLogger;
import com.yahoo.vespa.config.server.tenant.Rotations;
import com.yahoo.vespa.config.server.tenant.Tenant;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
-import com.yahoo.vespa.model.VespaModel;
import java.io.File;
import java.io.IOException;
@@ -485,7 +484,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
// ---------------- Logs ----------------------------------------------------------------
public HttpResponse getLogs(ApplicationId applicationId) {
- String logServerHostName = getLogServerHostname(applicationId);
+ String logServerHostName = getLogServerURI(applicationId);
LogRetriever logRetriever = new LogRetriever();
return logRetriever.getLogs(logServerHostName);
}
@@ -703,27 +702,28 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
}
}
- private String getLogServerHostname(ApplicationId applicationId) {
+ private String getLogServerURI(ApplicationId applicationId) {
Application application = getApplication(applicationId);
- VespaModel model = (VespaModel) application.getModel();
- String logServerHostname = model.getAdmin().getLogserver().getHostName();
Collection<HostInfo> hostInfos = application.getModel().getHosts();
HostInfo logServerHostInfo = hostInfos.stream()
- .filter(host -> host.getHostname().equals(logServerHostname))
- .findFirst().orElseThrow(() -> new IllegalArgumentException("Could not find HostInfo"));
+ .filter(host -> host.getServices().stream()
+ .filter(serviceInfo ->
+ serviceInfo.getServiceType().equalsIgnoreCase("logserver"))
+ .count() > 0)
+ .findFirst().orElseThrow(() -> new IllegalArgumentException("Could not find HostInfo for LogServer"));
- ServiceInfo serviceInfo = logServerHostInfo.getServices().stream()
+ ServiceInfo containerServiceInfo = logServerHostInfo.getServices().stream()
.filter(service -> service.getServiceType().equals("container"))
.findFirst().orElseThrow(() -> new IllegalArgumentException("No container running on logserver host"));
- int port = serviceInfo.getPorts().stream()
+ int port = containerServiceInfo.getPorts().stream()
.filter(portInfo -> portInfo.getTags().stream()
.filter(tag -> tag.equalsIgnoreCase("http")).count() > 0)
.findFirst().orElseThrow(() -> new IllegalArgumentException("Could not find HTTP port"))
.getPort();
- return logServerHostname + ":" + port + "/logs";
+ return "http://" + logServerHostInfo.getHostname() + ":" + port + "/logs";
}
/** Returns version to use when deploying application in given environment */
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/BuildService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/BuildService.java
index 56c2ee8da6b..d0edbdcb8a6 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/BuildService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/BuildService.java
@@ -37,8 +37,6 @@ public interface BuildService {
}
- // TODO jvenstad: Argh, refactor this, considering the new JobId, etc..
- // TODO jvenstad: Probably: make jobName JobType instead.
class BuildJob {
private final ApplicationId applicationId;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index a3a4e99c38d..af5b9198343 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -43,6 +43,7 @@ import com.yahoo.vespa.hosted.controller.application.JobList;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
import com.yahoo.vespa.hosted.controller.application.JobStatus.JobRun;
import com.yahoo.vespa.hosted.controller.application.SystemApplication;
+import com.yahoo.vespa.hosted.controller.concurrent.Once;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentTrigger;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import com.yahoo.vespa.hosted.controller.rotation.Rotation;
@@ -117,13 +118,17 @@ public class ApplicationController {
this.rotationRepository = new RotationRepository(rotationsConfig, this, curator);
this.deploymentTrigger = new DeploymentTrigger(controller, buildService, clock);
- Instant start = clock.instant();
- int count = 0;
- for (Application application : curator.readApplications()) {
- lockIfPresent(application.id(), this::store);
- count++;
- }
- log.log(Level.INFO, String.format("Wrote %d applications in %s", count, Duration.between(start, clock.instant())));
+ // Update serialization format of all applications
+ Once.after(Duration.ofMinutes(1), () -> {
+ Instant start = clock.instant();
+ int count = 0;
+ for (Application application : curator.readApplications()) {
+ lockIfPresent(application.id(), this::store);
+ count++;
+ }
+ log.log(Level.INFO, String.format("Wrote %d applications in %s", count,
+ Duration.between(start, clock.instant())));
+ });
}
/** Returns the application with the given id, or null if it is not present */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java
index 21db5c0b68f..1ae3e6a6577 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java
@@ -10,6 +10,7 @@ import com.yahoo.vespa.curator.Lock;
import com.yahoo.vespa.hosted.controller.api.identifiers.UserId;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.AthenzClientFactory;
import com.yahoo.vespa.hosted.controller.api.integration.athenz.ZmsClient;
+import com.yahoo.vespa.hosted.controller.concurrent.Once;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant;
import com.yahoo.vespa.hosted.controller.tenant.Tenant;
@@ -47,22 +48,30 @@ public class TenantController {
this.curator = Objects.requireNonNull(curator, "curator must be non-null");
this.athenzClientFactory = Objects.requireNonNull(athenzClientFactory, "athenzClientFactory must be non-null");
- // Write all tenants to ensure persisted data uses latest serialization format
- Instant start = controller.clock().instant();
- int count = 0;
- for (Tenant tenant : curator.readTenants()) {
- try (Lock lock = lock(tenant.name())) {
- if (tenant instanceof AthenzTenant) {
- curator.writeTenant((AthenzTenant) tenant);
- } else if (tenant instanceof UserTenant) {
- curator.writeTenant((UserTenant) tenant);
- } else {
- throw new IllegalArgumentException("Unknown tenant type: " + tenant.getClass().getSimpleName());
+ // Update serialization format of all tenants
+ Once.after(Duration.ofMinutes(1), () -> {
+ Instant start = controller.clock().instant();
+ int count = 0;
+ for (TenantName name : curator.readTenantNames()) {
+ try (Lock lock = lock(name)) {
+ // Get while holding lock so that we know we're operating on a current version
+ Optional<Tenant> optionalTenant = tenant(name);
+ if (!optionalTenant.isPresent()) continue; // Deleted while updating, skip
+
+ Tenant tenant = optionalTenant.get();
+ if (tenant instanceof AthenzTenant) {
+ curator.writeTenant((AthenzTenant) tenant);
+ } else if (tenant instanceof UserTenant) {
+ curator.writeTenant((UserTenant) tenant);
+ } else {
+ throw new IllegalArgumentException("Unknown tenant type: " + tenant.getClass().getSimpleName());
+ }
}
+ count++;
}
- count++;
- }
- log.log(Level.INFO, String.format("Wrote %d tenants in %s", count, Duration.between(start, controller.clock().instant())));
+ log.log(Level.INFO, String.format("Wrote %d tenants in %s", count,
+ Duration.between(start, controller.clock().instant())));
+ });
}
/** Returns a list of all known tenants sorted by name */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/concurrent/Once.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/concurrent/Once.java
new file mode 100644
index 00000000000..81ddd8d2d70
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/concurrent/Once.java
@@ -0,0 +1,46 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.concurrent;
+
+import java.time.Duration;
+import java.util.Objects;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Execute a runnable exactly once in a background thread.
+ *
+ * @author mpolden
+ */
+public class Once extends TimerTask {
+
+ private static final Logger log = Logger.getLogger(Once.class.getName());
+
+ private final Runnable runnable;
+ private final Timer timer = new Timer(true);
+
+ // private to avoid exposing run method
+ private Once(Runnable runnable, Duration delay) {
+ this.runnable = Objects.requireNonNull(runnable, "runnable must be non-null");
+ Objects.requireNonNull(delay, "delay must be non-null");
+ timer.schedule(this, delay.toMillis());
+ }
+
+ /** Execute runnable after given delay */
+ public static void after(Duration delay, Runnable runnable) {
+ new Once(runnable, delay);
+ }
+
+ @Override
+ public void run() {
+ try {
+ runnable.run();
+ } catch (Throwable t) {
+ log.log(Level.WARNING, "Task '" + runnable + "' failed", t);
+ } finally {
+ timer.cancel();
+ }
+ }
+
+}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java
index 0cad9e98d5d..f7794747db9 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobProfile.java
@@ -15,7 +15,6 @@ import static com.yahoo.vespa.hosted.controller.deployment.Step.*;
*/
public enum JobProfile {
- // TODO jvenstad: runTests is not a run-always step, as it really means: check if tests are done, and store whatever is ready.
systemTest(EnumSet.of(deployReal,
installReal,
deployTester,
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgrader.java
index bf9fbeb26d3..a83c9cdf06f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgrader.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/OsUpgrader.java
@@ -46,8 +46,10 @@ public class OsUpgrader extends InfrastructureUpgrader {
@Override
protected void upgrade(Version target, SystemApplication application, ZoneId zone) {
+ if (wantedVersion(zone, application, target).equals(target)) {
+ return;
+ }
log.info(String.format("Upgrading OS of %s to version %s in %s", application.id(), target, zone));
- // Node repository ensures the upgrade call is idempotent
application.nodeTypesWithUpgradableOs().forEach(nodeType -> controller().configServer().nodeRepository()
.upgradeOs(zone, nodeType, target));
}
@@ -75,6 +77,10 @@ public class OsUpgrader extends InfrastructureUpgrader {
return minVersion(zone, application, Node::currentOsVersion).orElse(defaultVersion);
}
+ private Version wantedVersion(ZoneId zone, SystemApplication application, Version defaultVersion) {
+ return minVersion(zone, application, Node::wantedOsVersion).orElse(defaultVersion);
+ }
+
/** Returns whether node in application should be upgraded by this */
public static boolean eligibleForUpgrade(Node node, SystemApplication application) {
return upgradableNodeStates.contains(node.state()) &&
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
index e117592d608..0d8ea8d2537 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
@@ -302,12 +302,17 @@ public class CuratorDb {
}
public List<Tenant> readTenants() {
+ return readTenantNames().stream()
+ .map(this::readTenant)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
+ }
+
+ public List<TenantName> readTenantNames() {
return curator.getChildren(tenantRoot).stream()
.map(TenantName::from)
- .map(this::readTenant)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .collect(collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
+ .collect(Collectors.toList());
}
public void removeTenant(TenantName name) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/LogSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/LogSerializer.java
index 457ef761c0f..17b4a42fb91 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/LogSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/LogSerializer.java
@@ -27,7 +27,6 @@ import java.util.stream.Collectors;
class LogSerializer {
private static final String idField = "id";
- private static final String levelField = "level";
private static final String typeField = "type";
private static final String timestampField = "at";
private static final String messageField = "message";
@@ -54,7 +53,6 @@ class LogSerializer {
private void toSlime(LogEntry entry, Cursor entryObject) {
entryObject.setLong(idField, entry.id());
entryObject.setLong(timestampField, entry.at());
- entryObject.setString(levelField, valueOf(entry.type())); // TODO jvenstad: Remove after one deployment.
entryObject.setString(typeField, valueOf(entry.type()));
entryObject.setString(messageField, entry.message());
}
@@ -87,9 +85,7 @@ class LogSerializer {
private LogEntry fromSlime(Inspector entryObject) {
return new LogEntry(entryObject.field(idField).asLong(),
entryObject.field(timestampField).asLong(),
- entryObject.field(typeField).valid() // TODO jvenstad: Remove after one deployment.
- ? typeOf(entryObject.field(typeField).asString())
- : typeOf(entryObject.field(levelField).asString()),
+ typeOf(entryObject.field(typeField).asString()),
entryObject.field(messageField).asString());
}
@@ -105,7 +101,7 @@ class LogSerializer {
}
static Type typeOf(String type) {
- switch (type.toLowerCase()) { // TODO jvenstad: Remove lowercasing after this has been deployed.
+ switch (type) {
case "debug": return Type.debug;
case "info": return Type.info;
case "warning": return Type.warning;
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/concurrent/OnceTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/concurrent/OnceTest.java
new file mode 100644
index 00000000000..e11fdcba7c6
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/concurrent/OnceTest.java
@@ -0,0 +1,25 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.concurrent;
+
+import org.junit.Test;
+
+import java.time.Duration;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author mpolden
+ */
+public class OnceTest {
+
+ @Test(timeout = 60_000)
+ public void test_run() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ Once.after(Duration.ZERO, latch::countDown);
+
+ assertTrue(latch.await(30, TimeUnit.SECONDS));
+ }
+
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/logs.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/logs.json
index a6a092109a1..ce9bd2139c7 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/logs.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/logs.json
@@ -3,13 +3,13 @@
[
{
"id": 0,
- "level": "info",
+ "type": "info",
"at": 0,
"message": "First"
},
{
"id": 2,
- "level": "debug",
+ "type": "debug",
"at": 1000,
"message": "Third"
}
@@ -18,13 +18,13 @@
[
{
"id": 1,
- "level": "info",
+ "type": "info",
"at": 0,
"message": "Second"
},
{
"id": 3,
- "level": "warning",
+ "type": "warning",
"at": 2000,
"message": "Fourth"
}
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerStatsImpl.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerStatsImpl.java
index f0419a36d46..a56c1e41a51 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerStatsImpl.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerStatsImpl.java
@@ -1,12 +1,14 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.dockerapi;
+import java.util.Collections;
import java.util.Map;
+import java.util.Optional;
/**
* Wrapper class for {@link com.github.dockerjava.api.model.Statistics} to prevent leaking from docker-java library.
*
- * @author valerijf
+ * @author freva
*/
public class ContainerStatsImpl implements Docker.ContainerStats {
private final Map<String, Object> networks;
@@ -16,7 +18,8 @@ public class ContainerStatsImpl implements Docker.ContainerStats {
public ContainerStatsImpl(Map<String, Object> networks, Map<String, Object> cpuStats,
Map<String, Object> memoryStats, Map<String, Object> blkioStats) {
- this.networks = networks;
+ // Network stats are null when container uses host network
+ this.networks = Optional.ofNullable(networks).orElse(Collections.emptyMap());
this.cpuStats = cpuStats;
this.memoryStats = memoryStats;
this.blkioStats = blkioStats;
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/Environment.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/Environment.java
index f0c0a9c31d3..dc0ac0df05d 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/Environment.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/Environment.java
@@ -15,16 +15,14 @@ import com.yahoo.vespa.hosted.node.admin.task.util.network.IPAddressesImpl;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import java.util.TimeZone;
/**
* Various utilities for getting values from node-admin's environment. Immutable.
@@ -33,7 +31,8 @@ import java.util.TimeZone;
* @author hmusum
*/
public class Environment {
- private static final DateFormat filenameFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
+ private static final DateTimeFormatter filenameFormatter = DateTimeFormatter
+ .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS").withZone(ZoneOffset.UTC);
public static final String APPLICATION_STORAGE_CLEANUP_PATH_PREFIX = "cleanup_";
private static final String ENVIRONMENT = "ENVIRONMENT";
@@ -52,13 +51,13 @@ public class Environment {
private final String environment;
private final String region;
private final String system;
+ private final String cloud;
private final String parentHostHostname;
private final IPAddresses ipAddresses;
private final PathResolver pathResolver;
private final List<String> logstashNodes;
private final Optional<String> coredumpFeedEndpoint;
private final NodeType nodeType;
- private final String cloud;
private final ContainerEnvironmentResolver containerEnvironmentResolver;
private final String certificateDnsSuffix;
private final URI ztsUri;
@@ -66,10 +65,7 @@ public class Environment {
private final boolean nodeAgentCertEnabled;
private final boolean isRunningOnHost;
private final Path trustStorePath;
-
- static {
- filenameFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
+ private final DockerNetworking dockerNetworking;
public Environment(ConfigServerConfig configServerConfig) {
this(configServerConfig,
@@ -77,19 +73,20 @@ public class Environment {
getEnvironmentVariable(ENVIRONMENT),
getEnvironmentVariable(REGION),
getEnvironmentVariable(SYSTEM),
+ getEnvironmentVariable(CLOUD),
Defaults.getDefaults().vespaHostname(),
new IPAddressesImpl(),
new PathResolver(),
getLogstashNodesFromEnvironment(),
Optional.of(getEnvironmentVariable(COREDUMP_FEED_ENDPOINT)),
NodeType.host,
- getEnvironmentVariable(CLOUD),
new DefaultContainerEnvironmentResolver(),
getEnvironmentVariable(CERTIFICATE_DNS_SUFFIX),
URI.create(getEnvironmentVariable(ZTS_URI)),
(AthenzService)AthenzIdentities.from(getEnvironmentVariable(NODE_ATHENZ_IDENTITY)),
Boolean.valueOf(getEnvironmentVariable(ENABLE_NODE_AGENT_CERT)),
- false);
+ false,
+ DockerNetworking.MACVLAN);
}
private Environment(ConfigServerConfig configServerConfig,
@@ -97,36 +94,33 @@ public class Environment {
String environment,
String region,
String system,
+ String cloud,
String parentHostHostname,
IPAddresses ipAddresses,
PathResolver pathResolver,
List<String> logstashNodes,
Optional<String> coreDumpFeedEndpoint,
NodeType nodeType,
- String cloud,
ContainerEnvironmentResolver containerEnvironmentResolver,
String certificateDnsSuffix,
URI ztsUri,
AthenzService nodeAthenzIdentity,
boolean nodeAgentCertEnabled,
- boolean isRunningOnHost) {
+ boolean isRunningOnHost,
+ DockerNetworking dockerNetworking) {
Objects.requireNonNull(configServerConfig, "configServerConfig cannot be null");
- Objects.requireNonNull(environment, "environment cannot be null");
- Objects.requireNonNull(region, "region cannot be null");
- Objects.requireNonNull(system, "system cannot be null");
- Objects.requireNonNull(cloud, "cloud cannot be null");
this.configServerInfo = new ConfigServerInfo(configServerConfig);
- this.environment = environment;
- this.region = region;
- this.system = system;
+ this.environment = Objects.requireNonNull(environment, "environment cannot be null");;
+ this.region = Objects.requireNonNull(region, "region cannot be null");;
+ this.system = Objects.requireNonNull(system, "system cannot be null");;
+ this.cloud = Objects.requireNonNull(cloud, "cloud cannot be null");
this.parentHostHostname = parentHostHostname;
this.ipAddresses = ipAddresses;
this.pathResolver = pathResolver;
this.logstashNodes = logstashNodes;
this.coredumpFeedEndpoint = coreDumpFeedEndpoint;
this.nodeType = nodeType;
- this.cloud = cloud;
this.containerEnvironmentResolver = containerEnvironmentResolver;
this.certificateDnsSuffix = certificateDnsSuffix;
this.ztsUri = ztsUri;
@@ -134,6 +128,7 @@ public class Environment {
this.nodeAgentCertEnabled = nodeAgentCertEnabled;
this.isRunningOnHost = isRunningOnHost;
this.trustStorePath = trustStorePath;
+ this.dockerNetworking = Objects.requireNonNull(dockerNetworking, "dockerNetworking cannot be null");
}
public List<String> getConfigServerHostNames() { return configServerInfo.getConfigServerHostNames(); }
@@ -148,6 +143,8 @@ public class Environment {
return system;
}
+ public String getCloud() { return cloud; }
+
public String getParentHostHostname() {
return parentHostHostname;
}
@@ -197,7 +194,7 @@ public class Environment {
public Path pathInNodeAdminToNodeCleanup(ContainerName containerName) {
return pathResolver.getApplicationStoragePathForNodeAdmin()
.resolve(APPLICATION_STORAGE_CLEANUP_PATH_PREFIX + containerName.asString() +
- "_" + filenameFormatter.format(Date.from(Instant.now())));
+ "_" + filenameFormatter.format(Instant.now()));
}
/**
@@ -243,8 +240,6 @@ public class Environment {
public NodeType getNodeType() { return nodeType; }
- public String getCloud() { return cloud; }
-
public ContainerEnvironmentResolver getContainerEnvironmentResolver() {
return containerEnvironmentResolver;
}
@@ -282,7 +277,7 @@ public class Environment {
}
public DockerNetworking getDockerNetworking() {
- return DockerNetworking.from(cloud, nodeType, isRunningOnHost);
+ return dockerNetworking;
}
public static class Builder {
@@ -290,13 +285,13 @@ public class Environment {
private String environment;
private String region;
private String system;
+ private String cloud;
private String parentHostHostname;
private IPAddresses ipAddresses;
private PathResolver pathResolver;
private List<String> logstashNodes = Collections.emptyList();
private Optional<String> coredumpFeedEndpoint = Optional.empty();
private NodeType nodeType = NodeType.tenant;
- private String cloud;
private ContainerEnvironmentResolver containerEnvironmentResolver;
private String certificateDnsSuffix;
private URI ztsUri;
@@ -304,6 +299,7 @@ public class Environment {
private boolean nodeAgentCertEnabled;
private boolean isRunningOnHost;
private Path trustStorePath;
+ private DockerNetworking dockerNetworking;
public Builder configServerConfig(ConfigServerConfig configServerConfig) {
this.configServerConfig = configServerConfig;
@@ -325,6 +321,11 @@ public class Environment {
return this;
}
+ public Builder cloud(String cloud) {
+ this.cloud = cloud;
+ return this;
+ }
+
public Builder parentHostHostname(String parentHostHostname) {
this.parentHostHostname = parentHostHostname;
return this;
@@ -360,11 +361,6 @@ public class Environment {
return this;
}
- public Builder cloud(String cloud) {
- this.cloud = cloud;
- return this;
- }
-
public Builder certificateDnsSuffix(String certificateDnsSuffix) {
this.certificateDnsSuffix = certificateDnsSuffix;
return this;
@@ -395,25 +391,31 @@ public class Environment {
return this;
}
+ public Builder dockerNetworking(DockerNetworking dockerNetworking) {
+ this.dockerNetworking = dockerNetworking;
+ return this;
+ }
+
public Environment build() {
return new Environment(configServerConfig,
trustStorePath,
environment,
region,
system,
+ cloud,
parentHostHostname,
Optional.ofNullable(ipAddresses).orElseGet(IPAddressesImpl::new),
Optional.ofNullable(pathResolver).orElseGet(PathResolver::new),
logstashNodes,
coredumpFeedEndpoint,
nodeType,
- cloud,
Optional.ofNullable(containerEnvironmentResolver).orElseGet(DefaultContainerEnvironmentResolver::new),
certificateDnsSuffix,
ztsUri,
nodeAthenzIdentity,
nodeAgentCertEnabled,
- isRunningOnHost);
+ isRunningOnHost,
+ Optional.ofNullable(dockerNetworking).orElseGet(() -> DockerNetworking.from(cloud, nodeType, isRunningOnHost)));
}
}
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerNetworking.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerNetworking.java
index 60146a4fbb7..7678ad8169a 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerNetworking.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerNetworking.java
@@ -10,13 +10,22 @@ import com.yahoo.config.provision.NodeType;
*/
public enum DockerNetworking {
/** Each container has an associated macvlan bridge. */
- MACVLAN,
+ MACVLAN("vespa-macvlan"),
/** Network Prefix-Translated networking. */
- NPT,
+ NPT("vespa-bridge"),
/** A host running a single container in the host network namespace. */
- HOST_NETWORK;
+ HOST_NETWORK("host");
+
+ private final String dockerNetworkMode;
+ DockerNetworking(String dockerNetworkMode) {
+ this.dockerNetworkMode = dockerNetworkMode;
+ }
+
+ public String getDockerNetworkMode() {
+ return dockerNetworkMode;
+ }
public static DockerNetworking from(String cloud, NodeType nodeType, boolean hostAdmin) {
if (cloud.equals("AWS")) {
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java
index 47729ebb416..a197eafe923 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java
@@ -10,7 +10,6 @@ import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import com.yahoo.vespa.hosted.dockerapi.ContainerResources;
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.dockerapi.DockerNetworkCreator;
import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
@@ -45,8 +44,7 @@ public class DockerOperationsImpl implements DockerOperations {
private static final String IPV6_NPT_PREFIX = "fd00::";
private static final String IPV4_NPT_PREFIX = "172.17.0.0";
- private static final String DOCKER_CUSTOM_BRIDGE_NETWORK_NAME = "vespa-bridge";
-
+
private final Docker docker;
private final Environment environment;
private final ProcessExecuter processExecuter;
@@ -107,11 +105,13 @@ public class DockerOperationsImpl implements DockerOperations {
}
}
- if (environment.getDockerNetworking() == DockerNetworking.MACVLAN) {
+ DockerNetworking networking = environment.getDockerNetworking();
+ command.withNetworkMode(networking.getDockerNetworkMode());
+
+ if (networking == DockerNetworking.MACVLAN) { // TODO: Remove this if when migration to host-admin is complete
command.withIpAddress(ipV6Address);
- command.withNetworkMode(DockerImpl.DOCKER_CUSTOM_MACVLAN_NETWORK_NAME);
command.withSharedVolume("/etc/hosts", "/etc/hosts");
- } else {
+ } else if (networking == DockerNetworking.NPT) {
InetAddress ipV6Prefix = InetAddresses.forString(IPV6_NPT_PREFIX);
InetAddress ipV6Local = IPAddresses.prefixTranslate(ipV6Address, ipV6Prefix, 8);
command.withIpAddress(ipV6Local);
@@ -125,8 +125,6 @@ public class DockerOperationsImpl implements DockerOperations {
ipV4Local.ifPresent(command::withIpAddress);
addEtcHosts(containerData, node.getHostname(), ipV4Local, ipV6Local);
-
- command.withNetworkMode(DOCKER_CUSTOM_BRIDGE_NETWORK_NAME);
}
for (Path pathInNode : directoriesToMount.keySet()) {
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java
index e2db75eb6fb..fa94a7ff819 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java
@@ -39,6 +39,7 @@ public class DockerOperationsImplTest {
.environment("prod")
.system("main")
.cloud("mycloud")
+ .dockerNetworking(DockerNetworking.HOST_NETWORK)
.build();
private final Docker docker = mock(Docker.class);
private final ProcessExecuter processExecuter = mock(ProcessExecuter.class);
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java
index d0e4377ffc5..15bb2825738 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java
@@ -10,6 +10,7 @@ import com.yahoo.vespa.hosted.dockerapi.Docker;
import com.yahoo.vespa.hosted.dockerapi.metrics.MetricReceiverWrapper;
import com.yahoo.vespa.hosted.node.admin.configserver.noderepository.NodeSpec;
import com.yahoo.vespa.hosted.node.admin.config.ConfigServerConfig;
+import com.yahoo.vespa.hosted.node.admin.docker.DockerNetworking;
import com.yahoo.vespa.hosted.node.admin.docker.DockerOperations;
import com.yahoo.vespa.hosted.node.admin.docker.DockerOperationsImpl;
import com.yahoo.vespa.hosted.node.admin.maintenance.acl.AclMaintainer;
@@ -69,8 +70,9 @@ public class DockerTester implements AutoCloseable {
.region("us-east-1")
.environment("prod")
.system("main")
- .pathResolver(new PathResolver(PATH_TO_VESPA_HOME, Paths.get("/tmp"), Paths.get("/tmp")))
.cloud("mycloud")
+ .pathResolver(new PathResolver(PATH_TO_VESPA_HOME, Paths.get("/tmp"), Paths.get("/tmp")))
+ .dockerNetworking(DockerNetworking.HOST_NETWORK)
.build();
NodeSpec hostSpec = new NodeSpec.Builder()
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/logging/FilebeatConfigProviderTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/logging/FilebeatConfigProviderTest.java
index 77c0a30ae18..f418552553e 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/logging/FilebeatConfigProviderTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/logging/FilebeatConfigProviderTest.java
@@ -6,6 +6,7 @@ import com.yahoo.config.provision.NodeType;
import com.yahoo.vespa.hosted.node.admin.configserver.noderepository.NodeSpec;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
import com.yahoo.vespa.hosted.node.admin.config.ConfigServerConfig;
+import com.yahoo.vespa.hosted.node.admin.docker.DockerNetworking;
import com.yahoo.vespa.hosted.provision.Node;
import org.junit.Test;
@@ -104,6 +105,7 @@ public class FilebeatConfigProviderTest {
.system(system)
.logstashNodes(logstashNodes)
.cloud("mycloud")
+ .dockerNetworking(DockerNetworking.HOST_NETWORK)
.build();
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainerTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainerTest.java
index 627517b824e..d9cce7f80a0 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainerTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/StorageMaintainerTest.java
@@ -10,6 +10,7 @@ import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import com.yahoo.vespa.hosted.dockerapi.metrics.MetricReceiverWrapper;
import com.yahoo.vespa.hosted.node.admin.configserver.noderepository.NodeSpec;
import com.yahoo.vespa.hosted.node.admin.config.ConfigServerConfig;
+import com.yahoo.vespa.hosted.node.admin.docker.DockerNetworking;
import com.yahoo.vespa.hosted.node.admin.docker.DockerOperations;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
import com.yahoo.vespa.hosted.node.admin.component.PathResolver;
@@ -41,8 +42,9 @@ public class StorageMaintainerTest {
.region("us-east-1")
.environment("prod")
.system("main")
- .pathResolver(new PathResolver())
.cloud("mycloud")
+ .pathResolver(new PathResolver())
+ .dockerNetworking(DockerNetworking.HOST_NETWORK)
.coredumpFeedEndpoint("http://domain.tld/docid")
.build();
private final DockerOperations docker = mock(DockerOperations.class);
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
index f5d4dcf4e5e..ebed20326a3 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
@@ -16,6 +16,7 @@ import com.yahoo.vespa.hosted.dockerapi.metrics.MetricReceiverWrapper;
import com.yahoo.vespa.hosted.node.admin.configserver.noderepository.NodeSpec;
import com.yahoo.vespa.hosted.node.admin.config.ConfigServerConfig;
import com.yahoo.vespa.hosted.node.admin.configserver.noderepository.NodeAttributes;
+import com.yahoo.vespa.hosted.node.admin.docker.DockerNetworking;
import com.yahoo.vespa.hosted.node.admin.docker.DockerOperations;
import com.yahoo.vespa.hosted.node.admin.maintenance.StorageMaintainer;
import com.yahoo.vespa.hosted.node.admin.maintenance.acl.AclMaintainer;
@@ -88,9 +89,10 @@ public class NodeAgentImplTest {
.environment("dev")
.region("us-east-1")
.system("main")
+ .cloud("mycloud")
.parentHostHostname("parent.host.name.yahoo.com")
.pathResolver(pathResolver)
- .cloud("mycloud")
+ .dockerNetworking(DockerNetworking.HOST_NETWORK)
.build();
private final NodeSpec.Builder nodeBuilder = new NodeSpec.Builder()
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/util/EnvironmentTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/util/EnvironmentTest.java
index a3a455605ad..893607f1806 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/util/EnvironmentTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/util/EnvironmentTest.java
@@ -6,6 +6,7 @@ import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
import com.yahoo.vespa.hosted.node.admin.component.PathResolver;
import com.yahoo.vespa.hosted.node.admin.config.ConfigServerConfig;
+import com.yahoo.vespa.hosted.node.admin.docker.DockerNetworking;
import org.junit.Test;
import java.nio.file.Path;
@@ -22,8 +23,9 @@ public class EnvironmentTest {
.region("us-east-1")
.environment("prod")
.system("main")
- .pathResolver(new PathResolver())
.cloud("mycloud")
+ .pathResolver(new PathResolver())
+ .dockerNetworking(DockerNetworking.HOST_NETWORK)
.build();
@Test
diff --git a/vespalib/src/tests/alloc/alloc_test.cpp b/vespalib/src/tests/alloc/alloc_test.cpp
index 0e52d06a2d5..dd4adfc2fa1 100644
--- a/vespalib/src/tests/alloc/alloc_test.cpp
+++ b/vespalib/src/tests/alloc/alloc_test.cpp
@@ -179,6 +179,7 @@ TEST("auto alloced mmap alloc can not be extended if no room") {
}
TEST("mmap alloc can be extended if room") {
+ Alloc dummy = Alloc::allocMMap(100);
Alloc reserved = Alloc::allocMMap(100);
Alloc buf = Alloc::allocMMap(100);
@@ -187,6 +188,7 @@ TEST("mmap alloc can be extended if room") {
}
TEST("mmap alloc can not be extended if no room") {
+ Alloc dummy = Alloc::allocMMap(100);
Alloc reserved = Alloc::allocMMap(100);
Alloc buf = Alloc::allocMMap(100);