mirror of https://github.com/apache/jclouds.git
Extends JClouds' OpenStack Nova API with the Diagnostics command
The diagnostics command returns a collection of system information for the a given server. At the moment, there is no formal specification for this command. Therefore, it is returned as a Map of hypervisor specific entries and corresponding values. More information about the command can be viewed here [1] in the section "Server Diagnostics". [1] http://api.openstack.org/api-ref.html
This commit is contained in:
parent
718874e348
commit
99375844a6
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.features;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -260,5 +261,24 @@ public interface ServerApi {
|
|||
* the name of the metadata item
|
||||
*/
|
||||
void deleteMetadata(String id, String key);
|
||||
|
||||
|
||||
/**
|
||||
* Get usage information about the server such as CPU usage, Memory and IO.
|
||||
* The information returned by this method is dependent on the hypervisor
|
||||
* in use by the OpenStack installation and whether that hypervisor supports
|
||||
* this method. More information can be found in the
|
||||
* <a href="http://api.openstack.org/api-ref.html"> OpenStack API
|
||||
* reference</a>. <br/>
|
||||
* At the moment the returned response is a generic map. In future versions
|
||||
* of OpenStack this might be subject to change.
|
||||
*
|
||||
* @param id
|
||||
* id of the server
|
||||
* @return A Map containing the collected values organized by key - value.
|
||||
* @Beta
|
||||
*/
|
||||
Optional<Map<String, String>> getDiagnostics(String id);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.features;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
|
@ -63,8 +64,10 @@ import org.jclouds.rest.functions.ReturnEmptyPagedIterableOnNotFoundOr404;
|
|||
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnAbsentOn403Or404Or500;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import org.jclouds.openstack.nova.v2_0.functions.internal.*;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Server via their REST API.
|
||||
|
@ -319,4 +322,14 @@ public interface ServerAsyncApi {
|
|||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||
ListenableFuture<Void> deleteMetadata(@PathParam("id") String id, @PathParam("key") String key);
|
||||
|
||||
|
||||
/**
|
||||
* @see ServerApi#getDiagnostics
|
||||
*/
|
||||
@GET
|
||||
@Path("/servers/{id}/diagnostics")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@ExceptionParser(ReturnAbsentOn403Or404Or500.class)
|
||||
@ResponseParser(ParseDiagnostics.class)
|
||||
ListenableFuture<Optional<Map<String, String>>> getDiagnostics(@PathParam("id") String id);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2012 jclouds.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.functions.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.functions.ParseJson;
|
||||
import org.jclouds.json.internal.GsonWrapper;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Leander Beernaert
|
||||
*/
|
||||
public class ParseDiagnostics implements Function<HttpResponse, Optional <Map<String,String>>> {
|
||||
|
||||
|
||||
private final ParseJson<Optional <Map<String,String>>> parser;
|
||||
|
||||
@Inject
|
||||
public ParseDiagnostics(ParseJson<Optional <Map<String,String>>> parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional <Map<String,String>> apply(HttpResponse response) {
|
||||
checkNotNull(response, "response");
|
||||
return parser.apply(response);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,6 +36,7 @@ import org.testng.annotations.Test;
|
|||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.jclouds.openstack.nova.v2_0.parse.*;
|
||||
|
||||
/**
|
||||
* Tests annotation parsing of {@code ServerAsyncApi}
|
||||
|
@ -577,4 +578,46 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
|
|||
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").deleteMetadata(serverId, key);
|
||||
|
||||
}
|
||||
|
||||
public void testGetDiagnosticsWhenResponseIs200() throws Exception {
|
||||
|
||||
String serverId = "123";
|
||||
HttpRequest getDiagnostics = HttpRequest
|
||||
.builder()
|
||||
.method("GET")
|
||||
.addHeader("Accept", "application/json")
|
||||
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/"+ serverId + "/diagnostics")
|
||||
.addHeader("X-Auth-Token", authToken)
|
||||
.build();
|
||||
|
||||
|
||||
HttpResponse serverDiagnosticsResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
|
||||
.payload(payloadFromResourceWithContentType("/server_diagnostics.json","application/json; charset=UTF-8")).build();
|
||||
|
||||
NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
|
||||
responseWithKeystoneAccess, getDiagnostics, serverDiagnosticsResponse);
|
||||
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").getDiagnostics(serverId),
|
||||
new ParseServerDiagnostics().expected());
|
||||
}
|
||||
|
||||
|
||||
public void testGetDiagnosticsWhenResponseIs403Or404Or500() throws Exception {
|
||||
|
||||
String serverId = "123";
|
||||
HttpRequest getDiagnostics = HttpRequest
|
||||
.builder()
|
||||
.method("GET")
|
||||
.addHeader("Accept", "application/json")
|
||||
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/"+ serverId + "/diagnostics")
|
||||
.addHeader("X-Auth-Token", authToken)
|
||||
.build();
|
||||
|
||||
for (int statusCode : ImmutableSet.of(403, 404, 500)) {
|
||||
assertTrue(!requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess, getDiagnostics,
|
||||
HttpResponse.builder().statusCode(statusCode).build()).getServerApiForZone("az-1.region-a.geo-1").getDiagnostics(serverId).isPresent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.parse;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import org.jclouds.json.BaseItemParserTest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leander Beernaert
|
||||
*/
|
||||
public class ParseServerDiagnostics extends BaseItemParserTest<Optional<Map<String,String>>> {
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<Map<String,String>> expected() {
|
||||
return Optional.<Map<String,String>>of(
|
||||
new ImmutableMap.Builder<String,String>()
|
||||
.put("vnet0_tx_errors", "0")
|
||||
.put("vda_read","77364736")
|
||||
.put("vda_write","415446016")
|
||||
.put("vnet0_tx_packets","9701")
|
||||
.put("vda_write_req","47278")
|
||||
.put("cpu0_time","143150000000")
|
||||
.put("vnet0_tx","1691221")
|
||||
.put("vnet0_rx_drop","0")
|
||||
.put("vda_errors","-1")
|
||||
.put("vnet0_rx_errors","0")
|
||||
.put("memory","524288")
|
||||
.put("vnet0_rx_packets","11271")
|
||||
.put("vda_read_req","9551")
|
||||
.put("vnet0_rx","1805288")
|
||||
.put("vnet0_tx_drop","0").build());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"vnet0_tx_errors": 0,
|
||||
"vda_read": 77364736,
|
||||
"vda_write": 415446016,
|
||||
"vnet0_tx_packets": 9701,
|
||||
"vda_write_req": 47278,
|
||||
"cpu0_time": 143150000000,
|
||||
"vnet0_tx": 1691221,
|
||||
"vnet0_rx_drop": 0,
|
||||
"vda_errors": -1,
|
||||
"vnet0_rx_errors": 0,
|
||||
"memory": 524288,
|
||||
"vnet0_rx_packets": 11271,
|
||||
"vda_read_req": 9551,
|
||||
"vnet0_rx": 1805288,
|
||||
"vnet0_tx_drop": 0
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.rest.functions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.primitives.Ints;
|
||||
import javax.inject.Singleton;
|
||||
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leander Beernaert
|
||||
*/
|
||||
@Singleton
|
||||
public class ReturnAbsentOn403Or404Or500 implements Function<Exception, Object> {
|
||||
|
||||
|
||||
public Object apply(Exception from) {
|
||||
Boolean returnVal = returnValueOnCodeOrNull(from, true, Predicates.in(Ints.asList(403, 404, 500)));
|
||||
if (returnVal != null)
|
||||
return Optional.absent();
|
||||
|
||||
throw Throwables.propagate(from);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue