1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.restapi.v1;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.container.jdisc.LoggingRequestHandler;
import com.yahoo.container.logging.AccessLog;
import com.yahoo.jdisc.Response;
import com.yahoo.slime.Cursor;
import com.yahoo.slime.Slime;
import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.Allocation;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;
/**
* The implementation of the /state/v1 API.
* This dumps the content of the node repository on request, possibly with a host filter to return just the single
* matching node.
*
* @author bratseth
*/
public class
NodesApiHandler extends LoggingRequestHandler {
private final NodeRepository nodeRepository;
public NodesApiHandler(Executor executor, AccessLog accessLog, NodeRepository nodeRepository) {
super(executor, accessLog);
this.nodeRepository = nodeRepository;
}
@Override
public HttpResponse handle(HttpRequest request) {
return new NodesResponse(Response.Status.OK,
Optional.ofNullable(request.getProperty("hostname")), nodeRepository);
}
private static class NodesResponse extends HttpResponse {
/** If present only the node with this hostname will be present in the response */
private final Optional<String> hostnameFilter;
private final NodeRepository nodeRepository;
public NodesResponse(int status, Optional<String> hostnameFilter, NodeRepository nodeRepository) {
super(status);
this.hostnameFilter = hostnameFilter;
this.nodeRepository = nodeRepository;
}
@Override
public void render(OutputStream stream) throws IOException {
stream.write(toJson());
}
@Override
public String getContentType() {
return "application/json";
}
private byte[] toJson() throws IOException {
Slime slime = new Slime();
toSlime(slime.setObject());
return SlimeUtils.toJsonBytes(slime);
}
private void toSlime(Cursor root) {
for (Node.State state : Node.State.values())
toSlime(state, root);
}
private void toSlime(Node.State state, Cursor object) {
List<Node> nodes = nodeRepository.getNodes(state);
Cursor nodeArray = null; // create if there are nodes
for (Node node : nodes) {
if (hostnameFilter.isPresent() && ! node.hostname().equals(hostnameFilter.get())) continue;
if (nodeArray == null)
nodeArray = object.setArray(state.name());
toSlime(node, nodeArray.addObject());
}
}
private void toSlime(Node node, Cursor object) {
object.setString("id", node.openStackId());
object.setString("hostname", node.hostname());
object.setString("flavor", node.configuration().flavor().name());
Optional<Allocation> allocation = node.allocation();
if (! allocation.isPresent()) return;
toSlime(allocation.get().owner(), object.setObject("owner"));
toSlime(allocation.get().membership(), object.setObject("membership"));
object.setLong("restartGeneration", allocation.get().restartGeneration().wanted());
}
private void toSlime(ApplicationId id, Cursor object) {
object.setString("tenant", id.tenant().value());
object.setString("application", id.application().value());
object.setString("instance", id.instance().value());
}
private void toSlime(ClusterMembership membership, Cursor object) {
object.setString("clustertype", membership.cluster().type().name());
object.setString("clusterid", membership.cluster().id().value());
object.setLong("index", membership.index());
object.setBool("retired", membership.retired());
}
}
}
|