diff options
Diffstat (limited to 'node-repository')
2 files changed, 43 insertions, 3 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypter.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypter.java index 6d88e43630a..c93f226603c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypter.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypter.java @@ -2,8 +2,11 @@ package com.yahoo.vespa.hosted.provision.maintenance; import com.yahoo.component.Version; +import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.NodeType; import com.yahoo.jdisc.Metric; +import com.yahoo.vespa.flags.BooleanFlag; +import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.IntFlag; import com.yahoo.vespa.hosted.provision.Node; @@ -20,6 +23,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Logger; +import java.util.stream.Collectors; /** * This maintainer triggers encryption of hosts that have unencrypted disk. @@ -36,10 +40,12 @@ public class HostEncrypter extends NodeRepositoryMaintainer { private static final Logger LOG = Logger.getLogger(HostEncrypter.class.getName()); private final IntFlag maxEncryptingHosts; + private final BooleanFlag deferHostEncryption; public HostEncrypter(NodeRepository nodeRepository, Duration interval, Metric metric) { super(nodeRepository, interval, metric); this.maxEncryptingHosts = Flags.MAX_ENCRYPTING_HOSTS.bindTo(nodeRepository.flagSource()); + this.deferHostEncryption = Flags.DEFER_HOST_ENCRYPTION.bindTo(nodeRepository.flagSource()); } @Override @@ -48,8 +54,6 @@ public class HostEncrypter extends NodeRepositoryMaintainer { NodeList allNodes = nodeRepository().nodes().list(); for (var nodeType : NodeType.values()) { if (!nodeType.isHost()) continue; - // TODO: Require a minimum number of proxies in Orchestrator. For now skip proxy hosts. - if (nodeType == NodeType.proxyhost) continue; if (upgradingVespa(allNodes, nodeType)) continue; unencryptedHosts(allNodes, nodeType).forEach(host -> encrypt(host, now)); } @@ -81,9 +85,11 @@ public class HostEncrypter extends NodeRepositoryMaintainer { NodeList candidates = hostsOfTargetType.state(Node.State.active) .not().encrypted() .not().encrypting() + .not().matching(host -> deferEncryptionOf(host, allNodes)) // Require an OS version supporting encryption .matching(node -> node.status().osVersion().current() - .orElse(Version.emptyVersion).getMajor() >= 8); + .orElse(Version.emptyVersion) + .getMajor() >= 8); for (Node host : candidates) { if (hostsToEncrypt.size() == hostLimit) break; @@ -106,6 +112,20 @@ public class HostEncrypter extends NodeRepositoryMaintainer { return Math.max(0, limit - hosts.encrypting().size()); } + private boolean deferEncryptionOf(Node host, NodeList allNodes) { + // TODO: Require a minimum number of proxies in Orchestrator. For now skip proxy hosts. + if (host.type() == NodeType.proxyhost) return true; + + Set<ApplicationId> applicationsOnHost = allNodes.childrenOf(host).stream() + .filter(node -> node.allocation().isPresent()) + .map(node -> node.allocation().get().owner()) + .collect(Collectors.toSet()); + return applicationsOnHost.stream() + .anyMatch(application -> deferHostEncryption.with(FetchVector.Dimension.APPLICATION_ID, + application.serializedForm()) + .value()); + } + private void encrypt(Node host, Instant now) { LOG.info("Retiring and encrypting " + host); nodeRepository().nodes().encrypt(host.hostname(), Agent.HostEncrypter, now); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypterTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypterTest.java index 5cae181f87d..f55452acba8 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypterTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/HostEncrypterTest.java @@ -47,6 +47,26 @@ public class HostEncrypterTest { } @Test + public void deferred_hosts_are_not_encrypted() { + int hostCount = 2; + int proxyHostCount = 1; + ApplicationId tenantApp = ApplicationId.from("t1", "a1", "i1"); + provisionHosts(hostCount); + deployApplication(tenantApp); + + ApplicationId proxyHostApp = ApplicationId.from("t2", "a2", "i2"); + List<Node> proxyHosts = tester.makeReadyNodes(proxyHostCount, "default", NodeType.proxyhost, 10); + tester.patchNodes(proxyHosts, (host) -> host.with(host.status().withOsVersion(host.status().osVersion().withCurrent(Optional.of(Version.fromString("8.0")))))); + tester.prepareAndActivateInfraApplication(proxyHostApp, NodeType.proxyhost); + + tester.flagSource() + .withIntFlag(Flags.MAX_ENCRYPTING_HOSTS.id(), hostCount + proxyHostCount) + .withBooleanFlag(Flags.DEFER_HOST_ENCRYPTION.id(), true); + encrypter.maintain(); + assertEquals("No hosts are encrypted", 0, tester.nodeRepository().nodes().list().encrypting().size()); + } + + @Test public void encrypt_hosts() { tester.flagSource().withIntFlag(Flags.MAX_ENCRYPTING_HOSTS.id(), 3); Supplier<NodeList> hosts = () -> tester.nodeRepository().nodes().list().nodeType(NodeType.host); |