Skip to content

Commit

Permalink
Merge pull request #32620 from vespa-engine/mpolden/restore
Browse files Browse the repository at this point in the history
Add restore operation to snapshot API
  • Loading branch information
hakonhall authored Oct 21, 2024
2 parents 185b001 + c67d8b0 commit b74ba36
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@ public Snapshot create(String hostname, Instant instant) {
}
}

/** Restore a node to given snapshot */
public Snapshot restore(SnapshotId id, String hostname) {
try (var lock = db.lockSnapshots(hostname)) {
Snapshot snapshot = require(id, hostname);
return write(id, hostname, (node) -> {
if (busy(node)) {
throw new IllegalArgumentException("Cannot restore snapshot: Node " + hostname +
" is busy with snapshot " + node.status().snapshot().get().id() + " in "+
node.status().snapshot().get().state() + " state");
}
return Optional.of(snapshot.with(Snapshot.State.restoring));
}, lock).get();
}
}

/** Remove given snapshot. Note that this only removes metadata about the snapshot, and not the underlying data */
public void remove(SnapshotId id, String hostname, boolean force) {
try (var lock = db.lockSnapshots(hostname)) {
Expand All @@ -82,7 +97,7 @@ public void remove(SnapshotId id, String hostname, boolean force) {
}
}

/** Move snapshot to given state */
/** Change state of an active snapshot */
public Snapshot move(SnapshotId id, String hostname, Snapshot.State newState) {
try (var lock = db.lockSnapshots(hostname)) {
Snapshot current = require(id, hostname);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ private HttpResponse handlePOST(HttpRequest request) {
return new MessageResponse("Triggered dropping of documents on " + count + " nodes");
}
if (path.matches("/nodes/v2/snapshot/{hostname}")) return snapshot(path.get("hostname"));
if (path.matches("/nodes/v2/snapshot/{hostname}/{snapshot}/restore")) return restoreSnapshot(SnapshotId.of(path.get("snapshot")), path.get("hostname"));

throw new NotFoundException("Nothing at path '" + request.getUri().getPath() + "'");
}
Expand All @@ -251,6 +252,11 @@ private HttpResponse snapshot(String hostname) {
return new MessageResponse("Triggered a new snapshot of " + hostname + ": " + snapshot.id());
}

private HttpResponse restoreSnapshot(SnapshotId id, String hostname) {
Snapshot snapshot = nodeRepository.snapshots().restore(id, hostname);
return new MessageResponse("Triggered restore of snapshot '" + snapshot.id() + "' to " + hostname);
}

private HttpResponse forgetSnapshot(SnapshotId id, String hostname, HttpRequest request) {
boolean force = request.getBooleanProperty("force");
nodeRepository.snapshots().remove(id, hostname, force);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,14 @@ public void test_snapshots() throws IOException {
String id1 = SlimeUtils.entriesStream(SlimeUtils.jsonToSlime(listResponse).get().field("snapshots"))
.toList().get(1).field("id").asString();

// Cannot change state of previous snapshot
// Cannot trigger restore while busy with a different snapshot
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/snapshot/host4.yahoo.com/" + id0 + "/restore",
new byte[0],
Request.Method.POST),
400,
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Cannot restore snapshot: Node host4.yahoo.com is busy with snapshot " + id1 + " in creating state\"}");

// Cannot change state of a non-active snapshot
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/snapshot/host4.yahoo.com/" + id0,
"""
{"state": "restored"}
Expand All @@ -919,6 +926,21 @@ public void test_snapshots() throws IOException {
400,
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Cannot move snapshot " + id0 + " to restored: Node host4.yahoo.com is not working on this snapshot\"}");

// Snapshot completes
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/snapshot/host4.yahoo.com/" + id1,
"""
{"state": "created"}
""",
Request.Method.PATCH),
"{\"message\":\"Updated snapshot '" + id1 + "' for node host4.yahoo.com\"}");

// Start restore of snapshot
tester.assertResponse(new Request("http://localhost:8080/nodes/v2/snapshot/host4.yahoo.com/" + id1 + "/restore",
new byte[0],
Request.Method.POST),
200,
"{\"message\":\"Triggered restore of snapshot '" + id1 + "' to host4.yahoo.com\"}");

// Forget about snapshot
assertResponse(new Request("http://localhost:8080/nodes/v2/snapshot/host4.yahoo.com/" + id0, new byte[0], Request.Method.DELETE),
"{\"message\":\"Removed snapshot '" + id0 + "' belonging to host4.yahoo.com\"}");
Expand Down

0 comments on commit b74ba36

Please sign in to comment.