diff options
Diffstat (limited to 'node-repository')
11 files changed, 133 insertions, 181 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureProvisioner.java index f61d4158253..07e4d586a91 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureProvisioner.java @@ -1,6 +1,7 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import com.google.common.collect.ImmutableList; import com.yahoo.component.Version; import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeType; @@ -13,11 +14,11 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.service.monitor.application.ConfigServerApplication; import com.yahoo.vespa.service.monitor.application.ConfigServerHostApplication; import com.yahoo.vespa.service.monitor.application.ControllerApplication; +import com.yahoo.vespa.service.monitor.application.ControllerHostApplication; import com.yahoo.vespa.service.monitor.application.HostedVespaApplication; import com.yahoo.vespa.service.monitor.application.ProxyHostApplication; import java.time.Duration; -import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.logging.Logger; @@ -33,11 +34,12 @@ import java.util.stream.Collectors; public class InfrastructureProvisioner extends Maintainer { private static final Logger logger = Logger.getLogger(InfrastructureProvisioner.class.getName()); - private static final List<HostedVespaApplication> HOSTED_VESPA_APPLICATIONS = Arrays.asList( + private static final List<HostedVespaApplication> HOSTED_VESPA_APPLICATIONS = ImmutableList.of( ConfigServerApplication.CONFIG_SERVER_APPLICATION, ConfigServerHostApplication.CONFIG_SERVER_HOST_APPLICATION, ProxyHostApplication.PROXY_HOST_APPLICATION, - ControllerApplication.CONTROLLER_APPLICATION); + ControllerApplication.CONTROLLER_APPLICATION, + ControllerHostApplication.CONTROLLER_HOST_APPLICATION); private final Provisioner provisioner; private final InfrastructureVersions infrastructureVersions; diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersions.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersions.java index 29ac88bd8b0..205ffca89b2 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersions.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersions.java @@ -34,6 +34,7 @@ public class InfrastructureVersions { case confighost: case proxyhost: case controller: + case controllerhost: break; default: throw new IllegalArgumentException("Cannot set version for type " + nodeType); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java index db3db139044..ddaa0e4173f 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java @@ -327,6 +327,7 @@ public class NodeSerializer { case "config": return NodeType.config; case "confighost": return NodeType.confighost; case "controller": return NodeType.controller; + case "controllerhost": return NodeType.controllerhost; default : throw new IllegalArgumentException("Unknown node type '" + typeString + "'"); } } @@ -340,6 +341,7 @@ public class NodeSerializer { case config: return "config"; case confighost: return "confighost"; case controller: return "controller"; + case controllerhost: return "controllerhost"; } throw new IllegalArgumentException("Serialized form of '" + type + "' not defined"); } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeSerializer.java new file mode 100644 index 00000000000..75a8dbdcffc --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeSerializer.java @@ -0,0 +1,70 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.restapi.v2; + +import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.hosted.provision.Node; + +/** + * Serializer for node wire format. Used to serialize node objects sent over the wire (HTTP). + * + * @author mpolden + */ +public class NodeSerializer { + + public Node.State stateFrom(String state) { + switch (state) { + case "active": return Node.State.active; + case "dirty": return Node.State.dirty; + case "failed": return Node.State.failed; + case "inactive": return Node.State.inactive; + case "parked": return Node.State.parked; + case "provisioned": return Node.State.provisioned; + case "ready": return Node.State.ready; + case "reserved": return Node.State.reserved; + default: throw new IllegalArgumentException("Unknown node state '" + state + "'"); + } + } + + public String toString(Node.State state) { + switch (state) { + case active: return "active"; + case dirty: return "dirty"; + case failed: return "failed"; + case inactive: return "inactive"; + case parked: return "parked"; + case provisioned: return "provisioned"; + case ready: return "ready"; + case reserved: return "reserved"; + default: throw new IllegalArgumentException("Unknown node state '" + state + "'"); + } + } + + public NodeType typeFrom(String nodeType) { + switch (nodeType) { + case "tenant": return NodeType.tenant; + case "host": return NodeType.host; + case "proxy": return NodeType.proxy; + case "proxyhost": return NodeType.proxyhost; + case "config": return NodeType.config; + case "confighost": return NodeType.confighost; + case "controller": return NodeType.controller; + case "controllerhost": return NodeType.controllerhost; + default: throw new IllegalArgumentException("Unknown node type '" + nodeType + "'"); + } + } + + public String toString(NodeType type) { + switch (type) { + case tenant: return "tenant"; + case host: return "host"; + case proxy: return "proxy"; + case proxyhost: return "proxyhost"; + case config: return "config"; + case confighost: return "confighost"; + case controller: return "controller"; + case controllerhost: return "controllerhost"; + default: throw new IllegalArgumentException("Unknown node type '" + type.name() + "'"); + } + } + +} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeStateSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeStateSerializer.java deleted file mode 100644 index 8c7f297eca8..00000000000 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeStateSerializer.java +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.restapi.v2; - -import com.yahoo.vespa.hosted.provision.Node; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Converts {@link Node.State} to/from serialized form in REST APIs. - * - * @author bakksjo - */ -public class NodeStateSerializer { - - private static final Map<Node.State, String> serializationMap = new HashMap<>(); - private static final Map<String, Node.State> deserializationMap = new HashMap<>(); - - private static void addMapping(final Node.State nodeState, final String wireName) { - serializationMap.put(nodeState, wireName); - deserializationMap.put(wireName, nodeState); - } - - static { - // Alphabetical order. No cheating, please - don't use .name(), .toString(), reflection etc. to get wire name. - addMapping(Node.State.active, "active"); - addMapping(Node.State.dirty, "dirty"); - addMapping(Node.State.failed, "failed"); - addMapping(Node.State.inactive, "inactive"); - addMapping(Node.State.parked, "parked"); - addMapping(Node.State.provisioned, "provisioned"); - addMapping(Node.State.ready, "ready"); - addMapping(Node.State.reserved, "reserved"); - } - - private NodeStateSerializer() {} // Utility class, no instances. - - public static Optional<Node.State> fromWireName(final String wireName) { - return Optional.ofNullable(deserializationMap.get(wireName)); - } - - public static String wireNameOf(final Node.State nodeState) { - final String wireName = serializationMap.get(nodeState); - if (wireName == null) { - throw new RuntimeException("Bug: Unknown serialization form of node state " + nodeState.name()); - } - return wireName; - } -} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java index adffb17c808..6b31adf10fa 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesApiHandler.java @@ -32,6 +32,7 @@ import com.yahoo.yolean.Exceptions; import javax.inject.Inject; import java.io.IOException; import java.io.InputStream; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -54,6 +55,7 @@ public class NodesApiHandler extends LoggingRequestHandler { private final NodeRepository nodeRepository; private final NodeRepositoryMaintenance maintenance; private final NodeFlavors nodeFlavors; + private final NodeSerializer serializer = new NodeSerializer(); @Inject public NodesApiHandler(LoggingRequestHandler.Context parentCtx, Orchestrator orchestrator, @@ -185,7 +187,6 @@ public class NodesApiHandler extends LoggingRequestHandler { private Node nodeFromRequest(HttpRequest request) { String hostname = lastElement(request.getUri().getPath()); - return nodeRepository.getNode(hostname).orElseThrow(() -> new NotFoundException("No node found with hostname " + hostname)); } @@ -200,7 +201,7 @@ public class NodesApiHandler extends LoggingRequestHandler { byte[] jsonBytes = IOUtils.readBytes(jsonStream, 1000 * 1000); return SlimeUtils.jsonToSlime(jsonBytes); } catch (IOException e) { - throw new RuntimeException(); + throw new UncheckedIOException(e); } } @@ -227,18 +228,9 @@ public class NodesApiHandler extends LoggingRequestHandler { nodeTypeFromSlime(inspector.field("type"))); } - private static NodeType nodeTypeFromSlime(Inspector object) { + private NodeType nodeTypeFromSlime(Inspector object) { if (! object.valid()) return NodeType.tenant; // default - switch (object.asString()) { - case "tenant": return NodeType.tenant; - case "host": return NodeType.host; - case "proxy": return NodeType.proxy; - case "proxyhost": return NodeType.proxyhost; - case "config": return NodeType.config; - case "confighost": return NodeType.confighost; - case "controller": return NodeType.controller; - default: throw new IllegalArgumentException("Unknown node type '" + object.asString() + "'"); - } + return serializer.typeFrom(object.asString()); } public static NodeFilter toNodeFilter(HttpRequest request) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java index 9364c5f5f80..26294f84040 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java @@ -42,8 +42,8 @@ class NodesResponse extends HttpResponse { private final boolean recursive; private final Orchestrator orchestrator; private final NodeRepository nodeRepository; - private final Slime slime; + private final NodeSerializer serializer = new NodeSerializer(); public NodesResponse(ResponseType responseType, HttpRequest request, Orchestrator orchestrator, NodeRepository nodeRepository) { @@ -60,7 +60,7 @@ class NodesResponse extends HttpResponse { switch (responseType) { case nodeList: nodesToSlime(root); break; case stateList : statesToSlime(root); break; - case nodesInStateList: nodesToSlime(stateFromString(lastElement(parentUrl)), root); break; + case nodesInStateList: nodesToSlime(serializer.stateFrom(lastElement(parentUrl)), root); break; case singleNode : nodeToSlime(lastElement(parentUrl), root); break; default: throw new IllegalArgumentException(); } @@ -96,11 +96,11 @@ class NodesResponse extends HttpResponse { private void statesToSlime(Cursor root) { Cursor states = root.setObject("states"); for (Node.State state : Node.State.values()) - toSlime(state, states.setObject(NodeStateSerializer.wireNameOf(state))); + toSlime(state, states.setObject(serializer.toString(state))); } private void toSlime(Node.State state, Cursor object) { - object.setString("url", parentUrl + NodeStateSerializer.wireNameOf(state)); + object.setString("url", parentUrl + serializer.toString(state)); if (recursive) nodesToSlime(state, object); } @@ -135,10 +135,10 @@ class NodesResponse extends HttpResponse { object.setString("url", nodeParentUrl + node.hostname()); if ( ! allFields) return; object.setString("id", node.id()); - object.setString("state", NodeStateSerializer.wireNameOf(node.state())); + object.setString("state", serializer.toString(node.state())); object.setString("type", node.type().name()); object.setString("hostname", node.hostname()); - object.setString("type", toString(node.type())); + object.setString("type", serializer.toString(node.type())); if (node.parentHostname().isPresent()) { object.setString("parentHostname", node.parentHostname().get()); } @@ -189,20 +189,6 @@ class NodesResponse extends HttpResponse { node.status().hardwareDivergence().ifPresent(hardwareDivergence -> object.setString("hardwareDivergence", hardwareDivergence)); } - private String toString(NodeType type) { - switch(type) { - case tenant: return "tenant"; - case host: return "host"; - case proxy: return "proxy"; - case proxyhost: return "proxyhost"; - case config: return "config"; - case confighost: return "confighost"; - case controller: return "controller"; - default: - throw new RuntimeException("New type added to enum, not implemented in NodesResponse: " + type.name()); - } - } - private void toSlime(ApplicationId id, Cursor object) { object.setString("tenant", id.tenant().value()); object.setString("application", id.application().value()); @@ -238,9 +224,4 @@ class NodesResponse extends HttpResponse { return path.substring(lastSlash+1); } - private static Node.State stateFromString(String stateString) { - return NodeStateSerializer.fromWireName(stateString) - .orElseThrow(() -> new RuntimeException("Node state '" + stateString + "' is not known")); - } - } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersionsTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersionsTest.java index afa6f74f604..4ee3ade351a 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersionsTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InfrastructureVersionsTest.java @@ -72,12 +72,16 @@ public class InfrastructureVersionsTest { infrastructureVersions.setTargetVersion(NodeType.config, version, false); infrastructureVersions.setTargetVersion(NodeType.confighost, version2, false); infrastructureVersions.setTargetVersion(NodeType.proxyhost, version, false); + infrastructureVersions.setTargetVersion(NodeType.controller, version, false); + infrastructureVersions.setTargetVersion(NodeType.controllerhost, version2, false); Map<NodeType, Version> expected = new HashMap<>(); expected.put(NodeType.config, version); expected.put(NodeType.confighost, version2); expected.put(NodeType.proxyhost, version); + expected.put(NodeType.controller, version); + expected.put(NodeType.controllerhost, version2); assertEquals(expected, infrastructureVersions.getTargetVersions()); } -}
\ No newline at end of file +} diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java index 6c9d0be69b2..6f7ba72ff7e 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java @@ -251,49 +251,6 @@ public class SerializationTest { node = createNode(); copy = nodeSerializer.fromJson(node.state(), nodeSerializer.toJson(node)); assertEquals(node.additionalIpAddresses(), copy.additionalIpAddresses()); - - // TODO remove after MAI 2017 - // Test deserialization of a json file without the additional ip addresses field - String json = "{\n" + - " \"url\": \"http://localhost:8080/nodes/v2/node/host1.yahoo.com\",\n" + - " \"id\": \"host1.yahoo.com\",\n" + - " \"state\": \"active\",\n" + - " \"type\": \"tenant\",\n" + - " \"hostname\": \"host1.yahoo.com\",\n" + - " \"openStackId\": \"node1\",\n" + - " \"flavor\": \"default\",\n" + - " \"canonicalFlavor\": \"default\",\n" + - " \"minDiskAvailableGb\":400.0,\n" + - " \"minMainMemoryAvailableGb\":16.0,\n" + - " \"description\":\"Flavor-name-is-default\",\n" + - " \"minCpuCores\":2.0,\n" + - " \"environment\":\"BARE_METAL\",\n" + - " \"owner\": {\n" + - " \"tenant\": \"tenant2\",\n" + - " \"application\": \"application2\",\n" + - " \"instance\": \"instance2\"\n" + - " },\n" + - " \"membership\": {\n" + - " \"clustertype\": \"content\",\n" + - " \"clusterid\": \"id2\",\n" + - " \"group\": \"0\",\n" + - " \"index\": 0,\n" + - " \"retired\": false\n" + - " },\n" + - " \"restartGeneration\": 0,\n" + - " \"currentRestartGeneration\": 0,\n" + - " \"wantedDockerImage\":\"foo:6.42.0\",\n" + - " \"wantedVespaVersion\":\"6.42.0\",\n" + - " \"rebootGeneration\": 1,\n" + - " \"currentRebootGeneration\": 0,\n" + - " \"failCount\": 0,\n" + - " \"wantToRetire\" : false,\n" + - " \"history\":[{\"type\":\"readied\",\"at\":123,\"type\":\"system\"},{\"type\":\"reserved\",\"at\":123,\"agent\":\"application\"},{\"type\":\"activated\",\"at\":123,\"agent\":\"application\"}],\n" + - " \"ipAddresses\":[\"::1\", \"127.0.0.1\"]\n" + - "}"; - - node = nodeSerializer.fromJson(State.active, Utf8.toBytes(json)); - assertEquals(Collections.emptySet(), node.additionalIpAddresses()); } @Test @@ -354,6 +311,13 @@ public class SerializationTest { assertEquals(Version.fromString("7.1"), serialized.status().osVersion().get()); } + @Test + public void serialize_node_types() { + for (NodeType t : NodeType.values()) { + assertEquals(t, NodeSerializer.nodeTypeFromString(NodeSerializer.toString(t))); + } + } + private byte[] createNodeJson(String hostname, String... ipAddress) { String ipAddressJsonPart = ""; if (ipAddress.length > 0) { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializerTest.java deleted file mode 100644 index f3f128ab19a..00000000000 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/NodeStateSerializerTest.java +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.restapi; - -import com.yahoo.vespa.hosted.provision.Node; -import com.yahoo.vespa.hosted.provision.restapi.v2.NodeStateSerializer; -import org.junit.Test; - -import java.util.HashSet; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author bakksjo - */ -public class NodeStateSerializerTest { - - @Test - public void allStatesHaveASerializedForm() { - for (Node.State nodeState : Node.State.values()) { - assertNotNull(NodeStateSerializer.wireNameOf(nodeState)); - } - } - - @Test - public void wireNamesDoNotOverlap() { - Set<String> wireNames = new HashSet<>(); - for (Node.State nodeState : Node.State.values()) { - wireNames.add(NodeStateSerializer.wireNameOf(nodeState)); - } - assertEquals(Node.State.values().length, wireNames.size()); - } - - @Test - public void serializationAndDeserializationIsSymmetric() { - for (Node.State nodeState : Node.State.values()) { - String serialized = NodeStateSerializer.wireNameOf(nodeState); - Node.State deserialized = NodeStateSerializer.fromWireName(serialized) - .orElseThrow(() -> new RuntimeException( - "Cannot deserialize '" + serialized + "', serialized form of " + nodeState.name())); - assertEquals(nodeState, deserialized); - } - } - -} diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeSerializerTest.java new file mode 100644 index 00000000000..05b23addddf --- /dev/null +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeSerializerTest.java @@ -0,0 +1,32 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.restapi.v2; + + +import com.yahoo.config.provision.NodeType; +import com.yahoo.vespa.hosted.provision.Node; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author mpolden + */ +public class NodeSerializerTest { + + private final NodeSerializer serializer = new NodeSerializer(); + + @Test + public void serialize_node_types() { + for (NodeType t : NodeType.values()) { + assertEquals(t, serializer.typeFrom(serializer.toString(t))); + } + } + + @Test + public void serialize_node_states() { + for (Node.State s : Node.State.values()) { + assertEquals(s, serializer.stateFrom(serializer.toString(s))); + } + } + +} |