From efc1785478573a184b97576b7b38b6673bcc716f Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Wed, 3 Mar 2021 11:33:50 +0100 Subject: Simplify --- .../java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'node-repository') diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java index 72967cca98a..809d4c5db96 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java @@ -65,8 +65,7 @@ public class RetiringUpgrader implements Upgrader { ", want " + target); nodeRepository.nodes().deprovision(host, Agent.RetiringUpgrader, now); nodeRepository.nodes().upgradeOs(NodeListFilter.from(host), Optional.of(target)); - NodeType nodeType = host.type(); - nodeRepository.osVersions().writeChange((change) -> change.withRetirementAt(now, nodeType)); + nodeRepository.osVersions().writeChange((change) -> change.withRetirementAt(now, host.type())); } } -- cgit v1.2.3 From 1a775b4672953ac85bc390749ca827162c1bf993 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Thu, 4 Mar 2021 13:54:04 +0100 Subject: Improve names --- .../hosted/provision/os/DelegatingOsUpgrader.java | 60 ++++++++++++++++++ .../hosted/provision/os/DelegatingUpgrader.java | 60 ------------------ .../vespa/hosted/provision/os/OsUpgrader.java | 19 ++++++ .../vespa/hosted/provision/os/OsVersions.java | 14 ++--- .../hosted/provision/os/RetiringOsUpgrader.java | 71 ++++++++++++++++++++++ .../hosted/provision/os/RetiringUpgrader.java | 71 ---------------------- .../yahoo/vespa/hosted/provision/os/Upgrader.java | 19 ------ .../vespa/hosted/provision/os/OsVersionsTest.java | 10 +-- 8 files changed, 162 insertions(+), 162 deletions(-) create mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingOsUpgrader.java delete mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingUpgrader.java create mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java create mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringOsUpgrader.java delete mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java delete mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/Upgrader.java (limited to 'node-repository') diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingOsUpgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingOsUpgrader.java new file mode 100644 index 00000000000..65215cecbdf --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingOsUpgrader.java @@ -0,0 +1,60 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.os; + +import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.hosted.provision.Node; +import com.yahoo.vespa.hosted.provision.NodeList; +import com.yahoo.vespa.hosted.provision.NodeRepository; +import com.yahoo.vespa.hosted.provision.node.filter.NodeListFilter; + +import java.util.Objects; +import java.util.Optional; +import java.util.logging.Logger; + +/** + * An upgrader that delegates the upgrade to the node itself, triggered by changing its wanted OS version. This + * implementation limits the number of parallel upgrades to avoid overloading the orchestrator with suspension requests. + * + * Used in clouds where nodes can upgrade themselves in-place, without data loss. + * + * @author mpolden + */ +public class DelegatingOsUpgrader implements OsUpgrader { + + private static final Logger LOG = Logger.getLogger(DelegatingOsUpgrader.class.getName()); + + private final NodeRepository nodeRepository; + + /** The maximum number of nodes, within a single node type, that can upgrade in parallel. */ + private final int maxActiveUpgrades; + + public DelegatingOsUpgrader(NodeRepository nodeRepository, int maxActiveUpgrades) { + this.nodeRepository = Objects.requireNonNull(nodeRepository); + this.maxActiveUpgrades = maxActiveUpgrades; + } + + @Override + public void upgradeTo(OsVersionTarget target) { + NodeList activeNodes = nodeRepository.nodes().list().nodeType(target.nodeType()).state(Node.State.active); + int numberToUpgrade = Math.max(0, maxActiveUpgrades - activeNodes.changingOsVersionTo(target.version()).size()); + NodeList nodesToUpgrade = activeNodes.not().changingOsVersionTo(target.version()) + .osVersionIsBefore(target.version()) + .byIncreasingOsVersion() + .first(numberToUpgrade); + if (nodesToUpgrade.size() == 0) return; + LOG.info("Upgrading " + nodesToUpgrade.size() + " nodes of type " + target.nodeType() + " to OS version " + + target.version().toFullString()); + nodeRepository.nodes().upgradeOs(NodeListFilter.from(nodesToUpgrade.asList()), Optional.of(target.version())); + } + + @Override + public void disableUpgrade(NodeType type) { + NodeList nodesUpgrading = nodeRepository.nodes().list() + .nodeType(type) + .changingOsVersion(); + if (nodesUpgrading.size() == 0) return; + LOG.info("Disabling OS upgrade of all " + type + " nodes"); + nodeRepository.nodes().upgradeOs(NodeListFilter.from(nodesUpgrading.asList()), Optional.empty()); + } + +} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingUpgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingUpgrader.java deleted file mode 100644 index 5410cb06269..00000000000 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/DelegatingUpgrader.java +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.os; - -import com.yahoo.config.provision.NodeType; -import com.yahoo.vespa.hosted.provision.Node; -import com.yahoo.vespa.hosted.provision.NodeList; -import com.yahoo.vespa.hosted.provision.NodeRepository; -import com.yahoo.vespa.hosted.provision.node.filter.NodeListFilter; - -import java.util.Objects; -import java.util.Optional; -import java.util.logging.Logger; - -/** - * An upgrader that delegates the upgrade to the node itself, triggered by changing its wanted OS version. This - * implementation limits the number of parallel upgrades to avoid overloading the orchestrator with suspension requests. - * - * Used in clouds where nodes can upgrade themselves in-place, without data loss. - * - * @author mpolden - */ -public class DelegatingUpgrader implements Upgrader { - - private static final Logger LOG = Logger.getLogger(DelegatingUpgrader.class.getName()); - - private final NodeRepository nodeRepository; - - /** The maximum number of nodes, within a single node type, that can upgrade in parallel. */ - private final int maxActiveUpgrades; - - public DelegatingUpgrader(NodeRepository nodeRepository, int maxActiveUpgrades) { - this.nodeRepository = Objects.requireNonNull(nodeRepository); - this.maxActiveUpgrades = maxActiveUpgrades; - } - - @Override - public void upgradeTo(OsVersionTarget target) { - NodeList activeNodes = nodeRepository.nodes().list().nodeType(target.nodeType()).state(Node.State.active); - int numberToUpgrade = Math.max(0, maxActiveUpgrades - activeNodes.changingOsVersionTo(target.version()).size()); - NodeList nodesToUpgrade = activeNodes.not().changingOsVersionTo(target.version()) - .osVersionIsBefore(target.version()) - .byIncreasingOsVersion() - .first(numberToUpgrade); - if (nodesToUpgrade.size() == 0) return; - LOG.info("Upgrading " + nodesToUpgrade.size() + " nodes of type " + target.nodeType() + " to OS version " + - target.version().toFullString()); - nodeRepository.nodes().upgradeOs(NodeListFilter.from(nodesToUpgrade.asList()), Optional.of(target.version())); - } - - @Override - public void disableUpgrade(NodeType type) { - NodeList nodesUpgrading = nodeRepository.nodes().list() - .nodeType(type) - .changingOsVersion(); - if (nodesUpgrading.size() == 0) return; - LOG.info("Disabling OS upgrade of all " + type + " nodes"); - nodeRepository.nodes().upgradeOs(NodeListFilter.from(nodesUpgrading.asList()), Optional.empty()); - } - -} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java new file mode 100644 index 00000000000..5dcbf245028 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsUpgrader.java @@ -0,0 +1,19 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.os; + +import com.yahoo.config.provision.NodeType; + +/** + * Interface for an OS upgrader. + * + * @author mpolden + */ +public interface OsUpgrader { + + /** Trigger upgrade to given target */ + void upgradeTo(OsVersionTarget target); + + /** Disable OS upgrade for all nodes of given type */ + void disableUpgrade(NodeType type); + +} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java index 8e38aabf7ce..6862c91b414 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/OsVersions.java @@ -14,7 +14,7 @@ import java.util.function.UnaryOperator; import java.util.logging.Logger; /** - * Thread-safe class that manages an OS version change for nodes in this repository. An {@link Upgrader} decides how a + * Thread-safe class that manages an OS version change for nodes in this repository. An {@link OsUpgrader} decides how a * {@link OsVersionTarget} is applied to nodes. * * A version target is initially inactive. Activation decision is taken by @@ -29,13 +29,13 @@ public class OsVersions { private static final Logger log = Logger.getLogger(OsVersions.class.getName()); private final CuratorDatabaseClient db; - private final Upgrader upgrader; + private final OsUpgrader upgrader; public OsVersions(NodeRepository nodeRepository) { this(nodeRepository, upgraderIn(nodeRepository)); } - OsVersions(NodeRepository nodeRepository, Upgrader upgrader) { + OsVersions(NodeRepository nodeRepository, OsUpgrader upgrader) { this.db = Objects.requireNonNull(nodeRepository).database(); this.upgrader = Objects.requireNonNull(upgrader); @@ -114,7 +114,7 @@ public class OsVersions { } private void requireUpgradeBudget(Optional upgradeBudget) { - if (upgrader instanceof RetiringUpgrader && upgradeBudget.isEmpty()) { + if (upgrader instanceof RetiringOsUpgrader && upgradeBudget.isEmpty()) { throw new IllegalArgumentException("Zone requires a time budget for OS upgrades"); } } @@ -131,11 +131,11 @@ public class OsVersions { } } - private static Upgrader upgraderIn(NodeRepository nodeRepository) { + private static OsUpgrader upgraderIn(NodeRepository nodeRepository) { if (nodeRepository.zone().getCloud().reprovisionToUpgradeOs()) { - return new RetiringUpgrader(nodeRepository); + return new RetiringOsUpgrader(nodeRepository); } - return new DelegatingUpgrader(nodeRepository, 30); + return new DelegatingOsUpgrader(nodeRepository, 30); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringOsUpgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringOsUpgrader.java new file mode 100644 index 00000000000..930db265066 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringOsUpgrader.java @@ -0,0 +1,71 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.os; + +import com.yahoo.component.Version; +import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.hosted.provision.Node; +import com.yahoo.vespa.hosted.provision.NodeList; +import com.yahoo.vespa.hosted.provision.NodeRepository; +import com.yahoo.vespa.hosted.provision.node.Agent; +import com.yahoo.vespa.hosted.provision.node.filter.NodeListFilter; + +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; +import java.util.logging.Logger; + +/** + * An upgrader that retires and deprovisions nodes on stale OS versions. Retirement of each node is spread out in time, + * according to a time budget, to avoid potential service impact of retiring too many nodes close together. + * + * Used in clouds where nodes must be re-provisioned to upgrade their OS. + * + * @author mpolden + */ +public class RetiringOsUpgrader implements OsUpgrader { + + private static final Logger LOG = Logger.getLogger(RetiringOsUpgrader.class.getName()); + + private final NodeRepository nodeRepository; + + public RetiringOsUpgrader(NodeRepository nodeRepository) { + this.nodeRepository = nodeRepository; + } + + @Override + public void upgradeTo(OsVersionTarget target) { + NodeList allNodes = nodeRepository.nodes().list(); + NodeList activeNodes = allNodes.state(Node.State.active).nodeType(target.nodeType()); + if (activeNodes.isEmpty()) return; // No nodes eligible for upgrade + + Instant now = nodeRepository.clock().instant(); + Duration nodeBudget = target.upgradeBudget() + .orElseThrow(() -> new IllegalStateException("OS upgrades in this zone requires " + + "a time budget, but none is set")) + .dividedBy(activeNodes.size()); + Instant retiredAt = target.lastRetiredAt().orElse(Instant.EPOCH); + if (now.isBefore(retiredAt.plus(nodeBudget))) return; // Budget has not been spent yet + + activeNodes.osVersionIsBefore(target.version()) + .not().deprovisioning() + .byIncreasingOsVersion() + .first(1) + .forEach(node -> upgrade(node, target.version(), now)); + } + + @Override + public void disableUpgrade(NodeType type) { + // No action needed in this implementation. + } + + /** Upgrade given host by retiring and deprovisioning it */ + private void upgrade(Node host, Version target, Instant now) { + LOG.info("Retiring and deprovisioning " + host + ": On stale OS version " + + host.status().osVersion().current().map(Version::toFullString).orElse("") + + ", want " + target); + nodeRepository.nodes().deprovision(host, Agent.RetiringUpgrader, now); + nodeRepository.nodes().upgradeOs(NodeListFilter.from(host), Optional.of(target)); + nodeRepository.osVersions().writeChange((change) -> change.withRetirementAt(now, host.type())); + } + +} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java deleted file mode 100644 index 809d4c5db96..00000000000 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/RetiringUpgrader.java +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.os; - -import com.yahoo.component.Version; -import com.yahoo.config.provision.NodeType; -import com.yahoo.vespa.hosted.provision.Node; -import com.yahoo.vespa.hosted.provision.NodeList; -import com.yahoo.vespa.hosted.provision.NodeRepository; -import com.yahoo.vespa.hosted.provision.node.Agent; -import com.yahoo.vespa.hosted.provision.node.filter.NodeListFilter; - -import java.time.Duration; -import java.time.Instant; -import java.util.Optional; -import java.util.logging.Logger; - -/** - * An upgrader that retires and deprovisions nodes on stale OS versions. Retirement of each node is spread out in time, - * according to a time budget, to avoid potential service impact of retiring too many nodes close together. - * - * Used in clouds where nodes must be re-provisioned to upgrade their OS. - * - * @author mpolden - */ -public class RetiringUpgrader implements Upgrader { - - private static final Logger LOG = Logger.getLogger(RetiringUpgrader.class.getName()); - - private final NodeRepository nodeRepository; - - public RetiringUpgrader(NodeRepository nodeRepository) { - this.nodeRepository = nodeRepository; - } - - @Override - public void upgradeTo(OsVersionTarget target) { - NodeList allNodes = nodeRepository.nodes().list(); - NodeList activeNodes = allNodes.state(Node.State.active).nodeType(target.nodeType()); - if (activeNodes.isEmpty()) return; // No nodes eligible for upgrade - - Instant now = nodeRepository.clock().instant(); - Duration nodeBudget = target.upgradeBudget() - .orElseThrow(() -> new IllegalStateException("OS upgrades in this zone requires " + - "a time budget, but none is set")) - .dividedBy(activeNodes.size()); - Instant retiredAt = target.lastRetiredAt().orElse(Instant.EPOCH); - if (now.isBefore(retiredAt.plus(nodeBudget))) return; // Budget has not been spent yet - - activeNodes.osVersionIsBefore(target.version()) - .not().deprovisioning() - .byIncreasingOsVersion() - .first(1) - .forEach(node -> upgrade(node, target.version(), now)); - } - - @Override - public void disableUpgrade(NodeType type) { - // No action needed in this implementation. - } - - /** Upgrade given host by retiring and deprovisioning it */ - private void upgrade(Node host, Version target, Instant now) { - LOG.info("Retiring and deprovisioning " + host + ": On stale OS version " + - host.status().osVersion().current().map(Version::toFullString).orElse("") + - ", want " + target); - nodeRepository.nodes().deprovision(host, Agent.RetiringUpgrader, now); - nodeRepository.nodes().upgradeOs(NodeListFilter.from(host), Optional.of(target)); - nodeRepository.osVersions().writeChange((change) -> change.withRetirementAt(now, host.type())); - } - -} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/Upgrader.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/Upgrader.java deleted file mode 100644 index e5e68cd258e..00000000000 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/os/Upgrader.java +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.os; - -import com.yahoo.config.provision.NodeType; - -/** - * Interface for an OS upgrader. - * - * @author mpolden - */ -public interface Upgrader { - - /** Trigger upgrade to given target */ - void upgradeTo(OsVersionTarget target); - - /** Disable OS upgrade for all nodes of given type */ - void disableUpgrade(NodeType type); - -} diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java index 3047661e62b..8dbfbf44604 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/os/OsVersionsTest.java @@ -38,7 +38,7 @@ public class OsVersionsTest { @Test public void upgrade() { - var versions = new OsVersions(tester.nodeRepository(), new DelegatingUpgrader(tester.nodeRepository(), Integer.MAX_VALUE)); + var versions = new OsVersions(tester.nodeRepository(), new DelegatingOsUpgrader(tester.nodeRepository(), Integer.MAX_VALUE)); provisionInfraApplication(10); Supplier hostNodes = () -> tester.nodeRepository().nodes().list().nodeType(NodeType.host); @@ -92,7 +92,7 @@ public class OsVersionsTest { public void max_active_upgrades() { int totalNodes = 20; int maxActiveUpgrades = 5; - var versions = new OsVersions(tester.nodeRepository(), new DelegatingUpgrader(tester.nodeRepository(), maxActiveUpgrades)); + var versions = new OsVersions(tester.nodeRepository(), new DelegatingOsUpgrader(tester.nodeRepository(), maxActiveUpgrades)); provisionInfraApplication(totalNodes); Supplier hostNodes = () -> tester.nodeRepository().nodes().list().state(Node.State.active).hosts(); @@ -138,7 +138,7 @@ public class OsVersionsTest { @Test public void newer_upgrade_aborts_upgrade_to_stale_version() { - var versions = new OsVersions(tester.nodeRepository(), new DelegatingUpgrader(tester.nodeRepository(), Integer.MAX_VALUE)); + var versions = new OsVersions(tester.nodeRepository(), new DelegatingOsUpgrader(tester.nodeRepository(), Integer.MAX_VALUE)); provisionInfraApplication(10); Supplier hostNodes = () -> tester.nodeRepository().nodes().list().hosts(); @@ -157,7 +157,7 @@ public class OsVersionsTest { @Test public void upgrade_by_retiring() { - var versions = new OsVersions(tester.nodeRepository(), new RetiringUpgrader(tester.nodeRepository())); + var versions = new OsVersions(tester.nodeRepository(), new RetiringOsUpgrader(tester.nodeRepository())); var clock = (ManualClock) tester.nodeRepository().clock(); int hostCount = 10; // Provision hosts and children @@ -222,7 +222,7 @@ public class OsVersionsTest { @Test public void upgrade_by_retiring_everything_at_once() { - var versions = new OsVersions(tester.nodeRepository(), new RetiringUpgrader(tester.nodeRepository())); + var versions = new OsVersions(tester.nodeRepository(), new RetiringOsUpgrader(tester.nodeRepository())); int hostCount = 3; provisionInfraApplication(hostCount, NodeType.confighost); Supplier hostNodes = () -> tester.nodeRepository().nodes().list() -- cgit v1.2.3