summaryrefslogtreecommitdiffstats
path: root/node-admin/src/test
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@verizonmedia.com>2019-09-27 14:47:45 +0200
committerValerij Fredriksen <valerijf@verizonmedia.com>2020-04-22 15:24:51 +0200
commitd2090d1f4b4a6c56fb528d819af7ee5b680f3ef7 (patch)
tree1ee6cea55e3a9e458de33e658b0e5333358b5dca /node-admin/src/test
parent95a6fc2366a2348f378ffc1c251296fc95a80726 (diff)
Create DiskCleanup
Diffstat (limited to 'node-admin/src/test')
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/CoredumpCleanupRuleTest.java103
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/DiskCleanupTest.java142
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/LinearCleanupRuleTest.java55
3 files changed, 300 insertions, 0 deletions
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/CoredumpCleanupRuleTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/CoredumpCleanupRuleTest.java
new file mode 100644
index 00000000000..e8ca2ff8491
--- /dev/null
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/CoredumpCleanupRuleTest.java
@@ -0,0 +1,103 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.node.admin.maintenance.disk;
+
+import com.yahoo.vespa.test.file.TestFileSystem;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.time.Instant;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import static com.yahoo.vespa.hosted.node.admin.maintenance.disk.DiskCleanupRule.PrioritizedFileAttributes;
+import static com.yahoo.vespa.hosted.node.admin.maintenance.disk.DiskCleanupRule.Priority;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author freva
+ */
+public class CoredumpCleanupRuleTest {
+
+ private final FileSystem fileSystem = TestFileSystem.create();
+
+ @Test
+ public void for_container_test() throws IOException {
+ Path path = fileSystem.getPath("/test/path");
+ DiskCleanupRule rule = CoredumpCleanupRule.forContainer(path);
+
+ assertPriorities(rule, Map.of());
+
+ createFile(path.resolve("core1"), Instant.ofEpochSecond(232));
+ assertPriorities(rule, Map.of("/test/path/core1", Priority.MEDIUM));
+
+ createFile(path.resolve("core2"), Instant.ofEpochSecond(123));
+ assertPriorities(rule, Map.of(
+ "/test/path/core2", Priority.MEDIUM,
+ "/test/path/core1", Priority.HIGHEST));
+
+ createFile(path.resolve("vespa-proton-bin.core.325"), Instant.ofEpochSecond(456));
+ createFile(path.resolve("vespa-distributor.core.764"), Instant.ofEpochSecond(256));
+ var expected = Map.of(
+ "/test/path/core2", Priority.HIGHEST,
+ "/test/path/core1", Priority.HIGHEST,
+ "/test/path/vespa-proton-bin.core.325", Priority.HIGHEST,
+ "/test/path/vespa-distributor.core.764", Priority.MEDIUM);
+ assertPriorities(rule, expected);
+
+ // processing core has no effect on this
+ Files.createDirectories(path.resolve("processing/abcd-1234"));
+ createFile(path.resolve("processing/abcd-1234/core5"), Instant.ofEpochSecond(67));
+ assertPriorities(rule, expected);
+ }
+
+ @Test
+ public void for_host_test() throws IOException {
+ Path path = fileSystem.getPath("/test/path");
+ DiskCleanupRule rule = CoredumpCleanupRule.forHost(path);
+
+ assertPriorities(rule, Map.of());
+
+ createFile(path.resolve("h123a/abcd-1234/dump_core1"), Instant.parse("2020-04-21T19:21:00Z"));
+ createFile(path.resolve("h123a/abcd-1234/metadata.json"), Instant.parse("2020-04-21T19:26:00Z"));
+ assertPriorities(rule, Map.of("/test/path/h123a/abcd-1234/dump_core1", Priority.MEDIUM));
+
+ createFile(path.resolve("h123a/abcd-efgh/dump_core1"), Instant.parse("2020-04-21T07:13:00Z"));
+ createFile(path.resolve("h123a/56ad-af42/dump_vespa-distributor.321"), Instant.parse("2020-04-21T23:37:00Z"));
+ createFile(path.resolve("h123a/4324-a23d/dump_core2"), Instant.parse("2020-04-22T04:56:00Z"));
+ createFile(path.resolve("h123a/8534-7da3/dump_vespa-proton-bin.123"), Instant.parse("2020-04-19T15:35:00Z"));
+
+ // Also create a core for a second container: h123b
+ createFile(path.resolve("h123b/db1a-ab34/dump_core1"), Instant.parse("2020-04-21T07:01:00Z"));
+ createFile(path.resolve("h123b/7392-59ad/dump_vespa-proton-bin.342"), Instant.parse("2020-04-22T12:05:00Z"));
+
+ assertPriorities(rule, Map.of(
+ "/test/path/h123a/abcd-1234/dump_core1", Priority.HIGH,
+ "/test/path/h123a/abcd-efgh/dump_core1", Priority.HIGH,
+
+ // Although it is the oldest core of the day for h123a, it is the first one that starts with vespa-
+ "/test/path/h123a/56ad-af42/dump_vespa-distributor.321", Priority.MEDIUM,
+ "/test/path/h123a/4324-a23d/dump_core2", Priority.MEDIUM,
+ "/test/path/h123a/8534-7da3/dump_vespa-proton-bin.123", Priority.MEDIUM,
+ "/test/path/h123b/db1a-ab34/dump_core1", Priority.MEDIUM,
+ "/test/path/h123b/7392-59ad/dump_vespa-proton-bin.342", Priority.MEDIUM
+ ));
+ }
+
+ private static void createFile(Path path, Instant instant) throws IOException {
+ Files.createDirectories(path.getParent());
+ Files.createFile(path);
+ Files.setLastModifiedTime(path, FileTime.from(instant));
+ }
+
+ private static void assertPriorities(DiskCleanupRule rule, Map<String, Priority> expected) {
+ Map<String, Priority> actual = rule.prioritize().stream()
+ .collect(Collectors.toMap(pfa -> pfa.fileAttributes().path().toString(), PrioritizedFileAttributes::priority));
+
+ assertEquals(new TreeMap<>(expected), new TreeMap<>(actual));
+ }
+} \ No newline at end of file
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/DiskCleanupTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/DiskCleanupTest.java
new file mode 100644
index 00000000000..3f383a68b84
--- /dev/null
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/DiskCleanupTest.java
@@ -0,0 +1,142 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.node.admin.maintenance.disk;
+
+import com.yahoo.vespa.hosted.node.admin.component.TestTaskContext;
+import com.yahoo.vespa.hosted.node.admin.task.util.file.FileFinder;
+import com.yahoo.vespa.test.file.TestFileSystem;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.yahoo.vespa.hosted.node.admin.task.util.file.FileFinder.FileAttributes;
+import static com.yahoo.vespa.hosted.node.admin.maintenance.disk.DiskCleanupRule.Priority;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author freva
+ */
+public class DiskCleanupTest {
+
+ private final TestTaskContext context = new TestTaskContext();
+ private final DiskCleanupTester tester = new DiskCleanupTester();
+ private final DiskCleanup diskCleanup = new DiskCleanup();
+
+ @Test
+ public void nothing_deleted() throws IOException {
+ assertFalse(diskCleanup.cleanup(context, List.of(), 0));
+ assertFalse(diskCleanup.cleanup(context, List.of(), 10));
+
+ DiskCleanupRuleMock rule1 = new DiskCleanupRuleMock();
+ DiskCleanupRuleMock rule2 = new DiskCleanupRuleMock();
+ assertFalse(diskCleanup.cleanup(context, List.of(rule1, rule2), 0));
+ assertFalse(diskCleanup.cleanup(context, List.of(rule1, rule2), 10));
+
+ tester.createFile("/path/that-should-not-be-deleted", 5);
+ assertFalse(diskCleanup.cleanup(context, List.of(rule1, rule2), 10));
+ tester.assertAllFilesExistExcept();
+
+ // Create a file and let rule return it, but before cleanup is run, the file is deleted
+ rule1.addFile(tester.createFile("/path/file-does-not-exist", 1), Priority.HIGHEST);
+ Files.delete(tester.path("/path/file-does-not-exist"));
+ assertFalse(diskCleanup.cleanup(context, List.of(rule1, rule2), 10));
+ }
+
+ @Test
+ public void delete_test() throws IOException {
+ tester.createFile("/opt/vespa/var/db/do-not-delete-1.db", 1);
+ tester.createFile("/opt/vespa/var/db/do-not-delete-2.db", 1);
+ tester.createFile("/opt/vespa/var/zookeeper/do-not-delete-3", 1);
+ tester.createFile("/opt/vespa/var/index/something-important", 1);
+
+ DiskCleanupRuleMock rule1 = new DiskCleanupRuleMock()
+ .addFile(tester.createFile("/opt/vespa/logs/vespa-1.log", 10), Priority.MEDIUM)
+ .addFile(tester.createFile("/opt/vespa/logs/vespa-2.log", 8), Priority.HIGH)
+ .addFile(tester.createFile("/opt/vespa/logs/vespa-3.log", 13), Priority.HIGHEST)
+ .addFile(tester.createFile("/opt/vespa/logs/vespa-4.log", 10), Priority.HIGHEST);
+ DiskCleanupRuleMock rule2 = new DiskCleanupRuleMock()
+ .addFile(tester.createFile("/opt/vespa/var/crash/core1", 105), Priority.LOW)
+ .addFile(tester.createFile("/opt/vespa/var/crash/vespa-proton-bin.core-232", 190), Priority.HIGH)
+ .addFile(tester.createFile("/opt/vespa/var/crash/core3", 54), Priority.MEDIUM)
+ .addFile(tester.createFile("/opt/vespa/var/crash/core4", 300), Priority.HIGH);
+
+ // 2 files with HIGHEST priority, tie broken by the largest size which is won by "vespa-3.log", since
+ // it is >= 10 bytes, no more files are deleted
+ assertTrue(diskCleanup.cleanup(context, List.of(rule1, rule2), 10));
+ tester.assertAllFilesExistExcept("/opt/vespa/logs/vespa-3.log");
+
+ // Called with the same arguments, but vespa-3.log is still missing...
+ assertTrue(diskCleanup.cleanup(context, List.of(rule1, rule2), 10));
+ tester.assertAllFilesExistExcept("/opt/vespa/logs/vespa-3.log", "/opt/vespa/logs/vespa-4.log");
+
+ assertTrue(diskCleanup.cleanup(context, List.of(rule1, rule2), 500));
+ tester.assertAllFilesExistExcept("/opt/vespa/logs/vespa-3.log", "/opt/vespa/logs/vespa-4.log", // from before
+ // 300 + 190 + 8 + 54
+ "/opt/vespa/var/crash/core4", "/opt/vespa/var/crash/vespa-proton-bin.core-232", "/opt/vespa/logs/vespa-2.log", "/opt/vespa/var/crash/core3");
+ }
+
+ @Test
+ public void bytes_to_display_count_test() {
+ assertEquals("-1 bytes", DiskCleanup.bytesToDisplayCount(-1));
+ assertEquals("123 bytes", DiskCleanup.bytesToDisplayCount(123));
+ assertEquals("1 kB", DiskCleanup.bytesToDisplayCount(1_000));
+ assertEquals("15 MB", DiskCleanup.bytesToDisplayCount(15_000_000));
+ assertEquals("123 GB", DiskCleanup.bytesToDisplayCount(123_456_789_012L));
+ assertEquals("987 TB", DiskCleanup.bytesToDisplayCount(987_654_321_098_765L));
+ assertEquals("2 PB", DiskCleanup.bytesToDisplayCount(2_000_000_000_000_000L));
+ assertEquals("9 EB", DiskCleanup.bytesToDisplayCount(Long.MAX_VALUE));
+
+ }
+
+ private static class DiskCleanupRuleMock implements DiskCleanupRule {
+ private final ArrayList<PrioritizedFileAttributes> pfa = new ArrayList<>();
+
+ private DiskCleanupRuleMock addFile(Path path, Priority priority) throws IOException {
+ PosixFileAttributes attributes = Files.getFileAttributeView(path, PosixFileAttributeView.class).readAttributes();
+ pfa.add(new PrioritizedFileAttributes(new FileAttributes(path, attributes), priority));
+ return this;
+ }
+
+ @Override
+ public Collection<PrioritizedFileAttributes> prioritize() {
+ return Collections.unmodifiableList(pfa);
+ }
+ }
+
+ private static class DiskCleanupTester {
+ private final FileSystem fileSystem = TestFileSystem.create();
+ private final Set<String> files = new HashSet<>();
+
+ private Path path(String path) {
+ return fileSystem.getPath(path);
+ }
+
+ private Path createFile(String pathStr, int size) throws IOException {
+ Path path = path(pathStr);
+ Files.createDirectories(path.getParent());
+ Files.write(path, new byte[size]);
+ files.add(path.toString());
+ return path;
+ }
+
+ private void assertAllFilesExistExcept(String... deletedPaths) {
+ Set<String> actual = FileFinder.files(path("/")).stream().map(fa -> fa.path().toString()).collect(Collectors.toSet());
+ Set<String> expected = new HashSet<>(files);
+ expected.removeAll(Set.of(deletedPaths));
+ assertEquals(expected, actual);
+ }
+ }
+} \ No newline at end of file
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/LinearCleanupRuleTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/LinearCleanupRuleTest.java
new file mode 100644
index 00000000000..ae2d3af4f21
--- /dev/null
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/maintenance/disk/LinearCleanupRuleTest.java
@@ -0,0 +1,55 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.node.admin.maintenance.disk;
+
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static com.yahoo.vespa.hosted.node.admin.task.util.file.FileFinder.FileAttributes;
+import static com.yahoo.vespa.hosted.node.admin.maintenance.disk.DiskCleanupRule.PrioritizedFileAttributes;
+import static com.yahoo.vespa.hosted.node.admin.maintenance.disk.DiskCleanupRule.Priority;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @author freva
+ */
+public class LinearCleanupRuleTest {
+
+ @Test
+ public void basic() {
+ assertRule(Map.of(), Priority.LOWEST, Priority.HIGHEST);
+
+ assertRule(Map.of(0.0, Priority.LOW, 0.5, Priority.LOW, 1.0, Priority.LOW), Priority.LOW, Priority.LOW);
+ assertRule(Map.of(0.0, Priority.LOW, 0.5, Priority.MEDIUM, 1.0, Priority.MEDIUM), Priority.LOW, Priority.MEDIUM);
+
+ assertRule(Map.of(
+ -5.0, Priority.LOW,
+ 0.0, Priority.LOW,
+ 0.2, Priority.LOW,
+ 0.35, Priority.MEDIUM,
+ 0.65, Priority.MEDIUM,
+ 0.8, Priority.HIGH,
+ 1.0, Priority.HIGH,
+ 5.0, Priority.HIGH),
+ Priority.LOW, Priority.HIGH);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void fail_if_high_priority_lower_than_low() {
+ assertRule(Map.of(), Priority.HIGHEST, Priority.LOWEST);
+ }
+
+ private static void assertRule(Map<Double, Priority> expectedPriorities, Priority low, Priority high) {
+ Map<FileAttributes, Double> fileAttributesByScore = expectedPriorities.keySet().stream()
+ .collect(Collectors.toMap(score -> mock(FileAttributes.class), score -> score));
+ LinearCleanupRule rule = new LinearCleanupRule(
+ () -> List.copyOf(fileAttributesByScore.keySet()), fileAttributesByScore::get, low, high);
+
+ Map<Double, Priority> actualPriorities = rule.prioritize().stream()
+ .collect(Collectors.toMap(pfa -> fileAttributesByScore.get(pfa.fileAttributes()), PrioritizedFileAttributes::priority));
+ assertEquals(expectedPriorities, actualPriorities);
+ }
+} \ No newline at end of file