summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docker-api/pom.xml6
-rw-r--r--node-admin/pom.xml6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java3
-rw-r--r--orchestrator-restapi/pom.xml6
-rw-r--r--orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java12
-rw-r--r--orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostRequest.java13
-rw-r--r--orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostResponse.java13
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java2
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java10
-rw-r--r--orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java35
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java9
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java49
12 files changed, 151 insertions, 13 deletions
diff --git a/docker-api/pom.xml b/docker-api/pom.xml
index d35cd158edf..655030a02b5 100644
--- a/docker-api/pom.xml
+++ b/docker-api/pom.xml
@@ -97,12 +97,6 @@
</dependency>
<dependency>
<groupId>com.yahoo.vespa</groupId>
- <artifactId>jaxrs_utils</artifactId>
- <version>${project.version}</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>com.yahoo.vespa</groupId>
<artifactId>jaxrs_client_utils</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
diff --git a/node-admin/pom.xml b/node-admin/pom.xml
index 10fe37cfc4b..628b774d729 100644
--- a/node-admin/pom.xml
+++ b/node-admin/pom.xml
@@ -69,12 +69,6 @@
</dependency>
<dependency>
<groupId>com.yahoo.vespa</groupId>
- <artifactId>jaxrs_utils</artifactId>
- <version>${project.version}</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>com.yahoo.vespa</groupId>
<artifactId>jaxrs_client_utils</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java
index 538feeb042d..5b559aef1a5 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/OrchestratorMock.java
@@ -33,6 +33,9 @@ public class OrchestratorMock implements Orchestrator {
}
@Override
+ public void setNodeStatus(HostName hostName, HostStatus state) throws OrchestrationException {}
+
+ @Override
public void resume(HostName hostName) throws HostStateChangeDeniedException, HostNameNotFoundException {}
@Override
diff --git a/orchestrator-restapi/pom.xml b/orchestrator-restapi/pom.xml
index b2b581a7fc6..79e8dc3e618 100644
--- a/orchestrator-restapi/pom.xml
+++ b/orchestrator-restapi/pom.xml
@@ -22,6 +22,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>jaxrs_utils</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson2.version}</version>
diff --git a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java
index a71db5b2749..2ddf05777ae 100644
--- a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java
+++ b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/HostApi.java
@@ -2,8 +2,11 @@
package com.yahoo.vespa.orchestrator.restapi;
import com.yahoo.vespa.orchestrator.restapi.wire.GetHostResponse;
+import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostRequest;
+import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostResponse;
import com.yahoo.vespa.orchestrator.restapi.wire.UpdateHostResponse;
+import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
@@ -37,6 +40,15 @@ public interface HostApi {
GetHostResponse getHost(@PathParam("hostname") String hostNameString);
/**
+ * Tweak internal Orchestrator state for host.
+ */
+ @PUT
+ @Path("/{hostname}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ PatchHostResponse patch(@PathParam("hostname") String hostNameString, PatchHostRequest request);
+
+ /**
* Ask for permission to temporarily suspend all services on a host.
*
* On success, none, some, or all services on the host may already have been effectively suspended,
diff --git a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostRequest.java b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostRequest.java
new file mode 100644
index 00000000000..6ce029e7f9c
--- /dev/null
+++ b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostRequest.java
@@ -0,0 +1,13 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.orchestrator.restapi.wire;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PatchHostRequest {
+ /** String representation of HostStatus enum value. */
+ @JsonProperty public String state;
+}
diff --git a/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostResponse.java b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostResponse.java
new file mode 100644
index 00000000000..f7468fe5907
--- /dev/null
+++ b/orchestrator-restapi/src/main/java/com/yahoo/vespa/orchestrator/restapi/wire/PatchHostResponse.java
@@ -0,0 +1,13 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.orchestrator.restapi.wire;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PatchHostResponse {
+ /** Description of the HTTP response status code. */
+ @JsonProperty public String description;
+}
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java
index 1a1ffe13b37..6925ee26ccd 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/Orchestrator.java
@@ -41,6 +41,8 @@ public interface Orchestrator {
*/
HostStatus getNodeStatus(HostName hostName) throws HostNameNotFoundException;
+ void setNodeStatus(HostName hostName, HostStatus state) throws OrchestrationException;
+
/**
* Resume normal operation for this host.
*
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java
index 5cd5f0ab638..23d723b84e2 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/OrchestratorImpl.java
@@ -83,7 +83,15 @@ public class OrchestratorImpl implements Orchestrator {
@Override
public HostStatus getNodeStatus(HostName hostName) throws HostNameNotFoundException {
- return getNodeStatus(getApplicationInstance(hostName).reference(),hostName);
+ return getNodeStatus(getApplicationInstance(hostName).reference(), hostName);
+ }
+
+ @Override
+ public void setNodeStatus(HostName hostName, HostStatus status) throws OrchestrationException {
+ ApplicationInstanceReference reference = getApplicationInstance(hostName).reference();
+ try (MutableStatusRegistry statusRegistry = statusService.lockApplicationInstance_forCurrentThreadOnly(reference)) {
+ statusRegistry.setHostState(hostName, status);
+ }
}
@Override
diff --git a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
index c6e9e5415ce..54f1723c914 100644
--- a/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
+++ b/orchestrator/src/main/java/com/yahoo/vespa/orchestrator/resources/HostResource.java
@@ -5,17 +5,23 @@ import com.yahoo.container.jaxrs.annotation.Component;
import com.yahoo.log.LogLevel;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.orchestrator.HostNameNotFoundException;
+import com.yahoo.vespa.orchestrator.OrchestrationException;
import com.yahoo.vespa.orchestrator.Orchestrator;
import com.yahoo.vespa.orchestrator.policy.HostStateChangeDeniedException;
import com.yahoo.vespa.orchestrator.restapi.HostApi;
import com.yahoo.vespa.orchestrator.restapi.wire.GetHostResponse;
import com.yahoo.vespa.orchestrator.restapi.wire.HostStateChangeDenialReason;
+import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostRequest;
+import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostResponse;
import com.yahoo.vespa.orchestrator.restapi.wire.UpdateHostResponse;
import com.yahoo.vespa.orchestrator.status.HostStatus;
import javax.inject.Inject;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -48,6 +54,35 @@ public class HostResource implements HostApi {
}
@Override
+ public PatchHostResponse patch(@PathParam("hostname") String hostNameString, PatchHostRequest request) {
+ HostName hostName = new HostName(hostNameString);
+
+ if (request.state != null) {
+ HostStatus state;
+ try {
+ state = HostStatus.valueOf(request.state);
+ } catch (IllegalArgumentException dummy) {
+ throw new BadRequestException("Bad state in request: '" + request.state + "'");
+ }
+
+ try {
+ orchestrator.setNodeStatus(hostName, state);
+ } catch (HostNameNotFoundException e) {
+ log.log(LogLevel.INFO, "Host not found: " + hostName);
+ throw new NotFoundException(e);
+ } catch (OrchestrationException e) {
+ String message = "Failed to set " + hostName + " to " + state + ": " + e.getMessage();
+ log.log(LogLevel.INFO, message, e);
+ throw new InternalServerErrorException(message);
+ }
+ }
+
+ PatchHostResponse response = new PatchHostResponse();
+ response.description = "ok";
+ return response;
+ }
+
+ @Override
public UpdateHostResponse suspend(String hostNameString) {
HostName hostName = new HostName(hostNameString);
try {
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java
index ccee70630af..448ae78a21a 100644
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java
@@ -218,6 +218,15 @@ public class OrchestratorImplTest {
}
@Test
+ public void testSetNodeState() throws OrchestrationException {
+ assertEquals(HostStatus.NO_REMARKS, orchestrator.getNodeStatus(app1_host1));
+ orchestrator.setNodeStatus(app1_host1, HostStatus.ALLOWED_TO_BE_DOWN);
+ assertEquals(HostStatus.ALLOWED_TO_BE_DOWN, orchestrator.getNodeStatus(app1_host1));
+ orchestrator.setNodeStatus(app1_host1, HostStatus.NO_REMARKS);
+ assertEquals(HostStatus.NO_REMARKS, orchestrator.getNodeStatus(app1_host1));
+ }
+
+ @Test
public void rollbackWorks() throws Exception {
// A spy is preferential because suspendAll() relies on delegating the hard work to suspend() and resume().
OrchestratorImpl orchestrator = spy(this.orchestrator);
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java
index 3d3117f9e07..aecfd79e505 100644
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostResourceTest.java
@@ -7,6 +7,8 @@ import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.applicationmodel.TenantId;
import com.yahoo.vespa.orchestrator.InstanceLookupService;
+import com.yahoo.vespa.orchestrator.OrchestrationException;
+import com.yahoo.vespa.orchestrator.Orchestrator;
import com.yahoo.vespa.orchestrator.OrchestratorImpl;
import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactoryMock;
import com.yahoo.vespa.orchestrator.model.ApplicationApi;
@@ -14,6 +16,8 @@ import com.yahoo.vespa.orchestrator.policy.HostStateChangeDeniedException;
import com.yahoo.vespa.orchestrator.policy.Policy;
import com.yahoo.vespa.orchestrator.restapi.wire.BatchHostSuspendRequest;
import com.yahoo.vespa.orchestrator.restapi.wire.BatchOperationResult;
+import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostRequest;
+import com.yahoo.vespa.orchestrator.restapi.wire.PatchHostResponse;
import com.yahoo.vespa.orchestrator.restapi.wire.UpdateHostResponse;
import com.yahoo.vespa.orchestrator.status.ApplicationInstanceStatus;
import com.yahoo.vespa.orchestrator.status.HostStatus;
@@ -22,6 +26,8 @@ import com.yahoo.vespa.orchestrator.status.StatusService;
import com.yahoo.vespa.service.monitor.ServiceMonitorStatus;
import org.junit.Test;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.WebApplicationException;
import java.util.Arrays;
import java.util.Collections;
@@ -31,9 +37,13 @@ import java.util.Set;
import static com.yahoo.vespa.orchestrator.TestUtil.makeServiceClusterSet;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class HostResourceTest {
@@ -262,4 +272,43 @@ public class HostResourceTest {
assertThat(w.getResponse().getStatus()).isEqualTo(409);
}
}
+
+ @Test(expected = BadRequestException.class)
+ public void patch_state_may_throw_bad_request() {
+ Orchestrator orchestrator = mock(Orchestrator.class);
+ HostResource hostResource = new HostResource(orchestrator);
+
+ String hostNameString = "hostname";
+ PatchHostRequest request = new PatchHostRequest();
+ request.state = "bad state";
+
+ hostResource.patch(hostNameString, request);
+ }
+
+ @Test
+ public void patch_works() throws OrchestrationException {
+ Orchestrator orchestrator = mock(Orchestrator.class);
+ HostResource hostResource = new HostResource(orchestrator);
+
+ String hostNameString = "hostname";
+ PatchHostRequest request = new PatchHostRequest();
+ request.state = "NO_REMARKS";
+
+ PatchHostResponse response = hostResource.patch(hostNameString, request);
+ assertEquals(response.description, "ok");
+ verify(orchestrator, times(1)).setNodeStatus(new HostName(hostNameString), HostStatus.NO_REMARKS);
+ }
+
+ @Test(expected = InternalServerErrorException.class)
+ public void patch_handles_exception_in_orchestrator() throws OrchestrationException {
+ Orchestrator orchestrator = mock(Orchestrator.class);
+ HostResource hostResource = new HostResource(orchestrator);
+
+ String hostNameString = "hostname";
+ PatchHostRequest request = new PatchHostRequest();
+ request.state = "NO_REMARKS";
+
+ doThrow(new OrchestrationException("error")).when(orchestrator).setNodeStatus(new HostName(hostNameString), HostStatus.NO_REMARKS);
+ hostResource.patch(hostNameString, request);
+ }
}