summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java5
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java7
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperations.java7
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java16
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java12
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java4
6 files changed, 47 insertions, 4 deletions
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 8344830e229..4e7ef5a1ff6 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
@@ -81,9 +81,8 @@ public interface Docker {
*/
boolean pullImageAsyncIfNeeded(DockerImage image);
- /**
- * Deletes the local images that are currently not in use by any container and not recently used.
- */
+ boolean noManagedContainersRunning(String manager);
+
boolean deleteUnusedDockerImages(List<DockerImage> excludes, Duration minImageAgeToDelete);
/**
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 9299cedaf21..8cdb0bee7c2 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
@@ -296,6 +296,13 @@ public class DockerImpl implements Docker {
return encodedContainerName.substring(FRAMEWORK_CONTAINER_PREFIX.length());
}
+ @Override
+ public boolean noManagedContainersRunning(String manager) {
+ return listAllContainers().stream()
+ .filter(container -> isManagedBy(container, manager))
+ .noneMatch(container -> "running".equalsIgnoreCase(container.getState()));
+ }
+
List<com.github.dockerjava.api.model.Container> listAllContainers() {
try {
return dockerClient.listContainersCmd().withShowAll(true).exec();
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperations.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperations.java
index 6b3c09e812a..2a40428cad2 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperations.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperations.java
@@ -9,6 +9,8 @@ import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
import com.yahoo.vespa.hosted.node.admin.nodeagent.ContainerData;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgentContext;
+import java.time.Duration;
+import java.util.List;
import java.util.Optional;
public interface DockerOperations {
@@ -48,4 +50,9 @@ public interface DockerOperations {
void stopServices(NodeAgentContext context);
Optional<ContainerStats> getContainerStats(NodeAgentContext context);
+
+ boolean noManagedContainersRunning();
+
+ /** Deletes the local images that are currently not in use by any container and not recently used. */
+ boolean deleteUnusedDockerImages(List<DockerImage> excludes, Duration minImageAgeToDelete);
}
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 2f5d6ae60d8..954ba25895a 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
@@ -15,12 +15,14 @@ import com.yahoo.vespa.hosted.node.admin.configserver.noderepository.NodeMembers
import com.yahoo.vespa.hosted.node.admin.nodeagent.ContainerData;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgentContext;
import com.yahoo.vespa.hosted.node.admin.task.util.network.IPAddresses;
+import com.yahoo.vespa.hosted.node.admin.task.util.network.IPAddressesImpl;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -47,6 +49,10 @@ public class DockerOperationsImpl implements DockerOperations {
private final ProcessExecuter processExecuter;
private final IPAddresses ipAddresses;
+ public DockerOperationsImpl(Docker docker) {
+ this(docker, new ProcessExecuter(), new IPAddressesImpl());
+ }
+
public DockerOperationsImpl(Docker docker, ProcessExecuter processExecuter, IPAddresses ipAddresses) {
this.docker = docker;
this.processExecuter = processExecuter;
@@ -323,6 +329,16 @@ public class DockerOperationsImpl implements DockerOperations {
command.withSharedVolume(Paths.get("/var/zpe"), context.pathInNodeUnderVespaHome("var/zpe"));
}
+ @Override
+ public boolean noManagedContainersRunning() {
+ return docker.noManagedContainersRunning(MANAGER_NAME);
+ }
+
+ @Override
+ public boolean deleteUnusedDockerImages(List<DockerImage> excludes, Duration minImageAgeToDelete) {
+ return docker.deleteUnusedDockerImages(excludes, minImageAgeToDelete);
+ }
+
/** Returns whether given nodeType is a Docker host for infrastructure nodes */
private static boolean isInfrastructureHost(NodeType nodeType) {
return nodeType == NodeType.config ||
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
index 77510f7b6ef..17d8126a5c9 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.node.admin.task.util.systemd;
import com.yahoo.vespa.hosted.node.admin.component.TaskContext;
+import com.yahoo.vespa.hosted.node.admin.task.util.process.CommandResult;
import com.yahoo.vespa.hosted.node.admin.task.util.process.Terminal;
import java.util.Objects;
@@ -58,7 +59,7 @@ public class SystemCtl {
public boolean serviceExists(TaskContext context, String unit) {
return terminal.newCommandLine(context)
- .add("systemctl").add("list-unit-files").add(unit + ".service").executeSilently()
+ .add("systemctl", "list-unit-files", unit + ".service").executeSilently()
.mapOutput(output -> {
// Last line of the form: "1 unit files listed."
Matcher matcher = UNIT_FILES_LISTED_PATTERN.matcher(output);
@@ -70,6 +71,15 @@ public class SystemCtl {
});
}
+ /** Returns true if the unit exists and is active (i.e. running). unit is e.g. "docker". */
+ public boolean isActive(TaskContext context, String unit) {
+ return terminal.newCommandLine(context)
+ .add("systemctl", "--quiet", "is-active", unit + ".service")
+ .ignoreExitCode()
+ .executeSilently()
+ .map(CommandResult::getExitCode) == 0;
+ }
+
public class SystemCtlEnable extends SystemCtlCommand {
private SystemCtlEnable(String unit) {
super("enable", unit);
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 31e64dc886f..e2ad9e3de97 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
@@ -91,6 +91,10 @@ public class DockerMock implements Docker {
return new ProcessResult(0, null, "");
}
+ @Override
+ public boolean noManagedContainersRunning(String manager) {
+ return false;
+ }
public class StartContainerCommandMock implements CreateContainerCommand {