JCLOUDS-702: JClouds ProfitBricks provider - Storage API

This commit is contained in:
Reijhanniel Jearl Campos 2015-02-05 21:45:03 +08:00 committed by Ignasi Barrera
parent ee24ddb2b4
commit 2a219a9948
90 changed files with 3278 additions and 1092 deletions

View File

@ -21,6 +21,7 @@ import java.io.Closeable;
import org.jclouds.profitbricks.features.DataCenterApi;
import org.jclouds.profitbricks.features.ImageApi;
import org.jclouds.profitbricks.features.ServerApi;
import org.jclouds.profitbricks.features.StorageApi;
import org.jclouds.rest.annotations.Delegate;
public interface ProfitBricksApi extends Closeable {
@ -33,4 +34,7 @@ public interface ProfitBricksApi extends Closeable {
@Delegate
ServerApi serverApi();
@Delegate
StorageApi storageApi();
}

View File

@ -55,11 +55,11 @@ public abstract class BaseProfitBricksRequestBinder<T> implements MapBinder {
protected abstract String createPayload(T payload);
protected String formatIfNotEmpty(String pattern, Object param) {
protected static String formatIfNotEmpty(String pattern, Object param) {
return Strings.isNullOrEmpty(nullableToString(param)) ? "" : String.format(pattern, param);
}
protected String nullableToString(Object object) {
protected static String nullableToString(Object object) {
return object == null ? "" : object.toString();
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.binder.storage;
import static java.lang.String.format;
import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
import org.jclouds.profitbricks.domain.Storage;
public class ConnectStorageToServerRequestBinder extends BaseProfitBricksRequestBinder<Storage.Request.ConnectPayload> {
protected final StringBuilder requestBuilder;
ConnectStorageToServerRequestBinder() {
super("storage");
this.requestBuilder = new StringBuilder(128 * 2);
}
@Override
protected String createPayload(Storage.Request.ConnectPayload payload) {
requestBuilder.append("<ws:connectStorageToServer>")
.append("<request>")
.append(format("<storageId>%s</storageId>", payload.storageId()))
.append(format("<serverId>%s</serverId>", payload.serverId()))
.append(formatIfNotEmpty("<busType>%s</busType>", payload.busType()))
.append(formatIfNotEmpty("<deviceNumber>%s</deviceNumber>", payload.deviceNumber()))
.append("</request>")
.append("</ws:connectStorageToServer>");
return requestBuilder.toString();
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.binder.storage;
import static java.lang.String.format;
import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
import org.jclouds.profitbricks.domain.Storage;
public class CreateStorageRequestBinder extends BaseProfitBricksRequestBinder<Storage.Request.CreatePayload> {
protected final StringBuilder requestBuilder;
CreateStorageRequestBinder() {
super("storage");
this.requestBuilder = new StringBuilder(128 * 2);
}
@Override
protected String createPayload(Storage.Request.CreatePayload payload) {
requestBuilder.append("<ws:createStorage>")
.append("<request>")
.append(format("<dataCenterId>%s</dataCenterId>", payload.dataCenterId()))
.append(formatIfNotEmpty("<storageName>%s</storageName>", payload.name()))
.append(format("<size>%.0f</size>", payload.size()))
.append(formatIfNotEmpty("<mountImageId>%s</mountImageId>", payload.mountImageId()))
.append(formatIfNotEmpty("<profitBricksImagePassword>%s</profitBricksImagePassword>", payload.profitBricksImagePassword()))
.append("</request>")
.append("</ws:createStorage>");
return requestBuilder.toString();
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.binder.storage;
import static java.lang.String.format;
import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
import org.jclouds.profitbricks.domain.Storage;
public class UpdateStorageRequestBinder extends BaseProfitBricksRequestBinder<Storage.Request.UpdatePayload> {
protected final StringBuilder requestBuilder;
UpdateStorageRequestBinder() {
super("storage");
this.requestBuilder = new StringBuilder(128 * 2);
}
@Override
protected String createPayload(Storage.Request.UpdatePayload payload) {
requestBuilder
.append("<ws:updateStorage>")
.append("<request>")
.append(format("<storageId>%s</storageId>", payload.id()))
.append(formatIfNotEmpty("<size>%.0f</size>", payload.size()))
.append(formatIfNotEmpty("<storageName>%s</storageName>", payload.name()))
.append(formatIfNotEmpty("<mountImageId>%s</mountImageId>", payload.mountImageId()))
.append("</request>")
.append("</ws:updateStorage>");
return requestBuilder.toString();
}
}

View File

@ -23,5 +23,5 @@ package org.jclouds.profitbricks.compute.internal;
*/
public enum ProvisioningStatusAware {
DATACENTER, SERVER;
DATACENTER, SERVER, STORAGE;
}

View File

@ -26,9 +26,8 @@ import com.google.common.base.Predicate;
/**
* A custom predicate for waiting until a virtual resource satisfies the given expected status
* <p>
* Performing api requests on a datacenter that is not {@link ProvisioningState#AVAILABLE} is not allowed. On some
* cases, the API user gets blocked from further requests, and will then need to contact tech support for api lock
* release.
* Performing api requests on a datacenter that is not {@link ProvisioningState#AVAILABLE} is not allowed. On some cases, the API user gets
* blocked from further requests, and will then need to contact tech support for api lock release.
*/
public class ProvisioningStatusPollingPredicate implements Predicate<String> {
@ -50,6 +49,8 @@ public class ProvisioningStatusPollingPredicate implements Predicate<String> {
return expect == api.dataCenterApi().getDataCenterState(input);
case SERVER:
return expect == api.serverApi().getServer(input).state();
case STORAGE:
return expect == api.storageApi().getStorage(input).state();
default:
throw new IllegalArgumentException("Unknown domain '" + domain + "'");
}

View File

@ -19,30 +19,43 @@ package org.jclouds.profitbricks.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import java.util.List;
import java.util.regex.Pattern;
import org.jclouds.javax.annotation.Nullable;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@AutoValue
public abstract class DataCenter {
public abstract String id();
@Nullable public abstract String name();
@Nullable
public abstract String name();
public abstract int version();
@Nullable public abstract ProvisioningState state();
@Nullable
public abstract ProvisioningState state();
@Nullable public abstract Location location();
@Nullable
public abstract Location location();
// @Nullable public abstract List<Server> servers();
// @Nullable public abstract List<Storage> storages();
@Nullable
public abstract List<Server> servers();
@Nullable
public abstract List<Storage> storages();
// @Nullable public abstract List<LoadBalancer> loadBalancers();
public static DataCenter create(String id, String name, int version, ProvisioningState state, Location location) {
return new AutoValue_DataCenter(id, name, version, state, location);
public static DataCenter create(String id, String name, int version, ProvisioningState state, Location location, List<Server> servers,
List<Storage> storages) {
return new AutoValue_DataCenter(id, name, version, state, location,
servers != null ? ImmutableList.copyOf(servers) : Lists.<Server>newArrayList(),
storages != null ? ImmutableList.copyOf(storages) : Lists.<Storage>newArrayList());
}
public static Builder builder() {
@ -60,8 +73,8 @@ public abstract class DataCenter {
private ProvisioningState state;
private Location location;
private int version;
// private List<Server> servers;
// private List<Storage> storage;
private List<Server> servers;
private List<Storage> storages;
// private List<LoadBalancer> loadBalancer;
public Builder id(String id) {
@ -89,12 +102,23 @@ public abstract class DataCenter {
return this;
}
public Builder servers(List<Server> servers) {
this.servers = servers;
return this;
}
public Builder storages(List<Storage> storages) {
this.storages = storages;
return this;
}
public DataCenter build() {
return DataCenter.create(id, name, version, state, location);
return DataCenter.create(id, name, version, state, location, servers, storages);
}
public Builder fromDataCenter(DataCenter in) {
return this.id(in.id()).name(in.name()).version(in.version()).state(in.state()).location(in.location());
return this.id(in.id()).name(in.name()).version(in.version()).state(in.state()).location(in.location()).servers(in.servers())
.storages(in.storages());
}
}

View File

@ -17,12 +17,20 @@
package org.jclouds.profitbricks.domain;
import org.jclouds.profitbricks.domain.internal.ServerCommonProperties;
import com.google.auto.value.AutoValue;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.List;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@AutoValue
public abstract class Server implements ServerCommonProperties {
@ -70,13 +78,17 @@ public abstract class Server implements ServerCommonProperties {
@Nullable
public abstract Date lastModificationTime();
// public abstract List<Storage> storages();
// public abstract List<Nic> storages();
@Nullable
public abstract List<Storage> storages();
// public abstract List<Nic> nics();
public static Server create(String id, String name, int cores, int ram, Boolean hasInternetAccess, ProvisioningState state,
Status status, OsType osType, AvailabilityZone availabilityZone, Date creationTime, Date lastModificationTime, Boolean isCpuHotPlug,
Boolean isRamHotPlug, Boolean isNicHotPlug, Boolean isNicHotUnPlug, Boolean isDiscVirtioHotPlug, Boolean isDiscVirtioHotUnPlug ) {
Status status, OsType osType, AvailabilityZone availabilityZone, Date creationTime, Date lastModificationTime,
List<Storage> storages, Boolean isCpuHotPlug, Boolean isRamHotPlug, Boolean isNicHotPlug, Boolean isNicHotUnPlug,
Boolean isDiscVirtioHotPlug, Boolean isDiscVirtioHotUnPlug) {
return new AutoValue_Server(isCpuHotPlug, isRamHotPlug, isNicHotPlug, isNicHotUnPlug, isDiscVirtioHotPlug, isDiscVirtioHotUnPlug,
cores, ram, id, name, hasInternetAccess, state, status, osType, availabilityZone, creationTime, lastModificationTime );
cores, ram, id, name, hasInternetAccess, state, status, osType, availabilityZone, creationTime, lastModificationTime,
storages != null ? ImmutableList.copyOf(storages) : Lists.<Storage>newArrayList());
}
@ -161,6 +173,7 @@ public abstract class Server implements ServerCommonProperties {
private Date creationTime;
private Date lastModificationTime;
private Boolean hasInternetAccess;
private List<Storage> storages;
public DescribingBuilder id(String id) {
this.id = id;
@ -202,10 +215,15 @@ public abstract class Server implements ServerCommonProperties {
return this;
}
public DescribingBuilder storages(List<Storage> storages) {
this.storages = storages;
return this;
}
@Override
public Server build() {
return Server.create(id, name, cores, ram, hasInternetAccess, state, status, osType, zone, creationTime,
lastModificationTime, cpuHotPlug, ramHotPlug, nicHotPlug, nicHotUnPlug, discVirtioHotPlug, discVirtioHotUnPlug );
lastModificationTime, storages, cpuHotPlug, ramHotPlug, nicHotPlug, nicHotUnPlug, discVirtioHotPlug, discVirtioHotUnPlug);
}
private DescribingBuilder fromServer(Server in) {
@ -213,7 +231,7 @@ public abstract class Server implements ServerCommonProperties {
.isCpuHotPlug(in.isCpuHotPlug()).isDiscVirtioHotPlug(in.isDiscVirtioHotPlug()).isDiscVirtioHotUnPlug(in.isDiscVirtioHotUnPlug())
.isNicHotPlug(in.isNicHotPlug()).isNicHotUnPlug(in.isNicHotUnPlug()).isRamHotPlug(in.isRamHotPlug())
.lastModificationTime(in.lastModificationTime()).name(in.name()).osType(in.osType()).ram(in.ram()).state(in.state())
.status( in.status() );
.status(in.status()).storages(in.storages());
}
@Override

View File

@ -0,0 +1,355 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.domain;
import com.google.auto.value.AutoValue;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.List;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@AutoValue
public abstract class Storage {
public enum BusType {
IDE, SCSI, VIRTIO, UNRECOGNIZED;
public static BusType fromValue(String value) {
try {
return valueOf(value);
} catch (IllegalArgumentException ex) {
return UNRECOGNIZED;
}
}
}
public abstract String id();
@Nullable
public abstract String name();
public abstract float size(); // GB
@Nullable
public abstract Date creationTime();
@Nullable
public abstract Date lastModificationTime();
public abstract ProvisioningState state();
@Nullable
public abstract List<String> serverIds();
@Nullable
public abstract Boolean bootDevice();
@Nullable
public abstract BusType busType();
@Nullable
public abstract Integer deviceNumber();
public static Storage create(String id, String name, float size, Date creationTime, Date lastModificationTime,
ProvisioningState state, List<String> serverIds, Boolean bootDevice, BusType busType, Integer deviceNumber) {
return new AutoValue_Storage(id, name, size, creationTime, lastModificationTime, state,
serverIds != null ? ImmutableList.copyOf(serverIds) : Lists.<String>newArrayList(),
bootDevice, busType, deviceNumber);
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromStorage(this);
}
public static class Builder {
private String id;
private String name;
private float size;
private Date creationTime;
private Date lastModificationTime;
private ProvisioningState state;
private List<String> serverIds;
private Boolean bootDevice;
private BusType busType;
private Integer deviceNumber;
public Builder id(String id) {
this.id = id;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder size(float size) {
this.size = size;
return this;
}
public Builder creationTime(Date creationTime) {
this.creationTime = creationTime;
return this;
}
public Builder lastModificationTime(Date lastModificationTime) {
this.lastModificationTime = lastModificationTime;
return this;
}
public Builder state(ProvisioningState state) {
this.state = state;
return this;
}
public Builder serverIds(List<String> serverIds) {
this.serverIds = serverIds;
return this;
}
public Builder bootDevice(Boolean bootDevice) {
this.bootDevice = bootDevice;
return this;
}
public Builder busType(BusType busType) {
this.busType = busType;
return this;
}
public Builder deviceNumber(Integer deviceNumber) {
this.deviceNumber = deviceNumber;
return this;
}
private Builder fromStorage(Storage in) {
return this.id(in.id()).name(in.name()).size(in.size()).creationTime(in.creationTime())
.lastModificationTime(in.lastModificationTime()).state(in.state()).serverIds(in.serverIds())
.bootDevice(in.bootDevice()).busType(in.busType()).deviceNumber(in.deviceNumber());
}
public Storage build() {
return Storage.create(id, name, size, creationTime, lastModificationTime, state, serverIds, bootDevice, busType, deviceNumber);
}
}
public static final class Request {
public static CreatePayload.Builder creatingBuilder() {
return new CreatePayload.Builder();
}
public static UpdatePayload.Builder updatingBuilder() {
return new UpdatePayload.Builder();
}
public static ConnectPayload.Builder connectingBuilder() {
return new ConnectPayload.Builder();
}
@AutoValue
public abstract static class CreatePayload {
public abstract String dataCenterId();
public abstract float size();
@Nullable
public abstract String name();
@Nullable
public abstract String mountImageId();
@Nullable
public abstract String profitBricksImagePassword();
public static CreatePayload create(String dataCenterId, float size, String name, String mountImageId, String imagePassword) {
validateSize(size);
return new AutoValue_Storage_Request_CreatePayload(dataCenterId, size, name, mountImageId, imagePassword);
}
public static class Builder {
private String dataCenterId;
private float size;
private String name;
private String mountImageId;
private String profitBricksImagePassword;
public Builder dataCenterId(String dataCenterId) {
this.dataCenterId = dataCenterId;
return this;
}
public Builder dataCenterId(DataCenter dataCenter) {
this.dataCenterId = checkNotNull(dataCenter, "Cannot pass null datacenter").id();
return this;
}
public Builder size(float size) {
this.size = size;
return this;
}
public Builder mountImageId(String mountImageId) {
this.mountImageId = mountImageId;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder imagePassword(String password) {
this.profitBricksImagePassword = password;
return this;
}
public CreatePayload build() {
return CreatePayload.create(dataCenterId, size, name, mountImageId, profitBricksImagePassword);
}
}
}
@AutoValue
public abstract static class UpdatePayload {
public abstract String id();
@Nullable
public abstract Float size();
@Nullable
public abstract String name();
@Nullable
public abstract String mountImageId();
public static UpdatePayload create(String id, Float size, String name, String mountImageId) {
validateSize(size);
return new AutoValue_Storage_Request_UpdatePayload(id, size, name, mountImageId);
}
public static class Builder {
private String id;
private Float size;
private String name;
private String mountImageId;
public Builder id(String id) {
this.id = id;
return this;
}
public Builder size(float size) {
this.size = size;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder mountImageId(String mountImageId) {
this.mountImageId = mountImageId;
return this;
}
public UpdatePayload build() {
return UpdatePayload.create(id, size, name, mountImageId);
}
}
}
@AutoValue
public abstract static class ConnectPayload {
public abstract String storageId();
public abstract String serverId();
@Nullable
public abstract BusType busType();
@Nullable
public abstract Integer deviceNumber();
public static ConnectPayload create(String storageId, String serverId, BusType busType, Integer deviceNumber) {
return new AutoValue_Storage_Request_ConnectPayload(storageId, serverId, busType, deviceNumber);
}
public static class Builder {
private String storageId;
private String serverId;
private BusType busType;
private Integer deviceNumber;
public Builder storageId(String storageId) {
this.storageId = storageId;
return this;
}
public Builder serverId(String serverId) {
this.serverId = serverId;
return this;
}
public Builder busType(BusType busType) {
this.busType = busType;
return this;
}
public Builder deviceNumber(Integer deviceNumber) {
this.deviceNumber = deviceNumber;
return this;
}
public ConnectPayload build() {
return ConnectPayload.create(storageId, serverId, busType, deviceNumber);
}
}
}
private static void validateSize(Float size) {
if (size != null)
checkArgument(size > 1, "Storage size must be > 1GB");
}
}
}

View File

@ -58,8 +58,7 @@ public interface DataCenterApi {
/**
* @param identifier Data Center identifier
* @return Returns information about an existing virtual data center's state and configuration or <code>null</code>
* if it doesn't exist.
* @return Returns information about an existing virtual data center's state and configuration or <code>null</code> if it doesn't exist.
*/
@POST
@Named("datacenter:get")
@ -69,8 +68,8 @@ public interface DataCenterApi {
DataCenter getDataCenter(@PayloadParam("id") String identifier);
/**
* This is a lightweight function for polling the current provisioning state of the Virtual Data Center. It is
* recommended to use this function for large Virtual Data Centers to query request results.
* This is a lightweight function for polling the current provisioning state of the Virtual Data Center. It is recommended to use this
* function for large Virtual Data Centers to query request results.
* <p>
* @param identifier Data Center identifier
*/
@ -119,9 +118,8 @@ public interface DataCenterApi {
DataCenter clearDataCenter(@PayloadParam("id") String identifier);
/**
* Deletes an Virtual Data Center. If a previous request on the target data center is still in progress, the data
* center is going to be deleted after this request has been completed. Once a Data Center has been deleted, no
* further request can be performed on it.
* Deletes an Virtual Data Center. If a previous request on the target data center is still in progress, the data center is going to be
* deleted after this request has been completed. Once a Data Center has been deleted, no further request can be performed on it.
* <p>
* @param identifier Identifier of the virtual data center
* @return Returns a boolean indicating whether delete operation was made

View File

@ -140,7 +140,7 @@ public interface ServerApi {
/**
* Updates parameters of an existing virtual server device.
*
* @param payload Paylaod
* @param payload Payload
* @return Identifier of current request
*/
@POST

View File

@ -0,0 +1,136 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.features;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.profitbricks.binder.storage.ConnectStorageToServerRequestBinder;
import org.jclouds.profitbricks.binder.storage.CreateStorageRequestBinder;
import org.jclouds.profitbricks.binder.storage.UpdateStorageRequestBinder;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.profitbricks.http.filters.ProfitBricksSoapMessageEnvelope;
import org.jclouds.profitbricks.http.parser.RequestIdOnlyResponseHandler;
import org.jclouds.profitbricks.http.parser.storage.StorageIdOnlyResponseHandler;
import org.jclouds.profitbricks.http.parser.storage.StorageInfoResponseHandler;
import org.jclouds.profitbricks.http.parser.storage.StorageListResponseHandler;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser;
@RequestFilters({BasicAuthentication.class, ProfitBricksSoapMessageEnvelope.class})
@Consumes(MediaType.TEXT_XML)
@Produces(MediaType.TEXT_XML)
public interface StorageApi {
/**
*
* @return Returns information about all virtual storage, such as configuration and provisioning state.
*/
@POST
@Named("storage:getall")
@Payload("<ws:getAllStorages/>")
@XMLResponseParser(StorageListResponseHandler.class)
@Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
List<Storage> getAllStorages();
/**
*
* @param id Storage identifier
* @return Returns information about a virtual storages configuration and provisioning state.
*/
@POST
@Named("storage:get")
@Payload("<ws:getStorage><storageId>{id}</storageId></ws:getStorage>")
@XMLResponseParser(StorageInfoResponseHandler.class)
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
Storage getStorage(@PayloadParam("id") String id);
/**
* Creates a virtual storage within an existing virtual data center. Additional parameters can be specified, e.g. for assigning a HDD
* image to the storage.
*
* @param payload Payload
* @return storageId of the created storage
*/
@POST
@Named("storage:create")
@MapBinder(CreateStorageRequestBinder.class)
@XMLResponseParser(StorageIdOnlyResponseHandler.class)
String createStorage(@PayloadParam("storage") Storage.Request.CreatePayload payload);
/**
* Updates parameters of an existing virtual storage device. It is possible to increase the storage size without reboot of an already
* provisioned storage. The additional capacity is not added to any partition. You have to partition the storage afterwards. Vice versa,
* it is not possible to decrease the storage size of an already provisioned storage.
*
* @param payload Payload
* @return Identifier of current request
*/
@POST
@Named("storage:update")
@MapBinder(UpdateStorageRequestBinder.class)
@XMLResponseParser(RequestIdOnlyResponseHandler.class)
String updateStorage(@PayloadParam("storage") Storage.Request.UpdatePayload payload);
/**
* Deletes an existing virtual storage device.
*
* @param id Identifier of the target virtual storage
* @return Identifier of current request
*/
@POST
@Named("storage:delete")
@Payload("<ws:deleteStorage><storageId>{id}</storageId></ws:deleteStorage>")
@Fallback(Fallbacks.FalseOnNotFoundOr404.class)
boolean deleteStorage(@PayloadParam("id") String id);
/**
* Connects a virtual storage device to an existing server.
*
* @param payload Payload
* @return Identifier of current request
*/
@POST
@Named("storage:connect")
@MapBinder(ConnectStorageToServerRequestBinder.class)
@XMLResponseParser(RequestIdOnlyResponseHandler.class)
String connectStorageToServer(@PayloadParam("storage") Storage.Request.ConnectPayload payload);
/**
* Disconnects a virtual storage device from a connected server.
*
* @param storageId Identifier of the connected virtual storage
* @param serverId Identifier of the connected virtual server
* @return Identifier of current request
*/
@POST
@Named("storage:disconnect")
@Payload("<ws:disconnectStorageFromServer><storageId>{storageId}</storageId><serverId>{serverId}</serverId></ws:disconnectStorageFromServer>")
@XMLResponseParser(RequestIdOnlyResponseHandler.class)
String disconnectStorageFromServer(@PayloadParam("storageId") String storageId, @PayloadParam("serverId") String serverId);
}

View File

@ -23,6 +23,7 @@ import javax.inject.Singleton;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InsufficientResourcesException;
import org.jclouds.rest.ResourceNotFoundException;
@ -46,7 +47,7 @@ public class ProfitBricksHttpErrorHandler implements HttpErrorHandler {
exception = new IllegalArgumentException(response.getMessage(), exception);
break;
case 401:
exception = new AuthorizationException(response.getMessage(), exception);
exception = new AuthorizationException("This request requires authentication.", exception);
break;
case 402:
case 409:
@ -59,6 +60,10 @@ public class ProfitBricksHttpErrorHandler implements HttpErrorHandler {
break;
case 413:
case 503:
// if nothing (default message was OK) was parsed from command executor, assume it was an 503 (Maintenance) html response.
if (response.getMessage().equals("OK"))
exception = new HttpResponseException("The ProfitBricks team is currently carrying out maintenance.", command, response);
else
exception = new InsufficientResourcesException(response.getMessage(), exception);
break;
}

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URI;
import java.util.regex.Pattern;
import javax.inject.Named;
import javax.inject.Singleton;
@ -51,14 +52,16 @@ import com.google.inject.Inject;
/**
* Custom implementation of the HTTP driver to read actual http status and message from SOAP Fault.
* <br/>
* ProfitBricks API errors are always returned with 500 HTTP code. This class parses and reads the SOAP response to map the actual http code
* and message
* ProfitBricks API errors are always returned with 500 HTTP code. This class parses and reads the SOAP response to map
* the actual http code and message
*/
@Singleton
public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrlHttpCommandExecutorService {
private final ParseSax<ServiceFault> faultHandler;
private static final Pattern endSoapTag = Pattern.compile("</.+:Envelope>$");
@Inject
ResponseStatusFromPayloadHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
@ -74,11 +77,12 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
HttpResponse originalResponse = super.invoke(connection);
HttpResponse.Builder<?> responseBuilder = originalResponse.toBuilder();
if (hasPayload(originalResponse) && hasServerError(originalResponse)) {
if (hasServerError(originalResponse) && hasPayload(originalResponse)) {
// As we need to read the response body to determine if there are errors, but we may need to process the body
// again later in the response parsers if everything is OK, we buffer the body into an InputStream we can reset
InputStream in = null;
InputStream originalInputStream = originalResponse.getPayload().openStream();
if (originalInputStream instanceof ByteArrayInputStream)
in = originalInputStream;
else
@ -87,13 +91,14 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
} finally {
closeQuietly(originalInputStream);
}
try {
if (isSoapPayload(in)) {
ServiceFault fault = faultHandler.parse(in);
if (fault != null)
responseBuilder
.statusCode(fault.httpCode())
.message(fault.message());
}
} catch (Exception ex) {
// ignore
} finally {
@ -119,4 +124,17 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
return response.getPayload() != null && response.getPayload().getRawContent() != null;
}
private static boolean isSoapPayload(final InputStream is) throws IOException {
int size = is.available();
char[] chars = new char[size];
byte[] bytes = new byte[size];
is.read(bytes, 0, size);
for (int i = 0; i < size;)
chars[i] = (char) (bytes[i++] & 0xff);
is.reset(); // throws premature end of file w/o this
return endSoapTag.matcher(new String(chars)).find();
}
}

View File

@ -16,23 +16,14 @@
*/
package org.jclouds.profitbricks.http.parser;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import org.jclouds.date.DateCodec;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.SAXException;
public abstract class BaseProfitBricksResponseHandler<T> extends ParseSax.HandlerForGeneratedRequestWithResult<T> {
protected final DateCodec dateCodec;
private final StringBuilder strBuilder;
public BaseProfitBricksResponseHandler(DateCodecFactory dateCodec) {
this.dateCodec = checkNotNull(checkNotNull(dateCodec, "dateCodecFactory null").iso8601(), "iso8601 date codec null");
public BaseProfitBricksResponseHandler() {
this.strBuilder = new StringBuilder();
}
@ -41,10 +32,6 @@ public abstract class BaseProfitBricksResponseHandler<T> extends ParseSax.Handle
strBuilder.append(ch, start, length);
}
protected final Date textToIso8601Date() {
return dateCodec.toDate(textToStringValue());
}
protected String textToStringValue() {
return strBuilder.toString().trim();
}

View File

@ -16,17 +16,13 @@
*/
package org.jclouds.profitbricks.http.parser;
import com.google.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.xml.sax.SAXException;
public class RequestIdOnlyResponseHandler extends BaseProfitBricksResponseHandler<String> {
private String requestId;
@Inject
RequestIdOnlyResponseHandler( DateCodecFactory dateCodec ) {
super( dateCodec );
RequestIdOnlyResponseHandler() {
}
@Override

View File

@ -16,20 +16,15 @@
*/
package org.jclouds.profitbricks.http.parser;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.ServiceFault;
import org.xml.sax.SAXException;
import com.google.inject.Inject;
public class ServiceFaultResponseHandler extends BaseProfitBricksResponseHandler<ServiceFault> {
private final ServiceFault.Builder builder;
private boolean done = false;
@Inject
ServiceFaultResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
ServiceFaultResponseHandler() {
this.builder = ServiceFault.builder();
}

View File

@ -16,9 +16,6 @@
*/
package org.jclouds.profitbricks.http.parser.datacenter;
import javax.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
@ -26,9 +23,7 @@ public abstract class BaseDataCenterResponseHandler<T> extends BaseProfitBricksR
protected DataCenter.Builder builder;
@Inject
BaseDataCenterResponseHandler(DateCodecFactory dateCodecFactory) {
super(dateCodecFactory);
BaseDataCenterResponseHandler() {
this.builder = DataCenter.builder();
}

View File

@ -16,21 +16,45 @@
*/
package org.jclouds.profitbricks.http.parser.datacenter;
import org.jclouds.date.DateCodecFactory;
import java.util.List;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.domain.Server;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.profitbricks.http.parser.server.ServerInfoResponseHandler;
import org.jclouds.profitbricks.http.parser.storage.StorageInfoResponseHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
public class DataCenterInfoResponseHandler extends BaseDataCenterResponseHandler<DataCenter> {
private final ServerInfoResponseHandler serverInfoResponseHandler;
private final StorageInfoResponseHandler storageInfoResponseHandler;
private final List<Server> servers = Lists.newArrayList();
private final List<Storage> storages = Lists.newArrayList();
private boolean done = false;
private boolean useServerParser = false;
private boolean useStorageParser = false;
@Inject
DataCenterInfoResponseHandler(DateCodecFactory dateCodecFactory) {
super(dateCodecFactory);
DataCenterInfoResponseHandler(ServerInfoResponseHandler serverInfoResponseHandler, StorageInfoResponseHandler storageInforResponseHandler) {
this.serverInfoResponseHandler = serverInfoResponseHandler;
this.storageInfoResponseHandler = storageInforResponseHandler;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("servers".equals(qName))
useServerParser = true;
else if ("storages".equals(qName))
useStorageParser = true;
}
@Override
@ -44,15 +68,43 @@ public class DataCenterInfoResponseHandler extends BaseDataCenterResponseHandler
builder.state(ProvisioningState.fromValue(textToStringValue()));
}
@Override
public void characters(char[] ch, int start, int length) {
if (useServerParser)
serverInfoResponseHandler.characters(ch, start, length);
else if (useStorageParser)
storageInfoResponseHandler.characters(ch, start, length);
else
super.characters(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (done)
return;
if ("servers".equals(qName)) {
useServerParser = false;
servers.add(serverInfoResponseHandler.getResult());
} else if ("storages".equals(qName)) {
useStorageParser = false;
storages.add(storageInfoResponseHandler.getResult());
}
if (useServerParser)
serverInfoResponseHandler.endElement(uri, localName, qName);
else if (useStorageParser)
storageInfoResponseHandler.endElement(uri, localName, qName);
else {
setPropertyOnEndTag(qName);
if ("return".equals(qName))
if ("return".equals(qName)) {
done = true;
builder.servers(servers);
builder.storages(storages);
}
clearTextBuffer();
}
}
@Override
public DataCenter getResult() {

View File

@ -18,22 +18,18 @@ package org.jclouds.profitbricks.http.parser.datacenter;
import java.util.List;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.xml.sax.SAXException;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
public class DataCenterListResponseHandler extends BaseDataCenterResponseHandler<List<DataCenter>> {
private final List<DataCenter> dataCenters;
@Inject
DataCenterListResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
DataCenterListResponseHandler() {
this.dataCenters = Lists.newArrayList();
}

View File

@ -16,9 +16,6 @@
*/
package org.jclouds.profitbricks.http.parser.image;
import javax.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.Image;
import org.jclouds.profitbricks.domain.Image.Type;
import org.jclouds.profitbricks.domain.Location;
@ -29,9 +26,7 @@ public abstract class BaseImageResponseHandler<T> extends BaseProfitBricksRespon
protected Image.Builder builder;
@Inject
BaseImageResponseHandler(DateCodecFactory dateCodecFactory) {
super(dateCodecFactory);
BaseImageResponseHandler() {
this.builder = Image.builder();
}

View File

@ -16,8 +16,6 @@
*/
package org.jclouds.profitbricks.http.parser.image;
import com.google.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.Image;
import org.xml.sax.SAXException;
@ -25,9 +23,7 @@ public class ImageInfoResponseHandler extends BaseImageResponseHandler<Image> {
private boolean done = false;
@Inject
ImageInfoResponseHandler(DateCodecFactory dateCodecFactory) {
super(dateCodecFactory);
ImageInfoResponseHandler() {
}
@Override

View File

@ -17,9 +17,9 @@
package org.jclouds.profitbricks.http.parser.image;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import java.util.List;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.Image;
import org.xml.sax.SAXException;
@ -27,9 +27,7 @@ public class ImageListResponseHandler extends BaseImageResponseHandler<List<Imag
private final List<Image> images;
@Inject
ImageListResponseHandler(DateCodecFactory dateCodecFactory) {
super(dateCodecFactory);
ImageListResponseHandler() {
this.images = Lists.newArrayList();
}

View File

@ -16,7 +16,12 @@
*/
package org.jclouds.profitbricks.http.parser.server;
import java.util.Date;
import org.jclouds.date.DateCodec;
import com.google.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.AvailabilityZone;
import org.jclouds.profitbricks.domain.OsType;
@ -28,12 +33,18 @@ public abstract class BaseServerResponseHandler<T> extends BaseProfitBricksRespo
protected Server.DescribingBuilder builder;
protected final DateCodec dateCodec;
@Inject
BaseServerResponseHandler(DateCodecFactory dateCodec) {
super( dateCodec );
this.dateCodec = dateCodec.iso8601();
this.builder = Server.builder();
}
protected final Date textToIso8601Date() {
return dateCodec.toDate(textToStringValue());
}
@Override
protected void setPropertyOnEndTag(String qName) {
if ("serverId".equals(qName))

View File

@ -16,8 +16,6 @@
*/
package org.jclouds.profitbricks.http.parser.server;
import com.google.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
import org.xml.sax.SAXException;
@ -30,9 +28,7 @@ public class ServerIdOnlyResponseHandler extends BaseProfitBricksResponseHandler
private String serverId;
@Inject
ServerIdOnlyResponseHandler( DateCodecFactory dateCodec ) {
super( dateCodec );
ServerIdOnlyResponseHandler() {
}
@Override

View File

@ -16,20 +16,15 @@
*/
package org.jclouds.profitbricks.http.parser.state;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
import org.xml.sax.SAXException;
import com.google.inject.Inject;
public class GetProvisioningStateResponseHandler extends BaseProfitBricksResponseHandler<ProvisioningState> {
private ProvisioningState state = ProvisioningState.UNRECOGNIZED;
@Inject
GetProvisioningStateResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
GetProvisioningStateResponseHandler() {
}
@Override

View File

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.http.parser.storage;
import java.util.Date;
import java.util.List;
import org.jclouds.date.DateCodec;
import com.google.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.profitbricks.domain.Storage.BusType;
import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
import com.google.common.collect.Lists;
public abstract class BaseStorageResponseHandler<T> extends BaseProfitBricksResponseHandler<T> {
protected final DateCodec dateCodec;
protected Storage.Builder builder;
protected List<String> serverIds;
@Inject
BaseStorageResponseHandler(DateCodecFactory dateCodec) {
this.dateCodec = dateCodec.iso8601();
this.builder = Storage.builder();
this.serverIds = Lists.newArrayList();
}
protected final Date textToIso8601Date() {
return dateCodec.toDate(textToStringValue());
}
@Override
protected void setPropertyOnEndTag(String qName) {
// <requestId>?</requestId>
// <dataCenterId>?</dataCenterId>
// <dataCenterVersion>?</dataCenterVersion>
if ("storageId".equals(qName))
builder.id(textToStringValue());
else if ("size".equals(qName))
builder.size(textToFloatValue());
else if ("storageName".equals(qName))
builder.name(textToStringValue());
else if ("provisioningState".equals(qName))
builder.state(ProvisioningState.fromValue(textToStringValue()));
else if ("creationTime".equals(qName))
builder.creationTime(textToIso8601Date());
else if ("lastModificationTime".equals(qName))
builder.lastModificationTime(textToIso8601Date());
// <mountImage>
// <imageId>?</imageId>
// <imageName>?</imageName>
// </mountImage>
else if ("serverIds".equals(qName))
serverIds.add(textToStringValue());
else if ("bootDevice".equals(qName))
builder.bootDevice(textToBooleanValue());
else if ("busType".equals(qName))
builder.busType(BusType.fromValue(textToStringValue()));
else if ("deviceNumber".equals(qName))
builder.deviceNumber(textToIntValue());
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.http.parser.storage;
import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
import org.xml.sax.SAXException;
public class StorageIdOnlyResponseHandler extends BaseProfitBricksResponseHandler<String> {
private String storageId;
StorageIdOnlyResponseHandler() {
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
setPropertyOnEndTag(qName);
clearTextBuffer();
}
@Override
protected void setPropertyOnEndTag(String qName) {
if ("storageId".equals(qName))
storageId = textToStringValue();
}
@Override
public String getResult() {
return storageId;
}
}

View File

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.http.parser.storage;
import com.google.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.Storage;
import org.xml.sax.SAXException;
public class StorageInfoResponseHandler extends BaseStorageResponseHandler<Storage> {
private boolean done = false;
@Inject
StorageInfoResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (done)
return;
setPropertyOnEndTag(qName);
if ("return".equals(qName)) {
done = true;
builder.serverIds(serverIds);
}
clearTextBuffer();
}
@Override
public Storage getResult() {
return builder.build();
}
}

View File

@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.http.parser.storage;
import autovalue.shaded.com.google.common.common.collect.Lists;
import com.google.inject.Inject;
import java.util.List;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.Storage;
import org.xml.sax.SAXException;
public class StorageListResponseHandler extends BaseStorageResponseHandler<List<Storage>> {
private final List<Storage> storages;
@Inject
StorageListResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
this.storages = Lists.newArrayList();
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
setPropertyOnEndTag(qName);
if ("return".equals(qName)) {
storages.add(builder
.serverIds(serverIds)
.build());
builder = Storage.builder();
serverIds = Lists.newArrayList();
}
clearTextBuffer();
}
@Override
public List<Storage> getResult() {
return storages;
}
}

View File

@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.binder.storage;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.profitbricks.domain.Storage;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ConnectStorageToServerRequestBinderTest")
public class ConnectStorageToServerRequestBinderTest {
@Test
public void testCreatePayload() {
ConnectStorageToServerRequestBinder binder = new ConnectStorageToServerRequestBinder();
Storage.Request.ConnectPayload payload = Storage.Request.connectingBuilder()
.serverId("qwertyui-qwer-qwer-qwer-qwertyyuiiop")
.storageId("qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh")
.busType(Storage.BusType.VIRTIO)
.deviceNumber(2)
.build();
String actual = binder.createPayload(payload);
assertNotNull(actual, "Binder returned null payload");
assertEquals(actual, expectedPayload);
}
private final String expectedPayload
= (" <ws:connectStorageToServer>\n"
+ " <request>\n"
+ " <storageId>qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh</storageId>\n"
+ " <serverId>qwertyui-qwer-qwer-qwer-qwertyyuiiop</serverId>\n"
+ " <busType>VIRTIO</busType>\n"
+ " <deviceNumber>2</deviceNumber>\n"
+ " </request>\n"
+ " </ws:connectStorageToServer>")
.replaceAll("\\s+", "");
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.binder.storage;
import org.jclouds.profitbricks.domain.Storage;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "CreateStorageRequestBinderTest")
public class CreateStorageRequestBinderTest {
@Test
public void testCreatePayload() {
CreateStorageRequestBinder binder = new CreateStorageRequestBinder();
Storage.Request.CreatePayload payload = Storage.Request.creatingBuilder()
.name("hdd-1")
.size(60f)
.dataCenterId("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")
.mountImageId("5ad99c9e-9166-11e4-9d74-52540066fee9")
.imagePassword("qqqqqqqqq")
.build();
String actual = binder.createPayload(payload);
assertNotNull(actual, "Binder returned null payload");
assertEquals(actual, expectedPayload);
}
private final String expectedPayload
= (" <ws:createStorage>\n"
+ " <request>\n"
+ " <dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>\n"
+ " <storageName>hdd-1</storageName>\n"
+ " <size>60</size>\n"
+ " <mountImageId>5ad99c9e-9166-11e4-9d74-52540066fee9</mountImageId>\n"
+ " <profitBricksImagePassword>qqqqqqqqq</profitBricksImagePassword>\n"
+ " </request>\n"
+ " </ws:createStorage>")
.replaceAll("\\s+", "");
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.binder.storage;
import org.jclouds.profitbricks.domain.Storage;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "UpdateStorageRequestBinderTest")
public class UpdateStorageRequestBinderTest {
@Test
public void testUpdatePayload() {
UpdateStorageRequestBinder binder = new UpdateStorageRequestBinder();
Storage.Request.UpdatePayload payload = Storage.Request.updatingBuilder()
.id("pppppppp-llkl-kkjk-fhgh-vnmegrdgdsgr")
.size(100f)
.name("hdd-2")
.mountImageId("5f3cac96-915f-11e4-9d74-52540066fee9")
.build();
String actual = binder.createPayload(payload);
assertNotNull(actual, "Binder returned null payload");
assertEquals(actual, expectedPayload);
}
private final String expectedPayload
= (" <ws:updateStorage>\n"
+ " <request>\n"
+ " <storageId>pppppppp-llkl-kkjk-fhgh-vnmegrdgdsgr</storageId>\n"
+ " <size>100</size>\n"
+ " <storageName>hdd-2</storageName>\n"
+ " <mountImageId>5f3cac96-915f-11e4-9d74-52540066fee9</mountImageId>\n"
+ " </request>\n"
+ " </ws:updateStorage>")
.replaceAll("\\s+", "");
}

View File

@ -39,7 +39,7 @@ import com.squareup.okhttp.mockwebserver.MockWebServer;
public class ProvisioningStatusPollingPredicateTest extends BaseProfitBricksMockTest {
@Test
public void testPredicate() throws Exception {
public void testDataCenterPredicate() throws Exception {
MockWebServer server = mockWebServer();
byte[] payloadInProcess = payloadFromResource("/datacenter/datacenter-state-inprocess.xml");
@ -71,4 +71,70 @@ public class ProvisioningStatusPollingPredicateTest extends BaseProfitBricksMock
}
}
@Test
public void testServerPredicate() throws Exception {
MockWebServer server = mockWebServer();
byte[] payloadInProcess = payloadFromResource("/server/server-state-inprocess.xml");
byte[] payloadAvailable = payloadFromResource("/server/server.xml");
// wait 3 times
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadAvailable));
server.enqueue(new MockResponse().setBody(payloadAvailable));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
Predicate<String> waitUntilAvailable = Predicates2.retry(
new ProvisioningStatusPollingPredicate(pbApi, ProvisioningStatusAware.SERVER, ProvisioningState.AVAILABLE),
30l, 1l, TimeUnit.SECONDS);
String id = "qwertyui-qwer-qwer-qwer-qwertyyuiiop";
try {
waitUntilAvailable.apply(id);
ProvisioningState finalState = pbApi.serverApi().getServer(id).state();
assertRequestHasCommonProperties(server.takeRequest());
assertEquals(finalState, ProvisioningState.AVAILABLE);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testStoragePredicate() throws Exception {
MockWebServer server = mockWebServer();
byte[] payloadInProcess = payloadFromResource("/storage/storage-state-inprocess.xml");
byte[] payloadAvailable = payloadFromResource("/storage/storage.xml");
// wait 3 times
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadAvailable));
server.enqueue(new MockResponse().setBody(payloadAvailable));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
Predicate<String> waitUntilAvailable = Predicates2.retry(
new ProvisioningStatusPollingPredicate(pbApi, ProvisioningStatusAware.STORAGE, ProvisioningState.AVAILABLE),
30l, 1l, TimeUnit.SECONDS);
String id = "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh";
try {
waitUntilAvailable.apply(id);
ProvisioningState finalState = pbApi.storageApi().getStorage(id).state();
assertRequestHasCommonProperties(server.takeRequest());
assertEquals(finalState, ProvisioningState.AVAILABLE);
} finally {
pbApi.close();
server.shutdown();
}
}
}

View File

@ -46,8 +46,6 @@ public class ServerBuilderTest {
private final String _bootFromStorageId = "some-random-storage-id";
private final String _bootFromImageId = "some-random-image-id";
private final String _serverId = "some-random-server-id";
@Test
public void testAutoValueServerPropertiesSettingCorrectly() {
Server actual = Server.builder()

View File

@ -168,7 +168,7 @@ public class DataCenterApiMockTest extends BaseProfitBricksMockTest {
@Test
public void testCreateDataCenterWithIllegalArguments() throws Exception {
String[] names = {"JCl@ouds", "JC|ouds", "^clouds", ""};
for (String name : names) {
for (String name : names)
try {
DataCenter.Request.CreatePayload.create(name, Location.US_LAS);
fail("Should have failed for name: ".concat(name));
@ -176,7 +176,6 @@ public class DataCenterApiMockTest extends BaseProfitBricksMockTest {
// expected exception
}
}
}
@Test
public void testUpdateDataCenter() throws Exception {

View File

@ -16,21 +16,27 @@
*/
package org.jclouds.profitbricks.features;
import static org.jclouds.profitbricks.internal.BaseProfitBricksMockTest.mockWebServer;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import java.util.List;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.domain.AvailabilityZone;
import org.jclouds.profitbricks.domain.OsType;
import org.jclouds.profitbricks.domain.Server;
import org.jclouds.profitbricks.internal.BaseProfitBricksMockTest;
import static org.jclouds.profitbricks.internal.BaseProfitBricksMockTest.mockWebServer;
import org.jclouds.rest.ResourceNotFoundException;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ServerApiMockTest")
@ -335,4 +341,23 @@ public class ServerApiMockTest extends BaseProfitBricksMockTest {
}
}
@Test
public void testDeleteNonExistingServer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
ServerApi api = pbApi.serverApi();
String id = "random-non-existing-id";
try {
boolean result = api.deleteServer(id);
assertRequestHasCommonProperties(server.takeRequest());
assertFalse(result);
} finally {
pbApi.close();
server.shutdown();
}
}
}

View File

@ -0,0 +1,167 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jclouds.profitbricks.BaseProfitBricksLiveTest;
import org.jclouds.profitbricks.compute.internal.ProvisioningStatusAware;
import org.jclouds.profitbricks.compute.internal.ProvisioningStatusPollingPredicate;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.domain.Server;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.rest.InsufficientResourcesException;
import org.jclouds.util.Predicates2;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@Test(groups = "live", testName = "StorageApiLiveTest", singleThreaded = true)
public class StorageApiLiveTest extends BaseProfitBricksLiveTest {
private Predicate<String> waitUntilAvailable;
private DataCenter dataCenter;
private Server server;
private String createdStorageId;
@Override
protected void initialize() {
super.initialize();
List<DataCenter> dataCenters = api.dataCenterApi().getAllDataCenters();
assertFalse(dataCenters.isEmpty(), "Must atleast have 1 datacenter available for storage testing.");
dataCenter = Iterables.getFirst(dataCenters, null);
if (dataCenter != null)
dataCenter = api.dataCenterApi().getDataCenter(dataCenter.id()); // fetch individual to load more properties
this.waitUntilAvailable = Predicates2.retry(
new ProvisioningStatusPollingPredicate(api, ProvisioningStatusAware.STORAGE, ProvisioningState.AVAILABLE),
6l * 60l, 2l, TimeUnit.SECONDS);
}
@Test(expectedExceptions = InsufficientResourcesException.class)
public void testUberStorage() {
api.storageApi().createStorage(
Storage.Request.creatingBuilder()
.dataCenterId(dataCenter)
.name("Uber Storage")
.size(9999999f)
.build());
}
@Test
public void testCreateStorage() {
String storageId = api.storageApi().createStorage(
Storage.Request.creatingBuilder()
.dataCenterId(dataCenter)
.name("hdd-1")
.size(2f)
.build());
assertNotNull(storageId);
createdStorageId = storageId;
}
@Test(dependsOnMethods = "testCreateStorage")
public void testGetStorage() {
Storage storage = api.storageApi().getStorage(createdStorageId);
assertNotNull(storage);
assertEquals(storage.id(), createdStorageId);
}
@Test(dependsOnMethods = "testCreateStorage")
public void testGetAllStorages() {
List<Storage> storages = api.storageApi().getAllStorages();
assertNotNull(storages);
assertFalse(storages.isEmpty());
}
@Test(dependsOnMethods = "testCreateStorage")
public void testWaitUntilAvailable() {
boolean available = waitUntilAvailable.apply(createdStorageId);
assertTrue(available);
}
@Test(dependsOnMethods = "testWaitUntilAvailable")
public void testUpdateStorage() {
String requestId = api.storageApi().updateStorage(
Storage.Request.updatingBuilder()
.id(createdStorageId)
.name("hdd-2")
.size(5l)
.build());
assertNotNull(requestId);
waitUntilAvailable.apply(createdStorageId);
Storage storage = api.storageApi().getStorage(createdStorageId);
assertEquals(storage.size(), 5f);
assertEquals(storage.name(), "hdd-2");
}
@Test(dependsOnMethods = "testUpdateStorage")
public void testConnectStorage() {
server = Iterables.getFirst(dataCenter.servers(), null);
assertNotNull(server, "No server to attach to.");
String requestId = api.storageApi().connectStorageToServer(
Storage.Request.connectingBuilder()
.storageId(createdStorageId)
.serverId(server.id())
.build()
);
assertNotNull(requestId);
waitUntilAvailable.apply(createdStorageId);
Storage storage = api.storageApi().getStorage(createdStorageId);
assertTrue(storage.serverIds().contains(server.id()));
}
@Test(dependsOnMethods = "testConnectStorage")
public void testDisconnectStorage() {
String requestId = api.storageApi()
.disconnectStorageFromServer(createdStorageId, server.id());
assertNotNull(requestId);
waitUntilAvailable.apply(createdStorageId);
Storage storage = api.storageApi().getStorage(createdStorageId);
assertFalse(storage.serverIds().contains(server.id()));
}
@AfterClass(alwaysRun = true)
public void testDeleteStorage() {
if (createdStorageId != null) {
boolean result = api.storageApi().deleteStorage(createdStorageId);
assertTrue(result, "Created test storage was not delete.");
}
}
}

View File

@ -0,0 +1,285 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.profitbricks.internal.BaseProfitBricksMockTest;
import org.testng.annotations.Test;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
@Test(groups = "unit", testName = "StorageApiMockTest")
public class StorageApiMockTest extends BaseProfitBricksMockTest {
@Test
public void testGetAllStorages() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/storage/storages.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
try {
List<Storage> storages = api.getAllStorages();
assertRequestHasCommonProperties(server.takeRequest(), "<ws:getAllStorages/>");
assertNotNull(storages);
assertTrue(storages.size() == 2);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testGetAllStoragesReturning404() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
try {
List<Storage> storages = api.getAllStorages();
assertRequestHasCommonProperties(server.takeRequest());
assertTrue(storages.isEmpty());
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testGetStorage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/storage/storage.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String id = "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh";
String content = "<ws:getStorage><storageId>" + id + "</storageId></ws:getStorage>";
try {
Storage storage = api.getStorage(id);
assertRequestHasCommonProperties(server.takeRequest(), content);
assertNotNull(storage);
assertEquals(storage.id(), id);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testGetNonExistingStorage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String id = "random-non-existing-id";
try {
Storage storage = api.getStorage(id);
assertRequestHasCommonProperties(server.takeRequest());
assertNull(storage);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testConnectStorageToServer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/storage/storage-connect.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String storageId = "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh";
String serverId = "qwertyui-qwer-qwer-qwer-qwertyyuiiop";
String content = "<ws:connectStorageToServer><request>"
+ "<storageId>" + storageId + "</storageId>"
+ "<serverId>" + serverId + "</serverId>"
+ "<busType>VIRTIO</busType>"
+ "<deviceNumber>2</deviceNumber>"
+ "</request></ws:connectStorageToServer>";
try {
String requestId = api.connectStorageToServer(
Storage.Request.connectingBuilder()
.serverId(serverId)
.storageId(storageId)
.busType(Storage.BusType.VIRTIO)
.deviceNumber(2)
.build()
);
assertRequestHasCommonProperties(server.takeRequest(), content);
assertEquals(requestId, "16463317");
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testDisconnectStorageFromServer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/storage/storage-disconnect.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String storageId = "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh";
String serverId = "qwertyui-qwer-qwer-qwer-qwertyyuiiop";
String content = "<ws:disconnectStorageFromServer>"
+ "<storageId>" + storageId + "</storageId>"
+ "<serverId>" + serverId + "</serverId>"
+ "</ws:disconnectStorageFromServer>";
try {
String requestId = api.disconnectStorageFromServer(storageId, serverId);
assertRequestHasCommonProperties(server.takeRequest(), content);
assertEquals(requestId, "16463318");
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testCreateStorage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/storage/storage-create.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String dataCenterId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
String imageId = "f0a59a5c-7940-11e4-8053-52540066fee9";
String content = "<ws:createStorage><request>"
+ "<dataCenterId>" + dataCenterId + "</dataCenterId>"
+ "<storageName>hdd-1</storageName>" + "<size>80</size>"
+ "<mountImageId>" + imageId + "</mountImageId>"
+ "<profitBricksImagePassword>qqqqqqqqq</profitBricksImagePassword>"
+ "</request></ws:createStorage>";
try {
String storageId = api.createStorage(
Storage.Request.creatingBuilder()
.dataCenterId(dataCenterId)
.name("hdd-1")
.size(80f)
.mountImageId(imageId)
.imagePassword("qqqqqqqqq")
.build());
assertRequestHasCommonProperties(server.takeRequest(), content);
assertNotNull(storageId);
assertEquals(storageId, "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh");
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testUpdateStorage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/storage/storage-update.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String storageId = "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh";
String imageId = "f4742db0-9160-11e4-9d74-52540066fee9";
String content = "<ws:updateStorage><request>"
+ "<storageId>" + storageId + "</storageId>"
+ "<size>20</size><storageName>hdd-2</storageName>"
+ "<mountImageId>" + imageId + "</mountImageId>"
+ "</request></ws:updateStorage>";
try {
String requestId = api.updateStorage(
Storage.Request.updatingBuilder()
.id(storageId)
.size(20f)
.name("hdd-2")
.mountImageId(imageId)
.build());
assertRequestHasCommonProperties(server.takeRequest(), content);
assertNotNull(requestId);
assertEquals(requestId, "1234568");
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testDeleteStorage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/storage/storage-delete.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String storageId = "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh";
String content = "<ws:deleteStorage><storageId>" + storageId + "</storageId></ws:deleteStorage>";
try {
boolean result = api.deleteStorage(storageId);
assertRequestHasCommonProperties(server.takeRequest(), content);
assertTrue(result);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testDeleteNonExistingStorage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
StorageApi api = pbApi.storageApi();
String id = "random-non-existing-id";
try {
boolean result = api.deleteStorage(id);
assertRequestHasCommonProperties(server.takeRequest());
assertFalse(result);
} finally {
pbApi.close();
server.shutdown();
}
}
}

View File

@ -20,12 +20,16 @@ import static org.jclouds.profitbricks.internal.BaseProfitBricksMockTest.mockWeb
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.jclouds.http.HttpResponseException;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.Server;
import org.jclouds.profitbricks.features.DataCenterApi;
import org.jclouds.profitbricks.features.ServerApi;
import org.jclouds.profitbricks.internal.BaseProfitBricksMockTest;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InsufficientResourcesException;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
@ -38,6 +42,8 @@ import com.squareup.okhttp.mockwebserver.MockWebServer;
@Test(groups = "unit", testName = "ResponseStatusFromPayloadHttpCommandExecutorServiceTest")
public class ResponseStatusFromPayloadHttpCommandExecutorServiceTest extends BaseProfitBricksMockTest {
private final int MAX_RETRIES = 5;
@Test
public void testNotFound() throws Exception {
MockWebServer server = mockWebServer();
@ -95,4 +101,43 @@ public class ResponseStatusFromPayloadHttpCommandExecutorServiceTest extends Bas
server.shutdown();
}
}
@Test
public void testOverLimitSettings() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(503).setBody(payloadFromResource("/fault-413.xml")));
ProfitBricksApi pbApi = api(server.getUrl("/"));
ServerApi api = pbApi.serverApi();
try {
api.createServer(Server.Request.CreatePayload.create("some-datacenter-id", "node1", 99, 12800));
fail("Request should have failed.");
} catch (Exception ex) {
assertTrue(ex instanceof InsufficientResourcesException, "Exception should be InsufficientResourcesException");
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testServiceUnderMaintenance() throws Exception {
MockWebServer server = mockWebServer();
for (int i = 0; i <= MAX_RETRIES; i++) // jclouds retries 5 times
server.enqueue(new MockResponse().setResponseCode(503).setBody(payloadFromResource("/maintenance-503.html")));
ProfitBricksApi pbApi = api(server.getUrl("/"));
DataCenterApi api = pbApi.dataCenterApi();
try {
api.clearDataCenter("some-datacenter-id");
fail("Request should have failed.");
} catch (Exception ex) {
assertTrue(ex instanceof HttpResponseException, "Exception should be HttpResponseException");
} finally {
pbApi.close();
server.shutdown();
}
}
}

View File

@ -19,14 +19,21 @@ package org.jclouds.profitbricks.http.parser.datacenter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.date.DateCodec;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.AvailabilityZone;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.OsType;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.domain.Server;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "DataCenterInfoResponseHandlerTest")
public class DataCenterInfoResponseHandlerTest extends BaseResponseHandlerTest<DataCenter> {
@ -35,19 +42,57 @@ public class DataCenterInfoResponseHandlerTest extends BaseResponseHandlerTest<D
return factory.create(injector.getInstance(DataCenterInfoResponseHandler.class));
}
protected DateCodecFactory createDateParser() {
return injector.getInstance(DateCodecFactory.class);
}
@Test
public void testParseResponseFromGetDataCenter() {
ParseSax<DataCenter> parser = createParser();
DataCenter actual = parser.parse(payloadFromResource("/datacenter/datacenter.xml"));
assertNotNull(actual, "Parsed content returned null");
DateCodec dateParser = createDateParser().iso8601();
DataCenter expected = DataCenter.builder()
.id("12345678-abcd-efgh-ijkl-987654321000")
.version(10)
.name("JClouds-DC")
.state(ProvisioningState.AVAILABLE)
.location(Location.US_LAS)
.servers(ImmutableList.<Server>of(
Server.builder()
.id("12345678-abcd-efgh-ijkl-987654321000")
.name("jnode1")
.cores(4)
.ram(4096)
.hasInternetAccess(true)
.state(ProvisioningState.AVAILABLE)
.status(Server.Status.RUNNING)
.creationTime(dateParser.toDate("2014-12-04T07:09:23.138Z"))
.lastModificationTime(dateParser.toDate("2014-12-12T03:08:35.629Z"))
.osType(OsType.LINUX)
.availabilityZone(AvailabilityZone.AUTO)
.isCpuHotPlug(true)
.isRamHotPlug(true)
.isNicHotPlug(true)
.isNicHotUnPlug(true)
.isDiscVirtioHotPlug(true)
.isDiscVirtioHotUnPlug(true)
.build()
))
.storages(ImmutableList.<Storage>of(
Storage.builder()
.id("ssssssss-aaaa-ffff-gggg-hhhhhhhhhhhh")
.size(40)
.name("jnode1-disk1")
.state(ProvisioningState.AVAILABLE)
.creationTime(dateParser.toDate("2014-12-04T07:09:23.138Z"))
.lastModificationTime(dateParser.toDate("2014-12-12T03:14:48.316Z"))
.build()
))
.build();
assertEquals(expected, actual);
assertEquals(actual, expected);
}
}

View File

@ -16,7 +16,9 @@
*/
package org.jclouds.profitbricks.http.parser.server;
import java.text.ParseException;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.date.DateCodec;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.http.functions.ParseSax;
@ -25,8 +27,7 @@ import org.jclouds.profitbricks.domain.OsType;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.domain.Server;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ServerInfoResponseHandlerTest")
@ -42,7 +43,7 @@ public class ServerInfoResponseHandlerTest extends BaseResponseHandlerTest<Serve
}
@Test
public void testParseResponseFromGetServer() throws ParseException {
public void testParseResponseFromGetServer() {
ParseSax<Server> parser = createParser();
Server actual = parser.parse(payloadFromResource("/server/server.xml"));

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.http.parser.storage;
import static org.testng.Assert.assertEquals;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "StorageIdOnlyResponseHandlerTest")
public class StorageIdOnlyResponseHandlerTest extends BaseResponseHandlerTest<String> {
@Override
protected ParseSax<String> createParser() {
return factory.create(injector.getInstance(StorageIdOnlyResponseHandler.class));
}
@Test
public void testParseResponseFromCreateStorage() {
ParseSax<String> parser = createParser();
String storageId = parser.parse(payloadFromResource("/storage/storage-create.xml"));
assertEquals("qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh", storageId);
}
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.http.parser.storage;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.date.DateCodec;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "StorageInfoResponseHandlerTest")
public class StorageInfoResponseHandlerTest extends BaseResponseHandlerTest<Storage> {
@Override
protected ParseSax<Storage> createParser() {
return factory.create(injector.getInstance(StorageInfoResponseHandler.class));
}
protected DateCodecFactory createDateParser() {
return injector.getInstance(DateCodecFactory.class);
}
@Test
public void testParseResponseFromGetStorage() {
ParseSax<Storage> parser = createParser();
Storage actual = parser.parse(payloadFromResource("/storage/storage.xml"));
assertNotNull(actual, "Parsed content returned null");
DateCodec dateParser = createDateParser().iso8601();
Storage expected = Storage.builder()
.id("qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh")
.size(40)
.name("hdd-1")
.state(ProvisioningState.AVAILABLE)
.serverIds(ImmutableList.<String>of("qwertyui-qwer-qwer-qwer-qwertyyuiiop"))
.creationTime(dateParser.toDate("2014-12-04T07:09:23.138Z"))
.lastModificationTime(dateParser.toDate("2014-12-12T03:14:48.316Z"))
.build();
assertEquals(actual, expected);
}
}

View File

@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.profitbricks.http.parser.storage;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.jclouds.date.DateCodec;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.domain.Storage;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "StorageListResponseHandlerTest")
public class StorageListResponseHandlerTest extends BaseResponseHandlerTest<List<Storage>> {
@Override
protected ParseSax<List<Storage>> createParser() {
return factory.create(injector.getInstance(StorageListResponseHandler.class));
}
protected DateCodecFactory createDateParser() {
return injector.getInstance(DateCodecFactory.class);
}
@Test
public void testParseResponseFromGetAllStorages() {
ParseSax<List<Storage>> parser = createParser();
List<Storage> actual = parser.parse(payloadFromResource("/storage/storages.xml"));
assertNotNull(actual, "Parsed content returned null");
DateCodec dateParser = createDateParser().iso8601();
List<Storage> expected = ImmutableList.<Storage>of(
Storage.builder()
.id("qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh")
.size(40f)
.name("hdd-1")
.state(ProvisioningState.AVAILABLE)
.serverIds(ImmutableList.<String>of("qwertyui-qwer-qwer-qwer-qwertyyuiiop"))
.creationTime(dateParser.toDate("2014-12-04T07:09:23.138Z"))
.lastModificationTime(dateParser.toDate("2014-12-12T03:14:48.316Z"))
.build(),
Storage.builder()
.id("asfasfle-f23n-cu89-klfr-njkdsvwllkfa")
.size(100f)
.name("hdd-2")
.state(ProvisioningState.INPROCESS)
.serverIds(ImmutableList.<String>of("asdfghjk-asdf-asdf-asdf-asdfghjklkjl"))
.creationTime(dateParser.toDate("2014-11-04T07:09:23.138Z"))
.lastModificationTime(dateParser.toDate("2014-11-12T03:14:48.316Z"))
.build()
);
assertEquals(actual, expected);
}
}

View File

@ -33,7 +33,7 @@
<serverId>12345678-abcd-efgh-ijkl-987654321000</serverId>
<ips>202.94.38.12</ips>
<macAddress>02:01:09:cd:f0:b0</macAddress>
<firewall>`
<firewall>
<active>false</active>
<firewallId>llllllll-kkkk-jjjj-hhhh-gggggggggggg</firewallId>
<firewallId>62383ec1-38c8-486b-8fa2-a3bb0a5edd97</firewallId>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Server</faultcode>
<faultstring>New request exceeds the current capacity settings of this user contract. Please refer to Request Id : 16503940. [VDC-5-1020] Server has 12,800 MiB configured RAM. Your personal limit is 10,240 MiB per server.</faultstring>
<detail>
<ns2:ProfitbricksServiceFault xmlns:ns2="http://ws.api.profitbricks.com/">
<faultCode>OVER_LIMIT_SETTING</faultCode>
<httpCode>413</httpCode>
<message>New request exceeds the current capacity settings of this user contract. Please refer to Request Id : 16503940. [VDC-5-1020] Server has 12,800 MiB configured RAM. Your personal limit is 10,240 MiB per server.</message>
<requestId>16503940</requestId>
</ns2:ProfitbricksServiceFault>
</detail>
</S:Fault>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,67 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta lang="en" http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Profitbricks | Maintenance</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<link rel="stylesheet" type="text/css" href="css/content.css" />
<link rel="stylesheet" type="text/css" href="css/recent_additions.css" />
<link rel="shortcut icon" href="https://my.profitbricks.com/errorpages/favicon.ico" type="image/x-icon" />
</head>
<body>
<div class="head1 h_bg"></div>
<div class="head2 h_bg"></div>
<div class="head3 h_bg"></div>
<div id="wrapper">
<div class="wrapper_inner">
<div id="header">
<a id="logo" href="#"><img alt="Profitbricks" src="img/logo.png" /></a>
</div>
<div id="main">
<div id="right" style="min-height: 550px;">
<div class="article msg">
<h1>Maintenance</h1>
<img width="49" height="49" title="" alt="message error" src="Profitbricks%20%7C%20Maintenance_files/msg_error.png" class="msg_sign" style="margin: 10px;" />
<div class="container" style="margin:20px 80px !important;">
<div class="bigmargin">
<h2>Dear ProfitBricks users,</h2>
<p>actually we are carrying out maintenance work right now.</p>
<p>For urgent matters please contact:<br /><a href="mailto:support@profitbricks.com">support@profitbricks.com</a>.</p>
<br />
<p>We ask for your understanding and your patience.</p>
<p>Your ProfitBricks Team</p>
</div>
<div class="bigmargin">
<h2>Sehr geehrte(r) ProfitBricks Nutzerin/Nutzer,</h2>
<p>zur Zeit führen wir Wartungsarbeiten durch.</p>
<p>Bei dringenden Angelegenheiten wenden Sie sich bitte an:<br />
<a href="mailto:support@profitbricks.com">support@profitbricks.com</a>
</p>
<br />
<p>Wir bitten Sie um Ihr Verständnis und um etwas Geduld.</p>
<p>Ihr ProfitBricks Team</p>
</div>
</div>
</div>
</div>
<br class="clear" />
</div>
</div>
</div>
<div id="footer">
<div class="bottom">
<div class="inner">
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getServerResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<requestId>16577212</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>22</dataCenterVersion>
<serverId>qwertyui-qwer-qwer-qwer-qwertyyuiiop</serverId>
<cores>1</cores>
<ram>512</ram>
<internetAccess>false</internetAccess>
<provisioningState>INPROCESS</provisioningState>
<virtualMachineState>NOSTATE</virtualMachineState>
<creationTime>2015-01-29T00:37:49.096Z</creationTime>
<lastModificationTime>2015-01-29T00:37:49.096Z</lastModificationTime>
<osType>UNKNOWN</osType>
<availabilityZone>AUTO</availabilityZone>
<cpuHotPlug>false</cpuHotPlug>
<ramHotPlug>false</ramHotPlug>
<nicHotPlug>false</nicHotPlug>
<nicHotUnPlug>false</nicHotUnPlug>
<discVirtioHotPlug>false</discVirtioHotPlug>
<discVirtioHotUnPlug>false</discVirtioHotUnPlug>
</return>
</ns2:getServerResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.api.profitbricks.com/">
<soapenv:Header/>
<soapenv:Body>
<ws:connectStorageToServerResponse>
<return>
<requestId>16463317</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>49</dataCenterVersion>
</return>
</ws:connectStorageToServerResponse>
</soapenv:Body>
</soapenv:Envelope>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.api.profitbricks.com/">
<soapenv:Header/>
<soapenv:Body>
<ws:createStorageReturn>
<return>
<requestId>1234567</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>45</dataCenterVersion>
<storageId>qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh</storageId>
</return>
</ws:createStorageReturn>
</soapenv:Body>
</soapenv:Envelope>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.api.profitbricks.com/">
<soapenv:Header/>
<soapenv:Body>
<ws:deleteStorageResponse>
<return>
<requestId>12345679</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>47</dataCenterVersion>
</return>
</ws:deleteStorageResponse>
</soapenv:Body>
</soapenv:Envelope>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.api.profitbricks.com/">
<soapenv:Header/>
<soapenv:Body>
<ws:disconnectStorageFromServerResponse>
<return>
<requestId>16463318</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>50</dataCenterVersion>
</return>
</ws:disconnectStorageFromServerResponse>
</soapenv:Body>
</soapenv:Envelope>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getStorageResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<requestId>16463316</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>49</dataCenterVersion>
<storageId>qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh</storageId>
<size>40</size>
<storageName>hdd-1</storageName>
<mountImage>
<imageId>f0a59a5c-7940-11e4-8053-52540066fee9</imageId>
<imageName>Ubuntu-14.04-LTS-server-2014-12-01</imageName>
</mountImage>
<serverIds>qwertyui-qwer-qwer-qwer-qwertyyuiiop</serverIds>
<provisioningState>INPROCESS</provisioningState>
<creationTime>2014-12-04T07:09:23.138Z</creationTime>
<lastModificationTime>2014-12-12T03:14:48.316Z</lastModificationTime>
</return>
</ns2:getStorageResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.api.profitbricks.com/">
<soapenv:Header/>
<soapenv:Body>
<ws:updateStorageResponse>
<return>
<requestId>1234568</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>46</dataCenterVersion>
</return>
</ws:updateStorageResponse>
</soapenv:Body>
</soapenv:Envelope>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getStorageResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<requestId>16463316</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>49</dataCenterVersion>
<storageId>qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh</storageId>
<size>40</size>
<storageName>hdd-1</storageName>
<mountImage>
<imageId>f0a59a5c-7940-11e4-8053-52540066fee9</imageId>
<imageName>Ubuntu-14.04-LTS-server-2014-12-01</imageName>
</mountImage>
<serverIds>qwertyui-qwer-qwer-qwer-qwertyyuiiop</serverIds>
<provisioningState>AVAILABLE</provisioningState>
<creationTime>2014-12-04T07:09:23.138Z</creationTime>
<lastModificationTime>2014-12-12T03:14:48.316Z</lastModificationTime>
</return>
</ns2:getStorageResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getAllStoragesResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>49</dataCenterVersion>
<storageId>qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh</storageId>
<size>40</size>
<storageName>hdd-1</storageName>
<mountImage>
<imageId>f0a59a5c-7940-11e4-8053-52540066fee9</imageId>
<imageName>Ubuntu-14.04-LTS-server-2014-12-01</imageName>
</mountImage>
<serverIds>qwertyui-qwer-qwer-qwer-qwertyyuiiop</serverIds>
<provisioningState>AVAILABLE</provisioningState>
<creationTime>2014-12-04T07:09:23.138Z</creationTime>
<lastModificationTime>2014-12-12T03:14:48.316Z</lastModificationTime>
</return>
<return>
<dataCenterId>qqqqqqqq-wwww-rrrr-tttt-yyyyyyyyyyyy</dataCenterId>
<dataCenterVersion>238</dataCenterVersion>
<storageId>asfasfle-f23n-cu89-klfr-njkdsvwllkfa</storageId>
<size>100</size>
<storageName>hdd-2</storageName>
<mountImage>
<imageId>f4742db0-9160-11e4-9d74-52540066fee9</imageId>
<imageName>Fedora-19-server-2015-01-01</imageName>
</mountImage>
<serverIds>asdfghjk-asdf-asdf-asdf-asdfghjklkjl</serverIds>
<provisioningState>INPROCESS</provisioningState>
<creationTime>2014-11-04T07:09:23.138Z</creationTime>
<lastModificationTime>2014-11-12T03:14:48.316Z</lastModificationTime>
</return>
</ns2:getAllStoragesResponse>
</S:Body>
</S:Envelope>